feat: 重构主题管理并优化UI样式

重构主题管理逻辑,将useTheme composable迁移至pinia store中管理
更新页面布局和样式,调整边距和卡片样式
添加新的主题配置文件并移除旧的主题图片资源
优化登录页和设置页的UI交互
更新unocss配置添加更多flex快捷类
This commit is contained in:
zhangtao
2025-08-28 01:14:29 +08:00
parent b93d1c61cb
commit 01387a53b4
41 changed files with 259 additions and 257 deletions
+1 -1
View File
@@ -7,7 +7,7 @@ VITE_APP_ENV=development
VITE_APP_TITLE=fastapiadmin
# 网络请求公用地址
VITE_API_BASE_URL=http://localhost:8001
VITE_API_BASE_URL=https://service.fastapiadmin.com
# 代理前缀
VITE_APP_BASE_API=/api/v1
+1 -63
View File
@@ -93,68 +93,6 @@
"watchSyncEffect": true,
"DirectiveBinding": true,
"MaybeRef": true,
"MaybeRefOrGetter": true,
"CommonUtil": true,
"Storage": true,
"acceptHMRUpdate": true,
"applyThemeOnPageShow": true,
"applyThemeToMiniProgram": true,
"auth": true,
"checkLogin": true,
"clearAll": true,
"clearToken": true,
"clearTokens": true,
"clearUserInfo": true,
"createPinia": true,
"createRouter": true,
"debounce": true,
"defineStore": true,
"dept": true,
"dict": true,
"file": true,
"getAccessToken": true,
"getActivePinia": true,
"getDarkerColor": true,
"getLighterColor": true,
"getRefreshToken": true,
"getToken": true,
"getUserInfo": true,
"isLoggedIn": true,
"log": true,
"mapActions": true,
"mapGetters": true,
"mapState": true,
"mapStores": true,
"mapWritableState": true,
"menu": true,
"notice": true,
"request": true,
"requireLogin": true,
"role": true,
"setAccessToken": true,
"setActivePinia": true,
"setMapStoreSuffix": true,
"setRefreshToken": true,
"setToken": true,
"setUserInfo": true,
"setupStore": true,
"store": true,
"storeToRefs": true,
"useDictStore": true,
"useMessage": true,
"useNotify": true,
"useRoute": true,
"useRouter": true,
"useThemeStore": true,
"useToast": true,
"useUserStore": true,
"user": true,
"config": true,
"extendedColorOptions": true,
"themeColorOptions": true,
"useStomp": true,
"useTabbar": true,
"useTheme": true,
"useWechat": true
"MaybeRefOrGetter": true
}
}
+7 -1
View File
@@ -1,5 +1,11 @@
{
"extends": ["stylelint-config-recommended", "stylelint-config-recommended-scss", "stylelint-config-recommended-vue/scss", "stylelint-config-html/vue", "stylelint-config-recess-order"],
"extends": [
"stylelint-config-recommended",
"stylelint-config-recommended-scss",
"stylelint-config-recommended-vue/scss",
"stylelint-config-html/vue",
"stylelint-config-recess-order"
],
"plugins": ["stylelint-prettier"],
"overrides": [
{
-7
View File
@@ -23,8 +23,6 @@ declare module 'vue' {
WdCell: typeof import('wot-design-uni/components/wd-cell/wd-cell.vue')['default']
WdCellGroup: typeof import('wot-design-uni/components/wd-cell-group/wd-cell-group.vue')['default']
WdCheckbox: typeof import('wot-design-uni/components/wd-checkbox/wd-checkbox.vue')['default']
WdCollapse: typeof import('wot-design-uni/components/wd-collapse/wd-collapse.vue')['default']
WdCollapseItem: typeof import('wot-design-uni/components/wd-collapse-item/wd-collapse-item.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']
WdForm: typeof import('wot-design-uni/components/wd-form/wd-form.vue')['default']
@@ -32,15 +30,12 @@ declare module 'vue' {
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']
WdImg: typeof import('wot-design-uni/components/wd-img/wd-img.vue')['default']
WdImgCropper: typeof import('wot-design-uni/components/wd-img-cropper/wd-img-cropper.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']
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']
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']
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']
WdRadioGroup: typeof import('wot-design-uni/components/wd-radio-group/wd-radio-group.vue')['default']
WdSwiper: typeof import('wot-design-uni/components/wd-swiper/wd-swiper.vue')['default']
@@ -49,8 +44,6 @@ declare module 'vue' {
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']
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']
WdUpload: typeof import('wot-design-uni/components/wd-upload/wd-upload.vue')['default']
}
}
+3 -9
View File
@@ -29,10 +29,6 @@ export default [
"**/u-charts/**",
"**/qiun-**/**",
"**/auto-imports.d.ts",
// unplugin-auto-import 生成的类型文件,每次提交都改变,所以加入这里吧,与 .gitignore 配合使用
"src/types/auto-imports.d.ts",
// vite-plugin-uni-pages 生成的类型文件,每次切换分支都一堆不同的,所以直接 .gitignore
"uni-pages.d.ts",
],
},
// 检查文件的配置
@@ -47,15 +43,13 @@ export default [
...{
uni: "readonly", // uni-app 全局对象
UniApp: "readonly", // uni-app 全局对象
PageResult: "readonly", // 分页结果数据类型
PageQuery: "readonly", // 分页查询数据类型
OptionType: "readonly", // 选项类型
getCurrentPages: "readonly", // uni-app 全局 API
ApiResponse: "readonly", // 统一响应数据类型
PageQuery: "readonly", // 分页查询数据类型
PageResult: "readonly", // 分页结果数据类型
OptionType: "readonly", // 选项类型
creatorType: "readonly", // 创建人类型
UploadFileResult: "readonly", // 上传文件返回类型
Todo: "readonly", // 待办事项
TodoState: "readonly", // 待办事项状态
plus: true, // HTML5+ 运行时环境
},
},
+42
View File
@@ -0,0 +1,42 @@
// pages.config.ts
import { defineUniPages } from "@uni-helper/vite-plugin-uni-pages";
export default defineUniPages({
// 你也可以定义 pages 字段,它具有最高的优先级。
pages: [],
globalStyle: {
navigationBarBackgroundColor: "@navBgColor",
navigationBarTextStyle: "@navTxtStyle",
navigationBarTitleText: "FastApp",
backgroundColor: "@bgColor",
backgroundTextStyle: "@bgTxtStyle",
backgroundColorTop: "@bgColorTop",
backgroundColorBottom: "@bgColorBottom",
enablePullDownRefresh: false,
onReachBottomDistance: 50,
animationType: "pop-in",
animationDuration: 300,
},
tabBar: {
custom: true,
customize: true,
overlay: true,
height: "0",
color: "@tabColor",
selectedColor: "@tabSelectedColor",
backgroundColor: "@tabBgColor",
borderStyle: "@tabBorderStyle",
list: [
{
pagePath: "pages/index/index",
},
{
pagePath: "pages/work/index",
},
{
pagePath: "pages/mine/index",
},
],
},
});
Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 MiB

-48
View File
@@ -1,48 +0,0 @@
import { useThemeStore, ThemeMode, ThemeColorOption } from "@/store";
export function useTheme() {
const store = useThemeStore();
/**
* 切换暗黑模式
* @param mode 指定主题模式,不传则自动切换
*/
function toggleTheme(mode?: ThemeMode) {
store.toggleTheme(mode);
}
/**
* 设置主题色
* @param option 主题色选项
*/
function setThemeColor(option: ThemeColorOption) {
store.setCurrentThemeColor(option);
}
/**
* 初始化主题
*/
function initTheme() {
store.initTheme();
}
// 注意:全局主题管理已在App.vue中处理
// 包括:系统主题监听、导航栏颜色同步等
// 组件中一般不需要再调用initTheme(),除非有特殊需求
return {
// 状态
theme: computed(() => store.theme),
isDark: computed(() => store.isDark),
currentThemeColor: computed(() => store.currentThemeColor),
themeVars: computed(() => store.themeVars),
// 主题选项
themeColorOptions: computed(() => store.themeColorOptions),
// 方法
initTheme,
toggleTheme,
setThemeColor,
};
}
+11 -2
View File
@@ -1,7 +1,16 @@
<script lang="ts" setup>
import { useTheme } from "@/composables/useTheme";
import { onLoad } from "@dcloudio/uni-app";
import { useThemeStore } from "@/store/modules/theme.store";
const { theme, themeVars } = useTheme();
const useTheme = useThemeStore();
let theme = useTheme.theme;
let themeVars = useTheme.themeVars;
onLoad(() => {
theme = useTheme.theme;
themeVars = useTheme.themeVars;
});
</script>
<script lang="ts">
+5 -2
View File
@@ -26,12 +26,15 @@
<script setup lang="ts">
import { useRouter, useRoute } from "uni-mini-router";
import { useTheme } from "@/composables/useTheme";
import { useTabbar } from "@/composables/useTabbar";
import { useThemeStore } from "@/store/modules/theme.store";
const useTheme = useThemeStore();
const router = useRouter();
const route = useRoute();
const { themeVars, theme } = useTheme();
let theme = useTheme.theme;
let themeVars = useTheme.themeVars;
const { activeTabbar, getTabbarItemValue, setTabbarItemActive, tabbarList } = useTabbar();
function handleTabbarChange({ value }: { value: string }) {
+19 -16
View File
@@ -1,12 +1,4 @@
{
"easycom": {
"autoscan": true,
"custom": {
"^wd-(.*)": "wot-design-uni/components/wd-$1/wd-$1.vue",
"^cu-(.*)": "@/components/cu-$1/index.vue"
}
},
"pages": [
{
"path": "pages/index/index",
@@ -19,7 +11,11 @@
},
{
"path": "pages/login/index",
"type": "page"
"type": "page",
"name": "login",
"style": {
"navigationBarTitleText": "登录"
}
},
{
"path": "pages/mine/index",
@@ -127,20 +123,27 @@
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarBackgroundColor": "@navBgColor",
"navigationBarTextStyle": "@navTxtStyle",
"navigationBarTitleText": "FastApp",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
"backgroundColor": "@bgColor",
"backgroundTextStyle": "@bgTxtStyle",
"backgroundColorTop": "@bgColorTop",
"backgroundColorBottom": "@bgColorBottom",
"enablePullDownRefresh": false,
"onReachBottomDistance": 50,
"animationType": "pop-in",
"animationDuration": 300
},
"tabBar": {
"custom": true,
"customize": true,
"overlay": true,
"height": "0",
"color": "#474747",
"selectedColor": "#3B8DFF",
"backgroundColor": "#F8F8F8",
"borderStyle": "black",
"color": "@tabColor",
"selectedColor": "@tabSelectedColor",
"backgroundColor": "@tabBgColor",
"borderStyle": "@tabBorderStyle",
"list": [
{
"pagePath": "pages/index/index"
+3 -14
View File
@@ -58,7 +58,7 @@
</wd-grid-item>
</wd-grid>
<wd-card>
<wd-card type="rectangle">
<template #title>
<view class="flex-between">
<view>访问趋势</view>
@@ -76,7 +76,7 @@
</view>
</template>
<view class="w-full h-360px mb-40rpx">
<view class="h-330px mb-2rpx">
<qiun-data-charts type="area" :chartData="chartData" :opts="chartOpts" />
</view>
</wd-card>
@@ -135,11 +135,7 @@ const chartOpts = ref({
// 日期范围
const recentDaysRange = ref(7);
const swiperList = ref([
"/static/images/banner02.jpg",
"/static/images/banner03.jpg",
"/static/images/banner01.png",
]);
const swiperList = ref(["/static/images/banner01.jpg", "/static/images/banner02.jpg"]);
// 快捷导航列表
const navList = reactive([
@@ -194,13 +190,6 @@ const generateStaticTrendData = (days: number) => {
};
};
function handleClick(e: any) {
console.log(e);
}
function onChange(e: any) {
console.log(e);
}
// 加载访问统计数据(使用静态数据)
const loadVisitStatsData = async () => {
// 模拟异步加载
+15 -6
View File
@@ -5,7 +5,7 @@
<!-- Logo和标题区域 -->
<view class="header">
<wd-img src="/static/logo.png" class="logo" mode="aspectFit" />
<wd-img src="./static/logo.png" class="logo" mode="aspectFit" />
<text class="title">FastApp管理系统</text>
<text class="subtitle">欢迎使用移动端管理平台</text>
</view>
@@ -174,15 +174,17 @@
import { onLoad } from "@dcloudio/uni-app";
import { useUserStore } from "@/store";
import { useToast } from "wot-design-uni";
import { useTheme } from "@/composables/useTheme";
import AuthAPI, { type LoginFormData, type CaptchaInfo } from "@/api/auth";
import { useThemeStore } from "@/store/modules/theme.store";
const useTheme = useThemeStore();
const loginFormRef = ref();
const toast = useToast();
const loading = ref(false);
const userStore = useUserStore();
const loginType = ref<"account" | "phone">("account");
const { theme } = useTheme();
let theme = useTheme.theme;
// 登录表单数据
const loginFormData = ref<LoginFormData>({
@@ -281,7 +283,7 @@ const handleWechatLogin = async () => {
};
// 是否暗黑模式
const isDarkMode = computed(() => theme.value === "dark");
const isDarkMode = computed(() => theme === "dark");
// 导航函数
const navigateToUserAgreement = () => {
@@ -314,14 +316,21 @@ onLoad((options) => {
}
});
</script>
<route lang="json">
{
"name": "login",
"style": {
"navigationBarTitleText": "登录"
}
}
</route>
<style lang="scss" scoped>
.app-container {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
height: 100%;
height: 100vh;
min-height: 100%;
overflow: hidden;
background-color: var(--wot-color-bg-container);
+1 -1
View File
@@ -5,7 +5,7 @@
<wd-img
width="120rpx"
height="120rpx"
src="/static/logo.png"
src="./static/logo.png"
mode="aspectFit"
class="about-logo"
/>
+13 -5
View File
@@ -47,16 +47,24 @@
<wd-collapse v-model="activeNames" accordion>
<wd-collapse-item title="常见问题" name="faq">
<view class="faq-list">
<view v-for="(item, index) in faqList" :key="index" class="faq-item" :class="{
active: currentFaq === index,
}" @tap="toggleFaq(index)">
<view
v-for="(item, index) in faqList"
:key="index"
class="faq-item"
:class="{ active: currentFaq === index }"
@tap="toggleFaq(index)"
>
<view class="faq-header">
<view class="faq-question">
<wd-icon name="question-filled" size="28rpx" color="#ff9500" />
<text class="question-text">{{ item.question }}</text>
</view>
<wd-icon name="arrow-down-bold" size="24rpx" color="#999"
:custom-class="currentFaq === index ? 'rotate-180' : ''" />
<wd-icon
name="arrow-down-bold"
size="24rpx"
color="#999"
:custom-class="currentFaq === index ? 'rotate-180' : ''"
/>
</view>
<view v-if="currentFaq === index" class="faq-answer">
<text class="answer-text">{{ item.answer }}</text>
+24 -6
View File
@@ -10,14 +10,32 @@
</wd-radio>
</wd-radio-group>
<wd-textarea v-model="formData.description" label="问题描述" prop="description" placeholder="请详细描述您遇到的问题或建议..."
:maxlength="120" show-word-limit />
<wd-textarea
v-model="formData.description"
label="问题描述"
prop="description"
placeholder="请详细描述您遇到的问题或建议..."
:maxlength="120"
show-word-limit
/>
<wd-upload v-model="formData.fileList" label="相关截图" prop="fileList" :max-count="3" :before-read="beforeRead"
@delete="handleDelete" />
<wd-upload
v-model="formData.fileList"
label="相关截图"
prop="fileList"
:max-count="3"
:before-read="beforeRead"
@delete="handleDelete"
/>
<wd-input v-model="formData.contact" label="联系方式" prop="contact" placeholder="请输入您的手机号或邮箱" clearable
:border="false" />
<wd-input
v-model="formData.contact"
label="联系方式"
prop="contact"
placeholder="请输入您的手机号或邮箱"
clearable
:border="false"
/>
<wd-text size="small">选填便于我们与您联系</wd-text>
</wd-cell-group>
+2 -2
View File
@@ -358,7 +358,7 @@ watch(
// 卡片容器
.card-container {
margin: 24rpx 30rpx;
margin: 24rpx 12rpx;
overflow: hidden;
background-color: #fff;
border-radius: 16rpx;
@@ -419,7 +419,7 @@ watch(
display: flex;
align-items: center;
padding: 30rpx;
margin: 20rpx 30rpx;
margin: 24rpx 12rpx;
background-color: #ffffff;
border-radius: 16rpx;
box-shadow: 0 1rpx 3rpx rgba(0, 0, 0, 0.1);
+3 -5
View File
@@ -1,6 +1,6 @@
<template>
<view class="app-container">
<wd-cell-group custom-style="margin-top: 20rpx">
<wd-cell-group>
<wd-cell v-if="isLogin" title="个人资料" icon="user" is-link @click="navigateToProfile" />
<wd-cell v-if="isLogin" title="账号和安全" icon="secured" is-link @click="navigateToAccount" />
<wd-cell title="主题设置" icon="setting1" is-link @click="navigateToTheme" />
@@ -8,9 +8,7 @@
<wd-cell title="隐私政策" icon="folder" is-link @click="navigateToPrivacy" />
<wd-cell title="关于我们" icon="info-circle" is-link @click="navigateToAbout" />
<wd-cell title="进入官网" icon="internet" is-link @click="navigateToOfficialWebsite" />
</wd-cell-group>
<wd-cell-group custom-style="margin-top:40rpx">
<wd-divider />
<wd-cell title="网络测试" icon="wifi" is-link @click="navigateToNetworkTest" />
<wd-cell title="清空缓存" icon="delete1" :value="cacheSize" clickable @click="handleClearCache" />
</wd-cell-group>
@@ -214,7 +212,7 @@ onLoad(() => {
align-items: center;
justify-content: center;
padding: 0 20rpx;
margin-top: 60rpx;
margin-top: 40rpx;
}
.logout-btn {
+12 -25
View File
@@ -29,10 +29,10 @@
<text class="color-label">预设主题色</text>
<view class="color-grid">
<view
v-for="(color, index) in themeColorOptions"
v-for="(color, index) in useTheme.themeColorOptions"
:key="index"
class="color-item"
:class="{ active: currentThemeColor === color.primary }"
:class="{ active: color.primary }"
@click="handleSelectColor(color)"
>
<view
@@ -113,13 +113,12 @@
</template>
<script lang="ts" setup>
import { useTheme } from "@/composables/useTheme";
import { useThemeStore } from "@/store/modules/theme.store";
// 使
const { isDark, themeVars, themeColorOptions, toggleTheme, setThemeColor } = useTheme();
const useTheme = useThemeStore();
//
const isDarkMode = computed(() => isDark.value);
const isDarkMode = computed(() => useTheme.isDark);
//
const customColor = ref("");
@@ -127,12 +126,12 @@ const showCustomColorInput = ref(false);
//
const currentThemeColor = computed(() => {
return themeVars.value.colorTheme || themeColorOptions.value[0].primary;
return useTheme.themeVars.colorTheme || useTheme.themeColorOptions[0].primary;
});
//
const handleSelectColor = (color: (typeof themeColorOptions.value)[0]) => {
setThemeColor(color);
const handleSelectColor = (color: (typeof useTheme.themeColorOptions)[0]) => {
useTheme.setCurrentThemeColor(color);
customColor.value = color.primary;
//
@@ -175,7 +174,7 @@ const applyCustomColor = () => {
primary: color,
};
setThemeColor(customColorOption);
useTheme.setCurrentThemeColor(customColorOption);
showCustomColorInput.value = false;
//
@@ -193,8 +192,8 @@ const handleResetTheme = () => {
content: "确定要重置为默认主题吗?",
success: (res) => {
if (res.confirm) {
setThemeColor(themeColorOptions.value[0]);
customColor.value = themeColorOptions.value[0].primary;
useTheme.setCurrentThemeColor(useTheme.themeColorOptions[0]);
customColor.value = useTheme.themeColorOptions[0].primary;
uni.showToast({
title: "已重置为默认主题",
@@ -208,7 +207,7 @@ const handleResetTheme = () => {
//
const handleToggleDarkMode = () => {
toggleTheme();
useTheme.toggleTheme();
nextTick(() => {
uni.showToast({
title: `已切换到${isDarkMode.value ? "暗黑" : "浅色"}模式`,
@@ -378,18 +377,6 @@ onShow(() => {
}
}
.preview-border {
display: flex;
align-items: center;
justify-content: center;
width: 200rpx;
height: 60rpx;
font-size: 26rpx;
color: var(--wot-color-text-secondary, #666);
border: 2rpx solid;
border-radius: 8rpx;
}
//
.custom-color-popup {
padding: 40rpx 30rpx;
+12 -2
View File
@@ -22,7 +22,12 @@
<text class="section-subtitle">常用功能一键直达</text>
</view>
<view class="actions-grid">
<view class="action-item" v-for="(action, index) in quickActions" :key="index" @tap="handleQuickAction(action)">
<view
v-for="(action, index) in quickActions"
:key="index"
class="action-item"
@tap="handleQuickAction(action)"
>
<view class="action-icon" :style="{ backgroundColor: action.color + '15' }">
<wd-icon :name="action.icon" :color="action.color" size="28" />
</view>
@@ -38,7 +43,12 @@
<text class="section-subtitle">{{ pendingTodos.length }} 项待处理</text>
</view>
<view class="todo-list">
<view class="todo-item" v-for="(todo, index) in pendingTodos" :key="index" @tap="handleTodoItem(todo)">
<view
v-for="(todo, index) in pendingTodos"
:key="index"
class="todo-item"
@tap="handleTodoItem(todo)"
>
<view class="todo-priority" :class="'priority-' + todo.priority">
<view class="priority-dot"></view>
</view>
-1
View File
@@ -32,7 +32,6 @@ const router = createRouter({
// 全局前置守卫
router.beforeEach((to, from, next) => {
// 检查页面是否需要登录
if (to.meta && to.meta.requireAuth && !isLoggedIn()) {
uni.showModal({
title: "提示",
Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 243 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

@@ -1,31 +0,0 @@
<svg width="100%" height="100%" viewBox="0 0 1000 1000" xmlns="http://www.w3.org/2000/svg">
<!-- 背景渐变 -->
<defs>
<linearGradient id="bgGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#94BFFF" />
<stop offset="100%" stop-color="#165DFF" />
</linearGradient>
<!-- 图形渐变 -->
<linearGradient id="shapeGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#ffffff" stop-opacity="0.3" />
<stop offset="100%" stop-color="#ffffff" stop-opacity="0.15" />
</linearGradient>
</defs>
<!-- 透明背景,不完全填充 -->
<rect width="100%" height="50%" fill="url(#bgGradient)" />
<!-- 左侧方块装饰 -->
<rect x="100" y="150" width="120" height="120" rx="15" fill="url(#shapeGradient)" transform="rotate(-10, 160, 210)" opacity="0.7" />
<rect x="190" y="90" width="80" height="80" rx="10" fill="url(#shapeGradient)" transform="rotate(15, 230, 130)" opacity="0.6" />
<rect x="60" y="250" width="100" height="100" rx="10" fill="url(#shapeGradient)" transform="rotate(-5, 110, 300)" opacity="0.5" />
<!-- 右侧圆形装饰 -->
<circle cx="750" cy="150" r="60" fill="url(#shapeGradient)" opacity="0.7" />
<circle cx="820" cy="230" r="90" fill="url(#shapeGradient)" opacity="0.5" />
<circle cx="690" cy="250" r="40" fill="url(#shapeGradient)" opacity="0.6" />
<!-- 底部波浪 -->
<path d="M0,900 C200,800 350,950 550,870 C750,790 850,900 1000,850 L1000,1000 L0,1000 Z" fill="#ffffff" />
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 MiB

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

+12 -7
View File
@@ -1,6 +1,7 @@
import { defineStore } from "pinia";
import type { ConfigProviderThemeVars } from "wot-design-uni";
import { useStorage } from "@uni-helper/uni-use";
import type { ConfigProviderThemeVars } from "wot-design-uni";
import { nextTick, reactive, computed } from "vue";
// 主题色选项接口
export interface ThemeColorOption {
@@ -46,12 +47,6 @@ export const useThemeStore = defineStore("appTheme", () => {
// 计算属性
const isDark = computed(() => theme.value === "dark");
// 切换主题, 指定主题模式,不传则自动切换
const toggleTheme = (mode?: ThemeMode) => {
theme.value = mode || (theme.value === "light" ? "dark" : "light");
setNavigationBarColor();
};
// 设置导航栏颜色
const setNavigationBarColor = () => {
console.log("设置导航栏颜色", theme.value);
@@ -61,6 +56,12 @@ export const useThemeStore = defineStore("appTheme", () => {
});
};
// 切换主题, 指定主题模式,不传则自动切换
const toggleTheme = (mode?: ThemeMode) => {
theme.value = mode || (theme.value === "light" ? "dark" : "light");
setNavigationBarColor();
};
// 设置主题色
const setCurrentThemeColor = (color: ThemeColorOption) => {
currentThemeColor.value = color;
@@ -79,6 +80,10 @@ export const useThemeStore = defineStore("appTheme", () => {
});
};
// 注意:全局主题管理已在App.vue中处理
// 包括:系统主题监听、导航栏颜色同步等
// 组件中一般不需要再调用initTheme(),除非有特殊需求
return {
// 状态
theme,
+26
View File
@@ -0,0 +1,26 @@
{
"light": {
"bgColor": "#F8F8F8",
"bgColorBottom": "#F8F8F8",
"bgColorTop": "#F8F8F8",
"bgTxtStyle": "dark",
"navBgColor": "#FFF",
"navTxtStyle": "black",
"tabBgColor": "#ffffff",
"tabBorderStyle": "black",
"tabColor": "#bfbfbf",
"tabSelectedColor": "#0165FF"
},
"dark": {
"bgColor": "#000",
"bgColorBottom": "#000",
"bgColorTop": "#000",
"bgTxtStyle": "light",
"navBgColor": "#000000",
"navTxtStyle": "white",
"tabBgColor": "#1a1a1a",
"tabBorderStyle": "white",
"tabColor": "#bfbfbf",
"tabSelectedColor": "#0165FF"
}
}
-1
View File
@@ -326,7 +326,6 @@ declare module 'vue' {
readonly useStomp: UnwrapRef<typeof import('../composables/useStomp')['useStomp']>
readonly useTabbar: UnwrapRef<typeof import('../composables/useTabbar')['useTabbar']>
readonly useTemplateRef: UnwrapRef<typeof import('vue')['useTemplateRef']>
readonly useTheme: UnwrapRef<typeof import('../composables/useTheme')['useTheme']>
readonly useThemeStore: UnwrapRef<typeof import('../store/modules/theme.store')['useThemeStore']>
readonly useToast: UnwrapRef<typeof import('wot-design-uni')['useToast']>
readonly useUserStore: UnwrapRef<typeof import('../store/modules/user.store')['useUserStore']>
+35
View File
@@ -0,0 +1,35 @@
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// Generated by vite-plugin-uni-pages
interface NavigateToOptions {
url: "/pages/index/index" |
"/pages/login/index" |
"/pages/mine/index" |
"/pages/work/index" |
"/pages/mine/about/index" |
"/pages/mine/faq/index" |
"/pages/mine/feedback/index" |
"/pages/mine/profile/complete-profile" |
"/pages/mine/profile/index" |
"/pages/mine/settings/index" |
"/pages/mine/settings/account/index" |
"/pages/mine/settings/agreement/index" |
"/pages/mine/settings/network/index" |
"/pages/mine/settings/theme/index";
}
interface RedirectToOptions extends NavigateToOptions {}
interface SwitchTabOptions {
url: "/pages/index/index" | "/pages/mine/index"
}
type ReLaunchOptions = NavigateToOptions | SwitchTabOptions;
declare interface Uni {
navigateTo(options: UniNamespace.NavigateToOptions & NavigateToOptions): void;
redirectTo(options: UniNamespace.RedirectToOptions & RedirectToOptions): void;
switchTab(options: UniNamespace.SwitchTabOptions & SwitchTabOptions): void;
reLaunch(options: UniNamespace.ReLaunchOptions & ReLaunchOptions): void;
}
+11 -1
View File
@@ -12,10 +12,20 @@ export default {
],
shortcuts: [
{
"flex-center": "flex justify-center items-center flex-wrap",
"flex-center": "flex justify-center items-center",
"flex-start": "flex justify-start items-center",
"flex-end": "flex justify-end items-center",
"flex-between": "flex justify-between items-center",
"flex-around": "flex justify-around items-center",
"flex-evenly": "flex justify-evenly items-center",
"flex-stretch": "flex justify-stretch items-center",
"flex-baseline": "flex justify-baseline items-center",
"flex-column": "flex flex-col",
"flex-row": "flex flex-row",
// 垂直布局并居中对齐
"flex-col-center": "flex flex-col items-center",
},
],
+1
View File
@@ -3,6 +3,7 @@ import uni from "@dcloudio/vite-plugin-uni";
import AutoImport from "unplugin-auto-import/vite";
import UniLayouts from "@uni-helper/vite-plugin-uni-layouts";
import UniPages from "@uni-helper/vite-plugin-uni-pages";
import Components from "@uni-helper/vite-plugin-uni-components";
import { WotResolver } from "@uni-helper/vite-plugin-uni-components/resolvers";
-1
View File
@@ -587,7 +587,6 @@ declare module 'vue' {
readonly useThrottleFn: UnwrapRef<typeof import('@vueuse/core')['useThrottleFn']>
readonly useThrottledRefHistory: UnwrapRef<typeof import('@vueuse/core')['useThrottledRefHistory']>
readonly useTimeAgo: UnwrapRef<typeof import('@vueuse/core')['useTimeAgo']>
readonly useTimeAgoIntl: UnwrapRef<typeof import('@vueuse/core')['useTimeAgoIntl']>
readonly useTimeout: UnwrapRef<typeof import('@vueuse/core')['useTimeout']>
readonly useTimeoutFn: UnwrapRef<typeof import('@vueuse/core')['useTimeoutFn']>
readonly useTimeoutPoll: UnwrapRef<typeof import('@vueuse/core')['useTimeoutPoll']>