diff --git a/EDITOR_UPLOAD_FIX.md b/EDITOR_UPLOAD_FIX.md deleted file mode 100644 index 92313ec..0000000 --- a/EDITOR_UPLOAD_FIX.md +++ /dev/null @@ -1,172 +0,0 @@ -# 编辑器图片上传问题修复 - -## 问题描述 -编辑器里上传的图片无法显示。 - -## 根本原因 -文件保存路径和静态文件URL映射不匹配。 - -## 已完成的修改 - -### 1. 后端文件保存路径 (`server/controllers/file.go`) - -**修改前:** -```go -uploadDir := path.Join("uploads", datePath) -``` -文件保存到:`server/uploads/` - -**修改后:** -```go -uploadDir := path.Join("..", "uploads", datePath) -``` -文件保存到:`项目根目录/uploads/` - -### 2. 静态文件映射 (`server/conf/app.conf`) - -**修改前:** -```conf -StaticDir = /uploads:uploads -``` - -**修改后:** -```conf -StaticDir = /uploads:../uploads -``` - -现在 `/uploads` URL 正确映射到项目根目录的 `uploads` 文件夹。 - -### 3. 前端URL拼接 (`front/src/components/WangEditor.vue`) - -添加了更健壮的URL拼接逻辑: - -```typescript -const fileUrl = response.data.data.file_url; // /uploads/2024/01/15/xxx.jpg -const baseUrl = getUploadUrl() ; - -let fullUrl = fileUrl; -if (!fileUrl.startsWith('http')) { - const base = baseUrl.replace(/\/$/, ''); - const url = fileUrl.startsWith('/') ? fileUrl : '/' + fileUrl; - fullUrl = `${base}${url}`; -} -``` - -这样可以确保URL正确拼接为:`http://localhost:8080/uploads/2024/01/15/xxx.jpg` - -## 目录结构 - -上传后文件将保存在: - -``` -yunzer_go/ -├── server/ -├── front/ -└── uploads/ ← 文件保存位置 - ├── 2024/ - │ └── 01/ - │ └── 15/ - │ └── 20240115143045_example.jpg -``` - -## 访问URL - -上传后可以通过以下URL访问: - -``` -http://localhost:8080/uploads/2024/01/15/20240115143045_example.jpg -``` - -## 如何验证 - -### 1. 上传一个图片 -在编辑器中使用图片上传功能上传一张图片。 - -### 2. 查看控制台日志 -打开浏览器开发者工具(F12),查看 Console 标签,应该看到: -``` -图片上传成功,URL: http://localhost:8080/uploads/2024/01/15/xxx.jpg -``` - -### 3. 检查文件是否保存 -查看项目根目录的 `uploads` 文件夹: -```bash -ls uploads/2024/01/15/ -``` - -### 4. 测试URL访问 -在浏览器中直接访问图片URL,应该能看到图片。 - -### 5. 检查数据库 -查看 `yz_files` 表中的记录: -```sql -SELECT file_path, file_url FROM yz_files ORDER BY upload_time DESC LIMIT 1; -``` - -应该看到: -- `file_path`: `uploads/2024/01/15/xxx.jpg` -- `file_url`: `/uploads/2024/01/15/xxx.jpg` - -## 重启服务器 - -修改配置后需要重启服务器才能生效: - -```bash -cd server -go run main.go -``` - -或者如果使用编译后的可执行文件: - -```bash -./server.exe -``` - -## 如果还是看不到图片 - -### 检查清单 - -1. ✅ 服务器是否重启 -2. ✅ 文件是否保存到 `uploads` 目录 -3. ✅ 浏览器控制台是否有错误 -4. ✅ URL是否正确拼接 -5. ✅ 静态文件映射是否正确 - -### 常见问题 - -**Q: 上传后文件保存在哪里?** -A: 项目根目录的 `uploads` 文件夹 - -**Q: 图片URL是什么格式?** -A: `http://localhost:8080/uploads/2024/01/15/filename.jpg` - -**Q: 为什么看不到图片?** -A: 检查: -- 文件是否正确保存 -- URL是否可访问 -- 浏览器控制台错误信息 -- 服务器是否重启 - -**Q: 如何自定义上传目录?** -A: 修改 `server/controllers/file.go` 和 `server/conf/app.conf` 中的路径配置 - -## 调试建议 - -如果图片仍不显示,检查以下内容: - -1. **查看浏览器网络请求** - - F12 → Network 标签 - - 查看图片请求是否返回 200 - - 如果返回 404,说明路径不对 - -2. **查看浏览器控制台** - - 查看是否有 CORS 错误 - - 查看上传成功后的 URL 是什么 - -3. **查看服务器日志** - - 确认文件是否正确上传 - - 确认路径是否正确 - -4. **检查文件权限** - - 确保应用有创建目录和写入文件的权限 - diff --git a/KNOWLEDGE_SETUP.md b/KNOWLEDGE_SETUP.md deleted file mode 100644 index 6d118e8..0000000 --- a/KNOWLEDGE_SETUP.md +++ /dev/null @@ -1,94 +0,0 @@ -# 知识库功能快速设置指南 - -## 问题原因 - -500 错误通常是因为数据库表没有创建导致的。 - -## 解决步骤 - -### 1. 创建数据库表 - -打开 MySQL 客户端,连接到您的数据库,执行: - -```bash -# 方法1:命令行执行 -mysql -u root -p your_database < server/database/create_knowledge_tables.sql - -# 方法2:在 MySQL 客户端中 -source server/database/create_knowledge_tables.sql; -``` - -### 2. 验证表创建成功 - -```sql -SHOW TABLES LIKE 'yz_knowledge%'; -``` - -应该看到以下表: -- yz_knowledge -- yz_knowledge_category -- yz_knowledge_tags - -### 3. 重启后端服务 - -```bash -cd server -go run main.go -``` - -### 4. 测试 API - -浏览器访问:http://localhost:8080/api/knowledge/list - -应该返回: -```json -{ - "code": 0, - "message": "success", - "data": { - "list": [], - "total": 0, - "page": 1, - "pageSize": 10 - } -} -``` - -## 已完成的修改 - -### 后端(Go) -- ✅ 创建 `server/models/knowledge.go` - 知识库模型 -- ✅ 创建 `server/controllers/knowledge.go` - 知识库控制器 -- ✅ 创建 `server/database/yz_knowledge.sql` - 数据库表结构 -- ✅ 更新 `server/routers/router.go` - 添加路由 -- ✅ 更新 `server/models/user.go` - 注册模型 -- ✅ 修复模型字段映射问题 - -### 前端(TypeScript) -- ✅ 更新 `front/src/api/knowledge.ts` - API 调用 -- ✅ 更新 `front/src/views/apps/knowledge/index.vue` - 列表页面 -- ✅ 更新 `front/src/views/apps/knowledge/components/edit.vue` - 编辑页面 -- ✅ 更新 `front/src/views/apps/knowledge/components/detail.vue` - 详情页面 -- ✅ 创建 `front/src/components/WangEditor.vue` - 富文本编辑器组件 -- ✅ 更新 `front/src/main.ts` - 全局注册组件 -- ✅ 更新 `front/src/router/index.ts` - 路由配置 - -## API 端点 - -- `GET /api/knowledge/list` - 获取列表 -- `GET /api/knowledge/detail?id=xxx` - 获取详情 -- `POST /api/knowledge/create` - 创建知识 -- `POST /api/knowledge/update` - 更新知识 -- `POST /api/knowledge/delete` - 删除知识 -- `GET /api/knowledge/categories` - 获取分类 -- `GET /api/knowledge/tags` - 获取标签 - -## 功能特性 - -- ✅ 富文本编辑器(wangEditor) -- ✅ 实时预览 -- ✅ 分类和标签管理 -- ✅ 搜索和分页 -- ✅ 主题支持 -- ✅ 响应式布局 - diff --git a/pc/src/api/file.js b/pc/src/api/file.js index bfeb413..0fe41ae 100644 --- a/pc/src/api/file.js +++ b/pc/src/api/file.js @@ -11,17 +11,6 @@ export function getAllFiles() { }); } -/** - * 获取我的文件 - * @returns {Promise} - */ -export function getMyFiles() { - return request({ - url: "/api/files/my", - method: "get", - }); -} - /** * 根据ID获取文件 * @param {number|string} id 文件ID @@ -34,6 +23,18 @@ export function getFileById(id) { }); } +/** + * 根据租户ID获取文件 + * @param {string} tenantId 租户ID + * @returns {Promise} + */ +export function getFilesByTenant(tenantId) { + return request({ + url: `/api/files/tenant?tenant_id=${tenantId}`, + method: "get", + }); +} + /** * 上传文件 * @param {FormData} formData 文件数据 diff --git a/pc/src/api/role.js b/pc/src/api/role.js new file mode 100644 index 0000000..11bd9e2 --- /dev/null +++ b/pc/src/api/role.js @@ -0,0 +1,46 @@ +import request from '@/utils/request' + +export function getAllRoles(params) { + return request({ + url: '/api/roles', + method: 'get', + params + }) +} + +export function createRole(data) { + return request({ + url: '/api/roles', + method: 'post', + data + }) +} + +export function getRoleById(id) { + return request({ + url: `/api/roles/${id}`, + method: 'get' + }) +} + +export function getRoleByTenantId(tenantId) { + return request({ + url: `/api/roles/tenant/${tenantId}`, + method: 'get' + }) +} + +export function updateRole(id, data) { + return request({ + url: `/api/roles/${id}`, + method: 'post', + data + }) +} + +export function deleteRole(id) { + return request({ + url: `/api/roles/${id}`, + method: 'delete' + }) +} diff --git a/pc/src/assets/less/style.less b/pc/src/assets/less/style.less index 7730e1c..29fda0e 100644 --- a/pc/src/assets/less/style.less +++ b/pc/src/assets/less/style.less @@ -40,4 +40,12 @@ body { position: fixed !important; z-index: var(--el-message-z-index, 9999) !important; pointer-events: auto !important; -} \ No newline at end of file +} + +.wang-editor-wrapper{ + border: 1px solid #dcdfe6 !important; + + .toolbar-container{ + border-bottom: 1px solid #dcdfe6 !important; + } +} diff --git a/pc/src/router/dynamicRoutes.js b/pc/src/router/dynamicRoutes.js index bfe2729..d00bf13 100644 --- a/pc/src/router/dynamicRoutes.js +++ b/pc/src/router/dynamicRoutes.js @@ -68,6 +68,14 @@ export function convertMenusToRoutes(menus) { } } + // 特殊处理:知识库的编辑和详情页需要支持动态参数 + // 如果最终路径是 edit 或 detail,转换为支持参数的路由 + if (currentRoute.path === 'edit') { + currentRoute.path = 'edit/:id'; + } else if (currentRoute.path === 'detail') { + currentRoute.path = 'detail/:id'; + } + if (!parentRoute.children) { parentRoute.children = []; } diff --git a/pc/src/router/index.js b/pc/src/router/index.js index f502787..aef497c 100644 --- a/pc/src/router/index.js +++ b/pc/src/router/index.js @@ -140,30 +140,25 @@ function addDynamicRoutes(menus) { router.addRoute(newMainRoute); - // 添加知识库的子路由(详情页和编辑页) - // 直接在 Main 路由下添加完整路径的子路由 - // router.addRoute('Main', { - // path: 'apps/knowledge/detail/:id', - // name: 'apps-knowledge-detail', - // component: () => import('@/views/apps/knowledge/components/detail.vue'), - // meta: { - // requiresAuth: true, - // title: '知识详情' - // } - // }); - // router.addRoute('Main', { - // path: 'apps/knowledge/edit/:id', - // name: 'apps-knowledge-edit', - // component: () => import('@/views/apps/knowledge/components/edit.vue'), - // meta: { - // requiresAuth: true, - // title: '编辑知识' - // } - // }); - dynamicRoutesAdded = true; } +// 递归查找路由(根据名称) +function findRouteByName(routes, routeName) { + for (const route of routes) { + if (route.name === routeName) { + return route; + } + if (route.children) { + const found = findRouteByName(route.children, routeName); + if (found) { + return found; + } + } + } + return null; +} + // 查找第一个有效的路由(有组件的路由) function findFirstValidRoute(routes) { for (const route of routes) { diff --git a/pc/src/stores/index.js b/pc/src/stores/index.js index 56a3e2c..0ffcde0 100644 --- a/pc/src/stores/index.js +++ b/pc/src/stores/index.js @@ -114,6 +114,48 @@ export const useTabsStore = defineTabsStore('tabs', () => { saveTabsToStorage(tabList.value, activeTab.value); } + // 关闭左侧(关闭指定tab左侧的所有tab,保留首页和目标tab) + function closeLeft(targetFullPath) { + const targetIndex = tabList.value.findIndex((t) => t.fullPath === targetFullPath); + if (targetIndex > -1) { + // 保留首页和目标tab及其右侧的所有tab + const beforeIndex = tabList.value.slice(0, targetIndex); + const hasCloseableLeft = beforeIndex.some(t => t.fullPath !== defaultDashboardPath); + + if (hasCloseableLeft) { + tabList.value = tabList.value.filter((t, index) => + t.fullPath === defaultDashboardPath || index >= targetIndex + ); + // 如果关闭的tab中包含了当前激活的tab,则激活目标tab + if (!tabList.value.find(t => t.fullPath === activeTab.value)) { + activeTab.value = targetFullPath; + } + saveTabsToStorage(tabList.value, activeTab.value); + } + } + } + + // 关闭右侧(关闭指定tab右侧的所有tab,保留首页和目标tab) + function closeRight(targetFullPath) { + const targetIndex = tabList.value.findIndex((t) => t.fullPath === targetFullPath); + if (targetIndex > -1) { + // 保留首页和目标tab及其左侧的所有tab + const afterIndex = tabList.value.slice(targetIndex + 1); + const hasCloseableRight = afterIndex.length > 0; + + if (hasCloseableRight) { + tabList.value = tabList.value.filter((t, index) => + t.fullPath === defaultDashboardPath || index <= targetIndex + ); + // 如果关闭的tab中包含了当前激活的tab,则激活目标tab + if (!tabList.value.find(t => t.fullPath === activeTab.value)) { + activeTab.value = targetFullPath; + } + saveTabsToStorage(tabList.value, activeTab.value); + } + } + } + // 关闭全部,只留首页 function closeAll() { tabList.value = tabList.value.filter((t) => t.fullPath === defaultDashboardPath); @@ -133,6 +175,8 @@ export const useTabsStore = defineTabsStore('tabs', () => { addTab, removeTab, closeOthers, + closeLeft, + closeRight, closeAll, setActiveTab, saveTabsToStorage, diff --git a/pc/src/views/Main.vue b/pc/src/views/Main.vue index 9e9ef1c..8f1d2a2 100644 --- a/pc/src/views/Main.vue +++ b/pc/src/views/Main.vue @@ -3,7 +3,7 @@ import CommonAside from '@/components/CommonAside.vue'; import CommonHeader from '@/components/CommonHeader.vue'; import { useTabsStore } from '@/stores'; import { useRouter, useRoute } from 'vue-router'; -import { ref, watch, reactive, nextTick, onMounted } from 'vue'; +import { ref, watch, reactive, nextTick, onMounted, computed } from 'vue'; import { More, Close, CircleClose } from '@element-plus/icons-vue' const tabsStore = useTabsStore(); @@ -42,6 +42,45 @@ onMounted(() => { // 刷新时,localStorage 中已保存的 tabs 会在 store 初始化时恢复 // 这里只需要确保当前路由对应的 tab 存在并激活 restoreTabFromRoute(); + + // 为 tabs 容器添加右键事件监听(使用事件委托) + const tabsWrapper = document.querySelector('.multi-tabs-wrapper'); + if (tabsWrapper) { + tabsWrapper.addEventListener('contextmenu', (e) => { + // 排除编辑器相关区域,避免影响编辑器功能 + // 如果点击在编辑器区域内,完全不做任何处理(优先检查) + const editorWrapper = e.target.closest?.('.wang-editor-wrapper'); + if (editorWrapper) { + // 在编辑器区域内,不处理右键菜单,也不阻止事件 + return; + } + + // 检查其他编辑器元素(工具栏、下拉面板等) + const editorElements = [ + '.w-e-toolbar', + '.w-e-drop-panel', + '.w-e-modal', + '.w-e-toolbar-menu', + '[data-menu-key]', + '[class*="w-e-"]' + ]; + + for (const selector of editorElements) { + if (e.target.closest && e.target.closest(selector)) { + // 在编辑器元素内,不处理右键菜单 + return; + } + } + + // 只有在非编辑器区域的 tab item 上才处理右键菜单 + const tabItem = e.target.closest('.el-tabs__item'); + if (tabItem) { + e.preventDefault(); + e.stopPropagation(); + handleTabsContextMenu(e); + } + }); + } }); }); @@ -114,16 +153,141 @@ const contextMenu = reactive({ }); const contextDropdownRef = ref(null); -const onTabContextMenu = (event, tab) => { +// 处理 tabs 容器的右键事件 +const handleTabsContextMenu = (event) => { event.preventDefault(); - contextMenu.visible = true; - contextMenu.x = event.clientX; - contextMenu.y = event.clientY; - contextMenu.tab = tab; + event.stopPropagation(); + + // 找到点击的 tab item 元素(el-tabs__item) + let target = event.target; + let tabItem = null; + + // 向上查找 el-tabs__item 元素 + while (target && target !== event.currentTarget) { + if (target.classList && target.classList.contains('el-tabs__item')) { + tabItem = target; + break; + } + target = target.parentElement; + } + + if (!tabItem) return; + + // Element Plus 的 tab item 的 id 格式通常是 "tab-{name}",其中 name 是 tab-pane 的 name 属性 + const tabId = tabItem.id; + if (tabId && tabId.startsWith('tab-')) { + const tabName = tabId.replace('tab-', ''); + const matchedTab = tabsStore.tabList.find(t => t.fullPath === tabName); + if (matchedTab) { + showContextMenu(event, matchedTab); + return; + } + } + + // 如果通过 id 找不到,尝试通过 aria-controls 或其他属性 + const ariaControls = tabItem.getAttribute('aria-controls'); + if (ariaControls) { + const tabName = ariaControls.replace('pane-', ''); + const matchedTab = tabsStore.tabList.find(t => t.fullPath === tabName); + if (matchedTab) { + showContextMenu(event, matchedTab); + } + } +}; + +// 显示右键菜单 +const showContextMenu = (event, tab) => { + // 使用 nextTick 确保在下一个事件循环中更新状态,避免在渲染过程中触发更新 nextTick(() => { - // 溢出优化可扩展 + contextMenu.visible = true; + contextMenu.x = event.clientX; + contextMenu.y = event.clientY; + contextMenu.tab = tab; + + // 延迟添加事件监听器,确保菜单已渲染 + // 关键:完全排除编辑器区域,确保编辑器的事件不被干扰 + setTimeout(() => { + const hideMenuHandler = (e) => { + // 如果右键菜单已经隐藏,直接返回 + if (!contextMenu.visible) { + return; + } + + const target = e.target; + if (!target) { + hideContextMenu(); + return; + } + + // 检查点击是否在右键菜单本身上 + if (target.closest?.('.context-menu')) { + return; // 点击在菜单上,不隐藏 + } + + // ========== 关键修复:优先检查编辑器区域 ========== + // 如果在编辑器区域内,立即返回,不执行任何操作,让编辑器的事件正常处理 + + // 先检查是否在编辑器包装器内(最快判断) + const wangEditorWrapper = target.closest?.('.wang-editor-wrapper'); + if (wangEditorWrapper) { + // 在编辑器包装器内,完全不做任何处理,让编辑器正常处理 + return; + } + + // 检查所有可能的编辑器元素(包括工具栏、下拉面板、模态框等) + const editorSelectors = [ + '.w-e-toolbar', + '.w-e-drop-panel', + '.w-e-modal', + '.w-e-toolbar-menu', + '.toolbar-container', + '.editor-container', + '.w-e-text-container', + '.w-e-text', + // 检查是否有 WangEditor 相关的元素 + '[data-menu-key]', + '[class*="w-e-"]' + ]; + + for (const selector of editorSelectors) { + if (target.closest?.(selector)) { + // 在编辑器区域内,完全不做任何处理,让编辑器的事件正常处理 + return; + } + } + + // 其他区域点击,隐藏菜单 + hideContextMenu(); + }; + + // 关键修复:使用 capture: false 在冒泡阶段处理,并且延迟注册 + // 这样可以确保编辑器的监听器(通常在目标元素上)先处理事件 + // 然后再处理我们的监听器(在 body 上) + // 注意:只有在右键菜单显示时才注册,并且排除编辑器区域 + setTimeout(() => { + // 再次检查右键菜单是否仍然可见 + if (contextMenu.visible) { + document.body.addEventListener('click', hideMenuHandler, { once: true, capture: false, passive: true }); + } + }, 100); // 延迟注册,确保编辑器的事件监听器已经注册并可以正常处理 + + const hideContextMenuHandler = (e) => { + const target = e.target; + if (!target) { + hideContextMenu(); + return; + } + + // 排除编辑器区域和右键菜单本身 + if (target.closest?.('.w-e-toolbar') || target.closest?.('.context-menu') || target.closest?.('.wang-editor-wrapper')) { + return; + } + hideContextMenu(); + }; + + document.body.addEventListener('contextmenu', hideContextMenuHandler, { once: true }); + }, 0); }); - document.body.addEventListener('click', hideContextMenu, { once: true }); }; function hideContextMenu() { contextMenu.visible = false; @@ -135,18 +299,63 @@ function closeTabContextTab() { } hideContextMenu(); } -function closeOthersContextTab() { +// 关闭左侧 +function closeLeftContextTab() { if (contextMenu.tab) { - tabsStore.activeTab = contextMenu.tab.fullPath; - tabsStore.closeOthers(); + tabsStore.closeLeft(contextMenu.tab.fullPath); + // 如果当前路由对应的tab被关闭了,跳转到激活的tab + if (!tabsStore.tabList.find(tab => tab.fullPath === route.fullPath)) { + router.push(tabsStore.activeTab); + } } hideContextMenu(); } + +// 关闭右侧 +function closeRightContextTab() { + if (contextMenu.tab) { + tabsStore.closeRight(contextMenu.tab.fullPath); + // 如果当前路由对应的tab被关闭了,跳转到激活的tab + if (!tabsStore.tabList.find(tab => tab.fullPath === route.fullPath)) { + router.push(tabsStore.activeTab); + } + } + hideContextMenu(); +} + +// 关闭其他 +function closeOthersContextTab() { + if (contextMenu.tab) { + tabsStore.setActiveTab(contextMenu.tab.fullPath); + tabsStore.closeOthers(); + if (!tabsStore.tabList.find(tab => tab.fullPath === route.fullPath)) { + router.push(tabsStore.activeTab); + } + } + hideContextMenu(); +} + +// 关闭全部 function closeAllTabs() { tabsStore.closeAll(); hideContextMenu(); router.push(defaultDashboardPath); } + +// 计算是否可以关闭左侧/右侧 +const canCloseLeft = computed(() => { + if (!contextMenu.tab) return false; + const targetIndex = tabsStore.tabList.findIndex(t => t.fullPath === contextMenu.tab.fullPath); + // 至少左侧有一个可关闭的tab(排除首页) + return targetIndex > 0 && tabsStore.tabList.slice(0, targetIndex).some(t => t.fullPath !== defaultDashboardPath); +}); + +const canCloseRight = computed(() => { + if (!contextMenu.tab) return false; + const targetIndex = tabsStore.tabList.findIndex(t => t.fullPath === contextMenu.tab.fullPath); + // 右侧至少有一个tab + return targetIndex < tabsStore.tabList.length - 1; +}); + diff --git a/pc/src/views/system/roles/components/edit.vue b/pc/src/views/system/roles/components/edit.vue new file mode 100644 index 0000000..87f80a2 --- /dev/null +++ b/pc/src/views/system/roles/components/edit.vue @@ -0,0 +1,216 @@ + + + + + + diff --git a/pc/src/views/system/roles/index.vue b/pc/src/views/system/roles/index.vue index 719bf2f..fb7d1e4 100644 --- a/pc/src/views/system/roles/index.vue +++ b/pc/src/views/system/roles/index.vue @@ -3,215 +3,241 @@

