diff --git a/.husky/uniapp从0到1.md b/.husky/uniapp从0到1.md
deleted file mode 100644
index a9f14dc..0000000
--- a/.husky/uniapp从0到1.md
+++ /dev/null
@@ -1,2064 +0,0 @@
-
-
-## 环境准备
-
-[vue-uniapp-template](https://gitee.com/youlaiorg/vue-uniapp-template) 是一个通过 `vue-cli ` 构建的跨移动端脚手架模板,结合了 `uniapp`、`vue3 `和 `typescript`。在开始之前,需要准备以下环境。如果环境准备OK,请忽略本节。
-
-### 安装 Node
-
-> `Node.js` 是运行 JavaScript 代码的环境,也是 `npm` 包管理器的依赖。
-
-打开 [Node.js 官方下载页面](https://nodejs.org/zh-cn/download/prebuilt-installer),根据你的操作系统选择合适的版本进行下载,**推荐安装 LTS 版本**,这是长期支持版本,适合开发环境,比如这里选择 `v20.18.0(LTS) ` 版本。
-
-
-
-下载之后,双击安装包根据提示安装,通过以下命令检查是否成功安装:
-
-```bash
-node -v
-```
-
-
-
-
-
-### 安装 VSCode
-
->`VSCode` 是一款非常流行的代码编辑器,特别适合前端开发。
-
-访问 [Visual Studio Code 官方网站](https://code.visualstudio.com/) ,根据你的操作系统下载相应版本的 `VSCode` ,下载完成后,双击安装程序并按照提示完成安装。
-
-
-
- ### 安装 vue-cli
-
-> `Vue CLI` 是 Vue.js 的命令行工具,能够快速创建、开发、构建 Vue.js 项目。
-
-打开终端或命令提示符, 使用 `npm` 全局安装 `Vue CLI`:
-
-```
-npm install -g @vue/cli
-```
-
-安装完成后,检查 `Vue CLI` 是否安装成功:
-
-```bash
-vue --version
-```
-
-
-
-## 创建项目
-
-### 初始化项目
-
-按照 [uni-app 官方文档](https://uniapp.dcloud.net.cn/quickstart-cli.html#创建uni-app) 的步骤,通过 `vue-cli` 创建 `uni-app` + `vue` + `typescript` 脚手架:
-
-```bash
-npx degit dcloudio/uni-preset-vue#vite-ts vue-uniapp-template
-```
-
-
-
-如果使用命令创建失败,可以通过 Gitee 下载 ZIP 包:[vite-ts 分支](https://gitee.com/dcloud/uni-preset-vue/tree/vite-ts)。
-
-### 配置编译器
-
-默认生成的 `TypeScript ` 编译器配置文件 `tsconfig.json` 中继承的 `@vue/tsconfig/tsconfig.json` 文件不存在。因此,你需要移除此继承配置并添加相应的编译设置。
-
-
-
-根据 [TypeScript 官方配置文档](https://www.typescriptlang.org/tsconfig/),调整后的完整配置如下:
-
-```json
-{
- "compilerOptions": {
- "module": "esnext",
- "moduleResolution": "node",
- "target": "esnext",
- "allowJs": true,
- "skipLibCheck": true,
- "strict": true,
-
- "sourceMap": true,
- "baseUrl": ".",
- "paths": {
- "@/*": ["./src/*"]
- },
- "lib": ["esnext", "dom"],
- "types": ["@dcloudio/types"]
- },
- "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
- "exclude": ["node_modules", "dist"]
-}
-```
-
-- `"module": "esnext"`: 指定模块系统为 `ESNext`,即最新的 ECMAScript 模块系统,支持 `import.meta` 和其他最新的特性。
-- `"moduleResolution": "node"`: 模块解析策略,通常设置为 `Node` 以支持 Node.js 风格的模块解析。
-- `"target": "esnext"`: 将目标 JavaScript 版本设置为 `ESNext`,编译输出现代浏览器能够支持的最新特性代码。
-- `"allowJs": true`: 允许 TypeScript 编译器处理 `.js` 文件,混合使用 TypeScript 和 JavaScript 文件。
-- `"skipLibCheck": true`: 跳过库文件的类型检查,提升编译速度。
-- `"strict": true` : 启用所有严格类型检查选项。
-
-### 启动项目
-
-创建完成后,使用 `VSCode` 打开项目并启动:
-
-```bash
-# 安装依赖
-pnpm install
-# 启动项目
-pnpm run dev:h5
-```
-
-
-
-项目启动后,访问 http://localhost:5173 预览效果:
-
-
-
-
-
-## 代码规范配置
-
-为了保证项目代码的规范性和一致性,可以为项目配置 `ESLint`、`Stylelint`、`Prettier` 以及 `Husky`,从而确保代码质量和开发流程的一致性。
-
- ### 集成 ESLint
-
-`ESLint` 是一款 JavaScript 和 TypeScript 的代码规范工具,能够帮助开发团队保持代码风格一致并减少常见错误。
-
-**ESLint 中文网**:[https://eslint.nodejs.cn/](https://eslint.nodejs.cn/)
-
-#### 安装插件
-
-VSCode 插件市场搜索 ESLint 插件并安装
-
-
-
-#### 配置 ESLint
-
-通过以下命令快速生成 ESLint 配置文件:
-
-```bash
-npx eslint --init
-```
-
-
-
-执行该命令后,ESLint 会通过交互式问题的方式,帮助生成配置文件。针对 9.x 版本,默认会生成基于 Flat Config 格式的 `eslint.config.mjs` 文件,与之前的 `.eslintrc` 格式有所不同。
-
-默认生成的 `eslint.config.mjs` 文件如下所示:
-
-
-
-在此基础上,可以根据项目的需求进行一些定制化配置,例如添加忽略规则或自定义的特殊规则。
-
-```js
-import globals from "globals"; // 全局变量配置
-import pluginJs from "@eslint/js"; // JavaScript 的推荐配置
-import tseslint from "typescript-eslint"; // TypeScript 配置
-import pluginVue from "eslint-plugin-vue"; // Vue 配置
-
-export default [
- {files: ["**/*.{js,mjs,cjs,ts,vue}"]}, // 校验的文件类型
- {languageOptions: { globals: {...globals.browser , ...globals.node} }}, // 浏览器/Node环境全局变量
- pluginJs.configs.recommended, // JavaScript 推荐配置
- ...tseslint.configs.recommended, // TypeScript 推荐配置
- ...pluginVue.configs["flat/essential"], // Vue 推荐配置
- { files: ["**/*.vue"], languageOptions: { parserOptions: { parser: tseslint.parser } } }, // 对 .vue 文件使用 TypeScript 解析器
-
- // 添加忽略的文件或目录
- {
- ignores: [
- "/dist",
- "/public",
- "/node_modules",
- "**/*.min.js",
- "**/*.config.mjs",
- "**/*.tsbuildinfo",
- "/src/manifest.json",
- ]
- },
-
- // 自定义规则
- {
- rules: {
- quotes: ["error", "double"], // 强制使用双引号
- "quote-props": ["error", "always"], // 强制对象的属性名使用引号
- semi: ["error", "always"], // 要求使用分号
- indent: ["error", 2], // 使用两个空格进行缩进
- "no-multiple-empty-lines": ["error", { max: 1 }], // 不允许多个空行
- "no-trailing-spaces": "error", // 不允许行尾有空格
-
- // TypeScript 规则
- "@typescript-eslint/no-explicit-any": "off", // 禁用 no-explicit-any 规则,允许使用 any 类型
- "@typescript-eslint/explicit-function-return-type": "off", // 不强制要求函数必须明确返回类型
- "@typescript-eslint/no-empty-interface": "off", // 禁用 no-empty-interface 规则,允许空接口声明
- "@typescript-eslint/no-empty-object-type": "off", // 允许空对象类型
-
- // Vue 规则
- "vue/multi-word-component-names": "off", // 关闭多单词组件名称的限制
- "vue/html-indent": ["error", 2], // Vue 模板中的 HTML 缩进使用两个空格
- "vue/no-v-html": "off", // 允许使用 v-html (根据实际项目需要)
- },
- },
-];
-```
-
-#### 添加 ESLint 脚本
-
-为了方便使用 ESLint,可以在 `package.json` 中添加 `lint` 脚本命令:
-
-```json
-{
- "scripts": {
- "lint:eslint": "eslint --fix ./src"
- }
-}
-```
-
-此脚本会自动修复符合 ESLint 规则的代码问题,并输出检查结果。
-
-#### 测试效果
-
-在 `App.vue` 文件中声明一个未使用的变量,并运行 `pnpm run lint:eslint`,可以看到 ESLint 提示该变量未使用。如下图所示:
-
-
-
-#### 推荐配置
-
-安装 Vue 文件解析器 `vue-eslint-parser`:
-
-```bash
-pnpm add -D vue-eslint-parser
-```
-
-针对不同文件配置插件和解析器:
-
-```javascript
-// eslint.config.mjs
-import globals from "globals";
-import js from "@eslint/js";
-
-// ESLint 核心插件
-import pluginVue from "eslint-plugin-vue";
-import pluginTypeScript from "@typescript-eslint/eslint-plugin";
-
-// Prettier 插件及配置
-import configPrettier from "eslint-config-prettier";
-import pluginPrettier from "eslint-plugin-prettier";
-
-// 解析器
-import * as parserVue from "vue-eslint-parser";
-import * as parserTypeScript from "@typescript-eslint/parser";
-
-// 定义 ESLint 配置
-export default [
- // 通用 JavaScript/TypeScript 配置
- {
- ...js.configs.recommended,
- ignores: [
- "/dist",
- "/public",
- "/node_modules",
- "**/*.min.js",
- "**/*.config.mjs",
- "**/*.tsbuildinfo",
- "/src/manifest.json",
- ],
- languageOptions: {
- globals: {
- ...globals.browser, // 浏览器变量 (window, document 等)
- ...globals.node, // Node.js 变量 (process, require 等)
- },
- },
- plugins: {
- prettier: pluginPrettier,
- },
- rules: {
- ...configPrettier.rules,
- ...pluginPrettier.configs.recommended.rules,
- "no-debug": "off", // 允许使用 debugger
- "prettier/prettier": [
- "error",
- {
- endOfLine: "auto", // 解决换行符冲突
- },
- ],
- },
- },
-
- // TypeScript 配置
- {
- files: ["**/*.?([cm])ts"],
- languageOptions: {
- parser: parserTypeScript,
- parserOptions: {
- sourceType: "module",
- },
- },
- plugins: {
- "@typescript-eslint": pluginTypeScript,
- },
- rules: {
- ...pluginTypeScript.configs.recommended.rules,
- "@typescript-eslint/no-explicit-any": "off", // 允许使用 any
- "@typescript-eslint/no-empty-function": "off", // 允许空函数
- "@typescript-eslint/no-empty-object-type": "off", // 允许空对象类型
- "@typescript-eslint/consistent-type-imports": [
- "error",
- { disallowTypeAnnotations: false, fixStyle: "inline-type-imports" },
- ], // 统一类型导入风格
- },
- },
-
- // TypeScript 声明文件的特殊配置
- {
- files: ["**/*.d.ts"],
- rules: {
- "eslint-comments/no-unlimited-disable": "off", // 关闭 eslint 注释相关规则
- "unused-imports/no-unused-vars": "off", // 忽略未使用的导入
- },
- },
-
- // JavaScript (commonjs) 配置
- {
- files: ["**/*.?([cm])js"],
- rules: {
- "@typescript-eslint/no-var-requires": "off", // 允许 require
- },
- },
-
- // Vue 文件配置
- {
- files: ["**/*.vue"],
- languageOptions: {
- parser: parserVue,
- parserOptions: {
- parser: "@typescript-eslint/parser",
- sourceType: "module",
- },
- },
- plugins: {
- vue: pluginVue,
- },
- processor: pluginVue.processors[".vue"],
- rules: {
- ...pluginVue.configs["vue3-recommended"].rules,
- "vue/no-v-html": "off", // 允许 v-html
- "vue/require-default-prop": "off", // 允许没有默认值的 prop
- "vue/multi-word-component-names": "off", // 关闭组件名称多词要求
- "vue/html-self-closing": [
- "error",
- {
- html: { void: "always", normal: "always", component: "always" },
- svg: "always",
- math: "always",
- },
- ], // 自闭合标签
- },
- },
-];
-```
-
-
-
-### 集成 Prettier
-
-Prettier 是一个代码格式化工具,能够和 ESLint 配合使用,确保代码风格统一。
-
-**prettier 中文网**:[https://prettier.nodejs.cn/](https://prettier.nodejs.cn/)
-
-#### 安装插件
-
-VSCode 插件市场搜索 `Prettier - Code formatter` 插件安装
-
-
-
-#### 安装依赖
-
-```bash
-pnpm install -D prettier eslint-config-prettier eslint-plugin-prettier
-```
-
-- **prettier**:主要的 Prettier 格式化库。
-
-- **eslint-plugin-prettier**:将 Prettier 的规则作为 ESLint 的规则来运行。
-
-- **eslint-config-prettier**:禁用所有与格式相关的 ESLint 规则,以避免和 Prettier 的冲突。
-
-#### 配置 Prettier
-
-项目根目录下新建配置文件 `prettier.config.mjs`,添加常用规则:
-
-```js
-export default {
- printWidth: 100, // 每行最多字符数量,超出换行(默认80)
- tabWidth: 2, // 缩进空格数,默认2个空格
- useTabs: false, // 指定缩进方式,空格或tab,默认false,即使用空格
- semi: true, // 使用分号
- singleQuote: false, // 使用单引号 (true:单引号;false:双引号)
- trailingComma: 'all', // 末尾使用逗号
-};
-```
-
-#### 配置忽略文件
-
-项目根目录新建 `.prettierignore` 文件指定 Prettier 不需要格式化的文件和文件夹
-
-```bash
-# .prettierignore
-node_modules
-dist
-public
-*.min.js
-```
-
-#### 添加格式化脚本
-
-在 `package.json` 文件中添加:
-
-```json
-{
- "scripts": {
- "format": "prettier --write ./src"
- }
-}
-```
-
-#### 保存自动格式化
-
-打开 VSCode 的 `File` → `Preferences` → `Settings`,然后选择 `Open Settings (JSON)`,添加以下配置
-
-```json
-{
- "editor.formatOnSave": true, // 保存格式化文件
- "editor.defaultFormatter": "esbenp.prettier-vscode" // 指定 prettier 为所有文件默认格式化器
-}
-```
-
-#### 测试
-
-下图演示了保存时的自动格式化效果,展示了代码中引号和换行的自动调整:
-
-
-
-
-
-### 集成 Stylelint
-
-Stylelint 一个强大的 CSS linter(检查器),可帮助您避免错误并强制执行约定。
-
-**Stylelint 官网**:[https://stylelint.io/](https://stylelint.io/)
-
-#### 安装插件
-
-VSCode 插件搜索 `Stylelint` 并安装
-
-
-
-
-
-#### 安装依赖
-
-```bash
-pnpm install -D postcss postcss-html postcss-scss stylelint stylelint-config-recommended stylelint-config-recommended-scss stylelint-config-recommended-vue stylelint-config-recess-order stylelint-config-html stylelint-prettier
-```
-
-| 依赖 | 说明 | 备注 |
-| --------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
-| postcss | CSS 解析工具,允许使用现代 CSS 语法并将其转换为兼容的旧语法 | |
-| postcss-html | 解析 HTML (类似 HTML) 的 PostCSS 语法 | [postcss-html 文档](https://github.com/gucong3000/postcss-html) |
-| postcss-scss | PostCSS 的 SCSS 解析器 | [postcss-scss 文档](https://github.com/postcss/postcss-scss),支持 CSS 行类注释 |
-| stylelint | stylelint 核心库 | [stylelint ](https://stylelint.io/) |
-| stylelint-config-standard | Stylelint 标准共享配置 | [stylelint-config-standard 文档](https://github.com/stylelint/stylelint-config-standard) |
-| stylelint-config-recommended | | |
-| stylelint-config-recommended-scss | 扩展 stylelint-config-recommended 共享配置并为 SCSS 配置其规则 | [stylelint-config-recommended-scss 文档](https://github.com/stylelint-scss/stylelint-config-recommended-scss) |
-| stylelint-config-recommended-vue | 扩展 stylelint-config-recommended 共享配置并为 Vue 配置其规则 | [stylelint-config-recommended-vue 文档](https://github.com/ota-meshi/stylelint-config-recommended-vue) |
-| stylelint-config-recess-order | 提供优化样式顺序的配置 | [CSS 书写顺序规范](https://jingyan.baidu.com/article/647f0115cf48957f2148a8a3.html) |
-| stylelint-config-html | 共享 HTML (类似 HTML) 配置,捆绑 postcss-html 并对其进行配置 | [stylelint-config-html 文档](https://github.com/ota-meshi/stylelint-config-html) |
-| stylelint-prettier | | |
-
-
-
-#### 配置 Stylelint
-
-根目录新建 `.stylelintrc.cjs` 文件,配置如下:
-
-```javascript
-{
- "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": [
- {
- "files": ["**/*.{vue,html}"],
- "customSyntax": "postcss-html"
- },
- {
- "files": ["**/*.{css,scss}"],
- "customSyntax": "postcss-scss"
- }
- ],
-
- "rules": {
- "import-notation": "string",
- "selector-class-pattern": null,
- "custom-property-pattern": null,
- "keyframes-name-pattern": null,
- "no-descending-specificity": null,
- "no-empty-source": null,
- "selector-pseudo-class-no-unknown": [
- true,
- {
- "ignorePseudoClasses": ["global", "export", "deep"]
- }
- ],
- "unit-no-unknown": [true, {
- "ignoreUnits": ["rpx"]
- }]
- "property-no-unknown": [
- true,
- {
- "ignoreProperties": []
- }
- ],
- "at-rule-no-unknown": [
- true,
- {
- "ignoreAtRules": ["apply", "use", "forward"]
- }
- ]
- }
-}
-```
-
-#### 配置忽略文件
-
-根目录创建 .stylelintignore 文件,配置忽略文件如下:
-
-```basic
-*.min.js
-dist
-public
-node_modules
-```
-
-#### 添加 Stylelint 脚本
-
-package.json 添加 Stylelint 检测指令:
-
-```json
- "scripts": {
- "lint:stylelint": "stylelint \"**/*.{css,scss,vue,html}\" --fix"
- }
-```
-
-#### 保存自动修复
-
-项目根目录下`.vscode/settings.json` 文件添加配置:
-
-```json
-{
- "editor.codeActionsOnSave": {
- "source.fixAll.stylelint": true
- },
- "stylelint.validate": ["css", "scss", "vue", "html"]
-}
-```
-
-为了验证把尺寸属性 width 放置在定位属性 position 前面,根据 [CSS 书写顺序规范](https://jingyan.baidu.com/article/647f0115cf48957f2148a8a3.html) 推断是不符合规范的,在保存时 Stylelint 自动将属性重新排序,达到预期。
-
-
-
-#### 测试
-
-执行以下命令进行检测
-
-```bash
-npm run lint:stylelint
-```
-
-
-
-## Git提交规范配置
-
-
-
-配置 Husky 的 `pre-commit` 和 `commit-msg` 钩子,实现代码提交的自动化检查和规范化。
-
-- **pre-commit**: 使用 Husky + Lint-staged,在提交前进行代码规范检测和格式化。确保项目已配置 ESLint、Prettier 和 Stylelint。
-- **commit-msg**: 结合 Husky、Commitlint、Commitizen 和 cz-git,生成规范化且自定义的 Git commit 信息。
-
-
-
-
-
-### 集成 Husky
-
-Husky 是 Git 钩子工具,可以设置在 git 各个阶段(`pre-commit`、`commit-msg` 等)触发。
-
-**Husky官网**:[https://typicode.github.io](https://typicode.github.io/husky/zh/get-started.html)
-
-
-
-#### 安装依赖
-
-```bash
-pnpm add -D husky
-```
-
-#### 初始化
-
-`init` 命令简化了项目中的 husky 设置。它会在 `.husky/` 中创建 `pre-commit` 脚本,并更新 `package.json` 中的 `prepare` 脚本。
-
-```bash
-pnpm exec husky init
-```
-
-#### 测试
-
-
-
-通过 `pre-commit` 钩子,可以自动运行各种代码检查工具,在提交代码前强制执行代码质量和样式检查。常见的工具包括:
-
-- **`eslint`**:用于检查和修复 JavaScript/TypeScript 代码中的问题。
-- **`stylelint`**:用于检测和修复 CSS/SCSS 样式问题。
-
-接下来,集成 **`lint-staged`** 和 **`commitlint`** 来进一步完善开发体验。
-
-### 集成 lint-staged
-
-`lint-staged` 是一个工具,专门用于只对 Git 暂存区的文件运行 lint 或其他任务,确保只检查和修复被修改或新增的代码部分,而不会影响整个代码库。这样可以显著提升效率,尤其是对于大型项目。
-
-#### 安装依赖
-
-使用以下命令安装 `lint-staged`:
-
-```json
-pnpm add -D lint-staged
-```
-
-#### 配置 lint-staged
-
-在 `package.json` 中添加 `lint-staged` 配置,确保在 `pre-commit` 阶段自动检测暂存的文件:
-
-```json
-{
- "name": "vue-uniapp-template",
- "version": "0.0.0",
- "lint-staged": {
- "*.{js,ts}": [
- "eslint --fix",
- "prettier --write"
- ],
- "*.{cjs,json}": [
- "prettier --write"
- ],
- "*.{vue,html}": [
- "eslint --fix",
- "prettier --write",
- "stylelint --fix"
- ],
- "*.{scss,css}": [
- "stylelint --fix",
- "prettier --write"
- ],
- "*.md": [
- "prettier --write"
- ]
- }
-}
-```
-
-在 `package.json` 的 `scripts` 部分中,添加用于运行 `lint-staged` 的命令:
-
-```json
-"scripts": {
- "lint:lint-staged": "lint-staged"
-}
-```
-
-#### 添加 Husky 钩子
-
-在项目根目录的 `.husky/pre-commit` 中添加以下命令,确保在提交代码前执行 `lint-staged`:
-
-```bash
-pnpm run lint:lint-staged
-```
-
-#### 测试
-
-提交代码时,`lint-staged` 会自动对暂存的文件运行相应的 lint 任务。
-
-
-
-通过这种集成方式,确保代码在提交前经过自动格式化和校验,提高代码质量和一致性。
-
-### 集成 Commitlint
-
-`commitlint` 用于检查 Git 提交信息是否符合特定规范(如 Angular 提交规范),从而保证提交信息的一致性。
-
-**Commitlint官网**:[https://commitlint.js.org/](https://commitlint.js.org/)
-
-#### 安装依赖
-
-```bash
-pnpm add -D @commitlint/cli @commitlint/config-conventional
-```
-
-#### 配置 Commitlint
-
-在项目根目录下创建 `commitlint.config.cjs` 文件,添加以下内容来启用 Angular 规范:
-
-```json
-module.exports = {
- // 继承的规则
- extends: ["@commitlint/config-conventional"],
- // 自定义规则
- rules: {
- // 提交类型枚举,git提交type必须是以下类型 @see https://commitlint.js.org/#/reference-rules
- "type-enum": [
- 2,
- "always",
- [
- "feat", // 新增功能
- "fix", // 修复缺陷
- "docs", // 文档变更
- "style", // 代码格式(不影响功能,例如空格、分号等格式修正)
- "refactor", // 代码重构(不包括 bug 修复、功能新增)
- "perf", // 性能优化
- "test", // 添加疏漏测试或已有测试改动
- "build", // 构建流程、外部依赖变更(如升级 npm 包、修改 webpack 配置等)
- "ci", // 修改 CI 配置、脚本
- "revert", // 回滚 commit
- "chore", // 对构建过程或辅助工具和库的更改(不影响源文件、测试用例)
- ],
- ],
- "subject-case": [0], // subject大小写不做校验
- },
-};
-```
-
-#### 添加 Husky 钩子
-
-将 `commitlint` 与 Husky 集成,在 `.husky/commit-msg` 文件中添加以下内容,确保提交信息符合规范:
-
-```bash
-npx --no-install commitlint --edit $1
-```
-
-#### 测试
-
-根据 Angular 的提交规范,提交信息由以下部分组成:
-
-1. **类型**:表示本次提交的类型,例如 `feat` (新功能)、`fix` (修复 bug)、`docs` (文档更新)。
-2. **作用域**(可选):说明本次提交影响的模块,例如 `auth`、`ui`。
-3. **简短描述**:简洁明了的提交描述,限定在 50 字符以内。
-
-当你尝试提交不符合规范的提交信息时,提交会被阻止,并显示相关错误提示。如下图所示:
-
-
-
-### 集成 Commitizen 和 cz-git
-
-- **commitizen**: 是一个帮助开发者以标准化格式生成提交信息的工具。--[Commitizen 官方文档](https://commitizen.github.io/cz-cli/)
-
-- **cz-git**: `cz-git` 是 `Commitizen` 的适配器之一,它基于 `Commitizen`,提供了更多自定义功能和增强的交互体验。--[cz-git 官方文档](https://cz-git.qbb.sh/zh/)
-
-#### 安装依赖
-
-```bash
-pnpm add -D commitizen cz-git
-```
-
-#### 配置 cz-git
-
-在项目中初始化 `Commitizen`,并配置使用 `cz-git` 作为适配器。在 `package.json` 中添加以下配置:
-
-```json
-"config": {
- "commitizen": {
- "path": "node_modules/cz-git"
- }
-}
-```
-
-在`commitlint` 的配置文件 `commitlint.config.cjs` 中添加配置,commitlint 配置模板:[https://cz-git.qbb.sh/zh/config/](https://cz-git.qbb.sh/zh/config/)
-
-```javascript
-module.exports = {
- // 继承的规则
- extends: ["@commitlint/config-conventional"],
- // 自定义规则
- rules: {
- // ...
- },
- // cz-git 配置
- prompt: {
- messages: {
- type: "选择你要提交的类型 :",
- scope: "选择一个提交范围(可选):",
- customScope: "请输入自定义的提交范围 :",
- subject: "填写简短精炼的变更描述 :\n",
- body: '填写更加详细的变更描述(可选)。使用 "|" 换行 :\n',
- breaking: '列举非兼容性重大的变更(可选)。使用 "|" 换行 :\n',
- footerPrefixesSelect: "选择关联issue前缀(可选):",
- customFooterPrefix: "输入自定义issue前缀 :",
- footer: "列举关联issue (可选) 例如: #31, #I3244 :\n",
- generatingByAI: "正在通过 AI 生成你的提交简短描述...",
- generatedSelectByAI: "选择一个 AI 生成的简短描述:",
- confirmCommit: "是否提交或修改commit ?",
- },
- // prettier-ignore
- types: [
- { value: "feat", name: "特性: ✨ 新增功能", emoji: ":sparkles:" },
- { value: "fix", name: "修复: 🐛 修复缺陷", emoji: ":bug:" },
- { value: "docs", name: "文档: 📝 文档变更", emoji: ":memo:" },
- { value: "style", name: "格式: 💄 代码格式(不影响功能,例如空格、分号等格式修正)", emoji: ":lipstick:" },
- { value: "refactor", name: "重构: ♻️ 代码重构(不包括 bug 修复、功能新增)", emoji: ":recycle:" },
- { value: "perf", name: "性能: ⚡️ 性能优化", emoji: ":zap:" },
- { value: "test", name: "测试: ✅ 添加疏漏测试或已有测试改动", emoji: ":white_check_mark:"},
- { value: "build", name: "构建: 📦️ 构建流程、外部依赖变更(如升级 npm 包、修改 vite 配置等)", emoji: ":package:"},
- { value: "ci", name: "集成: 🎡 修改 CI 配置、脚本", emoji: ":ferris_wheel:"},
- { value: "revert", name: "回退: ⏪️ 回滚 commit",emoji: ":rewind:"},
- { value: "chore", name: "其他: 🔨 对构建过程或辅助工具和库的更改(不影响源文件、测试用例)", emoji: ":hammer:"},
- ],
- useEmoji: true,
- emojiAlign: "center",
- useAI: false,
- aiNumber: 1,
- themeColorCode: "",
- scopes: [],
- allowCustomScopes: true,
- allowEmptyScopes: true,
- customScopesAlign: "bottom",
- customScopesAlias: "custom",
- emptyScopesAlias: "empty",
- upperCaseSubject: false,
- markBreakingChangeMode: false,
- allowBreakingChanges: ["feat", "fix"],
- breaklineNumber: 100,
- breaklineChar: "|",
- skipQuestions: [],
- issuePrefixes: [{ value: "closed", name: "closed: ISSUES has been processed" }],
- customIssuePrefixAlign: "top",
- emptyIssuePrefixAlias: "skip",
- customIssuePrefixAlias: "custom",
- allowCustomIssuePrefix: true,
- allowEmptyIssuePrefix: true,
- confirmColorize: true,
- maxHeaderLength: Infinity,
- maxSubjectLength: Infinity,
- minSubjectLength: 0,
- scopeOverrides: undefined,
- defaultBody: "",
- defaultIssues: "",
- defaultScope: "",
- defaultSubject: "",
- },
-};
-
-```
-
-#### 添加 cz-git 脚本
-
-在`package.json` 文件中添加 `commit` 脚本命令
-
-```json
- "scripts": {
- "commit": "git-cz"
- }
-```
-
-#### 测试
-
-执行 `pnpm run commit` 命令后,按照提示输入相关信息,最终生成符合规范的提交信息。
-
-
-
-## 整合 Sass
-
-**Sass**是帮助开发者编写、管理和维护样式的强大工具,通过 `
-```
-
-在 `pages.json` 文件中,声明登录页面的路由:
-
-```json
-// src/pages.json
-{
- "pages": [
- {
- "path": "pages/login/index",
- "style": {
- "navigationBarTitleText": "登录"
- }
- }
- ]
-}
-```
-
-
-
-### 登录测试
-
-访问登录页面:http://localhost:5173/#/pages/login/index,输入用户名和密码 (`admin`/`123456`) 测试登录接口,登录成功后可以看到返回的访问令牌。
-
-
-
-### 整合源码
-
-整合`HTTP请求`代码版本:[vue-uniapp-template#737f6a](hhttps://gitee.com/youlaiorg/vue-uniapp-template/commit/737f6a3ee5217dcad006fa06b6fae63374d9826b)。
-
-
-
-## 整合 Pinia
-
-> Pinia 是 Vue 的状态管理库,专为跨组件或页面共享状态设计。
-
-- **Pinia 官方文档**: https://pinia.vuejs.org/zh/getting-started.html
-
- 
-
-### 安装依赖
-
-首先,安装 `pinia` 依赖:
-
-```bash
-pnpm add pinia
-```
-
-### 全局注册
-
-在项目的 `src` 目录下创建 `store` 文件夹,并新建 `index.ts` 文件,初始化并注册 Pinia 实例。
-
-```typescript
-// src/store/index.ts
-import type { App } from "vue";
-import { createPinia } from "pinia";
-
-const store = createPinia();
-// 注册 Pinia
-export function setupStore(app: App) {
- app.use(store); // 全局注册 Pinia
-}
-```
-
-接着,将 `store` 在项目入口文件 `main.ts` 中引入,并将其作为全局插件传递给应用:
-
-```typescript
-// src/main.ts
-import { createSSRApp } from "vue";
-import App from "./App.vue";
-
-import { setupStore } from "@/store";
-
-export function createApp() {
- const app = createSSRApp(App);
- // 全局注册 store
- setupStore(app);
-
- return {
- app,
- };
-}
-
-```
-
-接下来,我们通过 Pinia 管理登录状态和用户信息,并在多个页面共享状态。
-
-### 用户信息接口
-
-编写一个 API 来获取当前登录用户的信息:
-
-```typescript
-import request from "@/utils/request";
-
-const USER_BASE_URL = "/api/v1/users";
-
-const UserAPI = {
- /**
- * 获取当前登录用户信息
- *
- * @returns 登录用户昵称、头像信息,包括角色和权限
- */
- getUserInfo(): Promise {
- return request({
- url: `${USER_BASE_URL}/me`,
- method: "GET",
- });
- },
-};
-export default UserAPI;
-
-/** 登录用户信息 */
-export interface UserInfo {
- /** 用户ID */
- userId?: number;
-
- /** 用户名 */
- username?: string;
-
- /** 昵称 */
- nickname?: string;
-
- /** 头像URL */
- avatar?: string;
-
- /** 角色 */
- roles: string[];
-
- /** 权限 */
- perms: string[];
-}
-```
-
-
-
-### 用户状态管理
-
-通过 Pinia 定义 `user` 模块,管理登录状态、用户信息等。
-
-```typescript
-// src/store/module/user.ts
-import { defineStore } from "pinia";
-import AuthAPI from "@/api/auth";
-import UserAPI, { UserInfo } from "@/api/user";
-
-export const useUserStore = defineStore("user", () => {
- // 确保 token 是响应式的
- const token = ref(uni.getStorageSync("token") || "");
- const userInfo = ref(null);
-
- // 登录
- const login = async (username: string, password: string) => {
- const { tokenType, accessToken } = await AuthAPI.login(username, password);
- token.value = `${tokenType} ${accessToken}`; // Bearer token
- uni.setStorageSync("token", token.value);
- };
-
- // 获取用户信息
- const getUserInfo = async () => {
- const info = await UserAPI.getUserInfo();
- userInfo.value = info;
- };
-
- // 登出
- const logout = async () => {
- await AuthAPI.logout();
- userInfo.value = null;
- token.value = ""; // 清空 token
- uni.removeStorageSync("token"); // 从本地缓存移除 token
- };
-
- return {
- token,
- userInfo,
- login,
- logout,
- getUserInfo,
- };
-});
-```
-
-### 个人中心页面
-
-个人中心页面展示用户的头像和昵称,未登录时引导用户去登录。
-
-```vue
-
-
- 我的
-
-
-
-
- {{ userInfo?.nickname }}
-
-
-
-
-
- 您还未登录,请先登录
-
-
-
-
-
-
-```
-
-登录页通过 `Pinia` 实现用户信息的全局状态管理,并在登录成功后跳转到个人中心页面。
-
-```vue
-
-
-
-
-
-
-
-
-
-
-
-```
-
-
-
-### 测试效果
-
-登录后,个人中心会显示用户的头像和昵称。通过 Pinia 实现了登录状态的共享和跨页面传递。
-
-
-
-
-
-### 整合源码
-
-整合`Pinia`代码版本:[vue-uniapp-template#737f6a3](https://gitee.com/youlaiorg/vue-uniapp-template/commit/737f6a3ee5217dcad006fa06b6fae63374d9826b)。
-
-## 反向代理
-
-在开发中,若服务端没有启用 CORS(跨域资源共享),浏览器会基于安全策略拦截跨域请求,导致无法访问接口。为了绕过这个问题,我们可以通过 Vite 的反向代理功能,将开发阶段的请求代理到真实的 API 服务器上,伪装成同源请求。
-
-本节将介绍如何配置 Vite 的反向代理来处理跨域请求。
-
----
-
-### 环境变量配置
-
-我们将通过环境变量来管理项目端口和 API 请求地址,以下是 `.env.development` 中的相关配置:
-
-```bash
-# .env.development
-
-# 项目运行的端口号
-VITE_APP_PORT=5173
-
-# API 请求的基础路径(开发环境)
-VITE_APP_BASE_API=/dev-api
-
-# 真实 API 服务器的 URL
-VITE_APP_API_URL=https://api.youlai.tech
-```
-
-### 请求工具的调整
-
-为了让请求走代理,我们需要在请求工具中将 `VITE_APP_API_URL` 替换为 `VITE_APP_BASE_API`。这样,所有对 `API` 的请求都会通过代理标识 `/dev-api` 进行转发。
-
-```typescript
-export default function request(options: UniApp.RequestOptions): Promise {
- return new Promise((resolve, reject) => {
- uni.request({
- ...options,
- // 原请求方式: 使用真实 API URL
- // url: `${import.meta.env.VITE_APP_API_URL}${options.url}`, // 示例: https://api.youlai.tech/login
-
- // 修改后:使用代理标识,实际转发到真实 API
- url: `${import.meta.env.VITE_APP_BASE_API}${options.url}`, // 示例: http://localhost:5173/dev-api/login
- });
- });
-}
-```
-
-### Vite 反向代理配置
-
-接下来,在 `vite.config.ts` 中添加反向代理配置,将 `/dev-api` 的请求代理到 `VITE_APP_API_URL`,通过 `http-proxy` 实现请求的转发。
-
-```typescript
-// vite.config.ts
-import { defineConfig, UserConfig, ConfigEnv, loadEnv } from "vite";
-
-export default defineConfig(async ({ mode }: ConfigEnv): Promise => {
- const env = loadEnv(mode, process.cwd());
-
- return {
- server: {
- host: "0.0.0.0",
- port: +env.VITE_APP_PORT,
- open: true,
- // 反向代理配置
- proxy: {
- [env.VITE_APP_BASE_API]: {
- target: env.VITE_APP_API_URL, // 目标服务器
- changeOrigin: true, // 支持跨域
- rewrite: (path) => path.replace(new RegExp("^" + env.VITE_APP_BASE_API), ""), // 去掉前缀
- },
- },
- },
- plugins: [
- // 插件配置...
- ],
- };
-});
-```
-
-### 测试与验证
-
-在配置好反向代理后,浏览器发出的请求将被 Vite 的代理服务器拦截并转发至真实的 API 地址。例如,浏览器请求 `http://localhost:5173/dev-api/api/v1/auth/login` 时,Vite 会将该请求代理到 `https://api.youlai.tech/api/v1/auth/login`。
-
-下图展示了这一过程,浏览器认为请求的 URL 与应用的主机地址一致,因此不会阻止该请求,即便真实请求已通过代理转发到外部服务器。
-
-
-
-需要注意,反向代理的目标是伪装请求来源,虽然它绕过了浏览器的同源策略,但有时也会让开发者误以为请求地址错误。实际上,这是由于代理转发过程造成的表面请求地址与真实请求地址的差异。
-
-### 整合源码
-
-整合`反向代理`和`环境变量`代码版本:[vue-uniapp-template#272d643](https://gitee.com/youlaiorg/vue-uniapp-template/tree/272d643744b3b009a90a54e9344a0fc827f8b9fc)。
-
-## 整合 `wot-design-uni`
-
-`wot-design-uni` 是基于 `Vue 3` 和 `TypeScript` 构建的高质量组件库。组件库遵循 `Wot Design` 的设计规范,提供 70 多个组件,支持暗黑模式、国际化和自定义主题,旨在为开发者提供一致的 UI 交互,同时提高开发效率。
-
-> **说明:** 本文档整合步骤基于 `wot-design-uni` 官方文档编写,建议开发者参考 [官方文档](https://wot-design-uni.pages.dev/guide/quick-use.html#npm-%E5%AE%89%E8%A3%85) 进行安装和配置,以确保组件库的正确使用。
-
----
-
-### 安装依赖
-
-根据官方文档,使用 `pnpm` 安装组件库的依赖:
-
-```bash
-pnpm add wot-design-uni
-```
-
-### 配置自动引入组件
-
-在传统的 `Vue` 项目中,使用组件需要手动安装、引用、注册。而使用 `easycom` 可以简化这些操作。只要组件路径符合规范,就可以直接在页面中使用,无需手动导入和注册。
-
-在 `pages.json` 文件中配置 `easycom` 自动引入:
-
-```json
-// pages.json
-{
- "easycom": {
- "autoscan": true,
- "custom": {
- "^wd-(.*)": "wot-design-uni/components/wd-$1/wd-$1.vue"
- }
- },
- "pages": [
- // 这里是项目已有的内容
- ]
-}
-```
-
-**关于 `easycom`:**
-`easycom` 是 `uni-app` 提供的自动化引入功能,更多细节请参考 [easycom 官方文档](https://uniapp.dcloud.net.cn/collocation/pages.html#easycom)。
-
-### Volar 支持
-
-为了让 `Volar` 正确识别和提示全局组件,你需要在项目的 `tsconfig.json` 文件中配置全局组件类型支持:
-
-```json
-// tsconfig.json
-{
- "compilerOptions": {
- "types": ["wot-design-uni/global"]
- }
-}
-```
-
-这将确保你在 `TypeScript` 项目中编写代码时,Volar 能提供完整的类型支持和代码提示。
-
-### 测试组件
-
-安装和配置完成后,你可以开始使用 `wot-design-uni` 的组件。在页面中,直接写组件标签即可,无需手动导入和注册:
-
-```vue
-
-
- 主要按钮
- 成功按钮
- 信息按钮
- 警告按钮
- 危险按钮
-
-
-```
-
-你将看到如下按钮效果:
-
-
-
-### 整合源码
-
-整合`wot-design-uni` 代码版本:[vue-uniapp-template#a775721](https://gitee.com/youlaiorg/vue-uniapp-template/tree/a7757213f282a6414a3cf2cc13aa2c54a9479ae4)。
-
-
-
-## 项目部署
-
-
-
-### H5 部署
-
-执行 `pnpm run build:h5` 命令来完成项目的打包:
-
-```bash
-pnpm run build:h5
-```
-
-打包后生成的静态文件位于 `dist/build/h5` 目录下。将该目录下的文件复制到服务器的 `/usr/share/nginx/html/vue-uniapp-template` 目录。
-
-接下来,配置 nginx:
-
-```nginx
-# nginx.conf
-server {
- listen 80;
- server_name localhost;
- location / {
- root /usr/share/nginx/html/vue-uniapp-template;
- index index.html index.htm;
- }
- # 反向代理配置
- location /prod-api/ {
- # 将 api.youlai.tech 替换为后端 API 地址,注意保留后面的斜杠 /
- proxy_pass http://api.youlai.tech/;
- }
-}
-```
-
-这样配置完成后,就可以通过 `nginx `服务器来访问你的项目了。
-
-### 小程序发布
-
-### 下载工具
-
-下载 [ HBuilder X ](https://www.dcloud.io/hbuilderx.html) 编辑器
-
-
-
-
-
-下载 [微信开发者工具](https://developers.weixin.qq.com/miniprogram/dev/devtools/stable.html)
-
-
-
-### 获取小程序 AppID
-
-访问 [微信公众平台](https://mp.weixin.qq.com/)申请小程序,获取 `AppID`。如果已申请,可在 `首页` → `小程序信息` → `查看详情` 查看 AppID
-
-
-
-
-
-### 配置项目
-
-使用 HBuilder X 打开项目,修改 `manifest.json` 文件中的小程序配置,并填写获取的 AppID。
-
-
-
-### 设置微信开发者工具
-
-使用微信扫码登录微信开发者工具,开启服务端口:点击工具栏`设置`→`安全设置`→`安全`→`服务端口`,选择打开。
-
-
-
-### 运行项目
-
-在 HBuilder X 中,点击 `运行`→`运行到小程序模拟器`→`微信开发者工具`。
-
-
-
-项目编译完成后,微信开发者工具会自动启动并呈现页面。
-
-
-
-### 上传发布
-
-在微信开发者工具中,点击 `上传` 将应用发布到小程序平台。
-
-
-
-
-
-### 查看效果
-
-最后,使用手机打开小程序查看效果:
-
-
diff --git a/.npmrc b/.npmrc
new file mode 100644
index 0000000..c483022
--- /dev/null
+++ b/.npmrc
@@ -0,0 +1 @@
+shamefully-hoist=true
\ No newline at end of file
diff --git a/components.d.ts b/components.d.ts
new file mode 100644
index 0000000..3f5fa27
--- /dev/null
+++ b/components.d.ts
@@ -0,0 +1,49 @@
+/* eslint-disable */
+/* prettier-ignore */
+// @ts-nocheck
+// Generated by vite-plugin-uni-components
+// Read more: https://github.com/vuejs/core/pull/3399
+export {}
+
+declare module 'vue' {
+ export interface GlobalComponents {
+ CuDateQuery: typeof import('./src/components/cu-date-query/index.vue')['default']
+ CuDict: typeof import('./src/components/cu-dict/index.vue')['default']
+ CuDictLabel: typeof import('./src/components/cu-dict-label/index.vue')['default']
+ CuPicker: typeof import('./src/components/cu-picker/index.vue')['default']
+ DaTree: typeof import('./src/components/da-tree/index.vue')['default']
+ Loading1: typeof import('./src/components/qiun-loading/loading1.vue')['default']
+ Loading2: typeof import('./src/components/qiun-loading/loading2.vue')['default']
+ Loading3: typeof import('./src/components/qiun-loading/loading3.vue')['default']
+ Loading4: typeof import('./src/components/qiun-loading/loading4.vue')['default']
+ Loading5: typeof import('./src/components/qiun-loading/loading5.vue')['default']
+ QiunDataCharts: typeof import('./src/components/qiun-data-charts/qiun-data-charts.vue')['default']
+ QiunError: typeof import('./src/components/qiun-error/qiun-error.vue')['default']
+ QiunLoading: typeof import('./src/components/qiun-loading/qiun-loading.vue')['default']
+ TodoItem: typeof import('./src/components/todo/TodoItem.vue')['default']
+ TodoList: typeof import('./src/components/todo/TodoList.vue')['default']
+ WdButton: typeof import('wot-design-uni/components/wd-button/wd-button.vue')['default']
+ WdCard: typeof import('wot-design-uni/components/wd-card/wd-card.vue')['default']
+ 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']
+ WdConfigProvider: typeof import('wot-design-uni/components/wd-config-provider/wd-config-provider.vue')['default']
+ WdForm: typeof import('wot-design-uni/components/wd-form/wd-form.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']
+ WdIcon: typeof import('wot-design-uni/components/wd-icon/wd-icon.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']
+ 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']
+ 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']
+ 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']
+ WdToast: typeof import('wot-design-uni/components/wd-toast/wd-toast.vue')['default']
+ WechatProfile: typeof import('./src/components/WechatProfile.vue')['default']
+ }
+}
diff --git a/docs/theme-guide.md b/docs/theme-guide.md
deleted file mode 100644
index 652c502..0000000
--- a/docs/theme-guide.md
+++ /dev/null
@@ -1,361 +0,0 @@
-# 主题设置功能指南
-
-## 功能概述
-
-本项目提供了完整的主题设置功能,支持暗黑模式切换和主题色自定义,让用户可以个性化应用的外观。
-
-## 功能特性
-
-### 1. 暗黑模式
-
-- 支持浅色/暗黑模式切换
-- 自动保存用户偏好设置
-- 平滑的过渡动画效果
-- 导航栏颜色自动适配
-
-### 2. 主题色设置
-
-- 12种预设主题色可选
-- 支持自定义十六进制颜色值
-- 实时预览效果
-- 主题色持久化存储
-
-### 3. 效果预览
-
-- 按钮样式预览
-- 文本颜色预览
-- 标签组件预览
-- 实时更新显示
-
-## 文件结构
-
-```
-src/
-├── composables/
-│ └── theme/
-│ ├── theme.ts # 主题管理核心逻辑
-│ └── rootTheme.ts # 主题配置和默认值
-├── store/
-│ └── modules/
-│ └── theme.ts # 主题状态管理
-├── pages/
-│ └── setting.vue # 主题设置页面
-├── utils/
-│ ├── theme.ts # 主题工具函数
-│ └── colorUtils.ts # 颜色处理工具
-└── styles/
- └── global.scss # 全局主题样式
-```
-
-## 核心组件说明
-
-### 1. useTheme Composable
-
-位置:`src/composables/theme/theme.ts`
-
-主要功能:
-
-- 主题模式切换(浅色/暗黑)
-- 主题色设置和保存
-- 导航栏颜色适配
-- 本地存储管理
-
-```typescript
-const {
- theme, // 当前主题模式
- themeVars, // 主题变量
- toggleTheme, // 切换主题模式
- setThemeColor, // 设置主题色
- initTheme, // 初始化主题
-} = useTheme();
-```
-
-### 2. useThemeStore
-
-位置:`src/store/modules/theme.ts`
-
-主要功能:
-
-- 主题色状态管理
-- CSS变量动态设置
-- 多平台兼容处理
-
-```typescript
-const themeStore = useThemeStore();
-
-// 设置主题色
-themeStore.setPrimaryColor("#165DFF");
-
-// 初始化主题
-themeStore.initTheme();
-```
-
-### 3. 主题设置页面
-
-位置:`src/pages/setting.vue`
-
-功能模块:
-
-- 暗黑模式开关
-- 预设主题色选择
-- 自定义颜色输入
-- 效果实时预览
-- 重置默认主题
-
-## 使用方法
-
-### 1. 基础使用
-
-在页面中引入主题功能:
-
-```vue
-
-
-
-
-
-
-
-```
-
-### 2. 在布局中使用
-
-在 `src/layouts/tabbar.vue` 中已经集成了主题功能:
-
-```vue
-
-
-
-
-
-```
-
-### 3. 自定义主题色
-
-支持的颜色格式:
-
-- 6位十六进制:`#165DFF`
-- 3位十六进制:`#16F`(会自动转换为6位)
-
-```javascript
-// 设置自定义主题色
-const customColor = "#FF6B6B";
-themeStore.setPrimaryColor(customColor);
-```
-
-## 预设主题色
-
-项目提供了12种预设主题色:
-
-| 颜色名称 | 颜色值 | 说明 |
-| -------- | ------- | ---------- |
-| 蓝色 | #0055FE | 默认主题色 |
-| 红色 | #CD5C5C | 经典红色 |
-| 绿色 | #228B22 | 自然绿色 |
-| 紫色 | #722ED1 | 优雅紫色 |
-| 橙色 | #FA8C16 | 活力橙色 |
-| 黄色 | #FADB14 | 明亮黄色 |
-| 青色 | #13C2C2 | 清新青色 |
-| 粉色 | #EB2F96 | 温馨粉色 |
-| 天蓝色 | #1890FF | 科技蓝色 |
-| 深红色 | #F5222D | 警示红色 |
-
-## 样式变量
-
-主题系统使用CSS变量来实现动态主题切换:
-
-```scss
-:root {
- /* 主色调 */
- --primary-color: #165dff;
- --primary-color-light: #94bfff;
- --primary-color-dark: #0e3c9b;
-
- /* 功能色 */
- --success-color: #0fc6c2;
- --warning-color: #ff7d00;
- --danger-color: #f5222d;
- --info-color: #86909c;
-}
-```
-
-在组件中使用:
-
-```scss
-.my-button {
- background-color: var(--primary-color);
- color: #fff;
-
- &:hover {
- background-color: var(--primary-color-dark);
- }
-}
-```
-
-## 平台兼容性
-
-### H5平台
-
-- 使用CSS变量动态设置主题
-- 支持所有现代浏览器
-- 平滑的过渡动画
-
-### 小程序平台
-
-- 使用原生API设置TabBar样式
-- 通过工具函数处理样式应用
-- 兼容微信、支付宝等小程序
-
-### APP平台
-
-- 支持原生导航栏颜色设置
-- 状态栏颜色自动适配
-- 性能优化处理
-
-## 最佳实践
-
-### 1. 主题初始化
-
-在应用启动时初始化主题:
-
-```typescript
-// src/App.vue
-import { useThemeStore } from "@/store/modules/theme";
-
-const themeStore = useThemeStore();
-
-onLaunch(() => {
- // 初始化主题
- themeStore.initTheme();
-});
-```
-
-### 2. 组件中使用主题
-
-```vue
-
-
- 标题
-
-
-
-
-
-```
-
-### 3. 暗黑模式适配
-
-```scss
-// 暗黑模式样式
-:deep(.wd-config-provider[data-theme="dark"]) {
- .my-component {
- background: #2a2a2a;
- color: #fff;
-
- .title {
- color: var(--primary-color);
- }
- }
-}
-```
-
-## 注意事项
-
-1. **性能优化**:主题切换时避免频繁的DOM操作
-2. **兼容性**:小程序环境下某些CSS特性可能不支持
-3. **用户体验**:提供平滑的过渡动画效果
-4. **持久化**:确保用户设置能够正确保存和恢复
-5. **响应式**:在不同屏幕尺寸下保持良好的显示效果
-
-## 故障排除
-
-### 1. 主题色不生效
-
-- 检查CSS变量是否正确设置
-- 确认组件是否在 `wd-config-provider` 包裹内
-- 验证颜色值格式是否正确
-
-### 2. 暗黑模式切换异常
-
-- 检查 `theme` 状态是否正确更新
-- 确认暗黑模式样式是否正确编写
-- 验证导航栏颜色设置是否生效
-
-### 3. 设置不持久化
-
-- 检查本地存储权限
-- 确认存储key是否正确
-- 验证初始化逻辑是否执行
-
-## 扩展开发
-
-### 1. 添加新的预设主题色
-
-在 `src/composables/theme/rootTheme.ts` 中添加:
-
-```typescript
-export const colorColumns = [
- // 现有颜色...
- {
- value: "#YOUR_COLOR",
- label: "你的颜色名称",
- },
-];
-```
-
-### 2. 自定义主题变量
-
-在 `src/composables/theme/rootTheme.ts` 中扩展:
-
-```typescript
-export const initThemeVars: ConfigProviderThemeVars = {
- colorTheme: colorColumns[0].value,
- // 添加更多主题变量
- colorSuccess: "#52c41a",
- colorWarning: "#faad14",
- colorDanger: "#ff4d4f",
-};
-```
-
-### 3. 添加主题切换动画
-
-```scss
-.theme-transition {
- transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
-}
-```
-
-通过以上指南,你可以充分利用项目的主题设置功能,为用户提供个性化的应用体验。
diff --git a/docs/wechat-login-guide.md b/docs/wechat-login-guide.md
deleted file mode 100644
index 9823d4d..0000000
--- a/docs/wechat-login-guide.md
+++ /dev/null
@@ -1,342 +0,0 @@
-# 微信小程序手机授权登录功能指南
-
-## 功能概述
-
-本项目实现了完整的微信小程序手机授权登录功能,包括:
-
-- 微信登录授权
-- 手机号获取授权
-- 头像昵称填写(使用微信小程序新能力)
-- 用户信息完善流程
-- 登录状态管理
-
-## 功能特性
-
-### 1. 微信登录流程
-
-- **基础微信登录**:使用 `uni.login()` 获取 code,调用后端接口完成登录
-- **增强微信登录**:支持更多用户信息和手机号一次性授权
-- **登录状态检查**:自动检查用户信息完整性,引导用户完善信息
-
-### 2. 手机号授权
-
-- **一键授权**:使用微信小程序 `getPhoneNumber` 能力
-- **安全获取**:通过后端接口解密获取真实手机号
-- **状态显示**:显示脱敏手机号,支持重新授权
-
-### 3. 头像昵称填写
-
-- **微信新能力**:使用 `chooseAvatar` 和 `type="nickname"` 输入框
-- **自动上传**:头像选择后自动上传到服务器
-- **实时预览**:支持头像实时预览和昵称输入
-
-### 4. 用户信息完善
-
-- **智能引导**:登录后自动检查信息完整性
-- **分步填写**:头像、昵称、性别、手机号分步骤完善
-- **跳过机制**:允许用户暂时跳过,但会提示影响功能使用
-
-## 文件结构
-
-```
-src/
-├── pages/
-│ └── login/
-│ ├── index.vue # 登录页面
-│ └── complete-profile.vue # 完善信息页面
-├── components/
-│ └── WechatProfile.vue # 微信头像昵称组件
-├── api/
-│ ├── auth.ts # 认证API
-│ ├── user.ts # 用户API
-│ └── file.ts # 文件上传API
-├── store/
-│ └── modules/
-│ └── user.ts # 用户状态管理
-└── utils/
- ├── auth.ts # 认证工具函数
- └── storage.ts # 存储工具函数
-```
-
-## 核心组件说明
-
-### 1. 登录页面 (`pages/login/index.vue`)
-
-**主要功能:**
-
-- 用户名密码登录
-- 微信一键登录
-- 登录状态检查和跳转
-
-**关键代码:**
-
-```typescript
-// 微信登录处理
-const handleWechatLogin = async () => {
- const { code } = await uni.login({ provider: "weixin" });
-
- // 尝试增强登录
- try {
- const result = await userStore.loginByWechatMini({ code });
- // 检查信息完整性
- if (result.isNewUser || !result.isProfileComplete) {
- // 跳转到完善信息页面
- uni.navigateTo({
- url: `/pages/login/complete-profile?redirect=${redirect}`,
- });
- }
- } catch (error) {
- // 回退到基础登录
- await userStore.loginByWechat(code);
- }
-};
-```
-
-### 2. 完善信息页面 (`pages/login/complete-profile.vue`)
-
-**主要功能:**
-
-- 头像上传(支持微信新能力)
-- 昵称输入
-- 性别选择
-- 手机号授权
-- 信息提交和验证
-
-**关键代码:**
-
-```typescript
-// 手机号授权
-const onGetPhoneNumber = async (e: any) => {
- if (e.detail.errMsg === "getPhoneNumber:ok") {
- const phoneData = await UserAPI.getPhoneNumber({
- code: e.detail.code,
- encryptedData: e.detail.encryptedData,
- iv: e.detail.iv,
- });
- profileForm.mobile = phoneData.phoneNumber;
- }
-};
-```
-
-### 3. 微信头像昵称组件 (`components/WechatProfile.vue`)
-
-**主要功能:**
-
-- 使用微信小程序头像选择能力
-- 昵称输入框(type="nickname")
-- 性别选择
-- 数据双向绑定
-
-**关键代码:**
-
-```vue
-
-
-
-
-
-```
-
-## API 接口说明
-
-### 1. 认证相关接口
-
-```typescript
-// 基础微信登录
-AuthAPI.wechatLogin(code: string): Promise
-
-// 增强微信登录
-AuthAPI.wechatMiniLogin(data: WechatMiniLoginData): Promise
-```
-
-### 2. 用户相关接口
-
-```typescript
-// 获取微信手机号
-UserAPI.getPhoneNumber(data: WechatPhoneData): Promise
-
-// 绑定手机号
-UserAPI.bindMobile(data: MobileBindingForm): Promise
-
-// 更新用户信息
-UserAPI.updateProfile(data: UserProfileForm): Promise
-```
-
-### 3. 文件上传接口
-
-```typescript
-// 上传文件
-FileAPI.upload(filePath: string): Promise
-```
-
-## 类型定义
-
-### 微信登录相关
-
-```typescript
-interface WechatMiniLoginData {
- code: string;
- userInfo?: {
- nickName?: string;
- avatarUrl?: string;
- gender?: number;
- };
- phoneData?: {
- code: string;
- encryptedData?: string;
- iv?: string;
- };
-}
-
-interface WechatLoginResult extends LoginResult {
- isNewUser?: boolean;
- isProfileComplete?: boolean;
- userInfo?: {
- userId?: number;
- username?: string;
- nickname?: string;
- avatar?: string;
- mobile?: string;
- };
-}
-```
-
-### 手机号授权相关
-
-```typescript
-interface WechatPhoneData {
- code: string;
- encryptedData?: string;
- iv?: string;
-}
-
-interface PhoneNumberResult {
- phoneNumber: string;
- purePhoneNumber?: string;
- countryCode?: string;
-}
-```
-
-## 使用流程
-
-### 1. 用户首次登录
-
-1. 用户点击微信登录按钮
-2. 调用 `uni.login()` 获取微信 code
-3. 调用后端登录接口,获取 token
-4. 检查用户信息完整性
-5. 如果信息不完整,跳转到完善信息页面
-
-### 2. 完善用户信息
-
-1. 用户进入完善信息页面
-2. 选择头像(使用微信新能力或传统上传)
-3. 输入昵称(使用 type="nickname" 输入框)
-4. 选择性别
-5. 授权获取手机号
-6. 提交信息,更新用户资料
-
-### 3. 后续登录
-
-1. 用户再次登录时,检查信息完整性
-2. 如果信息完整,直接跳转到主页
-3. 如果信息不完整,引导用户完善
-
-## 配置要求
-
-### 1. 微信小程序配置
-
-在 `manifest.json` 中配置:
-
-```json
-{
- "mp-weixin": {
- "appid": "your-appid",
- "setting": {
- "urlCheck": false
- },
- "permission": {
- "scope.userInfo": {
- "desc": "用于完善用户资料"
- }
- }
- }
-}
-```
-
-### 2. 后端接口要求
-
-- 支持微信登录 code 解析
-- 支持微信手机号解密
-- 支持文件上传
-- 支持用户信息更新
-
-## 注意事项
-
-### 1. 微信小程序新能力
-
-- `chooseAvatar` 和 `type="nickname"` 需要微信基础库 2.21.2+
-- 需要在微信开发者工具中测试
-- 真机调试时需要注意兼容性
-
-### 2. 手机号授权
-
-- 需要微信小程序认证
-- 需要在微信公众平台配置服务器域名
-- 手机号解密需要在后端完成
-
-### 3. 用户体验
-
-- 提供跳过机制,避免强制完善信息
-- 显示脱敏手机号,保护用户隐私
-- 支持重新授权和修改信息
-
-## 扩展功能
-
-### 1. 社交登录
-
-可以扩展支持其他社交平台登录:
-
-- QQ 登录
-- 支付宝登录
-- 苹果登录
-
-### 2. 实名认证
-
-可以添加实名认证功能:
-
-- 身份证验证
-- 人脸识别
-- 银行卡验证
-
-### 3. 多端同步
-
-可以实现多端登录状态同步:
-
-- H5 端登录
-- APP 端登录
-- 小程序端登录
-
-## 故障排除
-
-### 1. 微信登录失败
-
-- 检查 appid 配置
-- 检查服务器域名配置
-- 检查网络连接
-
-### 2. 手机号授权失败
-
-- 检查小程序是否已认证
-- 检查后端解密接口
-- 检查用户授权状态
-
-### 3. 头像上传失败
-
-- 检查文件上传接口
-- 检查文件大小限制
-- 检查网络状态
-
-## 总结
diff --git a/package.json b/package.json
index f9e5359..c6481e3 100644
--- a/package.json
+++ b/package.json
@@ -90,11 +90,12 @@
"@dcloudio/uni-mp-weixin": "3.0.0-4020420240722002",
"@dcloudio/uni-mp-xhs": "3.0.0-4020420240722002",
"@dcloudio/uni-quickapp-webview": "3.0.0-4020420240722002",
+ "@stomp/stompjs": "^7.1.1",
"@uni-helper/uni-use": "^0.19.14",
- "@vueuse/core": "10.11.1",
+ "@vueuse/core": "9.13.0",
"pinia": "^2.2.2",
"vue": "^3.5.13",
- "wot-design-uni": "^1.4.0"
+ "wot-design-uni": "^1.9.1"
},
"devDependencies": {
"@commitlint/cli": "^19.5.0",
@@ -105,6 +106,7 @@
"@dcloudio/uni-stacktracey": "3.0.0-4020420240722002",
"@dcloudio/vite-plugin-uni": "3.0.0-4020420240722002",
"@eslint/js": "^9.10.0",
+ "@uni-helper/vite-plugin-uni-components": "^0.2.0",
"@uni-helper/vite-plugin-uni-layouts": "^0.1.10",
"@uni-helper/vite-plugin-uni-pages": "^0.2.28",
"@vue/runtime-core": "^3.4.21",
@@ -135,7 +137,7 @@
"unocss": "^0.62.4",
"unocss-preset-weapp": "^0.62.2",
"unplugin-auto-import": "^0.18.3",
- "vite": "5.2.8",
+ "vite": "6.3.2",
"vue-eslint-parser": "^9.4.3",
"vue-tsc": "^1.0.24"
}
diff --git a/pages.config.ts b/pages.config.ts
index f6d4302..4d68a28 100644
--- a/pages.config.ts
+++ b/pages.config.ts
@@ -3,9 +3,36 @@ import { defineUniPages } from "@uni-helper/vite-plugin-uni-pages";
export default defineUniPages({
// 你也可以定义 pages 字段,它具有最高的优先级。
- pages: [],
+ pages: [
+ {
+ path: "pages/index/index",
+ layout: "tabbar",
+ },
+ {
+ path: "pages/mine/index",
+ layout: "tabbar",
+ },
+ ],
globalStyle: {
navigationBarTextStyle: "black",
- navigationBarTitleText: "@uni-helper",
+ navigationBarTitleText: "vue-uniapp-template",
+ },
+
+ tabBar: {
+ custom: true,
+ height: "0px",
+ color: "#00000000",
+ selectedColor: "#00000000",
+ backgroundColor: "#00000000",
+ list: [
+ {
+ text: "首页",
+ pagePath: "pages/index/index",
+ },
+ {
+ text: "我的",
+ pagePath: "pages/mine/index",
+ },
+ ],
},
});
diff --git a/src/api/file.ts b/src/api/file.ts
index c472c5c..118880f 100644
--- a/src/api/file.ts
+++ b/src/api/file.ts
@@ -1,5 +1,5 @@
import { getToken } from "@/utils/storage";
-import { ResultCodeEnum } from "@/enums/ResultCodeEnum";
+import { ApiCode } from "@/enums/api-code.enum";
// H5 使用 VITE_APP_BASE_API 作为代理路径,其他平台使用 VITE_APP_API_URL 作为请求路径
let baseApi = import.meta.env.VITE_APP_API_URL;
@@ -31,7 +31,7 @@ const FileAPI = {
success: (response) => {
const resData = JSON.parse(response.data) as ResponseData;
// 业务状态码 00000 表示成功
- if (resData.code === ResultCodeEnum.SUCCESS) {
+ if (resData.code === ApiCode.SUCCESS) {
resolve(resData.data);
} else {
// 其他业务处理失败
diff --git a/src/composables/theme/rootTheme.ts b/src/composables/theme/rootTheme.ts
deleted file mode 100644
index 0d5bb3d..0000000
--- a/src/composables/theme/rootTheme.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import type { ConfigProviderThemeVars } from "wot-design-uni";
-/* 默认的主题list */
-export const colorColumns = [
- {
- value: "#0055FE",
- label: "蓝色",
- },
- {
- value: "#CD5C5C",
- label: "红色",
- },
- {
- value: "#228B22",
- label: "绿色",
- },
-];
-/* 默认的主题 */
-export const initThemState = "light";
-/* 默认的主题 */
-export const initThemeVars: ConfigProviderThemeVars = {
- colorTheme: colorColumns[0].value,
-};
diff --git a/src/composables/theme/theme.ts b/src/composables/theme/theme.ts
deleted file mode 100644
index 983a135..0000000
--- a/src/composables/theme/theme.ts
+++ /dev/null
@@ -1,74 +0,0 @@
-import { colorColumns, initThemState, initThemeVars } from "./rootTheme";
-/* 暗黑模式切换 */
-const theme = ref<"light" | "dark">(initThemState);
-/* 组件库的主题色 */
-const themeVars = ref({ ...initThemeVars });
-
-// 从本地存储恢复主题设置
-function loadThemeFromStorage() {
- try {
- const savedTheme = uni.getStorageSync("app_theme_mode");
- const savedThemeColor = uni.getStorageSync("app_theme_color");
-
- if (savedTheme && (savedTheme === "light" || savedTheme === "dark")) {
- theme.value = savedTheme;
- }
-
- if (savedThemeColor) {
- themeVars.value.colorTheme = savedThemeColor;
- }
- } catch (error) {
- console.error("加载主题设置失败:", error);
- }
-}
-
-// 保存主题设置到本地存储
-function saveThemeToStorage() {
- try {
- uni.setStorageSync("app_theme_mode", theme.value);
- uni.setStorageSync("app_theme_color", themeVars.value.colorTheme);
- } catch (error) {
- console.error("保存主题设置失败:", error);
- }
-}
-
-export function useTheme() {
- /* 切换暗黑模式 */
- function toggleTheme(mode?: "light" | "dark") {
- theme.value = mode || (theme.value === "light" ? "dark" : "light");
- setNavigationBarColor();
- saveThemeToStorage();
- }
-
- /* 设置主题色 */
- function setThemeColor(color: string) {
- themeVars.value.colorTheme = color;
- saveThemeToStorage();
- }
-
- /* 初始化theme */
- function initTheme() {
- loadThemeFromStorage();
- setNavigationBarColor();
- }
-
- function setNavigationBarColor() {
- uni.setNavigationBarColor({
- frontColor: theme.value === "light" ? "#000000" : "#ffffff",
- backgroundColor: theme.value === "light" ? "#ffffff" : "#000000",
- animation: {
- duration: 400,
- timingFunc: "easeIn",
- },
- });
- }
-
- return {
- theme,
- themeVars,
- initTheme,
- colorColumns,
- toggleTheme,
- setThemeColor,
- };
-}
diff --git a/src/composables/useStomp.ts b/src/composables/useStomp.ts
index c2b8912..fb2777a 100644
--- a/src/composables/useStomp.ts
+++ b/src/composables/useStomp.ts
@@ -1,5 +1,5 @@
import { Client, type IMessage, type StompSubscription } from "@stomp/stompjs";
-import { Auth } from "@/utils/auth";
+import { getAccessToken } from "@/utils/auth";
export interface UseStompOptions {
/** WebSocket 地址,不传时使用 VITE_APP_WS_ENDPOINT 环境变量 */
@@ -70,7 +70,7 @@ export function useStomp(options: UseStompOptions = {}) {
}
// 每次连接前重新获取最新令牌,不依赖之前的token值
- const currentToken = Auth.getAccessToken();
+ const currentToken = getAccessToken();
// 检查令牌是否为空,如果为空则不进行连接
if (!currentToken) {
@@ -123,7 +123,7 @@ export function useStomp(options: UseStompOptions = {}) {
};
// 设置 Web Socket 关闭监听器
- client.value.onWebSocketClose = (event) => {
+ client.value.onWebSocketClose = (event: CloseEvent) => {
isConnected.value = false;
isConnecting = false;
console.log(`WebSocket已关闭: ${event?.code} ${event?.reason}`);
@@ -147,7 +147,7 @@ export function useStomp(options: UseStompOptions = {}) {
};
// 设置错误监听器
- client.value.onStompError = (frame) => {
+ client.value.onStompError = (frame: any) => {
console.error("STOMP错误:", frame.headers, frame.body);
isConnecting = false;
diff --git a/src/composables/useTabbar.ts b/src/composables/useTabbar.ts
deleted file mode 100644
index 27179b9..0000000
--- a/src/composables/useTabbar.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * @Author: weisheng
- * @Date: 2024-10-29 22:12:54
- * @LastEditTime: 2025-01-13 16:45:28
- * @LastEditors: 810505339
- * @Description:
- * @FilePath: \wot-demo\src\composables\useTabbar.ts
- * 记得注释
- */
-export interface TabbarItem {
- name: string;
- value: number | null;
- active: boolean;
- title: string;
- icon: string;
-}
-
-const tabbarItems = ref([
- { name: "home", value: null, active: true, title: "home", icon: "home" },
- { name: "hi", value: null, active: false, title: "hi", icon: "app" },
- { name: "setting", value: null, active: false, title: "setting", icon: "setting" },
-]);
-
-export function useTabbar() {
- const tabbarList = computed(() => tabbarItems.value);
-
- const activeTabbar = computed(() => {
- const item = tabbarItems.value.find((item) => item.active);
- return item || tabbarItems.value[0];
- });
-
- const getTabbarItemValue = (name: string) => {
- const item = tabbarItems.value.find((item) => item.name === name);
- return item && item.value ? item.value : null;
- };
-
- const setTabbarItem = (name: string, value: number) => {
- const tabbarItem = tabbarItems.value.find((item) => item.name === name);
- if (tabbarItem) {
- tabbarItem.value = value;
- }
- };
-
- const setTabbarItemActive = (name: string) => {
- tabbarItems.value.forEach((item) => {
- if (item.name === name) {
- item.active = true;
- } else {
- item.active = false;
- }
- });
- };
-
- return {
- tabbarList,
- activeTabbar,
- getTabbarItemValue,
- setTabbarItem,
- setTabbarItemActive,
- };
-}
diff --git a/src/composables/useTheme.ts b/src/composables/useTheme.ts
new file mode 100644
index 0000000..b5ab3ee
--- /dev/null
+++ b/src/composables/useTheme.ts
@@ -0,0 +1,76 @@
+import { ref, computed } from "vue";
+import type { ConfigProviderThemeVars } from "wot-design-uni";
+
+/* 默认的主题list */
+export const colorColumns = [
+ {
+ value: "#0055FE",
+ label: "蓝色",
+ },
+ {
+ value: "#CD5C5C",
+ label: "红色",
+ },
+ {
+ value: "#228B22",
+ label: "绿色",
+ },
+];
+
+/* 默认的主题 */
+export const initThemState = "light";
+
+/* 默认的主题变量 - 只使用wot-design-uni支持的变量 */
+export const initThemeVars: ConfigProviderThemeVars = {
+ colorTheme: colorColumns[0].value,
+};
+
+/* 暗黑模式主题变量 */
+export const darkThemeVars: ConfigProviderThemeVars = {
+ colorTheme: colorColumns[0].value,
+};
+
+/* 主题状态 */
+export const themeState = ref(initThemState);
+
+/* 主题变量 */
+export const themeVars = ref(initThemeVars);
+
+/* 计算属性:根据主题状态返回对应的主题变量 */
+export const computedThemeVars = computed(() => {
+ const baseVars = themeState.value === "dark" ? darkThemeVars : initThemeVars;
+ return {
+ ...baseVars,
+ ...themeVars.value,
+ };
+});
+
+/* 切换主题 */
+export const toggleTheme = () => {
+ themeState.value = themeState.value === "light" ? "dark" : "light";
+ // 更新主题变量
+ const newBaseVars = themeState.value === "dark" ? darkThemeVars : initThemeVars;
+ themeVars.value = {
+ ...newBaseVars,
+ colorTheme: themeVars.value.colorTheme, // 保持用户选择的主题色
+ };
+};
+
+/* 设置主题色 */
+export const setThemeColor = (color: string) => {
+ themeVars.value = {
+ ...themeVars.value,
+ colorTheme: color,
+ };
+};
+
+/* 导出主题相关的工具 */
+export const useTheme = () => {
+ return {
+ themeState,
+ themeVars: computedThemeVars,
+ toggleTheme,
+ setThemeColor,
+ colorColumns,
+ };
+};
diff --git a/src/constants/index.ts b/src/constants/index.ts
index f8be9d9..1e8e3b6 100644
--- a/src/constants/index.ts
+++ b/src/constants/index.ts
@@ -1,4 +1,6 @@
-export const ROLE_ROOT = "ROOT";
+/**
+ * 常量统一导出
+ */
-// 🔗 导出所有存储键常量
-export * from "./storage-keys";
+// 存储相关常量
+export * from "./storage.constant";
diff --git a/src/constants/storage-keys.ts b/src/constants/storage.constant.ts
similarity index 100%
rename from src/constants/storage-keys.ts
rename to src/constants/storage.constant.ts
diff --git a/src/directive/index.ts b/src/directive/index.ts
deleted file mode 100644
index 72de857..0000000
--- a/src/directive/index.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import type { App } from "vue";
-
-import { hasPerm, hasRole } from "./permission";
-
-// 全局注册 directive
-export function setupDirective(app: App) {
- // 使 v-hasPerm 在所有组件中都可用
- app.directive("hasPerm", hasPerm);
- app.directive("hasRole", hasRole);
-}
diff --git a/src/directive/permission/index.ts b/src/directive/permission/index.ts
deleted file mode 100644
index cdeb15c..0000000
--- a/src/directive/permission/index.ts
+++ /dev/null
@@ -1,69 +0,0 @@
-import type { Directive, DirectiveBinding } from "vue";
-
-import { useUserStore } from "@/store";
-
-/**
- * 按钮权限
- */
-export const hasPerm: Directive = {
- mounted(el: HTMLElement, binding: DirectiveBinding) {
- const requiredPerms = binding.value;
-
- console.log("requiredPerms", requiredPerms);
- if (!requiredPerms) {
- return;
- }
-
- // 校验传入的权限值是否合法
- if (!requiredPerms || (typeof requiredPerms !== "string" && !Array.isArray(requiredPerms))) {
- throw new Error(
- "需要提供权限标识!例如:v-has-perm=\"'sys:user:add'\" 或 v-has-perm=\"['sys:user:add', 'sys:user:edit']\""
- );
- }
-
- const { roles = [], perms = [] } = useUserStore().userInfo || {};
-
- // 超级管理员拥有所有权限
- if (roles?.includes("ROOT")) {
- return;
- }
-
- // 检查权限
- const hasAuth = Array.isArray(requiredPerms)
- ? requiredPerms.some((perm) => perms.includes(perm))
- : perms.includes(requiredPerms);
-
- // 如果没有权限,移除该元素
- if (!hasAuth && el.parentNode) {
- el.parentNode.removeChild(el);
- }
- },
-};
-
-/**
- * 角色权限指令
- */
-export const hasRole: Directive = {
- mounted(el: HTMLElement, binding: DirectiveBinding) {
- const requiredRoles = binding.value;
-
- // 校验传入的角色值是否合法
- if (!requiredRoles || (typeof requiredRoles !== "string" && !Array.isArray(requiredRoles))) {
- throw new Error(
- "需要提供角色标识!例如:v-has-role=\"'ADMIN'\" 或 v-has-role=\"['ADMIN', 'TEST']\""
- );
- }
-
- const { roles = [] } = useUserStore().userInfo || {};
-
- // 检查是否有对应角色权限
- const hasAuth = Array.isArray(requiredRoles)
- ? requiredRoles.some((role) => roles.includes(role))
- : roles.includes(requiredRoles);
-
- // 如果没有权限,移除元素
- if (!hasAuth && el.parentNode) {
- el.parentNode.removeChild(el);
- }
- },
-};
diff --git a/src/enums/ResultCodeEnum.ts b/src/enums/ResultCodeEnum.ts
deleted file mode 100644
index 7a71a04..0000000
--- a/src/enums/ResultCodeEnum.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-/**
- * 响应码枚举
- */
-export const enum ResultCodeEnum {
- /**
- * 成功
- */
- SUCCESS = "00000",
- /**
- * 错误
- */
- ERROR = "B0001",
-
- /**
- * 令牌无效或过期
- */
- TOKEN_INVALID = "A0230",
-}
diff --git a/src/enums/api-code.enum.ts b/src/enums/api-code.enum.ts
new file mode 100644
index 0000000..3772a3b
--- /dev/null
+++ b/src/enums/api-code.enum.ts
@@ -0,0 +1,49 @@
+/**
+ * API响应码枚举
+ */
+export const enum ApiCode {
+ /**
+ * 成功
+ */
+ SUCCESS = "00000",
+
+ /**
+ * 通用错误
+ */
+ ERROR = "B0001",
+
+ /**
+ * 令牌无效或过期
+ */
+ TOKEN_INVALID = "A0230",
+
+ /**
+ * 令牌已过期
+ */
+ TOKEN_EXPIRED = "A0231",
+
+ /**
+ * 未授权访问
+ */
+ UNAUTHORIZED = "A0232",
+
+ /**
+ * 禁止访问
+ */
+ FORBIDDEN = "A0233",
+
+ /**
+ * 参数校验失败
+ */
+ PARAM_INVALID = "A0400",
+
+ /**
+ * 资源不存在
+ */
+ NOT_FOUND = "A0404",
+
+ /**
+ * 服务器内部错误
+ */
+ INTERNAL_ERROR = "B0500",
+}
diff --git a/src/layouts/default.vue b/src/layouts/default.vue
index 2d5d262..54d7c3e 100644
--- a/src/layouts/default.vue
+++ b/src/layouts/default.vue
@@ -1,4 +1,32 @@
+
+
+
+
- 默认布局
-
+
+
+
+
+
+
+
diff --git a/src/layouts/tabbar.vue b/src/layouts/tabbar.vue
index b022b8a..b7a6af2 100644
--- a/src/layouts/tabbar.vue
+++ b/src/layouts/tabbar.vue
@@ -8,26 +8,79 @@
* 记得注释
-->
-
+
import { dayjs } from "wot-design-uni";
-import LogAPI, { VisitStatsVO } from "@/api/system/log";
+// 定义访问统计数据类型
+interface VisitStatsVO {
+ todayUvCount: number;
+ uvGrowthRate: number;
+ totalUvCount: number;
+ todayPvCount: number;
+ pvGrowthRate: number;
+ totalPvCount: number;
+}
const current = ref(0);
const visitStatsData = ref({
- todayUvCount: 0,
- uvGrowthRate: 0,
- totalUvCount: 0,
- todayPvCount: 0,
- pvGrowthRate: 0,
- totalPvCount: 0,
+ todayUvCount: 1234,
+ uvGrowthRate: 15.6,
+ totalUvCount: 45678,
+ todayPvCount: 5678,
+ pvGrowthRate: 23.4,
+ totalPvCount: 123456,
});
// 图表数据
@@ -163,6 +171,31 @@ const navList = reactive([
},
]);
+// 生成静态的访问趋势数据
+const generateStaticTrendData = (days: number) => {
+ const dates = [];
+ const ipList = [];
+ const pvList = [];
+
+ const today = new Date();
+
+ for (let i = days - 1; i >= 0; i--) {
+ const date = new Date(today);
+ date.setDate(today.getDate() - i);
+ dates.push(dayjs(date).format("MM-DD"));
+
+ // 生成模拟数据
+ ipList.push(Math.floor(Math.random() * 500) + 200);
+ pvList.push(Math.floor(Math.random() * 1000) + 500);
+ }
+
+ return {
+ dates,
+ ipList,
+ pvList,
+ };
+};
+
function handleClick(e: any) {
console.log(e);
}
@@ -170,25 +203,27 @@ function onChange(e: any) {
console.log(e);
}
-// 加载访问统计数据
+// 加载访问统计数据(使用静态数据)
const loadVisitStatsData = async () => {
- LogAPI.getVisitStats().then((data) => {
- visitStatsData.value = data;
- });
+ // 模拟异步加载
+ setTimeout(() => {
+ visitStatsData.value = {
+ todayUvCount: 1234,
+ uvGrowthRate: 15.6,
+ totalUvCount: 45678,
+ todayPvCount: 5678,
+ pvGrowthRate: 23.4,
+ totalPvCount: 123456,
+ };
+ }, 100);
};
-// 加载访问趋势数据
+// 加载访问趋势数据(使用静态数据)
const loadVisitTrendData = () => {
- const endDate = new Date();
- const startDate = new Date(endDate);
- startDate.setDate(endDate.getDate() - recentDaysRange.value + 1);
+ // 模拟异步加载
+ setTimeout(() => {
+ const data = generateStaticTrendData(recentDaysRange.value);
- const visitTrendQuery = {
- startDate: dayjs(startDate).format("YYYY-MM-DD"),
- endDate: dayjs(endDate).format("YYYY-MM-DD"),
- };
-
- LogAPI.getVisitTrend(visitTrendQuery).then((data) => {
const res = {
categories: data.dates,
series: [
@@ -203,7 +238,7 @@ const loadVisitTrendData = () => {
],
};
chartData.value = JSON.parse(JSON.stringify(res));
- });
+ }, 100);
};
// 数据范围变化
diff --git a/src/pages/login/complete-profile.vue b/src/pages/login/complete-profile.vue
index bcce91a..0a31770 100644
--- a/src/pages/login/complete-profile.vue
+++ b/src/pages/login/complete-profile.vue
@@ -115,7 +115,7 @@
import { ref, reactive, computed } from "vue";
import { onLoad } from "@dcloudio/uni-app";
import { useToast } from "wot-design-uni";
-import { useUserStore } from "@/store/modules/user";
+import { useUserStore } from "@/store/modules/user.store";
import UserAPI, { type UserProfileForm } from "@/api/user";
import FileAPI, { type FileInfo } from "@/api/file";
import WechatProfile from "@/components/WechatProfile.vue";
diff --git a/src/pages/login/index.vue b/src/pages/login/index.vue
index 348af18..6143f89 100644
--- a/src/pages/login/index.vue
+++ b/src/pages/login/index.vue
@@ -92,7 +92,7 @@
diff --git a/src/pages/mine/settings/theme/index.vue b/src/pages/mine/settings/theme/index.vue
index b43b26a..2b60615 100644
--- a/src/pages/mine/settings/theme/index.vue
+++ b/src/pages/mine/settings/theme/index.vue
@@ -114,12 +114,12 @@