修改上传方法,添加上传组件,修改资质审核
main
zxf 5 days ago
parent df8a36ea16
commit b5108ac704

@ -26,6 +26,18 @@ export function cmcustUpdateApi(data) {
})
}
/**
* cmcust更新
* @param pram
*/
export function cmcustUpdateApiByFiles(data) {
return request({
url: `autogencode/cmcust/updateByFiles`,
method: 'POST',
data
})
}
/**
* cmcust详情
* @param pram

@ -0,0 +1,63 @@
import request from '@/utils/request'
/**
* 新增cmcustitem
* @param pram
*/
export function cmcustitemCreateApi(data) {
return request({
url: `autogencode/cmcustitem/save`,
method: 'POST',
data
})
}
/**
* cmcustitem更新
* @param pram
*/
export function cmcustitemUpdateApi(data) {
return request({
url: `autogencode/cmcustitem/update`,
method: 'POST',
data
})
}
/**
* cmcustitem详情
* @param pram
*/
export function cmcustitemDetailApi(id) {
return request({
url: `autogencode/cmcustitem/info/${id}`,
method: 'GET'
})
}
/**
* cmcustitem批量删除
* @param ids
*/
export function cmcustitemDeleteApi(ids) {
return request({
url: `autogencode/cmcustitem/delete`,
method: 'POST',
data: ids
})
}
/**
* cmcustitem列表
* @param pram
*/
export function cmcustitemListApi(params) {
return request({
url: `autogencode/cmcustitem/list`,
method: 'GET',
params
})
}

