# 文件上传分析文档
## 概述
本文档分析了项目中购机者照片、证件附件和发票附件这三个文件上传功能的接口和参数。
## 文件上传接口
所有文件上传都使用同一个接口:
- **接口地址**: `/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张图片
### 代码示例
```vue
```
## 2. 证件附件上传
### 接口参数
| 参数名 | 类型 | 必填 | 说明 |
| -------- | ------ | ---- | ------------------------------ |
| file | File | 是 | 上传的图片文件 |
| attmodel | String | 是 | "coupon_identity" (关联模块) |
| attpath | String | 是 | "/coupon_identity/" (上传路径) |
| token | String | 是 | 用户认证token (在请求头中) |
### 使用场景
- **页面位置**: `src/pages/coupon/modify-info.vue`
- **是否必填**: 是
- **用途**: 根据用户类型上传不同的证件
- 个人用户:上传身份证照片
- 企业用户:上传营业执照照片
- **限制**: 最多上传1张图片
### 代码示例
```vue
```
## 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
### 代码示例
```vue
```
## 文件上传流程
1. 所有文件上传都使用同一个接口 `/api/attachment/addimg`
2. 通过 `attmodel` 和 `attpath` 参数区分不同类型的文件
3. 上传成功后,服务器返回文件ID,前端将文件ID保存到相应的数组中
4. 提交表单时,将所有文件ID通过逗号连接成一个字符串,通过 `filesid` 参数提交给后端
## 文件ID处理
在表单提交时,不同类型的文件ID会被收集到同一个数组中,然后通过逗号连接成一个字符串:
```javascript
// 示例代码
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. 文件删除功能
### 核心方法
```javascript
// 创建自定义上传方法
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` 中实现:
```javascript
export function uploadFile({ 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` 表中,表结构如下:
```sql
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收集起来,在表单提交时统一提交给后端。这种设计简化了文件上传的实现,同时保持了足够的灵活性来处理不同类型的文件上传需求。