2026-03-26 20:18:20 +08:00
|
|
|
<script setup lang="ts">
|
|
|
|
|
import { computed, ref, watch } from 'vue';
|
|
|
|
|
import { dictStatusOptions } from '@/constants/business';
|
|
|
|
|
import { fetchCreateDictData, fetchUpdateDictData } from '@/service/api';
|
|
|
|
|
import { useForm, useFormRules } from '@/hooks/common/form';
|
|
|
|
|
import BusinessFormDialog from '@/components/custom/business-form-dialog.vue';
|
|
|
|
|
import { $t } from '@/locales';
|
|
|
|
|
|
|
|
|
|
defineOptions({ name: 'DictDataOperateModal' });
|
|
|
|
|
|
|
|
|
|
interface Props {
|
|
|
|
|
operateType: UI.TableOperateType;
|
|
|
|
|
rowData?: Api.Dict.DictData | null;
|
|
|
|
|
currentType?: Api.Dict.DictType | null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const props = defineProps<Props>();
|
|
|
|
|
|
|
|
|
|
interface Emits {
|
|
|
|
|
(e: 'submitted'): void;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const emit = defineEmits<Emits>();
|
|
|
|
|
|
|
|
|
|
const visible = defineModel<boolean>('visible', {
|
|
|
|
|
default: false
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const { formRef, validate, restoreValidation } = useForm();
|
|
|
|
|
const { defaultRequiredRule } = useFormRules();
|
|
|
|
|
|
|
|
|
|
const isEdit = computed(() => props.operateType === 'edit');
|
|
|
|
|
const submitting = ref(false);
|
|
|
|
|
|
|
|
|
|
const title = computed(() => {
|
|
|
|
|
const titleMap: Record<UI.TableOperateType, string> = {
|
|
|
|
|
add: $t('page.system.dict.addData'),
|
|
|
|
|
edit: $t('page.system.dict.editData')
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return titleMap[props.operateType];
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
type Model = Api.Dict.SaveDictDataParams;
|
|
|
|
|
|
|
|
|
|
const model = ref(createDefaultModel());
|
|
|
|
|
|
|
|
|
|
const currentTypeName = computed(() => props.currentType?.name ?? '-');
|
|
|
|
|
const currentTypeCode = computed(() => props.currentType?.type ?? model.value.dictType ?? '-');
|
|
|
|
|
|
|
|
|
|
function createDefaultModel(): Model {
|
|
|
|
|
return {
|
|
|
|
|
label: '',
|
2026-05-18 16:49:12 +08:00
|
|
|
sign: '',
|
2026-03-26 20:18:20 +08:00
|
|
|
value: '',
|
|
|
|
|
dictType: '',
|
|
|
|
|
sort: 0,
|
|
|
|
|
status: 0,
|
|
|
|
|
remark: ''
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type RuleKey = Extract<keyof Model, 'label' | 'value' | 'sort' | 'status'>;
|
|
|
|
|
|
|
|
|
|
const rules: Record<RuleKey, App.Global.FormRule> = {
|
|
|
|
|
label: defaultRequiredRule,
|
|
|
|
|
value: defaultRequiredRule,
|
|
|
|
|
sort: defaultRequiredRule,
|
|
|
|
|
status: defaultRequiredRule
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
function handleInitModel() {
|
|
|
|
|
model.value = createDefaultModel();
|
|
|
|
|
|
|
|
|
|
// 新增字典数据时默认继承左侧当前选中的字典类型。
|
|
|
|
|
const currentDictType = props.currentType?.type ?? '';
|
|
|
|
|
model.value.dictType = currentDictType;
|
|
|
|
|
|
|
|
|
|
if (isEdit.value && props.rowData) {
|
|
|
|
|
// 编辑时直接使用表格行数据回填,保持弹框打开速度。
|
|
|
|
|
Object.assign(model.value, {
|
|
|
|
|
label: props.rowData.label,
|
2026-05-18 16:49:12 +08:00
|
|
|
sign: props.rowData.sign ?? '',
|
2026-03-26 20:18:20 +08:00
|
|
|
value: props.rowData.value,
|
|
|
|
|
dictType: props.rowData.dictType,
|
|
|
|
|
sort: props.rowData.sort,
|
|
|
|
|
status: props.rowData.status,
|
|
|
|
|
remark: props.rowData.remark ?? ''
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function closeModal() {
|
|
|
|
|
visible.value = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function handleSubmit() {
|
|
|
|
|
await validate();
|
|
|
|
|
|
|
|
|
|
// 右侧数据必须依附左侧字典类型,没有选中类型时不允许提交。
|
|
|
|
|
const dictType = model.value.dictType || props.currentType?.type;
|
|
|
|
|
|
|
|
|
|
if (!dictType) {
|
|
|
|
|
window.$message?.warning($t('page.system.dict.emptyType'));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
submitting.value = true;
|
|
|
|
|
|
|
|
|
|
const params: Api.Dict.SaveDictDataParams = {
|
|
|
|
|
...model.value,
|
|
|
|
|
dictType
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const request =
|
|
|
|
|
isEdit.value && props.rowData
|
|
|
|
|
? fetchUpdateDictData({ id: props.rowData.id, ...params })
|
|
|
|
|
: fetchCreateDictData(params);
|
|
|
|
|
|
|
|
|
|
const { error } = await request;
|
|
|
|
|
|
|
|
|
|
submitting.value = false;
|
|
|
|
|
|
|
|
|
|
if (error) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
window.$message?.success($t(isEdit.value ? 'common.updateSuccess' : 'common.addSuccess'));
|
|
|
|
|
|
|
|
|
|
closeModal();
|
|
|
|
|
emit('submitted');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
watch(visible, value => {
|
|
|
|
|
if (value) {
|
|
|
|
|
handleInitModel();
|
|
|
|
|
restoreValidation();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
<BusinessFormDialog
|
|
|
|
|
v-model="visible"
|
|
|
|
|
:title="title"
|
|
|
|
|
preset="md"
|
|
|
|
|
:confirm-loading="submitting"
|
|
|
|
|
:scrollbar="false"
|
|
|
|
|
@confirm="handleSubmit"
|
|
|
|
|
>
|
|
|
|
|
<ElForm ref="formRef" :model="model" :rules="rules" label-position="top">
|
|
|
|
|
<ElRow :gutter="16">
|
|
|
|
|
<ElCol :span="12">
|
|
|
|
|
<ElFormItem :label="$t('page.system.dict.currentType')">
|
|
|
|
|
<ElInput :model-value="currentTypeName" disabled />
|
|
|
|
|
</ElFormItem>
|
|
|
|
|
</ElCol>
|
|
|
|
|
<ElCol :span="12">
|
|
|
|
|
<ElFormItem :label="$t('page.system.dict.dictCode')">
|
|
|
|
|
<ElInput :model-value="currentTypeCode" disabled />
|
|
|
|
|
</ElFormItem>
|
|
|
|
|
</ElCol>
|
|
|
|
|
<ElCol :span="12">
|
|
|
|
|
<ElFormItem :label="$t('page.system.dict.dictLabel')" prop="label">
|
|
|
|
|
<ElInput v-model="model.label" :placeholder="$t('page.system.dict.form.dictLabel')" />
|
|
|
|
|
</ElFormItem>
|
|
|
|
|
</ElCol>
|
|
|
|
|
<ElCol :span="12">
|
|
|
|
|
<ElFormItem :label="$t('page.system.dict.dictValue')" prop="value">
|
|
|
|
|
<ElInput v-model="model.value" :placeholder="$t('page.system.dict.form.dictValue')" />
|
|
|
|
|
</ElFormItem>
|
|
|
|
|
</ElCol>
|
2026-05-18 16:49:12 +08:00
|
|
|
<ElCol :span="12">
|
|
|
|
|
<ElFormItem label="标志" prop="sign">
|
|
|
|
|
<ElInput v-model="model.sign" placeholder="请输入标志" />
|
|
|
|
|
</ElFormItem>
|
|
|
|
|
</ElCol>
|
2026-03-26 20:18:20 +08:00
|
|
|
<ElCol :span="12">
|
|
|
|
|
<ElFormItem :label="$t('page.system.dict.sort')" prop="sort">
|
|
|
|
|
<ElInputNumber
|
|
|
|
|
v-model="model.sort"
|
|
|
|
|
class="w-full"
|
|
|
|
|
:min="0"
|
|
|
|
|
:placeholder="$t('page.system.dict.form.sort')"
|
|
|
|
|
/>
|
|
|
|
|
</ElFormItem>
|
|
|
|
|
</ElCol>
|
|
|
|
|
<ElCol :span="12">
|
|
|
|
|
<ElFormItem :label="$t('page.system.dict.dictStatus')" prop="status">
|
|
|
|
|
<ElRadioGroup v-model="model.status" class="business-form-radio-group">
|
|
|
|
|
<ElRadio v-for="{ label, value } in dictStatusOptions" :key="value" :value="value" :label="$t(label)" />
|
|
|
|
|
</ElRadioGroup>
|
|
|
|
|
</ElFormItem>
|
|
|
|
|
</ElCol>
|
|
|
|
|
<ElCol :span="24">
|
|
|
|
|
<ElFormItem :label="$t('page.system.dict.remark')" prop="remark">
|
|
|
|
|
<ElInput
|
|
|
|
|
v-model="model.remark"
|
|
|
|
|
type="textarea"
|
|
|
|
|
:rows="4"
|
|
|
|
|
:placeholder="$t('page.system.dict.form.remark')"
|
|
|
|
|
/>
|
|
|
|
|
</ElFormItem>
|
|
|
|
|
</ElCol>
|
|
|
|
|
</ElRow>
|
|
|
|
|
</ElForm>
|
|
|
|
|
</BusinessFormDialog>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<style scoped></style>
|