调整 合同、运力、客商、项目

This commit is contained in:
2026-09-15 11:59:55 +08:00
parent 79aa4f9fae
commit 6a87066097
15 changed files with 1857 additions and 957 deletions
@@ -103,8 +103,8 @@
<div class="contract-attachment-upload-dialog__body">
<div class="contract-attachment-upload-dialog__field">
<span class="contract-attachment-upload-dialog__label">附件位置</span>
<el-select model-value="合同文件" disabled style="width: 100%">
<el-option label="合同文件" value="合同文件" />
<el-select :model-value="attachmentLocation" disabled style="width: 100%">
<el-option :label="attachmentLocation" :value="attachmentLocation" />
</el-select>
</div>
<div class="contract-attachment-upload-dialog__field">
@@ -152,13 +152,16 @@ import { UploadFilled } from '@element-plus/icons-vue';
import { baseUrl } from '@/config/env';
import { getUploadHeaders } from '@/utils/upload';
import { downloadFileByUrl } from '@/utils/util';
import { getDictionary as getBizDictionary } from '@/api/system/dictbiz';
const CONTRACT_ATTACHMENT_TYPE_OTHER = '其它文件';
export const contractAttachmentTypeOptions = [
export const defaultContractAttachmentTypeOptions = [
{ label: '合同文件', value: '合同文件' },
{ label: '双章归档文件', value: '双章归档文件' },
{ label: '其它文件', value: CONTRACT_ATTACHMENT_TYPE_OTHER },
];
/** @deprecated 兼容旧引用,实际选项由业务字典 contract_attachment_type 动态加载 */
export const contractAttachmentTypeOptions = defaultContractAttachmentTypeOptions;
export const attachmentFileTypes = [
'pdf',
'bmp',
@@ -204,13 +207,29 @@ const attachmentTypeKeywords = fileType => {
return [fileType];
};
export const resolveContractAttachmentType = (row = {}) => {
const values = contractAttachmentTypeOptions.map(item => item.value);
const resolveOtherAttachmentType = (options = []) => {
const list = options.length ? options : defaultContractAttachmentTypeOptions;
const matched = list.find(
item =>
String(item.value) === CONTRACT_ATTACHMENT_TYPE_OTHER ||
String(item.label).includes('其它') ||
String(item.label).includes('其他')
);
return matched?.value || list[list.length - 1]?.value || CONTRACT_ATTACHMENT_TYPE_OTHER;
};
export const resolveContractAttachmentType = (
row = {},
options = defaultContractAttachmentTypeOptions
) => {
const list = options.length ? options : defaultContractAttachmentTypeOptions;
const values = list.map(item => item.value);
if (values.includes(row.fileType)) return row.fileType;
const fileName = normalizeAttachmentTypeText(attachmentName(row));
if (!fileName) return CONTRACT_ATTACHMENT_TYPE_OTHER;
const matched = contractAttachmentTypeOptions
.filter(item => item.value !== CONTRACT_ATTACHMENT_TYPE_OTHER)
const otherType = resolveOtherAttachmentType(list);
if (!fileName) return otherType;
const matched = list
.filter(item => item.value !== otherType)
.flatMap(item =>
attachmentTypeKeywords(item.value).map(keyword => ({
value: item.value,
@@ -220,16 +239,27 @@ export const resolveContractAttachmentType = (row = {}) => {
.filter(item => item.keyword)
.sort((a, b) => b.keyword.length - a.keyword.length)
.find(item => fileName.includes(item.keyword));
return matched?.value || CONTRACT_ATTACHMENT_TYPE_OTHER;
return matched?.value || otherType;
};
export const normalizeContractFileRows = rows =>
export const normalizeContractFileRows = (rows, options = defaultContractAttachmentTypeOptions) =>
(rows || []).map(row => ({
...row,
fileType: resolveContractAttachmentType(row),
fileType: resolveContractAttachmentType(row, options),
description: row.description || '',
}));
const mapDictOptions = response => {
const data = response?.data?.data || response?.data || [];
const records = Array.isArray(data) ? data : data.records || [];
return records
.map(item => ({
label: item.dictValue,
value: item.dictKey,
}))
.filter(item => item.label && item.value);
};
export default {
name: 'ContractAttachmentSection',
components: { UploadFilled },
@@ -242,6 +272,7 @@ export default {
lockApproved: Boolean,
markApprovedOnUpload: Boolean,
useUploadDialog: Boolean,
attachmentLocation: { type: String, default: '合同文件' },
preview: { type: Function, default: null },
},
emits: ['update:rows'],
@@ -249,9 +280,9 @@ export default {
return {
selected: [],
attachmentFileTypes,
contractAttachmentTypeOptions,
contractAttachmentTypeOptions: [...defaultContractAttachmentTypeOptions],
uploadDialogVisible: false,
uploadDialogType: CONTRACT_ATTACHMENT_TYPE_OTHER,
uploadDialogType: resolveOtherAttachmentType(defaultContractAttachmentTypeOptions),
uploadDialogFiles: [],
uploadDialogFileList: [],
};
@@ -266,9 +297,32 @@ export default {
acceptText() {
return this.attachmentFileTypes.map(item => `.${item}`).join(',');
},
defaultAttachmentType() {
return resolveOtherAttachmentType(this.contractAttachmentTypeOptions);
},
},
created() {
this.loadAttachmentTypeOptions();
},
methods: {
attachmentName,
loadAttachmentTypeOptions() {
return getBizDictionary({ code: 'contract_attachment_type' })
.then(res => {
const options = mapDictOptions(res);
if (options.length) {
this.contractAttachmentTypeOptions = options;
if (
!options.some(item => String(item.value) === String(this.uploadDialogType))
) {
this.uploadDialogType = this.defaultAttachmentType;
}
}
})
.catch(() => {
// 字典加载失败时保留默认选项
});
},
isRowLocked(row) {
return this.lockApproved && isAttachmentApproved(row);
},
@@ -286,7 +340,7 @@ export default {
this.update([...this.rows]);
},
openUploadDialog() {
this.uploadDialogType = CONTRACT_ATTACHMENT_TYPE_OTHER;
this.uploadDialogType = this.defaultAttachmentType;
this.uploadDialogFiles = [];
this.uploadDialogFileList = [];
this.uploadDialogVisible = true;
@@ -294,7 +348,7 @@ export default {
resetUploadDialog() {
this.uploadDialogFiles = [];
this.uploadDialogFileList = [];
this.uploadDialogType = CONTRACT_ATTACHMENT_TYPE_OTHER;
this.uploadDialogType = this.defaultAttachmentType;
},
beforeUpload(file) {
const extension = String(file.name || '')
@@ -337,10 +391,13 @@ export default {
...this.uploadDialogFiles.filter(item => String(item.uid) !== String(file.uid)),
normalized,
];
this.uploadDialogType = resolveContractAttachmentType({
...normalized,
fileType: '',
});
this.uploadDialogType = resolveContractAttachmentType(
{
...normalized,
fileType: '',
},
this.contractAttachmentTypeOptions
);
this.$message.success('上传成功');
},
handleDialogError() {
@@ -359,7 +416,7 @@ export default {
this.$message.warning('请先上传附件');
return;
}
if (this.attachmentType && !this.uploadDialogType) {
if (!this.uploadDialogType) {
this.$message.warning('请选择附件类型');
return;
}
@@ -367,7 +424,7 @@ export default {
const uploadTime = this.$dayjs().format('YYYY-MM-DD HH:mm:ss');
const appended = this.uploadDialogFiles.map(row => ({
...row,
fileType: this.attachmentType ? this.uploadDialogType : row.fileType,
fileType: this.uploadDialogType,
description: row.description || '',
uploadUserName: row.uploadUserName || uploadUserName,
uploadTime: row.uploadTime || uploadTime,
@@ -398,10 +455,13 @@ export default {
approved: existing?.approved || row.approved || false,
};
if (this.attachmentType) {
next.fileType = resolveContractAttachmentType({
...next,
fileType: existing?.fileType || row.fileType,
});
next.fileType = resolveContractAttachmentType(
{
...next,
fileType: existing?.fileType || row.fileType,
},
this.contractAttachmentTypeOptions
);
}
if (this.markApprovedOnUpload && !existing) next.approved = true;
return next;
@@ -441,6 +501,49 @@ export default {
</script>
<style lang="scss" scoped>
.contract-manage-form__section {
margin: 12px 0 0;
padding: 14px 16px 16px;
overflow: hidden;
background: #fff;
border-radius: 6px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
.dialog-section-title {
margin-bottom: 20px;
color: #303133;
font-size: 16px;
font-weight: 600;
&::before {
display: inline-block;
width: 4px;
height: 16px;
margin-right: 8px;
vertical-align: -2px;
background: #409eff;
content: '';
}
}
}
.contract-manage-form__attachment-head {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 16px;
.dialog-section-title {
margin-bottom: 0;
}
}
.contract-manage-form__attachment-upload {
display: flex;
align-items: center;
margin-top: 12px;
}
.contract-manage-form__attachment-tip {
margin-left: 30px;
color: #909399;