当前位置: 首页 > news >正文

企业级表单与文件上传统一管理方案

1.概念

说明:通过父组件统一管理多个子组件表单(包括上传文件表单),子组件通过函数回调暴露异步校验接口,父组件使用 Promise.all 同步校验各表单,整合表单数据和上传文件信息后统一提交接口。

1.子组件

说明:

  1. 负责文件上传逻辑、显示文件列表、校验文件必填/大小/类型;
  2. 封装 validateFieldAsync() 异步校验方法;
  3. 使用 props.getChildFile 将方法暴露给父组件;
  4. 支持事件回调:上传前 (before-upload-child) 和手动提交 (submit-upload-child)。
<template><div class="upload"><!-- 上传组件容器 --><div class="upload-component"><!-- 表单容器 --><el-form :form="form" ref="form" :model="form"><!-- 表单项 --><el-form-item label="保函扫描件" prop="scanfile" :rules="rules.scanfile"><!-- 上传组件 --><el-uploadref="upload"                <!-- 引用,方便在方法里调用 -->drag                        <!-- 开启拖拽上传 -->multiple                     <!-- 允许上传多个文件 -->class="upload-file"          <!-- 样式类 -->:auto-upload="true"          <!-- 自动上传 -->:file-list="fileList"        <!-- 上传文件列表 -->:before-upload="beforeUpload" <!-- 上传前钩子 -->action="/api/upload"         <!-- 上传接口地址 -->:accept="accept"             <!-- 可上传文件类型 -->><!-- 上传图标 --><i class="el-icon-upload" /><div class="el-upload__text">点击或拖拽文件到此处上传<p>只能上传 jpg、png、pdf 格式,单个文件不超过 10M</p></div><!-- 自定义文件列表展示 --><template #file="{ file }"><div class="upload-file-item"><i class="el-icon-document" @click="openFile(file)" /><span class="file-name" @click="openFile(file)">{{ file.name }}</span><i class="el-icon-delete" @click="handleRemove(file)" style="margin-left: 10px; color: #f56565; cursor: pointer;" /></div></template></el-upload></el-form-item></el-form></div></div>
</template><script>
export default {name: 'CustomUpload',props: {// 父组件传递函数,用于获取子组件方法getChildFile:{type:Function,default:()=>{}},// 标题,可配置title: {type: String,default: '保函扫描件'},// 可上传文件类型accept:{type: String,default: '.jpg,.png,.pdf'},// 单文件最大尺寸(MB)maxsize:{type: Number,default: 10}},data() {return {// 表单对象form:{scanfile: []  // 文件列表绑定字段},// 校验规则rules:{scanfile: [{ required: true, message: '请上传保函扫描件', trigger: 'change' },{validator: (rule, value, callback) => {if (!value || value.length === 0) {callback(new Error('请上传扫描件'))} else {callback()}},trigger: 'change'}]},// 上传文件列表fileList: []}},mounted() {// 父组件通过 props 获取子组件方法if(this.getChildFile){this.getChildFile({validateFieldAsync:this.validateFieldAsync  // 暴露表单校验方法})}},methods: {// 异步校验方法,返回 Promise,供父组件调用validateFieldAsync(){let self=thisreturn new Promise((resolve, reject) => {self.$refs.form.validate(valid => {if (valid) {resolve(self.form)  // 校验通过,返回表单数据}else {reject(false)       // 校验失败}})})},// 上传前校验文件大小beforeUpload(file) {const maxSize = this.maxsize * 1024 * 1024if (file.size > maxSize) {this.$message.error(`文件大小不能超过${this.maxsize}MB`)return false}// 添加到 fileListthis.fileList.push(file)this.form.scanfile = this.fileList// 校验表单字段this.$refs.form.validateField('scanfile')// 向父组件派发事件this.$emit('before-upload-child', this.fileList)return false // 阻止自动上传},// 移除文件handleRemove(file) {// 从 fileList 过滤掉删除的文件this.fileList = this.fileList.filter(f => f.uid !== file.uid)this.form.scanfile = this.fileList// 校验表单字段this.$refs.form.validateField('scanfile')},// 上传文件变化(可选,用于同步 fileList)handleChange(file, fileList) {this.fileList = fileList},// 上传成功回调(可选)handleSuccess(response, file, fileList) {this.fileList = fileList},// 打开文件openFile(file) {const url = file.url || (file ? URL.createObjectURL(file) : '')if (url) window.open(url, '_blank')},// 提交上传,手动触发submitUpload() {if (!this.fileList.length) {this.$message.warning('请先选择文件再提交!')return}this.$emit('submit-upload-child',this.fileList)}}
}
</script><style scoped>
.upload-file{width: 100%;
}
:deep(.el-upload.el-upload--text){width: 100%;
}
:deep(.upload-file .el-upload-dragger){width: 100%;height: 100%;
}
</style>

2.父组件

说明:

  1. 管理主表单 (childForm) 和上传表单 (childFile)

  2. 接收子组件方法,统一调用 validateFieldAsync 校验

  3. 在所有表单通过校验后整合数据提交接口

<template><div><!-- 上传组件 --><custom-upload:get-child-file="getChildFile"            <!-- 父组件获取子组件方法 -->@before-upload-child="beforeUploadChild"  <!-- 上传前事件 -->@submit-upload-child="submitUploadChild"  <!-- 手动提交事件 -->accept=".jpg,.png,.pdf"                   <!-- 可上传文件类型 -->:maxsize="1"                               <!-- 单文件最大尺寸(MB) -->/></div>
</template><script>
export default {data() {return {disabled: false,      // 控制按钮或交互禁用状态childFile: null,      // 存放子组件上传方法对象// 假设还有 childForm 存放普通表单方法}},methods: {// ================================// 父组件接收子组件方法// ================================getChildFile(param) {// 子组件回调过来的方法对象// param = { validateFieldAsync: function }this.childFile = param},// ================================// 上传前事件(可选)// ================================beforeUploadChild(fileList) {// fileList: 当前上传列表console.log('上传前文件列表', fileList)// 可以做额外逻辑:例如限制文件数量、提示等},// ================================// 手动触发上传事件(可选)// ================================submitUploadChild(fileList) {// fileList: 当前上传列表console.log('手动提交文件列表', fileList)},// ================================// 表单提交(整合文件表单 + 主表单)// ================================submitUpload(param) {let self = this;// 同时校验上传表单和主表单Promise.all([this.childFile.validateFieldAsync(),   // 子组件上传表单校验this.childForm.validateFieldAsync()    // 主表单校验]).then(([fileForm, mainForm]) => {// 处理上传文件信息const files = (fileForm.scanfile || []).map(item => ({name: item.name,url: item.url || "/no",   // 如果没有 url 用占位type: item.type}))// 调用提交方法,将主表单 + 上传文件 + 其他信息一起提交self.submit({...mainForm,                              // 主表单数据letterScanPath: JSON.stringify(files),    // 上传文件列表intentionId: self.detailData.intentionId, // 其他必要字段branchId: self.detailData.branchId})}).catch(() => {// 如果任意一个表单校验失败,可以做提示或阻止提交console.log('表单校验未通过')})},// ================================// 真正的提交方法(示例)// ================================submit(data) {console.log('最终提交数据', data)// TODO: 调用接口提交}}
}
</script>

3.效果图

4.总结

父子组件低耦合、表单校验统一、上传文件与表单字段绑定、数据整合集中、可复用和可扩展,适合复杂企业级表单场景。

http://www.dtcms.com/a/524123.html

相关文章:

  • 报错解决:IEEE latex模版中thanks不显示 隶属关系 / 邮箱不显示
  • 第四章:向量数据库:解锁Embeddings价值的钥匙
  • 微信的微网站模板下载wordpress 后台502
  • 基于JavaWeb技术的在线考试系统设计与实现
  • Function Calling VS MCP
  • 找公司网站建设销售网页
  • C++仿muduo库高并发服务器项目:Channel模块
  • 网站开发前端php 后端python张家界seo
  • [特殊字符]兰亭妙微审美积累|总结三个情感化设计细节✨
  • 【数列求和】
  • 第一章-第二节-Cursor IDE与MCP集成.md
  • 做网站的的人收入多少钱wordpress 4.8.4 漏洞
  • 网站开发的英文书有什么如何做网站好看
  • 前端如何判断用户是否离开了当前页面?
  • Flutter项目搭建最佳实践
  • # AI高精度提示词生成项目——3D-VR 课件—— 最终仓库级 AI 提示词:生成《EduVR Studio》—— 专业级 3D-VR 课件创作平台
  • 巡检机器人落地攻略:RK3576驱动12路低延迟视觉
  • 网站开发 文件上传慢wordpress 上线到centos
  • 嘉兴网站建设多少钱广州装修公司口碑最好的是哪家
  • Docker Swarm 的负载均衡和平滑切换原理
  • RabbitMQ 发送方确认机制详解
  • Keepalived 多节点负载均衡配置
  • Windows下载安装配置rabbitmq
  • 了解前端连接 RabbitMQ 的方式
  • 【ROS2】ROS2+Qt6在编译时报错:target_link_libraries
  • 从0到1理解智能体模式
  • 怎么做家具定制网站qq自动发货平台网站怎么做
  • 微网站开发合同网站建设项目付款方式
  • HarmonyOS ArkUI框架中AceContainer类的成员变量定义
  • 数据结构——希尔排序