From d5fb0075b2be00927c596a9525936faca98386d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E6=88=90?= Date: Thu, 9 Oct 2025 16:09:53 +0800 Subject: [PATCH] 1 --- build.bat | 76 --- build.sh | 65 -- demo-project/.gitignore | 28 - demo-project/CHANGELOG.md | 131 ---- demo-project/INSTALL.md | 164 ----- demo-project/PROJECT_STRUCTURE.md | 160 ----- demo-project/README.md | 292 --------- demo-project/README_FIRST.txt | 64 -- demo-project/README_使用打包框架.md | 270 -------- demo-project/Source_Map_说明.md | 222 ------- demo-project/Vuex错误修复说明.md | 399 ------------ demo-project/_doc/API直接导入重构说明.md | 372 ----------- .../_doc/authorityMenus接口失败解决方案.md | 314 ---------- demo-project/_doc/修复完成报告.md | 225 ------- demo-project/_doc/修复说明.md | 203 ------- demo-project/_doc/启动前必读.md | 115 ---- demo-project/_doc/如何启动.txt | 50 -- demo-project/_doc/快速配置组件映射.md | 143 ----- demo-project/_doc/文档更新说明.md | 362 ----------- demo-project/_doc/未登录接口调用问题修复.md | 387 ------------ demo-project/_doc/权限菜单组件配置指南.md | 575 ------------------ demo-project/_doc/权限菜单说明.md | 326 ---------- demo-project/_doc/登录功能修复说明.md | 277 --------- demo-project/_doc/登录功能完整修复报告.md | 386 ------------ demo-project/_doc/登录跳转首页修复说明.md | 412 ------------- demo-project/_doc/移除硬编码首页说明.md | 452 -------------- demo-project/_doc/组件映射修复总结.md | 233 ------- demo-project/_doc/组件映射说明.md | 339 ----------- demo-project/_doc/调试指南.md | 233 ------- demo-project/_doc/路由重复导航警告修复.md | 409 ------------- demo-project/_doc/路由重复导航错误完全修复.md | 483 --------------- demo-project/_doc/首页路由梳理说明.md | 427 ------------- demo-project/babel.config.js | 14 - demo-project/install.bat | 39 -- demo-project/package.json | 49 -- demo-project/public/index.html | 31 - demo-project/src/App.vue | 25 - demo-project/src/config/index.js | 23 - demo-project/src/main.js | 92 --- .../src/views/business/product_list.vue | 193 ------ demo-project/start.bat | 38 -- demo-project/start.sh | 34 -- demo-project/test-import.js | 9 - demo-project/webpack.config.js | 115 ---- demo-project/使用打包框架说明.md | 206 ------- demo-project/启动说明.md | 119 ---- demo-project/框架更新完成.md | 157 ----- demo-project/注释乱码修复说明.md | 175 ------ package-lock.json | 64 ++ package.json | 2 + postcss.config.js | 16 + 51 files changed, 82 insertions(+), 9913 deletions(-) delete mode 100644 build.bat delete mode 100644 build.sh delete mode 100644 demo-project/.gitignore delete mode 100644 demo-project/CHANGELOG.md delete mode 100644 demo-project/INSTALL.md delete mode 100644 demo-project/PROJECT_STRUCTURE.md delete mode 100644 demo-project/README.md delete mode 100644 demo-project/README_FIRST.txt delete mode 100644 demo-project/README_使用打包框架.md delete mode 100644 demo-project/Source_Map_说明.md delete mode 100644 demo-project/Vuex错误修复说明.md delete mode 100644 demo-project/_doc/API直接导入重构说明.md delete mode 100644 demo-project/_doc/authorityMenus接口失败解决方案.md delete mode 100644 demo-project/_doc/修复完成报告.md delete mode 100644 demo-project/_doc/修复说明.md delete mode 100644 demo-project/_doc/启动前必读.md delete mode 100644 demo-project/_doc/如何启动.txt delete mode 100644 demo-project/_doc/快速配置组件映射.md delete mode 100644 demo-project/_doc/文档更新说明.md delete mode 100644 demo-project/_doc/未登录接口调用问题修复.md delete mode 100644 demo-project/_doc/权限菜单组件配置指南.md delete mode 100644 demo-project/_doc/权限菜单说明.md delete mode 100644 demo-project/_doc/登录功能修复说明.md delete mode 100644 demo-project/_doc/登录功能完整修复报告.md delete mode 100644 demo-project/_doc/登录跳转首页修复说明.md delete mode 100644 demo-project/_doc/移除硬编码首页说明.md delete mode 100644 demo-project/_doc/组件映射修复总结.md delete mode 100644 demo-project/_doc/组件映射说明.md delete mode 100644 demo-project/_doc/调试指南.md delete mode 100644 demo-project/_doc/路由重复导航警告修复.md delete mode 100644 demo-project/_doc/路由重复导航错误完全修复.md delete mode 100644 demo-project/_doc/首页路由梳理说明.md delete mode 100644 demo-project/babel.config.js delete mode 100644 demo-project/install.bat delete mode 100644 demo-project/package.json delete mode 100644 demo-project/public/index.html delete mode 100644 demo-project/src/App.vue delete mode 100644 demo-project/src/config/index.js delete mode 100644 demo-project/src/main.js delete mode 100644 demo-project/src/views/business/product_list.vue delete mode 100644 demo-project/start.bat delete mode 100644 demo-project/start.sh delete mode 100644 demo-project/test-import.js delete mode 100644 demo-project/webpack.config.js delete mode 100644 demo-project/使用打包框架说明.md delete mode 100644 demo-project/启动说明.md delete mode 100644 demo-project/框架更新完成.md delete mode 100644 demo-project/注释乱码修复说明.md create mode 100644 postcss.config.js diff --git a/build.bat b/build.bat deleted file mode 100644 index 9f7edf6..0000000 --- a/build.bat +++ /dev/null @@ -1,76 +0,0 @@ -@echo off -chcp 65001 >nul -setlocal enabledelayedexpansion - -echo ================================ -echo Admin Framework 构建工具 -echo ================================ -echo. - -REM 检查 Node.js 是否安装 -where node >nul 2>nul -if %errorlevel% neq 0 ( - echo ❌ 错误: 未检测到 Node.js,请先安装 Node.js - pause - exit /b 1 -) - -for /f "tokens=*" %%i in ('node -v') do set NODE_VERSION=%%i -for /f "tokens=*" %%i in ('npm -v') do set NPM_VERSION=%%i - -echo ✅ Node.js 版本: %NODE_VERSION% -echo ✅ NPM 版本: %NPM_VERSION% -echo. - -REM 检查是否已安装依赖 -if not exist "node_modules" ( - echo 📦 正在安装依赖... - call npm install - if !errorlevel! neq 0 ( - echo ❌ 依赖安装失败 - pause - exit /b 1 - ) - echo ✅ 依赖安装成功 - echo. -) else ( - echo ✅ 依赖已安装 - echo. -) - -REM 执行打包 -echo 🔨 正在打包框架... -call npm run build - -if %errorlevel% equ 0 ( - echo. - echo ================================ - echo ✅ 打包成功! - echo ================================ - echo. - echo 📦 输出文件: dist\admin-framework.js - - REM 显示文件大小 - if exist "dist\admin-framework.js" ( - for %%A in (dist\admin-framework.js) do ( - set SIZE=%%~zA - set /a SIZE_KB=!SIZE! / 1024 - echo 📊 文件大小: !SIZE_KB! KB - ) - ) - - echo. - echo 📚 下一步: - echo 1. 将 dist\admin-framework.js 复制到你的项目 - echo 2. 查看 QUICK_START.md 了解如何使用 - echo 3. 查看 USAGE_EXAMPLE.md 了解详细示例 - echo. -) else ( - echo. - echo ❌ 打包失败,请检查错误信息 - pause - exit /b 1 -) - -pause - diff --git a/build.sh b/build.sh deleted file mode 100644 index 86d7a1d..0000000 --- a/build.sh +++ /dev/null @@ -1,65 +0,0 @@ -#!/bin/bash - -# Admin Framework 构建脚本 - -echo "================================" -echo " Admin Framework 构建工具" -echo "================================" -echo "" - -# 检查 Node.js 是否安装 -if ! command -v node &> /dev/null -then - echo "❌ 错误: 未检测到 Node.js,请先安装 Node.js" - exit 1 -fi - -echo "✅ Node.js 版本: $(node -v)" -echo "✅ NPM 版本: $(npm -v)" -echo "" - -# 检查是否已安装依赖 -if [ ! -d "node_modules" ]; then - echo "📦 正在安装依赖..." - npm install - if [ $? -ne 0 ]; then - echo "❌ 依赖安装失败" - exit 1 - fi - echo "✅ 依赖安装成功" - echo "" -else - echo "✅ 依赖已安装" - echo "" -fi - -# 执行打包 -echo "🔨 正在打包框架..." -npm run build - -if [ $? -eq 0 ]; then - echo "" - echo "================================" - echo " ✅ 打包成功!" - echo "================================" - echo "" - echo "📦 输出文件: dist/admin-framework.js" - - # 显示文件大小 - if [ -f "dist/admin-framework.js" ]; then - SIZE=$(du -h dist/admin-framework.js | cut -f1) - echo "📊 文件大小: $SIZE" - fi - - echo "" - echo "📚 下一步:" - echo " 1. 将 dist/admin-framework.js 复制到你的项目" - echo " 2. 查看 QUICK_START.md 了解如何使用" - echo " 3. 查看 USAGE_EXAMPLE.md 了解详细示例" - echo "" -else - echo "" - echo "❌ 打包失败,请检查错误信息" - exit 1 -fi - diff --git a/demo-project/.gitignore b/demo-project/.gitignore deleted file mode 100644 index cc49625..0000000 --- a/demo-project/.gitignore +++ /dev/null @@ -1,28 +0,0 @@ -# 依赖 -node_modules/ -package-lock.json -yarn.lock - -# 构建产物 -dist/ -*.log - -# 框架文件(从根目录复制过来的) -src/libs/admin-framework.js - -# 编辑器 -.vscode/ -.idea/ -*.swp -*.swo -*~ - -# 系统文件 -.DS_Store -Thumbs.db - -# 环境变量 -.env -.env.local -.env.*.local - diff --git a/demo-project/CHANGELOG.md b/demo-project/CHANGELOG.md deleted file mode 100644 index 7a2fb7b..0000000 --- a/demo-project/CHANGELOG.md +++ /dev/null @@ -1,131 +0,0 @@ -# Demo Project 更新日志 - -## [最新更新] - 2025-10-08 - -### ✅ 添加 Source Map 支持 - -**新增功能**: -- ✅ 完整的 Source Map 支持 -- ✅ 开发模式使用 `eval-source-map` -- ✅ 生产模式使用 `source-map` -- ✅ CSS/Less 也启用了 source map -- ✅ 创建了详细的调试指南 - -**好处**: -- 🐛 可以在浏览器中直接调试源码 -- 🔍 支持断点调试 -- 📍 精确定位到源码行和列 -- 🎯 可以调试框架源码和业务代码 - -**文档**: -- 新增 [调试指南.md](./调试指南.md) -- 更新 [README.md](./README.md) 添加调试说明 - ---- - -## [2025-10-08] - 修改为使用框架源码 - -**重要变更**: -- ✅ 现在直接使用框架源码而不是打包文件 -- ✅ 更方便调试和开发 -- ✅ 更新了 webpack 和 babel 配置 - -### 📦 需要重新安装依赖 - -由于添加了新的依赖,请重新安装: - -```bash -cd demo-project - -# 删除旧的依赖(可选) -rm -rf node_modules -rm package-lock.json - -# 重新安装 -npm install -``` - -### 🔄 主要更新内容 - -#### 1. main.js -```javascript -// 之前:使用打包文件 -import AdminFramework from './libs/admin-framework.js' - -// 现在:使用源码 -import AdminFramework from '../../src/index.js' -``` - -#### 2. webpack.config.js -添加了框架源码的路径别名: -```javascript -alias: { - '@': path.resolve(__dirname, 'src'), - '@component': path.resolve(__dirname, '../src/components'), - '@utils': path.resolve(__dirname, '../src/utils'), - '@api': path.resolve(__dirname, '../src/api'), - '@config': path.resolve(__dirname, '../src/config'), - '@assets': path.resolve(__dirname, '../src/assets') -} -``` - -#### 3. babel.config.js -添加了 JSX 支持: -```javascript -presets: [ - '@babel/preset-env', - '@vue/babel-preset-jsx' // ← 新增 -] -``` - -#### 4. package.json -新增依赖: -- `@vue/babel-preset-jsx` - JSX 支持 -- `brace` - 代码编辑器 -- `vue2-ace-editor` - Ace 编辑器 - -### 🚀 启动项目 - -```bash -# 安装依赖 -npm install - -# 启动开发服务器 -npm run dev -``` - -### ✅ 优势 - -使用框架源码的好处: - -1. **实时调试** - - 可以直接修改框架源码查看效果 - - 无需重新打包框架 - -2. **开发便利** - - 可以在框架源码中添加 console.log - - 方便追踪问题 - -3. **热更新** - - 修改框架代码后自动刷新 - - 开发体验更好 - -### ⚠️ 注意事项 - -1. **API 地址已更新** - - 从 `http://localhost:3000/api/` 改为 `http://localhost:9098/api/` - - 在 `src/config/index.js` 中修改 - -2. **首次启动** - - 需要运行 `npm install` 安装新依赖 - - Windows 用户可以双击 `start.bat` 自动安装 - -3. **如果遇到错误** - - 删除 `node_modules` 和 `package-lock.json` - - 重新运行 `npm install` - ---- - -**更新时间**: 2025-10-08 -**作者**: light - diff --git a/demo-project/INSTALL.md b/demo-project/INSTALL.md deleted file mode 100644 index 0ffe34a..0000000 --- a/demo-project/INSTALL.md +++ /dev/null @@ -1,164 +0,0 @@ -# Demo Project 安装指南 - -## 📦 安装步骤 - -### 步骤 1:复制框架文件 - -框架文件已经在创建 demo 时自动复制到 `src/libs/admin-framework.js`。 - -如果需要更新框架,执行: - -```bash -# 在 admin-framework 目录重新构建 -cd ../ -npm run build - -# 复制最新的框架文件 -cp dist/admin-framework.js demo-project/src/libs/ -``` - -### 步骤 2:安装依赖 - -```bash -cd demo-project -npm install -``` - -安装过程中会下载以下依赖: -- vue, vue-router, vuex -- view-design (UI 组件库) -- axios (HTTP 客户端) -- webpack 相关工具 - -### 步骤 3:启动项目 - -#### 开发模式 - -```bash -npm run dev -``` - -启动后自动打开浏览器访问 `http://localhost:8080` - -#### 生产构建 - -```bash -npm run build -``` - -构建完成后,产物在 `dist` 目录。 - -## 🎯 功能演示 - -### 1. 登录页面 - -访问:`http://localhost:8080/login` - -默认登录信息(示例): -- 用户名:admin -- 密码:123456 - -### 2. 主页 - -登录后自动跳转到主页:`http://localhost:8080/home` - -显示系统欢迎信息和标题。 - -### 3. 系统管理页面 - -框架内置的系统页面: -- `/system/user` - 用户管理 -- `/system/role` - 角色管理 -- `/system_high/menu` - 菜单管理 - -### 4. 业务示例页面 - -访问:`http://localhost:8080/business/product` - -查看产品列表示例(包含增删改查操作演示)。 - -## 🔧 开发提示 - -### 修改配置 - -编辑 `src/config/index.js`: - -```javascript -export default { - title: '你的系统名称', // 修改系统标题 - apiUrl: 'http://your-api.com/api/', // 修改 API 地址 - uploadUrl: 'http://your-api.com/api/upload' -} -``` - -### 添加新页面 - -1. 在 `src/views/business/` 创建新的 `.vue` 文件 -2. 在 `src/main.js` 中添加路由: - -```javascript -import NewPage from './views/business/new_page.vue' - -const businessRoutes = [ - { - path: '/business/newpage', - name: 'new_page', - component: NewPage - } -] -``` - -### 调用 API - -```javascript -// GET 请求 -const res = await this.$http.get('user/list', { page: 1 }) - -// POST 请求 -const res = await this.$http.post('user/add', { name: '张三' }) -``` - -### 使用 Store - -```javascript -// 获取用户信息 -const userName = this.$store.getters['user/userName'] - -// 获取系统配置 -const sysTitle = this.$store.getters['app/sysFormModel'] -``` - -## ⚠️ 常见问题 - -### Q1: 启动后页面空白? - -检查浏览器控制台错误,确保: -1. 框架文件已正确复制到 `src/libs/` -2. 依赖已完全安装 `npm install` - -### Q2: 接口请求失败? - -修改 `src/config/index.js` 中的 `apiUrl` 为正确的后端地址。 - -### Q3: 样式显示异常? - -确保已引入 ViewUI 样式: -```javascript -import 'view-design/dist/styles/iview.css' -``` - -## 📚 更多帮助 - -- 查看完整框架文档:`../完整使用文档.md` -- 框架 API 文档:`../完整使用文档.md#api-文档` - -## 🎉 开始开发 - -所有准备工作已完成,现在可以开始开发了! - -```bash -npm run dev -``` - -祝开发愉快!🚀 - diff --git a/demo-project/PROJECT_STRUCTURE.md b/demo-project/PROJECT_STRUCTURE.md deleted file mode 100644 index f1ff581..0000000 --- a/demo-project/PROJECT_STRUCTURE.md +++ /dev/null @@ -1,160 +0,0 @@ -# Demo Project 项目结构说明 - -## 📁 完整目录树 - -``` -demo-project/ -│ -├── 📄 package.json # 项目依赖配置 -├── 📄 webpack.config.js # Webpack 构建配置 -├── 📄 babel.config.js # Babel 编译配置 -├── 📄 .gitignore # Git 忽略文件 -│ -├── 📄 README.md # 项目说明文档 -├── 📄 INSTALL.md # 安装指南 -├── 📄 PROJECT_STRUCTURE.md # 本文件 - 项目结构说明 -│ -├── 🚀 start.bat # Windows 快速启动脚本 -├── 🚀 start.sh # Linux/Mac 快速启动脚本 -│ -├── 📂 public/ # 静态资源 -│ └── index.html # HTML 模板 -│ -└── 📂 src/ # 源代码目录 - │ - ├── 📄 main.js # 入口文件 ⭐ - ├── 📄 App.vue # 根组件 - │ - ├── 📂 config/ # 配置文件 - │ └── index.js # 项目配置(API 地址、系统标题等) - │ - ├── 📂 libs/ # 第三方库 - │ └── admin-framework.js # Admin Framework 框架文件 - │ - └── 📂 views/ # 页面组件 - └── business/ # 业务页面 - └── product_list.vue # 产品列表示例页面 -``` - -## 📝 核心文件说明 - -### 1. 入口文件 `src/main.js` -```javascript -// 项目启动入口 -// 1. 引入框架 -// 2. 配置 Vue 实例 -// 3. 挂载应用 -``` - -**主要功能**: -- ✅ 引入并初始化 AdminFramework -- ✅ 配置 Router 和 Store -- ✅ 添加自定义业务路由 -- ✅ 设置响应式适配 - -### 2. 配置文件 `src/config/index.js` -```javascript -export default { - title: 'Demo 管理系统', - apiUrl: 'http://localhost:3000/api/', - uploadUrl: 'http://localhost:3000/api/upload', - tokenKey: 'demo_token' -} -``` - -**说明**: -- 系统标题、API 地址等配置 -- 可根据环境切换配置 - -### 3. 框架文件 `src/libs/admin-framework.js` -- 从 `admin-framework/dist/` 复制的打包文件 -- 包含所有框架功能(页面、组件、工具等) -- 大小:约 1.64 MB - -### 4. 业务页面 `src/views/business/product_list.vue` -- 完整的 CRUD 示例 -- 展示如何使用框架的组件和工具 -- 包含 Table、Modal、Message 等组件使用 - -## 🔧 配置文件说明 - -### webpack.config.js -- 入口:`src/main.js` -- 输出:`dist/bundle.[hash].js` -- 开发服务器:`localhost:8080` -- 支持 Vue、Less、图片等文件处理 - -### package.json -**主要依赖**: -- `vue` - Vue 框架 -- `vue-router` - 路由管理 -- `vuex` - 状态管理 -- `view-design` - UI 组件库 -- `axios` - HTTP 客户端 - -**开发依赖**: -- `webpack` - 打包工具 -- `babel` - JS 编译 -- `vue-loader` - Vue 文件加载器 - -## 📂 扩展目录说明 - -随着项目发展,可以添加以下目录: - -``` -src/ -├── api/ # API 接口封装 -│ └── business/ -│ └── product.js -│ -├── assets/ # 业务资源文件 -│ ├── images/ # 图片 -│ └── styles/ # 样式 -│ -├── components/ # 业务组件 -│ └── CustomTable.vue -│ -├── router/ # 路由配置 -│ └── index.js -│ -└── store/ # 业务状态管理 - └── modules/ - └── product.js -``` - -## 🚀 启动流程 - -1. **执行** `start.bat` 或 `npm run dev` -2. **Webpack** 读取 `webpack.config.js` -3. **入口** 加载 `src/main.js` -4. **初始化** AdminFramework -5. **创建** Vue 实例 -6. **挂载** 到 `#app` -7. **启动** 开发服务器 -8. **打开** 浏览器 `http://localhost:8080` - -## 📊 文件大小参考 - -| 文件 | 大小 | 说明 | -|------|------|------| -| admin-framework.js | ~1.64 MB | 框架打包文件 | -| main.js | ~2 KB | 入口文件 | -| App.vue | ~0.5 KB | 根组件 | -| product_list.vue | ~4 KB | 业务示例 | -| bundle.js(开发) | ~3 MB | 包含所有依赖 | -| bundle.js(生产) | ~500 KB | 压缩后 | - -## 🎯 下一步 - -1. **修改配置**:编辑 `src/config/index.js` -2. **添加页面**:在 `src/views/business/` 创建新页面 -3. **注册路由**:在 `src/main.js` 添加路由配置 -4. **开始开发**:基于框架快速开发业务功能 - ---- - -**查看更多**: -- [README.md](./README.md) - 项目概述 -- [INSTALL.md](./INSTALL.md) - 安装指南 -- [../完整使用文档.md](../完整使用文档.md) - 框架完整文档 - diff --git a/demo-project/README.md b/demo-project/README.md deleted file mode 100644 index fcd5c9e..0000000 --- a/demo-project/README.md +++ /dev/null @@ -1,292 +0,0 @@ -# Demo Project - Admin Framework 使用示例 - -这是一个使用 **Admin Framework** 框架的完整示例项目。 - -## 📁 项目结构 - -``` -demo-project/ -├── public/ -│ └── index.html # HTML 模板 -├── src/ -│ ├── config/ -│ │ └── index.js # 配置文件 -│ ├── libs/ -│ │ └── admin-framework.js # 框架文件(从 dist 复制) -│ ├── views/ -│ │ └── business/ -│ │ └── product_list.vue # 示例业务页面 -│ ├── App.vue # 根组件 -│ └── main.js # 入口文件 -├── babel.config.js -├── package.json -├── webpack.config.js -└── README.md -``` - -## ⚠️ 重要说明 - -**本项目已更新为直接使用框架源码**(不再使用打包文件),更方便调试! - -**✅ 已启用完整的 Source Map 支持**,可以在浏览器中直接调试源码! - -**首次运行或更新后,请先安装依赖**: -```bash -npm install -``` - -如果遇到问题,删除 `node_modules` 和 `package-lock.json` 后重新安装。 - ---- - -## 🚀 快速开始 - -### 方式一:一键启动(推荐) - -#### Windows 用户 -双击运行 `start.bat`,会自动: -1. 检查并安装依赖 -2. 启动开发服务器 -3. 自动打开浏览器 - -#### Linux/Mac 用户 -```bash -chmod +x start.sh -./start.sh -``` - -### 方式二:手动启动 - -```bash -# 1. 安装依赖(首次运行必须) -npm install - -# 2. 启动开发服务器 -npm run dev -``` - -### ~~ 方式三:复制框架文件(已废弃)~~ - -### 1. 使用源码(当前方式) - -将框架打包文件复制到项目中: - -```bash -# 在 admin-framework 目录执行构建 -cd admin-framework -npm run build - -# 创建 libs 目录 -mkdir demo-project/src/libs - -# 复制打包文件 -cp dist/admin-framework.js demo-project/src/libs/ -``` - -### 2. 安装依赖 - -```bash -cd demo-project -npm install -``` - -### 3. 启动开发服务器 - -```bash -npm run dev -``` - -浏览器会自动打开 `http://localhost:8080` - -### 4. 构建生产版本 - -```bash -npm run build -``` - -生成的文件在 `dist` 目录中。 - -## 📝 核心文件说明 - -### main.js - 入口文件 - -```javascript -import AdminFramework from './libs/admin-framework.js' -import config from './config' - -// 使用框架 -Vue.use(AdminFramework, { - config, - ViewUI, - VueRouter, - Vuex, - createPersistedState -}) - -// 创建 Vue 实例 -new Vue({ - router: AdminFramework.router, - store: AdminFramework.store, - render: h => h(App) -}).$mount('#app') -``` - -### config/index.js - 配置文件 - -```javascript -export default { - title: 'Demo 管理系统', - apiUrl: 'http://localhost:3000/api/', - uploadUrl: 'http://localhost:3000/api/upload', - tokenKey: 'demo_token' -} -``` - -### 业务页面示例 - -`src/views/business/product_list.vue` 展示了如何: -- 使用 ViewUI 组件(Table、Button、Modal 等) -- 调用 API 接口(this.$http) -- 使用框架提供的工具方法 - -## 🎯 框架提供的功能 - -### 1. 内置页面 - -- ✅ **主页**(HomePage)- 欢迎页面 -- ✅ **系统页面**(SysUser、SysRole、SysMenu 等) -- ✅ **登录页面**(LoginPage) -- ✅ **错误页面**(401、404、500) - -### 2. 布局组件 - -- ✅ **Main** - 主布局 -- ✅ **ParentView** - 父级视图 - -### 3. 工具方法 - -```javascript -// HTTP 请求 -this.$http.get(url, params) -this.$http.post(url, data) - -// 工具函数 -this.$tools.formatDate(date, format) -this.$tools.setToken(token) -this.$tools.getToken() - -// UI 工具 -this.$uiTool.delConfirm(callback) -this.$uiTool.setRem() -``` - -### 4. Store 状态管理 - -```javascript -// 用户模块 -this.$store.dispatch('user/handleLogin', data) -this.$store.dispatch('user/handleLogOut') -this.$store.getters['user/userName'] - -// 应用模块 -this.$store.dispatch('app/getSysTitle', { defaultTitle: '系统' }) -this.$store.getters['app/sysFormModel'] -``` - -## 🐛 调试功能 - -### Source Map 已启用 - -项目已配置完整的 Source Map 支持: - -✅ **开发模式**:使用 `eval-source-map` -- 高质量的源码映射 -- 可以在浏览器中看到原始源代码 -- 支持断点调试 -- 包含行和列信息 - -✅ **生产模式**:使用 `source-map` -- 生成独立的 .map 文件 -- 完整的源码信息 - -### 如何调试 - -1. **启动开发服务器**: - ```bash - npm run dev - ``` - -2. **打开浏览器开发者工具**(F12) - -3. **在 Sources 标签页查看源码**: - ``` - webpack:// - ├── demo-project/src/ ← Demo 项目源码 - └── src/ ← 框架源码(可直接调试) - ``` - -4. **设置断点调试**: - - 点击行号设置断点 - - 或在代码中添加 `debugger` 语句 - -### 详细调试指南 - -查看完整调试教程:**[调试指南.md](./调试指南.md)** 📚 - -包含: -- Source Map 配置说明 -- 浏览器调试技巧 -- 框架源码调试方法 -- Vue DevTools 使用 -- Console 调试技巧 - -## 🔧 自定义开发 - -### 添加业务路由 - -在 `main.js` 中添加自定义路由: - -```javascript -const businessRoutes = [ - { - path: '/business/product', - name: 'product_list', - component: ProductList - } -] - -// 添加到主路由 -const mainRoute = AdminFramework.router.options.routes.find(r => r.path === '/') -mainRoute.children.push(...businessRoutes) -``` - -### 使用系统页面 - -```javascript -import { SysUser, SysRole } from './libs/admin-framework.js' - -// 或者直接使用 -const SysUser = AdminFramework.SysUser -``` - -## 📚 更多文档 - -查看完整文档:`admin-framework/完整使用文档.md` - -## 💡 提示 - -1. **框架文件**:确保将最新的 `admin-framework.js` 复制到 `src/libs/` 目录 -2. **ViewUI 样式**:已在 main.js 中引入 `view-design/dist/styles/iview.css` -3. **API 配置**:修改 `config/index.js` 中的 `apiUrl` 为你的后端地址 -4. **登录功能**:访问 `/login` 可以看到登录页面 - -## 🎉 开始开发 - -现在你可以: -1. 访问 `http://localhost:8080/login` 查看登录页面 -2. 访问 `http://localhost:8080/home` 查看主页 -3. 访问 `http://localhost:8080/business/product` 查看业务页面示例 -4. 开始开发你的业务页面! - -祝开发愉快! 🚀 - diff --git a/demo-project/README_FIRST.txt b/demo-project/README_FIRST.txt deleted file mode 100644 index b0b0813..0000000 --- a/demo-project/README_FIRST.txt +++ /dev/null @@ -1,64 +0,0 @@ -===================================================== - ⭐ 首次运行必读 ⭐ -===================================================== - -Demo 项目已更新为使用框架源码(更方便调试)! - -【第一步:安装依赖】 - -Windows 用户(推荐): - 双击运行 install.bat - -或者手动运行: - npm install - -【第二步:启动项目】 - -Windows 用户: - 双击运行 start.bat - -或者手动运行: - npm run dev - -【验证安装成功】 - -运行以下命令检查依赖: - npm list --depth=0 - -应该看到(无 UNMET DEPENDENCY 错误): - ✅ @vue/babel-preset-jsx - ✅ brace - ✅ vue2-ace-editor - ✅ 其他依赖... - -【访问地址】 - -http://localhost:8080 - -可用页面: - /login - 登录页面 - /home - 主页 - /business/product - 产品列表示例 - -【遇到错误?】 - -1. 依赖缺失: - npm install @vue/babel-preset-jsx brace vue2-ace-editor - -2. 端口占用: - 修改 webpack.config.js 中的 port: 8081 - -3. 删除重装: - rm -rf node_modules package-lock.json - npm install - -【详细文档】 - -- 启动前必读.md - 完整启动指南 -- CHANGELOG.md - 更新日志 -- README.md - 项目说明 - -===================================================== - 准备好了?运行 install.bat 开始吧! -===================================================== - diff --git a/demo-project/README_使用打包框架.md b/demo-project/README_使用打包框架.md deleted file mode 100644 index 60437b6..0000000 --- a/demo-project/README_使用打包框架.md +++ /dev/null @@ -1,270 +0,0 @@ -# Demo 项目 - 使用打包框架 - -## 📦 项目说明 - -这是一个使用 Admin Framework 打包版本的演示项目。 - -## ✅ 已完成的配置 - -### 1. 框架引用方式 - -**文件**:`src/main.js` - -```javascript -// 使用打包好的框架 -import AdminFramework from './libs/admin-framework.js' -``` - -### 2. 文件结构 - -``` -demo-project/ -├── src/ -│ ├── libs/ -│ │ └── admin-framework.js ← 打包好的框架(从 ../../dist/ 复制) -│ ├── main.js ← 引用框架 -│ ├── App.vue -│ ├── config/ -│ ├── views/ -│ └── ... -├── public/ -├── package.json -└── webpack.config.js -``` - -### 3. .gitignore 配置 - -``` -# 框架文件(从根目录复制过来的) -src/libs/admin-framework.js -``` - -## 🚀 快速开始 - -### 1. 确保框架文件存在 - -检查 `src/libs/admin-framework.js` 是否存在。 - -如果不存在,在**项目根目录**(不是 demo-project)执行: - -```powershell -# 打包框架 -npm run build - -# 复制到 demo 项目 -Copy-Item "dist\admin-framework.js" "demo-project\src\libs\admin-framework.js" -Force -``` - -### 2. 安装依赖(首次运行) - -```bash -cd demo-project -npm install -``` - -### 3. 启动开发服务器 - -```bash -npm run dev -``` - -### 4. 访问应用 - -打开浏览器访问:http://localhost:8080 - -**测试账号**: -- 用户名:admin -- 密码:admin123 - -## 🔄 更新框架 - -当框架源码(`../../src/`)有更新时: - -### 快速更新(推荐) - -在**项目根目录**执行: - -```powershell -# 一键打包并复制 -npm run build; Copy-Item "dist\admin-framework.js" "demo-project\src\libs\admin-framework.js" -Force; Write-Host "✅ 框架已更新!" -ForegroundColor Green -``` - -### 分步操作 - -```bash -# 1. 在项目根目录打包框架 -npm run build - -# 2. 复制到 demo 项目(PowerShell) -Copy-Item "dist\admin-framework.js" "demo-project\src\libs\admin-framework.js" -Force - -# 3. 重启 demo 项目(如果正在运行) -cd demo-project -npm run dev -``` - -## 📊 优势对比 - -### 使用打包框架(当前方式) - -**优点**: -- ✅ 性能更好(打包优化) -- ✅ 更接近生产环境 -- ✅ 依赖隔离 -- ✅ 边界清晰 - -**缺点**: -- ❌ 修改框架后需要重新打包 -- ❌ 调试稍微不便 - -### 使用源码引用(开发调试) - -**优点**: -- ✅ 实时更新 -- ✅ 调试方便 - -**缺点**: -- ❌ 性能较差 -- ❌ 需要安装框架的所有依赖 - -## 🔧 开发建议 - -### 调试框架时 - -临时修改 `src/main.js`: - -```javascript -// 临时改为源码引用 -import AdminFramework from '../../src/index.js' -``` - -**注意**:调试完成后记得改回来! - -### 测试框架时 - -使用打包文件(当前配置): - -```javascript -// 使用打包文件 -import AdminFramework from './libs/admin-framework.js' -``` - -## 📝 组件映射配置 - -在 `src/main.js` 中配置业务组件映射: - -```javascript -Vue.use(AdminFramework, { - config, - ViewUI, - VueRouter, - Vuex, - createPersistedState, - // 业务组件映射 - componentMap: { - 'business/product_list': ProductList, - // 添加更多业务组件... - } -}) -``` - -## 🔍 故障排查 - -### 问题 1:找不到 admin-framework.js - -**错误**: -``` -Module not found: Error: Can't resolve './libs/admin-framework.js' -``` - -**解决**: -```powershell -# 在项目根目录 -Copy-Item "dist\admin-framework.js" "demo-project\src\libs\admin-framework.js" -Force -``` - -### 问题 2:修改框架源码后没有变化 - -**原因**:使用的是打包文件,不会自动更新 - -**解决**: -```powershell -# 重新打包并复制 -npm run build -Copy-Item "dist\admin-framework.js" "demo-project\src\libs\admin-framework.js" -Force -``` - -### 问题 3:控制台报错 - -**检查步骤**: -1. 确保框架已正确打包 -2. 确保文件已复制到正确位置 -3. 查看浏览器控制台的详细错误 -4. 检查 `src/main.js` 的引用路径 - -### 问题 4:端口被占用 - -**错误**: -``` -Error: listen EADDRINUSE: address already in use :::8080 -``` - -**解决**: -1. 关闭占用 8080 端口的程序 -2. 或修改 `webpack.config.js` 中的端口 - -## 📚 相关文档 - -- `使用打包框架说明.md` - 详细使用说明 -- `框架更新完成.md` - 更新记录 -- `启动说明.md` - 启动步骤 -- `../../完整使用文档.md` - 框架完整文档 - -## 🎯 项目结构 - -``` -demo-project/ -├── src/ -│ ├── libs/ -│ │ └── admin-framework.js # 打包好的框架 -│ ├── main.js # 入口文件 -│ ├── App.vue # 根组件 -│ ├── config/ -│ │ ├── index.js # 配置文件 -│ │ └── menuConfig.js # 菜单配置 -│ ├── views/ -│ │ ├── business/ # 业务页面 -│ │ └── home/ # 首页 -│ └── ... -├── public/ -│ └── index.html -├── package.json -├── webpack.config.js -├── babel.config.js -└── README.md -``` - -## 🌟 特性 - -- ✅ 基于 Vue 2.x -- ✅ 使用 ViewUI 组件库 -- ✅ 动态路由和权限管理 -- ✅ Vuex 状态管理 -- ✅ 响应式布局 -- ✅ 热更新开发 - -## 📞 支持 - -如有问题,请查看: -1. 浏览器控制台错误信息 -2. 终端编译错误信息 -3. 相关文档 - ---- - -**框架版本**:1.0.0 - -**Node.js 版本要求**:>= 14.0.0 - -**当前状态**:✅ 就绪 - diff --git a/demo-project/Source_Map_说明.md b/demo-project/Source_Map_说明.md deleted file mode 100644 index 49ef8d2..0000000 --- a/demo-project/Source_Map_说明.md +++ /dev/null @@ -1,222 +0,0 @@ -# Source Map 配置说明 - -## ✅ 已完成配置 - -Demo 项目现在已经配置了完整的 Source Map 支持! - -### 📝 配置内容 - -#### 1. Webpack 配置(`webpack.config.js`) - -```javascript -module.exports = (env, argv) => { - const isDevelopment = argv.mode === 'development' - - return { - // Source Map 配置 - devtool: isDevelopment ? 'eval-source-map' : 'source-map', - - // CSS/Less Source Map - module: { - rules: [ - { - test: /\.css$/, - use: [ - 'vue-style-loader', - { - loader: 'css-loader', - options: { sourceMap: isDevelopment } - } - ] - }, - { - test: /\.less$/, - use: [ - 'vue-style-loader', - { - loader: 'css-loader', - options: { sourceMap: isDevelopment } - }, - { - loader: 'less-loader', - options: { sourceMap: isDevelopment } - } - ] - } - ] - } - } -} -``` - -#### 2. DevServer 配置 - -```javascript -devServer: { - port: 8080, - hot: true, - open: true, - historyApiFallback: true, - // 错误覆盖层 - client: { - overlay: { - errors: true, // 显示错误 - warnings: false // 不显示警告 - } - } -} -``` - -### 🎯 Source Map 类型 - -#### 开发模式:`eval-source-map` - -**优点**: -- ✅ 高质量的源码映射 -- ✅ 包含行和列信息 -- ✅ 重新构建速度快 -- ✅ 适合开发调试 - -**缺点**: -- ❌ 生成的文件较大 -- ❌ 不适合生产环境 - -#### 生产模式:`source-map` - -**优点**: -- ✅ 最高质量的源码映射 -- ✅ 生成独立的 .map 文件 -- ✅ 不影响主文件加载 - -**缺点**: -- ❌ 构建速度慢 -- ❌ 文件体积大 - -### 🔍 调试效果 - -启动开发服务器后,在浏览器开发者工具中可以看到: - -``` -webpack:// -├── demo-project/ -│ └── src/ -│ ├── main.js ← 可以看到原始源码 -│ ├── App.vue -│ ├── config/ -│ │ └── index.js -│ └── views/ -│ └── business/ -│ └── product_list.vue -│ -└── src/ ← 框架源码 - ├── index.js - ├── components/ - │ ├── main/ - │ └── ... - ├── views/ - │ ├── login/ - │ ├── home/ - │ └── ... - ├── store/ - │ ├── user.js - │ └── app.js - └── utils/ - ├── http.js - ├── tools.js - └── uiTool.js -``` - -### 💡 使用方法 - -#### 1. 设置断点 - -在浏览器开发者工具的 Sources 面板: -1. 找到要调试的源文件 -2. 点击行号设置断点 -3. 刷新页面触发断点 - -#### 2. 使用 debugger - -在代码中直接添加: -```javascript -export default { - mounted() { - debugger // ← 程序会在这里暂停 - console.log('组件已挂载') - } -} -``` - -#### 3. Console 调试 - -```javascript -// 在 Console 中执行 -$vm.$store.state // 查看 Vuex 状态 -$vm.$route // 查看路由信息 -$vm.$root // 查看根实例 -``` - -### 📊 对比 - -| 功能 | 有 Source Map | 无 Source Map | -|------|--------------|---------------| -| 看到的代码 | 原始源码 | 编译后的代码 | -| 断点位置 | 精确到源码行列 | 只能在编译后代码设置 | -| 变量名 | 原始变量名 | 可能被压缩 | -| 调试体验 | ⭐⭐⭐⭐⭐ | ⭐⭐ | - -### ⚠️ 注意事项 - -#### 1. 文件大小 - -开发模式的 bundle 会包含 source map 信息,体积较大: -- 开发环境:约 3-5 MB(包含 source map) -- 生产环境:约 500 KB(压缩后,.map 文件独立) - -#### 2. 性能影响 - -- **开发环境**:首次构建较慢,热更新很快 -- **生产环境**:构建时间增加,但运行时无影响 - -#### 3. 安全性 - -生产环境的 .map 文件: -- 不要部署到公开的服务器 -- 或配置服务器禁止访问 .map 文件 -- 或使用错误追踪服务(如 Sentry)管理 source map - -### 🚀 快速开始 - -1. **启动开发服务器**: - ```bash - npm run dev - ``` - -2. **打开浏览器**: - 访问 `http://localhost:8080` - -3. **打开开发者工具**: - 按 `F12` - -4. **查看源码**: - 在 Sources 标签页中可以看到完整的源码结构 - -5. **设置断点调试**: - 点击行号或在代码中添加 `debugger` - -### 📚 相关文档 - -- **[调试指南.md](./调试指南.md)** - 完整的调试教程 -- **[README.md](./README.md)** - 项目说明 -- **[CHANGELOG.md](./CHANGELOG.md)** - 更新日志 - -### 🔗 参考资源 - -- [Webpack DevTool 文档](https://webpack.js.org/configuration/devtool/) -- [Chrome DevTools](https://developer.chrome.com/docs/devtools/) -- [Vue DevTools](https://devtools.vuejs.org/) - ---- - -**现在你可以愉快地调试代码了!** 🎉 - diff --git a/demo-project/Vuex错误修复说明.md b/demo-project/Vuex错误修复说明.md deleted file mode 100644 index 330b908..0000000 --- a/demo-project/Vuex错误修复说明.md +++ /dev/null @@ -1,399 +0,0 @@ -# Vuex 错误修复说明 - -## 🔍 问题描述 - -控制台出现多个 Vuex 相关错误: - -1. `[vuex] unknown action type: getSysTitle` -2. `[vuex] unknown getter: isServerRun` -3. `[vuex] unknown getter: infoMsg` -4. `Unknown custom element: ` - -## 📝 修复内容 - -### 1. 修复 `getSysTitle` action 错误 - -**问题位置**:`src/components/main/main.vue` - -**错误原因**: -- 在 `created` 钩子中调用了 `this.$store.dispatch('getSysTitle')` -- 缺少模块命名空间前缀 `app/` -- 且在 `demo-project/src/main.js` 中已经调用过,不需要重复调用 - -**修改前**: -```javascript -created() { - this.init() -}, -methods: { - async init() { - await this.$store.dispatch('getSysTitle') // ❌ 错误 - }, -} -``` - -**修改后**: -```javascript -created() { - this.init() -}, -methods: { - async init() { - // 获取系统标题(已在 main.js 中调用,这里不需要重复调用) - // await this.$store.dispatch('app/getSysTitle') - }, -} -``` - -**说明**: -- ✅ 移除了重复的 `getSysTitle` 调用 -- ✅ 系统标题在 `demo-project/src/main.js` 的 `mounted` 钩子中统一获取 -- ✅ 避免了重复请求 - -### 2. 修复 `isServerRun` getter 错误 - -**问题位置**:`src/components/main/components/terminal/index.vue` - -**错误原因**: -- 使用了不存在的 `isServerRun` getter -- 这是 Terminal 功能相关的状态,但 store 中没有定义 - -**修改前**: -```javascript -computed: { - ...mapGetters({ - isServerRun: 'isServerRun' // ❌ 不存在的 getter - }), - iconclass() { - let curClass = 'terminal-icon ml10 ' - if (this.isServerRun) { - curClass += ' run' - } - return curClass - } -}, -``` - -**修改后**: -```javascript -computed: { - iconclass() { - let curClass = 'terminal-icon ml10' - // Terminal 功能暂时禁用 - // if (this.isServerRun) { - // curClass += ' run' - // } - return curClass - } -}, -``` - -**说明**: -- ✅ 移除了对不存在的 `isServerRun` getter 的依赖 -- ✅ Terminal 功能暂时禁用 -- ✅ 如果需要启用,需要在 store 中添加相应的 state 和 getter - -### 3. 修复 `infoMsg` getter 错误 - -**问题位置**:`src/components/main/components/terminal/terminal.vue` - -**错误原因**: -- 使用了不存在的 `infoMsg` getter -- 调用了不存在的 `clearInfoMsg` mutation 和 `setInteverLog` action - -**修改前**: -```javascript -computed: { - ...mapGetters({ - infoMsg: 'infoMsg' // ❌ 不存在的 getter - }) -}, -methods: { - clearLog() { - this.$store.commit('clearInfoMsg') // ❌ 不存在的 mutation - }, - reloadLog() { - this.$store.dispatch('setInteverLog') // ❌ 不存在的 action - }, -} -``` - -**修改后**: -```javascript -computed: { - infoMsg() { - // Terminal 功能暂时禁用 - return '终端功能暂未启用' - } -}, -methods: { - clearLog() { - // Terminal 功能暂时禁用 - this.$Message.info('终端功能暂未启用') - }, - reloadLog() { - // Terminal 功能暂时禁用 - this.$Message.info('终端功能暂未启用') - }, -} -``` - -**说明**: -- ✅ 移除了对不存在的 Vuex 状态的依赖 -- ✅ 提供了友好的提示信息 -- ✅ 避免了运行时错误 - -### 4. 修复 `asyncModal` 组件未注册错误 - -**问题位置**:`src/components/main/components/terminal/index.vue` - -**错误原因**: -- 模板中使用了 `` 组件 -- 但没有在 `components` 中注册 - -**修改前**: -```javascript -import { mapGetters } from 'vuex' -import Terminal from './terminal.vue' -export default { - components: { - Terminal // ❌ 缺少 asyncModal - }, -} -``` - -**修改后**: -```javascript -import Terminal from './terminal.vue' -import asyncModal from '@/components/asyncModal' -export default { - components: { - Terminal, - asyncModal // ✅ 添加 asyncModal 组件 - }, -} -``` - -**说明**: -- ✅ 导入了 `asyncModal` 组件 -- ✅ 在 `components` 中注册 -- ✅ 移除了不需要的 `mapGetters` 导入 - -## 📊 修复总结 - -### 修改的文件 - -1. **`src/components/main/main.vue`** - - 移除了重复的 `getSysTitle` 调用 - -2. **`src/components/main/components/terminal/index.vue`** - - 移除了 `isServerRun` getter 的使用 - - 添加了 `asyncModal` 组件注册 - -3. **`src/components/main/components/terminal/terminal.vue`** - - 移除了 `infoMsg` getter 的使用 - - 修改了 `clearLog` 和 `reloadLog` 方法 - -### 错误修复 - -- ✅ `[vuex] unknown action type: getSysTitle` - 已修复 -- ✅ `[vuex] unknown getter: isServerRun` - 已修复 -- ✅ `[vuex] unknown getter: infoMsg` - 已修复 -- ✅ `Unknown custom element: ` - 已修复 - -## 💡 Terminal 功能说明 - -### 当前状态 - -Terminal 功能已**暂时禁用**,因为: -- 缺少相关的 Vuex store 配置 -- 缺少后端接口支持 -- 不影响系统核心功能 - -### 如何启用 Terminal 功能 - -如果需要启用 Terminal 功能,需要: - -**1. 在 Vuex store 中添加 Terminal 模块** - -创建 `src/store/terminal.js`: -```javascript -export default { - namespaced: true, - state: { - isServerRun: false, - infoMsg: '' - }, - getters: { - isServerRun: state => state.isServerRun, - infoMsg: state => state.infoMsg - }, - mutations: { - setServerRun(state, value) { - state.isServerRun = value - }, - setInfoMsg(state, msg) { - state.infoMsg += msg + '\n' - }, - clearInfoMsg(state) { - state.infoMsg = '' - } - }, - actions: { - async setInteverLog({ commit }) { - // 实现日志加载逻辑 - } - } -} -``` - -**2. 在 `src/store/index.js` 中注册模块** - -```javascript -import terminal from './terminal' - -export default new Vuex.Store({ - modules: { - user, - app, - terminal // 添加 terminal 模块 - } -}) -``` - -**3. 更新组件代码** - -`src/components/main/components/terminal/index.vue`: -```javascript -computed: { - ...mapGetters('terminal', { - isServerRun: 'isServerRun' - }), - iconclass() { - let curClass = 'terminal-icon ml10 ' - if (this.isServerRun) { - curClass += ' run' - } - return curClass - } -} -``` - -`src/components/main/components/terminal/terminal.vue`: -```javascript -computed: { - ...mapGetters('terminal', { - infoMsg: 'infoMsg' - }) -}, -methods: { - clearLog() { - this.$store.commit('terminal/clearInfoMsg') - }, - reloadLog() { - this.$store.dispatch('terminal/setInteverLog') - } -} -``` - -## ⚠️ 注意事项 - -### 1. 系统标题获取时机 - -系统标题在 `demo-project/src/main.js` 的 `mounted` 钩子中获取: - -```javascript -mounted() { - AdminFramework.uiTool.setRem() - - // 只在已登录时获取系统标题 - const token = this.$store.state.user.token - if (token) { - this.$store.dispatch('app/getSysTitle', { - defaultTitle: 'Demo 管理系统', - defaultLogo: '' - }) - } else { - document.title = 'Demo 管理系统' - } -} -``` - -**不要在其他地方重复调用**,避免: -- 重复的 HTTP 请求 -- 不必要的性能开销 -- 可能的竞态条件 - -### 2. Vuex 模块命名空间 - -所有 Vuex 模块都使用了 `namespaced: true`: - -```javascript -// ✅ 正确的调用方式 -this.$store.dispatch('app/getSysTitle') -this.$store.commit('user/setToken', token) -this.$store.getters['user/userName'] - -// ❌ 错误的调用方式 -this.$store.dispatch('getSysTitle') -this.$store.commit('setToken', token) -this.$store.getters['userName'] -``` - -**使用 mapGetters/mapActions 时**: -```javascript -// ✅ 正确 -...mapGetters('app', ['sysFormModel']) -...mapActions('user', ['handleLogin']) - -// 或者 -...mapGetters({ - sysFormModel: 'app/sysFormModel' -}) -``` - -### 3. 组件注册 - -使用第三方组件或自定义组件时,必须: -1. 导入组件 -2. 在 `components` 中注册 -3. 才能在模板中使用 - -```javascript -// ✅ 正确 -import asyncModal from '@/components/asyncModal' -export default { - components: { - asyncModal - } -} - -// ❌ 错误(直接在模板中使用未注册的组件) - -``` - -## ✅ 验证清单 - -### 功能验证 - -- ✅ 登录功能正常 -- ✅ 系统标题正确显示 -- ✅ 菜单正确显示 -- ✅ 页面跳转正常 -- ✅ 控制台没有 Vuex 错误 - -### 错误检查 - -- ✅ 没有 `[vuex] unknown action` 错误 -- ✅ 没有 `[vuex] unknown getter` 错误 -- ✅ 没有 `Unknown custom element` 错误 -- ✅ 没有组件注册错误 - ---- - -**所有 Vuex 错误已修复!** 🎉 - -现在系统可以正常运行,Terminal 功能暂时禁用但不影响核心功能。 - diff --git a/demo-project/_doc/API直接导入重构说明.md b/demo-project/_doc/API直接导入重构说明.md deleted file mode 100644 index 82b94aa..0000000 --- a/demo-project/_doc/API直接导入重构说明.md +++ /dev/null @@ -1,372 +0,0 @@ -# API 直接导入重构说明 - -## 📋 重构内容 - -### 重构目标 - -将框架中的 API server 从**注入模式**改为**直接导入模式**,简化代码结构。 - -### 修改前(注入模式) - -**问题**: -- 需要在 `src/index.js` 中调用 `setUserServer` 和 `setParamSetupServer` -- Store 模块需要导出 setter 函数 -- 代码结构复杂,不够直观 - -**代码示例**: -```javascript -// src/store/user.js -let userServerInstance = null - -export const setUserServer = (server) => { - userServerInstance = server -} - -// 使用时 -if (!userServerInstance) { - throw new Error('userServer not initialized') -} -let res = await userServerInstance.login(userFrom) -``` - -```javascript -// src/index.js -import { setUserServer } from './store/user' -import { setParamSetupServer } from './store/app' -import * as systemApi from './api/system' -import * as systemHighApi from './api/system_high' - -// 自动设置 API -setUserServer(systemApi.userServer) -setParamSetupServer(systemHighApi.paramSetupServer) -``` - -### 修改后(直接导入模式) - -**优点**: -- ✅ 代码更简洁 -- ✅ 不需要额外的 setter 函数 -- ✅ 依赖关系更清晰 -- ✅ 符合 ES6 模块化规范 - -**代码示例**: -```javascript -// src/store/user.js -import userServer from '../api/system/userServer' - -// 直接使用 -let res = await userServer.login(userFrom) -``` - -```javascript -// src/index.js -// 不再需要 setUserServer 和 setParamSetupServer -import * as systemApi from './api/system' -import * as systemHighApi from './api/system_high' -``` - -## 📁 修改的文件 - -### 1. `src/store/user.js` - -**修改前**: -```javascript -import { setToken, getToken } from '../utils/tools' -import uiTool from '../utils/uiTool' -import { defaultMenus, filterMenusByIds } from '../config/menuConfig' - -// 注意:这里的 userServer 需要在使用时注入 -let userServerInstance = null - -export const setUserServer = (server) => { - userServerInstance = server -} - -// 使用时 -if (!userServerInstance) { - throw new Error('userServer not initialized') -} -let res = await userServerInstance.login(userFrom) -``` - -**修改后**: -```javascript -import { setToken, getToken } from '../utils/tools' -import uiTool from '../utils/uiTool' -import { defaultMenus, filterMenusByIds } from '../config/menuConfig' -import userServer from '../api/system/userServer' - -// 直接使用 -let res = await userServer.login(userFrom) -``` - -**变更点**: -- ✅ 移除了 `userServerInstance` 变量 -- ✅ 移除了 `setUserServer` 导出函数 -- ✅ 直接导入 `userServer` -- ✅ 移除了 `if (!userServerInstance)` 检查 -- ✅ 将所有 `userServerInstance` 替换为 `userServer` - -### 2. `src/store/app.js` - -**修改前**: -```javascript -import { getBreadCrumbList, getHomeRoute } from '../utils/tools' - -// 注意:这里的 paramSetupServer 需要在使用时注入 -let paramSetupServerInstance = null - -export const setParamSetupServer = (server) => { - paramSetupServerInstance = server -} - -// 使用时 -if (!paramSetupServerInstance) { - commit('setSysTitle', formModel) - return -} -let res1 = await paramSetupServerInstance.getOne('sys_title') -``` - -**修改后**: -```javascript -import { getBreadCrumbList, getHomeRoute } from '../utils/tools' -import paramSetupServer from '../api/system_high/paramSetupServer' - -// 直接使用 -let res1 = await paramSetupServer.getOne('sys_title') -``` - -**变更点**: -- ✅ 移除了 `paramSetupServerInstance` 变量 -- ✅ 移除了 `setParamSetupServer` 导出函数 -- ✅ 直接导入 `paramSetupServer` -- ✅ 移除了 `if (!paramSetupServerInstance)` 检查 -- ✅ 将所有 `paramSetupServerInstance` 替换为 `paramSetupServer` - -### 3. `src/index.js` - -**修改前**: -```javascript -// ==================== Store 模块 ==================== -import storeModules, { userModule, appModule } from './store' -import { setUserServer } from './store/user' -import { setParamSetupServer } from './store/app' - -// ==================== 系统 API ==================== -import * as systemApi from './api/system' -import * as systemHighApi from './api/system_high' - -// 自动设置 API -setUserServer(systemApi.userServer) -setParamSetupServer(systemHighApi.paramSetupServer) - -// AdminFramework 类中的方法 -class AdminFramework { - /** - * 设置用户服务实例 - */ - setUserServer(userServer) { - setUserServer(userServer) - } - - /** - * 设置参数设置服务实例 - */ - setParamSetupServer(paramSetupServer) { - setParamSetupServer(paramSetupServer) - } -} -``` - -**修改后**: -```javascript -// ==================== Store 模块 ==================== -import storeModules, { userModule, appModule } from './store' - -// ==================== 系统 API ==================== -import * as systemApi from './api/system' -import * as systemHighApi from './api/system_high' - -// AdminFramework 类中移除了 setUserServer 和 setParamSetupServer 方法 -``` - -**变更点**: -- ✅ 移除了 `setUserServer` 和 `setParamSetupServer` 的导入 -- ✅ 移除了自动设置 API 的代码 -- ✅ 移除了 `AdminFramework` 类中的 `setUserServer` 和 `setParamSetupServer` 方法 - -## 🎯 影响范围 - -### 不受影响的功能 - -- ✅ 登录功能 -- ✅ 权限菜单 -- ✅ 系统标题 -- ✅ 所有业务功能 - -### 代码简化 - -**减少的代码行数**: -- `src/store/user.js`: -7 行 -- `src/store/app.js`: -7 行 -- `src/index.js`: -12 行 -- **总计**: -26 行 - -**移除的概念**: -- ❌ `userServerInstance` 变量 -- ❌ `paramSetupServerInstance` 变量 -- ❌ `setUserServer` 函数 -- ❌ `setParamSetupServer` 函数 -- ❌ API 注入机制 - -## 📊 对比表 - -| 特性 | 注入模式 | 直接导入模式 | -|------|---------|------------| -| 代码行数 | 多 | 少 | -| 复杂度 | 高 | 低 | -| 依赖关系 | 隐式 | 显式 | -| 初始化检查 | 需要 | 不需要 | -| 灵活性 | 高(可运行时替换) | 中(编译时确定) | -| 可读性 | 中 | 高 | -| 维护性 | 中 | 高 | - -## 💡 设计理念 - -### 为什么选择直接导入? - -1. **简单性优先** - - 对于大多数项目,API server 是固定的 - - 不需要运行时动态替换 - - 直接导入更符合直觉 - -2. **符合 ES6 规范** - - 使用标准的 `import` 语法 - - 依赖关系在文件顶部清晰可见 - - 便于静态分析和 tree-shaking - -3. **减少样板代码** - - 不需要额外的 setter 函数 - - 不需要初始化检查 - - 代码更简洁 - -### 何时使用注入模式? - -如果你的项目需要以下特性,可以考虑使用注入模式: - -1. **运行时替换 API** - - 例如:测试环境使用 mock API - - 例如:多租户系统使用不同的 API - -2. **插件化架构** - - 框架作为独立包发布 - - 使用者可以自定义 API 实现 - -3. **依赖注入容器** - - 使用 IoC 容器管理依赖 - - 需要复杂的依赖管理 - -对于本项目,直接导入模式更合适。 - -## 🧪 测试验证 - -### 测试步骤 - -1. **启动项目** - ```bash - cd demo-project - npm run dev - ``` - -2. **测试登录** - - 访问 `http://localhost:8080` - - 输入用户名密码 - - 点击登录 - -3. **验证功能** - - ✅ 登录成功 - - ✅ 菜单显示正常 - - ✅ 系统标题显示正常 - - ✅ 页面跳转正常 - -### 预期结果 - -所有功能正常工作,与重构前完全一致。 - -## 📝 迁移指南 - -如果你的项目使用了旧的注入模式,可以按以下步骤迁移: - -### 步骤 1:修改 Store 模块 - -**user.js**: -```javascript -// 删除 -let userServerInstance = null -export const setUserServer = (server) => { - userServerInstance = server -} - -// 添加 -import userServer from '../api/system/userServer' - -// 替换所有 userServerInstance 为 userServer -``` - -**app.js**: -```javascript -// 删除 -let paramSetupServerInstance = null -export const setParamSetupServer = (server) => { - paramSetupServerInstance = server -} - -// 添加 -import paramSetupServer from '../api/system_high/paramSetupServer' - -// 替换所有 paramSetupServerInstance 为 paramSetupServer -``` - -### 步骤 2:修改 index.js - -```javascript -// 删除这些导入 -import { setUserServer } from './store/user' -import { setParamSetupServer } from './store/app' - -// 删除这些调用 -setUserServer(systemApi.userServer) -setParamSetupServer(systemHighApi.paramSetupServer) - -// 删除 AdminFramework 类中的这些方法 -setUserServer(userServer) { ... } -setParamSetupServer(paramSetupServer) { ... } -``` - -### 步骤 3:测试验证 - -运行项目,确保所有功能正常。 - -## ✅ 总结 - -### 重构成果 - -- ✅ 代码更简洁(减少 26 行) -- ✅ 结构更清晰 -- ✅ 依赖关系更明确 -- ✅ 维护更容易 -- ✅ 功能完全正常 - -### 后续建议 - -1. **保持简单**:除非有特殊需求,否则使用直接导入 -2. **统一风格**:项目中的所有 API 都使用相同的导入方式 -3. **文档更新**:更新项目文档,说明 API 的使用方式 - ---- - -**重构完成!** 🎉 - -现在框架代码更简洁、更易维护了。 - diff --git a/demo-project/_doc/authorityMenus接口失败解决方案.md b/demo-project/_doc/authorityMenus接口失败解决方案.md deleted file mode 100644 index d805b4e..0000000 --- a/demo-project/_doc/authorityMenus接口失败解决方案.md +++ /dev/null @@ -1,314 +0,0 @@ -# authorityMenus 接口失败解决方案 - -## 🔧 问题描述 - -登录成功后,调用 `/sys_user/authorityMenus` 接口失败,导致无法获取完整的菜单数据。 - -## ✅ 解决方案 - -### 方案:使用默认菜单配置 - -当 `authorityMenus` 接口失败时,系统会自动使用默认的菜单配置,并根据登录接口返回的菜单 ID 数组进行过滤。 - -## 📁 新增文件 - -### `src/config/menuConfig.js` - -这个文件包含了默认的菜单配置,包括: - -1. **系统管理** - - 用户管理 (`/system/user`) - - 角色管理 (`/system/role`) - - 系统日志 (`/system/log`) - - 参数设置 (`/system/param`) - -2. **高级管理** - - 菜单管理 (`/system_high/menu`) - - 控制管理 (`/system_high/control`) - - 系统标题 (`/system_high/title`) - -3. **首页** (`/home`) - -## 🔄 工作流程 - -### 1. 登录流程 - -``` -用户登录 - ↓ -调用 /sys_user/login 接口 - ↓ -返回: { token, user, authorityMenus: "[1,142,121,...]" } - ↓ -保存 token 和用户信息 - ↓ -解析 authorityMenus (字符串 → 数组) - ↓ -调用 /sys_user/authorityMenus 接口 - ↓ -接口失败 ❌ - ↓ -使用默认菜单配置 + 根据 ID 过滤 - ↓ -生成路由 - ↓ -登录成功 ✅ -``` - -### 2. 菜单过滤逻辑 - -```javascript -// 登录返回的菜单 IDs -authorityMenus: "[1,142,121,143,144,145,124,147,120,123,125,...]" - -// 解析为数组 -menuIds: [1, 142, 121, 143, 144, 145, 124, 147, 120, 123, 125, ...] - -// 从默认菜单配置中过滤出这些 ID 对应的菜单 -filteredMenus = filterMenusByIds(menuIds, defaultMenus) - -// 生成路由 -routes = uiTool.getRoutes(Main, ParentView, Page404) -``` - -## 📝 代码修改 - -### 1. `src/store/user.js` - -**导入默认菜单配置:** -```javascript -import { defaultMenus, filterMenusByIds } from '../config/menuConfig' -``` - -**修改 `setAuthorityMenus` 方法:** -```javascript -async setAuthorityMenus({ state, commit }, { Main, ParentView, Page404, authorityMenus, menuIds }) { - let menus = authorityMenus - - if (!menus && userServerInstance) { - try { - // 尝试调用接口 - let res = await userServerInstance.authorityMenus() - if (res && res.code === 0 && res.data) { - menus = res.data - } - } catch (error) { - console.error('获取权限菜单失败:', error) - console.warn('将使用默认菜单配置') - - // 接口失败,使用默认菜单配置 - if (menuIds && menuIds.length > 0) { - // 根据 ID 过滤菜单 - menus = filterMenusByIds(menuIds, defaultMenus) - } else { - // 使用所有默认菜单 - menus = defaultMenus - } - } - } - - // ... 后续处理 -} -``` - -**修改 `handleLogin` 方法:** -```javascript -async handleLogin({ state, commit, dispatch }, { userFrom, Main, ParentView, Page404 }) { - let res = await userServerInstance.login(userFrom) - - let token = res.data.token - let user = res.data.user - let authorityMenusIds = res.data.authorityMenus - - commit('setUserName', user.name.trim()) - commit('setToken', token) - - // 解析菜单 IDs - let menuIds = [] - if (authorityMenusIds) { - if (typeof authorityMenusIds === 'string') { - menuIds = JSON.parse(authorityMenusIds) - } else if (Array.isArray(authorityMenusIds)) { - menuIds = authorityMenusIds - } - } - - // 传递 menuIds,以便在接口失败时使用 - await dispatch('setAuthorityMenus', { - Main, - ParentView, - Page404, - menuIds - }) -} -``` - -## 🎯 测试步骤 - -### 1. 启动项目 -```bash -cd demo-project -npm run dev -``` - -### 2. 登录测试 -- 用户名:`zc` -- 密码:对应的密码 - -### 3. 查看控制台日志 - -**成功的日志:** -``` -登录接口返回: { code: 0, data: { token, user, authorityMenus } } -登录返回的菜单 IDs: "[1,142,121,...]" -获取权限菜单失败: [错误信息] -将使用默认菜单配置 -根据菜单 IDs 过滤后的菜单: [...] -最终处理的权限菜单: [...] -生成的主菜单: { path: '/', children: [...] } -``` - -### 4. 验证结果 - -登录成功后,应该能看到: -- ✅ 页面刷新 -- ✅ 进入系统首页 -- ✅ 左侧显示菜单(根据权限过滤) -- ✅ 顶部显示用户名 - -## 📊 菜单 ID 映射 - -根据登录返回的菜单 IDs: -``` -[1,142,121,143,144,145,124,147,120,123,125,132,133,126,136,137,138,139,151,152,153,154,149,150,156,157,158,122,159,5,11,12,13,67,68,15] -``` - -默认菜单配置中包含的 IDs: -- `1` - 首页 -- `5` - 系统管理 -- `11` - 用户管理 -- `12` - 角色管理 -- `13` - 系统日志 -- `15` - 参数设置 -- `120` - 高级管理 -- `122` - 菜单管理 -- `123` - 控制管理 -- `124` - 系统标题 - -过滤后会显示这些菜单。 - -## ⚠️ 注意事项 - -### 1. 默认菜单配置的限制 - -默认菜单配置只包含了常用的系统管理菜单。如果你的系统有其他业务菜单,需要: - -**选项 A:扩展默认菜单配置** - -编辑 `src/config/menuConfig.js`,添加更多菜单: -```javascript -export const defaultMenus = [ - // ... 现有菜单 - { - id: 200, - name: '业务管理', - path: '/business', - component: '', - parent_id: 0, - type: '菜单', - is_show_menu: 1, - icon: 'md-briefcase', - children: [ - { - id: 201, - name: '订单管理', - path: '/business/order', - component: 'business/order', - parent_id: 200, - type: '页面', - is_show_menu: 1 - } - ] - } -] -``` - -**选项 B:修复后端接口** - -这是推荐的长期方案。修复 `/sys_user/authorityMenus` 接口,使其返回完整的菜单对象数组。 - -### 2. 菜单组件路径 - -默认菜单配置中的 `component` 字段指向 `src/views/` 目录下的组件。 - -例如: -- `component: 'system/sys_user'` → `src/views/system/sys_user.vue` -- `component: 'home/index'` → `src/views/home/index.vue` - -确保这些组件文件存在。 - -### 3. 菜单权限 - -即使使用默认菜单配置,也会根据登录返回的菜单 IDs 进行过滤。 - -用户只能看到他有权限的菜单。 - -## 🔧 后续优化建议 - -### 短期方案(当前实现) -✅ 使用默认菜单配置 + ID 过滤 -- 优点:快速解决问题,用户可以登录 -- 缺点:需要手动维护默认菜单配置 - -### 长期方案(推荐) -🎯 修复后端 `authorityMenus` 接口 -- 优点:动态获取菜单,灵活性高 -- 缺点:需要修改后端代码 - -**建议后端接口返回格式:** -```json -{ - "code": 0, - "message": "请求成功", - "data": [ - { - "id": 1, - "name": "首页", - "path": "/home", - "component": "home/index", - "parent_id": 0, - "type": "页面", - "is_show_menu": 1, - "icon": "md-home", - "sort": 1 - }, - { - "id": 5, - "name": "系统管理", - "path": "/system", - "component": "", - "parent_id": 0, - "type": "菜单", - "is_show_menu": 1, - "icon": "md-settings", - "sort": 2, - "children": [...] - } - ] -} -``` - -## 🎉 总结 - -现在即使 `authorityMenus` 接口失败,系统也能: -1. ✅ 正常登录 -2. ✅ 显示菜单(根据权限过滤) -3. ✅ 访问有权限的页面 -4. ✅ 提供良好的用户体验 - -如果需要添加更多菜单,请编辑 `src/config/menuConfig.js` 文件。 - ---- - -**当前状态**:登录功能已修复,可以正常使用!🎉 - diff --git a/demo-project/_doc/修复完成报告.md b/demo-project/_doc/修复完成报告.md deleted file mode 100644 index 888325d..0000000 --- a/demo-project/_doc/修复完成报告.md +++ /dev/null @@ -1,225 +0,0 @@ -# Demo 项目修复完成报告 - -## ✅ 修复完成时间 -**2025-10-08** - -## 🎯 修复的问题 - -### 1. ✅ 路径别名配置问题 -**问题描述**:框架源码中的组件使用 `@/` 别名引用内部文件,但 webpack 配置中的 `@` 别名指向 demo-project/src,导致无法找到框架的工具类和组件。 - -**解决方案**: -修改 `demo-project/webpack.config.js`,将 `@` 别名指向框架源码目录: - -```javascript -resolve: { - extensions: ['.js', '.vue', '.json'], - alias: { - // 框架源码的别名(必须在前面,优先级高) - '@': path.resolve(__dirname, '../src'), - '@component': path.resolve(__dirname, '../src/components'), - '@utils': path.resolve(__dirname, '../src/utils'), - '@api': path.resolve(__dirname, '../src/api'), - '@config': path.resolve(__dirname, '../src/config'), - '@assets': path.resolve(__dirname, '../src/assets'), - // demo 项目的别名 - '~': path.resolve(__dirname, 'src'), - 'vue$': 'vue/dist/vue.esm.js' - } -} -``` - -### 2. ✅ 缺少 core-js 依赖 -**问题描述**:Babel 编译时需要 core-js 提供 polyfill,但项目中未安装。 - -**解决方案**: -```bash -npm install core-js@3 -``` - -### 3. ✅ 登录接口未调用问题 -**问题描述**:登录页面调用 `handleLogin` action 时,参数格式不正确,缺少必需的 `Main`、`ParentView`、`Page404` 组件参数。 - -**原代码**(`src/views/login/login.vue`): -```javascript -async handleSubmit({ userName, password }) { - let user = { name: userName, password: password } - await this.handleLogin(user) // ❌ 参数不完整 - window.location.reload() -} -``` - -**修复后**: -```javascript -import Main from '@component/main' -import ParentView from '@component/parent-view' -import Page404 from '@/views/error-page/404.vue' -import { mapActions } from 'vuex' - -export default { - methods: { - ...mapActions('user', ['handleLogin']), - async handleSubmit({ userName, password }) { - try { - let userFrom = { name: userName, password: password } - await this.handleLogin({ - userFrom, // ✅ 用户信息 - Main, // ✅ 主布局组件 - ParentView, // ✅ 父视图组件 - Page404 // ✅ 404页面组件 - }) - this.$Message.success('登录成功!') - window.location.reload() - } catch (error) { - console.error('登录失败:', error) - this.$Message.error(error.message || '登录失败,请检查用户名和密码') - } - }, - }, -} -``` - -## 📊 修复结果 - -### 编译状态 -✅ **webpack 5.102.1 compiled successfully** - -### 功能验证 -- ✅ 项目可以正常启动 -- ✅ 没有编译错误 -- ✅ 登录功能可以正确调用登录接口 -- ✅ 框架的所有组件和工具类都能正确引用 - -## 🚀 如何启动项目 - -### 方式一:使用启动脚本 -```bash -双击 demo-project/start.bat -``` - -### 方式二:命令行启动 -```bash -cd demo-project -npm run dev -``` - -### 访问地址 -浏览器会自动打开:`http://localhost:8080` - -## 📝 登录测试 - -项目启动后,你可以在登录页面输入用户名和密码进行测试。 - -**注意**: -- 登录接口会调用 `userServer.login(userFrom)` 方法 -- 需要确保后端 API 服务正常运行(默认地址:`http://localhost:9098/api/`) -- 如果后端未启动,登录会失败并显示错误信息 - -## 🔧 配置说明 - -### API 配置 -在 `demo-project/src/config/index.js` 中配置: - -```javascript -export default { - // 系统标题 - title: 'Demo 管理系统', - - // API 基础路径 - apiUrl: 'http://localhost:9098/api/', - - // 文件上传路径 - uploadUrl: 'http://localhost:9098/api/upload', - - // Token 存储的 key - tokenKey: 'demo_token', - - // 其他配置 - timeout: 30000, - - // 是否显示页面加载进度条 - showProgressBar: true -} -``` - -### 修改 API 地址 -如果你的后端 API 地址不同,请修改 `apiUrl` 和 `uploadUrl`。 - -## 🎉 框架功能 - -现在你的 Demo 项目已经完全集成了框架的所有功能: - -### 1. 用户认证 -- ✅ 登录功能 -- ✅ 登出功能 -- ✅ Token 管理 -- ✅ 权限菜单获取 - -### 2. 路由管理 -- ✅ 动态路由 -- ✅ 权限路由 -- ✅ 路由守卫 - -### 3. 状态管理 -- ✅ Vuex Store -- ✅ 用户状态 -- ✅ 应用状态 -- ✅ 状态持久化 - -### 4. UI 组件 -- ✅ 主布局(Main) -- ✅ 侧边菜单 -- ✅ 顶部导航 -- ✅ 面包屑导航 -- ✅ 错误页面(401、404、500) - -### 5. 工具库 -- ✅ HTTP 请求封装 -- ✅ UI 工具类 -- ✅ 通用工具函数 - -### 6. 系统管理页面 -- ✅ 系统日志(sys_log) -- ✅ 参数设置(sys_param_setup) -- ✅ 角色管理(sys_role) -- ✅ 用户管理(sys_user) -- ✅ 控制管理(sys_control) -- ✅ 菜单管理(sys_menu) -- ✅ 系统标题(sys_title) - -## 📚 下一步 - -1. **启动后端服务**:确保后端 API 服务运行在 `http://localhost:9098/api/` -2. **测试登录**:使用有效的用户名和密码进行登录测试 -3. **开发业务功能**:在 `demo-project/src/views/business/` 目录下添加你的业务页面 -4. **添加路由**:在 `demo-project/src/main.js` 中添加业务路由 - -## ⚠️ 注意事项 - -1. **后端 API**:项目需要配套的后端 API 服务才能完整运行 -2. **端口占用**:确保 8080 端口未被占用 -3. **浏览器兼容**:推荐使用 Chrome、Edge 或 Firefox 浏览器 -4. **Node 版本**:建议使用 Node.js 14+ 版本 - -## 🐛 常见问题 - -### Q1: 登录后提示"userServer not initialized" -**A**: 这是因为 userServer 未正确初始化。框架已经在 `src/index.js` 中自动设置了 API,应该不会出现这个问题。 - -### Q2: 登录失败,提示网络错误 -**A**: 检查后端 API 服务是否正常运行,以及 `config/index.js` 中的 `apiUrl` 配置是否正确。 - -### Q3: 页面空白或报错 -**A**: 打开浏览器控制台查看具体错误信息,通常是路由或组件引用问题。 - -## 📞 技术支持 - -如果遇到问题,请检查: -1. 浏览器控制台的错误信息 -2. 终端的编译输出 -3. 网络请求是否正常(F12 -> Network) - ---- - -**修复完成!项目现在可以正常运行了!** 🎉 - diff --git a/demo-project/_doc/修复说明.md b/demo-project/_doc/修复说明.md deleted file mode 100644 index 27ff554..0000000 --- a/demo-project/_doc/修复说明.md +++ /dev/null @@ -1,203 +0,0 @@ -# Demo 项目修复说明 - -## ✅ 已完成的修复 - -### 1. 配置更新 - -#### ✅ `src/main.js` -```javascript -// 修改为直接使用框架源码 -import AdminFramework from '../../src/index.js' -``` - -**好处**: -- 实时调试框架代码 -- 热更新支持 -- 无需重新打包 - -#### ✅ `webpack.config.js` -添加了框架源码的路径别名: -```javascript -alias: { - '@component': path.resolve(__dirname, '../src/components'), - '@utils': path.resolve(__dirname, '../src/utils'), - '@api': path.resolve(__dirname, '../src/api'), - '@config': path.resolve(__dirname, '../src/config'), - '@assets': path.resolve(__dirname, '../src/assets') -} -``` - -#### ✅ `babel.config.js` -添加了 JSX 支持: -```javascript -presets: [ - '@babel/preset-env', - '@vue/babel-preset-jsx' -] -``` - -#### ✅ `package.json` -新增依赖: -- `@vue/babel-preset-jsx@^1.4.0` - JSX 支持 -- `brace@^0.11.1` - 代码编辑器 -- `vue2-ace-editor@^0.0.15` - Ace 编辑器 - -### 2. 脚本文件 - -#### ✅ `install.bat` - 一键安装脚本 -```batch -双击运行即可安装所有依赖 -``` - -#### ✅ `start.bat` - 启动脚本(已更新) -```batch -自动检查并安装缺失的依赖 -``` - -### 3. 文档文件 - -#### ✅ 创建的文档: -- `README_FIRST.txt` - 首次运行必读 ⭐ -- `启动前必读.md` - 详细启动指南 -- `修复说明.md` - 本文件 -- `CHANGELOG.md` - 更新日志 - -#### ✅ 更新的文档: -- `README.md` - 项目说明 -- `如何启动.txt` - 快速指南 - -## 🚀 用户需要做什么 - -### 第一步:安装依赖 - -**方式一(推荐)**: -```bash -双击 install.bat -``` - -**方式二**: -```bash -cd demo-project -npm install -``` - -如果遇到依赖缺失,运行: -```bash -npm install @vue/babel-preset-jsx brace vue2-ace-editor -``` - -### 第二步:启动项目 - -**方式一(推荐)**: -```bash -双击 start.bat -``` - -**方式二**: -```bash -npm run dev -``` - -### 第三步:访问应用 - -浏览器自动打开 `http://localhost:8080` - -## 📋 检查清单 - -运行前确保: - -- [ ] 已进入 `demo-project` 目录 -- [ ] 已运行 `npm install` 或 `install.bat` -- [ ] 没有 "UNMET DEPENDENCY" 错误 -- [ ] 端口 8080 未被占用 - -验证命令: -```bash -npm list --depth=0 -``` - -应该看到: -``` -✅ @vue/babel-preset-jsx@1.4.0 -✅ brace@0.11.1 -✅ vue2-ace-editor@0.0.15 -✅ vue@2.7.16 -✅ vuex@3.6.2 -✅ vue-router@3.6.5 -✅ view-design@4.7.0 -``` - -## ⚠️ 常见错误及解决 - -### 错误1:UNMET DEPENDENCY - -**原因**:依赖未安装 - -**解决**: -```bash -npm install @vue/babel-preset-jsx brace vue2-ace-editor -``` - -### 错误2:Cannot find module '../../src/index.js' - -**原因**:项目结构不正确 - -**解决**:确保目录结构为: -``` -f:\项目\前端框架项目\ -├── src\ ← 框架源码 -│ └── index.js -└── demo-project\ ← Demo 项目 -``` - -### 错误3:端口被占用 - -**原因**:8080 端口已被使用 - -**解决**:修改 `webpack.config.js`: -```javascript -devServer: { - port: 8081 // 改成其他端口 -} -``` - -### 错误4:Babel 编译错误 - -**原因**:JSX preset 未安装 - -**解决**: -```bash -npm install @vue/babel-preset-jsx --save-dev -``` - -## 📊 项目状态 - -| 项目 | 状态 | -|------|------| -| 框架源码引用 | ✅ 已配置 | -| Webpack 配置 | ✅ 已更新 | -| Babel 配置 | ✅ 已更新 | -| 依赖列表 | ✅ 已更新 | -| 安装脚本 | ✅ 已创建 | -| 启动脚本 | ✅ 已更新 | -| 文档 | ✅ 已完善 | - -## 🎯 下一步 - -1. **运行** `install.bat` 安装依赖 -2. **运行** `start.bat` 启动项目 -3. **访问** `http://localhost:8080` -4. **开始** 开发你的应用! - -## 📚 相关文档 - -- [README_FIRST.txt](./README_FIRST.txt) - 首次运行必读 -- [启动前必读.md](./启动前必读.md) - 详细指南 -- [CHANGELOG.md](./CHANGELOG.md) - 更新日志 -- [README.md](./README.md) - 完整说明 - ---- - -**修复完成时间**: 2025-10-08 -**修复人员**: AI Assistant - diff --git a/demo-project/_doc/启动前必读.md b/demo-project/_doc/启动前必读.md deleted file mode 100644 index b878436..0000000 --- a/demo-project/_doc/启动前必读.md +++ /dev/null @@ -1,115 +0,0 @@ -# ⚠️ 启动前必读 - -## 📦 第一步:安装依赖 - -**在 `demo-project` 目录下**运行: - -```bash -npm install -``` - -如果遇到依赖缺失错误,运行: - -```bash -npm install @vue/babel-preset-jsx brace vue2-ace-editor --save -``` - -## 🚀 第二步:启动项目 - -### 方式一:使用脚本(推荐) - -**Windows 用户**: -```bash -双击 start.bat -``` - -**Linux/Mac 用户**: -```bash -./start.sh -``` - -### 方式二:手动启动 - -```bash -npm run dev -``` - -## ✅ 验证安装 - -运行以下命令检查依赖是否完整: - -```bash -npm list --depth=0 -``` - -应该看到以下关键依赖: -- ✅ @vue/babel-preset-jsx -- ✅ brace -- ✅ vue2-ace-editor -- ✅ vue -- ✅ vuex -- ✅ vue-router -- ✅ view-design - -## 🔍 常见问题 - -### 问题1:依赖缺失 - -**症状**:看到 "UNMET DEPENDENCY" 错误 - -**解决**: -```bash -# 删除依赖重装 -rm -rf node_modules -rm package-lock.json -npm install -``` - -### 问题2:端口被占用 - -**症状**:8080 端口已被占用 - -**解决**:修改 `webpack.config.js` 中的端口 -```javascript -devServer: { - port: 8081 // 改成其他端口 -} -``` - -### 问题3:路径找不到 - -**症状**:无法找到 ../../src/index.js - -**解决**:确保项目结构正确 -``` -f:\项目\前端框架项目\ -├── src\ # ← 框架源码 -│ └── index.js # ← 框架入口 -└── demo-project\ # ← Demo 项目 - └── src\ - └── main.js # ← 引用 ../../src/index.js -``` - -## 📝 项目说明 - -本项目直接使用框架源码(不是打包文件),好处: -- ✅ 实时调试 -- ✅ 热更新 -- ✅ 方便开发 - -## 🎯 访问地址 - -启动后访问:`http://localhost:8080` - -可用页面: -- `/login` - 登录页面 -- `/home` - 主页 -- `/business/product` - 产品列表示例 - ---- - -**如有问题,请查看**: -- [CHANGELOG.md](./CHANGELOG.md) - 更新日志 -- [README.md](./README.md) - 完整说明 -- [如何启动.txt](./如何启动.txt) - 快速指南 - diff --git a/demo-project/_doc/如何启动.txt b/demo-project/_doc/如何启动.txt deleted file mode 100644 index 8af391f..0000000 --- a/demo-project/_doc/如何启动.txt +++ /dev/null @@ -1,50 +0,0 @@ -==================================== - Demo 项目启动说明 -==================================== - -本项目现在使用框架源码,更方便调试! - -⚠️ 重要:首次运行必须先安装依赖! - -【方式一:一键安装+启动(推荐)】 - -Windows 用户: - 1. 双击 install.bat(安装依赖) - 2. 双击 start.bat(启动项目) - -【方式二:手动安装+启动】 - -1. 安装依赖(首次必须) - npm install - -2. 如果提示依赖缺失,运行: - npm install @vue/babel-preset-jsx brace vue2-ace-editor - -3. 启动开发服务器 - npm run dev - -4. 浏览器自动打开 - http://localhost:8080 - -【可访问页面】 - -/login - 登录页面 -/home - 主页 -/business/product - 产品列表示例 - -【遇到错误?】 - -1. 删除依赖重装: - rm -rf node_modules - rm package-lock.json - npm install - -2. 查看更新日志: - CHANGELOG.md - -3. 查看详细文档: - README.md - 快速启动.md - -==================================== - diff --git a/demo-project/_doc/快速配置组件映射.md b/demo-project/_doc/快速配置组件映射.md deleted file mode 100644 index 3292cb1..0000000 --- a/demo-project/_doc/快速配置组件映射.md +++ /dev/null @@ -1,143 +0,0 @@ -# 快速配置组件映射 - -## 🎯 一句话说明 - -**在 `Vue.use()` 时传入 `componentMap` 参数,将后端权限菜单中的组件路径映射到实际组件。** - -## 📝 三步配置 - -### 步骤1:查看权限菜单接口 - -查看后端接口返回的所有 `component` 字段: - -```json -{ - "data": [ - { "component": "ball/games.vue" }, - { "component": "order/pay_orders.vue" }, - { "component": "ball/wch_users.vue" } - ] -} -``` - -### 步骤2:创建并导入组件 - -```javascript -// src/main.js -import GamesComponent from './views/ball/games.vue' -import PayOrdersComponent from './views/order/pay_orders.vue' -import WchUsersComponent from './views/ball/wch_users.vue' -``` - -### 步骤3:配置映射 - -```javascript -Vue.use(AdminFramework, { - config, - ViewUI, - VueRouter, - Vuex, - createPersistedState, - componentMap: { - 'ball/games': GamesComponent, - 'order/pay_orders': PayOrdersComponent, - 'ball/wch_users': WchUsersComponent - } -}) -``` - -## ✅ 完成! - -现在权限菜单中的所有业务页面都能正常显示了。 - -## 📋 配置模板 - -```javascript -import Vue from 'vue' -import VueRouter from 'vue-router' -import Vuex from 'vuex' -import ViewUI from 'view-design' -import createPersistedState from 'vuex-persistedstate' -import 'view-design/dist/styles/iview.css' - -import AdminFramework from '../../src/index.js' -import config from './config' -import App from './App.vue' - -// ==================== 导入业务组件 ==================== -// TODO: 根据权限菜单接口,导入所有业务组件 -// import XXXComponent from './views/xxx/xxx.vue' - -Vue.use(AdminFramework, { - config, - ViewUI, - VueRouter, - Vuex, - createPersistedState, - componentMap: { - // TODO: 配置组件映射 - // 'xxx/xxx': XXXComponent - } -}) - -new Vue({ - el: '#app', - router: AdminFramework.router, - store: AdminFramework.store, - render: h => h(App), - mounted() { - AdminFramework.uiTool.setRem() - this.$store.dispatch('user/setAuthorityMenus', { - Main: AdminFramework.Main, - ParentView: AdminFramework.ParentView, - Page404: AdminFramework.Page404 - }) - } -}) -``` - -## 💡 关键要点 - -### 1. 路径不需要 .vue 后缀 - -```javascript -// ✅ 正确 -componentMap: { - 'ball/games': GamesComponent -} - -// ❌ 错误(虽然也能用,但不推荐) -componentMap: { - 'ball/games.vue': GamesComponent -} -``` - -### 2. 系统组件无需配置 - -这些已自动映射,**不需要**在 componentMap 中配置: -- `home/index.vue` -- `system/sys_user.vue` -- `system/sys_role.vue` -- `system/sys_log.vue` -- `system/sys_param_setup.vue` -- `system_high/sys_menu.vue` -- `system_high/sys_control.vue` -- `system_high/sys_title.vue` - -### 3. 未映射的组件会显示提示 - -如果组件没有配置映射,页面会显示: -``` -⚠️ 警告 -页面组件未加载: ball/games.vue -请在项目中创建此组件或在组件映射表中注册 -``` - -## 📚 完整文档 - -查看详细说明:[权限菜单组件配置指南.md](./权限菜单组件配置指南.md) - ---- - -**配置完成后,所有权限菜单中的页面都能正常显示!** 🎉 - diff --git a/demo-project/_doc/文档更新说明.md b/demo-project/_doc/文档更新说明.md deleted file mode 100644 index ee9fea3..0000000 --- a/demo-project/_doc/文档更新说明.md +++ /dev/null @@ -1,362 +0,0 @@ -# 文档更新说明 - -## 📝 更新内容 - -已更新 `完整使用文档.md`,主要修改如下: - -### 1. 移除已废弃的方法 - -**移除的方法**: -- ❌ `setUserServer(userServer)` - 已废弃 -- ❌ `setParamSetupServer(paramSetupServer)` - 已废弃 - -**原因**: -- 框架已改为直接导入 API 模块 -- 不再使用依赖注入模式 -- 简化了代码结构 - -### 2. 添加 HomePage 参数说明 - -**新增内容**: - -#### install 方法参数 - -```javascript -Vue.use(AdminFramework, { - config: yourConfig, - ViewUI: ViewUI, - VueRouter: VueRouter, - Vuex: Vuex, - createPersistedState: createPersistedState, - HomePage: HomePage // ✅ 新增:可选的自定义首页组件 -}) -``` - -**参数说明**: -- `HomePage`: 自定义首页组件(可选,不传则使用框架内置组件) - -### 3. 完善 Q11: 主页 HomePage 组件说明 - -**新增两种使用方式**: - -#### 方式一:使用框架内置的主页组件(默认) - -```javascript -// 不传入 HomePage,框架会使用内置组件 -Vue.use(AdminFramework, { - config, - ViewUI, - VueRouter, - Vuex, - createPersistedState -}) -``` - -**内置组件特性**: -- ✅ 自动从 Vuex Store 获取系统标题 -- ✅ 优雅的欢迎页面样式 -- ✅ 无需额外配置 - -#### 方式二:传入自定义首页组件(推荐) - -**创建自定义首页**: -```vue - - - - -``` - -**传入自定义组件**: -```javascript -import HomePage from './views/home/index.vue' - -Vue.use(AdminFramework, { - config, - ViewUI, - VueRouter, - Vuex, - createPersistedState, - HomePage // ✅ 传入自定义首页组件 -}) -``` - -### 4. 重要说明:首页路由配置 - -**关键点**: -- ⚠️ **首页路由完全由后端权限菜单返回** -- ⚠️ 后端必须返回 `path: '/home'` 的菜单配置 -- ⚠️ 后端返回的 `component` 字段会映射到实际组件 - -**后端菜单配置示例**: -```json -{ - "id": 1, - "name": "首页", - "path": "/home", - "component": "home/index", // 映射到 src/views/home/index.vue - "parent_id": 0, - "type": "页面", - "is_show_menu": 1, - "icon": "md-home", - "sort": 1 -} -``` - -**组件映射规则**: -```javascript -// 后端返回: "component": "home/index" -// 实际加载: src/views/home/index.vue - -// 后端返回: "component": "system/user" -// 实际加载: src/views/system/user.vue -``` - -### 5. 降级方案 - -如果后端接口失败,框架会使用默认菜单配置(`src/config/menuConfig.js`): - -```javascript -export const defaultMenus = [ - { - id: 1, - name: '首页', - path: '/home', - component: 'home/index', - parent_id: 0, - type: '页面', - is_show_menu: 1, - icon: 'md-home', - sort: 1 - }, - // ... 其他菜单 -] -``` - -### 6. 更新快速开始示例 - -**新的 main.js 示例**: -```javascript -import Vue from 'vue' -import VueRouter from 'vue-router' -import Vuex from 'vuex' -import ViewUI from 'view-design' -import createPersistedState from 'vuex-persistedstate' -import AdminFramework from './libs/admin-framework.js' -import App from './App.vue' -import config from './config' -import HomePage from './views/home/index.vue' // ✅ 导入自定义首页 - -Vue.use(AdminFramework, { - config, - ViewUI, - VueRouter, - Vuex, - createPersistedState, - HomePage // ✅ 传入自定义首页组件 -}) - -new Vue({ - el: '#app', - router: AdminFramework.router, - store: AdminFramework.store, - render: h => h(App), - mounted() { - AdminFramework.uiTool.setRem() - - // 只在已登录时获取系统标题 - const token = this.$store.state.user.token - if (token) { - this.$store.dispatch('app/getSysTitle', { - defaultTitle: 'Demo 管理系统', - defaultLogo: '' - }) - } else { - document.title = 'Demo 管理系统' - } - } -}) -``` - -## 📊 更新对比 - -### 旧版本(已废弃) - -```javascript -// ❌ 旧版本:使用依赖注入 -import { systemApi, systemHighApi } from 'admin-framework' - -AdminFramework.setUserServer(systemApi.userServer) -AdminFramework.setParamSetupServer(systemHighApi.paramSetupServer) - -// ❌ 旧版本:首页路由硬编码在框架中 -// 无法自定义首页组件 -``` - -### 新版本(当前) - -```javascript -// ✅ 新版本:直接导入 API -import userServer from '../api/system/userServer' -import paramSetupServer from '../api/system_high/paramSetupServer' - -// ✅ 新版本:支持自定义首页组件 -import HomePage from './views/home/index.vue' - -Vue.use(AdminFramework, { - config, - ViewUI, - VueRouter, - Vuex, - createPersistedState, - HomePage // 可选:传入自定义首页组件 -}) -``` - -## 🎯 最佳实践 - -### 推荐做法 - -1. **创建自定义首页组件** - ```bash - src/views/home/index.vue - ``` - -2. **在 Vue.use() 时传入 HomePage 参数** - ```javascript - import HomePage from './views/home/index.vue' - - Vue.use(AdminFramework, { - config, - ViewUI, - VueRouter, - Vuex, - createPersistedState, - HomePage // 传入自定义首页组件 - }) - ``` - -3. **确保后端返回首页菜单配置** - ```json - { - "id": 1, - "name": "首页", - "path": "/home", - "component": "home/index", - "parent_id": 0, - "type": "页面", - "is_show_menu": 1 - } - ``` - -4. **在 defaultMenus 中包含首页配置作为降级方案** - ```javascript - // src/config/menuConfig.js - export const defaultMenus = [ - { - id: 1, - name: '首页', - path: '/home', - component: 'home/index', - // ... - } - ] - ``` - -### 不推荐的做法 - -1. ❌ 使用已废弃的 `setUserServer` 和 `setParamSetupServer` 方法 -2. ❌ 在代码中硬编码首页路由 -3. ❌ 不提供降级方案(defaultMenus) - -## 📝 迁移指南 - -### 从旧版本迁移到新版本 - -**步骤 1:移除废弃的方法调用** - -```javascript -// ❌ 删除这些代码 -AdminFramework.setUserServer(systemApi.userServer) -AdminFramework.setParamSetupServer(systemHighApi.paramSetupServer) -``` - -**步骤 2:创建自定义首页组件** - -```bash -# 创建首页组件文件 -mkdir -p src/views/home -touch src/views/home/index.vue -``` - -**步骤 3:更新 main.js** - -```javascript -// 添加 HomePage 导入 -import HomePage from './views/home/index.vue' - -// 在 Vue.use() 时传入 -Vue.use(AdminFramework, { - config, - ViewUI, - VueRouter, - Vuex, - createPersistedState, - HomePage // 新增 -}) -``` - -**步骤 4:确保后端返回首页配置** - -检查后端 `authorityMenus` 接口是否返回首页配置。 - -**步骤 5:测试** - -```bash -npm run dev -``` - -登录后应该能看到自定义的首页。 - -## ✅ 验证清单 - -- ✅ 移除了 `setUserServer` 和 `setParamSetupServer` 的调用 -- ✅ 创建了自定义首页组件 `src/views/home/index.vue` -- ✅ 在 `Vue.use()` 时传入了 `HomePage` 参数 -- ✅ 后端返回了首页菜单配置 -- ✅ `defaultMenus` 中包含了首页配置 -- ✅ 登录后能正常跳转到首页 -- ✅ 首页显示正确的内容 - -## 📚 相关文档 - -- `完整使用文档.md` - 完整的框架使用文档 -- `demo-project/README.md` - Demo 项目说明 -- `demo-project/登录跳转首页修复说明.md` - 登录跳转逻辑说明 -- `demo-project/移除硬编码首页说明.md` - 移除硬编码首页的说明 - ---- - -**文档已更新完成!** 🎉 - -现在文档更准确地反映了框架的当前实现,包括: -- ✅ 移除了已废弃的方法 -- ✅ 添加了 HomePage 参数说明 -- ✅ 完善了首页组件的使用方式 -- ✅ 提供了最佳实践和迁移指南 - diff --git a/demo-project/_doc/未登录接口调用问题修复.md b/demo-project/_doc/未登录接口调用问题修复.md deleted file mode 100644 index d74c3dc..0000000 --- a/demo-project/_doc/未登录接口调用问题修复.md +++ /dev/null @@ -1,387 +0,0 @@ -# 未登录接口调用问题修复 - -## 🔍 问题描述 - -### 错误现象 - -在用户未登录时,`sys_parameter/key` 接口被调用,因为没有 token 导致接口报错。 - -### 错误原因 - -在 `demo-project/src/main.js` 的 `mounted` 钩子中,无条件调用了 `getSysTitle` action: - -```javascript -mounted() { - AdminFramework.uiTool.setRem() - - // ❌ 无论是否登录都调用 - this.$store.dispatch('app/getSysTitle', { - defaultTitle: 'Demo 管理系统', - defaultLogo: '' - }) -} -``` - -`getSysTitle` action 会调用后端接口: -- `paramSetupServer.getOne('sys_title')` - 获取系统标题 -- `paramSetupServer.getOne('sys_logo')` - 获取系统 Logo - -这些接口需要 token 认证,但在应用启动时用户可能还没登录,导致接口调用失败。 - -### 调用时机问题 - -``` -应用启动 - ↓ -Vue 实例 mounted - ↓ -调用 getSysTitle ← ❌ 此时可能未登录 - ↓ -调用后端接口 - ↓ -没有 token,接口报错 ❌ -``` - -## ✅ 解决方案 - -### 方案:只在已登录时调用接口 - -**核心思路**: -1. 在调用 `getSysTitle` 前检查是否已登录(是否有 token) -2. 已登录:调用接口获取系统标题 -3. 未登录:直接使用默认标题 - -### 修改 1:`demo-project/src/main.js` - -**修改前**: -```javascript -mounted() { - AdminFramework.uiTool.setRem() - - // ❌ 无条件调用,可能导致未登录时接口报错 - this.$store.dispatch('app/getSysTitle', { - defaultTitle: 'Demo 管理系统', - defaultLogo: '' - }) -} -``` - -**修改后**: -```javascript -mounted() { - AdminFramework.uiTool.setRem() - - // ✅ 检查是否已登录 - const token = this.$store.state.user.token - if (token) { - // 已登录,调用接口获取系统标题 - this.$store.dispatch('app/getSysTitle', { - defaultTitle: 'Demo 管理系统', - defaultLogo: '' - }) - } else { - // 未登录,直接设置默认标题 - document.title = 'Demo 管理系统' - } -} -``` - -### 修改 2:`src/store/app.js` 的 `getSysTitle` action - -**修改前**: -```javascript -async getSysTitle({ state, commit }, { defaultTitle = '智能代码平台', defaultLogo = '' }) { - let formModel = { - title: defaultTitle, - logoUrl: defaultLogo - } - - try { - // ❌ 直接调用接口,不检查是否已登录 - let res1 = await paramSetupServer.getOne('sys_title') - if (res1 && res1.data) { - formModel.title = res1.data.value - document.title = res1.data.value - } - let res2 = await paramSetupServer.getOne('sys_logo') - if (res2 && res2.data) { - formModel.logoUrl = res2.data.value - } - } catch (error) { - console.warn('获取系统标题失败,使用默认标题:', error || '接口调用失败') - document.title = formModel.title - } - - commit('setSysTitle', formModel) -} -``` - -**修改后**: -```javascript -async getSysTitle({ state, commit, rootState }, { defaultTitle = '智能代码平台', defaultLogo = '' }) { - let formModel = { - title: defaultTitle, - logoUrl: defaultLogo - } - - // ✅ 检查是否已登录(有 token) - const token = rootState.user.token - - if (token) { - // 已登录,尝试从后端获取系统标题 - try { - let res1 = await paramSetupServer.getOne('sys_title') - if (res1 && res1.data) { - formModel.title = res1.data.value - document.title = res1.data.value - } - let res2 = await paramSetupServer.getOne('sys_logo') - if (res2 && res2.data) { - formModel.logoUrl = res2.data.value - } - } catch (error) { - console.warn('获取系统标题失败,使用默认标题:', error || '接口调用失败') - document.title = formModel.title - } - } else { - // 未登录,直接使用默认标题 - document.title = formModel.title - } - - commit('setSysTitle', formModel) -} -``` - -## 📊 修复后的流程 - -### 未登录时 - -``` -应用启动 - ↓ -Vue 实例 mounted - ↓ -检查 token - ↓ -token 不存在 ✅ - ↓ -直接设置默认标题 "Demo 管理系统" - ↓ -不调用后端接口 ✅ -``` - -### 已登录时 - -``` -应用启动 - ↓ -Vue 实例 mounted - ↓ -检查 token - ↓ -token 存在 ✅ - ↓ -调用 getSysTitle action - ↓ -检查 rootState.user.token - ↓ -token 存在 ✅ - ↓ -调用后端接口获取系统标题 - ↓ -成功:使用后端返回的标题 -失败:使用默认标题 -``` - -### 登录流程 - -``` -用户登录 - ↓ -保存 token 到 store - ↓ -刷新页面 - ↓ -应用重新启动 - ↓ -Vue 实例 mounted - ↓ -检查 token(此时有 token)✅ - ↓ -调用 getSysTitle 获取系统标题 -``` - -## 🎯 优化点 - -### 1. 双重检查 - -**第一层检查**(`main.js`): -```javascript -const token = this.$store.state.user.token -if (token) { - this.$store.dispatch('app/getSysTitle', ...) -} -``` - -**第二层检查**(`app.js`): -```javascript -const token = rootState.user.token -if (token) { - // 调用接口 -} -``` - -**为什么需要双重检查?** -- 第一层:避免不必要的 action 调用 -- 第二层:防止 action 被其他地方调用时没有检查 token - -### 2. 默认标题处理 - -**未登录时**: -```javascript -document.title = 'Demo 管理系统' -``` - -**已登录但接口失败时**: -```javascript -document.title = formModel.title // 使用传入的 defaultTitle -``` - -**已登录且接口成功时**: -```javascript -document.title = res1.data.value // 使用后端返回的标题 -``` - -### 3. 错误处理 - -```javascript -try { - // 调用接口 -} catch (error) { - console.warn('获取系统标题失败,使用默认标题:', error || '接口调用失败') - document.title = formModel.title -} -``` - -即使接口调用失败,也会优雅降级到默认标题,不影响用户使用。 - -## ✅ 验证清单 - -### 未登录场景 - -- ✅ 访问首页显示登录页面 -- ✅ 页面标题显示 "Demo 管理系统" -- ✅ 控制台没有接口报错 -- ✅ Network 标签中没有 `sys_parameter/key` 请求 - -### 已登录场景 - -- ✅ 登录成功后刷新页面 -- ✅ 页面标题显示系统标题(如果后端有配置) -- ✅ 如果后端接口失败,显示默认标题 -- ✅ 系统 Logo 正确显示(如果后端有配置) - -### 登录流程 - -- ✅ 输入用户名密码 -- ✅ 点击登录 -- ✅ 登录成功 -- ✅ 页面刷新 -- ✅ 进入系统首页 -- ✅ 系统标题正确显示 - -## 💡 最佳实践 - -### 1. 接口调用前检查认证状态 - -```javascript -// ✅ 好的做法 -if (token) { - await api.getData() -} - -// ❌ 不好的做法 -try { - await api.getData() // 可能因为没有 token 而失败 -} catch (error) { - // 处理错误 -} -``` - -### 2. 提供默认值 - -```javascript -// ✅ 好的做法 -const title = res.data?.value || defaultTitle - -// ❌ 不好的做法 -const title = res.data.value // 可能是 undefined -``` - -### 3. 优雅降级 - -```javascript -// ✅ 好的做法 -if (token) { - try { - const data = await api.getData() - useData(data) - } catch (error) { - useDefaultData() - } -} else { - useDefaultData() -} -``` - -### 4. 避免不必要的请求 - -```javascript -// ✅ 好的做法 -if (needData && token) { - await api.getData() -} - -// ❌ 不好的做法 -await api.getData() // 无论是否需要都请求 -``` - -## 🔧 相关修改 - -### 其他可能需要检查的地方 - -如果项目中还有其他在应用启动时调用的接口,也需要检查是否需要 token: - -1. **检查 `main.js` 的 `mounted` 钩子** - - 确保所有接口调用都检查了 token - -2. **检查 `App.vue` 的 `mounted` 钩子** - - 确保没有未登录时调用需要认证的接口 - -3. **检查路由守卫** - - 确保路由守卫正确处理未登录的情况 - -4. **检查 Vuex actions** - - 确保需要认证的 actions 都检查了 token - -## 📝 总结 - -### 修复的问题 - -- ✅ 未登录时不再调用需要认证的接口 -- ✅ 避免了接口报错 -- ✅ 提供了优雅的降级方案 -- ✅ 改善了用户体验 - -### 代码改进 - -- **更健壮**:双重检查确保不会在未登录时调用接口 -- **更友好**:即使接口失败也能正常显示默认标题 -- **更清晰**:代码逻辑更容易理解和维护 - ---- - -**未登录接口调用问题已修复!** 🎉 - -现在系统会智能判断是否已登录,只在必要时调用后端接口。 - diff --git a/demo-project/_doc/权限菜单组件配置指南.md b/demo-project/_doc/权限菜单组件配置指南.md deleted file mode 100644 index c0d5d3e..0000000 --- a/demo-project/_doc/权限菜单组件配置指南.md +++ /dev/null @@ -1,575 +0,0 @@ -# 权限菜单组件配置指南 - -## 🎯 核心问题 - -**问题**:后端权限菜单接口返回的组件路径需要映射到实际组件,否则会显示 404。 - -**解决**:在 `Vue.use()` 时传入 `componentMap` 参数,一次性注册所有业务组件。 - -## 📝 配置步骤 - -### 第一步:查看权限菜单接口返回的组件路径 - -后端接口返回的菜单数据示例: -```json -{ - "code": 0, - "data": [ - { "component": "home/index.vue" }, - { "component": "system/sys_user.vue" }, - { "component": "ball/games.vue" }, - { "component": "order/pay_orders.vue" }, - { "component": "ball/wch_users.vue" } - ] -} -``` - -### 第二步:创建对应的业务组件 - -在项目中创建对应的组件文件: -``` -src/views/ -├── ball/ -│ ├── games.vue -│ └── wch_users.vue -└── order/ - └── pay_orders.vue -``` - -### 第三步:在 main.js 中配置组件映射 - -```javascript -import Vue from 'vue' -import AdminFramework from '../../src/index.js' -import config from './config' - -// ✅ 导入所有业务组件(根据权限菜单接口的 component 字段) -import GamesComponent from './views/ball/games.vue' -import PayOrdersComponent from './views/order/pay_orders.vue' -import WchUsersComponent from './views/ball/wch_users.vue' - -// 使用框架 -Vue.use(AdminFramework, { - config, - ViewUI, - VueRouter, - Vuex, - createPersistedState, - // ✅ 一次性注册所有组件映射 - componentMap: { - 'ball/games': GamesComponent, - 'order/pay_orders': PayOrdersComponent, - 'ball/wch_users': WchUsersComponent - // 添加更多业务组件... - } -}) - -// 创建 Vue 实例 -new Vue({ - el: '#app', - router: AdminFramework.router, - store: AdminFramework.store, - render: h => h(App), - mounted() { - // 设置权限菜单(会自动加载映射的组件) - this.$store.dispatch('user/setAuthorityMenus', { - Main: AdminFramework.Main, - ParentView: AdminFramework.ParentView, - Page404: AdminFramework.Page404 - }) - } -}) -``` - -## 🔧 两种配置方式 - -### 方式一:在 Vue.use 时配置(推荐) - -```javascript -Vue.use(AdminFramework, { - config, - ViewUI, - VueRouter, - Vuex, - createPersistedState, - componentMap: { - 'ball/games': GamesComponent, - 'order/pay_orders': PayOrdersComponent - } -}) -``` - -**优点**: -- ✅ 集中配置,清晰明了 -- ✅ 在框架初始化时就完成映射 -- ✅ 代码简洁 - -### 方式二:使用 addComponentMap 方法 - -```javascript -Vue.use(AdminFramework, { config, ViewUI, VueRouter, Vuex, createPersistedState }) - -// 之后添加映射 -AdminFramework.addComponentMap({ - 'ball/games': GamesComponent, - 'order/pay_orders': PayOrdersComponent -}) -``` - -**适用场景**: -- 需要动态添加组件映射 -- 分模块配置 - -## 📋 完整示例 - -### 根据你的权限菜单接口配置 - -查看你的接口返回数据,列出所有 `component` 字段: - -```javascript -// 权限菜单返回的组件列表: -// - home/index.vue -// - system/sys_user.vue -// - system/sys_role.vue -// - system_high/sys_menu.vue -// - system/sys_log.vue -// - system/sys_param_setup.vue -// - ball/games.vue ← 业务组件,需要自己创建 -// - ball/wch_users.vue ← 业务组件,需要自己创建 -// - ball/venues.vue ← 业务组件,需要自己创建 -// - order/pay_orders.vue ← 业务组件,需要自己创建 -// - order/wch_wallets.vue ← 业务组件,需要自己创建 -// - users/user_follows.vue ← 业务组件,需要自己创建 -``` - -### 完整的 main.js 配置 - -```javascript -import Vue from 'vue' -import VueRouter from 'vue-router' -import Vuex from 'vuex' -import ViewUI from 'view-design' -import createPersistedState from 'vuex-persistedstate' -import 'view-design/dist/styles/iview.css' - -import AdminFramework from '../../src/index.js' -import config from './config' -import App from './App.vue' - -// ==================== 导入业务组件 ==================== -// 球局模块 -import GamesComponent from './views/ball/games.vue' -import WchUsersComponent from './views/ball/wch_users.vue' -import VenuesComponent from './views/ball/venues.vue' -import GameParticipantsComponent from './views/ball/game_participants.vue' -import GameCommentsComponent from './views/ball/game_comments.vue' - -// 订单模块 -import PayOrdersComponent from './views/order/pay_orders.vue' -import WchWalletsComponent from './views/order/wch_wallets.vue' -import WalletTransactionsComponent from './views/order/wallet_transactions.vue' -import TransferDetailsComponent from './views/order/transfer_details.vue' -import FrozenFundsComponent from './views/order/frozen_funds.vue' - -// 用户模块 -import UserFollowsComponent from './views/users/user_follows.vue' -import RecommendBlocksComponent from './views/users/recommend_blocks.vue' -import UserTrackingComponent from './views/users/user_tracking.vue' - -// 资源模块 -import ResourcesComponent from './views/statistics/resources.vue' -import NtrQuestionsComponent from './views/ntrp/ntr_questions.vue' -import NtrRecordsComponent from './views/ntrp/ntr_records.vue' - -// 消息模块 -import MsgNotificationsComponent from './views/message/msg_notifications.vue' - -// 使用框架 -Vue.use(AdminFramework, { - config, - ViewUI, - VueRouter, - Vuex, - createPersistedState, - // ✅ 组件映射表 - componentMap: { - // 球局模块 - 'ball/games': GamesComponent, - 'ball/wch_users': WchUsersComponent, - 'ball/venues': VenuesComponent, - 'ball/game_participants': GameParticipantsComponent, - 'ball/game_comments': GameCommentsComponent, - - // 订单模块 - 'order/pay_orders': PayOrdersComponent, - 'order/wch_wallets': WchWalletsComponent, - 'order/wallet_transactions': WalletTransactionsComponent, - 'order/transfer_details': TransferDetailsComponent, - 'order/frozen_funds': FrozenFundsComponent, - - // 用户模块 - 'users/user_follows': UserFollowsComponent, - 'users/recommend_blocks': RecommendBlocksComponent, - 'users/user_tracking': UserTrackingComponent, - - // 资源模块 - 'statistics/resources': ResourcesComponent, - 'ntrp/ntr_questions': NtrQuestionsComponent, - 'ntrp/ntr_records': NtrRecordsComponent, - - // 消息模块 - 'message/msg_notifications': MsgNotificationsComponent - } -}) - -// 创建 Vue 实例 -new Vue({ - el: '#app', - router: AdminFramework.router, - store: AdminFramework.store, - render: h => h(App), - mounted() { - AdminFramework.uiTool.setRem() - - // 设置权限菜单(会自动根据映射表加载组件) - this.$store.dispatch('user/setAuthorityMenus', { - Main: AdminFramework.Main, - ParentView: AdminFramework.ParentView, - Page404: AdminFramework.Page404 - }) - - // 获取系统标题 - this.$store.dispatch('app/getSysTitle', { - defaultTitle: 'Demo 管理系统', - defaultLogo: '' - }) - } -}) - -// 响应式适配 -window.addEventListener('load', AdminFramework.uiTool.setRem) -window.addEventListener('resize', AdminFramework.uiTool.setRem) -``` - -## 🎯 关键要点 - -### 1. 路径命名规则 - -**后端返回**: -```json -{ "component": "ball/games.vue" } -``` - -**项目文件**: -``` -src/views/ball/games.vue -``` - -**配置映射**(不需要 .vue 后缀): -```javascript -componentMap: { - 'ball/games': GamesComponent // ✅ 不需要写 .vue -} -``` - -**框架会自动处理**: -- `ball/games` ✅ -- `ball/games.vue` ✅ - -### 2. 框架内置组件 - -以下组件**无需配置**,框架已自动映射: -- `home/index.vue` → HomePage -- `system/sys_user.vue` → SysUser -- `system/sys_role.vue` → SysRole -- `system/sys_log.vue` → SysLog -- `system/sys_param_setup.vue` → SysParamSetup -- `system_high/sys_menu.vue` → SysMenu -- `system_high/sys_control.vue` → SysControl -- `system_high/sys_title.vue` → SysTitle - -### 3. 业务组件 - -需要在项目中: -1. **创建组件文件** -2. **在 main.js 中导入** -3. **在 componentMap 中配置** - -## ⚠️ 组件未找到的提示 - -如果后端返回的组件路径没有在映射表中,会显示: - -``` -┌────────────────────────────────────┐ -│ ⚠️ 警告 │ -│ 页面组件未加载: ball/games.vue │ -│ 请在项目中创建此组件或在组件映射表中注册 │ -└────────────────────────────────────┘ -``` - -**控制台也会输出**: -``` -⚠️ 组件未找到: ball/games.vue,使用占位组件 -``` - -## 💡 快速配置技巧 - -### 技巧1:批量导入组件 - -```javascript -// 按模块组织导入 -// 球局模块 -import GamesComponent from './views/ball/games.vue' -import WchUsersComponent from './views/ball/wch_users.vue' - -// 订单模块 -import PayOrdersComponent from './views/order/pay_orders.vue' -import WchWalletsComponent from './views/order/wch_wallets.vue' -``` - -### 技巧2:使用对象展开 - -```javascript -// 定义模块组件映射 -const ballComponents = { - 'ball/games': GamesComponent, - 'ball/wch_users': WchUsersComponent -} - -const orderComponents = { - 'order/pay_orders': PayOrdersComponent, - 'order/wch_wallets': WchWalletsComponent -} - -// 合并配置 -Vue.use(AdminFramework, { - config, - ViewUI, - VueRouter, - Vuex, - createPersistedState, - componentMap: { - ...ballComponents, - ...orderComponents - } -}) -``` - -### 技巧3:注释待开发的组件 - -```javascript -componentMap: { - 'ball/games': GamesComponent, // ✅ 已开发 - // 'ball/venues': VenuesComponent, // ⏳ 待开发 - // 'order/pay_orders': PayOrdersComponent // ⏳ 待开发 -} -``` - -## 📊 配置流程图 - -``` -后端接口返回菜单 - ↓ -查看所有 component 字段 - ↓ -在项目中创建对应的 .vue 文件 - ↓ -在 main.js 中导入组件 - ↓ -在 componentMap 中配置映射 - ↓ -框架自动生成路由 - ↓ -页面正常显示 ✅ -``` - -## 🚀 实战示例 - -### 示例:添加"球局管理"页面 - -#### 1. 后端返回的菜单 -```json -{ - "id": 123, - "name": "球局表", - "path": "games", - "component": "ball/games.vue", - "type": "页面" -} -``` - -#### 2. 创建组件文件 -```vue - - - - -``` - -#### 3. 在 main.js 中配置 -```javascript -// 导入 -import GamesComponent from './views/ball/games.vue' - -// 配置映射 -Vue.use(AdminFramework, { - config, - ViewUI, - VueRouter, - Vuex, - createPersistedState, - componentMap: { - 'ball/games': GamesComponent // ✅ 添加映射 - } -}) -``` - -#### 4. 完成! - -登录后,权限菜单中的"球局表"会自动加载 `GamesComponent` 组件。 - -## 📚 框架自动处理 - -### 已自动映射的系统组件 - -| 后端路径 | 组件 | 说明 | -|---------|------|------| -| `home/index.vue` | HomePage | 主页 | -| `system/sys_user.vue` | SysUser | 用户管理 | -| `system/sys_role.vue` | SysRole | 角色管理 | -| `system/sys_log.vue` | SysLog | 日志管理 | -| `system/sys_param_setup.vue` | SysParamSetup | 参数设置 | -| `system_high/sys_menu.vue` | SysMenu | 菜单管理 | -| `system_high/sys_control.vue` | SysControl | 控制器管理 | -| `system_high/sys_title.vue` | SysTitle | 系统标题设置 | - -### 需要手动配置的业务组件 - -根据你的权限菜单接口,需要配置: -- ✅ `ball/games.vue` - 球局表 -- ✅ `ball/wch_users.vue` - 微信用户 -- ✅ `ball/venues.vue` - 场地表 -- ✅ `ball/game_participants.vue` - 球局参与者 -- ✅ `ball/game_comments.vue` - 球局评论 -- ✅ `order/pay_orders.vue` - 支付订单 -- ✅ `order/wch_wallets.vue` - 用户钱包 -- ✅ `order/wallet_transactions.vue` - 交易记录 -- ✅ `order/transfer_details.vue` - 转账详情 -- ✅ `order/frozen_funds.vue` - 冻结资金 -- ✅ `users/user_follows.vue` - 用户关注 -- ✅ `users/recommend_blocks.vue` - 推荐屏蔽 -- ✅ `users/user_tracking.vue` - 行为追踪 -- ✅ `statistics/resources.vue` - 图库资源表 -- ✅ `ntrp/ntr_questions.vue` - 题库管理 -- ✅ `ntrp/ntr_records.vue` - 测试记录 -- ✅ `message/msg_notifications.vue` - 消息管理 -- ✅ `system/wch_professions.vue` - 职业管理 -- ✅ `system/wch_cities.vue` - 城市管理 -- ✅ `business/hot_city_qr.vue` - 热门城市 - -## 🎯 推荐配置模板 - -```javascript -import Vue from 'vue' -import VueRouter from 'vue-router' -import Vuex from 'vuex' -import ViewUI from 'view-design' -import createPersistedState from 'vuex-persistedstate' -import 'view-design/dist/styles/iview.css' - -import AdminFramework from '../../src/index.js' -import config from './config' -import App from './App.vue' - -// ==================== 导入业务组件 ==================== -// TODO: 根据权限菜单接口返回的 component 字段,导入对应组件 - -// 使用框架 -Vue.use(AdminFramework, { - config, - ViewUI, - VueRouter, - Vuex, - createPersistedState, - componentMap: { - // TODO: 在这里添加业务组件映射 - // 格式:'后端返回的路径(不含.vue)': 导入的组件 - } -}) - -// 创建 Vue 实例 -new Vue({ - el: '#app', - router: AdminFramework.router, - store: AdminFramework.store, - render: h => h(App), - mounted() { - AdminFramework.uiTool.setRem() - - this.$store.dispatch('user/setAuthorityMenus', { - Main: AdminFramework.Main, - ParentView: AdminFramework.ParentView, - Page404: AdminFramework.Page404 - }) - - this.$store.dispatch('app/getSysTitle', { - defaultTitle: config.title, - defaultLogo: '' - }) - } -}) - -window.addEventListener('load', AdminFramework.uiTool.setRem) -window.addEventListener('resize', AdminFramework.uiTool.setRem) -``` - -## 📝 总结 - -### ✅ 优化后的优势 - -1. **代码简洁** - - 不需要重复写 `.vue` 后缀的映射 - - 框架自动生成 - -2. **集中配置** - - 在 `Vue.use()` 时一次性配置所有映射 - - 清晰明了 - -3. **灵活扩展** - - 可以随时使用 `addComponentMap()` 添加新映射 - - 支持分模块配置 - -### 🔗 相关文档 - -- [../README.md](../README.md) - 项目说明 -- [../CHANGELOG.md](../CHANGELOG.md) - 更新日志 -- [../../完整使用文档.md](../../完整使用文档.md) - 框架文档 - ---- - -**配置完成后,重启项目即可看到所有权限菜单中的页面!** 🎉 - diff --git a/demo-project/_doc/权限菜单说明.md b/demo-project/_doc/权限菜单说明.md deleted file mode 100644 index 68a80e5..0000000 --- a/demo-project/_doc/权限菜单说明.md +++ /dev/null @@ -1,326 +0,0 @@ -# 权限菜单处理说明 - -## 📊 当前情况 - -### 登录接口返回的数据 -```json -{ - "code": 0, - "message": "请求成功", - "data": { - "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", - "user": { - "id": 1, - "name": "zc", - "roleId": 6 - }, - "authorityMenus": "[1,142,121,143,144,145,124,147,120,123,125,132,133,126,136,137,138,139,151,152,153,154,149,150,156,157,158,122,159,5,11,12,13,67,68,15]" - } -} -``` - -### 问题分析 - -**登录接口返回的 `authorityMenus`**: -- 类型:字符串 -- 内容:菜单 ID 数组 `"[1,142,121,...]"` -- 作用:表示用户有权限访问的菜单 ID 列表 - -**框架期望的 `authorityMenus`**: -- 类型:对象数组 -- 内容:完整的菜单对象,包含以下字段: - ```javascript - { - id: 1, - name: "系统管理", - path: "/system", - component: "...", - parent_id: 0, - type: "菜单", - is_show_menu: 1, - children: [...] - } - ``` - -## 🔧 解决方案 - -### 方案一:调用 authorityMenus 接口(当前实现) - -登录成功后,调用 `/sys_user/authorityMenus` 接口获取完整的菜单对象数组。 - -**流程:** -1. 用户登录 → 获取 token 和菜单 ID 列表 -2. 保存 token -3. 调用 `authorityMenus` 接口 → 获取完整菜单对象数组 -4. 生成路由 - -**代码实现:** -```javascript -// src/store/user.js -async handleLogin({ state, commit, dispatch }, { userFrom, Main, ParentView, Page404 }) { - let res = await userServerInstance.login(userFrom) - - let token = res.data.token - let user = res.data.user - - commit('setUserName', user.name.trim()) - commit('setToken', token) - - // 调用 authorityMenus 接口获取完整菜单数据 - await dispatch('setAuthorityMenus', { Main, ParentView, Page404 }) -} -``` - -**优点:** -- 简单直接 -- 不需要修改后端接口 - -**缺点:** -- 需要额外的 HTTP 请求 -- 如果 authorityMenus 接口失败,用户无法进入系统 - -### 方案二:后端直接返回完整菜单对象(推荐) - -修改后端登录接口,直接返回完整的菜单对象数组,而不是菜单 ID 数组。 - -**修改后的返回数据:** -```json -{ - "code": 0, - "message": "请求成功", - "data": { - "token": "...", - "user": {...}, - "authorityMenus": [ - { - "id": 1, - "name": "系统管理", - "path": "/system", - "component": "Main", - "parent_id": 0, - "type": "菜单", - "is_show_menu": 1, - "children": [...] - }, - ... - ] - } -} -``` - -**优点:** -- 减少 HTTP 请求 -- 登录更快 -- 数据一致性更好 - -**缺点:** -- 需要修改后端代码 - -## 📝 当前实现 - -### 登录流程 - -1. **用户输入用户名密码** - ```javascript - // src/views/login/login.vue - handleSubmit({ userName, password }) { - let userFrom = { name: userName, password: password } - this.handleLogin({ userFrom, Main, ParentView, Page404 }) - } - ``` - -2. **调用登录接口** - ```javascript - // src/store/user.js - let res = await userServerInstance.login(userFrom) - // 返回: { code: 0, data: { token, user, authorityMenus: "[1,2,3...]" } } - ``` - -3. **保存 token 和用户信息** - ```javascript - commit('setUserName', user.name.trim()) - commit('setToken', token) - ``` - -4. **获取完整菜单数据** - ```javascript - // 调用 /sys_user/authorityMenus 接口 - await dispatch('setAuthorityMenus', { Main, ParentView, Page404 }) - ``` - -5. **处理菜单数据** - ```javascript - // src/store/user.js - setAuthorityMenus - let res = await userServerInstance.authorityMenus() - // 期望返回: { code: 0, data: [{id, name, path, ...}, ...] } - - let menus = res.data - commit('setAuthorityMenus', JSON.stringify(menus)) - - // 生成路由 - let mainMenu = uiTool.getRoutes(Main, ParentView, Page404) - commit('setMenuList', mainMenu.children) - ``` - -6. **刷新页面进入系统** - ```javascript - window.location.reload() - ``` - -## ⚠️ 需要确认的事项 - -### 1. authorityMenus 接口返回的数据格式 - -请确认 `/sys_user/authorityMenus` 接口返回的数据格式: - -**期望格式:** -```json -{ - "code": 0, - "message": "请求成功", - "data": [ - { - "id": 1, - "name": "首页", - "path": "/home", - "component": "home/index", - "parent_id": 0, - "type": "页面", - "is_show_menu": 1, - "icon": "md-home", - "sort": 1 - }, - { - "id": 5, - "name": "系统管理", - "path": "/system", - "component": "", - "parent_id": 0, - "type": "菜单", - "is_show_menu": 1, - "icon": "md-settings", - "sort": 2, - "children": [ - { - "id": 11, - "name": "用户管理", - "path": "/system/user", - "component": "system/sys_user", - "parent_id": 5, - "type": "页面", - "is_show_menu": 1 - } - ] - } - ] -} -``` - -### 2. 菜单对象的必需字段 - -每个菜单对象需要包含以下字段: - -| 字段 | 类型 | 说明 | 必需 | -|------|------|------|------| -| id | Number | 菜单 ID | ✅ | -| name | String | 菜单名称 | ✅ | -| path | String | 路由路径 | ✅ | -| component | String | 组件路径 | ✅ | -| parent_id | Number | 父菜单 ID(0 表示顶级菜单) | ✅ | -| type | String | 类型:"菜单"、"页面"、"功能" | ✅ | -| is_show_menu | Number | 是否显示在菜单中(1=显示,0=隐藏) | ✅ | -| icon | String | 图标名称 | ❌ | -| sort | Number | 排序 | ❌ | -| children | Array | 子菜单 | ❌ | - -## 🐛 调试方法 - -### 1. 查看 authorityMenus 接口返回 - -在浏览器控制台查看: -```javascript -// 登录成功后,查看控制台日志 -获取权限菜单返回: { code: 0, data: [...] } -处理权限菜单: [...] -生成的主菜单: { path: '/', children: [...] } -``` - -### 2. 查看 localStorage - -打开浏览器开发者工具 → Application → Local Storage: -```javascript -authorityMenus: "[{\"id\":1,\"name\":\"首页\",...}]" -``` - -### 3. 查看网络请求 - -打开浏览器开发者工具 → Network: -1. 查看 `/sys_user/login` 请求的响应 -2. 查看 `/sys_user/authorityMenus` 请求的响应 - -## 🎯 测试步骤 - -### 1. 测试登录 -```bash -# 启动项目 -cd demo-project -npm run dev - -# 打开浏览器 -http://localhost:8080 - -# 输入用户名密码 -用户名: zc -密码: *** - -# 点击登录 -``` - -### 2. 查看控制台日志 -应该看到: -``` -登录接口返回: { code: 0, data: { token, user, authorityMenus } } -登录返回的菜单 IDs: "[1,142,121,...]" -获取权限菜单返回: { code: 0, data: [...] } -处理权限菜单: [...] -生成的主菜单: { path: '/', children: [...] } -``` - -### 3. 验证登录成功 -- ✅ 显示"登录成功!"提示 -- ✅ 页面刷新 -- ✅ 进入系统首页 -- ✅ 左侧显示菜单 - -## 💡 建议 - -### 短期方案(当前实现) -保持现有实现,登录后调用 `authorityMenus` 接口获取完整菜单数据。 - -### 长期方案(推荐) -建议后端修改登录接口,直接返回完整的菜单对象数组,减少 HTTP 请求,提升用户体验。 - -**修改建议:** -```javascript -// 后端登录接口返回 -{ - "code": 0, - "message": "请求成功", - "data": { - "token": "...", - "user": {...}, - "authorityMenus": [ - // 完整的菜单对象数组,而不是 ID 数组字符串 - { id: 1, name: "首页", path: "/home", ... }, - { id: 5, name: "系统管理", path: "/system", children: [...] } - ] - } -} -``` - -这样前端就可以直接使用,不需要额外的 HTTP 请求。 - ---- - -**当前状态**:登录功能正常,需要确认 `authorityMenus` 接口返回的数据格式是否正确。 - diff --git a/demo-project/_doc/登录功能修复说明.md b/demo-project/_doc/登录功能修复说明.md deleted file mode 100644 index 0d99aee..0000000 --- a/demo-project/_doc/登录功能修复说明.md +++ /dev/null @@ -1,277 +0,0 @@ -# 登录功能修复说明 - -## 🔧 修复的问题 - -### 问题描述 -登录时出现错误:`Cannot read properties of undefined (reading 'message')` - -### 根本原因 -登录接口返回的数据结构与代码中期望的不一致。 - -## 📊 数据结构分析 - -### 后端返回的数据结构 -```json -{ - "code": 0, - "message": "请求成功", - "data": { - "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", - "user": { - "id": 1, - "name": "zc", - "password": "d3df61764ee9a26091f714b88958caef", - "roleId": 6, - "create_time": "2022-10-24 05:45:40", - "last_modify_time": "2025-09-12 06:48:54" - }, - "authorityMenus": "[1,142,121,143,144,145,124,147,120,123,125,132,133,126,136,137,138,139,151,152,153,154,149,150,156,157,158,122,159,5,11,12,13,67,68,15]" - } -} -``` - -### HTTP 工具类的处理流程 - -1. **axios 响应拦截器**(`src/utils/http.js` 第 55-69 行) - ```javascript - instance.interceptors.response.use( - response => { - if (response.status === 200) { - if (response.data && response.data.code === 0) { - return response // 返回整个 response 对象 - } else { - // code 不为 0,拒绝 - return Promise.reject(response.data.message) - } - } - } - ) - ``` - -2. **http.post 方法**(`src/utils/http.js` 第 176-191 行) - ```javascript - async post(url, param, config) { - let instance = this.getHttpInstance(config) - let promise = new Promise((resolve, reject) => { - instance.post(url, param).then(response => { - resolve(response.data) // 返回 response.data - }) - }) - return promise - } - ``` - -3. **最终在 user.js 中得到的数据结构** - ```javascript - let res = await userServerInstance.login(userFrom) - // res 的结构是: - // { - // code: 0, - // message: "请求成功", - // data: { token, user, authorityMenus } - // } - ``` - -## ✅ 修复方案 - -### 1. 修复 `src/store/user.js` 中的 `handleLogin` 方法 - -**修复前:** -```javascript -let res = await userServerInstance.login(userFrom) -let token = res.data.token // ❌ 错误:res.data 是整个数据对象 -let user = res.data.user -``` - -**修复后:** -```javascript -let res = await userServerInstance.login(userFrom) - -// 检查返回数据结构 -if (res.code !== 0) { - throw new Error(res.message || '登录失败') -} - -// 实际数据在 res.data 中 -let token = res.data.token // ✅ 正确 -let user = res.data.user // ✅ 正确 -let authorityMenus = res.data.authorityMenus // ✅ 正确 -``` - -### 2. 修复 `src/store/user.js` 中的 `setAuthorityMenus` 方法 - -**修复前:** -```javascript -let res = await userServerInstance.authorityMenus() -let authorityMenus = res.data // ❌ 可能不正确 -``` - -**修复后:** -```javascript -let res = await userServerInstance.authorityMenus() - -// res 的结构是 { code, message, data } -if (res && res.code === 0 && res.data) { - menus = res.data // ✅ 正确获取数据 -} -``` - -### 3. 增强错误处理 - -在 `src/views/login/login.vue` 中: - -```javascript -async handleSubmit({ userName, password }) { - try { - let userFrom = { name: userName, password: password } - await this.handleLogin({ - userFrom, - Main, - ParentView, - Page404 - }) - this.$Message.success('登录成功!') - window.location.reload() - } catch (error) { - console.error('登录失败:', error) - - // 处理不同类型的错误 - let errorMsg = '登录失败,请检查用户名和密码' - - if (error) { - if (typeof error === 'string') { - errorMsg = error - } else if (error.message) { - errorMsg = error.message - } else if (error.data && error.data.message) { - errorMsg = error.data.message - } - } - - this.$Message.error(errorMsg) - } -} -``` - -## 🎯 登录流程 - -### 完整的登录流程 - -1. **用户输入用户名和密码** - - 组件:`src/components/login-form/login-form.vue` - - 触发事件:`on-success-valid` - -2. **登录页面处理** - - 组件:`src/views/login/login.vue` - - 调用:`handleLogin` action - -3. **Vuex Action 处理** - - 文件:`src/store/user.js` - - 方法:`handleLogin` - - 步骤: - 1. 调用登录接口 - 2. 保存 token 和用户名 - 3. 处理权限菜单 - 4. 生成路由 - -4. **HTTP 请求** - - 文件:`src/api/system/userServer.js` - - 接口:`POST /sys_user/login` - - 参数:`{ name, password }` - -5. **登录成功后** - - 显示成功提示 - - 刷新页面 - - 自动跳转到首页 - -## 📝 测试步骤 - -### 1. 启动项目 -```bash -cd demo-project -npm run dev -``` - -### 2. 打开浏览器 -访问:`http://localhost:8080` - -### 3. 输入登录信息 -- 用户名:`zc`(或其他有效用户名) -- 密码:对应的密码 - -### 4. 查看控制台日志 -应该能看到以下日志: -``` -登录接口返回: { code: 0, message: "请求成功", data: {...} } -处理权限菜单: [1,142,121,...] -生成的主菜单: { path: '/', children: [...] } -✅ Demo 项目启动成功! -``` - -### 5. 验证登录成功 -- ✅ 显示"登录成功!"提示 -- ✅ 页面刷新 -- ✅ 跳转到系统首页 -- ✅ 显示用户名和菜单 - -## 🐛 调试技巧 - -### 查看登录请求 -1. 打开浏览器开发者工具(F12) -2. 切换到 Network 标签 -3. 输入用户名密码,点击登录 -4. 查看 `/sys_user/login` 请求 -5. 检查 Response 数据结构 - -### 查看 Vuex 状态 -1. 安装 Vue DevTools 浏览器插件 -2. 打开 Vue DevTools -3. 切换到 Vuex 标签 -4. 查看 `user` 模块的状态: - - `token`:应该有值 - - `userName`:应该是登录的用户名 - - `authorityMenus`:应该是权限菜单数组 - -### 查看 localStorage -1. 打开浏览器开发者工具(F12) -2. 切换到 Application 标签 -3. 展开 Local Storage -4. 查看存储的数据: - - `demo_token`:token 值 - - `userName`:用户名 - - `authorityMenus`:权限菜单 JSON 字符串 - -## ⚠️ 注意事项 - -### 1. authorityMenus 的数据格式 -后端返回的 `authorityMenus` 是一个 **字符串**: -```json -"authorityMenus": "[1,142,121,143,...]" -``` - -代码会自动解析这个字符串为数组。 - -### 2. 权限菜单的处理 -- 登录接口返回的 `authorityMenus` 是菜单 ID 数组 -- 需要根据这些 ID 从菜单配置中生成实际的路由 -- 使用 `uiTool.getRoutes()` 方法生成路由 - -### 3. Token 的使用 -- Token 保存在 Vuex store 和 localStorage 中 -- 每次 HTTP 请求都会自动带上 token(在请求头 `admin-token` 中) -- Token 失效时会自动跳转到登录页 - -## 🎉 修复完成 - -现在登录功能应该可以正常工作了! - -### 验证清单 -- ✅ 登录接口正确调用 -- ✅ Token 正确保存 -- ✅ 用户信息正确保存 -- ✅ 权限菜单正确处理 -- ✅ 登录成功后正确跳转 -- ✅ 错误处理完善 - -如果还有问题,请查看浏览器控制台的错误信息和网络请求详情。 - diff --git a/demo-project/_doc/登录功能完整修复报告.md b/demo-project/_doc/登录功能完整修复报告.md deleted file mode 100644 index f9214db..0000000 --- a/demo-project/_doc/登录功能完整修复报告.md +++ /dev/null @@ -1,386 +0,0 @@ -# 登录功能完整修复报告 - -## 📋 问题总结 - -### 1. ✅ 登录接口调用成功 -- 接口返回:`{ code: 0, message: "请求成功", data: {...} }` -- Token 获取成功 -- 用户信息获取成功 - -### 2. ⚠️ authorityMenus 接口失败 -- 问题:`/sys_user/authorityMenus` 接口调用失败 -- 影响:无法从后端获取完整的菜单数据 -- 解决:使用默认菜单配置 + 根据 ID 过滤 - -### 3. ⚠️ 系统标题接口失败 -- 问题:`/sys_param_setup/getOne` 接口调用失败 -- 影响:无法获取自定义的系统标题和 Logo -- 解决:使用默认标题 "Demo 管理系统" - -## 🔧 修复内容 - -### 修复 1:数据结构适配 - -**文件**:`src/store/user.js` - -**问题**:登录接口返回的数据结构与代码期望不一致 - -**修复**: -```javascript -// 修复前 -let token = res.data.token // ❌ 错误 - -// 修复后 -if (res.code !== 0) { - throw new Error(res.message) -} -let token = res.data.token // ✅ 正确 -``` - -### 修复 2:authorityMenus 接口失败降级 - -**文件**:`src/store/user.js`、`src/config/menuConfig.js` - -**问题**:`authorityMenus` 接口失败导致无法获取菜单 - -**修复**: -1. 创建默认菜单配置文件 -2. 接口失败时使用默认菜单 -3. 根据登录返回的菜单 ID 过滤菜单 - -```javascript -try { - let res = await userServerInstance.authorityMenus() - menus = res.data -} catch (error) { - console.warn('将使用默认菜单配置') - // 使用默认菜单 + ID 过滤 - menus = filterMenusByIds(menuIds, defaultMenus) -} -``` - -### 修复 3:系统标题接口失败处理 - -**文件**:`src/store/app.js` - -**问题**: -1. 代码中有 debugger 语句 -2. 接口失败时错误处理不完善 - -**修复**: -```javascript -try { - let res1 = await paramSetupServerInstance.getOne('sys_title') - if (res1 && res1.data) { - formModel.title = res1.data.value - document.title = res1.data.value - } -} catch (error) { - console.warn('获取系统标题失败,使用默认标题') - document.title = formModel.title -} -``` - -## 📁 新增文件 - -### `src/config/menuConfig.js` - -默认菜单配置文件,包含: - -1. **首页** (`/home`) -2. **系统管理** - - 用户管理 (`/system/user`) - - 角色管理 (`/system/role`) - - 系统日志 (`/system/log`) - - 参数设置 (`/system/param`) -3. **高级管理** - - 菜单管理 (`/system_high/menu`) - - 控制管理 (`/system_high/control`) - - 系统标题 (`/system_high/title`) - -## 🎯 当前状态 - -### ✅ 正常工作的功能 - -1. **用户登录** - - ✅ 调用登录接口 - - ✅ 保存 token - - ✅ 保存用户信息 - - ✅ 登录成功提示 - -2. **菜单显示** - - ✅ 使用默认菜单配置 - - ✅ 根据权限 ID 过滤菜单 - - ✅ 生成路由 - - ✅ 左侧菜单栏显示 - -3. **页面跳转** - - ✅ 登录后跳转到首页 - - ✅ 可以访问有权限的页面 - - ✅ 路由正常工作 - -4. **系统标题** - - ✅ 使用默认标题 "Demo 管理系统" - - ✅ 页面标题正常显示 - -### ⚠️ 降级处理的功能 - -1. **权限菜单** - - 后端接口失败 - - 使用默认菜单配置 - - 根据 ID 过滤 - -2. **系统标题** - - 后端接口失败 - - 使用默认标题 - -## 🔍 控制台日志 - -### 正常的日志输出 - -``` -✅ Demo 项目启动成功! -框架版本: 1.0.0 -App 组件已挂载 -登录接口返回: { code: 0, data: { token, user, authorityMenus } } -登录返回的菜单 IDs: "[1,142,121,143,144,145,124,147,120,123,125,...]" -获取权限菜单失败: undefined -将使用默认菜单配置 -根据菜单 IDs 过滤后的菜单: [...] -最终处理的权限菜单: [...] -生成的主菜单: { path: '/', children: [...] } -获取系统标题失败,使用默认标题: 接口调用失败 -``` - -### 说明 - -- `获取权限菜单失败: undefined` - 这是正常的,因为后端接口不可用 -- `获取系统标题失败,使用默认标题` - 这是正常的,因为后端接口不可用 -- 这些都是**警告信息**,不影响系统正常使用 - -## 📊 登录流程图 - -``` -用户输入用户名密码 - ↓ -点击登录按钮 - ↓ -调用 /sys_user/login 接口 - ↓ -返回: { code: 0, data: { token, user, authorityMenus: "[1,2,3...]" } } - ↓ -保存 token 和用户信息 - ↓ -解析 authorityMenus 字符串 → 数组 - ↓ -尝试调用 /sys_user/authorityMenus 接口 - ↓ -接口失败 ❌ - ↓ -使用默认菜单配置 - ↓ -根据菜单 ID 数组过滤菜单 - ↓ -生成路由 - ↓ -保存到 Vuex store - ↓ -显示"登录成功!"提示 - ↓ -刷新页面 - ↓ -进入系统首页 ✅ - ↓ -显示左侧菜单栏 -``` - -## 🎉 测试结果 - -### 测试步骤 - -1. **启动项目** - ```bash - cd demo-project - npm run dev - ``` - -2. **访问登录页** - - URL: `http://localhost:8080` - -3. **输入登录信息** - - 用户名:`zc` - - 密码:对应的密码 - -4. **点击登录** - -### 预期结果 - -- ✅ 显示"登录成功!"提示 -- ✅ 页面刷新 -- ✅ 进入系统首页 -- ✅ 左侧显示菜单栏 -- ✅ 顶部显示用户名 "zc" -- ✅ 页面标题显示 "Demo 管理系统" - -### 实际结果 - -**全部通过!** ✅ - -## 💡 后续优化建议 - -### 短期方案(当前实现) - -✅ **已完成** -- 使用默认菜单配置 -- 根据权限 ID 过滤菜单 -- 使用默认系统标题 -- 完善错误处理 - -### 长期方案(推荐) - -🎯 **建议后端修复以下接口**: - -#### 1. `/sys_user/authorityMenus` 接口 - -**期望返回格式**: -```json -{ - "code": 0, - "message": "请求成功", - "data": [ - { - "id": 1, - "name": "首页", - "path": "/home", - "component": "home/index", - "parent_id": 0, - "type": "页面", - "is_show_menu": 1, - "icon": "md-home", - "sort": 1 - }, - { - "id": 5, - "name": "系统管理", - "path": "/system", - "component": "", - "parent_id": 0, - "type": "菜单", - "is_show_menu": 1, - "icon": "md-settings", - "sort": 2, - "children": [ - { - "id": 11, - "name": "用户管理", - "path": "/system/user", - "component": "system/sys_user", - "parent_id": 5, - "type": "页面", - "is_show_menu": 1 - } - ] - } - ] -} -``` - -#### 2. `/sys_param_setup/getOne` 接口 - -**期望返回格式**: -```json -{ - "code": 0, - "message": "请求成功", - "data": { - "key": "sys_title", - "value": "我的管理系统" - } -} -``` - -### 扩展默认菜单 - -如果需要添加更多业务菜单,编辑 `src/config/menuConfig.js`: - -```javascript -export const defaultMenus = [ - // ... 现有菜单 - { - id: 200, - name: '业务管理', - path: '/business', - component: '', - parent_id: 0, - type: '菜单', - is_show_menu: 1, - icon: 'md-briefcase', - sort: 4, - children: [ - { - id: 201, - name: '订单管理', - path: '/business/order', - component: 'business/order', - parent_id: 200, - type: '页面', - is_show_menu: 1, - icon: 'md-cart', - sort: 1 - }, - { - id: 202, - name: '产品管理', - path: '/business/product', - component: 'business/product_list', - parent_id: 200, - type: '页面', - is_show_menu: 1, - icon: 'md-cube', - sort: 2 - } - ] - } -] -``` - -## 📝 相关文档 - -1. **登录功能修复说明.md** - 登录数据结构修复详情 -2. **权限菜单说明.md** - 权限菜单处理流程 -3. **authorityMenus接口失败解决方案.md** - 接口失败降级方案 - -## ✅ 总结 - -### 修复完成的问题 - -1. ✅ 登录接口数据结构适配 -2. ✅ authorityMenus 接口失败降级处理 -3. ✅ 系统标题接口失败降级处理 -4. ✅ 错误处理完善 -5. ✅ 调试代码清理(debugger) - -### 当前系统状态 - -**完全可用!** 🎉 - -- ✅ 登录功能正常 -- ✅ 菜单显示正常 -- ✅ 路由跳转正常 -- ✅ 权限控制正常 -- ✅ 用户体验良好 - -### 已知限制 - -1. **菜单数据来源**:使用默认配置,不是从后端动态获取 -2. **系统标题**:使用默认标题,不是从后端获取 -3. **菜单扩展**:需要手动编辑配置文件 - -这些限制不影响系统的核心功能,可以正常使用。 - ---- - -**🎉 恭喜!你的 Demo 项目已经可以完美运行了!** - -如果需要添加更多功能或修复其他问题,请随时告诉我。 - diff --git a/demo-project/_doc/登录跳转首页修复说明.md b/demo-project/_doc/登录跳转首页修复说明.md deleted file mode 100644 index 4799941..0000000 --- a/demo-project/_doc/登录跳转首页修复说明.md +++ /dev/null @@ -1,412 +0,0 @@ -# 登录跳转首页修复说明 - -## 🎯 需求 - -1. 登录成功后自动跳转到首页 -2. 访问 `/` 时自动重定向到 `/home` - -## 📋 问题分析 - -### 原来的问题 - -**登录流程**: -``` -用户登录 - ↓ -调用 handleLogin - ↓ -保存 token 和 authorityMenus - ↓ -显示"登录成功!" - ↓ -window.location.reload() ← ❌ 刷新当前页面(/login) - ↓ -停留在登录页面 ❌ -``` - -**问题**: -- 登录成功后刷新了登录页面 -- 虽然路由守卫会检测到 token 并重定向到首页 -- 但是刷新操作会导致页面停留在 `/login` - -### 路由守卫逻辑 - -`src/router/index.js` 中的路由守卫: -```javascript -router.beforeEach((to, from, next) => { - const token = getToken() - - if (!token && to.name !== 'login') { - // 未登录且访问非登录页 → 跳转到登录页 - next({ name: 'login' }) - } else if (!token && to.name === 'login') { - // 未登录且访问登录页 → 允许访问 - next() - } else if (token && to.name === 'login') { - // 已登录且访问登录页 → 重定向到首页 - next({ name: homeName }) // homeName = 'home' - } else { - // 其他情况 → 允许访问 - next() - } -}) -``` - -**说明**: -- 如果已登录(有 token)且访问登录页,会重定向到首页 -- 但是 `window.location.reload()` 会刷新当前页面,不会触发路由跳转 - -### 主路由重定向配置 - -`src/utils/uiTool.js` 中的主路由配置: -```javascript -let mainRoute = { - path: '/', - name: '主视图', - redirect: '/home', // ← 访问 / 时重定向到 /home - component: Main, - children: [] -} -``` - -**说明**: -- 访问 `/` 时会自动重定向到 `/home` -- 前提是 `/home` 路由存在(从后端权限菜单生成) - -## ✅ 解决方案 - -### 修改登录成功后的跳转逻辑 - -**修改文件**:`src/views/login/login.vue` - -**修改前**: -```javascript -async handleSubmit({ userName, password }) { - try { - let userFrom = { name: userName, password: password } - await this.handleLogin({ - userFrom, - Main, - ParentView, - Page404 - }) - this.$Message.success('登录成功!') - window.location.reload() // ❌ 刷新当前页面(/login) - } catch (error) { - // 错误处理 - } -} -``` - -**修改后**: -```javascript -async handleSubmit({ userName, password }) { - try { - let userFrom = { name: userName, password: password } - await this.handleLogin({ - userFrom, - Main, - ParentView, - Page404 - }) - this.$Message.success('登录成功!') - - // ✅ 跳转到首页(使用 location.href 触发完整页面加载) - setTimeout(() => { - window.location.href = window.location.origin + window.location.pathname + '#/' - }, 500) - } catch (error) { - // 错误处理 - } -} -``` - -**改进点**: -- ✅ 使用 `window.location.href` 跳转到 `#/` -- ✅ 触发完整的页面加载 -- ✅ 路由会重定向到 `/home` -- ✅ 延迟 500ms 确保提示信息显示 - -## 📊 新的登录流程 - -### 完整流程 - -``` -用户输入用户名密码 - ↓ -点击登录 - ↓ -调用 handleLogin action - ↓ -调用登录接口 - ↓ -保存 token 到 localStorage - ↓ -保存用户信息到 Vuex - ↓ -调用 setAuthorityMenus - ├─ 尝试获取权限菜单 - ├─ 如果失败,使用默认菜单 - └─ 保存到 localStorage.authorityMenus - ↓ -显示"登录成功!"提示 - ↓ -延迟 500ms - ↓ -跳转到 #/ (window.location.href) - ↓ -触发完整页面加载 - ↓ -框架初始化 - ↓ -从 localStorage 读取 authorityMenus - ↓ -生成路由(包括首页) - ↓ -访问 / 路由 - ↓ -重定向到 /home ✅ - ↓ -显示首页 ✅ -``` - -### 路由重定向流程 - -``` -访问 #/ - ↓ -匹配主路由 { path: '/', redirect: '/home' } - ↓ -重定向到 /home - ↓ -匹配首页路由 { path: '/home', component: HomePage } - ↓ -显示首页组件 ✅ -``` - -### 已登录用户访问登录页 - -``` -已登录用户访问 #/login - ↓ -路由守卫检测到 token - ↓ -检测到访问登录页 - ↓ -重定向到首页 next({ name: 'home' }) - ↓ -显示首页 ✅ -``` - -## 🎯 关键点说明 - -### 1. 为什么使用 `window.location.href` 而不是 `this.$router.push`? - -**`this.$router.push({ path: '/' })`**: -- 只是客户端路由跳转 -- 不会重新加载页面 -- 不会重新初始化框架 -- 不会重新从 localStorage 读取 authorityMenus - -**`window.location.href = '#/'`**: -- 触发完整的页面加载 -- 重新初始化框架 -- 重新从 localStorage 读取 authorityMenus -- 重新生成路由 -- 确保路由和菜单正确加载 - -### 2. 为什么延迟 500ms? - -```javascript -setTimeout(() => { - window.location.href = window.location.origin + window.location.pathname + '#/' -}, 500) -``` - -**原因**: -- 让"登录成功!"提示信息有时间显示 -- 给用户更好的体验 -- 确保 localStorage 写入完成 - -### 3. URL 构造说明 - -```javascript -window.location.origin + window.location.pathname + '#/' -``` - -**示例**: -- `window.location.origin` = `http://localhost:8080` -- `window.location.pathname` = `/` 或 `/demo-project/` -- 最终 URL = `http://localhost:8080/#/` 或 `http://localhost:8080/demo-project/#/` - -**为什么这样构造**: -- 兼容不同的部署路径 -- 确保 hash 路由正确 -- 避免硬编码 URL - -### 4. 主路由的 redirect 配置 - -```javascript -let mainRoute = { - path: '/', - redirect: '/home', - component: Main, - children: [ - { path: '/home', name: 'home', component: HomePage }, - // ... 其他路由 - ] -} -``` - -**工作原理**: -- 访问 `/` 时,自动重定向到 `/home` -- `/home` 路由由后端权限菜单生成 -- 如果后端没有返回首页配置,会使用默认菜单配置 - -## ✅ 验证清单 - -### 登录流程验证 - -- ✅ 访问登录页面 -- ✅ 输入用户名密码 -- ✅ 点击登录 -- ✅ 显示"登录成功!"提示 -- ✅ 自动跳转到首页 -- ✅ 首页正确显示 -- ✅ 菜单正确显示 - -### 路由重定向验证 - -- ✅ 登录后访问 `#/` 自动重定向到 `#/home` -- ✅ 已登录状态访问 `#/login` 自动重定向到 `#/home` -- ✅ 未登录状态访问 `#/home` 自动重定向到 `#/login` - -### 刷新页面验证 - -- ✅ 登录后刷新页面,停留在当前页面 -- ✅ 菜单和路由保持正确 -- ✅ 用户信息保持正确 - -## 🔧 相关配置 - -### 路由守卫配置 - -**文件**:`src/router/index.js` - -```javascript -export const setupRouterGuards = (router, ViewUI, homeName = 'home') => { - router.beforeEach((to, from, next) => { - const token = getToken() - ViewUI.LoadingBar.start() - - if (!token && to.name !== 'login') { - // 未登录 → 跳转到登录页 - next({ name: 'login' }) - } else if (!token && to.name === 'login') { - // 未登录访问登录页 → 允许 - next() - } else if (token && to.name === 'login') { - // 已登录访问登录页 → 重定向到首页 - next({ name: homeName }) - } else { - // 其他情况 → 允许 - next() - } - }) - - router.afterEach(to => { - ViewUI.LoadingBar.finish() - window.scrollTo(0, 0) - }) - - return router -} -``` - -### 主路由配置 - -**文件**:`src/utils/uiTool.js` - -```javascript -static getRoutes(Main, ParentView, Page404) { - let mainRoute = { - path: '/', - name: '主视图', - redirect: '/home', - component: Main, - meta: { title: '首页', notCache: true }, - children: [] - } - - // 从 localStorage 读取权限菜单 - if (localStorage.authorityMenus && localStorage.authorityMenus !== 'undefined') { - let authorityMenus = JSON.parse(localStorage.authorityMenus) || [] - - if (authorityMenus && authorityMenus.length > 0) { - let menus = uiTool.transformTree(authorityMenus) - let curRoutes = uiTool.menuToRoute(menus, ParentView, Page404) - - // 使用后端返回的路由(包括首页) - mainRoute.children = curRoutes - } - } - - return mainRoute -} -``` - -## 💡 最佳实践 - -### 1. 登录后的跳转 - -**推荐**: -```javascript -// 使用 location.href 触发完整页面加载 -window.location.href = window.location.origin + window.location.pathname + '#/' -``` - -**不推荐**: -```javascript -// 只刷新当前页面,不跳转 -window.location.reload() - -// 客户端路由跳转,不重新加载 -this.$router.push({ path: '/' }) -``` - -### 2. 路由守卫 - -**推荐**: -- 在路由守卫中统一处理登录状态检查 -- 已登录访问登录页时自动重定向到首页 -- 未登录访问受保护页面时自动重定向到登录页 - -### 3. 主路由配置 - -**推荐**: -- 设置 `redirect: '/home'` 确保访问 `/` 时重定向到首页 -- 从后端权限菜单生成路由 -- 提供默认菜单配置作为降级方案 - -## 📝 总结 - -### 修改内容 - -- ✅ 修改了登录成功后的跳转逻辑 -- ✅ 使用 `window.location.href` 跳转到首页 -- ✅ 触发完整页面加载 -- ✅ 确保路由和菜单正确初始化 - -### 效果 - -- ✅ 登录成功后自动跳转到首页 -- ✅ 访问 `/` 自动重定向到 `/home` -- ✅ 已登录访问登录页自动重定向到首页 -- ✅ 用户体验更流畅 - ---- - -**登录跳转首页功能已完成!** 🎉 - -现在登录成功后会自动跳转到首页,访问 `/` 也会正确重定向到 `/home`。 - diff --git a/demo-project/_doc/移除硬编码首页说明.md b/demo-project/_doc/移除硬编码首页说明.md deleted file mode 100644 index ed555bc..0000000 --- a/demo-project/_doc/移除硬编码首页说明.md +++ /dev/null @@ -1,452 +0,0 @@ -# 移除硬编码首页说明 - -## 🎯 修改目标 - -移除代码中硬编码的首页路由,完全依赖后端接口返回的菜单配置(包括首页)。 - -## 📋 修改原因 - -### 之前的问题 - -**硬编码首页**: -```javascript -// 在代码中创建默认首页 -const defaultHomeRoute = { - path: '/home', - name: 'home', - meta: { title: '首页', notCache: true }, - component: HomePage -} -``` - -**问题**: -- ❌ 首页配置写死在代码中 -- ❌ 无法通过后端动态配置首页 -- ❌ 首页和其他菜单的处理逻辑不一致 -- ❌ 增加了代码复杂度 - -### 新的设计 - -**完全依赖后端**: -- ✅ 首页配置由后端返回 -- ✅ 首页和其他菜单统一处理 -- ✅ 代码更简洁 -- ✅ 配置更灵活 - -## 📝 修改内容 - -### 1. 修改 `src/utils/uiTool.js` 的 `getRoutes` 方法 - -**修改前**: -```javascript -static getRoutes(Main, ParentView, Page404, HomePage) { - // 创建默认的首页路由 - const defaultHomeRoute = { - path: '/home', - name: 'home', - meta: { title: '首页', notCache: true }, - component: HomePage || { - render: h => h('div', { style: { padding: '20px' } }, '欢迎使用管理系统') - } - } - - let mainRoute = { - path: '/', - name: '主视图', - redirect: '/home', - component: Main, - meta: { title: '首页', notCache: true }, - children: [defaultHomeRoute] // ❌ 硬编码首页 - } - - // 从 localStorage 读取权限菜单 - if (localStorage.authorityMenus && localStorage.authorityMenus !== 'undefined') { - let authorityMenus = JSON.parse(localStorage.authorityMenus) || [] - - if (authorityMenus && authorityMenus.length > 0) { - let menus = uiTool.transformTree(authorityMenus) - let curRoutes = uiTool.menuToRoute(menus, ParentView, Page404) - - // 检查权限路由中是否有 home - const hasHome = curRoutes.some(r => r.name === 'home') - - if (hasHome) { - mainRoute.children = curRoutes - } else { - mainRoute.children = [defaultHomeRoute, ...curRoutes] // ❌ 复杂的合并逻辑 - } - } - } - - return mainRoute -} -``` - -**修改后**: -```javascript -static getRoutes(Main, ParentView, Page404) { - let mainRoute = { - path: '/', - name: '主视图', - redirect: '/home', - component: Main, - meta: { title: '首页', notCache: true }, - children: [] // ✅ 初始为空 - } - - // 从 localStorage 读取权限菜单 - if (localStorage.authorityMenus && localStorage.authorityMenus !== 'undefined') { - let authorityMenus = JSON.parse(localStorage.authorityMenus) || [] - - if (authorityMenus && authorityMenus.length > 0) { - let menus = uiTool.transformTree(authorityMenus) - let curRoutes = uiTool.menuToRoute(menus, ParentView, Page404) - - // ✅ 直接使用后端返回的路由(包括首页) - mainRoute.children = curRoutes - } - } - - return mainRoute -} -``` - -**改进点**: -- ✅ 移除了 `HomePage` 参数 -- ✅ 移除了 `defaultHomeRoute` 的创建 -- ✅ 移除了复杂的首页合并逻辑 -- ✅ 代码更简洁,逻辑更清晰 - -### 2. 更新 `src/index.js` 中的调用 - -**修改前**: -```javascript -// 获取主路由配置(包含 home) -const mainRoute = this.getRoutes({ Main, ParentView, Page404, HomePage }) - -// getRoutes 方法 -getRoutes(components = {}) { - const { Main, ParentView, Page404, HomePage } = components - - if (!Main || !ParentView || !Page404) { - console.error('Missing required layout components') - return null - } - - return uiTool.getRoutes(Main, ParentView, Page404, HomePage) -} -``` - -**修改后**: -```javascript -// 获取主路由配置(从后端权限菜单生成) -const mainRoute = this.getRoutes({ Main, ParentView, Page404 }) - -// getRoutes 方法 -getRoutes(components = {}) { - const { Main, ParentView, Page404 } = components - - if (!Main || !ParentView || !Page404) { - console.error('Missing required layout components') - return null - } - - return uiTool.getRoutes(Main, ParentView, Page404) -} -``` - -**改进点**: -- ✅ 移除了 `HomePage` 参数 -- ✅ 注释更准确 - -### 3. 确保默认菜单配置包含首页 - -**`src/config/menuConfig.js`**: -```javascript -export const defaultMenus = [ - { - id: 1, - name: '首页', - path: '/home', - component: 'home/index', - parent_id: 0, - type: '页面', - is_show_menu: 1, - icon: 'md-home', - sort: 1 - }, - // ... 其他菜单 -] -``` - -**说明**: -- ✅ 默认菜单配置中包含首页(id: 1) -- ✅ 当 `authorityMenus` 接口失败时,会使用这个默认配置 -- ✅ 确保即使接口失败,也能显示首页 - -## 📊 新的路由生成流程 - -### 应用启动时 - -``` -应用启动 - ↓ -框架初始化 - ↓ -调用 getRoutes - ↓ -从 localStorage 读取 authorityMenus - ↓ -authorityMenus 存在? - ├─ 是 → 解析菜单数据 - │ ↓ - │ transformTree (构建树形结构) - │ ↓ - │ menuToRoute (转换为路由配置) - │ ↓ - │ 生成路由(包括首页)✅ - │ - └─ 否 → children = [] (空路由) - ↓ - 显示登录页面 -``` - -### 登录后 - -``` -用户登录 - ↓ -调用登录接口 - ↓ -保存 token 和用户信息 - ↓ -调用 setAuthorityMenus - ├─ 尝试调用 authorityMenus 接口 - │ ├─ 成功 → 使用后端返回的菜单(包括首页) - │ └─ 失败 → 使用默认菜单配置(包括首页) - ↓ -保存到 localStorage - ↓ -刷新页面 - ↓ -重新执行应用启动流程 - ↓ -从 localStorage 读取菜单 - ↓ -生成路由(包括首页)✅ -``` - -## 🎯 后端接口要求 - -### authorityMenus 接口返回格式 - -**必须包含首页配置**: -```json -{ - "code": 0, - "message": "请求成功", - "data": [ - { - "id": 1, - "name": "首页", - "path": "/home", - "component": "home/index", - "parent_id": 0, - "type": "页面", - "is_show_menu": 1, - "icon": "md-home", - "sort": 1 - }, - { - "id": 5, - "name": "系统管理", - "path": "/system", - "component": "", - "parent_id": 0, - "type": "菜单", - "is_show_menu": 1, - "icon": "md-settings", - "sort": 2, - "children": [ - { - "id": 11, - "name": "用户管理", - "path": "/system/user", - "component": "system/sys_user", - "parent_id": 5, - "type": "页面", - "is_show_menu": 1 - } - ] - } - ] -} -``` - -### 首页配置说明 - -**必需字段**: -- `id`: 菜单 ID(建议使用 1) -- `name`: 菜单名称(如 "首页") -- `path`: 路由路径(必须是 `/home`) -- `component`: 组件路径(如 `home/index`) -- `parent_id`: 父菜单 ID(0 表示顶级菜单) -- `type`: 类型("页面") -- `is_show_menu`: 是否显示在菜单中(1=显示,0=隐藏) - -**可选字段**: -- `icon`: 图标名称(如 `md-home`) -- `sort`: 排序(建议设为 1,让首页排在第一位) - -## ✅ 优势 - -### 1. 代码更简洁 - -**代码行数减少**: -- 移除了 `defaultHomeRoute` 的创建 -- 移除了首页合并逻辑 -- 移除了 `HomePage` 参数传递 - -**复杂度降低**: -- 不需要判断是否有首页 -- 不需要合并首页和其他路由 -- 逻辑更直观 - -### 2. 配置更灵活 - -**后端控制**: -- ✅ 首页路径可以动态配置 -- ✅ 首页组件可以动态指定 -- ✅ 首页标题可以动态设置 -- ✅ 首页图标可以动态配置 - -**统一管理**: -- ✅ 所有菜单(包括首页)都由后端管理 -- ✅ 权限控制统一 -- ✅ 配置方式统一 - -### 3. 维护更容易 - -**单一数据源**: -- ✅ 菜单配置只来自后端 -- ✅ 不需要维护前端的默认首页 -- ✅ 修改首页只需要修改后端配置 - -**降级方案**: -- ✅ 如果 `authorityMenus` 接口失败 -- ✅ 使用 `defaultMenus` 配置(包含首页) -- ✅ 确保系统可用 - -## ⚠️ 注意事项 - -### 1. 后端必须返回首页配置 - -如果后端返回的菜单数据中没有首页,用户登录后会看不到首页。 - -**解决方案**: -- 确保后端 `authorityMenus` 接口返回包含首页的菜单数据 -- 或者在 `defaultMenus` 中包含首页作为兜底 - -### 2. 首页路径必须是 `/home` - -因为主路由的 `redirect` 设置为 `/home`: -```javascript -let mainRoute = { - path: '/', - redirect: '/home', // ← 重定向到 /home - // ... -} -``` - -**要求**: -- 后端返回的首页配置中,`path` 必须是 `/home` -- 或者修改主路由的 `redirect` 配置 - -### 3. 组件路径映射 - -后端返回的 `component` 字段(如 `home/index`)会被映射到: -``` -src/views/home/index.vue -``` - -**要求**: -- 确保组件文件存在 -- 组件路径正确 - -## 🧪 测试验证 - -### 测试场景 1:正常登录 - -``` -1. 启动项目 -2. 访问登录页面 -3. 输入用户名密码 -4. 点击登录 -5. 登录成功 -6. 页面刷新 -7. 进入系统首页 ✅ -``` - -**验证点**: -- ✅ 首页正确显示 -- ✅ 首页路由是 `/home` -- ✅ 首页组件正确加载 - -### 测试场景 2:authorityMenus 接口失败 - -``` -1. 启动项目 -2. 登录(authorityMenus 接口失败) -3. 使用默认菜单配置 -4. 页面刷新 -5. 进入系统首页 ✅ -``` - -**验证点**: -- ✅ 使用默认菜单配置 -- ✅ 首页正确显示 -- ✅ 控制台有警告信息 - -### 测试场景 3:刷新页面 - -``` -1. 已登录状态 -2. 刷新页面 -3. 从 localStorage 读取菜单 -4. 重新生成路由 -5. 首页正确显示 ✅ -``` - -**验证点**: -- ✅ 首页路由正确 -- ✅ 菜单正确显示 -- ✅ 用户状态保持 - -## 📝 总结 - -### 修改内容 - -- ✅ 移除了硬编码的首页路由 -- ✅ 移除了 `HomePage` 参数 -- ✅ 简化了路由生成逻辑 -- ✅ 统一了菜单处理方式 - -### 优势 - -- ✅ 代码更简洁(减少约 20 行代码) -- ✅ 逻辑更清晰 -- ✅ 配置更灵活 -- ✅ 维护更容易 - -### 要求 - -- ⚠️ 后端必须返回首页配置 -- ⚠️ 首页路径必须是 `/home` -- ⚠️ 组件文件必须存在 - ---- - -**硬编码首页已移除!** 🎉 - -现在首页完全由后端配置控制,代码更简洁、更灵活。 - diff --git a/demo-project/_doc/组件映射修复总结.md b/demo-project/_doc/组件映射修复总结.md deleted file mode 100644 index a8dd3df..0000000 --- a/demo-project/_doc/组件映射修复总结.md +++ /dev/null @@ -1,233 +0,0 @@ -# 组件映射修复总结 - -## ✅ 问题解决 - -### 问题:所有页面都显示 404 - -**原因**: -1. 权限菜单接口返回的组件路径(如 `ball/games.vue`)没有映射到实际组件 -2. 之前的代码将所有未知组件都设置为 `Page404` - -### 解决方案 - -创建了完整的组件映射机制: -- ✅ 框架自动映射系统组件 -- ✅ 支持用户配置业务组件映射 -- ✅ 自动处理带和不带 `.vue` 后缀的路径 -- ✅ 未映射组件显示友好提示 - -## 🔧 核心修改 - -### 1. `src/utils/uiTool.js` - -#### 添加组件映射功能 - -```javascript -// 组件映射表 -const componentMap = {} - -// 设置组件映射 -static setComponentMap(map) { - Object.assign(componentMap, map) -} - -// 获取组件 -static getComponent(componentPath) { - const normalizedPath = componentPath.replace(/\.vue$/, '') - return componentMap[normalizedPath] || componentMap[componentPath] -} -``` - -#### 优化 menuToRoute 方法 - -```javascript -static menuToRoute(menus, ParentView, Page404) { - menus.forEach(item => { - if (item.type === '页面') { - // 从映射表获取组件 - let component = uiTool.getComponent(item.component) - - if (component) { - item.component = component // ✅ 使用映射的组件 - } else { - // 显示友好提示 - console.warn(`组件未找到: ${item.component}`) - item.component = PlaceholderComponent - } - } - }) -} -``` - -### 2. `src/index.js` - -#### 添加 setupComponentMap 方法 - -```javascript -setupComponentMap(customMap = {}) { - // 框架内置组件 - const components = { - 'home/index': HomePage, - 'system/sys_log': SysLog, - 'system/sys_param_setup': SysParamSetup, - 'system/sys_role': SysRole, - 'system/sys_user': SysUser, - 'system_high/sys_control': SysControl, - 'system_high/sys_menu': SysMenu, - 'system_high/sys_title': SysTitle, - // 合并用户传入的业务组件 - ...customMap - } - - // 自动生成带 .vue 和不带 .vue 的映射 - const map = {} - Object.keys(components).forEach(path => { - const cleanPath = path.replace(/\.vue$/, '') - map[cleanPath] = components[path] - map[cleanPath + '.vue'] = components[path] - }) - - uiTool.setComponentMap(map) -} -``` - -#### 支持在 install 时传入 componentMap - -```javascript -install(Vue, options = {}) { - const { config, ViewUI, VueRouter, Vuex, createPersistedState, componentMap } = options - - // 设置组件映射(包含用户传入的映射) - this.setupComponentMap(componentMap) - - // ... -} -``` - -#### 添加 addComponentMap 方法 - -```javascript -addComponentMap(customMap) { - uiTool.setComponentMap(customMap) -} -``` - -## 📊 代码优化 - -### 优化前(重复代码多) - -```javascript -const map = { - 'system/sys_user.vue': SysUser, - 'system/sys_user': SysUser, // ← 重复 - 'system/sys_role.vue': SysRole, - 'system/sys_role': SysRole, // ← 重复 - // ...每个组件都写两遍 -} -``` - -### 优化后(自动生成) - -```javascript -const components = { - 'system/sys_user': SysUser, - 'system/sys_role': SysRole -} - -// 自动生成带 .vue 的映射 -Object.keys(components).forEach(path => { - map[path] = components[path] - map[path + '.vue'] = components[path] -}) -``` - -**代码量减少 50%** ✅ - -## 🚀 使用方法 - -### 方法一:在 Vue.use 时配置(推荐) - -```javascript -import GamesComponent from './views/ball/games.vue' - -Vue.use(AdminFramework, { - config, - ViewUI, - VueRouter, - Vuex, - createPersistedState, - componentMap: { - 'ball/games': GamesComponent - } -}) -``` - -### 方法二:使用 addComponentMap - -```javascript -Vue.use(AdminFramework, { config, ViewUI, VueRouter, Vuex, createPersistedState }) - -AdminFramework.addComponentMap({ - 'ball/games': GamesComponent -}) -``` - -## 📝 配置清单 - -根据你的权限菜单接口,需要配置的业务组件: - -### 球局模块 -- [ ] `ball/games.vue` - 球局表 -- [ ] `ball/wch_users.vue` - 微信用户 -- [ ] `ball/venues.vue` - 场地表 -- [ ] `ball/game_participants.vue` - 球局参与者 -- [ ] `ball/game_comments.vue` - 球局评论 - -### 订单模块 -- [ ] `order/pay_orders.vue` - 支付订单 -- [ ] `order/wch_wallets.vue` - 用户钱包 -- [ ] `order/wallet_transactions.vue` - 交易记录 -- [ ] `order/transfer_details.vue` - 转账详情 -- [ ] `order/frozen_funds.vue` - 冻结资金 - -### 用户模块 -- [ ] `users/user_follows.vue` - 用户关注 -- [ ] `users/recommend_blocks.vue` - 推荐屏蔽 -- [ ] `users/user_tracking.vue` - 行为追踪 - -### 资源模块 -- [ ] `statistics/resources.vue` - 图库资源表 -- [ ] `ntrp/ntr_questions.vue` - 题库管理 -- [ ] `ntrp/ntr_records.vue` - 测试记录 - -### 其他 -- [ ] `message/msg_notifications.vue` - 消息管理 -- [ ] `system/wch_professions.vue` - 职业管理 -- [ ] `system/wch_cities.vue` - 城市管理 -- [ ] `business/hot_city_qr.vue` - 热门城市 - -## 🎯 已自动映射(无需配置) - -- ✅ `home/index.vue` - 主页 -- ✅ `system/sys_user.vue` - 系统用户 -- ✅ `system/sys_role.vue` - 角色管理 -- ✅ `system/sys_log.vue` - 日志管理 -- ✅ `system/sys_param_setup.vue` - 参数设置 -- ✅ `system_high/sys_menu.vue` - 菜单管理 -- ✅ `system_high/sys_control.vue` - 控制器管理 -- ✅ `system_high/sys_title.vue` - 系统标题设置 - -## 📚 相关文档 - -- [快速配置组件映射.md](./快速配置组件映射.md) - 快速指南 -- [权限菜单组件配置指南.md](./权限菜单组件配置指南.md) - 详细教程 -- [../README.md](../README.md) - 项目说明 -- [../../完整使用文档.md](../../完整使用文档.md) - 框架文档 - ---- - -**修复时间**: 2025-10-08 -**修复人员**: light - -**现在配置完 componentMap,所有菜单页面都能正常显示了!** 🎉 - diff --git a/demo-project/_doc/组件映射说明.md b/demo-project/_doc/组件映射说明.md deleted file mode 100644 index 56ca79f..0000000 --- a/demo-project/_doc/组件映射说明.md +++ /dev/null @@ -1,339 +0,0 @@ -# 组件映射机制说明 - -## 🎯 问题原因 - -之前所有页面都显示 404 是因为: -- 后端返回的权限菜单包含组件路径(如 `"component": "system/sys_user.vue"`) -- 但框架没有将这些路径映射到实际组件 -- 所有页面都被设置为 `Page404` 组件 - -## ✅ 解决方案 - -### 1. 框架内置组件映射 - -框架现在自动映射以下系统页面: - -```javascript -// 框架自动映射的组件 -{ - 'home/index': HomePage, // 主页 - 'system/sys_log': SysLog, // 日志管理 - 'system/sys_param_setup': SysParamSetup, // 参数设置 - 'system/sys_role': SysRole, // 角色管理 - 'system/sys_user': SysUser, // 用户管理 - 'system_high/sys_control': SysControl, // 控制器管理 - 'system_high/sys_menu': SysMenu, // 菜单管理 - 'system_high/sys_title': SysTitle // 系统标题设置 -} -``` - -**自动支持**: -- ✅ `home/index` 和 `home/index.vue` 都能识别 -- ✅ `system/sys_user` 和 `system/sys_user.vue` 都能识别 - -### 2. 添加自定义业务组件 - -在项目的 `main.js` 中添加自定义组件映射: - -```javascript -import ProductList from './views/business/product_list.vue' -import GamesComponent from './views/ball/games.vue' -import PayOrdersComponent from './views/order/pay_orders.vue' - -// 使用框架 -Vue.use(AdminFramework, { config, ViewUI, VueRouter, Vuex, createPersistedState }) - -// 添加自定义组件映射 -AdminFramework.addComponentMap({ - 'business/product_list.vue': ProductList, - 'ball/games.vue': GamesComponent, - 'order/pay_orders.vue': PayOrdersComponent -}) -``` - -**说明**: -- 只需要添加 `.vue` 后缀的映射 -- 框架会自动处理不带后缀的路径 - -### 3. 权限菜单格式 - -后端返回的菜单格式: -```json -{ - "code": 0, - "data": [ - { - "id": 1, - "name": "首页", - "path": "home", - "component": "home/index.vue", ← 这个路径会自动映射到 HomePage 组件 - "type": "页面" - }, - { - "id": 11, - "name": "系统用户", - "path": "sys_user", - "component": "system/sys_user.vue", ← 映射到 SysUser 组件 - "type": "页面" - }, - { - "id": 123, - "name": "球局表", - "path": "games", - "component": "ball/games.vue", ← 需要在项目中添加映射 - "type": "页面" - } - ] -} -``` - -## 🔧 完整示例 - -### demo-project/src/main.js - -```javascript -import Vue from 'vue' -import VueRouter from 'vue-router' -import Vuex from 'vuex' -import ViewUI from 'view-design' -import createPersistedState from 'vuex-persistedstate' -import 'view-design/dist/styles/iview.css' - -import AdminFramework from '../../src/index.js' -import config from './config' -import App from './App.vue' - -// 引入业务组件 -import ProductList from './views/business/product_list.vue' -// import GamesComponent from './views/ball/games.vue' -// import PayOrdersComponent from './views/order/pay_orders.vue' - -// 使用框架 -Vue.use(AdminFramework, { - config, - ViewUI, - VueRouter, - Vuex, - createPersistedState -}) - -// 添加业务组件映射 -AdminFramework.addComponentMap({ - 'business/product_list.vue': ProductList - // 'ball/games.vue': GamesComponent, - // 'order/pay_orders.vue': PayOrdersComponent -}) - -// 创建 Vue 实例 -new Vue({ - el: '#app', - router: AdminFramework.router, - store: AdminFramework.store, - render: h => h(App), - mounted() { - AdminFramework.uiTool.setRem() - - // 设置权限菜单(会自动根据映射表加载组件) - this.$store.dispatch('user/setAuthorityMenus', { - Main: AdminFramework.Main, - ParentView: AdminFramework.ParentView, - Page404: AdminFramework.Page404 - }) - } -}) -``` - -## 📋 映射机制 - -### 1. 框架自动映射 - -框架在 `install` 时自动映射系统组件: -```javascript -Vue.use(AdminFramework, { ... }) -// ↓ 自动执行 -setupComponentMap() -// ↓ 映射系统页面 -{ - 'home/index': HomePage, - 'home/index.vue': HomePage, - 'system/sys_user': SysUser, - 'system/sys_user.vue': SysUser, - // ... -} -``` - -### 2. 用户添加映射 - -用户可以添加自定义业务组件映射: -```javascript -AdminFramework.addComponentMap({ - 'ball/games.vue': GamesComponent -}) -// ↓ 添加到映射表 -{ - ...已有映射, - 'ball/games.vue': GamesComponent -} -``` - -### 3. 路由生成 - -当调用 `setAuthorityMenus` 时: -```javascript -// 后端返回菜单 -[ - { component: "system/sys_user.vue", ... } -] -// ↓ menuToRoute 处理 -// ↓ 从映射表获取组件 -component: SysUser // ✅ 找到对应组件 -``` - -## ⚠️ 未找到组件的处理 - -如果后端返回的组件路径在映射表中不存在: -```javascript -// 显示占位组件 -component: { - render: h => h('div', [ - h('Alert', { type: 'warning' }, [ - h('p', '页面组件未加载: ball/games.vue'), - h('p', '请在项目中创建此组件或在组件映射表中注册') - ]) - ]) -} -``` - -**控制台警告**: -``` -⚠️ 组件未找到: ball/games.vue,使用占位组件 -``` - -## 💡 最佳实践 - -### 1. 框架内置页面 - -直接使用,无需配置: -- `home/index.vue` - 主页 -- `system/sys_user.vue` - 用户管理 -- `system/sys_role.vue` - 角色管理 -- `system/sys_log.vue` - 日志管理 -- `system/sys_param_setup.vue` - 参数设置 -- `system_high/sys_menu.vue` - 菜单管理 -- `system_high/sys_control.vue` - 控制器管理 -- `system_high/sys_title.vue` - 系统标题设置 - -### 2. 自定义业务页面 - -在 main.js 中添加映射: -```javascript -// 1. 导入组件 -import GamesComponent from './views/ball/games.vue' - -// 2. 添加映射 -AdminFramework.addComponentMap({ - 'ball/games.vue': GamesComponent -}) -``` - -### 3. 路径命名建议 - -保持后端返回的路径与实际文件路径一致: -``` -后端:component: "ball/games.vue" -项目:src/views/ball/games.vue -``` - -## 📊 代码优化对比 - -### 优化前(重复代码) -```javascript -const map = { - 'system/sys_user.vue': SysUser, - 'system/sys_user': SysUser, // 重复 - 'system/sys_role.vue': SysRole, - 'system/sys_role': SysRole, // 重复 - 'system/sys_log.vue': SysLog, - 'system/sys_log': SysLog, // 重复 - // 每个组件写两遍... -} -``` - -### 优化后(自动生成) -```javascript -const components = { - 'system/sys_user': SysUser, - 'system/sys_role': SysRole, - 'system/sys_log': SysLog -} - -// 自动生成带 .vue 和不带 .vue 的映射 -const map = {} -Object.keys(components).forEach(path => { - map[path] = components[path] - map[path + '.vue'] = components[path] -}) -``` - -**优势**: -- ✅ 代码量减少 50% -- ✅ 易于维护 -- ✅ 不易出错 - -## 🚀 使用方法 - -### 步骤 1:创建业务组件 - -在项目中创建组件文件: -```vue - - - - -``` - -### 步骤 2:添加组件映射 - -在 `src/main.js` 中: -```javascript -import GamesComponent from './views/ball/games.vue' - -AdminFramework.addComponentMap({ - 'ball/games.vue': GamesComponent -}) -``` - -### 步骤 3:后端返回菜单 - -确保后端菜单中的路径正确: -```json -{ - "component": "ball/games.vue", - "path": "games" -} -``` - -### 步骤 4:自动生成路由 - -框架会自动将菜单转换为路由,并加载对应组件! - -## 📚 相关文档 - -- [README.md](./README.md) - 项目说明 -- [CHANGELOG.md](./CHANGELOG.md) - 更新日志 -- [../完整使用文档.md](../完整使用文档.md) - 框架完整文档 - ---- - -**现在启动项目,权限菜单中的系统页面都能正常显示了!** 🎉 - -对于业务页面(ball/games.vue, order/pay_orders.vue 等),只需: -1. 在项目中创建对应组件 -2. 在 main.js 中添加组件映射 - diff --git a/demo-project/_doc/调试指南.md b/demo-project/_doc/调试指南.md deleted file mode 100644 index 2c91060..0000000 --- a/demo-project/_doc/调试指南.md +++ /dev/null @@ -1,233 +0,0 @@ -# 调试指南 - -## ✅ Source Map 已启用 - -现在 Demo 项目已配置了完整的 Source Map 支持,可以在浏览器中直接调试源码! - -### 📋 Source Map 配置 - -#### 开发模式(`npm run dev`) -```javascript -devtool: 'eval-source-map' -``` - -**特点**: -- ✅ 高质量的 source map -- ✅ 可以看到原始源代码 -- ✅ 可以设置断点调试 -- ✅ 包含列信息(精确定位) -- ⚡ 重新构建速度快 - -#### 生产模式(`npm run build`) -```javascript -devtool: 'source-map' -``` - -**特点**: -- ✅ 完整的 source map -- ✅ 生成独立的 .map 文件 -- 📦 适合部署到生产环境 - -### 🔍 如何调试 - -#### 1. 在浏览器中调试 - -**启动开发服务器**: -```bash -npm run dev -``` - -**打开浏览器开发者工具**: -- Chrome:按 `F12` 或 `Ctrl+Shift+I` -- Firefox:按 `F12` - -**查看源码**: -1. 点击 **Sources** 标签页(Chrome)或 **调试器** 标签页(Firefox) -2. 在左侧文件树中可以看到: - ``` - webpack:// - ├── demo-project/ - │ └── src/ - │ ├── main.js ← Demo 项目源码 - │ ├── App.vue - │ └── views/ - └── src/ ← 框架源码 - ├── index.js - ├── components/ - ├── views/ - └── utils/ - ``` - -#### 2. 设置断点 - -**在源码中设置断点**: -1. 在 Sources 中找到要调试的文件 -2. 点击行号设置断点(会出现蓝色标记) -3. 刷新页面或触发相关操作 - -**使用 debugger 语句**: -```javascript -// 在代码中添加 -debugger - -// 例如在 main.js 中 -mounted() { - debugger // ← 程序会在这里暂停 - this.$store.dispatch('user/setAuthorityMenus', { - Main: AdminFramework.Main, - ParentView: AdminFramework.ParentView, - Page404: AdminFramework.Page404 - }) -} -``` - -#### 3. 查看变量 - -断点暂停时可以: -- 在 **Scope** 面板查看局部变量 -- 在 **Watch** 面板添加监视表达式 -- 在 **Console** 中输入变量名查看值 - -#### 4. 单步调试 - -使用调试控制按钮: -- **继续** (`F8`) - 继续执行到下一个断点 -- **单步跳过** (`F10`) - 执行当前行,不进入函数 -- **单步进入** (`F11`) - 进入函数内部 -- **单步跳出** (`Shift+F11`) - 跳出当前函数 - -### 🎯 调试框架源码 - -由于项目直接使用框架源码(`../../src/index.js`),你可以: - -#### 1. 直接在框架代码中设置断点 - -例如在 `src/index.js` 的 install 方法中: -```javascript -install(Vue, options = {}) { - debugger // ← 可以在这里调试框架初始化过程 - if (this.installed) return - // ... -} -``` - -#### 2. 调试 Store Actions - -在 `src/store/user.js` 中: -```javascript -async handleLogin({ state, commit, dispatch }, { userFrom, Main, ParentView, Page404 }) { - debugger // ← 调试登录流程 - // ... -} -``` - -#### 3. 调试 HTTP 请求 - -在 `src/utils/http.js` 中: -```javascript -post(url, data, config) { - debugger // ← 调试 API 请求 - // ... -} -``` - -### 📊 Source Map 类型对比 - -| 类型 | 构建速度 | 重构速度 | 质量 | 适用场景 | -|------|---------|---------|------|---------| -| `eval-source-map` | 慢 | 快 | 高 | **开发** ✅ | -| `cheap-module-source-map` | 中 | 中 | 中 | 开发 | -| `source-map` | 很慢 | 很慢 | 最高 | **生产** ✅ | -| `none` | 最快 | 最快 | 无 | 不调试 | - -### 💡 调试技巧 - -#### 1. 使用 Vue DevTools - -安装 Vue DevTools 浏览器插件: -- Chrome: [Vue.js devtools](https://chrome.google.com/webstore) -- Firefox: [Vue.js devtools](https://addons.mozilla.org/firefox) - -功能: -- 查看组件树 -- 检查组件数据和 props -- 查看 Vuex 状态 -- 追踪事件 - -#### 2. Console 调试技巧 - -```javascript -// 查看 Store 状态 -console.log('Store:', this.$store.state) - -// 查看路由信息 -console.log('Route:', this.$route) - -// 查看组件实例 -console.log('Component:', this) - -// 使用 console.table 显示数组 -console.table(this.list) - -// 使用 console.dir 显示对象结构 -console.dir(AdminFramework) -``` - -#### 3. 网络请求调试 - -在 **Network** 标签页中: -- 查看 API 请求和响应 -- 检查请求头和响应头 -- 查看请求耗时 - -### ⚠️ 注意事项 - -#### 1. Source Map 文件大小 - -开发模式的 source map 会增加包体积,但: -- ✅ 只在开发环境使用 -- ✅ 不影响生产环境性能 -- ✅ 不会部署到生产服务器 - -#### 2. 刷新页面 - -修改代码后: -- 保存文件会自动热更新(HMR) -- 如果 HMR 失败,手动刷新页面(`F5`) - -#### 3. 清除缓存 - -如果看到旧代码: -- 硬刷新:`Ctrl+Shift+R` (Chrome) 或 `Ctrl+F5` -- 或在开发者工具中禁用缓存 - -### 🚀 开始调试 - -1. **启动开发服务器**: - ```bash - npm run dev - ``` - -2. **打开浏览器**: - 访问 `http://localhost:8080` - -3. **打开开发者工具**: - 按 `F12` - -4. **设置断点**: - 在 Sources 中找到源文件并设置断点 - -5. **开始调试**: - 刷新页面或触发相关操作 - -### 📚 相关资源 - -- [Chrome DevTools 官方文档](https://developer.chrome.com/docs/devtools/) -- [Firefox Developer Tools](https://developer.mozilla.org/docs/Tools) -- [Vue DevTools](https://devtools.vuejs.org/) -- [Webpack DevTool 文档](https://webpack.js.org/configuration/devtool/) - ---- - -**现在启动项目,打开浏览器开发者工具,就可以看到完整的源码并进行调试了!** 🎉 - diff --git a/demo-project/_doc/路由重复导航警告修复.md b/demo-project/_doc/路由重复导航警告修复.md deleted file mode 100644 index 1a86a56..0000000 --- a/demo-project/_doc/路由重复导航警告修复.md +++ /dev/null @@ -1,409 +0,0 @@ -# 路由重复导航警告修复 - -## 🔍 问题描述 - -控制台出现警告: -``` -Avoided redundant navigation to current location: "/home". -NavigationDuplicated: Avoided redundant navigation to current location: "/home". -``` - -## 📋 问题原因 - -### 警告产生的场景 - -**场景 1:已在首页时访问登录页** -``` -当前路由: /home - ↓ -用户访问: /login - ↓ -路由守卫检测到已登录 - ↓ -尝试重定向: next({ name: 'home' }) - ↓ -目标路由: /home - ↓ -❌ 警告:已经在 /home,避免重复导航 -``` - -**场景 2:刷新首页** -``` -当前路由: /home - ↓ -刷新页面 - ↓ -路由守卫再次执行 - ↓ -检测到已登录且访问登录页(可能的中间状态) - ↓ -尝试重定向: next({ name: 'home' }) - ↓ -❌ 警告:已经在 /home,避免重复导航 -``` - -### 原来的路由守卫代码 - -```javascript -router.beforeEach((to, from, next) => { - const token = getToken() - ViewUI.LoadingBar.start() - - if (to.name === 'view_log') { - next() - return - } - - if (!token && to.name !== 'login') { - next({ name: 'login' }) - } else if (!token && to.name === 'login') { - next() - } else if (token && to.name === 'login') { - // ❌ 没有检查来源路由,可能导致重复导航 - next({ name: homeName }) - } else { - next() - } -}) -``` - -**问题**: -- 当已登录用户访问登录页时,总是重定向到首页 -- 没有检查来源路由是否已经是首页 -- 导致重复导航警告 - -## ✅ 解决方案 - -### 修改路由守卫逻辑 - -**修改文件**:`src/router/index.js` - -**修改后的代码**: -```javascript -router.beforeEach((to, from, next) => { - const token = getToken() - ViewUI.LoadingBar.start() - - if (to.name === 'view_log') { - next() - return - } - - if (!token && to.name !== 'login') { - // 未登录且访问非登录页 → 跳转到登录页 - next({ name: 'login' }) - } else if (!token && to.name === 'login') { - // 未登录且访问登录页 → 允许访问 - next() - } else if (token && to.name === 'login') { - // 已登录且访问登录页 → 重定向到首页 - // ✅ 避免重复导航警告 - if (from.name === homeName) { - next(false) // 取消导航,停留在当前页面 - } else { - next({ name: homeName }) // 重定向到首页 - } - } else { - // 其他情况 → 允许访问 - next() - } -}) -``` - -### 关键改进 - -**添加了来源路由检查**: -```javascript -if (from.name === homeName) { - next(false) // 如果来自首页,取消导航 -} else { - next({ name: homeName }) // 否则重定向到首页 -} -``` - -**`next(false)` 的作用**: -- 取消当前导航 -- 停留在当前页面(首页) -- 不会触发重复导航警告 - -## 📊 修复后的流程 - -### 场景 1:从首页访问登录页 - -``` -当前路由: /home (from.name = 'home') - ↓ -用户访问: /login (to.name = 'login') - ↓ -路由守卫检测到已登录 - ↓ -检查来源路由: from.name === 'home' ✅ - ↓ -执行: next(false) - ↓ -取消导航,停留在首页 ✅ - ↓ -✅ 没有警告 -``` - -### 场景 2:从其他页面访问登录页 - -``` -当前路由: /system/user (from.name = 'sys_user') - ↓ -用户访问: /login (to.name = 'login') - ↓ -路由守卫检测到已登录 - ↓ -检查来源路由: from.name !== 'home' ✅ - ↓ -执行: next({ name: 'home' }) - ↓ -重定向到首页 ✅ - ↓ -✅ 正常导航,没有警告 -``` - -### 场景 3:未登录访问登录页 - -``` -当前路由: 无 (from.name = undefined) - ↓ -用户访问: /login (to.name = 'login') - ↓ -路由守卫检测到未登录 - ↓ -执行: next() - ↓ -允许访问登录页 ✅ -``` - -### 场景 4:登录成功后跳转 - -``` -登录成功 - ↓ -执行: window.location.href = '#/' - ↓ -触发完整页面加载 - ↓ -访问: / (重定向到 /home) - ↓ -路由守卫检测到已登录 - ↓ -to.name = 'home' (不是 'login') - ↓ -执行: next() - ↓ -允许访问首页 ✅ -``` - -## 🎯 `next()` 方法说明 - -### `next()` 的不同用法 - -**1. `next()`** -- 允许当前导航 -- 继续执行路由跳转 - -**2. `next(false)`** -- 取消当前导航 -- 停留在当前页面 -- 不会触发路由变化 - -**3. `next({ name: 'home' })`** -- 重定向到指定路由 -- 取消当前导航 -- 跳转到新路由 - -**4. `next({ path: '/home' })`** -- 重定向到指定路径 -- 取消当前导航 -- 跳转到新路由 - -**5. `next(error)`** -- 终止导航 -- 触发错误处理 - -### 为什么使用 `next(false)` 而不是 `next()`? - -**如果使用 `next()`**: -```javascript -if (token && to.name === 'login') { - next() // ❌ 允许访问登录页 -} -``` -- 会允许已登录用户访问登录页 -- 不符合业务逻辑 - -**如果使用 `next({ name: homeName })`**: -```javascript -if (token && to.name === 'login') { - next({ name: homeName }) // ❌ 如果已在首页,会重复导航 -} -``` -- 如果来源路由已经是首页,会触发重复导航警告 - -**使用 `next(false)`**: -```javascript -if (token && to.name === 'login') { - if (from.name === homeName) { - next(false) // ✅ 取消导航,停留在首页 - } else { - next({ name: homeName }) // ✅ 重定向到首页 - } -} -``` -- 如果来源是首页,取消导航,停留在首页 -- 如果来源不是首页,重定向到首页 -- 避免重复导航警告 - -## ✅ 验证清单 - -### 功能验证 - -- ✅ 未登录访问登录页 → 正常显示登录页 -- ✅ 未登录访问其他页面 → 重定向到登录页 -- ✅ 已登录访问登录页(从首页) → 停留在首页 -- ✅ 已登录访问登录页(从其他页面) → 重定向到首页 -- ✅ 登录成功 → 跳转到首页 - -### 警告检查 - -- ✅ 控制台没有 "Avoided redundant navigation" 警告 -- ✅ 控制台没有 "NavigationDuplicated" 警告 -- ✅ 路由跳转正常工作 - -### 边界情况 - -- ✅ 刷新首页 → 停留在首页 -- ✅ 刷新其他页面 → 停留在当前页面 -- ✅ 直接访问 URL → 正确处理 - -## 💡 最佳实践 - -### 1. 路由守卫中检查来源路由 - -**推荐**: -```javascript -if (token && to.name === 'login') { - if (from.name === homeName) { - next(false) // 来自首页,取消导航 - } else { - next({ name: homeName }) // 来自其他页面,重定向 - } -} -``` - -**不推荐**: -```javascript -if (token && to.name === 'login') { - next({ name: homeName }) // 可能导致重复导航 -} -``` - -### 2. 使用 `next(false)` 取消不必要的导航 - -**推荐**: -```javascript -if (shouldCancelNavigation) { - next(false) // 取消导航 -} -``` - -**不推荐**: -```javascript -if (shouldCancelNavigation) { - // 什么都不做,导航会继续 -} -``` - -### 3. 避免在路由守卫中使用 `window.location` - -**推荐**: -```javascript -router.beforeEach((to, from, next) => { - if (needRedirect) { - next({ name: 'home' }) // 使用 next() 重定向 - } -}) -``` - -**不推荐**: -```javascript -router.beforeEach((to, from, next) => { - if (needRedirect) { - window.location.href = '#/home' // 不要在守卫中使用 - next(false) - } -}) -``` - -## 🔧 相关代码 - -### 完整的路由守卫代码 - -**文件**:`src/router/index.js` - -```javascript -// 路由守卫配置 -export const setupRouterGuards = (router, ViewUI, homeName = 'home') => { - router.beforeEach((to, from, next) => { - const token = getToken() - ViewUI.LoadingBar.start() - - if (to.name === 'view_log') { - next() - return - } - - if (!token && to.name !== 'login') { - // 未登录且访问非登录页 → 跳转到登录页 - next({ name: 'login' }) - } else if (!token && to.name === 'login') { - // 未登录且访问登录页 → 允许访问 - next() - } else if (token && to.name === 'login') { - // 已登录且访问登录页 → 重定向到首页 - // 避免重复导航警告 - if (from.name === homeName) { - next(false) // 来自首页,取消导航 - } else { - next({ name: homeName }) // 来自其他页面,重定向到首页 - } - } else { - // 其他情况 → 允许访问 - next() - } - }) - - router.afterEach(to => { - ViewUI.LoadingBar.finish() - window.scrollTo(0, 0) - }) - - return router -} -``` - -## 📝 总结 - -### 修改内容 - -- ✅ 在路由守卫中添加了来源路由检查 -- ✅ 使用 `next(false)` 避免重复导航 -- ✅ 保持了原有的业务逻辑 - -### 效果 - -- ✅ 消除了 "Avoided redundant navigation" 警告 -- ✅ 消除了 "NavigationDuplicated" 警告 -- ✅ 路由跳转更加流畅 -- ✅ 用户体验更好 - ---- - -**路由重复导航警告已修复!** 🎉 - -现在控制台不会再出现重复导航的警告了。 - diff --git a/demo-project/_doc/路由重复导航错误完全修复.md b/demo-project/_doc/路由重复导航错误完全修复.md deleted file mode 100644 index 52e9e15..0000000 --- a/demo-project/_doc/路由重复导航错误完全修复.md +++ /dev/null @@ -1,483 +0,0 @@ -# 路由重复导航错误完全修复 - -## 🔍 问题描述 - -页面直接报错: -``` -ERROR -Avoided redundant navigation to current location: "/home". -NavigationDuplicated: Avoided redundant navigation to current location: "/home". - at HashHistory.push - at VueComponent.turnToPage (main.vue:108:20) -``` - -## 📋 问题原因 - -### 错误来源 - -错误来自 `src/components/main/main.vue` 的两个方法: - -**1. `goHome()` 方法** -```javascript -goHome() { - this.$router.push({ path: '/' }) // ❌ 如果已在首页,会报错 -} -``` - -**2. `turnToPage()` 方法** -```javascript -turnToPage(route) { - // ... - this.$router.push({ - name, - params, - query - }) // ❌ 如果跳转到当前页面,会报错 -} -``` - -### 触发场景 - -**场景 1:点击 Logo 回到首页** -``` -当前页面: /home - ↓ -点击 Logo - ↓ -调用 goHome() - ↓ -执行 this.$router.push({ path: '/' }) - ↓ -❌ 错误:已经在首页,重复导航 -``` - -**场景 2:点击当前激活的菜单** -``` -当前页面: /home - ↓ -点击"首页"菜单 - ↓ -调用 turnToPage({ name: 'home' }) - ↓ -执行 this.$router.push({ name: 'home' }) - ↓ -❌ 错误:已经在首页,重复导航 -``` - -**场景 3:刷新页面后点击菜单** -``` -刷新页面 - ↓ -当前路由: /home - ↓ -菜单激活状态: home - ↓ -点击"首页"菜单 - ↓ -❌ 错误:重复导航 -``` - -### Vue Router 的行为 - -**Vue Router 2.x/3.x**: -- `router.push()` 返回一个 Promise -- 如果导航到当前路由,会抛出 `NavigationDuplicated` 错误 -- 这个错误会导致页面崩溃(如果没有捕获) - -## ✅ 解决方案 - -### 方案 1:在跳转前检查是否是当前路由(推荐) - -**优点**: -- 避免不必要的路由跳转 -- 性能更好 -- 代码更清晰 - -**缺点**: -- 需要在每个跳转方法中添加检查 - -### 方案 2:捕获 Promise 错误 - -**优点**: -- 代码简单 -- 统一处理错误 - -**缺点**: -- 仍然会触发路由跳转逻辑 -- 性能稍差 - -### 方案 3:结合使用(本次采用) - -**优点**: -- 既避免不必要的跳转 -- 又捕获可能的错误 -- 最稳健的方案 - -## 📝 修改内容 - -### 修改 `goHome()` 方法 - -**修改前**: -```javascript -goHome() { - this.$router.push({ path: '/' }) // ❌ 可能重复导航 -} -``` - -**修改后**: -```javascript -goHome() { - // 避免重复导航到当前页面 - if (this.$route.path !== '/' && this.$route.path !== '/home') { - this.$router.push({ path: '/' }).catch(err => { - // 忽略重复导航错误 - if (err.name !== 'NavigationDuplicated') { - console.error(err) - } - }) - } -} -``` - -**改进点**: -- ✅ 检查当前路由是否是 `/` 或 `/home` -- ✅ 只在不是首页时才跳转 -- ✅ 捕获并忽略重复导航错误 -- ✅ 其他错误仍然会打印到控制台 - -### 修改 `turnToPage()` 方法 - -**修改前**: -```javascript -turnToPage(route) { - let { name, params, query } = {} - if (typeof route === 'string') name = route - else { - name = route.name - params = route.params - query = route.query - } - if (name.indexOf('isTurnByHref_') > -1) { - window.open(name.split('_')[1]) - return - } - this.$router.push({ - name, - params, - query - }) // ❌ 可能重复导航 -} -``` - -**修改后**: -```javascript -turnToPage(route) { - let { name, params, query } = {} - if (typeof route === 'string') name = route - else { - name = route.name - params = route.params - query = route.query - } - if (name.indexOf('isTurnByHref_') > -1) { - window.open(name.split('_')[1]) - return - } - - // 避免重复导航到当前页面 - if (this.$route.name === name) { - return - } - - this.$router.push({ - name, - params, - query - }).catch(err => { - // 忽略重复导航错误 - if (err.name !== 'NavigationDuplicated') { - console.error(err) - } - }) -} -``` - -**改进点**: -- ✅ 检查目标路由是否是当前路由 -- ✅ 如果是当前路由,直接返回,不跳转 -- ✅ 捕获并忽略重复导航错误 -- ✅ 其他错误仍然会打印到控制台 - -## 📊 修复后的流程 - -### 场景 1:在首页点击 Logo - -``` -当前路由: /home - ↓ -点击 Logo - ↓ -调用 goHome() - ↓ -检查: this.$route.path === '/home' ✅ - ↓ -直接返回,不跳转 ✅ - ↓ -✅ 没有错误 -``` - -### 场景 2:在其他页面点击 Logo - -``` -当前路由: /system/user - ↓ -点击 Logo - ↓ -调用 goHome() - ↓ -检查: this.$route.path !== '/' && this.$route.path !== '/home' ✅ - ↓ -执行跳转: this.$router.push({ path: '/' }) - ↓ -跳转到首页 ✅ - ↓ -✅ 正常跳转 -``` - -### 场景 3:点击当前激活的菜单 - -``` -当前路由: /home (name: 'home') - ↓ -点击"首页"菜单 - ↓ -调用 turnToPage({ name: 'home' }) - ↓ -检查: this.$route.name === 'home' ✅ - ↓ -直接返回,不跳转 ✅ - ↓ -✅ 没有错误 -``` - -### 场景 4:点击其他菜单 - -``` -当前路由: /home (name: 'home') - ↓ -点击"用户管理"菜单 - ↓ -调用 turnToPage({ name: 'sys_user' }) - ↓ -检查: this.$route.name !== 'sys_user' ✅ - ↓ -执行跳转: this.$router.push({ name: 'sys_user' }) - ↓ -跳转到用户管理页面 ✅ - ↓ -✅ 正常跳转 -``` - -## 🎯 关键点说明 - -### 1. 为什么要检查两个路径? - -```javascript -if (this.$route.path !== '/' && this.$route.path !== '/home') { - // 跳转 -} -``` - -**原因**: -- 主路由配置了 `redirect: '/home'` -- 访问 `/` 会重定向到 `/home` -- 所以需要检查两个路径 - -### 2. 为什么使用 `catch()` 捕获错误? - -```javascript -this.$router.push({ path: '/' }).catch(err => { - if (err.name !== 'NavigationDuplicated') { - console.error(err) - } -}) -``` - -**原因**: -- `router.push()` 返回 Promise -- 重复导航会抛出 `NavigationDuplicated` 错误 -- 如果不捕获,错误会导致页面崩溃 -- 捕获后可以忽略重复导航错误,但保留其他错误的日志 - -### 3. 为什么检查 `err.name !== 'NavigationDuplicated'`? - -```javascript -if (err.name !== 'NavigationDuplicated') { - console.error(err) -} -``` - -**原因**: -- 只忽略重复导航错误 -- 其他错误(如路由不存在、权限错误等)仍然需要打印 -- 方便调试和排查问题 - -### 4. 为什么在 `turnToPage` 中直接 `return`? - -```javascript -if (this.$route.name === name) { - return // 直接返回 -} -``` - -**原因**: -- 如果是当前路由,不需要跳转 -- 直接返回可以避免不必要的路由操作 -- 性能更好 - -## ✅ 验证清单 - -### 功能验证 - -- ✅ 在首页点击 Logo → 不跳转,没有错误 -- ✅ 在其他页面点击 Logo → 跳转到首页 -- ✅ 点击当前激活的菜单 → 不跳转,没有错误 -- ✅ 点击其他菜单 → 正常跳转 -- ✅ 刷新页面后点击菜单 → 正常工作 - -### 错误检查 - -- ✅ 控制台没有 "NavigationDuplicated" 错误 -- ✅ 控制台没有 "Avoided redundant navigation" 警告 -- ✅ 页面不会崩溃 - -### 边界情况 - -- ✅ 快速连续点击菜单 → 正常工作 -- ✅ 快速连续点击 Logo → 正常工作 -- ✅ 在不同页面之间快速切换 → 正常工作 - -## 💡 最佳实践 - -### 1. 路由跳转前检查目标路由 - -**推荐**: -```javascript -if (this.$route.name !== targetName) { - this.$router.push({ name: targetName }) -} -``` - -**不推荐**: -```javascript -this.$router.push({ name: targetName }) // 可能重复导航 -``` - -### 2. 捕获 Promise 错误 - -**推荐**: -```javascript -this.$router.push({ name: targetName }).catch(err => { - if (err.name !== 'NavigationDuplicated') { - console.error(err) - } -}) -``` - -**不推荐**: -```javascript -this.$router.push({ name: targetName }) // 错误会导致页面崩溃 -``` - -### 3. 结合使用检查和捕获 - -**推荐**: -```javascript -if (this.$route.name !== targetName) { - this.$router.push({ name: targetName }).catch(err => { - if (err.name !== 'NavigationDuplicated') { - console.error(err) - } - }) -} -``` - -**优点**: -- 避免不必要的跳转 -- 捕获可能的错误 -- 最稳健的方案 - -## 🔧 相关代码 - -### 完整的 `goHome()` 方法 - -```javascript -goHome() { - // 避免重复导航到当前页面 - if (this.$route.path !== '/' && this.$route.path !== '/home') { - this.$router.push({ path: '/' }).catch(err => { - // 忽略重复导航错误 - if (err.name !== 'NavigationDuplicated') { - console.error(err) - } - }) - } -} -``` - -### 完整的 `turnToPage()` 方法 - -```javascript -turnToPage(route) { - let { name, params, query } = {} - if (typeof route === 'string') name = route - else { - name = route.name - params = route.params - query = route.query - } - if (name.indexOf('isTurnByHref_') > -1) { - window.open(name.split('_')[1]) - return - } - - // 避免重复导航到当前页面 - if (this.$route.name === name) { - return - } - - this.$router.push({ - name, - params, - query - }).catch(err => { - // 忽略重复导航错误 - if (err.name !== 'NavigationDuplicated') { - console.error(err) - } - }) -} -``` - -## 📝 总结 - -### 修改内容 - -- ✅ 修改了 `goHome()` 方法,添加路由检查和错误捕获 -- ✅ 修改了 `turnToPage()` 方法,添加路由检查和错误捕获 -- ✅ 避免了重复导航错误 -- ✅ 保持了原有的业务逻辑 - -### 效果 - -- ✅ 消除了 "NavigationDuplicated" 错误 -- ✅ 页面不会崩溃 -- ✅ 路由跳转更加流畅 -- ✅ 用户体验更好 - ---- - -**路由重复导航错误已完全修复!** 🎉 - -现在可以放心地点击菜单和 Logo,不会再出现错误了。 - diff --git a/demo-project/_doc/首页路由梳理说明.md b/demo-project/_doc/首页路由梳理说明.md deleted file mode 100644 index 74c5e6e..0000000 --- a/demo-project/_doc/首页路由梳理说明.md +++ /dev/null @@ -1,427 +0,0 @@ -# 首页路由梳理说明 - -## 🔍 问题分析 - -### 原来的问题 - -首页在多个地方被设置,导致路由混乱和错误: - -1. **`src/utils/uiTool.js` 的 `getRoutes` 方法** - - 接收了 `HomePage` 参数但没有使用 - - `children` 初始化为空数组 - - 尝试查找不存在的 `homeRoute`,返回 `undefined` - - 使用 `undefined` 导致路由错误 - -2. **`src/index.js` 的 `install` 方法** - - 调用 `getRoutes` 创建路由 - - 传入了 `HomePage` 但没有被使用 - -3. **`demo-project/src/main.js` 的 `mounted` 钩子** - - 又调用了 `setAuthorityMenus` 重新设置菜单 - - 导致路由被重复设置 - -### 错误信息 - -``` -vue-router.esm.js:1396 Uncaught TypeError: Cannot read properties of undefined (reading 'path') -[vuex] unknown action type: getSysTitle -[vuex] unknown getter: sysFormModel -``` - -## ✅ 解决方案 - -### 设计原则 - -1. **单一职责**:每个方法只负责一件事 -2. **避免重复**:路由只在一个地方创建和设置 -3. **清晰的流程**:首页设置流程清晰可追踪 - -### 新的首页设置流程 - -``` -应用启动 - ↓ -框架 install 方法 - ↓ -调用 getRoutes 创建主路由 - ↓ -创建默认首页路由 (/home) - ↓ -检查 localStorage 中的权限菜单 - ↓ -如果有权限菜单,合并到主路由 - ↓ -创建 VueRouter 实例 - ↓ -应用启动完成 - ↓ -用户登录 - ↓ -保存权限菜单到 localStorage - ↓ -刷新页面 - ↓ -重新执行上述流程(此时有权限菜单) -``` - -## 📝 修改内容 - -### 1. 修复 `src/utils/uiTool.js` 的 `getRoutes` 方法 - -**修改前**: -```javascript -static getRoutes(Main, ParentView, Page404, HomePage) { - let mainRoute = { - path: '/', - name: '主视图', - redirect: '/home', - component: Main, - meta: { title: '首页', notCache: true }, - children: [] // ❌ 空数组,没有默认首页 - } - - // ... 后续逻辑尝试使用不存在的 homeRoute - const homeRoute = mainRoute.children.find(r => r.name === 'home') // ❌ undefined - mainRoute.children = [homeRoute, ...curRoutes] // ❌ 使用 undefined -} -``` - -**修改后**: -```javascript -static getRoutes(Main, ParentView, Page404, HomePage) { - // ✅ 创建默认的首页路由 - const defaultHomeRoute = { - path: '/home', - name: 'home', - meta: { title: '首页', notCache: true }, - component: HomePage || { - render: h => h('div', { style: { padding: '20px' } }, '欢迎使用管理系统') - } - } - - let mainRoute = { - path: '/', - name: '主视图', - redirect: '/home', - component: Main, - meta: { title: '首页', notCache: true }, - children: [defaultHomeRoute] // ✅ 包含默认首页 - } - - // 从 localStorage 读取权限菜单 - if (localStorage.authorityMenus && localStorage.authorityMenus !== 'undefined') { - let authorityMenus = JSON.parse(localStorage.authorityMenus) || [] - - if (authorityMenus && authorityMenus.length > 0) { - let menus = uiTool.transformTree(authorityMenus) - let curRoutes = uiTool.menuToRoute(menus, ParentView, Page404) - - // 检查权限路由中是否有 home - const hasHome = curRoutes.some(r => r.name === 'home') - - if (hasHome) { - // 如果权限路由中有 home,使用权限路由的 home - mainRoute.children = curRoutes - } else { - // 如果权限路由中没有 home,保留默认 home 并添加其他路由 - mainRoute.children = [defaultHomeRoute, ...curRoutes] - } - } - } - - return mainRoute -} -``` - -**改进点**: -- ✅ 使用传入的 `HomePage` 参数 -- ✅ 创建默认的首页路由 -- ✅ 正确处理权限菜单的合并 -- ✅ 避免使用 `undefined` - -### 2. 简化 `demo-project/src/main.js` - -**修改前**: -```javascript -window.rootVue = new Vue({ - el: '#app', - router: AdminFramework.router, - store: AdminFramework.store, - render: h => h(App), - mounted() { - AdminFramework.uiTool.setRem() - - // ❌ 重复设置权限菜单 - this.$store.dispatch('user/setAuthorityMenus', { - Main: AdminFramework.Main, - ParentView: AdminFramework.ParentView, - Page404: AdminFramework.Page404 - }) - - this.$store.dispatch('app/getSysTitle', { - defaultTitle: 'Demo 管理系统', - defaultLogo: '' - }) - } -}) -``` - -**修改后**: -```javascript -window.rootVue = new Vue({ - el: '#app', - router: AdminFramework.router, - store: AdminFramework.store, - render: h => h(App), - mounted() { - AdminFramework.uiTool.setRem() - - // ✅ 只获取系统标题,不重复设置菜单 - this.$store.dispatch('app/getSysTitle', { - defaultTitle: 'Demo 管理系统', - defaultLogo: '' - }) - } -}) -``` - -**改进点**: -- ✅ 移除了重复的 `setAuthorityMenus` 调用 -- ✅ 路由只在框架初始化时创建一次 -- ✅ 登录后通过刷新页面重新加载路由 - -### 3. 修复 Vuex 模块命名空间问题 - -**修改的文件**: -- `src/components/main/main.vue` -- `src/components/main/components/user/user.vue` - -**修改前**: -```javascript -// main.vue -...mapGetters({ - sysFormModel: 'sysFormModel', // ❌ 缺少模块前缀 - menuList: 'menuList', - userName: 'userName', - userAvator: 'avatorImgPath' -}) - -// user.vue -...mapActions(['handleLogOut']) // ❌ 缺少模块前缀 -``` - -**修改后**: -```javascript -// main.vue -...mapGetters({ - sysFormModel: 'app/sysFormModel', // ✅ 添加模块前缀 - menuList: 'user/menuList', - userName: 'user/userName', - userAvator: 'user/avatorImgPath' -}) - -// user.vue -...mapActions('user', ['handleLogOut']) // ✅ 指定模块 -``` - -## 🎯 完整的首页路由流程 - -### 首次访问(未登录) - -``` -1. 用户访问 http://localhost:8080 - ↓ -2. 框架初始化 - ↓ -3. getRoutes 创建主路由 - - localStorage 中没有 authorityMenus - - 使用默认首页路由 - ↓ -4. 路由配置: - { - path: '/', - component: Main, - children: [ - { path: '/home', name: 'home', component: HomePage } - ] - } - ↓ -5. 显示登录页面 -``` - -### 登录流程 - -``` -1. 用户输入用户名密码 - ↓ -2. 调用登录接口 - ↓ -3. 保存 token 和用户信息 - ↓ -4. 调用 setAuthorityMenus - - 尝试获取权限菜单(可能失败) - - 使用默认菜单配置 - - 保存到 localStorage - ↓ -5. 刷新页面 (window.location.reload()) - ↓ -6. 重新执行首次访问流程 - - 此时 localStorage 中有 authorityMenus - - 根据权限菜单生成路由 -``` - -### 登录后访问 - -``` -1. 用户访问 http://localhost:8080 - ↓ -2. 框架初始化 - ↓ -3. getRoutes 创建主路由 - - localStorage 中有 authorityMenus - - 解析权限菜单 - - 生成权限路由 - ↓ -4. 路由配置: - { - path: '/', - component: Main, - children: [ - { path: '/home', name: 'home', component: HomePage }, - { path: '/system/user', name: 'sys_user', component: SysUser }, - { path: '/system/role', name: 'sys_role', component: SysRole }, - // ... 其他权限路由 - ] - } - ↓ -5. 显示系统首页 -``` - -## 📊 路由结构 - -### 完整的路由树 - -``` -routes: [ - // 登录页面 - { - path: '/login', - name: 'login', - component: LoginPage - }, - - // 主路由 - { - path: '/', - name: '主视图', - redirect: '/home', - component: Main, - children: [ - // 默认首页 - { - path: '/home', - name: 'home', - component: HomePage, - meta: { title: '首页', notCache: true } - }, - - // 权限路由(从 authorityMenus 生成) - { - path: '/system/user', - name: 'sys_user', - component: SysUser, - meta: { title: '用户管理' } - }, - { - path: '/system/role', - name: 'sys_role', - component: SysRole, - meta: { title: '角色管理' } - }, - // ... 更多权限路由 - ] - }, - - // 错误页面 - { - path: '/401', - name: 'error_401', - component: Page401 - }, - { - path: '/500', - name: 'error_500', - component: Page500 - }, - { - path: '*', - name: 'error_404', - component: Page404 - } -] -``` - -## ✅ 验证清单 - -### 功能验证 - -- ✅ 首次访问显示登录页面 -- ✅ 登录成功后跳转到首页 -- ✅ 首页正确显示 -- ✅ 左侧菜单正确显示 -- ✅ 系统标题正确显示 -- ✅ 用户名正确显示 -- ✅ 页面跳转正常 -- ✅ 刷新页面后状态保持 - -### 错误修复 - -- ✅ 修复了 `Cannot read properties of undefined (reading 'path')` 错误 -- ✅ 修复了 `[vuex] unknown action type: getSysTitle` 错误 -- ✅ 修复了 `[vuex] unknown getter: sysFormModel` 错误 -- ✅ 修复了首页路由重复设置的问题 - -## 💡 最佳实践 - -### 1. 路由创建原则 - -- **单一入口**:路由只在框架初始化时创建一次 -- **数据驱动**:根据 localStorage 中的数据动态生成路由 -- **默认兜底**:始终提供默认的首页路由 - -### 2. 权限菜单处理 - -- **登录时保存**:登录成功后保存权限菜单到 localStorage -- **启动时读取**:应用启动时从 localStorage 读取权限菜单 -- **刷新更新**:登录后刷新页面,重新生成路由 - -### 3. 避免的陷阱 - -- ❌ 不要在多个地方创建或修改路由 -- ❌ 不要在 mounted 钩子中重复设置菜单 -- ❌ 不要忘记处理 undefined 的情况 -- ❌ 不要忘记 Vuex 模块的命名空间 - -## 🎉 总结 - -### 修复的问题 - -1. ✅ 首页路由正确创建 -2. ✅ 权限菜单正确合并 -3. ✅ 避免了重复设置 -4. ✅ 修复了 Vuex 命名空间问题 -5. ✅ 流程清晰可维护 - -### 代码改进 - -- **减少复杂度**:移除了重复的菜单设置逻辑 -- **提高可读性**:流程更清晰,易于理解 -- **增强健壮性**:正确处理各种边界情况 -- **符合规范**:遵循 Vue 和 Vuex 的最佳实践 - ---- - -**首页路由梳理完成!** 🎉 - -现在路由创建流程清晰、简洁、可靠。 - diff --git a/demo-project/babel.config.js b/demo-project/babel.config.js deleted file mode 100644 index 30b8d8c..0000000 --- a/demo-project/babel.config.js +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = { - presets: [ - [ - '@babel/preset-env', - { - targets: { - browsers: ['> 1%', 'last 2 versions', 'not ie <= 8'] - } - } - ], - '@vue/babel-preset-jsx' - ] -} - diff --git a/demo-project/install.bat b/demo-project/install.bat deleted file mode 100644 index 21d6165..0000000 --- a/demo-project/install.bat +++ /dev/null @@ -1,39 +0,0 @@ -@echo off -echo ==================================== -echo 安装 Demo 项目依赖 -echo ==================================== -echo. - -echo [1/3] 清理旧依赖... -if exist "node_modules\" ( - echo 删除 node_modules 目录... - rmdir /s /q node_modules -) -if exist "package-lock.json" ( - echo 删除 package-lock.json... - del /f /q package-lock.json -) -echo. - -echo [2/3] 安装所有依赖... -echo 这可能需要几分钟时间,请耐心等待... -echo. -call npm install -echo. - -echo [3/3] 验证关键依赖... -echo. -call npm list @vue/babel-preset-jsx brace vue2-ace-editor --depth=0 -echo. - -echo ==================================== -echo 安装完成! -echo ==================================== -echo. -echo 现在可以运行以下命令启动项目: -echo 1. 双击 start.bat -echo 2. 或运行: npm run dev -echo. - -pause - diff --git a/demo-project/package.json b/demo-project/package.json deleted file mode 100644 index 9b5cb0b..0000000 --- a/demo-project/package.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "name": "demo-project", - "version": "1.0.0", - "description": "Admin Framework 使用示例项目", - "main": "src/main.js", - "scripts": { - "dev": "webpack-dev-server --mode development --open", - "build": "webpack --mode production" - }, - "keywords": [ - "admin", - "vue", - "demo" - ], - "author": "light", - "license": "MIT", - "dependencies": { - "axios": "^0.21.4", - "brace": "^0.11.1", - "core-js": "^3.45.1", - "dayjs": "^1.10.0", - "js-cookie": "^2.2.1", - "view-design": "^4.7.0", - "vue": "^2.6.14", - "vue-router": "^3.5.3", - "vue2-ace-editor": "^0.0.15", - "vuex": "^3.6.2", - "vuex-persistedstate": "^4.1.0" - }, - "devDependencies": { - "@babel/core": "^7.12.0", - "@babel/preset-env": "^7.12.0", - "@vue/babel-preset-jsx": "^1.4.0", - "babel-loader": "^8.2.0", - "css-loader": "^5.0.0", - "file-loader": "^6.2.0", - "html-webpack-plugin": "^5.5.0", - "less": "^4.0.0", - "less-loader": "^7.0.0", - "style-loader": "^2.0.0", - "url-loader": "^4.1.0", - "vue-loader": "^15.9.0", - "vue-style-loader": "^4.1.0", - "vue-template-compiler": "^2.6.14", - "webpack": "^5.0.0", - "webpack-cli": "^4.0.0", - "webpack-dev-server": "^4.0.0" - } -} diff --git a/demo-project/public/index.html b/demo-project/public/index.html deleted file mode 100644 index 388a2bf..0000000 --- a/demo-project/public/index.html +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - Demo 管理系统 - - - -
- - - diff --git a/demo-project/src/App.vue b/demo-project/src/App.vue deleted file mode 100644 index 1006329..0000000 --- a/demo-project/src/App.vue +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - diff --git a/demo-project/src/config/index.js b/demo-project/src/config/index.js deleted file mode 100644 index c8d73ea..0000000 --- a/demo-project/src/config/index.js +++ /dev/null @@ -1,23 +0,0 @@ -/** - * 项目配置文件 - */ -export default { - // 系统标题 - title: 'Demo 管理系统', - - // API 基础路径 - apiUrl: 'http://localhost:9098/admin_api/', - - // 文件上传路径 - uploadUrl: 'http://localhost:9098/admin_api/upload', - - // Token 存储的 key - tokenKey: 'demo_token', - - // 其他配置 - timeout: 30000, - - // 是否显示页面加载进度条 - showProgressBar: true -} - diff --git a/demo-project/src/main.js b/demo-project/src/main.js deleted file mode 100644 index 9dc3503..0000000 --- a/demo-project/src/main.js +++ /dev/null @@ -1,92 +0,0 @@ -import Vue from 'vue' -import VueRouter from 'vue-router' -import Vuex from 'vuex' -import ViewUI from 'view-design' -import createPersistedState from 'vuex-persistedstate' -import 'view-design/dist/styles/iview.css' - -// 引入框架(使用打包好的框架 JS) -import AdminFramework from './libs/admin-framework.js' - -// 引入配置 -import config from './config' - -// 引入根组件 -import App from './App.vue' - -// 引入业务页面(根据后端权限菜单接口返回的组件路径导入) -import ProductList from './views/business/product_list.vue' -// 根据你的权限菜单接口,导入所有可能用到的业务组件: -// import GamesComponent from './views/ball/games.vue' -// import PayOrdersComponent from './views/order/pay_orders.vue' -// import WchUsersComponent from './views/ball/wch_users.vue' -// ... 导入更多业务组件 - -// 🎉 使用框架 - 自动完成所有初始化 -Vue.use(AdminFramework, { - config, - ViewUI, - VueRouter, - Vuex, - createPersistedState, - // ✅ 在这里一次性注册所有业务组件映射 - componentMap: { - // 业务组件映射(根据后端菜单中的 component 字段配置) - 'business/product_list': ProductList - // 根据权限菜单接口返回的 component 字段添加映射: - // 'ball/games': GamesComponent, - // 'order/pay_orders': PayOrdersComponent, - // 'ball/wch_users': WchUsersComponent, - // 'order/wch_wallets': WchWalletsComponent, - // 'users/user_follows': UserFollowsComponent, - // ... 添加更多业务组件 - } -}) - -// 添加自定义业务路由(手动添加的路由) -const businessRoutes = [ - { - path: '/business/product', - name: 'product_list', - meta: { title: '产品列表' }, - component: ProductList - } -] - -// 将业务路由添加到主路由中 -const mainRoute = AdminFramework.router.options.routes.find(r => r.path === '/') -if (mainRoute && mainRoute.children) { - mainRoute.children.push(...businessRoutes) -} - -// 创建 Vue 实例 -window.rootVue = new Vue({ - el: '#app', - router: AdminFramework.router, - store: AdminFramework.store, - render: h => h(App), - mounted() { - // 设置响应式适配 - AdminFramework.uiTool.setRem() - - // 只在已登录时获取系统标题 - const token = this.$store.state.user.token - if (token) { - this.$store.dispatch('app/getSysTitle', { - defaultTitle: 'Demo 管理系统', - defaultLogo: '' - }) - } else { - // 未登录时,直接设置默认标题 - document.title = 'Demo 管理系统' - } - } -}) - -// 响应式适配 -window.addEventListener('load', AdminFramework.uiTool.setRem) -window.addEventListener('resize', AdminFramework.uiTool.setRem) - -console.log('✅ Demo 项目启动成功!') -console.log('框架版本:', AdminFramework.version) - diff --git a/demo-project/src/views/business/product_list.vue b/demo-project/src/views/business/product_list.vue deleted file mode 100644 index 9674bc0..0000000 --- a/demo-project/src/views/business/product_list.vue +++ /dev/null @@ -1,193 +0,0 @@ - - - - - - diff --git a/demo-project/start.bat b/demo-project/start.bat deleted file mode 100644 index ba6bed4..0000000 --- a/demo-project/start.bat +++ /dev/null @@ -1,38 +0,0 @@ -@echo off -echo ==================================== -echo Admin Framework Demo 启动脚本 -echo ==================================== -echo. - -:: 检查关键依赖是否存在 -if not exist "node_modules\@vue\babel-preset-jsx\" ( - echo [1/2] 首次运行或依赖缺失,正在安装依赖... - echo. - call npm install - echo. - echo [提示] 如果仍有错误,请运行以下命令: - echo npm install @vue/babel-preset-jsx brace vue2-ace-editor --save - echo. -) else ( - echo [✓] 依赖已安装 - echo. -) - -echo [2/2] 启动开发服务器... -echo. -echo 浏览器将自动打开 http://localhost:8080 -echo. -echo 可访问: -echo - /login - 登录页面 -echo - /home - 主页 -echo - /business/product - 业务示例 -echo. -echo 按 Ctrl+C 停止服务器 -echo. -echo ==================================== -echo. - -call npm run dev - -pause - diff --git a/demo-project/start.sh b/demo-project/start.sh deleted file mode 100644 index c692893..0000000 --- a/demo-project/start.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash - -echo "====================================" -echo " Admin Framework Demo 启动脚本" -echo "====================================" -echo "" - -# 检查 node_modules 是否存在 -if [ ! -d "node_modules" ]; then - echo "[1/2] 首次运行,正在安装依赖..." - echo "" - npm install - echo "" -else - echo "[✓] 依赖已安装" - echo "" -fi - -echo "[2/2] 启动开发服务器..." -echo "" -echo "浏览器将自动打开 http://localhost:8080" -echo "" -echo "可访问:" -echo " - /login - 登录页面" -echo " - /home - 主页" -echo " - /business/product - 业务示例" -echo "" -echo "按 Ctrl+C 停止服务器" -echo "" -echo "====================================" -echo "" - -npm run dev - diff --git a/demo-project/test-import.js b/demo-project/test-import.js deleted file mode 100644 index d4c9931..0000000 --- a/demo-project/test-import.js +++ /dev/null @@ -1,9 +0,0 @@ -// 测试引用框架源码 -try { - const AdminFramework = require('../src/index.js') - console.log('✅ 框架引用成功!') - console.log('框架版本:', AdminFramework.version || AdminFramework.default?.version) -} catch (error) { - console.error('❌ 框架引用失败:', error.message) -} - diff --git a/demo-project/webpack.config.js b/demo-project/webpack.config.js deleted file mode 100644 index eb99403..0000000 --- a/demo-project/webpack.config.js +++ /dev/null @@ -1,115 +0,0 @@ -const path = require('path') -const HtmlWebpackPlugin = require('html-webpack-plugin') -const { VueLoaderPlugin } = require('vue-loader') - -module.exports = (env, argv) => { - const isDevelopment = argv.mode === 'development' - - return { - entry: './src/main.js', - output: { - path: path.resolve(__dirname, 'dist'), - filename: isDevelopment ? 'bundle.js' : 'bundle.[contenthash:8].js', - clean: true - }, - // 开发模式使用高质量的 source map,方便调试 - devtool: isDevelopment ? 'eval-source-map' : 'source-map', - module: { - rules: [ - { - test: /\.vue$/, - loader: 'vue-loader' - }, - { - test: /\.js$/, - loader: 'babel-loader', - exclude: /node_modules/ - }, - { - test: /\.css$/, - use: [ - 'vue-style-loader', - { - loader: 'css-loader', - options: { - sourceMap: isDevelopment - } - } - ] - }, - { - test: /\.less$/, - use: [ - 'vue-style-loader', - { - loader: 'css-loader', - options: { - sourceMap: isDevelopment - } - }, - { - loader: 'less-loader', - options: { - sourceMap: isDevelopment - } - } - ] - }, - { - test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, - loader: 'url-loader', - options: { - limit: 10000, - name: 'images/[name].[hash:7].[ext]', - esModule: false - } - }, - { - test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, - loader: 'url-loader', - options: { - limit: 10000, - name: 'fonts/[name].[hash:7].[ext]', - esModule: false - } - } - ] - }, - plugins: [ - new VueLoaderPlugin(), - new HtmlWebpackPlugin({ - template: './public/index.html', - filename: 'index.html' - }) - ], - resolve: { - extensions: ['.js', '.vue', '.json'], - alias: { - // 框架源码的别名(必须在前面,优先级高) - '@': path.resolve(__dirname, '../src'), - '@component': path.resolve(__dirname, '../src/components'), - '@utils': path.resolve(__dirname, '../src/utils'), - '@api': path.resolve(__dirname, '../src/api'), - '@config': path.resolve(__dirname, '../src/config'), - '@assets': path.resolve(__dirname, '../src/assets'), - // demo 项目的别名 - '~': path.resolve(__dirname, 'src'), - 'vue$': 'vue/dist/vue.esm.js' - } - }, - devServer: { - port: 8080, - hot: true, - open: true, - historyApiFallback: true, - // 启用覆盖层显示编译错误 - client: { - overlay: { - errors: true, - warnings: false - } - } - } - } -} - diff --git a/demo-project/使用打包框架说明.md b/demo-project/使用打包框架说明.md deleted file mode 100644 index db40ee5..0000000 --- a/demo-project/使用打包框架说明.md +++ /dev/null @@ -1,206 +0,0 @@ -# 使用打包框架说明 - -## ✅ 已完成的修改 - -Demo 项目现在使用打包好的框架 JS 文件,而不是直接引用源码。 - -### 修改内容 - -**文件**: `demo-project/src/main.js` - -```javascript -// 修改前(直接使用源码) -import AdminFramework from '../../src/index.js' - -// 修改后(使用打包好的框架) -import AdminFramework from './libs/admin-framework.js' -``` - -### 文件结构 - -``` -demo-project/ -├── src/ -│ ├── libs/ -│ │ └── admin-framework.js ← 打包好的框架文件 -│ ├── main.js ← 引用框架的入口文件 -│ └── ... -└── ... -``` - -## 🔄 更新框架的步骤 - -当框架源码(`src/` 目录)有更新时,需要重新打包并复制到 demo 项目: - -### 方法一:使用 PowerShell 命令(推荐) - -```powershell -# 1. 在项目根目录打包框架 -npm run build - -# 2. 复制到 demo 项目 -if (-not (Test-Path "demo-project\src\libs")) { - New-Item -ItemType Directory -Path "demo-project\src\libs" -Force | Out-Null -} -Copy-Item "dist\admin-framework.js" "demo-project\src\libs\admin-framework.js" -Force -Write-Host "✅ 复制成功!" -ForegroundColor Green -``` - -### 方法二:手动操作 - -1. **打包框架** - ```bash - # 在项目根目录 - npm run build - ``` - -2. **复制文件** - - 将 `dist/admin-framework.js` 复制到 `demo-project/src/libs/admin-framework.js` - -3. **重启开发服务器** - ```bash - cd demo-project - npm run dev - ``` - -## 📊 优势 - -### 使用打包框架的优势 - -1. **✅ 性能更好** - - 打包后的文件经过优化和压缩 - - 减少了模块解析时间 - -2. **✅ 更接近生产环境** - - Demo 项目的使用方式和实际项目一致 - - 更容易发现潜在问题 - -3. **✅ 依赖隔离** - - Demo 项目不需要安装框架的所有依赖 - - 减少了依赖冲突的可能性 - -4. **✅ 更清晰的边界** - - 框架和业务代码分离更明确 - - 便于理解框架的使用方式 - -### 使用源码的优势(调试时) - -1. **✅ 实时更新** - - 修改源码后立即生效 - - 不需要重新打包 - -2. **✅ 调试方便** - - 可以直接在源码中打断点 - - 错误堆栈更清晰 - -## 🔧 开发建议 - -### 开发框架时 - -**使用源码引用**(临时修改): -```javascript -// demo-project/src/main.js -import AdminFramework from '../../src/index.js' -``` - -**优点**: -- 修改框架源码后立即生效 -- 方便调试和测试 - -### 测试框架时 - -**使用打包文件**(当前配置): -```javascript -// demo-project/src/main.js -import AdminFramework from './libs/admin-framework.js' -``` - -**优点**: -- 测试打包后的实际效果 -- 发现打包可能引入的问题 - -## 📝 注意事项 - -1. **打包后需要复制** - - 每次修改框架源码并打包后,需要重新复制到 demo 项目 - - 否则 demo 项目使用的还是旧版本 - -2. **Source Map** - - 打包时会生成 source map 文件 - - 方便在浏览器中调试打包后的代码 - -3. **版本管理** - - `demo-project/src/libs/admin-framework.js` 不应该提交到 Git - - 应该在 `.gitignore` 中忽略这个文件 - -4. **依赖更新** - - 如果框架的依赖有更新,需要重新打包 - - Demo 项目不需要安装框架的依赖 - -## 🎯 快速命令 - -### 一键更新框架到 Demo 项目 - -```powershell -# 打包并复制 -npm run build; if (-not (Test-Path "demo-project\src\libs")) { New-Item -ItemType Directory -Path "demo-project\src\libs" -Force | Out-Null }; Copy-Item "dist\admin-framework.js" "demo-project\src\libs\admin-framework.js" -Force; Write-Host "✅ 框架已更新到 Demo 项目!" -ForegroundColor Green -``` - -### 启动 Demo 项目 - -```bash -cd demo-project -npm run dev -``` - -## 📚 相关文件 - -- `build.bat` / `build.sh` - 框架打包脚本 -- `webpack.config.js` - Webpack 配置文件 -- `dist/admin-framework.js` - 打包后的框架文件 -- `demo-project/src/libs/admin-framework.js` - Demo 项目使用的框架文件 -- `demo-project/src/main.js` - Demo 项目入口文件 - -## 🔍 故障排查 - -### 问题:修改框架源码后,Demo 项目没有变化 - -**原因**:Demo 项目使用的是打包后的文件,不会自动更新 - -**解决方案**: -1. 重新打包框架:`npm run build` -2. 复制到 Demo 项目(使用上面的 PowerShell 命令) -3. 重启 Demo 项目的开发服务器 - -### 问题:找不到 admin-framework.js 文件 - -**原因**:还没有复制打包文件到 Demo 项目 - -**解决方案**: -```powershell -# 确保先打包 -npm run build - -# 然后复制 -if (-not (Test-Path "demo-project\src\libs")) { - New-Item -ItemType Directory -Path "demo-project\src\libs" -Force | Out-Null -} -Copy-Item "dist\admin-framework.js" "demo-project\src\libs\admin-framework.js" -Force -``` - -### 问题:控制台报错找不到模块 - -**原因**:可能是打包配置有问题,或者依赖没有正确打包 - -**解决方案**: -1. 检查 `webpack.config.js` 配置 -2. 确保所有依赖都已安装 -3. 重新打包:`npm run build` -4. 查看打包日志是否有错误 - ---- - -**当前状态**:✅ Demo 项目已配置为使用打包后的框架文件 - -**下一步**:启动 Demo 项目测试:`cd demo-project && npm run dev` - diff --git a/demo-project/启动说明.md b/demo-project/启动说明.md deleted file mode 100644 index 0202b1a..0000000 --- a/demo-project/启动说明.md +++ /dev/null @@ -1,119 +0,0 @@ -# Demo 项目启动说明 - -## ✅ 配置完成 - -Demo 项目已配置为使用打包好的框架 JS 文件。 - -## 🚀 启动步骤 - -### 1. 确保框架文件已复制 - -检查文件是否存在: -``` -demo-project/src/libs/admin-framework.js -``` - -如果不存在,在项目根目录执行: -```powershell -Copy-Item "dist\admin-framework.js" "demo-project\src\libs\admin-framework.js" -Force -``` - -### 2. 启动开发服务器 - -**方法一:使用命令行** -```bash -cd demo-project -npm run dev -``` - -**方法二:使用 start.bat(Windows)** -```bash -cd demo-project -start.bat -``` - -**方法三:使用 start.sh(Linux/Mac)** -```bash -cd demo-project -./start.sh -``` - -### 3. 访问应用 - -打开浏览器访问: -- **开发环境**:http://localhost:8080 -- **测试账号**:admin / admin123 - -## 📝 注意事项 - -1. **端口占用** - - 如果 8080 端口被占用,webpack 会自动使用其他端口 - - 查看终端输出的实际端口号 - -2. **首次启动** - - 首次启动可能需要较长时间编译 - - 等待 "Compiled successfully" 消息 - -3. **热更新** - - 修改代码后会自动刷新浏览器 - - 如果没有自动刷新,手动刷新页面 - -## 🔍 故障排查 - -### 问题:找不到 admin-framework.js - -**错误信息**: -``` -Module not found: Error: Can't resolve './libs/admin-framework.js' -``` - -**解决方案**: -```powershell -# 在项目根目录执行 -Copy-Item "dist\admin-framework.js" "demo-project\src\libs\admin-framework.js" -Force -``` - -### 问题:端口被占用 - -**错误信息**: -``` -Error: listen EADDRINUSE: address already in use :::8080 -``` - -**解决方案**: -1. 关闭占用 8080 端口的程序 -2. 或修改 `webpack.config.js` 中的端口配置 - -### 问题:编译错误 - -**解决方案**: -1. 检查 `src/main.js` 的引用路径是否正确 -2. 确保 `admin-framework.js` 文件完整 -3. 删除 `node_modules` 重新安装: - ```bash - rm -rf node_modules - npm install - ``` - -## 📚 相关文档 - -- `使用打包框架说明.md` - 详细使用说明 -- `框架更新完成.md` - 更新记录 -- `README.md` - 项目说明 - -## 🎯 下一步 - -启动成功后: -1. 使用测试账号登录 -2. 测试菜单导航功能 -3. 测试系统管理功能 -4. 查看浏览器控制台,确保没有错误 - ---- - -**当前状态**:✅ 就绪 - -**框架版本**:1.0.0 - -**启动命令**:`npm run dev` - diff --git a/demo-project/框架更新完成.md b/demo-project/框架更新完成.md deleted file mode 100644 index 76e604b..0000000 --- a/demo-project/框架更新完成.md +++ /dev/null @@ -1,157 +0,0 @@ -# 框架更新完成 ✅ - -## 📝 更新内容 - -Demo 项目已成功切换为使用打包好的框架 JS 文件。 - -### 修改的文件 - -1. **`demo-project/src/main.js`** - ```javascript - // 修改前 - import AdminFramework from '../../src/index.js' - - // 修改后 - import AdminFramework from './libs/admin-framework.js' - ``` - -2. **`demo-project/.gitignore`** - ``` - # 新增 - src/libs/admin-framework.js - ``` - -3. **新增文件** - - `demo-project/src/libs/admin-framework.js` - 打包好的框架文件 - - `demo-project/使用打包框架说明.md` - 使用说明文档 - -## 🎯 当前状态 - -- ✅ 框架已打包:`dist/admin-framework.js` -- ✅ 已复制到 Demo 项目:`demo-project/src/libs/admin-framework.js` -- ✅ Demo 项目已配置为使用打包文件 -- ✅ `.gitignore` 已更新,忽略框架文件 - -## 🚀 启动 Demo 项目 - -```bash -cd demo-project -npm run dev -``` - -访问:http://localhost:8080 - -## 🔄 更新框架的步骤 - -当框架源码有更新时: - -### 快速更新(一键命令) - -```powershell -# 在项目根目录执行 -npm run build; Copy-Item "dist\admin-framework.js" "demo-project\src\libs\admin-framework.js" -Force; Write-Host "✅ 框架已更新!" -ForegroundColor Green -``` - -### 分步操作 - -```bash -# 1. 打包框架 -npm run build - -# 2. 复制到 Demo 项目(PowerShell) -Copy-Item "dist\admin-framework.js" "demo-project\src\libs\admin-framework.js" -Force - -# 3. 重启 Demo 项目(如果正在运行) -cd demo-project -npm run dev -``` - -## 📊 优势 - -### 使用打包框架的好处 - -1. **性能更好** - 打包后的文件经过优化 -2. **更接近生产环境** - 和实际使用方式一致 -3. **依赖隔离** - Demo 项目不需要框架的所有依赖 -4. **边界清晰** - 框架和业务代码分离明确 - -### 开发时的建议 - -**调试框架时**:临时改回源码引用 -```javascript -// demo-project/src/main.js -import AdminFramework from '../../src/index.js' -``` - -**测试框架时**:使用打包文件(当前配置) -```javascript -// demo-project/src/main.js -import AdminFramework from './libs/admin-framework.js' -``` - -## 📚 相关文档 - -- `demo-project/使用打包框架说明.md` - 详细使用说明 -- `完整使用文档.md` - 框架完整文档 -- `README.md` - 项目说明 - -## 🔍 故障排查 - -### 问题:修改框架源码后,Demo 项目没有变化 - -**解决**: -```powershell -# 重新打包并复制 -npm run build -Copy-Item "dist\admin-framework.js" "demo-project\src\libs\admin-framework.js" -Force -``` - -### 问题:找不到 admin-framework.js - -**解决**: -```powershell -# 确保文件已复制 -if (-not (Test-Path "demo-project\src\libs\admin-framework.js")) { - Write-Host "❌ 文件不存在,正在复制..." -ForegroundColor Yellow - Copy-Item "dist\admin-framework.js" "demo-project\src\libs\admin-framework.js" -Force - Write-Host "✅ 复制完成!" -ForegroundColor Green -} -``` - -### 问题:控制台报错 - -**检查**: -1. 确保框架已正确打包:`npm run build` -2. 确保文件已复制到正确位置 -3. 查看浏览器控制台的详细错误信息 -4. 检查 `demo-project/src/main.js` 的引用路径 - -## 🎉 下一步 - -1. **启动 Demo 项目** - ```bash - cd demo-project - npm run dev - ``` - -2. **访问应用** - - 打开浏览器访问:http://localhost:8080 - - 使用测试账号登录 - -3. **测试功能** - - 登录功能 - - 菜单导航 - - 系统管理功能 - -4. **查看控制台** - - 确保没有错误 - - 查看框架版本信息 - ---- - -**更新完成时间**:2025-10-08 - -**框架版本**:1.0.0 - -**状态**:✅ 就绪 - diff --git a/demo-project/注释乱码修复说明.md b/demo-project/注释乱码修复说明.md deleted file mode 100644 index 6a012d0..0000000 --- a/demo-project/注释乱码修复说明.md +++ /dev/null @@ -1,175 +0,0 @@ -# 注释乱码修复说明 - -## 🐛 问题描述 - -控制台出现多个错误,主要原因是 `src/index.js` 文件中的中文注释出现了乱码,导致: - -1. **Upload 组件错误**:`TypeError: Cannot read properties of undefined (reading 'user')` - - 原因:`src/components/upload/Single.vue` 和 `Multiple.vue` 中使用了 `store.state.user.token`,但 store 未正确初始化 - -2. **TreeGrid 组件错误**:`ReferenceError: Cannot access '__WEBPACK_DEFAULT_EXPORT__' before initialization` - - 原因:`src/components/treeGrid/component/subTreeGrid.vue` 中有循环引用问题 - -3. **LoginPage 未定义错误**:`ReferenceError: LoginPage is not defined` - - 原因:`src/index.js` 第43行的 import 语句和注释在同一行,导致 import 被注释掉 - -4. **Editor 未定义错误**:`ReferenceError: Editor is not defined` - - 原因:`registerGlobalComponents` 方法中引用了未导入的组件 - -5. **map 未定义错误**:`ReferenceError: map is not defined` - - 原因:`setupComponentMap` 方法中的注释格式不对,导致代码被注释掉 - -## ✅ 已修复的问题 - -### 1. Upload 组件修复 - -**修改文件**: -- `src/components/upload/Single.vue` -- `src/components/upload/Multiple.vue` - -**修改内容**: -```javascript -// 修改前 -import store from '@/store' -let headers = { - 'admin-token': store.state.user.token, -} - -// 修改后 -import { getToken } from '@/utils/tools' -let headers = { - 'admin-token': getToken(), -} -``` - -**原因**: -- 使用 `getToken()` 函数从 localStorage 获取 token,避免依赖 store 初始化顺序 - -### 2. TreeGrid 组件修复 - -**修改文件**: -- `src/components/treeGrid/component/subTreeGrid.vue` - -**修改内容**: -```javascript -// 修改前 -import SubTreeGrid from './subTreeGrid.vue' -export default { - components: { - SubTreeGrid, - // ... - } -} - -// 修改后 -export default { - components: { - SubTreeGrid: () => import('./subTreeGrid.vue'), // 使用异步组件 - // ... - } -} -``` - -**原因**: -- 递归组件需要使用异步组件来避免循环引用问题 - -## ⚠️ 待修复的问题 - -### 3. src/index.js 文件乱码 - -**问题**: -- 文件中的中文注释出现乱码(如:`閫氱敤鍚庡彴绠$悊绯荤粺妗嗘灦` 应该是 `通用后台管理系统框架`) -- 第43行的 import 语句和注释在同一行 -- `registerGlobalComponents` 方法中有重复的组件注册 -- `setupComponentMap` 方法中的注释格式不对 - -**需要修复的关键行**: - -#### 第43行(最关键) -```javascript -// 当前(错误) -// 鐧诲綍鍜岄敊璇〉闈?import LoginPage from './views/login/login.vue' - -// 应该改为 -// 登录和错误页面 -import LoginPage from './views/login/login.vue' -``` - -#### registerGlobalComponents 方法 -```javascript -// 删除重复的组件注册(第218-235行) -// 只保留第206-216行的组件注册 -``` - -#### setupComponentMap 方法 -```javascript -// 第234行 -// 当前(错误) - // 鍚堝苟澶栭儴浼犲叆鐨勭粍浠舵槧灏? ...customMap - -// 应该改为 - // 合并外部传入的组件映射 - ...customMap - -// 第237行 -// 当前(错误) - // 鑷姩鐢熸垚甯?.vue 鍜屼笉甯?.vue 鐨勬槧灏? const map = {} - -// 应该改为 - // 自动生成带.vue 和不带.vue 的映射 - const map = {} -``` - -## 🔧 修复方法 - -### 方法一:使用 Git 恢复 + 手动修复 - -```bash -# 1. 恢复文件到最近的正确版本 -git checkout src/index.js - -# 2. 手动修复关键问题(使用编辑器) -# - 确保第43行的 import 语句独立一行 -# - 删除重复的组件注册 -# - 修复注释格式 -``` - -### 方法二:重新创建文件 - -由于乱码问题严重,建议: -1. 备份当前文件 -2. 从 Git 历史中找到最近的正确版本 -3. 重新应用必要的修改 - -## 📝 预防措施 - -1. **使用 UTF-8 编码保存文件** - - 确保编辑器设置为 UTF-8 编码 - - 避免使用 ANSI 或 GBK 编码 - -2. **避免注释和代码在同一行** - - 注释应该独立一行 - - 特别是 import 语句前的注释 - -3. **定期检查文件编码** - - 使用 `file` 命令检查文件编码 - - 使用 `iconv` 或编辑器转换编码 - -## 🎯 下一步 - -1. 修复 `src/index.js` 文件的编码问题 -2. 确保所有中文注释正确显示 -3. 测试页面是否正常加载 -4. 检查控制台是否还有错误 - -## 📚 相关文件 - -- `src/index.js` - 框架入口文件(需要修复) -- `src/components/upload/Single.vue` - 已修复 -- `src/components/upload/Multiple.vue` - 已修复 -- `src/components/treeGrid/component/subTreeGrid.vue` - 已修复 - ---- - -**修复状态**:部分完成,等待 `src/index.js` 文件修复 - diff --git a/package-lock.json b/package-lock.json index 42ade6c..d55c5f5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,11 +24,13 @@ "devDependencies": { "@babel/core": "^7.12.0", "@babel/preset-env": "^7.12.0", + "autoprefixer": "^10.4.21", "babel-loader": "^8.2.0", "css-loader": "^5.0.0", "file-loader": "^6.2.0", "less": "^4.0.0", "less-loader": "^7.0.0", + "postcss": "^8.5.6", "style-loader": "^2.0.0", "url-loader": "^4.1.0", "vue-loader": "^15.9.0", @@ -2455,6 +2457,44 @@ "license": "MIT", "peer": true }, + "node_modules/autoprefixer": { + "version": "10.4.21", + "resolved": "https://registry.npmmirror.com/autoprefixer/-/autoprefixer-10.4.21.tgz", + "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.24.4", + "caniuse-lite": "^1.0.30001702", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, "node_modules/axios": { "version": "0.21.4", "resolved": "https://registry.npmmirror.com/axios/-/axios-0.21.4.tgz", @@ -3209,6 +3249,20 @@ } } }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmmirror.com/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz", @@ -3816,6 +3870,16 @@ "integrity": "sha512-cCmFDMSm26S6tQSDpBCg/NR8NENrVPhAJSf+XbxBG4rPFaaonlEoE9wHQmun+cls499TQGSb7ZyPBRlzgKfpeg==", "license": "MIT" }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmmirror.com/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-2.3.0.tgz", diff --git a/package.json b/package.json index 8eca3c1..8ca283e 100644 --- a/package.json +++ b/package.json @@ -38,11 +38,13 @@ "devDependencies": { "@babel/core": "^7.12.0", "@babel/preset-env": "^7.12.0", + "autoprefixer": "^10.4.21", "babel-loader": "^8.2.0", "css-loader": "^5.0.0", "file-loader": "^6.2.0", "less": "^4.0.0", "less-loader": "^7.0.0", + "postcss": "^8.5.6", "style-loader": "^2.0.0", "url-loader": "^4.1.0", "vue-loader": "^15.9.0", diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..fba5f9e --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,16 @@ +// PostCSS 配置文件 +// 用于处理 CSS 样式转换和优化 +module.exports = { + plugins: { + // 自动添加浏览器前缀 + autoprefixer: { + overrideBrowserslist: [ + '> 1%', + 'last 2 versions', + 'not dead', + 'not ie <= 11' + ] + } + } +} +