refactor: 主题设置重构优化
This commit is contained in:
1
components.d.ts
vendored
1
components.d.ts
vendored
@@ -35,6 +35,7 @@ declare module 'vue' {
|
|||||||
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']
|
||||||
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']
|
||||||
WdSwiper: typeof import('wot-design-uni/components/wd-swiper/wd-swiper.vue')['default']
|
WdSwiper: typeof import('wot-design-uni/components/wd-swiper/wd-swiper.vue')['default']
|
||||||
WdSwitch: typeof import('wot-design-uni/components/wd-switch/wd-switch.vue')['default']
|
WdSwitch: typeof import('wot-design-uni/components/wd-switch/wd-switch.vue')['default']
|
||||||
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']
|
||||||
|
|||||||
@@ -1,13 +1,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onLaunch, onShow, onHide } from "@dcloudio/uni-app";
|
import { onLaunch, onShow, onHide } from "@dcloudio/uni-app";
|
||||||
import { useTheme } from "@/composables/useTheme";
|
|
||||||
|
|
||||||
const { initTheme } = useTheme();
|
|
||||||
|
|
||||||
onLaunch(() => {
|
onLaunch(() => {
|
||||||
console.log("App Launch");
|
console.log("App Launch");
|
||||||
// 初始化主题
|
|
||||||
initTheme();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
onShow(() => {
|
onShow(() => {
|
||||||
|
|||||||
46
src/composables/types/theme.ts
Normal file
46
src/composables/types/theme.ts
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import type { ConfigProviderThemeVars } from "wot-design-uni";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主题色选项接口
|
||||||
|
*/
|
||||||
|
export interface ThemeColorOption {
|
||||||
|
name: string;
|
||||||
|
value: string;
|
||||||
|
primary: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主题类型
|
||||||
|
*/
|
||||||
|
export type ThemeMode = "light" | "dark";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主题状态接口
|
||||||
|
*/
|
||||||
|
export interface ThemeState {
|
||||||
|
theme: ThemeMode;
|
||||||
|
followSystem: boolean;
|
||||||
|
hasUserSet: boolean;
|
||||||
|
currentThemeColor: ThemeColorOption;
|
||||||
|
themeVars: ConfigProviderThemeVars;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统主题状态接口(简化版)
|
||||||
|
*/
|
||||||
|
export interface SystemThemeState {
|
||||||
|
theme: ThemeMode;
|
||||||
|
themeVars: ConfigProviderThemeVars;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预定义的主题色选项
|
||||||
|
*/
|
||||||
|
export const themeColorOptions: ThemeColorOption[] = [
|
||||||
|
{ name: "默认蓝", value: "blue", primary: "#4D7FFF" },
|
||||||
|
{ name: "活力橙", value: "orange", primary: "#FF7D00" },
|
||||||
|
{ name: "薄荷绿", value: "green", primary: "#07C160" },
|
||||||
|
{ name: "樱花粉", value: "pink", primary: "#FF69B4" },
|
||||||
|
{ name: "紫罗兰", value: "purple", primary: "#8A2BE2" },
|
||||||
|
{ name: "朱砂红", value: "red", primary: "#FF4757" },
|
||||||
|
];
|
||||||
@@ -1,178 +1,132 @@
|
|||||||
import type { ConfigProviderThemeVars } from "wot-design-uni";
|
import { defineStore } from "pinia";
|
||||||
|
import type { ThemeColorOption, ThemeMode, ThemeState } from "@/composables/types/theme";
|
||||||
|
import { themeColorOptions } from "@/composables/types/theme";
|
||||||
|
|
||||||
// 定义主题色选项
|
/**
|
||||||
export interface ThemeColorOption {
|
* 完整版主题状态管理
|
||||||
name: string;
|
* 支持手动切换主题、主题色选择、跟随系统主题等完整功能
|
||||||
value: string;
|
*/
|
||||||
primary: string;
|
export const useThemeStore = defineStore("theme", {
|
||||||
}
|
state: (): ThemeState => ({
|
||||||
|
theme: "light",
|
||||||
|
followSystem: true, // 是否跟随系统主题
|
||||||
|
hasUserSet: false, // 用户是否手动设置过主题
|
||||||
|
currentThemeColor: themeColorOptions[0],
|
||||||
|
themeVars: {
|
||||||
|
darkBackground: "#0f0f0f",
|
||||||
|
darkBackground2: "#1a1a1a",
|
||||||
|
darkBackground3: "#242424",
|
||||||
|
darkBackground4: "#2f2f2f",
|
||||||
|
darkBackground5: "#3d3d3d",
|
||||||
|
darkBackground6: "#4a4a4a",
|
||||||
|
darkBackground7: "#606060",
|
||||||
|
darkColor: "#ffffff",
|
||||||
|
darkColor2: "#e0e0e0",
|
||||||
|
darkColor3: "#a0a0a0",
|
||||||
|
colorTheme: themeColorOptions[0].primary,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
// 预定义的主题色选项
|
getters: {
|
||||||
export const themeColorOptions: ThemeColorOption[] = [
|
isDark: (state) => state.theme === "dark",
|
||||||
{ name: "默认蓝", value: "blue", primary: "#4D7FFF" },
|
},
|
||||||
{ name: "活力橙", value: "orange", primary: "#FF7D00" },
|
|
||||||
{ name: "薄荷绿", value: "green", primary: "#07C160" },
|
|
||||||
{ name: "樱花粉", value: "pink", primary: "#FF69B4" },
|
|
||||||
{ name: "紫罗兰", value: "purple", primary: "#8A2BE2" },
|
|
||||||
{ name: "朱砂红", value: "red", primary: "#FF4757" },
|
|
||||||
];
|
|
||||||
|
|
||||||
export function useTheme() {
|
actions: {
|
||||||
// 状态定义
|
/**
|
||||||
const theme = ref<"light" | "dark">("light");
|
* 手动切换主题
|
||||||
const followSystem = ref(true); // 是否跟随系统主题
|
* @param mode 指定主题模式,不传则自动切换
|
||||||
const hasUserSet = ref(false); // 用户是否手动设置过主题
|
*/
|
||||||
const currentThemeColor = ref<ThemeColorOption>(themeColorOptions[0]);
|
toggleTheme(mode?: ThemeMode) {
|
||||||
const showThemeColorSheet = ref(false);
|
this.theme = mode || (this.theme === "light" ? "dark" : "light");
|
||||||
|
this.hasUserSet = true; // 标记用户已手动设置
|
||||||
|
this.followSystem = false; // 不再跟随系统
|
||||||
|
this.setNavigationBarColor();
|
||||||
|
},
|
||||||
|
|
||||||
const themeVars = reactive<ConfigProviderThemeVars>({
|
/**
|
||||||
darkBackground: "#0f0f0f",
|
* 设置是否跟随系统主题
|
||||||
darkBackground2: "#1a1a1a",
|
* @param follow 是否跟随系统
|
||||||
darkBackground3: "#242424",
|
*/
|
||||||
darkBackground4: "#2f2f2f",
|
setFollowSystem(follow: boolean) {
|
||||||
darkBackground5: "#3d3d3d",
|
this.followSystem = follow;
|
||||||
darkBackground6: "#4a4a4a",
|
if (follow) {
|
||||||
darkBackground7: "#606060",
|
this.hasUserSet = false;
|
||||||
darkColor: "#ffffff",
|
this.initTheme(); // 重新获取系统主题
|
||||||
darkColor2: "#e0e0e0",
|
|
||||||
darkColor3: "#a0a0a0",
|
|
||||||
colorTheme: themeColorOptions[0].primary,
|
|
||||||
});
|
|
||||||
|
|
||||||
// 计算属性
|
|
||||||
const isDark = computed(() => theme.value === "dark");
|
|
||||||
|
|
||||||
/* 手动切换主题 */
|
|
||||||
function toggleTheme(mode?: "light" | "dark") {
|
|
||||||
theme.value = mode || (theme.value === "light" ? "dark" : "light");
|
|
||||||
hasUserSet.value = true; // 标记用户已手动设置
|
|
||||||
followSystem.value = false; // 不再跟随系统
|
|
||||||
setNavigationBarColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 设置是否跟随系统主题 */
|
|
||||||
function setFollowSystem(follow: boolean) {
|
|
||||||
followSystem.value = follow;
|
|
||||||
if (follow) {
|
|
||||||
hasUserSet.value = false;
|
|
||||||
initTheme(); // 重新获取系统主题
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 设置导航栏颜色 */
|
|
||||||
function setNavigationBarColor() {
|
|
||||||
uni.setNavigationBarColor({
|
|
||||||
frontColor: theme.value === "light" ? "#000000" : "#ffffff",
|
|
||||||
backgroundColor: theme.value === "light" ? "#ffffff" : "#000000",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 设置主题色 */
|
|
||||||
function setCurrentThemeColor(color: ThemeColorOption) {
|
|
||||||
currentThemeColor.value = color;
|
|
||||||
themeVars.colorTheme = color.primary;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 获取系统主题 */
|
|
||||||
function getSystemTheme(): "light" | "dark" {
|
|
||||||
try {
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
// 微信小程序使用 getAppBaseInfo
|
|
||||||
const appBaseInfo = uni.getAppBaseInfo();
|
|
||||||
if (appBaseInfo && appBaseInfo.theme) {
|
|
||||||
return appBaseInfo.theme as "light" | "dark";
|
|
||||||
}
|
}
|
||||||
// #endif
|
},
|
||||||
|
|
||||||
// #ifndef MP-WEIXIN
|
/**
|
||||||
// 其他平台使用 getSystemInfoSync
|
* 设置导航栏颜色
|
||||||
const systemInfo = uni.getSystemInfoSync();
|
*/
|
||||||
if (systemInfo && systemInfo.theme) {
|
setNavigationBarColor() {
|
||||||
return systemInfo.theme as "light" | "dark";
|
uni.setNavigationBarColor({
|
||||||
}
|
frontColor: this.theme === "light" ? "#000000" : "#ffffff",
|
||||||
// #endif
|
backgroundColor: this.theme === "light" ? "#ffffff" : "#000000",
|
||||||
} catch (error) {
|
|
||||||
console.warn("获取系统主题失败:", error);
|
|
||||||
}
|
|
||||||
return "light"; // 默认返回 light
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 初始化主题 */
|
|
||||||
function initTheme() {
|
|
||||||
// 如果用户已手动设置且不跟随系统,保持当前主题
|
|
||||||
if (hasUserSet.value && !followSystem.value) {
|
|
||||||
console.log("使用用户设置的主题:", theme.value);
|
|
||||||
setNavigationBarColor();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取系统主题
|
|
||||||
const systemTheme = getSystemTheme();
|
|
||||||
|
|
||||||
// 如果是首次启动或跟随系统,使用系统主题
|
|
||||||
if (!hasUserSet.value || followSystem.value) {
|
|
||||||
theme.value = systemTheme;
|
|
||||||
if (!hasUserSet.value) {
|
|
||||||
followSystem.value = true;
|
|
||||||
console.log("首次启动,使用系统主题:", theme.value);
|
|
||||||
} else {
|
|
||||||
console.log("跟随系统主题:", theme.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setNavigationBarColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 打开主题色选择 */
|
|
||||||
function openThemeColorPicker() {
|
|
||||||
showThemeColorSheet.value = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 关闭主题色选择 */
|
|
||||||
function closeThemeColorPicker() {
|
|
||||||
showThemeColorSheet.value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 选择主题色 */
|
|
||||||
function selectThemeColor(option: ThemeColorOption) {
|
|
||||||
setCurrentThemeColor(option);
|
|
||||||
closeThemeColorPicker();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查函数是否存在的工具函数
|
|
||||||
const isFunction = (fn: any): boolean => typeof fn === "function";
|
|
||||||
|
|
||||||
onBeforeMount(() => {
|
|
||||||
initTheme();
|
|
||||||
if (isFunction(uni.onThemeChange)) {
|
|
||||||
uni.onThemeChange((res) => {
|
|
||||||
toggleTheme(res.theme);
|
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
});
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
/**
|
||||||
if (isFunction(uni.offThemeChange)) {
|
* 设置主题色
|
||||||
uni.offThemeChange((res) => {
|
* @param color 主题色选项
|
||||||
toggleTheme(res.theme);
|
*/
|
||||||
});
|
setCurrentThemeColor(color: ThemeColorOption) {
|
||||||
}
|
this.currentThemeColor = color;
|
||||||
});
|
this.themeVars.colorTheme = color.primary;
|
||||||
|
},
|
||||||
|
|
||||||
return {
|
/**
|
||||||
theme: computed(() => theme.value),
|
* 获取系统主题
|
||||||
isDark,
|
* @returns 系统主题模式
|
||||||
followSystem: computed(() => followSystem.value),
|
*/
|
||||||
hasUserSet: computed(() => hasUserSet.value),
|
getSystemTheme(): ThemeMode {
|
||||||
currentThemeColor: computed(() => currentThemeColor.value),
|
try {
|
||||||
showThemeColorSheet,
|
// #ifdef MP-WEIXIN
|
||||||
themeVars,
|
// 微信小程序使用 getAppBaseInfo
|
||||||
themeColorOptions,
|
const appBaseInfo = uni.getAppBaseInfo();
|
||||||
initTheme,
|
if (appBaseInfo && appBaseInfo.theme) {
|
||||||
toggleTheme,
|
return appBaseInfo.theme as ThemeMode;
|
||||||
setFollowSystem,
|
}
|
||||||
openThemeColorPicker,
|
// #endif
|
||||||
closeThemeColorPicker,
|
|
||||||
selectThemeColor,
|
// #ifndef MP-WEIXIN
|
||||||
};
|
// 其他平台使用 getSystemInfoSync
|
||||||
}
|
const systemInfo = uni.getSystemInfoSync();
|
||||||
|
if (systemInfo && systemInfo.theme) {
|
||||||
|
return systemInfo.theme as ThemeMode;
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
} catch (error) {
|
||||||
|
console.warn("获取系统主题失败:", error);
|
||||||
|
}
|
||||||
|
return "light"; // 默认返回 light
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化主题
|
||||||
|
*/
|
||||||
|
initTheme() {
|
||||||
|
// 如果用户已手动设置且不跟随系统,保持当前主题
|
||||||
|
if (this.hasUserSet && !this.followSystem) {
|
||||||
|
console.log("使用用户设置的主题:", this.theme);
|
||||||
|
this.setNavigationBarColor();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取系统主题
|
||||||
|
const systemTheme = this.getSystemTheme();
|
||||||
|
|
||||||
|
// 如果是首次启动或跟随系统,使用系统主题
|
||||||
|
if (!this.hasUserSet || this.followSystem) {
|
||||||
|
this.theme = systemTheme;
|
||||||
|
if (!this.hasUserSet) {
|
||||||
|
this.followSystem = true;
|
||||||
|
console.log("首次启动,使用系统主题:", this.theme);
|
||||||
|
} else {
|
||||||
|
console.log("跟随系统主题:", this.theme);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setNavigationBarColor();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|||||||
@@ -2,5 +2,14 @@
|
|||||||
* 常量统一导出
|
* 常量统一导出
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// 存储相关常量
|
/**
|
||||||
export * from "./storage.constant";
|
* 存储键常量统一管理
|
||||||
|
* 包括 localStorage、sessionStorage 等各种存储的键名
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 🔐 用户认证相关
|
||||||
|
export const ACCESS_TOKEN_KEY = "access_token";
|
||||||
|
export const REFRESH_TOKEN_KEY = "refresh_token";
|
||||||
|
|
||||||
|
// 📊 用户缓存相关
|
||||||
|
export const USER_INFO_KEY = "user_info";
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
/**
|
|
||||||
* 存储键常量统一管理
|
|
||||||
* 包括 localStorage、sessionStorage 等各种存储的键名
|
|
||||||
*/
|
|
||||||
|
|
||||||
// 🔐 用户认证相关
|
|
||||||
export const ACCESS_TOKEN_KEY = "access_token";
|
|
||||||
export const REFRESH_TOKEN_KEY = "refresh_token";
|
|
||||||
|
|
||||||
// 📊 用户缓存相关
|
|
||||||
export const USER_INFO_KEY = "user_info";
|
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
const { theme, themeVars } = useTheme();
|
import { useThemeStore } from "@/composables/useTheme";
|
||||||
|
import { storeToRefs } from "pinia";
|
||||||
|
|
||||||
|
const themeStore = useThemeStore();
|
||||||
|
const { theme, themeVars } = storeToRefs(themeStore);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
|||||||
@@ -26,13 +26,15 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useRoute } from "vue-router";
|
import { useRoute } from "vue-router";
|
||||||
import { useTheme } from "@/composables/useTheme";
|
import { useThemeStore } from "@/composables/useTheme";
|
||||||
import { useTabbar } from "@/composables/useTabbar";
|
import { useTabbar } from "@/composables/useTabbar";
|
||||||
import { useRouter } from "uni-mini-router";
|
import { useRouter } from "uni-mini-router";
|
||||||
|
import { storeToRefs } from "pinia";
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { themeVars, theme } = useTheme();
|
const themeStore = useThemeStore();
|
||||||
|
const { themeVars, theme } = storeToRefs(themeStore);
|
||||||
const { activeTabbar, getTabbarItemValue, setTabbarItemActive, tabbarList } = useTabbar();
|
const { activeTabbar, getTabbarItemValue, setTabbarItemActive, tabbarList } = useTabbar();
|
||||||
|
|
||||||
function handleTabbarChange({ value }: { value: string }) {
|
function handleTabbarChange({ value }: { value: string }) {
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ import { type LoginData } from "@/api/auth";
|
|||||||
import { useUserStore } from "@/store/modules/user.store";
|
import { useUserStore } from "@/store/modules/user.store";
|
||||||
import { useToast } from "wot-design-uni";
|
import { useToast } from "wot-design-uni";
|
||||||
import { useWechat } from "@/composables/useWechat";
|
import { useWechat } from "@/composables/useWechat";
|
||||||
import { useTheme } from "@/composables/useTheme";
|
import { useThemeStore } from "@/composables/useTheme";
|
||||||
import { computed, onMounted } from "vue";
|
import { computed, onMounted } from "vue";
|
||||||
|
|
||||||
const loginFormRef = ref();
|
const loginFormRef = ref();
|
||||||
@@ -136,10 +136,10 @@ const userStore = useUserStore();
|
|||||||
const showPassword = ref(false);
|
const showPassword = ref(false);
|
||||||
const loginType = ref<"account" | "phone">("account");
|
const loginType = ref<"account" | "phone">("account");
|
||||||
const { authState, getLoginCode, getPhoneNumber } = useWechat();
|
const { authState, getLoginCode, getPhoneNumber } = useWechat();
|
||||||
const { theme } = useTheme();
|
const themeStore = useThemeStore();
|
||||||
|
|
||||||
// 是否暗黑模式
|
// 是否暗黑模式
|
||||||
const isDarkMode = computed(() => theme.value === "dark");
|
const isDarkMode = computed(() => themeStore.theme === "dark");
|
||||||
|
|
||||||
// 登录表单数据
|
// 登录表单数据
|
||||||
const loginFormData = ref<LoginData>({
|
const loginFormData = ref<LoginData>({
|
||||||
|
|||||||
@@ -162,12 +162,13 @@
|
|||||||
import { onShow } from "@dcloudio/uni-app";
|
import { onShow } from "@dcloudio/uni-app";
|
||||||
import { useToast } from "wot-design-uni";
|
import { useToast } from "wot-design-uni";
|
||||||
import { useUserStore } from "@/store/modules/user.store";
|
import { useUserStore } from "@/store/modules/user.store";
|
||||||
import { useTheme } from "@/composables/useTheme";
|
import { useThemeStore } from "@/composables/useTheme";
|
||||||
import { computed } from "vue";
|
import { computed } from "vue";
|
||||||
|
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const { currentThemeColor } = useTheme();
|
const themeStore = useThemeStore();
|
||||||
|
const currentThemeColor = computed(() => themeStore.themeVars.colorTheme);
|
||||||
const userInfo = computed(() => userStore.userInfo);
|
const userInfo = computed(() => userStore.userInfo);
|
||||||
const isLogin = computed(() => !!userInfo.value);
|
const isLogin = computed(() => !!userInfo.value);
|
||||||
const defaultAvatar = "/static/images/default-avatar.png";
|
const defaultAvatar = "/static/images/default-avatar.png";
|
||||||
|
|||||||
@@ -9,11 +9,11 @@
|
|||||||
<!-- 暗黑模式设置 -->
|
<!-- 暗黑模式设置 -->
|
||||||
<wd-card class="setting-section">
|
<wd-card class="setting-section">
|
||||||
<view class="section-header">
|
<view class="section-header">
|
||||||
<wd-icon name="moon" size="20" :color="theme === 'dark' ? '#FFD700' : '#666'" />
|
<wd-icon name="moon" size="20" :color="isDarkMode ? '#FFD700' : '#666'" />
|
||||||
<text class="section-title">外观模式</text>
|
<text class="section-title">外观模式</text>
|
||||||
</view>
|
</view>
|
||||||
<wd-cell title="暗黑模式" :value="theme === 'dark' ? '已开启' : '已关闭'">
|
<wd-cell title="暗黑模式" :value="isDarkMode ? '已开启' : '已关闭'">
|
||||||
<wd-switch :model-value="theme === 'dark'" @change="handleToggleDarkMode" />
|
<wd-switch :model-value="isDarkMode" @change="handleToggleDarkMode" />
|
||||||
</wd-cell>
|
</wd-cell>
|
||||||
</wd-card>
|
</wd-card>
|
||||||
|
|
||||||
@@ -95,6 +95,16 @@
|
|||||||
</wd-grid>
|
</wd-grid>
|
||||||
</wd-card>
|
</wd-card>
|
||||||
|
|
||||||
|
<!-- 跟随系统设置 -->
|
||||||
|
<wd-card class="setting-section">
|
||||||
|
<wd-cell title="跟随系统主题" :value="followSystemActive ? '已开启' : '已关闭'">
|
||||||
|
<wd-switch :model-value="followSystemActive" @change="handleFollowSystemChange" />
|
||||||
|
</wd-cell>
|
||||||
|
<view class="follow-system-tip p-3 text-sm text-gray-500">
|
||||||
|
开启后,应用会自动适配系统的深色/浅色模式设置
|
||||||
|
</view>
|
||||||
|
</wd-card>
|
||||||
|
|
||||||
<!-- 操作按钮 -->
|
<!-- 操作按钮 -->
|
||||||
<wd-card class="action-section">
|
<wd-card class="action-section">
|
||||||
<wd-button type="info" size="large" block @click="handleResetTheme">重置为默认主题</wd-button>
|
<wd-button type="info" size="large" block @click="handleResetTheme">重置为默认主题</wd-button>
|
||||||
@@ -136,9 +146,17 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useTheme, themeColorOptions } from "@/composables/useTheme";
|
import { useThemeStore } from "@/composables/useTheme";
|
||||||
|
import { themeColorOptions } from "@/composables/types/theme";
|
||||||
|
import { storeToRefs } from "pinia";
|
||||||
|
|
||||||
const { theme, themeVars, toggleTheme, selectThemeColor } = useTheme();
|
const themeStore = useThemeStore();
|
||||||
|
// 将store中的数据解构为响应式引用
|
||||||
|
const { themeVars } = storeToRefs(themeStore);
|
||||||
|
|
||||||
|
// 创建响应式的计算属性来解决类型问题
|
||||||
|
const isDarkMode = computed(() => themeStore.theme === "dark");
|
||||||
|
const followSystemActive = computed(() => themeStore.followSystem);
|
||||||
|
|
||||||
// 自定义颜色输入
|
// 自定义颜色输入
|
||||||
const customColor = ref("");
|
const customColor = ref("");
|
||||||
@@ -146,12 +164,12 @@ const showCustomColorInput = ref(false);
|
|||||||
|
|
||||||
// 当前选中的主题色
|
// 当前选中的主题色
|
||||||
const currentThemeColor = computed(() => {
|
const currentThemeColor = computed(() => {
|
||||||
return themeVars.colorTheme || themeColorOptions[0].primary;
|
return themeVars.value.colorTheme || themeColorOptions[0].primary;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 选择预设颜色
|
// 选择预设颜色
|
||||||
const handleSelectColor = (color: (typeof themeColorOptions)[0]) => {
|
const handleSelectColor = (color: (typeof themeColorOptions)[0]) => {
|
||||||
selectThemeColor(color);
|
themeStore.setCurrentThemeColor(color);
|
||||||
customColor.value = color.primary;
|
customColor.value = color.primary;
|
||||||
|
|
||||||
// 提示
|
// 提示
|
||||||
@@ -194,7 +212,7 @@ const applyCustomColor = () => {
|
|||||||
primary: color,
|
primary: color,
|
||||||
};
|
};
|
||||||
|
|
||||||
selectThemeColor(customColorOption);
|
themeStore.setCurrentThemeColor(customColorOption);
|
||||||
showCustomColorInput.value = false;
|
showCustomColorInput.value = false;
|
||||||
|
|
||||||
// 提示
|
// 提示
|
||||||
@@ -212,7 +230,7 @@ const handleResetTheme = () => {
|
|||||||
content: "确定要重置为默认主题吗?",
|
content: "确定要重置为默认主题吗?",
|
||||||
success: (res) => {
|
success: (res) => {
|
||||||
if (res.confirm) {
|
if (res.confirm) {
|
||||||
selectThemeColor(themeColorOptions[0]);
|
themeStore.setCurrentThemeColor(themeColorOptions[0]);
|
||||||
customColor.value = themeColorOptions[0].primary;
|
customColor.value = themeColorOptions[0].primary;
|
||||||
|
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
@@ -227,16 +245,21 @@ const handleResetTheme = () => {
|
|||||||
|
|
||||||
// 切换暗黑模式
|
// 切换暗黑模式
|
||||||
const handleToggleDarkMode = () => {
|
const handleToggleDarkMode = () => {
|
||||||
toggleTheme();
|
themeStore.toggleTheme();
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: `已切换到${theme.value === "dark" ? "暗黑" : "浅色"}模式`,
|
title: `已切换到${isDarkMode.value ? "暗黑" : "浅色"}模式`,
|
||||||
icon: "success",
|
icon: "success",
|
||||||
duration: 1500,
|
duration: 1500,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 处理跟随系统设置的变更
|
||||||
|
const handleFollowSystemChange = (value: boolean) => {
|
||||||
|
themeStore.setFollowSystem(value);
|
||||||
|
};
|
||||||
|
|
||||||
onLoad(() => {
|
onLoad(() => {
|
||||||
// 初始化自定义颜色输入框
|
// 初始化自定义颜色输入框
|
||||||
customColor.value = currentThemeColor.value;
|
customColor.value = currentThemeColor.value;
|
||||||
@@ -245,13 +268,15 @@ onLoad(() => {
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 初始化自定义颜色输入框
|
// 初始化自定义颜色输入框
|
||||||
customColor.value = currentThemeColor.value;
|
customColor.value = currentThemeColor.value;
|
||||||
|
// 初始化主题
|
||||||
|
themeStore.initTheme();
|
||||||
});
|
});
|
||||||
|
|
||||||
// 页面显示时确保主题色同步
|
// 页面显示时确保主题色同步
|
||||||
onShow(() => {
|
onShow(() => {
|
||||||
customColor.value = currentThemeColor.value;
|
customColor.value = currentThemeColor.value;
|
||||||
console.log("主题设置页面显示,当前主题:", {
|
console.log("主题设置页面显示,当前主题:", {
|
||||||
mode: theme.value,
|
mode: isDarkMode.value ? "dark" : "light",
|
||||||
color: currentThemeColor.value,
|
color: currentThemeColor.value,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
3
src/types/auto-imports.d.ts
vendored
3
src/types/auto-imports.d.ts
vendored
@@ -143,6 +143,7 @@ declare global {
|
|||||||
const useInterceptor: typeof import('@uni-helper/uni-use')['useInterceptor']
|
const useInterceptor: typeof import('@uni-helper/uni-use')['useInterceptor']
|
||||||
const useLink: (typeof import("vue-router"))["useLink"]
|
const useLink: (typeof import("vue-router"))["useLink"]
|
||||||
const useLoading: typeof import('@uni-helper/uni-use')['useLoading']
|
const useLoading: typeof import('@uni-helper/uni-use')['useLoading']
|
||||||
|
const useManualTheme: typeof import('../composables/useTheme')['useManualTheme']
|
||||||
const useMessage: typeof import('wot-design-uni')['useMessage']
|
const useMessage: typeof import('wot-design-uni')['useMessage']
|
||||||
const useModal: typeof import('@uni-helper/uni-use')['useModal']
|
const useModal: typeof import('@uni-helper/uni-use')['useModal']
|
||||||
const useModel: typeof import('vue')['useModel']
|
const useModel: typeof import('vue')['useModel']
|
||||||
@@ -296,7 +297,6 @@ declare module 'vue' {
|
|||||||
readonly shallowRef: UnwrapRef<typeof import('vue')['shallowRef']>
|
readonly shallowRef: UnwrapRef<typeof import('vue')['shallowRef']>
|
||||||
readonly store: UnwrapRef<typeof import('../store/index')['store']>
|
readonly store: UnwrapRef<typeof import('../store/index')['store']>
|
||||||
readonly storeToRefs: UnwrapRef<typeof import('pinia')['storeToRefs']>
|
readonly storeToRefs: UnwrapRef<typeof import('pinia')['storeToRefs']>
|
||||||
readonly themeColorOptions: UnwrapRef<typeof import('../composables/useTheme')['themeColorOptions']>
|
|
||||||
readonly toRaw: UnwrapRef<typeof import('vue')['toRaw']>
|
readonly toRaw: UnwrapRef<typeof import('vue')['toRaw']>
|
||||||
readonly toRef: UnwrapRef<typeof import('vue')['toRef']>
|
readonly toRef: UnwrapRef<typeof import('vue')['toRef']>
|
||||||
readonly toRefs: UnwrapRef<typeof import('vue')['toRefs']>
|
readonly toRefs: UnwrapRef<typeof import('vue')['toRefs']>
|
||||||
@@ -316,7 +316,6 @@ declare module 'vue' {
|
|||||||
readonly useStomp: UnwrapRef<typeof import('../composables/useStomp')['useStomp']>
|
readonly useStomp: UnwrapRef<typeof import('../composables/useStomp')['useStomp']>
|
||||||
readonly useTabbar: UnwrapRef<typeof import('../composables/useTabbar')['useTabbar']>
|
readonly useTabbar: UnwrapRef<typeof import('../composables/useTabbar')['useTabbar']>
|
||||||
readonly useTemplateRef: UnwrapRef<typeof import('vue')['useTemplateRef']>
|
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 useThemeStore: UnwrapRef<typeof import('../store/modules/theme.store')['useThemeStore']>
|
||||||
readonly useToast: UnwrapRef<typeof import('wot-design-uni')['useToast']>
|
readonly useToast: UnwrapRef<typeof import('wot-design-uni')['useToast']>
|
||||||
readonly useUserStore: UnwrapRef<typeof import('../store/modules/user.store')['useUserStore']>
|
readonly useUserStore: UnwrapRef<typeof import('../store/modules/user.store')['useUserStore']>
|
||||||
|
|||||||
Reference in New Issue
Block a user