Industrial-image-management.../src/views/system/menu/index.vue

249 lines
8.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<GiPageLayout>
<GiTable
ref="tableRef"
row-key="id"
:data="dataList"
:columns="columns"
:loading="loading"
:scroll="{ x: '100%', y: '100%', minWidth: 1700 }"
:pagination="false"
:disabled-column-keys="['title']"
@refresh="search"
>
<template #expand-icon="{ expanded }">
<IconDown v-if="expanded" />
<IconRight v-else />
</template>
<template #toolbar-left>
<a-input v-model="queryForm.menuName" placeholder="搜索菜单名称" allow-clear @change="handleSearch">
<template #prefix><icon-search /></template>
</a-input>
<a-button @click="reset">
<template #icon><icon-refresh /></template>
<template #default>重置</template>
</a-button>
</template>
<template #toolbar-right>
<a-button v-permission="['system:menu:create']" type="primary" @click="onAdd()">
<template #icon><icon-plus /></template>
<template #default>新增</template>
</a-button>
<a-button v-permission="['system:menu:clearCache']" type="outline" status="warning" @click="onClearCache">
<template #icon><icon-delete /></template>
<template #default>清除缓存</template>
</a-button>
<a-button @click="onExpanded">
<template #icon>
<icon-list v-if="isExpanded" />
<icon-mind-mapping v-else />
</template>
<template #default>
<span v-if="!isExpanded">展开</span>
<span v-else>折叠</span>
</template>
</a-button>
</template>
<template #menuName="{ record }">
<GiSvgIcon :name="(record as any).icon" :size="15" />
<span style="margin-left: 5px; vertical-align: middle">{{ (record as any).menuName || (record as any).title }}</span>
</template>
<template #menuType="{ record }">
<a-tag :color="getMenuTypeColor((record as any).menuType || (record as any).type)" size="small">
{{ getMenuTypeLabel((record as any).menuType || (record as any).type) }}
</a-tag>
</template>
<template #visible="{ record }">
<a-tag :color="getMenuVisibleColor((record as any).visible)" size="small">
{{ getMenuVisibleLabel((record as any).visible) }}
</a-tag>
</template>
<template #isExternal="{ record }">
<a-tag v-if="record.isExternal" color="arcoblue" size="small">是</a-tag>
<a-tag v-else color="red" size="small">否</a-tag>
</template>
<template #isHidden="{ record }">
<a-tag v-if="record.isHidden" color="arcoblue" size="small">是</a-tag>
<a-tag v-else color="red" size="small">否</a-tag>
</template>
<template #isCache="{ record }">
<a-tag v-if="record.isCache" color="arcoblue" size="small">是</a-tag>
<a-tag v-else color="red" size="small">否</a-tag>
</template>
<template #action="{ record }">
<a-space>
<a-link v-permission="['system:menu:update']" title="修改" @click="onUpdate(record)">修改</a-link>
<a-link v-permission="['system:menu:delete']" status="danger" title="删除" @click="onDelete(record)">删除</a-link>
<a-link
v-permission="['system:menu:create']"
:disabled="!canAddSubMenu((record as any).menuType || (record as any).type)"
:title="!canAddSubMenu((record as any).menuType || (record as any).type) ? '不可添加下级菜单' : '新增'"
@click="onAdd((record as any).menuId || (record as any).id)"
>
新增
</a-link>
</a-space>
</template>
</GiTable>
<MenuAddModal ref="MenuAddModalRef" @save-success="search" />
</GiPageLayout>
</template>
<script setup lang="ts">
import type { TableInstance } from '@arco-design/web-vue'
import { Message, Modal } from '@arco-design/web-vue'
import MenuAddModal from './MenuAddModal.vue'
import { type MenuTreeQuery, type MenuResp, clearMenuCache, deleteMenu, getMenuTree } from '@/apis/system/menu'
import type GiTable from '@/components/GiTable/index.vue'
import { useTable } from '@/hooks'
import { isMobile } from '@/utils'
import has from '@/utils/has'
defineOptions({ name: 'SystemMenu' })
const queryForm = reactive<MenuTreeQuery>({})
const {
tableData,
loading,
search,
handleDelete,
} = useTable(() => getMenuTree(queryForm), { immediate: true })
const dataList = computed(() => tableData.value)
// 菜单类型显示映射
const getMenuTypeLabel = (type: any): string => {
// 支持新API的字符串格式和旧API的数字格式
const typeMap: Record<string | number, string> = {
'catalog': '目录',
'route': '菜单',
'button': '按钮',
1: '目录',
2: '菜单',
3: '按钮'
}
return typeMap[type] || String(type)
}
// 菜单类型颜色映射
const getMenuTypeColor = (type: any): string => {
// 支持新API的字符串格式和旧API的数字格式
const colorMap: Record<string | number, string> = {
'catalog': 'arcoblue',
'route': 'green',
'button': 'orange',
1: 'arcoblue',
2: 'green',
3: 'orange'
}
return colorMap[type] || 'gray'
}
// 判断是否可以添加子菜单(只有目录和菜单可以添加子项)
const canAddSubMenu = (type: any): boolean => {
return ['catalog', 'route', 1, 2].includes(type)
}
// 菜单可见性状态显示映射
const getMenuVisibleLabel = (visible: any): string => {
// 根据API文档visible字段 '0'表示隐藏,'1'表示显示
if (visible === '0' || visible === 0 || visible === false) {
return '隐藏'
}
if (visible === '1' || visible === 1 || visible === true) {
return '显示'
}
return String(visible) || '未知'
}
// 菜单可见性状态颜色映射
const getMenuVisibleColor = (visible: any): string => {
// 显示状态为绿色,隐藏状态为红色
if (visible === '0' || visible === 0 || visible === false) {
return 'red' // 隐藏状态用红色
}
if (visible === '1' || visible === 1 || visible === true) {
return 'green' // 显示状态用绿色
}
return 'gray'
}
const columns: TableInstance['columns'] = [
{ title: '菜单标题', dataIndex: 'menuName', slotName: 'menuName', width: 170, fixed: !isMobile() ? 'left' : undefined },
{ title: '类型', dataIndex: 'menuType', slotName: 'menuType', align: 'center' },
{ title: '状态', dataIndex: 'visible', slotName: 'visible', align: 'center' },
{ title: '排序', dataIndex: 'orderNum', align: 'orderNum', show: false },
{
title: '操作',
dataIndex: 'action',
slotName: 'action',
width: 160,
align: 'center',
fixed: !isMobile() ? 'right' : undefined,
show: has.hasPermOr(['system:menu:update', 'system:menu:delete', 'system:menu:create']),
},
]
// 处理搜索
const handleSearch = () => {
search()
}
// 重置
const reset = () => {
queryForm.menuName = ''
queryForm.terminalType = ''
search()
}
// 删除
const onDelete = (record: any) => {
// 适配新旧API字段名差异
const menuId = record.menuId || record.id
const menuTitle = record.menuName || record.title
return handleDelete(() => deleteMenu(menuId), {
content: `是否确定删除菜单「${menuTitle}」?`,
showModal: true,
})
}
// 清除缓存
const onClearCache = () => {
Modal.warning({
title: '提示',
content: `是否确定清除全部菜单缓存?`,
hideCancel: false,
maskClosable: false,
onOk: async () => {
await clearMenuCache()
Message.success('清除成功')
},
})
}
const isExpanded = ref(false)
const tableRef = ref<InstanceType<typeof GiTable>>()
// 展开/折叠
const onExpanded = () => {
isExpanded.value = !isExpanded.value
tableRef.value?.tableRef?.expandAll(isExpanded.value)
}
const MenuAddModalRef = ref<InstanceType<typeof MenuAddModal>>()
// 新增
const onAdd = (parentId?: string) => {
MenuAddModalRef.value?.onAdd(parentId)
}
// 修改
const onUpdate = (record: any) => {
// 适配新旧API字段名差异
const menuId = record.menuId || record.id
MenuAddModalRef.value?.onUpdate(menuId)
}
</script>
<style scoped lang="scss"></style>