20260518172616
This commit is contained in:
1 parent
2e704bbbb0
commit
5cfc87eee8
8 files changed
+500
-276
No files matched your search
+77
@@ -304,4 +304,81 @@ public class FileController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/deletes")
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public Result<Void> deleteFiles(@RequestBody List<Object> subids) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
if (subids == null || subids.isEmpty()) {
|
||||||
|
return Result.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Object subidObj : subids) {
|
||||||
|
|
||||||
|
if (subidObj == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Long subid = Long.valueOf(subidObj.toString());
|
||||||
|
|
||||||
|
// 1. 查询文件记录
|
||||||
|
List<Map<String, Object>> maps = dbUtils.loadData(
|
||||||
|
"SELECT * FROM bf_file WHERE subid = ?",
|
||||||
|
subid
|
||||||
|
);
|
||||||
|
|
||||||
|
if (maps.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> objectMap = maps.get(0);
|
||||||
|
|
||||||
|
// 2. 获取文件路径
|
||||||
|
String mxMapfilename = objectMap.get("mx_mapfilename") == null
|
||||||
|
? ""
|
||||||
|
: objectMap.get("mx_mapfilename").toString();
|
||||||
|
|
||||||
|
// 3. 删除本地文件
|
||||||
|
if (StringUtils.isNotBlank(mxMapfilename)) {
|
||||||
|
|
||||||
|
String filePath = PathUtils.joinFilePath(
|
||||||
|
fileConfig.getBaseDir(),
|
||||||
|
mxMapfilename
|
||||||
|
);
|
||||||
|
|
||||||
|
boolean deleted = FileUtils.deleteFileByPath(filePath);
|
||||||
|
|
||||||
|
if (!deleted) {
|
||||||
|
System.out.println("文件删除失败或不存在: " + filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 删除数据库记录
|
||||||
|
dbUtils.deleteById("bf_file", "subid", subid);
|
||||||
|
|
||||||
|
// 5. 记录日志
|
||||||
|
Map<String, Object> mapData = new HashMap<>();
|
||||||
|
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
String dataStr = objectMapper.writeValueAsString(objectMap);
|
||||||
|
|
||||||
|
String currentDateTime = TimeUtils.getDateTime();
|
||||||
|
|
||||||
|
mapData.put("b_table", "bf_file");
|
||||||
|
mapData.put("b_option", "DELETE");
|
||||||
|
mapData.put("b_datas", dataStr);
|
||||||
|
mapData.put("b_inputdatetime", currentDateTime);
|
||||||
|
mapData.put("b_inputuser_id", UserContext.get().getUserId());
|
||||||
|
|
||||||
|
dbUtils.insert("log_datas", "b_id", mapData);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.ok();
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return Result.fail("批量删除失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -16,7 +16,7 @@ spring:
|
|||||||
time-zone: "Asia/Shanghai"
|
time-zone: "Asia/Shanghai"
|
||||||
date-format: yyyy-MM-dd HH:mm:ss
|
date-format: yyyy-MM-dd HH:mm:ss
|
||||||
profiles:
|
profiles:
|
||||||
active: build
|
active: dev
|
||||||
|
|
||||||
file:
|
file:
|
||||||
base-dir: D:/data/file
|
base-dir: D:/data/file
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
#url=jdbc:sqlserver://118.89.70.199:1433;databaseName=G3BoxOCR
|
url=jdbc:sqlserver://118.89.70.199:1433;databaseName=G3BoxOCR
|
||||||
#username=sa
|
|
||||||
#password=zhang520..
|
|
||||||
#driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
|
|
||||||
|
|
||||||
url=jdbc:sqlserver://127.0.0.1:1433;databaseName=G3ContainerOCR
|
|
||||||
username=sa
|
username=sa
|
||||||
password=123456@aaa
|
password=zhang520..
|
||||||
driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
|
driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
|
||||||
|
|
||||||
|
#url=jdbc:sqlserver://127.0.0.1:1433;databaseName=G3ContainerOCR
|
||||||
|
#username=sa
|
||||||
|
#password=123456@aaa
|
||||||
|
#driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
|
||||||
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
import type { UploadFile, UploadFileItem } from 'sard-uniapp'
|
import type { UploadFile, UploadFileItem } from 'sard-uniapp'
|
||||||
import { dialog, isImageUrl, isVideoUrl, toast } from 'sard-uniapp'
|
import { dialog, isImageUrl, isVideoUrl, toast } from 'sard-uniapp'
|
||||||
import { getOrgBaseUrl } from '@/request'
|
import { getOrgBaseUrl } from '@/request'
|
||||||
import { deleteFileApi, loadDataApi, saveObjectApi, uploadContainerFileApi } from '@/request/api'
|
import { deleteFileApi, deleteFilesApi, loadDataApi, saveObjectApi, uploadContainerFileApi } from '@/request/api'
|
||||||
import { useUserStore } from '@/store'
|
import { useUserStore } from '@/store'
|
||||||
import { buildPubicUrl, downloadFile, getFileExtension, imageCompress, isImage } from '@/utils/file'
|
import { buildPubicUrl, downloadFile, getFileExtension, imageCompress, isImage } from '@/utils/file'
|
||||||
|
|
||||||
@@ -14,6 +14,12 @@ const form = ref<any>({
|
|||||||
b_container_img: '',
|
b_container_img: '',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const subFileListRef = ref()
|
||||||
|
const subFileListRef2 = ref()
|
||||||
|
|
||||||
|
const oldSubFileList = ref([])
|
||||||
|
const oldSubFileList2 = ref([])
|
||||||
|
|
||||||
const subFileList = ref([]) // 装货照片
|
const subFileList = ref([]) // 装货照片
|
||||||
const subFileList2 = ref([]) // 发货单、签收单、过磅单
|
const subFileList2 = ref([]) // 发货单、签收单、过磅单
|
||||||
|
|
||||||
@@ -101,6 +107,9 @@ async function loadMainData() {
|
|||||||
subFileList2.value = allFiles
|
subFileList2.value = allFiles
|
||||||
.filter(f => f.mx_cate_id === '2')
|
.filter(f => f.mx_cate_id === '2')
|
||||||
.map(formatFile)
|
.map(formatFile)
|
||||||
|
|
||||||
|
oldSubFileList.value = JSON.parse(JSON.stringify(subFileList.value))
|
||||||
|
oldSubFileList2.value = JSON.parse(JSON.stringify(subFileList2.value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
@@ -111,51 +120,19 @@ async function loadMainData() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onItemClick(fileItem: UploadFileItem) {
|
function handleBeforeRemove({ file, fileList, resolve }) {
|
||||||
console.log(fileItem)
|
dialog.confirm({
|
||||||
if (!isImageUrl(fileItem.mx_mapfilename) && !isVideoUrl(fileItem.mx_mapfilename)) {
|
title: '提示',
|
||||||
downloadFile(fileItem.mx_mapfilename, fileItem.name)
|
message: '确定删除该文件吗?',
|
||||||
}
|
onConfirm: () => {
|
||||||
}
|
resolve(true)
|
||||||
|
},
|
||||||
function beforeRead(file: UploadFile): boolean | Promise<UploadFile> {
|
onCancel: () => {
|
||||||
// 非图片直接允许上传
|
resolve(false)
|
||||||
if (!isImage(file.name))
|
},
|
||||||
return true
|
|
||||||
|
|
||||||
// 图片异步压缩,返回修改后的 UploadFile 对象
|
|
||||||
return imageCompress(file.path).then((res) => {
|
|
||||||
file.path = res.path
|
|
||||||
file.size = res.size
|
|
||||||
return file
|
|
||||||
}).catch((err) => {
|
|
||||||
console.error('图片压缩失败:', err)
|
|
||||||
return file
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function beforeRemove(_index: number, _fileItem: UploadFileItem): boolean | Promise<void> {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
dialog.confirm({
|
|
||||||
title: '提示',
|
|
||||||
message: `确定删除该张图片吗?`,
|
|
||||||
onConfirm: () => resolve(),
|
|
||||||
onCancel: () => reject(),
|
|
||||||
onClose: () => reject(),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function onRemove(index: number, item: UploadFileItem) {
|
|
||||||
if (item.subid) {
|
|
||||||
deleteFileApi(item.subid).then((res) => {
|
|
||||||
if (res.success) {
|
|
||||||
toast.success('删除成功')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handleConfirm() {
|
async function handleConfirm() {
|
||||||
if (form.value.b_container_img === '') {
|
if (form.value.b_container_img === '') {
|
||||||
toast.fail('集装箱号图片不能为空')
|
toast.fail('集装箱号图片不能为空')
|
||||||
@@ -177,91 +154,209 @@ async function handleConfirm() {
|
|||||||
transparent: false,
|
transparent: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
const fileInserts = []
|
try {
|
||||||
const fileUpdates = []
|
const fileInserts = []
|
||||||
|
const fileUpdates = []
|
||||||
|
const fileDeletes = []
|
||||||
|
|
||||||
const allFiles = [
|
// =========================
|
||||||
...subFileList.value.map(item => ({ ...item, cate: '1' })),
|
// 当前上传组件文件
|
||||||
...subFileList2.value.map(item => ({ ...item, cate: '2' })),
|
// =========================
|
||||||
]
|
const subFiles
|
||||||
|
= subFileListRef.value?.$.setupState.uploadFiles || []
|
||||||
|
|
||||||
const grouped = allFiles.reduce((acc, item) => {
|
const subFiles2
|
||||||
if (!acc[item.cate])
|
= subFileListRef2.value?.$.setupState.uploadFiles || []
|
||||||
acc[item.cate] = []
|
|
||||||
acc[item.cate].push(item)
|
|
||||||
return acc
|
|
||||||
}, {})
|
|
||||||
|
|
||||||
for (const cate in grouped) {
|
// 当前所有文件
|
||||||
let index = 1
|
const allFiles = [
|
||||||
|
...subFiles.map(item => ({
|
||||||
|
...item,
|
||||||
|
cate: '1',
|
||||||
|
})),
|
||||||
|
...subFiles2.map(item => ({
|
||||||
|
...item,
|
||||||
|
cate: '2',
|
||||||
|
})),
|
||||||
|
]
|
||||||
|
|
||||||
for (const fileItem of grouped[cate]) {
|
// 原始文件
|
||||||
const mx_xh = index++
|
const oldFiles = [
|
||||||
|
...(oldSubFileList.value || []).map(item => ({
|
||||||
|
...item,
|
||||||
|
cate: '1',
|
||||||
|
})),
|
||||||
|
...(oldSubFileList2.value || []).map(item => ({
|
||||||
|
...item,
|
||||||
|
cate: '2',
|
||||||
|
})),
|
||||||
|
]
|
||||||
|
|
||||||
// 已存在 → update
|
// =========================
|
||||||
if (fileItem.subid) {
|
// 删除文件
|
||||||
fileUpdates.push({
|
// =========================
|
||||||
subid: fileItem.subid,
|
const currentSubIds = new Set(
|
||||||
mx_xh,
|
allFiles
|
||||||
mx_cate_id: cate,
|
.map(item => item.subid)
|
||||||
})
|
.filter(Boolean),
|
||||||
continue
|
)
|
||||||
|
|
||||||
|
fileDeletes.push(
|
||||||
|
...oldFiles
|
||||||
|
.filter(item =>
|
||||||
|
item.subid
|
||||||
|
&& !currentSubIds.has(item.subid),
|
||||||
|
)
|
||||||
|
.map(item => ({
|
||||||
|
subid: item.subid,
|
||||||
|
})),
|
||||||
|
)
|
||||||
|
|
||||||
|
// =========================
|
||||||
|
// 分类排序
|
||||||
|
// =========================
|
||||||
|
const grouped = allFiles.reduce((acc, item) => {
|
||||||
|
if (!acc[item.cate]) {
|
||||||
|
acc[item.cate] = []
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新增 → upload
|
acc[item.cate].push(item)
|
||||||
const res = await uploadContainerFileApi(fileItem.file.path, {
|
|
||||||
jobId: form.value.b_id,
|
|
||||||
containerNo: form.value.b_container_no,
|
|
||||||
fileName: fileItem.name,
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!res.success)
|
return acc
|
||||||
continue
|
}, {})
|
||||||
|
|
||||||
fileInserts.push({
|
// =========================
|
||||||
subid: res.data.uid,
|
// 处理新增/更新
|
||||||
father: form.value.b_id,
|
// =========================
|
||||||
mx_xh,
|
for (const cate in grouped) {
|
||||||
mx_filename: res.data.fileName,
|
let index = 1
|
||||||
mx_filesize: fileItem.file.size,
|
|
||||||
mx_fileext: getFileExtension(fileItem.file.name),
|
|
||||||
mx_mapfilename: res.data.path,
|
|
||||||
mx_moduleid: 'b_container',
|
|
||||||
mx_cate_id: cate,
|
|
||||||
})
|
|
||||||
|
|
||||||
fileItem.subid = res.data.uid
|
for (const fileItem of grouped[cate]) {
|
||||||
|
const mx_xh = index++
|
||||||
|
|
||||||
|
// 已存在 → update
|
||||||
|
if (fileItem.subid) {
|
||||||
|
fileUpdates.push({
|
||||||
|
subid: fileItem.subid,
|
||||||
|
mx_xh,
|
||||||
|
mx_cate_id: cate,
|
||||||
|
})
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 上传路径
|
||||||
|
let uploadPath
|
||||||
|
= fileItem.path
|
||||||
|
|| fileItem.url
|
||||||
|
|| fileItem.tempFilePath
|
||||||
|
|
||||||
|
// 图片压缩
|
||||||
|
if (isImage(fileItem.name)) {
|
||||||
|
const compressRes = await imageCompress(uploadPath)
|
||||||
|
|
||||||
|
uploadPath = compressRes.path
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上传文件
|
||||||
|
const res = await uploadContainerFileApi(
|
||||||
|
uploadPath,
|
||||||
|
{
|
||||||
|
jobId: form.value.b_id,
|
||||||
|
containerNo: form.value.b_container_no,
|
||||||
|
fileName: fileItem.name,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!res.success) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增记录
|
||||||
|
fileInserts.push({
|
||||||
|
subid: res.data.uid,
|
||||||
|
father: form.value.b_id,
|
||||||
|
mx_xh,
|
||||||
|
mx_filename: res.data.fileName,
|
||||||
|
mx_filesize: fileItem.size,
|
||||||
|
mx_fileext: getFileExtension(fileItem.name),
|
||||||
|
mx_mapfilename: res.data.path,
|
||||||
|
mx_moduleid: 'b_container',
|
||||||
|
mx_cate_id: cate,
|
||||||
|
})
|
||||||
|
|
||||||
|
// 回填 subid
|
||||||
|
fileItem.subid = res.data.uid
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
console.error('附件上传失败:', fileItem, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (fileInserts.length === 0 && fileUpdates.length === 0) {
|
// =========================
|
||||||
toast.success('保存成功')
|
// 先删除物理文件
|
||||||
|
// =========================
|
||||||
|
if (fileDeletes.length > 0) {
|
||||||
|
const deleteRes = await deleteFilesApi(
|
||||||
|
fileDeletes.map(item => item.subid),
|
||||||
|
)
|
||||||
|
|
||||||
setTimeout(() => {
|
if (!deleteRes.success) {
|
||||||
loadMainData()
|
toast.fail('删除文件失败')
|
||||||
}, 1000)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const reqData = [
|
return
|
||||||
{
|
}
|
||||||
tableName: 'bf_file',
|
}
|
||||||
keyField: 'subid',
|
|
||||||
inserts: fileInserts,
|
|
||||||
updates: fileUpdates,
|
|
||||||
deletes: [],
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
saveObjectApi(reqData).then((res) => {
|
// =========================
|
||||||
if (res.success) {
|
// 无新增/更新
|
||||||
|
// 删除已经单独处理了
|
||||||
|
// =========================
|
||||||
|
if (
|
||||||
|
fileInserts.length === 0
|
||||||
|
&& fileUpdates.length === 0
|
||||||
|
) {
|
||||||
toast.success('保存成功')
|
toast.success('保存成功')
|
||||||
|
|
||||||
setTimeout(() => {
|
return
|
||||||
loadMainData()
|
|
||||||
}, 1000)
|
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
// =========================
|
||||||
|
// 保存数据
|
||||||
|
// =========================
|
||||||
|
const reqData = [
|
||||||
|
{
|
||||||
|
tableName: 'bf_file',
|
||||||
|
keyField: 'subid',
|
||||||
|
inserts: fileInserts,
|
||||||
|
updates: fileUpdates,
|
||||||
|
deletes: [],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const res = await saveObjectApi(reqData)
|
||||||
|
|
||||||
|
if (res.success) {
|
||||||
|
toast.success('保存成功')
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
toast.fail('保存失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
|
||||||
|
toast.fail('保存失败')
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
setTimeout(() => {
|
||||||
|
toast.hide()
|
||||||
|
|
||||||
|
loadMainData()
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 集装箱号校验
|
// 集装箱号校验
|
||||||
@@ -385,13 +480,14 @@ const templateCollapse = ref<string[]>(['template1'])
|
|||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
<view class="step-content">
|
<view class="step-content">
|
||||||
<sar-upload
|
<wd-upload
|
||||||
v-model="subFileList"
|
ref="subFileListRef"
|
||||||
|
v-model:file-list="subFileList"
|
||||||
|
:auto-upload="false"
|
||||||
|
:before-remove="handleBeforeRemove"
|
||||||
multiple
|
multiple
|
||||||
:before-read="beforeRead"
|
accept="all"
|
||||||
:before-remove="beforeRemove"
|
:max-size="50 * 1024 * 1024"
|
||||||
@item-click="onItemClick"
|
|
||||||
@remove="onRemove"
|
|
||||||
/>
|
/>
|
||||||
</view>
|
</view>
|
||||||
</wd-cell-group>
|
</wd-cell-group>
|
||||||
@@ -406,13 +502,14 @@ const templateCollapse = ref<string[]>(['template1'])
|
|||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
<view class="step-content">
|
<view class="step-content">
|
||||||
<sar-upload
|
<wd-upload
|
||||||
v-model="subFileList2"
|
ref="subFileListRef2"
|
||||||
|
v-model:file-list="subFileList2"
|
||||||
|
:auto-upload="false"
|
||||||
|
:before-remove="handleBeforeRemove"
|
||||||
multiple
|
multiple
|
||||||
:before-read="beforeRead"
|
accept="all"
|
||||||
:before-remove="beforeRemove"
|
:max-size="50 * 1024 * 1024"
|
||||||
@item-click="onItemClick"
|
|
||||||
@remove="onRemove"
|
|
||||||
/>
|
/>
|
||||||
</view>
|
</view>
|
||||||
</wd-cell-group>
|
</wd-cell-group>
|
||||||
|
|||||||
@@ -19,6 +19,9 @@ const form = ref({
|
|||||||
ocrNo: '',
|
ocrNo: '',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const subFileListRef = ref()
|
||||||
|
const subFileListRef2 = ref()
|
||||||
|
|
||||||
const subFileList = ref([]) // 装货照片
|
const subFileList = ref([]) // 装货照片
|
||||||
const subFileList2 = ref([]) // 发货单、签收单、过磅单
|
const subFileList2 = ref([]) // 发货单、签收单、过磅单
|
||||||
|
|
||||||
@@ -114,38 +117,16 @@ function handleDeleteBoxImage() {
|
|||||||
resetForm()
|
resetForm()
|
||||||
}
|
}
|
||||||
|
|
||||||
function onItemClick(fileItem: UploadFileItem) {
|
function handleBeforeRemove({ file, fileList, resolve }) {
|
||||||
console.log(fileItem)
|
dialog.confirm({
|
||||||
if (!isImageUrl(fileItem.mx_mapfilename) && !isVideoUrl(fileItem.mx_mapfilename)) {
|
title: '提示',
|
||||||
downloadFile(fileItem.mx_mapfilename, fileItem.name)
|
message: '确定删除该文件吗?',
|
||||||
}
|
onConfirm: () => {
|
||||||
}
|
resolve(true)
|
||||||
|
},
|
||||||
function beforeRead(file: UploadFile): boolean | Promise<UploadFile> {
|
onCancel: () => {
|
||||||
// 非图片直接允许上传
|
resolve(false)
|
||||||
if (!isImage(file.name))
|
},
|
||||||
return true
|
|
||||||
|
|
||||||
// 图片异步压缩,返回修改后的 UploadFile 对象
|
|
||||||
return imageCompress(file.path).then((res) => {
|
|
||||||
file.path = res.path
|
|
||||||
file.size = res.size
|
|
||||||
return file
|
|
||||||
}).catch((err) => {
|
|
||||||
console.error('图片压缩失败:', err)
|
|
||||||
return file
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function beforeRemove(_index: number, _fileItem: UploadFileItem): boolean | Promise<void> {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
dialog.confirm({
|
|
||||||
title: '提示',
|
|
||||||
message: `确定删除该张图片吗?`,
|
|
||||||
onConfirm: () => resolve(),
|
|
||||||
onCancel: () => reject(),
|
|
||||||
onClose: () => reject(),
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,7 +136,7 @@ async function handleConfirm() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (form.value.b_container_no === '') {
|
if (!form.value.b_container_no) {
|
||||||
toast.fail('集装箱号不能为空')
|
toast.fail('集装箱号不能为空')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -170,112 +151,154 @@ async function handleConfirm() {
|
|||||||
transparent: false,
|
transparent: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
const mainTable = {
|
try {
|
||||||
b_id: form.value.b_id,
|
const mainTable = {
|
||||||
b_container_no: form.value.b_container_no,
|
b_id: form.value.b_id,
|
||||||
b_container_img: form.value.b_container_img,
|
b_container_no: form.value.b_container_no,
|
||||||
b_ocr_no: form.value.ocrNo,
|
b_container_img: form.value.b_container_img,
|
||||||
b_ocr_score: form.value.ocrScore || 0.00,
|
b_ocr_no: form.value.ocrNo,
|
||||||
}
|
b_ocr_score: form.value.ocrScore || 0.00,
|
||||||
const fileInserts = []
|
}
|
||||||
|
|
||||||
// 主表
|
const fileInserts = []
|
||||||
await uploadContainerFileApi(boxImage.value.path, {
|
|
||||||
jobId: form.value.b_id,
|
// =========================
|
||||||
containerNo: form.value.b_container_no,
|
// 上传主图
|
||||||
fileName: boxImage.value.name,
|
// =========================
|
||||||
}).then((res) => {
|
const mainRes = await uploadContainerFileApi(
|
||||||
if (res.success) {
|
boxImage.value.path,
|
||||||
mainTable.b_container_img = res.data.path
|
{
|
||||||
|
jobId: form.value.b_id,
|
||||||
|
containerNo: form.value.b_container_no,
|
||||||
|
fileName: boxImage.value.name,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
if (mainRes.success) {
|
||||||
|
mainTable.b_container_img = mainRes.data.path
|
||||||
|
|
||||||
fileInserts.push({
|
fileInserts.push({
|
||||||
subid: res.data.uid,
|
subid: mainRes.data.uid,
|
||||||
father: form.value.b_id,
|
father: form.value.b_id,
|
||||||
mx_xh: 0,
|
mx_xh: 0,
|
||||||
mx_filename: res.data.fileName,
|
mx_filename: mainRes.data.fileName,
|
||||||
mx_filesize: boxImage.value.size,
|
mx_filesize: boxImage.value.size,
|
||||||
mx_fileext: getFileExtension(boxImage.value.name),
|
mx_fileext: getFileExtension(boxImage.value.name),
|
||||||
mx_mapfilename: res.data.path,
|
mx_mapfilename: mainRes.data.path,
|
||||||
mx_moduleid: 'b_container',
|
mx_moduleid: 'b_container',
|
||||||
mx_cate_id: '0',
|
mx_cate_id: '0',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
|
||||||
const indexMap = {}
|
// =========================
|
||||||
|
// 附件排序
|
||||||
|
// =========================
|
||||||
|
const indexMap = {}
|
||||||
|
|
||||||
const getNextIndex = (cate) => {
|
const getNextIndex = (cate) => {
|
||||||
if (!indexMap[cate]) {
|
if (!indexMap[cate]) {
|
||||||
indexMap[cate] = 1
|
indexMap[cate] = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return indexMap[cate]++
|
||||||
}
|
}
|
||||||
return indexMap[cate]++
|
|
||||||
}
|
|
||||||
|
|
||||||
const allFiles = [
|
// =========================
|
||||||
...subFileList.value.map(item => ({
|
// 获取附件
|
||||||
...item,
|
// =========================
|
||||||
cate: '1',
|
const subFiles = subFileListRef.value?.$.setupState.uploadFiles || []
|
||||||
})),
|
const subFiles2 = subFileListRef2.value?.$.setupState.uploadFiles || []
|
||||||
...subFileList2.value.map(item => ({
|
|
||||||
...item,
|
|
||||||
cate: '2',
|
|
||||||
})),
|
|
||||||
]
|
|
||||||
|
|
||||||
for (const fileItem of allFiles) {
|
const allFiles = [
|
||||||
const res = await uploadContainerFileApi(fileItem.file.path, {
|
...subFiles.map(item => ({
|
||||||
jobId: form.value.b_id,
|
...item,
|
||||||
containerNo: form.value.b_container_no,
|
cate: '1',
|
||||||
fileName: fileItem.name,
|
})),
|
||||||
})
|
...subFiles2.map(item => ({
|
||||||
|
...item,
|
||||||
|
cate: '2',
|
||||||
|
})),
|
||||||
|
]
|
||||||
|
|
||||||
if (!res.success)
|
// =========================
|
||||||
continue
|
// 上传附件
|
||||||
|
// =========================
|
||||||
|
for (const fileItem of allFiles) {
|
||||||
|
try {
|
||||||
|
let uploadPath = fileItem.url
|
||||||
|
|
||||||
fileInserts.push({
|
// 图片压缩
|
||||||
subid: res.data.uid,
|
if (isImage(fileItem.name)) {
|
||||||
father: form.value.b_id,
|
const compressRes = await imageCompress(fileItem.url)
|
||||||
mx_xh: getNextIndex(fileItem.cate),
|
uploadPath = compressRes.path
|
||||||
mx_filename: res.data.fileName,
|
}
|
||||||
mx_filesize: fileItem.file.size,
|
|
||||||
mx_fileext: getFileExtension(fileItem.file.name),
|
|
||||||
mx_mapfilename: res.data.path,
|
|
||||||
mx_moduleid: 'b_container',
|
|
||||||
mx_cate_id: fileItem.cate,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const reqData = [
|
const res = await uploadContainerFileApi(uploadPath, {
|
||||||
{
|
jobId: form.value.b_id,
|
||||||
tableName: 'b_container',
|
containerNo: form.value.b_container_no,
|
||||||
keyField: 'b_id',
|
fileName: fileItem.name,
|
||||||
inserts: [mainTable],
|
})
|
||||||
updates: [],
|
|
||||||
deletes: [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tableName: 'bf_file',
|
|
||||||
keyField: 'subid',
|
|
||||||
inserts: fileInserts,
|
|
||||||
updates: [],
|
|
||||||
deletes: [],
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
saveObjectApi(reqData).then((res) => {
|
if (!res.success) {
|
||||||
if (res.success) {
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fileInserts.push({
|
||||||
|
subid: res.data.uid,
|
||||||
|
father: form.value.b_id,
|
||||||
|
mx_xh: getNextIndex(fileItem.cate),
|
||||||
|
mx_filename: res.data.fileName,
|
||||||
|
mx_filesize: fileItem.size,
|
||||||
|
mx_fileext: getFileExtension(fileItem.name),
|
||||||
|
mx_mapfilename: res.data.path,
|
||||||
|
mx_moduleid: 'b_container',
|
||||||
|
mx_cate_id: fileItem.cate,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
console.error('附件上传失败:', fileItem, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// =========================
|
||||||
|
// 保存数据
|
||||||
|
// =========================
|
||||||
|
const reqData = [
|
||||||
|
{
|
||||||
|
tableName: 'b_container',
|
||||||
|
keyField: 'b_id',
|
||||||
|
inserts: [mainTable],
|
||||||
|
updates: [],
|
||||||
|
deletes: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tableName: 'bf_file',
|
||||||
|
keyField: 'subid',
|
||||||
|
inserts: fileInserts,
|
||||||
|
updates: [],
|
||||||
|
deletes: [],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const saveRes = await saveObjectApi(reqData)
|
||||||
|
|
||||||
|
if (saveRes.success) {
|
||||||
toast.success('保存成功')
|
toast.success('保存成功')
|
||||||
|
|
||||||
tipContainerNo.value = form.value.b_container_no
|
tipContainerNo.value = form.value.b_container_no
|
||||||
showResult.value = true
|
showResult.value = true
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
toast.fail('保存失败')
|
toast.fail('保存失败')
|
||||||
}
|
}
|
||||||
}).catch(() => {
|
}
|
||||||
|
catch (err) {
|
||||||
|
console.error(err)
|
||||||
toast.fail('保存失败')
|
toast.fail('保存失败')
|
||||||
}).finally(() => {
|
}
|
||||||
|
finally {
|
||||||
toast.hide()
|
toast.hide()
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 集装箱号校验
|
// 集装箱号校验
|
||||||
@@ -446,12 +469,14 @@ const templateCollapse = ref<string[]>(['template1'])
|
|||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
<view class="step-content">
|
<view class="step-content">
|
||||||
<sar-upload
|
<wd-upload
|
||||||
v-model="subFileList"
|
ref="subFileListRef"
|
||||||
|
v-model:file-list="subFileList"
|
||||||
|
:auto-upload="false"
|
||||||
|
:before-remove="handleBeforeRemove"
|
||||||
multiple
|
multiple
|
||||||
:before-read="beforeRead"
|
accept="all"
|
||||||
:before-remove="beforeRemove"
|
:max-size="50 * 1024 * 1024"
|
||||||
@item-click="onItemClick"
|
|
||||||
/>
|
/>
|
||||||
</view>
|
</view>
|
||||||
</wd-cell-group>
|
</wd-cell-group>
|
||||||
@@ -465,12 +490,14 @@ const templateCollapse = ref<string[]>(['template1'])
|
|||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
<view class="step-content">
|
<view class="step-content">
|
||||||
<sar-upload
|
<wd-upload
|
||||||
v-model="subFileList2"
|
ref="subFileListRef2"
|
||||||
|
v-model:file-list="subFileList2"
|
||||||
|
:auto-upload="false"
|
||||||
|
:before-remove="handleBeforeRemove"
|
||||||
multiple
|
multiple
|
||||||
:before-read="beforeRead"
|
accept="all"
|
||||||
:before-remove="beforeRemove"
|
:max-size="50 * 1024 * 1024"
|
||||||
@item-click="onItemClick"
|
|
||||||
/>
|
/>
|
||||||
</view>
|
</view>
|
||||||
</wd-cell-group>
|
</wd-cell-group>
|
||||||
|
|||||||
@@ -48,6 +48,10 @@ export function deleteFileApi(subid) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function deleteFilesApi(subids: any[]) {
|
||||||
|
return httpPost(`file/deletes`, subids)
|
||||||
|
}
|
||||||
|
|
||||||
export function deleteAliyunFileApi(fileUrl) {
|
export function deleteAliyunFileApi(fileUrl) {
|
||||||
return httpPost(`/file/deleteAliyunFile`, {
|
return httpPost(`/file/deleteAliyunFile`, {
|
||||||
bucketName: aliyunBucket,
|
bucketName: aliyunBucket,
|
||||||
|
|||||||
@@ -126,35 +126,63 @@ export function formatFileSize(size: number): string {
|
|||||||
|
|
||||||
/** 获取文件名:从 URL 提取最后一段 */
|
/** 获取文件名:从 URL 提取最后一段 */
|
||||||
function getFileName(fileUrl: string) {
|
function getFileName(fileUrl: string) {
|
||||||
return decodeURIComponent(fileUrl.split('/').pop() || '未命名文件')
|
return decodeURIComponent(
|
||||||
|
fileUrl.split('/').pop() || '未命名文件',
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 获取文件后缀 */
|
/** 获取文件后缀(根据文件名) */
|
||||||
export function getFileExtension(fileUrl: string) {
|
export function getFileExtension(fileName: string) {
|
||||||
const clean = fileUrl.split('?')[0].split('#')[0].trim()
|
const clean = fileName
|
||||||
|
.split('?')[0]
|
||||||
|
.split('#')[0]
|
||||||
|
.trim()
|
||||||
|
|
||||||
const lastDot = clean.lastIndexOf('.')
|
const lastDot = clean.lastIndexOf('.')
|
||||||
return lastDot === -1 ? '' : clean.substring(lastDot + 1).toLowerCase()
|
|
||||||
|
return lastDot === -1
|
||||||
|
? ''
|
||||||
|
: clean.substring(lastDot + 1).toLowerCase()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 文件类型判断 */
|
/** 文件类型判断(根据文件名) */
|
||||||
export function isImage(fileUrl: string) {
|
export function isImage(fileName: string) {
|
||||||
return ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp'].includes(getFileExtension(fileUrl))
|
return [
|
||||||
|
'jpg',
|
||||||
|
'jpeg',
|
||||||
|
'png',
|
||||||
|
'gif',
|
||||||
|
'webp',
|
||||||
|
'bmp',
|
||||||
|
].includes(getFileExtension(fileName))
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isVideo(fileUrl: string) {
|
export function isVideo(fileName: string) {
|
||||||
return ['mp4', 'avi', 'mov', 'mkv', 'flv', 'wmv', '3gp'].includes(getFileExtension(fileUrl))
|
return [
|
||||||
|
'mp4',
|
||||||
|
'avi',
|
||||||
|
'mov',
|
||||||
|
'mkv',
|
||||||
|
'flv',
|
||||||
|
'wmv',
|
||||||
|
'3gp',
|
||||||
|
].includes(getFileExtension(fileName))
|
||||||
}
|
}
|
||||||
|
|
||||||
/** =================== 下载入口 =================== */
|
/** =================== 下载入口 =================== */
|
||||||
export function downloadFile(fileUrl: string, fileName?: string) {
|
export function downloadFile(
|
||||||
const type: 'image' | 'video' | 'file' = isImage(fileUrl)
|
fileUrl: string,
|
||||||
? 'image'
|
fileName?: string,
|
||||||
: isVideo(fileUrl)
|
) {
|
||||||
? 'video'
|
|
||||||
: 'file'
|
|
||||||
|
|
||||||
const finalName = fileName ?? getFileName(fileUrl)
|
const finalName = fileName ?? getFileName(fileUrl)
|
||||||
|
|
||||||
|
const type: 'image' | 'video' | 'file'
|
||||||
|
= isImage(finalName)
|
||||||
|
? 'image'
|
||||||
|
: isVideo(finalName)
|
||||||
|
? 'video'
|
||||||
|
: 'file'
|
||||||
|
|
||||||
if (isH5) {
|
if (isH5) {
|
||||||
downloadH5(fileUrl, finalName)
|
downloadH5(fileUrl, finalName)
|
||||||
}
|
}
|
||||||
@@ -165,7 +193,6 @@ export function downloadFile(fileUrl: string, fileName?: string) {
|
|||||||
downloadApp(fileUrl, type, finalName)
|
downloadApp(fileUrl, type, finalName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** =================== H5 下载 =================== */
|
/** =================== H5 下载 =================== */
|
||||||
async function downloadH5(fileUrl: string, fileName: string) {
|
async function downloadH5(fileUrl: string, fileName: string) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
-8
@@ -18,7 +18,6 @@ declare module 'vue' {
|
|||||||
ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
|
ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
|
||||||
ElDialog: typeof import('element-plus/es')['ElDialog']
|
ElDialog: typeof import('element-plus/es')['ElDialog']
|
||||||
ElDivider: typeof import('element-plus/es')['ElDivider']
|
ElDivider: typeof import('element-plus/es')['ElDivider']
|
||||||
ElDrawer: typeof import('element-plus/es')['ElDrawer']
|
|
||||||
ElDropdown: typeof import('element-plus/es')['ElDropdown']
|
ElDropdown: typeof import('element-plus/es')['ElDropdown']
|
||||||
ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
|
ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
|
||||||
ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
|
ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
|
||||||
@@ -28,23 +27,16 @@ declare module 'vue' {
|
|||||||
ElInput: typeof import('element-plus/es')['ElInput']
|
ElInput: typeof import('element-plus/es')['ElInput']
|
||||||
ElMenu: typeof import('element-plus/es')['ElMenu']
|
ElMenu: typeof import('element-plus/es')['ElMenu']
|
||||||
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
|
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
|
||||||
ElOption: typeof import('element-plus/es')['ElOption']
|
|
||||||
ElPagination: typeof import('element-plus/es')['ElPagination']
|
ElPagination: typeof import('element-plus/es')['ElPagination']
|
||||||
ElPopover: typeof import('element-plus/es')['ElPopover']
|
ElPopover: typeof import('element-plus/es')['ElPopover']
|
||||||
ElRadio: typeof import('element-plus/es')['ElRadio']
|
ElRadio: typeof import('element-plus/es')['ElRadio']
|
||||||
ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
|
ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
|
||||||
ElResult: typeof import('element-plus/es')['ElResult']
|
ElResult: typeof import('element-plus/es')['ElResult']
|
||||||
ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
|
ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
|
||||||
ElSelect: typeof import('element-plus/es')['ElSelect']
|
|
||||||
ElSplitter: typeof import('element-plus/es')['ElSplitter']
|
ElSplitter: typeof import('element-plus/es')['ElSplitter']
|
||||||
ElSplitterPanel: typeof import('element-plus/es')['ElSplitterPanel']
|
ElSplitterPanel: typeof import('element-plus/es')['ElSplitterPanel']
|
||||||
ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
|
ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
|
||||||
ElSwitch: typeof import('element-plus/es')['ElSwitch']
|
ElSwitch: typeof import('element-plus/es')['ElSwitch']
|
||||||
ElTable: typeof import('element-plus/es')['ElTable']
|
|
||||||
ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
|
|
||||||
ElTabPane: typeof import('element-plus/es')['ElTabPane']
|
|
||||||
ElTabs: typeof import('element-plus/es')['ElTabs']
|
|
||||||
ElText: typeof import('element-plus/es')['ElText']
|
|
||||||
ElTooltip: typeof import('element-plus/es')['ElTooltip']
|
ElTooltip: typeof import('element-plus/es')['ElTooltip']
|
||||||
ElTree: typeof import('element-plus/es')['ElTree']
|
ElTree: typeof import('element-plus/es')['ElTree']
|
||||||
G3Column: typeof import('./src/components/g3-table/g3-column.vue')['default']
|
G3Column: typeof import('./src/components/g3-table/g3-column.vue')['default']
|
||||||
|
|||||||
Reference in new issue
Block a user