<template>
|
<el-dialog v-model="dialogVisible" :title="title" :width="width" :destroy-on-close="true" @close="handleClose">
|
<el-form ref="formRef" :model="formData" :rules="finalRules" label-width="150px" size="default">
|
<!-- 动态渲染表单项 -->
|
<el-form-item
|
v-for="(item, index) in fields"
|
:key="index + item.prop"
|
:label="item.label"
|
:prop="item.prop"
|
:required="item.required"
|
:disabled="item.disabled"
|
>
|
<!-- 输入框 -->
|
<el-input
|
v-if="item.type === 'input'"
|
v-model="formData[item.prop]"
|
:placeholder="item.placeholder || `请输入${item.label}`"
|
:maxlength="item.maxlength"
|
:disabled="item.disabled"
|
/>
|
|
<!-- 下拉选择 -->
|
<el-select
|
v-else-if="item.type === 'select'"
|
v-model="formData[item.prop]"
|
:placeholder="item.placeholder || `请选择${item.label}`"
|
:disabled="item.disabled || !item.options || item.options.length === 0"
|
>
|
<el-option
|
v-for="dict in item.options"
|
:key="dict.value"
|
:label="dict.label"
|
:value="dict.value"
|
/>
|
</el-select>
|
|
<!-- 文本域 -->
|
<el-input
|
v-else-if="item.type === 'textarea'"
|
v-model="formData[item.prop]"
|
type="textarea"
|
:rows="item.rows || 3"
|
:placeholder="item.placeholder || `请输入${item.label}`"
|
:disabled="item.disabled"
|
/>
|
</el-form-item>
|
</el-form>
|
|
<template #footer>
|
<span class="dialog-footer">
|
<el-button @click="handleClose">取消</el-button>
|
<el-button type="primary" @click="handleSubmit">确定</el-button>
|
</span>
|
</template>
|
</el-dialog>
|
</template>
|
|
<script setup lang="ts">
|
import useCurrentInstance from "@/utils/useCurrentInstance";
|
import { ref, reactive, watch, onMounted, computed } from 'vue';
|
import type { FormInstance, FormRules } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
|
// 定义字段类型,强化中文提示相关配置
|
interface FormField {
|
prop: string; // 字段标识
|
label: string; // 标签名
|
type: 'input' | 'select' | 'textarea'; // 组件类型
|
required?: boolean; // 是否必填
|
disabled?: boolean; // 是否禁用(新增:控制字段是否可修改)
|
placeholder?: string; // 输入框占位符(中文)
|
requiredMessage?: string; // 自定义必填提示(中文,优先级最高)
|
maxlength?: number; // 最大长度
|
rows?: number; // 文本域行数
|
options?: { label: string; value: string | number }[]; // 下拉选项(中文标签)
|
}
|
|
const { proxy } = useCurrentInstance();
|
// 获取字典数据
|
const { sys_invoice_type } = proxy.useDict('sys_invoice_type');
|
|
// 定义表单字段配置(内部集成)
|
const fields = ref<FormField[]>([
|
{
|
prop: 'relatedCustomerName',
|
label: '关联客户',
|
type: 'input',
|
required: true,
|
placeholder: '请输入关联客户',
|
requiredMessage: '请输入关联客户',
|
disabled: true, // 核心修改:设置为禁用状态,禁止修改
|
},
|
{
|
prop: 'invoiceCompanyName',
|
label: '抬头公司',
|
type: 'input',
|
required: true,
|
placeholder: '请输入抬头公司',
|
},
|
{
|
prop: 'invoiceCreditCode',
|
label: '统一社会信用代码',
|
type: 'input',
|
required: true,
|
placeholder: '请输入统一社会信用代码',
|
maxlength: 18,
|
},
|
{
|
prop: 'invoiceType',
|
label: '发票类型',
|
type: 'select',
|
required: true,
|
placeholder: '请选择发票类型',
|
options: [], // 初始为空,后续从字典填充
|
},
|
{
|
prop: 'invoiceBankName',
|
label: '开户银行名称',
|
type: 'input',
|
placeholder: '请输入开户银行名称',
|
},
|
{
|
prop: 'invoiceBankNo',
|
label: '基本开户账号',
|
type: 'input',
|
placeholder: '请输入基本开户账号',
|
},
|
{
|
prop: 'invoiceOperatingLicenseAddress',
|
label: '注册场所地址',
|
type: 'input',
|
placeholder: '请输入注册场所地址',
|
},
|
{
|
prop: 'invoiceOperatingLicensePhone',
|
label: '注册固定电话',
|
type: 'input',
|
required: true,
|
placeholder: '请输入注册固定电话',
|
},
|
{
|
prop: 'invoiceOperatingLicenseEmail',
|
label: '邮箱',
|
type: 'input',
|
required: true,
|
placeholder: '请输入邮箱',
|
},
|
]);
|
|
// Props
|
const props = defineProps({
|
visible: {
|
type: Boolean,
|
default: false,
|
},
|
// 新增:操作类型 add 或 edit
|
mode: {
|
type: String as () => 'add' | 'edit',
|
default: 'add'
|
},
|
title: {
|
type: String,
|
default: '发票信息表单', // 中文标题默认值
|
},
|
width: {
|
type: String,
|
default: '60%', // 适当加宽以适应长标签
|
},
|
// 初始表单数据(用于编辑场景)
|
initialData: {
|
type: Object,
|
default: () => ({}),
|
},
|
// 自定义校验规则(可选)
|
rules: {
|
type: Object as () => FormRules,
|
default: () => ({}),
|
},
|
});
|
|
// Emits
|
const emit = defineEmits(['close', 'submit']);
|
|
// 表单实例
|
const formRef = ref<FormInstance>();
|
// 弹窗显示状态
|
const dialogVisible = ref(false);
|
// 表单数据
|
const formData = reactive<Record<string, any>>({});
|
// 最终校验规则(合并默认中文提示规则)
|
const finalRules = ref<FormRules>({});
|
|
// 监听字典数据变化,填充到发票类型选项
|
watch(
|
() => sys_invoice_type.value,
|
(newVal) => {
|
const invoiceTypeField = fields.value.find(item => item.prop === 'invoiceType');
|
if (invoiceTypeField && newVal && newVal.length > 0) {
|
invoiceTypeField.options = newVal;
|
}
|
},
|
{ immediate: true }
|
);
|
|
// 生成默认中文校验规则
|
const generateDefaultRules = () => {
|
const defaultRules: FormRules = {};
|
fields.value.forEach((field) => {
|
if (field.required) {
|
// 优先使用自定义中文提示,否则自动生成
|
const message = field.requiredMessage ||
|
(field.type === 'select'
|
? `请选择${field.label}`
|
: `请输入${field.label}`);
|
|
defaultRules[field.prop] = [
|
{
|
required: true,
|
message,
|
trigger: field.type === 'select' ? 'change' : 'blur'
|
}
|
];
|
}
|
});
|
return defaultRules;
|
};
|
|
// 初始化表单数据和规则
|
const initForm = () => {
|
// 重置表单数据
|
fields.value.forEach((field) => {
|
formData[field.prop] = props.initialData[field.prop] ?? (field.type === 'select' ? '' : '');
|
});
|
|
// 生成并合并规则
|
finalRules.value = { ...generateDefaultRules(), ...props.rules };
|
};
|
|
// 监听visible变化,控制弹窗
|
watch(
|
() => props.visible,
|
(val) => {
|
dialogVisible.value = val;
|
if (val) {
|
initForm(); // 显示时初始化表单
|
}
|
},
|
{ immediate: true }
|
);
|
|
// 提交表单
|
const handleSubmit = async () => {
|
if (!formRef.value) return;
|
try {
|
await formRef.value.validate();
|
emit('submit', { ...formData },props.mode);
|
dialogVisible.value = false;
|
} catch (err) {
|
// 校验失败时显示全局中文提示
|
ElMessage({
|
message: '表单验证失败,请检查必填项',
|
type: 'warning',
|
});
|
}
|
};
|
|
// 关闭弹窗
|
const handleClose = () => {
|
dialogVisible.value = false;
|
formRef.value?.resetFields();
|
emit('close');
|
};
|
|
// 初始化
|
onMounted(() => {
|
initForm();
|
});
|
</script>
|
|
<style scoped>
|
.dialog-footer {
|
text-align: right;
|
}
|
</style>
|