文件上传分析文档.md 8.4 KB

文件上传分析文档

概述

本文档分析了项目中购机者照片、证件附件和发票附件这三个文件上传功能的接口和参数。

文件上传接口

所有文件上传都使用同一个接口:

  • 接口地址: /api/attachment/addimg
  • 请求方法: POST
  • 请求类型: multipart/form-data
  • 认证方式: 通过请求头中的 token 参数进行用户认证

1. 购机者照片上传

接口参数

参数名 类型 必填 说明
file File 上传的图片文件
attmodel String "coupon_buyer" (关联模块)
attpath String "/coupon_buyer/" (上传路径)
token String 用户认证token (在请求头中)

使用场景

  • 页面位置: src/pages/coupon/modify-info.vue
  • 是否必填: 否
  • 用途: 用于确认购机者身份
  • 限制: 最多上传1张图片

代码示例

<UploadComponent
  v-model="formData.buyerPhoto"
  v-model:fileIds="formData.buyerPhotoIds"
  :limit="1"
  :required="false"
  attmodel="coupon_buyer"
  attpath="/coupon_buyer/"
  modelStats="buyerPhotoIds"
  message="请上传购机者照片"
  tips="用于确认购机者身份"
/>

2. 证件附件上传

接口参数

参数名 类型 必填 说明
file File 上传的图片文件
attmodel String "coupon_identity" (关联模块)
attpath String "/coupon_identity/" (上传路径)
token String 用户认证token (在请求头中)

使用场景

  • 页面位置: src/pages/coupon/modify-info.vue
  • 是否必填: 是
  • 用途: 根据用户类型上传不同的证件
    • 个人用户:上传身份证照片
    • 企业用户:上传营业执照照片
  • 限制: 最多上传1张图片

代码示例

<!-- 个人身份证上传 -->
<UploadComponent
  v-model="formData.idCardFiles"
  v-model:fileIds="formData.idCardIds"
  :limit="1"
  attmodel="coupon_identity"
  attpath="/coupon_identity/"
  modelStats="idCardIds"
  message="请上传身份证照片"
  tips="请上传身份证正面照片"
/>

<!-- 企业营业执照上传 -->
<UploadComponent
  v-model="formData.businessLicenseFiles"
  v-model:fileIds="formData.businessLicenseIds"
  :limit="1"
  attmodel="coupon_identity"
  attpath="/coupon_identity/"
  modelStats="businessLicenseIds"
  message="请上传营业执照照片"
/>

3. 发票附件上传

接口参数

参数名 类型 必填 说明
file File 上传的文件(支持图片和PDF)
attmodel String "coupon_invoice" (关联模块)
attpath String "/coupon_invoice/" (上传路径)
token String 用户认证token (在请求头中)

使用场景

  • 页面位置: src/pages/form/formStep4.vue
  • 是否必填: 是
  • 用途: 上传购买发票
  • 限制:
    • 最多上传1个文件
    • 支持格式:JPG、PNG、PDF
    • 文件大小:不超过10MB

代码示例

<UploadComponent
  v-model="formData.invoiceFiles"
  v-model:fileIds="formData.invoiceFileIds"
  :limit="1"
  :required="true"
  accept="all"
  :extension="['.jpg', '.jpeg', '.png', '.pdf']"
  attmodel="coupon_invoice"
  attpath="/coupon_invoice/"
  modelStats="invoiceFileIds"
  message="请上传发票照片或PDF文件"
  tips="支持图片格式(JPG、PNG)和PDF文件,文件大小不超过10MB"
/>

文件上传流程

  1. 所有文件上传都使用同一个接口 /api/attachment/addimg
  2. 通过 attmodelattpath 参数区分不同类型的文件
  3. 上传成功后,服务器返回文件ID,前端将文件ID保存到相应的数组中
  4. 提交表单时,将所有文件ID通过逗号连接成一个字符串,通过 filesid 参数提交给后端

文件ID处理

在表单提交时,不同类型的文件ID会被收集到同一个数组中,然后通过逗号连接成一个字符串:

// 示例代码
const fileIds = [
  ...idCardIds.map((item) => item.id), // 证件照片ID
  ...buyerPhotoIds.map((item) => item.id), // 购机者照片ID
  ...invoiceFileIds.map((item) => item.id), // 发票文件ID
];
const fileIdsString = fileIds.join(',');

