style: 将样式单位标准化为 rpx

This commit is contained in:
Ray.Hao
2026-04-15 09:33:37 +08:00
parent e87c2cad53
commit 012362f61d
15 changed files with 405 additions and 258 deletions

View File

@@ -48,6 +48,10 @@ export default [
PageQuery: "readonly", // 分页查询数据类型
OptionType: "readonly", // 选项类型
getCurrentPages: "readonly", // uni-app 全局 API
wx: "readonly", // 微信小程序 API
useToast: "readonly", // wot-design-uni
useMessage: "readonly", // wot-design-uni
useNotify: "readonly", // wot-design-uni
},
},
},

View File

@@ -62,7 +62,7 @@ const props = withDefaults(defineProps<Props>(), {
showBack: true,
showHome: false,
backIcon: "arrow-left",
backIconSize: "20px",
backIconSize: "40rpx",
iconColor: "var(--color-text)",
fixed: true,
placeholder: false,
@@ -223,6 +223,6 @@ export default {
.custom-navbar__capsule-space {
flex: 0 0 auto;
height: 1px;
height: 2rpx;
}
</style>

View File

@@ -36,7 +36,7 @@
<!-- 表单区域 -->
<view v-if="loginMode !== 'WECHAT'" class="login__form">
<!-- 用户名/手机号 -->
<view class="login__field">
<view class="login__form-item login__field">
<wd-icon name="person" size="20" color="var(--color-text-placeholder)" />
<input
v-model="formData.username"
@@ -47,7 +47,7 @@
</view>
<!-- 密码 -->
<view v-if="loginMode === 'PASSWORD'" class="login__field">
<view v-if="loginMode === 'PASSWORD'" class="login__form-item login__field">
<wd-icon name="lock" size="20" color="var(--color-text-placeholder)" />
<input
v-model="formData.password"
@@ -60,7 +60,7 @@
</view>
<!-- 图形验证码(密码登录时显示) -->
<view v-if="loginMode === 'PASSWORD'" class="login__field">
<view v-if="loginMode === 'PASSWORD'" class="login__form-item login__field">
<wd-icon name="shield" size="20" color="var(--color-text-placeholder)" />
<input
v-model="formData.captchaCode"
@@ -79,7 +79,7 @@
</view>
<!-- 短信验证码 -->
<view v-else class="login__field">
<view v-else class="login__form-item login__field">
<wd-icon name="shield" size="20" color="var(--color-text-placeholder)" />
<input
v-model="formData.code"
@@ -99,17 +99,19 @@
</view>
<!-- 演示环境提示 -->
<view v-if="loginMode === 'SMS'" class="login__demo-hint">
<view v-if="loginMode === 'SMS'" class="login__form-item login__demo-hint">
<text class="login__demo-hint-text">演示环境验证码:123456</text>
</view>
<!-- 登录按钮 -->
<wd-button type="primary" block :loading="loading" @click="handleLogin">
登 录
</wd-button>
<view class="login__form-item">
<wd-button type="primary" block :loading="loading" @click="handleLogin">
登 录
</wd-button>
</view>
<!-- 切换登录方式 -->
<view class="login__mode-switch" @click="toggleLoginMode">
<view class="login__form-item login__mode-switch" @click="toggleLoginMode">
<text class="login__mode-switch-text">
{{ loginMode === "PASSWORD" ? "忘记密码?" : "记得密码?" }}
</text>
@@ -122,17 +124,19 @@
<!-- #ifdef MP-WEIXIN -->
<!-- 微信登录区域 -->
<view v-else class="login__form">
<button
class="login__wx-btn"
open-type="getPhoneNumber"
@getphonenumber="handleWechatPhoneLogin"
>
<image class="login__wx-btn-icon" src="/static/icons/weixin.png" mode="aspectFit" />
微信一键登录
</button>
<view class="login__form-item">
<button
class="login__wx-btn"
open-type="getPhoneNumber"
@getphonenumber="handleWechatPhoneLogin"
>
<image class="login__wx-btn-icon" src="/static/icons/weixin.png" mode="aspectFit" />
微信一键登录
</button>
</view>
<!-- 其他登录方式 -->
<view class="login__mode-switch" @click="loginMode = 'PASSWORD'">
<view class="login__form-item login__mode-switch" @click="loginMode = 'PASSWORD'">
<text class="login__mode-switch-text">其他登录方式</text>
<text class="login__mode-switch-link">账号登录</text>
</view>
@@ -159,7 +163,7 @@
<!-- 协议勾选 -->
<view class="login__policy">
<wd-checkbox v-model="isAgreePolicy" shape="square" size="16px">
<wd-checkbox v-model="isAgreePolicy" shape="square" size="32rpx">
<text class="login__policy-text">
我已阅读并同意
<text class="login__policy-link" @click.stop="navigateToAgreement('user')">
@@ -575,7 +579,10 @@ onUnload(() => {
// ==========================================================================
.login__decoration {
position: fixed;
inset: 0;
top: 0;
right: 0;
bottom: 0;
left: 0;
overflow: hidden;
pointer-events: none;
}
@@ -586,18 +593,18 @@ onUnload(() => {
border-radius: 50%;
&--1 {
top: -80px;
left: -80px;
width: 240px;
height: 240px;
top: -160rpx;
left: -160rpx;
width: 480rpx;
height: 480rpx;
background-color: rgba(96, 165, 250, 0.2);
}
&--2 {
right: -80px;
bottom: -80px;
width: 320px;
height: 320px;
right: -160rpx;
bottom: -160rpx;
width: 640rpx;
height: 640rpx;
background-color: rgba(59, 130, 246, 0.15);
}
}
@@ -611,7 +618,7 @@ onUnload(() => {
left: 0;
right: 0;
z-index: var(--z-navbar);
padding: 0 16px;
padding: 0 32rpx;
}
.login__navbar-bar {
@@ -636,8 +643,8 @@ onUnload(() => {
.login__navbar-btn {
left: 0;
background-color: rgba(255, 255, 255, 0.18);
border: 1px solid rgba(255, 255, 255, 0.35);
border-radius: 999px;
border: 2rpx solid rgba(255, 255, 255, 0.35);
border-radius: 999rpx;
&--active {
opacity: 0.8;
@@ -670,7 +677,7 @@ onUnload(() => {
display: flex;
flex-direction: column;
align-items: center;
padding: 0 48px;
padding: 0 96rpx;
}
// ==========================================================================
@@ -680,18 +687,18 @@ onUnload(() => {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 8px;
margin-bottom: 36px;
margin-top: 16rpx;
margin-bottom: 72rpx;
}
.login__logo {
width: 80px;
height: 80px;
margin-bottom: 16px;
width: 160rpx;
height: 160rpx;
margin-bottom: 32rpx;
}
.login__brand-name {
font-size: 20px;
font-size: 40rpx;
font-weight: 600;
letter-spacing: 0.05em;
color: var(--color-text);
@@ -702,41 +709,40 @@ onUnload(() => {
// ==========================================================================
.login__card {
width: 100%;
padding: 32px;
padding: 64rpx;
background-color: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(24px);
border-radius: 24px;
box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1);
border-radius: 48rpx;
box-shadow: 0 20rpx 50rpx -10rpx rgba(0, 0, 0, 0.1);
}
// 卡片头部
.login__card-head {
margin-bottom: 32px;
margin-bottom: 64rpx;
text-align: center;
}
.login__card-title {
font-size: 24px;
font-size: 48rpx;
font-weight: 700;
color: var(--color-text);
}
.login__card-subtitle {
display: block;
margin-top: 8px;
font-size: 14px;
margin-top: 16rpx;
font-size: 28rpx;
color: var(--color-text-secondary);
}
// ==========================================================================
// 表单区域
// ==========================================================================
.login__form {
> view,
> button {
&:not(:first-child) {
margin-top: 16px;
}
.login__form-item {
margin-top: 32rpx;
&:first-child {
margin-top: 0;
}
}
@@ -744,29 +750,25 @@ onUnload(() => {
.login__field {
display: flex;
align-items: center;
height: 48px;
padding: 0 16px;
height: 96rpx;
padding: 0 32rpx;
background-color: var(--color-bg-secondary);
border-radius: 12px;
&:focus-within {
box-shadow: 0 0 0 2px var(--color-primary);
}
border-radius: 24rpx;
}
.login__field-input {
flex: 1;
height: 100%;
margin-left: 12px;
font-size: 14px;
margin-left: 24rpx;
font-size: 28rpx;
color: var(--color-text);
}
// 图形验证码图片
.login__captcha-img {
width: 100px;
height: 36px;
border-radius: 6px;
width: 200rpx;
height: 72rpx;
border-radius: 12rpx;
}
// ==========================================================================
@@ -777,13 +779,13 @@ onUnload(() => {
align-items: center;
justify-content: center;
width: 100%;
height: 48px;
font-size: 16px;
height: 96rpx;
font-size: 32rpx;
font-weight: 600;
color: #fff;
background-color: #22c55e;
border-radius: 12px;
box-shadow: 0 10px 15px -3px rgba(34, 197, 94, 0.3);
color: var(--color-text-inverse);
background-color: var(--color-wx-green);
border-radius: 24rpx;
box-shadow: 0 20rpx 30rpx -6rpx rgba(34, 197, 94, 0.3);
&:active {
transform: scale(0.98);
@@ -791,9 +793,9 @@ onUnload(() => {
}
.login__wx-btn-icon {
width: 20px;
height: 20px;
margin-right: 8px;
width: 40rpx;
height: 40rpx;
margin-right: 16rpx;
}
// ==========================================================================
@@ -803,15 +805,11 @@ onUnload(() => {
display: flex;
align-items: center;
justify-content: center;
height: 32px;
padding: 0 16px;
font-size: 14px;
height: 64rpx;
padding: 0 32rpx;
font-size: 28rpx;
font-weight: 500;
border-radius: 8px;
transition:
background-color 0.2s,
color 0.2s;
border-radius: 16rpx;
&--active {
color: var(--color-primary);
background-color: var(--color-primary-light);
@@ -829,20 +827,20 @@ onUnload(() => {
.login__mode-switch {
display: flex;
justify-content: center;
padding-top: 16px;
padding-top: 32rpx;
}
.login__mode-switch-text {
font-size: 14px;
font-size: 28rpx;
color: var(--color-text-secondary);
}
.login__mode-switch-link {
margin-left: 4px;
font-size: 14px;
margin-left: 8rpx;
font-size: 28rpx;
font-weight: 500;
color: var(--color-primary);
border-bottom: 1px solid var(--color-primary);
border-bottom: 2rpx solid var(--color-primary);
}
// ==========================================================================
@@ -851,18 +849,18 @@ onUnload(() => {
.login__divider {
display: flex;
align-items: center;
margin: 24px 0;
margin: 48rpx 0;
}
.login__divider-line {
flex: 1;
height: 1px;
height: 2rpx;
background-color: var(--color-border);
}
.login__divider-text {
padding: 0 16px;
font-size: 12px;
padding: 0 32rpx;
font-size: 24rpx;
color: var(--color-text-placeholder);
}
@@ -872,12 +870,12 @@ onUnload(() => {
.login__oauth-row {
display: flex;
justify-content: center;
gap: 32px;
gap: 64rpx;
}
.login__wx-icon {
width: 40px;
height: 40px;
width: 80rpx;
height: 80rpx;
&:active {
transform: scale(0.95);
@@ -891,13 +889,13 @@ onUnload(() => {
display: flex;
align-items: flex-start;
justify-content: center;
padding-top: 16px;
margin-top: 24px;
border-top: 1px solid var(--color-border-light);
padding-top: 32rpx;
margin-top: 48rpx;
border-top: 2rpx solid var(--color-border-light);
}
.login__policy-text {
font-size: 12px;
font-size: 24rpx;
line-height: 1.5;
color: var(--color-text-secondary);
}
@@ -910,13 +908,13 @@ onUnload(() => {
// 绑定手机号弹窗
// ==========================================================================
.login__bind-panel {
padding: 24px;
padding: 48rpx;
}
.login__bind-panel-title {
display: block;
margin-bottom: 24px;
font-size: 18px;
margin-bottom: 48rpx;
font-size: 36rpx;
font-weight: 600;
text-align: center;
color: var(--color-text);
@@ -928,14 +926,14 @@ onUnload(() => {
.login__demo-hint {
display: flex;
justify-content: center;
margin-top: 12px;
margin-top: 24rpx;
}
.login__demo-hint-text {
padding: 4px 12px;
font-size: 12px;
padding: 8rpx 24rpx;
font-size: 24rpx;
color: var(--color-warning);
background-color: var(--color-warning-light);
border-radius: 4px;
border-radius: 8rpx;
}
</style>

View File

@@ -1,21 +1,17 @@
<template>
<view class="page page--padding">
<wd-card>
<view class="flex items-center p-20rpx">
<image
class="w-120rpx h-120rpx mr-16rpx"
src="/static/logo.png"
mode="aspectFit"
/>
<view class="flex-1">
<text class="app-title">youlai-app</text>
<text class="app-version">版本 {{ version }}</text>
<view class="about__header">
<image class="about__logo" src="/static/logo.png" mode="aspectFit" />
<view class="about__info">
<text class="about__app-title">youlai-app</text>
<text class="about__app-version">版本 {{ version }}</text>
</view>
</view>
<view class="px-20rpx pb-20rpx">
<text class="intro-title">项目介绍</text>
<text class="intro-desc">
<view class="about__intro">
<text class="about__intro-title">项目介绍</text>
<text class="about__intro-desc">
一个基于 uni-app + Vue 3 + TypeScript 的移动端模板,内置主题系统与 wot-design-uni
组件库。同时提供管理端与多后端版本(Java / Gin / Nest / Django / ThinkPHP /
ASP.NET),并包含多租户实现。
@@ -30,7 +26,7 @@
<wd-cell
title="vue3-element-admin"
icon="desktop"
title-width="200px"
title-width="400rpx"
value="简介"
clickable
@click="openProjectIntro('vue3-element-admin')"
@@ -38,7 +34,7 @@
<wd-cell
title="vue3-element-admin-js"
icon="desktop"
title-width="200px"
title-width="400rpx"
value="简介"
clickable
@click="openProjectIntro('vue3-element-admin-js')"
@@ -46,7 +42,7 @@
<wd-cell
title="vue3-element-template"
icon="desktop"
title-width="200px"
title-width="400rpx"
value="简介"
clickable
@click="openProjectIntro('vue3-element-template')"
@@ -59,7 +55,7 @@
<wd-cell
title="youlai-app"
icon="mobile"
title-width="200px"
title-width="400rpx"
value="简介"
clickable
@click="openProjectIntro('youlai-app')"
@@ -72,7 +68,7 @@
<wd-cell
title="youlai-boot"
icon="server"
title-width="200px"
title-width="400rpx"
value="简介"
clickable
@click="openProjectIntro('youlai-boot')"
@@ -80,7 +76,7 @@
<wd-cell
title="youlai-gin"
icon="server"
title-width="200px"
title-width="400rpx"
value="简介"
clickable
@click="openProjectIntro('youlai-gin')"
@@ -88,7 +84,7 @@
<wd-cell
title="youlai-nest"
icon="server"
title-width="200px"
title-width="400rpx"
value="简介"
clickable
@click="openProjectIntro('youlai-nest')"
@@ -96,7 +92,7 @@
<wd-cell
title="youlai-django"
icon="server"
title-width="200px"
title-width="400rpx"
value="简介"
clickable
@click="openProjectIntro('youlai-django')"
@@ -104,7 +100,7 @@
<wd-cell
title="youlai-think"
icon="server"
title-width="200px"
title-width="400rpx"
value="简介"
clickable
@click="openProjectIntro('youlai-think')"
@@ -112,7 +108,7 @@
<wd-cell
title="youlai-aspnet"
icon="server"
title-width="200px"
title-width="400rpx"
value="简介"
clickable
@click="openProjectIntro('youlai-aspnet')"
@@ -125,7 +121,7 @@
<wd-cell
title="youlai-boot-tenant"
icon="server"
title-width="200px"
title-width="400rpx"
value="简介"
clickable
@click="openProjectIntro('youlai-boot-tenant')"
@@ -161,21 +157,21 @@
</wd-cell-group>
</wd-card>
<view class="py-32rpx text-center">
<text class="copyright">Copyright {{ getYear() }} 有来开源组织</text>
<text class="copyright mt-8rpx">All Rights Reserved</text>
<view class="about__footer">
<text class="about__copyright">Copyright {{ getYear() }} 有来开源组织</text>
<text class="about__copyright about__copyright--sub">All Rights Reserved</text>
</view>
<wd-popup v-model="introPopupVisible" position="bottom">
<view class="p-24rpx">
<view class="text-32rpx font-700">{{ currentProject?.title }}</view>
<view v-if="currentProject?.stack" class="mt-12rpx text-26rpx text-secondary">
<view class="about__popup">
<view class="about__popup-title">{{ currentProject?.title }}</view>
<view v-if="currentProject?.stack" class="about__popup-stack">
技术栈:{{ currentProject.stack }}
</view>
<view v-if="currentProject?.summary" class="mt-12rpx text-26rpx text-secondary">
<view v-if="currentProject?.summary" class="about__popup-summary">
{{ currentProject.summary }}
</view>
<view class="mt-20rpx">
<view class="about__popup-action">
<wd-button type="primary" block @click="goCurrentProjectRepo">去仓库</wd-button>
</view>
</view>
@@ -338,55 +334,88 @@ onMounted(() => {
}
}
.app-title {
// ==========================================================================
// 头部区域(Logo + 应用信息)
// ==========================================================================
.about__header {
display: flex;
align-items: center;
padding: 20rpx;
}
.about__logo {
width: 120rpx;
height: 120rpx;
margin-right: 16rpx;
}
.about__info {
flex: 1;
}
.about__app-title {
display: block;
margin-bottom: 8rpx;
font-size: 32rpx;
font-weight: 700;
}
.app-version {
.about__app-version {
display: block;
font-size: 24rpx;
color: var(--color-text-secondary);
}
.intro-title {
.about__intro-title {
display: block;
margin-bottom: 8rpx;
font-size: 28rpx;
font-weight: 500;
}
.intro-desc {
.about__intro-desc {
display: block;
font-size: 24rpx;
line-height: 1.6;
color: var(--color-text-secondary);
}
.section-title {
display: flex;
align-items: center;
margin-bottom: 12rpx;
font-size: 28rpx;
font-weight: 500;
:deep(.wd-icon) {
margin-right: 12rpx;
}
.about__intro {
padding: 0 20rpx 20rpx;
}
.section-subtitle {
display: block;
padding-left: 32rpx;
font-size: 24rpx;
color: var(--color-text-secondary);
.about__footer {
padding: 32rpx 0;
text-align: center;
}
.copyright {
.about__copyright {
display: block;
font-size: 24rpx;
color: var(--color-text-placeholder);
&--sub {
margin-top: 8rpx;
}
}
.about__popup {
padding: 24rpx;
}
.about__popup-title {
font-size: 32rpx;
font-weight: 700;
}
.about__popup-stack,
.about__popup-summary {
margin-top: 12rpx;
font-size: 26rpx;
color: var(--color-text-secondary);
}
.about__popup-action {
margin-top: 20rpx;
}
</style>

View File

@@ -1,5 +1,5 @@
<template>
<view class="page account-page dark:text-[var(--wot-color-text)] py-2">
<view class="page account-page">
<wd-card>
<wd-cell-group border>
<wd-cell
@@ -73,7 +73,7 @@
:rules="rules.confirmPassword"
/>
</wd-cell-group>
<view class="p-6">
<view class="account-page__submit">
<wd-button type="primary" size="large" block @click="handleSubmit">提交</wd-button>
</view>
</wd-form>
@@ -113,7 +113,7 @@
</template>
</wd-input>
</wd-cell-group>
<view class="p-6">
<view class="account-page__submit">
<wd-button type="primary" size="large" block @click="handleSubmit">提交</wd-button>
</view>
</wd-form>
@@ -153,7 +153,7 @@
</template>
</wd-input>
</wd-cell-group>
<view class="p-6">
<view class="account-page__submit">
<wd-button type="primary" size="large" block @click="handleSubmit">提交</wd-button>
</view>
</wd-form>
@@ -162,6 +162,7 @@
</template>
<script setup lang="ts">
import { onMounted, onUnmounted, reactive, ref } from "vue";
import { useToast, useMessage } from "wot-design-uni";
import UserAPI, {
PasswordChangeForm,
MobileBindingForm,
@@ -169,6 +170,9 @@ import UserAPI, {
UserProfile,
} from "@/api/user";
const toast = useToast();
const { messageBox } = useMessage();
const validatorConfirmPassword = (value: string) => {
if (!value) {
return Promise.reject("请确认密码");
@@ -223,7 +227,11 @@ const emailTimer = ref<ReturnType<typeof setTimeout> | null>(null);
const handleUnbindWechat = async () => {
try {
await messageBox({ title: "提示", msg: "确定要解绑微信吗?解绑后将无法使用微信小程序登录", type: "warning" });
await messageBox({
title: "提示",
msg: "确定要解绑微信吗?解绑后将无法使用微信小程序登录",
type: "warning",
});
await UserAPI.unbindSocial("WECHAT_MINI");
toast.success("解绑成功");
loadUserProfile();
@@ -352,4 +360,11 @@ onUnmounted(() => {
});
</script>
<style lang="scss" scoped>
.account-page {
padding: 16rpx 0;
}
.account-page__submit {
padding: 24rpx;
}
</style>

View File

@@ -481,7 +481,6 @@ const openOfficialAccount = () => {
letter-spacing: 2rpx;
}
.profile-card__status,
.profile-tag,
.profile-card__gender {
display: inline-flex;
@@ -626,17 +625,6 @@ const openOfficialAccount = () => {
text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.1);
}
.profile-card__status {
flex-shrink: 0;
padding: 8rpx 16rpx;
font-size: 20rpx;
font-weight: 500;
color: rgba(255, 255, 255, 0.95);
background: rgba(255, 255, 255, 0.2);
border: 1rpx solid rgba(255, 255, 255, 0.3);
border-radius: 20rpx;
}
.profile-card__desc {
display: -webkit-box;
margin-top: 12rpx;
@@ -700,7 +688,10 @@ const openOfficialAccount = () => {
.community-card__bg {
position: absolute;
inset: 0;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: var(--z-base);
width: 100%;
height: 100%;
@@ -710,7 +701,10 @@ const openOfficialAccount = () => {
.community-card__mask {
position: absolute;
inset: 0;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: var(--z-sticky);
background: linear-gradient(
90deg,
@@ -722,7 +716,10 @@ const openOfficialAccount = () => {
.community-card__sparkle {
position: absolute;
inset: 0;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: var(--z-sticky);
pointer-events: none;
background:
@@ -740,7 +737,7 @@ const openOfficialAccount = () => {
height: 84rpx;
padding: 10rpx;
background: rgba(255, 255, 255, 0.96);
border: 1rpx solid rgba(148, 163, 184, 0.22);
border: 1rpx solid var(--color-border-glass);
border-radius: 20rpx;
box-shadow: 0 6rpx 18rpx rgba(15, 23, 42, 0.06);
}
@@ -776,7 +773,7 @@ const openOfficialAccount = () => {
font-size: 32rpx;
font-weight: 600;
color: var(--color-text);
letter-spacing: 0.2px;
letter-spacing: 0.4rpx;
}
:deep(.community-card__tag) {
@@ -784,7 +781,6 @@ const openOfficialAccount = () => {
}
.community-card__desc {
display: block;
display: -webkit-box;
margin-top: 10rpx;
overflow: hidden;
@@ -823,7 +819,6 @@ const openOfficialAccount = () => {
background: var(--color-bg);
border-radius: 24rpx;
box-shadow: 0 8rpx 24rpx rgba(15, 23, 42, 0.04);
transition: all 0.2s ease;
}
.quick-card:active {
@@ -936,7 +931,7 @@ const openOfficialAccount = () => {
}
.menu-row + .menu-row {
border-top: 1rpx solid rgba(148, 163, 184, 0.14);
border-top: 1rpx solid var(--color-border-light);
}
.menu-row__main {
@@ -987,7 +982,7 @@ const openOfficialAccount = () => {
background: var(--color-bg);
border: 1rpx solid rgba(239, 68, 68, 0.18);
border-radius: 24rpx;
box-shadow: 0 12rpx 30rpx rgba(239, 68, 68, 0.08);
box-shadow: 0 12rpx 30rpx var(--color-danger-shadow);
}
:deep(.loading-center) {

View File

@@ -1,9 +1,9 @@
<template>
<view class="page">
<!-- 头部 -->
<view class="hero">
<view class="hero__title">完善个人信息</view>
<view class="hero__subtitle">为了给您提供更好的服务,请完善以下信息</view>
<view class="complete-profile__hero">
<view class="complete-profile__hero-title">完善个人信息</view>
<view class="complete-profile__hero-subtitle">为了给您提供更好的服务,请完善以下信息</view>
</view>
<!-- 表单 -->
@@ -121,12 +121,12 @@
<script lang="ts" setup>
import { ref, reactive, computed } from "vue";
import { onLoad } from "@dcloudio/uni-app";
import { useToast, useMessage } from "wot-design-uni";
import { useUserStore } from "@/store";
import UserAPI, { type UserProfileForm } from "@/api/user";
import FileAPI, { type FileInfo } from "@/api/file";
const toast = useToast();
const { messageBox } = useMessage();
const userStore = useUserStore();
const redirect = ref("/pages/index/index");
@@ -267,22 +267,22 @@ const handleSkip = async () => {
</script>
<style lang="scss" scoped>
.hero {
.complete-profile__hero {
margin-bottom: 60rpx;
text-align: center;
}
&__title {
margin-bottom: 20rpx;
font-size: 48rpx;
font-weight: bold;
color: var(--color-text-inverse);
}
.complete-profile__hero-title {
margin-bottom: 20rpx;
font-size: 48rpx;
font-weight: bold;
color: var(--color-text-inverse);
}
&__subtitle {
font-size: 28rpx;
line-height: 1.5;
color: rgba(255, 255, 255, 0.8);
}
.complete-profile__hero-subtitle {
font-size: 28rpx;
line-height: 1.5;
color: rgba(255, 255, 255, 0.8);
}
.profile-form {

View File

@@ -1,17 +1,21 @@
<template>
<view class="page dark:text-[var(--wot-color-text)]">
<view class="page">
<view class="profile-content">
<view class="pt-20rpx">
<view class="profile-content__card-area">
<wd-card v-if="userProfile">
<wd-cell-group border>
<wd-cell class="avatar-cell" title="头像" center is-link>
<view class="avatar">
<view v-if="!userProfile.avatar" class="img" @click="handleAvatarUpload">
<wd-icon name="fill-camera" custom-class="img-icon" />
<view class="avatar-cell__avatar">
<view
v-if="!userProfile.avatar"
class="avatar-cell__img"
@click="handleAvatarUpload"
>
<wd-icon name="fill-camera" custom-class="avatar-cell__img-icon" />
</view>
<image
v-if="userProfile.avatar"
class="img"
class="avatar-cell__img"
:src="userProfile.avatar"
mode="aspectFit"
@click="handleAvatarUpload"
@@ -63,7 +67,7 @@
</wd-radio-group>
</wd-cell>
</wd-cell-group>
<view class="p-6">
<view class="edit-form__submit">
<wd-button type="primary" size="large" block @click="handleSubmit">提交</wd-button>
</view>
</wd-form>
@@ -185,28 +189,40 @@ function handleTouchMove(event: TouchEvent) {
:deep(.wd-cell__body) {
align-items: center;
}
.avatar {
display: flex;
align-items: center;
justify-content: right;
.img {
position: relative;
width: 80px;
height: 80px;
background-color: rgba(0, 0, 0, 0.04);
border-radius: 50%;
.img-icon {
position: absolute;
top: 50%;
left: 50%;
color: var(--color-text-inverse);
}
}
}
}
.avatar-cell__avatar {
display: flex;
align-items: center;
justify-content: right;
}
.avatar-cell__img {
position: relative;
width: 160rpx;
height: 160rpx;
background-color: rgba(0, 0, 0, 0.04);
border-radius: 50%;
}
.profile-content__card-area {
padding-top: 20rpx;
}
.avatar-cell__img-icon {
position: absolute;
top: 50%;
left: 50%;
color: var(--color-text-inverse);
}
.edit-form {
padding-top: 40rpx;
&__submit {
padding: 24rpx;
}
.ef-radio-group {
line-height: 1;
text-align: left;

View File

@@ -1,5 +1,5 @@
<template>
<view class="page-container dark:text-[var(--wot-color-text)]">
<view class="page">
<wd-collapse v-model="activeNames" accordion>
<wd-collapse-item
v-for="(section, index) in agreementContent"
@@ -7,13 +7,13 @@
:title="section.title"
:name="String(index)"
>
<view class="py-3 px-4">
<text class="text-base leading-relaxed text-gray-600">{{ section.content }}</text>
<view class="agreement__content">
<text class="agreement__text">{{ section.content }}</text>
</view>
</wd-collapse-item>
</wd-collapse>
<view class="mt-6 px-4">
<view class="agreement__action">
<wd-button type="primary" block @click="handleAgree">我已阅读并同意</wd-button>
</view>
</view>
@@ -76,4 +76,19 @@ const handleAgree = () => {
}
</route>
<style lang="scss" scoped></style>
<style lang="scss" scoped>
.agreement__content {
padding: 24rpx 32rpx;
}
.agreement__text {
font-size: 28rpx;
line-height: 1.6;
color: var(--color-text-secondary);
}
.agreement__action {
margin-top: 48rpx;
padding: 0 32rpx;
}
</style>

View File

@@ -1,5 +1,5 @@
<template>
<view class="page-container dark:text-[var(--wot-color-text)]">
<view class="page">
<wd-cell-group>
<wd-cell title="主题设置" icon="setting1" is-link @click="navigateToTheme" />
<wd-cell title="用户协议" icon="user" is-link @click="navigateToUserAgreement" />
@@ -186,7 +186,6 @@ onLoad(() => {
font-size: 32rpx;
font-weight: bold;
border-radius: 40rpx;
transition: all 0.3s ease;
&:active {
opacity: 0.8;

View File

@@ -1,28 +1,30 @@
<template>
<view class="page">
<view class="px-32rpx py-24rpx">
<text class="text-sm" style="color: var(--color-text-placeholder)">温馨提示:点击下方「开始测试」按钮,即可自动检测当前网络延迟。</text>
<view class="network__tip">
<text class="network__tip-text">
温馨提示:点击下方「开始测试」按钮,即可自动检测当前网络延迟。
</text>
</view>
<view class="px-32rpx">
<view class="network__action">
<wd-button block plain @click="startTest">开始测试</wd-button>
</view>
<view v-if="isTesting" class="flex-col-center py-40rpx">
<view v-if="isTesting" class="network__loading">
<wd-loading color="var(--wot-color-theme)" />
<text class="mt-16rpx text-sm" style="color: var(--color-text-secondary)">正在测试中...</text>
<text class="network__loading-text">正在测试中...</text>
</view>
<view v-if="result !== null" class="px-32rpx">
<view v-if="result !== null" class="network__result">
<view class="result-card">
<view class="result-card__header">测试结果</view>
<view class="result-card__row">
<text style="color: var(--color-text-secondary)">网络延迟</text>
<text :class="['text-36rpx font-semibold', statusColor]">{{ result }}ms</text>
<text :class="['network__delay', statusColor]">{{ result }}ms</text>
</view>
<view class="result-card__row">
<text style="color: var(--color-text-secondary)">网络状态</text>
<text :class="['font-medium', statusColor]">{{ statusText }}</text>
<text :class="['network__status', statusColor]">{{ statusText }}</text>
</view>
</view>
</view>
@@ -95,14 +97,14 @@ onLoad(() => {
.result-card {
background: var(--color-bg);
border-radius: 16rpx;
border: 1px solid var(--color-border);
border: 1rpx solid var(--color-border);
overflow: hidden;
&__header {
padding: 24rpx;
font-size: 32rpx;
font-weight: 600;
border-bottom: 1px solid var(--color-border);
border-bottom: 1rpx solid var(--color-border);
}
&__row {
@@ -112,13 +114,63 @@ onLoad(() => {
padding: 24rpx;
& + & {
border-top: 1px solid var(--color-border-light);
border-top: 1rpx solid var(--color-border-light);
}
}
}
.color-success { color: var(--color-success); }
.color-primary { color: var(--color-primary); }
.color-warning { color: var(--color-warning); }
.color-danger { color: var(--color-danger); }
.network__tip {
padding: 24rpx 32rpx;
}
.network__tip-text {
font-size: 24rpx;
color: var(--color-text-placeholder);
}
.network__action {
padding: 0 32rpx;
}
.network__loading {
display: flex;
flex-direction: column;
align-items: center;
padding: 40rpx 0;
}
.network__loading-text {
margin-top: 16rpx;
font-size: 24rpx;
color: var(--color-text-secondary);
}
.network__result {
padding: 0 32rpx;
}
.network__delay {
font-size: 36rpx;
font-weight: 600;
}
.network__status {
font-weight: 500;
}
.color-success {
color: var(--color-success);
}
.color-primary {
color: var(--color-primary);
}
.color-warning {
color: var(--color-warning);
}
.color-danger {
color: var(--color-danger);
}
</style>

View File

@@ -1,5 +1,5 @@
<template>
<view class="page-container dark:text-[var(--wot-color-text)]">
<view class="page">
<wd-collapse v-model="activeNames" accordion>
<wd-collapse-item
v-for="(section, index) in privacyContent"
@@ -7,13 +7,13 @@
:title="section.title"
:name="String(index)"
>
<view class="py-3 px-4">
<text class="text-base leading-relaxed text-gray-600">{{ section.content }}</text>
<view class="privacy__content">
<text class="privacy__text">{{ section.content }}</text>
</view>
</wd-collapse-item>
</wd-collapse>
<view class="mt-6 px-4">
<view class="privacy__action">
<wd-button type="primary" block @click="handleAgree">我已阅读并同意</wd-button>
</view>
</view>
@@ -91,4 +91,19 @@ const handleAgree = () => {
}
</route>
<style lang="scss" scoped></style>
<style lang="scss" scoped>
.privacy__content {
padding: 24rpx 32rpx;
}
.privacy__text {
font-size: 28rpx;
line-height: 1.6;
color: var(--color-text-secondary);
}
.privacy__action {
margin-top: 48rpx;
padding: 0 32rpx;
}
</style>

View File

@@ -108,10 +108,14 @@
<script lang="ts" setup>
import { useTheme } from "@/composables/useTheme";
import { useToast, useMessage } from "wot-design-uni";
// 使用主题组合函数
const { isDark, themeVars, themeColorOptions, toggleTheme, setThemeColor } = useTheme();
const toast = useToast();
const { messageBox } = useMessage();
// 创建响应式的计算属性
const isDarkMode = computed(() => isDark.value);
@@ -236,7 +240,6 @@ onShow(() => {
height: 48rpx;
cursor: pointer;
border-radius: 50%;
transition: transform 0.2s;
&--active {
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.2);

View File

@@ -43,7 +43,7 @@ body {
}
.page--tabbar {
padding-bottom: calc(50px + env(safe-area-inset-bottom));
padding-bottom: calc(100rpx + env(safe-area-inset-bottom));
}
// 筛选栏

View File

@@ -33,6 +33,7 @@ page {
--color-warning-light: #fff4e6;
--color-danger: #ff4757;
--color-danger-light: #fff1f2;
--color-wx-green: #22c55e;
// -----------------------------------------------------------------------
// 背景色 (Material Design)
@@ -56,13 +57,15 @@ page {
--color-border: #e5e7eb;
--color-border-light: #f3f4f6;
--color-border-dark: #d1d5db;
--color-border-glass: rgba(148, 163, 184, 0.22);
--color-danger-shadow: rgba(239, 68, 68, 0.08);
// -----------------------------------------------------------------------
// 阴影
// -----------------------------------------------------------------------
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1);
--shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1);
--shadow-sm: 0 2rpx 4rpx rgba(0, 0, 0, 0.05);
--shadow-md: 0 8rpx 12rpx rgba(0, 0, 0, 0.1);
--shadow-lg: 0 20rpx 30rpx rgba(0, 0, 0, 0.1);
// -----------------------------------------------------------------------
// wot-design-uni 组件库变量
@@ -113,6 +116,7 @@ page {
--color-warning-light: #78350f;
--color-danger: #f87171;
--color-danger-light: #7f1d1d;
--color-wx-green: #22c55e;
// -----------------------------------------------------------------------
// 背景色 (Material Design) - 不使用纯黑 #000000
@@ -136,13 +140,15 @@ page {
--color-border: #374151;
--color-border-light: #1f2937;
--color-border-dark: #4b5563;
--color-border-glass: rgba(148, 163, 184, 0.15);
--color-danger-shadow: rgba(239, 68, 68, 0.15);
// -----------------------------------------------------------------------
// 阴影
// -----------------------------------------------------------------------
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.2);
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.3);
--shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.4);
--shadow-sm: 0 2rpx 4rpx rgba(0, 0, 0, 0.2);
--shadow-md: 0 8rpx 12rpx rgba(0, 0, 0, 0.3);
--shadow-lg: 0 20rpx 30rpx rgba(0, 0, 0, 0.4);
// -----------------------------------------------------------------------
// wot-design-uni 组件库变量