refactor: ♻️ 暗黑模式适配调整和代码优化
This commit is contained in:
250
.cursor/rules/css-style-guide.mdc
Normal file
250
.cursor/rules/css-style-guide.mdc
Normal file
@@ -0,0 +1,250 @@
|
|||||||
|
---
|
||||||
|
alwaysApply: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# CSS样式与UnoCSS使用规范
|
||||||
|
|
||||||
|
## 样式选择原则
|
||||||
|
|
||||||
|
### UnoCSS原子类使用规则
|
||||||
|
|
||||||
|
- **≤5个原子类**: 直接使用UnoCSS原子类
|
||||||
|
- **>5个原子类**: 必须提取为语义化CSS类,避免模板膨胀
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<!-- ✅ 好的做法:5个以内原子类 -->
|
||||||
|
<view class="flex items-center p-20rpx text-center bg-white"></view>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 优先使用UnoCSS预设shortcuts
|
||||||
|
|
||||||
|
参考 [unocss.config.ts](mdc:unocss.config.ts) 中定义的shortcuts:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 已定义的shortcuts,优先使用
|
||||||
|
"flex-center": "flex justify-center items-center"
|
||||||
|
"flex-start": "flex justify-start items-center"
|
||||||
|
"flex-between": "flex justify-between items-center"
|
||||||
|
"flex-col-center": "flex flex-col items-center"
|
||||||
|
```
|
||||||
|
|
||||||
|
## CSS类命名规范
|
||||||
|
|
||||||
|
### BEM命名规范
|
||||||
|
|
||||||
|
严格遵循BEM (Block\_\_Element--Modifier) 命名规范:
|
||||||
|
|
||||||
|
```scss
|
||||||
|
// Block: 独立的功能组件
|
||||||
|
.user-profile {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Element: Block的子元素
|
||||||
|
.user-profile__avatar {
|
||||||
|
}
|
||||||
|
.user-profile__action {
|
||||||
|
}
|
||||||
|
.user-profile__badge {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modifier: Block或Element的状态/变体
|
||||||
|
.user-profile--dark {
|
||||||
|
}
|
||||||
|
.user-profile__action--active {
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 命名要求
|
||||||
|
|
||||||
|
1. **使用简短、易理解的英文单词**
|
||||||
|
2. **符合业务场景语义**
|
||||||
|
3. **避免缩写,除非是通用缩写**
|
||||||
|
|
||||||
|
```scss
|
||||||
|
// ✅ 好的命名
|
||||||
|
.user-profile__action
|
||||||
|
.stats-card
|
||||||
|
.service-icon
|
||||||
|
.tool-item
|
||||||
|
|
||||||
|
// ❌ 坏的命名
|
||||||
|
.up-act
|
||||||
|
.sc
|
||||||
|
.si
|
||||||
|
.ti
|
||||||
|
```
|
||||||
|
|
||||||
|
## 样式组织原则
|
||||||
|
|
||||||
|
### 1. 复用性判断
|
||||||
|
|
||||||
|
- 同一组合在项目中出现 >3次 → 提取为语义化类
|
||||||
|
- 具备明确语义的区域 → 提取为语义化类
|
||||||
|
- 需要主题适配的样式 → 提取为语义化类
|
||||||
|
|
||||||
|
### 2. 常用组合添加到shortcuts
|
||||||
|
|
||||||
|
当发现重复的原子类组合时,添加到 [unocss.config.ts](mdc:unocss.config.ts):
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
shortcuts: [
|
||||||
|
{
|
||||||
|
// 现有shortcuts...
|
||||||
|
|
||||||
|
// 新增常用组合
|
||||||
|
"card-container": "mx-30rpx my-20rpx bg-white rounded-16rpx shadow-sm",
|
||||||
|
"action-button": "flex-center w-70rpx h-70rpx bg-white bg-opacity-90 rounded-full",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 主题适配
|
||||||
|
|
||||||
|
使用wot-design-uni的CSS变量或自定义变量:
|
||||||
|
|
||||||
|
```scss
|
||||||
|
// ✅ 使用主题变量
|
||||||
|
.service-icon {
|
||||||
|
background-color: var(--wot-color-bg-light, #f3f4f6);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ 响应式主题色
|
||||||
|
:color="themeStore.isDark ? '#fff' : '#333'";
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 暗黑模式适配规则
|
||||||
|
|
||||||
|
#### 优先级顺序
|
||||||
|
|
||||||
|
1. **优先使用wot-design-uni内置变量** - 自动适配暗黑模式
|
||||||
|
2. **使用项目 [theme.scss](mdc:src/styles/theme.scss) 定义的变量** - 统一管理主题色
|
||||||
|
3. **最后考虑组件内部定义** - 仅用于特殊场景
|
||||||
|
|
||||||
|
#### 自定义主题变量定义
|
||||||
|
|
||||||
|
当需要自定义颜色时,必须在 [theme.scss](mdc:src/styles/theme.scss) 中定义:
|
||||||
|
|
||||||
|
```scss
|
||||||
|
/* 在 theme.scss 中添加自定义变量 */
|
||||||
|
:root,
|
||||||
|
page {
|
||||||
|
--custom-text-color: #333333;
|
||||||
|
--custom-bg-color: #ffffff;
|
||||||
|
--custom-border-color: #e5e7eb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wot-theme-dark {
|
||||||
|
--custom-text-color: #ffffff;
|
||||||
|
--custom-bg-color: #1a1a1a;
|
||||||
|
--custom-border-color: #374151;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 组件中使用主题变量
|
||||||
|
|
||||||
|
```scss
|
||||||
|
// ✅ 推荐:使用wot内置变量
|
||||||
|
.my-component {
|
||||||
|
background-color: var(--wot-card-bg);
|
||||||
|
color: var(--wot-color-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ 推荐:使用theme.scss定义的变量
|
||||||
|
.my-component {
|
||||||
|
background-color: var(--custom-bg-color);
|
||||||
|
border-color: var(--custom-border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ❌ 避免:组件内部硬编码暗黑模式
|
||||||
|
.my-component {
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
.wot-theme-dark .my-component {
|
||||||
|
background-color: #1a1a1a;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 图标和文字颜色适配
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<!-- ✅ 推荐:使用计算属性适配 -->
|
||||||
|
<wd-icon :color="iconColor" />
|
||||||
|
|
||||||
|
<!-- ✅ 推荐:使用CSS变量 -->
|
||||||
|
<text style="color: var(--wot-color-text)">文本</text>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
// 图标颜色适配
|
||||||
|
const iconColor = computed(() => (themeStore.isDark ? "#ffffff" : "#333333"));
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 实践示例
|
||||||
|
|
||||||
|
### 数据统计卡片
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<!-- 使用wot组件 + 少量原子类 -->
|
||||||
|
<wd-card custom-class="mx-30rpx my-20rpx">
|
||||||
|
<wd-grid :column="3" border>
|
||||||
|
<wd-grid-item class="flex-col-center py-20rpx">
|
||||||
|
<view class="text-36rpx font-600">0.00</view>
|
||||||
|
<view class="text-26rpx text-gray-500">我的余额</view>
|
||||||
|
</wd-grid-item>
|
||||||
|
</wd-grid>
|
||||||
|
</wd-card>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 用户操作按钮
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<view class="user-profile__action" @click="handleClick">
|
||||||
|
<wd-icon name="setting1" :color="iconColor" />
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.user-profile__action {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 70rpx;
|
||||||
|
height: 70rpx;
|
||||||
|
background-color: rgba(255, 255, 255, 0.9);
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 禁止项
|
||||||
|
|
||||||
|
❌ **不要在SCSS中重复定义UnoCSS已提供的工具类**
|
||||||
|
❌ **不要使用 `@apply` 指令**
|
||||||
|
❌ **不要把一次性样式放到全局**
|
||||||
|
❌ **不要使用非语义化的类名**
|
||||||
|
❌ **不要在模板中堆叠超过5个原子类**
|
||||||
|
|
||||||
|
## 组件库样式覆盖
|
||||||
|
|
||||||
|
使用wot-design-uni组件时:
|
||||||
|
|
||||||
|
- 使用 `custom-class` 传入类名
|
||||||
|
- 使用 `:deep()` 进行样式穿透
|
||||||
|
- 添加 `!important` 提升优先级
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<wd-button custom-class="logout-button" @click="logout">
|
||||||
|
退出登录
|
||||||
|
</wd-button>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
:deep(.logout-button) {
|
||||||
|
width: 100% !important;
|
||||||
|
height: 80rpx !important;
|
||||||
|
border-radius: 40rpx !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
```
|
||||||
6
components.d.ts
vendored
6
components.d.ts
vendored
@@ -26,7 +26,6 @@ declare module 'vue' {
|
|||||||
WdConfigProvider: typeof import('wot-design-uni/components/wd-config-provider/wd-config-provider.vue')['default']
|
WdConfigProvider: typeof import('wot-design-uni/components/wd-config-provider/wd-config-provider.vue')['default']
|
||||||
WdDivider: typeof import('wot-design-uni/components/wd-divider/wd-divider.vue')['default']
|
WdDivider: typeof import('wot-design-uni/components/wd-divider/wd-divider.vue')['default']
|
||||||
WdForm: typeof import('wot-design-uni/components/wd-form/wd-form.vue')['default']
|
WdForm: typeof import('wot-design-uni/components/wd-form/wd-form.vue')['default']
|
||||||
WdFormItem: typeof import('wot-design-uni/components/wd-form-item/wd-form-item.vue')['default']
|
|
||||||
WdGrid: typeof import('wot-design-uni/components/wd-grid/wd-grid.vue')['default']
|
WdGrid: typeof import('wot-design-uni/components/wd-grid/wd-grid.vue')['default']
|
||||||
WdGridItem: typeof import('wot-design-uni/components/wd-grid-item/wd-grid-item.vue')['default']
|
WdGridItem: typeof import('wot-design-uni/components/wd-grid-item/wd-grid-item.vue')['default']
|
||||||
WdIcon: typeof import('wot-design-uni/components/wd-icon/wd-icon.vue')['default']
|
WdIcon: typeof import('wot-design-uni/components/wd-icon/wd-icon.vue')['default']
|
||||||
@@ -35,10 +34,10 @@ declare module 'vue' {
|
|||||||
WdInput: typeof import('wot-design-uni/components/wd-input/wd-input.vue')['default']
|
WdInput: typeof import('wot-design-uni/components/wd-input/wd-input.vue')['default']
|
||||||
WdLoading: typeof import('wot-design-uni/components/wd-loading/wd-loading.vue')['default']
|
WdLoading: typeof import('wot-design-uni/components/wd-loading/wd-loading.vue')['default']
|
||||||
WdMessageBox: typeof import('wot-design-uni/components/wd-message-box/wd-message-box.vue')['default']
|
WdMessageBox: typeof import('wot-design-uni/components/wd-message-box/wd-message-box.vue')['default']
|
||||||
WdNavbar: typeof import('wot-design-uni/components/wd-navbar/wd-navbar.vue')['default']
|
|
||||||
WdNoticeBar: typeof import('wot-design-uni/components/wd-notice-bar/wd-notice-bar.vue')['default']
|
WdNoticeBar: typeof import('wot-design-uni/components/wd-notice-bar/wd-notice-bar.vue')['default']
|
||||||
WdNotify: typeof import('wot-design-uni/components/wd-notify/wd-notify.vue')['default']
|
WdNotify: typeof import('wot-design-uni/components/wd-notify/wd-notify.vue')['default']
|
||||||
WdPopup: typeof import('wot-design-uni/components/wd-popup/wd-popup.vue')['default']
|
WdPopup: typeof import('wot-design-uni/components/wd-popup/wd-popup.vue')['default']
|
||||||
|
WdProgress: typeof import('wot-design-uni/components/wd-progress/wd-progress.vue')['default']
|
||||||
WdRadio: typeof import('wot-design-uni/components/wd-radio/wd-radio.vue')['default']
|
WdRadio: typeof import('wot-design-uni/components/wd-radio/wd-radio.vue')['default']
|
||||||
WdRadioGroup: typeof import('wot-design-uni/components/wd-radio-group/wd-radio-group.vue')['default']
|
WdRadioGroup: typeof import('wot-design-uni/components/wd-radio-group/wd-radio-group.vue')['default']
|
||||||
WdStatusTip: typeof import('wot-design-uni/components/wd-status-tip/wd-status-tip.vue')['default']
|
WdStatusTip: typeof import('wot-design-uni/components/wd-status-tip/wd-status-tip.vue')['default']
|
||||||
@@ -47,9 +46,6 @@ declare module 'vue' {
|
|||||||
WdTabbar: typeof import('wot-design-uni/components/wd-tabbar/wd-tabbar.vue')['default']
|
WdTabbar: typeof import('wot-design-uni/components/wd-tabbar/wd-tabbar.vue')['default']
|
||||||
WdTabbarItem: typeof import('wot-design-uni/components/wd-tabbar-item/wd-tabbar-item.vue')['default']
|
WdTabbarItem: typeof import('wot-design-uni/components/wd-tabbar-item/wd-tabbar-item.vue')['default']
|
||||||
WdTag: typeof import('wot-design-uni/components/wd-tag/wd-tag.vue')['default']
|
WdTag: typeof import('wot-design-uni/components/wd-tag/wd-tag.vue')['default']
|
||||||
WdText: typeof import('wot-design-uni/components/wd-text/wd-text.vue')['default']
|
|
||||||
WdTextarea: typeof import('wot-design-uni/components/wd-textarea/wd-textarea.vue')['default']
|
|
||||||
WdToast: typeof import('wot-design-uni/components/wd-toast/wd-toast.vue')['default']
|
WdToast: typeof import('wot-design-uni/components/wd-toast/wd-toast.vue')['default']
|
||||||
WdUpload: typeof import('wot-design-uni/components/wd-upload/wd-upload.vue')['default']
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,7 +95,7 @@
|
|||||||
"@vueuse/core": "9.13.0",
|
"@vueuse/core": "9.13.0",
|
||||||
"pinia": "^2.2.2",
|
"pinia": "^2.2.2",
|
||||||
"vue": "^3.5.13",
|
"vue": "^3.5.13",
|
||||||
"wot-design-uni": "^1.9.1"
|
"wot-design-uni": "^1.13.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@commitlint/cli": "^19.5.0",
|
"@commitlint/cli": "^19.5.0",
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ export default defineUniPages({
|
|||||||
globalStyle: {
|
globalStyle: {
|
||||||
navigationBarBackgroundColor: "@navBgColor",
|
navigationBarBackgroundColor: "@navBgColor",
|
||||||
navigationBarTextStyle: "@navTxtStyle",
|
navigationBarTextStyle: "@navTxtStyle",
|
||||||
navigationBarTitleText: "Wot-Demo",
|
navigationBarTitleText: "vue-uniapp-template",
|
||||||
backgroundColor: "@bgColor",
|
backgroundColor: "@bgColor",
|
||||||
backgroundTextStyle: "@bgTxtStyle",
|
backgroundTextStyle: "@bgTxtStyle",
|
||||||
backgroundColorTop: "@bgColorTop",
|
backgroundColorTop: "@bgColorTop",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { getToken } from "@/utils/storage";
|
import { getToken } from "@/utils/storage";
|
||||||
import { ApiCode } from "@/enums/api-code.enum";
|
import { ApiCode } from "@/enums/api-code-enum";
|
||||||
|
|
||||||
// H5 使用 VITE_APP_BASE_API 作为代理路径,其他平台使用 VITE_APP_API_URL 作为请求路径
|
// H5 使用 VITE_APP_BASE_API 作为代理路径,其他平台使用 VITE_APP_API_URL 作为请求路径
|
||||||
let baseApi = import.meta.env.VITE_APP_API_URL;
|
let baseApi = import.meta.env.VITE_APP_API_URL;
|
||||||
|
|||||||
@@ -66,7 +66,17 @@ export default {
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.page-wraper {
|
.page-wraper {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
// 页面最小高度 = 视窗高度 - 状态栏高度
|
||||||
|
// --window-top: uni-app提供的状态栏高度CSS变量(包含状态栏+导航栏)
|
||||||
min-height: calc(100vh - var(--window-top));
|
min-height: calc(100vh - var(--window-top));
|
||||||
|
|
||||||
|
// 为固定定位的tabbar预留底部空间,避免内容被遮挡
|
||||||
|
// 50px: wd-tabbar组件的固定高度
|
||||||
|
// env(safe-area-inset-bottom): iOS设备底部安全区域高度(iPhone X系列的Home Indicator区域)
|
||||||
|
// 34px: 当设备不支持safe-area-inset-bottom时的降级值(一般Android设备)
|
||||||
|
padding-bottom: calc(50px + env(safe-area-inset-bottom, 34px));
|
||||||
|
|
||||||
background: #f9f9f9;
|
background: #f9f9f9;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,10 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/login/index",
|
"path": "pages/login/index",
|
||||||
"type": "page"
|
"type": "page",
|
||||||
|
"style": {
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/mine/index",
|
"path": "pages/mine/index",
|
||||||
@@ -96,7 +99,7 @@
|
|||||||
"globalStyle": {
|
"globalStyle": {
|
||||||
"navigationBarBackgroundColor": "@navBgColor",
|
"navigationBarBackgroundColor": "@navBgColor",
|
||||||
"navigationBarTextStyle": "@navTxtStyle",
|
"navigationBarTextStyle": "@navTxtStyle",
|
||||||
"navigationBarTitleText": "Wot-Demo",
|
"navigationBarTitleText": "vue-uniapp-template",
|
||||||
"backgroundColor": "@bgColor",
|
"backgroundColor": "@bgColor",
|
||||||
"backgroundTextStyle": "@bgTxtStyle",
|
"backgroundTextStyle": "@bgTxtStyle",
|
||||||
"backgroundColorTop": "@bgColorTop",
|
"backgroundColorTop": "@bgColorTop",
|
||||||
@@ -124,6 +127,5 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"__esModule": true,
|
|
||||||
"subPackages": []
|
"subPackages": []
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,107 +1,103 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="app-container">
|
<view class="login-page dark:text-[var(--wot-dark-color)]">
|
||||||
<!-- 背景图 -->
|
<!-- 背景图 -->
|
||||||
<image src="/static/images/login-bg.svg" mode="aspectFill" class="login-bg" />
|
<image src="/static/images/login-bg.svg" mode="aspectFill" class="login-page__bg" />
|
||||||
|
|
||||||
<!-- Logo和标题区域 -->
|
|
||||||
<view class="header"></view>
|
|
||||||
|
|
||||||
|
<!-- 登录卡片 -->
|
||||||
<view class="login-card">
|
<view class="login-card">
|
||||||
<view class="form-wrap">
|
<!-- 账号密码登录表单 -->
|
||||||
<!-- 账号密码登录表单 -->
|
<wd-form v-if="loginType === 'account'" ref="loginFormRef" :model="loginFormData">
|
||||||
<wd-form v-if="loginType === 'account'" ref="loginFormRef" :model="loginFormData">
|
<!-- 用户名输入框 -->
|
||||||
<!-- 用户名输入框 -->
|
<view class="login-form__item">
|
||||||
<view class="form-item">
|
<wd-icon name="user" size="22" class="mr-20rpx" />
|
||||||
<wd-icon name="user" size="22" class="input-icon" />
|
<input
|
||||||
<input
|
v-model="loginFormData.username"
|
||||||
v-model="loginFormData.username"
|
class="login-form__input"
|
||||||
class="form-input input-transparent"
|
placeholder="请输入用户名"
|
||||||
placeholder="请输入用户名"
|
placeholder-class="login-form__placeholder"
|
||||||
placeholder-class="input-placeholder"
|
/>
|
||||||
/>
|
</view>
|
||||||
</view>
|
<view class="login-form__divider"></view>
|
||||||
<view class="divider"></view>
|
|
||||||
|
|
||||||
<!-- 密码输入框 -->
|
<!-- 密码输入框 -->
|
||||||
<view class="form-item">
|
<view class="login-form__item">
|
||||||
<wd-icon name="lock-on" size="22" class="input-icon" />
|
<wd-icon name="lock-on" size="22" class="mr-20rpx" />
|
||||||
<input
|
<input
|
||||||
v-model="loginFormData.password"
|
v-model="loginFormData.password"
|
||||||
class="form-input input-transparent"
|
class="login-form__input"
|
||||||
:password="!showPassword"
|
:password="!showPassword"
|
||||||
placeholder="请输入密码"
|
placeholder="请输入密码"
|
||||||
placeholder-class="input-placeholder"
|
placeholder-class="login-form__placeholder"
|
||||||
/>
|
/>
|
||||||
<wd-icon
|
<wd-icon
|
||||||
:name="showPassword ? 'eye-open' : 'eye-close'"
|
:name="showPassword ? 'eye-open' : 'eye-close'"
|
||||||
size="18"
|
size="18"
|
||||||
class="eye-icon"
|
class="p-10rpx"
|
||||||
@click="showPassword = !showPassword"
|
@click="showPassword = !showPassword"
|
||||||
/>
|
/>
|
||||||
</view>
|
</view>
|
||||||
<view class="divider"></view>
|
<view class="login-form__divider"></view>
|
||||||
|
|
||||||
<!-- 登录按钮 -->
|
<!-- 登录按钮 -->
|
||||||
<button
|
<button
|
||||||
class="login-btn"
|
class="login-btn"
|
||||||
:disabled="loading"
|
:disabled="loading"
|
||||||
:style="loading ? 'opacity: 0.7;' : ''"
|
:class="{ 'login-btn--loading': loading }"
|
||||||
@click="handleAccountLogin"
|
@click="handleAccountLogin"
|
||||||
>
|
>
|
||||||
{{ loading ? "登录中..." : "账号登录" }}
|
{{ loading ? "登录中..." : "账号登录" }}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<!-- 切换登录方式 -->
|
<!-- 切换登录方式 -->
|
||||||
<view class="switch-login-type" @click="loginType = 'phone'">
|
<view class="login-switch" @click="loginType = 'phone'">
|
||||||
<text>使用手机号一键登录</text>
|
<text>使用手机号一键登录</text>
|
||||||
<wd-icon name="arrow-right" size="12" />
|
<wd-icon name="arrow-right" size="12" />
|
||||||
</view>
|
</view>
|
||||||
</wd-form>
|
</wd-form>
|
||||||
|
|
||||||
<!-- 手机号登录 -->
|
<!-- 手机号登录 -->
|
||||||
<view v-else class="phone-login-form">
|
<view v-else class="phone-login">
|
||||||
<view class="phone-login-title">微信一键登录</view>
|
<view class="phone-login__title">微信一键登录</view>
|
||||||
<view class="phone-login-subtitle">授权后将获取您的手机号</view>
|
<view class="phone-login__subtitle">授权后将获取您的手机号</view>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="wechat-phone-btn"
|
class="wechat-btn"
|
||||||
:disabled="loading"
|
:disabled="loading"
|
||||||
open-type="getPhoneNumber"
|
open-type="getPhoneNumber"
|
||||||
@getphonenumber="handleWechatPhoneLogin"
|
@getphonenumber="handleWechatPhoneLogin"
|
||||||
>
|
>
|
||||||
<wd-icon name="weixin" size="24" color="#ffffff" />
|
<wd-icon name="weixin" size="24" color="#ffffff" />
|
||||||
<text>微信一键登录</text>
|
<text class="ml-16rpx">微信一键登录</text>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<!-- 切换登录方式 -->
|
<!-- 切换登录方式 -->
|
||||||
<view class="switch-login-type" @click="loginType = 'account'">
|
<view class="login-switch" @click="loginType = 'account'">
|
||||||
<text>使用账号密码登录</text>
|
<text>使用账号密码登录</text>
|
||||||
<wd-icon name="arrow-right" size="12" />
|
<wd-icon name="arrow-right" size="12" />
|
||||||
</view>
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 其他登录方式 -->
|
||||||
|
<view class="other-login">
|
||||||
|
<view class="other-login__title">
|
||||||
|
<view class="other-login__line"></view>
|
||||||
|
<text class="other-login__text">其他登录方式</text>
|
||||||
|
<view class="other-login__line"></view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 其他登录方式 -->
|
<view class="flex-center" @click="handleWechatLogin">
|
||||||
<view class="other-login">
|
<view class="wechat-icon">
|
||||||
<view class="other-login-title">
|
<image src="/static/icons/weixin.png" class="w-40rpx h-40rpx" />
|
||||||
<view class="line"></view>
|
|
||||||
<text class="text">其他登录方式</text>
|
|
||||||
<view class="line"></view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="wechat-login" @click="handleWechatLogin">
|
|
||||||
<view class="wechat-icon-wrapper">
|
|
||||||
<image src="/static/icons/weixin.png" class="wechat-icon" />
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
<!-- 底部协议 -->
|
<!-- 底部协议 -->
|
||||||
<view class="agreement">
|
<view class="login-agreement">
|
||||||
<text class="text">登录即同意</text>
|
<text class="login-agreement__text">登录即同意</text>
|
||||||
<text class="link" @click="navigateToUserAgreement">《用户协议》</text>
|
<text class="login-agreement__link" @click="navigateToUserAgreement">《用户协议》</text>
|
||||||
<text class="text">和</text>
|
<text class="login-agreement__text">和</text>
|
||||||
<text class="link" @click="navigateToPrivacy">《隐私政策》</text>
|
<text class="login-agreement__link" @click="navigateToPrivacy">《隐私政策》</text>
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@@ -285,169 +281,87 @@ const navigateToPrivacy = () => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.app-container {
|
// 登录页面主容器
|
||||||
|
.login-page {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
height: 100%;
|
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background-color: var(--wot-color-bg-container);
|
background-color: var(--wot-color-bg-container);
|
||||||
|
|
||||||
|
// 背景图
|
||||||
|
&__bg {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 1;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-bg {
|
// 登录卡片
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header {
|
|
||||||
z-index: 2;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
margin-top: 120rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo {
|
|
||||||
width: 140rpx;
|
|
||||||
height: 140rpx;
|
|
||||||
margin-bottom: 20rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
margin-bottom: 10rpx;
|
|
||||||
font-size: 48rpx;
|
|
||||||
font-weight: bold;
|
|
||||||
color: #ffffff;
|
|
||||||
text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.subtitle {
|
|
||||||
font-size: 28rpx;
|
|
||||||
color: #ffffff;
|
|
||||||
text-align: center;
|
|
||||||
text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-card {
|
.login-card {
|
||||||
z-index: 2;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
width: 90%;
|
|
||||||
margin-top: 80rpx;
|
|
||||||
overflow: hidden;
|
|
||||||
background-color: rgba(255, 255, 255, 0.9);
|
|
||||||
backdrop-filter: blur(10px);
|
|
||||||
border-radius: 24rpx;
|
|
||||||
box-shadow: 0 8rpx 40rpx rgba(0, 0, 0, 0.1);
|
|
||||||
|
|
||||||
.wot-theme-dark & {
|
|
||||||
background-color: rgba(31, 31, 31, 0.95);
|
|
||||||
box-shadow: 0 8rpx 40rpx rgba(0, 0, 0, 0.5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-wrap {
|
|
||||||
padding: 40rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-item {
|
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
z-index: 2;
|
||||||
align-items: center;
|
width: 80%; // 进一步减少宽度,增加更多左右间距
|
||||||
padding: 24rpx 0;
|
padding: 40rpx;
|
||||||
background-color: transparent;
|
margin-top: 200rpx;
|
||||||
|
background-color: var(--wot-card-bg);
|
||||||
|
border-radius: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
.wot-theme-dark & {
|
// 登录表单
|
||||||
background-color: transparent;
|
.login-form {
|
||||||
|
&__item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 24rpx 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.input-icon {
|
&__input {
|
||||||
margin-right: 20rpx;
|
flex: 1;
|
||||||
}
|
height: 60rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
/* 强制所有输入元素为透明背景 */
|
line-height: 60rpx;
|
||||||
input,
|
color: var(--wot-color-text);
|
||||||
.form-input,
|
|
||||||
.input-transparent {
|
|
||||||
flex: 1;
|
|
||||||
height: 60rpx;
|
|
||||||
font-size: 28rpx;
|
|
||||||
line-height: 60rpx;
|
|
||||||
color: #333;
|
|
||||||
background-color: transparent !important;
|
|
||||||
-webkit-box-shadow: none !important;
|
|
||||||
box-shadow: none !important;
|
|
||||||
|
|
||||||
.wot-theme-dark & {
|
|
||||||
color: #f5f5f5;
|
|
||||||
background-color: transparent !important;
|
background-color: transparent !important;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__divider {
|
||||||
|
height: 1px;
|
||||||
|
background-color: var(--wot-color-border-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__placeholder {
|
||||||
|
color: var(--wot-color-text-placeholder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 修复webkit浏览器自动填充问题 */
|
// 登录按钮
|
||||||
input:-webkit-autofill,
|
|
||||||
input:-webkit-autofill:hover,
|
|
||||||
input:-webkit-autofill:focus,
|
|
||||||
input:-webkit-autofill:active {
|
|
||||||
caret-color: var(--wot-color-text);
|
|
||||||
background-color: transparent !important;
|
|
||||||
-webkit-box-shadow: 0 0 0 1000px transparent inset !important;
|
|
||||||
transition: background-color 5000s;
|
|
||||||
-webkit-text-fill-color: var(--wot-color-text) !important;
|
|
||||||
|
|
||||||
.wot-theme-dark & {
|
|
||||||
-webkit-text-fill-color: #f5f5f5 !important;
|
|
||||||
background-color: transparent !important;
|
|
||||||
-webkit-box-shadow: 0 0 0 1000px rgba(31, 31, 31, 0) inset !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 尝试通过更强的选择器覆盖自动填充 */
|
|
||||||
.form-item input,
|
|
||||||
input.form-input,
|
|
||||||
input.input-transparent {
|
|
||||||
-webkit-appearance: none;
|
|
||||||
background: none !important;
|
|
||||||
background-color: transparent !important;
|
|
||||||
border: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.clear-icon,
|
|
||||||
.eye-icon {
|
|
||||||
padding: 10rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.divider {
|
|
||||||
height: 1px;
|
|
||||||
margin: 0;
|
|
||||||
background-color: rgba(0, 0, 0, 0.06);
|
|
||||||
|
|
||||||
.wot-theme-dark & {
|
|
||||||
background-color: rgba(255, 255, 255, 0.15);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-btn {
|
.login-btn {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 88rpx;
|
height: 88rpx;
|
||||||
margin-top: 60rpx;
|
margin-top: 60rpx;
|
||||||
font-size: 32rpx;
|
font-size: 32rpx;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
line-height: 88rpx;
|
|
||||||
color: #fff;
|
color: #fff;
|
||||||
text-align: center;
|
|
||||||
background-color: var(--wot-color-theme);
|
background-color: var(--wot-color-theme);
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 44rpx;
|
border-radius: 44rpx;
|
||||||
|
transition: opacity 0.2s;
|
||||||
|
|
||||||
|
&--loading {
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.switch-login-type {
|
// 切换登录方式
|
||||||
|
.login-switch {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@@ -456,35 +370,29 @@ input.input-transparent {
|
|||||||
color: var(--wot-color-theme);
|
color: var(--wot-color-theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
.phone-login-form {
|
// 手机号登录
|
||||||
|
.phone-login {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 40rpx 0;
|
padding: 40rpx 0;
|
||||||
}
|
|
||||||
|
|
||||||
.phone-login-title {
|
&__title {
|
||||||
margin-bottom: 16rpx;
|
margin-bottom: 16rpx;
|
||||||
font-size: 36rpx;
|
font-size: 36rpx;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: #333;
|
color: var(--wot-color-text);
|
||||||
|
}
|
||||||
|
|
||||||
.wot-theme-dark & {
|
&__subtitle {
|
||||||
color: #f5f5f5;
|
margin-bottom: 60rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: var(--wot-color-text-secondary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.phone-login-subtitle {
|
// 微信按钮
|
||||||
margin-bottom: 60rpx;
|
.wechat-btn {
|
||||||
font-size: 28rpx;
|
|
||||||
color: #666;
|
|
||||||
|
|
||||||
.wot-theme-dark & {
|
|
||||||
color: #c0c0c0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.wechat-phone-btn {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@@ -495,49 +403,34 @@ input.input-transparent {
|
|||||||
background-color: #07c160;
|
background-color: #07c160;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 44rpx;
|
border-radius: 44rpx;
|
||||||
|
|
||||||
text {
|
|
||||||
margin-left: 16rpx;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 其他登录方式
|
||||||
.other-login {
|
.other-login {
|
||||||
margin-top: 60rpx;
|
margin-top: 60rpx;
|
||||||
}
|
|
||||||
|
|
||||||
.other-login-title {
|
&__title {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-bottom: 40rpx;
|
margin-bottom: 40rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.line {
|
&__line {
|
||||||
width: 80rpx;
|
width: 80rpx;
|
||||||
height: 1rpx;
|
height: 1rpx;
|
||||||
background-color: rgba(0, 0, 0, 0.1);
|
background-color: var(--wot-color-border-light);
|
||||||
|
}
|
||||||
|
|
||||||
.wot-theme-dark & {
|
&__text {
|
||||||
background-color: rgba(255, 255, 255, 0.2);
|
margin: 0 20rpx;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: var(--wot-color-text-secondary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.text {
|
// 微信图标
|
||||||
margin: 0 20rpx;
|
.wechat-icon {
|
||||||
font-size: 26rpx;
|
|
||||||
color: rgba(0, 0, 0, 0.4);
|
|
||||||
|
|
||||||
.wot-theme-dark & {
|
|
||||||
color: rgba(255, 255, 255, 0.6);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.wechat-login {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wechat-icon-wrapper {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@@ -545,59 +438,21 @@ input.input-transparent {
|
|||||||
height: 80rpx;
|
height: 80rpx;
|
||||||
background-color: #07c160;
|
background-color: #07c160;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
|
||||||
.wot-theme-dark & {
|
|
||||||
box-shadow: 0 4rpx 12rpx rgba(7, 193, 96, 0.3);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.wechat-icon {
|
// 登录协议
|
||||||
width: 40rpx;
|
.login-agreement {
|
||||||
height: 40rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.agreement {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-top: 60rpx;
|
margin-top: 60rpx;
|
||||||
font-size: 24rpx;
|
font-size: 24rpx;
|
||||||
}
|
|
||||||
|
|
||||||
.link {
|
&__text {
|
||||||
color: var(--wot-color-theme);
|
color: var(--wot-color-text-secondary);
|
||||||
}
|
|
||||||
|
|
||||||
.input-placeholder {
|
|
||||||
color: rgba(0, 0, 0, 0.3);
|
|
||||||
|
|
||||||
.wot-theme-dark & {
|
|
||||||
color: rgba(255, 255, 255, 0.4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 加强输入框透明度 - 暗黑模式特别处理 */
|
|
||||||
.wot-theme-dark {
|
|
||||||
:deep(input) {
|
|
||||||
background: none !important;
|
|
||||||
background-color: transparent !important;
|
|
||||||
-webkit-box-shadow: none !important;
|
|
||||||
box-shadow: none !important;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-input,
|
&__link {
|
||||||
input {
|
color: var(--wot-color-theme);
|
||||||
background: none !important;
|
|
||||||
background-color: transparent !important;
|
|
||||||
background-image: none !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 修复Android Chrome输入框背景色问题 */
|
|
||||||
@supports (-webkit-appearance: none) {
|
|
||||||
input {
|
|
||||||
-webkit-appearance: none;
|
|
||||||
background: transparent !important;
|
|
||||||
background-color: transparent !important;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -30,125 +30,144 @@
|
|||||||
</wd-button>
|
</wd-button>
|
||||||
</block>
|
</block>
|
||||||
</view>
|
</view>
|
||||||
<view class="actions">
|
<view class="flex">
|
||||||
<view class="action-btn" @click="navigateToSettings">
|
<view class="user-profile__action" @click="navigateToSettings">
|
||||||
<wd-icon name="setting1" size="22" color="#333" />
|
<wd-icon name="setting1" size="22" :color="themeStore.isDark ? '#fff' : '#333'" />
|
||||||
</view>
|
</view>
|
||||||
<view v-if="isLogin" class="action-btn" @click="navigateToSection('messages')">
|
<view
|
||||||
<wd-icon name="notification" size="22" color="#333" />
|
v-if="isLogin"
|
||||||
<view v-if="true" class="badge">2</view>
|
class="user-profile__action relative ml-16rpx"
|
||||||
|
@click="navigateToSection('messages')"
|
||||||
|
>
|
||||||
|
<wd-icon name="notification" size="22" />
|
||||||
|
<view v-if="true" class="user-profile__badge">2</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 数据统计 -->
|
<!-- 数据统计 -->
|
||||||
<view class="stats-card">
|
<wd-card custom-class="mx-30rpx my-20rpx">
|
||||||
<view class="stats-item" @click="navigateToSection('wallet')">
|
<wd-grid :column="3" border>
|
||||||
<view class="mb-8rpx text-36rpx font-600">0.00</view>
|
<wd-grid-item @click="navigateToSection('wallet')">
|
||||||
<view class="text-26rpx text-gray-500">我的余额</view>
|
<view class="flex-col-center py-20rpx">
|
||||||
</view>
|
<view class="mb-8rpx text-36rpx font-600">0.00</view>
|
||||||
<view class="stats-divider"></view>
|
<view class="text-26rpx text-gray-500">我的余额</view>
|
||||||
<view class="stats-item" @click="navigateToSection('favorites')">
|
</view>
|
||||||
<view class="mb-8rpx text-36rpx font-600">0</view>
|
</wd-grid-item>
|
||||||
<view class="text-26rpx text-gray-500">我的收藏</view>
|
<wd-grid-item @click="navigateToSection('favorites')">
|
||||||
</view>
|
<view class="flex-col-center py-20rpx">
|
||||||
<view class="stats-divider"></view>
|
<view class="mb-8rpx text-36rpx font-600">0</view>
|
||||||
<view class="stats-item" @click="navigateToSection('history')">
|
<view class="text-26rpx text-gray-500">我的收藏</view>
|
||||||
<view class="mb-8rpx text-36rpx font-600">0</view>
|
</view>
|
||||||
<view class="text-26rpx text-gray-500">浏览历史</view>
|
</wd-grid-item>
|
||||||
</view>
|
<wd-grid-item @click="navigateToSection('history')">
|
||||||
</view>
|
<view class="flex-col-center py-20rpx">
|
||||||
|
<view class="mb-8rpx text-36rpx font-600">0</view>
|
||||||
|
<view class="text-26rpx text-gray-500">浏览历史</view>
|
||||||
|
</view>
|
||||||
|
</wd-grid-item>
|
||||||
|
</wd-grid>
|
||||||
|
</wd-card>
|
||||||
|
|
||||||
<!-- 常用工具 -->
|
<!-- 常用工具 -->
|
||||||
<view class="card-container">
|
<wd-card>
|
||||||
<view class="card-header">
|
<template #header>
|
||||||
<view class="flex-start">
|
<view class="flex-start">
|
||||||
<wd-icon name="tools" size="18" :color="currentThemeColor" />
|
<wd-icon name="tools" size="18" :color="currentThemeColor" />
|
||||||
<text class="ml-12rpx text-28rpx font-600">常用工具</text>
|
<text class="ml-12rpx text-28rpx font-600">常用工具</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</template>
|
||||||
<view class="flex flex-wrap p-20rpx pt-20rpx pb-10rpx">
|
|
||||||
<view class="tool-item" @click="navigateToProfile">
|
<wd-grid :column="4" border>
|
||||||
<view class="tool-icon">
|
<wd-grid-item @click="navigateToProfile">
|
||||||
<wd-icon name="user" size="24" :color="currentThemeColor" />
|
<view class="flex-col-center py-20rpx">
|
||||||
|
<view class="tool-icon mb-12rpx">
|
||||||
|
<wd-icon name="user" size="24" :color="currentThemeColor" />
|
||||||
|
</view>
|
||||||
|
<view class="text-24rpx">个人资料</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="text-24rpx">个人资料</view>
|
</wd-grid-item>
|
||||||
</view>
|
<wd-grid-item @click="navigateToFAQ">
|
||||||
<view class="tool-item" @click="navigateToFAQ">
|
<view class="flex-col-center py-20rpx">
|
||||||
<view class="tool-icon">
|
<view class="tool-icon mb-12rpx">
|
||||||
<wd-icon name="help-circle" size="24" :color="currentThemeColor" />
|
<wd-icon name="help-circle" size="24" :color="currentThemeColor" />
|
||||||
|
</view>
|
||||||
|
<view class="text-24rpx">常见问题</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="text-24rpx">常见问题</view>
|
</wd-grid-item>
|
||||||
</view>
|
<wd-grid-item @click="handleQuestionFeedback">
|
||||||
<view class="tool-item" @click="handleQuestionFeedback">
|
<view class="flex-col-center py-20rpx">
|
||||||
<view class="tool-icon">
|
<view class="tool-icon mb-12rpx">
|
||||||
<wd-icon name="check-circle" size="24" :color="currentThemeColor" />
|
<wd-icon name="check-circle" size="24" :color="currentThemeColor" />
|
||||||
|
</view>
|
||||||
|
<view class="text-24rpx">问题反馈</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="text-24rpx">问题反馈</view>
|
</wd-grid-item>
|
||||||
</view>
|
<wd-grid-item @click="navigateToAbout">
|
||||||
<view class="tool-item" @click="navigateToAbout">
|
<view class="flex-col-center py-20rpx">
|
||||||
<view class="tool-icon">
|
<view class="tool-icon mb-12rpx">
|
||||||
<wd-icon name="info-circle" size="24" :color="currentThemeColor" />
|
<wd-icon name="info-circle" size="24" :color="currentThemeColor" />
|
||||||
|
</view>
|
||||||
|
<view class="text-24rpx">关于我们</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="text-24rpx">关于我们</view>
|
</wd-grid-item>
|
||||||
</view>
|
</wd-grid>
|
||||||
</view>
|
</wd-card>
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 推荐服务 -->
|
<!-- 推荐服务 -->
|
||||||
<view class="card-container">
|
<wd-card>
|
||||||
<view class="card-header">
|
<template #header>
|
||||||
<view class="flex-start">
|
<view class="flex-start">
|
||||||
<wd-icon name="star" size="18" :color="currentThemeColor" />
|
<wd-icon name="star" size="18" :color="currentThemeColor" />
|
||||||
<text class="ml-12rpx text-28rpx font-600">推荐服务</text>
|
<text class="ml-12rpx text-28rpx font-600">推荐服务</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</template>
|
||||||
<view>
|
|
||||||
<view class="service-item" @click="navigateToSection('services', 'vip')">
|
<wd-cell-group>
|
||||||
<view class="flex-start">
|
<wd-cell
|
||||||
<view class="service-icon">
|
title="会员中心"
|
||||||
|
label="解锁更多特权"
|
||||||
|
is-link
|
||||||
|
@click="navigateToSection('services', 'vip')"
|
||||||
|
>
|
||||||
|
<template #icon>
|
||||||
|
<view class="service-icon mr-20rpx">
|
||||||
<wd-icon name="dong" size="22" :color="currentThemeColor" />
|
<wd-icon name="dong" size="22" :color="currentThemeColor" />
|
||||||
</view>
|
</view>
|
||||||
<view>
|
</template>
|
||||||
<view class="text-28rpx font-500">会员中心</view>
|
</wd-cell>
|
||||||
<view class="mt-8rpx text-24rpx text-gray-500">解锁更多特权</view>
|
|
||||||
</view>
|
<wd-cell
|
||||||
</view>
|
title="优惠券"
|
||||||
<wd-icon name="arrow-right" size="14" />
|
label="查看我的优惠券"
|
||||||
</view>
|
is-link
|
||||||
<view class="service-item" @click="navigateToSection('services', 'coupon')">
|
@click="navigateToSection('services', 'coupon')"
|
||||||
<view class="flex-start">
|
>
|
||||||
<view class="service-icon">
|
<template #icon>
|
||||||
|
<view class="service-icon mr-20rpx">
|
||||||
<wd-icon name="discount" size="22" :color="currentThemeColor" />
|
<wd-icon name="discount" size="22" :color="currentThemeColor" />
|
||||||
</view>
|
</view>
|
||||||
<view>
|
</template>
|
||||||
<view class="text-28rpx font-500">优惠券</view>
|
</wd-cell>
|
||||||
<view class="mt-8rpx text-24rpx text-gray-500">查看我的优惠券</view>
|
|
||||||
</view>
|
<wd-cell
|
||||||
</view>
|
title="邀请有礼"
|
||||||
<wd-icon name="arrow-right" size="14" />
|
label="邀请好友得奖励"
|
||||||
</view>
|
is-link
|
||||||
<view
|
|
||||||
class="service-item service-item-last"
|
|
||||||
@click="navigateToSection('services', 'invite')"
|
@click="navigateToSection('services', 'invite')"
|
||||||
>
|
>
|
||||||
<view class="flex-start">
|
<template #icon>
|
||||||
<view class="service-icon">
|
<view class="service-icon mr-20rpx">
|
||||||
<wd-icon name="share" size="22" :color="currentThemeColor" />
|
<wd-icon name="share" size="22" :color="currentThemeColor" />
|
||||||
</view>
|
</view>
|
||||||
<view>
|
</template>
|
||||||
<view class="text-28rpx font-500">邀请有礼</view>
|
</wd-cell>
|
||||||
<view class="mt-8rpx text-24rpx text-gray-500">邀请好友得奖励</view>
|
</wd-cell-group>
|
||||||
</view>
|
</wd-card>
|
||||||
</view>
|
|
||||||
<wd-icon name="arrow-right" size="14" />
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 退出登录按钮 -->
|
<!-- 退出登录按钮 -->
|
||||||
<view v-if="isLogin" class="p-30rpx">
|
<view v-if="isLogin">
|
||||||
<wd-button custom-class="logout-button" plain @click="handleLogout">退出登录</wd-button>
|
<wd-button custom-class="logout-button" plain @click="handleLogout">退出登录</wd-button>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@@ -299,156 +318,35 @@ const navigateToSection = (section: string, subSection?: string) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.actions {
|
// BEM命名规范的用户操作按钮
|
||||||
|
.user-profile__action {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
.action-btn {
|
justify-content: center;
|
||||||
position: relative;
|
width: 70rpx;
|
||||||
display: flex;
|
height: 70rpx;
|
||||||
align-items: center;
|
background-color: rgba(255, 255, 255, 0.9);
|
||||||
justify-content: center;
|
border-radius: 50%;
|
||||||
width: 70rpx;
|
// 移除无效果的box-shadow
|
||||||
height: 70rpx;
|
|
||||||
margin-left: 16rpx;
|
|
||||||
background-color: rgba(255, 255, 255, 0.9);
|
|
||||||
border-radius: 50%;
|
|
||||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
|
|
||||||
|
|
||||||
.badge {
|
|
||||||
position: absolute;
|
|
||||||
top: -6rpx;
|
|
||||||
right: -6rpx;
|
|
||||||
z-index: 2;
|
|
||||||
min-width: 32rpx;
|
|
||||||
height: 32rpx;
|
|
||||||
padding: 0 6rpx;
|
|
||||||
font-size: 20rpx;
|
|
||||||
line-height: 32rpx;
|
|
||||||
color: #fff;
|
|
||||||
text-align: center;
|
|
||||||
background-color: var(--wot-color-danger);
|
|
||||||
border: 2rpx solid #fff;
|
|
||||||
border-radius: 16rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 卡片容器
|
// 通知徽章 - 超过5个原子类,使用CSS类
|
||||||
.card-container {
|
.user-profile__badge {
|
||||||
margin: 24rpx 30rpx;
|
position: absolute;
|
||||||
overflow: hidden;
|
top: -6rpx;
|
||||||
background-color: #fff;
|
right: -6rpx;
|
||||||
border-radius: 16rpx;
|
z-index: 2;
|
||||||
box-shadow: 0 1rpx 3rpx rgba(0, 0, 0, 0.1);
|
min-width: 32rpx;
|
||||||
}
|
height: 32rpx;
|
||||||
|
padding: 0 6rpx;
|
||||||
// 卡片头部
|
font-size: 20rpx;
|
||||||
.card-header {
|
line-height: 32rpx;
|
||||||
display: flex;
|
color: #fff;
|
||||||
align-items: center;
|
text-align: center;
|
||||||
justify-content: space-between;
|
background-color: #ff4757; // 明确的红色
|
||||||
padding: 20rpx 24rpx;
|
border: 2rpx solid #fff;
|
||||||
border-bottom: 1rpx solid #e5e7eb;
|
border-radius: 16rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 暗色模式下的卡片样式
|
|
||||||
:deep(.dark) .card-container {
|
|
||||||
background-color: #1f2937;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.dark) .card-header {
|
|
||||||
border-bottom-color: #374151;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 工具项
|
|
||||||
.tool-item {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
width: 25%;
|
|
||||||
margin-bottom: 30rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 工具图标
|
|
||||||
.tool-icon {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
width: 90rpx;
|
|
||||||
height: 90rpx;
|
|
||||||
margin-bottom: 12rpx;
|
|
||||||
background-color: #f3f4f6;
|
|
||||||
border-radius: 18rpx;
|
|
||||||
transition: transform 0.15s ease;
|
|
||||||
|
|
||||||
&:active {
|
|
||||||
transform: scale(0.95);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 暗色模式下的工具图标样式
|
|
||||||
:deep(.dark) .tool-icon {
|
|
||||||
background-color: #374151;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 数据统计卡片(减少原子类堆叠)
|
|
||||||
.stats-card {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 30rpx;
|
|
||||||
margin: 20rpx 30rpx;
|
|
||||||
background-color: #ffffff;
|
|
||||||
border-radius: 16rpx;
|
|
||||||
box-shadow: 0 1rpx 3rpx rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.dark) .stats-card {
|
|
||||||
background-color: #1f2937;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stats-item {
|
|
||||||
display: flex;
|
|
||||||
flex: 1;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stats-divider {
|
|
||||||
width: 1px;
|
|
||||||
margin: 0 20rpx;
|
|
||||||
background-color: #e5e7eb;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.dark) .stats-divider {
|
|
||||||
background-color: #374151;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 服务项
|
|
||||||
.service-item {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
padding: 24rpx;
|
|
||||||
border-bottom: 1rpx solid #e5e7eb;
|
|
||||||
transition: background-color 0.15s ease;
|
|
||||||
|
|
||||||
&:active {
|
|
||||||
background-color: #f3f4f6;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.service-item-last {
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 暗色模式下的服务项样式
|
|
||||||
:deep(.dark) .service-item {
|
|
||||||
border-bottom-color: #374151;
|
|
||||||
|
|
||||||
&:active {
|
|
||||||
background-color: rgba(255, 255, 255, 0.1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -459,14 +357,24 @@ const navigateToSection = (section: string, subSection?: string) => {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
width: 80rpx;
|
width: 80rpx;
|
||||||
height: 80rpx;
|
height: 80rpx;
|
||||||
margin-right: 20rpx;
|
background-color: var(--wot-color-bg-light, #f3f4f6);
|
||||||
background-color: #f3f4f6;
|
|
||||||
border-radius: 16rpx;
|
border-radius: 16rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 暗色模式下的服务图标样式
|
// 工具图标
|
||||||
:deep(.dark) .service-icon {
|
.tool-icon {
|
||||||
background-color: #374151;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 90rpx;
|
||||||
|
height: 90rpx;
|
||||||
|
background-color: var(--wot-color-bg-light, #f3f4f6);
|
||||||
|
border-radius: 18rpx;
|
||||||
|
transition: transform 0.15s ease;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 登录按钮样式
|
// 登录按钮样式
|
||||||
|
|||||||
@@ -1,132 +1,134 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="app-container dark:text-[var(--wot-dark-color)]">
|
<view class="app-container">
|
||||||
<!-- 页面标题 -->
|
|
||||||
<view class="page-header">
|
|
||||||
<text class="page-title">主题设置</text>
|
|
||||||
<text class="page-subtitle">个性化您的应用外观</text>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 暗黑模式设置 -->
|
<!-- 暗黑模式设置 -->
|
||||||
<wd-card class="setting-section">
|
<wd-card custom-class="mx-30rpx my-20rpx">
|
||||||
<view class="section-header">
|
<template #header>
|
||||||
<wd-icon name="moon" size="20" :color="isDarkMode ? '#FFD700' : '#666'" />
|
<view class="flex-start">
|
||||||
<text class="section-title">外观模式</text>
|
<wd-icon name="moon" size="20" :color="isDarkMode ? '#FFD700' : '#666'" />
|
||||||
</view>
|
<text class="ml-12rpx text-28rpx font-600">外观模式</text>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
<wd-cell title="暗黑模式" :value="isDarkMode ? '已开启' : '已关闭'">
|
<wd-cell title="暗黑模式" :value="isDarkMode ? '已开启' : '已关闭'">
|
||||||
<wd-switch :model-value="isDarkMode" @change="handleToggleDarkMode" />
|
<wd-switch :model-value="isDarkMode" @change="handleToggleDarkMode" />
|
||||||
</wd-cell>
|
</wd-cell>
|
||||||
</wd-card>
|
</wd-card>
|
||||||
|
|
||||||
<!-- 主题色设置 -->
|
<!-- 主题色设置 -->
|
||||||
<wd-card class="setting-section">
|
<wd-card custom-class="mx-30rpx my-20rpx">
|
||||||
<view class="section-header">
|
<template #header>
|
||||||
<wd-icon name="palette" size="20" color="#666" />
|
<view class="flex-start">
|
||||||
<text class="section-title">主题色彩</text>
|
<wd-icon name="palette" size="20" color="#666" />
|
||||||
</view>
|
<text class="ml-12rpx text-28rpx font-600">主题色彩</text>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
<!-- 预设颜色选择 -->
|
<!-- 预设颜色选择 -->
|
||||||
<view class="color-section">
|
<view class="theme-colors">
|
||||||
<text class="color-label">预设主题色</text>
|
<view class="theme-colors__label">预设主题色</view>
|
||||||
<view class="color-grid">
|
<wd-grid :column="3" border>
|
||||||
<view
|
<wd-grid-item
|
||||||
v-for="(color, index) in themeColorOptions"
|
v-for="(color, index) in themeColorOptions"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="color-item"
|
|
||||||
:class="{ active: currentThemeColor === color.primary }"
|
|
||||||
@click="handleSelectColor(color)"
|
@click="handleSelectColor(color)"
|
||||||
>
|
>
|
||||||
<view
|
<view class="theme-colors__item">
|
||||||
class="color-preview"
|
<view
|
||||||
:style="{
|
class="theme-colors__preview"
|
||||||
backgroundColor: color.primary,
|
:class="{ 'theme-colors__preview--active': currentThemeColor === color.primary }"
|
||||||
border:
|
:style="{ backgroundColor: color.primary }"
|
||||||
currentThemeColor === color.primary ? '3px solid #fff' : '1px solid #e0e0e0',
|
>
|
||||||
}"
|
<text v-if="currentThemeColor === color.primary" class="theme-colors__check">
|
||||||
>
|
✓
|
||||||
<text v-if="currentThemeColor === color.primary" class="check-icon">✓</text>
|
</text>
|
||||||
|
</view>
|
||||||
|
<text class="theme-colors__name">{{ color.name }}</text>
|
||||||
</view>
|
</view>
|
||||||
<text class="color-name">{{ color.name }}</text>
|
</wd-grid-item>
|
||||||
</view>
|
</wd-grid>
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 当前主题色显示 -->
|
<!-- 当前主题色显示 -->
|
||||||
<view class="current-theme-section">
|
<view class="current-theme">
|
||||||
<view class="current-theme-item">
|
<view class="current-theme__item">
|
||||||
<text class="current-theme-label">当前主题色</text>
|
<view class="current-theme__info">
|
||||||
<view class="current-theme-value">
|
|
||||||
<view
|
<view
|
||||||
class="current-color-preview"
|
class="current-theme__preview"
|
||||||
:style="{ backgroundColor: currentThemeColor }"
|
:style="{ backgroundColor: currentThemeColor }"
|
||||||
></view>
|
></view>
|
||||||
<text class="current-color-text">{{ currentThemeColor }}</text>
|
<text class="current-theme__label">当前主题色</text>
|
||||||
</view>
|
</view>
|
||||||
|
<text class="current-theme__value">{{ currentThemeColor }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 自定义颜色 -->
|
<!-- 自定义颜色 -->
|
||||||
<wd-cell title="自定义颜色" is-link @click="showCustomInput">
|
<wd-cell title="自定义颜色" is-link @click="showCustomInput">
|
||||||
<wd-icon name="edit" size="16" color="#999" />
|
<template #icon>
|
||||||
|
<wd-icon name="edit" size="16" :color="themeStore.isDark ? '#fff' : '#999'" />
|
||||||
|
</template>
|
||||||
</wd-cell>
|
</wd-cell>
|
||||||
</wd-card>
|
</wd-card>
|
||||||
|
|
||||||
<!-- 预览区域 -->
|
<!-- 效果预览 -->
|
||||||
<wd-card class="setting-section">
|
<wd-card title="效果预览" custom-class="mx-30rpx my-20rpx">
|
||||||
<view class="section-header">
|
<wd-grid :column="3" border>
|
||||||
<wd-icon name="eye" size="20" />
|
|
||||||
<text class="section-title">效果预览</text>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<wd-divider />
|
|
||||||
|
|
||||||
<wd-grid :column="2" border>
|
|
||||||
<wd-grid-item>
|
<wd-grid-item>
|
||||||
<wd-button type="primary">主要按钮</wd-button>
|
<view class="flex-col-center py-20rpx">
|
||||||
|
<wd-button type="primary" size="small">主要按钮</wd-button>
|
||||||
|
</view>
|
||||||
</wd-grid-item>
|
</wd-grid-item>
|
||||||
<wd-grid-item>
|
<wd-grid-item>
|
||||||
<text class="preview-text" :style="{ color: currentThemeColor }">主题色文本</text>
|
<view class="flex-col-center py-20rpx">
|
||||||
|
<text class="text-28rpx font-500" :style="{ color: currentThemeColor }">
|
||||||
|
主题色文本
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
</wd-grid-item>
|
</wd-grid-item>
|
||||||
<wd-grid-item>
|
<wd-grid-item>
|
||||||
<view class="preview-border" :style="{ borderColor: currentThemeColor }">主题色边框</view>
|
<view class="flex-col-center py-20rpx">
|
||||||
</wd-grid-item>
|
<wd-tag type="primary" size="small">标签</wd-tag>
|
||||||
<wd-grid-item>
|
</view>
|
||||||
<wd-tag type="primary" size="small">标签</wd-tag>
|
|
||||||
</wd-grid-item>
|
</wd-grid-item>
|
||||||
</wd-grid>
|
</wd-grid>
|
||||||
</wd-card>
|
</wd-card>
|
||||||
|
|
||||||
<!-- 操作按钮 -->
|
<!-- 操作按钮 -->
|
||||||
<wd-card class="action-section">
|
<view class="p-30rpx">
|
||||||
<wd-button type="info" size="large" block @click="handleResetTheme">重置为默认主题</wd-button>
|
<wd-button type="info" size="large" block @click="handleResetTheme">重置为默认主题</wd-button>
|
||||||
</wd-card>
|
</view>
|
||||||
|
|
||||||
<!-- 自定义颜色输入弹窗 -->
|
<!-- 自定义颜色输入弹窗 -->
|
||||||
<wd-popup v-model="showCustomColorInput" position="bottom" :safe-area-inset-bottom="true">
|
<wd-popup v-model="showCustomColorInput" position="bottom" :safe-area-inset-bottom="true">
|
||||||
<view class="custom-color-popup">
|
<view class="custom-color-popup">
|
||||||
<view class="popup-header">
|
<view class="custom-color-popup__header">
|
||||||
<text class="popup-title">自定义主题色</text>
|
<text class="custom-color-popup__title">自定义主题色</text>
|
||||||
<wd-icon name="close" size="20" color="#999" @click="showCustomColorInput = false" />
|
<wd-icon
|
||||||
|
name="close"
|
||||||
|
size="20"
|
||||||
|
:color="themeStore.isDark ? '#999' : '#666'"
|
||||||
|
@click="showCustomColorInput = false"
|
||||||
|
/>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<wd-divider />
|
<view class="custom-color-popup__content">
|
||||||
|
<text class="custom-color-popup__label">请输入十六进制颜色值</text>
|
||||||
<view class="color-input-section">
|
<view class="custom-color-popup__input-row">
|
||||||
<view class="input-label">请输入十六进制颜色值</view>
|
<view
|
||||||
<view class="input-container">
|
class="custom-color-popup__preview"
|
||||||
<view class="color-preview-small" :style="{ backgroundColor: customColor }"></view>
|
:style="{ backgroundColor: customColor || '#FF4757' }"
|
||||||
|
></view>
|
||||||
<wd-input
|
<wd-input
|
||||||
v-model="customColor"
|
v-model="customColor"
|
||||||
placeholder="例如: #165DFF"
|
placeholder="例如: #FF4757"
|
||||||
:maxlength="7"
|
:maxlength="7"
|
||||||
class="color-input"
|
custom-class="custom-color-popup__input"
|
||||||
/>
|
/>
|
||||||
</view>
|
</view>
|
||||||
<view class="input-tip">支持格式:#RGB 或 #RRGGBB</view>
|
<text class="custom-color-popup__tip">支持格式:#RGB 或 #RRGGBB</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<wd-divider />
|
<view class="custom-color-popup__actions">
|
||||||
|
|
||||||
<view class="popup-actions">
|
|
||||||
<wd-button type="info" size="large" @click="showCustomColorInput = false">取消</wd-button>
|
<wd-button type="info" size="large" @click="showCustomColorInput = false">取消</wd-button>
|
||||||
<wd-button type="primary" size="large" @click="applyCustomColor">应用</wd-button>
|
<wd-button type="primary" size="large" @click="applyCustomColor">应用</wd-button>
|
||||||
</view>
|
</view>
|
||||||
@@ -198,7 +200,7 @@ const applyCustomColor = () => {
|
|||||||
primary: color,
|
primary: color,
|
||||||
};
|
};
|
||||||
|
|
||||||
setCurrentThemeColor(customColorOption);
|
setThemeColor(customColorOption);
|
||||||
showCustomColorInput.value = false;
|
showCustomColorInput.value = false;
|
||||||
|
|
||||||
// 提示
|
// 提示
|
||||||
@@ -265,217 +267,152 @@ onShow(() => {
|
|||||||
</route>
|
</route>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
// 基础布局
|
// 主题颜色选择区域
|
||||||
.page-header {
|
.theme-colors {
|
||||||
padding: 40rpx 20rpx;
|
|
||||||
margin-bottom: 30rpx;
|
|
||||||
text-align: center;
|
|
||||||
background: linear-gradient(135deg, var(--wot-color-theme, #165dff) 0%, #667eea 100%);
|
|
||||||
border-radius: 16rpx;
|
|
||||||
|
|
||||||
.page-title {
|
|
||||||
display: block;
|
|
||||||
margin-bottom: 10rpx;
|
|
||||||
font-size: 36rpx;
|
|
||||||
font-weight: bold;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-subtitle {
|
|
||||||
font-size: 26rpx;
|
|
||||||
color: rgba(255, 255, 255, 0.8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.setting-section {
|
|
||||||
margin-bottom: 30rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 30rpx 30rpx 20rpx;
|
|
||||||
border-bottom: 1rpx solid var(--wot-color-border, #f0f0f0);
|
|
||||||
|
|
||||||
.section-title {
|
|
||||||
margin-left: 12rpx;
|
|
||||||
font-size: 32rpx;
|
|
||||||
font-weight: 600;
|
|
||||||
color: var(--wot-color-text, #333);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 颜色选择区域
|
|
||||||
.color-section {
|
|
||||||
padding: 30rpx;
|
padding: 30rpx;
|
||||||
|
|
||||||
.color-label {
|
&__label {
|
||||||
|
display: block;
|
||||||
margin-bottom: 20rpx;
|
margin-bottom: 20rpx;
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
color: var(--wot-color-text-secondary, #666);
|
color: var(--wot-color-text-secondary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.color-grid {
|
&__item {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-direction: column;
|
||||||
gap: 20rpx;
|
align-items: center;
|
||||||
justify-content: space-between;
|
padding: 10rpx;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.color-item {
|
&__preview {
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
width: calc(25% - 15rpx);
|
|
||||||
padding: 10rpx;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
|
|
||||||
.color-preview {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
width: 60rpx;
|
width: 60rpx;
|
||||||
height: 60rpx;
|
height: 60rpx;
|
||||||
margin-bottom: 8rpx;
|
margin-bottom: 8rpx;
|
||||||
|
border: 2rpx solid var(--wot-color-border);
|
||||||
border-radius: 12rpx;
|
border-radius: 12rpx;
|
||||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
.check-icon {
|
&--active {
|
||||||
font-size: 24rpx;
|
border-color: var(--wot-color-theme);
|
||||||
font-weight: bold;
|
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.2);
|
||||||
color: #fff;
|
transform: scale(1.05);
|
||||||
text-shadow: 0 1rpx 2rpx rgba(0, 0, 0, 0.5);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.color-name {
|
&__check {
|
||||||
|
font-size: 24rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #fff;
|
||||||
|
text-shadow: 0 1rpx 2rpx rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__name {
|
||||||
font-size: 22rpx;
|
font-size: 22rpx;
|
||||||
color: var(--wot-color-text-secondary);
|
color: var(--wot-color-text-secondary);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.active .color-preview {
|
|
||||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.2);
|
|
||||||
transform: scale(1.05);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active .color-preview {
|
|
||||||
transform: scale(0.95);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 当前主题色显示
|
// 当前主题色显示区域
|
||||||
.current-theme-section {
|
.current-theme {
|
||||||
padding: 30rpx;
|
padding: 30rpx;
|
||||||
|
border-bottom: 1rpx solid var(--wot-color-border);
|
||||||
|
|
||||||
.current-theme-item {
|
&__item {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
||||||
.current-theme-label {
|
|
||||||
font-size: 28rpx;
|
|
||||||
color: var(--wot-color-text-secondary, #666);
|
|
||||||
}
|
|
||||||
|
|
||||||
.current-theme-value {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
.current-color-preview {
|
|
||||||
width: 40rpx;
|
|
||||||
height: 40rpx;
|
|
||||||
border: 2rpx solid var(--wot-color-border, #f0f0f0);
|
|
||||||
border-radius: 8rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.current-color-text {
|
|
||||||
margin-left: 10rpx;
|
|
||||||
font-size: 28rpx;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// 效果预览
|
&__info {
|
||||||
.preview-text {
|
display: flex;
|
||||||
font-size: 28rpx;
|
align-items: center;
|
||||||
font-weight: 500;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.preview-border {
|
&__preview {
|
||||||
display: flex;
|
width: 40rpx;
|
||||||
align-items: center;
|
height: 40rpx;
|
||||||
justify-content: center;
|
margin-right: 12rpx;
|
||||||
width: 200rpx;
|
border: 2rpx solid var(--wot-color-border);
|
||||||
height: 60rpx;
|
border-radius: 8rpx;
|
||||||
font-size: 26rpx;
|
}
|
||||||
color: var(--wot-color-text-secondary, #666);
|
|
||||||
border: 2rpx solid;
|
&__label {
|
||||||
border-radius: 8rpx;
|
font-size: 28rpx;
|
||||||
|
color: var(--wot-color-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__value {
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--wot-color-text-secondary);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 自定义颜色弹窗
|
// 自定义颜色弹窗
|
||||||
.custom-color-popup {
|
.custom-color-popup {
|
||||||
padding: 40rpx 30rpx;
|
min-height: 400rpx;
|
||||||
background: var(--wot-popup-bg-color, #fff);
|
background-color: var(--wot-card-bg);
|
||||||
border-radius: 20rpx 20rpx 0 0;
|
border-radius: 20rpx 20rpx 0 0;
|
||||||
|
|
||||||
.popup-header {
|
&__header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin-bottom: 30rpx;
|
padding: 30rpx;
|
||||||
|
border-bottom: 1rpx solid var(--wot-color-border);
|
||||||
.popup-title {
|
|
||||||
font-size: 32rpx;
|
|
||||||
font-weight: 600;
|
|
||||||
color: var(--wot-color-text, #333);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.color-input-section {
|
&__title {
|
||||||
margin-bottom: 40rpx;
|
font-size: 32rpx;
|
||||||
|
font-weight: 600;
|
||||||
.input-label {
|
color: var(--wot-color-text);
|
||||||
margin-bottom: 20rpx;
|
|
||||||
font-size: 28rpx;
|
|
||||||
color: var(--wot-color-text-secondary, #666);
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-container {
|
|
||||||
display: flex;
|
|
||||||
gap: 20rpx;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 10rpx;
|
|
||||||
|
|
||||||
.color-preview-small {
|
|
||||||
flex-shrink: 0;
|
|
||||||
width: 60rpx;
|
|
||||||
height: 60rpx;
|
|
||||||
border: 2rpx solid var(--wot-color-border, #f0f0f0);
|
|
||||||
border-radius: 8rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.color-input {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-tip {
|
|
||||||
margin-left: 80rpx;
|
|
||||||
font-size: 24rpx;
|
|
||||||
color: var(--wot-color-text-placeholder, #999);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.popup-actions {
|
&__content {
|
||||||
|
padding: 40rpx 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__label {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: var(--wot-color-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__input-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 20rpx;
|
gap: 20rpx;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__preview {
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: 60rpx;
|
||||||
|
height: 60rpx;
|
||||||
|
border: 2rpx solid var(--wot-color-border);
|
||||||
|
border-radius: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__input {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__tip {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: var(--wot-color-text-placeholder);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 20rpx;
|
||||||
|
padding: 20rpx 30rpx 30rpx;
|
||||||
|
border-top: 1rpx solid var(--wot-color-border);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
@use "./theme";
|
||||||
|
|
||||||
html,
|
html,
|
||||||
body,
|
body,
|
||||||
#app {
|
#app {
|
||||||
|
|||||||
48
src/styles/theme.scss
Normal file
48
src/styles/theme.scss
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
/* 默认主题 (light) */
|
||||||
|
:root,
|
||||||
|
page {
|
||||||
|
/* 官方主题变量 */
|
||||||
|
--wot-color-theme: #4d80f0;
|
||||||
|
--wot-color-success: #34d19d;
|
||||||
|
--wot-color-warning: #f0883a;
|
||||||
|
--wot-color-danger: #ff4757;
|
||||||
|
|
||||||
|
/* 自定义扩展变量 */
|
||||||
|
--wot-button-normal-bg: #ffffff;
|
||||||
|
--wot-card-bg: #ffffff;
|
||||||
|
--wot-color-bg-light: #f3f4f6;
|
||||||
|
--wot-dark-color: #333333;
|
||||||
|
|
||||||
|
/* 文本颜色变量 */
|
||||||
|
--wot-color-text: #333333;
|
||||||
|
--wot-color-text-secondary: #666666;
|
||||||
|
--wot-color-text-placeholder: #999999;
|
||||||
|
|
||||||
|
/* 边框和背景变量 */
|
||||||
|
--wot-color-border: #e5e7eb;
|
||||||
|
--wot-color-bg-container: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 暗黑主题 (dark) */
|
||||||
|
.wot-theme-dark {
|
||||||
|
/* 官方主题变量 */
|
||||||
|
--wot-color-theme: #1a73e8;
|
||||||
|
--wot-color-success: #28a745;
|
||||||
|
--wot-color-warning: #ffc107;
|
||||||
|
--wot-color-danger: #ff4757;
|
||||||
|
|
||||||
|
/* 自定义扩展变量 */
|
||||||
|
--wot-button-normal-bg: #2a2a2a;
|
||||||
|
--wot-card-bg: #1b1b1b;
|
||||||
|
--wot-color-bg-light: #2a2a2a;
|
||||||
|
--wot-dark-color: #ffffff;
|
||||||
|
|
||||||
|
/* 暗黑模式下的文本颜色变量 */
|
||||||
|
--wot-color-text: #ffffff;
|
||||||
|
--wot-color-text-secondary: #cccccc;
|
||||||
|
--wot-color-text-placeholder: #999999;
|
||||||
|
|
||||||
|
/* 暗黑模式下的边框和背景变量 */
|
||||||
|
--wot-color-border: #374151;
|
||||||
|
--wot-color-bg-container: #111111;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user