// 提交参数
const submitParams = {
  // ...其他参数
  filesid: fileIdsString, // 文件ID字符串
};

上传组件实现

文件上传功能通过 UploadComponent 组件实现,该组件位于 src/components/UploadComponent.vue

主要功能

  1. 文件选择和预览
  2. 文件上传前的验证
  3. 自定义上传方法
  4. 文件ID管理
  5. 文件删除功能

核心方法

// 创建自定义上传方法
function createCustomUpload({ attmodel, attpath, modelStats }) {
  return async function (file, formData, options) {
    const requestFromData = {
      attmodel,
      attpath,
    };

    if (props.attlsh) {
      requestFromData.attlsh = props.attlsh;
    }

    await uploadFile({
      tempFilePath: file.url,
      formData: requestFromData,
      data,
      error,
      loading,
    });

    if (!error.value) {
      options.onSuccess('', file, formData);
      // 处理返回的文件ID
      let dataObject = data.value;
      if (typeof data.value === 'string') {
        dataObject = JSON.parse(data.value);
      }
      const newFileIds = [...props.fileIds];
      newFileIds.push({
        url: file.url,
        id: dataObject.Data,
      });
      emit('update:fileIds', newFileIds);
    }
  };
}

上传钩子实现

文件上传的核心逻辑在 src/hooks/useUpload.ts 中实现:

export function uploadFile<T>({ tempFilePath, formData, data, error, loading }) {
  return new Promise((resolve, reject) => {
    const appStore = useAppStore()
    uni.uploadFile({
      url: VITE_UPLOAD_BASEURL + '/api/attachment/addimg',
      filePath: tempFilePath,
      name: 'file',
      formData,
      header: {
        token: `${appStore.appInfo.token}`, // 请求token
      },
      success: (uploadFileRes) => {
        const decryptedRes = decryptResponse(uploadFileRes)
        data.value = decryptedRes.data as T
        resolve(data.value)
      },
      fail: (err) => {
        console.error('uni.uploadFile err->', err)
        error.value = true
        reject(err)
      },
      complete: () => {
        loading.value = false
      },
    })
  })
}

数据库表结构

文件上传相关的数据存储在 attachment 表中,表结构如下:

CREATE TABLE `attachment` (
  `attid` varchar(32) NOT NULL COMMENT '附件ID(查询条件)',
  `attname` varchar(32) NOT NULL COMMENT '文件名',
  `attpath` varchar(200) NOT NULL COMMENT '路径',
  `atttype` varchar(10) NOT NULL COMMENT '扩展名',
  `attsize` varchar(20) NOT NULL COMMENT '文件大小',
  `attmodel` varchar(20) NOT NULL COMMENT '关联模块(查询条件)',
  `attlsh` varchar(32) DEFAULT NULL COMMENT '关联表单流水号(查询条件)',
  `attcreate` datetime NOT NULL COMMENT '创建时间#不可编辑(禁止前端编辑)(查询条件)',
  `attcreateuser` varchar(30) DEFAULT NULL COMMENT '上传者#不可编辑(禁止前端编辑)',
  `attdelcode` tinyint(4) DEFAULT NULL COMMENT '删除标记(禁止前端编辑)(禁止插入)',
  `attother1` varchar(50) DEFAULT NULL COMMENT '附加参数1',
  `attother2` varchar(50) DEFAULT NULL COMMENT '附加参数2',
  `attother3` varchar(50) DEFAULT NULL COMMENT '附加参数3',
  `attorginname` varchar(255) DEFAULT NULL COMMENT '文件原始名称',
  `attfileSHA1` varchar(100) DEFAULT NULL COMMENT '文件SHA1值',
  `attfileSHA256` varchar(100) DEFAULT NULL COMMENT '文件SHA256值',
  `attfileMD5` varchar(100) DEFAULT NULL COMMENT '文件MD5值',
  PRIMARY KEY (`attid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='附件';

总结

项目中的文件上传功能采用了统一的上传接口,通过不同的参数来区分不同类型的文件。上传成功后,服务器返回文件ID,前端将这些ID收集起来,在表单提交时统一提交给后端。这种设计简化了文件上传的实现,同时保持了足够的灵活性来处理不同类型的文件上传需求。