220 lines
7.1 KiB
Vue
220 lines
7.1 KiB
Vue
<template>
|
||
<el-form ref="form" :model="formData" :rules="rules" label-width="120px">
|
||
<el-form-item label="单位名称" prop="companyName">
|
||
<el-input v-model="formData.companyName" placeholder="请输入单位名称" />
|
||
</el-form-item>
|
||
|
||
<el-form-item label="联系人" prop="contactPerson">
|
||
<el-input v-model="formData.contactPerson" placeholder="请输入联系人" />
|
||
</el-form-item>
|
||
|
||
<el-form-item label="联系电话" prop="contactPhone">
|
||
<el-input v-model="formData.contactPhone" placeholder="请输入联系电话" />
|
||
</el-form-item>
|
||
|
||
<el-form-item label="单位地址" prop="address">
|
||
<el-input v-model="formData.address" placeholder="请输入单位地址" />
|
||
</el-form-item>
|
||
<!--
|
||
<el-form-item label="状态" prop="status">
|
||
<el-switch v-model="formData.status" active-text="启用" inactive-text="禁用" />
|
||
</el-form-item> -->
|
||
|
||
<el-form-item label="备注" prop="remark">
|
||
<el-input v-model="formData.remark" placeholder="请输入备注" type="textarea" />
|
||
</el-form-item>
|
||
</el-form>
|
||
</template>
|
||
|
||
<script>
|
||
export default {
|
||
name: 'ChargeCompanyForm',
|
||
props: {
|
||
// 用于 v-model 的 value(对象)
|
||
value: {
|
||
type: Object,
|
||
default: () => ({})
|
||
},
|
||
// systemCode 允许字符串或数字
|
||
systemCode: {
|
||
type: [String, Number],
|
||
default: ''
|
||
}
|
||
},
|
||
data() {
|
||
return {
|
||
// 本地表单数据 — 保持对象引用(方便 el-form resetFields)
|
||
formData: {
|
||
id: null,
|
||
companyName: null,
|
||
contactPerson: null,
|
||
contactPhone: null,
|
||
address: null,
|
||
status: false,
|
||
systemCode: '', // 会在 created 中初始化
|
||
remark: null
|
||
},
|
||
// 防止同步回流的标志
|
||
isSyncingFromParent: false,
|
||
rules: {
|
||
companyName: [
|
||
{ required: true, message: '单位名称不能为空', trigger: 'blur' }
|
||
],
|
||
contactPerson: [
|
||
{ required: true, message: '联系人不能为空', trigger: 'blur' }
|
||
],
|
||
contactPhone: [
|
||
{ required: true, message: '联系电话不能为空', trigger: 'blur' },
|
||
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号码', trigger: 'blur' }
|
||
]
|
||
}
|
||
}
|
||
},
|
||
watch: {
|
||
// 当外部传入 systemCode 变化时,更新本地 field(外部 systemCode 优先)
|
||
systemCode: {
|
||
handler(newVal) {
|
||
// 使用 $set 保证响应式(Vue2)
|
||
this.$set(this.formData, 'systemCode', newVal === undefined || newVal === null ? '' : newVal)
|
||
},
|
||
immediate: true
|
||
},
|
||
|
||
// 监听 value(父组件通过 v-model 传入的数据)变化并同步到本地表单
|
||
value: {
|
||
handler(newVal) {
|
||
// 标志:正在同步来自父组件的数据,避免触发 emit 回父组件
|
||
this.isSyncingFromParent = true
|
||
|
||
if (newVal && Object.keys(newVal).length > 0) {
|
||
// 保持 systemCode 优先为当前本地 systemCode(外部 systemCode Prop 会单独处理)
|
||
const keepSystemCode = this.formData.systemCode
|
||
|
||
// 使用 Object.assign 保持 formData 对象引用,避免意外破坏 el-form 的绑定
|
||
Object.assign(this.formData, { ...newVal })
|
||
|
||
// 恢复/保持本地 systemCode(如果你需要让 value 中的 systemCode 覆盖,改这里)
|
||
this.$set(this.formData, 'systemCode', keepSystemCode)
|
||
} else {
|
||
// 如果 newVal 为空对象或 null,则只清空可编辑字段(保持 systemCode)
|
||
const keepSystemCode = this.formData.systemCode
|
||
Object.assign(this.formData, {
|
||
id: null,
|
||
companyName: null,
|
||
contactPerson: null,
|
||
contactPhone: null,
|
||
address: null,
|
||
status: false,
|
||
remark: null
|
||
})
|
||
this.$set(this.formData, 'systemCode', keepSystemCode)
|
||
}
|
||
|
||
// 等下一个 tick 再允许 emit(保证同步完成后不回流)
|
||
this.$nextTick(() => {
|
||
this.isSyncingFromParent = false
|
||
})
|
||
},
|
||
immediate: true,
|
||
deep: true
|
||
},
|
||
|
||
// 本地表单变化时向外 emit(用于 v-model 双向绑定)
|
||
// 但如果是我们从父组件同步过来的改动,则不 emit(避免回流)
|
||
formData: {
|
||
handler(newVal) {
|
||
if (this.isSyncingFromParent) {
|
||
// 来自父组件的同步,不应再次 emit
|
||
return
|
||
}
|
||
// 发出副本,防止父组件直接修改传入对象引用
|
||
this.$emit('input', { ...newVal })
|
||
},
|
||
deep: true
|
||
}
|
||
},
|
||
methods: {
|
||
// 验证表单:callback 接收 (valid, fields)
|
||
validate(callback) {
|
||
if (!this.$refs.form) {
|
||
const error = new Error('form ref not found')
|
||
if (typeof callback === 'function') callback(false, error)
|
||
return Promise.reject(error)
|
||
}
|
||
// Element UI validate 支持回调或 Promise
|
||
return new Promise((resolve, reject) => {
|
||
this.$refs.form.validate((valid, fields) => {
|
||
if (typeof callback === 'function') callback(valid, fields)
|
||
if (valid) resolve(true)
|
||
else reject(fields)
|
||
})
|
||
})
|
||
},
|
||
|
||
// 重置表单验证与字段(保留 systemCode)
|
||
resetFields() {
|
||
if (!this.$refs.form) return
|
||
// resetFields 会根据 model 将字段恢复为 model 中的初始值
|
||
this.$refs.form.resetFields()
|
||
// 重新确保 systemCode 设置为 props 的值(或空字符串)
|
||
this.$set(this.formData, 'systemCode', this.systemCode || '')
|
||
},
|
||
|
||
// 清除校验提示
|
||
clearValidate() {
|
||
if (!this.$refs.form) return
|
||
this.$refs.form.clearValidate()
|
||
},
|
||
|
||
// 彻底重置 formData(保持 systemCode)
|
||
resetFormData() {
|
||
const keepSystemCode = this.systemCode || this.formData.systemCode || ''
|
||
Object.assign(this.formData, {
|
||
id: null,
|
||
companyName: null,
|
||
contactPerson: null,
|
||
contactPhone: null,
|
||
address: null,
|
||
status: false,
|
||
remark: null
|
||
})
|
||
this.$set(this.formData, 'systemCode', keepSystemCode)
|
||
|
||
this.$nextTick(() => {
|
||
this.clearValidate()
|
||
// 主动 emit 一次空的表单状态(如果需要通知父组件)
|
||
this.$emit('input', { ...this.formData })
|
||
})
|
||
},
|
||
|
||
// 外部主动传入数据设置到表单(不会改变 systemCode)
|
||
setFormData(data = {}) {
|
||
if (!data) return
|
||
const keepSystemCode = this.formData.systemCode
|
||
// 阻止在同步过程中 emit
|
||
this.isSyncingFromParent = true
|
||
Object.assign(this.formData, { ...data })
|
||
this.$set(this.formData, 'systemCode', keepSystemCode)
|
||
this.$nextTick(() => {
|
||
this.isSyncingFromParent = false
|
||
})
|
||
}
|
||
},
|
||
created() {
|
||
// 初始时确保 systemCode 使用 props 值(或空字符串)
|
||
this.$set(this.formData, 'systemCode', this.systemCode || '')
|
||
// 如果父组件通过 value 传入初始数据,value watcher 的 immediate 会处理同步
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.el-form {
|
||
padding: 20px 10px 0 0;
|
||
}
|
||
.el-input,
|
||
.el-textarea {
|
||
width: 100%;
|
||
}
|
||
</style>
|