401 lines
16 KiB
Markdown
401 lines
16 KiB
Markdown
# apes-Authon-Web — 账权管理前端
|
||
|
||
> Vue 2.7 账权管理前端,与后端 [apes-Authon-Server](https://gitea.apescale.com/apes-Arise/apes-Authon-Server) 配合使用
|
||
> **已通过构建验证**,可独立部署
|
||
|
||
## 项目背景
|
||
|
||
apes-Authon-Web 是一套独立的账权管理前端应用,提供用户管理、角色权限、客户管理、应用管理、系统配置和 AI/LLM 工具管理等功能。采用 Vue 2.7 + Element UI 技术栈,通过 CDN externals 机制优化构建体积,支持动态路由和多应用菜单切换。
|
||
|
||
## 技术栈
|
||
|
||
| 组件 | 版本 | 用途 |
|
||
|------|------|------|
|
||
| Vue | 2.7.14 | 前端框架 |
|
||
| Element UI | 2.15.14 | UI 组件库 |
|
||
| Vue Router | 3.5.4 | 路由管理 |
|
||
| Vuex | 3.1.3 | 状态管理 |
|
||
| Axios | 0.18.1 | HTTP 请求 |
|
||
| Monaco Editor | 0.30.1 | AI 工具代码编辑器 |
|
||
| marked | 4.3.0 | Markdown 渲染(AI 对话) |
|
||
| highlight.js | 11.11.1 | 代码高亮(AI 对话) |
|
||
| Sass | 1.26.8 | 样式预处理 |
|
||
|
||
> Vue / VueRouter / Vuex / ElementUI / Axios 通过 CDN externals 引入(见 `public/index.html`),不打包进 bundle,显著减小构建体积。
|
||
|
||
## 功能模块
|
||
|
||
| 模块 | 页面数 | 说明 |
|
||
|------|--------|------|
|
||
| 登录注册 | 2 | 短信验证码登录、密码登录、SSO 单点登录、用户注册 |
|
||
| 用户管理 | 5 | 账号列表、个人信息、编辑资料、修改密码、SSO 配置 |
|
||
| 客户管理 | 12 | 客户列表、详情、编辑、员工管理、套餐、配额变更、AccessToken |
|
||
| 权限管理 | 3 | 菜单管理、权限项管理、角色管理 |
|
||
| 应用管理 | 2 | 应用列表、应用详情 |
|
||
| 系统配置 | 4 | 组织架构、操作日志、配额模板、套餐方案 |
|
||
| AI/LLM 配置 | 4 | LLM 模型配置、Agent 管理、Agent 编辑/详情、AI 助手测试 |
|
||
| AI 工具管理 | 7 | 工具列表、工具编辑、技能管理、调用日志、工具日志、对话历史、AI 对话 |
|
||
| 首页 | 1 | 数据看板 |
|
||
| **合计** | **40** | |
|
||
|
||
## 项目结构
|
||
|
||
```
|
||
apes-Authon-Web/
|
||
├── docs/ # 文档
|
||
│ ├── apes-Authon-Web-剥离方案.md # 剥离方案(计划文档)
|
||
│ ├── apes-Authon-Web-剥离方案.html # 剥离方案(HTML 版)
|
||
│ └── 剥离历史与说明.md # 剥离执行记录与变更说明
|
||
├── public/ # 静态资源
|
||
│ ├── index.html # HTML 模板(含 CDN externals)
|
||
│ └── static/ # 静态文件
|
||
├── src/
|
||
│ ├── api/ # API 接口层(19 个文件)
|
||
│ │ ├── user.js # 登录/注册/用户管理
|
||
│ │ ├── permissionApi.js # 菜单/权限/角色 CRUD
|
||
│ │ ├── menuApi.js # 动态路由构建(require.context)
|
||
│ │ ├── customerApi.js # 客户管理
|
||
│ │ ├── customerPackageApi.js # 客户套餐
|
||
│ │ ├── accessTokenApi.js # API 令牌管理
|
||
│ │ ├── appApi.js # 应用管理
|
||
│ │ ├── organizationApi.js # 组织架构
|
||
│ │ ├── quotaApi.js # 配额管理
|
||
│ │ ├── packagePlanApi.js # 套餐方案
|
||
│ │ ├── baseApi.js # 基础接口(文件上传等)
|
||
│ │ ├── llmModelApi.js # LLM 模型配置
|
||
│ │ ├── llmAgentApi.js # LLM Agent 管理
|
||
│ │ ├── llmAgentSkillApi.js # Agent 技能管理
|
||
│ │ ├── llmAgentToolApi.js # Agent 工具管理
|
||
│ │ ├── llmToolApi.js # LLM 工具管理
|
||
│ │ ├── llmToolLogApi.js # 工具调用日志
|
||
│ │ ├── llmConversationApi.js # 对话历史
|
||
│ │ └── aiSkill.js # AI 技能管理
|
||
│ ├── assets/ # 图片资源
|
||
│ ├── components/ # 公共组件
|
||
│ │ ├── breadcrumb.vue # 面包屑导航
|
||
│ │ ├── tagView.vue # 标签页缓存
|
||
│ │ ├── pageBox.vue # 页面容器
|
||
│ │ ├── iframeView.vue # 通用 iframe(menuType 2/3/4)
|
||
│ │ ├── MarkdownContent.vue # Markdown 渲染(marked + hljs)
|
||
│ │ └── ai/
|
||
│ │ └── ai_helper.vue # AI 助手浮窗组件
|
||
│ ├── layout/ # 布局组件
|
||
│ │ ├── index.vue # 主布局(侧栏 + 顶栏 + 内容区)
|
||
│ │ ├── components/
|
||
│ │ │ ├── Sidebar/ # 侧边栏菜单
|
||
│ │ │ ├── TagsView/ # 标签页导航
|
||
│ │ │ └── TopHeader.vue # 顶部导航栏
|
||
│ ├── router/
|
||
│ │ └── index.js # 路由配置(静态路由 + 动态路由容器)
|
||
│ ├── store/ # Vuex 状态管理
|
||
│ │ ├── index.js # Store 入口
|
||
│ │ ├── getters.js # 全局 getters
|
||
│ │ └── modules/
|
||
│ │ ├── user.js # 用户/客户/应用/菜单状态
|
||
│ │ ├── tagsView.js # 标签页缓存状态
|
||
│ │ └── settings.js # 布局设置
|
||
│ ├── styles/ # 全局样式
|
||
│ │ ├── index.scss # 样式入口
|
||
│ │ ├── variables.scss # SCSS 变量
|
||
│ │ ├── mixin.scss # 混入
|
||
│ │ ├── sidebar.scss # 侧边栏样式
|
||
│ │ ├── element-ui.scss # Element UI 覆写
|
||
│ │ └── transition.scss # 过渡动画
|
||
│ ├── utils/ # 工具函数
|
||
│ │ ├── request.js # Axios 封装(拦截器/Token/错误处理)
|
||
│ │ ├── index.js # 通用工具函数
|
||
│ │ ├── validate.js # 校验工具
|
||
│ │ ├── msgUtil.js # 消息提示工具
|
||
│ │ ├── public.js # 公共方法
|
||
│ │ ├── constUtil.js # 常量
|
||
│ │ ├── envUtil.js # 环境变量
|
||
│ │ ├── autoRefresh.js # 自动刷新
|
||
│ │ ├── uiSizeUtil.js # UI 尺寸
|
||
│ │ └── get-page-title.js # 页面标题
|
||
│ ├── views/ # 页面
|
||
│ │ ├── login/ # 登录
|
||
│ │ ├── register/ # 注册
|
||
│ │ ├── user/ # 用户管理(5 页面)
|
||
│ │ ├── permission/ # 权限管理(3 页面)
|
||
│ │ ├── customer/ # 客户管理(12 页面)
|
||
│ │ ├── app/ # 应用管理(2 页面)
|
||
│ │ ├── system/ # 系统配置 + AI/LLM(8 页面)
|
||
│ │ ├── ai/ # AI 工具管理(7 页面)
|
||
│ │ ├── home/ # 首页看板
|
||
│ │ ├── base/ # 基础页面(图片上传)
|
||
│ │ └── 404.vue # 404 错误页
|
||
│ ├── App.vue # 根组件
|
||
│ └── main.js # 应用入口
|
||
├── package.json
|
||
├── vue.config.js
|
||
├── babel.config.js
|
||
├── postcss.config.js
|
||
├── jsconfig.json
|
||
└── .gitignore
|
||
```
|
||
|
||
## 快速开始
|
||
|
||
### 环境要求
|
||
|
||
- Node.js >= 14(推荐 16.x / 18.x)
|
||
- npm >= 6
|
||
|
||
### 安装与运行
|
||
|
||
```bash
|
||
# 1. 克隆仓库
|
||
git clone https://gitea.apescale.com/apes-Arise/apes-Authon-Web.git
|
||
cd apes-Authon-Web
|
||
|
||
# 2. 安装依赖
|
||
npm install
|
||
|
||
# 3. 启动开发服务器(默认端口 8201)
|
||
npm run dev
|
||
|
||
# 4. 构建生产版本
|
||
npm run build:prod
|
||
|
||
# 5. 构建预发布版本
|
||
npm run build:stage
|
||
```
|
||
|
||
开发服务器启动后访问 `http://localhost:8201`。
|
||
|
||
### 代理配置
|
||
|
||
`vue.config.js` 中已配置开发环境代理:
|
||
|
||
```javascript
|
||
proxy: {
|
||
'/api/user-service': {
|
||
target: 'http://localhost:8202', // 后端 apes-Authon-Server 服务地址
|
||
changeOrigin: true,
|
||
pathRewrite: { '^/api/user-service': '/' }
|
||
}
|
||
}
|
||
```
|
||
|
||
如后端地址不同,修改 `target` 即可。
|
||
|
||
### 部署
|
||
|
||
```bash
|
||
# 构建产物在 authon-web/ 目录
|
||
npm run build:prod
|
||
|
||
# 将 authon-web/ 部署到 Nginx / 其他 Web 服务器
|
||
# Nginx 参考配置:
|
||
# server {
|
||
# listen 80;
|
||
# server_name your-domain.com;
|
||
# root /path/to/authon-web;
|
||
# index index.html;
|
||
# location / { try_files $uri $uri/ /index.html; }
|
||
# location /api/ { proxy_pass http://backend:8090; }
|
||
# }
|
||
```
|
||
|
||
> 构建输出目录为 `authon-web`(在 `vue.config.js` 的 `outputDir` 中配置)。
|
||
|
||
## 架构说明
|
||
|
||
### 路由体系
|
||
|
||
本项目采用 **静态路由 + 动态路由** 双层路由架构:
|
||
|
||
**静态路由**(`router/index.js`):
|
||
- `/login` — 登录页
|
||
- `/register` — 注册页
|
||
- `/user/*` — 用户管理(5 个子路由)
|
||
- `/base/*` — 基础配置(图片上传、应用管理、权限管理)
|
||
- `/customer/*` — 客户管理(6 个子路由)
|
||
- `/common` — **动态路由容器**(children 初始为空)
|
||
- `/error/404` — 404 页面
|
||
- `/` — 首页看板(重定向到 `/login`)
|
||
|
||
**动态路由**(`menuApi.js`):
|
||
应用启动时,`main.js` 调用后端接口获取当前用户的菜单列表,`menuApi.handleMenu()` 根据菜单数据动态注册路由到 `/common` 下:
|
||
|
||
| menuType | 处理方式 | 示例 |
|
||
|----------|----------|------|
|
||
| 1 | Vue 页面 — 通过 `require.context` 映射到 `@/views/${menu.vuePath}` | `views/user/list.vue` |
|
||
| 2 | 伙伴云 iframe — 使用 `iframeView` 组件 | 外部表单 |
|
||
| 3 | 支付 iframe — 使用 `iframeView` 组件 | 支付页面 |
|
||
| 4 | Web iframe — 使用 `iframeView` 组件 | 外部链接 |
|
||
|
||
```javascript
|
||
// menuApi.js 核心逻辑
|
||
handleMenu(menuList) {
|
||
menuList.forEach(menu => {
|
||
if (menu.menuType === 2 || menu.menuType === 3 || menu.menuType === 4) {
|
||
// iframe 类型:统一使用 iframeView 组件
|
||
router.addRoute('common', {
|
||
path: typePrefix + '/' + menu.id,
|
||
component: () => import('@/components/iframeView'),
|
||
...
|
||
})
|
||
}
|
||
if (menu.menuType === 1) {
|
||
// Vue 页面:动态加载对应组件
|
||
router.addRoute('common', {
|
||
path: menu.menuPath,
|
||
component: (resolve) => require([`@/views/${menu.vuePath}`], resolve),
|
||
...
|
||
})
|
||
}
|
||
if (menu.child) this.handleMenu(menu.child) // 递归处理子菜单
|
||
})
|
||
}
|
||
```
|
||
|
||
### 状态管理
|
||
|
||
Vuex Store 包含两个模块:
|
||
|
||
**user 模块**(`store/modules/user.js`):
|
||
|
||
| State | 说明 |
|
||
|-------|------|
|
||
| `loginUser` | 当前登录用户信息 |
|
||
| `currentCustomer` | 当前客户/企业信息 |
|
||
| `appList` | 用户可访问的应用列表 |
|
||
| `currentApp` | 当前选中应用 |
|
||
| `currentAppMenus` | 当前应用的菜单树 |
|
||
| `allAppMenus` | 所有应用的菜单映射 |
|
||
| `menuList` | 当前菜单列表 |
|
||
|
||
**tagsView 模块**(`store/modules/tagsView.js`):
|
||
- 管理标签页的打开/关闭/缓存
|
||
|
||
### 请求层
|
||
|
||
`utils/request.js` 封装了 Axios 实例:
|
||
|
||
- **请求拦截器**:自动注入 `token`(从 `localStorage` 读取)、`time`(时间戳)、`version`(API 版本)
|
||
- **响应拦截器**:检测 `code === 99`(未登录),自动跳转登录页(注册页除外)
|
||
- **方法封装**:`apiGet` / `apiPost` / `apiPostJson` / `apiDownloadPost`
|
||
|
||
```javascript
|
||
// 请求拦截器自动注入 token
|
||
config.headers = {
|
||
...config.headers,
|
||
time: new Date().getTime(),
|
||
version: '1.1',
|
||
token: localStorage.getItem('_token') || ''
|
||
}
|
||
```
|
||
|
||
### 启动流程
|
||
|
||
`main.js` 的应用启动流程:
|
||
|
||
```
|
||
1. 从 URL 参数读取 token(支持 SSO 跳转) → 写入 localStorage
|
||
2. 调用 getCurrentUser() → 获取用户信息 + 客户信息
|
||
3. 调用 getMyApps() → 获取应用列表
|
||
4. 遍历应用 → 调用 getAppMenus() → 获取每个应用的菜单
|
||
5. menuApi.handleMenu() → 动态注册路由
|
||
6. 匹配当前 URL → 设置当前应用和菜单
|
||
7. 实例化 Vue 应用
|
||
```
|
||
|
||
### CDN Externals 机制
|
||
|
||
`public/index.html` 通过 CDN `<script>` 标签引入核心库,`vue.config.js` 的 `externals` 配置告诉 Webpack 不打包这些库:
|
||
|
||
| 库 | CDN 地址 | externals 映射 |
|
||
|----|----------|----------------|
|
||
| Vue | unpkg.com/vue@2.7.14 | `vue` → `Vue` |
|
||
| Vue Router | unpkg.com/vue-router@3.5.4 | `vue-router` → `VueRouter` |
|
||
| Vuex | unpkg.com/vuex@3.1.3 | `vuex` → `Vuex` |
|
||
| Element UI | unpkg.com/element-ui@2.15.14 | `element-ui` → `ELEMENT` |
|
||
| Axios | unpkg.com/axios@0.18.1 | `axios` → `axios` |
|
||
|
||
> **离线部署**:如需离线使用,将 CDN 资源下载到 `public/static/` 并修改 `index.html` 中的引用路径,同时移除 `vue.config.js` 中的 `externals` 配置。
|
||
|
||
## 与后端对应关系
|
||
|
||
| 后端 Controller (apes-Authon-Server) | 前端页面 | API 文件 |
|
||
|-------------------------------|----------|----------|
|
||
| UserController | views/user/ | user.js |
|
||
| PermissionController | views/permission/ | permissionApi.js |
|
||
| CustomerController | views/customer/ | customerApi.js |
|
||
| AppController | views/app/ | appApi.js |
|
||
| MenuController (内嵌) | — | menuApi.js |
|
||
| AccessTokenController | views/customer/accessToken.vue | accessTokenApi.js |
|
||
| SSOController (内嵌于 User) | views/user/sso.vue, views/login/ | user.js |
|
||
| CustomerPackageController | views/customer/packages.vue | customerPackageApi.js |
|
||
| SysOrganizationController | views/system/organization/ | organizationApi.js |
|
||
| SysOperationLogController | views/system/operationlog/ | — |
|
||
| SysQuotaController | views/system/quota/ | quotaApi.js |
|
||
| SysPackagePlanController | views/system/packagePlan/ | packagePlanApi.js |
|
||
| LlmModelConfigController | views/system/llmModel/ | llmModelApi.js |
|
||
| LlmAgentConfigController | views/system/llmAgent/ | llmAgentApi.js |
|
||
| AiController | views/system/aiHelper/ | aiSkill.js |
|
||
| LlmToolController | views/ai/tool.vue | llmToolApi.js |
|
||
| LlmChatController | views/ai/chat.vue | — |
|
||
| LlmConversationController | views/ai/conversationHistory.vue | llmConversationApi.js |
|
||
|
||
## 开发指南
|
||
|
||
### 新增页面
|
||
|
||
1. 在 `src/views/` 下创建 `.vue` 文件
|
||
2. 如为静态路由:在 `router/index.js` 的 `constantRoutes` 中添加路由配置
|
||
3. 如为动态路由:在后端菜单管理中配置 `menuType=1`、`menuPath`(路由路径)、`vuePath`(组件路径,如 `user/list`)
|
||
|
||
### 新增 API
|
||
|
||
1. 在 `src/api/` 下创建或复用 `.js` 文件
|
||
2. 导入 request 实例:`import http from '@/utils/request'`
|
||
3. 定义 API 方法:
|
||
|
||
```javascript
|
||
import http from '@/utils/request'
|
||
|
||
export default {
|
||
getList(params) {
|
||
return http.apiGet('/api/user-service/some/endpoint', params)
|
||
},
|
||
create(data) {
|
||
return http.apiPost('/api/user-service/some/endpoint', data)
|
||
}
|
||
}
|
||
```
|
||
|
||
### 新增组件
|
||
|
||
在 `src/components/` 下创建 `.vue` 文件,通过 `import` 引入使用。
|
||
|
||
## 文件统计
|
||
|
||
| 类型 | 数量 |
|
||
|------|------|
|
||
| Vue 页面 (.vue) | 40 |
|
||
| API 接口 (.js) | 19 |
|
||
| 公共组件 (.vue) | 6 |
|
||
| 工具函数 (.js) | 10 |
|
||
| 样式文件 (.scss) | 6 |
|
||
| 布局组件 (.vue) | 4 |
|
||
|
||
## 剥离说明
|
||
|
||
本项目的完整剥离方案和执行记录已归档至 [apes-Authon-history](https://gitea.apescale.com/apes-Arise/apes-Authon-history) 仓库,`docs/` 目录保留操作参考文档:
|
||
|
||
- [剥离方案](docs/apes-Authon-Web-剥离方案.md) — 保留/删除/修改清单
|
||
- [剥离历史与说明](docs/剥离历史与说明.md) — 变更明细和框架修改说明
|
||
|
||
## 关联仓库
|
||
|
||
| 仓库 | 说明 | 地址 |
|
||
|------|------|------|
|
||
| apes-Authon-Server | 后端账权服务 | https://gitea.apescale.com/apes-Arise/apes-Authon-Server |
|
||
| apes-Authon-Web | 前端账权管理(本仓库) | https://gitea.apescale.com/apes-Arise/apes-Authon-Web |
|
||
| apes-Authon-history | 剥离历史与分析归档 | https://gitea.apescale.com/apes-Arise/apes-Authon-history |
|
||
|
||
## License
|
||
|
||
MIT
|