|
|
@@ -1,347 +1,182 @@
|
|
|
<template>
|
|
|
- <PageWrapper>
|
|
|
- <el-row :gutter="24">
|
|
|
- <el-col :span="8" class="mb-4">
|
|
|
- <el-card title="字典类型" :bordered="false">
|
|
|
- <template #header>
|
|
|
- <div class="flex justify-between">
|
|
|
- <h4>字典类型</h4>
|
|
|
- <div class="flex">
|
|
|
- <el-input
|
|
|
- clearable
|
|
|
- :style="{ width: '80%' }"
|
|
|
- v-model="leftParams.dictName"
|
|
|
- @keyup.enter="leftReloadTable"
|
|
|
- placeholder="请输入字典名称"
|
|
|
- />
|
|
|
- <el-button type="primary" @click="leftReloadTable" class="ml-2">
|
|
|
- <template #icon>
|
|
|
- <el-icon>
|
|
|
- <SearchOutlined />
|
|
|
- </el-icon>
|
|
|
- </template>
|
|
|
- 查询
|
|
|
- </el-button>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </template>
|
|
|
- <BasicTable
|
|
|
- :columns="leftColumns"
|
|
|
- :request="leftLoadDataTable"
|
|
|
- :row-key="(row) => row.dictId"
|
|
|
- ref="leftTableRef"
|
|
|
- :actionColumn="leftActionColumn"
|
|
|
- @update:checked-row-keys="onCheckedRow"
|
|
|
- >
|
|
|
- <template #tableTitle>
|
|
|
- <el-space>
|
|
|
- <el-button type="primary" @click="addDictType">
|
|
|
- <template #icon>
|
|
|
- <el-icon>
|
|
|
- <FileAddOutlined />
|
|
|
- </el-icon>
|
|
|
- </template>
|
|
|
- 添加
|
|
|
- </el-button>
|
|
|
- </el-space>
|
|
|
- </template>
|
|
|
- </BasicTable>
|
|
|
- </el-card>
|
|
|
- </el-col>
|
|
|
- <el-col :span="16">
|
|
|
- <el-card :bordered="false" class="mb-4 proCard">
|
|
|
- <BasicTable
|
|
|
- :columns="rightColumn"
|
|
|
- :request="loadDataTable"
|
|
|
- :row-key="(row) => row.dictCode"
|
|
|
- ref="rightTableRef"
|
|
|
- :actionColumn="actionColumn"
|
|
|
- >
|
|
|
- <template #tableTitle>
|
|
|
- <el-space>
|
|
|
- <el-input
|
|
|
- clearable
|
|
|
- :style="{ width: '80%' }"
|
|
|
- v-model="rightParams.dictLabel"
|
|
|
- @keyup.enter="rightReloadTable"
|
|
|
- placeholder="请输入字典名称"
|
|
|
- />
|
|
|
- <el-button type="primary" @click="rightReloadTable">
|
|
|
- <template #icon>
|
|
|
- <el-icon>
|
|
|
- <SearchOutlined />
|
|
|
- </el-icon>
|
|
|
- </template>
|
|
|
- 查询
|
|
|
- </el-button>
|
|
|
- <el-button type="primary" @click="addDictData">
|
|
|
- <template #icon>
|
|
|
- <el-icon>
|
|
|
- <FileAddOutlined />
|
|
|
- </el-icon>
|
|
|
- </template>
|
|
|
- 添加
|
|
|
- </el-button>
|
|
|
- </el-space>
|
|
|
- </template>
|
|
|
- </BasicTable>
|
|
|
- </el-card>
|
|
|
- </el-col>
|
|
|
- </el-row>
|
|
|
- <!-- 添加/编辑 字典 -->
|
|
|
- <AddDictType ref="addDictTypeRef" :title="addDictTypeTitle" @change="leftReloadTable()" />
|
|
|
- <!-- 添加/编辑 字典项 -->
|
|
|
- <AddDictData ref="addDictDataRef" :title="addDictDataTitle" @change="rightReloadTable()" />
|
|
|
- </PageWrapper>
|
|
|
+ <div class="dictionary-container">
|
|
|
+ <div class="table-operations">
|
|
|
+ <el-button type="primary" @click="handleAddDialogShow">新增字典</el-button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <el-table v-loading="loading" height="calc(100vh - 220px)" :data="dataSource" style="width: 100%" border>
|
|
|
+ <!-- <el-table-column prop="id" label="序号" /> -->
|
|
|
+ <el-table-column prop="dictName" label="字典名称" />
|
|
|
+ <el-table-column prop="dictCode" label="字典编码" />
|
|
|
+ <el-table-column prop="description" label="字典描述" show-overflow-tooltip />
|
|
|
+ <el-table-column prop="dictType" label="分类" width="180">
|
|
|
+ <template #default="{ row }">
|
|
|
+ {{ typeLabelMap[row.dictType] || '' }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="status" label="状态" width="180">
|
|
|
+ <template #default="{ row }">
|
|
|
+ {{ statusLabelMap[row.status] || '' }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="操作" width="200" fixed="right">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <el-button type="primary" link @click="handleEdit(row)">编辑</el-button>
|
|
|
+ <el-button type="danger" link @click="handleDelete(row)">删除</el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+
|
|
|
+ <div class="pagination-container">
|
|
|
+ <el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize" :page-sizes="[10, 20, 50, 100]"
|
|
|
+ :total="totalPage" layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange"
|
|
|
+ @current-change="handleCurrentChange" />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <AddDict v-if="dialogVisible" ref="addDictRef" @close="closeAddDialog" @submit="handleSubmit"
|
|
|
+ :dictCode="currentDictCode" />
|
|
|
+ </div>
|
|
|
</template>
|
|
|
|
|
|
<script lang="ts" setup>
|
|
|
- import { ref, reactive, h, onMounted, nextTick, unref } from 'vue';
|
|
|
- import { BasicTable, TableAction } from '@/components/Table';
|
|
|
- import { dictTypeList, dictInfo, delDictType, delDictData } from '@/api/system/dictionary';
|
|
|
- import AddDictType from './components/AddDictType.vue';
|
|
|
- import AddDictData from './components/AddDictData.vue';
|
|
|
- import { PageWrapper } from '@/components/Page';
|
|
|
-
|
|
|
- import { ElMessage, ElCheckbox, ElTag } from 'element-plus';
|
|
|
- import { FileAddOutlined, SearchOutlined } from '@vicons/antd';
|
|
|
-
|
|
|
- const message = ElMessage;
|
|
|
- const leftTableRef = ref();
|
|
|
- const rightTableRef = ref();
|
|
|
- const dictTableList = ref<any[]>([]);
|
|
|
- const rowKeys = ref<any[]>([]);
|
|
|
- const rowKeysName = ref('');
|
|
|
- const isEdit = ref(false);
|
|
|
- const dictTypeTableList = ref();
|
|
|
- const dictType = ref('');
|
|
|
- const addDictTypeRef = ref();
|
|
|
- const addDictDataRef = ref();
|
|
|
- const addDictTypeTitle = ref('添加字典');
|
|
|
- const addDictDataTitle = ref('添加字典项');
|
|
|
-
|
|
|
- const leftParams = ref({
|
|
|
- dictName: '',
|
|
|
- });
|
|
|
-
|
|
|
- const rightParams = ref({
|
|
|
- dictLabel: '',
|
|
|
+ import { ref, reactive, onMounted, computed } from 'vue';
|
|
|
+ import { ElMessage, ElMessageBox, FormInstance } from 'element-plus';
|
|
|
+ import AddDict from './components/AddDict.vue';
|
|
|
+ import { queryDictPageApi, createDictApi, SaveDictParams, updateDict, deleteDict } from '@/api/dict';
|
|
|
+ import { useDataSource } from './useDataSource';
|
|
|
+ import { dictionaryStatusOptions, dictionaryTypeOptions } from './constants'
|
|
|
+
|
|
|
+ // 表格数据
|
|
|
+ const loading = ref(false);
|
|
|
+
|
|
|
+ const { dataSource, getDataSource, pageSize, currentPage, totalPage } = useDataSource();
|
|
|
+
|
|
|
+ onMounted(() => {
|
|
|
+ getDataSource();
|
|
|
});
|
|
|
+ // 搜索
|
|
|
+ function handleSearch() {
|
|
|
+ currentPage.value = 1;
|
|
|
+ getDataSource();
|
|
|
+ }
|
|
|
|
|
|
- const leftColumns = [
|
|
|
- {
|
|
|
- fixed: 'left',
|
|
|
- width: 60,
|
|
|
- render(record) {
|
|
|
- return h(ElCheckbox, {
|
|
|
- modelValue: dictType.value === record.row.dictType,
|
|
|
- onChange() {
|
|
|
- dictType.value = record.row.dictType;
|
|
|
- rightTableRef.value.reload();
|
|
|
- },
|
|
|
- });
|
|
|
- },
|
|
|
- },
|
|
|
- {
|
|
|
- label: '字典名称',
|
|
|
- prop: 'dictName',
|
|
|
- },
|
|
|
- {
|
|
|
- label: '字典类型',
|
|
|
- prop: 'dictType',
|
|
|
- },
|
|
|
- ];
|
|
|
-
|
|
|
- const leftActionColumn = reactive({
|
|
|
- width: 140,
|
|
|
- label: '操作',
|
|
|
- prop: 'action',
|
|
|
- fixed: 'right',
|
|
|
- align: 'center',
|
|
|
- render(record) {
|
|
|
- return h(TableAction as any, {
|
|
|
- actions: [
|
|
|
- {
|
|
|
- label: '删除',
|
|
|
- isConfirm: true,
|
|
|
- popConfirm: {
|
|
|
- onConfirm: removeDictType.bind(null, record.row),
|
|
|
- title: `您确定要删除【${record.row.dictName}】吗?`,
|
|
|
- width: 300,
|
|
|
- confirmButtonText: '确定',
|
|
|
- cancelButtonText: '取消',
|
|
|
- },
|
|
|
- },
|
|
|
- {
|
|
|
- label: '编辑',
|
|
|
- onClick: editDictType.bind(null, record.row),
|
|
|
- },
|
|
|
- ],
|
|
|
- });
|
|
|
- },
|
|
|
- });
|
|
|
+ // 分页相关
|
|
|
+ function handleSizeChange(val: number) {
|
|
|
+ pageSize.value = val;
|
|
|
+ getDataSource();
|
|
|
+ }
|
|
|
|
|
|
- const rightColumn = [
|
|
|
- {
|
|
|
- label: '字典项名称',
|
|
|
- prop: 'dictLabel',
|
|
|
- },
|
|
|
- {
|
|
|
- label: '字典项值',
|
|
|
- prop: 'dictValue',
|
|
|
- },
|
|
|
- {
|
|
|
- label: '排序',
|
|
|
- prop: 'dictSort',
|
|
|
- },
|
|
|
- {
|
|
|
- label: '状态',
|
|
|
- prop: 'status',
|
|
|
- render(record) {
|
|
|
- return h(
|
|
|
- ElTag,
|
|
|
- {
|
|
|
- type: record.row.status === '0' ? 'success' : 'danger',
|
|
|
- },
|
|
|
- {
|
|
|
- default: () => (record.row.status === '0' ? '正常' : '停用'),
|
|
|
- },
|
|
|
- );
|
|
|
- },
|
|
|
- },
|
|
|
- {
|
|
|
- label: '创建时间',
|
|
|
- prop: 'createTime',
|
|
|
- },
|
|
|
- ];
|
|
|
+ function handleCurrentChange(val: number) {
|
|
|
+ currentPage.value = val;
|
|
|
+ getDataSource();
|
|
|
+ }
|
|
|
|
|
|
- const actionColumn = reactive({
|
|
|
- width: 140,
|
|
|
- label: '操作',
|
|
|
- prop: 'action',
|
|
|
- fixed: 'right',
|
|
|
- align: 'center',
|
|
|
- render(record) {
|
|
|
- return h(TableAction as any, {
|
|
|
- actions: [
|
|
|
- {
|
|
|
- label: '删除',
|
|
|
- isConfirm: true,
|
|
|
- popConfirm: {
|
|
|
- onConfirm: removeDictData.bind(null, record.row),
|
|
|
- title: `您确定要删除【${record.row.dictLabel}】吗?`,
|
|
|
- width: 300,
|
|
|
- confirmButtonText: '确定',
|
|
|
- cancelButtonText: '取消',
|
|
|
- },
|
|
|
- },
|
|
|
- {
|
|
|
- label: '编辑',
|
|
|
- onClick: editDictData.bind(null, record.row),
|
|
|
- },
|
|
|
- ],
|
|
|
- });
|
|
|
- },
|
|
|
- });
|
|
|
+ // 表单相关
|
|
|
+ const dialogVisible = ref(false);
|
|
|
+ const dialogTitle = ref('新增字典');
|
|
|
+ const addDictRef = ref<InstanceType<typeof AddDict>>();
|
|
|
+ const currentDictCode = ref('');
|
|
|
+
|
|
|
+ const formRules = {
|
|
|
+ name: [
|
|
|
+ { required: true, message: '请输入字典名称', trigger: 'blur' },
|
|
|
+ { min: 2, max: 50, message: '长度在 2 到 50 个字符', trigger: 'blur' },
|
|
|
+ ],
|
|
|
+ code: [
|
|
|
+ { required: true, message: '请输入字典编码', trigger: 'blur' },
|
|
|
+ { min: 2, max: 50, message: '长度在 2 到 50 个字符', trigger: 'blur' },
|
|
|
+ ],
|
|
|
+ };
|
|
|
|
|
|
- //添加字典类型
|
|
|
- function addDictType() {
|
|
|
- addDictTypeRef.value.openModal();
|
|
|
- nextTick(() => {
|
|
|
- isEdit.value = false;
|
|
|
- addDictTypeRef.value.setProps({ label: '添加字典类型' });
|
|
|
- });
|
|
|
+ // 新增字典
|
|
|
+ function handleAddDialogShow() {
|
|
|
+ dialogVisible.value = true;
|
|
|
+ currentDictCode.value = '';
|
|
|
}
|
|
|
|
|
|
- //删除字典类型
|
|
|
- function removeDictType(record) {
|
|
|
- rowKeysName.value = record.dictName;
|
|
|
- delDictType({ dictId: record.dictId }).then(() => {
|
|
|
- message.success('删除成功');
|
|
|
- leftReloadTable();
|
|
|
- });
|
|
|
+ const closeAddDialog = () => {
|
|
|
+ dialogVisible.value = false;
|
|
|
+ if (addDictRef.value) {
|
|
|
+ addDictRef.value.resetForm();
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // 编辑字典
|
|
|
+ function handleEdit(row: any) {
|
|
|
+ dialogTitle.value = '编辑字典';
|
|
|
+ dialogVisible.value = true;
|
|
|
+ currentDictCode.value = row.dictCode;
|
|
|
}
|
|
|
|
|
|
- //编辑字段类型
|
|
|
- function editDictType(record) {
|
|
|
- addDictTypeRef.value.openModal();
|
|
|
- nextTick(() => {
|
|
|
- isEdit.value = true;
|
|
|
- addDictTypeRef.value.setProps({ title: '编辑字典类型' });
|
|
|
- addDictTypeRef.value.setFieldsValue({
|
|
|
- ...unref(record),
|
|
|
+ // 删除字典
|
|
|
+ async function handleDelete(row: any) {
|
|
|
+ try {
|
|
|
+ await ElMessageBox.confirm('确定要删除这条字典记录吗?', '提示', {
|
|
|
+ type: 'warning',
|
|
|
});
|
|
|
- });
|
|
|
+ await deleteDictionary(row.dictId)
|
|
|
+ } catch {
|
|
|
+ // 用户取消删除
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- //删除字典
|
|
|
- function removeDictData(record) {
|
|
|
- rowKeysName.value = record.dictName;
|
|
|
- delDictData({ dictCode: record.dictCode }).then(() => {
|
|
|
- message.success('删除成功');
|
|
|
- rightReloadTable();
|
|
|
- });
|
|
|
+ // 提交表单
|
|
|
+ async function handleSubmit(formData: SaveDictParams) {
|
|
|
+ if (!addDictRef.value) return;
|
|
|
+ if (formData.dictId) {
|
|
|
+ await updateDictionary(formData)
|
|
|
+ } else {
|
|
|
+ await createDictionary(formData)
|
|
|
+ }
|
|
|
+ dialogVisible.value = false;
|
|
|
+ getDataSource();
|
|
|
}
|
|
|
|
|
|
- //添加字典
|
|
|
- function addDictData() {
|
|
|
- addDictDataRef.value.openModal();
|
|
|
- nextTick(() => {
|
|
|
- isEdit.value = false;
|
|
|
- addDictDataRef.value.setProps({ title: '添加字典项' });
|
|
|
- addDictDataRef.value.setFieldsValue({
|
|
|
- dictType: dictType.value,
|
|
|
- });
|
|
|
+ const createDictionary = (formData: SaveDictParams) => {
|
|
|
+ createDictApi(formData).then((res) => {
|
|
|
+ ElMessage.success('保存成功');
|
|
|
});
|
|
|
- }
|
|
|
+ };
|
|
|
|
|
|
- //编辑字典
|
|
|
- function editDictData(record) {
|
|
|
- addDictDataRef.value.openModal();
|
|
|
- nextTick(() => {
|
|
|
- isEdit.value = true;
|
|
|
- addDictDataRef.value.setProps({ title: '编辑字典项' });
|
|
|
- addDictDataRef.value.setFieldsValue({
|
|
|
- ...unref(record),
|
|
|
- });
|
|
|
- });
|
|
|
+ const updateDictionary = (formData: SaveDictParams) => {
|
|
|
+ updateDict(formData).then((res) => {
|
|
|
+ ElMessage.success('编辑成功');
|
|
|
+ })
|
|
|
}
|
|
|
|
|
|
- //选择字典项
|
|
|
- function onCheckedRow(keys) {
|
|
|
- rowKeys.value = keys;
|
|
|
+ const deleteDictionary = (id: number) => {
|
|
|
+ deleteDict(id).then((res) => {
|
|
|
+ ElMessage.success('删除成功');
|
|
|
+ getDataSource();
|
|
|
+ })
|
|
|
}
|
|
|
|
|
|
- //刷新字典类型
|
|
|
- function leftReloadTable() {
|
|
|
- leftTableRef.value.restReload();
|
|
|
- }
|
|
|
+ const typeLabelMap = computed(() =>
|
|
|
+ Object.fromEntries(dictionaryTypeOptions.map(item => [item.value, item.label]))
|
|
|
+ );
|
|
|
|
|
|
- //刷新字典列表
|
|
|
- function rightReloadTable() {
|
|
|
- rightTableRef.value.restReload();
|
|
|
- }
|
|
|
+ const statusLabelMap = computed(() =>
|
|
|
+ Object.fromEntries(dictionaryStatusOptions.map(item => [item.value, item.label]))
|
|
|
+ );
|
|
|
+
|
|
|
+</script>
|
|
|
|
|
|
- //加载字典项列表
|
|
|
- const leftLoadDataTable = async (res) => {
|
|
|
- const result = await dictTypeList({ ...leftParams.value, ...res });
|
|
|
- dictTypeTableList.value = result.list;
|
|
|
- if (result.list.length) {
|
|
|
- dictType.value = result.list[0].dictType;
|
|
|
- rightReloadTable();
|
|
|
- }
|
|
|
- return result;
|
|
|
- };
|
|
|
+<style lang="scss" scoped>
|
|
|
+ .dictionary-container {
|
|
|
+ padding: 16px;
|
|
|
|
|
|
- //加载字典项值列表
|
|
|
- const loadDataTable = async (res) => {
|
|
|
- if (!dictType.value) return;
|
|
|
- const result = await dictInfo({ dictType: dictType.value, ...rightParams.value, ...res });
|
|
|
- dictTableList.value = result.list;
|
|
|
- return result;
|
|
|
- };
|
|
|
+ .search-form {
|
|
|
+ margin-bottom: 16px;
|
|
|
+ }
|
|
|
|
|
|
- onMounted(() => {});
|
|
|
-</script>
|
|
|
+ .table-operations {
|
|
|
+ margin-bottom: 16px;
|
|
|
+ }
|
|
|
|
|
|
-<style lang="scss" setup></style>
|
|
|
+ .pagination-container {
|
|
|
+ margin-top: 16px;
|
|
|
+ display: flex;
|
|
|
+ justify-content: flex-end;
|
|
|
+ }
|
|
|
+ }
|
|
|
+</style>
|