mirror of
https://gitee.com/xiaonuobase/snowy.git
synced 2026-10-06 06:52:58 +08:00
【优化】文件上传组件支持文件名称正常回显及多职位选不到的优化
This commit is contained in:
@@ -80,6 +80,10 @@ export default {
|
||||
fileGetFileListByUrlList(data) {
|
||||
return request('getFileListByUrlList', data)
|
||||
},
|
||||
// 根据文件id集合获取文件集合
|
||||
fileGetFileListByIds(data) {
|
||||
return request('getFileListByIds', data)
|
||||
},
|
||||
// 删除文件
|
||||
fileDelete(data) {
|
||||
return request('delete', data)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
v-if="props.uploadMode === 'file'"
|
||||
v-model:file-list="fileList"
|
||||
name="file"
|
||||
:multiple="props.uploadNumber > 1"
|
||||
:action="action"
|
||||
:headers="headers"
|
||||
:maxCount="props.uploadNumber"
|
||||
@@ -23,6 +24,7 @@
|
||||
v-if="props.uploadMode === 'video'"
|
||||
v-model:file-list="fileList"
|
||||
name="file"
|
||||
:multiple="props.uploadNumber > 1"
|
||||
:action="action"
|
||||
:headers="headers"
|
||||
:maxCount="props.uploadNumber"
|
||||
@@ -45,6 +47,7 @@
|
||||
v-if="props.uploadMode === 'image'"
|
||||
v-model:file-list="fileList"
|
||||
name="file"
|
||||
:multiple="props.uploadNumber > 1"
|
||||
:action="action"
|
||||
:headers="headers"
|
||||
:maxCount="props.uploadNumber"
|
||||
@@ -84,7 +87,7 @@
|
||||
v-if="props.uploadMode === 'drag'"
|
||||
v-model:fileList="fileList"
|
||||
name="file"
|
||||
:multiple="true"
|
||||
:multiple="props.uploadNumber > 1"
|
||||
:action="action"
|
||||
:headers="headers"
|
||||
:maxCount="props.uploadNumber"
|
||||
@@ -108,6 +111,7 @@
|
||||
|
||||
<script setup name="uploadIndex">
|
||||
import tool from '@/utils/tool'
|
||||
import fileApi from '@/api/dev/fileApi'
|
||||
import { convertUrl } from '@/utils/apiAdaptive'
|
||||
import { message, Upload } from 'ant-design-vue'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
@@ -205,9 +209,25 @@
|
||||
|
||||
// 构造文件对象
|
||||
const buildFileObject = (url, id) => {
|
||||
let name = id
|
||||
if (url) {
|
||||
// 提取最后一段路径
|
||||
name = url.substring(url.lastIndexOf('/') + 1)
|
||||
// 去除查询参数
|
||||
if (name.includes('?')) {
|
||||
name = name.split('?')[0]
|
||||
}
|
||||
// 特殊处理:如果是 download 接口且带 id 参数,尝试提取 id 作为备选名称
|
||||
if ((name === 'download' || !name) && url.includes('id=')) {
|
||||
const match = url.match(/[?&]id=([^&]+)/)
|
||||
if (match) {
|
||||
name = match[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
data: url ? url : '/api' + props.uploadIdDownloadUrl + id,
|
||||
name: url ? url : id,
|
||||
name: name,
|
||||
url: url ? url : '/api' + props.uploadIdDownloadUrl + id,
|
||||
status: 'done',
|
||||
response: {
|
||||
@@ -218,22 +238,37 @@
|
||||
}
|
||||
// 处理回显
|
||||
const echo = (newVal) => {
|
||||
const oldFileList = cloneDeep(fileList.value)
|
||||
fileList.value = []
|
||||
const idsToFetch = []
|
||||
const urlsToFetch = []
|
||||
|
||||
// 字符串隔离情况
|
||||
if (props.uploadResultCategory === 'interval') {
|
||||
// id隔离
|
||||
if (props.uploadResultType === 'id') {
|
||||
newVal.split(',').forEach((id) => {
|
||||
const file = buildFileObject(undefined, id)
|
||||
fileList.value.push(file)
|
||||
fileList.value.reverse()
|
||||
const existing = oldFileList.find((f) => f.response?.data === id)
|
||||
if (existing) {
|
||||
fileList.value.push(existing)
|
||||
} else {
|
||||
const file = buildFileObject(undefined, id)
|
||||
fileList.value.push(file)
|
||||
idsToFetch.push(id)
|
||||
}
|
||||
})
|
||||
}
|
||||
// url隔离
|
||||
if (props.uploadResultType === 'url') {
|
||||
newVal.split(',').forEach((url) => {
|
||||
const file = buildFileObject(url)
|
||||
fileList.value.push(file)
|
||||
fileList.value.reverse()
|
||||
const existing = oldFileList.find((f) => f.url === url || f.response?.data === url)
|
||||
if (existing) {
|
||||
fileList.value.push(existing)
|
||||
} else {
|
||||
const file = buildFileObject(url)
|
||||
fileList.value.push(file)
|
||||
urlsToFetch.push(url)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -258,25 +293,66 @@
|
||||
// id数组
|
||||
if (props.uploadResultType === 'id') {
|
||||
newVal.forEach((id) => {
|
||||
fileList.value.push(buildFileObject(undefined, id))
|
||||
const existing = oldFileList.find((f) => f.response?.data === id)
|
||||
if (existing) {
|
||||
fileList.value.push(existing)
|
||||
} else {
|
||||
const file = buildFileObject(undefined, id)
|
||||
fileList.value.push(file)
|
||||
idsToFetch.push(id)
|
||||
}
|
||||
})
|
||||
}
|
||||
// url数组
|
||||
if (props.uploadResultType === 'url') {
|
||||
newVal.forEach((url) => {
|
||||
fileList.value.push(buildFileObject(url))
|
||||
const existing = oldFileList.find((f) => f.url === url || f.response?.data === url)
|
||||
if (existing) {
|
||||
fileList.value.push(existing)
|
||||
} else {
|
||||
const file = buildFileObject(url)
|
||||
fileList.value.push(file)
|
||||
urlsToFetch.push(url)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 异步获取文件详情以修正名称
|
||||
if (idsToFetch.length > 0) {
|
||||
fileApi.fileGetFileListByIds(idsToFetch).then((data) => {
|
||||
if (data) {
|
||||
fileList.value.forEach((file) => {
|
||||
const detail = data.find((d) => d.id === file.response?.data)
|
||||
if (detail) {
|
||||
file.name = detail.name
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
if (urlsToFetch.length > 0) {
|
||||
fileApi.fileGetFileListByUrlList({ urlList: urlsToFetch }).then((data) => {
|
||||
if (data) {
|
||||
fileList.value.forEach((file) => {
|
||||
const detail = data.find((d) => d.downloadPath === file.url || d.downloadPath === file.response?.data)
|
||||
if (detail) {
|
||||
file.name = detail.name
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
// 监听参数
|
||||
watch(
|
||||
() => props.value,
|
||||
(newVal) => {
|
||||
if (props.value && newVal) {
|
||||
fileList.value = []
|
||||
if (newVal) {
|
||||
echo(newVal)
|
||||
} else {
|
||||
fileList.value = []
|
||||
}
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
@@ -337,49 +413,49 @@
|
||||
}
|
||||
// 上传事件
|
||||
const handleChange = (uploads) => {
|
||||
let result = []
|
||||
const file = uploads.file
|
||||
if (file && (file.status === 'done' || file.status === 'removed') && file.response && file.response.code === 200) {
|
||||
uploads.fileList.forEach((f) => {
|
||||
result.push(f)
|
||||
})
|
||||
}
|
||||
if (result.length > 0) {
|
||||
if (props.uploadResultCategory === 'interval') {
|
||||
const resultIntervalValue = ref('')
|
||||
result.forEach((data) => {
|
||||
resultIntervalValue.value =
|
||||
data.response.data + (resultIntervalValue.value ? ',' + resultIntervalValue.value : '')
|
||||
})
|
||||
emit('update:value', resultIntervalValue)
|
||||
emit('onSuccessful', resultIntervalValue)
|
||||
emit('onChange', resultIntervalValue)
|
||||
} else if (props.uploadResultCategory === 'array') {
|
||||
if (props.completeResult) {
|
||||
// 得去掉数组里面的thumbUrl,一个base64太大,无用
|
||||
let newResult = cloneDeep(result)
|
||||
newResult.map((e) => {
|
||||
if (e.thumbUrl) {
|
||||
delete e.thumbUrl
|
||||
}
|
||||
})
|
||||
emit('update:value', newResult)
|
||||
emit('onSuccessful', newResult)
|
||||
emit('onChange', newResult)
|
||||
} else {
|
||||
const resultArrayValue = ref([])
|
||||
result.forEach((data) => {
|
||||
resultArrayValue.value.push(data.response.data)
|
||||
})
|
||||
emit('update:value', resultArrayValue)
|
||||
emit('onSuccessful', resultArrayValue)
|
||||
emit('onChange', resultArrayValue)
|
||||
}
|
||||
if (file.status === 'done' || file.status === 'removed') {
|
||||
if (file.status === 'done' && file.response && file.response.code !== 200) {
|
||||
message.error(file.response.message || '上传失败')
|
||||
return
|
||||
}
|
||||
return
|
||||
const result = uploads.fileList.filter((f) => f.status === 'done' && f.response && f.response.code === 200)
|
||||
if (result.length > 0) {
|
||||
if (props.uploadResultCategory === 'interval') {
|
||||
let resultIntervalValue = ''
|
||||
result.forEach((data) => {
|
||||
resultIntervalValue = (resultIntervalValue ? resultIntervalValue + ',' : '') + data.response.data
|
||||
})
|
||||
emit('update:value', resultIntervalValue)
|
||||
emit('onSuccessful', resultIntervalValue)
|
||||
emit('onChange', resultIntervalValue)
|
||||
} else if (props.uploadResultCategory === 'array') {
|
||||
if (props.completeResult) {
|
||||
// 得去掉数组里面的thumbUrl,一个base64太大,无用
|
||||
let newResult = cloneDeep(result)
|
||||
newResult.map((e) => {
|
||||
if (e.thumbUrl) {
|
||||
delete e.thumbUrl
|
||||
}
|
||||
})
|
||||
emit('update:value', newResult)
|
||||
emit('onSuccessful', newResult)
|
||||
emit('onChange', newResult)
|
||||
} else {
|
||||
let resultArrayValue = []
|
||||
result.forEach((data) => {
|
||||
resultArrayValue.push(data.response.data)
|
||||
})
|
||||
emit('update:value', resultArrayValue)
|
||||
emit('onSuccessful', resultArrayValue)
|
||||
emit('onChange', resultArrayValue)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
emit('update:value', undefined)
|
||||
emit('onChange', undefined)
|
||||
}
|
||||
emit('update:value', undefined)
|
||||
emit('onChange', undefined)
|
||||
}
|
||||
// 通过DOM获取上传的文件
|
||||
const uploadFileList = () => {
|
||||
|
||||
@@ -95,9 +95,9 @@
|
||||
<a-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<a-form-item label="任职信息" name="positionJson">
|
||||
<a-row :gutter="10" class="bg-[var(--item-hover-bg)] p-1 mb-2.5 !mx-0">
|
||||
<a-col :span="7" class="text-center truncate"> 机构 </a-col>
|
||||
<a-col :span="7" class="text-center truncate"> 岗位 </a-col>
|
||||
<a-col :span="7" class="text-center truncate"> 主管 </a-col>
|
||||
<a-col :span="7" class="truncate"> 机构 </a-col>
|
||||
<a-col :span="7" class="truncate"> 岗位 </a-col>
|
||||
<a-col :span="7" class="truncate"> 主管 </a-col>
|
||||
<a-col :span="3">
|
||||
<a-button type="primary" @click="addDomains()" size="small">
|
||||
<PlusOutlined />
|
||||
@@ -107,7 +107,7 @@
|
||||
</a-row>
|
||||
<div :key="positionInfo" v-for="(positionInfo, index) in formData.positionJson">
|
||||
<a-row :gutter="10" class="!mx-0">
|
||||
<a-col :xs="24" :sm="24" :md="7" :lg="7" :xl="7" class="text-center truncate">
|
||||
<a-col :xs="24" :sm="24" :md="7" :lg="7" :xl="7" class="truncate">
|
||||
<a-form-item
|
||||
:name="['positionJson', index, 'orgId']"
|
||||
:rules="{ required: true, message: '请选择机构' }"
|
||||
@@ -122,7 +122,7 @@
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :xs="24" :sm="24" :md="7" :lg="7" :xl="7" class="text-center truncate">
|
||||
<a-col :xs="24" :sm="24" :md="7" :lg="7" :xl="7" class="truncate">
|
||||
<a-form-item
|
||||
:name="['positionJson', index, 'positionId']"
|
||||
:rules="{ required: true, message: '请选择岗位' }"
|
||||
@@ -137,7 +137,7 @@
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :xs="24" :sm="24" :md="7" :lg="7" :xl="7" class="text-center truncate">
|
||||
<a-col :xs="24" :sm="24" :md="7" :lg="7" :xl="7" class="truncate">
|
||||
<a-form-item :name="['positionJson', index, 'directorId']">
|
||||
<xn-page-select
|
||||
ref="xnChildUserPageSelectRef"
|
||||
@@ -314,6 +314,16 @@
|
||||
convertFormData(record).then(() => {
|
||||
const allOrgIds = collectAllOrgIds()
|
||||
orgTreeSelectRef.value.echo(allOrgIds)
|
||||
// 子表树回显
|
||||
nextTick(() => {
|
||||
if (formData.value.positionJson) {
|
||||
formData.value.positionJson.forEach((item, index) => {
|
||||
if (childTreeSelectRefs.value[index]) {
|
||||
childTreeSelectRefs.value[index].echo(allOrgIds)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
} else if (orgId) {
|
||||
orgTreeSelectRef.value.echo([orgId])
|
||||
@@ -390,6 +400,12 @@
|
||||
formData.value.positionJson = []
|
||||
}
|
||||
formData.value.positionJson.push({ orgId: undefined, positionId: undefined, directorId: undefined })
|
||||
nextTick(() => {
|
||||
const index = formData.value.positionJson.length - 1
|
||||
if (childTreeSelectRefs.value[index]) {
|
||||
childTreeSelectRefs.value[index].init()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const delDomains = (index) => {
|
||||
|
||||
@@ -95,9 +95,9 @@
|
||||
<a-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<a-form-item label="任职信息" name="positionJson">
|
||||
<a-row :gutter="10" class="bg-[var(--item-hover-bg)] p-1 mb-2.5 !mx-0">
|
||||
<a-col :span="7" class="text-center truncate"> 机构 </a-col>
|
||||
<a-col :span="7" class="text-center truncate"> 职位 </a-col>
|
||||
<a-col :span="7" class="text-center truncate"> 主管 </a-col>
|
||||
<a-col :span="7" class="truncate"> 机构 </a-col>
|
||||
<a-col :span="7" class="truncate"> 职位 </a-col>
|
||||
<a-col :span="7" class="truncate"> 主管 </a-col>
|
||||
<a-col :span="3" class="text-center">
|
||||
<a-button type="primary" @click="addDomains()" size="small">
|
||||
<PlusOutlined />
|
||||
@@ -107,7 +107,7 @@
|
||||
</a-row>
|
||||
<div :key="positionInfo" v-for="(positionInfo, index) in formData.positionJson">
|
||||
<a-row :gutter="10" class="!mx-0">
|
||||
<a-col :xs="24" :sm="24" :md="7" :lg="7" :xl="7" class="text-center truncate">
|
||||
<a-col :xs="24" :sm="24" :md="7" :lg="7" :xl="7" class="truncate">
|
||||
<a-form-item
|
||||
:name="['positionJson', index, 'orgId']"
|
||||
:rules="{ required: true, message: '请选择组织' }"
|
||||
@@ -122,7 +122,7 @@
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :xs="24" :sm="24" :md="7" :lg="7" :xl="7" class="text-center truncate">
|
||||
<a-col :xs="24" :sm="24" :md="7" :lg="7" :xl="7" class="truncate">
|
||||
<a-form-item
|
||||
:name="['positionJson', index, 'positionId']"
|
||||
:rules="{ required: true, message: '请选择职位' }"
|
||||
@@ -137,7 +137,7 @@
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :xs="24" :sm="24" :md="7" :lg="7" :xl="7" class="text-center truncate">
|
||||
<a-col :xs="24" :sm="24" :md="7" :lg="7" :xl="7" class="truncate">
|
||||
<a-form-item :name="['positionJson', index, 'directorId']">
|
||||
<xn-page-select
|
||||
ref="xnChildUserPageSelectRef"
|
||||
@@ -317,7 +317,16 @@
|
||||
const allOrgIds = collectAllOrgIds()
|
||||
// 主表树回显
|
||||
orgTreeSelectRef.value.echo(allOrgIds)
|
||||
// 任职信息的子行树回显(共享同一份 treeData,无需重复请求)
|
||||
// 子表树回显
|
||||
nextTick(() => {
|
||||
if (formData.value.positionJson) {
|
||||
formData.value.positionJson.forEach((item, index) => {
|
||||
if (childTreeSelectRefs.value[index]) {
|
||||
childTreeSelectRefs.value[index].echo(allOrgIds)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
} else if (orgId) {
|
||||
// 新增 + 预选组织
|
||||
@@ -403,6 +412,12 @@
|
||||
formData.value.positionJson = []
|
||||
}
|
||||
formData.value.positionJson.push({ orgId: undefined, positionId: undefined, directorId: undefined })
|
||||
nextTick(() => {
|
||||
const index = formData.value.positionJson.length - 1
|
||||
if (childTreeSelectRefs.value[index]) {
|
||||
childTreeSelectRefs.value[index].init()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 删减行
|
||||
|
||||
+12
@@ -278,6 +278,18 @@ public class DevFileController {
|
||||
return CommonResult.data(devFileService.detail(devFileIdParam));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据文件id集合获取文件集合
|
||||
*
|
||||
* @author yubaoshan
|
||||
* @date 2024/6/9 23:52
|
||||
**/
|
||||
@Operation(summary = "根据文件id集合获取文件集合")
|
||||
@PostMapping("/dev/file/getFileListByIds")
|
||||
public CommonResult<List<DevFile>> getFileListByIds(@RequestBody @Valid @NotEmpty(message = "集合不能为空") List<String> ids) {
|
||||
return CommonResult.data(devFileService.getFileListByIds(ids));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据文件url集合获取文件集合
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user