feat(contract-manage): 将合同详情由弹窗改为独立页面

- 新增路由 /business/contract-manage/detail,详情页共享合同管理组件
- 列表、表单、详情三分支用 isFormPage 和 isDetailPage 控制
- openDetail 方法改为跳转详情路由,initDetailPage 获取详情数据
- 新增 resetDetailState 和 closeDetailPage 方法,复用关闭逻辑
- 详情页去除弹窗高度限制,样式改为页面自滚动
- 详情页底栏使用固定位置关闭按钮,保持页面布局一致
- watch 和 created 中添加对 isDetailPage 的初始化调用和监听
This commit is contained in:
2026-09-11 12:30:05 +08:00
parent 6e5b15f203
commit 2131e99ec4
10 changed files with 189 additions and 90 deletions
+105 -69
View File
@@ -1,6 +1,8 @@
<template>
<basic-container :class="['contract-manage-page', { 'contract-manage-page--form': isFormPage }]">
<template v-if="!isFormPage">
<basic-container
:class="['contract-manage-page', { 'contract-manage-page--form': isFormPage || isDetailPage }]"
>
<template v-if="!isFormPage && !isDetailPage">
<avue-crud
ref="crud"
v-model:page="page"
@@ -96,7 +98,7 @@
/>
</template>
<template v-else>
<template v-else-if="isFormPage">
<div class="archive-page-form__title">{{ formPageTitle }}</div>
<el-form
@@ -558,65 +560,13 @@
</div>
</template>
<billing-plan-editor
ref="billingPlanEditor"
v-model="billingPlanBox"
:value="billingPlanForm"
:index="billingPlanIndex"
@save="saveBillingPlan"
/>
<template v-else>
<div class="archive-page-form__title">{{ detailPageTitle }}</div>
<el-dialog
v-model="attachmentDocumentPreviewVisible"
:title="attachmentPreviewFile.name || '附件预览'"
append-to-body
destroy-on-close
width="90%"
top="4vh"
>
<pdf-preview
v-if="
attachmentDocumentPreviewVisible &&
attachmentPreviewFile.url &&
attachmentPreviewFile.isPdf
"
:source="attachmentPreviewFile.url"
@error="handleAttachmentPreviewError"
/>
<open-file-viewer
v-else-if="attachmentDocumentPreviewVisible && attachmentPreviewFile.url"
:file="attachmentPreviewFile.url"
:file-name="attachmentPreviewFile.name"
:mime-type="attachmentPreviewFile.mimeType"
width="100%"
height="72vh"
fit="contain"
theme="auto"
locale="zh-CN"
:toolbar="attachmentViewerToolbar"
:plugins="attachmentViewerPlugins"
@unsupported="handleAttachmentPreviewUnsupported"
@error="handleAttachmentPreviewError"
/>
</el-dialog>
<el-image-viewer
v-if="attachmentImagePreviewVisible"
:url-list="attachmentImagePreviewUrls"
:initial-index="attachmentImagePreviewIndex"
@close="attachmentImagePreviewVisible = false"
/>
<el-dialog
v-model="detailBox"
title="合同详情"
append-to-body
destroy-on-close
class="contract-manage-detail-dialog"
width="92%"
top="4vh"
>
<div v-loading="detailLoading" class="contract-manage-form contract-manage-detail">
<div
v-loading="detailLoading"
class="contract-manage-form contract-manage-detail contract-manage-detail--page"
>
<section class="contract-manage-form__section contract-manage-form__section--panel">
<div class="dialog-section-title">基本信息</div>
<el-descriptions :column="3" class="contract-manage-detail__descriptions">
@@ -819,11 +769,61 @@
</el-table>
</section>
</div>
<template #footer
><el-button type="primary" @click="detailBox = false">关闭</el-button></template
>
<div class="contract-manage-page__footer">
<el-button type="primary" @click="closeDetailPage">关闭</el-button>
</div>
</template>
<billing-plan-editor
ref="billingPlanEditor"
v-model="billingPlanBox"
:value="billingPlanForm"
:index="billingPlanIndex"
@save="saveBillingPlan"
/>
<el-dialog
v-model="attachmentDocumentPreviewVisible"
:title="attachmentPreviewFile.name || '附件预览'"
append-to-body
destroy-on-close
width="90%"
top="4vh"
>
<pdf-preview
v-if="
attachmentDocumentPreviewVisible &&
attachmentPreviewFile.url &&
attachmentPreviewFile.isPdf
"
:source="attachmentPreviewFile.url"
@error="handleAttachmentPreviewError"
/>
<open-file-viewer
v-else-if="attachmentDocumentPreviewVisible && attachmentPreviewFile.url"
:file="attachmentPreviewFile.url"
:file-name="attachmentPreviewFile.name"
:mime-type="attachmentPreviewFile.mimeType"
width="100%"
height="72vh"
fit="contain"
theme="auto"
locale="zh-CN"
:toolbar="attachmentViewerToolbar"
:plugins="attachmentViewerPlugins"
@unsupported="handleAttachmentPreviewUnsupported"
@error="handleAttachmentPreviewError"
/>
</el-dialog>
<el-image-viewer
v-if="attachmentImagePreviewVisible"
:url-list="attachmentImagePreviewUrls"
:initial-index="attachmentImagePreviewIndex"
@close="attachmentImagePreviewVisible = false"
/>
<el-dialog
v-model="detailChangeRecordVisible"
title="变更记录详情"
@@ -1313,7 +1313,6 @@ export default {
changeRecordRows: [],
settlementTypeOptions: ['月结', '日结', '周结', '半月结', '固定天数周期结算'],
billCycleTypeOptions: ['固定截单日', '自然月'],
detailBox: false,
detailLoading: false,
detailRow: {},
detailContractFileRows: [],
@@ -1352,6 +1351,9 @@ export default {
isFormPage() {
return this.$route.path === '/business/contract-manage/form';
},
isDetailPage() {
return this.$route.path === '/business/contract-manage/detail';
},
formMode() {
return this.$route.query.mode === 'edit' ? 'edit' : 'add';
},
@@ -1362,6 +1364,9 @@ export default {
formPageTitle() {
return this.$route.query.name || `${this.formMode === 'edit' ? '编辑' : '新增'}合同管理`;
},
detailPageTitle() {
return this.$route.query.name || '合同详情';
},
ids() {
return this.selectionList.map(item => item.id).join(',');
},
@@ -1461,6 +1466,7 @@ export default {
watch: {
'$route.fullPath'() {
if (this.isFormPage) this.initFormPage();
else if (this.isDetailPage) this.initDetailPage();
},
settlementConfigTab(tab, oldTab) {
if (tab === oldTab) return;
@@ -1476,6 +1482,7 @@ export default {
this.loadSettlementDictionaries();
this.loadOrganizationOptions();
if (this.isFormPage) this.initFormPage();
else if (this.isDetailPage) this.initDetailPage();
},
methods: {
buildTableOption() {
@@ -2204,19 +2211,42 @@ export default {
if (Number(nextValue) > 100) nextValue = '100';
row.ratioLimit = nextValue;
},
// 合同详情:与新增/编辑一致,跳转独立页面(/business/contract-manage/detail
openDetail(row) {
this.detailBox = true;
this.$router.push({
path: '/business/contract-manage/detail',
query: { id: row.id, name: row.contractName ? `合同详情-${row.contractName}` : '合同详情' },
});
},
initDetailPage() {
this.resetDetailState();
const id = this.$route.query.id;
if (!id) return;
this.detailLoading = true;
this.applyDetailState(row);
this.api
.getDetail(row.id)
.getDetail(id)
.then(res => {
this.applyDetailState(res.data?.data || row);
this.applyDetailState(res.data?.data || {});
})
.finally(() => {
this.detailLoading = false;
});
},
resetDetailState() {
this.detailRow = {};
this.detailContractFileRows = [];
this.detailAttachmentRows = [];
this.detailBillingPlanRows = [];
this.detailPaymentRatioRows = [];
this.detailChangeRecordRows = [];
this.detailPreSettlementRuleForm = defaultSettlementRule();
this.detailFormalSettlementRuleForm = defaultSettlementRule();
this.detailSettlementConfigTab = 'pre';
},
closeDetailPage() {
this.$router.$avueRouter?.closeTag?.();
this.$router.push('/business/contract-manage');
},
applyDetailState(detail = {}) {
this.detailRow = {
...detail,
@@ -2895,6 +2925,12 @@ export default {
max-height: 74vh;
overflow-y: auto;
// 独立详情页面:不再受弹窗高度限制,交给页面自身滚动
&--page {
max-height: none;
overflow: visible;
}
&__descriptions {
:deep(.el-descriptions__label) {
display: inline-block;
+1 -1
View File
@@ -288,7 +288,7 @@
<el-form-item prop="fundLimit" class="project-apply-form__tip-label">
<template #label>
<span>项目资金使用额度</span>
<el-tooltip content="实际业务回款周期内付款" placement="top">
<el-tooltip content="实际业务回款周期内付款额度" placement="top">
<el-icon class="project-apply-form__label-tip"><QuestionFilled /></el-icon>
</el-tooltip>
</template>
@@ -763,6 +763,7 @@ export default {
align-items: center;
justify-content: flex-end;
margin-bottom: 12px;
margin-top: 12px;
}
&__attachment-upload {
@@ -840,6 +841,13 @@ export default {
.temporary-credit-limit-dialog .business-crud-page__detail-content .el-descriptions__label {
width: 180px !important;
}
// 仅查看(detail)态加宽 label 列:长字段名(如「剩余项目资金使用额度(万元)」)收敛为最多两行,
// 避免撑坏详情表格。新增 / 编辑弹窗的 avue-form 无 .avue--detail 类,不受影响
.temporary-credit-limit-dialog .avue--detail .el-form-item__label {
width: 148px !important;
flex: 0 0 148px !important;
}
.el-form-item--default .el-form-item__label {
height: auto !important;
}
+5 -2
View File
@@ -1829,10 +1829,13 @@ export default {
overflow: hidden;
}
// 大尺寸模式:缩成 1.586:1 比例,左对齐(不再 100% 占栏)
// 大尺寸模式:跟随列宽自适应(最大 240px,约 1.586:1 证件比例),
// 保证不同分辨率 / 系统缩放下都与上方输入框左右对齐
:deep(.driver-uploader--large) {
display: block;
width: 240px;
width: 100%;
max-width: 240px;
flex: none;
margin: 0;
}
+5 -1
View File
@@ -1349,9 +1349,13 @@ export default {
height: 151px;
}
// 大尺寸模式:跟随列宽自适应(最大 248px),
// 保证不同分辨率 / 系统缩放下都与上方输入框左右对齐
:deep(.ship-uploader--large) {
display: block;
width: 248px;
width: 100%;
max-width: 248px;
flex: none;
margin: 0;
}
+5 -2
View File
@@ -1741,10 +1741,13 @@ export default {
overflow: hidden;
}
// 大尺寸模式:缩成 1.586:1 比例,左对齐(不再 100% 占栏)
// 大尺寸模式:跟随列宽自适应(最大 240px,约 1.586:1 证件比例),
// 保证不同分辨率 / 系统缩放下都与上方输入框左右对齐
:deep(.vehicle-uploader--large) {
display: block;
width: 240px;
width: 100%;
max-width: 240px;
flex: none;
margin: 0;
}