312 lines
8.9 KiB
Plaintext
312 lines
8.9 KiB
Plaintext
<template>
|
||
<div>
|
||
<div class="n-layout-page-header">
|
||
<a-card :bordered="false" title="字典管理">
|
||
可代替后台管理系统,设置的大量枚举值和配置,统一标准化管理,随时修改或增加
|
||
</a-card>
|
||
</div>
|
||
<a-row class="mt-4" :gutter="[16, 16]">
|
||
<a-col :xs="24" :sm="24" :md="24" :lg="6" :xl="6" class="mb-4">
|
||
<a-card :bordered="false">
|
||
<template #title>
|
||
<a-space>
|
||
<a-button type="primary" @click="addDictionary">新建</a-button>
|
||
<a-button type="primary" @click="editDictionary" :disabled="!selectedKey"
|
||
>编辑</a-button
|
||
>
|
||
<a-button type="primary" danger @click="removeDictionary" :disabled="!selectedKey"
|
||
>删除</a-button
|
||
>
|
||
</a-space>
|
||
</template>
|
||
<template #header-extra>
|
||
<a-input type="text" v-model:value="pattern">
|
||
<template #prefix>
|
||
<SearchOutlined />
|
||
</template>
|
||
</a-input>
|
||
</template>
|
||
<a-table :dataSource="treeData" :columns="leftColumns" childrenColumnName="noChildren">
|
||
<template #bodyCell="{ column, record }">
|
||
<template v-if="column.key === 'name'">
|
||
<div class="w-full">
|
||
<div class="text-center" v-if="loading">
|
||
<a-spin size="medium" style="margin-left: auto" />
|
||
</div>
|
||
<a-tree
|
||
v-else
|
||
selectable
|
||
draggable
|
||
v-model:selectedKeys="selectedKeys"
|
||
:fieldNames="{ children: 'children', title: 'label', key: 'key' }"
|
||
:tree-data="[record]"
|
||
:pattern="pattern"
|
||
@select="selectedTree"
|
||
/>
|
||
</div>
|
||
</template>
|
||
</template>
|
||
</a-table>
|
||
</a-card>
|
||
</a-col>
|
||
<a-col :xs="24" :sm="24" :md="24" :lg="18" :xl="18">
|
||
<a-card :bordered="false" class="mb-4 proCard">
|
||
<BasicTable
|
||
:columns="columns"
|
||
:request="loadDataTable"
|
||
:row-key="(row) => row.id"
|
||
ref="tableRef"
|
||
:actionColumn="actionColumn"
|
||
:row-selection="rowSelection"
|
||
:canResize="false"
|
||
>
|
||
<template #tableTitle>
|
||
<a-space>
|
||
<a-input type="text" v-model:value="params.keywords">
|
||
<template #prefix>
|
||
<SearchOutlined />
|
||
</template>
|
||
</a-input>
|
||
<a-button type="primary" @click="reloadTable"> 查询 </a-button>
|
||
<a-button type="primary" :disabled="!selectedKey" @click="addDictionaryValue"
|
||
>新建</a-button
|
||
>
|
||
<a-button
|
||
type="primary"
|
||
danger
|
||
:disabled="!rowKeys.length"
|
||
@click="removeDictionaryValues"
|
||
>删除</a-button
|
||
>
|
||
</a-space>
|
||
</template>
|
||
</BasicTable>
|
||
</a-card>
|
||
</a-col>
|
||
</a-row>
|
||
|
||
<basicModal @register="lightModalRegister" ref="modalRef" @ok="removeOkModal">
|
||
<template #default>
|
||
<p class="text-gray-600" style="padding-left: 35px"
|
||
>您确认要删除,<a-typography-text strong>{{ rowKeysName }} ?</a-typography-text></p
|
||
>
|
||
</template>
|
||
</basicModal>
|
||
|
||
<CreateModal ref="createModalRef" :createType="createType" :isEdit="isEdit" />
|
||
</div>
|
||
</template>
|
||
|
||
<script lang="ts" setup>
|
||
import { ref, reactive, h, onMounted, nextTick, unref } from 'vue';
|
||
import { SearchOutlined } from '@ant-design/icons-vue';
|
||
import { BasicTable, TableAction } from '@/components/Table';
|
||
import { getDictionary, getDictionaryInfo } from '@/api/system/dictionary';
|
||
import { basicModal, useModal } from '@/components/Modal';
|
||
import CreateModal from './CreateModal.vue';
|
||
import { columns } from './columns';
|
||
import { getTreeItem } from '@/utils';
|
||
import { message } from 'ant-design-vue';
|
||
|
||
const createModalRef = ref();
|
||
const tableRef = ref();
|
||
const loading = ref(true);
|
||
const selectedKey = ref('');
|
||
const treeData = ref<any[]>([]);
|
||
const dictionaryValues = ref<any[]>([]);
|
||
const rowKeys = ref<any[]>([]);
|
||
const rowKeysName = ref('');
|
||
const createType = ref(1);
|
||
const isEdit = ref(false);
|
||
const pattern = ref('');
|
||
const selectedKeys = ref([]);
|
||
|
||
const leftColumns = [
|
||
{
|
||
title: 'ID',
|
||
dataIndex: 'id',
|
||
key: 'id',
|
||
},
|
||
{
|
||
title: '字典名称',
|
||
dataIndex: 'name',
|
||
key: 'name',
|
||
},
|
||
];
|
||
|
||
const params = ref({
|
||
pageSize: 10,
|
||
name: 'xiaoMa',
|
||
keywords: '',
|
||
});
|
||
|
||
const rowSelection = {
|
||
onChange: (selectedRowKeys: string[], selectedRows) => {
|
||
rowKeys.value = selectedRows.map((item) => item.id);
|
||
console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
|
||
},
|
||
};
|
||
|
||
const actionColumn = reactive({
|
||
width: 150,
|
||
title: '操作',
|
||
key: 'action',
|
||
fixed: 'right',
|
||
render(record) {
|
||
return h(TableAction as any, {
|
||
style: 'text',
|
||
actions: [
|
||
{
|
||
label: '删除',
|
||
icon: 'ic:outline-delete-outline',
|
||
onClick: removeDictionaryValueOne.bind(null, record),
|
||
},
|
||
{
|
||
label: '编辑',
|
||
onClick: editDictionaryValue.bind(null, record),
|
||
},
|
||
],
|
||
});
|
||
},
|
||
});
|
||
|
||
//左右共用删除确认
|
||
const [
|
||
lightModalRegister,
|
||
{ openModal: lightOpenModal, closeModal: lightCloseModal, setSubLoading: lightSetSubLoading },
|
||
] = useModal({
|
||
title: '删除确认',
|
||
showIcon: true,
|
||
type: 'warning',
|
||
closable: false,
|
||
maskClosable: true,
|
||
width: 380,
|
||
});
|
||
|
||
//新建字典
|
||
function addDictionary() {
|
||
createType.value = 1;
|
||
createModalRef.value.setProps({ title: '添加字典' });
|
||
createModalRef.value.openModal();
|
||
}
|
||
|
||
//新建字典项
|
||
function addDictionaryValue() {
|
||
createType.value = 2;
|
||
createModalRef.value.setProps({ title: '添加字典项' });
|
||
createModalRef.value.openModal();
|
||
}
|
||
|
||
//确认删除
|
||
function removeOkModal() {
|
||
lightCloseModal();
|
||
lightSetSubLoading();
|
||
message.error('抱歉,您没有操作权限');
|
||
}
|
||
|
||
//刷新字典项值列表
|
||
function reloadTable() {
|
||
tableRef.value.reload();
|
||
}
|
||
|
||
//删除字典值
|
||
function openRemoveModal() {
|
||
lightOpenModal();
|
||
}
|
||
|
||
//加载字典项值列表
|
||
const loadDataTable = async (res) => {
|
||
const key = selectedKey.value.length ? selectedKey.value[0] : '';
|
||
const result = await getDictionaryInfo({ ...params.value, key, ...res });
|
||
dictionaryValues.value = result.list;
|
||
return result;
|
||
};
|
||
|
||
//删除字典项
|
||
function removeDictionaryValues() {
|
||
//自行简化,仅为演示
|
||
rowKeysName.value = dictionaryValues.value
|
||
.filter((item) => {
|
||
return rowKeys.value.includes(item.id as number);
|
||
})
|
||
.map((item) => {
|
||
return item.label;
|
||
})
|
||
.join(',');
|
||
openRemoveModal();
|
||
}
|
||
|
||
//删除单个字典项
|
||
function removeDictionaryValueOne(record: Recordable) {
|
||
console.log('点击了删除', record);
|
||
rowKeysName.value = record.label;
|
||
openRemoveModal();
|
||
}
|
||
|
||
//删除字典
|
||
function removeDictionary() {
|
||
//自行简化,仅为演示
|
||
if (!selectedKey.value.length) return;
|
||
const treeItem = getTreeItem(treeData.value, unref(selectedKey)[0]);
|
||
rowKeysName.value = treeItem.label;
|
||
openRemoveModal();
|
||
}
|
||
|
||
//左侧字典选择
|
||
function selectedTree(key: string) {
|
||
selectedKey.value = key.length ? key : '';
|
||
rowKeysName.value = getLabelStr(treeData.value, key);
|
||
reloadTable();
|
||
}
|
||
|
||
//组装label字符串
|
||
function getLabelStr(data: any[], key: string): string {
|
||
return data
|
||
.filter((item) => {
|
||
return key.includes(item.key);
|
||
})
|
||
.map((item) => {
|
||
return item.label;
|
||
})
|
||
.join(',');
|
||
}
|
||
|
||
//编辑字典项
|
||
function editDictionaryValue(record: Recordable) {
|
||
console.log('点击了编辑', record);
|
||
createModalRef.value.openModal();
|
||
nextTick(() => {
|
||
isEdit.value = true;
|
||
createModalRef.value.setProps({ title: '编辑字典项' });
|
||
createModalRef.value.setFieldsValue({
|
||
...unref(record),
|
||
});
|
||
});
|
||
}
|
||
|
||
//编辑字典
|
||
function editDictionary() {
|
||
if (!selectedKey.value.length) return;
|
||
const treeItem = getTreeItem(treeData.value, unref(selectedKey)[0]);
|
||
createModalRef.value.openModal();
|
||
nextTick(() => {
|
||
isEdit.value = true;
|
||
createModalRef.value.setProps({ title: '编辑字典' });
|
||
createModalRef.value.setFieldsValue({
|
||
...unref(treeItem),
|
||
});
|
||
});
|
||
}
|
||
|
||
//初始化数据
|
||
async function init() {
|
||
const res = await getDictionary();
|
||
treeData.value = res;
|
||
loading.value = false;
|
||
}
|
||
|
||
onMounted(() => {
|
||
init();
|
||
});
|
||
</script>
|