From 6a245e9d26590f8335d168de159984f29f851bac Mon Sep 17 00:00:00 2001 From: "Ray.Hao" <1490493387@qq.com> Date: Sat, 5 Apr 2025 10:05:05 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20:recycle:=20=E6=88=91=E7=9A=84?= =?UTF-8?q?=E5=92=8C=E7=99=BB=E5=BD=95=E9=A1=B5=E9=9D=A2=E4=BC=98=E5=8C=96?= =?UTF-8?q?=EF=BC=8C=E6=B7=BB=E5=8A=A0=E4=B8=BB=E9=A2=98=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.vue | 18 +- src/components/todo/TodoItem.vue | 122 ++++ src/components/todo/TodoList.vue | 43 ++ src/main.ts | 1 + src/pages.json | 12 + src/pages/login/complete-profile.vue | 487 +++++++++++++ src/pages/login/index.vue | 435 +++++++++--- src/pages/mine/feedback/index.vue | 6 + src/pages/mine/index.vue | 665 ++++++++++++++++-- src/pages/mine/profile/index.vue | 11 +- src/pages/mine/settings/index.vue | 10 + src/pages/mine/settings/theme/index.vue | 288 ++++++++ src/pages/todo/index.vue | 273 +++++++ src/static/images/auth/login-bg.svg | 31 + .../images/{login-bg.png => header-bg.png} | Bin src/store/index.ts | 2 + src/store/modules/theme.ts | 82 +++ src/store/modules/user.ts | 8 + src/styles/global.scss | 244 +++++++ src/types/todo.ts | 16 + src/utils/auth.ts | 22 + 21 files changed, 2594 insertions(+), 182 deletions(-) create mode 100644 src/components/todo/TodoItem.vue create mode 100644 src/components/todo/TodoList.vue create mode 100644 src/pages/login/complete-profile.vue create mode 100644 src/pages/mine/settings/theme/index.vue create mode 100644 src/pages/todo/index.vue create mode 100644 src/static/images/auth/login-bg.svg rename src/static/images/{login-bg.png => header-bg.png} (100%) create mode 100644 src/store/modules/theme.ts create mode 100644 src/styles/global.scss create mode 100644 src/types/todo.ts create mode 100644 src/utils/auth.ts diff --git a/src/App.vue b/src/App.vue index 3984899..220abd9 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,16 +1,32 @@ + diff --git a/src/components/todo/TodoList.vue b/src/components/todo/TodoList.vue new file mode 100644 index 0000000..dc8a449 --- /dev/null +++ b/src/components/todo/TodoList.vue @@ -0,0 +1,43 @@ + + + + + diff --git a/src/main.ts b/src/main.ts index 5763cc7..cb34f51 100644 --- a/src/main.ts +++ b/src/main.ts @@ -3,6 +3,7 @@ import App from "./App.vue"; import setupPlugins from "@/plugins"; import "uno.css"; +import "@/styles/global.scss"; import { setupStore } from "@/store"; diff --git a/src/pages.json b/src/pages.json index 1b4da6b..a7e9929 100644 --- a/src/pages.json +++ b/src/pages.json @@ -68,6 +68,12 @@ "navigationBarTitleText": "隐私政策" } }, + { + "path": "pages/mine/settings/theme/index", + "style": { + "navigationBarTitleText": "主题设置" + } + }, { "path": "pages/mine/settings/network/index", "style": { @@ -80,6 +86,12 @@ "navigationBarTitleText": "登录" } }, + { + "path": "pages/login/complete-profile", + "style": { + "navigationBarTitleText": "完善个人信息" + } + }, { "path": "pages/mine/profile/index", "style": { diff --git a/src/pages/login/complete-profile.vue b/src/pages/login/complete-profile.vue new file mode 100644 index 0000000..ceac9f7 --- /dev/null +++ b/src/pages/login/complete-profile.vue @@ -0,0 +1,487 @@ + + + + + diff --git a/src/pages/login/index.vue b/src/pages/login/index.vue index eaf3faa..5275fcd 100644 --- a/src/pages/login/index.vue +++ b/src/pages/login/index.vue @@ -1,107 +1,159 @@ diff --git a/src/pages/mine/feedback/index.vue b/src/pages/mine/feedback/index.vue index 89502a1..1f53a7d 100644 --- a/src/pages/mine/feedback/index.vue +++ b/src/pages/mine/feedback/index.vue @@ -59,9 +59,15 @@ diff --git a/src/pages/mine/profile/index.vue b/src/pages/mine/profile/index.vue index 47ee78c..a2be5a7 100644 --- a/src/pages/mine/profile/index.vue +++ b/src/pages/mine/profile/index.vue @@ -65,6 +65,7 @@ diff --git a/src/pages/mine/settings/theme/index.vue b/src/pages/mine/settings/theme/index.vue new file mode 100644 index 0000000..e80fce9 --- /dev/null +++ b/src/pages/mine/settings/theme/index.vue @@ -0,0 +1,288 @@ + + + + + diff --git a/src/pages/todo/index.vue b/src/pages/todo/index.vue new file mode 100644 index 0000000..103bdaf --- /dev/null +++ b/src/pages/todo/index.vue @@ -0,0 +1,273 @@ + + + + + diff --git a/src/static/images/auth/login-bg.svg b/src/static/images/auth/login-bg.svg new file mode 100644 index 0000000..765ad33 --- /dev/null +++ b/src/static/images/auth/login-bg.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/static/images/login-bg.png b/src/static/images/header-bg.png similarity index 100% rename from src/static/images/login-bg.png rename to src/static/images/header-bg.png diff --git a/src/store/index.ts b/src/store/index.ts index f982f05..8f9d085 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -9,4 +9,6 @@ export function setupStore(app: App) { } export * from "./modules/user"; +export * from "./modules/dict"; +export * from "./modules/theme"; export { store }; diff --git a/src/store/modules/theme.ts b/src/store/modules/theme.ts new file mode 100644 index 0000000..4f4265f --- /dev/null +++ b/src/store/modules/theme.ts @@ -0,0 +1,82 @@ +import { defineStore } from "pinia"; +import { ref } from "vue"; + +// 从缓存获取主题色 +const getThemeColor = (): string => { + const savedColor = uni.getStorageSync("themeColor"); + return savedColor || "#165DFF"; // 默认Arco蓝色 +}; + +// 保存主题色到缓存 +const setThemeColorCache = (color: string) => { + uni.setStorageSync("themeColor", color); +}; + +export const useThemeStore = defineStore("theme", () => { + // 主题色 + const primaryColor = ref(getThemeColor()); + + // 设置主题色 + const setPrimaryColor = (color: string) => { + primaryColor.value = color; + setThemeColorCache(color); + + // 设置CSS变量,方便全局使用 + document.documentElement.style.setProperty("--primary-color", color); + + // 计算衍生色 + const lighterColor = getLighterColor(color, 0.8); + const darkerColor = getDarkerColor(color, 0.8); + document.documentElement.style.setProperty("--primary-color-light", lighterColor); + document.documentElement.style.setProperty("--primary-color-dark", darkerColor); + }; + + // 获取浅色版本主题色 + const getLighterColor = (hexColor: string, factor: number): string => { + // 去掉#前缀 + const hex = hexColor.replace("#", ""); + + // 解析RGB值 + let r = parseInt(hex.substring(0, 2), 16); + let g = parseInt(hex.substring(2, 4), 16); + let b = parseInt(hex.substring(4, 6), 16); + + // 调亮颜色 + r = Math.min(255, Math.floor(r + (255 - r) * factor)); + g = Math.min(255, Math.floor(g + (255 - g) * factor)); + b = Math.min(255, Math.floor(b + (255 - b) * factor)); + + // 转回16进制 + return `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`; + }; + + // 获取深色版本主题色 + const getDarkerColor = (hexColor: string, factor: number): string => { + // 去掉#前缀 + const hex = hexColor.replace("#", ""); + + // 解析RGB值 + let r = parseInt(hex.substring(0, 2), 16); + let g = parseInt(hex.substring(2, 4), 16); + let b = parseInt(hex.substring(4, 6), 16); + + // 调暗颜色 + r = Math.max(0, Math.floor(r * factor)); + g = Math.max(0, Math.floor(g * factor)); + b = Math.max(0, Math.floor(b * factor)); + + // 转回16进制 + return `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`; + }; + + // 初始化,应用主题色 + const initTheme = () => { + setPrimaryColor(primaryColor.value); + }; + + return { + primaryColor, + setPrimaryColor, + initTheme, + }; +}); diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts index 8911584..0f364f9 100644 --- a/src/store/modules/user.ts +++ b/src/store/modules/user.ts @@ -64,11 +64,19 @@ export const useUserStore = defineStore("user", () => { } }; + // 判断用户信息是否完整 + const isUserInfoComplete = (): boolean => { + if (!userInfo.value) return false; + + return !!(userInfo.value.nickname && userInfo.value.avatar); + }; + return { userInfo, login, loginByWechat, logout, getInfo, + isUserInfoComplete, }; }); diff --git a/src/styles/global.scss b/src/styles/global.scss new file mode 100644 index 0000000..3277c14 --- /dev/null +++ b/src/styles/global.scss @@ -0,0 +1,244 @@ +/** + * 全局样式变量 + */ + +/* + * 主题颜色 - 会被theme.ts中的动态设置覆盖 + * 这里作为默认值和IDE提示 + */ +:root { + /* 主色 */ + --primary-color: #165dff; + --primary-color-light: #94bfff; + --primary-color-dark: #0e3c9b; + + /* 功能色 */ + --success-color: #0fc6c2; + --warning-color: #ff7d00; + --danger-color: #f5222d; + --info-color: #86909c; + + /* 文字颜色 */ + --text-primary: #1d2129; + --text-regular: #4e5969; + --text-secondary: #86909c; + --text-placeholder: #c9cdd4; + --text-inverse: #ffffff; + + /* 边框颜色 */ + --border-color: #e5e6eb; + --border-light: #f2f3f5; + + /* 背景颜色 */ + --bg-white: #ffffff; + --bg-light: #f2f3f5; + --bg-gray: #f7f8fa; +} + +/** + * 主题相关的通用类 + */ + +/* 主色文本 */ +.text-primary { + color: var(--primary-color) !important; +} + +/* 主色背景 */ +.bg-primary { + color: #fff; + background-color: var(--primary-color) !important; +} + +/* 主色边框 */ +.border-primary { + border-color: var(--primary-color) !important; +} + +/* 主色按钮样式 */ +.btn-primary { + color: #fff; + background-color: var(--primary-color); + border: none; + border-radius: 8rpx; + transition: opacity 0.3s; + + &:active { + opacity: 0.8; + } +} + +/* 圆角按钮 */ +.btn-rounded { + border-radius: 45rpx !important; +} + +/* 次级按钮 */ +.btn-secondary { + color: var(--primary-color); + background-color: #fff; + border: 1px solid var(--primary-color); + border-radius: 8rpx; + transition: background-color 0.3s; + + &:active { + background-color: rgba(22, 93, 255, 0.05); + } +} + +/** + * 字体大小 + */ +.font-xs { + font-size: 24rpx; +} + +.font-sm { + font-size: 28rpx; +} + +.font-md { + font-size: 32rpx; +} + +.font-lg { + font-size: 36rpx; +} + +.font-xl { + font-size: 40rpx; +} + +/** + * 边距辅助类 + */ +.mt-10 { + margin-top: 10rpx; +} +.mt-20 { + margin-top: 20rpx; +} +.mt-30 { + margin-top: 30rpx; +} +.mt-40 { + margin-top: 40rpx; +} + +.mb-10 { + margin-bottom: 10rpx; +} +.mb-20 { + margin-bottom: 20rpx; +} +.mb-30 { + margin-bottom: 30rpx; +} +.mb-40 { + margin-bottom: 40rpx; +} + +.ml-10 { + margin-left: 10rpx; +} +.ml-20 { + margin-left: 20rpx; +} +.ml-30 { + margin-left: 30rpx; +} +.ml-40 { + margin-left: 40rpx; +} + +.mr-10 { + margin-right: 10rpx; +} +.mr-20 { + margin-right: 20rpx; +} +.mr-30 { + margin-right: 30rpx; +} +.mr-40 { + margin-right: 40rpx; +} + +.p-10 { + padding: 10rpx; +} +.p-20 { + padding: 20rpx; +} +.p-30 { + padding: 30rpx; +} +.p-40 { + padding: 40rpx; +} + +/** + * 布局辅助类 + */ +.flex { + display: flex; +} +.flex-wrap { + flex-wrap: wrap; +} +.flex-column { + flex-direction: column; +} +.items-center { + align-items: center; +} +.items-start { + align-items: flex-start; +} +.items-end { + align-items: flex-end; +} +.justify-center { + justify-content: center; +} +.justify-between { + justify-content: space-between; +} +.justify-around { + justify-content: space-around; +} +.justify-start { + justify-content: flex-start; +} +.justify-end { + justify-content: flex-end; +} + +/** + * 其他辅助类 + */ +.text-center { + text-align: center; +} +.text-left { + text-align: left; +} +.text-right { + text-align: right; +} + +.rounded-sm { + border-radius: 4rpx; +} +.rounded { + border-radius: 8rpx; +} +.rounded-lg { + border-radius: 16rpx; +} +.rounded-xl { + border-radius: 24rpx; +} +.rounded-full { + border-radius: 9999rpx; +} diff --git a/src/types/todo.ts b/src/types/todo.ts new file mode 100644 index 0000000..a500742 --- /dev/null +++ b/src/types/todo.ts @@ -0,0 +1,16 @@ +export interface Todo { + id: string; + title: string; + description?: string; + completed: boolean; + deadline?: string; + priority?: "low" | "medium" | "high"; + createdAt: string; + updatedAt?: string; +} + +export interface TodoState { + todos: Todo[]; + loading: boolean; + error: string | null; +} diff --git a/src/utils/auth.ts b/src/utils/auth.ts new file mode 100644 index 0000000..dfbb479 --- /dev/null +++ b/src/utils/auth.ts @@ -0,0 +1,22 @@ +import { useUserStore } from "@/store/modules/user"; + +/** + * 检查用户登录状态,未登录则跳转到登录页面 + * @returns 返回用户是否已登录 + */ +export function checkLogin(): boolean { + const userStore = useUserStore(); + + if (!userStore.userInfo) { + const pages = getCurrentPages(); + const currentPage = pages[pages.length - 1]; + const currentPagePath = `/${currentPage.route}`; + + uni.navigateTo({ + url: `/pages/login/index?redirect=${encodeURIComponent(currentPagePath)}`, + }); + return false; + } + + return true; +}