diff --git a/CHANGELOG.md b/CHANGELOG.md index d4b8a4ba..fd2cef30 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,46 @@ +# 2.11.5 (2024/6/18) + +## ✨ feat + +- 支持后端文件导入([#142](https://github.com/youlaitech/vue3-element-admin/pull/142)) [@cshaptx4869](https://github.com/cshaptx4869) + + +## 🐛 fix +- vue-dev-tools 插件导致菜单路由切换卡死,暂时关闭 ([28349e](https://github.com/youlaitech/vue3-element-admin/commit/28349efe147afab36531ba148eaac3a448fe6c71)) [@haoxianrui](https://github.com/haoxianrui) + + + +# 2.11.4 (2024/6/16) + +## ✨ feat + +- 操作栏增加render配置参数([#138](https://github.com/youlaitech/vue3-element-admin/pull/140)) [@cshaptx4869](https://github.com/cshaptx4869) +- 左侧工具栏增加type配置参数([#141](https://github.com/youlaitech/vue3-element-admin/pull/141)) [@diamont1001](https://github.com/diamont1001) + +## ♻️ refactor +- 更换权限分配弹窗类型为 drawer 并添加父子联动开关([2d9193](https://github.com/youlaitech/vue3-element-admin/commit/2d9193c47fd224f01f82b9c0b2bbeb5e7cb33584)) [@haoxianrui](https://github.com/haoxianrui) + + + +# 2.11.3 (2024/6/11) + +## ✨ feat + +- 支持默认工具栏的导入([#138](https://github.com/youlaitech/vue3-element-admin/pull/138)) [@cshaptx4869](https://github.com/cshaptx4869) +- 添加CURD导入示例([19e7bb](https://github.com/youlaitech/vue3-element-admin/commit/eab91effd6a01d5a3d9257249c8d06aa252b3bf8)) [@cshaptx4869](https://github.com/cshaptx4869) + +## ♻️ refactor +- 修改导出全量数据选项文本([904fec](https://github.com/youlaitech/vue3-element-admin/commit/904fecad65217650482fcdbb10ffb7f3d27eb9ea)) [@cshaptx4869](https://github.com/cshaptx4869) + +## 🐛 fix +- 菜单列表未适配el-icon导致图标不显示问题修复([e72b68](https://github.com/youlaitech/vue3-element-admin/commit/e72b68337562b5a7ea24ad55bbe00023e1266b40)) [@haoxianrui](https://github.com/haoxianrui) + # 2.11.2 (2024/6/8) ## ✨ feat -- 支持表格远程筛选([#131](https://github.com/youlaitech/vue3-element-admin/pull/119)) [@cshaptx4869](https://github.com/cshaptx4869) +- 支持表格远程筛选([#131](https://github.com/youlaitech/vue3-element-admin/pull/131)) [@cshaptx4869](https://github.com/cshaptx4869) - 支持标签输入框([#132](https://github.com/youlaitech/vue3-element-admin/pull/132)) [@cshaptx4869](https://github.com/cshaptx4869) - 表单项支持tips配置([#133](https://github.com/youlaitech/vue3-element-admin/pull/133)) [@cshaptx4869](https://github.com/cshaptx4869) - 前端导出支持全量数据([#134](https://github.com/youlaitech/vue3-element-admin/pull/134)) [@cshaptx4869](https://github.com/cshaptx4869) diff --git a/README.en-US.md b/README.en-US.md index 5112d0ad..68cc3371 100644 --- a/README.en-US.md +++ b/README.en-US.md @@ -1,6 +1,6 @@
- - + + diff --git a/README.md b/README.md index 986bea32..5566178c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@
- - + + @@ -30,7 +30,7 @@ - **基础设施**:动态路由、按钮权限、国际化、代码规范、Git 提交规范、常用组件封装。 -- **持续更新**:自2021年起,该项目持续开源更新,实时更新工具和依赖,积累了广泛的用户群体。 +- **持续更新**:项目持续开源更新,实时更新工具和依赖。 @@ -44,17 +44,18 @@ ## 项目地址 -| 项目 | Gitee | Github | GitCode | -| ---- | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | +| 项目 | Gitee | Github | +| ---- | ------------------------------------------------------------ | ------------------------------------------------------------ | | 前端 | [vue3-element-admin](https://gitee.com/youlaiorg/vue3-element-admin) | [vue3-element-admin](https://github.com/youlaitech/vue3-element-admin) | [vue3-element-admin](https://gitcode.net/youlai/vue3-element-admin) | -| 后端 | [youlai-boot](https://gitee.com/youlaiorg/youlai-boot) | [youlai-boot](https://github.com/haoxianrui/youlai-boot.git) | [youlai-boot](https://gitcode.net/youlai/youlai-boot) | +| 精简版 | [vue3-element-admin-thin](https://gitee.com/cshaptx4869/vue3-element-admin-thin) | [vue3-element-admin-thin](https://github.com/youlaitech/vue3-element-admin-thin) | +| 后端 | [youlai-boot](https://gitee.com/youlaiorg/youlai-boot) | [youlai-boot](https://github.com/haoxianrui/youlai-boot.git) | ## 环境准备 | 环境 | 名称版本 | 下载地址 | | -------------------- | :----------------------------------------------------------- | ------------------------------------------------------------ | -| **开发工具** | VSCode | [下载](https://code.visualstudio.com/Download) | -| **运行环境** | Node ≥18 | [下载](http://nodejs.cn/download) | +| **开发工具** | VSCode | [下载](https://code.visualstudio.com/Download) | +| **运行环境** | Node ≥18 (其中 20.6.0 版本不可用) | [下载](http://nodejs.cn/download) | ## 项目启动 diff --git a/mock/dept.mock.ts b/mock/dept.mock.ts index eac3aa83..e9b6d1bb 100644 --- a/mock/dept.mock.ts +++ b/mock/dept.mock.ts @@ -36,6 +36,7 @@ export default defineMock([ id: 1, parentId: 0, name: "有来技术", + code: "YOULAI", sort: 1, status: 1, children: [ @@ -43,6 +44,7 @@ export default defineMock([ id: 2, parentId: 1, name: "研发部门", + code: "RD001", sort: 1, status: 1, children: [], @@ -53,6 +55,7 @@ export default defineMock([ id: 3, parentId: 1, name: "测试部门", + code: "QA001", sort: 1, status: 1, children: [], @@ -126,6 +129,7 @@ const deptMap: Record = { 1: { id: 1, name: "有来技术", + code: "YOULAI", parentId: 0, status: 1, sort: 1, @@ -133,6 +137,7 @@ const deptMap: Record = { 2: { id: 2, name: "研发部门", + code: "RD001", parentId: 1, status: 1, sort: 1, @@ -140,6 +145,7 @@ const deptMap: Record = { 3: { id: 3, name: "测试部门", + code: "QA001", parentId: 1, status: 1, sort: 1, diff --git a/mock/dict.mock.ts b/mock/dict.mock.ts index 178a75a2..63b4b2c1 100644 --- a/mock/dict.mock.ts +++ b/mock/dict.mock.ts @@ -5,11 +5,11 @@ export default defineMock([ url: "dict/:code/options", method: ["GET"], body: ({ params }) => { - const typeCode = params.code; + const code = params.code; let list = null; - if (typeCode == "gender") { + if (code == "gender") { list = [ { value: "1", @@ -21,7 +21,7 @@ export default defineMock([ }, { value: "0", - label: "未知", + label: "保密", }, ]; } @@ -35,7 +35,7 @@ export default defineMock([ }, { - url: "dict/types/page", + url: "dict/page", method: ["GET"], body: { code: "00000", @@ -46,104 +46,37 @@ export default defineMock([ name: "性别", code: "gender", status: 1, - }, - { - id: 2, - name: "状态", - code: "status", - status: 1, + dictItems: [ + { + id: 1, + name: "男", + value: "1", + sort: 1, + status: 1, + }, + { + id: 2, + name: "女", + value: "2", + sort: 2, + status: 1, + }, + { + id: 3, + name: "保密", + value: "0", + sort: 3, + status: 1, + }, + ], }, ], - total: 2, + total: 1, }, msg: "一切ok", }, }, - { - url: "dict/page", - method: ["GET"], - body: { - code: "00000", - data: { - list: [ - { - id: 1, - name: "男", - value: "1", - status: 1, - }, - { - id: 2, - name: "女", - value: "2", - status: 1, - }, - { - id: 3, - name: "未知", - value: "0", - status: 1, - }, - ], - total: 3, - }, - msg: "一切ok", - }, - }, - - // 新增字典类型 - { - url: "dict/types", - method: ["POST"], - body({ body }) { - return { - code: "00000", - data: null, - msg: "新增字典类型" + body.name + "成功", - }; - }, - }, - - // 获取字典类型表单数据 - { - url: "dict/types/:id/form", - method: ["GET"], - body: ({ params }) => { - return { - code: "00000", - data: dictTypeMap[params.id], - msg: "一切ok", - }; - }, - }, - - // 修改字典类型 - { - url: "dict/types/:id", - method: ["PUT"], - body({ body }) { - return { - code: "00000", - data: null, - msg: "修改字典类型" + body.name + "成功", - }; - }, - }, - - // 删除字典类型 - { - url: "dict/types/:id", - method: ["DELETE"], - body({ params }) { - return { - code: "00000", - data: null, - msg: "删除字典类型" + params.id + "成功", - }; - }, - }, - // 新增字典 { url: "dict", @@ -178,7 +111,7 @@ export default defineMock([ return { code: "00000", data: null, - msg: "修改字典类型" + body.name + "成功", + msg: "修改字典" + body.name + "成功", }; }, }, @@ -197,51 +130,39 @@ export default defineMock([ }, ]); -// 字典类型映射表数据 -const dictTypeMap: Record = { - 1: { - id: 1, - name: "性别", - code: "gender", - status: 1, - remark: null, - }, - 2: { - id: 2, - name: "状态", - code: "status", - status: 1, - remark: null, - }, -}; - // 字典映射表数据 const dictMap: Record = { 1: { - id: 1, - typeCode: "gender", - name: "男", - value: "1", - status: 1, - sort: 1, - remark: null, - }, - 2: { - id: 2, - typeCode: "gender", - name: "女", - value: "2", - status: 1, - sort: 2, - remark: null, - }, - 3: { - id: 3, - typeCode: "gender", - name: "未知", - value: "0", - status: 1, - sort: 1, - remark: null, + code: "00000", + data: { + id: 1, + name: "性别", + code: "gender", + status: 1, + dictItems: [ + { + id: 1, + name: "男", + value: "1", + sort: 1, + status: 1, + }, + { + id: 2, + name: "女", + value: "2", + sort: 2, + status: 1, + }, + { + id: 3, + name: "未知", + value: "0", + sort: 3, + status: 1, + }, + ], + }, + msg: "一切ok", }, }; diff --git a/mock/menu.mock.ts b/mock/menu.mock.ts index 1e552cfe..993bc63d 100644 --- a/mock/menu.mock.ts +++ b/mock/menu.mock.ts @@ -454,7 +454,8 @@ export default defineMock([ parentId: 0, name: "系统管理", type: "CATALOG", - path: "/system", + routeName: "", + routePath: "/system", component: "Layout", sort: 1, visible: 1, @@ -467,7 +468,8 @@ export default defineMock([ parentId: 1, name: "用户管理", type: "MENU", - path: "user", + routeName: "User", + routePath: "user", component: "system/user/index", sort: 1, visible: 1, @@ -475,12 +477,28 @@ export default defineMock([ redirect: null, perm: null, children: [ + { + id: 105, + parentId: 2, + name: "用户查询", + type: "BUTTON", + routeName: null, + routePath: "", + component: null, + sort: 0, + visible: 1, + icon: "", + redirect: null, + perm: "sys:user:query", + children: [], + }, { id: 31, parentId: 2, name: "用户新增", type: "BUTTON", - path: "", + routeName: null, + routePath: "", component: null, sort: 1, visible: 1, @@ -494,7 +512,8 @@ export default defineMock([ parentId: 2, name: "用户编辑", type: "BUTTON", - path: "", + routeName: null, + routePath: "", component: null, sort: 2, visible: 1, @@ -508,7 +527,8 @@ export default defineMock([ parentId: 2, name: "用户删除", type: "BUTTON", - path: "", + routeName: null, + routePath: "", component: null, sort: 3, visible: 1, @@ -522,7 +542,8 @@ export default defineMock([ parentId: 2, name: "重置密码", type: "BUTTON", - path: "", + routeName: null, + routePath: "", component: null, sort: 4, visible: 1, @@ -531,6 +552,36 @@ export default defineMock([ perm: "sys:user:password:reset", children: [], }, + { + id: 106, + parentId: 2, + name: "用户导入", + type: "BUTTON", + routeName: null, + routePath: "", + component: null, + sort: 5, + visible: 1, + icon: "", + redirect: null, + perm: "sys:user:import", + children: [], + }, + { + id: 107, + parentId: 2, + name: "用户导出", + type: "BUTTON", + routeName: null, + routePath: "", + component: null, + sort: 6, + visible: 1, + icon: "", + redirect: null, + perm: "sys:user:export", + children: [], + }, ], }, { @@ -538,7 +589,8 @@ export default defineMock([ parentId: 1, name: "角色管理", type: "MENU", - path: "role", + routeName: "Role", + routePath: "role", component: "system/role/index", sort: 2, visible: 1, @@ -551,7 +603,8 @@ export default defineMock([ parentId: 3, name: "角色新增", type: "BUTTON", - path: "", + routeName: null, + routePath: "", component: null, sort: 1, visible: 1, @@ -565,7 +618,8 @@ export default defineMock([ parentId: 3, name: "角色编辑", type: "BUTTON", - path: "", + routeName: null, + routePath: "", component: null, sort: 2, visible: 1, @@ -579,7 +633,8 @@ export default defineMock([ parentId: 3, name: "角色删除", type: "BUTTON", - path: "", + routeName: null, + routePath: "", component: null, sort: 3, visible: 1, @@ -595,7 +650,8 @@ export default defineMock([ parentId: 1, name: "菜单管理", type: "MENU", - path: "menu", + routeName: "Menu", + routePath: "menu", component: "system/menu/index", sort: 3, visible: 1, @@ -608,7 +664,8 @@ export default defineMock([ parentId: 4, name: "菜单新增", type: "BUTTON", - path: "", + routeName: null, + routePath: "", component: null, sort: 1, visible: 1, @@ -617,26 +674,13 @@ export default defineMock([ perm: "sys:menu:add", children: [], }, - { - id: 74, - parentId: 4, - name: "菜单编辑", - type: "BUTTON", - path: "", - component: null, - sort: 3, - visible: 1, - icon: "", - redirect: null, - perm: "sys:menu:edit", - children: [], - }, { id: 75, parentId: 4, name: "菜单删除", type: "BUTTON", - path: "", + routeName: null, + routePath: "", component: null, sort: 3, visible: 1, @@ -645,6 +689,21 @@ export default defineMock([ perm: "sys:menu:delete", children: [], }, + { + id: 74, + parentId: 4, + name: "菜单编辑", + type: "BUTTON", + routeName: null, + routePath: "", + component: null, + sort: 3, + visible: 1, + icon: "", + redirect: null, + perm: "sys:menu:edit", + children: [], + }, ], }, { @@ -652,7 +711,8 @@ export default defineMock([ parentId: 1, name: "部门管理", type: "MENU", - path: "dept", + routeName: "Dept", + routePath: "dept", component: "system/dept/index", sort: 4, visible: 1, @@ -665,7 +725,8 @@ export default defineMock([ parentId: 5, name: "部门新增", type: "BUTTON", - path: "", + routeName: null, + routePath: "", component: null, sort: 1, visible: 1, @@ -679,7 +740,8 @@ export default defineMock([ parentId: 5, name: "部门编辑", type: "BUTTON", - path: "", + routeName: null, + routePath: "", component: null, sort: 2, visible: 1, @@ -693,7 +755,8 @@ export default defineMock([ parentId: 5, name: "部门删除", type: "BUTTON", - path: "", + routeName: null, + routePath: "", component: null, sort: 3, visible: 1, @@ -709,7 +772,8 @@ export default defineMock([ parentId: 1, name: "字典管理", type: "MENU", - path: "dict", + routeName: "Dict", + routePath: "dict", component: "system/dict/index", sort: 5, visible: 1, @@ -722,7 +786,8 @@ export default defineMock([ parentId: 6, name: "字典类型新增", type: "BUTTON", - path: "", + routeName: null, + routePath: "", component: null, sort: 1, visible: 1, @@ -736,7 +801,8 @@ export default defineMock([ parentId: 6, name: "字典类型编辑", type: "BUTTON", - path: "", + routeName: null, + routePath: "", component: null, sort: 2, visible: 1, @@ -750,7 +816,8 @@ export default defineMock([ parentId: 6, name: "字典类型删除", type: "BUTTON", - path: "", + routeName: null, + routePath: "", component: null, sort: 3, visible: 1, @@ -764,7 +831,8 @@ export default defineMock([ parentId: 6, name: "字典数据新增", type: "BUTTON", - path: "", + routeName: null, + routePath: "", component: null, sort: 4, visible: 1, @@ -778,7 +846,8 @@ export default defineMock([ parentId: 6, name: "字典数据编辑", type: "BUTTON", - path: "", + routeName: null, + routePath: "", component: null, sort: 5, visible: 1, @@ -792,7 +861,8 @@ export default defineMock([ parentId: 6, name: "字典数据删除", type: "BUTTON", - path: "", + routeName: null, + routePath: "", component: null, sort: 6, visible: 1, @@ -810,7 +880,8 @@ export default defineMock([ parentId: 0, name: "接口文档", type: "CATALOG", - path: "/api", + routeName: null, + routePath: "/api", component: "Layout", sort: 7, visible: 1, @@ -823,7 +894,8 @@ export default defineMock([ parentId: 40, name: "Apifox", type: "MENU", - path: "apifox", + routeName: null, + routePath: "apifox", component: "demo/api/apifox", sort: 1, visible: 1, @@ -832,34 +904,6 @@ export default defineMock([ perm: null, children: [], }, - { - id: 103, - parentId: 40, - name: "Swagger", - type: "MENU", - path: "swagger", - component: "demo/api/swagger", - sort: 2, - visible: 0, - icon: "api", - redirect: "", - perm: null, - children: [], - }, - { - id: 104, - parentId: 40, - name: "Knife4j", - type: "MENU", - path: "knife4j", - component: "demo/api/knife4j", - sort: 3, - visible: 0, - icon: "api", - redirect: "", - perm: null, - children: [], - }, ], }, { @@ -867,12 +911,13 @@ export default defineMock([ parentId: 0, name: "平台文档", type: "CATALOG", - path: "/doc", + routeName: null, + routePath: "/doc", component: "Layout", sort: 8, visible: 1, icon: "document", - redirect: null, + redirect: "https://juejin.cn/post/7228990409909108793", perm: null, children: [ { @@ -880,7 +925,8 @@ export default defineMock([ parentId: 26, name: "平台文档(内嵌)", type: "EXTLINK", - path: "internal-doc", + routeName: null, + routePath: "internal-doc", component: "demo/internal-doc", sort: 1, visible: 1, @@ -894,7 +940,8 @@ export default defineMock([ parentId: 26, name: "平台文档(外链)", type: "EXTLINK", - path: "https://juejin.cn/post/7228990409909108793", + routeName: null, + routePath: "https://juejin.cn/post/7228990409909108793", component: "", sort: 2, visible: 1, @@ -910,12 +957,13 @@ export default defineMock([ parentId: 0, name: "多级菜单", type: "CATALOG", - path: "/multi-level", + routeName: null, + routePath: "/multi-level", component: "Layout", sort: 9, visible: 1, icon: "cascader", - redirect: "/multi-level/multi-level1", + redirect: "", perm: null, children: [ { @@ -923,12 +971,13 @@ export default defineMock([ parentId: 20, name: "菜单一级", type: "MENU", - path: "multi-level1", + routeName: null, + routePath: "multi-level1", component: "demo/multi-level/level1", sort: 1, visible: 1, icon: "", - redirect: "/multi-level/multi-level2", + redirect: "", perm: null, children: [ { @@ -936,12 +985,13 @@ export default defineMock([ parentId: 21, name: "菜单二级", type: "MENU", - path: "multi-level2", + routeName: null, + routePath: "multi-level2", component: "demo/multi-level/children/level2", sort: 1, visible: 1, icon: "", - redirect: "/multi-level/multi-level2/multi-level3-1", + redirect: null, perm: null, children: [ { @@ -949,7 +999,8 @@ export default defineMock([ parentId: 22, name: "菜单三级-1", type: "MENU", - path: "multi-level3-1", + routeName: null, + routePath: "multi-level3-1", component: "demo/multi-level/children/children/level3-1", sort: 1, visible: 1, @@ -963,7 +1014,8 @@ export default defineMock([ parentId: 22, name: "菜单三级-2", type: "MENU", - path: "multi-level3-2", + routeName: null, + routePath: "multi-level3-2", component: "demo/multi-level/children/children/level3-2", sort: 2, visible: 1, @@ -983,7 +1035,8 @@ export default defineMock([ parentId: 0, name: "组件封装", type: "CATALOG", - path: "/component", + routeName: null, + routePath: "/component", component: "Layout", sort: 10, visible: 1, @@ -991,14 +1044,45 @@ export default defineMock([ redirect: "", perm: null, children: [ + { + id: 108, + parentId: 36, + name: "增删改查", + type: "MENU", + routeName: null, + routePath: "curd", + component: "demo/curd/index", + sort: 0, + visible: 1, + icon: "", + redirect: "", + perm: null, + children: [], + }, + { + id: 109, + parentId: 36, + name: "列表选择器", + type: "MENU", + routeName: null, + routePath: "table-select", + component: "demo/table-select/index", + sort: 1, + visible: 1, + icon: "", + redirect: "", + perm: null, + children: [], + }, { id: 37, parentId: 36, name: "富文本编辑器", type: "MENU", - path: "wang-editor", + routeName: null, + routePath: "wang-editor", component: "demo/wang-editor", - sort: 1, + sort: 2, visible: 1, icon: "", redirect: "", @@ -1010,22 +1094,9 @@ export default defineMock([ parentId: 36, name: "图片上传", type: "MENU", - path: "upload", + routeName: null, + routePath: "upload", component: "demo/upload", - sort: 2, - visible: 1, - icon: "", - redirect: "", - perm: null, - children: [], - }, - { - id: 39, - parentId: 36, - name: "图标选择器", - type: "MENU", - path: "icon-selector", - component: "demo/icon-selector", sort: 3, visible: 1, icon: "", @@ -1038,7 +1109,8 @@ export default defineMock([ parentId: 36, name: "字典组件", type: "MENU", - path: "dict-demo", + routeName: null, + routePath: "dict-demo", component: "demo/dict", sort: 4, visible: 1, @@ -1048,30 +1120,63 @@ export default defineMock([ children: [], }, { - id: 93, + id: 39, parentId: 36, - name: "签名", + name: "图标选择器", type: "MENU", - path: "signature", - component: "demo/signature", - sort: 6, + routeName: null, + routePath: "icon-selector", + component: "demo/icon-selector", + sort: 4, visible: 1, icon: "", redirect: "", perm: null, children: [], }, + ], + }, + { + id: 110, + parentId: 0, + name: "路由参数", + type: "CATALOG", + routeName: null, + routePath: "/route-param", + component: "Layout", + sort: 11, + visible: 1, + icon: "el-icon-ElementPlus", + redirect: null, + perm: null, + children: [ { - id: 94, - parentId: 36, - name: "表格", + id: 111, + parentId: 110, + name: "参数(type=1)", type: "MENU", - path: "table", - component: "demo/table", - sort: 7, + routeName: null, + routePath: "route-param-type1", + component: "demo/route-param", + sort: 1, visible: 1, - icon: "", - redirect: "", + icon: "el-icon-Star", + redirect: null, + perm: null, + children: [], + }, + { + id: 112, + parentId: 110, + name: "参数(type=2)", + type: "MENU", + routeName: null, + routePath: "route-param-type2", + component: "demo/route-param", + sort: 2, + visible: 1, + icon: "el-icon-StarFilled", + redirect: null, perm: null, children: [], }, @@ -1082,9 +1187,10 @@ export default defineMock([ parentId: 0, name: "功能演示", type: "CATALOG", - path: "/function", + routeName: null, + routePath: "/function", component: "Layout", - sort: 11, + sort: 12, visible: 1, icon: "menu", redirect: "", @@ -1095,11 +1201,12 @@ export default defineMock([ parentId: 89, name: "Icons", type: "MENU", - path: "icon-demo", + routeName: null, + routePath: "icon-demo", component: "demo/icons", sort: 2, visible: 1, - icon: "el-icon-edit", + icon: "el-icon-Notification", redirect: "", perm: null, children: [], @@ -1109,7 +1216,8 @@ export default defineMock([ parentId: 89, name: "Websocket", type: "MENU", - path: "/function/websocket", + routeName: null, + routePath: "/function/websocket", component: "demo/websocket", sort: 3, visible: 1, @@ -1123,7 +1231,8 @@ export default defineMock([ parentId: 89, name: "敬请期待...", type: "CATALOG", - path: "other", + routeName: null, + routePath: "other/:id", component: "demo/other", sort: 4, visible: 1, @@ -1153,6 +1262,10 @@ export default defineMock([ value: 2, label: "用户管理", children: [ + { + value: 105, + label: "用户查询", + }, { value: 31, label: "用户新增", @@ -1169,6 +1282,14 @@ export default defineMock([ value: 88, label: "重置密码", }, + { + value: 106, + label: "用户导入", + }, + { + value: 107, + label: "用户导出", + }, ], }, { @@ -1197,14 +1318,14 @@ export default defineMock([ value: 73, label: "菜单新增", }, - { - value: 74, - label: "菜单编辑", - }, { value: 75, label: "菜单删除", }, + { + value: 74, + label: "菜单编辑", + }, ], }, { @@ -1265,14 +1386,6 @@ export default defineMock([ value: 41, label: "Apifox", }, - { - value: 103, - label: "Swagger", - }, - { - value: 104, - label: "Knife4j", - }, ], }, { @@ -1319,6 +1432,14 @@ export default defineMock([ value: 36, label: "组件封装", children: [ + { + value: 108, + label: "增删改查", + }, + { + value: 109, + label: "列表选择器", + }, { value: 37, label: "富文本编辑器", @@ -1327,21 +1448,27 @@ export default defineMock([ value: 38, label: "图片上传", }, - { - value: 39, - label: "图标选择器", - }, { value: 95, label: "字典组件", }, { - value: 93, - label: "签名", + value: 39, + label: "图标选择器", + }, + ], + }, + { + value: 110, + label: "路由参数", + children: [ + { + value: 111, + label: "参数(type=1)", }, { - value: 94, - label: "表格", + value: 112, + label: "参数(type=2)", }, ], }, @@ -1428,7 +1555,8 @@ const menuMap: Record = { parentId: 0, name: "系统管理", type: "CATALOG", - path: "/system", + routeName: "", + routePath: "/system", component: "Layout", perm: null, visible: 1, @@ -1437,13 +1565,15 @@ const menuMap: Record = { redirect: "/system/user", keepAlive: null, alwaysShow: null, + params: null, }, 2: { id: 2, parentId: 1, name: "用户管理", type: "MENU", - path: "user", + routeName: "User", + routePath: "user", component: "system/user/index", perm: null, visible: 1, @@ -1458,7 +1588,8 @@ const menuMap: Record = { parentId: 1, name: "角色管理", type: "MENU", - path: "role", + routeName: "Role", + routePath: "role", component: "system/role/index", perm: null, visible: 1, @@ -1473,7 +1604,8 @@ const menuMap: Record = { parentId: 1, name: "菜单管理", type: "MENU", - path: "menu", + routeName: "Menu", + routePath: "menu", component: "system/menu/index", perm: null, visible: 1, @@ -1488,7 +1620,8 @@ const menuMap: Record = { parentId: 1, name: "部门管理", type: "MENU", - path: "dept", + routeName: "Dept", + routePath: "dept", component: "system/dept/index", perm: null, visible: 1, @@ -1503,7 +1636,8 @@ const menuMap: Record = { parentId: 1, name: "字典管理", type: "MENU", - path: "dict", + routeName: "Dict", + routePath: "dict", component: "system/dict/index", perm: null, visible: 1, diff --git a/package.json b/package.json index f28faa98..ed6f20f5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vue3-element-admin", - "version": "2.11.3", + "version": "2.12.0", "private": true, "type": "module", "scripts": { @@ -63,7 +63,7 @@ "sockjs-client": "1.6.1", "sortablejs": "^1.15.2", "stompjs": "^2.3.3", - "vue": "^3.4.27", + "vue": "^3.4.29", "vue-i18n": "9.9.1", "vue-router": "^4.3.3" }, @@ -73,14 +73,14 @@ "@iconify-json/ep": "^1.1.15", "@types/color": "^3.0.6", "@types/lodash": "^4.17.5", - "@types/node": "^20.14.2", + "@types/node": "^20.14.3", "@types/nprogress": "^0.2.3", "@types/path-browserify": "^1.0.2", "@types/sockjs-client": "^1.5.4", "@types/sortablejs": "^1.15.8", "@types/stompjs": "^2.3.9", - "@typescript-eslint/eslint-plugin": "^7.13.0", - "@typescript-eslint/parser": "^7.13.0", + "@typescript-eslint/eslint-plugin": "^7.13.1", + "@typescript-eslint/parser": "^7.13.1", "@vitejs/plugin-vue": "^5.0.5", "@vitejs/plugin-vue-jsx": "^3.1.0", "autoprefixer": "^10.4.19", @@ -98,7 +98,7 @@ "postcss-html": "^1.7.0", "postcss-scss": "^4.0.9", "prettier": "^3.3.2", - "sass": "^1.77.5", + "sass": "^1.77.6", "stylelint": "^16.6.1", "stylelint-config-html": "^1.1.0", "stylelint-config-recess-order": "^4.6.0", @@ -111,10 +111,10 @@ "unplugin-auto-import": "^0.17.6", "unplugin-icons": "^0.18.5", "unplugin-vue-components": "^0.26.0", - "vite": "^5.2.13", + "vite": "^5.3.1", "vite-plugin-mock-dev-server": "^1.5.0", "vite-plugin-svg-icons": "^2.0.1", - "vite-plugin-vue-devtools": "^7.2.1", + "vite-plugin-vue-devtools": "^7.3.0", "vue-tsc": "^2.0.21" }, "repository": "https://gitee.com/youlaiorg/vue3-element-admin.git", diff --git a/src/api/auth.ts b/src/api/auth.ts new file mode 100644 index 00000000..eb904d87 --- /dev/null +++ b/src/api/auth.ts @@ -0,0 +1,72 @@ +import request from "@/utils/request"; + +const AUTH_BASE_URL = "/api/v1/auth"; + +class AuthAPI { + /** 登录 接口*/ + static login(data: LoginData) { + const formData = new FormData(); + formData.append("username", data.username); + formData.append("password", data.password); + formData.append("captchaKey", data.captchaKey); + formData.append("captchaCode", data.captchaCode); + return request({ + url: `${AUTH_BASE_URL}/login`, + method: "post", + data: formData, + headers: { + "Content-Type": "multipart/form-data", + }, + }); + } + + /** 注销 接口*/ + static logout() { + return request({ + url: `${AUTH_BASE_URL}/logout`, + method: "delete", + }); + } + + /** 获取验证码 接口*/ + static getCaptcha() { + return request({ + url: `${AUTH_BASE_URL}/captcha`, + method: "get", + }); + } +} + +export default AuthAPI; + +/** 登录请求参数 */ +export interface LoginData { + /** 用户名 */ + username: string; + /** 密码 */ + password: string; + /** 验证码缓存key */ + captchaKey: string; + /** 验证码 */ + captchaCode: string; +} + +/** 登录响应 */ +export interface LoginResult { + /** 访问token */ + accessToken?: string; + /** 过期时间(单位:毫秒) */ + expires?: number; + /** 刷新token */ + refreshToken?: string; + /** token 类型 */ + tokenType?: string; +} + +/** 验证码响应 */ +export interface CaptchaResult { + /** 验证码缓存key */ + captchaKey: string; + /** 验证码图片Base64字符串 */ + captchaBase64: string; +} diff --git a/src/api/auth/index.ts b/src/api/auth/index.ts deleted file mode 100644 index 57cf1e7c..00000000 --- a/src/api/auth/index.ts +++ /dev/null @@ -1,48 +0,0 @@ -import request from "@/utils/request"; -import { CaptchaResult, LoginData, LoginResult } from "./model"; - -class AuthAPI { - /** - * 登录API - * - * @param data {LoginData} - * @returns - */ - static login(data: LoginData) { - const formData = new FormData(); - formData.append("username", data.username); - formData.append("password", data.password); - formData.append("captchaKey", data.captchaKey || ""); - formData.append("captchaCode", data.captchaCode || ""); - return request({ - url: "/api/v1/auth/login", - method: "post", - data: formData, - headers: { - "Content-Type": "multipart/form-data", - }, - }); - } - - /** - * 注销API - */ - static logout() { - return request({ - url: "/api/v1/auth/logout", - method: "delete", - }); - } - - /** - * 获取验证码 - */ - static getCaptcha() { - return request({ - url: "/api/v1/auth/captcha", - method: "get", - }); - } -} - -export default AuthAPI; diff --git a/src/api/auth/model.ts b/src/api/auth/model.ts deleted file mode 100644 index 0da661ed..00000000 --- a/src/api/auth/model.ts +++ /dev/null @@ -1,59 +0,0 @@ -/** - * 登录请求参数 - */ -export interface LoginData { - /** - * 用户名 - */ - username: string; - /** - * 密码 - */ - password: string; - - /** - * 验证码缓存key - */ - captchaKey?: string; - - /** - * 验证码 - */ - captchaCode?: string; -} - -/** - * 登录响应 - */ -export interface LoginResult { - /** - * 访问token - */ - accessToken?: string; - /** - * 过期时间(单位:毫秒) - */ - expires?: number; - /** - * 刷新token - */ - refreshToken?: string; - /** - * token 类型 - */ - tokenType?: string; -} - -/** - * 验证码响应 - */ -export interface CaptchaResult { - /** - * 验证码缓存key - */ - captchaKey: string; - /** - * 验证码图片Base64字符串 - */ - captchaBase64: string; -} diff --git a/src/api/dept.ts b/src/api/dept.ts new file mode 100644 index 00000000..9bd46739 --- /dev/null +++ b/src/api/dept.ts @@ -0,0 +1,130 @@ +import request from "@/utils/request"; + +const DEPT_BASE_URL = "/api/v1/dept"; + +class DeptAPI { + /** + * 获取部门列表 + * + * @param queryParams 查询参数(可选) + * @returns 部门树形表格数据 + */ + static getList(queryParams?: DeptQuery) { + return request({ + url: `${DEPT_BASE_URL}`, + method: "get", + params: queryParams, + }); + } + + /** 获取部门下拉列表 */ + static getOptions() { + return request({ + url: `${DEPT_BASE_URL}/options`, + method: "get", + }); + } + + /** + * 获取部门详情表单数据 + * + * @param id 部门ID + * @returns 部门详情表单数据 + */ + static getFormData(id: number) { + return request({ + url: `${DEPT_BASE_URL}/${id}/form`, + method: "get", + }); + } + + /** + * 新增部门 + * + * @param data 部门表单数据 + * @returns 请求结果 + */ + static add(data: DeptForm) { + return request({ + url: `${DEPT_BASE_URL}`, + method: "post", + data: data, + }); + } + + /** + * 修改部门 + * + * @param id 部门ID + * @param data 部门表单数据 + * @returns 请求结果 + */ + static update(id: number, data: DeptForm) { + return request({ + url: `${DEPT_BASE_URL}/${id}`, + method: "put", + data: data, + }); + } + + /** + * 删除部门 + * + * @param ids 部门ID,多个以英文逗号(,)分隔 + * @returns 请求结果 + */ + static deleteByIds(ids: string) { + return request({ + url: `${DEPT_BASE_URL}/${ids}`, + method: "delete", + }); + } +} + +export default DeptAPI; + +/** 部门查询参数 */ +export interface DeptQuery { + /** 搜索关键字 */ + keywords?: string; + /** 状态 */ + status?: number; +} + +/** 部门类型 */ +export interface DeptVO { + /** 子部门 */ + children?: DeptVO[]; + /** 创建时间 */ + createTime?: Date; + /** 部门ID */ + id?: number; + /** 部门名称 */ + name?: string; + /** 部门编号 */ + code?: string; + /** 父部门ID */ + parentId?: number; + /** 排序 */ + sort?: number; + /** 状态(1:启用;0:禁用) */ + status?: number; + /** 修改时间 */ + updateTime?: Date; +} + +/** 部门表单类型 */ +export interface DeptForm { + /** 部门ID(新增不填) */ + id?: number; + /** 部门名称 */ + name?: string; + /** 部门编号 */ + code?: string; + /** 父部门ID */ + parentId: number; + /** 排序 */ + sort?: number; + /** 状态(1:启用;0:禁用) */ + status?: number; +} diff --git a/src/api/dept/index.ts b/src/api/dept/index.ts deleted file mode 100644 index 45f689a6..00000000 --- a/src/api/dept/index.ts +++ /dev/null @@ -1,80 +0,0 @@ -import request from "@/utils/request"; -import { DeptForm, DeptQuery, DeptVO } from "./model"; - -class DeptAPI { - /** - * 部门树形表格 - * - * @param queryParams - */ - static getList(queryParams?: DeptQuery) { - return request({ - url: "/api/v1/dept", - method: "get", - params: queryParams, - }); - } - - /** - * 部门下拉列表 - */ - static getOptions() { - return request({ - url: "/api/v1/dept/options", - method: "get", - }); - } - - /** - * 获取部门详情 - * - * @param id - */ - static getFormData(id: number) { - return request({ - url: "/api/v1/dept/" + id + "/form", - method: "get", - }); - } - - /** - * 新增部门 - * - * @param data - */ - static add(data: DeptForm) { - return request({ - url: "/api/v1/dept", - method: "post", - data: data, - }); - } - - /** - * 修改部门 - * - * @param id - * @param data - */ - static update(id: number, data: DeptForm) { - return request({ - url: "/api/v1/dept/" + id, - method: "put", - data: data, - }); - } - - /** - * 删除部门 - * - * @param ids - */ - static deleteByIds(ids: string) { - return request({ - url: "/api/v1/dept/" + ids, - method: "delete", - }); - } -} - -export default DeptAPI; diff --git a/src/api/dept/model.ts b/src/api/dept/model.ts deleted file mode 100644 index 408c39c4..00000000 --- a/src/api/dept/model.ts +++ /dev/null @@ -1,71 +0,0 @@ -/** - * 部门查询参数 - */ -export interface DeptQuery { - keywords?: string; - status?: number; -} - -/** - * 部门类型 - */ -export interface DeptVO { - /** - * 子部门 - */ - children?: DeptVO[]; - /** - * 创建时间 - */ - createTime?: Date; - /** - * 部门ID - */ - id?: number; - /** - * 部门名称 - */ - name?: string; - /** - * 父部门ID - */ - parentId?: number; - /** - * 排序 - */ - sort?: number; - /** - * 状态(1:启用;0:禁用) - */ - status?: number; - /** - * 修改时间 - */ - updateTime?: Date; -} - -/** - * 部门表单类型 - */ -export interface DeptForm { - /** - * 部门ID(新增不填) - */ - id?: number; - /** - * 部门名称 - */ - name?: string; - /** - * 父部门ID - */ - parentId: number; - /** - * 排序 - */ - sort?: number; - /** - * 状态(1:启用;0:禁用) - */ - status?: number; -} diff --git a/src/api/dict.ts b/src/api/dict.ts new file mode 100644 index 00000000..b9512005 --- /dev/null +++ b/src/api/dict.ts @@ -0,0 +1,183 @@ +import request from "@/utils/request"; + +const DICT_BASE_URL = "/api/v1/dict"; + +class DictAPI { + /** + * 获取字典分页列表 + * + * @param queryParams 查询参数 + * @returns 字典分页结果 + */ + static getPage(queryParams: DictPageQuery) { + return request>({ + url: `${DICT_BASE_URL}/page`, + method: "get", + params: queryParams, + }); + } + + /** + * 获取字典表单数据 + * + * @param id 字典ID + * @returns 字典表单数据 + */ + static getFormData(id: number) { + return request>({ + url: `${DICT_BASE_URL}/${id}/form`, + method: "get", + }); + } + + /** + * 新增字典 + * + * @param data 字典表单数据 + * @returns 请求结果 + */ + static add(data: DictForm) { + return request({ + url: `${DICT_BASE_URL}`, + method: "post", + data: data, + }); + } + + /** + * 修改字典 + * + * @param id 字典ID + * @param data 字典表单数据 + * @returns 请求结果 + */ + static update(id: number, data: DictForm) { + return request({ + url: `${DICT_BASE_URL}/${id}`, + method: "put", + data: data, + }); + } + + /** + * 删除字典 + * + * @param ids 字典ID,多个以英文逗号(,)分隔 + * @returns 请求结果 + */ + static deleteByIds(ids: string) { + return request({ + url: `${DICT_BASE_URL}/${ids}`, + method: "delete", + }); + } + + /** + * 获取字典的数据项 + * + * @param typeCode 字典编码 + * @returns 字典数据项 + */ + static getOptions(code: string) { + return request({ + url: `${DICT_BASE_URL}/${code}/options`, + method: "get", + }); + } +} + +export default DictAPI; + +/** + * 字典查询参数 + */ +export interface DictPageQuery extends PageQuery { + /** + * 关键字(字典名称/编码) + */ + keywords?: string; +} + +/** + * 字典分页对象 + */ +export interface DictPageVO { + /** + * 字典ID + */ + id: number; + /** + * 字典名称 + */ + name: string; + /** + * 字典编码 + */ + code: string; + /** + * 字典状态(1-启用,0-禁用) + */ + status: number; + /** + * 字典项列表 + */ + dictItems: DictItem[]; +} + +/** + * 字典项 + */ +export interface DictItem { + /** + * 字典项ID + */ + id?: number; + /** + * 字典项名称 + */ + name?: string; + /** + * 字典项值 + */ + value?: string; + /** + * 排序 + */ + sort?: number; + /** + * 状态(1-启用,0-禁用) + */ + status?: number; +} + +// TypeScript 类型声明 + +/** + * 字典 + */ +export interface DictForm { + /** + * 字典ID + */ + id?: number; + /** + * 字典名称 + */ + name?: string; + /** + * 字典编码 + */ + code?: string; + /** + * 字典状态(1-启用,0-禁用) + */ + status?: number; + /** + * 备注 + */ + remark?: string; + /** + * 字典数据项列表 + */ + dictItems?: DictItem[]; +} diff --git a/src/api/dict/index.ts b/src/api/dict/index.ts deleted file mode 100644 index adef210f..00000000 --- a/src/api/dict/index.ts +++ /dev/null @@ -1,149 +0,0 @@ -import request from "@/utils/request"; -import { - DictTypeQuery, - DictTypePageResult, - DictTypeForm, - DictQuery, - DictForm, - DictPageResult, -} from "./model"; - -class DictAPI { - /** - * 字典类型分页列表 - * - * @param queryParams - */ - static getDictTypePage(queryParams: DictTypeQuery) { - return request({ - url: "/api/v1/dict/types/page", - method: "get", - params: queryParams, - }); - } - - /** - * 字典类型表单数据 - * - * @param id - */ - static getDictTypeForm(id: number) { - return request>({ - url: "/api/v1/dict/types/" + id + "/form", - method: "get", - }); - } - - /** - * 新增字典类型 - * - * @param data - */ - static addDictType(data: DictTypeForm) { - return request({ - url: "/api/v1/dict/types", - method: "post", - data: data, - }); - } - - /** - * 修改字典类型 - * - * @param id - * @param data - */ - static updateDictType(id: number, data: DictTypeForm) { - return request({ - url: "/api/v1/dict/types/" + id, - method: "put", - data: data, - }); - } - - /** - * 删除字典类型 - */ - static deleteDictTypes(ids: string) { - return request({ - url: "/api/v1/dict/types/" + ids, - method: "delete", - }); - } - - /** - * 获取字典类型的数据项 - * - * @param typeCode 字典类型编码 - */ - static getDictOptions(typeCode: string) { - return request({ - url: "/api/v1/dict/" + typeCode + "/options", - method: "get", - }); - } - - /** - * 字典分页列表 - */ - static getDictPage(queryParams: DictQuery) { - return request({ - url: "/api/v1/dict/page", - method: "get", - params: queryParams, - }); - } - - /** - * 获取字典表单数据 - * - * @param id - */ - static getDictFormData(id: number) { - return request({ - url: "/api/v1/dict/" + id + "/form", - method: "get", - }); - } - - /** - * 新增字典 - * - * @param data - */ - static addDict(data: DictForm) { - return request({ - url: "/api/v1/dict", - method: "post", - data: data, - }); - } - - /** - * 修改字典项 - * - * @param id - * @param data - */ - static updateDict(id: number, data: DictForm) { - return request({ - url: "/api/v1/dict/" + id, - method: "put", - data: data, - }); - } - - /** - * 删除字典 - * - * @param ids 字典项ID,多个以英文逗号(,)分割 - */ - static deleteDictByIds(ids: string) { - return request({ - url: "/api/v1/dict/" + ids, - method: "delete", - }); - } -} - -export default DictAPI; diff --git a/src/api/dict/model.ts b/src/api/dict/model.ts deleted file mode 100644 index 315da6d7..00000000 --- a/src/api/dict/model.ts +++ /dev/null @@ -1,142 +0,0 @@ -/** - * 字典类型查询参数 - */ -export interface DictTypeQuery extends PageQuery { - /** - * 关键字(字典类型名称/编码) - */ - keywords?: string; -} - -/** - * 字典类型分页对象 - */ -export interface DictTypePageVO { - /** - * 字典类型ID - */ - id: number; - /** - * 类型编码 - */ - code: string; - /** - * 类型名称 - */ - name: string; - /** - * 状态(1:启用;0:禁用) - */ - status?: number; - /** - * 备注 - */ - remark?: string; -} - -/** - * 字典分页项类型声明 - */ -export type DictTypePageResult = PageResult; - -/** - * 字典表单类型声明 - */ -export interface DictTypeForm { - /** - * 字典类型ID - */ - id?: number; - /** - * 类型名称 - */ - name?: string; - /** - * 类型编码 - */ - code?: string; - /** - * 类型状态:1:启用;0:禁用 - */ - status: number; - /** - * 备注 - */ - remark?: string; -} - -/** - * 字典查询参数 - */ -export interface DictQuery extends PageQuery { - /** - * 字典项名称 - */ - name?: string; - /** - * 字典类型编码 - */ - typeCode?: string; -} - -/** - * 字典分页对象 - */ -export interface DictPageVO { - /** - * 字典ID - */ - id?: number; - /** - * 字典名称 - */ - name?: string; - /** - * 状态(1:启用;0:禁用) - */ - status?: number; - /** - * 字典值 - */ - value?: string; -} - -/** - * 字典分页 - */ -export type DictPageResult = PageResult; - -/** - * 字典表单 - */ -export interface DictForm { - /** - * 字典ID - */ - id?: number; - /** - * 字典名称 - */ - name?: string; - /** - * 排序 - */ - sort?: number; - /** - * 状态(1:启用;0:禁用) - */ - status?: number; - /** - * 类型编码 - */ - typeCode?: string; - /** - * 值 - */ - value?: string; - - /** - * 备注 - */ - remark?: string; -} diff --git a/src/api/file/index.ts b/src/api/file.ts similarity index 83% rename from src/api/file/index.ts rename to src/api/file.ts index 82364624..3203195b 100644 --- a/src/api/file/index.ts +++ b/src/api/file.ts @@ -1,5 +1,4 @@ import request from "@/utils/request"; -import { FileInfo } from "./model"; class FileAPI { /** @@ -35,3 +34,13 @@ class FileAPI { } export default FileAPI; + +/** + * 文件API类型声明 + */ +export interface FileInfo { + /** 文件名 */ + name: string; + /** 文件路径 */ + url: string; +} diff --git a/src/api/file/model.ts b/src/api/file/model.ts deleted file mode 100644 index 22b2be55..00000000 --- a/src/api/file/model.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * 文件API类型声明 - */ -export interface FileInfo { - name: string; - url: string; -} diff --git a/src/api/menu.ts b/src/api/menu.ts new file mode 100644 index 00000000..31065f16 --- /dev/null +++ b/src/api/menu.ts @@ -0,0 +1,209 @@ +import request from "@/utils/request"; +// 菜单基础URL +const MENU_BASE_URL = "/api/v1/menus"; + +class MenuAPI { + /** + * 获取路由列表 + * + * @returns 路由列表 + */ + static getRoutes() { + return request({ + url: `${MENU_BASE_URL}/routes`, + method: "get", + }); + } + + /** + * 获取菜单树形列表 + * + * @param queryParams 查询参数 + * @returns 菜单树形列表 + */ + static getList(queryParams: MenuQuery) { + return request({ + url: `${MENU_BASE_URL}`, + method: "get", + params: queryParams, + }); + } + + /** + * 获取菜单下拉数据源 + * + * @returns 菜单下拉数据源 + */ + static getOptions() { + return request({ + url: `${MENU_BASE_URL}/options`, + method: "get", + }); + } + + /** + * 获取菜单表单数据 + * + * @param id 菜单ID + * @returns 菜单表单数据 + */ + static getFormData(id: number) { + return request({ + url: `${MENU_BASE_URL}/${id}/form`, + method: "get", + }); + } + + /** + * 添加菜单 + * + * @param data 菜单表单数据 + * @returns 请求结果 + */ + static add(data: MenuForm) { + return request({ + url: `${MENU_BASE_URL}`, + method: "post", + data: data, + }); + } + + /** + * 修改菜单 + * + * @param id 菜单ID + * @param data 菜单表单数据 + * @returns 请求结果 + */ + static update(id: string, data: MenuForm) { + return request({ + url: `${MENU_BASE_URL}/${id}`, + method: "put", + data: data, + }); + } + + /** + * 删除菜单 + * + * @param id 菜单ID + * @returns 请求结果 + */ + static deleteById(id: number) { + return request({ + url: `${MENU_BASE_URL}/${id}`, + method: "delete", + }); + } +} + +export default MenuAPI; + +import { MenuTypeEnum } from "@/enums/MenuTypeEnum"; + +/** 菜单查询参数 */ +export interface MenuQuery { + /** 搜索关键字 */ + keywords?: string; +} + +/** 菜单视图对象 */ +export interface MenuVO { + /** 子菜单 */ + children?: MenuVO[]; + /** 组件路径 */ + component?: string; + /** ICON */ + icon?: string; + /** 菜单ID */ + id?: number; + /** 菜单名称 */ + name?: string; + /** 父菜单ID */ + parentId?: number; + /** 按钮权限标识 */ + perm?: string; + /** 跳转路径 */ + redirect?: string; + /** 路由名称 */ + routeName?: string; + /** 路由相对路径 */ + routePath?: string; + /** 菜单排序(数字越小排名越靠前) */ + sort?: number; + /** 菜单 */ + type?: MenuTypeEnum; + /** 菜单是否可见(1:显示;0:隐藏) */ + visible?: number; +} + +/** 菜单表单对象 */ +export interface MenuForm { + /** 菜单ID */ + id?: string; + /** 父菜单ID */ + parentId?: number; + /** 菜单名称 */ + name?: string; + /** 菜单是否可见(1-是 0-否) */ + visible: number; + /** ICON */ + icon?: string; + /** 排序 */ + sort?: number; + /** 路由名称 */ + routeName?: string; + /** 路由路径 */ + routePath?: string; + /** 组件路径 */ + component?: string; + /** 跳转路由路径 */ + redirect?: string; + /** 菜单 */ + type?: MenuTypeEnum; + /** 权限标识 */ + perm?: string; + /** 【菜单】是否开启页面缓存 */ + keepAlive?: number; + /** 【目录】只有一个子路由是否始终显示 */ + alwaysShow?: number; + /** 参数 */ + params?: KeyValue[]; +} + +interface KeyValue { + key: string; + value: string; +} + +/** RouteVO,路由对象 */ +export interface RouteVO { + /** 子路由列表 */ + children: RouteVO[]; + /** 组件路径 */ + component?: string; + /** 路由属性 */ + meta?: Meta; + /** 路由名称 */ + name?: string; + /** 路由路径 */ + path?: string; + /** 跳转链接 */ + redirect?: string; +} + +/** Meta,路由属性 */ +export interface Meta { + /** 【目录】只有一个子路由是否始终显示 */ + alwaysShow?: boolean; + /** 是否隐藏(true-是 false-否) */ + hidden?: boolean; + /** ICON */ + icon?: string; + /** 【菜单】是否开启页面缓存 */ + keepAlive?: boolean; + /** 拥有路由权限的角色编码 */ + roles?: string[]; + /** 路由title */ + title?: string; +} diff --git a/src/api/menu/index.ts b/src/api/menu/index.ts deleted file mode 100644 index 9657fcb3..00000000 --- a/src/api/menu/index.ts +++ /dev/null @@ -1,90 +0,0 @@ -import request from "@/utils/request"; -import { MenuQuery, MenuVO, MenuForm, RouteVO } from "./model"; - -class MenuAPI { - /** - * 获取路由列表 - */ - static getRoutes() { - return request({ - url: "/api/v1/menus/routes", - method: "get", - }); - } - - /** - * 获取菜单树形列表 - * - * @param queryParams - */ - static getList(queryParams: MenuQuery) { - return request({ - url: "/api/v1/menus", - method: "get", - params: queryParams, - }); - } - - /** - * 获取菜单下拉数据源 - */ - static getOptions() { - return request({ - url: "/api/v1/menus/options", - method: "get", - }); - } - - /** - * 获取菜单表单数据 - * - * @param id - */ - static getFormData(id: number) { - return request({ - url: "/api/v1/menus/" + id + "/form", - method: "get", - }); - } - - /** - * 添加菜单 - * - * @param data - */ - static add(data: MenuForm) { - return request({ - url: "/api/v1/menus", - method: "post", - data: data, - }); - } - - /** - * 修改菜单 - * - * @param id - * @param data - */ - static update(id: string, data: MenuForm) { - return request({ - url: "/api/v1/menus/" + id, - method: "put", - data: data, - }); - } - - /** - * 删除菜单 - * - * @param id 菜单ID - */ - static deleteById(id: number) { - return request({ - url: "/api/v1/menus/" + id, - method: "delete", - }); - } -} - -export default MenuAPI; diff --git a/src/api/menu/model.ts b/src/api/menu/model.ts deleted file mode 100644 index a9e846f5..00000000 --- a/src/api/menu/model.ts +++ /dev/null @@ -1,188 +0,0 @@ -import { MenuTypeEnum } from "@/enums/MenuTypeEnum"; - -/** - * 菜单查询参数类型 - */ -export interface MenuQuery { - keywords?: string; -} - -/** - * 菜单视图对象类型 - */ -export interface MenuVO { - /** - * 子菜单 - */ - children?: MenuVO[]; - /** - * 组件路径 - */ - component?: string; - /** - * ICON - */ - icon?: string; - /** - * 菜单ID - */ - id?: number; - /** - * 菜单名称 - */ - name?: string; - /** - * 父菜单ID - */ - parentId?: number; - /** - * 按钮权限标识 - */ - perm?: string; - /** - * 跳转路径 - */ - redirect?: string; - /** - * 路由名称 - */ - routeName?: string; - /** - * 路由相对路径 - */ - routePath?: string; - /** - * 菜单排序(数字越小排名越靠前) - */ - sort?: number; - /** - * 菜单类型 - */ - type?: MenuTypeEnum; - /** - * 菜单是否可见(1:显示;0:隐藏) - */ - visible?: number; -} - -/** - * 菜单表单对象类型 - */ -export interface MenuForm { - /** - * 菜单ID - */ - id?: string; - /** - * 父菜单ID - */ - parentId?: number; - /** - * 菜单名称 - */ - name?: string; - /** - * 菜单是否可见(1:是;0:否;) - */ - visible: number; - icon?: string; - /** - * 排序 - */ - sort?: number; - /** - * 组件路径 - */ - component?: string; - /** - * 路由路径 - */ - path?: string; - /** - * 跳转路由路径 - */ - redirect?: string; - - /** - * 菜单类型 - */ - type?: MenuTypeEnum; - - /** - * 权限标识 - */ - perm?: string; - /** - * 【菜单】是否开启页面缓存 - */ - keepAlive?: number; - - /** - * 【目录】只有一个子路由是否始终显示 - */ - alwaysShow?: number; - - params?: KeyValue[]; -} - -interface KeyValue { - key: string; - value: string; -} - -/** - * RouteVO,路由对象 - */ -export interface RouteVO { - /** - * 子路由列表 - */ - children: RouteVO[]; - /** - * 组件路径 - */ - component?: string; - meta?: Meta; - /** - * 路由名称 - */ - name?: string; - /** - * 路由路径 - */ - path?: string; - /** - * 跳转链接 - */ - redirect?: string; -} - -/** - * Meta,路由属性类型 - */ -export interface Meta { - /** - * 【目录】只有一个子路由是否始终显示 - */ - alwaysShow?: boolean; - /** - * 是否隐藏(true-是 false-否) - */ - hidden?: boolean; - /** - * ICON - */ - icon?: string; - /** - * 【菜单】是否开启页面缓存 - */ - keepAlive?: boolean; - /** - * 拥有路由权限的角色编码 - */ - roles?: string[]; - /** - * 路由title - */ - title?: string; -} diff --git a/src/api/role.ts b/src/api/role.ts new file mode 100644 index 00000000..bfbbac21 --- /dev/null +++ b/src/api/role.ts @@ -0,0 +1,140 @@ +import request from "@/utils/request"; + +const ROLE_BASE_URL = "/api/v1/roles"; + +class RoleAPI { + /** 获取角色分页数据 */ + static getPage(queryParams?: RolePageQuery) { + return request>({ + url: `${ROLE_BASE_URL}/page`, + method: "get", + params: queryParams, + }); + } + + /** 获取角色下拉数据源 */ + static getOptions() { + return request({ + url: `${ROLE_BASE_URL}/options`, + method: "get", + }); + } + + /** + * 获取角色的菜单ID集合 + * + * @param roleId 角色ID + * @returns 角色的菜单ID集合 + */ + static getRoleMenuIds(roleId: number) { + return request({ + url: `${ROLE_BASE_URL}/${roleId}/menuIds`, + method: "get", + }); + } + + /** + * 分配菜单权限 + * + * @param roleId 角色ID + * @param data 菜单ID集合 + * @returns 请求结果 + */ + static updateRoleMenus(roleId: number, data: number[]) { + return request({ + url: `${ROLE_BASE_URL}/${roleId}/menus`, + method: "put", + data: data, + }); + } + + /** + * 获取角色表单数据 + * + * @param id 角色ID + * @returns 角色表单数据 + */ + static getFormData(id: number) { + return request({ + url: `${ROLE_BASE_URL}/${id}/form`, + method: "get", + }); + } + + /** 添加角色 */ + static add(data: RoleForm) { + return request({ + url: `${ROLE_BASE_URL}`, + method: "post", + data: data, + }); + } + + /** + * 更新角色 + * + * @param id 角色ID + * @param data 角色表单数据 + */ + static update(id: number, data: RoleForm) { + return request({ + url: `${ROLE_BASE_URL}/${id}`, + method: "put", + data: data, + }); + } + + /** + * 批量删除角色,多个以英文逗号(,)分割 + * + * @param ids 角色ID字符串,多个以英文逗号(,)分割 + */ + static deleteByIds(ids: string) { + return request({ + url: `${ROLE_BASE_URL}/${ids}`, + method: "delete", + }); + } +} + +export default RoleAPI; + +/** 角色分页查询参数 */ +export interface RolePageQuery extends PageQuery { + /** 搜索关键字 */ + keywords?: string; +} + +/** 角色分页对象 */ +export interface RolePageVO { + /** 角色编码 */ + code?: string; + /** 角色ID */ + id?: number; + /** 角色名称 */ + name?: string; + /** 排序 */ + sort?: number; + /** 角色状态 */ + status?: number; + /** 创建时间 */ + createTime?: Date; + /** 修改时间 */ + updateTime?: Date; +} + +/** 角色表单对象 */ +export interface RoleForm { + /** 角色ID */ + id?: number; + /** 角色编码 */ + code: string; + /** 数据权限 */ + dataScope?: number; + /** 角色名称 */ + name: string; + /** 排序 */ + sort?: number; + /** 角色状态(1-正常;0-停用) */ + status?: number; +} diff --git a/src/api/role/index.ts b/src/api/role/index.ts deleted file mode 100644 index 148a2518..00000000 --- a/src/api/role/index.ts +++ /dev/null @@ -1,108 +0,0 @@ -import request from "@/utils/request"; -import { RoleQuery, RolePageResult, RoleForm } from "./model"; - -class RoleAPI { - /** - * 获取角色分页数据 - * - * @param queryParams - */ - static getPage(queryParams?: RoleQuery) { - return request({ - url: "/api/v1/roles/page", - method: "get", - params: queryParams, - }); - } - - /** - * 获取角色下拉数据源 - * - * @param queryParams - */ - static getOptions(queryParams?: RoleQuery) { - return request({ - url: "/api/v1/roles/options", - method: "get", - params: queryParams, - }); - } - - /** - * 获取角色的菜单ID集合 - * - * @param queryParams - */ - static getRoleMenuIds(roleId: number) { - return request({ - url: "/api/v1/roles/" + roleId + "/menuIds", - method: "get", - }); - } - - /** - * 分配菜单权限给角色 - * - * @param queryParams - */ - static updateRoleMenus(roleId: number, data: number[]) { - return request({ - url: "/api/v1/roles/" + roleId + "/menus", - method: "put", - data: data, - }); - } - - /** - * 获取角色表单数据 - * - * @param id - */ - static getFormData(id: number) { - return request({ - url: "/api/v1/roles/" + id + "/form", - method: "get", - }); - } - - /** - * 添加角色 - * - * @param data - */ - static add(data: RoleForm) { - return request({ - url: "/api/v1/roles", - method: "post", - data: data, - }); - } - - /** - * 更新角色 - * - * @param id - * @param data - */ - static update(id: number, data: RoleForm) { - return request({ - url: "/api/v1/roles/" + id, - method: "put", - data: data, - }); - } - - /** - * 批量删除角色,多个以英文逗号(,)分割 - * - * @param ids - */ - static deleteByIds(ids: string) { - return request({ - url: "/api/v1/roles/" + ids, - method: "delete", - }); - } -} - -export default RoleAPI; diff --git a/src/api/role/model.ts b/src/api/role/model.ts deleted file mode 100644 index 2d259c7f..00000000 --- a/src/api/role/model.ts +++ /dev/null @@ -1,78 +0,0 @@ -/** - * 角色查询参数 - */ -export interface RoleQuery extends PageQuery { - keywords?: string; -} - -/** - * 角色分页对象 - */ -export interface RolePageVO { - /** - * 角色编码 - */ - code?: string; - - /** - * 角色ID - */ - id?: number; - /** - * 角色名称 - */ - name?: string; - /** - * 排序 - */ - sort?: number; - /** - * 角色状态 - */ - status?: number; - /** - * 创建时间 - */ - createTime?: Date; - /** - * 修改时间 - */ - updateTime?: Date; -} - -/** - * 角色分页 - */ -export type RolePageResult = PageResult; - -/** - * 角色表单对象 - */ -export interface RoleForm { - /** - * 角色ID - */ - id?: number; - - /** - * 角色编码 - */ - code: string; - /** - * 数据权限 - */ - dataScope?: number; - - /** - * 角色名称 - */ - name: string; - /** - * 排序 - */ - sort?: number; - /** - * 角色状态(1-正常;0-停用) - */ - status?: number; -} diff --git a/src/api/user.ts b/src/api/user.ts new file mode 100644 index 00000000..e4d29d55 --- /dev/null +++ b/src/api/user.ts @@ -0,0 +1,232 @@ +import request from "@/utils/request"; + +const USER_BASE_URL = "/api/v1/users"; + +class UserAPI { + /** + * 获取当前登录用户信息 + * + * @returns 登录用户昵称、头像信息,包括角色和权限 + */ + static getInfo() { + return request({ + url: `${USER_BASE_URL}/me`, + method: "get", + }); + } + + /** + * 获取用户分页列表 + * + * @param queryParams 查询参数 + */ + static getPage(queryParams: UserPageQuery) { + return request>({ + url: `${USER_BASE_URL}/page`, + method: "get", + params: queryParams, + }); + } + + /** + * 获取用户表单详情 + * + * @param userId 用户ID + * @returns 用户表单详情 + */ + static getFormData(userId: number) { + return request({ + url: `${USER_BASE_URL}/${userId}/form`, + method: "get", + }); + } + + /** + * 添加用户 + * + * @param data 用户表单数据 + */ + static add(data: UserForm) { + return request({ + url: `${USER_BASE_URL}`, + method: "post", + data: data, + }); + } + + /** + * 修改用户 + * + * @param id 用户ID + * @param data 用户表单数据 + */ + static update(id: number, data: UserForm) { + return request({ + url: `${USER_BASE_URL}/${id}`, + method: "put", + data: data, + }); + } + + /** + * 修改用户密码 + * + * @param id 用户ID + * @param password 新密码 + */ + static updatePassword(id: number, password: string) { + return request({ + url: `${USER_BASE_URL}/${id}/password`, + method: "patch", + params: { password: password }, + }); + } + + /** + * 批量删除用户,多个以英文逗号(,)分割 + * + * @param ids 用户ID字符串,多个以英文逗号(,)分割 + */ + static deleteByIds(ids: string) { + return request({ + url: `${USER_BASE_URL}/${ids}`, + method: "delete", + }); + } + + /** 下载用户导入模板 */ + static downloadTemplate() { + return request({ + url: `${USER_BASE_URL}/template`, + method: "get", + responseType: "arraybuffer", + }); + } + + /** + * 导出用户 + * + * @param queryParams 查询参数 + */ + static export(queryParams: UserPageQuery) { + return request({ + url: `${USER_BASE_URL}/export`, + method: "get", + params: queryParams, + responseType: "arraybuffer", + }); + } + + /** + * 导入用户 + * + * @param deptId 部门ID + * @param file 导入文件 + */ + static import(deptId: number, file: File) { + const formData = new FormData(); + formData.append("file", file); + return request({ + url: `${USER_BASE_URL}/import`, + method: "post", + params: { deptId: deptId }, + data: formData, + headers: { + "Content-Type": "multipart/form-data", + }, + }); + } +} + +export default UserAPI; + +/** 登录用户信息 */ +export interface UserInfo { + /** 用户ID */ + userId?: number; + + /** 用户名 */ + username?: string; + + /** 昵称 */ + nickname?: string; + + /** 头像URL */ + avatar?: string; + + /** 角色 */ + roles: string[]; + + /** 权限 */ + perms: string[]; +} + +/** + * 用户分页查询对象 + */ +export interface UserPageQuery extends PageQuery { + /** 搜索关键字 */ + keywords?: string; + + /** 用户状态 */ + status?: number; + + /** 部门ID */ + deptId?: number; + + /** 开始时间 */ + startTime?: string; + + /** 结束时间 */ + endTime?: string; +} + +/** 用户分页对象 */ +export interface UserPageVO { + /** 用户头像URL */ + avatar?: string; + /** 创建时间 */ + createTime?: Date; + /** 部门名称 */ + deptName?: string; + /** 用户邮箱 */ + email?: string; + /** 性别 */ + genderLabel?: string; + /** 用户ID */ + id?: number; + /** 手机号 */ + mobile?: string; + /** 用户昵称 */ + nickname?: string; + /** 角色名称,多个使用英文逗号(,)分割 */ + roleNames?: string; + /** 用户状态(1:启用;0:禁用) */ + status?: number; + /** 用户名 */ + username?: string; +} + +/** 用户表单类型 */ +export interface UserForm { + /** 用户头像 */ + avatar?: string; + /** 部门ID */ + deptId?: number; + /** 邮箱 */ + email?: string; + /** 性别 */ + gender?: number; + /** 用户ID */ + id?: number; + /** 手机号 */ + mobile?: string; + /** 昵称 */ + nickname?: string; + /** 角色ID集合 */ + roleIds?: number[]; + /** 用户状态(1:正常;0:禁用) */ + status?: number; + /** 用户名 */ + username?: string; +} diff --git a/src/api/user/index.ts b/src/api/user/index.ts deleted file mode 100644 index 306bfb44..00000000 --- a/src/api/user/index.ts +++ /dev/null @@ -1,141 +0,0 @@ -import request from "@/utils/request"; -import { UserForm, UserInfo, UserPageVO, UserQuery } from "./model"; - -class UserAPI { - /** - * 登录成功后获取用户信息(昵称、头像、权限集合和角色集合) - */ - static getInfo() { - return request({ - url: "/api/v1/users/me", - method: "get", - }); - } - - /** - * 获取用户分页列表 - * - * @param queryParams - */ - static getPage(queryParams: UserQuery) { - return request>({ - url: "/api/v1/users/page", - method: "get", - params: queryParams, - }); - } - - /** - * 获取用户表单详情 - * - * @param userId - */ - static getFormData(userId: number) { - return request({ - url: "/api/v1/users/" + userId + "/form", - method: "get", - }); - } - - /** - * 添加用户 - * - * @param data - */ - static add(data: UserForm) { - return request({ - url: "/api/v1/users", - method: "post", - data: data, - }); - } - - /** - * 修改用户 - * - * @param id - * @param data - */ - static update(id: number, data: UserForm) { - return request({ - url: "/api/v1/users/" + id, - method: "put", - data: data, - }); - } - - /** - * 修改用户密码 - * - * @param id - * @param password - */ - static updatePassword(id: number, password: string) { - return request({ - url: "/api/v1/users/" + id + "/password", - method: "patch", - params: { password: password }, - }); - } - - /** - * 删除用户 - * - * @param ids - */ - static deleteByIds(ids: string) { - return request({ - url: "/api/v1/users/" + ids, - method: "delete", - }); - } - - /** - * 下载用户导入模板 - * - * @returns - */ - static downloadTemplate() { - return request({ - url: "/api/v1/users/template", - method: "get", - responseType: "arraybuffer", - }); - } - - /** - * 导出用户 - * - * @param queryParams - * @returns - */ - static export(queryParams: UserQuery) { - return request({ - url: "/api/v1/users/export", - method: "get", - params: queryParams, - responseType: "arraybuffer", - }); - } - - /** - * 导入用户 - * - * @param file - */ - static import(deptId: number, file: File) { - const formData = new FormData(); - formData.append("file", file); - return request({ - url: "/api/v1/users/import", - method: "post", - params: { deptId: deptId }, - data: formData, - headers: { - "Content-Type": "multipart/form-data", - }, - }); - } -} - -export default UserAPI; diff --git a/src/api/user/model.ts b/src/api/user/model.ts deleted file mode 100644 index c0060f27..00000000 --- a/src/api/user/model.ts +++ /dev/null @@ -1,115 +0,0 @@ -/** - * 登录用户信息 - */ -export interface UserInfo { - userId?: number; - username?: string; - nickname?: string; - avatar?: string; - roles: string[]; - perms: string[]; -} - -/** - * 用户查询对象类型 - */ -export interface UserQuery extends PageQuery { - keywords?: string; - status?: number; - deptId?: number; - startTime?: string; - endTime?: string; -} - -/** - * 用户分页对象 - */ -export interface UserPageVO { - /** - * 用户头像地址 - */ - avatar?: string; - /** - * 创建时间 - */ - createTime?: Date; - /** - * 部门名称 - */ - deptName?: string; - /** - * 用户邮箱 - */ - email?: string; - /** - * 性别 - */ - genderLabel?: string; - /** - * 用户ID - */ - id?: number; - /** - * 手机号 - */ - mobile?: string; - /** - * 用户昵称 - */ - nickname?: string; - /** - * 角色名称,多个使用英文逗号(,)分割 - */ - roleNames?: string; - /** - * 用户状态(1:启用;0:禁用) - */ - status?: number; - /** - * 用户名 - */ - username?: string; -} - -/** - * 用户表单类型 - */ -export interface UserForm { - /** - * 用户头像 - */ - avatar?: string; - /** - * 部门ID - */ - deptId?: number; - /** - * 邮箱 - */ - email?: string; - /** - * 性别 - */ - gender?: number; - /** - * 用户ID - */ - id?: number; - mobile?: string; - /** - * 昵称 - */ - nickname?: string; - /** - * 角色ID集合 - */ - roleIds?: number[]; - /** - * 用户状态(1:正常;0:禁用) - */ - status?: number; - /** - * 用户名 - */ - username?: string; -} diff --git a/src/assets/images/login-bg-dark.jpg b/src/assets/images/login-background-dark.jpg similarity index 100% rename from src/assets/images/login-bg-dark.jpg rename to src/assets/images/login-background-dark.jpg diff --git a/src/assets/images/login-bg.jpg b/src/assets/images/login-background-light.jpg similarity index 100% rename from src/assets/images/login-bg.jpg rename to src/assets/images/login-background-light.jpg diff --git a/src/components/CURD/PageContent.vue b/src/components/CURD/PageContent.vue index f093ff57..7b73799f 100644 --- a/src/components/CURD/PageContent.vue +++ b/src/components/CURD/PageContent.vue @@ -29,11 +29,22 @@ 删除 + + @@ -575,8 +586,8 @@ function handleSelectionChange(selection: any[]) { } // 刷新 -function handleRefresh() { - fetchPageData(lastFormData); +function handleRefresh(isRestart = false) { + fetchPageData(lastFormData, isRestart); } // 删除 @@ -595,7 +606,7 @@ function handleDelete(id?: number | string) { if (props.contentConfig.deleteAction) { props.contentConfig.deleteAction(ids).then(() => { ElMessage.success("删除成功"); - fetchPageData({}, true); + handleRefresh(true); }); } else { ElMessage.error("未配置deleteAction"); @@ -695,20 +706,22 @@ function handleExports() { } // 导入表单 +let isFileImport = false; const uploadRef = ref(); -const importsModalVisible = ref(false); -const importsFormRef = ref(); -const importsFormData = reactive<{ +const importModalVisible = ref(false); +const importFormRef = ref(); +const importFormData = reactive<{ files: UploadUserFile[]; }>({ files: [], }); -const importsFormRules: FormRules = { +const importFormRules: FormRules = { files: [{ required: true, message: "请选择文件" }], }; // 打开导入弹窗 -function handleOpenImportsModal() { - importsModalVisible.value = true; +function handleOpenImportModal(isFile: boolean = false) { + importModalVisible.value = true; + isFileImport = isFile; } // 覆盖前一个文件 function handleFileExceed(files: File[]) { @@ -719,11 +732,11 @@ function handleFileExceed(files: File[]) { } // 下载导入模板 function handleDownloadTemplate() { - const importsTemplate = props.contentConfig.importsTemplate; - if (typeof importsTemplate === "string") { - window.open(importsTemplate); - } else if (typeof importsTemplate === "function") { - importsTemplate().then((response) => { + const importTemplate = props.contentConfig.importTemplate; + if (typeof importTemplate === "string") { + window.open(importTemplate); + } else if (typeof importTemplate === "function") { + importTemplate().then((response) => { const fileData = response.data; const fileName = decodeURI( response.headers["content-disposition"].split(";")[1].split("=")[1] @@ -731,21 +744,40 @@ function handleDownloadTemplate() { saveXlsx(fileData, fileName); }); } else { - ElMessage.error("未配置importsTemplate"); + ElMessage.error("未配置importTemplate"); } } // 导入确认 -const handleImportsSubmit = useThrottleFn(() => { - importsFormRef.value?.validate((valid: boolean) => { - valid && handleImports(); +const handleImportSubmit = useThrottleFn(() => { + importFormRef.value?.validate((valid: boolean) => { + if (valid) { + if (isFileImport) { + handleImport(); + } else { + handleImports(); + } + } }); }, 3000); // 关闭导入弹窗 -function handleCloseImportsModal() { - importsModalVisible.value = false; - importsFormRef.value?.resetFields(); +function handleCloseImportModal() { + importModalVisible.value = false; + importFormRef.value?.resetFields(); nextTick(() => { - importsFormRef.value?.clearValidate(); + importFormRef.value?.clearValidate(); + }); +} +// 文件导入 +function handleImport() { + const importAction = props.contentConfig.importAction; + if (importAction === undefined) { + ElMessage.error("未配置importAction"); + return; + } + importAction(importFormData.files[0].raw as File).then(() => { + ElMessage.success("导入数据成功"); + handleCloseImportModal(); + handleRefresh(true); }); } // 导入 @@ -756,7 +788,7 @@ function handleImports() { return; } // 获取选择的文件 - const file = importsFormData.files[0].raw as File; + const file = importFormData.files[0].raw as File; // 创建Workbook实例 const workbook = new ExcelJS.Workbook(); // 使用FileReader对象来读取文件内容 @@ -803,7 +835,8 @@ function handleImports() { } importsAction(data).then(() => { ElMessage.success("导入数据成功"); - handleCloseImportsModal(); + handleCloseImportModal(); + handleRefresh(true); }); }) .catch((error) => console.log(error)); @@ -823,7 +856,7 @@ function handleToolbar(name: string) { handleOpenExportsModal(); break; case "imports": - handleOpenImportsModal(); + handleOpenImportModal(); break; case "search": emit("searchClick"); @@ -834,6 +867,9 @@ function handleToolbar(name: string) { case "delete": handleDelete(); break; + case "import": + handleOpenImportModal(true); + break; case "export": emit("exportClick"); break; @@ -878,11 +914,11 @@ function handleModify( // 分页切换 function handleSizeChange(value: number) { pagination.pageSize = value; - fetchPageData(lastFormData); + handleRefresh(); } function handleCurrentChange(value: number) { pagination.currentPage = value; - fetchPageData(lastFormData); + handleRefresh(); } // 远程数据筛选 diff --git a/src/components/CURD/types.ts b/src/components/CURD/types.ts index 1cbdb561..af0cd7f9 100644 --- a/src/components/CURD/types.ts +++ b/src/components/CURD/types.ts @@ -92,8 +92,10 @@ export interface IContentConfig { exportAction?: (queryParams: T) => Promise; // 前端全量导出的网络请求函数(需返回promise) exportsAction?: (queryParams: T) => Promise; - // 前端导入模板 - importsTemplate?: string | (() => Promise); + // 导入模板 + importTemplate?: string | (() => Promise); + // 后端导入的网络请求函数(需返回promise) + importAction?: (file: File) => Promise; // 前端导入的网络请求函数(需返回promise) importsAction?: (data: IObject[]) => Promise; // 主键名(默认为id) @@ -102,6 +104,7 @@ export interface IContentConfig { toolbar?: Array< | "add" | "delete" + | "import" | "export" | { auth: string; diff --git a/src/components/Dictionary/index.vue b/src/components/Dictionary/index.vue index a3804ff3..763c2c6f 100644 --- a/src/components/Dictionary/index.vue +++ b/src/components/Dictionary/index.vue @@ -20,9 +20,9 @@ import DictAPI from "@/api/dict"; const props = defineProps({ /** - * 字典类型编码(eg: 性别-gender) + * 字典编码(eg: 性别-gender) */ - typeCode: { + code: { type: String, required: true, }, @@ -39,14 +39,17 @@ const props = defineProps({ }, }); -const emits = defineEmits(["update:modelValue"]); // 父组件监听事件,同步子组件值的变化给父组件 +const emits = defineEmits(["update:modelValue"]); -const options: Ref = ref([]); // 字典下拉数据源 +const options: Ref = ref([]); const selectedValue = ref(); watch([options, () => props.modelValue], ([newOptions, newModelValue]) => { - if (newOptions.length === 0) return; // 下拉数据源加载未完成不回显 + if (newOptions.length === 0) { + // 下拉数据源加载未完成不回显 + return; + } if (newModelValue == undefined) { selectedValue.value = undefined; return; @@ -65,8 +68,8 @@ function handleChange(val?: string | number | undefined) { } onBeforeMount(() => { - // 根据字典类型编码(typeCode)获取字典选项 - DictAPI.getDictOptions(props.typeCode).then((data) => { + // 根据字典编码获取字典项 + DictAPI.getOptions(props.code).then((data) => { options.value = data; }); }); diff --git a/src/layout/components/Sidebar/components/SidebarMenuItem.vue b/src/layout/components/Sidebar/components/SidebarMenuItem.vue index 625b02e9..e45ec8d1 100644 --- a/src/layout/components/Sidebar/components/SidebarMenuItem.vue +++ b/src/layout/components/Sidebar/components/SidebarMenuItem.vue @@ -1,6 +1,7 @@