物料新增批量导入照片按钮

This commit is contained in:
2026-03-05 14:48:32 +08:00
parent 7f5ab90f22
commit 7058245cdf
4 changed files with 151 additions and 7 deletions

View File

@@ -77,3 +77,8 @@ export function parseImportMaterial(data: FormData) {
export function importMaterial(data: any) {
return http.post(`${BASE_URL}/import`, data)
}
/** @desc 解析物料信息导入数据 */
export function uploadMaterialPhotos(data: FormData) {
return http.post(`${BASE_URL}/import/uploadMaterialPhotos`, data)
}

View File

@@ -0,0 +1,134 @@
<template>
<a-drawer
v-model:visible="visible"
title="批量导入物料照片"
:mask-closable="false"
:esc-to-close="false"
:width="width >= 600 ? 600 : '100%'"
ok-text="确认导入"
cancel-text="取消导入"
@before-ok="save"
@close="reset"
>
<a-form ref="formRef" :model="form" size="large" auto-label-width>
<fieldset>
<legend>zip文件上传</legend>
<div class="file-box">
<a-upload
draggable
:custom-request="handleUpload"
:limit="1"
:show-retry-button="false"
:show-cancel-button="false"
tip="仅支持zip格式"
:file-list="uploadFile"
accept=".zip"
/>
</div>
</fieldset>
</a-form>
</a-drawer>
</template>
<script setup lang="ts">
import { type FormInstance, Message, type RequestOption } from '@arco-design/web-vue'
import { useWindowSize } from '@vueuse/core'
import { uploadMaterialPhotos } from '@/apis/material/materialInfo'
import { useResetReactive } from '@/hooks'
const emit = defineEmits<{
(e: 'save-success'): void
}>()
const { width } = useWindowSize()
const visible = ref(false)
const formRef = ref<FormInstance>()
const uploadFile = ref([])
// 新增:保存上传的文件对象
const uploadFileObj = ref<File | null>(null)
// 移除不必要的表单字段,只保留空对象即可
const [form, resetForm] = useResetReactive({})
// 重置
const reset = () => {
formRef.value?.resetFields()
uploadFile.value = []
uploadFileObj.value = null // 重置文件对象
resetForm()
}
// 修改上传逻辑:仅保存文件对象,不做解析
const handleUpload = (options: RequestOption) => {
const { onProgress, onError, onSuccess, fileItem } = options
onProgress(100) // 直接标记上传完成(仅前端显示)
// 保存文件对象供后续提交使用
uploadFileObj.value = fileItem.file as File
uploadFile.value = [fileItem] // 更新文件列表显示
Message.success('文件已选择,点击确认导入即可上传')
onSuccess({}) // 通知上传组件完成
return {
abort() {
// 空实现取消时会走reset逻辑
},
}
}
// 执行导入:直接上传文件到后端
const save = async () => {
try {
// 校验是否选择了文件
if (!uploadFileObj.value) {
Message.warning('请先选择要上传的ZIP文件')
return false
}
// 构建FormData
const formData = new FormData()
formData.append('zipFile', uploadFileObj.value) // 后端接收参数名保持为zipFile
// 调用后端照片批量导入接口
await uploadMaterialPhotos(formData)
Message.success('物料照片批量导入成功!')
emit('save-success') // 通知父组件刷新列表
visible.value = false // 关闭抽屉
return true
} catch (error) {
Message.error('物料照片导入失败,请重试!')
return false
}
}
// 打开抽屉
const onOpen = () => {
reset()
visible.value = true
}
defineExpose({ onOpen })
</script>
<style scoped lang="scss">
fieldset {
padding: 15px 15px 0 15px;
margin-bottom: 15px;
border: 1px solid var(--color-neutral-3);
border-radius: 3px;
}
fieldset legend {
color: rgb(var(--gray-10));
padding: 2px 5px 2px 5px;
border: 1px solid var(--color-neutral-3);
border-radius: 3px;
}
.file-box {
margin-bottom: 20px;
margin-left: 10px;
}
</style>

View File

@@ -33,8 +33,11 @@
<template #icon><icon-download /></template>
<template #default>导出</template>
</a-button>
<a-button v-permission="['admin:materialInfo:import']" @click="onPhotosImport">
<template #icon><icon-upload /></template>
<template #default>照片批量导入</template>
</a-button>
</template>
<!-- 物料照片插槽核心新增部分 -->
<template #photoUrl="{ record }">
<div class="photo-container">
<img
@@ -65,12 +68,14 @@
<MaterialInfoAddModal ref="MaterialInfoAddModalRef" @save-success="search" />
<MaterialInfoImportDrawer ref="MaterialInfoImportDrawerRef" @save-success="search" />
<PhotosImport ref="PhotosImportRef" @save-success="search"/>
</div>
</template>
<script setup lang="ts">
import MaterialInfoAddModal from './MaterialInfoAddModal.vue'
import MaterialInfoImportDrawer from './MaterialInfoImportDrawer.vue'
import PhotosImport from '@/views/material/PhotosImport.vue';
import { type MaterialInfoQuery, type MaterialInfoResp, deleteMaterialInfo, exportMaterialInfo, listMaterialInfo } from '@/apis/material/materialInfo'
import type { TableInstanceColumns } from '@/components/GiTable/type'
import { useDownload, useTable } from '@/hooks'
@@ -153,6 +158,11 @@ const MaterialInfoImportDrawerRef = ref<InstanceType<typeof MaterialInfoImportDr
const onImport = () => {
MaterialInfoImportDrawerRef.value?.onOpen()
}
const PhotosImportRef = ref<InstanceType<typeof PhotosImport>>()
const onPhotosImport = () => {
PhotosImportRef.value?.onOpen()
}
</script>
<style scoped lang="scss">

View File

@@ -204,7 +204,7 @@ const reset = () => {
const onDelete = (record: UserResp) => {
return handleDelete(() => deleteUser(record.id), {
content: `是否确定删除用户「${record.nickname}(${record.username})」?`,
content: `是否确定删除用户「${record.username}」?`,
showModal: true,
})
}
@@ -227,11 +227,6 @@ const onUpdate = (record: UserResp) => {
UserAddDrawerRef.value?.onUpdate(record.id)
}
const UserDetailDrawerRef = ref<InstanceType<typeof UserDetailDrawer>>()
const onDetail = (record: UserResp) => {
UserDetailDrawerRef.value?.onOpen(record.id)
}
const UserResetPwdModalRef = ref<InstanceType<typeof UserResetPwdModal>>()
const onResetPwd = (record: UserResp) => {
UserResetPwdModalRef.value?.onOpen(record.id)