feat(biz): 订单模块新增详情查看和作废功能并优化附件管理
This commit is contained in:
parent
51b7227c5f
commit
18b50cee6f
@ -87,7 +87,7 @@ public class TsoOrderController {
|
||||
respPageResult.getList().forEach(item -> {
|
||||
AdminUserDO userEntity = userService.getUser(item.getSaleMan());
|
||||
if (userEntity != null) {
|
||||
item.setSaleManName(userEntity.getUsername());
|
||||
item.setSaleManName(userEntity.getNickname());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -39,6 +39,10 @@ public class SecurityConfiguration {
|
||||
.antMatchers(adminSeverContextPath + "/**").anonymous();
|
||||
// 文件读取
|
||||
registry.antMatchers(buildAdminApi("/infra/file/*/get/**")).permitAll();
|
||||
|
||||
registry.antMatchers(buildAdminApi("/infra/file/upload")).permitAll();
|
||||
registry.antMatchers(buildAdminApi("/infra/file/uploadBatch")).permitAll();
|
||||
registry.antMatchers(buildAdminApi("/infra/file/uploadWatch")).permitAll();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@ -2,9 +2,10 @@ package com.ningxia.yunxi.chemmes.module.infra.service.logger;
|
||||
|
||||
import com.ningxia.yunxi.chemmes.framework.common.pojo.PageResult;
|
||||
import com.ningxia.yunxi.chemmes.framework.common.util.object.BeanUtils;
|
||||
import com.ningxia.yunxi.chemmes.framework.tenant.core.aop.TenantIgnore;
|
||||
import com.ningxia.yunxi.chemmes.module.infra.api.logger.dto.ApiAccessLogCreateReqDTO;
|
||||
import com.ningxia.yunxi.chemmes.module.infra.dal.dataobject.logger.ApiAccessLogDO;
|
||||
import com.ningxia.yunxi.chemmes.module.infra.controller.admin.logger.vo.apiaccesslog.ApiAccessLogPageReqVO;
|
||||
import com.ningxia.yunxi.chemmes.module.infra.dal.dataobject.logger.ApiAccessLogDO;
|
||||
import com.ningxia.yunxi.chemmes.module.infra.dal.mysql.logger.ApiAccessLogMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
@ -27,6 +28,7 @@ public class ApiAccessLogServiceImpl implements ApiAccessLogService {
|
||||
private ApiAccessLogMapper apiAccessLogMapper;
|
||||
|
||||
@Override
|
||||
@TenantIgnore
|
||||
public void createApiAccessLog(ApiAccessLogCreateReqDTO createDTO) {
|
||||
ApiAccessLogDO apiAccessLog = BeanUtils.toBean(createDTO, ApiAccessLogDO.class);
|
||||
if (apiAccessLog.getResultMsg().length()>200){
|
||||
|
||||
@ -217,6 +217,7 @@
|
||||
<div class="product-detail">
|
||||
<div class="section-header">
|
||||
<h3 class="section-title">产品明细</h3>
|
||||
|
||||
<el-button type="primary" plain size="small" @click="openMaterialSelect">
|
||||
<Icon icon="ep:plus" /> 新增
|
||||
</el-button>
|
||||
@ -272,13 +273,53 @@
|
||||
<!-- 附件信息区域 -->
|
||||
<div class="attachment-info">
|
||||
<h3 class="section-title">附件信息</h3>
|
||||
<el-form-item label="附件">
|
||||
<div class="upload-placeholder">
|
||||
<el-button type="primary" plain>
|
||||
<Icon icon="ep:upload" class="mr-5px" /> 点击上传
|
||||
<el-form-item label="上传附件">
|
||||
<el-upload
|
||||
ref="uploadRef"
|
||||
:action="uploadUrl"
|
||||
:headers="uploadHeaders"
|
||||
:auto-upload="true"
|
||||
:limit="10"
|
||||
:on-success="handleUploadSuccess"
|
||||
:on-error="handleUploadError"
|
||||
:on-remove="handleRemoveFile"
|
||||
:on-exceed="handleExceed"
|
||||
class="upload-component"
|
||||
@before-upload="handleBeforeUpload"
|
||||
>
|
||||
<el-button type="primary" plain size="small">
|
||||
<Icon icon="ep:upload" class="mr-5px" /> 上传文件
|
||||
</el-button>
|
||||
<span class="upload-tip">支持格式:doc, docx, pdf, jpg, jpeg, png 单个文件不超过50MB</span>
|
||||
<template #tip>
|
||||
<div class="upload-tip">
|
||||
支持扩展名: xls, xlsx, doc, docx, pdf, jpg...
|
||||
</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
|
||||
<!-- 文件列表表格 -->
|
||||
<el-table
|
||||
v-if="uploadedFiles.length > 0"
|
||||
:data="uploadedFiles"
|
||||
border
|
||||
size="small"
|
||||
class="mt-20px"
|
||||
>
|
||||
<el-table-column type="index" label="序号" width="80" align="center" />
|
||||
<el-table-column prop="name" label="文件名称" align="center" />
|
||||
<el-table-column prop="uploadTime" label="上传时间" width="200" align="center" />
|
||||
<el-table-column label="操作" width="80" align="center">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
type="text"
|
||||
size="small"
|
||||
@click="removeUploadedFile(scope.row)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
@ -331,6 +372,12 @@ const deptTreeRef = ref()
|
||||
const userList = ref<UserApi.UserVO[]>([])
|
||||
const userSelectLoading = ref(false)
|
||||
|
||||
// 文件上传相关
|
||||
const uploadRef = ref()
|
||||
const uploadUrl = import.meta.env.VITE_UPLOAD_URL
|
||||
const uploadHeaders = ref({})
|
||||
const uploadedFiles = ref<Array<{ id: string; name: string; uploadTime: string; url: string }>>([])
|
||||
|
||||
// 用途数据字典
|
||||
const purposeOptions = ref([])
|
||||
|
||||
@ -497,6 +544,24 @@ const open = async (type: string, id?: number) => {
|
||||
const rows = Array.isArray(rawItems) ? rawItems : (rawItems != null ? [rawItems] : [])
|
||||
productList.value = rows.length ? rows.map((r) => ({ ...r })) : []
|
||||
|
||||
// 处理附件信息回显
|
||||
const rawAttFile = data?.attFile
|
||||
if (rawAttFile) {
|
||||
try {
|
||||
const attFileArray = typeof rawAttFile === 'string' ? JSON.parse(rawAttFile) : rawAttFile
|
||||
if (Array.isArray(attFileArray)) {
|
||||
uploadedFiles.value = attFileArray.map((item: any) => ({
|
||||
id: item.filePath?.split('/').pop() || Date.now().toString(),
|
||||
name: item.fileName,
|
||||
uploadTime: item.uploadTime || '-',
|
||||
url: item.filePath
|
||||
}))
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('解析附件信息失败', e)
|
||||
}
|
||||
}
|
||||
|
||||
console.log('处理后productList:', productList.value)
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
@ -532,6 +597,16 @@ const submitForm = async () => {
|
||||
|
||||
await formRef.value?.validate?.()
|
||||
formLoading.value = true
|
||||
|
||||
// 将上传的文件列表同步到 formData.attFile
|
||||
if (uploadedFiles.value.length > 0) {
|
||||
formData.attFile = JSON.stringify(uploadedFiles.value.map(item => ({
|
||||
fileName: item.name,
|
||||
filePath: item.url,
|
||||
uploadTime: item.uploadTime
|
||||
})))
|
||||
}
|
||||
|
||||
const data = {
|
||||
...formData,
|
||||
items: productList.value,
|
||||
@ -561,6 +636,16 @@ const submitAudit = async () => {
|
||||
|
||||
await formRef.value?.validate?.()
|
||||
formLoading.value = true
|
||||
|
||||
// 将上传的文件列表同步到 formData.attFile
|
||||
if (uploadedFiles.value.length > 0) {
|
||||
formData.attFile = JSON.stringify(uploadedFiles.value.map(item => ({
|
||||
fileName: item.name,
|
||||
filePath: item.url,
|
||||
uploadTime: item.uploadTime
|
||||
})))
|
||||
}
|
||||
|
||||
const data = {
|
||||
...formData,
|
||||
ordStatus: 2,
|
||||
@ -580,6 +665,9 @@ const submitAudit = async () => {
|
||||
}
|
||||
|
||||
const resetForm = () => {
|
||||
// 清空附件列表
|
||||
uploadedFiles.value = []
|
||||
|
||||
// 重置表单数据,确保每个字段都是正确的类型
|
||||
formData.id = undefined
|
||||
formData.saleOrdNo = '自动生成'
|
||||
@ -771,6 +859,59 @@ const validateProductList = () => {
|
||||
const removeProductItem = (index: number) => {
|
||||
productList.value.splice(index, 1)
|
||||
}
|
||||
// 添加上传开始时间记录
|
||||
const uploadStartTime = ref<Map<string, number>>(new Map())
|
||||
|
||||
// 文件上传前记录开始时间
|
||||
const handleBeforeUpload = (file: any) => {
|
||||
uploadStartTime.value.set(file.name, Date.now())
|
||||
}
|
||||
|
||||
// 文件上传成功处理
|
||||
const handleUploadSuccess = (response: any, file: any, fileList: any) => {
|
||||
if (response.code === 0) {
|
||||
const fileUrl = response.data
|
||||
// 计算上传耗时(秒)
|
||||
const startTime = uploadStartTime.value.get(file.name) || Date.now()
|
||||
const uploadDuration = ((Date.now() - startTime) / 1000).toFixed(2) + 's'
|
||||
uploadStartTime.value.delete(file.name)
|
||||
|
||||
const fileId = fileUrl.split('/').pop() || Date.now().toString()
|
||||
|
||||
uploadedFiles.value.push({
|
||||
id: fileId,
|
||||
name: file.name,
|
||||
uploadTime: uploadDuration, // 显示上传耗时,如 "2.35s"
|
||||
url: fileUrl
|
||||
})
|
||||
// ...
|
||||
}
|
||||
}
|
||||
|
||||
// 文件上传失败时清理开始时间
|
||||
const handleUploadError = (error: any, file: any, fileList: any) => {
|
||||
uploadStartTime.value.delete(file.name)
|
||||
message.error('文件上传失败:' + (error.message || '未知错误'))
|
||||
}
|
||||
|
||||
// 文件移除处理
|
||||
const handleRemoveFile = (file: any, fileList: any) => {
|
||||
// 可以在这里添加删除服务器文件的逻辑
|
||||
}
|
||||
|
||||
// 文件超出限制处理
|
||||
const handleExceed = (files: any, fileList: any) => {
|
||||
message.warning(`最多只能上传10个文件`)
|
||||
}
|
||||
|
||||
// 删除已上传的文件
|
||||
const removeUploadedFile = (row: any) => {
|
||||
const index = uploadedFiles.value.findIndex(item => item.id === row.id)
|
||||
if (index > -1) {
|
||||
uploadedFiles.value.splice(index, 1)
|
||||
message.success('文件删除成功')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@ -832,8 +973,9 @@ const removeProductItem = (index: number) => {
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
@ -871,10 +1013,17 @@ const removeProductItem = (index: number) => {
|
||||
z-index: 2001;
|
||||
}
|
||||
|
||||
.upload-component {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.upload-tip {
|
||||
display: block;
|
||||
margin-top: 8px;
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.mt-20px {
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -101,7 +101,7 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="合同编号" align="center" prop="contractNo" width="120px" />
|
||||
<el-table-column label="业务人员" align="center" prop="saleMan" width="120px" />
|
||||
<el-table-column label="业务人员" align="center" prop="saleManName" width="120px" />
|
||||
<el-table-column label="是否变更" align="center" prop="isChange" width="120px">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.SYSTEM_IS_CELL" :value="scope.row.isChange" />
|
||||
@ -125,8 +125,16 @@
|
||||
<dict-tag :type="DICT_TYPE.SHIPPING_STATUS" :value="scope.row.deliveryStatus" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" width="180px" fixed="right">
|
||||
<el-table-column label="操作" align="center" width="300px" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="openDetail(scope.row.id)"
|
||||
v-hasPermi="['biz:order:query']"
|
||||
>
|
||||
详情
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@ -136,13 +144,22 @@
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="warning"
|
||||
v-if="scope.row.ordStatus === 1"
|
||||
@click="handleInvalidate(scope.row)"
|
||||
v-hasPermi="['biz:order:update']"
|
||||
>
|
||||
作废
|
||||
</el-button>
|
||||
<!-- <el-button
|
||||
link
|
||||
type="danger"
|
||||
@click="handleDelete(scope.row.id)"
|
||||
v-hasPermi="['biz:order:delete']"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</el-button> -->
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@ -157,6 +174,8 @@
|
||||
|
||||
<!-- 表单弹窗:添加/修改 -->
|
||||
<OrderForm ref="formRef" @success="getList" @close="handleQuery"/>
|
||||
<!-- 详情页面 -->
|
||||
<OrderDetail ref="detailRef" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
@ -164,6 +183,7 @@ import { getStrDictOptions, DICT_TYPE } from '@/utils/dict'
|
||||
import { dateFormatter, getCurrentMonthRange } from '@/utils/formatTime'
|
||||
import * as OrderApi from '@/api/biz/tsoorder/index'
|
||||
import OrderForm from './OrderForm.vue'
|
||||
import OrderDetail from './OrderDetail.vue'
|
||||
|
||||
defineOptions({ name: 'TsoOrder' })
|
||||
|
||||
@ -223,6 +243,12 @@ const openForm = (type: string, id?: number) => {
|
||||
formRef.value.open(type, id)
|
||||
}
|
||||
|
||||
/** 详情操作 */
|
||||
const detailRef = ref()
|
||||
const openDetail = (id: number) => {
|
||||
detailRef.value.open(id)
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (id: number) => {
|
||||
try {
|
||||
@ -236,9 +262,26 @@ const handleDelete = async (id: number) => {
|
||||
} catch {}
|
||||
}
|
||||
|
||||
/** 作废按钮操作 */
|
||||
const handleInvalidate = async (row: any) => {
|
||||
try {
|
||||
// 作废的二次确认
|
||||
await message.confirm(`是否确认作废订单编号为"${row.saleOrdNo}"的数据项?`)
|
||||
// 调用更新接口,将订单状态设置为9
|
||||
await OrderApi.updateOrder({
|
||||
id: row.id,
|
||||
ordStatus: 9
|
||||
})
|
||||
message.success('作废成功')
|
||||
// 刷新列表
|
||||
await getList()
|
||||
} catch {}
|
||||
}
|
||||
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(() => {
|
||||
// 默认不自动查询,需手动点击搜索按钮
|
||||
// 设置默认日期范围:当月1号到当天
|
||||
queryParams.ordDate = getCurrentMonthRange()
|
||||
})
|
||||
</script>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user