优化更新

This commit is contained in:
2026-02-11 17:13:18 +08:00
parent ada5e027fa
commit e265bcc28d
28 changed files with 1661 additions and 155 deletions
@@ -12,14 +12,12 @@
</div>
<div class="actions">
<a-space size="small">
<a-tooltip title="展开全部">
<a-button type="text" size="small" @click="handleExpandAll">
<template #icon><UnorderedListOutlined /></template>
</a-button>
</a-tooltip>
<a-tooltip title="折叠全部">
<a-button type="text" size="small" @click="handleCollapseAll">
<template #icon><OrderedListOutlined /></template>
<a-tooltip :title="isAllExpanded ? '折叠全部' : '展开全部'">
<a-button type="text" size="small" @click="handleToggleExpand">
<template #icon>
<UnorderedListOutlined v-if="!isAllExpanded" />
<OrderedListOutlined v-else />
</template>
</a-button>
</a-tooltip>
<a-tooltip title="添加根权限">
@@ -43,7 +41,6 @@
checkable
:check-strictly="false"
:expand-on-click-node="false"
block-node
@select="onMenuSelect"
@check="onMenuCheck">
<template #icon="{ dataRef }">
@@ -81,6 +78,25 @@
<template #icon><DeleteOutlined /></template>
批量删除 ({{ checkedMenuKeys.length }})
</a-button>
<a-dropdown>
<a-button type="link" size="small">
<template #icon><MoreOutlined /></template>
更多
</a-button>
<template #overlay>
<a-menu>
<a-menu-item @click="handleImport">
<ImportOutlined />导入权限
</a-menu-item>
<a-menu-item @click="handleExport">
<ExportOutlined />导出权限
</a-menu-item>
<a-menu-item @click="handleDownloadTemplate">
<DownloadOutlined />下载模板
</a-menu-item>
</a-menu>
</template>
</a-dropdown>
<a-button type="link" size="small" @click="handleRefresh">
<template #icon><ReloadOutlined /></template>
刷新
@@ -96,6 +112,15 @@
</div>
</div>
</div>
<!-- 导入权限弹窗 -->
<sc-import v-model:open="dialog.import" title="导入权限" :api="authApi.permissions.import.post"
:template-api="authApi.permissions.downloadTemplate.get" filename="权限" @success="handleImportSuccess" />
<!-- 导出权限弹窗 -->
<sc-export v-model:open="dialog.export" title="导出权限" :api="handleExportApi"
:default-filename="`权限列表_${Date.now()}`" :show-options="false" tip="导出当前选中或所有权限数据"
@success="handleExportSuccess" />
</template>
<script setup>
@@ -112,9 +137,16 @@ import {
UnorderedListOutlined,
OrderedListOutlined,
DeleteOutlined,
StopOutlined
StopOutlined,
ImportOutlined,
ExportOutlined,
DownloadOutlined,
MoreOutlined
} from '@ant-design/icons-vue'
import { computed } from 'vue'
import saveForm from './components/SaveForm.vue'
import scImport from '@/components/scImport/index.vue'
import scExport from '@/components/scExport/index.vue'
import authApi from '@/api/auth'
defineOptions({
@@ -137,9 +169,30 @@ const parentId = ref(null)
const loading = ref(false)
const detailLoading = ref(false)
// 对话框状态
const dialog = ref({
import: false,
export: false
})
// 树引用
const treeRef = ref()
// 是否全部展开
const isAllExpanded = computed(() => {
const allKeys = getAllKeys(filteredMenuTree.value)
return allKeys.length > 0 && expandedKeys.value.length === allKeys.length
})
// 切换展开/折叠
const handleToggleExpand = () => {
if (isAllExpanded.value) {
handleCollapseAll()
} else {
handleExpandAll()
}
}
// 加载权限树
const loadMenuTree = async () => {
try {
@@ -363,6 +416,52 @@ const handleSaveSuccess = async () => {
message.success('保存成功')
}
// 导出权限
const handleExport = () => {
dialog.value.export = true
}
// 导出API封装
const handleExportApi = async () => {
return await authApi.permissions.export.post({
ids: checkedMenuKeys.value.length > 0 ? checkedMenuKeys.value : undefined
})
}
// 导出成功回调
const handleExportSuccess = () => {
checkedMenuKeys.value = []
}
// 导入权限
const handleImport = () => {
dialog.value.import = true
}
// 导入成功回调
const handleImportSuccess = () => {
loadMenuTree()
}
// 下载模板
const handleDownloadTemplate = async () => {
try {
const blob = await authApi.permissions.downloadTemplate.get()
const url = window.URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.download = '权限导入模板.xlsx'
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
window.URL.revokeObjectURL(url)
message.success('下载成功')
} catch (error) {
console.error('下载模板失败:', error)
message.error('下载失败')
}
}
// 初始化
onMounted(() => {
loadMenuTree()
@@ -401,8 +500,11 @@ defineExpose({
background: transparent;
.ant-tree-node-content-wrapper {
padding: 4px 0;
padding: 2px 4px;
transition: background-color 0.2s;
display: flex;
align-items: center;
min-height: 28px;
&:hover {
background-color: #f5f5f5;
@@ -411,22 +513,37 @@ defineExpose({
.ant-tree-switcher {
color: rgba(0, 0, 0, 0.45);
display: flex;
align-items: center;
min-width: 20px;
}
.ant-tree-iconEle {
margin-right: 6px;
margin-right: 4px;
flex-shrink: 0;
display: flex;
align-items: center;
}
.ant-tree-title {
display: flex;
align-items: center;
flex: 1;
min-width: 0;
}
}
.tree-node-content {
display: inline-flex;
display: flex;
align-items: center;
gap: 6px;
flex-wrap: wrap;
gap: 4px;
max-width: 100%;
.tree-node-title {
font-size: 14px;
font-size: 13px;
color: #262626;
flex-shrink: 0;
line-height: 1.4;
}
.tree-node-code {
@@ -434,14 +551,17 @@ defineExpose({
font-size: 11px;
background: #f0f0f0;
border: none;
padding: 1px 6px;
padding: 0 4px;
border-radius: 2px;
color: #595959;
flex-shrink: 0;
margin-right: 2px;
}
.tree-node-disabled {
color: #ff4d4f;
margin-left: 4px;
font-size: 12px;
flex-shrink: 0;
}
}