b5d414d9af
Co-Authored-By: Claude <noreply@anthropic.com>
6.8 KiB
6.8 KiB
备货单车辆明细附件上传 设计
- 日期:2026-08-06
- 分支:feature/crm_pc
- 涉及前端:
src/views/crmpc/stocking/Add.vue、src/composables/useStockingForm.ts - 涉及后端:
stock_order_items.attachment(已加字段)、备货单 store/update/show 接口
1. 背景
添加备货单(Add.vue)时,车辆明细(items,每行一辆车)目前只能录入车型 / 颜色 / 价格等字段,没有附件。业务需要每辆车能上传若干附件(如该车相关文件),随车辆一起保存。
后端 stock_order_items 表已新增 attachment 字段(本次由后端同事完成)。
2. 需求
- 添加备货单时,车辆明细每辆车可上传多个附件。
- UI 为行内紧凑形态:每行一个「上传附件」入口,已传文件以文件名标签列出、可删除,不撑高行高。
- 附件随车辆数据一起提交,存入
stock_order_items.attachment。 - 字段名统一用
attachment,值为file_name字符串数组(与备货单级contract/pi_doc/transaction_slip的存储模式一致)。
3. 现状(复用基础)
- 车辆明细
items由useStockingForm(false)提供,每行item是ItemRow。 - 备货单级文件已有成熟模式:前端维护
FileItem[]({name, url, file_name},带 url 供预览/下载),提交时映射成file_name[]存入baseForm.contract等。 - 上传走通用接口
${VITE_API_URL}/ticket/upload?scene=stock_orders,header 带 token(useUploadHeaders),成功返回{ data: { original_name, file_url, file_name } }。此接口无需改动。 - 现成组件
MultiFileUpload(120px 大拖拽区)适合整页文件区,不适合塞进行内——故行内用el-upload直接内联。
4. 设计
4.1 数据层 useStockingForm.ts
ItemRow类型增加attachment_files: { name: string; url: string; file_name: string }[]。newItem()初始化attachment_files: []。- 提交映射
mappedItems增加:attachment: (it.attachment_files || []).map((f) => f.file_name) - 详情回填
populateFromDetail:从后端返回的it.attachment反解为attachment_files(格式见 4.4,Add 为新建不走回填,但 composable 与 edit 共享,一并支持)。 copyRow已是JSON.parse(JSON.stringify(...)),自动带上附件,无需改。- 草稿
pickDraftPayload已含items: toRaw(items.value),附件自然入草稿,无需改。 - 新增车辆附件上传/删除方法(仿现有
handleContractUpload等):handleItemAttachmentUpload(response: any, idx: number):校验response.code===200,把{ name: data.original_name, url: data.file_url, file_name: data.file_name }push 进items.value[idx].attachment_files。removeItemAttachment(idx: number, fileIdx: number):从items.value[idx].attachment_files删除指定项。
4.2 UI 层 Add.vue
在车辆明细 v-for="(item, idx) in items" 的行内末尾增加一个 ElCol「附件」:
<ElCol :sm="12" :md="12" :lg="6" :xl="4">
<ElFormItem label="附件" label-width="85px">
<el-upload
:action="`${VITE_API_URL}/ticket/upload?scene=stock_orders`"
:headers="uploadHeaders"
:show-file-list="false"
:before-upload="(file) => beforeItemAttachmentUpload(file)"
:on-success="(res) => handleItemAttachmentUpload(res, idx)"
multiple
:accept="itemAttachmentAccept"
>
<el-button size="small" type="primary" plain>上传附件</el-button>
</el-upload>
<div class="item-attachment-tags" v-if="item.attachment_files?.length">
<el-tag
v-for="(f, fIdx) in item.attachment_files"
:key="fIdx"
closable
@close="removeItemAttachment(idx, fIdx)"
style="margin: 2px 4px 2px 0"
>
{{ f.name }}
</el-tag>
</div>
</ElFormItem>
</ElCol>
VITE_API_URL、uploadHeaders(useUploadHeaders)、beforeItemAttachmentUpload(类型/大小校验,复用MultiFileUpload的 accept 与 10MB 限制)、handleItemAttachmentUpload、removeItemAttachment均由useStockingFormreturn,模板解构使用,与现有contractFiles等用法一致。
4.3 后端配合
stock_order_items.attachment字段已加(DB 就绪)。- 接口层需对接:
- store / update:接收
items[].attachment(file_name数组),写入stock_order_items.attachment(按 json/序列化存储)。 - show / detail:返回
items[].attachment(file_name数组,或含original_name/file_url的对象数组——见 4.4 约定)。
- store / update:接收
4.4 回填格式约定(需与后端对齐)
详情接口返回的 items[].attachment 有两种可能,择一与后端确认:
- A:
file_name字符串数组(如["xxx.pdf"])——前端回填时url需另行拼接,预览受限。 - B(推荐):对象数组(如
[{ original_name, file_url, file_name }],与/ticket/upload返回一致)——前端直接还原成attachment_files,预览/下载可用。
实现(plan)阶段以前端实际请求详情接口的返回为准;若为 A,前端按现有 populateFromDetail 中文件字段的拼 url 方式处理。
5. 安全 / 限制
- 复用
beforeUpload:类型限制.jpg,.jpeg,.png,.gif,.pdf,.doc,.docx,.xls,.xlsx,.txt,单文件 ≤ 10MB。 - 上传 header 带 token(
useUploadHeaders),鉴权由后端/ticket/upload既有机制处理。 attachment只存file_name,不含敏感信息。
6. 改动清单
| 端 | 文件 | 改动 |
|---|---|---|
| 前端 | src/composables/useStockingForm.ts |
ItemRow 加 attachment_files;newItem 初始化;mappedItems 映射 attachment;populateFromDetail 回填;新增 handleItemAttachmentUpload/removeItemAttachment/beforeItemAttachmentUpload/暴露 uploadHeaders |
| 前端 | src/views/crmpc/stocking/Add.vue |
车辆明细行末尾加「附件」ElCol(el-upload + 标签列表);解构新方法 |
| 后端 | store/update/show 接口 | 对接 items[].attachment(DB 字段已就绪) |
7. 验收标准
- 添加备货单:每辆车行有「上传附件」按钮,点选多文件逐个上传成功后,文件名以标签列出。
- 标签可点 × 删除;删除后提交不包含该文件。
- 提交备货单,Network 里
items[].attachment为对应file_name数组;后端stock_order_items.attachment落库正确。 - (后端 show 返回后)进入编辑/详情,已存附件能回显为标签列表。
- 超格式 / 超 10MB 文件被拦截并提示。
8. 未做项 / 后续
- 本次只改
Add.vue模板;stocking_edit.vue共用useStockingForm,数据层已支持,如需在编辑页也展示附件上传,后续加同款ElCol即可。 - 终版(final_add/final_edit)是否需要同等能力,待业务确认。