@ -50,13 +50,13 @@
<dict-tag :options="typeOptions" :value="file.remark"></dict-tag>
</div>
<div class="ele-upload-list__item-content">
<el-link :underline="false" @click="handleFileDownload(file)">
<span class="el-icon-document"> {{ getFileName(file.oldName) }} </span>
</el-link>
<div class="ele-upload-list__item-content-action">
<el-link :underline="false" @click="handleDelete(index)" type="danger">删除</el-link>
</div>
<el-link :href="getFullFileUrl(file.attachFileUrl)" :underline="false" target="_blank">
<span class="el-icon-document"> {{ getFileName(file.oldName) }} </span>
</el-link>
<div class="ele-upload-list__item-content-action">
<el-link :underline="false" @click="handleDelete(index)" type="danger">删除</el-link>
</div>
</div>
</li>
</transition-group>
</div>
@ -117,18 +117,28 @@ export default {
watch: {
value: {
handler(val) {
console.log('===== Watch value 触发 =====');
console.log('原始 value:', val);
if (val) {
let temp = 1;
const list = Array.isArray(val) ? val : [val];
this.fileList = list.map(function (item) {
// oldName attachFileUrl
item.oldName = item.oldName || '未知文件名';
item.attachFileUrl = item.attachFileUrl || '';
item.uid = item.uid || new Date().getTime() + temp++;
return item;
console.log('转换后的文件列表:', list);
//
this.fileList = list.map(function (item, index) {
console.log(`处理文件项 ${index} 前:`, item);
//
const newItem = JSON.parse(JSON.stringify(item));
//
newItem.oldName = newItem.oldName || '未知文件名';
newItem.attachFileUrl = newItem.attachFileUrl || '';
console.log(`处理文件项 ${index} 后:`, newItem);
return newItem;
});
console.log('最终 fileList:', this.fileList);
} else {
this.fileList = [];
console.log('值为空清空fileList');
}
},
deep: true,
@ -217,19 +227,31 @@ export default {
})
var _this = this;
console.log(this.baseUrl);
fileFileApi(formData, data).then(function (res) {
loading.close()
// code
//
// SystemAttachment
const fileInfo = res || {};
const newFile = {
id: fileInfo.id || '',
// SystemAttachment
// attIdfileId
attId: fileInfo.attId || fileInfo.id || '', // 使attIdfallbackid
fileId: fileInfo.fileId || fileInfo.id || '', // 使fileIdfallbackid
//
debugInfo: {
originalFileInfo: JSON.parse(JSON.stringify(fileInfo)),
timestamp: new Date().toISOString()
},
name: fileInfo.fileName || param.file.name, //
attDir: fileInfo.url || fileInfo.path || '', //
//
oldName: fileInfo.fileName || param.file.name,
attachFileUrl: fileInfo.url || fileInfo.path || '',
attachFileUrl: fileInfo.url || fileInfo.path || '',
remark: _this.uploadParame.remark || '',
uid: param.file.uid
// SystemAttachment
attSize: param.file.size ? param.file.size.toString() : '', //
attType: param.file.name ? param.file.name.split('.').pop().toLowerCase() : '' //
};
_this.uploadList.push(newFile);
_this.uploadedSuccessfully();
@ -239,21 +261,6 @@ export default {
_this.$message.error('上传失败,请重试')
})
},
//
handleUploadSuccess(res, file) {
//
if (res && res.code === 200) {
const newFile = {
id: res.id || '',
oldName: file.name,
attachFileUrl: res.url || '',
remark: this.uploadParame.remark || '',
uid: file.uid
};
this.uploadList.push(newFile);
this.uploadedSuccessfully();
}
},
handleRemove(file) {
this.fileList = this.fileList.filter(function (item) {
return item !== file;
@ -268,7 +275,11 @@ export default {
//
uploadedSuccessfully() {
if (this.number > 0 && this.uploadList.length === this.number) {
this.fileList = this.fileList.concat(this.uploadList);
// 使
const updatedFileList = JSON.parse(JSON.stringify(this.fileList));
//
updatedFileList.push(...this.uploadList);
this.fileList = updatedFileList;
this.uploadList = [];
this.number = 0;
this.$emit("input", this.fileList);
@ -285,16 +296,23 @@ export default {
},
// URL
getFullFileUrl(url) {
if (!url) return '';
// URLHTTP
if (url.startsWith('http://') || url.startsWith('https://')) {
return url;
if (!url) return '#'; // #
//
let path = url;
if (!path.startsWith('/')) {
path = '/' + path;
}
// baseUrl
//
const base = this.baseUrl.endsWith('/') ? this.baseUrl.slice(0, -1) : this.baseUrl;
const path = url.startsWith('/') ? url : '/' + url;
return base + path;
// baseUrl
const base = this.baseUrl && this.baseUrl.trim() !== '' ?
(this.baseUrl.endsWith('/') ? this.baseUrl.slice(0, -1) : this.baseUrl) :
'';
// URL
const fullUrl = base ? (base + path) : path;
console.log('构建的完整URL:', fullUrl);
return fullUrl;
},
//
listToString(list, separator) {
@ -304,76 +322,6 @@ export default {
strs += list[i].attachFileUrl + separator;
}
return strs !== '' ? strs.substr(0, strs.length - 1) : '';
},
//
handleFileDownload(file) {
//
this.$modal.loading("下载文件中,请稍候...");
// token
const token = getToken();
if (!token) {
this.$modal.closeLoading();
this.$modal.msgError("未获取到登录凭证,请重新登录");
return;
}
// XMLHttpRequest
const xhr = new XMLHttpRequest();
const fileUrl = this.getFullFileUrl(file.attachFileUrl);
xhr.open('GET', fileUrl, true);
// blob
xhr.responseType = 'blob';
// token
xhr.setRequestHeader('X-Token', token);
//
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
this.$modal.closeLoading();
if (xhr.status === 200) {
//
const url = window.URL.createObjectURL(new Blob([xhr.response]));
const link = document.createElement('a');
link.style.display = 'none';
link.href = url;
//
link.setAttribute('download', file.oldName || `file_${Date.now()}`);
document.body.appendChild(link);
link.click();
//
setTimeout(() => {
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
}, 100);
} else {
//
let errorMsg = `文件下载失败,状态码: ${xhr.status}`;
try {
//
const errorData = JSON.parse(xhr.responseText);
if (errorData.message) {
errorMsg = errorData.message;
}
} catch (e) {
// JSON
}
this.$modal.msgError(errorMsg);
}
}
};
//
xhr.onerror = () => {
this.$modal.closeLoading();
this.$modal.msgError("网络错误,文件下载失败");
};
//
xhr.send();
}
}
};

@ -1,162 +1,543 @@
<template>
<!-- 基于 Element UI 新增和修改弹窗 -->
<!-- 供应商资质详情弹窗 -->
<el-dialog
:title="!dataForm.id ? '添加' : '修改'"
:close-on-click-modal="false"
:visible.sync="visible">
<!-- 新增和修改表单 -->
<el-form :model="dataForm" :rules="dataRule" ref="dataForm" @keyup.enter.native="dataSubmit()" label-width="100px">
<!-- <el-form-item label="供应商id" prop="custId">
<el-input v-model="dataForm.custId" placeholder="供应商id"></el-input>
</el-form-item>-->
<el-form-item label="供应商名称" prop="custName">
<el-input v-model="dataForm.custName" placeholder="供应商名称"></el-input>
</el-form-item>
<!-- <el-form-item label="资质id" prop="qualifyId">
<el-input v-model="dataForm.qualifyId" placeholder="资质id"></el-input>
</el-form-item>-->
<el-form-item label="资质名称" prop="qualifyName">
<el-input v-model="dataForm.qualifyName" placeholder="资质名称"></el-input>
</el-form-item>
<!-- <el-form-item label="文件id" prop="fileId">
<el-input v-model="dataForm.fileId" placeholder="文件id"></el-input>
</el-form-item>-->
<el-form-item label="提交日期" prop="submitDate">
<el-input v-model="dataForm.submitDate" placeholder="提交日期"></el-input>
</el-form-item>
<el-form-item label="资质文件" prop="file">
<FileUploadVO v-model="dataForm.file" ></FileUploadVO>
</el-form-item>
<el-form-item label="是否通过" prop="isPass">
<el-input v-model="dataForm.isPass" placeholder="是否通过"></el-input>
</el-form-item>
<el-form-item label="不通过原因" prop="passContent">
<el-input v-model="dataForm.passContent" placeholder="不通过原因"></el-input>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-input v-model="dataForm.status" placeholder="状态"></el-input>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="dataForm.remark" placeholder="备注"></el-input>
</el-form-item>
</el-form>
title="供应商资质详情"
:close-on-click-modal="false"
:visible.sync="visible"
width="80%">
<!-- 供应商基础信息展示 -->
<div class="base-info">
<el-row :gutter="20">
<el-col :span="6">
<div class="info-item">
<span class="label">客户代码</span>
<span class="value">{{ dataForm.custCode }}</span>
</div>
</el-col>
<el-col :span="6">
<div class="info-item">
<span class="label">客户名称</span>
<span class="value">{{ dataForm.custName }}</span>
</div>
</el-col>
<el-col :span="6">
<div class="info-item">
<span class="label">营业执照号码</span>
<span class="value">{{ dataForm.licenseNumber || '' }}</span>
</div>
</el-col>
<el-col :span="6">
<div class="info-item">
<span class="label">联系方式</span>
<span class="value">{{ dataForm.contactWay }}</span>
</div>
</el-col>
<el-col :span="6">
<div class="info-item">
<span class="label">联系人</span>
<span class="value">{{ dataForm.contactPerson || '' }}</span>
</div>
</el-col>
<el-col :span="6">
<div class="info-item">
<span class="label">供应商类型</span>
<span class="value">{{ dataForm.supplierType || '' }}</span>
</div>
</el-col>
</el-row>
</div>
<!-- 资质列表展示 -->
<div class="qualify-list" v-if="qualifyList.length > 0">
<div v-for="(qualify, index) in qualifyList" :key="index" class="qualify-item">
<el-card shadow="hover">
<el-row :gutter="20">
<el-col :span="6">
<div class="info-item">
<span class="label">资质类型</span>
<span class="value">{{ qualify.qualifyType === '1' ? '基础资质' : '其他资质' }}</span>
</div>
</el-col>
<el-col :span="6">
<div class="info-item">
<span class="label">资质名称</span>
<span class="value">{{ qualify.qualifyName }}</span>
</div>
</el-col>
<el-col :span="6">
<div class="info-item">
<span class="label">是否必填</span>
<span class="value required" v-if="qualify.isRequired === '1'"></span>
<span class="value" v-else></span>
</div>
</el-col>
</el-row>
<el-divider></el-divider>
<div v-if="qualify.cmCustQualifyFileList && qualify.cmCustQualifyFileList.length > 0">
<el-row :gutter="20">
<el-col :span="6">
<div class="info-item">
<span class="label">提交日期</span>
<span class="value">{{ qualify.cmCustQualifyFileList[0].submitDate || '' }}</span>
</div>
</el-col>
<el-col :span="6">
<div class="info-item">
<span class="label">是否通过</span>
<span class="value success" v-if="qualify.cmCustQualifyFileList[0].isPass === '1'"></span>
<span class="value danger" v-else-if="qualify.cmCustQualifyFileList[0].isPass === '0'"></span>
<span class="value" v-else>-</span>
</div>
</el-col>
<el-col :span="6">
<div class="info-item">
<span class="label">状态</span>
<el-tag :type="getStatusType(qualify.cmCustQualifyFileList[0].status)">
{{ getStatusText(qualify.cmCustQualifyFileList[0].status) }}
</el-tag>
</div>
</el-col>
</el-row>
<el-divider></el-divider>
<div class="file-section">
<div class="info-item">
<span class="label">不通过原因</span>
<span class="value" v-if="qualify.cmCustQualifyFileList[0].status === '0'">
{{ qualify.cmCustQualifyFileList[0].remark || '无' }}
</span>
<span class="value" v-else>-</span>
</div>
<!-- 处理qualify.cmCustQualifyFileList中的files每个cmCustQualifyFileList可能有多个files -->
<!-- 使用FileUploadVO组件进行文件上传和预览 -->
<div v-for="(qualifyFile, fileIndex) in qualify.cmCustQualifyFileList" :key="fileIndex" class="file-group"
style="margin-bottom: 20px;">
<div v-if="qualify.cmCustQualifyFileList.length > 1" class="file-group-header">
<span style="font-weight: 500; color: #606266;">文件组 {{ fileIndex + 1 }}</span>
<el-button type="danger" size="small" @click="deleteQualifyFile(qualify, fileIndex)"
style="float: right; margin-top: -5px;">删除文件组</el-button>
</div>
<div v-else class="file-group-header">
<el-button type="danger" size="small" @click="deleteQualifyFile(qualify, fileIndex)"
style="float: right; margin-top: -5px;">删除文件组</el-button>
</div>
<FileUploadVO
:value="formatFilesForUploadVO(qualifyFile.files || [])"
@input="updateFileList($event, qualify, fileIndex)"
></FileUploadVO>
</div>
</div>
</div>
<div v-else class="no-file">
<span>暂无上传文件</span>
<el-button type="primary" size="small" @click="addNewQualifyFile(qualify)" style="margin-left: 10px;">上传文件
</el-button>
</div>
</el-card>
</div>
</div>
<div v-else class="no-data">
<el-empty description="暂无资质信息"></el-empty>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="visible = false">取消</el-button>
<el-button type="primary" @click="dataSubmit()"></el-button>
<el-button @click="visible = false">关闭</el-button>
<el-button type="primary" @click="saveQualifyFiles" :loading="loading">保存</el-button>
</span>
</el-dialog>
</template>
<script>
import * as api from '@/api/cmcustqualifyfile.js'
import FileUploadVO from '@/components/FileUploadVO/index.vue'
export default {
components: {
FileUploadVO
},
data () {
return {
visible: false,
dataForm: {
id: 0,
custId: '' ,
custName: '' ,
qualifyId: '' ,
qualifyName: '' ,
fileId: '' ,
fileUrl: '',
submitDate: '' ,
isPass: '' ,
passContent: '' ,
status: '' ,
remark: '' ,
},
fileList: [],
dataRule: {
custName: [
{ required: true, message: '供应商名称 为必填项', trigger: 'blur' }
],
qualifyName: [
{ required: true, message: '资质名称 为必填项', trigger: 'blur' }
],
}
import {cmcustDetailApi, cmcustUpdateApiByFiles} from '@/api/cmcust.js'
import {cmcustqualifyfileDeleteApi} from '@/api/cmcustqualifyfile.js'
import FileUploadVO from '@/components/FileUploadVO/index.vue'
export default {
components: {
FileUploadVO
},
data() {
return {
visible: false,
loading: false,
dataForm: {
id: 0,
custName: '',
custCode: '',
contactPerson: '',
contactWay: '',
licenseNumber: '',
supplierType: '',
createTime: '',
qualifyStatus: '',
remark: ''
},
qualifyList: []
}
},
methods: {
//
addNewQualifyFile(qualify) {
// cmCustQualifyFileList
if (!qualify.cmCustQualifyFileList) {
qualify.cmCustQualifyFileList = []
}
// files
qualify.cmCustQualifyFileList.push({
files: [],
submitDate: this.formatDateToYmdHms(new Date()), //
status: '2', //
isPass: '0',
remark: ''
});
//
this.$message.success('新增资质文件项成功')
},
methods: {
init (id) { //
this.dataForm.id = id || 0
this.visible = true
this.$nextTick(function() {
this.$refs['dataForm'].resetFields()
if (this.dataForm.id) {
api.cmcustqualifyfileDetailApi(id).then(function(res) {
this.dataForm = res;
//
if (res.fileId && res.fileUrl) {
this.fileList = [{
id: res.fileId,
oldName: res.fileUrl.split('/').pop() || '未知文件',
attachFileUrl: res.fileUrl
}];
} else if (res.fileId) {
this.fileList = [{
id: res.fileId,
oldName: '未知文件',
attachFileUrl: res.fileId
}];
} else {
this.fileList = [];
}
}.bind(this))
} else {
this.fileList = [];
}
}.bind(this))
},
//
dataSubmit () {
this.$refs['dataForm'].validate((valid) => {
if (valid) {
// fileListdataForm
if (this.fileList && this.fileList.length > 0) {
const file = this.fileList[0];
this.dataForm.fileId = file.id || '';
this.dataForm.fileUrl = file.attachFileUrl || '';
//
formatDateToYmdHms(date) {
const year = date.getFullYear();
// ////
const month = String(date.getMonth() + 1).padStart(2, '0'); // 0+1
const day = String(date.getDate()).padStart(2, '0');
const hour = String(date.getHours()).padStart(2, '0'); // 12date.getHours() % 12120
const minute = String(date.getMinutes()).padStart(2, '0');
const second = String(date.getSeconds()).padStart(2, '0');
// yyyy-MM-dd hh:mm:ss hh12HH24
return `${year}-${month}-${day} ${hour}:${minute}:${second}`;
},
//
saveQualifyFiles() {
//
const saveData = {
id: this.dataForm.id,
cmCustQualifyList: this.qualifyList
}
this.loading = true
console.log('保存的数据:', saveData)
// API
cmcustUpdateApiByFiles(saveData)
.then(res => {
console.log('保存API返回结果:', res)
// APInull
if (res) {
// code
if (res.code === 200 || res.code === undefined) {
this.$message.success('保存成功')
this.visible = false
} else {
this.dataForm.fileId = '';
this.dataForm.fileUrl = '';
this.$message.error(res.message || '保存失败')
}
} else {
// null
this.$message.success('保存成功')
this.visible = false
}
})
.catch(err => {
console.error('保存失败:', err)
this.$message.error('保存失败,请重试')
})
.finally(() => {
this.loading = false
})
},
this.$confirm('确认要' + (this.dataForm.id ? '修改' : '新增') + '吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(function() {
if (this.dataForm.id) {
api.cmcustqualifyfileUpdateApi(this.dataForm).then(function(res) {
if (res.code === 200) {
this.$message.success('操作成功')
this.visible = false
this.$emit('refreshDataList')
} else {
this.$message.error(res.msg || '操作失败')
}
}.bind(this))
} else {
api.cmcustqualifyfileCreateApi(this.dataForm).then(function(res) {
if (res.code === 200) {
this.$message.success('操作成功')
this.visible = false
this.$emit('refreshDataList')
} else {
this.$message.error(res.msg || '操作失败')
}
}.bind(this))
}
}.bind(this))
//
init(id) {
this.dataForm.id = id || 0
this.visible = true
this.qualifyList = []
if (this.dataForm.id) {
cmcustDetailApi(id).then(res => {
console.log('接口返回数据:', res)
//
this.dataForm = {
id: res.id || 0,
custName: res.custName || '',
custCode: res.custCode || '',
contactPerson: res.contactPerson || '',
contactWay: res.contactWay || '',
licenseNumber: res.licenseNumber || '',
supplierType: res.supplierType || '',
createTime: res.createTime || '',
qualifyStatus: res.qualifyStatus || '',
remark: res.remark || ''
}
//
if (res.cmCustQualifyList && Array.isArray(res.cmCustQualifyList)) {
this.qualifyList = res.cmCustQualifyList
}
}).catch(err => {
console.error('获取供应商详情失败:', err)
this.$message.error('获取供应商详情失败')
})
}
},
//
getStatusText(status) {
const statusMap = {
'0': '未通过',
'1': '已通过',
'2': '待审核'
}
return statusMap[String(status)] || '-'
},
//
getStatusType(status) {
const typeMap = {
'0': 'danger',
'1': 'success',
'2': 'warning'
}
return typeMap[String(status)] || 'info'
},
//
getQualifyStatusText(status) {
if (!status && status !== 0 && status !== '0') {
return '未知状态'
}
const statusMap = {
'0': '未提交',
'1': '部分提交',
'2': '已提交未审核',
'3': '审核通过',
'4': '审核未通过'
}
return statusMap[String(status)] || '未知状态'
},
//
getQualifyStatusType(status) {
if (!status && status !== 0 && status !== '0') {
return 'info'
}
const typeMap = {
'0': 'info',
'1': 'warning',
'2': 'warning',
'3': 'success',
'4': 'danger'
}
return typeMap[String(status)] || 'info'
},
// FileUploadVO
formatFilesForUploadVO(files) {
console.log('原始文件数据:', files)
if (!files || !Array.isArray(files)) {
return []
}
return files.map(file => {
// 使sattDir访
let attachFileUrl = file.sattDir || file.attDir || file.filePath || file.url || ''
// sattDir使
// sattDir
if (!file.sattDir && attachFileUrl && !attachFileUrl.startsWith('http')) {
//
attachFileUrl = attachFileUrl.replace(/(\/file\/public\/cm\/)+/g, '/file/public/cm/')
attachFileUrl = attachFileUrl.replace(/(file\/public\/cm\/)+/g, 'file/public/cm/')
}
// ID
const attId = file.id || file.fileId || ''
const fileId = file.id || file.fileId || ''
return {
// SystemAttachment
attId: attId.toString(), //
fileId: fileId.toString(), //
name: file.name || file.fileName || '',
oldName: file.name || file.fileName || '',
attachFileUrl: attachFileUrl,
attDir: file.attDir || file.filePath || file.url || '',
attSize: file.attSize || '',
attType: file.attType || '',
remark: file.remark || '',
uid: file.id || file.fileId || new Date().getTime()
}
})
},
// qualify.cmCustQualifyFileListfiles
updateFileList(newFiles, qualify, fileIndex) {
console.log('更新文件列表:', newFiles, qualify, fileIndex)
// qualify.cmCustQualifyFileListfiles
if (!qualify.cmCustQualifyFileList) {
qualify.cmCustQualifyFileList = []
}
if (!qualify.cmCustQualifyFileList[fileIndex]) {
qualify.cmCustQualifyFileList[fileIndex] = {}
}
// FileUploadVOSystemAttachment
const formattedFiles = newFiles.map(file => {
//
let attDir = file.attDir || file.attachFileUrl || ''
// /file/public/
if (attDir.startsWith('/file/public/')) {
attDir = attDir.replace('/file/public/', '')
} else if (attDir.startsWith('/file/')) {
attDir = attDir.replace('/file/', '')
}
// IDInteger
const attId = file.id || file.fileId || ''
const fileId = file.id || file.fileId || ''
return {
// SystemAttachment
attId: attId.toString(), //
fileId: fileId.toString(), // id
name: file.name || file.oldName || '', //
attDir: attDir, //
attSize: file.attSize || '', //
attType: file.attType || '', //
//
fileName: file.name || file.oldName || '',
filePath: attDir,
url: attDir,
createTime: null,
createdBy: null,
createTimeStr: null,
delFlag: '0',
updateBy: null,
updateTime: null,
i18nCode: '',
i18nLanguage: '',
originalFileName: file.name || file.oldName || '',
position: 0,
remark: file.remark || '',
sort: 0,
status: ''
}
})
// files
qualify.cmCustQualifyFileList[fileIndex].files = formattedFiles
console.log('更新后的文件数组:', qualify.cmCustQualifyFileList[fileIndex].files)
},
//
deleteQualifyFile(qualify, fileIndex) {
const qualifyFile = qualify.cmCustQualifyFileList[fileIndex]
//
this.$confirm('确定要删除这个资质文件吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
// ID
if (qualifyFile && qualifyFile.id) {
this.loading = true
let ids = [qualifyFile.id]
cmcustqualifyfileDeleteApi(ids)
.then(res => {
//
qualify.cmCustQualifyFileList.splice(fileIndex, 1)
this.$message.success('删除成功')
})
} else {
// ID
qualify.cmCustQualifyFileList.splice(fileIndex, 1)
this.$message.success('删除成功')
}
}).catch(() => {
//
this.$message.info('已取消删除')
})
}
}
}
</script>
<style scoped>
.base-info {
margin-bottom: 20px;
padding: 15px;
background-color: #f5f7fa;
border-radius: 4px;
}
.info-item {
margin-bottom: 10px;
line-height: 2;
}
.info-item .label {
font-weight: 500;
color: #606266;
margin-right: 10px;
}
.info-item .value {
color: #303133;
}
.info-item .value.required {
color: #409eff;
}
.info-item .value.success {
color: #67c23a;
}
.info-item .value.danger {
color: #f56c6c;
}
.qualify-list {
margin-bottom: 15px;
}
.qualify-item {
margin-bottom: 20px;
}
.file-section {
margin-top: 15px;
}
.file-group {
border: 1px solid #ebeef5;
border-radius: 4px;
padding: 15px;
background-color: #fafafa;
}
.file-group-header {
margin-bottom: 10px;
padding-bottom: 5px;
border-bottom: 1px solid #ebeef5;
}
/* FileUploadVO组件的样式已由组件内部定义 */
.no-file {
padding: 20px 0;
text-align: center;
color: #909399;
}
.no-data {
padding: 40px 0;
}
</style>

@ -0,0 +1,366 @@
<template>
<el-dialog
:visible="visible"
title="供应商资质详情"
width="80%"
@close="handleClose"
destroy-on-close
>
<div class="qualify-detail-container">
<!-- 供应商基础信息 -->
<div class="basic-info-section">
<h3>供应商基础信息</h3>
<div class="info-content">
<el-row :gutter="20">
<el-col :span="8">
<div class="info-item">
<label>供应商名称</label>
<span>{{ supplierInfo.custName || '-' }}</span>
</div>
</el-col>
<el-col :span="8">
<div class="info-item">
<label>联系人</label>
<span>{{ supplierInfo.contactPerson || '-' }}</span>
</div>
</el-col>
<el-col :span="8">
<div class="info-item">
<label>联系电话</label>
<span>{{ supplierInfo.contactPhone || '-' }}</span>
</div>
</el-col>
<el-col :span="8">
<div class="info-item">
<label>供应商编码</label>
<span>{{ supplierInfo.custCode || '-' }}</span>
</div>
</el-col>
<!-- <el-col :span="8">-->
<!-- <div class="info-item">-->
<!-- <label>资质状态</label>-->
<!-- <span>{{ getQualifyStatusText(supplierInfo.qualifyStatus) }}</span>-->
<!-- </div>-->
<!-- </el-col>-->
<!-- <el-col :span="8">-->
<!-- <div class="info-item">-->
<!-- <label>创建时间</label>-->
<!-- <span>{{ formatDate(supplierInfo.createTime) }}</span>-->
<!-- </div>-->
<!-- </el-col>-->
</el-row>
</div>
</div>
<!-- 资质信息分组展示 -->
<!-- <div class="qualify-groups-section">-->
<!-- <template v-if="groupedQualifies.length > 0">-->
<!-- <div v-for="(group, index) in groupedQualifies" :key="index" class="qualify-group">-->
<!-- <div class="group-header">-->
<!-- <h4>类型{{ group.typeName }}</h4>-->
<!-- </div>-->
<!-- <div class="group-content">-->
<!-- <el-table :data="group.qualifies" stripe style="width: 100%">-->
<!-- <el-table-column prop="qualifyName" label="资质名称" min-width="180">-->
<!-- <template slot-scope="scope">-->
<!-- <span>{{ scope.row.qualifyName }}</span>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- <el-table-column prop="qualifyType" label="资质类型" min-width="120">-->
<!-- <template slot-scope="scope">-->
<!-- <span>{{ getQualifyTypeText(scope.row.qualifyType) }}</span>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- <el-table-column prop="isRequired" label="是否必填" min-width="80">-->
<!-- <template slot-scope="scope">-->
<!-- <el-tag :type="scope.row.isRequired === '1' ? 'success' : 'info'">-->
<!-- {{ scope.row.isRequired === '1' ? '必填' : '选填' }}-->
<!-- </el-tag>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- <el-table-column prop="status" label="审核状态" min-width="100">-->
<!-- <template slot-scope="scope">-->
<!-- <el-tag :type="getStatusTagType(scope.row.status)">-->
<!-- {{ getStatusText(scope.row.status) }}-->
<!-- </el-tag>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- <el-table-column prop="submitDate" label="提交日期" min-width="120">-->
<!-- <template slot-scope="scope">-->
<!-- <span>{{ formatDate(scope.row.submitDate) }}</span>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- <el-table-column label="资质文件" min-width="200">-->
<!-- <template slot-scope="scope">-->
<!-- <div v-if="scope.row.files && scope.row.files.length > 0">-->
<!-- <div v-for="(file, fileIndex) in scope.row.files" :key="fileIndex" class="file-item">-->
<!-- <el-link :href="file.attDir" target="_blank" :underline="false">-->
<!-- <i class="el-icon-document"></i>-->
<!-- {{ file.name || '文件' + (fileIndex + 1) }}-->
<!-- </el-link>-->
<!-- </div>-->
<!-- </div>-->
<!-- <span v-else class="text-gray">暂无文件</span>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- <el-table-column prop="remark" label="备注" min-width="150">-->
<!-- <template slot-scope="scope">-->
<!-- <span>{{ scope.row.remark || '-' }}</span>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- </el-table>-->
<!-- </div>-->
<!-- </div>-->
<!-- </template>-->
<!-- <div v-else class="empty-state">-->
<!-- <el-empty description="暂无资质信息"></el-empty>-->
<!-- </div>-->
<!-- </div>-->
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="handleClose"></el-button>
</span>
</el-dialog>
</template>
<script>
import * as api from '@/api/cmcustqualifyfile.js'
import { formatDate } from '@/utils/index'
export default {
name: 'CmCustQualifyFileDetail',
props: {
supplierId: {
type: [String, Number],
default: null
},
visible: {
type: Boolean,
default: false
}
},
data() {
return {
supplierInfo: {},
qualifyList: [],
groupedQualifies: []
}
},
watch: {
visible(val) {
if (val && this.supplierId) {
this.handleOpen()
}
},
supplierId() {
if (this.visible && this.supplierId) {
this.loadData()
}
}
},
methods: {
loadData() {
// 使API
api.cmcustqualifyfileDetailApi(this.supplierId).then(res => {
if (res.code === 200) {
this.supplierInfo = res.data || {}
//
//
this.qualifyList = res.data.qualifies || []
this.groupQualifiesByType()
} else {
//
this.supplierInfo = {}
this.qualifyList = []
this.groupedQualifies = []
}
}).catch(err => {
//
console.error('获取详情失败:', err)
this.supplierInfo = {}
this.qualifyList = []
this.groupedQualifies = []
})
}
},
groupQualifiesByType() {
const groups = {}
this.qualifyList.forEach(qualify => {
const typeName = this.getTypeNameByType(qualify.qualifyType)
if (!groups[typeName]) {
groups[typeName] = {
typeName: typeName,
type: qualify.qualifyType,
qualifies: []
}
}
groups[typeName].qualifies.push(qualify)
})
this.groupedQualifies = Object.values(groups).sort((a, b) => {
return a.type.localeCompare(b.type)
})
},
getTypeNameByType(type) {
//
if (!type && type !== 0 && type !== '0') {
return '未分类资质'
}
const typeMap = {
'1': '基本资质',
'2': '行业资质',
'3': '产品资质',
'4': '其他资质'
}
//
return typeMap[String(type)] || '未分类资质'
},
getQualifyTypeText(type) {
//
if (!type && type !== 0 && type !== '0') {
return '未知类型'
}
const typeMap = {
'1': '营业执照',
'2': '税务登记证',
'3': '组织机构代码证',
'4': '法人身份证',
'5': '行业许可证',
'6': '产品认证',
'7': '其他'
}
//
return typeMap[String(type)] || '未知类型'
},
getQualifyStatusText(status) {
//
if (!status && status !== 0 && status !== '0') {
return '未知状态'
}
const statusMap = {
'0': '未提交',
'1': '部分提交',
'2': '已提交未审核',
'3': '审核通过',
'4': '审核未通过'
}
//
return statusMap[String(status)] || '未知状态'
},
getStatusText(status) {
//
if (!status && status !== 0 && status !== '0') {
return '未知状态'
}
const statusMap = {
'0': '待审核',
'1': '审核通过',
'2': '审核不通过'
}
//
return statusMap[String(status)] || '未知状态'
},
getStatusTagType(status) {
//
if (!status && status !== 0 && status !== '0') {
return 'info'
}
const typeMap = {
'0': 'warning',
'1': 'success',
'2': 'danger'
}
//
return typeMap[String(status)] || 'info'
},
formatDate(date) {
//
if (!date) {
return '-'
}
try {
return formatDate(date, 'YYYY-MM-DD')
} catch (error) {
return '-'
}
},
refreshData() {
this.loadData()
},
handleClose() {
this.$emit('update:visible', false)
},
handleOpen() {
this.loadData()
}
}
</script>
<style scoped>
.qualify-detail-container {
padding: 20px;
background: #fff;
border-radius: 4px;
}
.basic-info-section {
margin-bottom: 30px;
padding: 15px;
background: #f5f7fa;
border-radius: 4px;
}
.basic-info-section h3 {
margin: 0 0 15px 0;
font-size: 16px;
font-weight: 600;
color: #303133;
}
.info-item {
margin-bottom: 10px;
display: flex;
align-items: center;
}
.info-item label {
font-weight: 500;
color: #606266;
width: 100px;
}
.info-item span {
color: #303133;
flex: 1;
}
.qualify-groups-section {
margin-top: 20px;
}
.qualify-group {
margin-bottom: 30px;
border: 1px solid #ebeef5;
border-radius: 4px;
overflow: hidden;
}
.group-header {
background: #f5f7fa;
padding: 15px 20px;
border-bottom: 1px solid #ebeef5;
}
.group-header h4 {
margin: 0;
font-size: 16px;
font-weight: 600;
color: #303133;
}
.group-content {
padding: 20px;
}
.file-item {
margin-bottom: 5px;
}
.file-item:last-child {
margin-bottom: 0;
}
.text-gray {
color: #909399;
}
.empty-state {
padding: 50px 0;
text-align: center;
}
</style>

@ -1,23 +1,32 @@
<template>
<div class="divBox">
<el-form :inline="true" :model="dataForm" @keyup.enter.native="getDataList()">
<el-form-item label="供应商名称">
<el-input v-model="dataForm.custName" placeholder="请输入供应商名称" clearable></el-input>
<!-- <el-form-item label="客户代码">-->
<!-- <el-input v-model="dataForm.custCode" placeholder="请输入客户代码" clearable></el-input>-->
<!-- </el-form-item>-->
<el-form-item label="客户名称">
<el-input v-model="dataForm.custName" placeholder="请输入客户名称" clearable></el-input>
</el-form-item>
<el-form-item label="资质名称">
<el-input v-model="dataForm.qualifyName" placeholder="请输入资质名称" clearable></el-input>
<el-form-item label="营业执照号码">
<el-input v-model="dataForm.licenseNumber" placeholder="请输入营业执照号码" clearable></el-input>
</el-form-item>
<el-form-item label="联系方式">
<el-input v-model="dataForm.contactWay" placeholder="请输入联系方式" clearable></el-input>
</el-form-item>
<el-form-item label="状态">
<el-input v-model="dataForm.status" placeholder="请输入状态" clearable></el-input>
</el-form-item>
<el-form-item label="联系人">
<el-input v-model="dataForm.contactPerson" placeholder="请输入联系人" clearable></el-input>
</el-form-item>
<el-form-item label="备注">
<el-input v-model="dataForm.remark" placeholder="请输入备注" clearable></el-input>
</el-form-item>
<el-form-item>
<el-button @click="getDataList()"></el-button>
<el-button @click="resetForm()"></el-button>
<el-button v-hasPermi="['autogencode:cmcustqualifyfile:save']" type="primary" @click="addOrUpdateHandle()"></el-button>
<el-button v-hasPermi="['autogencode:cmcustqualifyfile:delete']" type="danger" @click="deleteHandle()" :disabled="dataListSelections.length <= 0"></el-button>
<el-button v-hasPermi="['autogencode:cmcust:save']" type="primary" @click="addOrUpdateHandle()"></el-button>
<el-button v-hasPermi="['autogencode:cmcust:delete']" type="danger" @click="deleteHandle()" :disabled="dataListSelections.length <= 0"></el-button>
</el-form-item>
</el-form>
<el-table
@ -33,40 +42,40 @@
width="50">
</el-table-column>
<el-table-column
prop="custName"
prop="custCode"
header-align="center"
align="center"
label="供应商名称">
label="客户代码">
</el-table-column>
<el-table-column
prop="qualifyName"
prop="custName"
header-align="center"
align="center"
label="资质名称">
label="客户名称">
</el-table-column>
<el-table-column
prop="submitDate"
prop="licenseNumber"
header-align="center"
align="center"
label="提交日期">
label="营业执照号码">
</el-table-column>
<el-table-column
prop="isPass"
prop="contactWay"
header-align="center"
align="center"
label="是否通过">
label="联系方式">
</el-table-column>
<el-table-column
prop="passContent"
prop="status"
header-align="center"
align="center"
label="不通过原因">
label="状态">
</el-table-column>
<el-table-column
prop="status"
prop="contactPerson"
header-align="center"
align="center"
label="状态">
label="联系人">
</el-table-column>
<el-table-column
prop="remark"
@ -78,11 +87,11 @@
fixed="right"
header-align="center"
align="center"
width="150"
width="200"
label="操作">
<template slot-scope="scope">
<el-button type="text" size="small" @click="addOrUpdateHandle(scope.row.id)">{{ '' }}</el-button>
<el-button v-hasPermi="['autogencode:cmcustqualifyfile:delete']" type="text" size="small" @click="deleteHandle(scope.row.id)" style="color: #f56c6c;"></el-button>
<el-button v-hasPermi="['autogencode:cmcust:delete']" type="text" size="small" @click="deleteHandle(scope.row.id)" style="color: #f56c6c;"></el-button>
</template>
</el-table-column>
</el-table>
@ -97,142 +106,144 @@
</el-pagination>
<!-- 表单弹窗, 新增数据和修改数据 -->
<add-or-update v-if="addOrUpdateVisible" ref="addOrUpdate" @refreshDataList="getDataList"></add-or-update>
<!-- 详情弹窗 -->
<detail v-if="detailVisible" :supplierId="currentDetailId" @close="detailVisible = false"></detail>
</div>
</template>
<script>
import AddOrUpdate from './cmcustqualifyfile-add-and-update'
import * as api from '@/api/cmcustqualifyfile.js'
export default {
data () {
return {
dataForm: {
custId: '',
custName: '',
qualifyId: '',
qualifyName: '',
fileId: '',
submitDate: '',
isPass: '',
passContent: '',
status: '',
remark: '',
},
import AddOrUpdate from './cmcustqualifyfile-add-and-update'
import detail from './cmcustqualifyfile-detail'
import * as api from '@/api/cmcust.js'
export default {
data () {
return {
dataForm: {
custCode: '',
custName: '',
licenseNumber: '',
contactWay: '',
status: '',
contactPerson: '',
remark: '',
},
//
resetForm() {
this.dataForm = {
custId: '',
custCode: '',
custName: '',
qualifyId: '',
qualifyName: '',
fileId: '',
submitDate: '',
isPass: '',
passContent: '',
licenseNumber: '',
contactWay: '',
status: '',
contactPerson: '',
remark: '',
}
},
dataList: [],
pageIndex: 1,
pageSize: 10,
totalPage: 0,
dataListLoading: false,
dataListSelections: [],
addOrUpdateVisible: false
dataList: [],
pageIndex: 1,
pageSize: 10,
totalPage: 0,
dataListLoading: false,
dataListSelections: [],
addOrUpdateVisible: false,
detailVisible: false,
currentDetailId: null
}
},
components: {
AddOrUpdate,
detail
},
activated () {
this.getDataList()
},
mounted() {
//
this.getDataList()
},
methods: {
//
getDataList () {
this.dataListLoading = true
// CmCustControllerPageParamRequest
const params = {
page: this.pageIndex,
limit: this.pageSize
}
//
if (this.dataForm.custCode) params.custCode = this.dataForm.custCode;
if (this.dataForm.custName) params.custName = this.dataForm.custName;
if (this.dataForm.licenseNumber) params.licenseNumber = this.dataForm.licenseNumber;
if (this.dataForm.contactWay) params.contactWay = this.dataForm.contactWay;
if (this.dataForm.status) params.status = this.dataForm.status;
if (this.dataForm.contactPerson) params.contactPerson = this.dataForm.contactPerson;
if (this.dataForm.remark) params.remark = this.dataForm.remark;
api.cmcustListApi(params).then(res => {
this.dataListLoading = false
this.dataList = res.list || [];
this.totalPage = res.total;
}).catch(e => {
this.dataListLoading = false
})
},
components: {
AddOrUpdate
},
activated () {
//
sizeChangeHandle (val) {
this.pageSize = val
this.pageIndex = 1
this.getDataList()
},
mounted() {
//
//
currentChangeHandle (val) {
this.pageIndex = val
this.getDataList()
},
methods: {
//
getDataList () {
this.dataListLoading = true
// CmCustQualifyFileControllerPageParamRequest
const params = {
page: this.pageIndex,
limit: this.pageSize
}
//
if (this.dataForm.custId) params.custId = this.dataForm.custId;
if (this.dataForm.custName) params.custName = this.dataForm.custName;
if (this.dataForm.qualifyId) params.qualifyId = this.dataForm.qualifyId;
if (this.dataForm.qualifyName) params.qualifyName = this.dataForm.qualifyName;
if (this.dataForm.fileId) params.fileId = this.dataForm.fileId;
if (this.dataForm.submitDate) params.submitDate = this.dataForm.submitDate;
if (this.dataForm.isPass) params.isPass = this.dataForm.isPass;
if (this.dataForm.passContent) params.passContent = this.dataForm.passContent;
if (this.dataForm.status) params.status = this.dataForm.status;
if (this.dataForm.remark) params.remark = this.dataForm.remark;
//
selectionChangeHandle (val) {
this.dataListSelections = val
},
// /
addOrUpdateHandle (id) {
this.addOrUpdateVisible = true
this.$nextTick(() => {
this.$refs.addOrUpdate.init(id)
})
},
//
deleteHandle (id) {
let ids = []
let idText = ''
api.cmcustqualifyfileListApi(params).then(res => {
this.dataListLoading = false
this.dataList = res.list || [];
this.totalPage = res.total;
}).catch(e => {
this.dataListLoading = false
})
},
//
sizeChangeHandle (val) {
this.pageSize = val
this.pageIndex = 1
this.getDataList()
},
//
currentChangeHandle (val) {
this.pageIndex = val
this.getDataList()
},
//
selectionChangeHandle (val) {
this.dataListSelections = val
},
// /
addOrUpdateHandle (id) {
this.addOrUpdateVisible = true
this.$nextTick(() => {
this.$refs.addOrUpdate.init(id)
// id
if (id) {
ids = [id]
idText = id
} else {
//
ids = this.dataListSelections.map(item => {
return item.id
})
},
//
deleteHandle (id) {
let ids = []
let idText = ''
// id
if (id) {
ids = [id]
idText = id
} else {
//
ids = this.dataListSelections.map(item => {
return item.id
})
idText = ids.join(',')
}
idText = ids.join(',')
}
this.$confirm(`确定进行删除操作?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
// API
api.cmcustqualifyfileDeleteApi(ids).then(res => {
this.$message.success('删除成功')
this.getDataList()
})
this.$confirm(`确定进行删除操作?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
// API
api.cmcustDeleteApi(ids).then(res => {
this.$message.success('删除成功')
this.getDataList()
})
},
}
})
},
//
detailHandle (id) {
this.currentDetailId = id
this.detailVisible = true
},
}
}
</script>

@ -1,9 +1,12 @@
package com.zbkj.admin.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import java.math.BigDecimal;

@ -92,11 +92,14 @@ public class WebConfig implements WebMvcConfigurer {
/** 本地文件上传路径 */
registry.addResourceHandler(Constants.UPLOAD_TYPE_IMAGE + "/**")
.addResourceLocations("file:" + crmebConfig.getImagePath() + "/" + Constants.UPLOAD_TYPE_IMAGE + "/");
registry.addResourceHandler("/file/public/**")
.addResourceLocations("file:" + crmebConfig.getImagePath() + "file/public/");
}
@Bean
public FilterRegistrationBean filterRegister() {
//注册过滤器
FilterRegistrationBean registration = new FilterRegistrationBean(responseFilter());
// 仅仅api前缀的请求才会拦截
registration.addUrlPatterns("/api/admin/*");

@ -141,6 +141,8 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
.antMatchers("/captcha/get", "/captcha/check").anonymous()
.antMatchers("/api/admin/payment/callback/**").anonymous()
.antMatchers("/api/public/**").anonymous()
// 放行公共文件访问
.antMatchers("/file/public/**").anonymous()
// 除上面外的所有请求全部需要鉴权认证
.anyRequest().authenticated()
.and()

@ -1,13 +1,20 @@
package com.zbkj.modules.autogencode.controller;
import java.util.Arrays;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zbkj.common.request.PageParamRequest;
import com.zbkj.common.response.CommonResult;
import com.zbkj.common.page.CommonPage;
import com.zbkj.modules.autogencode.entity.CmCustItem;
import com.zbkj.modules.autogencode.entity.CmCustQualify;
import com.zbkj.modules.autogencode.entity.CmCustQualifyFile;
import com.zbkj.modules.autogencode.service.CmCustItemService;
import com.zbkj.modules.autogencode.service.CmCustQualifyService;
import com.zbkj.modules.autogencode.service.CmCustQualifyFileService;
import com.zbkj.service.service.SystemAttachmentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@ -15,13 +22,9 @@ import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zbkj.modules.autogencode.entity.CmCust;
import com.zbkj.modules.autogencode.service.CmCustService;
import com.zbkj.common.model.system.SystemAttachment;
/**
@ -33,6 +36,17 @@ public class CmCustController {
@Autowired
private CmCustService cmCustService;
@Autowired
private CmCustQualifyService cmCustQualifyService;
@Autowired
private CmCustQualifyFileService cmCustQualifyFileService;
@Autowired
private SystemAttachmentService systemAttachmentService;
@Autowired
private CmCustItemService cmCustItemService;
/**
@ -126,18 +140,102 @@ public class CmCustController {
/**
*
* @param request
*
* @param request
* @param pageParamRequest
*/
@ApiOperation(value = "分页列表")
@RequestMapping(value = "/list", method = RequestMethod.GET)
public CommonResult<CommonPage<CmCust>> getList(@Validated CmCust request, @Validated PageParamRequest pageParamRequest) {
public CommonResult<CommonPage<CmCust>> getList(@Validated CmCust request, @Validated PageParamRequest pageParamRequest) {
LambdaQueryWrapper<CmCust> queryWrapper = new LambdaQueryWrapper();
// 应用搜索条件
condition(queryWrapper, request);
CommonPage<CmCust> page = CommonPage.restPage(cmCustService.pageList(queryWrapper, pageParamRequest));
// 优化版:批量查询数据,减少数据库交互
List<CmCust> supplierList = page.getList();
if (supplierList.isEmpty()) {
return CommonResult.success(page);
}
// 1. 提取所有供应商ID
List<Long> supplierIds = supplierList.stream().map(CmCust::getId).collect(Collectors.toList());
// 2. 批量查询所有供应商对应的供应商类别构建custId到supplierItem的映射
Map<Long, CmCustItem> supplierItemMap = new HashMap<>();
List<CmCustItem> allSupplierItems = cmCustItemService.list(new LambdaQueryWrapper<CmCustItem>()
.in(CmCustItem::getCustId, supplierIds));
for (CmCustItem item : allSupplierItems) {
supplierItemMap.put(item.getCustId(), item);
}
// 3. 收集所有需要的itemCode批量查询对应的资质类型
Set<String> itemCodes = new HashSet<>();
for (CmCustItem item : allSupplierItems) {
if (StrUtil.isNotBlank(item.getItemCode())) {
itemCodes.add(item.getItemCode());
}
}
// 构建itemCode到qualifies列表的映射
Map<String, List<CmCustQualify>> qualifyMap = new HashMap<>();
if (!itemCodes.isEmpty()) {
List<CmCustQualify> allQualifies = cmCustQualifyService.list(new LambdaQueryWrapper<CmCustQualify>()
.in(CmCustQualify::getQualifyType, itemCodes));
for (CmCustQualify qualify : allQualifies) {
qualifyMap.computeIfAbsent(qualify.getQualifyType(), k -> new ArrayList<>()).add(qualify);
}
}
// 4. 批量查询所有供应商已通过审核的资质文件
Map<Long, List<CmCustQualifyFile>> passedFilesMap = new HashMap<>();
List<CmCustQualifyFile> allPassedFiles = cmCustQualifyFileService.list(new LambdaQueryWrapper<CmCustQualifyFile>()
.in(CmCustQualifyFile::getCustId, supplierIds)
.eq(CmCustQualifyFile::getStatus, 2));
for (CmCustQualifyFile file : allPassedFiles) {
passedFilesMap.computeIfAbsent(file.getCustId(), k -> new ArrayList<>()).add(file);
}
// 5. 遍历供应商列表,使用映射数据设置资质状态
for (CmCust supplier : supplierList) {
// 默认资质状态0为资质不完整
String qualifyStatus = "0";
// 获取供应商对应的类别
CmCustItem supplierItem = supplierItemMap.get(supplier.getId());
if (supplierItem != null && StrUtil.isNotBlank(supplierItem.getItemCode())) {
// 获取该类别需要的资质列表
List<CmCustQualify> requiredQualifies = qualifyMap.getOrDefault(supplierItem.getItemCode(), Collections.emptyList());
int requiredCount = requiredQualifies.size();
if (requiredCount > 0) {
// 获取该供应商已通过的资质文件
List<CmCustQualifyFile> passedFiles = passedFilesMap.getOrDefault(supplier.getId(), Collections.emptyList());
// 统计已通过的不同资质类型数量
Set<Long> passedQualifyIds = new HashSet<>();
for (CmCustQualifyFile file : passedFiles) {
if (file.getQualifyId() != null) {
passedQualifyIds.add(file.getQualifyId());
}
}
// 判断资质状态只有当所有必需的资质类型都有通过审核的文件时才为1资质完整
if (passedQualifyIds.size() == requiredCount) {
qualifyStatus = "1";
}
}
}
// 直接设置资质状态到实体类的虚拟字段中
supplier.setQualifyStatus(qualifyStatus);
}
return CommonResult.success(page);
}
@ -146,8 +244,105 @@ public class CmCustController {
*
*/
@RequestMapping(value = "/info/{id}", method = RequestMethod.GET)
public CommonResult<CmCust> info(@PathVariable("id") Long id){
CmCust cmCust = cmCustService.getById(id);
public CommonResult<CmCust> info(@PathVariable("id") Long id) {
// 参数验证
if (id == null) {
return CommonResult.failed("ID不能为空");
}
CmCust cmCust = cmCustService.getById(id);
if (cmCust != null) {
// 1. 查询该供应商相关的所有资质类型
List<CmCustItem> cmCustItems = cmCustItemService.list(new LambdaQueryWrapper<CmCustItem>()
.eq(CmCustItem::getCustId, cmCust.getId()));
List<String> itemCodeList = Optional.ofNullable(cmCustItems)
.orElse(Collections.emptyList()) // 集合为 null 时返回空集合
.stream()
.filter(Objects::nonNull) // 过滤 null 的 CmCustItem 元素
.map(CmCustItem::getItemCode) // 提取 itemCode
.filter(StrUtil::isNotBlank) // 过滤 null 或空的 itemCode
.collect(Collectors.toList());
// 只有当itemCodeList非空时才执行后续查询和处理
if (!itemCodeList.isEmpty()) {
// 构建资质查询条件
LambdaQueryWrapper<CmCustQualify> qualifyQuery = new LambdaQueryWrapper<CmCustQualify>()
.eq(CmCustQualify::getDelFlag, "0")
.in(CmCustQualify::getQualifyType, itemCodeList);
List<CmCustQualify> qualifyList = cmCustQualifyService.list(qualifyQuery);
if (!qualifyList.isEmpty()) {
// 提取所有资质ID
List<Long> qualifyIds = qualifyList.stream()
.filter(Objects::nonNull)
.map(CmCustQualify::getId)
.filter(Objects::nonNull)
.collect(Collectors.toList());
// 2. 批量查询该供应商的所有资质文件
LambdaQueryWrapper<CmCustQualifyFile> fileQuery = new LambdaQueryWrapper<CmCustQualifyFile>()
.eq(CmCustQualifyFile::getCustId, id)
.eq(CmCustQualifyFile::getDelFlag, "0");
// 只有当qualifyIds非空时才添加in条件
if (!qualifyIds.isEmpty()) {
fileQuery.in(CmCustQualifyFile::getQualifyId, qualifyIds);
}
List<CmCustQualifyFile> fileList = cmCustQualifyFileService.list(fileQuery);
if (!fileList.isEmpty()) {
// 提取所有文件ID并转换为String类型
List<String> fileIds = fileList.stream()
.filter(Objects::nonNull)
.filter(file -> file.getFileId() != null)
.map(file -> file.getFileId().toString())
.collect(Collectors.toList());
// 3. 批量查询所有系统附件先检查fileIds是否为空
List<SystemAttachment> attachments = new ArrayList<>();
if (!fileIds.isEmpty()) {
attachments = systemAttachmentService.list(new LambdaQueryWrapper<SystemAttachment>()
.in(SystemAttachment::getFileId, fileIds));
}
// 构建文件ID到附件列表的映射
Map<String, List<SystemAttachment>> fileToAttachmentMap = attachments.stream()
.filter(Objects::nonNull)
.collect(Collectors.groupingBy(SystemAttachment::getFileId));
// 为每个资质文件设置附件列表
for (CmCustQualifyFile file : fileList) {
if (file != null && file.getFileId() != null) {
file.setFiles(fileToAttachmentMap.getOrDefault(file.getFileId().toString(), Collections.emptyList()));
}
}
}
// 构建资质ID到文件列表的映射
Map<Long, List<CmCustQualifyFile>> qualifyToFileMap = fileList.stream()
.filter(Objects::nonNull)
.filter(file -> file.getQualifyId() != null)
.collect(Collectors.groupingBy(CmCustQualifyFile::getQualifyId));
// 为每个资质设置文件列表
for (CmCustQualify qualify : qualifyList) {
if (qualify != null && qualify.getId() != null) {
qualify.setCmCustQualifyFileList(qualifyToFileMap.getOrDefault(qualify.getId(), Collections.emptyList()));
}
}
}
// 设置供应商的资质列表
cmCust.setCmCustQualifyList(qualifyList);
} else {
// 如果没有资质类型,设置空列表避免空指针
cmCust.setCmCustQualifyList(Collections.emptyList());
}
}
return CommonResult.success(cmCust);
}
@ -156,7 +351,7 @@ public class CmCustController {
*
*/
@RequestMapping(value = "/save", method = RequestMethod.POST)
public CommonResult<String> save(@RequestBody CmCust cmCust){
public CommonResult<String> save(@RequestBody CmCust cmCust) {
if (cmCustService.save(cmCust)) {
return CommonResult.success();
}
@ -167,18 +362,68 @@ public class CmCustController {
*
*/
@RequestMapping(value = "/update", method = RequestMethod.POST)
public CommonResult<String> update(@RequestBody CmCust cmCust){
public CommonResult<String> update(@RequestBody CmCust cmCust) {
if (cmCustService.updateById(cmCust)) {
return CommonResult.success();
}
return CommonResult.failed();
}
/**
*
*/
@RequestMapping(value = "/updateByFiles", method = RequestMethod.POST)
public CommonResult<String> updateByFiles(@RequestBody CmCust cmCust) {
List<CmCustQualify> cmCustQualifyList = cmCust.getCmCustQualifyList();
if (null != cmCustQualifyList && cmCustQualifyList.size() > 0) {
for (CmCustQualify cmQualify : cmCustQualifyList) {
List<CmCustQualifyFile> cmCustQualifyFileList = cmQualify.getCmCustQualifyFileList();
for (CmCustQualifyFile cmCustQualifyFile : cmCustQualifyFileList) {
if (null == cmCustQualifyFile.getId()) {
cmCustQualifyFile.setCustId(cmCust.getId());
cmCustQualifyFile.setQualifyId(cmQualify.getId());
cmCustQualifyFile.setQualifyName(cmQualify.getQualifyName());
cmCustQualifyFileService.save(cmCustQualifyFile);
}
if (null != cmCustQualifyFile) {
updateFile(cmCustQualifyFile);
}
}
}
}
return CommonResult.success();
}
private void updateFile(CmCustQualifyFile cmCustQualifyFile) {
Long newId = System.currentTimeMillis() + new Random().nextInt(100);
List<SystemAttachment> files = cmCustQualifyFile.getFiles();
if (null != files) {
for (SystemAttachment cmAttach : files) {
cmAttach.setFileId(String.valueOf(newId));
}
systemAttachmentService.updateBatchById(files);
cmCustQualifyFile.setFileId(newId);
}
cmCustQualifyFileService.updateById(cmCustQualifyFile);
}
private void setFile(CmCustQualifyFile cmCustQualifyFile) {
Long fileId = cmCustQualifyFile.getFileId();
if (null != fileId) {
List<SystemAttachment> list = systemAttachmentService.list(new LambdaQueryWrapper<SystemAttachment>()
.eq(SystemAttachment::getFileId, fileId));
cmCustQualifyFile.setFiles(list);
}
}
/**
* :id
*/
@RequestMapping(value = "/delete", method = RequestMethod.POST)
public CommonResult<String> delete(@RequestBody Long[] ids){
public CommonResult<String> delete(@RequestBody Long[] ids) {
if (cmCustService.removeByIds(Arrays.asList(ids))) {
return CommonResult.success();
}

@ -0,0 +1,183 @@
package com.zbkj.modules.autogencode.controller;
import java.util.Arrays;
import java.util.Map;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zbkj.common.request.PageParamRequest;
import com.zbkj.common.response.CommonResult;
import com.zbkj.common.page.CommonPage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zbkj.modules.autogencode.entity.CmCustItem;
import com.zbkj.modules.autogencode.service.CmCustItemService;
/**
*
*/
@RestController
@RequestMapping("api/autogencode/cmcustitem")
public class CmCustItemController {
@Autowired
private CmCustItemService cmCustItemService;
/**
*
*
*/
private void condition(LambdaQueryWrapper<CmCustItem> queryWrapper, CmCustItem request) {
if (request == null) {
return;
}
// 根据实体类字段自动生成查询条件
// id
if (request.getId() != null) {
queryWrapper.eq(CmCustItem::getId, request.getId());
}
// 客户id
if (request.getCustId() != null) {
queryWrapper.eq(CmCustItem::getCustId, request.getCustId());
}
// 子项代码
if (StrUtil.isNotBlank(request.getItemCode())) {
queryWrapper.eq(CmCustItem::getItemCode, request.getItemCode());
}
// 子项值
if (StrUtil.isNotBlank(request.getItemValue())) {
queryWrapper.eq(CmCustItem::getItemValue, request.getItemValue());
}
// 排序码
if (request.getSortCode() != null) {
queryWrapper.eq(CmCustItem::getSortCode, request.getSortCode());
}
// 备注
if (StrUtil.isNotBlank(request.getRemark())) {
queryWrapper.eq(CmCustItem::getRemark, request.getRemark());
}
//
if (StrUtil.isNotBlank(request.getTenantId())) {
queryWrapper.eq(CmCustItem::getTenantId, request.getTenantId());
}
// 项目类型
if (StrUtil.isNotBlank(request.getItemType())) {
queryWrapper.eq(CmCustItem::getItemType, request.getItemType());
}
// 创建部门
if (request.getCreateDept() != null) {
queryWrapper.eq(CmCustItem::getCreateDept, request.getCreateDept());
}
// 创建人
if (request.getCreateBy() != null) {
queryWrapper.eq(CmCustItem::getCreateBy, request.getCreateBy());
}
// 创建时间
if (request.getCreateTime() != null) {
queryWrapper.eq(CmCustItem::getCreateTime, request.getCreateTime());
}
// 修改人
if (request.getUpdateBy() != null) {
queryWrapper.eq(CmCustItem::getUpdateBy, request.getUpdateBy());
}
// 修改时间
if (request.getUpdateTime() != null) {
queryWrapper.eq(CmCustItem::getUpdateTime, request.getUpdateTime());
}
// 删除标志0代表存在 2代表删除
if (StrUtil.isNotBlank(request.getDelFlag())) {
queryWrapper.eq(CmCustItem::getDelFlag, request.getDelFlag());
}
}
/**
*
* @param request
* @param pageParamRequest
*/
@ApiOperation(value = "分页列表")
@RequestMapping(value = "/list", method = RequestMethod.GET)
public CommonResult<CommonPage<CmCustItem>> getList(@Validated CmCustItem request, @Validated PageParamRequest pageParamRequest) {
LambdaQueryWrapper<CmCustItem> queryWrapper = new LambdaQueryWrapper();
// 应用搜索条件
condition(queryWrapper, request);
CommonPage<CmCustItem> page = CommonPage.restPage(cmCustItemService.pageList(queryWrapper, pageParamRequest));
return CommonResult.success(page);
}
/**
*
*/
@RequestMapping(value = "/info/{id}", method = RequestMethod.GET)
public CommonResult<CmCustItem> info(@PathVariable("id") Long id){
CmCustItem cmCustItem = cmCustItemService.getById(id);
return CommonResult.success(cmCustItem);
}
/**
*
*/
@RequestMapping(value = "/save", method = RequestMethod.POST)
public CommonResult<String> save(@RequestBody CmCustItem cmCustItem){
if (cmCustItemService.save(cmCustItem)) {
return CommonResult.success();
}
return CommonResult.failed();
}
/**
*
*/
@RequestMapping(value = "/update", method = RequestMethod.POST)
public CommonResult<String> update(@RequestBody CmCustItem cmCustItem){
if (cmCustItemService.updateById(cmCustItem)) {
return CommonResult.success();
}
return CommonResult.failed();
}
/**
* :id
*/
@RequestMapping(value = "/delete", method = RequestMethod.POST)
public CommonResult<String> delete(@RequestBody Long[] ids){
if (cmCustItemService.removeByIds(Arrays.asList(ids))) {
return CommonResult.success();
}
return CommonResult.failed();
}
}

@ -0,0 +1,13 @@
package com.zbkj.modules.autogencode.dao;
import com.zbkj.modules.autogencode.entity.CmCustItem;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* DAO
*/
@Mapper
public interface CmCustItemDao extends BaseMapper<CmCustItem> {
}

@ -1,11 +1,14 @@
package com.zbkj.modules.autogencode.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import lombok.Data;
@ -91,4 +94,17 @@ public class CmCust implements Serializable {
@ApiModelProperty(value = "")
private String tenantId;
/**
* 01
*/
@ApiModelProperty(value = "资质状态0为资质不完整1为资质完整")
@TableField(exist = false)
private String qualifyStatus;
/**
*
*/
@TableField(exist = false)
private List<CmCustQualify> cmCustQualifyList;
}

@ -0,0 +1,89 @@
package com.zbkj.modules.autogencode.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import java.util.Date;
import lombok.Data;
@Data
@TableName("cm_cust_item")
public class CmCustItem implements Serializable {
private static final long serialVersionUID = 1L;
/**
* id
*/
@ApiModelProperty(value = "id")
@TableId
private Long id;
/**
* id
*/
@ApiModelProperty(value = "客户id")
private Long custId;
/**
*
*/
@ApiModelProperty(value = "子项代码")
private String itemCode;
/**
*
*/
@ApiModelProperty(value = "子项值")
private String itemValue;
/**
*
*/
@ApiModelProperty(value = "排序码")
private Integer sortCode;
/**
*
*/
@ApiModelProperty(value = "备注")
private String remark;
/**
*
*/
@ApiModelProperty(value = "")
private String tenantId;
/**
*
*/
@ApiModelProperty(value = "项目类型")
private String itemType;
/**
*
*/
@ApiModelProperty(value = "创建部门")
private Long createDept;
/**
*
*/
@ApiModelProperty(value = "创建人")
private Long createBy;
/**
*
*/
@ApiModelProperty(value = "创建时间")
private Date createTime;
/**
*
*/
@ApiModelProperty(value = "修改人")
private Long updateBy;
/**
*
*/
@ApiModelProperty(value = "修改时间")
private Date updateTime;
/**
* 0 2
*/
@ApiModelProperty(value = "删除标志0代表存在 2代表删除")
private String delFlag;
}

@ -1,11 +1,14 @@
package com.zbkj.modules.autogencode.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import lombok.Data;
@ -86,4 +89,10 @@ public class CmCustQualify implements Serializable {
@ApiModelProperty(value = "租户ID")
private String tenantId;
/**
*
*/
@TableField(exist = false)
private List<CmCustQualifyFile> cmCustQualifyFileList;
}

@ -1,11 +1,16 @@
package com.zbkj.modules.autogencode.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.zbkj.common.model.system.SystemAttachment;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import lombok.Data;
@ -48,6 +53,7 @@ public class CmCustQualifyFile implements Serializable {
/**
*
*/
@JsonFormat(pattern = "yyyy-MM-dd hh:mm:ss")
@ApiModelProperty(value = "提交日期")
private Date submitDate;
/**
@ -106,4 +112,10 @@ public class CmCustQualifyFile implements Serializable {
@ApiModelProperty(value = "租户ID")
private String tenantId;
/**
*
*/
@TableField(exist = false)
private List<SystemAttachment> files;
}

@ -0,0 +1,25 @@
package com.zbkj.modules.autogencode.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.zbkj.modules.autogencode.entity.CmCustItem;
import com.zbkj.common.request.PageParamRequest;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import java.util.List;
import java.util.Map;
/**
*
* +----------------------------------------------------------------------
*/
public interface CmCustItemService extends IService<CmCustItem> {
/**
* CmCustItem
* @param pageParamRequest
* @return
*/
List<CmCustItem> pageList(LambdaQueryWrapper<CmCustItem> queryWrapper, PageParamRequest pageParamRequest);
}

@ -0,0 +1,42 @@
package com.zbkj.modules.autogencode.service.impl;
import com.github.pagehelper.PageHelper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import com.zbkj.modules.autogencode.dao.CmCustItemDao;
import com.zbkj.modules.autogencode.entity.CmCustItem;
import com.zbkj.modules.autogencode.service.CmCustItemService;
import com.zbkj.common.page.CommonPage;
import com.zbkj.common.request.PageParamRequest;
import javax.annotation.Resource;
import java.util.Map;
import java.util.Arrays;
import java.util.List;
@Service("cmCustItemService")
public class CmCustItemServiceImpl extends ServiceImpl<CmCustItemDao, CmCustItem> implements CmCustItemService {
@Resource
private CmCustItemDao dao;
/**
*
*/
@Override
public List<CmCustItem> pageList(LambdaQueryWrapper<CmCustItem> queryWrapper, PageParamRequest pageParamRequest) {
PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());
return dao.selectList(queryWrapper);
}
}

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zbkj.modules.autogencode.dao.CmCustItemDao">
<!-- 根据包名 模块名 以及类名 生成Mapper XML 配置文件 -->
<resultMap type="com.zbkj.modules.autogencode.entity.CmCustItem" id="cmCustItemMap">
<result property="id" column="id"/>
<result property="custId" column="CUST_ID"/>
<result property="itemCode" column="ITEM_CODE"/>
<result property="itemValue" column="ITEM_VALUE"/>
<result property="sortCode" column="SORT_CODE"/>
<result property="remark" column="REMARK"/>
<result property="tenantId" column="tenant_id"/>
<result property="itemType" column="item_type"/>
<result property="createDept" column="create_dept"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
<result property="delFlag" column="del_flag"/>
</resultMap>
</mapper>

@ -39,7 +39,7 @@ public class SystemAttachment implements Serializable {
@ApiModelProperty(value = "附件名称")
private String name;
@ApiModelProperty(value = "附件名称")
@ApiModelProperty(value = "附件id")
private String fileId;
@ApiModelProperty(value = "附件路径")

Loading…
Cancel
Save