From b8cb28589d2dc3761affd4c9241401f38942d6a6 Mon Sep 17 00:00:00 2001 From: JiaoTianBo Date: Sat, 28 Mar 2026 10:39:02 +0800 Subject: [PATCH] =?UTF-8?q?refactor(auth):=20=E8=B0=83=E6=95=B4=E9=A3=9E?= =?UTF-8?q?=E4=B9=A6OAuth=E5=9B=9E=E8=B0=83=E5=8F=8A=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E8=8F=9C=E5=8D=95=E4=B8=8E=E9=83=A8=E9=97=A8?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 从系统路由配置中删除了菜单和部门权限管理路由配置 - 飞书OAuth使用hash路由模式,调整redirect_uri以包含“#” - 优化飞书回调code处理,支持code在hash之前和hash内部两种情况 - 清理飞书登录页面中URL,避免重复处理code参数 - 删除系统部门管理视图及相关逻辑代码 - 删除系统菜单管理视图及相关逻辑代码 - 移除系统菜单和部门相关的表单、hooks、工具类型与验证规则等代码 --- src/router/modules/system.ts | 20 -- src/views/login/index.vue | 24 +- src/views/system/dept/form.vue | 139 --------- src/views/system/dept/index.vue | 172 ----------- src/views/system/dept/utils/hook.tsx | 181 ------------ src/views/system/dept/utils/rule.ts | 37 --- src/views/system/dept/utils/types.ts | 16 -- src/views/system/menu/README.md | 26 -- src/views/system/menu/form.vue | 342 ---------------------- src/views/system/menu/index.vue | 163 ----------- src/views/system/menu/utils/enums.ts | 108 ------- src/views/system/menu/utils/hook.tsx | 228 --------------- src/views/system/menu/utils/rule.ts | 10 - src/views/system/menu/utils/types.ts | 30 -- src/views/system/user/index.vue | 380 ++++++++++++------------- src/views/system/user/svg/expand.svg | 1 - src/views/system/user/svg/unexpand.svg | 1 - src/views/system/user/tree.vue | 211 -------------- src/views/system/user/utils/hook.tsx | 52 +--- 19 files changed, 203 insertions(+), 1938 deletions(-) delete mode 100644 src/views/system/dept/form.vue delete mode 100644 src/views/system/dept/index.vue delete mode 100644 src/views/system/dept/utils/hook.tsx delete mode 100644 src/views/system/dept/utils/rule.ts delete mode 100644 src/views/system/dept/utils/types.ts delete mode 100644 src/views/system/menu/README.md delete mode 100644 src/views/system/menu/form.vue delete mode 100644 src/views/system/menu/index.vue delete mode 100644 src/views/system/menu/utils/enums.ts delete mode 100644 src/views/system/menu/utils/hook.tsx delete mode 100644 src/views/system/menu/utils/rule.ts delete mode 100644 src/views/system/menu/utils/types.ts delete mode 100644 src/views/system/user/svg/expand.svg delete mode 100644 src/views/system/user/svg/unexpand.svg delete mode 100644 src/views/system/user/tree.vue diff --git a/src/router/modules/system.ts b/src/router/modules/system.ts index 9fcd66b..1bc8c07 100644 --- a/src/router/modules/system.ts +++ b/src/router/modules/system.ts @@ -39,26 +39,6 @@ export default { title: "权限管理", roles: ["admin"] } - }, - { - path: "/system/menu", - name: "SystemMenu", - component: () => import("@/views/system/menu/index.vue"), - meta: { - icon: "ep:menu", - title: $t("menus.pureSystemMenu"), - roles: ["admin"] - } - }, - { - path: "/system/dept", - name: "SystemDept", - component: () => import("@/views/system/dept/index.vue"), - meta: { - icon: "ri:git-branch-line", - title: $t("menus.pureDept"), - roles: ["admin"] - } } ] } satisfies RouteConfigsTable; diff --git a/src/views/login/index.vue b/src/views/login/index.vue index 891d962..f1c8a83 100644 --- a/src/views/login/index.vue +++ b/src/views/login/index.vue @@ -43,8 +43,9 @@ defineOptions({ // 飞书OAuth配置 const FEISHU_APP_ID = "cli_a94c8a7930badcd5"; +// 使用hash路由模式,redirect_uri需要包含# const FEISHU_REDIRECT_URI = encodeURIComponent( - window.location.origin + "/login" + window.location.origin + "/#/login" ); const imgCode = ref(""); @@ -207,14 +208,27 @@ const switchToFeishuLogin = () => { // 页面加载时检查是否有飞书回调code onMounted(() => { - // 从 URL 中解析 code 参数(处理 hash 路由模式下 query 参数在 hash 之前的情况) + // hash路由模式下,飞书回调URL格式为: http://localhost:8848/?code=xxx#/login + // 或者在hash内部: http://localhost:8848/#/login?code=xxx + // 需要同时检查两种情况 + let code: string | null = null; + + // 方式1: code在hash之前 (飞书回调的标准方式) const urlParams = new URLSearchParams(window.location.search); - const code = urlParams.get("code"); + code = urlParams.get("code"); + + // 方式2: 如果没有找到,尝试从hash内部获取 + if (!code) { + const hash = window.location.hash; + const hashParams = new URLSearchParams(hash.split("?")[1] || ""); + code = hashParams.get("code"); + } + if (code) { handleFeishuCallback(code); // 清除 URL 中的 code 参数,避免重复处理 - const newUrl = window.location.pathname + window.location.hash; - window.history.replaceState({}, document.title, newUrl); + const cleanUrl = window.location.origin + "/#/login"; + window.history.replaceState({}, document.title, cleanUrl); } }); diff --git a/src/views/system/dept/form.vue b/src/views/system/dept/form.vue deleted file mode 100644 index acc333a..0000000 --- a/src/views/system/dept/form.vue +++ /dev/null @@ -1,139 +0,0 @@ - - - diff --git a/src/views/system/dept/index.vue b/src/views/system/dept/index.vue deleted file mode 100644 index b4e8f90..0000000 --- a/src/views/system/dept/index.vue +++ /dev/null @@ -1,172 +0,0 @@ - - - - - diff --git a/src/views/system/dept/utils/hook.tsx b/src/views/system/dept/utils/hook.tsx deleted file mode 100644 index f015232..0000000 --- a/src/views/system/dept/utils/hook.tsx +++ /dev/null @@ -1,181 +0,0 @@ -import dayjs from "dayjs"; -import editForm from "../form.vue"; -import { handleTree } from "@/utils/tree"; -import { message } from "@/utils/message"; -import { getDeptList } from "@/api/system"; -import { usePublicHooks } from "../../hooks"; -import { addDialog } from "@/components/ReDialog"; -import { reactive, ref, onMounted, h } from "vue"; -import type { FormItemProps } from "../utils/types"; -import { cloneDeep, isAllEmpty, deviceDetection } from "@pureadmin/utils"; - -export function useDept() { - const form = reactive({ - name: "", - status: null - }); - - const formRef = ref(); - const dataList = ref([]); - const loading = ref(true); - const { tagStyle } = usePublicHooks(); - - const columns: TableColumnList = [ - { - label: "部门名称", - prop: "name", - width: 180, - align: "left" - }, - { - label: "排序", - prop: "sort", - minWidth: 70 - }, - { - label: "状态", - prop: "status", - minWidth: 100, - cellRenderer: ({ row, props }) => ( - - {row.status === 1 ? "启用" : "停用"} - - ) - }, - { - label: "创建时间", - minWidth: 200, - prop: "createTime", - formatter: ({ createTime }) => - dayjs(createTime).format("YYYY-MM-DD HH:mm:ss") - }, - { - label: "备注", - prop: "remark", - minWidth: 320 - }, - { - label: "操作", - fixed: "right", - width: 210, - slot: "operation" - } - ]; - - function handleSelectionChange(val) { - console.log("handleSelectionChange", val); - } - - function resetForm(formEl) { - if (!formEl) return; - formEl.resetFields(); - onSearch(); - } - - async function onSearch() { - loading.value = true; - const { code, data } = await getDeptList(); // 这里是返回一维数组结构,前端自行处理成树结构,返回格式要求:唯一id加父节点parentId,parentId取父节点id - if (code === 200) { - let newData = data; - if (!isAllEmpty(form.name)) { - // 前端搜索部门名称 - newData = newData.filter(item => item.name.includes(form.name)); - } - if (!isAllEmpty(form.status)) { - // 前端搜索状态 - newData = newData.filter(item => item.status === form.status); - } - dataList.value = handleTree(newData); // 处理成树结构 - } - - setTimeout(() => { - loading.value = false; - }, 500); - } - - function formatHigherDeptOptions(treeList) { - // 根据返回数据的status字段值判断追加是否禁用disabled字段,返回处理后的树结构,用于上级部门级联选择器的展示(实际开发中也是如此,不可能前端需要的每个字段后端都会返回,这时需要前端自行根据后端返回的某些字段做逻辑处理) - if (!treeList || !treeList.length) return; - const newTreeList = []; - for (let i = 0; i < treeList.length; i++) { - treeList[i].disabled = treeList[i].status === 0 ? true : false; - formatHigherDeptOptions(treeList[i].children); - newTreeList.push(treeList[i]); - } - return newTreeList; - } - - function openDialog(title = "新增", row?: FormItemProps) { - addDialog({ - title: `${title}部门`, - props: { - formInline: { - higherDeptOptions: formatHigherDeptOptions(cloneDeep(dataList.value)), - parentId: row?.parentId ?? 0, - name: row?.name ?? "", - principal: row?.principal ?? "", - phone: row?.phone ?? "", - email: row?.email ?? "", - sort: row?.sort ?? 0, - status: row?.status ?? 1, - remark: row?.remark ?? "" - } - }, - width: "40%", - draggable: true, - fullscreen: deviceDetection(), - fullscreenIcon: true, - closeOnClickModal: false, - contentRenderer: () => h(editForm, { ref: formRef, formInline: null }), - beforeSure: (done, { options }) => { - const FormRef = formRef.value.getRef(); - const curData = options.props.formInline as FormItemProps; - function chores() { - message(`您${title}了部门名称为${curData.name}的这条数据`, { - type: "success" - }); - done(); // 关闭弹框 - onSearch(); // 刷新表格数据 - } - FormRef.validate(valid => { - if (valid) { - console.log("curData", curData); - // 表单规则校验通过 - if (title === "新增") { - // 实际开发先调用新增接口,再进行下面操作 - chores(); - } else { - // 实际开发先调用修改接口,再进行下面操作 - chores(); - } - } - }); - } - }); - } - - function handleDelete(row) { - message(`您删除了部门名称为${row.name}的这条数据`, { type: "success" }); - onSearch(); - } - - onMounted(() => { - onSearch(); - }); - - return { - form, - loading, - columns, - dataList, - /** 搜索 */ - onSearch, - /** 重置 */ - resetForm, - /** 新增、修改部门 */ - openDialog, - /** 删除部门 */ - handleDelete, - handleSelectionChange - }; -} diff --git a/src/views/system/dept/utils/rule.ts b/src/views/system/dept/utils/rule.ts deleted file mode 100644 index b20bf67..0000000 --- a/src/views/system/dept/utils/rule.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { reactive } from "vue"; -import type { FormRules } from "element-plus"; -import { isPhone, isEmail } from "@pureadmin/utils"; - -/** 自定义表单规则校验 */ -export const formRules = reactive({ - name: [{ required: true, message: "部门名称为必填项", trigger: "blur" }], - phone: [ - { - validator: (rule, value, callback) => { - if (value === "") { - callback(); - } else if (!isPhone(value)) { - callback(new Error("请输入正确的手机号码格式")); - } else { - callback(); - } - }, - trigger: "blur" - // trigger: "click" // 如果想在点击确定按钮时触发这个校验,trigger 设置成 click 即可 - } - ], - email: [ - { - validator: (rule, value, callback) => { - if (value === "") { - callback(); - } else if (!isEmail(value)) { - callback(new Error("请输入正确的邮箱格式")); - } else { - callback(); - } - }, - trigger: "blur" - } - ] -}); diff --git a/src/views/system/dept/utils/types.ts b/src/views/system/dept/utils/types.ts deleted file mode 100644 index 7547d6b..0000000 --- a/src/views/system/dept/utils/types.ts +++ /dev/null @@ -1,16 +0,0 @@ -interface FormItemProps { - higherDeptOptions: Record[]; - parentId: number; - name: string; - principal: string; - phone: string | number; - email: string; - sort: number; - status: number; - remark: string; -} -interface FormProps { - formInline: FormItemProps; -} - -export type { FormItemProps, FormProps }; diff --git a/src/views/system/menu/README.md b/src/views/system/menu/README.md deleted file mode 100644 index a6e8459..0000000 --- a/src/views/system/menu/README.md +++ /dev/null @@ -1,26 +0,0 @@ -## 字段含义 - -| 字段 | 说明 | -| :---------------- | :----------------------------------------------------------- | -| `menuType` | 菜单类型(`0`代表菜单、`1`代表`iframe`、`2`代表外链、`3`代表按钮) | -| `parentId` | | -| `title` | 菜单名称(兼容国际化、非国际化,如果用国际化的写法就必须在根目录的`locales`文件夹下对应添加) | -| `name` | 路由名称(必须唯一并且和当前路由`component`字段对应的页面里用`defineOptions`包起来的`name`保持一致) | -| `path` | 路由路径 | -| `component` | 组件路径(传`component`组件路径,那么`path`可以随便写,如果不传,`component`组件路径会跟`path`保持一致) | -| `rank` | 菜单排序(平台规定只有`home`路由的`rank`才能为`0`,所以后端在返回`rank`的时候需要从非`0`开始 [点击查看更多](https://pure-admin.cn/pages/routerMenu/#%E8%8F%9C%E5%8D%95%E6%8E%92%E5%BA%8F-rank)) | -| `redirect` | 路由重定向 | -| `icon` | 菜单图标 | -| `extraIcon` | 右侧图标 | -| `enterTransition` | 进场动画(页面加载动画) | -| `leaveTransition` | 离场动画(页面加载动画) | -| `activePath` | 菜单激活(将某个菜单激活,主要用于通过`query`或`params`传参的路由,当它们通过配置`showLink: false`后不在菜单中显示,就不会有任何菜单高亮,而通过设置`activePath`指定激活菜单即可获得高亮,`activePath`为指定激活菜单的`path`) | -| `auths` | 权限标识(按钮级别权限设置) | -| `frameSrc` | 链接地址(需要内嵌的`iframe`链接地址) | -| `frameLoading` | 加载动画(内嵌的`iframe`页面是否开启首次加载动画) | -| `keepAlive` | 缓存页面(是否缓存该路由页面,开启后会保存该页面的整体状态,刷新后会清空状态) | -| `hiddenTag` | 标签页(当前菜单名称或自定义信息禁止添加到标签页) | -| `fixedTag` | 固定标签页(当前菜单名称是否固定显示在标签页且不可关闭) | -| `showLink` | 菜单(是否显示该菜单) | -| `showParent` | 父级菜单(是否显示父级菜单 [点击查看更多](https://pure-admin.cn/pages/routerMenu/#%E7%AC%AC%E4%B8%80%E7%A7%8D-%E8%AF%A5%E6%A8%A1%E5%BC%8F%E9%92%88%E5%AF%B9%E7%88%B6%E7%BA%A7%E8%8F%9C%E5%8D%95%E4%B8%8B%E5%8F%AA%E6%9C%89%E4%B8%80%E4%B8%AA%E5%AD%90%E8%8F%9C%E5%8D%95%E7%9A%84%E6%83%85%E5%86%B5-%E5%9C%A8%E5%AD%90%E8%8F%9C%E5%8D%95%E7%9A%84-meta-%E5%B1%9E%E6%80%A7%E4%B8%AD%E5%8A%A0%E4%B8%8A-showparent-true-%E5%8D%B3%E5%8F%AF)) | - diff --git a/src/views/system/menu/form.vue b/src/views/system/menu/form.vue deleted file mode 100644 index 76e8159..0000000 --- a/src/views/system/menu/form.vue +++ /dev/null @@ -1,342 +0,0 @@ - - - diff --git a/src/views/system/menu/index.vue b/src/views/system/menu/index.vue deleted file mode 100644 index 43ad780..0000000 --- a/src/views/system/menu/index.vue +++ /dev/null @@ -1,163 +0,0 @@ - - - - - diff --git a/src/views/system/menu/utils/enums.ts b/src/views/system/menu/utils/enums.ts deleted file mode 100644 index 4466b61..0000000 --- a/src/views/system/menu/utils/enums.ts +++ /dev/null @@ -1,108 +0,0 @@ -import type { OptionsType } from "@/components/ReSegmented"; - -const menuTypeOptions: Array = [ - { - label: "菜单", - value: 0 - }, - { - label: "iframe", - value: 1 - }, - { - label: "外链", - value: 2 - }, - { - label: "按钮", - value: 3 - } -]; - -const showLinkOptions: Array = [ - { - label: "显示", - tip: "会在菜单中显示", - value: true - }, - { - label: "隐藏", - tip: "不会在菜单中显示", - value: false - } -]; - -const fixedTagOptions: Array = [ - { - label: "固定", - tip: "当前菜单名称固定显示在标签页且不可关闭", - value: true - }, - { - label: "不固定", - tip: "当前菜单名称不固定显示在标签页且可关闭", - value: false - } -]; - -const keepAliveOptions: Array = [ - { - label: "缓存", - tip: "会保存该页面的整体状态,刷新后会清空状态", - value: true - }, - { - label: "不缓存", - tip: "不会保存该页面的整体状态", - value: false - } -]; - -const hiddenTagOptions: Array = [ - { - label: "允许", - tip: "当前菜单名称或自定义信息允许添加到标签页", - value: false - }, - { - label: "禁止", - tip: "当前菜单名称或自定义信息禁止添加到标签页", - value: true - } -]; - -const showParentOptions: Array = [ - { - label: "显示", - tip: "会显示父级菜单", - value: true - }, - { - label: "隐藏", - tip: "不会显示父级菜单", - value: false - } -]; - -const frameLoadingOptions: Array = [ - { - label: "开启", - tip: "有首次加载动画", - value: true - }, - { - label: "关闭", - tip: "无首次加载动画", - value: false - } -]; - -export { - menuTypeOptions, - showLinkOptions, - fixedTagOptions, - keepAliveOptions, - hiddenTagOptions, - showParentOptions, - frameLoadingOptions -}; diff --git a/src/views/system/menu/utils/hook.tsx b/src/views/system/menu/utils/hook.tsx deleted file mode 100644 index 3ca1872..0000000 --- a/src/views/system/menu/utils/hook.tsx +++ /dev/null @@ -1,228 +0,0 @@ -import editForm from "../form.vue"; -import { handleTree } from "@/utils/tree"; -import { message } from "@/utils/message"; -import { getMenuList } from "@/api/system"; -import { transformI18n } from "@/plugins/i18n"; -import { addDialog } from "@/components/ReDialog"; -import { reactive, ref, onMounted, h } from "vue"; -import type { FormItemProps } from "../utils/types"; -import { useRenderIcon } from "@/components/ReIcon/src/hooks"; -import { cloneDeep, isAllEmpty, deviceDetection } from "@pureadmin/utils"; - -export function useMenu() { - const form = reactive({ - title: "" - }); - - const formRef = ref(); - const dataList = ref([]); - const loading = ref(true); - - const getMenuType = (type, text = false) => { - switch (type) { - case 0: - return text ? "菜单" : "primary"; - case 1: - return text ? "iframe" : "warning"; - case 2: - return text ? "外链" : "danger"; - case 3: - return text ? "按钮" : "info"; - } - }; - - const columns: TableColumnList = [ - { - label: "菜单名称", - prop: "title", - align: "left", - cellRenderer: ({ row }) => ( - <> - - {h(useRenderIcon(row.icon), { - style: { paddingTop: "1px" } - })} - - {transformI18n(row.title)} - - ) - }, - { - label: "菜单类型", - prop: "menuType", - width: 100, - cellRenderer: ({ row, props }) => ( - - {getMenuType(row.menuType, true)} - - ) - }, - { - label: "路由路径", - prop: "path" - }, - { - label: "组件路径", - prop: "component", - formatter: ({ path, component }) => - isAllEmpty(component) ? path : component - }, - { - label: "权限标识", - prop: "auths" - }, - { - label: "排序", - prop: "rank", - width: 100 - }, - { - label: "隐藏", - prop: "showLink", - formatter: ({ showLink }) => (showLink ? "否" : "是"), - width: 100 - }, - { - label: "操作", - fixed: "right", - width: 210, - slot: "operation" - } - ]; - - function handleSelectionChange(val) { - console.log("handleSelectionChange", val); - } - - function resetForm(formEl) { - if (!formEl) return; - formEl.resetFields(); - onSearch(); - } - - async function onSearch() { - loading.value = true; - const { code, data } = await getMenuList(); // 这里是返回一维数组结构,前端自行处理成树结构,返回格式要求:唯一id加父节点parentId,parentId取父节点id - if (code === 200) { - let newData = data; - if (!isAllEmpty(form.title)) { - // 前端搜索菜单名称 - newData = newData.filter(item => - transformI18n(item.title).includes(form.title) - ); - } - dataList.value = handleTree(newData); // 处理成树结构 - } - - setTimeout(() => { - loading.value = false; - }, 500); - } - - function formatHigherMenuOptions(treeList) { - if (!treeList || !treeList.length) return; - const newTreeList = []; - for (let i = 0; i < treeList.length; i++) { - treeList[i].title = transformI18n(treeList[i].title); - formatHigherMenuOptions(treeList[i].children); - newTreeList.push(treeList[i]); - } - return newTreeList; - } - - function openDialog(title = "新增", row?: FormItemProps) { - addDialog({ - title: `${title}菜单`, - props: { - formInline: { - menuType: row?.menuType ?? 0, - higherMenuOptions: formatHigherMenuOptions(cloneDeep(dataList.value)), - parentId: row?.parentId ?? 0, - title: row?.title ?? "", - name: row?.name ?? "", - path: row?.path ?? "", - component: row?.component ?? "", - rank: row?.rank ?? 99, - redirect: row?.redirect ?? "", - icon: row?.icon ?? "", - extraIcon: row?.extraIcon ?? "", - enterTransition: row?.enterTransition ?? "", - leaveTransition: row?.leaveTransition ?? "", - activePath: row?.activePath ?? "", - auths: row?.auths ?? "", - frameSrc: row?.frameSrc ?? "", - frameLoading: row?.frameLoading ?? true, - keepAlive: row?.keepAlive ?? false, - hiddenTag: row?.hiddenTag ?? false, - fixedTag: row?.fixedTag ?? false, - showLink: row?.showLink ?? true, - showParent: row?.showParent ?? false - } - }, - width: "45%", - draggable: true, - fullscreen: deviceDetection(), - fullscreenIcon: true, - closeOnClickModal: false, - contentRenderer: () => h(editForm, { ref: formRef, formInline: null }), - beforeSure: (done, { options }) => { - const FormRef = formRef.value.getRef(); - const curData = options.props.formInline as FormItemProps; - function chores() { - message( - `您${title}了菜单名称为${transformI18n(curData.title)}的这条数据`, - { - type: "success" - } - ); - done(); // 关闭弹框 - onSearch(); // 刷新表格数据 - } - FormRef.validate(valid => { - if (valid) { - console.log("curData", curData); - // 表单规则校验通过 - if (title === "新增") { - // 实际开发先调用新增接口,再进行下面操作 - chores(); - } else { - // 实际开发先调用修改接口,再进行下面操作 - chores(); - } - } - }); - } - }); - } - - function handleDelete(row) { - message(`您删除了菜单名称为${transformI18n(row.title)}的这条数据`, { - type: "success" - }); - onSearch(); - } - - onMounted(() => { - onSearch(); - }); - - return { - form, - loading, - columns, - dataList, - /** 搜索 */ - onSearch, - /** 重置 */ - resetForm, - /** 新增、修改菜单 */ - openDialog, - /** 删除菜单 */ - handleDelete, - handleSelectionChange - }; -} diff --git a/src/views/system/menu/utils/rule.ts b/src/views/system/menu/utils/rule.ts deleted file mode 100644 index 90b3548..0000000 --- a/src/views/system/menu/utils/rule.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { reactive } from "vue"; -import type { FormRules } from "element-plus"; - -/** 自定义表单规则校验 */ -export const formRules = reactive({ - title: [{ required: true, message: "菜单名称为必填项", trigger: "blur" }], - name: [{ required: true, message: "路由名称为必填项", trigger: "blur" }], - path: [{ required: true, message: "路由路径为必填项", trigger: "blur" }], - auths: [{ required: true, message: "权限标识为必填项", trigger: "blur" }] -}); diff --git a/src/views/system/menu/utils/types.ts b/src/views/system/menu/utils/types.ts deleted file mode 100644 index f07d1f7..0000000 --- a/src/views/system/menu/utils/types.ts +++ /dev/null @@ -1,30 +0,0 @@ -interface FormItemProps { - /** 菜单类型(0代表菜单、1代表iframe、2代表外链、3代表按钮)*/ - menuType: number; - higherMenuOptions: Record[]; - parentId: number; - title: string; - name: string; - path: string; - component: string; - rank: number; - redirect: string; - icon: string; - extraIcon: string; - enterTransition: string; - leaveTransition: string; - activePath: string; - auths: string; - frameSrc: string; - frameLoading: boolean; - keepAlive: boolean; - hiddenTag: boolean; - fixedTag: boolean; - showLink: boolean; - showParent: boolean; -} -interface FormProps { - formInline: FormItemProps; -} - -export type { FormItemProps, FormProps }; diff --git a/src/views/system/user/index.vue b/src/views/system/user/index.vue index 87437cd..46a43f6 100644 --- a/src/views/system/user/index.vue +++ b/src/views/system/user/index.vue @@ -1,6 +1,5 @@ diff --git a/src/views/system/user/svg/expand.svg b/src/views/system/user/svg/expand.svg deleted file mode 100644 index bb41c35..0000000 --- a/src/views/system/user/svg/expand.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/views/system/user/svg/unexpand.svg b/src/views/system/user/svg/unexpand.svg deleted file mode 100644 index 04b3e9d..0000000 --- a/src/views/system/user/svg/unexpand.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/views/system/user/tree.vue b/src/views/system/user/tree.vue deleted file mode 100644 index 4998cd2..0000000 --- a/src/views/system/user/tree.vue +++ /dev/null @@ -1,211 +0,0 @@ - - - - - diff --git a/src/views/system/user/utils/hook.tsx b/src/views/system/user/utils/hook.tsx index 2deff43..8ac1ada 100644 --- a/src/views/system/user/utils/hook.tsx +++ b/src/views/system/user/utils/hook.tsx @@ -3,7 +3,6 @@ import dayjs from "dayjs"; import roleForm from "../form/role.vue"; import editForm from "../form/index.vue"; import { zxcvbn } from "@zxcvbn-ts/core"; -import { handleTree } from "@/utils/tree"; import { message } from "@/utils/message"; import userAvatar from "@/assets/user.jpg"; import { usePublicHooks } from "../../hooks"; @@ -17,12 +16,7 @@ import { hideTextAtIndex, deviceDetection } from "@pureadmin/utils"; -import { - getRoleIds, - getDeptList, - getUserList, - getAllRoleList -} from "@/api/system"; +import { getUserRoleIds, getUserList, getAllRoleList } from "@/api/system"; import { ElForm, ElInput, @@ -32,10 +26,8 @@ import { } from "element-plus"; import { type Ref, h, ref, watch, computed, reactive, onMounted } from "vue"; -export function useUser(tableRef: Ref, treeRef: Ref) { +export function useUser(tableRef: Ref) { const form = reactive({ - // 左侧部门树的id - deptId: "", username: "", phone: "", status: "" @@ -48,9 +40,6 @@ export function useUser(tableRef: Ref, treeRef: Ref) { const avatarInfo = ref(); const switchLoadMap = ref({}); const { switchStyle } = usePublicHooks(); - const higherDeptOptions = ref(); - const treeData = ref([]); - const treeLoading = ref(true); const selectedNum = ref(0); const pagination = reactive({ total: 0, @@ -279,36 +268,15 @@ export function useUser(tableRef: Ref, treeRef: Ref) { const resetForm = formEl => { if (!formEl) return; formEl.resetFields(); - form.deptId = ""; - treeRef.value.onTreeReset(); onSearch(); }; - function onTreeSelect({ id, selected }) { - form.deptId = selected ? id : ""; - onSearch(); - } - - function formatHigherDeptOptions(treeList) { - // 根据返回数据的status字段值判断追加是否禁用disabled字段,返回处理后的树结构,用于上级部门级联选择器的展示(实际开发中也是如此,不可能前端需要的每个字段后端都会返回,这时需要前端自行根据后端返回的某些字段做逻辑处理) - if (!treeList || !treeList.length) return; - const newTreeList = []; - for (let i = 0; i < treeList.length; i++) { - treeList[i].disabled = treeList[i].status === 0 ? true : false; - formatHigherDeptOptions(treeList[i].children); - newTreeList.push(treeList[i]); - } - return newTreeList; - } - function openDialog(title = "新增", row?: FormItemProps) { addDialog({ title: `${title}用户`, props: { formInline: { title, - higherDeptOptions: formatHigherDeptOptions(higherDeptOptions.value), - parentId: row?.dept.id ?? 0, nickname: row?.nickname ?? "", username: row?.username ?? "", password: row?.password ?? "", @@ -459,7 +427,7 @@ export function useUser(tableRef: Ref, treeRef: Ref) { /** 分配角色 */ async function handleRole(row) { // 选中的角色列表 - const ids = (await getRoleIds({ userId: row.id })).data ?? []; + const ids = (await getUserRoleIds(row.id)).data ?? []; addDialog({ title: `分配 ${row.username} 用户的角色`, props: { @@ -486,18 +454,7 @@ export function useUser(tableRef: Ref, treeRef: Ref) { } onMounted(async () => { - treeLoading.value = true; onSearch(); - - // 归属部门 - const { code, data } = await getDeptList(); - if (code === 200) { - higherDeptOptions.value = handleTree(data); - treeData.value = handleTree(data); - } - - treeLoading.value = false; - // 角色列表 roleOptions.value = (await getAllRoleList()).data ?? []; }); @@ -507,8 +464,6 @@ export function useUser(tableRef: Ref, treeRef: Ref) { loading, columns, dataList, - treeData, - treeLoading, selectedNum, pagination, buttonClass, @@ -517,7 +472,6 @@ export function useUser(tableRef: Ref, treeRef: Ref) { resetForm, onbatchDel, openDialog, - onTreeSelect, handleUpdate, handleDelete, handleUpload,