fix: 附件同步不再自动填充描述,调整附件类型不再重排,回显保持原位置
This commit is contained in:
@@ -415,7 +415,8 @@
|
|||||||
><el-input
|
><el-input
|
||||||
v-model="row.description"
|
v-model="row.description"
|
||||||
:disabled="readonly"
|
:disabled="readonly"
|
||||||
maxlength="200" /></template></el-table-column
|
maxlength="200"
|
||||||
|
placeholder="请输入" /></template></el-table-column
|
||||||
><el-table-column label="文件大小" width="120"
|
><el-table-column label="文件大小" width="120"
|
||||||
><template #default="{ row }">{{
|
><template #default="{ row }">{{
|
||||||
formatAttachmentSize(row)
|
formatAttachmentSize(row)
|
||||||
@@ -2084,10 +2085,10 @@ export default {
|
|||||||
mergeAutomaticAttachments(
|
mergeAutomaticAttachments(
|
||||||
files,
|
files,
|
||||||
materials,
|
materials,
|
||||||
sourceName,
|
|
||||||
defaultMaterial = null,
|
defaultMaterial = null,
|
||||||
sourceKey = '',
|
sourceKey = '',
|
||||||
keepUnmatched = false
|
keepUnmatched = false,
|
||||||
|
insertIndex = -1
|
||||||
) {
|
) {
|
||||||
const existingUrls = new Set(
|
const existingUrls = new Set(
|
||||||
(this.form.attachments || []).map(file => this.attachmentFileUrl(file)).filter(Boolean)
|
(this.form.attachments || []).map(file => this.attachmentFileUrl(file)).filter(Boolean)
|
||||||
@@ -2111,35 +2112,39 @@ export default {
|
|||||||
url,
|
url,
|
||||||
link: file.link || url,
|
link: file.link || url,
|
||||||
attachmentType: material ? MATERIAL_TYPE_MAP[material.key] : 'other',
|
attachmentType: material ? MATERIAL_TYPE_MAP[material.key] : 'other',
|
||||||
description: file.description || `自动取自${sourceName}`,
|
description: file.description || '',
|
||||||
sourceImported: true,
|
sourceImported: true,
|
||||||
sourceKey: sourceKey || undefined,
|
sourceKey: sourceKey || undefined,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
if (imported.length) this.form.attachments = [...this.form.attachments, ...imported];
|
if (imported.length) {
|
||||||
|
// 回填到被替换附件的原起始位置,避免回显/切换时把用户新传附件顶到前面
|
||||||
|
const attachments = [...this.form.attachments];
|
||||||
|
const insertAt =
|
||||||
|
insertIndex >= 0 ? Math.min(insertIndex, attachments.length) : attachments.length;
|
||||||
|
attachments.splice(insertAt, 0, ...imported);
|
||||||
|
this.form.attachments = attachments;
|
||||||
|
}
|
||||||
return imported;
|
return imported;
|
||||||
},
|
},
|
||||||
/** 移除指定来源的自动关联附件(切换结算单/合同时整批替换) */
|
/** 移除指定来源的自动关联附件(切换结算单/合同时整批替换),返回首个被移除的位置 */
|
||||||
removeAutomaticAttachments(sourceKey, sourceName = '') {
|
removeAutomaticAttachments(sourceKey) {
|
||||||
const previousUrls = new Set(
|
const previousUrls = new Set(
|
||||||
sourceKey === 'settlement' ? this.linkedSettlementAttachmentUrls || [] : []
|
sourceKey === 'settlement' ? this.linkedSettlementAttachmentUrls || [] : []
|
||||||
);
|
);
|
||||||
this.form.attachments = (this.form.attachments || []).filter(file => {
|
let firstRemovedIndex = -1;
|
||||||
|
this.form.attachments = (this.form.attachments || []).filter((file, index) => {
|
||||||
const url = this.attachmentFileUrl(file);
|
const url = this.attachmentFileUrl(file);
|
||||||
if (sourceKey && file.sourceKey === sourceKey) return false;
|
const keep =
|
||||||
if (
|
!(sourceKey && file.sourceKey === sourceKey) &&
|
||||||
sourceName &&
|
!(previousUrls.size && url && previousUrls.has(url));
|
||||||
file.sourceImported &&
|
if (!keep && firstRemovedIndex === -1) firstRemovedIndex = index;
|
||||||
String(file.description || '').includes(`自动取自${sourceName}`)
|
return keep;
|
||||||
) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (previousUrls.size && url && previousUrls.has(url)) return false;
|
|
||||||
return true;
|
|
||||||
});
|
});
|
||||||
if (sourceKey === 'settlement') {
|
if (sourceKey === 'settlement') {
|
||||||
this.linkedSettlementAttachmentUrls = [];
|
this.linkedSettlementAttachmentUrls = [];
|
||||||
}
|
}
|
||||||
|
return firstRemovedIndex;
|
||||||
},
|
},
|
||||||
/** 按当前结算单附件整批同步:先清旧关联,再写入新结算单上传的附件 */
|
/** 按当前结算单附件整批同步:先清旧关联,再写入新结算单上传的附件 */
|
||||||
syncSettlementAttachments(settlementRows = []) {
|
syncSettlementAttachments(settlementRows = []) {
|
||||||
@@ -2154,14 +2159,14 @@ export default {
|
|||||||
.map(file => this.attachmentFileUrl(file))
|
.map(file => this.attachmentFileUrl(file))
|
||||||
.filter(url => url && nextUrlSet.has(url));
|
.filter(url => url && nextUrlSet.has(url));
|
||||||
}
|
}
|
||||||
this.removeAutomaticAttachments('settlement', '结算单');
|
const removedAt = this.removeAutomaticAttachments('settlement');
|
||||||
const imported = this.mergeAutomaticAttachments(
|
const imported = this.mergeAutomaticAttachments(
|
||||||
settlementFiles,
|
settlementFiles,
|
||||||
settlementMaterials,
|
settlementMaterials,
|
||||||
'结算单',
|
|
||||||
null,
|
null,
|
||||||
'settlement',
|
'settlement',
|
||||||
true
|
true,
|
||||||
|
removedAt
|
||||||
);
|
);
|
||||||
this.linkedSettlementAttachmentUrls = imported
|
this.linkedSettlementAttachmentUrls = imported
|
||||||
.map(file => this.attachmentFileUrl(file))
|
.map(file => this.attachmentFileUrl(file))
|
||||||
@@ -2212,7 +2217,7 @@ export default {
|
|||||||
this.syncSettlementAttachments(settlementRows);
|
this.syncSettlementAttachments(settlementRows);
|
||||||
if (!this.form.contractId) {
|
if (!this.form.contractId) {
|
||||||
this.firstContractPayment = false;
|
this.firstContractPayment = false;
|
||||||
this.removeAutomaticAttachments('contract', '合同');
|
this.removeAutomaticAttachments('contract');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const contractResponse = await getContractDetail(this.form.contractId);
|
const contractResponse = await getContractDetail(this.form.contractId);
|
||||||
@@ -2224,13 +2229,14 @@ export default {
|
|||||||
this.contractSignatureFileAvailable = contractFiles.some(file =>
|
this.contractSignatureFileAvailable = contractFiles.some(file =>
|
||||||
Boolean(this.attachmentFileUrl(file))
|
Boolean(this.attachmentFileUrl(file))
|
||||||
);
|
);
|
||||||
this.removeAutomaticAttachments('contract', '合同');
|
const contractRemovedAt = this.removeAutomaticAttachments('contract');
|
||||||
this.mergeAutomaticAttachments(
|
this.mergeAutomaticAttachments(
|
||||||
contractFiles,
|
contractFiles,
|
||||||
[ATTACHMENT_MATERIALS.contract],
|
[ATTACHMENT_MATERIALS.contract],
|
||||||
'合同',
|
|
||||||
ATTACHMENT_MATERIALS.contract,
|
ATTACHMENT_MATERIALS.contract,
|
||||||
'contract'
|
'contract',
|
||||||
|
false,
|
||||||
|
contractRemovedAt
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2244,14 +2250,15 @@ export default {
|
|||||||
String(item.id || '') !== String(this.form.id || '') &&
|
String(item.id || '') !== String(this.form.id || '') &&
|
||||||
item.approvalStatus !== 'voided'
|
item.approvalStatus !== 'voided'
|
||||||
);
|
);
|
||||||
this.removeAutomaticAttachments('contract', '合同');
|
const contractRemovedAt = this.removeAutomaticAttachments('contract');
|
||||||
if (this.firstContractPayment) {
|
if (this.firstContractPayment) {
|
||||||
this.mergeAutomaticAttachments(
|
this.mergeAutomaticAttachments(
|
||||||
this.parse(contract.contractFileJson),
|
this.parse(contract.contractFileJson),
|
||||||
[ATTACHMENT_MATERIALS.contract],
|
[ATTACHMENT_MATERIALS.contract],
|
||||||
'合同',
|
|
||||||
ATTACHMENT_MATERIALS.contract,
|
ATTACHMENT_MATERIALS.contract,
|
||||||
'contract'
|
'contract',
|
||||||
|
false,
|
||||||
|
contractRemovedAt
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -362,7 +362,6 @@
|
|||||||
v-model="row.type"
|
v-model="row.type"
|
||||||
filterable
|
filterable
|
||||||
placeholder="请选择类型"
|
placeholder="请选择类型"
|
||||||
@change="sortAttachments"
|
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in attachmentTypeOptions"
|
v-for="item in attachmentTypeOptions"
|
||||||
@@ -1530,7 +1529,6 @@ export default {
|
|||||||
this.selectedAttachmentRows = [];
|
this.selectedAttachmentRows = [];
|
||||||
this.invoices = data.invoices || [];
|
this.invoices = data.invoices || [];
|
||||||
this.issuedInvoices = data.issuedInvoices || [];
|
this.issuedInvoices = data.issuedInvoices || [];
|
||||||
this.sortAttachments();
|
|
||||||
this.contracts = this.filterContracts(this.allContracts, this.form.projectId);
|
this.contracts = this.filterContracts(this.allContracts, this.form.projectId);
|
||||||
},
|
},
|
||||||
async initialize() {
|
async initialize() {
|
||||||
@@ -3235,7 +3233,6 @@ export default {
|
|||||||
label: item.dictValue,
|
label: item.dictValue,
|
||||||
value: item.dictValue,
|
value: item.dictValue,
|
||||||
}));
|
}));
|
||||||
this.sortAttachments();
|
|
||||||
},
|
},
|
||||||
resolveAttachmentType(fileName) {
|
resolveAttachmentType(fileName) {
|
||||||
const normalizedName = String(fileName || '').toLocaleLowerCase();
|
const normalizedName = String(fileName || '').toLocaleLowerCase();
|
||||||
@@ -3259,25 +3256,6 @@ export default {
|
|||||||
const typeText = String(item?.label || item?.value || '').trim();
|
const typeText = String(item?.label || item?.value || '').trim();
|
||||||
return typeText === '其他' || typeText === '其他附件';
|
return typeText === '其他' || typeText === '其他附件';
|
||||||
},
|
},
|
||||||
getAttachmentTypeOrder(type) {
|
|
||||||
const normalizedType = String(type || '').trim();
|
|
||||||
const index = this.attachmentTypeOptions.findIndex(
|
|
||||||
item =>
|
|
||||||
String(item.value || '').trim() === normalizedType ||
|
|
||||||
String(item.label || '').trim() === normalizedType
|
|
||||||
);
|
|
||||||
return index === -1 ? Number.MAX_SAFE_INTEGER : index;
|
|
||||||
},
|
|
||||||
sortAttachments() {
|
|
||||||
this.attachments = (this.attachments || [])
|
|
||||||
.map((file, index) => ({ file, index }))
|
|
||||||
.sort((a, b) => {
|
|
||||||
const orderDifference =
|
|
||||||
this.getAttachmentTypeOrder(a.file.type) - this.getAttachmentTypeOrder(b.file.type);
|
|
||||||
return orderDifference || a.index - b.index;
|
|
||||||
})
|
|
||||||
.map(item => item.file);
|
|
||||||
},
|
|
||||||
getMissingAttachmentTypes(files = this.attachments) {
|
getMissingAttachmentTypes(files = this.attachments) {
|
||||||
const uploadedTypes = new Set(
|
const uploadedTypes = new Set(
|
||||||
(files || [])
|
(files || [])
|
||||||
@@ -3307,7 +3285,6 @@ export default {
|
|||||||
size: this.formatAttachmentSize(file.size),
|
size: this.formatAttachmentSize(file.size),
|
||||||
url: file.url || file.link || '',
|
url: file.url || file.link || '',
|
||||||
});
|
});
|
||||||
this.sortAttachments();
|
|
||||||
},
|
},
|
||||||
handleAttachmentSelectionChange(rows) {
|
handleAttachmentSelectionChange(rows) {
|
||||||
this.selectedAttachmentRows = rows || [];
|
this.selectedAttachmentRows = rows || [];
|
||||||
|
|||||||
@@ -371,7 +371,6 @@
|
|||||||
v-model="row.type"
|
v-model="row.type"
|
||||||
filterable
|
filterable
|
||||||
placeholder="请选择"
|
placeholder="请选择"
|
||||||
@change="sortAttachments"
|
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in attachmentTypeOptions"
|
v-for="item in attachmentTypeOptions"
|
||||||
@@ -1573,7 +1572,6 @@ export default {
|
|||||||
row => !isApprovalSettlementChange(row.changeContent)
|
row => !isApprovalSettlementChange(row.changeContent)
|
||||||
);
|
);
|
||||||
this.attachments = this.parseAttachments(detail.attachmentsJson);
|
this.attachments = this.parseAttachments(detail.attachmentsJson);
|
||||||
this.sortAttachments();
|
|
||||||
this.selectedAttachmentRows = [];
|
this.selectedAttachmentRows = [];
|
||||||
if (detail.contractId) {
|
if (detail.contractId) {
|
||||||
await this.ensureContractPartyOptions(detail.contractId, {
|
await this.ensureContractPartyOptions(detail.contractId, {
|
||||||
@@ -3099,7 +3097,6 @@ export default {
|
|||||||
uploadTime: existing?.uploadTime || file.uploadTime || uploadTime,
|
uploadTime: existing?.uploadTime || file.uploadTime || uploadTime,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
this.sortAttachments();
|
|
||||||
this.selectedAttachmentRows = [];
|
this.selectedAttachmentRows = [];
|
||||||
},
|
},
|
||||||
async loadAttachmentTypeOptions() {
|
async loadAttachmentTypeOptions() {
|
||||||
@@ -3115,7 +3112,6 @@ export default {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.attachmentTypeOptions = [];
|
this.attachmentTypeOptions = [];
|
||||||
}
|
}
|
||||||
this.sortAttachments();
|
|
||||||
},
|
},
|
||||||
resolveAttachmentType(fileName) {
|
resolveAttachmentType(fileName) {
|
||||||
const normalizedName = String(fileName || '').toLocaleLowerCase();
|
const normalizedName = String(fileName || '').toLocaleLowerCase();
|
||||||
@@ -3143,25 +3139,6 @@ export default {
|
|||||||
typeText === '其它附件'
|
typeText === '其它附件'
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
getAttachmentTypeOrder(type) {
|
|
||||||
const normalizedType = String(type || '').trim();
|
|
||||||
const index = this.attachmentTypeOptions.findIndex(
|
|
||||||
item =>
|
|
||||||
String(item.value || '').trim() === normalizedType ||
|
|
||||||
String(item.label || '').trim() === normalizedType
|
|
||||||
);
|
|
||||||
return index === -1 ? Number.MAX_SAFE_INTEGER : index;
|
|
||||||
},
|
|
||||||
sortAttachments() {
|
|
||||||
this.attachments = (this.attachments || [])
|
|
||||||
.map((file, index) => ({ file, index }))
|
|
||||||
.sort((a, b) => {
|
|
||||||
const orderDifference =
|
|
||||||
this.getAttachmentTypeOrder(a.file.type) - this.getAttachmentTypeOrder(b.file.type);
|
|
||||||
return orderDifference || a.index - b.index;
|
|
||||||
})
|
|
||||||
.map(item => item.file);
|
|
||||||
},
|
|
||||||
attachmentTypeName(type) {
|
attachmentTypeName(type) {
|
||||||
const option = this.attachmentTypeOptions.find(
|
const option = this.attachmentTypeOptions.find(
|
||||||
item => String(item.value) === String(type) || String(item.label) === String(type)
|
item => String(item.value) === String(type) || String(item.label) === String(type)
|
||||||
|
|||||||
Reference in New Issue
Block a user