角色管理

- + 添加角色 + + + 刷新
- -
-
-

正在加载角色数据...

-
- -
+
- 重试 + 重试
- - - - - + + + + + + + + + + + + + + -
- -
- - - - - - - - - - - - - - - + + + + +
diff --git a/pc/src/views/system/tenant/index.vue b/pc/src/views/system/tenant/index.vue index fa16da2..93e3158 100644 --- a/pc/src/views/system/tenant/index.vue +++ b/pc/src/views/system/tenant/index.vue @@ -3,14 +3,14 @@ @@ -24,7 +24,7 @@
- + 重试
@@ -37,6 +37,7 @@ stripe style="width: 100%" v-loading="loading" + element-loading-text="正在加载..." > @@ -203,6 +204,16 @@ const handlePageChange = (val: number) => { fetchTenants(); }; +// 刷新界面 +async function refresh() { + try { + await fetchTenants(); + ElMessage.success('刷新成功'); + } catch (error) { + ElMessage.error('刷新失败'); + } +} + // 审核状态相关方法 function getAuditStatusType( status: string diff --git a/pc/src/views/system/users/index.vue b/pc/src/views/system/users/index.vue index 3b89041..9b953fa 100644 --- a/pc/src/views/system/users/index.vue +++ b/pc/src/views/system/users/index.vue @@ -7,12 +7,16 @@ 添加用户 + + + 刷新 + - + - + @@ -123,9 +127,23 @@ - - - + + + {{ role.roleName }} + + ({{ role.roleCode }}) + + @@ -146,7 +164,7 @@