| | |
| | | size="default" |
| | | ref="formRef" |
| | | :rules="state.formRules" |
| | | label-width="150px" |
| | | label-width="160px" |
| | | > |
| | | <template v-for="(item, index) in config.formItems" :key="index"> |
| | | <el-divider v-if="item.type === 'divider'" content-position="left">{{item.content}}</el-divider> |
| | |
| | | title: '', |
| | | formData: {}, |
| | | formRules: {}, |
| | | // 文件上传相关 |
| | | uploadUrl: props.uploadConfig.uploadUrl, |
| | | header: { |
| | | Authorization: getToken() |
| | | }, |
| | | fileLists: {}, // 存储各上传字段的文件列表 |
| | | // 数据列表 |
| | | fileLists: {}, |
| | | companyList: [], |
| | | deptList: [], |
| | | userList: [], |
| | |
| | | dialogImageUrl: '' |
| | | }) |
| | | |
| | | // 初始化表单数据 |
| | | const initFormData = () => { |
| | | const formData = {} |
| | | state.fileLists = {} |
| | | |
| | | // 初始化普通表单项 |
| | | props.config.formItems?.forEach(item => { |
| | | // 对于多选选择框,默认值为空数组 |
| | | |
| | | if (item.type === 'select' && item.multiple) { |
| | | formData[item.prop] = Array.isArray(item.defaultValue) ? item.defaultValue : [] |
| | | } else { |
| | | formData[item.prop] = item.defaultValue !== undefined ? item.defaultValue : null |
| | | } |
| | | |
| | | // 初始化文件上传字段的文件列表 |
| | | if (item.type === 'upload') { |
| | | state.fileLists[item.prop] = [] |
| | | } |
| | | }) |
| | | |
| | | // 初始化表单规则 |
| | | const formRules = {} |
| | | props.config.formItems?.forEach(item => { |
| | | if (item.rules) { |
| | | formRules[item.prop] = item.rules |
| | | } |
| | | |
| | | // 为文件上传字段添加自定义验证规则 |
| | | if (item.type === 'upload' && item.required) { |
| | | formRules[item.prop] = formRules[item.prop] || [] |
| | | formRules[item.prop].push({ |
| | |
| | | }) |
| | | } |
| | | |
| | | // 为多选选择框添加自定义验证规则 |
| | | if (item.type === 'select' && item.multiple && item.required) { |
| | | formRules[item.prop] = formRules[item.prop] || [] |
| | | formRules[item.prop].push({ |
| | |
| | | state.formRules = formRules |
| | | } |
| | | |
| | | // 获取选项数据 |
| | | const getOptions = (options) => { |
| | | if (!options) return [] |
| | | |
| | | // 如果是函数,执行函数获取选项 |
| | | if (typeof options === 'function') { |
| | | return options() |
| | | } |
| | | |
| | | // 如果是数组,直接返回 |
| | | if (Array.isArray(options)) { |
| | | return options |
| | | } |
| | |
| | | const getCascaderOptions = (item) => { |
| | | if (!item.options) return [] |
| | | |
| | | // 如果是函数,执行函数获取选项 |
| | | if (typeof item.options === 'function') { |
| | | return item.options() |
| | | } |
| | | |
| | | // 如果是数组,直接返回 |
| | | if (Array.isArray(item.options)) { |
| | | return item.options |
| | | } |
| | | |
| | | // 如果是响应式引用 |
| | | if (item.options && typeof item.options === 'object' && 'value' in item.options) { |
| | | return item.options.value |
| | | } |
| | |
| | | return [] |
| | | } |
| | | |
| | | // 文件上传前的校验 |
| | | const beforeUpload = (rawFile, item) => { |
| | | const maxSize = item.maxSize || 5 |
| | | if (rawFile.size / 1024 / 1024 > maxSize) { |
| | |
| | | return true |
| | | } |
| | | |
| | | // 文件上传成功处理 |
| | | const handleUploadSuccess = (res, uploadFile, prop) => { |
| | | if (res.code === 200) { |
| | | ElMessage.success('上传成功') |
| | | } else { |
| | | // 上传失败,移除文件 |
| | | state.fileLists[prop] = state.fileLists[prop].filter(file => file.uid !== uploadFile.uid) |
| | | ElMessage.warning(res.message || '文件上传失败') |
| | | } |
| | |
| | | }).join(',') |
| | | } |
| | | |
| | | // 文件移除处理 |
| | | const handleRemove = async (file, uploadFiles, prop) => { |
| | | try { |
| | | if(file.uid){ |
| | |
| | | state.dialogVisible = true |
| | | } |
| | | |
| | | // 超出文件数量限制提示 |
| | | const showTip = () => { |
| | | ElMessage.warning('超出文件上传数量') |
| | | } |
| | | |
| | | // 处理事件 |
| | | const handleEvent = async (eventName, value) => { |
| | | try { |
| | | if (eventName === 'getUserListByRole' && props.dataLoader.getUserListByRole) { |
| | |
| | | } |
| | | } |
| | | |
| | | // 打开对话框 |
| | | const openDialog = async (type, initialData) => { |
| | | state.title = type === 'add' ? '新增' : type === 'edit' ? '编辑' : type === 'rectify' ? '整改' : '查看' |
| | | // 初始化表单数据 |
| | | |
| | | initFormData() |
| | | // 加载初始数据 |
| | | |
| | | try { |
| | | if (props.dataLoader.loadInitialData) { |
| | | const initialData = await props.dataLoader.loadInitialData(id) |
| | |
| | | console.error('无初始数据:', error) |
| | | } |
| | | |
| | | // 如果有初始数据,填充表单 |
| | | if (initialData) { |
| | | Object.keys(state.formData).forEach(key => { |
| | | if (key in initialData) { |
| | | // 对于多选字段,确保值是数组 |
| | | |
| | | const item = props.config.formItems.find(i => i.prop === key) |
| | | if (item && item.type === 'select' && item.multiple) { |
| | | state.formData[key] = Array.isArray(initialData[key]) ? initialData[key] : (initialData[key] ? [initialData[key]] : []) |
| | |
| | | } |
| | | }) |
| | | state.formData.id = initialData.id || null |
| | | // 初始化文件上传字段的文件列表 |
| | | |
| | | props.config.formItems?.forEach(item => { |
| | | if (item.type === 'upload' && initialData[item.prop]) { |
| | | state.fileLists[item.prop] = [{ |
| | |
| | | try { |
| | | const valid = await formRef.value.validate() |
| | | if (valid) { |
| | | // 准备提交数据 |
| | | |
| | | const submitData = { ...state.formData } |
| | | |
| | | // 对于多选字段,如果是空数组则转为null(根据后端需求) |
| | | props.config.formItems?.forEach(item => { |
| | | if (item.type === 'select' && item.multiple && |
| | | Array.isArray(submitData[item.prop]) && |
| | |
| | | } |
| | | }) |
| | | |
| | | // 触发提交事件 |
| | | emit('submit', submitData, state.title) |
| | | } |
| | | } catch (error) { |
| | |
| | | } |
| | | } |
| | | |
| | | // 关闭对话框 |
| | | |
| | | const closeDialog = () => { |
| | | formRef.value.clearValidate() |
| | | formRef.value.resetFields() |
| | | dialogVisible.value = false |
| | | } |
| | | |
| | | // 暴露方法给父组件 |
| | | |
| | | defineExpose({ |
| | | openDialog, |
| | | closeDialog |
| | | }) |
| | | |
| | | // 初始化 |
| | | |
| | | initFormData() |
| | | </script> |
| | | |
| | |
| | | margin-top: 7px; |
| | | } |
| | | |
| | | // 多选选择框样式调整 |
| | | |
| | | :deep(.el-select__tags) { |
| | | white-space: nowrap; |
| | | overflow: hidden; |