<script lang="ts" setup>
|
import type { ActionItem, BasicColumn } from '@jnpf/ui/vxeTable';
|
|
import { computed, onMounted, reactive, ref, toRefs, unref } from 'vue';
|
|
import { useMessage } from '@jnpf/hooks';
|
import { BasicLeftTree } from '@jnpf/ui';
|
import { useModal } from '@jnpf/ui/modal';
|
import { BasicVxeTable, TableAction, useVxeTable } from '@jnpf/ui/vxeTable';
|
|
import { DownOutlined } from '@ant-design/icons-vue';
|
|
import { del as delButtonAuthorize, getButtonAuthorizeList, selectActions } from '#/api/system/buttonAuthorize';
|
import { del as delColumnAuthorize, getColumnAuthorizeList } from '#/api/system/columnAuthorize';
|
import { create, del as delDataAuthorize, getDataAuthorizeList } from '#/api/system/dataAuthorize';
|
import { del as delFormAuthorize, getFormAuthorizeList } from '#/api/system/formAuthorize';
|
import { getMenuList } from '#/api/system/menu';
|
import { $t } from '#/locales';
|
|
import ActionAuthForm from './actionAuthorize/Form.vue';
|
import ColumnAuthForm from './columnAuthorize/Form.vue';
|
import ActionModal from './components/ActionModal.vue';
|
import DataAuthForm from './dataAuthorize/Form.vue';
|
import BatchForm from './formAuthorize/BatchForm.vue';
|
import FormAuthForm from './formAuthorize/Form.vue';
|
|
defineOptions({ name: 'PermissionResource' });
|
|
const props = defineProps({
|
isSystem: {
|
type: Boolean,
|
default: true,
|
},
|
});
|
|
interface State {
|
treeData: any[];
|
treeLoading: boolean;
|
tabActiveKey: string;
|
activeKey: number;
|
tableKey: number;
|
searchInfo: any;
|
menuType: any;
|
webType: number;
|
hasPermission: boolean;
|
}
|
|
const state = reactive<State>({
|
treeData: [],
|
treeLoading: false,
|
tabActiveKey: 'Web',
|
activeKey: 0,
|
tableKey: 0,
|
searchInfo: {
|
menuId: '',
|
},
|
menuType: undefined,
|
webType: 0,
|
hasPermission: false,
|
});
|
const { treeData, treeLoading, tabActiveKey, activeKey } = toRefs(state);
|
const { createMessage } = useMessage();
|
const leftTreeRef = ref<Nullable<any>>(null);
|
const tabList = [
|
{ fullName: '动作', id: 0 },
|
{ fullName: '表单字段', id: 1 },
|
{ fullName: '列表字段', id: 2 },
|
{ fullName: '数据权限', id: 3 },
|
];
|
const noPermissionConfigList = new Set([4, 5, 6, 7, 8, 10]); // 4字典、5报表(原)、6大屏、7门户、8外链、9报表
|
const actionColumns: BasicColumn[] = [
|
{ title: '动作名称', dataIndex: 'fullName', minWidth: 200 },
|
{ title: '动作编码', dataIndex: 'enCode', width: 150 },
|
{ title: '状态', dataIndex: 'enabledMark', width: 70, align: 'center', slots: { default: 'enabledMark' } },
|
];
|
const formColumns: BasicColumn[] = [
|
{ title: '数据库表', dataIndex: 'bindTable', width: 180 },
|
{ title: '字段名称', dataIndex: 'enCode', width: 180 },
|
{ title: '字段说明', dataIndex: 'fullName', minWidth: 200 },
|
{ title: '排序', dataIndex: 'sortCode', width: 70, align: 'center' },
|
{ title: '状态', dataIndex: 'enabledMark', width: 70, align: 'center', slots: { default: 'enabledMark' } },
|
];
|
const dataColumns: BasicColumn[] = [
|
{ title: '方案编码', dataIndex: 'enCode', width: 160 },
|
{ title: '方案名称', dataIndex: 'fullName', width: 160 },
|
{ title: '过滤条件', dataIndex: 'conditionText', minWidth: 200 },
|
];
|
const [registerActionTable, { reload: reloadActionTable }] = useVxeTable({ api: getButtonAuthorizeList, columns: actionColumns });
|
const [registerFormTable, { reload: reloadFormTable }] = useVxeTable({ api: getFormAuthorizeList, columns: formColumns });
|
const [registerColumnTable, { reload: reloadColumnTable }] = useVxeTable({ api: getColumnAuthorizeList, columns: formColumns });
|
const [registerDataTable, { reload: reloadDataTable }] = useVxeTable({ api: getDataAuthorizeList, columns: dataColumns });
|
const [registerActionAuthForm, { openModal: openActionAuthFormModal }] = useModal();
|
const [registerFormAuthForm, { openModal: openFormAuthFormModal }] = useModal();
|
const [registerColumnAuthForm, { openModal: openColumnAuthFormModal }] = useModal();
|
const [registerDataAuthForm, { openModal: openDataAuthFormModal }] = useModal();
|
const [registerBatchForm, { openModal: openBatchFormModal }] = useModal();
|
const [registerAction, { openModal: openActionModal }] = useModal();
|
|
const getAlertMessage = computed(() => {
|
if (state.menuType == 1) return '请选择右侧的菜单资源';
|
if (state.menuType == 3 && state.webType === 4) return '视图菜单无权限配置,默认查看该菜单的全部数据和全部字段。';
|
if (!state.hasPermission && !noPermissionConfigList.has(state.menuType))
|
return '该菜单未开启资源的权限控制,默认查看该菜单的全部数据和全部字段。若需要开启,请在表单的“列表设计”中开启!';
|
return '该菜单无可配置的权限资源(报表、大屏、门户、字典、外链类型的菜单无权限资源配置)';
|
});
|
const getTableBindValue = computed(() => ({
|
searchInfo: state.searchInfo,
|
immediate: false,
|
actionColumn: {
|
width: 100,
|
title: '操作',
|
dataIndex: 'action',
|
},
|
tableKey: state.tableKey,
|
}));
|
const getShowAlertStatus = computed(
|
() => noPermissionConfigList.has(state.menuType) || (state.menuType == 3 && (!state.hasPermission || state.webType == 4)) || state.menuType == 1,
|
);
|
const getTabList = computed(() => {
|
if (props.isSystem) return tabList.filter((o) => o.id === 0);
|
if (state.menuType == 9) return tabList.filter((o) => o.id !== 1);
|
return tabList;
|
});
|
|
function initTreeData() {
|
state.treeLoading = true;
|
getMenuList({ category: state.tabActiveKey })
|
.then((res) => {
|
state.treeData = res.data.list || [];
|
state.treeLoading = false;
|
if (!state.treeData.length) return;
|
state.searchInfo.menuId = state.treeData[0]?.id;
|
state.hasPermission = state.treeData[0]?.hasPermission || false;
|
state.menuType = state.treeData[0]?.type;
|
state.webType = state.treeData[0]?.webType;
|
unref(leftTreeRef)?.setSelectedKeys([state.treeData[0]?.id]);
|
setTimeout(() => {
|
reload();
|
}, 100);
|
})
|
.catch(() => {
|
state.treeLoading = false;
|
});
|
}
|
function handleTreeSelect(id, item) {
|
if (id == state.searchInfo.menuId) return;
|
state.searchInfo.menuId = id;
|
state.menuType = item.type;
|
state.webType = item.webType;
|
state.hasPermission = !!item.hasPermission;
|
state.tableKey = Date.now();
|
state.activeKey = 0;
|
onTabChange();
|
}
|
function onTabChange() {
|
setTimeout(() => {
|
reload();
|
}, 10);
|
}
|
function handleAddAction({ key }) {
|
if (key === 0) addOrUpdateHandle();
|
if (key == 1) openActionModal(true, {});
|
}
|
function reload() {
|
if (unref(getShowAlertStatus)) return;
|
if (state.activeKey === 0) reloadActionTable();
|
if (state.activeKey === 1) reloadFormTable();
|
if (state.activeKey === 2) reloadColumnTable();
|
if (state.activeKey === 3) reloadDataTable();
|
}
|
function getTableActions(record): ActionItem[] {
|
return [
|
{
|
label: $t('common.editText'),
|
disabled: record.enCode === 'jnpf_alldata' && state.activeKey == 3,
|
onClick: addOrUpdateHandle.bind(null, record.id),
|
},
|
{
|
label: $t('common.delText'),
|
color: 'error',
|
disabled: record.isMain == 1,
|
modelConfirm: {
|
onOk: handleDelete.bind(null, record.id),
|
},
|
},
|
];
|
}
|
function addOrUpdateHandle(id?) {
|
let openFormModal = openActionAuthFormModal;
|
if (state.activeKey === 1) openFormModal = openFormAuthFormModal;
|
if (state.activeKey === 2) openFormModal = openColumnAuthFormModal;
|
if (state.activeKey === 3) openFormModal = openDataAuthFormModal;
|
openFormModal(true, { id, menuId: state.searchInfo.menuId, type: state.menuType, dataType: 2 });
|
}
|
function handleBatchAdd() {
|
if (state.activeKey !== 1 && state.activeKey !== 2) return;
|
const type = state.activeKey === 1 ? 'form' : 'column';
|
openBatchFormModal(true, { menuId: state.searchInfo.menuId, type });
|
}
|
function handleDelete(id) {
|
let del = delButtonAuthorize;
|
if (state.activeKey === 1) del = delFormAuthorize;
|
if (state.activeKey === 2) del = delColumnAuthorize;
|
if (state.activeKey === 3) del = delDataAuthorize;
|
del(id).then((res) => {
|
createMessage.success(res.msg);
|
reload();
|
});
|
}
|
function onActionChange(ids) {
|
selectActions({ ids, menuId: state.searchInfo.menuId }).then((res) => {
|
createMessage.success(res.msg);
|
reload();
|
});
|
}
|
function handleAdd() {
|
const data = {
|
moduleId: state.searchInfo.menuId,
|
enCode: 'jnpf_alldata',
|
fullName: '全部数据',
|
allData: 1,
|
};
|
create(data).then((res) => {
|
createMessage.success(res.msg);
|
reload();
|
});
|
}
|
function onTabActiveKeyChange() {
|
unref(leftTreeRef)?.clearSearchValue();
|
initTreeData();
|
}
|
|
onMounted(() => {
|
initTreeData();
|
});
|
</script>
|
<template>
|
<div class="jnpf-content-wrapper">
|
<div class="jnpf-content-wrapper-left !w-[260px]" :class="{ 'resource-content-wrapper-left': !isSystem }">
|
<BasicLeftTree
|
:title="isSystem ? '系统菜单' : '应用菜单'"
|
ref="leftTreeRef"
|
:tree-data="treeData"
|
:loading="treeLoading"
|
@select="handleTreeSelect"
|
@reload="onTabActiveKeyChange">
|
<template #headerTitle v-if="!isSystem">
|
<a-tabs v-model:active-key="tabActiveKey" class="jnpf-content-wrapper-tabs" :tab-bar-gutter="10" @change="onTabActiveKeyChange">
|
<a-tab-pane key="Web" tab="Web菜单" />
|
<a-tab-pane key="App" tab="App菜单" />
|
</a-tabs>
|
</template>
|
</BasicLeftTree>
|
</div>
|
<div class="jnpf-content-wrapper-center">
|
<div class="jnpf-content-wrapper-content relative bg-white" v-loading="treeLoading">
|
<div class="flex h-full w-full flex-col" v-if="!treeLoading">
|
<template v-if="treeData.length">
|
<a-alert :message="getAlertMessage" class="m-[10px]" type="warning" show-icon v-if="getShowAlertStatus" />
|
<template v-else>
|
<a-tabs v-model:active-key="activeKey" class="jnpf-content-wrapper-tabs" @change="onTabChange">
|
<a-tab-pane :key="item.id" :tab="item.fullName" v-for="item in getTabList" />
|
</a-tabs>
|
<BasicVxeTable @register="registerActionTable" v-bind="getTableBindValue" v-if="activeKey === 0">
|
<template #tableTitle>
|
<a-dropdown>
|
<template #overlay>
|
<a-menu @click="handleAddAction">
|
<a-menu-item :key="0"><i class="icon-ym icon-ym-btn-add pr-[5px]"></i>新建动作</a-menu-item>
|
<a-menu-item :key="1"> <i class="icon-ym icon-ym icon-ym-generator-user pr-[5px]"></i>选择动作</a-menu-item>
|
</a-menu>
|
</template>
|
<a-button type="primary" pre-icon="icon-ym icon-ym-btn-add">添加动作<DownOutlined /></a-button>
|
</a-dropdown>
|
</template>
|
<template #enabledMark="{ record }">
|
<a-tag :color="record.enabledMark == 1 ? 'success' : 'error'">{{ record.enabledMark == 1 ? '启用' : '禁用' }}</a-tag>
|
</template>
|
<template #action="{ record }">
|
<TableAction :actions="getTableActions(record)" />
|
</template>
|
</BasicVxeTable>
|
<BasicVxeTable @register="registerFormTable" v-bind="getTableBindValue" v-else-if="activeKey === 1">
|
<template #tableTitle>
|
<a-button type="primary" pre-icon="icon-ym icon-ym-btn-add" @click="addOrUpdateHandle()">新建</a-button>
|
<a-button type="link" pre-icon="ym-custom ym-custom-content-copy" @click="handleBatchAdd()">批量新增</a-button>
|
</template>
|
<template #enabledMark="{ record }">
|
<a-tag :color="record.enabledMark == 1 ? 'success' : 'error'">{{ record.enabledMark == 1 ? '启用' : '禁用' }}</a-tag>
|
</template>
|
<template #action="{ record }">
|
<TableAction :actions="getTableActions(record)" />
|
</template>
|
</BasicVxeTable>
|
<BasicVxeTable @register="registerColumnTable" v-bind="getTableBindValue" v-else-if="activeKey === 2">
|
<template #tableTitle>
|
<a-button type="primary" pre-icon="icon-ym icon-ym-btn-add" @click="addOrUpdateHandle()">新建</a-button>
|
<a-button type="link" pre-icon="ym-custom ym-custom-content-copy" @click="handleBatchAdd()">批量新增</a-button>
|
</template>
|
<template #enabledMark="{ record }">
|
<a-tag :color="record.enabledMark == 1 ? 'success' : 'error'">{{ record.enabledMark == 1 ? '启用' : '禁用' }}</a-tag>
|
</template>
|
<template #action="{ record }">
|
<TableAction :actions="getTableActions(record)" />
|
</template>
|
</BasicVxeTable>
|
<BasicVxeTable @register="registerDataTable" v-bind="getTableBindValue" v-else-if="activeKey === 3">
|
<template #tableTitle>
|
<a-button type="primary" pre-icon="icon-ym icon-ym-btn-add" @click="addOrUpdateHandle()">新建</a-button>
|
<a-dropdown>
|
<template #overlay>
|
<a-menu>
|
<a-menu-item @click="handleAdd">全部数据</a-menu-item>
|
</a-menu>
|
</template>
|
<a-button type="link" pre-icon="icon-ym icon-ym-btn-add">常用方案<DownOutlined /></a-button>
|
</a-dropdown>
|
</template>
|
<template #enabledMark="{ record }">
|
<a-tag :color="record.enabledMark == 1 ? 'success' : 'error'">{{ record.enabledMark == 1 ? '启用' : '禁用' }}</a-tag>
|
</template>
|
<template #action="{ record }">
|
<TableAction :actions="getTableActions(record)" />
|
</template>
|
</BasicVxeTable>
|
</template>
|
</template>
|
<jnpf-empty class="mt-[150px]" v-else />
|
</div>
|
</div>
|
</div>
|
<ActionAuthForm @register="registerActionAuthForm" @reload="reload" />
|
<FormAuthForm @register="registerFormAuthForm" @reload="reload" />
|
<ColumnAuthForm @register="registerColumnAuthForm" @reload="reload" />
|
<DataAuthForm @register="registerDataAuthForm" @reload="reload" />
|
<BatchForm @register="registerBatchForm" @reload="reload" />
|
<ActionModal @register="registerAction" @change="onActionChange" />
|
</div>
|
</template>
|