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

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
+408 -20
View File
@@ -50,7 +50,13 @@
</el-tag>
</template>
<template #projectName-label>项目额度信息</template>
<template #projectQuotaInfoTitle-form>
<div class="dialog-section-title">项目额度信息</div>
</template>
<template #temporaryCreditInfoTitle-form>
<div class="dialog-section-title">临时额度信息</div>
</template>
<template #projectName-form>
<el-select
@@ -130,22 +136,19 @@
</template>
<template #menu-form-before>
<el-button
v-if="!dialogReadonly"
type="primary"
plain
:loading="draftLoading"
@click="saveDraft"
>
保存
</el-button>
<template v-if="!dialogReadonly">
<el-button @click="closeFormDialog">取消</el-button>
<el-button type="primary" plain :loading="draftLoading" @click="saveDraft">
保存
</el-button>
</template>
</template>
<template #menu="{ row }">
<el-link
v-if="hasPermission(`${config.permission}_view`)"
type="primary"
@click="$refs.crud.rowView(row)"
@click="openDetail(row)"
>
查看
</el-link>
@@ -164,6 +167,74 @@
</template>
</avue-crud>
<el-dialog
v-model="detailVisible"
title="查看临时额度申请"
append-to-body
destroy-on-close
width="96%"
class="temporary-credit-limit-dialog temporary-credit-limit-detail-dialog"
>
<div v-loading="detailLoading" class="business-crud-page__detail-content">
<section
v-for="section in detailSections"
:key="section.title"
class="temporary-credit-limit-detail-dialog__section"
>
<div class="dialog-section-title">{{ section.title }}</div>
<el-descriptions :column="4" class="temporary-credit-limit-detail-dialog__descriptions">
<el-descriptions-item
v-for="field in section.fields"
:key="field[0]"
:label="field[1]"
:span="field[2] || 1"
>
{{ formatDetailValue(field[0]) }}
</el-descriptions-item>
</el-descriptions>
<div
v-if="section.showAttachment"
class="temporary-credit-limit-detail-dialog__attachment"
>
<div class="temporary-credit-limit-page__attachment-head">
<span class="temporary-credit-limit-detail-dialog__attachment-label">附件</span>
<el-button type="primary" :disabled="!attachmentRows.length" @click="batchDownload">
批量下载
</el-button>
</div>
<el-table :data="attachmentRows" empty-text="暂无附件">
<el-table-column type="index" label="序号" width="70" align="center" />
<el-table-column label="文件名" min-width="240" show-overflow-tooltip>
<template #default="{ row }">
<el-link type="primary" @click="previewAttachment(row)">
{{ attachmentName(row) }}
</el-link>
</template>
</el-table-column>
<el-table-column label="文件大小" width="120" align="center">
<template #default="{ row }">{{ formatFileSize(row.size) }}</template>
</el-table-column>
<el-table-column prop="uploadUserName" label="上传人" width="140" align="center" />
<el-table-column
prop="uploadTime"
label="上传时间"
:width="config.detailAttachmentUploadTimeWidth || 180"
align="center"
/>
<el-table-column label="操作" width="100" align="center" fixed="right">
<template #default="{ row }">
<el-link type="primary" @click="downloadAttachment(row)">下载</el-link>
</template>
</el-table-column>
</el-table>
</div>
</section>
</div>
<template #footer>
<el-button @click="detailVisible = false">关闭</el-button>
</template>
</el-dialog>
<empty-pagination
:page="page"
@size-change="sizeChange"
@@ -313,6 +384,9 @@ export default {
zoom: true,
},
attachmentFileTypes,
detailVisible: false,
detailLoading: false,
detailRow: {},
flowBox: false,
flowUrl: '',
processInstanceId: '',
@@ -323,6 +397,9 @@ export default {
permissionList() {
return { addBtn: this.canCreate };
},
detailSections() {
return this.config.detailSections || [];
},
isAdmin() {
const authority = this.userInfo?.authority;
return Array.isArray(authority)
@@ -341,14 +418,54 @@ export default {
},
methods: {
buildTableOption() {
const columns = (option.column || []).map(column => ({ ...column }));
const sectionTitleProps = ['projectQuotaInfoTitle', 'temporaryCreditInfoTitle'];
const formGroups = [];
let current = [];
columns.forEach(col => {
if (sectionTitleProps.includes(col.prop)) {
if (current.length) formGroups.push(current);
current = [col];
return;
}
if (!current.length) return;
// 列表/搜索专用字段不进入表单分组白卡
if (col.addDisplay === false && col.editDisplay === false) return;
current.push(col);
});
if (current.length) formGroups.push(current);
const formSectionProps = new Set();
formGroups.forEach(group => {
group.forEach(col => {
if (col.prop) formSectionProps.add(col.prop);
});
});
// 表单字段全部进 group 拆白卡;Avue 会额外生成空的主列 group,由样式隐藏去掉顶部白横条
return {
...option,
addBtn: false,
viewBtn: false,
editBtn: false,
delBtn: false,
// 隐藏 Avue 默认取消按钮,改由 menu-form-before 按「取消、保存、提交」顺序自定义
cancelBtn: false,
menuWidth: 320,
column: (option.column || []).map(column => ({ ...column })),
column: columns.map(col => {
if (!formSectionProps.has(col.prop)) return col;
return {
...col,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
};
}),
group: formGroups.map(group => ({
label: '',
arrow: false,
column: group,
})),
};
},
hasPermission(code) {
@@ -451,6 +568,32 @@ export default {
.then(res => this.applyDetail(res.data?.data || {}))
.finally(done);
},
openDetail(row) {
this.detailVisible = true;
this.detailLoading = true;
this.detailRow = { ...row };
this.attachmentRows = [];
this.selectedAttachments = [];
this.api
.getDetail(row.id)
.then(res => {
const detail = res.data?.data || {};
this.detailRow = { ...detail };
this.attachmentRows = this.parseJsonArray(detail.attachmentsJson);
})
.finally(() => {
this.detailLoading = false;
});
},
formatDetailValue(prop) {
const row = this.detailRow || {};
if (prop === 'approvalStatus') {
return this.displayStatus(row, 'approvalStatus');
}
const value = row[prop];
if (value === undefined || value === null || value === '') return '-';
return value;
},
applyDetail(detail) {
this.form = { ...detail };
this.selectedProjectId = detail.projectId || '';
@@ -459,9 +602,10 @@ export default {
this.syncCurrentProjectOption();
},
normalizeForm(row = this.form) {
const { projectQuotaInfoTitle, temporaryCreditInfoTitle, ...payload } = row || {};
return {
...row,
applyLimit: row.applyLimit === '' ? '' : Number(row.applyLimit),
...payload,
applyLimit: payload.applyLimit === '' ? '' : Number(payload.applyLimit),
attachmentsJson: JSON.stringify(this.attachmentRows),
};
},
@@ -492,13 +636,20 @@ export default {
.saveDraft(this.normalizeForm())
.then(() => {
this.$message.success('保存成功');
this.$refs.crud?.closeDialog();
this.closeFormDialog();
this.onLoad(this.page, this.query);
})
.finally(() => {
this.draftLoading = false;
});
},
closeFormDialog() {
if (typeof this.$refs.crud?.closeDialog === 'function') {
this.$refs.crud.closeDialog();
return;
}
this.$refs.crud?.$refs?.dialogForm?.hide?.();
},
rowDel(row) {
this.removeRows([row]);
},
@@ -824,7 +975,6 @@ export default {
.el-form-item__label {
height: auto !important;
line-height: 18px;
//padding-top: 7px; // 视觉补偿:让单行 label 仍接近 input 中线
}
// 强制必填星号垂直居中于行盒,与第一行汉字字符中心同基线(关键)
@@ -832,19 +982,257 @@ export default {
display: inline-block;
line-height: 18px;
height: 18px;
vertical-align: middle; // 关键:相对 baseline 上移,与汉字字符中心对齐
vertical-align: middle;
margin-right: 4px;
}
// 「项目额度信息 / 临时额度信息」小标题:对齐项目管理「项目基本信息」样式
.avue-form__group:has(.dialog-section-title) {
.dialog-section-title {
display: flex;
align-items: center;
gap: 8px;
width: 100%;
padding: 14px 16px 4px;
margin-bottom: 0;
color: #303133;
font-size: 15px;
font-weight: 500;
}
.avue-form__group--flex:has(.dialog-section-title),
.el-form-item:has(.dialog-section-title) {
margin-bottom: 0;
}
.el-form-item:has(.dialog-section-title) .el-form-item__content {
margin-left: 0 !important;
}
}
// 分组白卡:Avue 实际结构为 .avue-form > .el-form > .el-row > .avue-group
.avue-form {
background: transparent !important;
box-shadow: none !important;
padding: 0 !important;
margin: 0 !important;
border-radius: 0 !important;
min-height: 0 !important;
}
.avue-form > .el-form > .el-row {
margin-left: 0 !important;
margin-right: 0 !important;
}
// 无分区标题的空分组(Avue 主列残留)隐藏,去掉顶部白横条
.avue-form > .el-form > .el-row > .avue-group:not(:has(.dialog-section-title)) {
display: none !important;
height: 0 !important;
margin: 0 !important;
padding: 0 !important;
overflow: hidden !important;
border: none !important;
}
// 有分区标题的分组渲染为独立白卡
.avue-form > .el-form > .el-row > .avue-group:has(.dialog-section-title) {
background: #fff;
border-radius: 6px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
margin-bottom: 12px;
padding: 0 0 4px;
overflow: hidden;
}
.avue-form > .el-form > .el-row > .avue-group:has(.dialog-section-title):last-child {
margin-bottom: 0;
}
.avue-group .el-collapse {
border: none !important;
}
.avue-group .el-collapse-item__header {
display: none !important;
height: 0 !important;
min-height: 0 !important;
line-height: 0 !important;
padding: 0 !important;
border: none !important;
overflow: hidden;
}
.avue-group .avue-group__header {
display: none !important;
height: 0 !important;
min-height: 0 !important;
padding: 0 !important;
margin: 0 !important;
border: none !important;
}
.avue-group .el-collapse-item__wrap {
border: none !important;
}
.avue-group .el-collapse-item__content {
padding: 0 !important;
}
// 卡片视觉由外层 avue-group 承担,内层去白底,避免叠卡/顶条
.avue-group .avue-form__group {
display: flex !important;
background: transparent !important;
box-shadow: none !important;
margin: 0 !important;
padding: 0 !important;
border-radius: 0 !important;
}
}
.temporary-credit-limit-dialog .business-crud-page__detail-content .el-descriptions__label {
width: 180px !important;
}
// 新增/编辑/查看:高度随内容自适应,超出时再滚动;去掉强制全屏导致的底部大片空白
.temporary-credit-limit-dialog.el-dialog {
margin-top: 20px !important;
margin-bottom: 20px !important;
height: auto !important;
max-height: calc(100vh - 40px) !important;
display: flex;
flex-direction: column;
}
.temporary-credit-limit-dialog .el-dialog__header {
flex: none;
}
.temporary-credit-limit-dialog .el-dialog__body {
flex: 0 1 auto;
min-height: 0;
max-height: calc(100vh - 140px) !important;
display: block;
overflow-y: auto;
}
// 覆盖全局 .el-dialog .avue-form 白底内边距,避免顶部出现白横条
.temporary-credit-limit-dialog:not(.temporary-credit-limit-detail-dialog) .avue-form {
background: transparent !important;
box-shadow: none !important;
padding: 0 !important;
margin: 0 !important;
border-radius: 0 !important;
}
.temporary-credit-limit-dialog:not(.temporary-credit-limit-detail-dialog) .avue-dialog__footer,
.temporary-credit-limit-detail-dialog .el-dialog__footer {
position: sticky;
bottom: 0;
z-index: 5;
flex: none;
display: flex;
align-items: center;
justify-content: flex-end;
gap: 12px;
margin-top: 0 !important;
padding: 12px 20px !important;
background: #fff;
border-top: 1px solid var(--el-border-color-lighter, #ebeef5) !important;
border-radius: 0;
box-shadow: none;
.el-button + .el-button {
margin-left: 0;
}
}
.temporary-credit-limit-detail-dialog {
.business-crud-page__detail-content {
flex: 1 1 auto;
min-height: 0;
overflow: auto;
padding: 0;
}
&__section {
margin-bottom: 12px;
padding: 0 0 4px;
background: #fff;
border-radius: 6px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
overflow: hidden;
&:last-child {
margin-bottom: 0;
}
}
&__descriptions {
padding: 0 16px 8px;
// 取消 Descriptions 表格边框样式,改为纯文本描述列表
.el-descriptions__body {
background: transparent;
}
.el-descriptions__table {
border-collapse: separate;
border-spacing: 0;
}
.el-descriptions__cell {
border: none !important;
background: transparent !important;
padding: 8px 12px 8px 0;
vertical-align: top;
}
.el-descriptions__label {
color: #606266;
font-weight: 400;
white-space: normal;
line-height: 18px;
}
.el-descriptions__content {
color: #303133;
line-height: 18px;
}
}
.dialog-section-title {
display: flex;
align-items: center;
gap: 8px;
width: 100%;
padding: 14px 16px 4px;
margin-bottom: 0;
color: #303133;
font-size: 15px;
font-weight: 500;
}
&__attachment {
padding: 8px 16px 16px;
}
&__attachment-label {
color: #606266;
font-size: 14px;
}
.temporary-credit-limit-page__attachment-head {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 12px;
}
}
.el-form-item--default .el-form-item__label {
height: auto !important;
}
.el-dialog .avue-form{
padding: 16px 16px 4px !important;
}
</style>