Compare commits
53 Commits
0b78af46cd
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b122a34331 | ||
|
|
463d7921c1 | ||
|
|
a147fb8a28 | ||
|
|
46e654aace | ||
|
|
d1546678e1 | ||
|
|
ff2d6004b6 | ||
|
|
ce7916c097 | ||
|
|
3e40ab372b | ||
|
|
af16450eb6 | ||
|
|
9a93a6dc99 | ||
|
|
cdd78aa057 | ||
|
|
9b5f89aa10 | ||
|
|
29efa21f0a | ||
|
|
4a8c9c4a2d | ||
|
|
ae36d6da81 | ||
|
|
2066796977 | ||
|
|
bad718ecb9 | ||
|
|
869dda515d | ||
|
|
2c7d438750 | ||
|
|
9a2ca57313 | ||
|
|
795cc37b49 | ||
|
|
5ae32a550d | ||
|
|
02c2d1a31c | ||
|
|
84563bafa1 | ||
|
|
6953193cf5 | ||
|
|
9d507c88ab | ||
|
|
c734e698de | ||
|
|
b02853d5f7 | ||
|
|
cac6e71adf | ||
|
|
2bd32e9a34 | ||
|
|
cfe380218e | ||
|
|
ff78438cfe | ||
|
|
fbed54474d | ||
|
|
bd7704f2c9 | ||
|
|
756a657c58 | ||
|
|
73d756628b | ||
|
|
970edeb759 | ||
|
|
0a723c4dfe | ||
|
|
42c977b815 | ||
|
|
5bea5f8c02 | ||
|
|
b101f49048 | ||
|
|
e66dd4430c | ||
|
|
e039ae8c62 | ||
|
|
a8d52f74ad | ||
|
|
96c8ba8c7e | ||
|
|
db46666bd4 | ||
|
|
d79a272f50 | ||
|
|
fd3c1a5563 | ||
|
|
0047086013 | ||
|
|
81aa1d49fd | ||
|
|
b39b206c4c | ||
|
|
f86ee00e3b | ||
|
|
88cd8d6e72 |
9
.claude/settings.local.json
Normal file
9
.claude/settings.local.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"permissions": {
|
||||||
|
"allow": [
|
||||||
|
"Bash(npm run build:*)"
|
||||||
|
],
|
||||||
|
"deny": [],
|
||||||
|
"ask": []
|
||||||
|
}
|
||||||
|
}
|
||||||
231
README.md
231
README.md
@@ -1,231 +0,0 @@
|
|||||||
# Admin Framework
|
|
||||||
|
|
||||||
一个基于 Vue2 的通用后台管理系统框架,包含完整的系统功能、登录、路由管理、布局等核心功能。
|
|
||||||
|
|
||||||
## 📦 项目结构
|
|
||||||
|
|
||||||
```
|
|
||||||
admin-framework/
|
|
||||||
├── src/ # 框架源码
|
|
||||||
│ ├── api/ # API 接口
|
|
||||||
│ ├── assets/ # 资源文件(样式、图片、字体)
|
|
||||||
│ ├── components/ # 全局组件
|
|
||||||
│ ├── config/ # 配置文件
|
|
||||||
│ ├── router/ # 路由配置
|
|
||||||
│ ├── store/ # Vuex 状态管理
|
|
||||||
│ ├── utils/ # 工具函数
|
|
||||||
│ ├── views/ # 页面组件
|
|
||||||
│ │ ├── home/ # 主页
|
|
||||||
│ │ ├── login/ # 登录页
|
|
||||||
│ │ ├── system/ # 系统管理页面
|
|
||||||
│ │ └── system_high/ # 高级系统页面
|
|
||||||
│ └── index.js # 框架入口
|
|
||||||
├── dist/ # 打包产物
|
|
||||||
│ └── admin-framework.js # 框架打包文件(1.64 MB)
|
|
||||||
├── demo-project/ # 完整示例项目 ⭐
|
|
||||||
│ ├── src/
|
|
||||||
│ │ ├── config/ # 配置
|
|
||||||
│ │ ├── libs/ # 框架文件
|
|
||||||
│ │ ├── views/ # 业务页面
|
|
||||||
│ │ ├── App.vue
|
|
||||||
│ │ └── main.js
|
|
||||||
│ ├── README.md # Demo 使用说明
|
|
||||||
│ └── INSTALL.md # 安装指南
|
|
||||||
├── webpack.config.js # 构建配置
|
|
||||||
├── package.json
|
|
||||||
└── 完整使用文档.md # 详细文档
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🚀 快速开始
|
|
||||||
|
|
||||||
### 方式一:运行 Demo 项目(推荐)⭐
|
|
||||||
|
|
||||||
**Demo 项目现已更新为使用框架源码**,更方便调试和开发!
|
|
||||||
|
|
||||||
#### 🎯 一键启动
|
|
||||||
|
|
||||||
**Windows 用户**:
|
|
||||||
```bash
|
|
||||||
cd demo-project
|
|
||||||
双击运行 start.bat
|
|
||||||
```
|
|
||||||
|
|
||||||
**Linux/Mac 用户**:
|
|
||||||
```bash
|
|
||||||
cd demo-project
|
|
||||||
chmod +x start.sh
|
|
||||||
./start.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 📝 手动启动
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. 进入 demo 项目
|
|
||||||
cd demo-project
|
|
||||||
|
|
||||||
# 2. 安装依赖(首次必须)
|
|
||||||
npm install
|
|
||||||
|
|
||||||
# 3. 启动开发服务器
|
|
||||||
npm run dev
|
|
||||||
```
|
|
||||||
|
|
||||||
浏览器会自动打开 `http://localhost:8080`
|
|
||||||
|
|
||||||
#### 📚 Demo 项目文档
|
|
||||||
|
|
||||||
- [快速启动.md](./demo-project/快速启动.md) - 快速启动指南 ⭐
|
|
||||||
- [README.md](./demo-project/README.md) - 项目说明
|
|
||||||
- [CHANGELOG.md](./demo-project/CHANGELOG.md) - 更新日志(重要)
|
|
||||||
- [INSTALL.md](./demo-project/INSTALL.md) - 安装指南
|
|
||||||
- [PROJECT_STRUCTURE.md](./demo-project/PROJECT_STRUCTURE.md) - 项目结构说明
|
|
||||||
|
|
||||||
#### ⚠️ 重要提示
|
|
||||||
|
|
||||||
- Demo 项目现在**直接使用框架源码**(`../../src/index.js`)
|
|
||||||
- **首次运行必须执行** `npm install` 安装新依赖
|
|
||||||
- 如遇到错误,删除 `node_modules` 和 `package-lock.json` 后重新安装
|
|
||||||
|
|
||||||
### 方式二:构建框架
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. 安装依赖
|
|
||||||
npm install
|
|
||||||
|
|
||||||
# 2. 构建框架
|
|
||||||
npm run build
|
|
||||||
|
|
||||||
# 3. 产物在 dist/admin-framework.js
|
|
||||||
```
|
|
||||||
|
|
||||||
## ✨ 特性
|
|
||||||
|
|
||||||
- ✅ **主页组件** - 欢迎页面,自动显示系统标题
|
|
||||||
- ✅ **系统管理页面** - 用户、角色、菜单等管理
|
|
||||||
- ✅ **登录和错误页面** - 完整的登录流程和错误处理
|
|
||||||
- ✅ **动态路由管理** - 基于权限的路由控制
|
|
||||||
- ✅ **Vuex 状态管理** - 用户、应用状态管理
|
|
||||||
- ✅ **内置样式** - base.less、animate.css、iconfont
|
|
||||||
- ✅ **工具库** - HTTP、日期、Token 等工具
|
|
||||||
|
|
||||||
## 📚 文档
|
|
||||||
|
|
||||||
- **完整使用文档**:[完整使用文档.md](./完整使用文档.md)
|
|
||||||
- **Demo 项目说明**:[demo-project/README.md](./demo-project/README.md)
|
|
||||||
- **安装指南**:[demo-project/INSTALL.md](./demo-project/INSTALL.md)
|
|
||||||
|
|
||||||
## 🎯 Demo 项目预览
|
|
||||||
|
|
||||||
Demo 项目包含:
|
|
||||||
|
|
||||||
1. **登录页面**(`/login`)
|
|
||||||
- 完整的登录表单
|
|
||||||
- 自动跳转功能
|
|
||||||
|
|
||||||
2. **主页**(`/home`)
|
|
||||||
- 欢迎页面
|
|
||||||
- 显示系统标题
|
|
||||||
|
|
||||||
3. **业务示例**(`/business/product`)
|
|
||||||
- 产品列表(Table)
|
|
||||||
- CRUD 操作示例
|
|
||||||
- Modal、Message 使用
|
|
||||||
|
|
||||||
4. **系统页面**(框架内置)
|
|
||||||
- 用户管理
|
|
||||||
- 角色管理
|
|
||||||
- 菜单管理
|
|
||||||
|
|
||||||
## 🔧 使用方式
|
|
||||||
|
|
||||||
### 1. 在新项目中使用
|
|
||||||
|
|
||||||
```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 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')
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 按需使用组件
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
import { HomePage, SysUser, SysRole } from './libs/admin-framework.js'
|
|
||||||
|
|
||||||
// 在路由中使用
|
|
||||||
const routes = [
|
|
||||||
{ path: '/home', component: HomePage },
|
|
||||||
{ path: '/system/user', component: SysUser }
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
## 📝 版本信息
|
|
||||||
|
|
||||||
**当前版本**: 1.0.0
|
|
||||||
|
|
||||||
**更新日志**:
|
|
||||||
- v1.0.0 - 初始版本
|
|
||||||
- ✅ 完整的系统管理功能
|
|
||||||
- ✅ 主页组件
|
|
||||||
- ✅ 登录和权限管理
|
|
||||||
- ✅ 动态路由
|
|
||||||
- ✅ 内置样式
|
|
||||||
- ✅ Demo 示例项目
|
|
||||||
|
|
||||||
## 💻 技术栈
|
|
||||||
|
|
||||||
- Vue 2.6+
|
|
||||||
- Vue Router 3.x
|
|
||||||
- Vuex 3.x
|
|
||||||
- View Design (iView) 4.x
|
|
||||||
- Axios
|
|
||||||
- Less
|
|
||||||
- Webpack 5
|
|
||||||
|
|
||||||
## 🛠️ 开发
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 安装依赖
|
|
||||||
npm install
|
|
||||||
|
|
||||||
# 开发模式
|
|
||||||
npm run dev
|
|
||||||
|
|
||||||
# 构建生产版本
|
|
||||||
npm run build
|
|
||||||
```
|
|
||||||
|
|
||||||
## 📄 许可证
|
|
||||||
|
|
||||||
MIT License
|
|
||||||
|
|
||||||
## 👨💻 作者
|
|
||||||
|
|
||||||
light
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**祝开发愉快!** 🎉
|
|
||||||
|
|
||||||
如有问题,请查看[完整使用文档.md](./完整使用文档.md)或查看 Demo 项目示例。
|
|
||||||
|
|
||||||
|
|||||||
781
_doc/使用说明.md
Normal file
781
_doc/使用说明.md
Normal file
@@ -0,0 +1,781 @@
|
|||||||
|
# Admin Framework 使用说明
|
||||||
|
|
||||||
|
一个基于 Vue2 的通用后台管理系统框架,包含完整的系统功能、登录、路由管理、布局等核心功能。
|
||||||
|
|
||||||
|
## 📦 框架特性
|
||||||
|
|
||||||
|
### ✨ 核心功能
|
||||||
|
- ✅ **简化的 API** - 只需调用 `createApp()` 即可完成所有初始化
|
||||||
|
- ✅ **模块化设计** - 组件、路由、状态管理等功能按模块组织
|
||||||
|
- ✅ **完整的系统管理页面** - 用户、角色、菜单、日志等管理
|
||||||
|
- ✅ **登录和权限管理** - 完整的登录流程和权限控制
|
||||||
|
- ✅ **动态路由管理** - 基于权限菜单的动态路由生成
|
||||||
|
- ✅ **Vuex 状态管理** - 用户、应用状态管理
|
||||||
|
- ✅ **全局组件库** - Tables、Editor、Upload、TreeGrid、FieldRenderer、FloatPanel 等
|
||||||
|
- ✅ **工具库** - HTTP、日期、Token、Cookie 等工具
|
||||||
|
- ✅ **内置样式** - base.less、animate.css、iconfont 等
|
||||||
|
- ✅ **响应式布局** - 支持移动端适配
|
||||||
|
|
||||||
|
### 🎯 内置页面组件
|
||||||
|
- **主页组件** (`HomePage`) - 欢迎页面,显示系统标题
|
||||||
|
- **系统管理页面** (`SysUser`, `SysRole`, `SysLog`, `SysParamSetup`)
|
||||||
|
- **高级管理页面** (`SysMenu`, `SysControl`, `SysTitle`)
|
||||||
|
- **登录页面** (`LoginPage`)
|
||||||
|
- **错误页面** (`Page401`, `Page404`, `Page500`)
|
||||||
|
|
||||||
|
### 🛠️ 内置工具
|
||||||
|
- **HTTP 工具** (`http`) - 封装了 axios,支持拦截器、文件上传下载
|
||||||
|
- **UI 工具** (`uiTool`) - 删除确认、树形转换、响应式设置、文件下载
|
||||||
|
- **通用工具** (`tools`) - 日期格式化、UUID 生成、Cookie 操作、深拷贝等
|
||||||
|
- **文件下载** - 支持 CSV 等格式的文件下载,自动处理换行符
|
||||||
|
|
||||||
|
## 🚀 快速开始
|
||||||
|
|
||||||
|
### 方式一:使用 Demo 项目(推荐)
|
||||||
|
|
||||||
|
我们提供了一个完整的 demo 项目,可以直接运行查看效果:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 进入 demo 项目
|
||||||
|
cd demo
|
||||||
|
|
||||||
|
# 2. 安装依赖
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# 3. 启动开发服务器
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
浏览器会自动打开 `http://localhost:8080`,查看:
|
||||||
|
- `/login` - 登录页面
|
||||||
|
- `/home` - 主页
|
||||||
|
- `/system/user` - 用户管理
|
||||||
|
- `/ball/games` - 业务示例页面
|
||||||
|
|
||||||
|
### 方式二:构建框架
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 安装依赖
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# 2. 构建框架
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# 3. 产物在 dist/admin-framework.js
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🎯 极简使用方式
|
||||||
|
|
||||||
|
### 只需 3 步即可完成集成!
|
||||||
|
|
||||||
|
#### 1. 引入框架
|
||||||
|
```javascript
|
||||||
|
import AdminFramework from './admin-framework.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. 创建应用
|
||||||
|
```javascript
|
||||||
|
const app = AdminFramework.createApp({
|
||||||
|
title: '我的管理系统',
|
||||||
|
apiUrl: 'http://localhost:9098/admin_api/',
|
||||||
|
componentMap: {
|
||||||
|
'business/product': ProductComponent,
|
||||||
|
'business/order': OrderComponent
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. 挂载应用
|
||||||
|
```javascript
|
||||||
|
app.$mount('#app')
|
||||||
|
```
|
||||||
|
|
||||||
|
**就这么简单!** 框架会自动完成所有初始化工作。
|
||||||
|
|
||||||
|
## 📖 完整使用指南
|
||||||
|
|
||||||
|
### 1. 项目结构准备
|
||||||
|
|
||||||
|
```
|
||||||
|
your-project/
|
||||||
|
├── src/
|
||||||
|
│ ├── config/
|
||||||
|
│ │ └── index.js # 配置文件
|
||||||
|
│ ├── libs/
|
||||||
|
│ │ └── admin-framework.js # 框架文件
|
||||||
|
│ ├── views/
|
||||||
|
│ │ └── business/ # 业务页面
|
||||||
|
│ ├── api/
|
||||||
|
│ │ └── business/ # 业务 API
|
||||||
|
│ ├── App.vue
|
||||||
|
│ └── main.js
|
||||||
|
├── package.json
|
||||||
|
└── webpack.config.js
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 安装依赖
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install vue vue-router vuex view-design axios dayjs js-cookie vuex-persistedstate
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 创建配置文件
|
||||||
|
|
||||||
|
在 `src/config/index.js` 中:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
module.exports = {
|
||||||
|
title: '你的系统名称',
|
||||||
|
homeName: '首页',
|
||||||
|
apiUrl: 'http://localhost:9090/admin_api/',
|
||||||
|
uploadUrl: 'http://localhost:9090/admin_api/upload',
|
||||||
|
cookieExpires: 7,
|
||||||
|
uploadMaxLimitSize: 10,
|
||||||
|
oss: {
|
||||||
|
region: 'oss-cn-shanghai',
|
||||||
|
accessKeyId: 'your-key',
|
||||||
|
accessKeySecret: 'your-secret',
|
||||||
|
bucket: 'your-bucket',
|
||||||
|
url: 'http://your-bucket.oss-cn-shanghai.aliyuncs.com',
|
||||||
|
basePath: 'your-path/'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 创建 main.js(新版本 - 推荐)
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import AdminFramework from './libs/admin-framework.js'
|
||||||
|
|
||||||
|
// 导入业务组件(根据权限菜单接口的 component 字段)
|
||||||
|
import GamesComponent from './views/ball/games.vue'
|
||||||
|
import PayOrdersComponent from './views/order/pay_orders.vue'
|
||||||
|
|
||||||
|
// 🎉 只需一行代码!框架自动完成所有初始化
|
||||||
|
const app = AdminFramework.createApp({
|
||||||
|
title: '我的管理系统',
|
||||||
|
apiUrl: 'http://localhost:9098/admin_api/',
|
||||||
|
componentMap: {
|
||||||
|
'ball/games': GamesComponent,
|
||||||
|
'order/pay_orders': PayOrdersComponent
|
||||||
|
// 添加更多业务组件...
|
||||||
|
},
|
||||||
|
onReady() {
|
||||||
|
console.log('应用已启动!')
|
||||||
|
// 应用启动完成后的回调
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 挂载应用
|
||||||
|
app.$mount('#app')
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### 5. 创建 App.vue
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<div id="app">
|
||||||
|
<router-view/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'App'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔧 API 使用指南
|
||||||
|
|
||||||
|
### 框架实例方法
|
||||||
|
|
||||||
|
#### createApp(config) - 推荐使用
|
||||||
|
创建应用实例(新版本 API)
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const app = AdminFramework.createApp({
|
||||||
|
title: '我的管理系统', // 应用标题(必需)
|
||||||
|
apiUrl: 'http://localhost:9098/admin_api/', // API 基础地址(必需)
|
||||||
|
uploadUrl: 'http://localhost:9098/admin_api/upload', // 上传地址(可选,默认为 apiUrl + 'upload')
|
||||||
|
componentMap: { // 业务组件映射(可选)
|
||||||
|
'business/product': ProductComponent,
|
||||||
|
'business/order': OrderComponent
|
||||||
|
},
|
||||||
|
onReady() { // 应用启动完成回调(可选)
|
||||||
|
console.log('应用已启动!')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
### 工具库使用
|
||||||
|
|
||||||
|
#### HTTP 工具
|
||||||
|
```javascript
|
||||||
|
// 在组件中使用
|
||||||
|
export default {
|
||||||
|
async mounted() {
|
||||||
|
// GET 请求
|
||||||
|
const res = await this.$http.get('/api/users', { page: 1 })
|
||||||
|
|
||||||
|
// POST 请求
|
||||||
|
const result = await this.$http.post('/api/users', { name: 'test' })
|
||||||
|
|
||||||
|
// 文件导出
|
||||||
|
await this.$http.fileExport('/api/export', { type: 'excel' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 在非 Vue 组件中使用
|
||||||
|
import AdminFramework from './libs/admin-framework.js'
|
||||||
|
const res = await AdminFramework.http.get('/api/users')
|
||||||
|
```
|
||||||
|
|
||||||
|
#### UI 工具
|
||||||
|
```javascript
|
||||||
|
// 在组件中使用
|
||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
handleDelete() {
|
||||||
|
// 删除确认
|
||||||
|
this.$uiTool.delConfirm(() => {
|
||||||
|
// 执行删除逻辑
|
||||||
|
})
|
||||||
|
|
||||||
|
// 设置响应式字体
|
||||||
|
this.$uiTool.setRem()
|
||||||
|
|
||||||
|
// 树形转换
|
||||||
|
const treeData = this.$uiTool.transformTree(flatData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 功能工具
|
||||||
|
```javascript
|
||||||
|
// 在组件中使用
|
||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
downloadFile() {
|
||||||
|
// 文件下载
|
||||||
|
this.$uiTool.downloadFile(response, 'filename.csv')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 通用工具
|
||||||
|
```javascript
|
||||||
|
// 在组件中使用
|
||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
formatDate() {
|
||||||
|
// 日期格式化
|
||||||
|
return this.$tools.formatDate(new Date(), 'YYYY-MM-DD HH:mm:ss')
|
||||||
|
},
|
||||||
|
|
||||||
|
generateId() {
|
||||||
|
// UUID 生成
|
||||||
|
return this.$tools.generateUUID()
|
||||||
|
},
|
||||||
|
|
||||||
|
setCookie() {
|
||||||
|
// Cookie 操作
|
||||||
|
this.$tools.setCookie('name', 'value')
|
||||||
|
const value = this.$tools.getCookie('name')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Store 模块使用
|
||||||
|
|
||||||
|
#### user 模块
|
||||||
|
```javascript
|
||||||
|
// 登录
|
||||||
|
await this.$store.dispatch('user/handleLogin', {
|
||||||
|
userFrom: { username, password },
|
||||||
|
Main: AdminFramework.Main,
|
||||||
|
ParentView: AdminFramework.ParentView,
|
||||||
|
Page404: AdminFramework.Page404
|
||||||
|
})
|
||||||
|
|
||||||
|
// 登出
|
||||||
|
this.$store.dispatch('user/handleLogOut')
|
||||||
|
|
||||||
|
// 设置权限菜单
|
||||||
|
this.$store.dispatch('user/setAuthorityMenus', {
|
||||||
|
Main: AdminFramework.Main,
|
||||||
|
ParentView: AdminFramework.ParentView,
|
||||||
|
Page404: AdminFramework.Page404
|
||||||
|
})
|
||||||
|
|
||||||
|
// 获取用户信息
|
||||||
|
const userName = this.$store.getters['user/userName']
|
||||||
|
const token = this.$store.state.user.token
|
||||||
|
```
|
||||||
|
|
||||||
|
#### app 模块
|
||||||
|
```javascript
|
||||||
|
// 设置面包屑
|
||||||
|
this.$store.commit('app/setBreadCrumb', route)
|
||||||
|
|
||||||
|
// 获取系统标题
|
||||||
|
this.$store.dispatch('app/getSysTitle', {
|
||||||
|
defaultTitle: '系统名称',
|
||||||
|
defaultLogo: '/logo.png'
|
||||||
|
})
|
||||||
|
|
||||||
|
// 获取系统配置
|
||||||
|
const sysFormModel = this.$store.getters['app/sysFormModel']
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🗂️ 组件映射配置
|
||||||
|
|
||||||
|
### 业务组件映射
|
||||||
|
|
||||||
|
当后端权限菜单接口返回组件路径时,需要配置映射表:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// 1. 导入业务组件
|
||||||
|
import GamesComponent from './views/ball/games.vue'
|
||||||
|
import PayOrdersComponent from './views/order/pay_orders.vue'
|
||||||
|
|
||||||
|
// 2. 配置映射
|
||||||
|
const componentMap = {
|
||||||
|
'ball/games': GamesComponent,
|
||||||
|
'ball/games.vue': GamesComponent, // 支持带 .vue 后缀
|
||||||
|
'order/pay_orders': PayOrdersComponent,
|
||||||
|
'order/pay_orders.vue': PayOrdersComponent
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 在 Vue.use 时传入
|
||||||
|
Vue.use(AdminFramework, {
|
||||||
|
config,
|
||||||
|
ViewUI,
|
||||||
|
VueRouter,
|
||||||
|
Vuex,
|
||||||
|
createPersistedState,
|
||||||
|
componentMap // 传入组件映射表
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### 框架已自动映射的系统组件
|
||||||
|
|
||||||
|
以下组件**无需配置**,框架已自动映射:
|
||||||
|
- ✅ `home/index` - 主页
|
||||||
|
- ✅ `system/sys_user` - 用户管理
|
||||||
|
- ✅ `system/sys_role` - 角色管理
|
||||||
|
- ✅ `system/sys_log` - 日志管理
|
||||||
|
- ✅ `system/sys_param_setup` - 参数设置
|
||||||
|
- ✅ `system/sys_menu` - 菜单管理
|
||||||
|
- ✅ `system/sys_control` - 控制器管理
|
||||||
|
- ✅ `system/sys_title` - 系统标题设置
|
||||||
|
|
||||||
|
## 🌐 全局访问
|
||||||
|
|
||||||
|
### window.framework
|
||||||
|
|
||||||
|
框架实例会自动暴露到全局,可以在任何地方访问:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// 在非 Vue 组件中使用
|
||||||
|
const http = window.framework.http
|
||||||
|
const uiTool = window.framework.uiTool
|
||||||
|
const config = window.framework.config
|
||||||
|
|
||||||
|
// HTTP 请求
|
||||||
|
const res = await window.framework.http.get('/api/users')
|
||||||
|
|
||||||
|
// UI 工具
|
||||||
|
window.framework.uiTool.delConfirm(() => {
|
||||||
|
// 删除逻辑
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Vue 原型方法
|
||||||
|
|
||||||
|
在 Vue 组件中可以直接使用:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
async loadData() {
|
||||||
|
// 直接使用 this.$xxx
|
||||||
|
const res = await this.$http.get('/api/users')
|
||||||
|
this.$uiTool.delConfirm(() => {})
|
||||||
|
this.$tools.formatDate(new Date())
|
||||||
|
this.$uiTool.downloadFile(response, 'file.csv')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📁 文件下载功能
|
||||||
|
|
||||||
|
### 使用 downloadFile 方法
|
||||||
|
|
||||||
|
框架提供了便捷的文件下载功能,支持 CSV 等格式:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// 在 Vue 组件中使用
|
||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
// 导出数据
|
||||||
|
exportData() {
|
||||||
|
// 调用 API 获取数据
|
||||||
|
this.$http.fileExport('/api/export', params).then(res => {
|
||||||
|
// 使用 downloadFile 下载
|
||||||
|
this.$uiTool.downloadFile(res, '数据导出.csv')
|
||||||
|
this.$Message.success('导出成功!')
|
||||||
|
}).catch(error => {
|
||||||
|
this.$Message.error('导出失败:' + error.message)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 支持的数据格式
|
||||||
|
|
||||||
|
- **CSV 格式**:自动处理换行符,保持表格格式
|
||||||
|
- **Blob 对象**:支持二进制文件下载
|
||||||
|
- **文本数据**:支持纯文本文件下载
|
||||||
|
|
||||||
|
### 自动处理特性
|
||||||
|
|
||||||
|
- ✅ **换行符保持**:CSV 文件的换行符会被正确保持
|
||||||
|
- ✅ **文件名处理**:自动清理文件名中的特殊字符
|
||||||
|
- ✅ **浏览器兼容**:支持所有现代浏览器
|
||||||
|
- ✅ **内存管理**:自动清理临时 URL 对象
|
||||||
|
|
||||||
|
## 🎨 全局组件使用
|
||||||
|
|
||||||
|
### FloatPanel - 浮动面板组件
|
||||||
|
|
||||||
|
`FloatPanel` 是一个浮动在父窗体上的面板组件,类似于抽屉效果,常用于详情展示、表单编辑等场景。
|
||||||
|
|
||||||
|
**基本使用:**
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<Button @click="showPanel">打开浮动面板</Button>
|
||||||
|
|
||||||
|
<FloatPanel
|
||||||
|
ref="floatPanel"
|
||||||
|
title="详情面板"
|
||||||
|
position="right"
|
||||||
|
:show-back="true"
|
||||||
|
back-text="返回"
|
||||||
|
@back="handleBack"
|
||||||
|
>
|
||||||
|
<div>这里是面板内容</div>
|
||||||
|
</FloatPanel>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
showPanel() {
|
||||||
|
// 通过 ref 调用 show 方法显示面板
|
||||||
|
this.$refs.floatPanel.show()
|
||||||
|
},
|
||||||
|
hidePanel() {
|
||||||
|
// 通过 ref 调用 hide 方法隐藏面板
|
||||||
|
this.$refs.floatPanel.hide()
|
||||||
|
},
|
||||||
|
handleBack() {
|
||||||
|
console.log('返回按钮被点击')
|
||||||
|
this.hidePanel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
**属性说明:**
|
||||||
|
|
||||||
|
| 属性 | 类型 | 默认值 | 说明 |
|
||||||
|
|------|------|--------|------|
|
||||||
|
| `title` | String | `''` | 面板标题 |
|
||||||
|
| `width` | String/Number | `'100%'` | 面板宽度(字符串或数字),默认占满父容器 |
|
||||||
|
| `height` | String/Number | `'100%'` | 面板高度(字符串或数字),默认占满父容器 |
|
||||||
|
| `position` | String | `'right'` | 面板位置:`left`、`right`、`top`、`bottom`、`center` |
|
||||||
|
| `showBack` | Boolean | `true` | 是否显示返回按钮 |
|
||||||
|
| `showClose` | Boolean | `false` | 是否显示关闭按钮 |
|
||||||
|
| `backText` | String | `'返回'` | 返回按钮文字 |
|
||||||
|
| `closeOnClickBackdrop` | Boolean | `false` | 点击遮罩是否关闭 |
|
||||||
|
| `mask` | Boolean | `false` | 是否显示遮罩(默认不显示) |
|
||||||
|
| `zIndex` | Number | `1000` | 层级 |
|
||||||
|
|
||||||
|
**方法:**
|
||||||
|
|
||||||
|
| 方法 | 说明 | 参数 |
|
||||||
|
|------|------|------|
|
||||||
|
| `show(callback)` | 显示面板 | `callback`: 可选的回调函数 |
|
||||||
|
| `hide()` | 隐藏面板 | - |
|
||||||
|
|
||||||
|
**事件:**
|
||||||
|
|
||||||
|
| 事件 | 说明 | 参数 |
|
||||||
|
|------|------|------|
|
||||||
|
| `back` | 点击返回按钮时触发 | - |
|
||||||
|
|
||||||
|
**插槽:**
|
||||||
|
|
||||||
|
| 插槽 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `default` | 面板主体内容 |
|
||||||
|
| `header-right` | 头部右侧内容(可用于添加自定义按钮) |
|
||||||
|
|
||||||
|
**位置说明:**
|
||||||
|
|
||||||
|
- `left`: 从左侧滑入
|
||||||
|
- `right`: 从右侧滑入(默认)
|
||||||
|
- `top`: 从顶部滑入
|
||||||
|
- `bottom`: 从底部滑入
|
||||||
|
- `center`: 居中显示,带缩放动画
|
||||||
|
|
||||||
|
**完整示例:**
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<Button @click="openDetailPanel">查看详情</Button>
|
||||||
|
|
||||||
|
<FloatPanel
|
||||||
|
ref="detailPanel"
|
||||||
|
title="用户详情"
|
||||||
|
position="right"
|
||||||
|
:show-back="true"
|
||||||
|
:show-close="true"
|
||||||
|
back-text="返回"
|
||||||
|
@back="handleBack"
|
||||||
|
>
|
||||||
|
<template #header-right>
|
||||||
|
<Button type="primary" @click="handleSave">保存</Button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<div class="detail-content">
|
||||||
|
<Form :model="formData" :label-width="100">
|
||||||
|
<FormItem label="用户名">
|
||||||
|
<Input v-model="formData.username" />
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label="邮箱">
|
||||||
|
<Input v-model="formData.email" />
|
||||||
|
</FormItem>
|
||||||
|
</Form>
|
||||||
|
</div>
|
||||||
|
</FloatPanel>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
formData: {
|
||||||
|
username: '',
|
||||||
|
email: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
openDetailPanel() {
|
||||||
|
this.$refs.detailPanel.show()
|
||||||
|
},
|
||||||
|
handleBack() {
|
||||||
|
this.$refs.detailPanel.hide()
|
||||||
|
},
|
||||||
|
handleSave() {
|
||||||
|
// 保存逻辑
|
||||||
|
console.log('保存数据', this.formData)
|
||||||
|
this.$Message.success('保存成功')
|
||||||
|
this.$refs.detailPanel.hide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
**特性说明:**
|
||||||
|
|
||||||
|
- ✅ 基于父元素定位,不会遮挡菜单
|
||||||
|
- ✅ 宽度和高度默认 100%,占满父容器
|
||||||
|
- ✅ 无遮罩背景,完全浮在父页面上
|
||||||
|
- ✅ 路由切换或组件销毁时自动关闭
|
||||||
|
- ✅ 支持多种位置和动画效果
|
||||||
|
- ✅ 支持自定义头部右侧内容
|
||||||
|
|
||||||
|
## 📝 业务开发示例
|
||||||
|
|
||||||
|
### 创建业务页面
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<!-- src/views/business/product.vue -->
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h1>产品管理</h1>
|
||||||
|
<Button @click="loadData">加载数据</Button>
|
||||||
|
<Tables :columns="columns" :data="list" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
list: [],
|
||||||
|
columns: [
|
||||||
|
{ title: 'ID', key: 'id' },
|
||||||
|
{ title: '名称', key: 'name' },
|
||||||
|
{ title: '价格', key: 'price' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async mounted() {
|
||||||
|
await this.loadData()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async loadData() {
|
||||||
|
// 使用框架提供的 http 工具
|
||||||
|
const res = await this.$http.get('/product/list', { page: 1 })
|
||||||
|
this.list = res.data
|
||||||
|
},
|
||||||
|
|
||||||
|
async handleDelete(id) {
|
||||||
|
// 使用框架提供的 UI 工具
|
||||||
|
this.$uiTool.delConfirm(async () => {
|
||||||
|
await this.$http.post('/product/delete', { id })
|
||||||
|
this.$Message.success('删除成功')
|
||||||
|
await this.loadData()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 创建业务 API
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// src/api/business/productServer.js
|
||||||
|
// 注意:不需要 import http,直接使用 http
|
||||||
|
|
||||||
|
class ProductServer {
|
||||||
|
async getList(params) {
|
||||||
|
return await http.get('/product/list', params)
|
||||||
|
}
|
||||||
|
|
||||||
|
async save(data) {
|
||||||
|
return await http.post('/product/save', data)
|
||||||
|
}
|
||||||
|
|
||||||
|
async delete(id) {
|
||||||
|
return await http.post('/product/delete', { id })
|
||||||
|
}
|
||||||
|
|
||||||
|
async exportCsv(params) {
|
||||||
|
return await http.fileExport('/product/export', params)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new ProductServer()
|
||||||
|
```
|
||||||
|
|
||||||
|
## ❓ 常见问题
|
||||||
|
|
||||||
|
### Q1: 打包后文件太大怎么办?
|
||||||
|
|
||||||
|
A: 框架已经将 Vue、VueRouter、Vuex、ViewUI、Axios 设置为外部依赖,不会打包进去。确保在项目中单独安装这些依赖。
|
||||||
|
|
||||||
|
### Q2: 如何只使用部分功能?
|
||||||
|
|
||||||
|
A: 可以按需导入:
|
||||||
|
```javascript
|
||||||
|
import { http, uiTool, tools } from './libs/admin-framework.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Q3: 权限菜单中的业务页面显示 404 怎么办?
|
||||||
|
|
||||||
|
A: 需要配置组件映射表:
|
||||||
|
```javascript
|
||||||
|
Vue.use(AdminFramework, {
|
||||||
|
// ... 其他配置
|
||||||
|
componentMap: {
|
||||||
|
'ball/games': GamesComponent,
|
||||||
|
'order/pay_orders': PayOrdersComponent
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Q4: 如何自定义配置?
|
||||||
|
|
||||||
|
A: 修改 `config/index.js` 文件:
|
||||||
|
```javascript
|
||||||
|
module.exports = {
|
||||||
|
title: '你的系统名称',
|
||||||
|
apiUrl: 'http://your-api-url/',
|
||||||
|
// ... 其他配置
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Q5: 如何使用登录功能?
|
||||||
|
|
||||||
|
A: 在组件中:
|
||||||
|
```javascript
|
||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
async login() {
|
||||||
|
await this.$store.dispatch('user/handleLogin', {
|
||||||
|
userFrom: { username: 'admin', password: '123456' },
|
||||||
|
Main: AdminFramework.Main,
|
||||||
|
ParentView: AdminFramework.ParentView,
|
||||||
|
Page404: AdminFramework.Page404
|
||||||
|
})
|
||||||
|
this.$router.push({ name: 'home' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Q6: 需要单独引入样式文件吗?
|
||||||
|
|
||||||
|
A: **不需要!** 框架已内置所有样式:
|
||||||
|
- ✅ `base.less` - 基础样式
|
||||||
|
- ✅ `animate.css` - 动画样式
|
||||||
|
- ✅ `ivewExpand.less` - ViewUI 扩展样式
|
||||||
|
- ✅ `iconfont.css` - 字体图标样式
|
||||||
|
|
||||||
|
只需引入框架即可:
|
||||||
|
```javascript
|
||||||
|
import AdminFramework from './libs/admin-framework.js'
|
||||||
|
Vue.use(AdminFramework, { ... })
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📦 技术栈
|
||||||
|
|
||||||
|
- Vue 2.6+
|
||||||
|
- Vue Router 3.x
|
||||||
|
- Vuex 3.x
|
||||||
|
- View Design (iView) 4.x
|
||||||
|
- Axios
|
||||||
|
- Less
|
||||||
|
- Webpack 5
|
||||||
|
|
||||||
|
## 📄 许可证
|
||||||
|
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
## 👨💻 作者
|
||||||
|
|
||||||
|
light
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**祝开发愉快!** 🎉
|
||||||
|
|
||||||
|
如有问题,请查看 Demo 项目示例或联系开发团队。
|
||||||
269
_doc/完整使用文档.md
269
_doc/完整使用文档.md
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
## 🎯 Demo 项目
|
## 🎯 Demo 项目
|
||||||
|
|
||||||
📦 **已提供完整的示例项目**:`demo-project/`
|
📦 **已提供完整的示例项目**:`demo/`
|
||||||
|
|
||||||
一个开箱即用的完整示例,包含:
|
一个开箱即用的完整示例,包含:
|
||||||
- ✅ 框架集成配置
|
- ✅ 框架集成配置
|
||||||
@@ -18,12 +18,12 @@
|
|||||||
|
|
||||||
**快速体验**:
|
**快速体验**:
|
||||||
```bash
|
```bash
|
||||||
cd demo-project
|
cd demo
|
||||||
npm install
|
npm install
|
||||||
npm run dev
|
npm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
详细说明:[demo-project/README.md](./demo-project/README.md)
|
详细说明:[demo/README.md](./demo/README.md)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -41,11 +41,14 @@ npm run dev
|
|||||||
|
|
||||||
## ✨ 特性
|
## ✨ 特性
|
||||||
|
|
||||||
|
✅ **极简 API** - 只需调用 `createApp()` 即可完成所有初始化
|
||||||
|
✅ **模块化设计** - 组件、路由、状态管理等功能按模块组织
|
||||||
✅ **主页组件**(欢迎页面,自动显示系统标题)
|
✅ **主页组件**(欢迎页面,自动显示系统标题)
|
||||||
✅ **系统管理页面**(sys 开头的所有页面和功能)
|
✅ **系统管理页面**(sys 开头的所有页面和功能)
|
||||||
✅ **系统 API**(system 和 system_high 所有 API)
|
✅ **系统 API**(system 和 system 所有 API)
|
||||||
✅ **全局组件**(Tables、Editor、Upload 等)
|
✅ **全局组件**(Tables、Editor、Upload、FieldRenderer、FloatPanel 等)
|
||||||
✅ **布局组件**(Main、ParentView)
|
✅ **布局组件**(Main、ParentView)
|
||||||
|
✅ **文件下载**(支持 CSV 等格式,自动处理换行符)
|
||||||
✅ **登录和错误页面**(Login、401、404、500)
|
✅ **登录和错误页面**(Login、401、404、500)
|
||||||
✅ **用户登录和权限管理**
|
✅ **用户登录和权限管理**
|
||||||
✅ **动态路由管理**
|
✅ **动态路由管理**
|
||||||
@@ -60,11 +63,11 @@ npm run dev
|
|||||||
|
|
||||||
### 🎯 方式一:使用 Demo 项目(推荐新手)
|
### 🎯 方式一:使用 Demo 项目(推荐新手)
|
||||||
|
|
||||||
我们提供了一个完整的 **demo-project** 示例项目,可以直接运行查看效果!
|
我们提供了一个完整的 **demo** 示例项目,可以直接运行查看效果!
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 1. 进入 demo 项目
|
# 1. 进入 demo 项目
|
||||||
cd demo-project
|
cd demo
|
||||||
|
|
||||||
# 2. 安装依赖
|
# 2. 安装依赖
|
||||||
npm install
|
npm install
|
||||||
@@ -78,7 +81,7 @@ npm run dev
|
|||||||
- `/home` - 主页
|
- `/home` - 主页
|
||||||
- `/business/product` - 业务示例页面
|
- `/business/product` - 业务示例页面
|
||||||
|
|
||||||
**详细说明**:查看 `demo-project/README.md` 和 `demo-project/INSTALL.md`
|
**详细说明**:查看 `demo/README.md`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -139,9 +142,9 @@ import AdminFramework from 'admin-framework'
|
|||||||
|
|
||||||
✅ **已包含**:
|
✅ **已包含**:
|
||||||
- **主页组件**(HomePage - 欢迎页面,显示系统标题)
|
- **主页组件**(HomePage - 欢迎页面,显示系统标题)
|
||||||
- 所有系统页面(system、system_high)
|
- 所有系统页面(system、system)
|
||||||
- 所有系统 API(system、system_high)
|
- 所有系统 API(system、system)
|
||||||
- 所有全局组件(Tables、Editor、Upload 等)
|
- 所有全局组件(Tables、Editor、Upload、FieldRenderer 等)
|
||||||
- 布局组件(Main、ParentView)
|
- 布局组件(Main、ParentView)
|
||||||
- 登录和错误页面
|
- 登录和错误页面
|
||||||
- 工具库和 Store 模块
|
- 工具库和 Store 模块
|
||||||
@@ -150,11 +153,39 @@ import AdminFramework from 'admin-framework'
|
|||||||
|
|
||||||
**只需准备**:
|
**只需准备**:
|
||||||
```
|
```
|
||||||
├── config/index.js # 配置文件(根据你的项目修改)
|
├── App.vue # 应用根组件(可选)
|
||||||
└── App.vue # 应用根组件
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 2. 创建 main.js(只需 10 行代码!)
|
#### 2. 创建 main.js(新版本 - 只需 8 行代码!)
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import AdminFramework from './libs/admin-framework.js'
|
||||||
|
|
||||||
|
// 导入业务组件(根据权限菜单接口的 component 字段)
|
||||||
|
import GamesComponent from './views/ball/games.vue'
|
||||||
|
import PayOrdersComponent from './views/order/pay_orders.vue'
|
||||||
|
|
||||||
|
// 🎉 只需一行代码!框架自动完成所有初始化
|
||||||
|
const app = AdminFramework.createApp({
|
||||||
|
title: '我的管理系统',
|
||||||
|
apiUrl: 'http://localhost:9098/admin_api/',
|
||||||
|
componentMap: {
|
||||||
|
'ball/games': GamesComponent,
|
||||||
|
'order/pay_orders': PayOrdersComponent
|
||||||
|
// 添加更多业务组件...
|
||||||
|
},
|
||||||
|
|
||||||
|
HomePage: CustomHomePage, // 可选:自定义首页组件,覆盖整个首页
|
||||||
|
onReady() {
|
||||||
|
console.log('应用已启动!')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 挂载应用
|
||||||
|
app.$mount('#app')
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2.1 传统方式(兼容旧版本)
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
@@ -335,19 +366,19 @@ export default {
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// src/api/business/productServer.js
|
// src/api/business/productServer.js
|
||||||
// 注意:不需要 import http,直接使用 window.framework.http
|
// 注意:不需要 import http,直接使用 http
|
||||||
|
|
||||||
class ProductServer {
|
class ProductServer {
|
||||||
async getList(params) {
|
async getList(params) {
|
||||||
return await window.framework.http.get('/product/list', params)
|
return await http.get('/product/list', params)
|
||||||
}
|
}
|
||||||
|
|
||||||
async save(data) {
|
async save(data) {
|
||||||
return await window.framework.http.post('/product/save', data)
|
return await http.post('/product/save', data)
|
||||||
}
|
}
|
||||||
|
|
||||||
async delete(id) {
|
async delete(id) {
|
||||||
return await window.framework.http.post('/product/delete', { id })
|
return await http.post('/product/delete', { id })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -599,13 +630,14 @@ import {
|
|||||||
```javascript
|
```javascript
|
||||||
import {
|
import {
|
||||||
SysLog, // 系统日志管理
|
SysLog, // 系统日志管理
|
||||||
|
SysLogOperate, // 系统操作日志
|
||||||
SysParamSetup, // 参数设置
|
SysParamSetup, // 参数设置
|
||||||
SysRole, // 角色管理
|
SysRole, // 角色管理
|
||||||
SysUser // 用户管理
|
SysUser // 用户管理
|
||||||
} from 'admin-framework'
|
} from 'admin-framework'
|
||||||
```
|
```
|
||||||
|
|
||||||
#### system_high 目录页面
|
#### system 目录页面
|
||||||
```javascript
|
```javascript
|
||||||
import {
|
import {
|
||||||
SysControl, // 控制器管理
|
SysControl, // 控制器管理
|
||||||
@@ -616,7 +648,7 @@ import {
|
|||||||
|
|
||||||
#### 在路由中使用
|
#### 在路由中使用
|
||||||
```javascript
|
```javascript
|
||||||
import { HomePage, SysUser, SysRole, SysMenu } from 'admin-framework'
|
import { HomePage, SysUser, SysRole, SysMenu, SysLog, SysLogOperate } from 'admin-framework'
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
{
|
{
|
||||||
@@ -635,9 +667,19 @@ const routes = [
|
|||||||
component: SysRole
|
component: SysRole
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/system_high/menu',
|
path: '/system/menu',
|
||||||
name: 'sys_menu',
|
name: 'sys_menu',
|
||||||
component: SysMenu
|
component: SysMenu
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/system/log',
|
||||||
|
name: 'sys_log',
|
||||||
|
component: SysLog
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/system/log_operate',
|
||||||
|
name: 'sys_log_operate',
|
||||||
|
component: SysLogOperate
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
@@ -662,19 +704,35 @@ const users = await userServer.getList({ page: 1 })
|
|||||||
const roles = await roleServer.getList()
|
const roles = await roleServer.getList()
|
||||||
```
|
```
|
||||||
|
|
||||||
#### system_high API
|
#### system API(所有 API 都在 systemApi 中)
|
||||||
```javascript
|
```javascript
|
||||||
import { systemHighApi } from 'admin-framework'
|
import { systemApi } from 'admin-framework'
|
||||||
|
|
||||||
// 使用示例
|
// 使用示例
|
||||||
const {
|
const {
|
||||||
|
userServer,
|
||||||
|
roleServer,
|
||||||
|
sysLogServe,
|
||||||
|
fileServe,
|
||||||
menuServer,
|
menuServer,
|
||||||
paramSetupServer,
|
paramSetupServer,
|
||||||
modelServer,
|
modelServer,
|
||||||
|
formServer,
|
||||||
|
formFieldServer,
|
||||||
|
modelFieldServer,
|
||||||
|
tableServer,
|
||||||
|
rolePermissionServer,
|
||||||
|
sysControlTypeServer,
|
||||||
|
sysModuleServer,
|
||||||
|
sysAddressServer,
|
||||||
|
systemTypeServer,
|
||||||
|
plaAccountServer,
|
||||||
// ... 其他 API
|
// ... 其他 API
|
||||||
} = systemHighApi
|
} = systemApi
|
||||||
|
|
||||||
// 调用 API
|
// 调用 API
|
||||||
|
const users = await userServer.getList({ page: 1 })
|
||||||
|
const roles = await roleServer.getList()
|
||||||
const menus = await menuServer.getTree()
|
const menus = await menuServer.getTree()
|
||||||
const params = await paramSetupServer.getOne('sys_title')
|
const params = await paramSetupServer.getOne('sys_title')
|
||||||
```
|
```
|
||||||
@@ -690,10 +748,137 @@ const params = await paramSetupServer.getOne('sys_title')
|
|||||||
<Editor v-model="content" />
|
<Editor v-model="content" />
|
||||||
<UploadSingle v-model="fileUrl" />
|
<UploadSingle v-model="fileUrl" />
|
||||||
<TreeGrid :data="treeData" />
|
<TreeGrid :data="treeData" />
|
||||||
|
<FloatPanel ref="floatPanel" title="详情面板" position="right" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### FloatPanel - 浮动面板组件
|
||||||
|
|
||||||
|
`FloatPanel` 是一个浮动在父窗体上的面板组件,类似于抽屉效果,调用方式和 `AsyncModal` 类似。
|
||||||
|
|
||||||
|
**基本使用:**
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<Button @click="showPanel">打开浮动面板</Button>
|
||||||
|
|
||||||
|
<FloatPanel
|
||||||
|
ref="floatPanel"
|
||||||
|
title="详情面板"
|
||||||
|
position="right"
|
||||||
|
:show-back="true"
|
||||||
|
back-text="返回"
|
||||||
|
@back="handleBack"
|
||||||
|
>
|
||||||
|
<div>这里是面板内容</div>
|
||||||
|
</FloatPanel>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
showPanel() {
|
||||||
|
this.$refs.floatPanel.show()
|
||||||
|
},
|
||||||
|
hidePanel() {
|
||||||
|
this.$refs.floatPanel.hide()
|
||||||
|
},
|
||||||
|
handleBack() {
|
||||||
|
console.log('返回按钮被点击')
|
||||||
|
this.hidePanel()
|
||||||
|
},
|
||||||
|
handleSave() {
|
||||||
|
console.log('保存')
|
||||||
|
this.hidePanel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
**调用方式(类似 AsyncModal):**
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<Button @click="openPanel">打开面板</Button>
|
||||||
|
|
||||||
|
<FloatPanel ref="floatPanel" title="详情" position="right">
|
||||||
|
<div>内容</div>
|
||||||
|
</FloatPanel>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
openPanel() {
|
||||||
|
// 通过 ref 调用 show 方法
|
||||||
|
this.$refs.floatPanel.show()
|
||||||
|
},
|
||||||
|
closePanel() {
|
||||||
|
// 通过 ref 调用 hide 方法
|
||||||
|
this.$refs.floatPanel.hide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
**属性说明:**
|
||||||
|
|
||||||
|
| 属性 | 类型 | 默认值 | 说明 |
|
||||||
|
|------|------|--------|------|
|
||||||
|
| `title` | String | `''` | 面板标题 |
|
||||||
|
| `width` | String/Number | `'100%'` | 面板宽度(字符串或数字),默认占满父容器 |
|
||||||
|
| `height` | String/Number | `'100%'` | 面板高度(字符串或数字),默认占满父容器 |
|
||||||
|
| `position` | String | `'right'` | 面板位置:`left`、`right`、`top`、`bottom`、`center` |
|
||||||
|
| `showBack` | Boolean | `true` | 是否显示返回按钮 |
|
||||||
|
| `showClose` | Boolean | `false` | 是否显示关闭按钮 |
|
||||||
|
| `backText` | String | `'返回'` | 返回按钮文字 |
|
||||||
|
| `closeOnClickBackdrop` | Boolean | `false` | 点击遮罩是否关闭 |
|
||||||
|
| `mask` | Boolean | `false` | 是否显示遮罩(默认不显示) |
|
||||||
|
| `zIndex` | Number | `1000` | 层级 |
|
||||||
|
|
||||||
|
**方法:**
|
||||||
|
|
||||||
|
| 方法 | 说明 | 参数 |
|
||||||
|
|------|------|------|
|
||||||
|
| `show(callback)` | 显示面板 | `callback`: 可选的回调函数 |
|
||||||
|
| `hide()` | 隐藏面板 | - |
|
||||||
|
|
||||||
|
**事件:**
|
||||||
|
|
||||||
|
| 事件 | 说明 | 参数 |
|
||||||
|
|------|------|------|
|
||||||
|
| `back` | 点击返回按钮时触发 | - |
|
||||||
|
|
||||||
|
**插槽:**
|
||||||
|
|
||||||
|
| 插槽 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `default` | 面板主体内容 |
|
||||||
|
| `header-right` | 头部右侧内容 |
|
||||||
|
|
||||||
|
**位置说明:**
|
||||||
|
|
||||||
|
- `left`: 从左侧滑入
|
||||||
|
- `right`: 从右侧滑入(默认)
|
||||||
|
- `top`: 从顶部滑入
|
||||||
|
- `bottom`: 从底部滑入
|
||||||
|
- `center`: 居中显示,带缩放动画
|
||||||
|
|
||||||
|
**特性说明:**
|
||||||
|
|
||||||
|
- ✅ 基于父元素定位,不会遮挡菜单
|
||||||
|
- ✅ 宽度和高度默认 100%,占满父容器
|
||||||
|
- ✅ 无遮罩背景,完全浮在父页面上
|
||||||
|
- ✅ 路由切换或组件销毁时自动关闭
|
||||||
|
- ✅ 支持多种位置和动画效果
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🛠️ 开发指南
|
## 🛠️ 开发指南
|
||||||
@@ -809,7 +994,35 @@ router.beforeEach((to, from, next) => {
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
### Q6: 如何扩展 Store 模块?
|
### Q6: 如何使用文件下载功能?
|
||||||
|
|
||||||
|
A: 框架提供了便捷的文件下载方法:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// 在 Vue 组件中使用
|
||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
exportData() {
|
||||||
|
// 调用 API 获取数据
|
||||||
|
this.$http.fileExport('/api/export', params).then(res => {
|
||||||
|
// 下载文件(自动处理换行符)
|
||||||
|
this.$uiTool.downloadFile(res, '数据导出.csv')
|
||||||
|
this.$Message.success('导出成功!')
|
||||||
|
}).catch(error => {
|
||||||
|
this.$Message.error('导出失败:' + error.message)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**特性:**
|
||||||
|
- ✅ 自动处理 CSV 换行符
|
||||||
|
- ✅ 支持多种文件格式
|
||||||
|
- ✅ 浏览器兼容性好
|
||||||
|
- ✅ 自动清理临时 URL 对象
|
||||||
|
|
||||||
|
### Q7: 如何扩展 Store 模块?
|
||||||
|
|
||||||
A: 在创建 Store 时传入自定义模块:
|
A: 在创建 Store 时传入自定义模块:
|
||||||
|
|
||||||
@@ -1229,9 +1442,9 @@ AdminFramework.addComponentMap({
|
|||||||
- ✅ `system/sys_role.vue` - 角色管理
|
- ✅ `system/sys_role.vue` - 角色管理
|
||||||
- ✅ `system/sys_log.vue` - 日志管理
|
- ✅ `system/sys_log.vue` - 日志管理
|
||||||
- ✅ `system/sys_param_setup.vue` - 参数设置
|
- ✅ `system/sys_param_setup.vue` - 参数设置
|
||||||
- ✅ `system_high/sys_menu.vue` - 菜单管理
|
- ✅ `system/sys_menu.vue` - 菜单管理
|
||||||
- ✅ `system_high/sys_control.vue` - 控制器管理
|
- ✅ `system/sys_control.vue` - 控制器管理
|
||||||
- ✅ `system_high/sys_title.vue` - 系统标题设置
|
- ✅ `system/sys_title.vue` - 系统标题设置
|
||||||
|
|
||||||
#### 配置技巧
|
#### 配置技巧
|
||||||
|
|
||||||
|
|||||||
325
_doc/快速开始.md
Normal file
325
_doc/快速开始.md
Normal file
@@ -0,0 +1,325 @@
|
|||||||
|
# AdminFramework 快速开始
|
||||||
|
|
||||||
|
## 🚀 3 分钟上手
|
||||||
|
|
||||||
|
### 第一步:引入框架
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import AdminFramework from './admin-framework.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
### 第二步:创建应用
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const app = AdminFramework.createApp({
|
||||||
|
title: '我的管理系统',
|
||||||
|
apiUrl: 'http://localhost:9098/admin_api/',
|
||||||
|
componentMap: {
|
||||||
|
'business/product': ProductComponent,
|
||||||
|
'business/order': OrderComponent
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### 第三步:挂载应用1
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
app.$mount('#app')
|
||||||
|
```
|
||||||
|
|
||||||
|
## ✨ 就这么简单!
|
||||||
|
|
||||||
|
**完整代码只需 12 行:**
|
||||||
|
|
||||||
|
## 📁 文件下载功能
|
||||||
|
|
||||||
|
框架内置了便捷的文件下载功能:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// 在组件中使用
|
||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
exportData() {
|
||||||
|
// 调用 API 获取数据
|
||||||
|
this.$http.fileExport('/api/export', params).then(res => {
|
||||||
|
// 下载文件(自动处理换行符)
|
||||||
|
this.$uiTool.downloadFile(res, '数据导出.csv')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**特性:**
|
||||||
|
- ✅ 自动处理 CSV 换行符
|
||||||
|
- ✅ 支持多种文件格式
|
||||||
|
- ✅ 浏览器兼容性好
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// main.js
|
||||||
|
import AdminFramework from './admin-framework.js'
|
||||||
|
import ProductComponent from './views/business/product.vue'
|
||||||
|
import OrderComponent from './views/business/order.vue'
|
||||||
|
|
||||||
|
const app = AdminFramework.createApp({
|
||||||
|
title: '我的管理系统',
|
||||||
|
apiUrl: 'http://localhost:9098/admin_api/',
|
||||||
|
componentMap: {
|
||||||
|
'business/product': ProductComponent,
|
||||||
|
'business/order': OrderComponent
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
app.$mount('#app')
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📋 组件映射表配置
|
||||||
|
|
||||||
|
`componentMap` 用于定义业务页面的动态路由。
|
||||||
|
|
||||||
|
**重要提示:** 只需传递不带 `.vue` 后缀的路径,框架会自动处理带后缀和不带后缀的两种情况!
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// 直接在 createApp 中配置
|
||||||
|
const app = AdminFramework.createApp({
|
||||||
|
title: '我的管理系统',
|
||||||
|
apiUrl: 'http://localhost:9098/admin_api/',
|
||||||
|
componentMap: {
|
||||||
|
// ✅ 正确:只传递不带 .vue 的路径
|
||||||
|
'business/product': ProductComponent,
|
||||||
|
'business/order': OrderComponent,
|
||||||
|
'system/user': UserComponent,
|
||||||
|
|
||||||
|
// ❌ 错误:不要同时传递带和不带 .vue 的路径(多余)
|
||||||
|
// 'business/product.vue': ProductComponent, // 框架会自动添加
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
**说明:** 框架内部会自动为每个组件创建两个映射:
|
||||||
|
- `'business/product'` → ProductComponent
|
||||||
|
- `'business/product.vue'` → ProductComponent(自动添加)
|
||||||
|
|
||||||
|
所以后台菜单配置 `business/product` 或 `business/product.vue` 都可以正常工作!
|
||||||
|
|
||||||
|
## ⚙️ 配置说明
|
||||||
|
|
||||||
|
### 必填参数
|
||||||
|
|
||||||
|
| 参数 | 说明 | 示例 |
|
||||||
|
|------|------|------|
|
||||||
|
| `title` | 应用标题 | `'我的管理系统'` |
|
||||||
|
| `apiUrl` | API 基础地址 | `'http://localhost:9098/admin_api/'` |
|
||||||
|
| `componentMap` | 组件映射表 | 见上方示例 |
|
||||||
|
|
||||||
|
### 可选参数
|
||||||
|
|
||||||
|
| 参数 | 说明 | 默认值 |
|
||||||
|
|------|------|--------|
|
||||||
|
| `uploadUrl` | 上传文件地址 | `apiUrl + 'upload'` |
|
||||||
|
| `onReady` | 应用启动回调 | - |
|
||||||
|
|
||||||
|
## 🎯 完整示例
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import AdminFramework from './admin-framework.js'
|
||||||
|
import componentMap from './router/component-map.js'
|
||||||
|
|
||||||
|
const app = AdminFramework.createApp({
|
||||||
|
// 必填配置
|
||||||
|
title: '我的管理系统',
|
||||||
|
apiUrl: 'http://localhost:9098/admin_api/',
|
||||||
|
componentMap: componentMap,
|
||||||
|
|
||||||
|
// 可选配置
|
||||||
|
uploadUrl: 'http://cdn.example.com/upload', // 可选,默认为 apiUrl + 'upload'
|
||||||
|
|
||||||
|
// 应用启动完成回调
|
||||||
|
onReady() {
|
||||||
|
console.log('应用已启动!')
|
||||||
|
console.log('当前登录用户:', this.$store.state.user)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
app.$mount('#app')
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📦 框架内置功能
|
||||||
|
|
||||||
|
使用 `createApp()` 后,框架会自动提供:
|
||||||
|
|
||||||
|
### 1. 内置页面
|
||||||
|
- ✅ 登录页面 (`/login`)
|
||||||
|
- ✅ 主页 (`/home`)
|
||||||
|
- ✅ 404 页面 (`/404`)
|
||||||
|
- ✅ 401 页面 (`/401`)
|
||||||
|
- ✅ 500 页面 (`/500`)
|
||||||
|
|
||||||
|
### 2. 系统管理页面
|
||||||
|
- ✅ 用户管理 (`/system/user`)
|
||||||
|
- ✅ 角色管理 (`/system/role`)
|
||||||
|
- ✅ 日志管理 (`/system/log`)
|
||||||
|
- ✅ 参数设置 (`/system/param`)
|
||||||
|
- ✅ 菜单管理 (`/system/menu`)
|
||||||
|
- ✅ 权限控制 (`/system/control`)
|
||||||
|
- ✅ 标题设置 (`/system/title`)
|
||||||
|
|
||||||
|
### 3. 全局组件
|
||||||
|
- ✅ `<Tables>` - 增强型表格
|
||||||
|
- ✅ `<UploadSingle>` - 单图上传
|
||||||
|
- ✅ `<UploadMultiple>` - 多图上传
|
||||||
|
- ✅ `<TreeGrid>` - 树形表格
|
||||||
|
- ✅ `<AsyncModal>` - 异步弹窗
|
||||||
|
- ✅ `<Editor>` - 富文本编辑器
|
||||||
|
- ✅ `<CommonIcon>` - 图标选择器
|
||||||
|
- ✅ `<FloatPanel>` - 浮动面板
|
||||||
|
|
||||||
|
### 4. 工具方法
|
||||||
|
|
||||||
|
在任何组件中可以使用:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// HTTP 请求
|
||||||
|
this.$http.get('/api/users')
|
||||||
|
this.$http.post('/api/users', data)
|
||||||
|
|
||||||
|
// UI 工具
|
||||||
|
this.$uiTool.showLoading()
|
||||||
|
this.$uiTool.hideLoading()
|
||||||
|
this.$uiTool.showSuccess('操作成功')
|
||||||
|
|
||||||
|
// 通用工具
|
||||||
|
this.$tools.formatDate(new Date())
|
||||||
|
this.$tools.deepClone(obj)
|
||||||
|
|
||||||
|
// 文件下载
|
||||||
|
this.$uiTool.downloadFile(response, 'filename.xlsx')
|
||||||
|
|
||||||
|
// 配置信息
|
||||||
|
this.$config.title
|
||||||
|
this.$config.apiUrl
|
||||||
|
this.$config.uploadUrl
|
||||||
|
|
||||||
|
// 状态管理
|
||||||
|
this.$store.state.user.token
|
||||||
|
this.$store.state.app.sysTitle
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🎨 自定义页面
|
||||||
|
|
||||||
|
### 1. 创建页面组件
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<!-- views/business/product-list.vue -->
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<Tables :columns="columns" :data="list" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
list: [],
|
||||||
|
columns: [
|
||||||
|
{ title: '产品名称', key: 'name' },
|
||||||
|
{ title: '价格', key: 'price' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.loadData()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async loadData() {
|
||||||
|
const res = await this.$http.get('/products')
|
||||||
|
this.list = res.data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 添加到组件映射表
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// router/component-map.js
|
||||||
|
import ProductList from '../views/business/product-list.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
'business/product': ProductList // 路径对应后台菜单的 component 字段
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 在后台配置菜单
|
||||||
|
|
||||||
|
在"菜单管理"中添加菜单项:
|
||||||
|
- 菜单名称: `产品列表`
|
||||||
|
- 路由路径: `/business/product`
|
||||||
|
- 组件路径: `business/product`(对应 componentMap 的 key)
|
||||||
|
|
||||||
|
## 📝 常见问题
|
||||||
|
|
||||||
|
### Q1: uploadUrl 如何配置?
|
||||||
|
|
||||||
|
**A:** 默认情况下无需配置,框架会自动设置为 `apiUrl + 'upload'`。
|
||||||
|
|
||||||
|
如果需要自定义(如使用 CDN),可以手动传入:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
AdminFramework.createApp({
|
||||||
|
apiUrl: 'http://localhost:9098/admin_api/',
|
||||||
|
uploadUrl: 'http://cdn.example.com/upload' // 自定义上传地址
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Q2: 如何访问框架实例?
|
||||||
|
|
||||||
|
**A:** 框架实例会自动暴露到全局:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// 浏览器控制台
|
||||||
|
window.framework // 框架实例
|
||||||
|
window.app // Vue 实例
|
||||||
|
window.rootVue // Vue 实例(别名)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Q3: 如何添加自定义 Vuex 模块?
|
||||||
|
|
||||||
|
**A:** 使用旧的 `install()` 方式:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import AdminFramework from './admin-framework.js'
|
||||||
|
|
||||||
|
AdminFramework.install(Vue, {
|
||||||
|
config: { ... },
|
||||||
|
ViewUI,
|
||||||
|
VueRouter,
|
||||||
|
Vuex,
|
||||||
|
customModules: {
|
||||||
|
myModule: myModuleConfig
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Q4: 框架文件太大怎么办?
|
||||||
|
|
||||||
|
**A:** 新版框架(3.6 MB)内置了所有依赖,使用更方便。如果需要减小文件大小,可以使用旧的 `install()` 方式,手动引入依赖。
|
||||||
|
|
||||||
|
## 🔗 相关文档
|
||||||
|
|
||||||
|
- [简化使用说明.md](./简化使用说明.md) - 详细的使用说明和对比
|
||||||
|
- [README.md](./README.md) - 项目介绍和特性
|
||||||
|
- [demo/src/main.js](./demo/src/main.js) - 完整示例代码
|
||||||
|
|
||||||
|
## 💡 最佳实践
|
||||||
|
|
||||||
|
1. **推荐使用 `createApp()`** - 代码更简洁,减少 77% 的代码量
|
||||||
|
2. **组件映射表单独管理** - 方便维护和扩展
|
||||||
|
3. **利用内置组件** - 如 `<Tables>`、`<UploadSingle>` 等,提高开发效率
|
||||||
|
4. **使用 `onReady` 回调** - 在应用启动后执行初始化逻辑
|
||||||
|
|
||||||
|
## 🎉 开始开发吧!
|
||||||
|
|
||||||
|
现在你已经了解了 AdminFramework 的快速使用方法,开始构建你的管理系统吧!
|
||||||
@@ -1,351 +0,0 @@
|
|||||||
# Admin Framework Demo - 本地版本
|
|
||||||
|
|
||||||
本地开发版本,不依赖 CDN,所有依赖都从 node_modules 加载。
|
|
||||||
|
|
||||||
## 目录结构
|
|
||||||
|
|
||||||
```
|
|
||||||
demo/
|
|
||||||
├── public/ # 静态资源
|
|
||||||
│ └── index.html # HTML 模板
|
|
||||||
├── src/ # 源代码
|
|
||||||
│ ├── components/ # 自定义组件
|
|
||||||
│ │ └── CustomPage.vue
|
|
||||||
│ ├── main.js # 基础示例入口
|
|
||||||
│ └── main-advanced.js # 高级示例入口
|
|
||||||
├── package.json # 依赖配置
|
|
||||||
├── webpack.config.js # Webpack 配置
|
|
||||||
└── .babelrc # Babel 配置
|
|
||||||
```
|
|
||||||
|
|
||||||
## 快速开始
|
|
||||||
|
|
||||||
### 1. 构建 Admin Framework
|
|
||||||
|
|
||||||
首先需要构建框架(在项目根目录执行):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 回到项目根目录
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
# 生产构建
|
|
||||||
npm run build
|
|
||||||
|
|
||||||
# 或开发构建(有 sourcemap)
|
|
||||||
npm run build:dev
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 安装 Demo 依赖
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 进入 demo 目录
|
|
||||||
cd demo
|
|
||||||
|
|
||||||
# 安装依赖
|
|
||||||
npm install
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 启动开发服务器
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 启动基础示例
|
|
||||||
npm run dev
|
|
||||||
|
|
||||||
# 浏览器会自动打开 http://localhost:8080
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. 构建生产版本
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 构建
|
|
||||||
npm run build
|
|
||||||
|
|
||||||
# 生成的文件在 demo/dist 目录
|
|
||||||
```
|
|
||||||
|
|
||||||
## 切换示例
|
|
||||||
|
|
||||||
### 基础示例(默认)
|
|
||||||
使用 `src/main.js` 作为入口,展示基本功能。
|
|
||||||
|
|
||||||
### 高级示例
|
|
||||||
要切换到高级示例,修改 `webpack.config.js`:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
module.exports = {
|
|
||||||
entry: './src/main-advanced.js', // 改为 main-advanced.js
|
|
||||||
// ... 其他配置
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
然后重新运行 `npm run dev`。
|
|
||||||
|
|
||||||
## 依赖说明
|
|
||||||
|
|
||||||
### 生产依赖
|
|
||||||
- **vue**: ^2.6.14 - Vue 核心库
|
|
||||||
- **vue-router**: ^3.5.3 - 路由管理
|
|
||||||
- **vuex**: ^3.6.2 - 状态管理
|
|
||||||
- **view-design**: ^4.7.0 - UI 组件库
|
|
||||||
- **axios**: ^0.27.2 - HTTP 客户端
|
|
||||||
|
|
||||||
### 开发依赖
|
|
||||||
- **webpack**: ^5.0.0 - 模块打包工具
|
|
||||||
- **webpack-dev-server**: ^4.0.0 - 开发服务器
|
|
||||||
- **babel-loader**: ^8.2.0 - ES6+ 转译
|
|
||||||
- **vue-loader**: ^15.9.0 - Vue 单文件组件加载器
|
|
||||||
- **html-webpack-plugin**: ^5.5.0 - HTML 生成插件
|
|
||||||
|
|
||||||
## 开发指南
|
|
||||||
|
|
||||||
### 1. 添加自定义页面
|
|
||||||
|
|
||||||
在 `src/components` 创建新组件:
|
|
||||||
|
|
||||||
```vue
|
|
||||||
<!-- src/components/MyPage.vue -->
|
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<h1>我的页面</h1>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'MyPage'
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 注册到路由
|
|
||||||
|
|
||||||
在 `src/main.js` 或 `src/main-advanced.js` 中:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
import MyPage from './components/MyPage.vue'
|
|
||||||
|
|
||||||
const customRoutes = [
|
|
||||||
{
|
|
||||||
path: '/my',
|
|
||||||
component: AdminFramework.Main,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: 'page',
|
|
||||||
component: MyPage,
|
|
||||||
meta: { title: '我的页面' }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
customRoutes.forEach(route => {
|
|
||||||
AdminFramework.router.addRoute(route)
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 添加 Vuex 模块
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
const myModule = {
|
|
||||||
namespaced: true,
|
|
||||||
state: { data: null },
|
|
||||||
mutations: {
|
|
||||||
SET_DATA(state, data) {
|
|
||||||
state.data = data
|
|
||||||
}
|
|
||||||
},
|
|
||||||
actions: {
|
|
||||||
fetchData({ commit }) {
|
|
||||||
// 获取数据逻辑
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AdminFramework.store.registerModule('myModule', myModule)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. 使用框架提供的组件
|
|
||||||
|
|
||||||
```vue
|
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<!-- 表格组件 -->
|
|
||||||
<Tables
|
|
||||||
:columns="columns"
|
|
||||||
:data="tableData"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- 上传组件 -->
|
|
||||||
<UploadSingle
|
|
||||||
v-model="fileUrl"
|
|
||||||
:action="uploadUrl"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- 富文本编辑器 -->
|
|
||||||
<Editor v-model="content" />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
columns: [],
|
|
||||||
tableData: [],
|
|
||||||
fileUrl: '',
|
|
||||||
content: '',
|
|
||||||
uploadUrl: this.$config.uploadUrl
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
|
|
||||||
## API 配置
|
|
||||||
|
|
||||||
修改 `src/main.js` 中的配置:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
const config = {
|
|
||||||
title: '系统标题',
|
|
||||||
apiUrl: 'http://your-api.com/api/',
|
|
||||||
uploadUrl: 'http://your-api.com/api/upload'
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## HTTP 请求示例
|
|
||||||
|
|
||||||
### 在组件中使用
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
export default {
|
|
||||||
methods: {
|
|
||||||
async fetchData() {
|
|
||||||
try {
|
|
||||||
// GET 请求
|
|
||||||
const res = await this.$http.get('/api/users')
|
|
||||||
console.log(res.data)
|
|
||||||
|
|
||||||
// POST 请求
|
|
||||||
const res2 = await this.$http.post('/api/users', {
|
|
||||||
name: '张三',
|
|
||||||
age: 25
|
|
||||||
})
|
|
||||||
console.log(res2.data)
|
|
||||||
} catch (error) {
|
|
||||||
this.$Message.error('请求失败')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 工具函数使用
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
export default {
|
|
||||||
methods: {
|
|
||||||
example() {
|
|
||||||
// 日期格式化
|
|
||||||
const formatted = this.$tools.formatDate(new Date(), 'yyyy-MM-dd')
|
|
||||||
|
|
||||||
// 深拷贝
|
|
||||||
const copy = this.$tools.deepClone(obj)
|
|
||||||
|
|
||||||
// 防抖
|
|
||||||
const debounced = this.$tools.debounce(() => {
|
|
||||||
console.log('执行')
|
|
||||||
}, 500)
|
|
||||||
|
|
||||||
// 节流
|
|
||||||
const throttled = this.$tools.throttle(() => {
|
|
||||||
console.log('执行')
|
|
||||||
}, 1000)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## UI 工具使用
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
export default {
|
|
||||||
methods: {
|
|
||||||
example() {
|
|
||||||
// 成功提示
|
|
||||||
this.$ window.framework.uiTool.success('操作成功')
|
|
||||||
|
|
||||||
// 错误提示
|
|
||||||
this.$ window.framework.uiTool.error('操作失败')
|
|
||||||
|
|
||||||
// 警告提示
|
|
||||||
this.$ window.framework.uiTool.warning('警告信息')
|
|
||||||
|
|
||||||
// 确认对话框
|
|
||||||
this.$ window.framework.uiTool.confirm('确定删除吗?').then(() => {
|
|
||||||
// 确认后的操作
|
|
||||||
}).catch(() => {
|
|
||||||
// 取消后的操作
|
|
||||||
})
|
|
||||||
|
|
||||||
// Loading
|
|
||||||
const loading = this.$ window.framework.uiTool.loading('加载中...')
|
|
||||||
setTimeout(() => loading.close(), 2000)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 常见问题
|
|
||||||
|
|
||||||
### 1. 模块找不到
|
|
||||||
确保先构建了 admin-framework:
|
|
||||||
```bash
|
|
||||||
cd .. && npm run build && cd demo
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 端口被占用
|
|
||||||
修改 `webpack.config.js` 中的端口:
|
|
||||||
```javascript
|
|
||||||
devServer: {
|
|
||||||
port: 8081, // 改为其他端口
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 热更新不生效
|
|
||||||
检查 `devServer.hot` 配置是否为 `true`。
|
|
||||||
|
|
||||||
### 4. 样式不生效
|
|
||||||
确保在入口文件中引入了 iView 样式:
|
|
||||||
```javascript
|
|
||||||
import 'view-design/dist/styles/iview.css'
|
|
||||||
```
|
|
||||||
|
|
||||||
## 生产部署
|
|
||||||
|
|
||||||
### 1. 构建
|
|
||||||
```bash
|
|
||||||
npm run build
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 部署
|
|
||||||
将 `demo/dist` 目录下的文件部署到服务器。
|
|
||||||
|
|
||||||
### 3. 注意事项
|
|
||||||
- 确保后端 API 配置正确
|
|
||||||
- 配置 Nginx 或其他服务器的路由重写规则(支持 Vue Router 的 history 模式)
|
|
||||||
|
|
||||||
## 更多示例
|
|
||||||
|
|
||||||
- 基础示例: 运行 `npm run dev`(默认)
|
|
||||||
- 高级示例: 修改 webpack.config.js 的 entry 为 `./src/main-advanced.js`
|
|
||||||
|
|
||||||
## 相关链接
|
|
||||||
|
|
||||||
- [Admin Framework 完整文档](../_doc/完整使用文档.md)
|
|
||||||
- [Vue 官方文档](https://cn.vuejs.org/)
|
|
||||||
- [Vue Router 文档](https://router.vuejs.org/zh/)
|
|
||||||
- [Vuex 文档](https://vuex.vuejs.org/zh/)
|
|
||||||
- [iView 文档](https://www.iviewui.com/)
|
|
||||||
|
|
||||||
@@ -65,11 +65,9 @@ npm run dev
|
|||||||
首先需要构建 admin-framework:
|
首先需要构建 admin-framework:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 生产构建(压缩,无 sourcemap)
|
# 在项目根目录执行
|
||||||
|
cd ..
|
||||||
npm run build
|
npm run build
|
||||||
|
|
||||||
# 开发构建(不压缩,有 sourcemap)
|
|
||||||
npm run build:dev
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. 启动示例
|
### 2. 启动示例
|
||||||
@@ -109,16 +107,26 @@ const config = {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 初始化框架
|
### 初始化框架(新版本 - 推荐)
|
||||||
```javascript
|
```javascript
|
||||||
framework.install(Vue, {
|
// 引入 Admin Framework
|
||||||
config: config, // 配置对象
|
import AdminFramework from '../../dist/admin-framework.js'
|
||||||
ViewUI: iview, // iView 实例
|
|
||||||
VueRouter: VueRouter, // Vue Router
|
// 引入组件映射表
|
||||||
Vuex: Vuex, // Vuex
|
import componentMap from './router/component-map.js'
|
||||||
createPersistedState: null, // Vuex 持久化插件(可选)
|
|
||||||
componentMap: {} // 自定义组件映射
|
// 创建应用
|
||||||
|
const app = AdminFramework.createApp({
|
||||||
|
title: '我的管理系统',
|
||||||
|
apiUrl: 'http://localhost:9098/admin_api/',
|
||||||
|
componentMap: componentMap,
|
||||||
|
onReady() {
|
||||||
|
console.log('应用已准备就绪!')
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 挂载应用
|
||||||
|
app.$mount('#app')
|
||||||
```
|
```
|
||||||
|
|
||||||
## 内置功能
|
## 内置功能
|
||||||
@@ -146,28 +154,30 @@ framework.install(Vue, {
|
|||||||
### HTTP 请求
|
### HTTP 请求
|
||||||
```javascript
|
```javascript
|
||||||
// GET 请求
|
// GET 请求
|
||||||
framework.http.get('/api/users').then(res => {
|
window.framework.http.get('/api/users').then(res => {
|
||||||
console.log(res.data)
|
console.log(res.data)
|
||||||
})
|
})
|
||||||
|
|
||||||
// POST 请求
|
// POST 请求
|
||||||
framework.http.post('/api/users', {
|
window.framework.http.post('/api/users', {
|
||||||
name: '张三',
|
name: '张三',
|
||||||
age: 25
|
age: 25
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
console.log(res.data)
|
console.log(res.data)
|
||||||
})
|
})
|
||||||
|
|
||||||
// 在组件中使用
|
// 在 API 文件中使用
|
||||||
this.$http.get('/api/users').then(res => {
|
class UserServer {
|
||||||
console.log(res.data)
|
async getList(params) {
|
||||||
})
|
return await window.framework.http.get('/api/users', params)
|
||||||
|
}
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 工具函数
|
### 工具函数
|
||||||
```javascript
|
```javascript
|
||||||
// 使用框架提供的工具函数
|
// 使用框架提供的工具函数
|
||||||
const tools = framework.tools
|
const tools = window.framework.tools
|
||||||
|
|
||||||
// 日期格式化
|
// 日期格式化
|
||||||
tools.formatDate(new Date(), 'yyyy-MM-dd HH:mm:ss')
|
tools.formatDate(new Date(), 'yyyy-MM-dd HH:mm:ss')
|
||||||
@@ -185,16 +195,16 @@ tools.throttle(fn, 500)
|
|||||||
### UI 工具
|
### UI 工具
|
||||||
```javascript
|
```javascript
|
||||||
// 使用 UI 工具
|
// 使用 UI 工具
|
||||||
const uiTool = framework.uiTool
|
const uiTool = window.framework.uiTool
|
||||||
|
|
||||||
// 成功提示
|
// 成功提示
|
||||||
window.framework.uiTool.success('操作成功')
|
window.framework.uiTool.success('操作成功')
|
||||||
|
|
||||||
// 错误提示
|
// 错误提示
|
||||||
window.framework.uiTool.error('操作失败')
|
window.framework.uiTool.error('操作失败')
|
||||||
|
|
||||||
// 确认对话框
|
// 确认对话框
|
||||||
window.framework.uiTool.confirm('确定删除吗?').then(() => {
|
window.framework.uiTool.confirm('确定删除吗?').then(() => {
|
||||||
// 确认后的操作
|
// 确认后的操作
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,77 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="zh-CN">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Admin Framework Demo</title>
|
|
||||||
|
|
||||||
<!-- 引入 iView 样式 -->
|
|
||||||
<link rel="stylesheet" href="https://unpkg.com/view-design@4.7.0/dist/styles/iview.css">
|
|
||||||
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif;
|
|
||||||
}
|
|
||||||
#app {
|
|
||||||
height: 100vh;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="app"></div>
|
|
||||||
|
|
||||||
<!-- 引入依赖库 -->
|
|
||||||
<script src="https://unpkg.com/vue@2.6.14/dist/vue.js"></script>
|
|
||||||
<script src="https://unpkg.com/vue-router@3.5.3/dist/vue-router.js"></script>
|
|
||||||
<script src="https://unpkg.com/vuex@3.6.2/dist/vuex.js"></script>
|
|
||||||
<script src="https://unpkg.com/view-design@4.7.0/dist/iview.js"></script>
|
|
||||||
<script src="https://unpkg.com/axios@0.27.2/dist/axios.js"></script>
|
|
||||||
|
|
||||||
<!-- 引入 admin-framework -->
|
|
||||||
<script src="../dist/admin-framework.js"></script>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// 获取框架实例
|
|
||||||
const framework = window.AdminFramework
|
|
||||||
|
|
||||||
// 配置参数
|
|
||||||
const config = {
|
|
||||||
title: 'Admin Framework Demo',
|
|
||||||
apiUrl: 'http://localhost:3000/api/', // 修改为你的 API 地址
|
|
||||||
uploadUrl: 'http://localhost:3000/api/upload' // 修改为你的上传地址
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化框架
|
|
||||||
framework.install(Vue, {
|
|
||||||
config: config,
|
|
||||||
ViewUI: iview,
|
|
||||||
VueRouter: VueRouter,
|
|
||||||
Vuex: Vuex,
|
|
||||||
createPersistedState: null, // 如需持久化,需引入 vuex-persistedstate
|
|
||||||
componentMap: {} // 可添加自定义组件映射
|
|
||||||
})
|
|
||||||
|
|
||||||
// 创建 Vue 实例
|
|
||||||
const app = new Vue({
|
|
||||||
router: framework.router,
|
|
||||||
store: framework.store,
|
|
||||||
render: h => h('router-view')
|
|
||||||
})
|
|
||||||
|
|
||||||
// 挂载应用
|
|
||||||
app.$mount('#app')
|
|
||||||
|
|
||||||
// 将 app 实例挂载到 window,方便调试
|
|
||||||
window.app = app
|
|
||||||
window.rootVue = app
|
|
||||||
|
|
||||||
console.log('Admin Framework Demo 启动成功!')
|
|
||||||
console.log('框架实例:', framework)
|
|
||||||
console.log('路由实例:', framework.router)
|
|
||||||
console.log('Store 实例:', framework.store)
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
||||||
203
demo/package-lock.json
generated
203
demo/package-lock.json
generated
@@ -21,6 +21,8 @@
|
|||||||
"css-loader": "^5.0.0",
|
"css-loader": "^5.0.0",
|
||||||
"file-loader": "^6.2.0",
|
"file-loader": "^6.2.0",
|
||||||
"html-webpack-plugin": "^5.5.0",
|
"html-webpack-plugin": "^5.5.0",
|
||||||
|
"less": "^4.1.0",
|
||||||
|
"less-loader": "^10.0.0",
|
||||||
"style-loader": "^2.0.0",
|
"style-loader": "^2.0.0",
|
||||||
"vue-loader": "^15.9.0",
|
"vue-loader": "^15.9.0",
|
||||||
"vue-style-loader": "^4.1.0",
|
"vue-style-loader": "^4.1.0",
|
||||||
@@ -2904,6 +2906,19 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/copy-anything": {
|
||||||
|
"version": "2.0.6",
|
||||||
|
"resolved": "https://registry.npmmirror.com/copy-anything/-/copy-anything-2.0.6.tgz",
|
||||||
|
"integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"is-what": "^3.14.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/mesqueeb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/core-js-compat": {
|
"node_modules/core-js-compat": {
|
||||||
"version": "3.45.1",
|
"version": "3.45.1",
|
||||||
"resolved": "https://registry.npmmirror.com/core-js-compat/-/core-js-compat-3.45.1.tgz",
|
"resolved": "https://registry.npmmirror.com/core-js-compat/-/core-js-compat-3.45.1.tgz",
|
||||||
@@ -3331,6 +3346,20 @@
|
|||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/errno": {
|
||||||
|
"version": "0.1.8",
|
||||||
|
"resolved": "https://registry.npmmirror.com/errno/-/errno-0.1.8.tgz",
|
||||||
|
"integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"prr": "~1.0.1"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"errno": "cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/es-define-property": {
|
"node_modules/es-define-property": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz",
|
"resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz",
|
||||||
@@ -4290,6 +4319,20 @@
|
|||||||
"postcss": "^8.1.0"
|
"postcss": "^8.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/image-size": {
|
||||||
|
"version": "0.5.5",
|
||||||
|
"resolved": "https://registry.npmmirror.com/image-size/-/image-size-0.5.5.tgz",
|
||||||
|
"integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"bin": {
|
||||||
|
"image-size": "bin/image-size.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/import-local": {
|
"node_modules/import-local": {
|
||||||
"version": "3.2.0",
|
"version": "3.2.0",
|
||||||
"resolved": "https://registry.npmmirror.com/import-local/-/import-local-3.2.0.tgz",
|
"resolved": "https://registry.npmmirror.com/import-local/-/import-local-3.2.0.tgz",
|
||||||
@@ -4466,6 +4509,13 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/is-what": {
|
||||||
|
"version": "3.14.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/is-what/-/is-what-3.14.1.tgz",
|
||||||
|
"integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/is-wsl": {
|
"node_modules/is-wsl": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmmirror.com/is-wsl/-/is-wsl-2.2.0.tgz",
|
"resolved": "https://registry.npmmirror.com/is-wsl/-/is-wsl-2.2.0.tgz",
|
||||||
@@ -4581,6 +4631,16 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/klona": {
|
||||||
|
"version": "2.0.6",
|
||||||
|
"resolved": "https://registry.npmmirror.com/klona/-/klona-2.0.6.tgz",
|
||||||
|
"integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/launch-editor": {
|
"node_modules/launch-editor": {
|
||||||
"version": "2.11.1",
|
"version": "2.11.1",
|
||||||
"resolved": "https://registry.npmmirror.com/launch-editor/-/launch-editor-2.11.1.tgz",
|
"resolved": "https://registry.npmmirror.com/launch-editor/-/launch-editor-2.11.1.tgz",
|
||||||
@@ -4592,6 +4652,80 @@
|
|||||||
"shell-quote": "^1.8.3"
|
"shell-quote": "^1.8.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/less": {
|
||||||
|
"version": "4.4.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/less/-/less-4.4.2.tgz",
|
||||||
|
"integrity": "sha512-j1n1IuTX1VQjIy3tT7cyGbX7nvQOsFLoIqobZv4ttI5axP923gA44zUj6miiA6R5Aoms4sEGVIIcucXUbRI14g==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"copy-anything": "^2.0.1",
|
||||||
|
"parse-node-version": "^1.0.1",
|
||||||
|
"tslib": "^2.3.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"lessc": "bin/lessc"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"errno": "^0.1.1",
|
||||||
|
"graceful-fs": "^4.1.2",
|
||||||
|
"image-size": "~0.5.0",
|
||||||
|
"make-dir": "^2.1.0",
|
||||||
|
"mime": "^1.4.1",
|
||||||
|
"needle": "^3.1.0",
|
||||||
|
"source-map": "~0.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/less-loader": {
|
||||||
|
"version": "10.2.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/less-loader/-/less-loader-10.2.0.tgz",
|
||||||
|
"integrity": "sha512-AV5KHWvCezW27GT90WATaDnfXBv99llDbtaj4bshq6DvAihMdNjaPDcUMa6EXKLRF+P2opFenJp89BXg91XLYg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"klona": "^2.0.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12.13.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/webpack"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"less": "^3.5.0 || ^4.0.0",
|
||||||
|
"webpack": "^5.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/less/node_modules/make-dir": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/make-dir/-/make-dir-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"pify": "^4.0.1",
|
||||||
|
"semver": "^5.6.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/less/node_modules/semver": {
|
||||||
|
"version": "5.7.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/semver/-/semver-5.7.2.tgz",
|
||||||
|
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"optional": true,
|
||||||
|
"bin": {
|
||||||
|
"semver": "bin/semver"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/loader-runner": {
|
"node_modules/loader-runner": {
|
||||||
"version": "4.3.1",
|
"version": "4.3.1",
|
||||||
"resolved": "https://registry.npmmirror.com/loader-runner/-/loader-runner-4.3.1.tgz",
|
"resolved": "https://registry.npmmirror.com/loader-runner/-/loader-runner-4.3.1.tgz",
|
||||||
@@ -4886,6 +5020,38 @@
|
|||||||
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/needle": {
|
||||||
|
"version": "3.3.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/needle/-/needle-3.3.1.tgz",
|
||||||
|
"integrity": "sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"iconv-lite": "^0.6.3",
|
||||||
|
"sax": "^1.2.4"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"needle": "bin/needle"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 4.4.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/needle/node_modules/iconv-lite": {
|
||||||
|
"version": "0.6.3",
|
||||||
|
"resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||||
|
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/negotiator": {
|
"node_modules/negotiator": {
|
||||||
"version": "0.6.4",
|
"version": "0.6.4",
|
||||||
"resolved": "https://registry.npmmirror.com/negotiator/-/negotiator-0.6.4.tgz",
|
"resolved": "https://registry.npmmirror.com/negotiator/-/negotiator-0.6.4.tgz",
|
||||||
@@ -5118,6 +5284,16 @@
|
|||||||
"tslib": "^2.0.3"
|
"tslib": "^2.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/parse-node-version": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/parse-node-version/-/parse-node-version-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/parseurl": {
|
"node_modules/parseurl": {
|
||||||
"version": "1.3.3",
|
"version": "1.3.3",
|
||||||
"resolved": "https://registry.npmmirror.com/parseurl/-/parseurl-1.3.3.tgz",
|
"resolved": "https://registry.npmmirror.com/parseurl/-/parseurl-1.3.3.tgz",
|
||||||
@@ -5202,6 +5378,17 @@
|
|||||||
"url": "https://github.com/sponsors/jonschlinkert"
|
"url": "https://github.com/sponsors/jonschlinkert"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/pify": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/pify/-/pify-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/pkg-dir": {
|
"node_modules/pkg-dir": {
|
||||||
"version": "4.2.0",
|
"version": "4.2.0",
|
||||||
"resolved": "https://registry.npmmirror.com/pkg-dir/-/pkg-dir-4.2.0.tgz",
|
"resolved": "https://registry.npmmirror.com/pkg-dir/-/pkg-dir-4.2.0.tgz",
|
||||||
@@ -5396,6 +5583,14 @@
|
|||||||
"node": ">= 0.10"
|
"node": ">= 0.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/prr": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/prr/-/prr-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"node_modules/pseudomap": {
|
"node_modules/pseudomap": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmmirror.com/pseudomap/-/pseudomap-1.0.2.tgz",
|
"resolved": "https://registry.npmmirror.com/pseudomap/-/pseudomap-1.0.2.tgz",
|
||||||
@@ -5704,6 +5899,14 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/sax": {
|
||||||
|
"version": "1.4.3",
|
||||||
|
"resolved": "https://registry.npmmirror.com/sax/-/sax-1.4.3.tgz",
|
||||||
|
"integrity": "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BlueOak-1.0.0",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"node_modules/schema-utils": {
|
"node_modules/schema-utils": {
|
||||||
"version": "2.7.1",
|
"version": "2.7.1",
|
||||||
"resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-2.7.1.tgz",
|
"resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-2.7.1.tgz",
|
||||||
|
|||||||
@@ -21,6 +21,8 @@
|
|||||||
"css-loader": "^5.0.0",
|
"css-loader": "^5.0.0",
|
||||||
"file-loader": "^6.2.0",
|
"file-loader": "^6.2.0",
|
||||||
"html-webpack-plugin": "^5.5.0",
|
"html-webpack-plugin": "^5.5.0",
|
||||||
|
"less": "^4.1.0",
|
||||||
|
"less-loader": "^10.0.0",
|
||||||
"style-loader": "^2.0.0",
|
"style-loader": "^2.0.0",
|
||||||
"vue-loader": "^15.9.0",
|
"vue-loader": "^15.9.0",
|
||||||
"vue-style-loader": "^4.1.0",
|
"vue-style-loader": "^4.1.0",
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Admin Framework Demo</title>
|
<title>Admin Framework </title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
|
|
||||||
|
const gameCommentsServer = {
|
||||||
export default {
|
|
||||||
// 获取球局评论列表
|
// 获取球局评论列表
|
||||||
getGameCommentsList: (params) => {
|
getGameCommentsList: (params) => {
|
||||||
return window.framework.http.post('/game_comments/page', params)
|
return window.framework.http.post('/game_comments/page', params)
|
||||||
@@ -50,4 +49,14 @@ export default {
|
|||||||
getCommentReplies: (params) => {
|
getCommentReplies: (params) => {
|
||||||
return window.framework.http.get('/game_comments/replies', params)
|
return window.framework.http.get('/game_comments/replies', params)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 添加简写方法名别名,保持向后兼容
|
||||||
|
gameCommentsServer.page = gameCommentsServer.getGameCommentsList
|
||||||
|
gameCommentsServer.all = gameCommentsServer.getAllGameComments
|
||||||
|
gameCommentsServer.add = gameCommentsServer.addGameComment
|
||||||
|
gameCommentsServer.edit = gameCommentsServer.updateGameComment
|
||||||
|
gameCommentsServer.del = gameCommentsServer.deleteGameComment
|
||||||
|
gameCommentsServer.exportCsv = gameCommentsServer.exportGameComments
|
||||||
|
|
||||||
|
export default gameCommentsServer
|
||||||
@@ -1,33 +1,24 @@
|
|||||||
import request from '@/libs/http'
|
/**
|
||||||
|
* 业务游戏管理 API
|
||||||
|
*
|
||||||
|
* 使用说明:
|
||||||
|
* 1. 不需要 import http
|
||||||
|
* 2. 直接使用 window.framework.http 调用接口
|
||||||
|
* 3. 所有方法返回 Promise
|
||||||
|
*/
|
||||||
|
|
||||||
export const getList = (params) => {
|
export const getList = (params) => {
|
||||||
return request({
|
return window.framework.http.get('/business/games/page', params)
|
||||||
url: '/business/games/page',
|
|
||||||
method: 'get',
|
|
||||||
params
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const add = (data) => {
|
export const add = (data) => {
|
||||||
return request({
|
return window.framework.http.post('/business/games/add', data)
|
||||||
url: '/business/games',
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const edit = (data) => {
|
export const edit = (data) => {
|
||||||
return request({
|
return window.framework.http.post('/business/games/edit', data)
|
||||||
url: '/business/games',
|
|
||||||
method: 'put',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const del = (params) => {
|
export const del = (params) => {
|
||||||
return request({
|
return window.framework.http.post('/business/games/del', params)
|
||||||
url: '/business/games',
|
|
||||||
method: 'delete',
|
|
||||||
params
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
export default {
|
export default {
|
||||||
// 获取消息通知列表
|
// 获取消息通知列表
|
||||||
page: (params) => {
|
page: (params) => {
|
||||||
return http.post('/msg_notifications/page', params)
|
return window.framework.http.post('/msg_notifications/page', params)
|
||||||
},
|
},
|
||||||
|
|
||||||
// 新增消息通知
|
// 新增消息通知
|
||||||
|
|||||||
@@ -1,33 +1,24 @@
|
|||||||
import request from '@/libs/http'
|
/**
|
||||||
|
* 系统文件管理 API
|
||||||
|
*
|
||||||
|
* 使用说明:
|
||||||
|
* 1. 不需要 import http
|
||||||
|
* 2. 直接使用 window.framework.http 调用接口
|
||||||
|
* 3. 所有方法返回 Promise
|
||||||
|
*/
|
||||||
|
|
||||||
export const getList = (params) => {
|
export const getList = (params) => {
|
||||||
return request({
|
return window.framework.http.get('/sys_file/page', params)
|
||||||
url: '/sys_file/page',
|
|
||||||
method: 'get',
|
|
||||||
params
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const add = (data) => {
|
export const add = (data) => {
|
||||||
return request({
|
return window.framework.http.post('/sys_file/add', data)
|
||||||
url: '/sys_file',
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const edit = (data) => {
|
export const edit = (data) => {
|
||||||
return request({
|
return window.framework.http.post('/sys_file/edit', data)
|
||||||
url: '/sys_file',
|
|
||||||
method: 'put',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const del = (params) => {
|
export const del = (params) => {
|
||||||
return request({
|
return window.framework.http.post('/sys_file/del', params)
|
||||||
url: '/sys_file',
|
|
||||||
method: 'delete',
|
|
||||||
params
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,57 +1,41 @@
|
|||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 球局统计 API
|
||||||
|
*
|
||||||
|
* 使用说明:
|
||||||
|
* 1. 不需要 import http
|
||||||
|
* 2. 直接使用 window.framework.http 调用接口
|
||||||
|
* 3. 所有方法返回 Promise
|
||||||
|
*/
|
||||||
|
|
||||||
// 获取球局统计列表
|
// 获取球局统计列表
|
||||||
export const getList = (params) => {
|
export const getList = (params) => {
|
||||||
return http.request({
|
return window.framework.http.post('/admin/game_statistics/list', params)
|
||||||
url: '/admin/game_statistics/list',
|
|
||||||
method: 'post',
|
|
||||||
data: params
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取球局统计详情
|
// 获取球局统计详情
|
||||||
export const getDetail = (params) => {
|
export const getDetail = (params) => {
|
||||||
return http.request({
|
return window.framework.http.post('/admin/game_statistics/detail', params)
|
||||||
url: '/admin/game_statistics/detail',
|
|
||||||
method: 'post',
|
|
||||||
data: params
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加球局统计
|
// 添加球局统计
|
||||||
export const add = (params) => {
|
export const add = (params) => {
|
||||||
return http.request({
|
return window.framework.http.post('/admin/game_statistics/add', params)
|
||||||
url: '/admin/game_statistics/add',
|
|
||||||
method: 'post',
|
|
||||||
data: params
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 编辑球局统计
|
// 编辑球局统计
|
||||||
export const edit = (params) => {
|
export const edit = (params) => {
|
||||||
return http.request({
|
return window.framework.http.post('/admin/game_statistics/edit', params)
|
||||||
url: '/admin/game_statistics/edit',
|
|
||||||
method: 'post',
|
|
||||||
data: params
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除球局统计
|
// 删除球局统计
|
||||||
export const del = (params) => {
|
export const del = (params) => {
|
||||||
return http.request({
|
return window.framework.http.post('/admin/game_statistics/del', params)
|
||||||
url: '/admin/game_statistics/del',
|
|
||||||
method: 'post',
|
|
||||||
data: params
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 导出球局统计
|
// 导出球局统计
|
||||||
export const exportData = (params) => {
|
export const exportData = (params) => {
|
||||||
return http.request({
|
return window.framework.http.fileExport('/admin/game_statistics/export', params)
|
||||||
url: '/admin/game_statistics/export',
|
|
||||||
method: 'post',
|
|
||||||
data: params,
|
|
||||||
responseType: 'blob'
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,66 +1,46 @@
|
|||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 营收统计 API
|
||||||
|
*
|
||||||
|
* 使用说明:
|
||||||
|
* 1. 不需要 import http
|
||||||
|
* 2. 直接使用 window.framework.http 调用接口
|
||||||
|
* 3. 所有方法返回 Promise
|
||||||
|
*/
|
||||||
|
|
||||||
// 获取营收统计列表
|
// 获取营收统计列表
|
||||||
export const getList = (params) => {
|
export const getList = (params) => {
|
||||||
return http.request({
|
return window.framework.http.post('/admin/revenue_statistics/list', params)
|
||||||
url: '/admin/revenue_statistics/list',
|
|
||||||
method: 'post',
|
|
||||||
data: params
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取营收统计详情
|
// 获取营收统计详情
|
||||||
export const getDetail = (params) => {
|
export const getDetail = (params) => {
|
||||||
return http.request({
|
return window.framework.http.post('/admin/revenue_statistics/detail', params)
|
||||||
url: '/admin/revenue_statistics/detail',
|
|
||||||
method: 'post',
|
|
||||||
data: params
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取营收统计概览
|
// 获取营收统计概览
|
||||||
export const getOverview = (params) => {
|
export const getOverview = (params) => {
|
||||||
return http.request({
|
return window.framework.http.post('/admin/revenue_statistics/overview', params)
|
||||||
url: '/admin/revenue_statistics/overview',
|
|
||||||
method: 'post',
|
|
||||||
data: params
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加营收统计
|
// 添加营收统计
|
||||||
export const add = (params) => {
|
export const add = (params) => {
|
||||||
return http.request({
|
return window.framework.http.post('/admin/revenue_statistics/add', params)
|
||||||
url: '/admin/revenue_statistics/add',
|
|
||||||
method: 'post',
|
|
||||||
data: params
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 编辑营收统计
|
// 编辑营收统计
|
||||||
export const edit = (params) => {
|
export const edit = (params) => {
|
||||||
return http.request({
|
return window.framework.http.post('/admin/revenue_statistics/edit', params)
|
||||||
url: '/admin/revenue_statistics/edit',
|
|
||||||
method: 'post',
|
|
||||||
data: params
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除营收统计
|
// 删除营收统计
|
||||||
export const del = (params) => {
|
export const del = (params) => {
|
||||||
return http.request({
|
return window.framework.http.post('/admin/revenue_statistics/del', params)
|
||||||
url: '/admin/revenue_statistics/del',
|
|
||||||
method: 'post',
|
|
||||||
data: params
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 导出营收统计
|
// 导出营收统计
|
||||||
export const exportData = (params) => {
|
export const exportData = (params) => {
|
||||||
return http.request({
|
return window.framework.http.fileExport('/admin/revenue_statistics/export', params)
|
||||||
url: '/admin/revenue_statistics/export',
|
|
||||||
method: 'post',
|
|
||||||
data: params,
|
|
||||||
responseType: 'blob'
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
|
|
||||||
class ShpProfitServer {
|
|
||||||
async report(param) {
|
|
||||||
let res = await window.framework.http.post('/shpProfit/report', param)
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
async list(param) {
|
|
||||||
let res = await window.framework.http.post('/shpProfit/list', param)
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const shpProfitServer = new ShpProfitServer()
|
|
||||||
export default shpProfitServer
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
|
|
||||||
class SysControlTypeServer {
|
|
||||||
async all(param) {
|
|
||||||
let res = await window.framework.http.get("/sys_control_type/all", param);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
async page(row) {
|
|
||||||
let res = await window.framework.http.post("/sys_control_type/page", row);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
async add(param) {
|
|
||||||
let res = await window.framework.http.post("/sys_control_type/add", param);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
async edit(param) {
|
|
||||||
let res = await window.framework.http.post("/sys_control_type/edit", param);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
async del(param) {
|
|
||||||
let res = await window.framework.http.post("/sys_control_type/del", param);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const sysControlTypeServer = new SysControlTypeServer();
|
|
||||||
export default sysControlTypeServer;
|
|
||||||
@@ -1,88 +1,22 @@
|
|||||||
// 引入依赖
|
// 开发环境直接引用源码以支持热更新
|
||||||
import Vue from 'vue'
|
|
||||||
import VueRouter from 'vue-router'
|
|
||||||
import Vuex from 'vuex'
|
|
||||||
import ViewUI from 'view-design'
|
|
||||||
|
|
||||||
|
|
||||||
// 引入样式
|
|
||||||
import 'view-design/dist/styles/iview.css'
|
|
||||||
|
|
||||||
// 引入 Admin Framework(使用本地构建的文件)
|
|
||||||
import AdminFramework from '../../dist/admin-framework.js'
|
import AdminFramework from '../../dist/admin-framework.js'
|
||||||
|
|
||||||
// 引入组件映射表
|
// 引入组件映射表
|
||||||
import componentMap from './router/component-map.js'
|
import componentMap from './router/component-map.js'
|
||||||
|
|
||||||
// 使用插件
|
// 【超级简化】只需一个函数调用!
|
||||||
Vue.use(ViewUI)
|
const app = AdminFramework.createApp({
|
||||||
|
|
||||||
// 配置参数
|
|
||||||
const config = {
|
|
||||||
title: 'tennis管理系统',
|
title: 'tennis管理系统',
|
||||||
apiUrl: 'http://localhost:9098/admin_api/', // 修改为你的 API 地址
|
apiUrl: 'http://localhost:9098/admin_api/', // API 地址(uploadUrl 会自动设置为 apiUrl + 'upload')
|
||||||
uploadUrl: 'http://localhost:9098/admin_api/upload' // 修改为你的上传地址
|
componentMap: componentMap, // 传入组件映射表,用于动态路由
|
||||||
}
|
onReady() {
|
||||||
|
// 可选:应用启动完成后的回调
|
||||||
// 初始化框架
|
console.log('应用已准备就绪!')
|
||||||
AdminFramework.install(Vue, {
|
|
||||||
config: config,
|
|
||||||
ViewUI: ViewUI,
|
|
||||||
VueRouter: VueRouter,
|
|
||||||
Vuex: Vuex,
|
|
||||||
createPersistedState: null,
|
|
||||||
componentMap: componentMap // 传入组件映射表,用于动态路由
|
|
||||||
})
|
|
||||||
|
|
||||||
// 创建 Vue 实例
|
|
||||||
const app = new Vue({
|
|
||||||
router: AdminFramework.router,
|
|
||||||
store: AdminFramework.store,
|
|
||||||
render: h => h('router-view'),
|
|
||||||
async created() {
|
|
||||||
console.log('=== Admin Framework Demo 启动成功 ===')
|
|
||||||
console.log('框架版本:', AdminFramework.version)
|
|
||||||
console.log('配置信息:', this.$config)
|
|
||||||
|
|
||||||
// 刷新时恢复菜单和标题
|
|
||||||
const token = this.$store.state.user.token
|
|
||||||
const authorityMenus = localStorage.getItem('authorityMenus')
|
|
||||||
|
|
||||||
if (token && authorityMenus) {
|
|
||||||
console.log('检测到登录状态,恢复菜单和标题...')
|
|
||||||
try {
|
|
||||||
// 先恢复菜单
|
|
||||||
await this.$store.dispatch('user/setAuthorityMenus', {
|
|
||||||
Main: AdminFramework.Main,
|
|
||||||
ParentView: AdminFramework.ParentView,
|
|
||||||
Page404: AdminFramework.Page404,
|
|
||||||
authorityMenus: authorityMenus
|
|
||||||
})
|
|
||||||
console.log('菜单恢复成功')
|
|
||||||
|
|
||||||
// 再获取系统标题(已登录,会从接口获取)
|
|
||||||
await this.$store.dispatch('app/getSysTitle', {
|
|
||||||
defaultTitle: this.$config.title,
|
|
||||||
defaultLogo: ''
|
|
||||||
})
|
|
||||||
} catch (error) {
|
|
||||||
console.error('恢复失败:', error)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 未登录,使用默认标题
|
|
||||||
console.log('未登录,使用默认标题')
|
|
||||||
document.title = this.$config.title
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// 挂载应用
|
// 挂载应用
|
||||||
app.$mount('#app')
|
app.$mount('#app')
|
||||||
|
|
||||||
// 全局暴露(方便调试)
|
|
||||||
window.app = app
|
|
||||||
window.rootVue = app
|
|
||||||
window.framework = AdminFramework
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -41,69 +41,55 @@ import WchProfessions from '../views/users/wch_professions.vue'
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 组件映射对象
|
* 组件映射对象
|
||||||
* key: 后端返回的组件路径(去掉 .vue 后缀或保留都可以)
|
*
|
||||||
|
* ✅ 重要提示:只需传递不带 .vue 后缀的路径!
|
||||||
|
* 框架会自动为每个组件创建带 .vue 和不带 .vue 的两个映射
|
||||||
|
*
|
||||||
|
* 例如:'ai/ai_messages': AiMessages
|
||||||
|
* 框架自动处理为:
|
||||||
|
* - 'ai/ai_messages' → AiMessages
|
||||||
|
* - 'ai/ai_messages.vue' → AiMessages (自动添加)
|
||||||
|
*
|
||||||
|
* key: 后端返回的组件路径(不带 .vue 后缀)
|
||||||
* value: 实际的 Vue 组件
|
* value: 实际的 Vue 组件
|
||||||
*/
|
*/
|
||||||
const componentMap = {
|
const componentMap = {
|
||||||
// ===== AI 模块 =====
|
// ===== AI 模块 =====
|
||||||
'ai/ai_messages': AiMessages,
|
'ai/ai_messages': AiMessages,
|
||||||
'ai/ai_messages.vue': AiMessages,
|
|
||||||
|
|
||||||
// ===== 球场模块 =====
|
// ===== 球场模块 =====
|
||||||
'ball/game_comments': GameComments,
|
'ball/game_comments': GameComments,
|
||||||
'ball/game_comments.vue': GameComments,
|
|
||||||
'ball/game_participants': GameParticipants,
|
'ball/game_participants': GameParticipants,
|
||||||
'ball/game_participants.vue': GameParticipants,
|
|
||||||
'ball/games': Games,
|
'ball/games': Games,
|
||||||
'ball/games.vue': Games,
|
|
||||||
'ball/venues': Venues,
|
'ball/venues': Venues,
|
||||||
'ball/venues.vue': Venues,
|
|
||||||
'ball/wch_users': WchUsers,
|
'ball/wch_users': WchUsers,
|
||||||
'ball/wch_users.vue': WchUsers,
|
|
||||||
|
|
||||||
// ===== 业务模块 =====
|
// ===== 业务模块 =====
|
||||||
'business/hot_city_qr': HotCityQr,
|
'business/hot_city_qr': HotCityQr,
|
||||||
'business/hot_city_qr.vue': HotCityQr,
|
|
||||||
|
|
||||||
// ===== 消息模块 =====
|
// ===== 消息模块 =====
|
||||||
'message/msg_notifications': MsgNotifications,
|
'message/msg_notifications': MsgNotifications,
|
||||||
'message/msg_notifications.vue': MsgNotifications,
|
|
||||||
|
|
||||||
// ===== NTRP 模块 =====
|
// ===== NTRP 模块 =====
|
||||||
'ntrp/ntr_questions': NtrQuestions,
|
'ntrp/ntr_questions': NtrQuestions,
|
||||||
'ntrp/ntr_questions.vue': NtrQuestions,
|
|
||||||
'ntrp/ntr_records': NtrRecords,
|
'ntrp/ntr_records': NtrRecords,
|
||||||
'ntrp/ntr_records.vue': NtrRecords,
|
|
||||||
|
|
||||||
// ===== 订单模块 =====
|
// ===== 订单模块 =====
|
||||||
'order/frozen_funds': FrozenFunds,
|
'order/frozen_funds': FrozenFunds,
|
||||||
'order/frozen_funds.vue': FrozenFunds,
|
|
||||||
'order/pay_orders': PayOrders,
|
'order/pay_orders': PayOrders,
|
||||||
'order/pay_orders.vue': PayOrders,
|
|
||||||
'order/transfer_details': TransferDetails,
|
'order/transfer_details': TransferDetails,
|
||||||
'order/transfer_details.vue': TransferDetails,
|
|
||||||
'order/wallet_transactions': WalletTransactions,
|
'order/wallet_transactions': WalletTransactions,
|
||||||
'order/wallet_transactions.vue': WalletTransactions,
|
|
||||||
'order/wch_wallets': WchWallets,
|
'order/wch_wallets': WchWallets,
|
||||||
'order/wch_wallets.vue': WchWallets,
|
|
||||||
|
|
||||||
// ===== 统计模块 =====
|
// ===== 统计模块 =====
|
||||||
'statistics/resources': Resources,
|
'statistics/resources': Resources,
|
||||||
'statistics/resources.vue': Resources,
|
|
||||||
|
|
||||||
// ===== 用户模块 =====
|
// ===== 用户模块 =====
|
||||||
'users/recommend_blocks': RecommendBlocks,
|
'users/recommend_blocks': RecommendBlocks,
|
||||||
'users/recommend_blocks.vue': RecommendBlocks,
|
|
||||||
'users/user_follows': UserFollows,
|
'users/user_follows': UserFollows,
|
||||||
'users/user_follows.vue': UserFollows,
|
|
||||||
'users/user_tracking': UserTracking,
|
'users/user_tracking': UserTracking,
|
||||||
'users/user_tracking.vue': UserTracking,
|
'users/wch_cities': WchCities,
|
||||||
"users/wch_cities.vue": WchCities,
|
'users/wch_professions': WchProfessions,
|
||||||
"users/wch_cities": WchCities,
|
|
||||||
"users/wch_professions.vue": WchProfessions,
|
|
||||||
"users/wch_professions": WchProfessions,
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default componentMap
|
export default componentMap
|
||||||
|
|||||||
@@ -140,13 +140,13 @@ export default {
|
|||||||
delConfirm(row) {
|
delConfirm(row) {
|
||||||
window.framework.uiTool.delConfirm(async () => {
|
window.framework.uiTool.delConfirm(async () => {
|
||||||
await ai_messagesServer.del(row)
|
await ai_messagesServer.del(row)
|
||||||
rootVue.$Message.success('删除成功!')
|
this.$Message.success('删除成功!')
|
||||||
this.query(1)
|
this.query(1)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
exportCsv() {
|
exportCsv() {
|
||||||
ai_messagesServer.exportCsv(this.gridOption.param).then(res => {
|
ai_messagesServer.exportCsv(this.gridOption.param).then(res => {
|
||||||
window.framework.funTool.downloadFile(res, 'AI消息管理.csv');
|
window.framework.tools.downloadFile(res, 'AI消息管理.csv');
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
resetQuery() {
|
resetQuery() {
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ export default {
|
|||||||
delConfirm(row) {
|
delConfirm(row) {
|
||||||
window.framework.uiTool.delConfirm(async () => {
|
window.framework.uiTool.delConfirm(async () => {
|
||||||
await game_commentsServer.del(row)
|
await game_commentsServer.del(row)
|
||||||
rootVue.$Message.success('删除成功!')
|
this.$Message.success('删除成功!')
|
||||||
this.query(1)
|
this.query(1)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -147,7 +147,7 @@ export default {
|
|||||||
},
|
},
|
||||||
exportCsv() {
|
exportCsv() {
|
||||||
game_commentsServer.exportCsv(this.gridOption.param).then(res => {
|
game_commentsServer.exportCsv(this.gridOption.param).then(res => {
|
||||||
window.framework.funTool.downloadFile(res, '球局评论.csv');
|
window.framework.tools.downloadFile(res, '球局评论.csv');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
<script>
|
<script>
|
||||||
|
|
||||||
|
|
||||||
import menuServer from '@/api/system_high/menuServer.js'
|
import menuServer from '@/api/system/menuServer.js'
|
||||||
import gameParticipantsServer from '@/api/ball/game_participants_server.js'
|
import gameParticipantsServer from '@/api/ball/game_participants_server.js'
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
@@ -270,7 +270,7 @@ export default {
|
|||||||
'joined_at': 'CURRENT_TIMESTAMP'
|
'joined_at': 'CURRENT_TIMESTAMP'
|
||||||
}, async (newRow) => {
|
}, async (newRow) => {
|
||||||
let res = await gameParticipantsServer.add(newRow)
|
let res = await gameParticipantsServer.add(newRow)
|
||||||
rootVue.$Message.success('新增成功!')
|
this.$Message.success('新增成功!')
|
||||||
this.init()
|
this.init()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -282,7 +282,7 @@ export default {
|
|||||||
let valid = await this.$refs['editModal'].$refs['From'].validate()
|
let valid = await this.$refs['editModal'].$refs['From'].validate()
|
||||||
if (valid) {
|
if (valid) {
|
||||||
let res = await gameParticipantsServer.edit(newRow)
|
let res = await gameParticipantsServer.edit(newRow)
|
||||||
rootVue.$Message.success('修改成功!')
|
this.$Message.success('修改成功!')
|
||||||
this.init()
|
this.init()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -290,7 +290,7 @@ export default {
|
|||||||
async delConfirm(row) {
|
async delConfirm(row) {
|
||||||
window.framework.uiTool.delConfirm(async () => {
|
window.framework.uiTool.delConfirm(async () => {
|
||||||
await gameParticipantsServer.del(row)
|
await gameParticipantsServer.del(row)
|
||||||
rootVue.$Message.success('删除成功!')
|
this.$Message.success('删除成功!')
|
||||||
this.init()
|
this.init()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -50,7 +50,7 @@
|
|||||||
<script>
|
<script>
|
||||||
|
|
||||||
|
|
||||||
import menuServer from '@/api/system_high/menuServer.js'
|
import menuServer from '@/api/system/menuServer.js'
|
||||||
import gamesServer from '@/api/ball/games_server.js'
|
import gamesServer from '@/api/ball/games_server.js'
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
@@ -513,7 +513,7 @@ export default {
|
|||||||
'remark': ''
|
'remark': ''
|
||||||
}, async (newRow) => {
|
}, async (newRow) => {
|
||||||
let res = await gamesServer.add(newRow)
|
let res = await gamesServer.add(newRow)
|
||||||
rootVue.$Message.success('新增成功!')
|
this.$Message.success('新增成功!')
|
||||||
this.init()
|
this.init()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -522,7 +522,7 @@ export default {
|
|||||||
let valid = await this.$refs['editModal'].$refs['From'].validate()
|
let valid = await this.$refs['editModal'].$refs['From'].validate()
|
||||||
if (valid) {
|
if (valid) {
|
||||||
let res = await gamesServer.edit(newRow)
|
let res = await gamesServer.edit(newRow)
|
||||||
rootVue.$Message.success('修改成功!')
|
this.$Message.success('修改成功!')
|
||||||
this.init()
|
this.init()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -530,7 +530,7 @@ export default {
|
|||||||
async delConfirm(row) {
|
async delConfirm(row) {
|
||||||
window.framework.uiTool.delConfirm(async () => {
|
window.framework.uiTool.delConfirm(async () => {
|
||||||
await gamesServer.del(row)
|
await gamesServer.del(row)
|
||||||
rootVue.$Message.success('删除成功!')
|
this.$Message.success('删除成功!')
|
||||||
this.init()
|
this.init()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -50,7 +50,7 @@
|
|||||||
<script>
|
<script>
|
||||||
|
|
||||||
|
|
||||||
import menuServer from '@/api/system_high/menuServer.js'
|
import menuServer from '@/api/system/menuServer.js'
|
||||||
import venuesServer from '@/api/ball/venues_server.js'
|
import venuesServer from '@/api/ball/venues_server.js'
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
@@ -257,7 +257,7 @@ export default {
|
|||||||
async showAddWarp() {
|
async showAddWarp() {
|
||||||
this.$refs.editModal.addShow({ 'venue_type': 'indoor', 'surface_type': 'hard', 'court_count': '1', 'status': 'active', 'create_time': 'CURRENT_TIMESTAMP', 'updated_at': 'CURRENT_TIMESTAMP', }, async (newRow) => {
|
this.$refs.editModal.addShow({ 'venue_type': 'indoor', 'surface_type': 'hard', 'court_count': '1', 'status': 'active', 'create_time': 'CURRENT_TIMESTAMP', 'updated_at': 'CURRENT_TIMESTAMP', }, async (newRow) => {
|
||||||
let res = await venuesServer.add(newRow)
|
let res = await venuesServer.add(newRow)
|
||||||
rootVue.$Message.success('新增成功!')
|
this.$Message.success('新增成功!')
|
||||||
this.init()
|
this.init()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -266,7 +266,7 @@ export default {
|
|||||||
let valid = await this.$refs['editModal'].$refs['From'].validate()
|
let valid = await this.$refs['editModal'].$refs['From'].validate()
|
||||||
if (valid) {
|
if (valid) {
|
||||||
let res = await venuesServer.edit(newRow)
|
let res = await venuesServer.edit(newRow)
|
||||||
rootVue.$Message.success('修改成功!')
|
this.$Message.success('修改成功!')
|
||||||
this.init()
|
this.init()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -274,7 +274,7 @@ export default {
|
|||||||
async delConfirm(row) {
|
async delConfirm(row) {
|
||||||
window.framework.uiTool.delConfirm(async () => {
|
window.framework.uiTool.delConfirm(async () => {
|
||||||
await venuesServer.del(row)
|
await venuesServer.del(row)
|
||||||
rootVue.$Message.success('删除成功!')
|
this.$Message.success('删除成功!')
|
||||||
this.init()
|
this.init()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
<script>
|
<script>
|
||||||
|
|
||||||
|
|
||||||
import menuServer from '@/api/system_high/menuServer.js'
|
import menuServer from '@/api/system/menuServer.js'
|
||||||
import wch_usersServer from '@/api/ball/wch_users_server.js'
|
import wch_usersServer from '@/api/ball/wch_users_server.js'
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
@@ -318,7 +318,7 @@ export default {
|
|||||||
async showAddWarp() {
|
async showAddWarp() {
|
||||||
this.$refs.editModal.addShow({ 'is_subscribed': '0', 'last_login_time': 'CURRENT_TIMESTAMP', 'create_time': 'CURRENT_TIMESTAMP', 'updated_at': 'CURRENT_TIMESTAMP', }, async (newRow) => {
|
this.$refs.editModal.addShow({ 'is_subscribed': '0', 'last_login_time': 'CURRENT_TIMESTAMP', 'create_time': 'CURRENT_TIMESTAMP', 'updated_at': 'CURRENT_TIMESTAMP', }, async (newRow) => {
|
||||||
let res = await wch_usersServer.add(newRow)
|
let res = await wch_usersServer.add(newRow)
|
||||||
rootVue.$Message.success('新增成功!')
|
this.$Message.success('新增成功!')
|
||||||
this.init()
|
this.init()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -327,7 +327,7 @@ export default {
|
|||||||
let valid = await this.$refs['editModal'].$refs['From'].validate()
|
let valid = await this.$refs['editModal'].$refs['From'].validate()
|
||||||
if (valid) {
|
if (valid) {
|
||||||
let res = await wch_usersServer.edit(newRow)
|
let res = await wch_usersServer.edit(newRow)
|
||||||
rootVue.$Message.success('修改成功!')
|
this.$Message.success('修改成功!')
|
||||||
this.init()
|
this.init()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -335,7 +335,7 @@ export default {
|
|||||||
async delConfirm(row) {
|
async delConfirm(row) {
|
||||||
window.framework.uiTool.delConfirm(async () => {
|
window.framework.uiTool.delConfirm(async () => {
|
||||||
await wch_usersServer.del(row)
|
await wch_usersServer.del(row)
|
||||||
rootVue.$Message.success('删除成功!')
|
this.$Message.success('删除成功!')
|
||||||
this.init()
|
this.init()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -349,7 +349,8 @@ export default {
|
|||||||
this.query(1);
|
this.query(1);
|
||||||
},
|
},
|
||||||
async exportCsv(row) {
|
async exportCsv(row) {
|
||||||
await wch_usersServer.exportCsv(row)
|
let res = await wch_usersServer.exportCsv(row)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ export default {
|
|||||||
},
|
},
|
||||||
exportCsv() {
|
exportCsv() {
|
||||||
msg_notificationsServer.exportCsv(this.gridOption.param).then(res => {
|
msg_notificationsServer.exportCsv(this.gridOption.param).then(res => {
|
||||||
window.framework.funTool.downloadFile(res, '消息通知.csv');
|
window.framework.tools.downloadFile(res, '消息通知.csv');
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
resetQuery() {
|
resetQuery() {
|
||||||
|
|||||||
@@ -229,7 +229,7 @@ export default {
|
|||||||
},
|
},
|
||||||
exportCsv() {
|
exportCsv() {
|
||||||
ntr_questionsServer.exportCsv(this.gridOption.param).then(res => {
|
ntr_questionsServer.exportCsv(this.gridOption.param).then(res => {
|
||||||
window.framework.funTool.downloadFile(res, '题库管理.csv');
|
window.framework.tools.downloadFile(res, '题库管理.csv');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -246,9 +246,7 @@ export default {
|
|||||||
this.query(1);
|
this.query(1);
|
||||||
},
|
},
|
||||||
exportCsv() {
|
exportCsv() {
|
||||||
ntr_recordsServer.exportCsv(this.gridOption.param).then(res => {
|
ntr_recordsServer.exportCsv(this.gridOption.param)
|
||||||
window.framework.funTool.downloadFile(res, '测试记录.csv');
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
<script>
|
<script>
|
||||||
|
|
||||||
|
|
||||||
import menuServer from '@/api/system_high/menuServer.js'
|
import menuServer from '@/api/system/menuServer.js'
|
||||||
import walletTransactionsServer from '@/api/ball/wallet_transactions_server.js'
|
import walletTransactionsServer from '@/api/ball/wallet_transactions_server.js'
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,6 @@ export default {
|
|||||||
{ key: 'blocked_user_id', value: '被屏蔽用户ID' },
|
{ key: 'blocked_user_id', value: '被屏蔽用户ID' },
|
||||||
{ key: 'nickname', value: '用户昵称' }
|
{ key: 'nickname', value: '用户昵称' }
|
||||||
],
|
],
|
||||||
seachTypePlaceholder: '请选择搜索类型',
|
|
||||||
gridOption: {
|
gridOption: {
|
||||||
param: {
|
param: {
|
||||||
seachOption: {
|
seachOption: {
|
||||||
@@ -93,9 +92,28 @@ export default {
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
editColumns: [
|
editColumns: [
|
||||||
{ title: '用户ID', key: 'user_id', type: 'number', required: true },
|
{
|
||||||
{ title: '被屏蔽用户ID', key: 'blocked_user_id', type: 'number', required: true },
|
title: '用户ID',
|
||||||
{ title: '屏蔽时间', key: 'block_time', type: 'datetime' }
|
key: 'user_id',
|
||||||
|
data_type: 'number',
|
||||||
|
com: 'InputNumber',
|
||||||
|
required: true,
|
||||||
|
is_show_edit: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '被屏蔽用户ID',
|
||||||
|
key: 'blocked_user_id',
|
||||||
|
data_type: 'number',
|
||||||
|
com: 'InputNumber',
|
||||||
|
required: true,
|
||||||
|
is_show_edit: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '屏蔽时间',
|
||||||
|
key: 'block_time',
|
||||||
|
com: 'DatePicker',
|
||||||
|
is_show_edit: 1
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -119,7 +137,7 @@ export default {
|
|||||||
delConfirm(row) {
|
delConfirm(row) {
|
||||||
window.framework.uiTool.delConfirm(async () => {
|
window.framework.uiTool.delConfirm(async () => {
|
||||||
await recommend_blocksServer.del(row)
|
await recommend_blocksServer.del(row)
|
||||||
rootVue.$Message.success('删除成功!')
|
this.$Message.success('删除成功!')
|
||||||
this.query(1)
|
this.query(1)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
return uiTool.getBtn(h, btns)
|
return window.framework.uiTool.getBtn(h, btns)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -131,27 +131,27 @@ export default {
|
|||||||
'follow_time': null
|
'follow_time': null
|
||||||
}, async (newRow) => {
|
}, async (newRow) => {
|
||||||
let res = await user_followsServer.add(newRow)
|
let res = await user_followsServer.add(newRow)
|
||||||
rootVue.$Message.success('新增成功!')
|
this.$Message.success('新增成功!')
|
||||||
this.query(1)
|
this.query(1)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
showEditWarp(row) {
|
showEditWarp(row) {
|
||||||
this.$refs.editModal.editShow(row, async (newRow) => {
|
this.$refs.editModal.editShow(row, async (newRow) => {
|
||||||
let res = await user_followsServer.edit(newRow)
|
let res = await user_followsServer.edit(newRow)
|
||||||
rootVue.$Message.success('修改成功!')
|
this.$Message.success('修改成功!')
|
||||||
this.query(1)
|
this.query(1)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
delConfirm(row) {
|
delConfirm(row) {
|
||||||
uiTool.delConfirm(async () => {
|
window.framework.uiTool.delConfirm(async () => {
|
||||||
await user_followsServer.del(row)
|
await user_followsServer.del(row)
|
||||||
rootVue.$Message.success('删除成功!')
|
this.$Message.success('删除成功!')
|
||||||
this.query(1)
|
this.query(1)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
exportCsv() {
|
exportCsv() {
|
||||||
user_followsServer.exportCsv(this.gridOption.param).then(res => {
|
user_followsServer.exportCsv(this.gridOption.param).then(res => {
|
||||||
window.framework. funTool.downloadFile(res, '用户关注关系.csv');
|
window.framework.funTool.downloadFile(res, '用户关注关系.csv');
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
resetQuery() {
|
resetQuery() {
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ export default {
|
|||||||
delConfirm(row) {
|
delConfirm(row) {
|
||||||
window.framework.uiTool.delConfirm(async () => {
|
window.framework.uiTool.delConfirm(async () => {
|
||||||
await user_trackingServer.del(row)
|
await user_trackingServer.del(row)
|
||||||
rootVue.$Message.success('删除成功!')
|
this.$Message.success('删除成功!')
|
||||||
this.query(1)
|
this.query(1)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -21,6 +21,51 @@
|
|||||||
@changePage="query"></tables>
|
@changePage="query"></tables>
|
||||||
</div>
|
</div>
|
||||||
<editModal ref="editModal" :columns="editColumns" :rules="gridOption.rules"> </editModal>
|
<editModal ref="editModal" :columns="editColumns" :rules="gridOption.rules"> </editModal>
|
||||||
|
|
||||||
|
<FloatPanel ref="floatPanel" title="城市详情" position="right">
|
||||||
|
<div v-if="currentRow" class="detail-content">
|
||||||
|
<div class="detail-item">
|
||||||
|
<label>ID:</label>
|
||||||
|
<span>{{ currentRow.id }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="detail-item">
|
||||||
|
<label>城市名称(中文):</label>
|
||||||
|
<span>{{ currentRow.cn_city }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="detail-item">
|
||||||
|
<label>城市代码:</label>
|
||||||
|
<span>{{ currentRow.city_code }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="detail-item">
|
||||||
|
<label>省份(中文):</label>
|
||||||
|
<span>{{ currentRow.cn_state || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="detail-item">
|
||||||
|
<label>国家(中文):</label>
|
||||||
|
<span>{{ currentRow.cn_country || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="detail-item">
|
||||||
|
<label>城市名称(英文):</label>
|
||||||
|
<span>{{ currentRow.city || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="detail-item">
|
||||||
|
<label>省份(英文):</label>
|
||||||
|
<span>{{ currentRow.state || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="detail-item">
|
||||||
|
<label>国家(英文):</label>
|
||||||
|
<span>{{ currentRow.country || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="detail-item">
|
||||||
|
<label>省份代码:</label>
|
||||||
|
<span>{{ currentRow.state_code || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="detail-item">
|
||||||
|
<label>国家代码:</label>
|
||||||
|
<span>{{ currentRow.country_code || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</FloatPanel>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
@@ -36,6 +81,7 @@ export default {
|
|||||||
rules["cn_country"] = [{ required: false, message: '请填写国家' }];
|
rules["cn_country"] = [{ required: false, message: '请填写国家' }];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
currentRow: null,
|
||||||
seachTypes: [
|
seachTypes: [
|
||||||
{ key: 'cn_city', value: '城市名称' },
|
{ key: 'cn_city', value: '城市名称' },
|
||||||
{ key: 'city_code', value: '城市代码' },
|
{ key: 'city_code', value: '城市代码' },
|
||||||
@@ -69,10 +115,17 @@ export default {
|
|||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
key: 'action',
|
key: 'action',
|
||||||
width: 200,
|
width: 250,
|
||||||
type: 'template',
|
type: 'template',
|
||||||
render: (h, params) => {
|
render: (h, params) => {
|
||||||
let btns = [
|
let btns = [
|
||||||
|
{
|
||||||
|
title: '详情',
|
||||||
|
type: 'info',
|
||||||
|
click: () => {
|
||||||
|
this.showDetail(params.row)
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '编辑',
|
title: '编辑',
|
||||||
type: 'primary',
|
type: 'primary',
|
||||||
@@ -138,7 +191,43 @@ export default {
|
|||||||
wch_citiesServer.exportCsv(this.gridOption.param).then(res => {
|
wch_citiesServer.exportCsv(this.gridOption.param).then(res => {
|
||||||
tools.downloadFile(res, '城市管理.csv');
|
tools.downloadFile(res, '城市管理.csv');
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
showDetail(row) {
|
||||||
|
this.currentRow = row
|
||||||
|
this.$refs.floatPanel.show()
|
||||||
|
},
|
||||||
|
hideDetail() {
|
||||||
|
this.$refs.floatPanel.hide()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.detail-content {
|
||||||
|
padding: 10px 0;
|
||||||
|
|
||||||
|
.detail-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 12px 0;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
min-width: 120px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #515a6e;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
flex: 1;
|
||||||
|
color: #17233d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
<script>
|
<script>
|
||||||
|
|
||||||
|
|
||||||
import menuServer from '@/api/system_high/menuServer.js'
|
import menuServer from '@/api/system/menuServer.js'
|
||||||
import wch_professionsServer from '@/api/system/wch_professions_server.js'
|
import wch_professionsServer from '@/api/system/wch_professions_server.js'
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ module.exports = {
|
|||||||
output: {
|
output: {
|
||||||
path: path.resolve(__dirname, 'dist'),
|
path: path.resolve(__dirname, 'dist'),
|
||||||
filename: 'app.js',
|
filename: 'app.js',
|
||||||
clean: true
|
clean: true,
|
||||||
|
publicPath: '/'
|
||||||
},
|
},
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
@@ -24,6 +25,10 @@ module.exports = {
|
|||||||
test: /\.css$/,
|
test: /\.css$/,
|
||||||
use: ['vue-style-loader', 'css-loader']
|
use: ['vue-style-loader', 'css-loader']
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
test: /\.less$/,
|
||||||
|
use: ['vue-style-loader', 'css-loader', 'less-loader']
|
||||||
|
},
|
||||||
{
|
{
|
||||||
test: /\.(png|jpe?g|gif|svg|woff2?|eot|ttf|otf)$/,
|
test: /\.(png|jpe?g|gif|svg|woff2?|eot|ttf|otf)$/,
|
||||||
type: 'asset/resource'
|
type: 'asset/resource'
|
||||||
@@ -45,7 +50,7 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
devServer: {
|
devServer: {
|
||||||
hot: true,
|
hot: true, // 启用热更新
|
||||||
open: true,
|
open: true,
|
||||||
port: 8080,
|
port: 8080,
|
||||||
historyApiFallback: true
|
historyApiFallback: true
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import http from "@/utils/http";
|
import http from "@/utils/http";
|
||||||
class FileServe {
|
class FileServe {
|
||||||
async upload_oos_img(row) {
|
async upload_oos_img(row) {
|
||||||
let res = await window.framework.http.postFormData("/sys_file/upload_oos_img", row);
|
let res = await http.postFormData("/sys_file/upload_oos_img", row);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
async upload_Img(row) {
|
async upload_Img(row) {
|
||||||
let res = await window.framework.http.postFormData("/file/upload_Img", row);
|
let res = await http.postFormData("/file/upload_Img", row);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
30
src/api/system/formFieldServer.js
Normal file
30
src/api/system/formFieldServer.js
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import http from "@/utils/http";
|
||||||
|
class FormFieldServer {
|
||||||
|
async all(param) {
|
||||||
|
let res = await http.get("/sys_form_field/all", param);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
async page(row) {
|
||||||
|
let res = await http.post("/sys_form_field/page", row);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
async add(row) {
|
||||||
|
let res = await http.post("/sys_form_field/add", row);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
async edit(row) {
|
||||||
|
let res = await http.post("/sys_form_field/edit", row);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
async del(row) {
|
||||||
|
let res = await http.post("/sys_form_field/del", row);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const formFieldServer = new FormFieldServer();
|
||||||
|
export default formFieldServer;
|
||||||
35
src/api/system/formServer.js
Normal file
35
src/api/system/formServer.js
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import http from "@/utils/http";
|
||||||
|
class FormServer {
|
||||||
|
async all(param) {
|
||||||
|
let res = await http.get("/sys_form/all", param);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
async page(row) {
|
||||||
|
let res = await http.post("/sys_form/page", row);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
async generate(row) {
|
||||||
|
let res = await http.post("/sys_form/generate", row);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
async add(row) {
|
||||||
|
let res = await http.post("/sys_form/add", row);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
async edit(row) {
|
||||||
|
let res = await http.post("/sys_form/edit", row);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
async del(row) {
|
||||||
|
let res = await http.post("/sys_form/del", row);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const formServer = new FormServer();
|
||||||
|
export default formServer;
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
import http from '@/utils/http';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 热门城市二维码配置相关API
|
|
||||||
*/
|
|
||||||
|
|
||||||
// 获取配置列表
|
|
||||||
const getHotCityQrConfigList = (params) => {
|
|
||||||
return window.framework.http.get('/wch_hot_city_qr_config/list', { params });
|
|
||||||
};
|
|
||||||
|
|
||||||
// 获取所有配置
|
|
||||||
const getAllHotCityQrConfig = () => {
|
|
||||||
return window.framework.http.get('/wch_hot_city_qr_config/all');
|
|
||||||
};
|
|
||||||
|
|
||||||
// 获取配置详情
|
|
||||||
const getHotCityQrConfigDetail = (id) => {
|
|
||||||
return window.framework.http.get(`/wch_hot_city_qr_config/detail/${id}`);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 创建配置
|
|
||||||
const createHotCityQrConfig = (data) => {
|
|
||||||
return window.framework.http.post('/wch_hot_city_qr_config/create', data);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 更新配置
|
|
||||||
const updateHotCityQrConfig = (id, data) => {
|
|
||||||
return window.framework.http.post(`/wch_hot_city_qr_config/update/${id}`, data);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 删除配置
|
|
||||||
const deleteHotCityQrConfig = (id) => {
|
|
||||||
return window.framework.http.post(`/wch_hot_city_qr_config/delete/${id}`);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 批量删除配置
|
|
||||||
const batchDeleteHotCityQrConfig = (ids) => {
|
|
||||||
return window.framework.http.post('/wch_hot_city_qr_config/batch_delete', { ids });
|
|
||||||
};
|
|
||||||
|
|
||||||
export default {
|
|
||||||
getHotCityQrConfigList,
|
|
||||||
getAllHotCityQrConfig,
|
|
||||||
getHotCityQrConfigDetail,
|
|
||||||
createHotCityQrConfig,
|
|
||||||
updateHotCityQrConfig,
|
|
||||||
deleteHotCityQrConfig,
|
|
||||||
batchDeleteHotCityQrConfig
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -1,17 +1,23 @@
|
|||||||
// 系统 API 统一导出
|
// 系统 API 统一导出
|
||||||
|
|
||||||
export { default as fileServe } from './fileServe'
|
export { default as fileServe } from './fileServe'
|
||||||
export { default as hotCityQrConfigServer } from './hot_city_qr_config_server'
|
|
||||||
export { default as plaAccountServer } from './pla_account_server'
|
export { default as plaAccountServer } from './pla_account_server'
|
||||||
export { default as rolePermissionServer } from './rolePermissionServer'
|
export { default as rolePermissionServer } from './rolePermissionServer'
|
||||||
export { default as roleServer } from './roleServer'
|
export { default as roleServer } from './roleServer'
|
||||||
export { default as shpProfitServer } from './shpProfitServer'
|
|
||||||
export { default as specificationServer } from './specificationServer'
|
|
||||||
export { default as sysAddressServer } from './sysAddressServer'
|
export { default as sysAddressServer } from './sysAddressServer'
|
||||||
export { default as sysModuleServer } from './sysModuleServer'
|
export { default as sysModuleServer } from './sysModuleServer'
|
||||||
export { default as sysLogServe } from './sys_log_serve'
|
export { default as sysLogServe } from './sys_log_serve'
|
||||||
export { default as systemTypeServer } from './systemType_server'
|
export { default as systemTypeServer } from './systemType_server'
|
||||||
export { default as tableServer } from './tableServer'
|
export { default as tableServer } from './tableServer'
|
||||||
export { default as userServer } from './userServer'
|
export { default as userServer } from './userServer'
|
||||||
export { default as wchProfessionsServer } from './wch_professions_server'
|
|
||||||
|
export { default as formFieldServer } from './formFieldServer'
|
||||||
|
export { default as formServer } from './formServer'
|
||||||
|
export { default as menuServer } from './menuServer'
|
||||||
|
export { default as modelFieldServer } from './modelFieldServer'
|
||||||
|
export { default as modelServer } from './modelServer'
|
||||||
|
export { default as paramSetupServer } from './paramSetupServer'
|
||||||
|
export { default as sysControlTypeServer } from './sysControlTypeServer'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
49
src/api/system/menuServer.js
Normal file
49
src/api/system/menuServer.js
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
import http from "@/utils/http";
|
||||||
|
|
||||||
|
class MenuServer {
|
||||||
|
async list(row) {
|
||||||
|
let res = await http.get("/sys_menu/index", row);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
async generate(row) {
|
||||||
|
let res = await http.post("/sys_menu/generate", row);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
async add(row) {
|
||||||
|
let res = await http.post("/sys_menu/add", row);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
async edit(row) {
|
||||||
|
let res = await http.post("/sys_menu/edit", row);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
async del(row) {
|
||||||
|
let res = await http.post("/sys_menu/del", row);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
async generate(row) {
|
||||||
|
let res = await http.post("/form/generate", row);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
async generateModel(row) {
|
||||||
|
let res = await http.post("/model/generate", row);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async modelAll(row) {
|
||||||
|
let res = await http.post("/model/all", row);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
async modelInterface(row) {
|
||||||
|
let res = await http.post("/model/interface", row);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const menuServer = new MenuServer();
|
||||||
|
export default menuServer;
|
||||||
@@ -1,29 +1,29 @@
|
|||||||
import http from "@/utils/http";
|
import http from "@/utils/http";
|
||||||
class ModelFieldServer {
|
class ModelFieldServer {
|
||||||
async all(row) {
|
async all(row) {
|
||||||
let res = await window.framework.http.get("/sys_model_field/all", row);
|
let res = await http.get("/sys_model_field/all", row);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
async allByKey(row) {
|
async allByKey(row) {
|
||||||
let res = await window.framework.http.get("/sys_model_field/allByKey", row, {
|
let res = await http.get("/sys_model_field/allByKey", row, {
|
||||||
hideLoad: true
|
hideLoad: true
|
||||||
});
|
});
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
async add(row) {
|
async add(row) {
|
||||||
let res = await window.framework.http.post("/sys_model_field/add", row);
|
let res = await http.post("/sys_model_field/add", row);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
async edit(row) {
|
async edit(row) {
|
||||||
let res = await window.framework.http.post("/sys_model_field/edit", row);
|
let res = await http.post("/sys_model_field/edit", row);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
async del(row) {
|
async del(row) {
|
||||||
let res = await window.framework.http.post("/sys_model_field/del", row);
|
let res = await http.post("/sys_model_field/del", row);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
40
src/api/system/modelServer.js
Normal file
40
src/api/system/modelServer.js
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import http from "@/utils/http";
|
||||||
|
class ModelServer {
|
||||||
|
async interface(row) {
|
||||||
|
let res = await http.post("/sys_model/interface", row);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
async all() {
|
||||||
|
let res = await http.get("/sys_model/all", {});
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
async detail(row) {
|
||||||
|
let res = await http.get("/sys_model/detail", row);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
async regenerate(row) {
|
||||||
|
let res = await http.post("/sys_model/regenerate", row);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
async add(row) {
|
||||||
|
let res = await http.post("/sys_model/add", row);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
async edit(row) {
|
||||||
|
let res = await http.post("/sys_model/edit", row);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
async del(row) {
|
||||||
|
let res = await http.post("/sys_model/del", row);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const modelServer = new ModelServer();
|
||||||
|
export default modelServer;
|
||||||
29
src/api/system/paramSetupServer.js
Normal file
29
src/api/system/paramSetupServer.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import http from "@/utils/http";
|
||||||
|
class ParamSetupServer {
|
||||||
|
async getAll() {
|
||||||
|
return await http.get("/sys_parameter/index", {});
|
||||||
|
}
|
||||||
|
|
||||||
|
async getOne(key) {
|
||||||
|
return await http.get("/sys_parameter/key", { key });
|
||||||
|
}
|
||||||
|
|
||||||
|
async add(row) {
|
||||||
|
return await http.post("/sys_parameter/add", row);
|
||||||
|
}
|
||||||
|
|
||||||
|
async edit(row) {
|
||||||
|
return await http.post("/sys_parameter/edit", row);
|
||||||
|
}
|
||||||
|
|
||||||
|
async setSysConfig(row) {
|
||||||
|
return await http.post("/sys_parameter/setSysConfig", row);
|
||||||
|
}
|
||||||
|
|
||||||
|
async del(row) {
|
||||||
|
return await http.post("/sys_parameter/del", row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const paramSetupServer = new ParamSetupServer();
|
||||||
|
export default paramSetupServer;
|
||||||
@@ -3,36 +3,36 @@ import http from '@/utils/http'
|
|||||||
export default {
|
export default {
|
||||||
// 获取所有平台账户
|
// 获取所有平台账户
|
||||||
all(param) {
|
all(param) {
|
||||||
return window.framework.http.get('/pla_account/all', param)
|
return http.get('/pla_account/all', param)
|
||||||
},
|
},
|
||||||
|
|
||||||
// 获取平台账户详情
|
// 获取平台账户详情
|
||||||
detail(param) {
|
detail(param) {
|
||||||
return window.framework.http.get('/pla_account/detail', param)
|
return http.get('/pla_account/detail', param)
|
||||||
},
|
},
|
||||||
|
|
||||||
// 分页查询平台账户
|
// 分页查询平台账户
|
||||||
page(param) {
|
page(param) {
|
||||||
return window.framework.http.post('/pla_account/page', param)
|
return http.post('/pla_account/page', param)
|
||||||
},
|
},
|
||||||
|
|
||||||
// 新增平台账户
|
// 新增平台账户
|
||||||
add(param) {
|
add(param) {
|
||||||
return window.framework.http.post('/pla_account/add', param)
|
return http.post('/pla_account/add', param)
|
||||||
},
|
},
|
||||||
|
|
||||||
// 编辑平台账户
|
// 编辑平台账户
|
||||||
edit(param) {
|
edit(param) {
|
||||||
return window.framework.http.post('/pla_account/edit', param)
|
return http.post('/pla_account/edit', param)
|
||||||
},
|
},
|
||||||
|
|
||||||
// 删除平台账户
|
// 删除平台账户
|
||||||
del(param) {
|
del(param) {
|
||||||
return window.framework.http.post('/pla_account/del', param)
|
return http.post('/pla_account/del', param)
|
||||||
},
|
},
|
||||||
|
|
||||||
// 导出平台账户数据
|
// 导出平台账户数据
|
||||||
exportCsv(param) {
|
exportCsv(param) {
|
||||||
return window.framework.http.post('/pla_account/export', param)
|
return http.post('/pla_account/export', param)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,27 +1,27 @@
|
|||||||
import http from '@/utils/http'
|
import http from '@/utils/http'
|
||||||
class RolePermissionServer {
|
class RolePermissionServer {
|
||||||
async getRoles(callback) {
|
async getRoles(callback) {
|
||||||
let res = await window.framework.http.get('/SysRolePermission/Query', {})
|
let res = await http.get('/SysRolePermission/Query', {})
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
async getRole(row) {
|
async getRole(row) {
|
||||||
let res = await window.framework.http.get('/SysRolePermission/QueryByRoleId', row)
|
let res = await http.get('/SysRolePermission/QueryByRoleId', row)
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
async add(row) {
|
async add(row) {
|
||||||
let res = await window.framework.http.post('/SysRolePermission/add', row)
|
let res = await http.post('/SysRolePermission/add', row)
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
async edit(row) {
|
async edit(row) {
|
||||||
let res = await window.framework.http.post('/SysRolePermission/edit', row)
|
let res = await http.post('/SysRolePermission/edit', row)
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
async del(row) {
|
async del(row) {
|
||||||
let res = await window.framework.http.post('/SysRolePermission/del', row)
|
let res = await http.post('/SysRolePermission/del', row)
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,23 @@
|
|||||||
import http from "@/utils/http";
|
import http from "@/utils/http";
|
||||||
class RoleServer {
|
class RoleServer {
|
||||||
async list() {
|
async list() {
|
||||||
let res = await window.framework.http.get("/sys_role/index", {});
|
let res = await http.get("/sys_role/index", {});
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
async add(row) {
|
async add(row) {
|
||||||
let res = await window.framework.http.post("/sys_role/add", row);
|
let res = await http.post("/sys_role/add", row);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
async edit(row) {
|
async edit(row) {
|
||||||
let res = await window.framework.http.post("/sys_role/edit", row);
|
let res = await http.post("/sys_role/edit", row);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
async del(row) {
|
async del(row) {
|
||||||
let res = await window.framework.http.post("/sys_role/del", row);
|
let res = await http.post("/sys_role/del", row);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
import http from '@/utils/http'
|
|
||||||
class ShpProfitServer {
|
|
||||||
async report(param) {
|
|
||||||
let res = await window.framework.http.post('/shpProfit/report', param)
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
async list(param) {
|
|
||||||
let res = await window.framework.http.post('/shpProfit/list', param)
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const shpProfitServer = new ShpProfitServer()
|
|
||||||
export default shpProfitServer
|
|
||||||
@@ -1,22 +1,22 @@
|
|||||||
import http from '@/utils/http'
|
import http from '@/utils/http'
|
||||||
class SpecificationServer {
|
class SpecificationServer {
|
||||||
async list() {
|
async list() {
|
||||||
let res = await window.framework.http.post('/specification/list', {})
|
let res = await http.post('/specification/list', {})
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
async add(row) {
|
async add(row) {
|
||||||
let res = await window.framework.http.post('/specification/add', row)
|
let res = await http.post('/specification/add', row)
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
async edit(row) {
|
async edit(row) {
|
||||||
let res = await window.framework.http.post('/specification/edit', row)
|
let res = await http.post('/specification/edit', row)
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
async del(row) {
|
async del(row) {
|
||||||
let res = await window.framework.http.post('/specification/del', row)
|
let res = await http.post('/specification/del', row)
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import http from "@/utils/http";
|
import http from "@/utils/http";
|
||||||
class SysAddress {
|
class SysAddress {
|
||||||
async index(param) {
|
async index(param) {
|
||||||
let res = await window.framework.http.get("/sys_address/index", param);
|
let res = await http.get("/sys_address/index", param);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
29
src/api/system/sysControlTypeServer.js
Normal file
29
src/api/system/sysControlTypeServer.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import http from "@/utils/http";
|
||||||
|
class SysControlTypeServer {
|
||||||
|
async all(param) {
|
||||||
|
let res = await http.get("/sys_control_type/all", param);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
async page(row) {
|
||||||
|
let res = await http.post("/sys_control_type/page", row);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
async add(param) {
|
||||||
|
let res = await http.post("/sys_control_type/add", param);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
async edit(param) {
|
||||||
|
let res = await http.post("/sys_control_type/edit", param);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
async del(param) {
|
||||||
|
let res = await http.post("/sys_control_type/del", param);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const sysControlTypeServer = new SysControlTypeServer();
|
||||||
|
export default sysControlTypeServer;
|
||||||
@@ -1,27 +1,27 @@
|
|||||||
import http from "@/utils/http";
|
import http from "@/utils/http";
|
||||||
class SysModuleServer {
|
class SysModuleServer {
|
||||||
async all() {
|
async all() {
|
||||||
let res = await window.framework.http.get("/sys_menu/all", {});
|
let res = await http.get("/sys_menu/all", {});
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
async list(row) {
|
async list(row) {
|
||||||
let res = await window.framework.http.get("/sys_menu/all", row);
|
let res = await http.get("/sys_menu/all", row);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
async add(row) {
|
async add(row) {
|
||||||
let res = await window.framework.http.post("/sys_menu/add", row);
|
let res = await http.post("/sys_menu/add", row);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
async edit(row) {
|
async edit(row) {
|
||||||
let res = await window.framework.http.post("/sys_menu/edit", row);
|
let res = await http.post("/sys_menu/edit", row);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
async del(row) {
|
async del(row) {
|
||||||
let res = await window.framework.http.post("/sys_menu/del", row);
|
let res = await http.post("/sys_menu/del", row);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,27 @@
|
|||||||
import http from "@/utils/http";
|
import http from "@/utils/http";
|
||||||
class SysLogServe {
|
class SysLogServe {
|
||||||
async all(param) {
|
async all(param) {
|
||||||
let res = await window.framework.http.get("/sys_log/all", param);
|
let res = await http.get("/sys_log/all", param);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
async detail(param) {
|
async detail(param) {
|
||||||
let res = await window.framework.http.get("/sys_log/detail", param);
|
let res = await http.get("/sys_log/detail", param);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
async delete(param) {
|
async delete(param) {
|
||||||
let res = await window.framework.http.get("/sys_log/delete", param);
|
let res = await http.get("/sys_log/delete", param);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
async delete_all(param) {
|
async delete_all(param) {
|
||||||
let res = await window.framework.http.get("/sys_log/delete_all", param);
|
let res = await http.get("/sys_log/delete_all", param);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
async operates(param) {
|
async operates(param) {
|
||||||
let res = await window.framework.http.get("/sys_log/operates", param);
|
let res = await http.get("/sys_log/operates", param);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import http from '@/utils/http';
|
import http from '@/utils/http';
|
||||||
class systemTypeClServer {
|
class systemTypeClServer {
|
||||||
async all(param) {
|
async all(param) {
|
||||||
let res= await window.framework.http.get('/sys_project_type/all', param);
|
let res= await http.get('/sys_project_type/all', param);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async page(row) {
|
async page(row) {
|
||||||
let res= await window.framework.http.post('/sys_project_type/page', row);
|
let res= await http.post('/sys_project_type/page', row);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -18,17 +18,17 @@ class systemTypeClServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async add(row) {
|
async add(row) {
|
||||||
let res= await window.framework.http.post('/sys_project_type/add', row);
|
let res= await http.post('/sys_project_type/add', row);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
async edit(row) {
|
async edit(row) {
|
||||||
let res= await window.framework.http.post('/sys_project_type/edit', row);
|
let res= await http.post('/sys_project_type/edit', row);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
async del(row) {
|
async del(row) {
|
||||||
let res= await window.framework.http.post('/sys_project_type/del', row);
|
let res= await http.post('/sys_project_type/del', row);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,29 +1,29 @@
|
|||||||
import http from '@/utils/http'
|
import http from '@/utils/http'
|
||||||
class TableServer {
|
class TableServer {
|
||||||
async getAll(callback) {
|
async getAll(callback) {
|
||||||
return await window.framework.http.get('/table/index', {})
|
return await http.get('/table/index', {})
|
||||||
}
|
}
|
||||||
|
|
||||||
async add(row, callback) {
|
async add(row, callback) {
|
||||||
return await window.framework.http.post('/table/add', row)
|
return await http.post('/table/add', row)
|
||||||
}
|
}
|
||||||
|
|
||||||
async edit(row, callback) {
|
async edit(row, callback) {
|
||||||
return await window.framework.http.post('/table/edit', row, function(res) {
|
return await http.post('/table/edit', row, function(res) {
|
||||||
callback && callback(res)
|
callback && callback(res)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async del(row, callback) {
|
async del(row, callback) {
|
||||||
return await window.framework.http.post('/table/del', row)
|
return await http.post('/table/del', row)
|
||||||
}
|
}
|
||||||
|
|
||||||
async autoApi(id) {
|
async autoApi(id) {
|
||||||
return await window.framework.http.get('/template/api', { id: id })
|
return await http.get('/template/api', { id: id })
|
||||||
}
|
}
|
||||||
|
|
||||||
async autoDb(id) {
|
async autoDb(id) {
|
||||||
return await window.framework.http.get('/template/autoDb', { id: id })
|
return await http.get('/template/autoDb', { id: id })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import http from "@/utils/http";
|
import http from "@/utils/http";
|
||||||
class UserServer {
|
class UserServer {
|
||||||
async login(row) {
|
async login(row) {
|
||||||
let res = await window.framework.http.post("/sys_user/login", row);
|
let res = await http.post("/sys_user/login", row);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
async all() {
|
async all() {
|
||||||
let res = await window.framework.http.get("/sys_user/index", {});
|
let res = await http.get("/sys_user/index", {});
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16,22 +16,22 @@ class UserServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async authorityMenus() {
|
async authorityMenus() {
|
||||||
let res = await window.framework.http.post("/sys_user/authorityMenus", {});
|
let res = await http.post("/sys_user/authorityMenus", {});
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
async add(row) {
|
async add(row) {
|
||||||
let res = await window.framework.http.post("/sys_user/add", row);
|
let res = await http.post("/sys_user/add", row);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
async edit(row) {
|
async edit(row) {
|
||||||
let res = await window.framework.http.post("/sys_user/edit", row);
|
let res = await http.post("/sys_user/edit", row);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
async del(row) {
|
async del(row) {
|
||||||
let res = await window.framework.http.post("/sys_user/del", row);
|
let res = await http.post("/sys_user/del", row);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
import http from '@/utils/http'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
// 获取职业列表
|
|
||||||
page: (params) => {
|
|
||||||
return window.framework.http.post('/wch_professions/page', params)
|
|
||||||
},
|
|
||||||
|
|
||||||
// 获取所有职业
|
|
||||||
all: (params) => {
|
|
||||||
return window.framework.http.post('/wch_professions/all', params)
|
|
||||||
},
|
|
||||||
|
|
||||||
// 新增职业
|
|
||||||
add: (params) => {
|
|
||||||
return window.framework.http.post('/wch_professions/add', params)
|
|
||||||
},
|
|
||||||
|
|
||||||
// 更新职业
|
|
||||||
edit: (params) => {
|
|
||||||
return window.framework.http.post('/wch_professions/edit', params)
|
|
||||||
},
|
|
||||||
|
|
||||||
// 删除职业
|
|
||||||
del: (params) => {
|
|
||||||
return window.framework.http.post('/wch_professions/del', params)
|
|
||||||
},
|
|
||||||
|
|
||||||
// 导出职业数据
|
|
||||||
exportCsv: (params) => {
|
|
||||||
return window.framework.http.post('/wch_professions/exportCsv', params)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
import http from "@/utils/http";
|
|
||||||
class FormFieldServer {
|
|
||||||
async all(param) {
|
|
||||||
let res = await window.framework.http.get("/sys_form_field/all", param);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
async page(row) {
|
|
||||||
let res = await window.framework.http.post("/sys_form_field/page", row);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
async add(row) {
|
|
||||||
let res = await window.framework.http.post("/sys_form_field/add", row);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
async edit(row) {
|
|
||||||
let res = await window.framework.http.post("/sys_form_field/edit", row);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
async del(row) {
|
|
||||||
let res = await window.framework.http.post("/sys_form_field/del", row);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const formFieldServer = new FormFieldServer();
|
|
||||||
export default formFieldServer;
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
import http from "@/utils/http";
|
|
||||||
class FormServer {
|
|
||||||
async all(param) {
|
|
||||||
let res = await window.framework.http.get("/sys_form/all", param);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
async page(row) {
|
|
||||||
let res = await window.framework.http.post("/sys_form/page", row);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
async generate(row) {
|
|
||||||
let res = await window.framework.http.post("/sys_form/generate", row);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
async add(row) {
|
|
||||||
let res = await window.framework.http.post("/sys_form/add", row);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
async edit(row) {
|
|
||||||
let res = await window.framework.http.post("/sys_form/edit", row);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
async del(row) {
|
|
||||||
let res = await window.framework.http.post("/sys_form/del", row);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const formServer = new FormServer();
|
|
||||||
export default formServer;
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
// 高级系统 API 统一导出
|
|
||||||
|
|
||||||
export { default as formFieldServer } from './formFieldServer'
|
|
||||||
export { default as formServer } from './formServer'
|
|
||||||
export { default as menuServer } from './menuServer'
|
|
||||||
export { default as modelFieldServer } from './modelFieldServer'
|
|
||||||
export { default as modelServer } from './modelServer'
|
|
||||||
export { default as paramSetupServer } from './paramSetupServer'
|
|
||||||
export { default as sysControlTypeServer } from './sysControlTypeServer'
|
|
||||||
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
import http from "@/utils/http";
|
|
||||||
|
|
||||||
class MenuServer {
|
|
||||||
async list(row) {
|
|
||||||
let res = await window.framework.http.get("/sys_menu/index", row);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
async generate(row) {
|
|
||||||
let res = await window.framework.http.post("/sys_menu/generate", row);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
async add(row) {
|
|
||||||
let res = await window.framework.http.post("/sys_menu/add", row);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
async edit(row) {
|
|
||||||
let res = await window.framework.http.post("/sys_menu/edit", row);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
async del(row) {
|
|
||||||
let res = await window.framework.http.post("/sys_menu/del", row);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
async generate(row) {
|
|
||||||
let res = await window.framework.http.post("/form/generate", row);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
async generateModel(row) {
|
|
||||||
let res = await window.framework.http.post("/model/generate", row);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async modelAll(row) {
|
|
||||||
let res = await window.framework.http.post("/model/all", row);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
async modelInterface(row) {
|
|
||||||
let res = await window.framework.http.post("/model/interface", row);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const menuServer = new MenuServer();
|
|
||||||
export default menuServer;
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
import http from "@/utils/http";
|
|
||||||
class ModelServer {
|
|
||||||
async interface(row) {
|
|
||||||
let res = await window.framework.http.post("/sys_model/interface", row);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
async all() {
|
|
||||||
let res = await window.framework.http.get("/sys_model/all", {});
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
async detail(row) {
|
|
||||||
let res = await window.framework.http.get("/sys_model/detail", row);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
async regenerate(row) {
|
|
||||||
let res = await window.framework.http.post("/sys_model/regenerate", row);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
async add(row) {
|
|
||||||
let res = await window.framework.http.post("/sys_model/add", row);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
async edit(row) {
|
|
||||||
let res = await window.framework.http.post("/sys_model/edit", row);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
async del(row) {
|
|
||||||
let res = await window.framework.http.post("/sys_model/del", row);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const modelServer = new ModelServer();
|
|
||||||
export default modelServer;
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
import http from "@/utils/http";
|
|
||||||
class ParamSetupServer {
|
|
||||||
async getAll() {
|
|
||||||
return await window.framework.http.get("/sys_parameter/index", {});
|
|
||||||
}
|
|
||||||
|
|
||||||
async getOne(key) {
|
|
||||||
return await window.framework.http.get("/sys_parameter/key", { key });
|
|
||||||
}
|
|
||||||
|
|
||||||
async add(row) {
|
|
||||||
return await window.framework.http.post("/sys_parameter/add", row);
|
|
||||||
}
|
|
||||||
|
|
||||||
async edit(row) {
|
|
||||||
return await window.framework.http.post("/sys_parameter/edit", row);
|
|
||||||
}
|
|
||||||
|
|
||||||
async setSysConfig(row) {
|
|
||||||
return await window.framework.http.post("/sys_parameter/setSysConfig", row);
|
|
||||||
}
|
|
||||||
|
|
||||||
async del(row) {
|
|
||||||
return await window.framework.http.post("/sys_parameter/del", row);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const paramSetupServer = new ParamSetupServer();
|
|
||||||
export default paramSetupServer;
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
import http from "@/utils/http";
|
|
||||||
class SysControlTypeServer {
|
|
||||||
async all(param) {
|
|
||||||
let res = await window.framework.http.get("/sys_control_type/all", param);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
async page(row) {
|
|
||||||
let res = await window.framework.http.post("/sys_control_type/page", row);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
async add(param) {
|
|
||||||
let res = await window.framework.http.post("/sys_control_type/add", param);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
async edit(param) {
|
|
||||||
let res = await window.framework.http.post("/sys_control_type/edit", param);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
async del(param) {
|
|
||||||
let res = await window.framework.http.post("/sys_control_type/del", param);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const sysControlTypeServer = new SysControlTypeServer();
|
|
||||||
export default sysControlTypeServer;
|
|
||||||
346
src/components/FloatPanel/index.vue
Normal file
346
src/components/FloatPanel/index.vue
Normal file
@@ -0,0 +1,346 @@
|
|||||||
|
<template>
|
||||||
|
<transition name="float-panel">
|
||||||
|
<div v-if="showPanel" class="float-panel-wrapper" @click.self="handleBackdropClick">
|
||||||
|
<div class="float-panel" :class="panelClass" :style="panelStyle">
|
||||||
|
<div class="float-panel-header">
|
||||||
|
<div class="header-left">
|
||||||
|
<Button v-if="showBack" type="text" icon="ios-arrow-back" @click="handleBack">
|
||||||
|
{{ backText }}
|
||||||
|
</Button>
|
||||||
|
<span v-if="title" class="panel-title">{{ title }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="header-right">
|
||||||
|
<slot name="header-right"></slot>
|
||||||
|
<Button v-if="showClose" type="text" icon="ios-close" @click="hide"></Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="float-panel-body">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'FloatPanel',
|
||||||
|
props: {
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
width: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: '100%'
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: '100%'
|
||||||
|
},
|
||||||
|
position: {
|
||||||
|
type: String,
|
||||||
|
default: 'right', // left, right, top, bottom, center
|
||||||
|
validator: (value) => ['left', 'right', 'top', 'bottom', 'center'].includes(value)
|
||||||
|
},
|
||||||
|
showBack: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
showClose: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
backText: {
|
||||||
|
type: String,
|
||||||
|
default: '返回'
|
||||||
|
},
|
||||||
|
closeOnClickBackdrop: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
mask: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
zIndex: {
|
||||||
|
type: Number,
|
||||||
|
default: 1000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
showPanel: false,
|
||||||
|
callback: null,
|
||||||
|
parentElement: null,
|
||||||
|
originalParentPosition: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
panelClass() {
|
||||||
|
return {
|
||||||
|
[`float-panel-${this.position}`]: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
panelStyle() {
|
||||||
|
const style = {
|
||||||
|
zIndex: this.zIndex,
|
||||||
|
width: typeof this.width === 'number' ? `${this.width}px` : this.width,
|
||||||
|
height: typeof this.height === 'number' ? `${this.height}px` : this.height
|
||||||
|
}
|
||||||
|
return style
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
show(callback) {
|
||||||
|
this.ensureParentPosition()
|
||||||
|
// 使用 requestAnimationFrame 确保在下一帧渲染时显示,避免闪烁
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
this.showPanel = true
|
||||||
|
this.callback = callback
|
||||||
|
})
|
||||||
|
},
|
||||||
|
hide() {
|
||||||
|
this.showPanel = false
|
||||||
|
this.callback = null
|
||||||
|
// 延迟恢复父容器定位,等待动画完成
|
||||||
|
setTimeout(() => {
|
||||||
|
this.restoreParentPosition()
|
||||||
|
}, 300)
|
||||||
|
},
|
||||||
|
ensureParentPosition() {
|
||||||
|
// 确保父容器有 position: relative,提前设置避免闪烁
|
||||||
|
if (!this.parentElement) {
|
||||||
|
// 在组件挂载后立即获取父元素
|
||||||
|
if (this.$el && this.$el.parentElement) {
|
||||||
|
this.parentElement = this.$el.parentElement
|
||||||
|
} else {
|
||||||
|
// 如果组件还未挂载,使用 $nextTick
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.$el && this.$el.parentElement) {
|
||||||
|
this.parentElement = this.$el.parentElement
|
||||||
|
}
|
||||||
|
this.setParentPosition()
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.setParentPosition()
|
||||||
|
},
|
||||||
|
setParentPosition() {
|
||||||
|
if (this.parentElement) {
|
||||||
|
const computedStyle = window.getComputedStyle(this.parentElement)
|
||||||
|
const position = computedStyle.position
|
||||||
|
if (position === 'static' || !position) {
|
||||||
|
this.originalParentPosition = this.parentElement.style.position || ''
|
||||||
|
// 使用 will-change 优化性能
|
||||||
|
this.parentElement.style.willChange = 'transform'
|
||||||
|
this.parentElement.style.position = 'relative'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
restoreParentPosition() {
|
||||||
|
// 恢复父容器的原始定位
|
||||||
|
if (this.parentElement && this.originalParentPosition !== null) {
|
||||||
|
if (this.originalParentPosition) {
|
||||||
|
this.parentElement.style.position = this.originalParentPosition
|
||||||
|
} else {
|
||||||
|
this.parentElement.style.position = ''
|
||||||
|
}
|
||||||
|
this.parentElement.style.willChange = ''
|
||||||
|
this.originalParentPosition = null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleBack() {
|
||||||
|
this.$emit('back')
|
||||||
|
this.hide()
|
||||||
|
},
|
||||||
|
handleBackdropClick() {
|
||||||
|
if (this.closeOnClickBackdrop) {
|
||||||
|
this.hide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
showPanel(newVal) {
|
||||||
|
// 不再控制 body 的 overflow,让父容器控制
|
||||||
|
},
|
||||||
|
// 监听路由变化
|
||||||
|
'$route'(to, from) {
|
||||||
|
if (this.showPanel) {
|
||||||
|
this.hide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
// 组件挂载后立即获取父元素并设置定位,避免后续闪烁
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.$el && this.$el.parentElement) {
|
||||||
|
this.parentElement = this.$el.parentElement
|
||||||
|
// 预先设置 position,避免显示时闪烁
|
||||||
|
this.setParentPosition()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
// 组件销毁时关闭面板并清理
|
||||||
|
if (this.showPanel) {
|
||||||
|
this.hide()
|
||||||
|
} else {
|
||||||
|
this.restoreParentPosition()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.float-panel-wrapper {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: 1000;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
/* 使用 will-change 优化性能,避免重排 */
|
||||||
|
will-change: transform;
|
||||||
|
/* 使用 transform 代替 position,避免触发重排 */
|
||||||
|
transform: translateZ(0);
|
||||||
|
backface-visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.float-panel {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: #fff;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
/* 使用 GPU 加速,避免闪烁 */
|
||||||
|
will-change: transform;
|
||||||
|
transform: translateZ(0);
|
||||||
|
backface-visibility: hidden;
|
||||||
|
|
||||||
|
&.float-panel-right {
|
||||||
|
animation: slideInRight 0.3s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.float-panel-left {
|
||||||
|
animation: slideInLeft 0.3s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.float-panel-top {
|
||||||
|
animation: slideInTop 0.3s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.float-panel-bottom {
|
||||||
|
animation: slideInBottom 0.3s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.float-panel-center {
|
||||||
|
animation: fadeInScale 0.3s ease-out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.float-panel-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 16px 20px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
.header-left {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.panel-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #17233d;
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-right {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.float-panel-body {
|
||||||
|
flex: 1;
|
||||||
|
padding: 20px;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 动画效果
|
||||||
|
.float-panel-enter-active,
|
||||||
|
.float-panel-leave-active {
|
||||||
|
transition: opacity 0.3s ease;
|
||||||
|
/* 使用 transform 代替 opacity,性能更好 */
|
||||||
|
will-change: transform, opacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
.float-panel-enter,
|
||||||
|
.float-panel-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
/* 使用 transform 避免重排 */
|
||||||
|
transform: translateZ(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slideInRight {
|
||||||
|
from {
|
||||||
|
transform: translateX(100%);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slideInLeft {
|
||||||
|
from {
|
||||||
|
transform: translateX(-100%);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slideInTop {
|
||||||
|
from {
|
||||||
|
transform: translateY(-100%);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slideInBottom {
|
||||||
|
from {
|
||||||
|
transform: translateY(100%);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeInScale {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(0.9);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
actionUrl: window.rootVue.$config.apiUrl + 'sys_file/upload_oos_img',
|
actionUrl: this.config.apiUrl + 'sys_file/upload_oos_img',
|
||||||
cropper: null,
|
cropper: null,
|
||||||
insideSrc: '',
|
insideSrc: '',
|
||||||
file: null,
|
file: null,
|
||||||
@@ -81,7 +81,7 @@ export default {
|
|||||||
reader.onload = async (event) => {
|
reader.onload = async (event) => {
|
||||||
this.getSize(event.srcElement.result).then(({ width, height }) => {
|
this.getSize(event.srcElement.result).then(({ width, height }) => {
|
||||||
if (width < 500 || height < 500) {
|
if (width < 500 || height < 500) {
|
||||||
rootVue.$Message.error('图片尺寸小于 500*500 ,请更换图片')
|
this.$Message.error('图片尺寸小于 500*500 ,请更换图片')
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
this.insideSrc = event.srcElement.result
|
this.insideSrc = event.srcElement.result
|
||||||
|
|||||||
21
src/components/date-picker/index.vue
Normal file
21
src/components/date-picker/index.vue
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<template>
|
||||||
|
<DatePicker
|
||||||
|
:value="value"
|
||||||
|
v-bind="$attrs"
|
||||||
|
@on-change="handleChange"
|
||||||
|
:style="'width:100%;'"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'DatePicker',
|
||||||
|
props: ['value'],
|
||||||
|
methods: {
|
||||||
|
handleChange(date) {
|
||||||
|
this.$emit('input', date)
|
||||||
|
this.$emit('change', date)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -25,7 +25,7 @@ export default {
|
|||||||
this.editor = new WangEditor(domId)
|
this.editor = new WangEditor(domId)
|
||||||
this.editor.config.uploadImgShowBase64 = true
|
this.editor.config.uploadImgShowBase64 = true
|
||||||
|
|
||||||
this.editor.config.uploadImgServer = window.rootVue.$config.apiUrl + 'sys_file/upload_oos_img'
|
this.editor.config.uploadImgServer =this.config.apiUrl + 'sys_file/upload_oos_img'
|
||||||
this.editor.config.uploadImgHooks = {
|
this.editor.config.uploadImgHooks = {
|
||||||
customInsert: (insertImg, result, editor) => {
|
customInsert: (insertImg, result, editor) => {
|
||||||
var url = result.data.path
|
var url = result.data.path
|
||||||
|
|||||||
89
src/components/index.js
Normal file
89
src/components/index.js
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
import Main from './main'
|
||||||
|
import ParentView from './parent-view'
|
||||||
|
|
||||||
|
|
||||||
|
// 导入页面组件
|
||||||
|
import pages from '../views/index'
|
||||||
|
const {LoginPage,Page401,Page404,Page500} = pages
|
||||||
|
|
||||||
|
import Tables from './tables'
|
||||||
|
import UploadSingle from './upload/Single.vue'
|
||||||
|
import UploadMultiple from './upload/Multiple.vue'
|
||||||
|
import TreeGrid from './treeGrid'
|
||||||
|
import AsyncModal from './asyncModal'
|
||||||
|
import InfoCard from './info-card'
|
||||||
|
import LoadFlower from './load-flower'
|
||||||
|
import SplitPane from './split-pane'
|
||||||
|
import TextArea from './text-area'
|
||||||
|
import CommonIcon from './common-icon'
|
||||||
|
import Editor from './editor/index.vue'
|
||||||
|
import editModal from './tables/editModal.vue'
|
||||||
|
import fieldItem from './tables/fieldItem.vue'
|
||||||
|
import FieldRenderer from './tables/fieldRenderer.vue'
|
||||||
|
import FloatPanel from './FloatPanel/index.vue'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 注册全局组件的方法
|
||||||
|
const registerGlobalComponents = (Vue) => {
|
||||||
|
Vue.component('Main', Main)
|
||||||
|
Vue.component('ParentView', ParentView)
|
||||||
|
|
||||||
|
Vue.component('Page401', Page401)
|
||||||
|
Vue.component('Page404', Page404)
|
||||||
|
Vue.component('Page500', Page500)
|
||||||
|
|
||||||
|
Vue.component('LoginPage', LoginPage)
|
||||||
|
|
||||||
|
Vue.component('Tables', Tables)
|
||||||
|
Vue.component('UploadSingle', UploadSingle)
|
||||||
|
Vue.component('UploadMultiple', UploadMultiple)
|
||||||
|
Vue.component('TreeGrid', TreeGrid)
|
||||||
|
Vue.component('AsyncModal', AsyncModal)
|
||||||
|
Vue.component('InfoCard', InfoCard)
|
||||||
|
Vue.component('LoadFlower', LoadFlower)
|
||||||
|
Vue.component('SplitPane', SplitPane)
|
||||||
|
Vue.component('TextArea', TextArea)
|
||||||
|
Vue.component('CommonIcon', CommonIcon)
|
||||||
|
Vue.component('Editor', Editor)
|
||||||
|
Vue.component('editModal', editModal)
|
||||||
|
Vue.component('fieldItem', fieldItem)
|
||||||
|
Vue.component('FieldRenderer', FieldRenderer)
|
||||||
|
Vue.component('FloatPanel', FloatPanel)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 注册自定义组件的方法
|
||||||
|
const registerComponents = (Vue, components = {}) => {
|
||||||
|
Object.keys(components).forEach(name => {
|
||||||
|
Vue.component(name, components[name])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
registerGlobalComponents,
|
||||||
|
registerComponents
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default {
|
||||||
|
Main,
|
||||||
|
ParentView,
|
||||||
|
Tables,
|
||||||
|
UploadSingle,
|
||||||
|
UploadMultiple,
|
||||||
|
TreeGrid,
|
||||||
|
AsyncModal,
|
||||||
|
InfoCard,
|
||||||
|
LoadFlower,
|
||||||
|
SplitPane,
|
||||||
|
TextArea,
|
||||||
|
CommonIcon,
|
||||||
|
Editor,
|
||||||
|
editModal,
|
||||||
|
fieldItem,
|
||||||
|
FieldRenderer,
|
||||||
|
FloatPanel
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -12,6 +12,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.header-con {
|
.header-con {
|
||||||
padding: 0px 10px;
|
padding: 0px 10px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -20,16 +22,37 @@
|
|||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.main-content-con {
|
.main-content-con {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
color: darkgray;
|
color: darkgray;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-layout-con {
|
.main-layout-con {
|
||||||
display: flex;
|
display: flex;
|
||||||
display: -webkit-flex;
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-con-main {
|
||||||
|
height: 64px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-layout-content {
|
||||||
|
height: calc(100% - 64px);
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
|
|
||||||
<Layout style="height: 100%" class="main">
|
<Layout style="height: 100%; display: flex; flex-direction: row;" class="main">
|
||||||
|
|
||||||
<Sider hide-trigger collapsible :width="256" :collapsed-width="64" v-model="collapsed" class="left-sider" :style="{overflow: 'hidden'}">
|
<Sider hide-trigger collapsible :width="256" :collapsed-width="64" v-model="collapsed" class="left-sider" :style="{overflow: 'hidden'}">
|
||||||
<div class="sidebar-brand" @click="goHome" v-if="!collapsed">
|
<div class="sidebar-brand" @click="goHome" v-if="!collapsed">
|
||||||
@@ -14,13 +14,13 @@
|
|||||||
<Content class="main-content-con">
|
<Content class="main-content-con">
|
||||||
<Layout class="main-layout-con">
|
<Layout class="main-layout-con">
|
||||||
|
|
||||||
<Header>
|
<Header class="header-con-main">
|
||||||
<headerBar class="header-con" @on-coll-change="collpasedChange" :collapsed="collapsed">
|
<headerBar class="header-con" @on-coll-change="collpasedChange" :collapsed="collapsed">
|
||||||
<Terminal></Terminal>
|
<Terminal></Terminal>
|
||||||
<user :userName="userName" :user-avator="userAvator || ''" />
|
<user :userName="userName" :user-avator="userAvator || ''" />
|
||||||
</headerBar>
|
</headerBar>
|
||||||
</Header>
|
</Header>
|
||||||
<Layout>
|
<Layout class="main-layout-content">
|
||||||
<Content class="content-wrapper">
|
<Content class="content-wrapper">
|
||||||
|
|
||||||
<router-view />
|
<router-view />
|
||||||
|
|||||||
20
src/components/switch/index.vue
Normal file
20
src/components/switch/index.vue
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<template>
|
||||||
|
<Switch
|
||||||
|
:value="value"
|
||||||
|
v-bind="$attrs"
|
||||||
|
@on-change="handleChange"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'Switch',
|
||||||
|
props: ['value'],
|
||||||
|
methods: {
|
||||||
|
handleChange(checked) {
|
||||||
|
this.$emit('input', checked)
|
||||||
|
this.$emit('change', checked)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -13,38 +13,14 @@
|
|||||||
<div :class="col.inLine?'inline-row':'line-row'" :key="col.name" v-if="col.key&&!col.display">
|
<div :class="col.inLine?'inline-row':'line-row'" :key="col.name" v-if="col.key&&!col.display">
|
||||||
<FormItem :label="col.title" :prop="col.key" :rules="curRules[col.key]" :style=" col.rowStyle">
|
<FormItem :label="col.title" :prop="col.key" :rules="curRules[col.key]" :style=" col.rowStyle">
|
||||||
<Row>
|
<Row>
|
||||||
|
<!-- 使用专门的字段渲染组件 -->
|
||||||
<Select class="text-left" filterable v-if="col.com==='Select'" v-model='row[col.key]' v-bind="col" :disabled="getDisabled(col)">
|
<FieldRenderer
|
||||||
<Option :value="item.key" :key="item.key" v-for="item in col.source">{{item.value }}</Option>
|
:col="col"
|
||||||
</Select>
|
:value="row[col.key]"
|
||||||
|
:disabled="getDisabled(col)"
|
||||||
<RadioGroup v-else-if="col.com==='Radio'" v-model="row[col.key]" v-bind="col" :disabled="getDisabled(col)">
|
@input="handleFieldInput(col.key, $event )"
|
||||||
<Radio :label="item.key" :key="item.key" v-for="item in col.source">
|
@change="handleFieldChange(col.key, $event)"
|
||||||
{{item.value}}
|
/>
|
||||||
</Radio>
|
|
||||||
</RadioGroup>
|
|
||||||
|
|
||||||
<AutoComplete v-else-if="col.com==='SelectIcon'" icon="ios-search" v-model="row[col.key]" v-bind="col" :disabled="getDisabled(col)">
|
|
||||||
<Option v-for="(icon,index) in icons" :value="icon" :key="index">
|
|
||||||
<Icon size="20" :type="icon" />
|
|
||||||
{{ icon }}
|
|
||||||
</Option>
|
|
||||||
</AutoComplete>
|
|
||||||
|
|
||||||
<UploadSingle v-else-if="col.com==='upload_Img'" v-model="row[col.key]" v-bind="col" :disabled="getDisabled(col)">
|
|
||||||
|
|
||||||
</UploadSingle>
|
|
||||||
|
|
||||||
<TextArea v-else-if="col.com==='TextArea'" v-model="row[col.key]" v-bind="col" :disabled="getDisabled(col)">
|
|
||||||
|
|
||||||
</TextArea>
|
|
||||||
|
|
||||||
<templateRender v-else-if="col.editRender" :value="row[col.key]" :render='col.editRender'></templateRender>
|
|
||||||
|
|
||||||
<Input v-else-if="!col.com" v-model="row[col.key]" v-bind="col" style="width:100%;" :disabled="getDisabled(col)" />
|
|
||||||
|
|
||||||
<component v-else v-bind:is="col.com" v-model="row[col.key]" v-bind="col" :disabled="getDisabled(col)"></component>
|
|
||||||
|
|
||||||
</Row>
|
</Row>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
</div>
|
</div>
|
||||||
@@ -64,12 +40,12 @@
|
|||||||
<script>
|
<script>
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import templateRender from './templateRender'
|
import FieldRenderer from './fieldRenderer'
|
||||||
const icons = require('@/config/icons')
|
|
||||||
export default {
|
export default {
|
||||||
props: ['columns', 'width'],
|
props: ['columns', 'width'],
|
||||||
components: {
|
components: {
|
||||||
templateRender
|
FieldRenderer
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -78,7 +54,6 @@ export default {
|
|||||||
isRefresh: true,
|
isRefresh: true,
|
||||||
isEdit: false,
|
isEdit: false,
|
||||||
isOPen: false,
|
isOPen: false,
|
||||||
icons: [],
|
|
||||||
row: {},
|
row: {},
|
||||||
callback: null
|
callback: null
|
||||||
}
|
}
|
||||||
@@ -114,6 +89,24 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
// 处理字段输入事件
|
||||||
|
handleFieldInput(key, value) {
|
||||||
|
// 确保接收到的是值而不是事件对象
|
||||||
|
if (value && typeof value === 'object' && value.target) {
|
||||||
|
value = value.target.value
|
||||||
|
}
|
||||||
|
this.$set(this.row, key, value)
|
||||||
|
},
|
||||||
|
|
||||||
|
// 处理字段变化事件
|
||||||
|
handleFieldChange(key, value) {
|
||||||
|
// 确保接收到的是值而不是事件对象
|
||||||
|
if (value && typeof value === 'object' && value.target) {
|
||||||
|
value = value.target.value
|
||||||
|
}
|
||||||
|
this.$set(this.row, key, value)
|
||||||
|
},
|
||||||
|
|
||||||
// 判断字段是否禁用
|
// 判断字段是否禁用
|
||||||
getDisabled(col) {
|
getDisabled(col) {
|
||||||
// 如果是编辑模式且字段设置了disabled,则禁用
|
// 如果是编辑模式且字段设置了disabled,则禁用
|
||||||
@@ -183,7 +176,6 @@ export default {
|
|||||||
this.isOPen = false
|
this.isOPen = false
|
||||||
},
|
},
|
||||||
async init(row, isgl) {
|
async init(row, isgl) {
|
||||||
this.icons = icons.map((item) => item.trim())
|
|
||||||
row = row || {}
|
row = row || {}
|
||||||
let rules = this.curRules
|
let rules = this.curRules
|
||||||
if (isgl) {
|
if (isgl) {
|
||||||
@@ -202,15 +194,23 @@ export default {
|
|||||||
.forEach((col) => {
|
.forEach((col) => {
|
||||||
let defaultVal = row[col.key]
|
let defaultVal = row[col.key]
|
||||||
|
|
||||||
|
// 如果值是 undefined 或 null,不赋值,保持原状态
|
||||||
|
if (defaultVal === undefined || defaultVal === null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 传递过来什么值就保持什么值
|
||||||
if (col.data_type === 'number') {
|
if (col.data_type === 'number') {
|
||||||
defaultVal = parseFloat(defaultVal) || 0
|
// 保持原始数值,包括 0
|
||||||
Vue.set(this.row, col.key, defaultVal)
|
const numVal = parseFloat(defaultVal)
|
||||||
|
Vue.set(this.row, col.key, isNaN(numVal) ? defaultVal : numVal)
|
||||||
} else if (col.data_type === 'date') {
|
} else if (col.data_type === 'date') {
|
||||||
Vue.set(this.row, col.key, dayjs(defaultVal).toDate())
|
Vue.set(this.row, col.key, dayjs(defaultVal).toDate())
|
||||||
} else if (col.data_type === 'boolean') {
|
} else if (col.data_type === 'boolean') {
|
||||||
Vue.set(this.row, col.key, defaultVal === 1 || defaultVal === true)
|
// 保持原始布尔值,包括 false
|
||||||
|
Vue.set(this.row, col.key, defaultVal === 1 || defaultVal === true || defaultVal === '1')
|
||||||
} else {
|
} else {
|
||||||
defaultVal = defaultVal !== undefined ? defaultVal : ''
|
// 保持原始值,包括空字符串 ''
|
||||||
Vue.set(this.row, col.key, defaultVal)
|
Vue.set(this.row, col.key, defaultVal)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
266
src/components/tables/fieldRenderer.vue
Normal file
266
src/components/tables/fieldRenderer.vue
Normal file
@@ -0,0 +1,266 @@
|
|||||||
|
<template>
|
||||||
|
<div style="width: 100%;">
|
||||||
|
<!-- 使用组件映射表来简化条件渲染 -->
|
||||||
|
<component
|
||||||
|
:is="getComponentName(col.com)"
|
||||||
|
:value="col.com === 'Radio' ? radioValue : value"
|
||||||
|
v-bind="getComponentProps(col)"
|
||||||
|
:disabled="disabled"
|
||||||
|
:class="getComponentClass(col.com)"
|
||||||
|
:style="getComponentStyle(col.com)"
|
||||||
|
@input="handleInput"
|
||||||
|
@on-change="handleChange"
|
||||||
|
>
|
||||||
|
<!-- Select 组件的选项 -->
|
||||||
|
<template v-if="col.com === 'Select'">
|
||||||
|
<Option
|
||||||
|
:value="item.key"
|
||||||
|
:key="item.key"
|
||||||
|
v-for="item in col.source"
|
||||||
|
>
|
||||||
|
{{ item.value }}
|
||||||
|
</Option>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- Radio 组件的选项 -->
|
||||||
|
<template v-else-if="col.com === 'Radio'">
|
||||||
|
<Radio
|
||||||
|
:label="getRadioValue(item)"
|
||||||
|
:key="getRadioKey(item)"
|
||||||
|
v-for="item in getRadioSource(col)"
|
||||||
|
>
|
||||||
|
{{ getRadioLabel(item) }}
|
||||||
|
</Radio>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- SelectIcon 组件的选项 -->
|
||||||
|
<template v-else-if="col.com === 'SelectIcon'">
|
||||||
|
<Option
|
||||||
|
v-for="(icon, index) in icons"
|
||||||
|
:value="icon"
|
||||||
|
:key="index"
|
||||||
|
>
|
||||||
|
<Icon size="20" :type="icon" />
|
||||||
|
{{ icon }}
|
||||||
|
</Option>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 自定义渲染 -->
|
||||||
|
<template v-else-if="col.editRender">
|
||||||
|
<templateRender
|
||||||
|
:value="value"
|
||||||
|
:render="col.editRender"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</component>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import templateRender from './templateRender'
|
||||||
|
|
||||||
|
// 导入框架中的图标配置
|
||||||
|
let icons = []
|
||||||
|
try {
|
||||||
|
icons = require('../../config/icons.json') || []
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('未找到图标配置文件,图标选择功能将不可用', e)
|
||||||
|
icons = []
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'FieldRenderer',
|
||||||
|
components: {
|
||||||
|
templateRender
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
col: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: [String, Number, Boolean, Array, Object, Date],
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
icons: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
// 直接返回原始值,不进行类型转换
|
||||||
|
radioValue() {
|
||||||
|
return this.value
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
// 安全处理图标数据
|
||||||
|
if (Array.isArray(icons)) {
|
||||||
|
this.icons = icons.map((item) => item.trim ? item.trim() : item)
|
||||||
|
} else {
|
||||||
|
this.icons = []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 组件映射表 - 统一管理组件类型
|
||||||
|
getComponentName(componentType) {
|
||||||
|
const componentMap = {
|
||||||
|
'Select': 'Select',
|
||||||
|
'Radio': 'RadioGroup',
|
||||||
|
'SelectIcon': 'AutoComplete',
|
||||||
|
'UploadSingle': 'UploadSingle',
|
||||||
|
'TextArea': 'TextArea',
|
||||||
|
'Input': 'Input',
|
||||||
|
'DatePicker': 'DatePicker',
|
||||||
|
'TimePicker': 'TimePicker',
|
||||||
|
'Switch': 'Switch',
|
||||||
|
'Checkbox': 'Checkbox',
|
||||||
|
'Slider': 'Slider',
|
||||||
|
'Rate': 'Rate',
|
||||||
|
'Cascader': 'Cascader',
|
||||||
|
'TreeSelect': 'TreeSelect',
|
||||||
|
'Transfer': 'Transfer',
|
||||||
|
'Upload': 'Upload',
|
||||||
|
'ColorPicker': 'ColorPicker',
|
||||||
|
'InputNumber': 'InputNumber'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果没有指定组件类型,默认为 Input
|
||||||
|
return componentMap[componentType] || 'Input'
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取组件属性
|
||||||
|
getComponentProps(col) {
|
||||||
|
const baseProps = { ...col }
|
||||||
|
|
||||||
|
// 移除不需要传递给组件的属性
|
||||||
|
delete baseProps.com
|
||||||
|
delete baseProps.source
|
||||||
|
delete baseProps.options
|
||||||
|
delete baseProps.editRender
|
||||||
|
delete baseProps.inLine
|
||||||
|
delete baseProps.display
|
||||||
|
delete baseProps.disabled
|
||||||
|
delete baseProps.disabledOnAdd
|
||||||
|
delete baseProps.required
|
||||||
|
delete baseProps.data_type
|
||||||
|
delete baseProps.type
|
||||||
|
delete baseProps.rowStyle
|
||||||
|
|
||||||
|
// 根据组件类型添加特定属性
|
||||||
|
if (col.com === 'Select') {
|
||||||
|
baseProps.filterable = true
|
||||||
|
baseProps.clearable = true
|
||||||
|
} else if (col.com === 'SelectIcon') {
|
||||||
|
baseProps.icon = 'ios-search'
|
||||||
|
} else if (col.com === 'TextArea') {
|
||||||
|
baseProps.rows = 4
|
||||||
|
baseProps.placeholder = '请输入内容'
|
||||||
|
} else if (col.com === 'Input' || !col.com) {
|
||||||
|
baseProps.placeholder = col.placeholder || '请输入' + col.title
|
||||||
|
baseProps.clearable = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return baseProps
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取 Radio 数据源(支持 source 和 options 两种格式)
|
||||||
|
getRadioSource(col) {
|
||||||
|
return col.source || col.options || []
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取 Radio 选项的值(支持多种数据格式)
|
||||||
|
getRadioValue(item) {
|
||||||
|
// 支持 { key: value, value: label } 格式
|
||||||
|
if (item.key !== undefined) {
|
||||||
|
return item.key
|
||||||
|
}
|
||||||
|
// 支持 { value: value, label: label } 格式
|
||||||
|
if (item.value !== undefined) {
|
||||||
|
return item.value
|
||||||
|
}
|
||||||
|
// 支持字符串数组
|
||||||
|
if (typeof item === 'string' || typeof item === 'number') {
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
return item
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取 Radio 选项的 key(用于 v-for)
|
||||||
|
getRadioKey(item) {
|
||||||
|
if (item.key !== undefined) {
|
||||||
|
return item.key
|
||||||
|
}
|
||||||
|
if (item.value !== undefined) {
|
||||||
|
return item.value
|
||||||
|
}
|
||||||
|
if (typeof item === 'string' || typeof item === 'number') {
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
return JSON.stringify(item)
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取 Radio 选项的显示文本
|
||||||
|
getRadioLabel(item) {
|
||||||
|
// 支持 { key: value, value: label } 格式
|
||||||
|
if (item.value !== undefined && typeof item.value === 'string') {
|
||||||
|
return item.value
|
||||||
|
}
|
||||||
|
// 支持 { value: value, label: label } 格式
|
||||||
|
if (item.label !== undefined) {
|
||||||
|
return item.label
|
||||||
|
}
|
||||||
|
// 支持字符串数组
|
||||||
|
if (typeof item === 'string' || typeof item === 'number') {
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
return item.value || item.key || item
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取组件样式类
|
||||||
|
getComponentClass(componentType) {
|
||||||
|
const classMap = {
|
||||||
|
'Select': 'text-left',
|
||||||
|
'SelectIcon': 'text-left'
|
||||||
|
}
|
||||||
|
return classMap[componentType] || ''
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取组件样式
|
||||||
|
getComponentStyle(componentType) {
|
||||||
|
const styleMap = {
|
||||||
|
'Input': 'width:100%;',
|
||||||
|
'TextArea': 'width:100%;',
|
||||||
|
'DatePicker': 'width:100%;',
|
||||||
|
'TimePicker': 'width:100%;'
|
||||||
|
}
|
||||||
|
return styleMap[componentType] || ''
|
||||||
|
},
|
||||||
|
|
||||||
|
// 处理输入事件
|
||||||
|
handleInput(value) {
|
||||||
|
// 如果接收到的是事件对象,提取值
|
||||||
|
if (value && typeof value === 'object' && value.target) {
|
||||||
|
value = value.target.value
|
||||||
|
}
|
||||||
|
// 直接传递值,不进行类型转换
|
||||||
|
this.$emit('input', value)
|
||||||
|
},
|
||||||
|
|
||||||
|
// 处理变化事件
|
||||||
|
handleChange(value) {
|
||||||
|
// 如果接收到的是事件对象,提取值
|
||||||
|
if (value && typeof value === 'object' && value.target) {
|
||||||
|
value = value.target.value
|
||||||
|
}
|
||||||
|
// 直接传递值,不进行类型转换
|
||||||
|
this.$emit('change', value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -90,13 +90,27 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
insideColumns() {
|
insideColumns() {
|
||||||
|
// 确保 columns 是数组
|
||||||
|
if (!Array.isArray(this.columns) || this.columns.length === 0) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
let columns = this.columns.map((item, index) => {
|
let columns = this.columns.map((item, index) => {
|
||||||
|
// 确保 item 是对象
|
||||||
|
if (!item || typeof item !== 'object') {
|
||||||
|
console.warn(`[Tables] 列配置第 ${index} 项格式不正确:`, item)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建新对象,避免直接修改原对象
|
||||||
|
let column = { ...item }
|
||||||
|
|
||||||
// 设置默认对齐方式
|
// 设置默认对齐方式
|
||||||
if (!item.align) {
|
if (!column.align) {
|
||||||
item.align = 'center'
|
column.align = 'center'
|
||||||
|
|
||||||
if (item.children && item.children.length > 0) {
|
if (column.children && column.children.length > 0) {
|
||||||
item.children = item.children.map((sonItem) => {
|
column.children = column.children.map((sonItem) => {
|
||||||
if (!sonItem.align) {
|
if (!sonItem.align) {
|
||||||
sonItem.align = 'center'
|
sonItem.align = 'center'
|
||||||
}
|
}
|
||||||
@@ -107,12 +121,12 @@ export default {
|
|||||||
|
|
||||||
// 确保列宽设置正确,优先使用 width,其次使用 minWidth
|
// 确保列宽设置正确,优先使用 width,其次使用 minWidth
|
||||||
// 如果都没有设置,则设置默认 minWidth
|
// 如果都没有设置,则设置默认 minWidth
|
||||||
if (!item.width && !item.minWidth) {
|
if (!column.width && !column.minWidth) {
|
||||||
item.minWidth = 120
|
column.minWidth = 120
|
||||||
}
|
}
|
||||||
|
|
||||||
return item
|
return column
|
||||||
})
|
}).filter(item => item !== null) // 过滤掉无效的列配置
|
||||||
|
|
||||||
return columns
|
return columns
|
||||||
},
|
},
|
||||||
@@ -139,11 +153,27 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
handleTableData() {
|
handleTableData() {
|
||||||
let values = this.value || []
|
// 确保 value 是数组
|
||||||
let data = values.filter((p) => p)
|
let values = Array.isArray(this.value) ? this.value : []
|
||||||
this.insideTableData = data.map((item, index) => {
|
|
||||||
let res = item
|
// 过滤掉 null 和 undefined,但保留其他 falsy 值(如 0、false、空字符串等)
|
||||||
return res
|
let data = values.filter((p) => p !== null && p !== undefined)
|
||||||
|
|
||||||
|
// 使用 $set 确保响应式更新
|
||||||
|
this.$set(this, 'insideTableData', data.map((item, index) => {
|
||||||
|
// 确保每个数据项都是对象
|
||||||
|
if (typeof item !== 'object' || item === null) {
|
||||||
|
return { value: item }
|
||||||
|
}
|
||||||
|
return item
|
||||||
|
}))
|
||||||
|
|
||||||
|
// 强制更新表格(如果表格已渲染)
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.$refs.tablesMain) {
|
||||||
|
// 触发表格重新渲染
|
||||||
|
this.$refs.tablesMain.$forceUpdate()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
onChangePage(page) {
|
onChangePage(page) {
|
||||||
@@ -177,11 +207,28 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
value(val) {
|
// 监听 value 变化
|
||||||
this.handleTableData()
|
value: {
|
||||||
|
handler(val) {
|
||||||
|
this.handleTableData()
|
||||||
|
},
|
||||||
|
immediate: true,
|
||||||
|
deep: true
|
||||||
},
|
},
|
||||||
|
// 监听 columns 变化,确保列配置更新时表格重新渲染
|
||||||
|
columns: {
|
||||||
|
handler() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.$refs.tablesMain) {
|
||||||
|
this.$refs.tablesMain.$forceUpdate()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
deep: true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
// 确保数据已处理
|
||||||
this.handleTableData()
|
this.handleTableData()
|
||||||
|
|
||||||
// 自适应高度
|
// 自适应高度
|
||||||
@@ -196,6 +243,14 @@ export default {
|
|||||||
|
|
||||||
// 动态计算偏移量
|
// 动态计算偏移量
|
||||||
this.calculateOffset()
|
this.calculateOffset()
|
||||||
|
|
||||||
|
// 如果数据或列配置为空,输出警告
|
||||||
|
if (!this.insideTableData || this.insideTableData.length === 0) {
|
||||||
|
console.warn('[Tables] 表格数据为空,请检查 value 属性是否正确绑定')
|
||||||
|
}
|
||||||
|
if (!this.columns || this.columns.length === 0) {
|
||||||
|
console.warn('[Tables] 表格列配置为空,请检查 columns 属性是否正确绑定')
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// 监听窗口大小变化,重新计算偏移量
|
// 监听窗口大小变化,重新计算偏移量
|
||||||
|
|||||||
@@ -15,8 +15,19 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
colStyle(col) {
|
colStyle(col) {
|
||||||
const width = col && col.width ? col.width : '150px'
|
// 为不同类型的列设置合适的默认宽度
|
||||||
return { width }
|
let defaultWidth = '150px'
|
||||||
|
if (col && col.type === 'operation') {
|
||||||
|
defaultWidth = '200px' // 操作列需要更多空间
|
||||||
|
} else if (col && col.key === 'name' || col.key === 'title') {
|
||||||
|
defaultWidth = '200px' // 名称列通常需要更多空间
|
||||||
|
}
|
||||||
|
|
||||||
|
const width = col && col.width ? col.width : defaultWidth
|
||||||
|
return {
|
||||||
|
width,
|
||||||
|
minWidth: col.minWidth || width
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,38 +1,31 @@
|
|||||||
<template>
|
<template>
|
||||||
<table cellspacing="0" width="100%" cellpadding="0" border="0">
|
<table cellspacing="0" cellpadding="0" border="0" style="width: 100%; min-width: inherit;">
|
||||||
<SubColmns :columns="columns"></SubColmns>
|
<SubColmns :columns="columns"></SubColmns>
|
||||||
<tbody class="endTbody" v-for="(row, index) in subData" :key="row.id">
|
<tbody class="endTbody" v-for="(row, index) in subData" :key="row.id">
|
||||||
|
|
||||||
<tr class="tr-row" v-if="row">
|
<tr class="tr-row" v-if="row">
|
||||||
<td v-for="(col, sonColIndex) in columns"
|
<td v-for="(col, sonColIndex) in columns" :key="sonColIndex" :class="[
|
||||||
:key="sonColIndex"
|
{ 'td-expand': sonColIndex === 0 },
|
||||||
:class="[
|
{ 'td-operations': col.type === 'operation' },
|
||||||
{'td-expand': sonColIndex === 0},
|
col.className
|
||||||
{'td-operations': col.type === 'operation'},
|
]" :style="getCellStyle(col, sonColIndex)">
|
||||||
col.className
|
|
||||||
]"
|
|
||||||
:style="{
|
|
||||||
width: col.width || 'auto',
|
|
||||||
minWidth: col.minWidth || (sonColIndex === 0 ? '200px' : '100px')
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<RenderCol v-if="col.render" :col="col.render" :param="{ row, index, col }" />
|
<RenderCol v-if="col.render" :col="col.render" :param="{ row, index, col }" />
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<div class="first-box" v-if="sonColIndex == 1">
|
<div class="first-box" v-if="sonColIndex == 1">
|
||||||
<div class="col-row expand-row" v-if="row.children && row.children.length > 0" @click="expander(row)">
|
<div class="col-row expand-row" v-if="row.children && row.children.length > 0" @click="expander(row)">
|
||||||
<span class="indent-span" :style="{width:`${row.indentWidth}px`}"></span>
|
<span class="indent-span" :style="{ width: `${row.indentWidth}px` }"></span>
|
||||||
<i :class="['ivu-icon', 'link', 'ivu-icon-' + row.indexIcon]" aria-hidden="true"></i>
|
<i :class="['ivu-icon', 'link', 'ivu-icon-' + row.indexIcon]" aria-hidden="true"></i>
|
||||||
<label>{{ row[col.key] }}</label>
|
<label>{{ row[col.key] }}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-row" v-else>
|
<div class="col-row" v-else>
|
||||||
<span class="indent-span" :style="{width:`${row.indentWidth}px`}"></span>
|
<span class="indent-span" :style="{ width: `${row.indentWidth}px` }"></span>
|
||||||
<label>{{ row[col.key] }}</label>
|
<label>{{ row[col.key] }}</label>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<label v-else>{{ row[col.key] }}</label>
|
<label v-else>{{ row[col.key] }}</label>
|
||||||
</template>
|
</template>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -77,6 +70,30 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
// 获取单元格样式
|
||||||
|
getCellStyle(col, colIndex) {
|
||||||
|
// 为不同类型的列设置合适的默认宽度
|
||||||
|
let defaultWidth = '150px'
|
||||||
|
let defaultMinWidth = '100px'
|
||||||
|
|
||||||
|
if (col.type === 'operation') {
|
||||||
|
defaultWidth = '200px'
|
||||||
|
defaultMinWidth = '180px'
|
||||||
|
} else if (col.key === 'name' || col.key === 'title' || colIndex === 1) {
|
||||||
|
defaultWidth = '200px'
|
||||||
|
defaultMinWidth = '180px'
|
||||||
|
} else if (colIndex === 0) {
|
||||||
|
defaultWidth = '200px'
|
||||||
|
defaultMinWidth = '150px'
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
width: col.width || defaultWidth,
|
||||||
|
minWidth: col.minWidth || defaultMinWidth,
|
||||||
|
maxWidth: col.maxWidth || 'none'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
// 本地存储 key,用于持久化展开状态
|
// 本地存储 key,用于持久化展开状态
|
||||||
_expandStoreKey() {
|
_expandStoreKey() {
|
||||||
return 'treegrid_expand_map_v1'
|
return 'treegrid_expand_map_v1'
|
||||||
@@ -208,13 +225,10 @@ table {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
border-collapse: separate;
|
border-collapse: separate;
|
||||||
border-spacing: 0;
|
border-spacing: 0;
|
||||||
|
/* 继承父容器的最小宽度设置 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 确保表格可以在容器内滚动 */
|
/* endTbody 样式现在由父容器控制滚动 */
|
||||||
.endTbody {
|
|
||||||
max-height: calc(100vh - 200px); /* 预留头部和其他元素的空间 */
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.link {
|
.link {
|
||||||
color: #2d8cf0;
|
color: #2d8cf0;
|
||||||
@@ -236,7 +250,7 @@ table {
|
|||||||
transition: background-color 0.2s;
|
transition: background-color 0.2s;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: rgba(45,140,240,0.05);
|
background-color: rgba(45, 140, 240, 0.05);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,7 +261,7 @@ table {
|
|||||||
line-height: 18px;
|
line-height: 18px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
background: rgba(45,140,240,0.08);
|
background: rgba(45, 140, 240, 0.08);
|
||||||
color: #2d8cf0;
|
color: #2d8cf0;
|
||||||
margin-right: 6px;
|
margin-right: 6px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -256,6 +270,7 @@ table {
|
|||||||
|
|
||||||
.tr-row {
|
.tr-row {
|
||||||
padding: 0px 5px;
|
padding: 0px 5px;
|
||||||
|
|
||||||
td {
|
td {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
@@ -295,38 +310,56 @@ table {
|
|||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
border-bottom: 1px solid #e8eaec;
|
border-bottom: 1px solid #e8eaec;
|
||||||
|
box-sizing: border-box;
|
||||||
/* 基础文本溢出处理 */
|
|
||||||
&:not(.td-operations) {
|
/* 改进的文本溢出处理 */
|
||||||
|
&:not(.td-operations):not(.td-expand) {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
max-width: 0; /* 配合 table-layout 实现更好的省略号效果 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 确保内容不会溢出单元格 */
|
||||||
|
> label, > div {
|
||||||
|
max-width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 展开列样式 */
|
/* 展开列样式优化 */
|
||||||
.td-expand {
|
.td-expand {
|
||||||
width: auto;
|
width: auto;
|
||||||
min-width: 200px; /* 给展开图标和文本预留足够空间 */
|
min-width: 200px;
|
||||||
|
max-width: 300px;
|
||||||
|
|
||||||
|
.first-box {
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 操作列样式 */
|
/* 操作列样式优化 */
|
||||||
.td-operations {
|
.td-operations {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
width: auto;
|
width: auto;
|
||||||
min-width: 180px; /* 增加按钮空间 */
|
min-width: 180px;
|
||||||
|
max-width: 250px;
|
||||||
padding-right: 16px;
|
padding-right: 16px;
|
||||||
overflow: visible !important; /* 强制确保内容可见 */
|
overflow: visible !important;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1; /* 确保按钮在最上层 */
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 确保操作列中的按钮组样式 */
|
/* 确保操作列中的按钮组样式 */
|
||||||
.td-operations .ivu-btn-group {
|
.td-operations .ivu-btn-group {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
flex-wrap: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 确保单个按钮样式 */
|
/* 确保单个按钮样式 */
|
||||||
@@ -335,6 +368,7 @@ table {
|
|||||||
visibility: visible;
|
visibility: visible;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
margin: 0 2px;
|
margin: 0 2px;
|
||||||
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,17 +1,21 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="ivu-table-wrapper">
|
<div class="tree-grid-container">
|
||||||
<div class="ivu-table ivu-table-border">
|
<div class="ivu-table-wrapper">
|
||||||
<table cellspacing="0" width="100%" cellpadding="0" border="0">
|
<div class="ivu-table ivu-table-border">
|
||||||
<SubColmns :columns="columns"></SubColmns>
|
<div class="table-scroll-container">
|
||||||
<subTheads :columns="columns"></subTheads>
|
<table cellspacing="0" cellpadding="0" border="0" :style="{ minWidth: tableMinWidth }">
|
||||||
|
<SubColmns :columns="columns"></SubColmns>
|
||||||
|
<subTheads :columns="columns"></subTheads>
|
||||||
|
|
||||||
<tr class="ivu-table-tbody">
|
<tr class="ivu-table-tbody">
|
||||||
<td style="width: 100%;" :colspan="columns.length" class="non-right">
|
<td :colspan="columns.length" class="non-right">
|
||||||
<SubTreeGrid :columns="columns" :data="data" :grade="1" v-bind="$attrs" />
|
<SubTreeGrid :columns="columns" :data="data" :grade="1" v-bind="$attrs" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
</table>
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -31,18 +35,54 @@ export default {
|
|||||||
SubColmns,
|
SubColmns,
|
||||||
subTheads
|
subTheads
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
// 计算表格的最小宽度,确保所有列都能正常显示
|
||||||
|
tableMinWidth() {
|
||||||
|
if (!this.columns || !this.columns.length) return '100%'
|
||||||
|
|
||||||
|
const totalWidth = this.columns.reduce((sum, col) => {
|
||||||
|
const width = col.width || (col.type === 'operation' ? 200 : 150)
|
||||||
|
const numWidth = typeof width === 'string' ? parseInt(width) || 0 : width
|
||||||
|
return sum + numWidth
|
||||||
|
}, 0)
|
||||||
|
|
||||||
|
// 如果计算出的总宽度小于容器宽度,则使用100%
|
||||||
|
return Math.max(totalWidth, 800) + 'px'
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {},
|
methods: {},
|
||||||
mounted() {}
|
mounted() {}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
.tree-grid-container {
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ivu-table-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
.ivu-table {
|
.ivu-table {
|
||||||
/* 限制最大宽度,超出显示横向滚动 */
|
width: 100%;
|
||||||
overflow: auto !important;
|
border: 1px solid #dcdee2;
|
||||||
max-width: 100%;
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
.table-scroll-container {
|
||||||
|
width: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
overflow-y: visible;
|
||||||
|
/* 横向滚动条始终可见,不需要滚动到底 */
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse: separate;
|
||||||
|
border-spacing: 0;
|
||||||
|
min-width: 800px; /* 设置最小表格宽度 */
|
||||||
|
}
|
||||||
|
|
||||||
.ivu-table-tbody {
|
.ivu-table-tbody {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
@@ -51,4 +91,23 @@ export default {
|
|||||||
border: none !important;
|
border: none !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 确保滚动条样式美观 */
|
||||||
|
.table-scroll-container::-webkit-scrollbar {
|
||||||
|
height: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-scroll-container::-webkit-scrollbar-track {
|
||||||
|
background: #f1f1f1;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-scroll-container::-webkit-scrollbar-thumb {
|
||||||
|
background: #c1c1c1;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-scroll-container::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: #a8a8a8;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ export default {
|
|||||||
return {
|
return {
|
||||||
headers,
|
headers,
|
||||||
uploadList: [],
|
uploadList: [],
|
||||||
actionUrl: window.rootVue.$config.apiUrl + 'sys_file/upload_oos_img',
|
actionUrl:this.config.apiUrl + 'sys_file/upload_oos_img',
|
||||||
imgSrc: '',
|
imgSrc: '',
|
||||||
visible: false,
|
visible: false,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,11 +30,17 @@ let headers = {
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ['value'],
|
props: ['value'],
|
||||||
computed: {},
|
computed: {
|
||||||
|
actionUrl() {
|
||||||
|
// 优先使用 $config,如果不存在则使用 window.framework.config
|
||||||
|
const config = this.$config || (window.framework && window.framework.config) || {}
|
||||||
|
const apiUrl = config.apiUrl || config.uploadUrl || ''
|
||||||
|
return apiUrl + 'sys_file/upload_oos_img'
|
||||||
|
}
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
headers,
|
headers,
|
||||||
actionUrl: window.rootVue.$config.apiUrl + 'sys_file/upload_oos_img',
|
|
||||||
imgUrl: '',
|
imgUrl: '',
|
||||||
visible: false,
|
visible: false,
|
||||||
}
|
}
|
||||||
|
|||||||
302
src/config/icons.json
Normal file
302
src/config/icons.json
Normal file
@@ -0,0 +1,302 @@
|
|||||||
|
[
|
||||||
|
"md-add",
|
||||||
|
"md-add-circle",
|
||||||
|
"md-alarm",
|
||||||
|
"md-albums",
|
||||||
|
"md-alert",
|
||||||
|
"md-american-football",
|
||||||
|
"md-analytics",
|
||||||
|
"md-aperture",
|
||||||
|
"md-apps",
|
||||||
|
"md-appstore",
|
||||||
|
"md-archive",
|
||||||
|
"md-arrow-back",
|
||||||
|
"md-arrow-down",
|
||||||
|
"md-arrow-dropdown",
|
||||||
|
"md-arrow-dropdown-circle",
|
||||||
|
"md-arrow-dropleft",
|
||||||
|
"md-arrow-dropleft-circle",
|
||||||
|
"md-arrow-dropright",
|
||||||
|
"md-arrow-dropright-circle",
|
||||||
|
"md-arrow-dropup",
|
||||||
|
"md-arrow-dropup-circle",
|
||||||
|
"md-arrow-forward",
|
||||||
|
"md-arrow-round-back",
|
||||||
|
"md-arrow-round-down",
|
||||||
|
"md-arrow-round-forward",
|
||||||
|
"md-arrow-round-up",
|
||||||
|
"md-arrow-up",
|
||||||
|
"md-at",
|
||||||
|
"md-attach",
|
||||||
|
"md-backspace",
|
||||||
|
"md-barcode",
|
||||||
|
"md-baseball",
|
||||||
|
"md-basket",
|
||||||
|
"md-basketball",
|
||||||
|
"md-battery-charging",
|
||||||
|
"md-battery-dead",
|
||||||
|
"md-battery-full",
|
||||||
|
"md-beaker",
|
||||||
|
"md-beer",
|
||||||
|
"md-bicycle",
|
||||||
|
"md-bluetooth",
|
||||||
|
"md-boat",
|
||||||
|
"md-body",
|
||||||
|
"md-bonfire",
|
||||||
|
"md-book",
|
||||||
|
"md-bookmark",
|
||||||
|
"md-bookmarks",
|
||||||
|
"md-bowtie",
|
||||||
|
"md-briefcase",
|
||||||
|
"md-browsers",
|
||||||
|
"md-brush",
|
||||||
|
"md-bug",
|
||||||
|
"md-build",
|
||||||
|
"md-bulb",
|
||||||
|
"md-bus",
|
||||||
|
"md-cafe",
|
||||||
|
"md-calculator",
|
||||||
|
"md-calendar",
|
||||||
|
"md-call",
|
||||||
|
"md-camera",
|
||||||
|
"md-car",
|
||||||
|
"md-card",
|
||||||
|
"md-cart",
|
||||||
|
"md-cash",
|
||||||
|
"md-chatboxes",
|
||||||
|
"md-chatbubbles",
|
||||||
|
"md-checkbox",
|
||||||
|
"md-checkbox-outline",
|
||||||
|
"md-checkmark",
|
||||||
|
"md-checkmark-circle",
|
||||||
|
"md-checkmark-circle-outline",
|
||||||
|
"md-clipboard",
|
||||||
|
"md-clock",
|
||||||
|
"md-close",
|
||||||
|
"md-close-circle",
|
||||||
|
"md-closed-captioning",
|
||||||
|
"md-cloud",
|
||||||
|
"md-cloud-circle",
|
||||||
|
"md-cloud-done",
|
||||||
|
"md-cloud-download",
|
||||||
|
"md-cloud-outline",
|
||||||
|
"md-cloud-upload",
|
||||||
|
"md-cloudy",
|
||||||
|
"md-cloudy-night",
|
||||||
|
"md-code",
|
||||||
|
"md-code-download",
|
||||||
|
"md-code-working",
|
||||||
|
"md-cog",
|
||||||
|
"md-color-fill",
|
||||||
|
"md-color-filter",
|
||||||
|
"md-color-palette",
|
||||||
|
"md-color-wand",
|
||||||
|
"md-compass",
|
||||||
|
"md-construct",
|
||||||
|
"md-contact",
|
||||||
|
"md-contacts",
|
||||||
|
"md-contract",
|
||||||
|
"md-contrast",
|
||||||
|
"md-copy",
|
||||||
|
"md-create",
|
||||||
|
"md-crop",
|
||||||
|
"md-cube",
|
||||||
|
"md-cut",
|
||||||
|
"md-desktop",
|
||||||
|
"md-disc",
|
||||||
|
"md-document",
|
||||||
|
"md-done-all",
|
||||||
|
"md-download",
|
||||||
|
"md-easel",
|
||||||
|
"md-egg",
|
||||||
|
"md-exit",
|
||||||
|
"md-expand",
|
||||||
|
"md-eye",
|
||||||
|
"md-eye-off",
|
||||||
|
"md-fastforward",
|
||||||
|
"md-female",
|
||||||
|
"md-filing",
|
||||||
|
"md-film",
|
||||||
|
"md-finger-print",
|
||||||
|
"md-flag",
|
||||||
|
"md-flame",
|
||||||
|
"md-flash",
|
||||||
|
"md-flask",
|
||||||
|
"md-flower",
|
||||||
|
"md-folder",
|
||||||
|
"md-folder-open",
|
||||||
|
"md-football",
|
||||||
|
"md-funnel",
|
||||||
|
"md-game-controller-a",
|
||||||
|
"md-game-controller-b",
|
||||||
|
"md-git-branch",
|
||||||
|
"md-git-commit",
|
||||||
|
"md-git-compare",
|
||||||
|
"md-git-merge",
|
||||||
|
"md-git-network",
|
||||||
|
"md-git-pull-request",
|
||||||
|
"md-glasses",
|
||||||
|
"md-globe",
|
||||||
|
"md-grid",
|
||||||
|
"md-hammer",
|
||||||
|
"md-hand",
|
||||||
|
"md-happy",
|
||||||
|
"md-headset",
|
||||||
|
"md-heart",
|
||||||
|
"md-heart-outline",
|
||||||
|
"md-help",
|
||||||
|
"md-help-buoy",
|
||||||
|
"md-help-circle",
|
||||||
|
"md-home",
|
||||||
|
"md-ice-cream",
|
||||||
|
"md-image",
|
||||||
|
"md-images",
|
||||||
|
"md-infinite",
|
||||||
|
"md-information",
|
||||||
|
"md-information-circle",
|
||||||
|
"md-ionic",
|
||||||
|
"md-ionitron",
|
||||||
|
"md-jet",
|
||||||
|
"md-key",
|
||||||
|
"md-keypad",
|
||||||
|
"md-laptop",
|
||||||
|
"md-leaf",
|
||||||
|
"md-link",
|
||||||
|
"md-list",
|
||||||
|
"md-list-box",
|
||||||
|
"md-locate",
|
||||||
|
"md-lock",
|
||||||
|
"md-log-in",
|
||||||
|
"md-log-out",
|
||||||
|
"md-magnet",
|
||||||
|
"md-mail",
|
||||||
|
"md-mail-open",
|
||||||
|
"md-male",
|
||||||
|
"md-man",
|
||||||
|
"md-map",
|
||||||
|
"md-medal",
|
||||||
|
"md-medical",
|
||||||
|
"md-medkit",
|
||||||
|
"md-megaphone",
|
||||||
|
"md-menu",
|
||||||
|
"md-mic",
|
||||||
|
"md-mic-off",
|
||||||
|
"md-microphone",
|
||||||
|
"md-moon",
|
||||||
|
"md-more",
|
||||||
|
"md-move",
|
||||||
|
"md-musical-note",
|
||||||
|
"md-musical-notes",
|
||||||
|
"md-navigate",
|
||||||
|
"md-no-smoking",
|
||||||
|
"md-notifications",
|
||||||
|
"md-notifications-off",
|
||||||
|
"md-notifications-outline",
|
||||||
|
"md-nuclear",
|
||||||
|
"md-nutrition",
|
||||||
|
"md-open",
|
||||||
|
"md-options",
|
||||||
|
"md-outlet",
|
||||||
|
"md-paper",
|
||||||
|
"md-paper-plane",
|
||||||
|
"md-partly-sunny",
|
||||||
|
"md-pause",
|
||||||
|
"md-paw",
|
||||||
|
"md-people",
|
||||||
|
"md-person",
|
||||||
|
"md-person-add",
|
||||||
|
"md-phone-landscape",
|
||||||
|
"md-phone-portrait",
|
||||||
|
"md-photos",
|
||||||
|
"md-pie",
|
||||||
|
"md-pin",
|
||||||
|
"md-pint",
|
||||||
|
"md-pizza",
|
||||||
|
"md-plane",
|
||||||
|
"md-planet",
|
||||||
|
"md-play",
|
||||||
|
"md-podium",
|
||||||
|
"md-power",
|
||||||
|
"md-pricetag",
|
||||||
|
"md-pricetags",
|
||||||
|
"md-print",
|
||||||
|
"md-pulse",
|
||||||
|
"md-qr-scanner",
|
||||||
|
"md-quote",
|
||||||
|
"md-radio",
|
||||||
|
"md-radio-button-off",
|
||||||
|
"md-radio-button-on",
|
||||||
|
"md-rainy",
|
||||||
|
"md-recording",
|
||||||
|
"md-redo",
|
||||||
|
"md-refresh",
|
||||||
|
"md-refresh-circle",
|
||||||
|
"md-remove",
|
||||||
|
"md-remove-circle",
|
||||||
|
"md-reorder",
|
||||||
|
"md-repeat",
|
||||||
|
"md-resize",
|
||||||
|
"md-restaurant",
|
||||||
|
"md-return-left",
|
||||||
|
"md-return-right",
|
||||||
|
"md-reverse-camera",
|
||||||
|
"md-rewind",
|
||||||
|
"md-ribbon",
|
||||||
|
"md-rose",
|
||||||
|
"md-sad",
|
||||||
|
"md-school",
|
||||||
|
"md-search",
|
||||||
|
"md-send",
|
||||||
|
"md-settings",
|
||||||
|
"md-share",
|
||||||
|
"md-share-alt",
|
||||||
|
"md-shirt",
|
||||||
|
"md-shuffle",
|
||||||
|
"md-skip-backward",
|
||||||
|
"md-skip-forward",
|
||||||
|
"md-snow",
|
||||||
|
"md-speedometer",
|
||||||
|
"md-square",
|
||||||
|
"md-square-outline",
|
||||||
|
"md-star",
|
||||||
|
"md-star-half",
|
||||||
|
"md-star-outline",
|
||||||
|
"md-stats",
|
||||||
|
"md-stopwatch",
|
||||||
|
"md-subway",
|
||||||
|
"md-sunny",
|
||||||
|
"md-swap",
|
||||||
|
"md-switch",
|
||||||
|
"md-sync",
|
||||||
|
"md-tablet-landscape",
|
||||||
|
"md-tablet-portrait",
|
||||||
|
"md-tennisball",
|
||||||
|
"md-text",
|
||||||
|
"md-thermometer",
|
||||||
|
"md-thumbs-down",
|
||||||
|
"md-thumbs-up",
|
||||||
|
"md-thunderstorm",
|
||||||
|
"md-time",
|
||||||
|
"md-timer",
|
||||||
|
"md-train",
|
||||||
|
"md-transgender",
|
||||||
|
"md-trash",
|
||||||
|
"md-trending-down",
|
||||||
|
"md-trending-up",
|
||||||
|
"md-trophy",
|
||||||
|
"md-umbrella",
|
||||||
|
"md-undo",
|
||||||
|
"md-unlock",
|
||||||
|
"md-videocam",
|
||||||
|
"md-volume-down",
|
||||||
|
"md-volume-mute",
|
||||||
|
"md-volume-off",
|
||||||
|
"md-volume-up",
|
||||||
|
"md-walk",
|
||||||
|
"md-warning",
|
||||||
|
"md-watch",
|
||||||
|
"md-water",
|
||||||
|
"md-wifi",
|
||||||
|
"md-wine",
|
||||||
|
"md-woman"
|
||||||
|
]
|
||||||
@@ -75,7 +75,7 @@ export const defaultMenus = [
|
|||||||
{
|
{
|
||||||
id: 120,
|
id: 120,
|
||||||
name: '高级管理',
|
name: '高级管理',
|
||||||
path: '/system_high',
|
path: '/system',
|
||||||
component: '',
|
component: '',
|
||||||
parent_id: 0,
|
parent_id: 0,
|
||||||
type: '菜单',
|
type: '菜单',
|
||||||
@@ -86,8 +86,8 @@ export const defaultMenus = [
|
|||||||
{
|
{
|
||||||
id: 122,
|
id: 122,
|
||||||
name: '菜单管理',
|
name: '菜单管理',
|
||||||
path: '/system_high/menu',
|
path: '/system/menu',
|
||||||
component: 'system_high/sys_menu',
|
component: 'system/sys_menu',
|
||||||
parent_id: 120,
|
parent_id: 120,
|
||||||
type: '页面',
|
type: '页面',
|
||||||
is_show_menu: 1,
|
is_show_menu: 1,
|
||||||
@@ -97,8 +97,8 @@ export const defaultMenus = [
|
|||||||
{
|
{
|
||||||
id: 123,
|
id: 123,
|
||||||
name: '控制管理',
|
name: '控制管理',
|
||||||
path: '/system_high/control',
|
path: '/system/control',
|
||||||
component: 'system_high/sys_control',
|
component: 'system/sys_control',
|
||||||
parent_id: 120,
|
parent_id: 120,
|
||||||
type: '页面',
|
type: '页面',
|
||||||
is_show_menu: 1,
|
is_show_menu: 1,
|
||||||
@@ -108,8 +108,8 @@ export const defaultMenus = [
|
|||||||
{
|
{
|
||||||
id: 124,
|
id: 124,
|
||||||
name: '系统标题',
|
name: '系统标题',
|
||||||
path: '/system_high/title',
|
path: '/system/title',
|
||||||
component: 'system_high/sys_title',
|
component: 'system/sys_title',
|
||||||
parent_id: 120,
|
parent_id: 120,
|
||||||
type: '页面',
|
type: '页面',
|
||||||
is_show_menu: 1,
|
is_show_menu: 1,
|
||||||
|
|||||||
409
src/index.js
409
src/index.js
@@ -3,6 +3,14 @@
|
|||||||
* Version: 1.0.0
|
* Version: 1.0.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// 引入核心依赖
|
||||||
|
import Vue from 'vue'
|
||||||
|
import VueRouter from 'vue-router'
|
||||||
|
import Vuex from 'vuex'
|
||||||
|
import ViewUI from 'view-design'
|
||||||
|
|
||||||
|
// 引入样式
|
||||||
|
import 'view-design/dist/styles/iview.css'
|
||||||
import './assets/css/animate.css'
|
import './assets/css/animate.css'
|
||||||
import './assets/css/base.less'
|
import './assets/css/base.less'
|
||||||
import './assets/css/ivewExpand.less'
|
import './assets/css/ivewExpand.less'
|
||||||
@@ -12,194 +20,48 @@ import uiTool from './utils/uiTool'
|
|||||||
import http from './utils/http'
|
import http from './utils/http'
|
||||||
import * as tools from './utils/tools'
|
import * as tools from './utils/tools'
|
||||||
|
|
||||||
import storeModules, { userModule, appModule } from './store'
|
import storeModules, { createStore } from './store'
|
||||||
|
|
||||||
import routerConfig, { createBaseRoutes, setupRouterGuards } from './router'
|
import { createBaseRoutes, setupRouterGuards, createRouter, getRoutes } from './router'
|
||||||
|
|
||||||
import HomePage from './views/home/index.vue'
|
|
||||||
|
|
||||||
import SysLog from './views/system/sys_log.vue'
|
import components ,{ registerGlobalComponents, registerComponents} from './components/index'
|
||||||
import SysParamSetup from './views/system/sys_param_setup.vue'
|
|
||||||
import SysRole from './views/system/sys_role.vue'
|
|
||||||
import SysUser from './views/system/sys_user.vue'
|
|
||||||
|
|
||||||
import SysControl from './views/system_high/sys_control.vue'
|
import pages from './views/index'
|
||||||
import SysMenu from './views/system_high/sys_menu.vue'
|
|
||||||
import SysTitle from './views/system_high/sys_title.vue'
|
|
||||||
|
|
||||||
import LoginPage from './views/login/login.vue'
|
const { LoginPage, Page401, Page404, Page500, setupComponentMap, HomePage } = pages
|
||||||
|
|
||||||
import Page401 from './views/error-page/401.vue'
|
|
||||||
import Page404 from './views/error-page/404.vue'
|
|
||||||
import Page500 from './views/error-page/500.vue'
|
|
||||||
|
|
||||||
|
// 导入页面组件
|
||||||
import Main from './components/main'
|
import Main from './components/main'
|
||||||
import ParentView from './components/parent-view'
|
import ParentView from './components/parent-view'
|
||||||
|
|
||||||
import Tables from './components/tables'
|
|
||||||
import UploadSingle from './components/upload/Single.vue'
|
|
||||||
import UploadMultiple from './components/upload/Multiple.vue'
|
|
||||||
import TreeGrid from './components/treeGrid'
|
|
||||||
import AsyncModal from './components/asyncModal'
|
|
||||||
import InfoCard from './components/info-card'
|
|
||||||
import LoadFlower from './components/load-flower'
|
|
||||||
import SplitPane from './components/split-pane'
|
|
||||||
import TextArea from './components/text-area'
|
|
||||||
import CommonIcon from './components/common-icon'
|
|
||||||
import Editor from './components/editor/index.vue'
|
|
||||||
import editModal from './components/tables/editModal.vue'
|
|
||||||
import fieldItem from './components/tables/fieldItem.vue'
|
|
||||||
|
|
||||||
import * as systemApi from './api/system'
|
import * as systemApi from './api/system'
|
||||||
import * as systemHighApi from './api/system_high'
|
|
||||||
|
|
||||||
class AdminFramework {
|
class AdminFramework {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.version = '1.0.0'
|
this.version = '1.0.0'
|
||||||
this.installed = false
|
|
||||||
this.config = {}
|
this.config = {}
|
||||||
this.store = null
|
this.store = null
|
||||||
this.router = null
|
this.router = null
|
||||||
|
this.HomePage = pages.HomePage // 默认使用框架内置的 HomePage
|
||||||
|
|
||||||
this.tools = tools
|
this.tools = tools
|
||||||
this.uiTool = uiTool
|
this.uiTool = uiTool
|
||||||
this.http = http
|
this.http = http
|
||||||
|
|
||||||
this.storeModules = storeModules
|
this.storeModules = storeModules
|
||||||
this.userModule = userModule
|
|
||||||
this.appModule = appModule
|
|
||||||
|
|
||||||
this.createBaseRoutes = createBaseRoutes
|
this.createBaseRoutes = createBaseRoutes
|
||||||
this.setupRouterGuards = setupRouterGuards
|
this.setupRouterGuards = setupRouterGuards
|
||||||
|
this.registerComponents = registerComponents
|
||||||
this.Main = Main
|
this.pages = pages
|
||||||
this.ParentView = ParentView
|
this.components = components
|
||||||
this.LoginPage = LoginPage
|
|
||||||
this.Page401 = Page401
|
|
||||||
this.Page404 = Page404
|
|
||||||
this.Page500 = Page500
|
|
||||||
|
|
||||||
this.HomePage = HomePage
|
|
||||||
this.SysLog = SysLog
|
|
||||||
this.SysParamSetup = SysParamSetup
|
|
||||||
this.SysRole = SysRole
|
|
||||||
this.SysUser = SysUser
|
|
||||||
this.SysControl = SysControl
|
|
||||||
this.SysMenu = SysMenu
|
|
||||||
this.SysTitle = SysTitle
|
|
||||||
|
|
||||||
this.systemApi = systemApi
|
this.systemApi = systemApi
|
||||||
this.systemHighApi = systemHighApi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Vue plugin install method
|
|
||||||
* @param {Object} Vue - Vue instance
|
|
||||||
* @param {Object} options - config options
|
|
||||||
*/
|
|
||||||
install(Vue, options = {}) {
|
|
||||||
if (this.installed) return
|
|
||||||
this.installed = true
|
|
||||||
|
|
||||||
const { config = {}, ViewUI, VueRouter, Vuex, createPersistedState, componentMap } = options
|
|
||||||
this.config = config
|
|
||||||
|
|
||||||
if (ViewUI) {
|
|
||||||
Vue.use(ViewUI)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (VueRouter) {
|
|
||||||
Vue.use(VueRouter)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Vuex) {
|
|
||||||
Vue.use(Vuex)
|
|
||||||
}
|
|
||||||
|
|
||||||
Vue.prototype.$config = config
|
|
||||||
Vue.prototype.$http = http
|
|
||||||
Vue.prototype.$tools = tools
|
|
||||||
Vue.prototype.$uiTool = uiTool
|
|
||||||
|
|
||||||
this.registerGlobalComponents(Vue)
|
|
||||||
|
|
||||||
this.setupComponentMap(componentMap)
|
|
||||||
|
|
||||||
if (Vuex && !this.store) {
|
|
||||||
this.store = this.createStore(Vuex, {}, createPersistedState)
|
|
||||||
http.init(config, this.store)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (VueRouter && !this.router) {
|
|
||||||
const mainRoute = this.getRoutes({ Main, ParentView, Page404, HomePage: this.HomePage })
|
|
||||||
|
|
||||||
this.router = this.createRouter(VueRouter, {
|
|
||||||
Main,
|
|
||||||
ParentView,
|
|
||||||
LoginPage,
|
|
||||||
Page401,
|
|
||||||
Page404,
|
|
||||||
Page500
|
|
||||||
}, mainRoute ? [mainRoute] : [], ViewUI)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register global components
|
|
||||||
*/
|
|
||||||
registerGlobalComponents(Vue) {
|
|
||||||
Vue.component('Main', Main)
|
|
||||||
Vue.component('ParentView', ParentView)
|
|
||||||
|
|
||||||
Vue.component('Page401', Page401)
|
|
||||||
Vue.component('Page404', Page404)
|
|
||||||
Vue.component('Page500', Page500)
|
|
||||||
|
|
||||||
Vue.component('LoginPage', LoginPage)
|
|
||||||
|
|
||||||
Vue.component('Tables', Tables)
|
|
||||||
Vue.component('UploadSingle', UploadSingle)
|
|
||||||
Vue.component('UploadMultiple', UploadMultiple)
|
|
||||||
Vue.component('TreeGrid', TreeGrid)
|
|
||||||
Vue.component('AsyncModal', AsyncModal)
|
|
||||||
Vue.component('InfoCard', InfoCard)
|
|
||||||
Vue.component('LoadFlower', LoadFlower)
|
|
||||||
Vue.component('SplitPane', SplitPane)
|
|
||||||
Vue.component('TextArea', TextArea)
|
|
||||||
Vue.component('CommonIcon', CommonIcon)
|
|
||||||
Vue.component('Editor', Editor)
|
|
||||||
Vue.component('editModal', editModal)
|
|
||||||
Vue.component('fieldItem', fieldItem)
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup component map
|
|
||||||
* @param {Object} customMap - custom component map
|
|
||||||
*/
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
const map = {}
|
|
||||||
Object.keys(components).forEach(path => {
|
|
||||||
const cleanPath = path.replace(/\.vue$/, '')
|
|
||||||
map[cleanPath] = components[path]
|
|
||||||
map[cleanPath + '.vue'] = components[path]
|
|
||||||
})
|
|
||||||
|
|
||||||
uiTool.setComponentMap(map)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add custom component map
|
* Add custom component map
|
||||||
@@ -211,7 +73,7 @@ class AdminFramework {
|
|||||||
* })
|
* })
|
||||||
*/
|
*/
|
||||||
addComponentMap(customMap) {
|
addComponentMap(customMap) {
|
||||||
uiTool.setComponentMap(customMap)
|
setupComponentMap(customMap, uiTool)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -224,125 +86,144 @@ class AdminFramework {
|
|||||||
this.store = store
|
this.store = store
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create router instance
|
|
||||||
* @param {Object} Router - VueRouter class
|
|
||||||
* @param {Object} components - component object
|
|
||||||
* @param {Array} customRoutes - custom routes
|
|
||||||
* @param {Object} ViewUI - ViewUI instance
|
|
||||||
* @param {String} homeName - home page name
|
|
||||||
* @returns {Object} router instance
|
|
||||||
*/
|
|
||||||
createRouter(Router, components = {}, customRoutes = [], ViewUI, homeName = 'home') {
|
|
||||||
const { LoginPage, Page401, Page404, Page500 } = components
|
|
||||||
|
|
||||||
if (!LoginPage || !Page401 || !Page404 || !Page500) {
|
|
||||||
console.error('Missing required page components')
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
const baseRoutes = createBaseRoutes(LoginPage, Page401, Page404, Page500)
|
|
||||||
|
|
||||||
const router = new Router({
|
|
||||||
routes: [...baseRoutes, ...customRoutes],
|
|
||||||
mode: 'hash'
|
|
||||||
})
|
|
||||||
|
|
||||||
if (ViewUI) {
|
|
||||||
setupRouterGuards(router, ViewUI, homeName)
|
|
||||||
}
|
|
||||||
|
|
||||||
return router
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create Store instance
|
* Create app with simplified API (推荐使用)
|
||||||
* @param {Object} Vuex - Vuex class
|
* @param {Object} config - application config
|
||||||
* @param {Object} customModules - custom modules
|
* @param {String} config.title - application title
|
||||||
* @param {Object} createPersistedState - vuex-persistedstate plugin
|
* @param {String} config.apiUrl - API base URL
|
||||||
* @returns {Object} store instance
|
* @param {String} config.uploadUrl - upload URL (可选,默认为 apiUrl + 'upload')
|
||||||
|
* @param {Object} config.componentMap - custom component map (optional)
|
||||||
|
* @param {Component} config.HomePage - custom home page component (optional)
|
||||||
|
* @param {Function} config.onReady - callback when app is ready (optional)
|
||||||
|
* @returns {Object} Vue instance
|
||||||
*/
|
*/
|
||||||
createStore(Vuex, customModules = {}, createPersistedState) {
|
createApp(config = {}) {
|
||||||
const store = new Vuex.Store({
|
// 如果没有提供 uploadUrl,自动从 apiUrl 推导
|
||||||
modules: {
|
if (!config.uploadUrl && config.apiUrl) {
|
||||||
user: userModule,
|
config.uploadUrl = config.apiUrl + (config.apiUrl.endsWith('/') ? 'upload' : '/upload')
|
||||||
app: appModule,
|
}
|
||||||
...customModules
|
|
||||||
},
|
// 如果提供了自定义 HomePage,使用自定义的,否则使用默认的
|
||||||
plugins: createPersistedState ? [
|
if (config.HomePage) {
|
||||||
createPersistedState({
|
this.HomePage = config.HomePage
|
||||||
storage: window.localStorage
|
}
|
||||||
|
|
||||||
|
// 设置配置
|
||||||
|
this.config = config
|
||||||
|
|
||||||
|
// 初始化 Vue 插件
|
||||||
|
Vue.use(ViewUI)
|
||||||
|
Vue.use(VueRouter)
|
||||||
|
Vue.use(Vuex)
|
||||||
|
|
||||||
|
// 设置全局属性
|
||||||
|
Vue.prototype.$config = config
|
||||||
|
Vue.prototype.$http = http
|
||||||
|
Vue.prototype.$tools = tools
|
||||||
|
Vue.prototype.$uiTool = uiTool
|
||||||
|
Vue.prototype.$framework = this
|
||||||
|
|
||||||
|
// 注册全局组件
|
||||||
|
registerGlobalComponents(Vue)
|
||||||
|
|
||||||
|
// 设置组件映射
|
||||||
|
setupComponentMap(config.componentMap || {}, uiTool)
|
||||||
|
|
||||||
|
// 创建 Store
|
||||||
|
if (!this.store) {
|
||||||
|
this.store = createStore(Vuex, {}, null)
|
||||||
|
http.init(config, this.store)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建 Router
|
||||||
|
if (!this.router) {
|
||||||
|
const mainRoute = getRoutes({ Main, ParentView, Page404, HomePage: this.HomePage }, uiTool)
|
||||||
|
|
||||||
|
this.router = createRouter(VueRouter, {
|
||||||
|
Main,
|
||||||
|
ParentView,
|
||||||
|
LoginPage,
|
||||||
|
Page401,
|
||||||
|
Page404,
|
||||||
|
Page500
|
||||||
|
}, mainRoute ? [mainRoute] : [], ViewUI)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create Vue instance with auto menu/title restoration
|
||||||
|
const app = new Vue({
|
||||||
|
router: this.router,
|
||||||
|
store: this.store,
|
||||||
|
render: h => h('router-view'),
|
||||||
|
async created() {
|
||||||
|
// 初始化响应式 rem 设置
|
||||||
|
|
||||||
|
uiTool.setRem()
|
||||||
|
|
||||||
|
// 监听窗口大小变化,重新设置 rem
|
||||||
|
window.addEventListener('resize', () => {
|
||||||
|
uiTool.setRem()
|
||||||
})
|
})
|
||||||
] : []
|
|
||||||
|
console.log('=== Admin Framework App Started ===')
|
||||||
|
console.log('Framework Version:', framework.version)
|
||||||
|
console.log('Config:', this.$config)
|
||||||
|
|
||||||
|
|
||||||
|
// Auto restore menu and title on refresh
|
||||||
|
const token = this.$store.state.user.token
|
||||||
|
const authorityMenus = localStorage.getItem('authorityMenus')
|
||||||
|
|
||||||
|
if (token && authorityMenus) {
|
||||||
|
console.log('Restoring menu and title...')
|
||||||
|
try {
|
||||||
|
// Restore menu
|
||||||
|
await this.$store.dispatch('user/setAuthorityMenus', {
|
||||||
|
Main: framework.Main,
|
||||||
|
ParentView: framework.ParentView,
|
||||||
|
Page404: framework.Page404,
|
||||||
|
HomePage: framework.HomePage,
|
||||||
|
authorityMenus: authorityMenus
|
||||||
|
})
|
||||||
|
console.log('Menu restored')
|
||||||
|
|
||||||
|
// Get system title
|
||||||
|
await this.$store.dispatch('app/getSysTitle', {
|
||||||
|
defaultTitle: this.$config.title,
|
||||||
|
defaultLogo: ''
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Restore failed:', error)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Not logged in, use default title
|
||||||
|
console.log('Not logged in, using default title')
|
||||||
|
document.title = this.$config.title
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call user callback if provided
|
||||||
|
if (config.onReady && typeof config.onReady === 'function') {
|
||||||
|
config.onReady.call(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
this.store = store
|
// Expose to global for debugging
|
||||||
return store
|
if (typeof window !== 'undefined') {
|
||||||
}
|
window.rootVue = app
|
||||||
|
window.framework = framework
|
||||||
/**
|
|
||||||
* Get dynamic routes
|
|
||||||
* @param {Object} components - component object
|
|
||||||
* @returns {Object} main route config
|
|
||||||
*/
|
|
||||||
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 || this.HomePage)
|
return app
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register global components
|
|
||||||
* @param {Object} Vue - Vue instance
|
|
||||||
* @param {Object} components - component object
|
|
||||||
*/
|
|
||||||
registerComponents(Vue, components = {}) {
|
|
||||||
Object.keys(components).forEach(name => {
|
|
||||||
Vue.component(name, components[name])
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const framework = new AdminFramework()
|
const framework = new AdminFramework()
|
||||||
|
|
||||||
|
// 【关键】框架实例创建后立即暴露到全局,确保在任何地方都能访问
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
window.framework = framework
|
||||||
|
}
|
||||||
|
|
||||||
export default framework
|
export default framework
|
||||||
|
|
||||||
export {
|
|
||||||
tools,
|
|
||||||
uiTool,
|
|
||||||
http,
|
|
||||||
|
|
||||||
storeModules,
|
|
||||||
userModule,
|
|
||||||
appModule,
|
|
||||||
|
|
||||||
createBaseRoutes,
|
|
||||||
setupRouterGuards,
|
|
||||||
|
|
||||||
HomePage,
|
|
||||||
SysLog,
|
|
||||||
SysParamSetup,
|
|
||||||
SysRole,
|
|
||||||
SysUser,
|
|
||||||
SysControl,
|
|
||||||
SysMenu,
|
|
||||||
SysTitle,
|
|
||||||
|
|
||||||
LoginPage,
|
|
||||||
Page401,
|
|
||||||
Page404,
|
|
||||||
Page500,
|
|
||||||
|
|
||||||
Main,
|
|
||||||
ParentView,
|
|
||||||
|
|
||||||
systemApi,
|
|
||||||
systemHighApi,
|
|
||||||
|
|
||||||
AdminFramework
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -57,6 +57,25 @@ export const setupRouterGuards = (router, ViewUI, homeName = 'home') => {
|
|||||||
next({ name: homeName })
|
next({ name: homeName })
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// 已登录,检查路由是否存在
|
||||||
|
if (token && to.matched.length === 0 && to.path !== '/') {
|
||||||
|
// 路由不存在,可能是动态路由还未加载完成
|
||||||
|
console.warn('路由未找到:', to.name || to.path, ',尝试等待动态路由加载')
|
||||||
|
|
||||||
|
// 等待一小段时间后重试
|
||||||
|
setTimeout(() => {
|
||||||
|
// 检查路由是否已经存在
|
||||||
|
const route = router.resolve(to.path)
|
||||||
|
if (route && route.matched.length > 0) {
|
||||||
|
next({ path: to.path, replace: true })
|
||||||
|
} else {
|
||||||
|
console.error('路由仍然不存在:', to.name || to.path, ',跳转到首页')
|
||||||
|
next({ name: homeName, replace: true })
|
||||||
|
}
|
||||||
|
}, 150)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// 其他情况 → 允许访问
|
// 其他情况 → 允许访问
|
||||||
next()
|
next()
|
||||||
}
|
}
|
||||||
@@ -70,8 +89,45 @@ export const setupRouterGuards = (router, ViewUI, homeName = 'home') => {
|
|||||||
return router
|
return router
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
// 获取动态路由的方法
|
||||||
createBaseRoutes,
|
export function getRoutes(components = {}, uiTool) {
|
||||||
setupRouterGuards
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建路由实例的方法
|
||||||
|
export function createRouter(Router, components = {}, customRoutes = [], ViewUI) {
|
||||||
|
const { LoginPage, Page401, Page404, Page500 } = components
|
||||||
|
|
||||||
|
if (!LoginPage || !Page401 || !Page404 || !Page500) {
|
||||||
|
console.error('Missing required page components')
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const baseRoutes = createBaseRoutes(LoginPage, Page401, Page404, Page500)
|
||||||
|
|
||||||
|
const router = new Router({
|
||||||
|
routes: [...baseRoutes, ...customRoutes],
|
||||||
|
mode: 'hash'
|
||||||
|
})
|
||||||
|
|
||||||
|
if (ViewUI) {
|
||||||
|
setupRouterGuards(router, ViewUI, 'home')
|
||||||
|
}
|
||||||
|
|
||||||
|
return router
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
createBaseRoutes,
|
||||||
|
setupRouterGuards,
|
||||||
|
createRouter,
|
||||||
|
getRoutes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { getBreadCrumbList, getHomeRoute } from '../utils/tools'
|
import { getBreadCrumbList, getHomeRoute } from '../utils/tools'
|
||||||
import paramSetupServer from '../api/system_high/paramSetupServer'
|
import paramSetupServer from '../api/system/paramSetupServer'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
namespaced: true,
|
namespaced: true,
|
||||||
@@ -26,9 +26,9 @@ export default {
|
|||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
async getSysTitle({ state, commit, rootState }, { defaultTitle, defaultLogo = '' } = {}) {
|
async getSysTitle({ state, commit, rootState }, { defaultTitle, defaultLogo = '' } = {}) {
|
||||||
// 如果没有传入 defaultTitle,尝试从 Vue 实例的配置中获取
|
// 如果没有传入 defaultTitle,尝试从框架配置中获取
|
||||||
if (!defaultTitle && window.rootVue && window.rootVue.$config) {
|
if (!defaultTitle && window.framework && window.framework.config) {
|
||||||
defaultTitle = window.rootVue.$config.title || '智能代码平台'
|
defaultTitle = window.framework.config.title || '智能代码平台'
|
||||||
} else if (!defaultTitle) {
|
} else if (!defaultTitle) {
|
||||||
defaultTitle = '智能代码平台'
|
defaultTitle = '智能代码平台'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,27 @@
|
|||||||
import userModule from './user'
|
import userModule from './user'
|
||||||
import appModule from './app'
|
import appModule from './app'
|
||||||
|
|
||||||
export { userModule, appModule }
|
// 创建 Store 实例的方法
|
||||||
|
export function createStore(Vuex, customModules = {}, createPersistedState) {
|
||||||
|
const store = new Vuex.Store({
|
||||||
|
modules: {
|
||||||
|
user: userModule,
|
||||||
|
app: appModule,
|
||||||
|
...customModules
|
||||||
|
},
|
||||||
|
plugins: createPersistedState ? [
|
||||||
|
createPersistedState({
|
||||||
|
storage: window.localStorage
|
||||||
|
})
|
||||||
|
] : []
|
||||||
|
})
|
||||||
|
|
||||||
|
return store
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
user: userModule,
|
user: userModule,
|
||||||
app: appModule
|
app: appModule,
|
||||||
|
createStore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export default {
|
|||||||
menuList: state => state.menuList
|
menuList: state => state.menuList
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
async setAuthorityMenus({ state, commit }, { Main, ParentView, Page404, authorityMenus, menuIds }) {
|
async setAuthorityMenus({ state, commit }, { Main, ParentView, Page404, HomePage, authorityMenus, menuIds }) {
|
||||||
// 如果传入了 authorityMenus,直接使用;否则从接口获取
|
// 如果传入了 authorityMenus,直接使用;否则从接口获取
|
||||||
let menus = authorityMenus
|
let menus = authorityMenus
|
||||||
|
|
||||||
@@ -95,19 +95,20 @@ export default {
|
|||||||
commit('setAuthorityMenus', JSON.stringify(menus))
|
commit('setAuthorityMenus', JSON.stringify(menus))
|
||||||
|
|
||||||
// 生成路由菜单(传递 HomePage 组件)
|
// 生成路由菜单(传递 HomePage 组件)
|
||||||
// 从框架导出的组件中获取 HomePage
|
// 优先使用传入的 HomePage,如果没有则从框架实例中获取
|
||||||
const HomePage = window.framework && window.framework.HomePage ? window.framework.HomePage : null
|
const homePageComponent = HomePage || (window.framework && window.framework.HomePage) || null
|
||||||
let mainMenu = uiTool.getRoutes(Main, ParentView, Page404, HomePage)
|
let mainMenu = uiTool.getRoutes(Main, ParentView, Page404, homePageComponent)
|
||||||
console.log('生成的主菜单:', mainMenu)
|
console.log('生成的主菜单:', mainMenu)
|
||||||
|
|
||||||
if (mainMenu && mainMenu.children) {
|
if (mainMenu && mainMenu.children) {
|
||||||
commit('setMenuList', mainMenu.children)
|
commit('setMenuList', mainMenu.children)
|
||||||
|
|
||||||
// 动态添加路由(重要!解决登录后点击菜单空白的问题)
|
// 动态添加路由(重要!解决登录后点击菜单空白的问题)
|
||||||
if (window.rootVue && window.rootVue.$router) {
|
// 从 window.framework 获取 router 实例
|
||||||
const router = window.rootVue.$router
|
const router = window.framework && window.framework.router
|
||||||
|
if (router) {
|
||||||
const routes = router.options.routes
|
const routes = router.options.routes
|
||||||
|
|
||||||
// 查找并移除旧的主路由
|
// 查找并移除旧的主路由
|
||||||
const mainRouteIndex = routes.findIndex(r => r.path === '/')
|
const mainRouteIndex = routes.findIndex(r => r.path === '/')
|
||||||
if (mainRouteIndex !== -1) {
|
if (mainRouteIndex !== -1) {
|
||||||
@@ -117,6 +118,11 @@ export default {
|
|||||||
// 添加新的主路由
|
// 添加新的主路由
|
||||||
router.addRoute(mainMenu)
|
router.addRoute(mainMenu)
|
||||||
console.log('动态路由已添加,redirect 设置为:', mainMenu.redirect)
|
console.log('动态路由已添加,redirect 设置为:', mainMenu.redirect)
|
||||||
|
|
||||||
|
// 等待路由更新完成
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 100))
|
||||||
|
} else {
|
||||||
|
console.warn('未找到 router 实例,动态路由添加失败')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -176,10 +182,13 @@ export default {
|
|||||||
|
|
||||||
// 调用 authorityMenus 接口获取完整菜单数据
|
// 调用 authorityMenus 接口获取完整菜单数据
|
||||||
// 如果接口失败,会使用默认菜单配置和 menuIds 进行过滤
|
// 如果接口失败,会使用默认菜单配置和 menuIds 进行过滤
|
||||||
|
// 从框架实例获取 HomePage
|
||||||
|
const HomePage = (window.framework && window.framework.HomePage) || null
|
||||||
await dispatch('setAuthorityMenus', {
|
await dispatch('setAuthorityMenus', {
|
||||||
Main,
|
Main,
|
||||||
ParentView,
|
ParentView,
|
||||||
Page404,
|
Page404,
|
||||||
|
HomePage,
|
||||||
menuIds
|
menuIds
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { formatDate } from './tools'
|
import { formatDate } from './tools'
|
||||||
|
|
||||||
|
|
||||||
class Http {
|
class Http {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.config = {
|
this.config = {}
|
||||||
apiUrl: '',
|
|
||||||
timeout: 300000
|
|
||||||
}
|
|
||||||
this.store = null
|
this.store = null
|
||||||
}
|
}
|
||||||
|
|
||||||
init(config, store) {
|
init(config, store) {
|
||||||
this.config = { ...this.config, ...config }
|
|
||||||
|
this.config = { timeout: 300000, ...config }
|
||||||
this.store = store
|
this.store = store
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,6 +24,8 @@ class Http {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getHttpInstance(config) {
|
getHttpInstance(config) {
|
||||||
|
|
||||||
|
console.log('getHttpInstance', this.baseUrl())
|
||||||
let defaultConfig = {
|
let defaultConfig = {
|
||||||
timeout: this.config.timeout,
|
timeout: this.config.timeout,
|
||||||
headers: {},
|
headers: {},
|
||||||
@@ -70,9 +72,10 @@ class Http {
|
|||||||
if (error && error.response && error.response.status === 401) {
|
if (error && error.response && error.response.status === 401) {
|
||||||
if (this.store) {
|
if (this.store) {
|
||||||
this.store.commit('user/setToken', '')
|
this.store.commit('user/setToken', '')
|
||||||
}
|
// 使用 store 中的 router 实例跳转
|
||||||
if (window.rootVue && window.rootVue.$router) {
|
if (window.framework && window.framework.router) {
|
||||||
window.rootVue.$router.push({ path: '/login' }) // 使用 path 而不是 name
|
window.framework.router.push({ path: '/login' })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return Promise.reject(error)
|
return Promise.reject(error)
|
||||||
}
|
}
|
||||||
@@ -106,8 +109,13 @@ class Http {
|
|||||||
}
|
}
|
||||||
|
|
||||||
showError(msg) {
|
showError(msg) {
|
||||||
if (window.rootVue && window.rootVue.$Message) {
|
// 使用框架存储的 ViewUI 实例
|
||||||
window.rootVue.$Message.error({ content: msg, duration: 3 })
|
if (window.framework && window.framework.ViewUI && window.framework.ViewUI.Message) {
|
||||||
|
window.framework.ViewUI.Message.error({ content: msg, duration: 3 })
|
||||||
|
} else if (window.$Message) {
|
||||||
|
window.$Message.error({ content: msg, duration: 3 })
|
||||||
|
} else {
|
||||||
|
console.error(msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,7 +194,7 @@ class Http {
|
|||||||
return promise
|
return promise
|
||||||
}
|
}
|
||||||
|
|
||||||
async fileExport(url, param) {
|
async fileExport(url, param, filename, is_down = true) {
|
||||||
let formData = this.formatFormDataParam(param)
|
let formData = this.formatFormDataParam(param)
|
||||||
|
|
||||||
let config = {
|
let config = {
|
||||||
@@ -198,14 +206,14 @@ class Http {
|
|||||||
url: url,
|
url: url,
|
||||||
responseType: 'blob'
|
responseType: 'blob'
|
||||||
}
|
}
|
||||||
|
|
||||||
let res = await axios.post(url, formData, config)
|
let res = await axios.post(url, formData, config)
|
||||||
const filename = res.headers.filename
|
// 直接下载
|
||||||
const a = document.createElement('a')
|
if (is_down) {
|
||||||
const href = window.URL.createObjectURL(res.data)
|
window.framework.uiTool.downloadFile(res.data, filename)
|
||||||
a.href = href
|
}
|
||||||
a.download = filename
|
|
||||||
a.click()
|
return res
|
||||||
window.URL.revokeObjectURL(url)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import http from './http'
|
|||||||
const componentMap = {}
|
const componentMap = {}
|
||||||
|
|
||||||
export default class uiTool {
|
export default class uiTool {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置组件映射表
|
* 设置组件映射表
|
||||||
* @param {Object} map - 组件映射对象
|
* @param {Object} map - 组件映射对象
|
||||||
@@ -12,7 +12,7 @@ export default class uiTool {
|
|||||||
static setComponentMap(map) {
|
static setComponentMap(map) {
|
||||||
Object.assign(componentMap, map)
|
Object.assign(componentMap, map)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据路径获取组件
|
* 根据路径获取组件
|
||||||
* @param {String} componentPath - 组件路径(如 "system/sys_user.vue")
|
* @param {String} componentPath - 组件路径(如 "system/sys_user.vue")
|
||||||
@@ -20,13 +20,33 @@ export default class uiTool {
|
|||||||
*/
|
*/
|
||||||
static getComponent(componentPath) {
|
static getComponent(componentPath) {
|
||||||
if (!componentPath) return null
|
if (!componentPath) return null
|
||||||
|
|
||||||
// 标准化路径(移除 .vue 后缀)
|
// 标准化路径(移除 .vue 后缀)
|
||||||
const normalizedPath = componentPath.replace(/\.vue$/, '')
|
const normalizedPath = componentPath.replace(/\.vue$/, '')
|
||||||
|
|
||||||
// 从映射表中查找
|
// 从映射表中查找
|
||||||
return componentMap[normalizedPath] || componentMap[componentPath]
|
return componentMap[normalizedPath] || componentMap[componentPath]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件下载工具
|
||||||
|
* @param {Object|Blob} res - 响应数据或Blob对象
|
||||||
|
* @param {String} fileName - 文件名(可选,默认为时间戳.csv)
|
||||||
|
*/
|
||||||
|
static downloadFile(res, fileName) {
|
||||||
|
// 开头和结尾去掉 中间不去掉
|
||||||
|
let tempFileName = fileName || `${new Date().getTime()}.csv`
|
||||||
|
|
||||||
|
const blob = new Blob([res.data || res])
|
||||||
|
const downloadElement = document.createElement('a')
|
||||||
|
const href = window.URL.createObjectURL(blob)
|
||||||
|
downloadElement.href = href
|
||||||
|
downloadElement.download = tempFileName
|
||||||
|
document.body.appendChild(downloadElement)
|
||||||
|
downloadElement.click()
|
||||||
|
document.body.removeChild(downloadElement)
|
||||||
|
window.URL.revokeObjectURL(href)
|
||||||
|
}
|
||||||
static setRem() {
|
static setRem() {
|
||||||
let whdef = 100 / 1920
|
let whdef = 100 / 1920
|
||||||
let bodyWidth = document.body.clientWidth
|
let bodyWidth = document.body.clientWidth
|
||||||
@@ -110,20 +130,22 @@ export default class uiTool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static delConfirm(callback) {
|
static delConfirm(callback) {
|
||||||
if (window.rootVue && window.rootVue.$Modal) {
|
const Modal = window.rootVue.$Modal
|
||||||
window.rootVue.$Modal.confirm({
|
|
||||||
title: '温馨提示',
|
Modal.confirm({
|
||||||
content: '<p>你确定删除吗?</p>',
|
title: '温馨提示',
|
||||||
onOk: () => {
|
content: '<p>你确定删除吗?</p>',
|
||||||
callback && callback()
|
onOk: () => {
|
||||||
}
|
callback && callback()
|
||||||
})
|
}
|
||||||
}
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static showConfirm({ title = '温馨提示', content = '内容' }, callback) {
|
static showConfirm({ title = '温馨提示', content = '内容' }, callback) {
|
||||||
if (window.rootVue && window.rootVue.$Modal) {
|
const Modal = window.rootVue.$Modal
|
||||||
window.rootVue.$Modal.confirm({
|
if (Modal) {
|
||||||
|
Modal.confirm({
|
||||||
title,
|
title,
|
||||||
content,
|
content,
|
||||||
onOk: () => {
|
onOk: () => {
|
||||||
@@ -169,10 +191,10 @@ export default class uiTool {
|
|||||||
} else if (item.type === '页面' || item.type === '功能') {
|
} else if (item.type === '页面' || item.type === '功能') {
|
||||||
try {
|
try {
|
||||||
let componentPath = item.component
|
let componentPath = item.component
|
||||||
|
|
||||||
// 从组件映射表中获取组件
|
// 从组件映射表中获取组件
|
||||||
let component = uiTool.getComponent(componentPath)
|
let component = uiTool.getComponent(componentPath)
|
||||||
|
|
||||||
if (component) {
|
if (component) {
|
||||||
// 找到了对应的组件
|
// 找到了对应的组件
|
||||||
item.component = component
|
item.component = component
|
||||||
@@ -277,7 +299,7 @@ export default class uiTool {
|
|||||||
// 递归检查所有层级中是否有首页路由
|
// 递归检查所有层级中是否有首页路由
|
||||||
const hasHomeInRoutes = (routes) => {
|
const hasHomeInRoutes = (routes) => {
|
||||||
if (!routes || !Array.isArray(routes)) return false
|
if (!routes || !Array.isArray(routes)) return false
|
||||||
|
|
||||||
for (let route of routes) {
|
for (let route of routes) {
|
||||||
// 检查当前路由的 path
|
// 检查当前路由的 path
|
||||||
if (route.path === '/home' || route.path === 'home') {
|
if (route.path === '/home' || route.path === 'home') {
|
||||||
@@ -295,7 +317,7 @@ export default class uiTool {
|
|||||||
|
|
||||||
const homeRoute = mainRoute.children.find(r => r.path === '/home')
|
const homeRoute = mainRoute.children.find(r => r.path === '/home')
|
||||||
const hasHome = hasHomeInRoutes(curRoutes)
|
const hasHome = hasHomeInRoutes(curRoutes)
|
||||||
|
|
||||||
if (hasHome) {
|
if (hasHome) {
|
||||||
// 如果权限路由中有 home,使用权限路由的 home(不添加默认首页)
|
// 如果权限路由中有 home,使用权限路由的 home(不添加默认首页)
|
||||||
mainRoute.children = curRoutes
|
mainRoute.children = curRoutes
|
||||||
@@ -310,14 +332,14 @@ export default class uiTool {
|
|||||||
// 优先查找首页路由,如果没有则使用第一个菜单项
|
// 优先查找首页路由,如果没有则使用第一个菜单项
|
||||||
const findFirstRoute = (routes) => {
|
const findFirstRoute = (routes) => {
|
||||||
if (!routes || routes.length === 0) return null
|
if (!routes || routes.length === 0) return null
|
||||||
|
|
||||||
for (let route of routes) {
|
for (let route of routes) {
|
||||||
// 优先查找 /home 路由
|
// 优先查找 /home 路由
|
||||||
if (route.path === '/home' || route.path === 'home') {
|
if (route.path === '/home' || route.path === 'home') {
|
||||||
return route.path.startsWith('/') ? route.path : '/' + route.path
|
return route.path.startsWith('/') ? route.path : '/' + route.path
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果没有 home,使用第一个页面路由
|
// 如果没有 home,使用第一个页面路由
|
||||||
for (let route of routes) {
|
for (let route of routes) {
|
||||||
if (route.type !== '菜单' && route.path) {
|
if (route.type !== '菜单' && route.path) {
|
||||||
@@ -329,7 +351,7 @@ export default class uiTool {
|
|||||||
if (childRoute) return childRoute
|
if (childRoute) return childRoute
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
70
src/views/index.js
Normal file
70
src/views/index.js
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
import HomePage from './home/index.vue'
|
||||||
|
|
||||||
|
import SysLog from './system/sys_log.vue'
|
||||||
|
import SysParamSetup from './system/sys_param_setup.vue'
|
||||||
|
import SysRole from './system/sys_role.vue'
|
||||||
|
import SysUser from './system/sys_user.vue'
|
||||||
|
import SysLogOperate from './system/sys_log_operate.vue'
|
||||||
|
|
||||||
|
|
||||||
|
import SysControl from './system/sys_control.vue'
|
||||||
|
import SysMenu from './system/sys_menu.vue'
|
||||||
|
import SysTitle from './system/sys_title.vue'
|
||||||
|
|
||||||
|
import LoginPage from './login/login.vue'
|
||||||
|
|
||||||
|
import Page401 from './error-page/401.vue'
|
||||||
|
import Page404 from './error-page/404.vue'
|
||||||
|
import Page500 from './error-page/500.vue'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 设置组件映射的方法
|
||||||
|
export function setupComponentMap(customMap = {}, uiTool) {
|
||||||
|
|
||||||
|
|
||||||
|
if (!customMap["home/index"]) {
|
||||||
|
customMap["home/index"] = HomePage
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const componentMap = {
|
||||||
|
'system/sys_log': SysLog,
|
||||||
|
'system/sys_param_setup': SysParamSetup,
|
||||||
|
'system/sys_role': SysRole,
|
||||||
|
'system/sys_user': SysUser,
|
||||||
|
'system/sys_control': SysControl,
|
||||||
|
'system/sys_menu': SysMenu,
|
||||||
|
'system/sys_title': SysTitle,
|
||||||
|
'system/sys_log_operate': SysLogOperate,
|
||||||
|
...customMap
|
||||||
|
}
|
||||||
|
|
||||||
|
const map = {}
|
||||||
|
Object.keys(componentMap).forEach(path => {
|
||||||
|
const cleanPath = path.replace(/\.vue$/, '')
|
||||||
|
map[cleanPath] = componentMap[path]
|
||||||
|
map[cleanPath + '.vue'] = componentMap[path]
|
||||||
|
})
|
||||||
|
|
||||||
|
uiTool.setComponentMap(map)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
SysLog,
|
||||||
|
SysLogOperate,
|
||||||
|
SysParamSetup,
|
||||||
|
SysRole,
|
||||||
|
SysUser,
|
||||||
|
SysControl,
|
||||||
|
SysMenu,
|
||||||
|
SysTitle,
|
||||||
|
LoginPage,
|
||||||
|
Page401,
|
||||||
|
Page404,
|
||||||
|
Page500,
|
||||||
|
setupComponentMap
|
||||||
|
}
|
||||||
@@ -21,8 +21,8 @@
|
|||||||
<script>
|
<script>
|
||||||
import tools from '@/utils/tools'
|
import tools from '@/utils/tools'
|
||||||
import uiTool from '@/utils/uiTool'
|
import uiTool from '@/utils/uiTool'
|
||||||
import modelServer from '@/api/system_high/modelServer.js'
|
import modelServer from '@/api/system/modelServer.js'
|
||||||
import sysControlTypeServer from '@/api/system_high/sysControlTypeServer.js'
|
import sysControlTypeServer from '@/api/system/sysControlTypeServer.js'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
@@ -119,7 +119,7 @@ export default {
|
|||||||
async showAddWarp() {
|
async showAddWarp() {
|
||||||
this.$refs.editModal.addShow({}, async (newRow) => {
|
this.$refs.editModal.addShow({}, async (newRow) => {
|
||||||
let res = await sysControlTypeServer.add(newRow)
|
let res = await sysControlTypeServer.add(newRow)
|
||||||
rootVue.$Message.success('新增成功!')
|
this.$Message.success('新增成功!')
|
||||||
this.init()
|
this.init()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -128,7 +128,7 @@ export default {
|
|||||||
let valid = await this.$refs['editModal'].$refs['From'].validate()
|
let valid = await this.$refs['editModal'].$refs['From'].validate()
|
||||||
if (valid) {
|
if (valid) {
|
||||||
let res = await sysControlTypeServer.edit(newRow)
|
let res = await sysControlTypeServer.edit(newRow)
|
||||||
rootVue.$Message.success('修改成功!')
|
this.$Message.success('修改成功!')
|
||||||
this.init()
|
this.init()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -137,7 +137,7 @@ export default {
|
|||||||
async delConfirm(row) {
|
async delConfirm(row) {
|
||||||
uiTool.delConfirm(async () => {
|
uiTool.delConfirm(async () => {
|
||||||
await sysControlTypeServer.del(row)
|
await sysControlTypeServer.del(row)
|
||||||
rootVue.$Message.success('删除成功!')
|
this.$Message.success('删除成功!')
|
||||||
this.init()
|
this.init()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
<div class="content-view ">
|
<div class="content-view ">
|
||||||
<div class="tree-box">
|
<div class="tree-box">
|
||||||
<div class="btn-top-box pa10">
|
<div class="btn-top-box pa10">
|
||||||
<Button type="warning" size="small" @click="delAll">全部删除</Button>
|
<Button type="warning" size="small" @click="delAll">全部删除2</Button>
|
||||||
</div>
|
</div>
|
||||||
<Tree class="mt10" :data="treeData" :render="renderContent" @on-select-change="selectChange"></Tree>
|
<Tree class="mt10" :data="treeData" :render="renderContent" @on-select-change="selectChange"></Tree>
|
||||||
</div>
|
</div>
|
||||||
@@ -83,25 +83,33 @@ export default {
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
h('span', data.title),
|
h('span', data.title),
|
||||||
h('Icon', {
|
h('span', {
|
||||||
props: {
|
|
||||||
type: 'ios-trash',
|
|
||||||
size: '18'
|
|
||||||
},
|
|
||||||
on: {
|
on: {
|
||||||
click: () => {
|
click: (e) => {
|
||||||
|
e.stopPropagation() // 阻止事件冒泡
|
||||||
|
e.preventDefault() // 阻止默认行为
|
||||||
this.deleteLog(data)
|
this.deleteLog(data)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
style: {
|
style: {
|
||||||
'margin-left': '8px'
|
'margin-left': '8px',
|
||||||
|
cursor: 'pointer',
|
||||||
|
display: 'inline-block'
|
||||||
}
|
}
|
||||||
})
|
}, [
|
||||||
|
h('Icon', {
|
||||||
|
props: {
|
||||||
|
type: 'ios-trash',
|
||||||
|
size: '18'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
])
|
||||||
])
|
])
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
async selectChange(row) {
|
async selectChange(row) {
|
||||||
|
|
||||||
row[0].selected = true
|
row[0].selected = true
|
||||||
this.selectRow = row[0].title
|
this.selectRow = row[0].title
|
||||||
let res = await sys_log_serve.detail({ title: this.selectRow })
|
let res = await sys_log_serve.detail({ title: this.selectRow })
|
||||||
@@ -135,7 +143,7 @@ export default {
|
|||||||
.content-view {
|
.content-view {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
.tree-box {
|
.log-box {
|
||||||
height: 90vh;
|
height: 90vh;
|
||||||
width: 300px;
|
width: 300px;
|
||||||
border-right: solid 1px #ccc;
|
border-right: solid 1px #ccc;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user