const {getModalConfig,registerModal} = require('../modal-registry/modal-registry');
Component({
properties: {
show: { type: Boolean, value: false },
title: { type: String, value: '表单标题' },
config: { type: Array, value: [] },
formData: { type: Object, value: {} },
modalName: { type: String, value: '' },
initData: {
type: null,
value: null,
}
},
data: {
parentParams: {},
tempData: {},
errors: {},
processedConfig: {},
loading: false
},
observers: {
'show, modalName'(show, modalName) {
show && modalName && this.loadModalConfig(modalName)
}
},
methods: {
// 加载弹窗配置
async loadModalConfig(modalName) {
this.setData({ loading: true })
try {
let config = getModalConfig(modalName)
if (!config) throw new Error(`未找到弹窗配置: ${modalName}`)
// 处理前置逻辑
config = await this.processBeforeShow(config)
this.setData({ processedConfig: config, loading: false })
} catch (error) {
console.error('加载失败:', error)
this.setData({ loading: false })
this.triggerEvent('error', { error })
}
},
// 处理前置逻辑, 这段代码已经处理好了不用任何修改
async processBeforeShow(config) {
const initData = this.properties.initData
let processedConfig = { ...config };
if (initData) {
if (Array.isArray(initData)) {
// 处理数组类型
processedConfig.config = config.config.map((item, index) =>
index < initData.length
? { ...item, ...initData[index] } // 正确合并属性
: { ...item } // 超出部分保留原配置
);
return processedConfig;
} else if (typeof initData === "object") {
// 处理对象类型
processedConfig.config = config.config.map(configItem => {
const key = configItem.field;
return initData.hasOwnProperty(key)
? { ...configItem, ...initData[key] } // 直接属性访问
: { ...configItem };
});
return processedConfig;
}
}
if (typeof config.beforeShow === 'function') {
const beforeData = await config.beforeShow()
processedConfig.config = config.config.map(configItem => {
const key = configItem.field;
return beforeData.hasOwnProperty(key)
? { ...configItem, ...beforeData[key] } // 直接属性访问
: { ...configItem };
});
return processedConfig;
}
return config
},
// 表单验证
validateForm() {
const errors = {};
this.data.processedConfig.config.forEach(item => {
if (item.verify) {
// 支持自定义验证函数
const isValid = item.verify(
this.data.formData[item.field],
item.field,
this.data.formData
);
if (isValid !== true) {
errors[item.field] = typeof isValid === 'string'
? isValid
: item.errorMessage || `${item.title}验证失败`;
}
}
});
return errors;
},
// 提交处理
async submitForm() {
if (this.data.loading) return
// 验证表单
const errors = this.validateForm()
if (Object.keys(errors).length) {
return this.setData({ errors })
}
if (this.data.processedConfig.onSubmit) {
await this.data.processedConfig.onSubmit(this.data.formData)
this.setData({ loading: true })
this.closeModal()
return;
}
try {
this.setData({ loading: true })
// 触发提交事件
this.triggerEvent('submit', this.data.formData)
this.closeModal()
} finally {
this.setData({ loading: false })
}
},
// 关闭弹窗
closeModal() {
this.setData({ show: false, processedConfig: [] })
this.triggerEvent('close')
},
// 输入处理
handleInput(e) {
const field = e.currentTarget.dataset.field;
const value = e.detail.value || e.detail;
this.setData({
[`formData.${field}`]: value,
[`errors.${field}`]: ''
});
// 触发字段级 change 事件
const item = this.findItemConfig(field, this.data.processedConfig.config);
if (item && item.onChange) {
item.onChange(value, field, this.data.formData);
}
this.triggerEvent('change', { field, value });
},
/**
* 处理时间选择变化事件
* @param {Object} e - 事件对象
* @param {string} e.currentTarget.dataset.field - 表单字段名
* @param {string} e.detail.value - 选择的时间值
* @fires change - 触发change事件,传递字段名和值
*/
handleTimeChange(e) {
const { field } = e.currentTarget.dataset;
const value = e.detail.value;
this.setData({
[`formData.${field}`]: value,
[`tempData.${field}_show`]: false
});
this.triggerEvent('change', { field, value });
},
/**
* 打开时间选择器
* @param {Object} e - 事件对象
* @param {string} e.currentTarget.dataset.field - 字段名
*/
openTimePicker(e) {
const { field } = e.currentTarget.dataset;
this.setData({ [`tempData.${field}_show`]: true });
},
// 新增:关闭时间选择器
closeTimePicker(e) {
const { field } = e.currentTarget.dataset;
this.setData({ [`tempData.${field}_show`]: false });
},
// 在custom-form-modal/index.js的methods中添加
handleSelectChange(e) {
const { field } = e.currentTarget.dataset;
const value = e.detail.value;
this.setData({
[`formData.${field}`]: value,
[`errors.${field}`]: ''
});
// 触发字段级change事件
const item = this.findItemConfig(field);
if (item && item.onChange) {
item.onChange(value, field, this.data.formData);
}
this.triggerEvent('change', { field, value });
},
// 查找按钮配置
findItemConfig(field) {
// processedConfig.config 是一维数组,直接遍历
for (const item of this.data.processedConfig.config) {
if (item.field === field && item.button) {
return item.button;
}
}
return null;
},
/**
* 处理自定义事件
* @param {Object} e - 事件对象
* @param {string} e.detail.field - 字段名
* @param {Object} e.detail.event - 事件详情
* @fires customEvent - 触发自定义事件
*/
handleCustomEvent(e) {
const { field, event } = e.detail;
this.triggerEvent('customEvent', { field, ...event });
},
// 打开子窗口的统一方法
/**
* 打开子模态框
* @param {string} childModalName - 子模态框名称
* @param {Object} [initData={}] - 初始化数据
* @param {string|null} [sourceField=null] - 触发子窗口的字段名
* @description 保存当前模态框状态到parentParams,并初始化子模态框状态
*/
openChildModal(childModalName, initData = {}, sourceField = null) {
// 保存当前状态到parentParams
const parentParams = {
modalName: this.properties.modalName,
formData: this.data.formData,
tempData: this.data.tempData,
errors: this.data.errors,
config: this.data.processedConfig,
sourceField: sourceField // 记录触发子窗口的字段
};
// 设置新的弹窗状态
this.setData({
modalName: childModalName,
parentParams: parentParams,
formData: this.getChildInitData(childModalName, initData, sourceField),
tempData: {},
errors: {},
processedConfig: {}
});
},
// 获取子窗口初始数据
getChildInitData(childModalName, initData, sourceField) {
// 默认初始化空对象
if (!initData) return {};
// 支持三种初始化方式:
// 1. 函数方式:动态生成数据
if (typeof initData === 'function') {
return initData(this.data.formData, sourceField);
}
// 2. 字符串方式:从父表单获取指定字段
if (typeof initData === 'string') {
return this.data.formData[initData] || {};
}
// 3. 对象方式:直接使用传入的对象
return initData;
},
// 关闭当前弹窗(可能恢复父窗口)
closeModal(result = null) {
// 如果有父级参数,恢复父窗口
if (this.data.parentParams) {
const parentParams = this.data.parentParams;
// 处理子窗口返回结果
if (result !== null && parentParams.sourceField) {
this.handleChildResult(parentParams.sourceField, result);
}
// 恢复父窗口状态
this.setData({
modalName: parentParams.modalName,
formData: parentParams.formData,
tempData: parentParams.tempData,
errors: parentParams.errors,
processedConfig: parentParams.config,
parentParams: parentParams.parentParams // 保持嵌套结构
});
} else {
// 没有父级参数,完全关闭弹窗
this.setData({
show: false,
modalName: '',
processedConfig: {}
});
this.triggerEvent('close', result);
}
},
// 修改后的按钮点击处理
handleButtonClick(e) {
const { field } = e.currentTarget.dataset;
const itemConfig = this.findItemConfig(field);
if (!itemConfig) return;
// 优先执行onClick回调
if (itemConfig.onClick) {
itemConfig.onClick();
return;
}
if (itemConfig.childModal) {
// 处理动态childData
const initData = typeof itemConfig.childData === 'function'
? itemConfig.childData(this.data.formData)
: itemConfig.childData || {};
this.openChildModal(
itemConfig.childModal,
initData,
field
);
} else {
this.triggerEvent('buttonClick', { field });
}
}
,
// 处理子窗口结果// 增强子窗口结果处理
handleChildResult(field, result) {
// 通用结果处理器
switch (field) {
case 'add_child':
// 处理数组类型字段追加
this.setData({
[`formData.${field}`]: [
...(this.data.formData[field] || []),
result
]
});
break;
case 'edit_item':
// 处理数组索引更新
const index = this.data.editingIndex;
this.setData({
[`formData.${field}[${index}]`]: result
});
break;
default:
// 通用字段更新
if (Array.isArray(this.data.formData[field])) {
// 数组字段替换整个数组
this.setData({
[`formData.${field}`]: result
});
} else {
// 对象字段合并
this.setData({
[`formData.${field}`]: {
...this.data.formData[field],
...result
}
});
}
}
// 触发更新事件
this.triggerEvent('change', { field, value: result });
}
,
}
})
传进来的初始数据如果是对象,之中的建没在配置中找到匹配项,直接把该键值对合并到提交数据中
最新发布