<script lang="ts" setup name="SystemEditDict"> import type { Ref } from 'vue' import { nextTick, reactive } from 'vue' import { ElMessage, ElMessageBox } from 'element-plus' import type { FormInstance, FormRules } from 'element-plus' import type { DictDetail, DictInfo, DictListInfo } from './dict-interface' import { addDict, updateDict } from '@/api/system/dict' import { toTreeList } from '@/utils/structure' // ----------------------- 以下是字段定义 emits props --------------------- const emits = defineEmits(['closeRefresh']) // 对话框类型:create,update const dialogStatus = ref('create') const dialogVisible = ref(false) // 显示标题 const textMap: { [key: string]: string } = { update: '编辑', create: '新增', } // 表单数据对象 const formData: Ref<DictInfo> = ref({ dictId: '', dictCode: '', dictName: '', dictTips: '', dictValues: [], }) // 保存按钮加载状态 const btnLoading = ref(false) // ---------------表单提交-------------------------------- // 表单对象 const dataFormRef = ref<FormInstance>() // 校验规则 const rules = reactive<FormRules>({ dictCode: [{ required: true, message: '字典编码不能为空', trigger: ['blur'] }], dictName: [{ required: true, message: '字典名称不能为空', trigger: ['blur'] }], value: [{ required: true, message: '值不能为空', trigger: ['blur'] }], name: [{ required: true, message: '名称不能为空', trigger: ['blur'] }], num: [{ required: true, message: '排序不能为空' }, { type: 'number', message: '必须为数字值' }], }) function submitForm() { if (dataFormRef) { dataFormRef.value?.validate((valid: boolean) => { if (valid) { if (dialogStatus.value === 'create') { createData() } else if (dialogStatus.value === 'update') { updateData() } } }) } } // 新增数据 function createData() { btnLoading.value = true addDict(formData.value).then((res) => { ElMessageBox.confirm( '新增成功,是否继续新增?', '提示', { confirmButtonText: '是', cancelButtonText: '否', type: 'info', }, ).then(() => { resetForm() }).catch(() => { closeRefresh() }) btnLoading.value = false }).catch((_) => { btnLoading.value = false }) } // 更新数据 function updateData() { updateDict(formData.value).then((res) => { ElMessage.success('修改成功') btnLoading.value = false closeRefresh() }).catch((_) => { // 异常情况,loading置为false btnLoading.value = false }) } // 添加一行 function addDetail() { formData.value.dictValues.push({ value: '', name: '', num: formData.value.dictValues.length, }) } // 删除一行 function deleteDetail(index: number) { formData.value.dictValues.splice(index, 1) } // 重置表单 function resetForm() { nextTick(() => { if (!dataFormRef.value) { return } dataFormRef.value?.resetFields() }) } // ----------初始化、关闭对话框相关----------------- function initDialog(dialogstatus: string, row: DictListInfo) { dialogStatus.value = dialogstatus dialogVisible.value = true btnLoading.value = false if (dialogstatus === 'create') { resetForm() } else if (dialogstatus === 'update') { const detailArr = row.detail.split(';') const details = [] as DictDetail[] for (const detail of detailArr) { const detailItem = detail.split(':') const item = { value: detailItem[0], name: detailItem[1], num: parseInt(detailItem[2]), } details.push(item) } formData.value = { dictId: row.id, dictCode: row.code, dictName: row.name, dictTips: row.tips, dictValues: details, } } } // 关闭并刷新 function closeRefresh() { dialogVisible.value = false resetForm() emits('closeRefresh') } // 关闭弹窗 function dialogClose() { dialogVisible.value = false } // ----------------------- 以下是暴露的方法内容 ---------------------------- defineExpose({ initDialog }) </script> <template> <el-dialog v-model="dialogVisible" :title="textMap[dialogStatus]" width="50%" :before-close="dialogClose" append-to-body :open-delay="0" :close-on-click-modal="false" > <el-form ref="dataFormRef" :model="formData" :rules="rules" label-position="left" label-width="80px" class="form-container" size="default" @submit.prevent > <el-row :gutter="10"> <el-col :span="12" class="grid-cell"> <el-form-item label="字典名称" prop="dictName" class="required"> <el-input v-model="formData.dictName" type="text" placeholder="必填" clearable /> </el-form-item> </el-col> <el-col :span="12" class="grid-cell"> <el-form-item label="字典编码" prop="dictCode" class="required"> <el-input v-model="formData.dictCode" type="text" placeholder="必填" clearable /> </el-form-item> </el-col> <el-col :span="24" class="grid-cell"> <el-form-item label="字典描述" prop="tips" class="required"> <el-input v-model="formData.dictTips" type="text" placeholder="非必填" clearable /> </el-form-item> </el-col> <div class="dict-detail"> <div class="title"> 字典值列表 <el-button type="default" style="margin-left: 20px;" @click="addDetail()"> 添加 </el-button> </div> <div class="body"> <el-row v-for="(detail, index) in formData.dictValues" :key="index" :gutter="10"> <el-col :span="6"> <el-form-item :required="true" label="值" label-width="40"> <el-input v-model="detail.value" style="width: 100%;" placeholder="必填" /> </el-form-item> </el-col> <el-col :span="7"> <el-form-item :required="true" label="名称" label-width="60"> <el-input v-model="detail.name" style="width: 100%;" placeholder="必填" /> </el-form-item> </el-col> <el-col :span="6"> <el-form-item :required="true" label="排序" label-width="60"> <el-input-number v-model.number="detail.num" style="width: 100%;" placeholder="必填" /> </el-form-item> </el-col> <el-col :span="2" :offset="1"> <el-button type="primary" @click="deleteDetail(index)"> 删除 </el-button> </el-col> </el-row> </div> </div> </el-row> </el-form> <template #footer> <div class="dialog-footer"> <el-button :loading="btnLoading" type="primary" @click="submitForm"> 保存 </el-button> <el-button @click="dialogClose"> 取消 </el-button> </div> </template> </el-dialog> </template> <style lang="scss" scoped> .form-container { width: 100%; .full-width-input { width: 100%; } .dict-detail { padding: 10px; .title { font-size: 16px; font-weight: bold; margin-bottom: 15px; } } } </style>