275 lines
7.3 KiB
Vue
275 lines
7.3 KiB
Vue
<template>
|
|
<a-drawer
|
|
:open="visible"
|
|
:title="`字典项管理 - ${dictData?.name || ''}`"
|
|
width="800"
|
|
:destroyOnClose="true"
|
|
@close="handleClose"
|
|
>
|
|
<div class="drawer-content">
|
|
<!-- 字典项操作栏 -->
|
|
<div class="item-toolbar">
|
|
<a-button type="primary" @click="handleAddItem">
|
|
<template #icon><PlusOutlined /></template>
|
|
新增字典项
|
|
</a-button>
|
|
</div>
|
|
|
|
<!-- 字典项表格 -->
|
|
<a-table
|
|
:columns="columns"
|
|
:data-source="tableData"
|
|
:loading="loading"
|
|
:pagination="false"
|
|
row-key="id"
|
|
size="small"
|
|
>
|
|
<template #bodyCell="{ column, record }">
|
|
<template v-if="column.dataIndex === 'status'">
|
|
<a-tag :color="record.status === 1 ? 'green' : 'red'" size="small">
|
|
{{ record.status === 1 ? '正常' : '禁用' }}
|
|
</a-tag>
|
|
</template>
|
|
<template v-if="column.dataIndex === 'isDefault'">
|
|
<a-tag v-if="record.isDefault === 1" color="blue">是</a-tag>
|
|
<span v-else class="text-muted">否</span>
|
|
</template>
|
|
<template v-if="column.dataIndex === 'action'">
|
|
<a-space>
|
|
<a-button type="link" size="small" @click="handleEditItem(record as DictItemRecord)">编辑</a-button>
|
|
<a-popconfirm
|
|
title="确定删除此字典项吗?"
|
|
@confirm="handleDeleteItem((record as DictItemRecord).id!)"
|
|
>
|
|
<a-button type="link" size="small" danger>删除</a-button>
|
|
</a-popconfirm>
|
|
</a-space>
|
|
</template>
|
|
</template>
|
|
</a-table>
|
|
</div>
|
|
|
|
<!-- 新增/编辑字典项弹窗 -->
|
|
<a-modal
|
|
v-model:open="itemModalVisible"
|
|
:title="isEditItem ? '编辑字典项' : '新增字典项'"
|
|
@ok="handleSubmitItem"
|
|
:confirm-loading="submitLoading"
|
|
>
|
|
<a-form
|
|
ref="formRef"
|
|
:model="formData"
|
|
:rules="formRules"
|
|
:label-col="{ span: 6 }"
|
|
:wrapper-col="{ span: 16 }"
|
|
>
|
|
<a-form-item label="字典项标签" name="label">
|
|
<a-input v-model:value="formData.label" placeholder="请输入显示的文本" />
|
|
</a-form-item>
|
|
<a-form-item label="字典项值" name="value">
|
|
<a-input v-model:value="formData.value" placeholder="请输入存储的值" />
|
|
</a-form-item>
|
|
<a-form-item label="排序" name="sort">
|
|
<a-input-number v-model:value="formData.sort" :min="0" :max="999" style="width: 100%" />
|
|
</a-form-item>
|
|
<a-form-item label="是否默认" name="isDefault">
|
|
<a-switch v-model:checked="formData.isDefault" :checked-value="1" :un-checked-value="0" />
|
|
</a-form-item>
|
|
<a-form-item label="状态" name="status">
|
|
<a-radio-group v-model:value="formData.status">
|
|
<a-radio :value="1">正常</a-radio>
|
|
<a-radio :value="0">禁用</a-radio>
|
|
</a-radio-group>
|
|
</a-form-item>
|
|
<a-form-item label="备注" name="remark">
|
|
<a-textarea v-model:value="formData.remark" placeholder="请输入备注" :rows="2" />
|
|
</a-form-item>
|
|
</a-form>
|
|
</a-modal>
|
|
</a-drawer>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, reactive, watch } from 'vue'
|
|
import { message } from 'ant-design-vue'
|
|
import { PlusOutlined } from '@ant-design/icons-vue'
|
|
import type { FormInstance } from 'ant-design-vue'
|
|
import { getDictItems, createDictItem, updateDictItem, deleteDictItem } from '@/api/system/dict'
|
|
|
|
// 类型定义
|
|
interface DictRecord {
|
|
id: number
|
|
name: string
|
|
code: string
|
|
}
|
|
|
|
interface DictItemRecord {
|
|
id?: number
|
|
dictId?: number
|
|
label: string
|
|
value: string
|
|
sort: number
|
|
isDefault: number
|
|
status: number
|
|
remark?: string
|
|
}
|
|
|
|
const props = defineProps<{
|
|
visible: boolean
|
|
dictData?: DictRecord | null
|
|
}>()
|
|
|
|
const emit = defineEmits(['update:visible'])
|
|
|
|
// 表格
|
|
const loading = ref(false)
|
|
const tableData = ref<DictItemRecord[]>([])
|
|
|
|
const columns = [
|
|
{ title: '标签', dataIndex: 'label', width: 120 },
|
|
{ title: '值', dataIndex: 'value', width: 100 },
|
|
{ title: '排序', dataIndex: 'sort', width: 70 },
|
|
{ title: '默认', dataIndex: 'isDefault', width: 70 },
|
|
{ title: '状态', dataIndex: 'status', width: 70 },
|
|
{ title: '备注', dataIndex: 'remark', ellipsis: true },
|
|
{ title: '操作', dataIndex: 'action', width: 120, fixed: 'right' as const }
|
|
]
|
|
|
|
// 字典项表单
|
|
const itemModalVisible = ref(false)
|
|
const isEditItem = ref(false)
|
|
const submitLoading = ref(false)
|
|
const formRef = ref<FormInstance>()
|
|
|
|
const formData = reactive<DictItemRecord>({
|
|
id: undefined,
|
|
dictId: undefined,
|
|
label: '',
|
|
value: '',
|
|
sort: 0,
|
|
isDefault: 0,
|
|
status: 1,
|
|
remark: ''
|
|
})
|
|
|
|
const formRules = {
|
|
label: [{ required: true, message: '请输入字典项标签' }],
|
|
value: [{ required: true, message: '请输入字典项值' }]
|
|
}
|
|
|
|
// 监听 visible 变化,加载数据
|
|
watch(
|
|
() => props.visible,
|
|
(val) => {
|
|
if (val && props.dictData) {
|
|
loadData(props.dictData.id)
|
|
}
|
|
}
|
|
)
|
|
|
|
function handleClose() {
|
|
emit('update:visible', false)
|
|
}
|
|
|
|
// 加载字典项数据
|
|
async function loadData(dictId: number) {
|
|
loading.value = true
|
|
try {
|
|
const res = await getDictItems(dictId)
|
|
tableData.value = res.data.data || []
|
|
} catch (error) {
|
|
console.error('加载字典项失败:', error)
|
|
tableData.value = []
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
function handleAddItem() {
|
|
isEditItem.value = false
|
|
formData.id = undefined
|
|
formData.dictId = props.dictData?.id
|
|
formData.label = ''
|
|
formData.value = ''
|
|
formData.sort = 0
|
|
formData.isDefault = 0
|
|
formData.status = 1
|
|
formData.remark = ''
|
|
itemModalVisible.value = true
|
|
}
|
|
|
|
function handleEditItem(record: DictItemRecord) {
|
|
isEditItem.value = true
|
|
formData.id = record.id
|
|
formData.dictId = record.dictId
|
|
formData.label = record.label
|
|
formData.value = record.value
|
|
formData.sort = record.sort
|
|
formData.isDefault = record.isDefault
|
|
formData.status = record.status
|
|
formData.remark = record.remark || ''
|
|
itemModalVisible.value = true
|
|
}
|
|
|
|
async function handleDeleteItem(id: number) {
|
|
try {
|
|
await deleteDictItem(id)
|
|
message.success('删除成功')
|
|
if (props.dictData) {
|
|
loadData(props.dictData.id)
|
|
}
|
|
} catch (error: any) {
|
|
if (error?.response?.data?.message) {
|
|
message.error(error.response.data.message)
|
|
}
|
|
}
|
|
}
|
|
|
|
async function handleSubmitItem() {
|
|
try {
|
|
await formRef.value?.validate()
|
|
submitLoading.value = true
|
|
|
|
const data = {
|
|
dictId: formData.dictId!,
|
|
label: formData.label,
|
|
value: formData.value,
|
|
sort: formData.sort,
|
|
isDefault: formData.isDefault,
|
|
status: formData.status,
|
|
remark: formData.remark
|
|
}
|
|
|
|
if (isEditItem.value && formData.id) {
|
|
await updateDictItem(formData.id, data)
|
|
} else {
|
|
await createDictItem(data)
|
|
}
|
|
|
|
message.success(isEditItem.value ? '编辑成功' : '新增成功')
|
|
itemModalVisible.value = false
|
|
if (props.dictData) {
|
|
loadData(props.dictData.id)
|
|
}
|
|
} catch (error: any) {
|
|
if (error?.response?.data?.message) {
|
|
message.error(error.response.data.message)
|
|
}
|
|
} finally {
|
|
submitLoading.value = false
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.drawer-content {
|
|
height: 100%;
|
|
}
|
|
.item-toolbar {
|
|
margin-bottom: 16px;
|
|
}
|
|
.text-muted {
|
|
color: #999;
|
|
}
|
|
</style>
|