diff --git a/src/api/system/menu.ts b/src/api/system/menu.ts new file mode 100644 index 0000000..54424c2 --- /dev/null +++ b/src/api/system/menu.ts @@ -0,0 +1,76 @@ +import request from "@/utils/request"; +// 菜单基础URL +const MENU_BASE_URL = "/api/v1/menus"; + +const MenuAPI = { + /** + * 获取当前用户的路由列表 + *

+ * 无需传入角色,后端解析token获取角色自行判断是否拥有路由的权限 + * + * @returns 路由列表 + */ + getRoutes() { + return request({ + url: `${MENU_BASE_URL}/routes`, + method: "GET", + }); + }, + + /** + * 获取菜单下拉数据源 + * + * @returns 菜单下拉数据源 + */ + getOptions(onlyParent?: boolean) { + return request({ + url: `${MENU_BASE_URL}/options`, + method: "GET", + data: { onlyParent: onlyParent }, + }); + }, +}; + +export default MenuAPI; + +/** 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; + /** 路由title */ + title?: string; +} + +/** + * 组件数据源 + */ +interface OptionType { + /** 值 */ + value: string | number; + /** 文本 */ + label: string; + /** 子列表 */ + children?: OptionType[]; +} diff --git a/src/components/da-tree/changelog.md b/src/components/da-tree/changelog.md new file mode 100644 index 0000000..7117197 --- /dev/null +++ b/src/components/da-tree/changelog.md @@ -0,0 +1,196 @@ +# 1.4.2 + +新增 + +1. 新增`filterValue`属性,支持通过此关键词来搜索并筛选树结构的内容 + +# 1.4.1 + +修复 + +1. 修复单选 onlyRadioLeaf 时末级节点无法选中的 bug + +# 1.4.0 + +版本调整 + +建议更新,但需要注意,异步数据的时候,后台需返回 leaf 字段来判断是否末项数据 + +1. **调整数据项格式,新增 `leaf` 字段,来判断是否为末节点** +2. **调整数据项格式,新增 `sort` 字段,来排序节点位置** +3. **注意:异步加载数据,当为末项的时候,需要服务端数据返回 `leaf` 字段** +4. 新增 `alwaysFirstLoad` ,即异步数据总会在第一次展开节点时,拉取一次后台数据,来比对是否一致 +5. 拆分 `field` 属性,**注意: 1.5.0 版本后将移除 `field` 属性** +6. 新增 `labelField` 同 `field.label`,指定节点对象中某个属性为**标签**字段,默认`label` +7. 新增 `valueField` 同 `field.key`,指定节点对象中某个属性为**值**字段,默认`value` +8. 新增 `childrenField` 同 `field.children`,指定节点对象中某个属性为**子树节点**字段,默认`children` +9. 新增 `disabledField` 同 `field.disabled`,指定节点对象中某个属性为**禁用**字段,默认`disabled` +10. 新增 `appendField` 同 `field.append`,指定节点对象中某个属性为**副标签**字段,默认`append` +11. 新增 `leafField` 同 `field.label`,指定节点对象中某个属性为**末级节点**字段,默认`leaf` +12. 新增 `sortField` 同 `field.label`,指定节点对象中某个属性为**排序**字段,默认`sort` +13. 新增 `isLeafFn` ,用来自定义控制数据项的末项 +14. 更多的项目示例 +15. 支持单选取消选中 +16. 修复节点展开时可能存在的 bug +17. 修复节点选择可能存在的 bug +18. 调整为子节点默认继承父节点禁用属性 +19. `setExpandedKeys` 添加参数一为 `all` 即可支持一键展开/收起全部节点 +20. 其它更多优化 + +# 1.3.4 + +优化 + +1. 优化图标字体命名 + +# 1.3.3 + +优化 + +1. 新增方法调用 + > - 新增`getUncheckedKeys`,返回未选的 key + > - 新增`getUncheckedNodes`,返回未选的节点 + > - 新增`getUnexpandedKeys`,返回未展开的 key + > - 新增`getUnexpandedNodes`,返回未展开的节点 +2. 优化示例项目 + +# 1.3.2 + +修复 + +1. 修复在 APP 真机环境中的报错 + +# 1.3.1 + +修复 + +1. 修复方法`setExpandedKeys`没联动展开上级父子节点 + +# 1.3.0 + +优化 + +1. `field`新增字段 `append` 用于在标签后面显示小提示 +2. 新增支持点击标签也能选中节点 +3. 方法`setExpandedKeys`支持加载动态数据 +4. 修复父节点禁用,则不能展开及图标展开显示 +5. 修复动态加载数据时,末级节点的 `children` 为 `null` 时仍显示展开图标 + +# 1.2.6 + +新增 + +1. 新增支持主题换色 +2. 支持单选的`onlyRadioLeaf`为`true`时可点父节点展开/收起 +3. 优化`expandChecked`调整为不展开无子节点的节点 + +# 1.2.5 + +新增 + +1. 新增 `expandChecked`,控制选择时是否展开当前已选的所有下级节点 + +# 1.2.4 + +修复 + +1. 修复动态数据展开状态异常问题 + +# 1.2.3 + +新增 + +1. 新增 `checkedDisabled`,是否渲染禁用值 +2. 新增 `packDisabledkey`,是否返回已禁用并选中的 key +3. 修复选择父级时,子级已禁用但仍被选中的问题 + +# 1.2.2 + +优化 + +1. 调整动态数据载入处理方式 +2. 修复节点数据因动态数据引起的状态异常 +3. 修复初始节点数据默认选中 + +# 1.2.1 + +修复 + +1. 修复切换`选中状态`被重复选中问题 +2. 修复动态数据引起的重复选择问题 + +# 1.2.0 + +新增 + +1. 新增方法调用 + > - 新增`setCheckedKeys`,方法设置指定 key 的节点选中状态 + > - 新增`setExpandedKeys`,方法设置指定 key 的节点展开状态 +2. 修复小程序重复插槽一直刷报错问题 +3. 优化展开时,会展开子级所以下级节点 + +# 1.1.1 + +新增 + +1. 新增`data`的`disabled`,支持节点禁用状态 +2. 新增`field`的`disabled`,可自定`disabled`字段值 + +# 1.1.0 + +新增 + +1. 新增`loadMode`、`loadApi`,支持展开时加载异步数据 +2. 新增方法调用 + > - 新增`getCheckedKeys`,方法返回已选的 key + > - 新增`getHalfCheckedKeys`,方法返回半选的 key + > - 新增`getExpandedKeys`,方法返回已展开的 key + > - 新增`getCheckedNodes`,方法返回已选的节点 + > - 新增`getHalfCheckedNodes`,方法返回半选的节点 + > - 新增`getExpandedNodes`,方法返回已展开的节点 +3. 对代码进行重构,更易于后期拓展 +4. 此次更新后,页面多个的 DaTee 组件间的数据不再关联 + +# 1.0.6 + +新增 + +1. 新增`checkStrictly`,多选模式下选中时是否父子不关联 + +# 1.0.5 + +修复 + +1. 修复多选时已选数据重复问题 + +# 1.0.4 + +修复 + +1. 修复 `change` 事件回调数据的问题 + +# 1.0.3 + +优化 + +1. 优化文档及示例说明 + +# 1.0.2 + +新增 + +1. 新增 `onlyRadioLeaf` ,单选时只允许选中末级 +2. 优化默认展开及默认选择的展开问题 + +# 1.0.1 + +新增 + +1. 支持展开/收起回调事件`@expand` + +# 1.0.0 + +初始版本 1.0.0,基于 Vue3 进行开发,支持单选、多选,兼容各大平台 + +1. 支持单选 +2. 支持多选 diff --git a/src/components/da-tree/index.vue b/src/components/da-tree/index.vue new file mode 100644 index 0000000..03b0329 --- /dev/null +++ b/src/components/da-tree/index.vue @@ -0,0 +1,1206 @@ + + + + + diff --git a/src/components/da-tree/props.ts b/src/components/da-tree/props.ts new file mode 100644 index 0000000..4b710df --- /dev/null +++ b/src/components/da-tree/props.ts @@ -0,0 +1,197 @@ +export default { + /** + * 树的数据 + */ + data: { + type: Array, + default: () => [], + }, + /** + * 主题色 + */ + themeColor: { + type: String, + default: "#007aff", + }, + /** + * 是否开启多选,默认单选 + */ + showCheckbox: { + type: Boolean, + default: false, + }, + /** + * 默认选中的节点,注意单选时为单个key,多选时为key的数组 + */ + defaultCheckedKeys: { + type: [Array, String, Number], + default: null, + }, + /** + * 是否默认展开全部 + */ + defaultExpandAll: { + type: Boolean, + default: false, + }, + /** + * 默认展开的节点 + */ + defaultExpandedKeys: { + type: Array, + default: null, + }, + /** + * 筛选关键词 + */ + filterValue: { + type: String, + default: "", + }, + /** + * 是否自动展开到选中的节点,默认不展开 + */ + expandChecked: { + type: Boolean, + default: false, + }, + + /** + * (旧)字段对应内容,默认为 {label: 'label',key: 'key', children: 'children', disabled: 'disabled', append: 'append'} + * 注意:1.5.0版本后不再兼容 + */ + field: { + type: Object, + default: null, + }, + /** + * 标签字段(新,拆分了) + */ + labelField: { + type: String, + default: "label", + }, + /** + * 值字段(新,拆分了) + */ + valueField: { + type: String, + default: "value", + }, + /** + * 下级字段(新,拆分了) + */ + childrenField: { + type: String, + default: "children", + }, + /** + * 禁用字段(新,拆分了) + */ + disabledField: { + type: String, + default: "disabled", + }, + /** + * 末级节点字段(新,拆分了) + */ + leafField: { + type: String, + default: "leaf", + }, + /** + * 副标签字段(新,拆分了) + */ + appendField: { + type: String, + default: "append", + }, + /** + * 排序字段(新,拆分了) + */ + sortField: { + type: String, + default: "sort", + }, + /** + * Api数据返回后的结果路径,支持嵌套如`data.list` + */ + resultField: { + type: String, + default: "", + }, + isLeafFn: { + type: Function, + default: null, + }, + /** + * 是否显示单选图标,默认显示 + */ + showRadioIcon: { + type: Boolean, + default: true, + }, + /** + * 单选时只允许选中末级,默认可随意选中 + */ + onlyRadioLeaf: { + type: Boolean, + default: false, + }, + /** + * 多选时,是否执行父子不关联的任意勾选,默认父子关联 + */ + checkStrictly: { + type: Boolean, + default: false, + }, + /** + * 为 true 时,空的 children 数组会显示展开图标 + */ + loadMode: { + type: Boolean, + default: false, + }, + /** + * 异步加载接口 + */ + loadApi: { + type: Function, + default: null, + }, + /** + * 是否总在首次的时候加载一下内容,来比对是否一致 + */ + alwaysFirstLoad: { + type: Boolean, + default: false, + }, + /** + * 是否渲染(操作)禁用值 + */ + checkedDisabled: { + type: Boolean, + default: false, + }, + /** + * 是否返回已禁用的但已选中的key + */ + packDisabledkey: { + type: Boolean, + default: true, + }, + /** + * 选择框的位置,可选 left/right + */ + checkboxPlacement: { + type: String, + default: "left", + }, + /** + * 子项缩进距离,默认40,单位rpx + */ + indent: { + type: Number, + default: 40, + }, +}; diff --git a/src/components/da-tree/readme.md b/src/components/da-tree/readme.md new file mode 100644 index 0000000..fa3f318 --- /dev/null +++ b/src/components/da-tree/readme.md @@ -0,0 +1,310 @@ +# da-tree + +一个基于 Vue3 的 tree(树)组件,同时支持主题换色,可能是最适合你的 tree(树)组件 + +组件一直在更新,遇到问题可在下方讨论。 + +`同时更新 Vue2 版本,在此查看 ===>` **[Vue2 版](https://ext.dcloud.net.cn/plugin?id=12692)** + +### 关于使用 + +可在右侧的`使用 HBuilderX 导入插件`或`下载示例项目ZIP`,方便快速上手。 + +可通过下方的示例及文档说明,进一步了解使用组件相关细节参数。 + +插件地址:https://ext.dcloud.net.cn/plugin?id=12384 + +### 组件示例 + +```jsx + +``` + +```js +import { defineComponent, ref } from "vue"; + +/** + * 模拟创建一个接口数据 + */ +function GetApiData(currentNode) { + const { key } = currentNode; + + return new Promise((resolve) => { + setTimeout(() => { + // 模拟返回空数据 + if (key.indexOf("-") > -1) { + return resolve(null); + // return resolve([]) + } + + return resolve([ + { + id: `${key}-1`, + name: `行政部X${key}-1`, + }, + { + id: `${key}-2`, + name: `财务部X${key}-2`, + append: "定义了末项数据", + leaf: true, + }, + { + id: `${key}-3`, + name: `资源部X${key}-3`, + }, + { + id: `${key}-4`, + name: `资源部X${key}-3`, + append: "被禁用,无展开图标", + disabled: true, + }, + ]); + }, 2000); + }); +} + +import DaTree from "@/components/da-tree/index.vue"; +export default defineComponent({ + components: { DaTree }, + setup() { + const DaTreeRef = ref(); + // key的类型必须对应树数据key的类型 + const defaultCheckedKeysValue = ref(["211", "222"]); + const defaultCheckedKeysValue2 = ref("222"); + const defaultExpandKeysValue3 = ref(["212", "231"]); + const roomTreeData = ref([ + { + id: "2", + name: "行政中心", + children: [ + { + id: "21", + name: "行政部", + children: [ + { + id: "211", + name: "行政一部", + children: null, + }, + { + id: "212", + name: "行政二部", + children: [], + disabled: true, + }, + ], + }, + { + id: "22", + name: "财务部", + children: [ + { + id: "221", + name: "财务一部", + children: [], + disabled: true, + }, + { + id: "222", + name: "财务二部", + children: [], + }, + ], + }, + { + id: "23", + name: "人力资源部", + children: [ + { + id: "231", + name: "人力一部", + children: [], + }, + { + id: "232", + name: "人力二部", + append: "更多示例,请下载示例项目查看", + }, + ], + }, + ], + }, + ]); + function doExpandTree(keys, expand) { + DaTreeRef.value?.setExpandedKeys(keys, expand); + + const gek = DaTreeRef.value?.getExpandedKeys(); + console.log("当前已展开的KEY ==>", gek); + } + function doCheckedTree(keys, checked) { + DaTreeRef.value?.setCheckedKeys(keys, checked); + + const gek = DaTreeRef.value?.getCheckedKeys(); + console.log("当前已选中的KEY ==>", gek); + } + function handleTreeChange(allSelectedKeys, currentItem) { + console.log("handleTreeChange ==>", allSelectedKeys, currentItem); + } + function handleExpandChange(expand, currentItem) { + console.log("handleExpandChange ==>", expand, currentItem); + } + return { + DaTreeRef, + roomTreeData, + defaultCheckedKeysValue, + defaultCheckedKeysValue2, + defaultExpandKeysValue3, + handleTreeChange, + handleExpandChange, + GetApiData, + doExpandTree, + doCheckedTree, + }; + }, +}); +``` + +** 更多示例请下载/导入示例项目 ZIP 查看 ** + +### 组件参数 + +| 属性 | 类型 | 默认值 | 必填 | 说明 | +| :------------------ | :------------------------------ | :--------- | :--- | :--------------------------------------------------------------------------- | +| data | `Array` | - | 是 | 树的数据 | +| themeColor | `String` | `#007aff` | 否 | 主题色,十六进制 | +| defaultCheckedKeys | `Array` \| `Number` \| `String` | - | 否 | 默认选中的节点,单选为单个 key,多选为 key 的数组 | +| showCheckbox | `Boolean` | `false` | 否 | 是否开启多选,默认单选 | +| checkStrictly | `Boolean` | `false` | 否 | 多选时,是否执行父子不关联的任意勾选,默认父子关联 | +| showRadioIcon | `Boolean` | `true` | 否 | 是否显示单选图标,默认显示 | +| onlyRadioLeaf | `Boolean` | `true` | 否 | 单选时只允许选中末级,默认可随意选中 | +| defaultExpandAll | `Boolean` | `false` | 否 | 是否默认展开全部 | +| defaultExpandedKeys | `Array` | - | 否 | 默认展开的节点 | +| indent | `Number` | `40` | 否 | 子项缩进距离,单位 rpx | +| checkboxPlacement | `String` | `left` | 否 | 选择框的位置,可选 left/right | +| loadMode | `Boolean` | `false` | 否 | 为 true 时,空的 children 数组会显示展开图标 | +| loadApi | `Function` | - | 否 | 选择框的位置,可选 left/right | +| checkedDisabled | `Boolean` | `false` | 否 | 是否渲染禁用值,默认不渲染 | +| packDisabledkey | `Boolean` | `true` | 否 | 是否返回已禁用的但已选中的 key,默认返回禁用已选值 | +| expandChecked | `Boolean` | `false` | 否 | 是否自动展开到选中的节点,默认不展开 | +| alwaysFirstLoad | `Boolean` | `false` | 否 | 是否总在首次的时候加载一下内容,默认不加载,否则只有展开末级节点才会加载数据 | +| isLeafFn | `Function` | - | 否 | 自定义函数返回来控制数据项的末项 | +| field | `Object` | - | 否 | 字段对应内容,格式参考下方(1.5.0 后移除,请用单独的字段匹配) | +| labelField | `String` | `label` | 否 | 指定节点对象中某个属性为标签字段,默认`label` | +| valueField | `String` | `value` | 否 | 指定节点对象中某个属性为值字段,默认`value` | +| childrenField | `String` | `children` | 否 | 指定节点对象中某个属性为子树节点字段,默认`children` | +| disabledField | `String` | `disabled` | 否 | 指定节点对象中某个属性为禁用字段,默认`disabled` | +| appendField | `String` | `append` | 否 | 指定节点对象中某个属性为副标签字段,默认`append` | +| leafField | `String` | `leaf` | 否 | 指定节点对象中某个属性为末级节点字段,默认`leaf` | +| sortField | `String` | `sort` | 否 | 指定节点对象中某个属性为排序字段,默认`sort` | +| filterValue | `String` | - | 否 | 搜索筛选的关键词,通过输入关键词筛选内容 | + +**field 格式(1.5.0 后移除,请用单独的字段匹配)** + +```js +{ + label: 'label', + key: 'key', + children: 'children', + disabled: 'disabled', + append: 'append' +} +``` + +### 组件事件 + +| 事件名称 | 回调参数 | 说明 | +| :------- | :-------------------------------------- | :-------------- | +| change | `(allCheckedKeys, currentItem) => void` | 选中时回调 | +| expand | `(expandState, currentItem) => void` | 展开/收起时回调 | + +### 组件方法 + +| 方法名称 | 参数 | 说明 | +| :------------------ | :--------------- | :------------------------------------------------------------------------------------------------ | +| setCheckedKeys | `(keys,checked)` | 设置指定 key 的节点选中/取消选中的状态。注: keys 单选时为 key,多选时为 key 的数组 | +| setExpandedKeys | `(keys,expand)` | 设置指定 key 的节点展开/收起的状态,当 keys 为 all 时即代表展开/收起全部。注:keys 为数组或 `all` | +| getCheckedKeys | - | 返回已选的 key | +| getHalfCheckedKeys | - | 返回半选的 key | +| getUncheckedKeys | - | 返回未选的 key | +| getCheckedNodes | - | 返回已选的节点 | +| getUncheckedNodes | - | 返回未选的节点 | +| getHalfCheckedNodes | - | 返回半选的节点 | +| getExpandedKeys | - | 返回已展开的 key | +| getUnexpandedKeys | - | 返回未展开的 key | +| getExpandedNodes | - | 返回已展开的节点 | +| getUnexpandedNodes | - | 返回未展开的节点 | + +### 组件版本 + +v1.4.2 + +### 差异化 + +已通过测试 + +> - H5 页面 +> - 微信小程序 +> - 支付宝、钉钉小程序 +> - 字节跳动、抖音、今日头条小程序 +> - 百度小程序 +> - 飞书小程序 +> - QQ 小程序 +> - 京东小程序 + +未测试 + +> - 快手小程序由于非企业用户暂无演示 +> - 快应用、360 小程序因 Vue3 支持的原因暂无演示 + +### 开发组 + +[@CRLANG](https://crlang.com) diff --git a/src/components/da-tree/utils.ts b/src/components/da-tree/utils.ts new file mode 100644 index 0000000..d79ea1e --- /dev/null +++ b/src/components/da-tree/utils.ts @@ -0,0 +1,150 @@ +/** 未选 */ +export const unCheckedStatus = 0; +/** 半选 */ +export const halfCheckedStatus = 1; +/** 选中 */ +export const isCheckedStatus = 2; + +/** + * 深拷贝内容 + * @param originData 拷贝对象 + * @author crlang(https://crlang.com) + */ +export function deepClone(originData) { + const type = Object.prototype.toString.call(originData); + let data; + if (type === "[object Array]") { + data = []; + for (let i = 0; i < originData.length; i++) { + data.push(deepClone(originData[i])); + } + } else if (type === "[object Object]") { + data = {}; + for (const prop in originData) { + if (originData.hasOwnProperty(prop)) { + // 非继承属性 + data[prop] = deepClone(originData[prop]); + } + } + } else { + data = originData; + } + return data; +} + +/** + * 获取所有指定的节点 + * @param type + * @param value + * @author crlang(https://crlang.com) + */ +export function getAllNodes(list, type, value, packDisabledkey = true) { + if (!list || list.length === 0) { + return []; + } + + const res = []; + for (let i = 0; i < list.length; i++) { + const item = list[i]; + if (item[type] === value) { + if ((packDisabledkey && item.disabled) || !item.disabled) { + res.push(item); + } + } + } + + return res; +} + +/** + * 获取所有指定的key值 + * @param type + * @param value + * @author crlang(https://crlang.com) + */ +export function getAllNodeKeys(list, type, value, packDisabledkey = true) { + if (!list || list.length === 0) { + return null; + } + + const res = []; + for (let i = 0; i < list.length; i++) { + const item = list[i]; + if (item[type] === value) { + if ((packDisabledkey && item.disabled) || !item.disabled) { + res.push(item.key); + } + } + } + + return res.length ? res : null; +} + +/** + * 错误输出 + * + * @param msg + */ +export function logError(msg, ...args) { + console.error(`DaTree: ${msg}`, ...args); +} + +const toString = Object.prototype.toString; + +export function is(val, type) { + return toString.call(val) === `[object ${type}]`; +} + +/** + * 是否对象(Object) + * @param val + + */ +export function isObject(val) { + return val !== null && is(val, "Object"); +} + +/** + * 是否数字(Number) + * @param val + + */ +export function isNumber(val) { + return is(val, "Number"); +} + +/** + * 是否字符串(String) + * @param val + + */ +export function isString(val) { + return is(val, "String"); +} + +/** + * 是否函数方法(Function) + * @param val + + */ +export function isFunction(val) { + return typeof val === "function"; +} + +/** + * 是否布尔(Boolean) + * @param val + + */ +export function isBoolean(val) { + return is(val, "Boolean"); +} + +/** + * 是否数组(Array) + * @param val + + */ +export function isArray(val) { + return val && Array.isArray(val); +} diff --git a/src/pages.json b/src/pages.json index 37a4746..e7afde2 100644 --- a/src/pages.json +++ b/src/pages.json @@ -67,6 +67,18 @@ "style": { "navigationBarTitleText": "通知详情" } + }, + { + "path": "pages/work/role/index", + "style": { + "navigationBarTitleText": "角色管理" + } + }, + { + "path": "pages/work/role/assign-perm", + "style": { + "navigationBarTitleText": "角色分配权限" + } } ], "globalStyle": { diff --git a/src/pages/mine/profile/index.vue b/src/pages/mine/profile/index.vue index a44bdf4..976edac 100644 --- a/src/pages/mine/profile/index.vue +++ b/src/pages/mine/profile/index.vue @@ -66,7 +66,7 @@ - + - + @@ -103,7 +103,7 @@ diff --git a/src/pages/work/index.vue b/src/pages/work/index.vue index cd6dd54..62c6da3 100644 --- a/src/pages/work/index.vue +++ b/src/pages/work/index.vue @@ -36,6 +36,7 @@ const gridList = reactive([ { icon: "/static/icons/role.png", title: "角色管理", + url: "/pages/work/role/index", prem: "sys:role:query", }, { diff --git a/src/pages/work/role/assign-perm.vue b/src/pages/work/role/assign-perm.vue new file mode 100644 index 0000000..0cb2843 --- /dev/null +++ b/src/pages/work/role/assign-perm.vue @@ -0,0 +1,113 @@ + + + + diff --git a/src/pages/work/role/index.vue b/src/pages/work/role/index.vue new file mode 100644 index 0000000..b7823e9 --- /dev/null +++ b/src/pages/work/role/index.vue @@ -0,0 +1,319 @@ + + + +