|
|
|
|
|
# RuoYi-Vue 前端现代化重构实施计划
|
|
|
|
|
|
|
|
|
|
|
|
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
```yaml
|
|
|
|
|
|
---
|
|
|
|
|
|
change: refactor-frontend-modernization
|
|
|
|
|
|
design-doc: docs/superpowers/specs/2026-06-28-frontend-modernization-design.md
|
|
|
|
|
|
base-ref: 1c7d266b7f70eae46abd1f011e443ac54b4cc7f4
|
|
|
|
|
|
---
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**Goal:** 将 RuoYi-Vue 前端从 Vue2 + Vue CLI + Element UI + Vuex 升级到 Vue3 + Vite + TypeScript + Element Plus + Pinia,同时参考 demo-dashboard-heatmap.html 的深色主题和数据可视化风格,保持与现有后端 API 完全兼容。
|
|
|
|
|
|
|
|
|
|
|
|
**Architecture:** 采用渐进式迁移策略,先在独立目录 (`ruoyi-ui-next/`) 构建新项目,按模块逐步迁移组件和页面,确保后端零改动。
|
|
|
|
|
|
|
|
|
|
|
|
**Tech Stack:**
|
|
|
|
|
|
| 类别 | 旧技术栈 | 新技术栈 |
|
|
|
|
|
|
|------|---------|---------|
|
|
|
|
|
|
| 框架 | Vue 2.6.12 | Vue 3.5+ |
|
|
|
|
|
|
| 构建 | Vue CLI 4.4.6 | Vite 6+ |
|
|
|
|
|
|
| 语言 | JavaScript | TypeScript 5+ |
|
|
|
|
|
|
| UI | Element UI 2.15.6 | Element Plus 2.9+ |
|
|
|
|
|
|
| 路由 | Vue Router 3.4.9 | Vue Router 4+ |
|
|
|
|
|
|
| 状态 | Vuex 3.6.0 | Pinia 2.3+ |
|
|
|
|
|
|
| HTTP | Axios 0.24.0 | Axios 1.7+ |
|
|
|
|
|
|
| 图表 | ECharts 4.9.0 | ECharts 5.5+ |
|
|
|
|
|
|
| CSS | Sass 1.32 | SCSS + CSS Variables |
|
|
|
|
|
|
|
|
|
|
|
|
## Global Constraints
|
|
|
|
|
|
|
|
|
|
|
|
- **新项目目录**: `ruoyi-ui-next/`(与 `ruoyi-ui/` 并存,不影响现有前端)
|
|
|
|
|
|
- **后端兼容**: 所有 API 路径、请求格式、响应格式保持完全一致
|
|
|
|
|
|
- **权限兼容**: 沿用 `Admin-Token` Cookie 认证和 `*:*:*` 权限标识体系
|
|
|
|
|
|
- **深色主题默认**: 默认深色主题,配色方案源自 `data/demo-dashboard-heatmap.html`
|
|
|
|
|
|
- **TypeScript 严格模式**: 启用 `strict: true`,所有新增代码必须有类型标注
|
|
|
|
|
|
- **代码风格**: ESLint + Prettier + Vue 3 `<script setup>` 语法
|
|
|
|
|
|
- **组件命名**: PascalCase 文件名,kebab-case 标签名
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## Task 1: 项目初始化
|
|
|
|
|
|
|
|
|
|
|
|
**目标**: 使用 Vite 创建 Vue3 + TypeScript 项目骨架,配置开发工具链
|
|
|
|
|
|
|
|
|
|
|
|
**Files:**
|
|
|
|
|
|
- Create: `ruoyi-ui-next/package.json`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/vite.config.ts`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/tsconfig.json`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/tsconfig.node.json`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/index.html`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/.env.development`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/.env.production`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/.eslintrc.cjs`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/.prettierrc`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/.editorconfig`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/.gitignore`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/main.ts`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/App.vue`
|
|
|
|
|
|
- Reference: `ruoyi-ui/package.json`(依赖参考)
|
|
|
|
|
|
- Reference: `ruoyi-ui/.env.development`(环境变量参考)
|
|
|
|
|
|
|
|
|
|
|
|
**Description:** 创建全新 Vite + Vue3 + TypeScript 项目,配置完整的开发工具链和项目结构
|
|
|
|
|
|
|
|
|
|
|
|
**Dependencies:** 无
|
|
|
|
|
|
|
|
|
|
|
|
### Step 1: 初始化项目结构
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
ruoyi-ui-next/
|
|
|
|
|
|
├── public/
|
|
|
|
|
|
│ └── favicon.ico
|
|
|
|
|
|
├── src/
|
|
|
|
|
|
│ ├── api/ # API 调用层
|
|
|
|
|
|
│ │ ├── index.ts # 通用 API
|
|
|
|
|
|
│ │ ├── login.ts # 登录/认证
|
|
|
|
|
|
│ │ ├── menu.ts # 路由菜单
|
|
|
|
|
|
│ │ ├── system/ # 系统管理 API
|
|
|
|
|
|
│ │ │ ├── user.ts
|
|
|
|
|
|
│ │ │ ├── role.ts
|
|
|
|
|
|
│ │ │ ├── menu.ts
|
|
|
|
|
|
│ │ │ ├── dept.ts
|
|
|
|
|
|
│ │ │ ├── config.ts
|
|
|
|
|
|
│ │ │ ├── notice.ts
|
|
|
|
|
|
│ │ │ ├── post.ts
|
|
|
|
|
|
│ │ │ └── dict/
|
|
|
|
|
|
│ │ │ ├── data.ts
|
|
|
|
|
|
│ │ │ └── type.ts
|
|
|
|
|
|
│ │ ├── monitor/ # 系统监控 API
|
|
|
|
|
|
│ │ │ ├── cache.ts
|
|
|
|
|
|
│ │ │ ├── job.ts
|
|
|
|
|
|
│ │ │ ├── logininfor.ts
|
|
|
|
|
|
│ │ │ ├── online.ts
|
|
|
|
|
|
│ │ │ ├── operlog.ts
|
|
|
|
|
|
│ │ │ └── server.ts
|
|
|
|
|
|
│ │ ├── booksystem/ # 账本系统 API
|
|
|
|
|
|
│ │ │ ├── account.ts
|
|
|
|
|
|
│ │ │ ├── book.ts
|
|
|
|
|
|
│ │ │ ├── operations.ts
|
|
|
|
|
|
│ │ │ ├── statistics.ts
|
|
|
|
|
|
│ │ │ ├── statistictotal.ts
|
|
|
|
|
|
│ │ │ └── statisticremain.ts
|
|
|
|
|
|
│ │ └── stocksystem/ # 股票系统 API
|
|
|
|
|
|
│ │ ├── stocks.ts
|
|
|
|
|
|
│ │ ├── stockbasic.ts
|
|
|
|
|
|
│ │ ├── stockindex.ts
|
|
|
|
|
|
│ │ ├── financial.ts
|
|
|
|
|
|
│ │ ├── trends.ts
|
|
|
|
|
|
│ │ ├── trendStocks.ts
|
|
|
|
|
|
│ │ ├── newrecord.ts
|
|
|
|
|
|
│ │ ├── stockslimit.ts
|
|
|
|
|
|
│ │ └── book.ts
|
|
|
|
|
|
│ ├── assets/
|
|
|
|
|
|
│ │ ├── icons/svg/ # SVG 图标(从 ruoyi-ui 复制全部)
|
|
|
|
|
|
│ │ ├── styles/ # 全局样式
|
|
|
|
|
|
│ │ │ ├── index.scss
|
|
|
|
|
|
│ │ │ ├── variables.scss
|
|
|
|
|
|
│ │ │ ├── dark-theme.scss
|
|
|
|
|
|
│ │ │ └── transition.scss
|
|
|
|
|
|
│ │ └── images/ # 静态图片
|
|
|
|
|
|
│ ├── components/ # 全局通用组件
|
|
|
|
|
|
│ │ ├── SvgIcon/
|
|
|
|
|
|
│ │ ├── DictTag/
|
|
|
|
|
|
│ │ ├── Pagination/
|
|
|
|
|
|
│ │ ├── Breadcrumb/
|
|
|
|
|
|
│ │ ├── Hamburger/
|
|
|
|
|
|
│ │ ├── Screenfull/
|
|
|
|
|
|
│ │ ├── SizeSelect/
|
|
|
|
|
|
│ │ ├── ThemePicker/
|
|
|
|
|
|
│ │ ├── TopNav/
|
|
|
|
|
|
│ │ ├── RightToolbar/
|
|
|
|
|
|
│ │ ├── Editor/
|
|
|
|
|
|
│ │ ├── FileUpload/
|
|
|
|
|
|
│ │ ├── ImageUpload/
|
|
|
|
|
|
│ │ ├── ImagePreview/
|
|
|
|
|
|
│ │ ├── IconSelect/
|
|
|
|
|
|
│ │ ├── HeaderSearch/
|
|
|
|
|
|
│ │ ├── Crontab/
|
|
|
|
|
|
│ │ ├── ParentView/
|
|
|
|
|
|
│ │ └── iFrame/
|
|
|
|
|
|
│ ├── components-business/ # 业务组件(解耦通用组件)
|
|
|
|
|
|
│ │ ├── Kdialog/
|
|
|
|
|
|
│ │ ├── NegativeDialog/
|
|
|
|
|
|
│ │ └── TrendStocksDialog/
|
|
|
|
|
|
│ ├── layout/ # 布局框架
|
|
|
|
|
|
│ │ ├── index.vue
|
|
|
|
|
|
│ │ └── components/
|
|
|
|
|
|
│ │ ├── AppMain.vue
|
|
|
|
|
|
│ │ ├── Navbar.vue
|
|
|
|
|
|
│ │ ├── Sidebar/
|
|
|
|
|
|
│ │ ├── TagsView/
|
|
|
|
|
|
│ │ ├── Settings/
|
|
|
|
|
|
│ │ └── InnerLink/
|
|
|
|
|
|
│ ├── router/
|
|
|
|
|
|
│ │ └── index.ts
|
|
|
|
|
|
│ ├── stores/ # Pinia 状态管理
|
|
|
|
|
|
│ │ ├── index.ts
|
|
|
|
|
|
│ │ ├── modules/
|
|
|
|
|
|
│ │ │ ├── app.ts
|
|
|
|
|
|
│ │ │ ├── user.ts
|
|
|
|
|
|
│ │ │ ├── permission.ts
|
|
|
|
|
|
│ │ │ ├── tagsView.ts
|
|
|
|
|
|
│ │ │ └── settings.ts
|
|
|
|
|
|
│ │ └── types.ts
|
|
|
|
|
|
│ ├── views/ # 页面视图
|
|
|
|
|
|
│ │ ├── dashboard/
|
|
|
|
|
|
│ │ ├── system/
|
|
|
|
|
|
│ │ ├── booksystem/
|
|
|
|
|
|
│ │ ├── stocksystem/
|
|
|
|
|
|
│ │ ├── monitor/
|
|
|
|
|
|
│ │ ├── tool/
|
|
|
|
|
|
│ │ ├── error/
|
|
|
|
|
|
│ │ ├── login.vue
|
|
|
|
|
|
│ │ ├── register.vue
|
|
|
|
|
|
│ │ └── index.vue
|
|
|
|
|
|
│ ├── utils/ # 工具函数
|
|
|
|
|
|
│ │ ├── request.ts
|
|
|
|
|
|
│ │ ├── auth.ts
|
|
|
|
|
|
│ │ ├── permission.ts
|
|
|
|
|
|
│ │ ├── validate.ts
|
|
|
|
|
|
│ │ ├── errorCode.ts
|
|
|
|
|
|
│ │ ├── ruoyi.ts
|
|
|
|
|
|
│ │ ├── dict/
|
|
|
|
|
|
│ │ └── types/
|
|
|
|
|
|
│ ├── directives/ # 自定义指令
|
|
|
|
|
|
│ │ ├── index.ts
|
|
|
|
|
|
│ │ └── permission.ts
|
|
|
|
|
|
│ ├── plugins/ # 插件(从 ruoyi-ui 重构)
|
|
|
|
|
|
│ │ ├── index.ts
|
|
|
|
|
|
│ │ ├── auth.ts
|
|
|
|
|
|
│ │ ├── cache.ts
|
|
|
|
|
|
│ │ ├── modal.ts
|
|
|
|
|
|
│ │ └── tab.ts
|
|
|
|
|
|
│ ├── types/ # TypeScript 类型定义
|
|
|
|
|
|
│ │ ├── api.d.ts
|
|
|
|
|
|
│ │ ├── store.d.ts
|
|
|
|
|
|
│ │ ├── router.d.ts
|
|
|
|
|
|
│ │ └── global.d.ts
|
|
|
|
|
|
│ └── permission.ts # 路由权限守卫
|
|
|
|
|
|
├── index.html
|
|
|
|
|
|
├── vite.config.ts
|
|
|
|
|
|
├── tsconfig.json
|
|
|
|
|
|
├── package.json
|
|
|
|
|
|
└── .env.*
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] **Step 1.1: 创建 package.json**
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"name": "ruoyi-ui-next",
|
|
|
|
|
|
"version": "4.0.0",
|
|
|
|
|
|
"private": true,
|
|
|
|
|
|
"type": "module",
|
|
|
|
|
|
"scripts": {
|
|
|
|
|
|
"dev": "vite",
|
|
|
|
|
|
"build": "vue-tsc --noEmit && vite build",
|
|
|
|
|
|
"build:prod": "vite build --mode production",
|
|
|
|
|
|
"preview": "vite preview",
|
|
|
|
|
|
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx --fix",
|
|
|
|
|
|
"format": "prettier --write src/"
|
|
|
|
|
|
},
|
|
|
|
|
|
"dependencies": {
|
|
|
|
|
|
"vue": "^3.5.0",
|
|
|
|
|
|
"vue-router": "^4.4.0",
|
|
|
|
|
|
"pinia": "^2.3.0",
|
|
|
|
|
|
"pinia-plugin-persistedstate": "^4.0.0",
|
|
|
|
|
|
"axios": "^1.7.0",
|
|
|
|
|
|
"element-plus": "^2.9.0",
|
|
|
|
|
|
"@element-plus/icons-vue": "^2.3.0",
|
|
|
|
|
|
"echarts": "^5.5.0",
|
|
|
|
|
|
"nprogress": "^0.2.0",
|
|
|
|
|
|
"js-cookie": "^3.0.5",
|
|
|
|
|
|
"jsencrypt": "^3.3.0",
|
|
|
|
|
|
"lodash-es": "^4.17.21",
|
|
|
|
|
|
"dayjs": "^1.11.0"
|
|
|
|
|
|
},
|
|
|
|
|
|
"devDependencies": {
|
|
|
|
|
|
"@vitejs/plugin-vue": "^5.2.0",
|
|
|
|
|
|
"vite": "^6.0.0",
|
|
|
|
|
|
"vite-plugin-svg-icons": "^2.0.1",
|
|
|
|
|
|
"vue-tsc": "^2.2.0",
|
|
|
|
|
|
"typescript": "^5.7.0",
|
|
|
|
|
|
"sass": "^1.83.0",
|
|
|
|
|
|
"@types/node": "^22.0.0",
|
|
|
|
|
|
"@types/nprogress": "^0.2.3",
|
|
|
|
|
|
"@types/js-cookie": "^3.0.6",
|
|
|
|
|
|
"@types/lodash-es": "^4.17.12",
|
|
|
|
|
|
"eslint": "^9.0.0",
|
|
|
|
|
|
"@eslint/js": "^9.0.0",
|
|
|
|
|
|
"eslint-plugin-vue": "^9.0.0",
|
|
|
|
|
|
"typescript-eslint": "^8.0.0",
|
|
|
|
|
|
"prettier": "^3.4.0",
|
|
|
|
|
|
"unplugin-auto-import": "^0.18.0",
|
|
|
|
|
|
"unplugin-vue-components": "^0.27.0"
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] **Step 1.2: 创建 vite.config.ts**
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
import { defineConfig, loadEnv } from 'vite'
|
|
|
|
|
|
import vue from '@vitejs/plugin-vue'
|
|
|
|
|
|
import { resolve } from 'path'
|
|
|
|
|
|
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
|
|
|
|
|
|
import AutoImport from 'unplugin-auto-import/vite'
|
|
|
|
|
|
import Components from 'unplugin-vue-components/vite'
|
|
|
|
|
|
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
|
|
|
|
|
|
|
|
|
|
|
|
export default defineConfig(({ mode }) => {
|
|
|
|
|
|
const env = loadEnv(mode, process.cwd())
|
|
|
|
|
|
return {
|
|
|
|
|
|
plugins: [
|
|
|
|
|
|
vue(),
|
|
|
|
|
|
createSvgIconsPlugin({
|
|
|
|
|
|
iconDirs: [resolve(__dirname, 'src/assets/icons/svg')],
|
|
|
|
|
|
symbolId: 'icon-[dir]-[name]',
|
|
|
|
|
|
}),
|
|
|
|
|
|
AutoImport({
|
|
|
|
|
|
imports: ['vue', 'vue-router', 'pinia'],
|
|
|
|
|
|
resolvers: [ElementPlusResolver()],
|
|
|
|
|
|
dts: 'src/types/auto-imports.d.ts',
|
|
|
|
|
|
}),
|
|
|
|
|
|
Components({
|
|
|
|
|
|
resolvers: [ElementPlusResolver()],
|
|
|
|
|
|
dts: 'src/types/components.d.ts',
|
|
|
|
|
|
}),
|
|
|
|
|
|
],
|
|
|
|
|
|
resolve: {
|
|
|
|
|
|
alias: {
|
|
|
|
|
|
'@': resolve(__dirname, 'src'),
|
|
|
|
|
|
},
|
|
|
|
|
|
extensions: ['.ts', '.js', '.vue', '.json'],
|
|
|
|
|
|
},
|
|
|
|
|
|
server: {
|
|
|
|
|
|
port: 80,
|
|
|
|
|
|
host: '0.0.0.0',
|
|
|
|
|
|
open: true,
|
|
|
|
|
|
proxy: {
|
|
|
|
|
|
'/dev-api': {
|
|
|
|
|
|
target: env.VITE_APP_BASE_URL || 'http://localhost:8080',
|
|
|
|
|
|
changeOrigin: true,
|
|
|
|
|
|
rewrite: (path) => path.replace(/^\/dev-api/, ''),
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
build: {
|
|
|
|
|
|
target: 'es2015',
|
|
|
|
|
|
outDir: 'dist',
|
|
|
|
|
|
sourcemap: false,
|
|
|
|
|
|
rollupOptions: {
|
|
|
|
|
|
output: {
|
|
|
|
|
|
manualChunks: {
|
|
|
|
|
|
'element-plus': ['element-plus'],
|
|
|
|
|
|
echarts: ['echarts'],
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
css: {
|
|
|
|
|
|
preprocessorOptions: {
|
|
|
|
|
|
scss: {
|
|
|
|
|
|
additionalData: `@use "@/assets/styles/variables.scss" as *;`,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] **Step 1.3: 创建 tsconfig.json**
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"compilerOptions": {
|
|
|
|
|
|
"target": "ES2020",
|
|
|
|
|
|
"module": "ESNext",
|
|
|
|
|
|
"moduleResolution": "bundler",
|
|
|
|
|
|
"strict": true,
|
|
|
|
|
|
"jsx": "preserve",
|
|
|
|
|
|
"importHelpers": true,
|
|
|
|
|
|
"experimentalDecorators": true,
|
|
|
|
|
|
"skipLibCheck": true,
|
|
|
|
|
|
"esModuleInterop": true,
|
|
|
|
|
|
"allowSyntheticDefaultImports": true,
|
|
|
|
|
|
"forceConsistentCasingInFileNames": true,
|
|
|
|
|
|
"useDefineForClassFields": true,
|
|
|
|
|
|
"sourceMap": true,
|
|
|
|
|
|
"baseUrl": ".",
|
|
|
|
|
|
"paths": {
|
|
|
|
|
|
"@/*": ["src/*"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
|
|
|
|
"types": ["vite/client"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.vue"],
|
|
|
|
|
|
"exclude": ["node_modules", "dist"]
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] **Step 1.4: 创建环境变量文件**
|
|
|
|
|
|
|
|
|
|
|
|
`.env.development`:
|
|
|
|
|
|
```
|
|
|
|
|
|
VITE_APP_TITLE=摸金分析系统
|
|
|
|
|
|
VITE_APP_BASE_API=/dev-api
|
|
|
|
|
|
VITE_APP_BASE_URL=http://localhost:8080
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
`.env.production`:
|
|
|
|
|
|
```
|
|
|
|
|
|
VITE_APP_TITLE=摸金分析系统
|
|
|
|
|
|
VITE_APP_BASE_API=/prod-api
|
|
|
|
|
|
VITE_APP_BASE_URL=
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] **Step 1.5: 创建 .eslintrc.cjs + .prettierrc**
|
|
|
|
|
|
|
|
|
|
|
|
配置 ESLint 规则:
|
|
|
|
|
|
- `@typescript-eslint/strict`
|
|
|
|
|
|
- `vue/vue3-recommended`
|
|
|
|
|
|
- Prettier 集成
|
|
|
|
|
|
|
|
|
|
|
|
Prettier 配置:
|
|
|
|
|
|
- 2 空格缩进
|
|
|
|
|
|
- 单引号
|
|
|
|
|
|
- 末尾无分号
|
|
|
|
|
|
- 行宽 100
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] **Step 1.6: 创建项目入口文件**
|
|
|
|
|
|
|
|
|
|
|
|
`src/main.ts`:
|
|
|
|
|
|
- 创建 Vue App
|
|
|
|
|
|
- 注册 Element Plus(含中文语言包)
|
|
|
|
|
|
- 注册 Pinia
|
|
|
|
|
|
- 注册 Vue Router
|
|
|
|
|
|
- 注册全局指令
|
|
|
|
|
|
- 注册全局插件
|
|
|
|
|
|
- 挂载应用
|
|
|
|
|
|
|
|
|
|
|
|
`src/App.vue`:
|
|
|
|
|
|
- 根组件,仅包含 `<router-view />`
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] **Step 1.7: 复制 SVG 图标资源**
|
|
|
|
|
|
|
|
|
|
|
|
从 `ruoyi-ui/src/assets/icons/svg/` 复制所有 SVG 文件到 `ruoyi-ui-next/src/assets/icons/svg/`
|
|
|
|
|
|
|
|
|
|
|
|
**验收标准:**
|
|
|
|
|
|
- [ ] `npm install` 无报错
|
|
|
|
|
|
- [ ] `npm run dev` 成功启动,访问 `http://localhost` 显示空白页面(仅 App.vue)
|
|
|
|
|
|
- [ ] TypeScript 编译通过(`vue-tsc --noEmit`)
|
|
|
|
|
|
- [ ] ESLint 检查通过(`npm run lint`)
|
|
|
|
|
|
- [ ] 项目结构与规范一致
|
|
|
|
|
|
- [ ] `ruoyi-ui/` 不受任何影响
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## Task 2: 核心架构搭建
|
|
|
|
|
|
|
|
|
|
|
|
**目标**: 配置 Vue Router 4、Pinia 状态管理、Axios 调用层、权限控制机制
|
|
|
|
|
|
|
|
|
|
|
|
**Files:**
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/router/index.ts`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/stores/index.ts`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/stores/modules/app.ts`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/stores/modules/user.ts`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/stores/modules/permission.ts`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/stores/modules/tagsView.ts`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/stores/modules/settings.ts`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/stores/types.ts`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/utils/request.ts`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/utils/auth.ts`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/utils/permission.ts`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/utils/errorCode.ts`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/utils/types/api.ts`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/types/global.d.ts`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/types/store.d.ts`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/types/router.d.ts`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/directives/index.ts`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/directives/permission.ts`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/plugins/index.ts`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/plugins/auth.ts`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/plugins/cache.ts`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/plugins/modal.ts`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/plugins/tab.ts`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/permission.ts`
|
|
|
|
|
|
- Reference: `ruoyi-ui/src/router/index.js`
|
|
|
|
|
|
- Reference: `ruoyi-ui/src/store/modules/*.js`
|
|
|
|
|
|
- Reference: `ruoyi-ui/src/utils/request.js`
|
|
|
|
|
|
- Reference: `ruoyi-ui/src/permission.js`
|
|
|
|
|
|
- Reference: `ruoyi-ui/src/plugins/*.js`
|
|
|
|
|
|
- Reference: `ruoyi-ui/src/directive/`
|
|
|
|
|
|
|
|
|
|
|
|
**Dependencies:** Task 1 完成
|
|
|
|
|
|
|
|
|
|
|
|
### Step 2.1: 配置 TypeScript 类型定义
|
|
|
|
|
|
|
|
|
|
|
|
定义全局类型:
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// src/types/global.d.ts
|
|
|
|
|
|
interface AjaxResult {
|
|
|
|
|
|
code: number
|
|
|
|
|
|
msg: string
|
|
|
|
|
|
data: any
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
interface TableDataInfo {
|
|
|
|
|
|
code: number
|
|
|
|
|
|
msg: string
|
|
|
|
|
|
total: number
|
|
|
|
|
|
rows: any[]
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
interface MenuOption {
|
|
|
|
|
|
name: string
|
|
|
|
|
|
path: string
|
|
|
|
|
|
hidden?: boolean
|
|
|
|
|
|
redirect?: string
|
|
|
|
|
|
component?: string
|
|
|
|
|
|
alwaysShow?: boolean
|
|
|
|
|
|
meta?: {
|
|
|
|
|
|
title: string
|
|
|
|
|
|
icon?: string
|
|
|
|
|
|
noCache?: boolean
|
|
|
|
|
|
link?: string
|
|
|
|
|
|
}
|
|
|
|
|
|
children?: MenuOption[]
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] 定义 `AjaxResult` 通用响应类型
|
|
|
|
|
|
- [ ] 定义 `TableDataInfo` 分页响应类型
|
|
|
|
|
|
- [ ] 定义 `MenuOption` 菜单路由类型
|
|
|
|
|
|
- [ ] 定义 `DictDataType` 字典数据类型
|
|
|
|
|
|
- [ ] 定义 `PaginationState` 分页状态类型
|
|
|
|
|
|
|
|
|
|
|
|
### Step 2.2: 配置 Vue Router 4
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] 创建 `router/index.ts`,使用 `createRouter` + `createWebHistory`
|
|
|
|
|
|
- [ ] 配置静态路由(`/login`、`/register`、`/404`、`/401`、首页重定向)
|
|
|
|
|
|
- [ ] 配置动态路由占位(登录后从后端加载)
|
|
|
|
|
|
- [ ] 实现 `loadView` 懒加载函数(统一使用 `() => import()`)
|
|
|
|
|
|
- [ ] 路由类型使用 `RouteRecordRaw`(Vue Router 4)
|
|
|
|
|
|
- [ ] 配置滚动行为 `scrollBehavior`
|
|
|
|
|
|
|
|
|
|
|
|
### Step 2.3: 配置 Pinia 状态管理
|
|
|
|
|
|
|
|
|
|
|
|
替换 Vuex 5 个模块为 Pinia stores:
|
|
|
|
|
|
|
|
|
|
|
|
**app store** (`stores/modules/app.ts`):
|
|
|
|
|
|
- [ ] `sidebar` (opened, withoutAnimation) — 侧边栏状态
|
|
|
|
|
|
- [ ] `device` ('desktop' | 'mobile') — 设备类型
|
|
|
|
|
|
- [ ] `size` ('default' | 'large' | 'small') — 组件尺寸(Element Plus 命名调整)
|
|
|
|
|
|
- [ ] 使用 `pinia-plugin-persistedstate` 持久化到 Cookie/localStorage
|
|
|
|
|
|
|
|
|
|
|
|
**user store** (`stores/modules/user.ts`):
|
|
|
|
|
|
- [ ] `token`, `name`, `avatar`, `roles`, `permissions`
|
|
|
|
|
|
- [ ] Actions: `login()`, `getInfo()`, `logout()`, `fedLogout()`
|
|
|
|
|
|
- [ ] 登录调用 `POST /login`(保持与现有后端一致)
|
|
|
|
|
|
- [ ] Token 存储到 Cookie(键名 `Admin-Token`,与后端一致)
|
|
|
|
|
|
|
|
|
|
|
|
**permission store** (`stores/modules/permission.ts`):
|
|
|
|
|
|
- [ ] `routes`: 完整路由表
|
|
|
|
|
|
- [ ] `addRoutes`: 动态添加的路由
|
|
|
|
|
|
- [ ] `sidebarRouters`: 侧边栏显示的路由
|
|
|
|
|
|
- [ ] Action: `generateRoutes(roles)` — 从后端 `/getRouters` 获取菜单并转换为路由
|
|
|
|
|
|
- [ ] 实现 `filterAsyncRouter` 字符串组件路径转 import 函数
|
|
|
|
|
|
- [ ] 实现权限过滤逻辑
|
|
|
|
|
|
|
|
|
|
|
|
**tagsView store** (`stores/modules/tagsView.ts`):
|
|
|
|
|
|
- [ ] `visitedViews`: 已访问标签页列表
|
|
|
|
|
|
- [ ] `cachedViews`: keep-alive 缓存列表
|
|
|
|
|
|
- [ ] Actions: `addView`, `delView`, `delOthersViews`, `delAllViews`, `delRightTags`, `delLeftTags`
|
|
|
|
|
|
|
|
|
|
|
|
**settings store** (`stores/modules/settings.ts`):
|
|
|
|
|
|
- [ ] `theme`, `sideTheme`, `showSettings`
|
|
|
|
|
|
- [ ] `topNav`, `tagsView`, `fixedHeader`, `sidebarLogo`, `dynamicTitle`
|
|
|
|
|
|
- [ ] 持久化到 localStorage(键名 `layout-setting`)
|
|
|
|
|
|
|
|
|
|
|
|
### Step 2.4: 配置 Axios 调用层
|
|
|
|
|
|
|
|
|
|
|
|
`src/utils/request.ts`:
|
|
|
|
|
|
- [ ] 创建 Axios 实例,`baseURL = import.meta.env.VITE_APP_BASE_API`
|
|
|
|
|
|
- [ ] 设置 `timeout: 60000`
|
|
|
|
|
|
- [ ] 请求拦截器:注入 `Authorization: Bearer {token}`(支持 `isToken: false` 跳过)
|
|
|
|
|
|
- [ ] 请求拦截器:GET 参数序列化(复用 `tansParams` 逻辑)
|
|
|
|
|
|
- [ ] 响应拦截器:解析 `res.data.code`,处理 401/500/其他
|
|
|
|
|
|
- [ ] 401 处理:使用 `ElMessageBox.confirm` → 退出登录 → `router.replace('/')`(修复原 `location.href` 硬跳转问题)
|
|
|
|
|
|
- [ ] 响应拦截器:HTTP 错误处理(Network Error / Timeout / 4xx / 5xx)
|
|
|
|
|
|
- [ ] 导出 `download(url, params, filename)` 方法(blob 下载 + 登录态处理)
|
|
|
|
|
|
|
|
|
|
|
|
### Step 2.5: 配置权限控制
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] **路由守卫** (`src/permission.ts`):
|
|
|
|
|
|
- 白名单检查(`/login`, `/register`, 等)
|
|
|
|
|
|
- Token 验证(从 Cookie 读取 `Admin-Token`)
|
|
|
|
|
|
- 用户信息加载(roles + permissions)
|
|
|
|
|
|
- 动态路由注册(`router.addRoute`)
|
|
|
|
|
|
- 页面标题设置
|
|
|
|
|
|
- [ ] **指令权限** (`src/directives/permission.ts`):
|
|
|
|
|
|
- `v-hasPermi` 指令:检查权限标识
|
|
|
|
|
|
- `v-hasRole` 指令:检查角色
|
|
|
|
|
|
- 支持超级权限 `*:*:*`
|
|
|
|
|
|
- 支持超级角色 `admin`
|
|
|
|
|
|
- [ ] **全局方法** (`src/plugins/auth.ts`):
|
|
|
|
|
|
- `$auth.hasPermi(permission)` 方法
|
|
|
|
|
|
- `$auth.hasRole(role)` 方法
|
|
|
|
|
|
|
|
|
|
|
|
### Step 2.6: 配置插件系统
|
|
|
|
|
|
|
|
|
|
|
|
重构 `ruoyi-ui/src/plugins/` 下的插件:
|
|
|
|
|
|
- [ ] `modal.ts` — 全局弹窗封装(ElMessage, ElMessageBox, ElNotification)
|
|
|
|
|
|
- [ ] `cache.ts` — 缓存封装(localStorage + sessionStorage,带过期支持)
|
|
|
|
|
|
- [ ] `tab.ts` — 标签页操作(切换、关闭、刷新)
|
|
|
|
|
|
- [ ] `auth.ts` — 权限校验方法
|
|
|
|
|
|
- [ ] `index.ts` — 统一注册为 Vue 全局属性
|
|
|
|
|
|
|
|
|
|
|
|
**验收标准:**
|
|
|
|
|
|
- [ ] Pinia DevTools 可查看 5 个 store 状态
|
|
|
|
|
|
- [ ] 访问 `/login` 页面可正常渲染
|
|
|
|
|
|
- [ ] Axios 请求拦截器正确注入 Token
|
|
|
|
|
|
- [ ] 401 响应触发确认弹窗而非硬跳转
|
|
|
|
|
|
- [ ] `v-hasPermi` 指令在元素上正确隐藏/显示
|
|
|
|
|
|
- [ ] 路由守卫阻止未登录访问受保护页面
|
|
|
|
|
|
- [ ] TypeScript 编译零错误
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## Task 3: 深色主题和 UI 框架
|
|
|
|
|
|
|
|
|
|
|
|
**目标**: 安装配置 Element Plus,实现深色主题系统,配置 CSS 变量
|
|
|
|
|
|
|
|
|
|
|
|
**Files:**
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/assets/styles/variables.scss`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/assets/styles/dark-theme.scss`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/assets/styles/index.scss`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/assets/styles/element-override.scss`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/assets/styles/sidebar.scss`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/assets/styles/transition.scss`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/assets/styles/btn.scss`
|
|
|
|
|
|
- Reference: `ruoyi-ui/src/assets/styles/` 目录
|
|
|
|
|
|
- Reference: `data/demo-dashboard-heatmap.html`(深色主题配色来源)
|
|
|
|
|
|
|
|
|
|
|
|
**Dependencies:** Task 1, Task 2 完成
|
|
|
|
|
|
|
|
|
|
|
|
### Step 3.1: 安装 Element Plus
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] 确认 `element-plus` 已安装(Task 1 package.json)
|
|
|
|
|
|
- [ ] 配置按需导入(通过 `unplugin-vue-components` 自动按需导入组件)
|
|
|
|
|
|
- [ ] 安装 `@element-plus/icons-vue` 图标库
|
|
|
|
|
|
- [ ] 配置 Element Plus 中文语言包
|
|
|
|
|
|
|
|
|
|
|
|
### Step 3.2: 实现深色主题 CSS 变量
|
|
|
|
|
|
|
|
|
|
|
|
基于 demo-dashboard-heatmap.html 的配色方案:
|
|
|
|
|
|
|
|
|
|
|
|
```scss
|
|
|
|
|
|
// src/assets/styles/variables.scss
|
|
|
|
|
|
|
|
|
|
|
|
// 源自 demo-dashboard-heatmap.html 的深色主题
|
|
|
|
|
|
:root {
|
|
|
|
|
|
// 背景色
|
|
|
|
|
|
--bg-primary: #0d1117; // 最深背景 (--bg0)
|
|
|
|
|
|
--bg-secondary: #161b22; // 侧边栏/顶栏 (--bg1)
|
|
|
|
|
|
--bg-tertiary: #1c2333; // 卡片背景 (--bg2)
|
|
|
|
|
|
--bg-elevated: #2a3040; // 悬浮背景 (--bg3)
|
|
|
|
|
|
|
|
|
|
|
|
// 边框
|
|
|
|
|
|
--border-color: #30363d; // 边框色 (--bd)
|
|
|
|
|
|
|
|
|
|
|
|
// 文字
|
|
|
|
|
|
--text-primary: #e6edf3; // 主文字 (--t1)
|
|
|
|
|
|
--text-secondary: #8b949e; // 次要文字 (--t2)
|
|
|
|
|
|
--text-muted: #6e7681; // 弱化文字 (--tm)
|
|
|
|
|
|
|
|
|
|
|
|
// 功能色
|
|
|
|
|
|
--color-danger: #f85149; // 红色/下跌 (--red)
|
|
|
|
|
|
--color-success: #3fb950; // 绿色/上涨 (--grn)
|
|
|
|
|
|
--color-warning: #d29922; // 橙色 (--org)
|
|
|
|
|
|
--color-info: #58a6ff; // 蓝色 (--blu)
|
|
|
|
|
|
|
|
|
|
|
|
// 热力图排名色阶
|
|
|
|
|
|
--heat-1: #ff4444;
|
|
|
|
|
|
--heat-2: #ff6b6b;
|
|
|
|
|
|
--heat-3: #ff9a76;
|
|
|
|
|
|
--heat-4: #ffa502;
|
|
|
|
|
|
--heat-5: #e3b341;
|
|
|
|
|
|
--heat-6: #e6d34a;
|
|
|
|
|
|
--heat-7: #8bda5e;
|
|
|
|
|
|
--heat-8: #4dd08b;
|
|
|
|
|
|
--heat-9: #36b37e;
|
|
|
|
|
|
--heat-10: #2d9cdb;
|
|
|
|
|
|
|
|
|
|
|
|
// 布局
|
|
|
|
|
|
--sidebar-width: 200px;
|
|
|
|
|
|
--navbar-height: 50px;
|
|
|
|
|
|
--tags-view-height: 34px;
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] 创建 `variables.scss` 定义所有 CSS 变量
|
|
|
|
|
|
- [ ] 创建 `dark-theme.scss` 包含热力图排名色阶样式
|
|
|
|
|
|
- [ ] 创建 `element-override.scss` 覆盖 Element Plus 默认样式为深色
|
|
|
|
|
|
- [ ] 创建 `index.scss` 整合所有样式文件
|
|
|
|
|
|
- [ ] 创建 `sidebar.scss` 侧边栏专属样式
|
|
|
|
|
|
- [ ] 创建 `transition.scss` 过渡动画样式
|
|
|
|
|
|
- [ ] 创建 `btn.scss` 按钮工具类
|
|
|
|
|
|
|
|
|
|
|
|
### Step 3.3: 覆盖 Element Plus 深色主题
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] 覆盖 `el-menu` 侧边栏菜单背景色和文字色
|
|
|
|
|
|
- [ ] 覆盖 `el-table` 表格背景色和边框色
|
|
|
|
|
|
- [ ] 覆盖 `el-dialog` 弹窗背景色
|
|
|
|
|
|
- [ ] 覆盖 `el-input` / `el-select` / `el-date-picker` 表单组件
|
|
|
|
|
|
- [ ] 覆盖 `el-pagination` 分页组件
|
|
|
|
|
|
- [ ] 覆盖 `el-message-box` / `el-notification`
|
|
|
|
|
|
- [ ] 覆盖 `el-tag` 标签组件
|
|
|
|
|
|
|
|
|
|
|
|
### Step 3.4: 实现主题切换功能
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] 创建 ThemePicker 组件(支持深色/浅色切换)
|
|
|
|
|
|
- [ ] 使用 CSS `data-theme` 属性切换主题
|
|
|
|
|
|
- [ ] 在 settings store 中保存主题偏好
|
|
|
|
|
|
- [ ] 默认主题为深色
|
|
|
|
|
|
- [ ] 主题切换时无闪烁过渡
|
|
|
|
|
|
|
|
|
|
|
|
### Step 3.5: 配置全局样式
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] 重置默认样式(margin/padding/box-sizing)
|
|
|
|
|
|
- [ ] 配置滚动条样式(`::-webkit-scrollbar`)
|
|
|
|
|
|
- [ ] 配置通用工具类(`.mt-10`, `.mb-10`, `.flex`, `.text-center` 等)
|
|
|
|
|
|
- [ ] 配置 NProgress 进度条深色样式
|
|
|
|
|
|
|
|
|
|
|
|
**验收标准:**
|
|
|
|
|
|
- [ ] 深色主题默认渲染正确
|
|
|
|
|
|
- [ ] Element Plus 组件在深色主题下视觉一致
|
|
|
|
|
|
- [ ] 主题切换功能正常工作
|
|
|
|
|
|
- [ ] CSS 变量在 DevTools 中可查看
|
|
|
|
|
|
- [ ] 热力图排名色阶样式正确(1-10 级 + >10 级)
|
|
|
|
|
|
- [ ] 与 demo-dashboard-heatmap.html 配色方案一致
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## Task 4: 核心组件迁移
|
|
|
|
|
|
|
|
|
|
|
|
**目标**: 迁移布局组件和通用组件,重构为 Composition API + TypeScript
|
|
|
|
|
|
|
|
|
|
|
|
**Files:**
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/layout/index.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/layout/components/AppMain.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/layout/components/Navbar.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/layout/components/Sidebar/index.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/layout/components/Sidebar/SidebarItem.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/layout/components/Sidebar/Item.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/layout/components/Sidebar/Link.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/layout/components/Sidebar/Logo.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/layout/components/TagsView/index.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/layout/components/TagsView/ScrollPane.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/layout/components/Settings/index.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/layout/components/InnerLink/index.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/components/Breadcrumb/index.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/components/Pagination/index.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/components/DictTag/index.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/components/SvgIcon/index.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/components/Hamburger/index.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/components/Screenfull/index.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/components/SizeSelect/index.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/components/ThemePicker/index.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/components/TopNav/index.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/components/RightToolbar/index.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/components/Editor/index.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/components/FileUpload/index.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/components/ImageUpload/index.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/components/ImagePreview/index.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/components/IconSelect/index.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/components/HeaderSearch/index.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/components/Crontab/index.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/components/Crontab/day.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/components/Crontab/hour.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/components/Crontab/min.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/components/Crontab/month.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/components/Crontab/week.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/components/Crontab/year.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/components/Crontab/second.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/components/Crontab/result.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/components/ParentView/index.vue`
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/components/iFrame/index.vue`
|
|
|
|
|
|
- Reference: `ruoyi-ui/src/layout/` 目录所有文件
|
|
|
|
|
|
- Reference: `ruoyi-ui/src/components/` 目录所有文件
|
|
|
|
|
|
|
|
|
|
|
|
**Dependencies:** Task 1, Task 2, Task 3 完成
|
|
|
|
|
|
|
|
|
|
|
|
### Step 4.1: 迁移布局组件
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] **Layout** (`layout/index.vue`): 主布局容器,使用 `<script setup lang="ts">`,使用 `useAppStore()` 获取侧边栏状态
|
|
|
|
|
|
- [ ] **AppMain**: 主内容区,包含 `<router-view>` + `<keep-alive>` + `<transition>`
|
|
|
|
|
|
- [ ] **Navbar**: 顶部导航栏,包含 Hamburger、Breadcrumb、搜索、全屏、通知、用户下拉菜单
|
|
|
|
|
|
- [ ] **Sidebar**: 侧边栏,包含 Logo + Menu + SidebarItem 递归渲染
|
|
|
|
|
|
- [ ] **SidebarItem**: 递归菜单项,支持嵌套路由
|
|
|
|
|
|
- [ ] **TagsView**: 标签页视图,支持右键菜单(刷新、关闭其他、关闭全部)
|
|
|
|
|
|
- [ ] **Settings**: 系统设置面板(主题、顶栏、标签页等开关)
|
|
|
|
|
|
- [ ] 移除 `ResizeHandler.js` Mixin,改用 `useResize()` Composition API 函数
|
|
|
|
|
|
|
|
|
|
|
|
### Step 4.2: 迁移高复用通用组件
|
|
|
|
|
|
|
|
|
|
|
|
每个组件迁移要求:
|
|
|
|
|
|
- 使用 `<script setup lang="ts">` 语法
|
|
|
|
|
|
- Props 使用 `defineProps<T>()` 类型标注
|
|
|
|
|
|
- Emits 使用 `defineEmits<T>()` 类型标注
|
|
|
|
|
|
- 移除 Vue 2 Mixin,改用 Composition API
|
|
|
|
|
|
- 保持原有功能不变
|
|
|
|
|
|
|
|
|
|
|
|
**高优先级组件(按复用程度)**:
|
|
|
|
|
|
- [ ] **Pagination**: 分页组件,Props 包括 `total`, `page`, `limit`,Emits `update:page`, `update:limit`, `pagination`
|
|
|
|
|
|
- [ ] **DictTag**: 字典标签渲染,Props 包括 `options`, `value`
|
|
|
|
|
|
- [ ] **RightToolbar**: 右侧工具栏(搜索、显隐列),Props 包括 `showSearch`, `columns`
|
|
|
|
|
|
- [ ] **Breadcrumb**: 面包屑导航,读取 `useRoute()` 生成面包屑
|
|
|
|
|
|
- [ ] **SvgIcon**: SVG 图标封装,使用 `vite-plugin-svg-icons`
|
|
|
|
|
|
- [ ] **Hamburger**: 汉堡菜单按钮
|
|
|
|
|
|
|
|
|
|
|
|
**中优先级组件**:
|
|
|
|
|
|
- [ ] **Screenfull**: 全屏切换
|
|
|
|
|
|
- [ ] **SizeSelect**: 组件尺寸选择
|
|
|
|
|
|
- [ ] **ThemePicker**: 主题选择器(与 Task 3 整合)
|
|
|
|
|
|
- [ ] **TopNav**: 顶部导航菜单
|
|
|
|
|
|
- [ ] **Editor**: 富文本编辑器(Quill),确认依赖兼容性
|
|
|
|
|
|
- [ ] **FileUpload**: 文件上传
|
|
|
|
|
|
- [ ] **ImageUpload**: 图片上传
|
|
|
|
|
|
- [ ] **ImagePreview**: 图片预览
|
|
|
|
|
|
|
|
|
|
|
|
**低优先级组件**:
|
|
|
|
|
|
- [ ] **HeaderSearch**: 头部搜索(Fuse.js 全文搜索)
|
|
|
|
|
|
- [ ] **IconSelect**: SVG 图标选择器
|
|
|
|
|
|
- [ ] **Crontab**: Cron 表达式生成器(9 个子组件)
|
|
|
|
|
|
- [ ] **ParentView**: 父级视图占位
|
|
|
|
|
|
- [ ] **iFrame**: 内嵌 iframe
|
|
|
|
|
|
|
|
|
|
|
|
### Step 4.3: 迁移业务组件
|
|
|
|
|
|
|
|
|
|
|
|
将业务组件从 `src/components/` 移至 `src/components-business/`:
|
|
|
|
|
|
- [ ] **Kdialog**: K 线对话框 → `components-business/Kdialog/`
|
|
|
|
|
|
- [ ] **NegativeDialog**: 涨跌停对话框 → `components-business/NegativeDialog/`
|
|
|
|
|
|
- [ ] **TrendStocksDialog**: 板块趋势对话框 → `components-business/TrendStocksDialog/`
|
|
|
|
|
|
|
|
|
|
|
|
### Step 4.4: 全局注册策略
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] 高复用组件(Pagination, DictTag, SvgIcon, RightToolbar)自动全局注册
|
|
|
|
|
|
- [ ] 布局组件按需导入
|
|
|
|
|
|
- [ ] 业务组件按需导入(仅在其所属模块页面中引用)
|
|
|
|
|
|
- [ ] 移除 `ruoyi-ui/src/main.js` 中的 `Vue.component()` 全局注册方式
|
|
|
|
|
|
|
|
|
|
|
|
### Step 4.5: 字典系统重构
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] 重构 `DictData` 模块为 TypeScript
|
|
|
|
|
|
- [ ] 创建 `utils/dict/index.ts` 统一管理字典加载
|
|
|
|
|
|
- [ ] 字典缓存使用 Pinia store 而非全局变量
|
|
|
|
|
|
- [ ] 保持 `getDicts(dictType)` API 调用兼容
|
|
|
|
|
|
|
|
|
|
|
|
**验收标准:**
|
|
|
|
|
|
- [ ] 所有组件使用 `<script setup lang="ts">` 语法
|
|
|
|
|
|
- [ ] Props 和 Emits 有完整 TypeScript 类型定义
|
|
|
|
|
|
- [ ] 无 Vue 2 特有 API 使用(`this.$xxx`, `Vue.extend`, Mixin)
|
|
|
|
|
|
- [ ] Layout 布局渲染正确(Sidebar + Navbar + TagsView + AppMain)
|
|
|
|
|
|
- [ ] Pagination 组件在列表中正常工作
|
|
|
|
|
|
- [ ] DictTag 正确渲染字典标签
|
|
|
|
|
|
- [ ] SvgIcon 正确渲染 SVG 图标
|
|
|
|
|
|
- [ ] 业务组件不再污染全局组件注册表
|
|
|
|
|
|
- [ ] 组件无 ESLint 报错
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## Task 5: 数据可视化实现
|
|
|
|
|
|
|
|
|
|
|
|
**目标**: 安装配置 ECharts 5,实现行情总览和趋势热力图页面
|
|
|
|
|
|
|
|
|
|
|
|
**Files:**
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/dashboard/index.vue` — 行情总览页面
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/dashboard/components/StatsCards.vue` — 统计卡片
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/dashboard/components/SentimentRow.vue` — 情绪指标行
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/dashboard/components/UpDownChart.vue` — 涨跌分布图
|
|
|
|
|
|
- [ ] Create: `ruoyi-ui-next/src/views/dashboard/components/TopTrends.vue` — 趋势板块 TOP 10
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/dashboard/components/TrendChanges.vue` — 趋势变化榜
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/dashboard/components/ConsecutiveStats.vue` — 连续统计
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/heatmap/index.vue` — 趋势热力图页面
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/heatmap/components/HeatmapMatrix.vue` — 热力矩阵
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/heatmap/components/EnhancedTable.vue` — 增强表格
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/heatmap/components/DetailModal.vue` — 详情弹窗
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/utils/echarts.ts` — ECharts 封装工具
|
|
|
|
|
|
- Reference: `data/demo-dashboard-heatmap.html`(UI 参考)
|
|
|
|
|
|
- Reference: `ruoyi-ui/src/views/dashboard/` 目录(旧图表组件)
|
|
|
|
|
|
|
|
|
|
|
|
**Dependencies:** Task 1, Task 2, Task 3, Task 4 完成
|
|
|
|
|
|
|
|
|
|
|
|
### Step 5.1: 配置 ECharts 5
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] 确认 `echarts@^5.5.0` 已安装
|
|
|
|
|
|
- [ ] 创建 `utils/echarts.ts` 封装工具:
|
|
|
|
|
|
- `initChart(dom, theme)` — 初始化图表
|
|
|
|
|
|
- `resizeChart(chart)` — 响应式调整
|
|
|
|
|
|
- 自定义深色主题配置(与全局 CSS 变量一致)
|
|
|
|
|
|
- [ ] 创建 `useECharts` Composition API Hook:
|
|
|
|
|
|
- 自动处理 resize
|
|
|
|
|
|
- 自动处理组件卸载时的 dispose
|
|
|
|
|
|
- 支持响应式 option 更新
|
|
|
|
|
|
|
|
|
|
|
|
### Step 5.2: 实现行情总览页面
|
|
|
|
|
|
|
|
|
|
|
|
参考 demo-dashboard-heatmap.html 中 `#pg-dashboard` 的布局:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
行情总览布局:
|
|
|
|
|
|
├── 市场范围筛选器(全A / 上证 / 深证 / 创业板 / 科创板 / 中证1000)
|
|
|
|
|
|
├── 迷你统计卡片(4 格)
|
|
|
|
|
|
│ ├── 上涨家数
|
|
|
|
|
|
│ ├── 下跌家数
|
|
|
|
|
|
│ ├── 涨停家数
|
|
|
|
|
|
│ └── 跌停家数
|
|
|
|
|
|
├── 情绪指标行(4 格)
|
|
|
|
|
|
│ ├── 全A情绪(含进度条 + 元信息)
|
|
|
|
|
|
│ ├── 中证1000情绪
|
|
|
|
|
|
│ ├── 创业板情绪
|
|
|
|
|
|
│ └── 科创板情绪
|
|
|
|
|
|
├── 双列布局
|
|
|
|
|
|
│ ├── 左:涨跌分布柱状图(ECharts)
|
|
|
|
|
|
│ └── 右:趋势板块 TOP 10(表格)
|
|
|
|
|
|
└── 双列布局
|
|
|
|
|
|
├── 左:趋势变化榜(上升/下降列表)
|
|
|
|
|
|
└── 右:强势板块连续统计(表格)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] **StatsCards**: 4 格迷你统计卡片组件
|
|
|
|
|
|
- [ ] **SentimentRow**: 情绪指标行,含热力色阶进度条
|
|
|
|
|
|
- [ ] **UpDownChart**: ECharts 涨跌分布柱状图
|
|
|
|
|
|
- [ ] **TopTrends**: 趋势板块 TOP 10 表格(含排名徽章、动量信号、详情按钮)
|
|
|
|
|
|
- [ ] **TrendChanges**: 趋势变化榜(上升红色/下降绿色箭头)
|
|
|
|
|
|
- [ ] **ConsecutiveStats**: 连续统计表格
|
|
|
|
|
|
|
|
|
|
|
|
### Step 5.3: 实现趋势热力图页面
|
|
|
|
|
|
|
|
|
|
|
|
参考 demo-dashboard-heatmap.html 中 `#pg-heatmap` 的布局:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
趋势热力图布局:
|
|
|
|
|
|
├── 筛选栏(动量周期:1日/3日/5日/10日/15日/20日/30日 + 日期选择 + 刷新)
|
|
|
|
|
|
├── 视图切换(热力矩阵 / 增强表格)
|
|
|
|
|
|
├── 热力矩阵视图
|
|
|
|
|
|
│ └── 2级行业 × 交易日排名矩阵
|
|
|
|
|
|
│ └── 点击单元格 → 详情弹窗
|
|
|
|
|
|
└── 增强表格视图
|
|
|
|
|
|
└── 行业 × 日期排名 + 趋势变化
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] **HeatmapMatrix**: 热力矩阵组件
|
|
|
|
|
|
- 2 级行业为行,交易日为列
|
|
|
|
|
|
- 排名 1-10 使用色阶渐变(源自 CSS 变量 `--heat-1` 至 `--heat-10`)
|
|
|
|
|
|
- 排名 >10 使用默认灰色
|
|
|
|
|
|
- 点击单元格触发详情弹窗
|
|
|
|
|
|
- [ ] **EnhancedTable**: 增强表格视图
|
|
|
|
|
|
- 行业 × 日期排名
|
|
|
|
|
|
- 趋势变化列(上升/下降)
|
|
|
|
|
|
- [ ] **DetailModal**: 详情弹窗
|
|
|
|
|
|
- 统计卡片(当前动量、近5日趋势、涨停家数、创新高、连续天数、平均排名)
|
|
|
|
|
|
- ECharts K 线图
|
|
|
|
|
|
- ECharts 排名趋势折线图
|
|
|
|
|
|
- Tab 切换(概览 / 排名趋势 / 成分股 / 历史数据)
|
|
|
|
|
|
|
|
|
|
|
|
### Step 5.4: 数据卡片和统计组件
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] 创建通用 `StatCard` 组件(label + value + sub)
|
|
|
|
|
|
- [ ] 创建通用 `MiniBarChart` 组件(小型柱状图)
|
|
|
|
|
|
- [ ] 创建通用 `RankBadge` 组件(排名徽章,1-3 金色/2 银色/3 铜色/其他普通)
|
|
|
|
|
|
- [ ] 创建通用 `SignalTag` 组件(动量信号标签)
|
|
|
|
|
|
|
|
|
|
|
|
### Step 5.5: 数据适配层
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] 创建 Mock 数据(开发阶段使用)
|
|
|
|
|
|
- [ ] 创建 API 调用函数(连接后端实际接口)
|
|
|
|
|
|
- [ ] 确保数据格式与现有后端 API 兼容
|
|
|
|
|
|
|
|
|
|
|
|
**验收标准:**
|
|
|
|
|
|
- [ ] 行情总览页面渲染正确,布局与 demo 一致
|
|
|
|
|
|
- [ ] 趋势热力图页面渲染正确,热力矩阵色阶正确
|
|
|
|
|
|
- [ ] ECharts 图表在窗口缩放时自适应
|
|
|
|
|
|
- [ ] 点击热力图单元格可打开详情弹窗
|
|
|
|
|
|
- [ ] 详情弹窗中 K 线图和排名趋势图正确渲染
|
|
|
|
|
|
- [ ] 视图切换(热力矩阵/增强表格)正常工作
|
|
|
|
|
|
- [ ] 所有图表使用深色主题
|
|
|
|
|
|
- [ ] 组件使用 Composition API + TypeScript
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## Task 6: 业务模块迁移
|
|
|
|
|
|
|
|
|
|
|
|
**目标**: 迁移所有业务模块页面,保持与后端 API 兼容
|
|
|
|
|
|
|
|
|
|
|
|
**Files:**
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/system/user/index.vue` — 用户管理
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/system/role/index.vue` — 角色管理
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/system/menu/index.vue` — 菜单管理
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/system/dept/index.vue` — 部门管理
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/system/config/index.vue` — 参数配置
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/system/notice/index.vue` — 通知公告
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/system/post/index.vue` — 岗位管理
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/system/dict/index.vue` — 字典管理
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/system/dict/data.vue` — 字典数据
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/system/user/profile/index.vue` — 个人中心
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/system/role/authUser.vue` — 角色分配用户
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/books/account/index.vue` — 交易账户
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/books/book/index.vue` — 账本管理
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/books/operations/index.vue` — 操作记录
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/books/statistics/index.vue` — 统计分析
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/books/statistictotal/index.vue` — 统计汇总
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/books/statisticremain/index.vue` — 统计结余
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/stocks/stocks/index.vue` — 股票列表
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/stocks/stockbasic/index.vue` — 股票基础信息
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/stocks/stockindex/index.vue` — 指数信息
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/stocks/financial/index.vue` — 财务数据
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/stocks/trends/index.vue` — 趋势数据
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/stocks/trendStocks/index.vue` — 板块趋势
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/stocks/newrecord/index.vue` — 新增记录
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/stocks/stockslimit/index.vue` — 涨跌停
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/stocks/book/index.vue` — 股票账本
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/monitor/cache/index.vue` — 缓存监控
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/monitor/job/index.vue` — 定时任务
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/monitor/job/log.vue` — 调度日志
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/monitor/logininfor/index.vue` — 登录日志
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/monitor/online/index.vue` — 在线用户
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/monitor/operlog/index.vue` — 操作日志
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/monitor/server/index.vue` — 服务器监控
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/tool/gen/index.vue` — 代码生成
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/login.vue` — 登录页
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/register.vue` — 注册页
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/error/401.vue` — 401 错误页
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/views/error/404.vue` — 404 错误页
|
|
|
|
|
|
- Create: `ruoyi-ui-next/src/api/*.ts` — 所有 API 模块(TypeScript)
|
|
|
|
|
|
- Reference: `ruoyi-ui/src/views/` 目录所有页面文件
|
|
|
|
|
|
- Reference: `ruoyi-ui/src/api/` 目录所有 API 文件
|
|
|
|
|
|
|
|
|
|
|
|
**Dependencies:** Task 1, Task 2, Task 3, Task 4 完成
|
|
|
|
|
|
|
|
|
|
|
|
### Step 6.1: 迁移 API 调用层
|
|
|
|
|
|
|
|
|
|
|
|
将 `ruoyi-ui/src/api/` 下所有 `.js` 文件重构为 `.ts` 文件:
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] **API 类型定义** — 为每个 API 模块定义请求参数和响应类型
|
|
|
|
|
|
- [ ] **system API** (8 文件) — user, role, menu, dept, config, notice, post, dict(data+type)
|
|
|
|
|
|
- [ ] **monitor API** (6 文件) — cache, job, jobLog, logininfor, online, operlog, server
|
|
|
|
|
|
- [ ] **booksystem API** (6 文件) — account, book, operations, statistics, statistictotal, statisticremain
|
|
|
|
|
|
- [ ] **stocksystem API** (9 文件) — stocks, stockbasic, stockindex, financial, trends, trendStocks, newrecord, stockslimit, book
|
|
|
|
|
|
- [ ] 保持 API 路径完全一致(如 `/system/user/list` 不变)
|
|
|
|
|
|
- [ ] 使用 `request.get<T>()` / `request.post<T>()` 泛型方法
|
|
|
|
|
|
|
|
|
|
|
|
### Step 6.2: 迁移系统管理模块(10+ 页面)
|
|
|
|
|
|
|
|
|
|
|
|
每个页面迁移要求:
|
|
|
|
|
|
- 使用 `<script setup lang="ts">` 语法
|
|
|
|
|
|
- 使用 Composition API 替代 Vue 2 Options API
|
|
|
|
|
|
- API 调用使用 TypeScript 类型
|
|
|
|
|
|
- 使用 Element Plus 组件替代 Element UI
|
|
|
|
|
|
- 保持搜索表单 + 表格 + 分页 + 弹窗的 CRUD 布局
|
|
|
|
|
|
- 使用 `v-hasPermi` 指令控制按钮权限
|
|
|
|
|
|
- 使用 `DictTag` 组件展示字典
|
|
|
|
|
|
- 使用 `Pagination` 组件分页
|
|
|
|
|
|
|
|
|
|
|
|
页面清单:
|
|
|
|
|
|
- [ ] **用户管理** — 用户列表、新增/编辑弹窗、分配角色、导入/导出
|
|
|
|
|
|
- [ ] **角色管理** — 角色列表、权限分配、数据权限、分配用户
|
|
|
|
|
|
- [ ] **菜单管理** — 菜单树、新增/编辑弹窗、图标选择
|
|
|
|
|
|
- [ ] **部门管理** — 部门树、新增/编辑弹窗
|
|
|
|
|
|
- [ ] **参数配置** — 配置列表、新增/编辑弹窗
|
|
|
|
|
|
- [ ] **通知公告** — 公告列表、富文本编辑
|
|
|
|
|
|
- [ ] **岗位管理** — 岗位列表、新增/编辑弹窗
|
|
|
|
|
|
- [ ] **字典管理** — 字典类型列表、字典数据子页面
|
|
|
|
|
|
- [ ] **个人中心** — 用户信息修改、头像上传、密码修改
|
|
|
|
|
|
|
|
|
|
|
|
### Step 6.3: 迁移账本系统模块(6 页面)
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] **交易账户** — 账户列表、CRUD
|
|
|
|
|
|
- [ ] **账本管理** — 账本列表、CRUD
|
|
|
|
|
|
- [ ] **操作记录** — 操作日志列表
|
|
|
|
|
|
- [ ] **统计分析** — 统计图表 + 列表
|
|
|
|
|
|
- [ ] **统计汇总** — 汇总数据展示
|
|
|
|
|
|
- [ ] **统计结余** — 结余数据展示
|
|
|
|
|
|
|
|
|
|
|
|
### Step 6.4: 迁移股票系统模块(8+ 页面)
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] **股票列表** — 股票信息列表、CRUD
|
|
|
|
|
|
- [ ] **股票基础信息** — 基础数据列表
|
|
|
|
|
|
- [ ] **指数信息** — 指数列表
|
|
|
|
|
|
- [ ] **财务数据** — 财务信息列表
|
|
|
|
|
|
- [ ] **趋势数据** — 趋势数据列表
|
|
|
|
|
|
- [ ] **板块趋势** — 板块趋势列表(含业务组件 TrendStocksDialog)
|
|
|
|
|
|
- [ ] **新增记录** — 新增记录列表
|
|
|
|
|
|
- [ ] **涨跌停** — 涨跌停列表(含业务组件 NegativeDialog)
|
|
|
|
|
|
- [ ] **股票账本** — 股票相关账本
|
|
|
|
|
|
|
|
|
|
|
|
### Step 6.5: 迁移监控模块(7 页面)
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] **缓存监控** — Redis 缓存信息
|
|
|
|
|
|
- [ ] **定时任务** — 任务列表、执行、日志
|
|
|
|
|
|
- [ ] **调度日志** — 任务执行日志
|
|
|
|
|
|
- [ ] **登录日志** — 登录记录列表
|
|
|
|
|
|
- [ ] **在线用户** — 在线用户列表、强退
|
|
|
|
|
|
- [ ] **操作日志** — 操作记录列表
|
|
|
|
|
|
- [ ] **服务器监控** — CPU/内存/磁盘信息
|
|
|
|
|
|
|
|
|
|
|
|
### Step 6.6: 迁移认证和错误页面
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] **登录页** — 用户名/密码/验证码登录,RSA 加密
|
|
|
|
|
|
- [ ] **注册页** — 用户注册
|
|
|
|
|
|
- [ ] **401 错误页** — 无权限页面
|
|
|
|
|
|
- [ ] **404 错误页** — 页面不存在
|
|
|
|
|
|
|
|
|
|
|
|
### Step 6.7: 优化 API 调用层
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] 添加请求重试机制(可配置重试次数和间隔)
|
|
|
|
|
|
- [ ] 添加请求取消机制(页面切换时取消未完成的请求)
|
|
|
|
|
|
- [ ] 统一错误码处理逻辑
|
|
|
|
|
|
- [ ] 添加 API 请求 loading 状态管理
|
|
|
|
|
|
|
|
|
|
|
|
**验收标准:**
|
|
|
|
|
|
- [ ] 所有页面可正常访问(路由配置正确)
|
|
|
|
|
|
- [ ] CRUD 操作功能正常(增删改查)
|
|
|
|
|
|
- [ ] 分页功能正常
|
|
|
|
|
|
- [ ] 搜索/过滤功能正常
|
|
|
|
|
|
- [ ] 权限按钮正确显示/隐藏
|
|
|
|
|
|
- [ ] 字典标签正确渲染
|
|
|
|
|
|
- [ ] 文件上传功能正常
|
|
|
|
|
|
- [ ] 富文本编辑器正常工作
|
|
|
|
|
|
- [ ] 与后端 API 完全兼容(无需后端改动)
|
|
|
|
|
|
- [ ] TypeScript 编译零错误
|
|
|
|
|
|
- [ ] 无 ESLint 报错
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## Task 7: 测试和优化
|
|
|
|
|
|
|
|
|
|
|
|
**目标**: 功能测试、性能优化、响应式适配、浏览器兼容性测试
|
|
|
|
|
|
|
|
|
|
|
|
**Files:**
|
|
|
|
|
|
- Modify: `ruoyi-ui-next/vite.config.ts`(构建优化配置)
|
|
|
|
|
|
- Modify: `ruoyi-ui-next/src/utils/request.ts`(性能优化)
|
|
|
|
|
|
- Create: `ruoyi-ui-next/.browserslistrc`
|
|
|
|
|
|
- Reference: 所有已创建的页面和组件文件
|
|
|
|
|
|
|
|
|
|
|
|
**Dependencies:** Task 1-6 全部完成
|
|
|
|
|
|
|
|
|
|
|
|
### Step 7.1: 功能测试
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] 登录/注册流程测试
|
|
|
|
|
|
- [ ] 动态路由加载测试(不同角色看到不同菜单)
|
|
|
|
|
|
- [ ] 权限控制测试(无权限按钮隐藏)
|
|
|
|
|
|
- [ ] 所有系统管理页面 CRUD 测试
|
|
|
|
|
|
- [ ] 所有业务模块页面功能测试
|
|
|
|
|
|
- [ ] 监控模块页面功能测试
|
|
|
|
|
|
- [ ] 数据可视化页面测试(行情总览 + 趋势热力图)
|
|
|
|
|
|
- [ ] 标签页操作测试(切换、关闭、刷新、关闭其他)
|
|
|
|
|
|
- [ ] 主题切换测试(深色/浅色)
|
|
|
|
|
|
- [ ] 文件上传/下载测试
|
|
|
|
|
|
- [ ] 富文本编辑器测试
|
|
|
|
|
|
- [ ] 401 处理测试(Token 过期 → 确认弹窗 → 退出登录)
|
|
|
|
|
|
|
|
|
|
|
|
### Step 7.2: 性能优化
|
|
|
|
|
|
|
|
|
|
|
|
**构建优化**:
|
|
|
|
|
|
- [ ] 配置 Vite 代码分割(`manualChunks`)
|
|
|
|
|
|
- `element-plus` 独立 chunk
|
|
|
|
|
|
- `echarts` 独立 chunk
|
|
|
|
|
|
- `vendor` 第三方库 chunk
|
|
|
|
|
|
- [ ] 启用 gzip/brotli 压缩
|
|
|
|
|
|
- [ ] 图片资源优化(自动 webp 转换)
|
|
|
|
|
|
- [ ] 移除开发环境的 source map
|
|
|
|
|
|
- [ ] 配置预加载/预取策略
|
|
|
|
|
|
|
|
|
|
|
|
**运行时优化**:
|
|
|
|
|
|
- [ ] 路由懒加载验证(所有路由页面按需加载)
|
|
|
|
|
|
- [ ] ECharts 按需引入(仅使用需要的图表类型)
|
|
|
|
|
|
- [ ] 大表格虚拟滚动(如数据量超过 100 行)
|
|
|
|
|
|
- [ ] 图片懒加载
|
|
|
|
|
|
- [ ] keep-alive 缓存策略优化
|
|
|
|
|
|
- [ ] 移除未使用的依赖和代码
|
|
|
|
|
|
|
|
|
|
|
|
**加载速度目标**:
|
|
|
|
|
|
- [ ] 首屏加载 < 2 秒(3G 网络模拟)
|
|
|
|
|
|
- [ ] 构建产物 < 2 MB(gzip 后)
|
|
|
|
|
|
- [ ] 构建时间 < 30 秒
|
|
|
|
|
|
|
|
|
|
|
|
### Step 7.3: 响应式适配
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] 桌面端(1920px / 1440px / 1280px)
|
|
|
|
|
|
- [ ] 平板端(1024px / 768px)
|
|
|
|
|
|
- [ ] 移动端(375px)— 侧边栏自动折叠
|
|
|
|
|
|
- [ ] 热力图矩阵在小屏幕下可横向滚动
|
|
|
|
|
|
- [ ] 表格在小屏幕下可横向滚动
|
|
|
|
|
|
- [ ] 弹窗在小屏幕下自适应宽度
|
|
|
|
|
|
|
|
|
|
|
|
### Step 7.4: 浏览器兼容性
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] Chrome 90+
|
|
|
|
|
|
- [ ] Firefox 90+
|
|
|
|
|
|
- [ ] Safari 14+
|
|
|
|
|
|
- [ ] Edge 90+
|
|
|
|
|
|
- [ ] 配置 `.browserslistrc`
|
|
|
|
|
|
- [ ] 验证无浏览器特有 API 使用(或添加 polyfill)
|
|
|
|
|
|
|
|
|
|
|
|
### Step 7.5: 代码质量检查
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] ESLint 全量检查通过(零警告)
|
|
|
|
|
|
- [ ] TypeScript 严格模式编译通过(零错误)
|
|
|
|
|
|
- [ ] Prettier 格式化全部代码
|
|
|
|
|
|
- [ ] 无 `any` 类型滥用(最多 5 处 `any`)
|
|
|
|
|
|
- [ ] 无 Vue 2 残留代码(`this.` 引用、Mixin、Options API)
|
|
|
|
|
|
- [ ] 组件命名规范检查
|
|
|
|
|
|
- [ ] 导入路径规范检查(使用 `@/` 别名)
|
|
|
|
|
|
|
|
|
|
|
|
**验收标准:**
|
|
|
|
|
|
- [ ] 所有页面功能测试通过
|
|
|
|
|
|
- [ ] 首屏加载 < 2 秒
|
|
|
|
|
|
- [ ] 构建产物 < 2 MB(gzip 后)
|
|
|
|
|
|
- [ ] 响应式适配桌面/平板/移动端
|
|
|
|
|
|
- [ ] 主流浏览器兼容
|
|
|
|
|
|
- [ ] ESLint + TypeScript 零错误
|
|
|
|
|
|
- [ ] 无 Vue 2 残留代码
|
|
|
|
|
|
- [ ] 项目可独立运行(`npm run dev` + `npm run build`)
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 任务依赖关系图
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
Task 1 (项目初始化)
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
Task 2 (核心架构搭建)
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
Task 3 (深色主题和 UI 框架) ──┐
|
|
|
|
|
|
│ │
|
|
|
|
|
|
▼ ▼
|
|
|
|
|
|
Task 4 (核心组件迁移) Task 5 (数据可视化实现)
|
|
|
|
|
|
│ │
|
|
|
|
|
|
└──────────┬───────────────┘
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
Task 6 (业务模块迁移)
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
Task 7 (测试和优化)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 里程碑
|
|
|
|
|
|
|
|
|
|
|
|
| 里程碑 | 包含任务 | 预期产出 |
|
|
|
|
|
|
|--------|---------|---------|
|
|
|
|
|
|
| **M1: 项目骨架** | Task 1 | 可运行的 Vite + Vue3 + TS 空项目 |
|
|
|
|
|
|
| **M2: 架构就绪** | Task 2 | 路由、状态、权限、API 层完成 |
|
|
|
|
|
|
| **M3: 主题完成** | Task 3 | 深色主题 + Element Plus 配置完成 |
|
|
|
|
|
|
| **M4: 组件迁移** | Task 4 | 所有布局组件和通用组件迁移完成 |
|
|
|
|
|
|
| **M5: 可视化完成** | Task 5 | 行情总览和趋势热力图页面完成 |
|
|
|
|
|
|
| **M6: 全量迁移** | Task 6 | 所有业务页面迁移完成 |
|
|
|
|
|
|
| **M7: 发布就绪** | Task 7 | 测试通过、性能达标、可部署 |
|
|
|
|
|
|
|
|
|
|
|
|
## 风险提示
|
|
|
|
|
|
|
|
|
|
|
|
| 风险 | 影响 | 应对策略 |
|
|
|
|
|
|
|------|------|---------|
|
|
|
|
|
|
| ECharts 5 API 变化 | 图表组件需适配 | 对比 4.x/5.x 文档,逐项验证 |
|
|
|
|
|
|
| Element Plus 组件 API 差异 | 部分组件属性变更 | 查阅 Element Plus 文档,逐个适配 |
|
|
|
|
|
|
| Quill 富文本编辑器兼容性 | 可能需替换方案 | 准备 wangEditor 作为备选 |
|
|
|
|
|
|
| 后端 API 未适配 Vue3 | 前端需额外处理 | 保持 API 调用层兼容,无需后端改动 |
|
|
|
|
|
|
| 大项目 TypeScript 类型定义工作量 | 开发周期延长 | 优先核心类型,逐步补充 |
|
|
|
|
|
|
| 旧组件逻辑复杂难以重构 | 重构风险高 | 先复制功能,再逐步优化 |
|
|
|
|
|
|
|
|
|
|
|
|
## 自检查
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 规范覆盖
|
|
|
|
|
|
- [x] Task 1: 项目初始化 ✓
|
|
|
|
|
|
- [x] Task 2: 核心架构搭建 ✓
|
|
|
|
|
|
- [x] Task 3: 深色主题和 UI 框架 ✓
|
|
|
|
|
|
- [x] Task 4: 核心组件迁移 ✓
|
|
|
|
|
|
- [x] Task 5: 数据可视化实现 ✓
|
|
|
|
|
|
- [x] Task 6: 业务模块迁移 ✓
|
|
|
|
|
|
- [x] Task 7: 测试和优化 ✓
|
|
|
|
|
|
|
|
|
|
|
|
### 2. Placeholder 扫描
|
|
|
|
|
|
- [x] 无 "TBD"、"TODO"
|
|
|
|
|
|
- [x] 无 "implement later"
|
|
|
|
|
|
- [x] 所有步骤包含具体文件路径和实施内容
|
|
|
|
|
|
- [x] 无 "Similar to Task N"
|
|
|
|
|
|
|
|
|
|
|
|
### 3. 类型一致性
|
|
|
|
|
|
- [x] 所有路径使用 `ruoyi-ui-next/` 前缀
|
|
|
|
|
|
- [x] 文件名命名一致(kebab-case / PascalCase)
|
|
|
|
|
|
- [x] API 路径与现有后端一致
|
|
|
|
|
|
- [x] CSS 变量命名与 demo 一致
|
|
|
|
|
|
|
|
|
|
|
|
### 4. 最小单元验证
|
|
|
|
|
|
- [x] 每个任务可独立执行(按依赖顺序)
|
|
|
|
|
|
- [x] 每个任务有明确输出和验收标准
|
|
|
|
|
|
- [x] 每个任务可独立验证
|
|
|
|
|
|
- [x] 依赖关系清晰
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 执行选择
|
|
|
|
|
|
|
|
|
|
|
|
计划完成!共 7 个任务,约 150+ 步骤,产出完整的 Vue3 前端项目。
|
|
|
|
|
|
|
|
|
|
|
|
**执行选项**:
|
|
|
|
|
|
|
|
|
|
|
|
1. **Subagent-Driven(推荐)** — 每个任务分发到独立子 agent 执行,任务间审查,快速迭代
|
|
|
|
|
|
2. **Inline Execution** — 在当前会话中顺序执行所有任务
|
|
|
|
|
|
3. **按里程碑分批执行** — 按 M1-M7 分批,每个里程碑完成后审查再继续
|
|
|
|
|
|
|
|
|
|
|
|
您希望采用哪种执行方式?
|