From 53aa1f66ef5a83edf531e900aeed5283f01f1cc0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=88=98=E6=B3=89=E4=BD=B3?= <1107186916@qq.com>
Date: Fri, 6 Nov 2026 14:06:01 +0800
Subject: [PATCH] =?UTF-8?q?fix:=20=E9=99=84=E4=BB=B6=E5=90=8C=E6=AD=A5?=
=?UTF-8?q?=E4=B8=8D=E5=86=8D=E8=87=AA=E5=8A=A8=E5=A1=AB=E5=85=85=E6=8F=8F?=
=?UTF-8?q?=E8=BF=B0=EF=BC=8C=E8=B0=83=E6=95=B4=E9=99=84=E4=BB=B6=E7=B1=BB?=
=?UTF-8?q?=E5=9E=8B=E4=B8=8D=E5=86=8D=E9=87=8D=E6=8E=92=EF=BC=8C=E5=9B=9E?=
=?UTF-8?q?=E6=98=BE=E4=BF=9D=E6=8C=81=E5=8E=9F=E4=BD=8D=E7=BD=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../payment/payment-application-form.vue | 63 ++++++++++---------
.../components/formal-settlement-editor.vue | 23 -------
.../components/pre-settlement-editor.vue | 23 -------
3 files changed, 35 insertions(+), 74 deletions(-)
diff --git a/src/views/payment/payment-application-form.vue b/src/views/payment/payment-application-form.vue
index 482272d..90bb5f0 100644
--- a/src/views/payment/payment-application-form.vue
+++ b/src/views/payment/payment-application-form.vue
@@ -415,7 +415,8 @@
>{{
formatAttachmentSize(row)
@@ -2084,10 +2085,10 @@ export default {
mergeAutomaticAttachments(
files,
materials,
- sourceName,
defaultMaterial = null,
sourceKey = '',
- keepUnmatched = false
+ keepUnmatched = false,
+ insertIndex = -1
) {
const existingUrls = new Set(
(this.form.attachments || []).map(file => this.attachmentFileUrl(file)).filter(Boolean)
@@ -2111,35 +2112,39 @@ export default {
url,
link: file.link || url,
attachmentType: material ? MATERIAL_TYPE_MAP[material.key] : 'other',
- description: file.description || `自动取自${sourceName}`,
+ description: file.description || '',
sourceImported: true,
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;
},
- /** 移除指定来源的自动关联附件(切换结算单/合同时整批替换) */
- removeAutomaticAttachments(sourceKey, sourceName = '') {
+ /** 移除指定来源的自动关联附件(切换结算单/合同时整批替换),返回首个被移除的位置 */
+ removeAutomaticAttachments(sourceKey) {
const previousUrls = new Set(
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);
- if (sourceKey && file.sourceKey === sourceKey) return false;
- if (
- sourceName &&
- file.sourceImported &&
- String(file.description || '').includes(`自动取自${sourceName}`)
- ) {
- return false;
- }
- if (previousUrls.size && url && previousUrls.has(url)) return false;
- return true;
+ const keep =
+ !(sourceKey && file.sourceKey === sourceKey) &&
+ !(previousUrls.size && url && previousUrls.has(url));
+ if (!keep && firstRemovedIndex === -1) firstRemovedIndex = index;
+ return keep;
});
if (sourceKey === 'settlement') {
this.linkedSettlementAttachmentUrls = [];
}
+ return firstRemovedIndex;
},
/** 按当前结算单附件整批同步:先清旧关联,再写入新结算单上传的附件 */
syncSettlementAttachments(settlementRows = []) {
@@ -2154,14 +2159,14 @@ export default {
.map(file => this.attachmentFileUrl(file))
.filter(url => url && nextUrlSet.has(url));
}
- this.removeAutomaticAttachments('settlement', '结算单');
+ const removedAt = this.removeAutomaticAttachments('settlement');
const imported = this.mergeAutomaticAttachments(
settlementFiles,
settlementMaterials,
- '结算单',
null,
'settlement',
- true
+ true,
+ removedAt
);
this.linkedSettlementAttachmentUrls = imported
.map(file => this.attachmentFileUrl(file))
@@ -2212,7 +2217,7 @@ export default {
this.syncSettlementAttachments(settlementRows);
if (!this.form.contractId) {
this.firstContractPayment = false;
- this.removeAutomaticAttachments('contract', '合同');
+ this.removeAutomaticAttachments('contract');
return;
}
const contractResponse = await getContractDetail(this.form.contractId);
@@ -2224,13 +2229,14 @@ export default {
this.contractSignatureFileAvailable = contractFiles.some(file =>
Boolean(this.attachmentFileUrl(file))
);
- this.removeAutomaticAttachments('contract', '合同');
+ const contractRemovedAt = this.removeAutomaticAttachments('contract');
this.mergeAutomaticAttachments(
contractFiles,
[ATTACHMENT_MATERIALS.contract],
- '合同',
ATTACHMENT_MATERIALS.contract,
- 'contract'
+ 'contract',
+ false,
+ contractRemovedAt
);
return;
}
@@ -2244,14 +2250,15 @@ export default {
String(item.id || '') !== String(this.form.id || '') &&
item.approvalStatus !== 'voided'
);
- this.removeAutomaticAttachments('contract', '合同');
+ const contractRemovedAt = this.removeAutomaticAttachments('contract');
if (this.firstContractPayment) {
this.mergeAutomaticAttachments(
this.parse(contract.contractFileJson),
[ATTACHMENT_MATERIALS.contract],
- '合同',
ATTACHMENT_MATERIALS.contract,
- 'contract'
+ 'contract',
+ false,
+ contractRemovedAt
);
}
} catch (error) {
diff --git a/src/views/settlement/components/formal-settlement-editor.vue b/src/views/settlement/components/formal-settlement-editor.vue
index bc9fe4e..ecf348d 100644
--- a/src/views/settlement/components/formal-settlement-editor.vue
+++ b/src/views/settlement/components/formal-settlement-editor.vue
@@ -362,7 +362,6 @@
v-model="row.type"
filterable
placeholder="请选择类型"
- @change="sortAttachments"
>
- 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) {
const uploadedTypes = new Set(
(files || [])
@@ -3307,7 +3285,6 @@ export default {
size: this.formatAttachmentSize(file.size),
url: file.url || file.link || '',
});
- this.sortAttachments();
},
handleAttachmentSelectionChange(rows) {
this.selectedAttachmentRows = rows || [];
diff --git a/src/views/settlement/components/pre-settlement-editor.vue b/src/views/settlement/components/pre-settlement-editor.vue
index f45102d..5a368a2 100644
--- a/src/views/settlement/components/pre-settlement-editor.vue
+++ b/src/views/settlement/components/pre-settlement-editor.vue
@@ -371,7 +371,6 @@
v-model="row.type"
filterable
placeholder="请选择"
- @change="sortAttachments"
>
!isApprovalSettlementChange(row.changeContent)
);
this.attachments = this.parseAttachments(detail.attachmentsJson);
- this.sortAttachments();
this.selectedAttachmentRows = [];
if (detail.contractId) {
await this.ensureContractPartyOptions(detail.contractId, {
@@ -3099,7 +3097,6 @@ export default {
uploadTime: existing?.uploadTime || file.uploadTime || uploadTime,
};
});
- this.sortAttachments();
this.selectedAttachmentRows = [];
},
async loadAttachmentTypeOptions() {
@@ -3115,7 +3112,6 @@ export default {
} catch (error) {
this.attachmentTypeOptions = [];
}
- this.sortAttachments();
},
resolveAttachmentType(fileName) {
const normalizedName = String(fileName || '').toLocaleLowerCase();
@@ -3143,25 +3139,6 @@ export default {
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) {
const option = this.attachmentTypeOptions.find(
item => String(item.value) === String(type) || String(item.label) === String(type)