已修改20个文件
已删除26个文件
已添加9个文件
对比新文件 |
| | |
| | | import request from '@/config/axios' |
| | | |
| | | /** |
| | | * 获取磁盘信息 |
| | | */ |
| | | export const getDiskInfo = () => { |
| | | return request.get({ url: '/infra/actuator/disk/info' }) |
| | | } |
| | | |
| | | /** |
| | | * 获取内存信息 |
| | | */ |
| | | export const getMemoryInfo = () => { |
| | | return request.get({ url: '/infra/actuator/memory/info' }) |
| | | } |
对比新文件 |
| | |
| | | export interface StorageMonitorInfoVO { |
| | | name: string |
| | | max: number |
| | | rest: number |
| | | restPPT: number |
| | | } |
| | |
| | | return request.get({ url: '/system/auth/get-permission-info' }) |
| | | } |
| | | |
| | | // 获取用应用户权限信息 |
| | | export const getUserAppInfo = (id: number) => { |
| | | return request.get({ url: '/system/auth/get-app-permission-info?id=' + id }) |
| | | } |
| | | |
| | | //获取登录验证码 |
| | | export const sendSmsCode = (data: SmsCodeVO) => { |
| | | return request.post({ url: '/system/auth/send-sms-code', data }) |
| | |
| | | createTime: Date |
| | | } |
| | | |
| | | // 查询列表 |
| | | // 查询分页列表 |
| | | export const getAppPage = (params: PageParam) => { |
| | | return request.get({ url: '/system/app/page', params }) |
| | | } |
| | | |
| | | // 查询列表 |
| | | export const getAppList = () => { |
| | | return request.get({ url: '/system/app/getAppList' }) |
| | | } |
| | | |
| | | // 获得 |
| | | export const getApp = (id: number) => { |
| | | return request.get({ url: '/system/app/get?id=' + id }) |
对比新文件 |
| | |
| | | import request from '@/config/axios' |
| | | |
| | | export interface AppGroupVO { |
| | | id: number |
| | | node: string |
| | | name: string |
| | | icon: string |
| | | sort: number |
| | | remark: string |
| | | createTime: Date |
| | | } |
| | | |
| | | // 查询分页列表 |
| | | export const getAppGroupPage = (params: PageParam) => { |
| | | return request.get({ url: '/system/app-group/page', params }) |
| | | } |
| | | |
| | | // 查询列表 |
| | | export const getAppGroupList = () => { |
| | | return request.get({ url: '/system/app-group/getAppGroupList' }) |
| | | } |
| | | |
| | | // 获得 |
| | | export const getAppGroup = (id: number) => { |
| | | return request.get({ url: '/system/app-group/get?id=' + id }) |
| | | } |
| | | |
| | | // 新增 |
| | | export const createAppGroup = (data: AppGroupVO) => { |
| | | return request.post({ url: '/system/app-group/create', data }) |
| | | } |
| | | |
| | | // 修改 |
| | | export const updateAppGroup = (data: AppGroupVO) => { |
| | | return request.put({ url: '/system/app-group/update', data }) |
| | | } |
| | | |
| | | // 删除 |
| | | export const deleteAppGroup = (id: number) => { |
| | | return request.delete({ url: '/system/app-group/delete?id=' + id }) |
| | | } |
对比新文件 |
| | |
| | | import request from '@/config/axios' |
| | | |
| | | export interface AppMenuVO { |
| | | id: number |
| | | name: string |
| | | permission: string |
| | | type: number |
| | | sort: number |
| | | parentId: number |
| | | path: string |
| | | icon: string |
| | | component: string |
| | | componentName?: string |
| | | status: number |
| | | visible: boolean |
| | | keepAlive: boolean |
| | | alwaysShow?: boolean |
| | | createTime: Date |
| | | } |
| | | |
| | | // 查询菜单(精简)列表 |
| | | export const getSimpleMenusList = () => { |
| | | return request.get({ url: '/system/app-menu/simple-list' }) |
| | | } |
| | | |
| | | // 查询菜单列表 |
| | | export const getMenuList = (params) => { |
| | | return request.get({ url: '/system/app-menu/list', params }) |
| | | } |
| | | |
| | | // 获取菜单详情 |
| | | export const getMenu = (id: number) => { |
| | | return request.get({ url: '/system/app-menu/get?id=' + id }) |
| | | } |
| | | |
| | | // 新增菜单 |
| | | export const createMenu = (data: AppMenuVO) => { |
| | | return request.post({ url: '/system/app-menu/create', data }) |
| | | } |
| | | |
| | | // 修改菜单 |
| | | export const updateMenu = (data: AppMenuVO) => { |
| | | return request.put({ url: '/system/app-menu/update', data }) |
| | | } |
| | | |
| | | // 删除菜单 |
| | | export const deleteMenu = (id: number) => { |
| | | return request.delete({ url: '/system/app-menu/delete?id=' + id }) |
| | | } |
| | |
| | | keepAlive: boolean |
| | | alwaysShow?: boolean |
| | | createTime: Date |
| | | appId: number |
| | | } |
| | | |
| | | // 查询菜单(精简)列表 |
| | |
| | | return request.get({ url: '/system/menu/simple-list' }) |
| | | } |
| | | |
| | | // 查询应用菜单(精简)列表 |
| | | export const getSimpleAppMenusList = () => { |
| | | return request.get({ url: '/system/menu/simple-app-menus' }) |
| | | } |
| | | |
| | | // 查询菜单列表 |
| | | export const getMenuList = (params) => { |
| | | return request.get({ url: '/system/menu/list', params }) |
| | | } |
| | | |
| | | // 查询应用菜单列表 |
| | | export const getAppMenuList = (params) => { |
| | | return request.get({ url: '/system/menu/app-menu-list', params }) |
| | | } |
| | | |
| | | // 获取菜单详情 |
| | |
| | | return request.get({ url: '/system/menu/get?id=' + id }) |
| | | } |
| | | |
| | | // 获取应用菜单详情 |
| | | export const getAppMenu = (id: number) => { |
| | | return request.get({ url: '/system/menu/getAppMenu?id=' + id }) |
| | | } |
| | | |
| | | // 新增菜单 |
| | | export const createMenu = (data: MenuVO) => { |
| | | return request.post({ url: '/system/menu/create', data }) |
| | | } |
| | | |
| | | // 新增应用菜单 |
| | | export const createAppMenu = (data: MenuVO) => { |
| | | return request.post({ url: '/system/menu/createAppMenu', data }) |
| | | } |
| | | |
| | | // 修改菜单 |
| | |
| | | return request.put({ url: '/system/menu/update', data }) |
| | | } |
| | | |
| | | // 修改应用菜单 |
| | | export const updateAppMenu = (data: MenuVO) => { |
| | | return request.put({ url: '/system/menu/updateAppMenu', data }) |
| | | } |
| | | |
| | | // 删除菜单 |
| | | export const deleteMenu = (id: number) => { |
| | | return request.delete({ url: '/system/menu/delete?id=' + id }) |
| | | } |
| | | |
| | | // 删除应用菜单 |
| | | export const deleteAppMenu = (id: number) => { |
| | | return request.delete({ url: '/system/menu/deleteAppMenu?id=' + id }) |
| | | } |
| | |
| | | import request from '@/config/axios' |
| | | |
| | | export interface OAuth2TokenVO { |
| | | id: number |
| | | accessToken: string |
| | | refreshToken: string |
| | | userId: number |
| | | userType: number |
| | | clientId: string |
| | | createTime: Date |
| | | expiresTime: Date |
| | | grantType: string |
| | | scope: string |
| | | refreshToken: any |
| | | username: string |
| | | password: string |
| | | redirectUri: string |
| | | } |
| | | |
| | | // 查询 token列表 |
| | |
| | | return request.get({ url: '/system/oauth2-token/page', params }) |
| | | } |
| | | |
| | | // 单点登录授权 |
| | | export const OAuth2Login = (params: OAuth2TokenVO) => { |
| | | return request.post({ url: '/system/oauth2/token', data: params }) |
| | | } |
| | | |
| | | // 删除 token |
| | | export const deleteAccessToken = (accessToken: string) => { |
| | | return request.delete({ url: '/system/oauth2-token/delete?accessToken=' + accessToken }) |
| | |
| | | return request.get({ url: '/system/tenant/page', params }) |
| | | } |
| | | |
| | | // 查询租户列表 |
| | | export const getSimpleTenant = () => { |
| | | return request.get({ url: '/system/tenant/simple-list' }) |
| | | } |
| | | |
| | | // 查询租户详情 |
| | | export const getTenant = (id: number) => { |
| | | return request.get({ url: '/system/tenant/get?id=' + id }) |
| | |
| | | </el-select> |
| | | ) |
| | | } |
| | | debugger |
| | | // debugger |
| | | return ( |
| | | <el-select |
| | | class="w-1/1" |
| | |
| | | } |
| | | // 移除监听器 |
| | | const removeListener = (index) => { |
| | | debugger |
| | | // debugger |
| | | ElMessageBox.confirm('确认移除该监听器吗?', '提示', { |
| | | confirmButtonText: '确 认', |
| | | cancelButtonText: '取 消' |
| | |
| | | const bpmnInstances = () => (window as any)?.bpmnInstances |
| | | // 创建监听器实例 |
| | | export function createListenerObject(options, isTask, prefix) { |
| | | debugger |
| | | // debugger |
| | | const listenerObj = Object.create(null) |
| | | listenerObj.event = options.event |
| | | isTask && (listenerObj.id = options.id) // 任务监听器特有的 id 字段 |
| | |
| | | ...config, |
| | | responseType: responseType, |
| | | headers: { |
| | | 'Content-Type': headersType || default_headers |
| | | 'Content-Type': headersType || default_headers, |
| | | } |
| | | }) |
| | | } |
| | |
| | | import { computed, onMounted, ref, unref, watch } from 'vue' |
| | | import { useAppStore } from '@/store/modules/app' |
| | | import { useDesign } from '@/hooks/web/useDesign' |
| | | import * as authUtil from "@/utils/auth"; |
| | | |
| | | defineOptions({ name: 'Logo' }) |
| | | |
| | |
| | | |
| | | const show = ref(true) |
| | | |
| | | const homePath = ref('/index') |
| | | |
| | | const title = computed(() => appStore.getTitle) |
| | | |
| | | const layout = computed(() => appStore.getLayout) |
| | | |
| | | const collapse = computed(() => appStore.getCollapse) |
| | | |
| | | let tenantId = authUtil.getTenantId() |
| | | console.log(tenantId) |
| | | if (tenantId && tenantId === 1) { |
| | | homePath.value = '/index' |
| | | } else { |
| | | homePath.value = '/home2' |
| | | } |
| | | console.log(homePath.value) |
| | | |
| | | onMounted(() => { |
| | | if (unref(collapse)) show.value = false |
| | |
| | | layout !== 'classic' ? `${prefixCls}__Top` : '', |
| | | 'flex !h-[var(--logo-height)] items-center cursor-pointer pl-8px relative decoration-none overflow-hidden' |
| | | ]" |
| | | to="/" |
| | | :to="homePath" |
| | | > |
| | | <img |
| | | class="h-[calc(var(--logo-height)-10px)] w-[calc(var(--logo-height)-10px)]" |
| | |
| | | } |
| | | if (!userStore.getIsSetUser) { |
| | | isRelogin.show = true |
| | | await userStore.setUserInfoAction() |
| | | await userStore. |
| | | setUserInfoAction() |
| | | isRelogin.show = false |
| | | // 后端过滤菜单 |
| | | await permissionStore.generateRoutes() |
| | |
| | | import 'virtual:uno.css' |
| | | import 'uno.css' |
| | |
| | | import { Layout } from '@/utils/routerHelper' |
| | | import {Layout} from '@/utils/routerHelper' |
| | | |
| | | const { t } = useI18n() |
| | | /** |
| | |
| | | } |
| | | }, |
| | | { |
| | | path: '/home2', |
| | | component: () => import('@/views/Home/Index2.vue'), |
| | | name: 'Home2', |
| | | meta: { |
| | | hidden: true, |
| | | noTagsView: true |
| | | }, |
| | | }, |
| | | { |
| | | path: '/', |
| | | component: Layout, |
| | | redirect: '/index', |
| | | name: 'Home', |
| | | meta: {}, |
| | | meta: { |
| | | hidden: true, |
| | | noTagsView: true |
| | | }, |
| | | children: [ |
| | | { |
| | | path: 'index', |
| | |
| | | } |
| | | |
| | | /** |
| | | * 应用菜单的类型枚举 |
| | | */ |
| | | export const SystemAppMenuTypeEnum = { |
| | | DIR: 1, // 应用 |
| | | MENU: 2, // 菜单 |
| | | BUTTON: 3 // 按钮 |
| | | } |
| | | |
| | | /** |
| | | * 角色的类型枚举 |
| | | */ |
| | | export const SystemRoleTypeEnum = { |
| | |
| | | // ========== SYSTEM 模块 ========== |
| | | SYSTEM_USER_SEX = 'system_user_sex', |
| | | SYSTEM_MENU_TYPE = 'system_menu_type', |
| | | SYSTEM_APP_MENU_TYPE = 'system_app_menu_type', |
| | | SYSTEM_APP_TYPE = 'system_app_type', |
| | | SYSTEM_ROLE_TYPE = 'system_role_type', |
| | | SYSTEM_DATA_SCOPE = 'system_data_scope', |
| | | SYSTEM_NOTICE_TYPE = 'system_notice_type', |
| | |
| | | /* Layout */ |
| | | export const Layout = () => import('@/layout/Layout.vue') |
| | | |
| | | |
| | | export const getParentLayout = () => { |
| | | return () => |
| | | new Promise((resolve) => { |
| | |
| | | mode="pop" |
| | | @success="handleLogin" |
| | | /> |
| | | <!--<el-col :span="24" style="padding-right: 10px; padding-left: 10px"> |
| | | <el-form-item> |
| | | <el-row :gutter="5" justify="space-between" style="width: 100%"> |
| | | <el-col :span="8"> |
| | | <XButton |
| | | :title="t('login.btnMobile')" |
| | | class="w-[100%]" |
| | | @click="setLoginState(LoginStateEnum.MOBILE)" |
| | | /> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <XButton |
| | | :title="t('login.btnQRCode')" |
| | | class="w-[100%]" |
| | | @click="setLoginState(LoginStateEnum.QR_CODE)" |
| | | /> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <XButton |
| | | :title="t('login.btnRegister')" |
| | | class="w-[100%]" |
| | | @click="setLoginState(LoginStateEnum.REGISTER)" |
| | | /> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form-item> |
| | | </el-col>--> |
| | | <!--<el-divider content-position="center">{{ t('login.otherLogin') }}</el-divider> |
| | | <el-col :span="24" style="padding-right: 10px; padding-left: 10px"> |
| | | <el-form-item> |
| | | <div class="w-[100%] flex justify-between"> |
| | | <Icon |
| | | v-for="(item, key) in socialList" |
| | | :key="key" |
| | | :icon="item.icon" |
| | | :size="30" |
| | | class="anticon cursor-pointer" |
| | | color="#999" |
| | | @click="doSocialLogin(item.type)" |
| | | /> |
| | | </div> |
| | | </el-form-item> |
| | | </el-col>--> |
| | | </el-row> |
| | | </el-form> |
| | | </template> |
| | |
| | | rememberMe: true // 默认记录我。如果不需要,可手动修改 |
| | | } |
| | | }) |
| | | |
| | | const socialList = [ |
| | | { icon: 'ant-design:wechat-filled', type: 30 }, |
| | | { icon: 'ant-design:dingtalk-circle-filled', type: 20 }, |
| | | { icon: 'ant-design:github-filled', type: 0 }, |
| | | { icon: 'ant-design:alipay-circle-filled', type: 0 } |
| | | ] |
| | | |
| | | // 获取验证码 |
| | | const getCode = async () => { |
| | |
| | | if (!redirect.value) { |
| | | redirect.value = '/' |
| | | } |
| | | // 判断是否为SSO登录 |
| | | if (redirect.value.indexOf('sso') !== -1) { |
| | | window.location.href = window.location.href.replace('/login?redirect=', '') |
| | | } else { |
| | | push({ path: redirect.value || permissionStore.addRouters[0].path }) |
| | | } |
| | | let tenantId = authUtil.getTenantId() |
| | | // if(tenantId != 1) { |
| | | // //只要不是系统租户,登录成功跳转到home2页面 |
| | | // window.location.href = '/home2' |
| | | // } else { |
| | | // 判断是否为SSO登录 |
| | | if (redirect.value.indexOf('sso') !== -1) { |
| | | window.location.href = window.location.href.replace('/login?redirect=', '') |
| | | } else { |
| | | push({ path: redirect.value || permissionStore.addRouters[0].path }) |
| | | } |
| | | // } |
| | | } finally { |
| | | loginLoading.value = false |
| | | loading.value.close() |
| | | } |
| | | } |
| | | |
| | | // 社交登录 |
| | | const doSocialLogin = async (type: number) => { |
| | | if (type === 0) { |
| | | message.error('此方式未配置') |
| | | } else { |
| | | loginLoading.value = true |
| | | if (loginData.tenantEnable === 'true') { |
| | | // 尝试先通过 tenantName 获取租户 |
| | | await getTenantId() |
| | | // 如果获取不到,则需要弹出提示,进行处理 |
| | | if (!authUtil.getTenantId()) { |
| | | try { |
| | | const data = await message.prompt('请输入租户名称', t('common.reminder')) |
| | | if (data?.action !== 'confirm') throw 'cancel' |
| | | const res = await LoginApi.getTenantIdByName(data.value) |
| | | authUtil.setTenantId(res) |
| | | } catch (error) { |
| | | if (error === 'cancel') return |
| | | } finally { |
| | | loginLoading.value = false |
| | | } |
| | | } |
| | | } |
| | | // 计算 redirectUri |
| | | // tricky: type、redirect需要先encode一次,否则钉钉回调会丢失。 |
| | | // 配合 Login/SocialLogin.vue#getUrlValue() 使用 |
| | | const redirectUri = |
| | | location.origin + |
| | | '/social-login?' + |
| | | encodeURIComponent(`type=${type}&redirect=${redirect.value || '/'}`) |
| | | |
| | | // 进行跳转 |
| | | const res = await LoginApi.socialAuthRedirect(type, encodeURIComponent(redirectUri)) |
| | | window.location.href = res |
| | | } |
| | | } |
| | | watch( |
| | | () => currentRoute.value, |
| | | (route: RouteLocationNormalizedLoaded) => { |
| | |
| | | const processDefinitionDetail = await DefinitionApi.getProcessDefinition( |
| | | row.processDefinitionId |
| | | ) |
| | | debugger |
| | | if (processDefinitionDetail.formType === 20) { |
| | | message.error('重新发起流程失败,原因:该流程使用业务表单,不支持重新发起') |
| | | return |
| | |
| | | <!-- 工作流 - 抄送我的流程 --> |
| | | <template> |
| | | <ContentWrap> |
| | | <!-- 搜索工作栏 --> |
| | | <el-form ref="queryFormRef" :inline="true" class="-mb-15px" label-width="68px"> |
| | |
| | | /** 初始化 */ |
| | | onMounted(async () => { |
| | | try { |
| | | // 友情提示:如果访问出现 404 问题: |
| | | // 1)boot 参考 https://doc.iocoder.cn/server-monitor/ 解决; |
| | | // 2)cloud 参考 https://cloud.iocoder.cn/server-monitor/ 解决 |
| | | const data = await ConfigApi.getConfigKey('url.spring-boot-admin') |
| | | if (data && data.length > 0) { |
| | | src.value = data |
对比新文件 |
| | |
| | | <template> |
| | | <el-scrollbar height="calc(100vh - 88px - 40px - 50px)"> |
| | | <el-row> |
| | | <!-- 磁盘使用量统计 --> |
| | | <el-col :span="12" class="mt-3"> |
| | | <el-card class="ml-3" :gutter="12" shadow="hover"> |
| | | <!-- <div ref="chartRef" style="width: 100%; height: 90%"></div>--> |
| | | <Echart :options="usedDiskEchartChika" :height="420" /> |
| | | <!-- <Echart :options="usedDiskEchartChika" :height="420" />--> |
| | | </el-card> |
| | | </el-col> |
| | | </el-row> |
| | | </el-scrollbar> |
| | | </template> |
| | | <script lang="ts" setup> |
| | | import { ref, onMounted } from "vue"; |
| | | import * as StorageApi from '@/api/infra/storage' |
| | | import { StorageMonitorInfoVO } from '@/api/infra/storage/types' |
| | | const disks = ref<StorageMonitorInfoVO>() |
| | | const disk = ref<StorageMonitorInfoVO>() |
| | | |
| | | // 基本信息 |
| | | const readDiskInfo = async () => { |
| | | const data = await StorageApi.getDiskInfo() |
| | | disks.value = data |
| | | disk.value = data[0] |
| | | } |
| | | |
| | | // 内存使用情况 |
| | | const usedDiskEchartChika = reactive<any>({ |
| | | title: { |
| | | // 仪表盘标题。 |
| | | text: '磁盘使用情况', |
| | | left: 'center', |
| | | show: true, // 是否显示标题,默认 true。 |
| | | offsetCenter: [0, '20%'], //相对于仪表盘中心的偏移位置,数组第一项是水平方向的偏移,第二项是垂直方向的偏移。可以是绝对的数值,也可以是相对于仪表盘半径的百分比。 |
| | | color: 'yellow', // 文字的颜色,默认 #333。 |
| | | fontSize: 20 // 文字的字体大小,默认 15。 |
| | | }, |
| | | toolbox: { |
| | | show: false, |
| | | feature: { |
| | | restore: { show: true }, |
| | | saveAsImage: { show: true } |
| | | } |
| | | }, |
| | | series: [ |
| | | { |
| | | name: '峰值', |
| | | type: 'gauge', |
| | | min: 0, |
| | | max: 500, |
| | | splitNumber: 10, |
| | | //这是指针的颜色 |
| | | color: '#F5C74E', |
| | | radius: '85%', |
| | | center: ['50%', '50%'], |
| | | startAngle: 225, |
| | | endAngle: -45, |
| | | axisLine: { |
| | | // 坐标轴线 |
| | | lineStyle: { |
| | | // 属性lineStyle控制线条样式 |
| | | color: [ |
| | | [0.2, '#7FFF00'], |
| | | [0.8, '#00FFFF'], |
| | | [1, '#FF0000'] |
| | | ], |
| | | //width: 6 外框的大小(环的宽度) |
| | | width: 10 |
| | | } |
| | | }, |
| | | axisTick: { |
| | | // 坐标轴小标记 |
| | | //里面的线长是5(短线) |
| | | length: 5, // 属性length控制线长 |
| | | lineStyle: { |
| | | // 属性lineStyle控制线条样式 |
| | | color: '#76D9D7' |
| | | } |
| | | }, |
| | | splitLine: { |
| | | // 分隔线 |
| | | length: 20, // 属性length控制线长 |
| | | lineStyle: { |
| | | // 属性lineStyle(详见lineStyle)控制线条样式 |
| | | color: '#76D9D7' |
| | | } |
| | | }, |
| | | axisLabel: { |
| | | color: '#76D9D7', |
| | | distance: 15, |
| | | fontSize: 15 |
| | | }, |
| | | pointer: { |
| | | // 指针的大小 |
| | | width: 7, |
| | | show: true |
| | | }, |
| | | detail: { |
| | | textStyle: { |
| | | fontWeight: 'normal', |
| | | // 里面文字下的数值大小(50) |
| | | fontSize: 15, |
| | | color: '#FFFFFF' |
| | | }, |
| | | valueAnimation: true |
| | | }, |
| | | progress: { |
| | | show: true |
| | | } |
| | | } |
| | | ] |
| | | }) |
| | | |
| | | |
| | | /** 加载数据 */ |
| | | const getSummary = () => { |
| | | // 初始化命令图表 |
| | | usedDiskInstance() |
| | | } |
| | | |
| | | const usedDiskInstance = async () => { |
| | | try { |
| | | const data = await StorageApi.getDiskInfo() |
| | | disks.value = data |
| | | disk.value = data[0] |
| | | // data.forEach((disk) => { |
| | | console.log(disk.value) |
| | | console.log(disk.value.name) |
| | | console.log(disk.value!.restPPT) |
| | | // 仪表盘详情,用于显示数据。 |
| | | usedDiskEchartChika.series[0].detail = { |
| | | show: true, // 是否显示详情,默认 true。 |
| | | offsetCenter: [0, '50%'], // 相对于仪表盘中心的偏移位置,数组第一项是水平方向的偏移,第二项是垂直方向的偏移。可以是绝对的数值,也可以是相对于仪表盘半径的百分比。 |
| | | color: 'auto', // 文字的颜色,默认 auto。 |
| | | fontSize: 30, // 文字的字体大小,默认 15。 |
| | | formatter: disk.value!.restPPT // 格式化函数或者字符串 |
| | | } |
| | | console.log(disk.value.restPPT) |
| | | usedDiskEchartChika.series[0].data[0] = { |
| | | value: disk.value!.restPPT, |
| | | name: '磁盘消耗' |
| | | } |
| | | console.log(disk.value) |
| | | usedDiskEchartChika.tooltip = { |
| | | formatter: '{b} <br/>{a} : ' + disk.value!.restPPT |
| | | } |
| | | // }) |
| | | } catch {} |
| | | } |
| | | |
| | | /** 初始化 **/ |
| | | onMounted(() => { |
| | | readDiskInfo() |
| | | // 读取 redis 信息 |
| | | // readDiskInfo() |
| | | // // 加载数据 |
| | | getSummary() |
| | | }) |
| | | </script> |
对比新文件 |
| | |
| | | <template> |
| | | <Dialog v-model="dialogVisible" :title="dialogTitle" width="50%"> |
| | | <el-form |
| | | ref="formRef" |
| | | v-loading="formLoading" |
| | | :model="formData" |
| | | :rules="formRules" |
| | | label-width="80px" |
| | | > |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="分组编号" prop="appCode"> |
| | | <el-input v-model="formData.code" placeholder="请输入应用分组编号" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="分组名称" prop="appName"> |
| | | <el-input v-model="formData.name" placeholder="请输入应用分组名称" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="分组图标" prop="icon"> |
| | | <UploadImg v-model="formData.icon" :limit="1" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="排序" prop="orderNum"> |
| | | <el-input-number v-model="formData.sort" placeholder="请输入排序" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="备注" prop="remark"> |
| | | <el-input v-model="formData.remark" clearable type="textarea" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> |
| | | <el-button @click="dialogVisible = false">取 消</el-button> |
| | | </template> |
| | | </Dialog> |
| | | </template> |
| | | <script lang="ts" setup> |
| | | import * as AppGroupApi from '@/api/system/appgroup' |
| | | |
| | | defineOptions({ name: 'SystemAppGroupForm' }) |
| | | |
| | | const { t } = useI18n() // 国际化 |
| | | const message = useMessage() // 消息弹窗 |
| | | const dialogVisible = ref(false) // 弹窗的是否展示 |
| | | const dialogTitle = ref('') // 弹窗的标题 |
| | | const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 |
| | | const formType = ref('') // 表单的类型:create - 新增;update - 修改 |
| | | const formData = ref({ |
| | | id: undefined, |
| | | code: undefined, |
| | | name: undefined, |
| | | icon: undefined, |
| | | sort: undefined, |
| | | remark: undefined |
| | | }) |
| | | const formRules = reactive({ |
| | | code: [{ required: true, message: '分组编号不能为空', trigger: 'blur' }], |
| | | name: [{ required: true, message: '分组名称不能为空', trigger: 'blur' }] |
| | | }) |
| | | const formRef = ref() // 表单 Ref |
| | | /** 打开弹窗 */ |
| | | const open = async (type: string, id?: number) => { |
| | | dialogVisible.value = true |
| | | dialogTitle.value = t('action.' + type) |
| | | formType.value = type |
| | | resetForm() |
| | | // 修改时,设置数据 |
| | | if (id) { |
| | | formLoading.value = true |
| | | try { |
| | | formData.value = await AppGroupApi.getAppGroup(id) |
| | | } finally { |
| | | formLoading.value = false |
| | | } |
| | | } |
| | | } |
| | | defineExpose({ open }) // 提供 open 方法,用于打开弹窗 |
| | | |
| | | /** 提交表单 */ |
| | | const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 |
| | | const submitForm = async () => { |
| | | // 校验表单 |
| | | if (!formRef) return |
| | | const valid = await formRef.value.validate() |
| | | if (!valid) return |
| | | // 提交请求 |
| | | formLoading.value = true |
| | | try { |
| | | const data = formData.value as unknown as AppGroupApi.AppGroupVO |
| | | if (formType.value === 'create') { |
| | | await AppGroupApi.createAppGroup(data) |
| | | message.success(t('common.createSuccess')) |
| | | } else { |
| | | await AppGroupApi.updateAppGroup(data) |
| | | message.success(t('common.updateSuccess')) |
| | | } |
| | | dialogVisible.value = false |
| | | // 发送操作成功的事件 |
| | | emit('success') |
| | | } finally { |
| | | formLoading.value = false |
| | | } |
| | | } |
| | | |
| | | /** 重置表单 */ |
| | | const resetForm = () => { |
| | | formData.value = { |
| | | id: undefined, |
| | | code: undefined, |
| | | name: undefined, |
| | | icon: undefined, |
| | | sort: undefined, |
| | | remark: undefined, |
| | | } |
| | | formRef.value?.resetFields() |
| | | } |
| | | </script> |
对比新文件 |
| | |
| | | <template> |
| | | <!-- 搜索 --> |
| | | <ContentWrap> |
| | | <el-form |
| | | class="-mb-15px" |
| | | :model="queryParams" |
| | | ref="queryFormRef" |
| | | :inline="true" |
| | | label-width="68px" |
| | | > |
| | | <el-form-item label="分组编号" prop="appCode"> |
| | | <el-input |
| | | v-model="queryParams.code" |
| | | placeholder="请输入分组编号" |
| | | clearable |
| | | @keyup.enter="handleQuery" |
| | | class="!w-240px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="分组名称" prop="appName"> |
| | | <el-input |
| | | v-model="queryParams.name" |
| | | placeholder="请输入分组名称" |
| | | clearable |
| | | @keyup.enter="handleQuery" |
| | | class="!w-240px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button @click="handleQuery"> |
| | | <Icon icon="ep:search" class="mr-5px" /> |
| | | 搜索 |
| | | </el-button> |
| | | <el-button @click="resetQuery"> |
| | | <Icon icon="ep:refresh" class="mr-5px" /> |
| | | 重置 |
| | | </el-button> |
| | | <el-button |
| | | type="primary" |
| | | plain |
| | | @click="openForm('create')" |
| | | v-hasPermi="['system:app-group:create']" |
| | | > |
| | | <Icon icon="ep:plus" class="mr-5px" /> |
| | | 新增 |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </ContentWrap> |
| | | |
| | | <!-- 列表 --> |
| | | <ContentWrap> |
| | | <el-table v-loading="loading" :data="list"> |
| | | <el-table-column label="分组编号" align="center" prop="code" /> |
| | | <el-table-column label="分组名称" align="center" prop="name" /> |
| | | <el-table-column label="分组图标" align="center" prop="logo"> |
| | | <template #default="scope"> |
| | | <img width="40px" height="40px" :src="scope.row.icon" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="排序" align="center" prop="sort" /> |
| | | <el-table-column label="备注" align="center" prop="remark" width="200" /> |
| | | <el-table-column |
| | | label="创建时间" |
| | | align="center" |
| | | prop="createTime" |
| | | width="180" |
| | | :formatter="dateFormatter" |
| | | /> |
| | | <el-table-column label="操作" align="center" min-width="110" fixed="right"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | link |
| | | type="primary" |
| | | @click="openForm('update', scope.row.id)" |
| | | v-hasPermi="['system:app-group:update']" |
| | | > |
| | | 编辑 |
| | | </el-button> |
| | | <el-button |
| | | link |
| | | type="danger" |
| | | @click="handleDelete(scope.row.id)" |
| | | v-hasPermi="['system:app-group:delete']" |
| | | > |
| | | 删除 |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <!-- 分页 --> |
| | | <Pagination |
| | | :total="total" |
| | | v-model:page="queryParams.pageNo" |
| | | v-model:limit="queryParams.pageSize" |
| | | @pagination="getList" |
| | | /> |
| | | </ContentWrap> |
| | | |
| | | <!-- 表单弹窗:添加/修改 --> |
| | | <AppGroupForm ref="formRef" @success="getList" /> |
| | | |
| | | </template> |
| | | <script lang="ts" setup> |
| | | import {dateFormatter} from '@/utils/formatTime' |
| | | import * as AppGroupApi from '@/api/system/appgroup' |
| | | import AppGroupForm from './AppGroupForm.vue' |
| | | import * as TenantApi from "@/api/system/tenant"; |
| | | |
| | | defineOptions({name: 'SystemAppGroup'}) |
| | | |
| | | const message = useMessage() // 消息弹窗 |
| | | const {t} = useI18n() // 国际化 |
| | | |
| | | const loading = ref(true) // 列表的加载中 |
| | | const total = ref(0) // 列表的总页数 |
| | | const list = ref([]) // 列表的数据 |
| | | const queryParams = reactive({ |
| | | pageNo: 1, |
| | | pageSize: 10, |
| | | code: undefined, |
| | | name: undefined, |
| | | createTime: [] |
| | | }) |
| | | const queryFormRef = ref() // 搜索的表单 |
| | | |
| | | /** 查询列表 */ |
| | | const getList = async () => { |
| | | loading.value = true |
| | | try { |
| | | const data = await AppGroupApi.getAppGroupPage(queryParams) |
| | | list.value = data.list |
| | | total.value = data.total |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | |
| | | /** 搜索按钮操作 */ |
| | | const handleQuery = () => { |
| | | queryParams.pageNo = 1 |
| | | getList() |
| | | } |
| | | |
| | | /** 重置按钮操作 */ |
| | | const resetQuery = () => { |
| | | queryFormRef.value.resetFields() |
| | | handleQuery() |
| | | } |
| | | |
| | | /** 添加/修改操作 */ |
| | | const formRef = ref() |
| | | const openForm = (type: string, id?: number) => { |
| | | formRef.value.open(type, id) |
| | | } |
| | | |
| | | /** 删除按钮操作 */ |
| | | const handleDelete = async (id: number) => { |
| | | try { |
| | | // 删除的二次确认 |
| | | await message.delConfirm() |
| | | // 发起删除 |
| | | await AppGroupApi.deleteAppGroup(id) |
| | | message.success(t('common.delSuccess')) |
| | | // 刷新列表 |
| | | await getList() |
| | | } catch { |
| | | } |
| | | } |
| | | |
| | | /** 初始化 **/ |
| | | onMounted(async () => { |
| | | await getList() |
| | | }) |
| | | |
| | | </script> |
对比新文件 |
| | |
| | | <template> |
| | | <Dialog v-model="dialogVisible" :title="dialogTitle"> |
| | | <el-form |
| | | ref="formRef" |
| | | v-loading="formLoading" |
| | | :model="formData" |
| | | :rules="formRules" |
| | | label-width="100px" |
| | | > |
| | | <el-form-item label="应用名称"> |
| | | <el-tree-select |
| | | v-model="formData.parentId" |
| | | :data="appMenuTree" |
| | | :default-expanded-keys="[0]" |
| | | :props="defaultProps" |
| | | check-strictly |
| | | node-key="id" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="菜单名称" prop="name"> |
| | | <el-input v-model="formData.name" clearable placeholder="请输入菜单名称" /> |
| | | </el-form-item> |
| | | <el-form-item label="菜单类型" prop="type"> |
| | | <el-radio-group v-model="formData.type"> |
| | | <el-radio-button |
| | | v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_APP_MENU_TYPE)" |
| | | :key="dict.label" |
| | | :label="dict.value" |
| | | > |
| | | {{ dict.label }} |
| | | </el-radio-button> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | <el-form-item v-if="formData.type !== 3" label="菜单图标"> |
| | | <IconSelect v-model="formData.icon" clearable /> |
| | | </el-form-item> |
| | | <el-form-item v-if="formData.type !== 3" label="路由地址" prop="path"> |
| | | <template #label> |
| | | <Tooltip |
| | | message="访问的路由地址,如:`user`。如需外网地址时,则以 `http(s)://` 开头" |
| | | title="路由地址" |
| | | /> |
| | | </template> |
| | | <el-input v-model="formData.path" clearable placeholder="请输入路由地址" /> |
| | | </el-form-item> |
| | | <el-form-item v-if="formData.type === 2" label="组件地址" prop="component"> |
| | | <el-input v-model="formData.component" clearable placeholder="例如说:system/user/index" /> |
| | | </el-form-item> |
| | | <el-form-item v-if="formData.type === 2" label="组件名字" prop="componentName"> |
| | | <el-input v-model="formData.componentName" clearable placeholder="例如说:SystemUser" /> |
| | | </el-form-item> |
| | | <el-form-item v-if="formData.type !== 1" label="权限标识" prop="permission"> |
| | | <template #label> |
| | | <Tooltip |
| | | message="Controller 方法上的权限字符,如:@PreAuthorize(`@ss.hasPermission('system:user:list')`)" |
| | | title="权限标识" |
| | | /> |
| | | </template> |
| | | <el-input v-model="formData.permission" clearable placeholder="请输入权限标识" /> |
| | | </el-form-item> |
| | | <el-form-item label="显示排序" prop="sort"> |
| | | <el-input-number v-model="formData.sort" :min="0" clearable controls-position="right" /> |
| | | </el-form-item> |
| | | <el-form-item label="菜单状态" prop="status"> |
| | | <el-radio-group v-model="formData.status"> |
| | | <el-radio |
| | | v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" |
| | | :key="dict.label" |
| | | :label="dict.value" |
| | | > |
| | | {{ dict.label }} |
| | | </el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | <el-form-item v-if="formData.type !== 3" label="显示状态" prop="visible"> |
| | | <template #label> |
| | | <Tooltip message="选择隐藏时,路由将不会出现在侧边栏,但仍然可以访问" title="显示状态" /> |
| | | </template> |
| | | <el-radio-group v-model="formData.visible"> |
| | | <el-radio key="true" :label="true" border>显示</el-radio> |
| | | <el-radio key="false" :label="false" border>隐藏</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | <el-form-item v-if="formData.type !== 3" label="总是显示" prop="alwaysShow"> |
| | | <template #label> |
| | | <Tooltip |
| | | message="选择不是时,当该菜单只有一个子菜单时,不展示自己,直接展示子菜单" |
| | | title="总是显示" |
| | | /> |
| | | </template> |
| | | <el-radio-group v-model="formData.alwaysShow"> |
| | | <el-radio key="true" :label="true" border>总是</el-radio> |
| | | <el-radio key="false" :label="false" border>不是</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | <el-form-item v-if="formData.type === 2" label="缓存状态" prop="keepAlive"> |
| | | <template #label> |
| | | <Tooltip |
| | | message="选择缓存时,则会被 `keep-alive` 缓存,必须填写「组件名称」字段" |
| | | title="缓存状态" |
| | | /> |
| | | </template> |
| | | <el-radio-group v-model="formData.keepAlive"> |
| | | <el-radio key="true" :label="true" border>缓存</el-radio> |
| | | <el-radio key="false" :label="false" border>不缓存</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> |
| | | <el-button @click="dialogVisible = false">取 消</el-button> |
| | | </template> |
| | | </Dialog> |
| | | </template> |
| | | <script lang="ts" setup> |
| | | import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' |
| | | import * as MenuApi from '@/api/system/menu' |
| | | import { CACHE_KEY, useCache } from '@/hooks/web/useCache' |
| | | import { CommonStatusEnum, SystemAppMenuTypeEnum } from '@/utils/constants' |
| | | import { defaultProps, handleTree } from '@/utils/tree' |
| | | |
| | | defineOptions({ name: 'SystemAppMenuForm' }) |
| | | |
| | | const { wsCache } = useCache() |
| | | const { t } = useI18n() // 国际化 |
| | | const message = useMessage() // 消息弹窗 |
| | | |
| | | const dialogVisible = ref(false) // 弹窗的是否展示 |
| | | const dialogTitle = ref('') // 弹窗的标题 |
| | | const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 |
| | | const formType = ref('') // 表单的类型:create - 新增;update - 修改 |
| | | const formData = ref({ |
| | | id: undefined, |
| | | name: '', |
| | | permission: '', |
| | | type: SystemAppMenuTypeEnum.DIR, |
| | | sort: Number(undefined), |
| | | parentId: 0, |
| | | path: '', |
| | | icon: '', |
| | | component: '', |
| | | componentName: '', |
| | | status: CommonStatusEnum.ENABLE, |
| | | visible: true, |
| | | keepAlive: true, |
| | | alwaysShow: true |
| | | }) |
| | | const formRules = reactive({ |
| | | name: [{ required: true, message: '菜单名称不能为空', trigger: 'blur' }], |
| | | sort: [{ required: true, message: '菜单顺序不能为空', trigger: 'blur' }], |
| | | path: [{ required: true, message: '路由地址不能为空', trigger: 'blur' }], |
| | | status: [{ required: true, message: '状态不能为空', trigger: 'blur' }] |
| | | }) |
| | | const formRef = ref() // 表单 Ref |
| | | |
| | | /** 打开弹窗 */ |
| | | const open = async (type: string, id?: number, parentId?: number) => { |
| | | dialogVisible.value = true |
| | | dialogTitle.value = t('action.' + type) |
| | | formType.value = type |
| | | resetForm() |
| | | if (parentId) { |
| | | formData.value.parentId = parentId |
| | | } |
| | | // 修改时,设置数据 |
| | | if (id) { |
| | | formLoading.value = true |
| | | try { |
| | | formData.value = await MenuApi.getAppMenu(id) |
| | | } finally { |
| | | formLoading.value = false |
| | | } |
| | | } |
| | | // 获得菜单列表 |
| | | await getTree() |
| | | } |
| | | defineExpose({ open }) // 提供 open 方法,用于打开弹窗 |
| | | |
| | | /** 提交表单 */ |
| | | const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 |
| | | const submitForm = async () => { |
| | | // 校验表单 |
| | | if (!formRef) return |
| | | const valid = await formRef.value.validate() |
| | | if (!valid) return |
| | | // 提交请求 |
| | | formLoading.value = true |
| | | try { |
| | | if ( |
| | | formData.value.type === SystemAppMenuTypeEnum.DIR || |
| | | formData.value.type === SystemAppMenuTypeEnum.MENU |
| | | ) { |
| | | if (!isExternal(formData.value.path)) { |
| | | if (formData.value.parentId === 0 && formData.value.path.charAt(0) !== '/') { |
| | | message.error('路径必须以 / 开头') |
| | | return |
| | | } /*else if (formData.value.parentId !== 0 && formData.value.path.charAt(0) === '/') { |
| | | message.error('路径不能以 / 开头') |
| | | return |
| | | }*/ |
| | | } |
| | | } |
| | | const data = formData.value as unknown as MenuApi.MenuVO |
| | | if (formType.value === 'create') { |
| | | await MenuApi.createAppMenu(data) |
| | | message.success(t('common.createSuccess')) |
| | | } else { |
| | | await MenuApi.updateAppMenu(data) |
| | | message.success(t('common.updateSuccess')) |
| | | } |
| | | dialogVisible.value = false |
| | | // 发送操作成功的事件 |
| | | emit('success') |
| | | } finally { |
| | | formLoading.value = false |
| | | // 清空,从而触发刷新 |
| | | wsCache.delete(CACHE_KEY.ROLE_ROUTERS) |
| | | } |
| | | } |
| | | |
| | | /** 获取下拉框[上级菜单]的数据 */ |
| | | const appMenuTree = ref<Tree[]>([]) // 树形结构 |
| | | const getTree = async () => { |
| | | appMenuTree.value = [] |
| | | const res = await MenuApi.getSimpleAppMenusList() |
| | | let menu: Tree = { id: 0, name: '主应用', children: [] } |
| | | menu.children = handleTree(res) |
| | | appMenuTree.value.push(menu) |
| | | } |
| | | |
| | | /** 重置表单 */ |
| | | const resetForm = () => { |
| | | formData.value = { |
| | | id: undefined, |
| | | name: '', |
| | | permission: '', |
| | | type: SystemAppMenuTypeEnum.DIR, |
| | | sort: Number(undefined), |
| | | parentId: 0, |
| | | path: '', |
| | | icon: '', |
| | | component: '', |
| | | componentName: '', |
| | | status: CommonStatusEnum.ENABLE, |
| | | visible: true, |
| | | keepAlive: true, |
| | | alwaysShow: true |
| | | } |
| | | formRef.value?.resetFields() |
| | | } |
| | | |
| | | /** 判断 path 是不是外部的 HTTP 等链接 */ |
| | | const isExternal = (path: string) => { |
| | | return /^(https?:|mailto:|tel:)/.test(path) |
| | | } |
| | | </script> |
对比新文件 |
| | |
| | | <template> |
| | | <!-- 搜索工作栏 --> |
| | | <ContentWrap> |
| | | <el-form |
| | | ref="queryFormRef" |
| | | :inline="true" |
| | | :model="queryParams" |
| | | class="-mb-15px" |
| | | label-width="68px" |
| | | > |
| | | <el-form-item label="菜单名称" prop="name"> |
| | | <el-input |
| | | v-model="queryParams.name" |
| | | class="!w-240px" |
| | | clearable |
| | | placeholder="请输入菜单名称" |
| | | @keyup.enter="handleQuery" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="状态" prop="status"> |
| | | <el-select |
| | | v-model="queryParams.status" |
| | | class="!w-240px" |
| | | clearable |
| | | placeholder="请选择菜单状态" |
| | | > |
| | | <el-option |
| | | v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" |
| | | :key="dict.value" |
| | | :label="dict.label" |
| | | :value="dict.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button @click="handleQuery"> |
| | | <Icon class="mr-5px" icon="ep:search" /> |
| | | 搜索 |
| | | </el-button> |
| | | <el-button @click="resetQuery"> |
| | | <Icon class="mr-5px" icon="ep:refresh" /> |
| | | 重置 |
| | | </el-button> |
| | | <el-button plain type="danger" @click="toggleExpandAll"> |
| | | <Icon class="mr-5px" icon="ep:sort" /> |
| | | 展开/折叠 |
| | | </el-button> |
| | | <el-button plain @click="refreshMenu"> |
| | | <Icon class="mr-5px" icon="ep:refresh" /> |
| | | 刷新菜单缓存 |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </ContentWrap> |
| | | |
| | | <!-- 列表 --> |
| | | <ContentWrap> |
| | | <el-table |
| | | v-if="refreshTable" |
| | | v-loading="loading" |
| | | :data="list" |
| | | :default-expand-all="isExpandAll" |
| | | row-key="id" |
| | | > |
| | | <el-table-column :show-overflow-tooltip="true" label="菜单名称" prop="name" width="250" /> |
| | | <el-table-column align="center" label="图标" prop="icon" width="100"> |
| | | <template #default="scope"> |
| | | <Icon :icon="scope.row.icon" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="排序" prop="sort" width="60" /> |
| | | <el-table-column :show-overflow-tooltip="true" label="权限标识" prop="permission" /> |
| | | <el-table-column :show-overflow-tooltip="true" label="组件路径" prop="component" /> |
| | | <el-table-column :show-overflow-tooltip="true" label="组件名称" prop="componentName" /> |
| | | <el-table-column label="状态" prop="status" width="80"> |
| | | <template #default="scope"> |
| | | <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column align="center" label="操作"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | v-hasPermi="['system:app-menu:update']" |
| | | link |
| | | type="primary" |
| | | @click="openForm('update', scope.row.id)" |
| | | > |
| | | 修改 |
| | | </el-button> |
| | | <el-button |
| | | v-hasPermi="['system:app-menu:create']" |
| | | link |
| | | type="primary" |
| | | @click="openForm('create', undefined, scope.row.id)" |
| | | > |
| | | 新增 |
| | | </el-button> |
| | | <el-button |
| | | v-hasPermi="['system:app-menu:delete']" |
| | | link |
| | | type="danger" |
| | | @click="handleDelete(scope.row.id)" |
| | | > |
| | | 删除 |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </ContentWrap> |
| | | |
| | | <!-- 表单弹窗:添加/修改 --> |
| | | <AppMenuForm ref="formRef" @success="getList" /> |
| | | </template> |
| | | <script lang="ts" setup> |
| | | import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' |
| | | import { handleTree } from '@/utils/tree' |
| | | import * as MenuApi from '@/api/system/menu' |
| | | import AppMenuForm from './AppMenuForm.vue' |
| | | import { CACHE_KEY, useCache } from '@/hooks/web/useCache' |
| | | |
| | | defineOptions({ name: 'SystemAppMenu' }) |
| | | |
| | | const { wsCache } = useCache() |
| | | const { t } = useI18n() // 国际化 |
| | | const message = useMessage() // 消息弹窗 |
| | | |
| | | const loading = ref(true) // 列表的加载中 |
| | | const list = ref<any>([]) // 列表的数据 |
| | | const queryParams = reactive({ |
| | | name: undefined, |
| | | status: undefined |
| | | }) |
| | | const queryFormRef = ref() // 搜索的表单 |
| | | const isExpandAll = ref(false) // 是否展开,默认全部折叠 |
| | | const refreshTable = ref(true) // 重新渲染表格状态 |
| | | |
| | | /** 查询列表 */ |
| | | const getList = async () => { |
| | | loading.value = true |
| | | try { |
| | | const data = await MenuApi.getAppMenuList(queryParams) |
| | | list.value = handleTree(data) |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | |
| | | /** 搜索按钮操作 */ |
| | | const handleQuery = () => { |
| | | getList() |
| | | } |
| | | |
| | | /** 重置按钮操作 */ |
| | | const resetQuery = () => { |
| | | queryFormRef.value.resetFields() |
| | | handleQuery() |
| | | } |
| | | |
| | | /** 添加/修改操作 */ |
| | | const formRef = ref() |
| | | const openForm = (type: string, id?: number, parentId?: number) => { |
| | | formRef.value.open(type, id, parentId) |
| | | } |
| | | |
| | | /** 展开/折叠操作 */ |
| | | const toggleExpandAll = () => { |
| | | refreshTable.value = false |
| | | isExpandAll.value = !isExpandAll.value |
| | | nextTick(() => { |
| | | refreshTable.value = true |
| | | }) |
| | | } |
| | | |
| | | /** 删除按钮操作 */ |
| | | const handleDelete = async (id: number) => { |
| | | try { |
| | | // 删除的二次确认 |
| | | await message.delConfirm() |
| | | // 发起删除 |
| | | await MenuApi.deleteAppMenu(id) |
| | | message.success(t('common.delSuccess')) |
| | | // 刷新列表 |
| | | await getList() |
| | | } catch {} |
| | | } |
| | | |
| | | /** 刷新菜单缓存按钮操作 */ |
| | | const refreshMenu = async () => { |
| | | try { |
| | | await message.confirm('即将更新缓存刷新浏览器!', '刷新菜单缓存') |
| | | // 清空,从而触发刷新 |
| | | wsCache.delete(CACHE_KEY.USER) |
| | | wsCache.delete(CACHE_KEY.ROLE_ROUTERS) |
| | | // 刷新浏览器 |
| | | location.reload() |
| | | } catch {} |
| | | } |
| | | |
| | | /** 初始化 **/ |
| | | onMounted(() => { |
| | | getList() |
| | | }) |
| | | </script> |