Merge remote-tracking branch 'websoft/master'

This commit is contained in:
2026-09-09 14:43:49 +08:00
14 changed files with 761 additions and 137 deletions
+19 -4
View File
@@ -63,7 +63,12 @@
</section>
<section class="change-section">
<div class="dialog-section-title">付款比例设置</div>
<div class="dialog-section-title">
付款比例设置
<el-tooltip content="非必填;配置付款比例时,合计必须等于100%。" placement="top">
<el-icon style="margin-left: 4px; color: #909399; cursor: pointer"><el-icon-question-filled /></el-icon>
</el-tooltip>
</div>
<el-table :data="paymentRatioRows" border class="change-table">
<el-table-column type="index" label="序号" width="70" />
<el-table-column prop="paymentTerm" label="付款笔数" min-width="180" />
@@ -79,13 +84,13 @@
<section class="change-section attachment-section">
<div class="section-head"><div class="dialog-section-title">其它附件</div><el-button type="primary" plain>批量下载</el-button></div>
<el-table :data="attachments" border class="change-table"><el-table-column type="index" label="序号" width="70" /><el-table-column label="文件名" min-width="240"><template #default="{ row }"><el-link type="primary" @click="previewAttachment(row, attachments)">{{ row.originalName || row.name }}</el-link></template></el-table-column><el-table-column prop="description" label="附件描述" min-width="240" /><el-table-column prop="size" label="文件大小" width="120" /><el-table-column prop="userName" label="上传人" width="140" /><el-table-column prop="uploadTime" label="上传时间" width="180" /><el-table-column label="操作" width="100"><template #default="{ $index }"><el-link type="danger" @click="attachments.splice($index, 1)">删除</el-link></template></el-table-column></el-table>
<el-upload action="#" :auto-upload="false" multiple :show-file-list="false" @change="handleAttachment"><el-button plain>上传附件</el-button></el-upload>
<el-upload action="#" :auto-upload="false" multiple :show-file-list="false" @change="handleAttachment"><el-button type="primary" plain icon="el-icon-upload">上传附件</el-button></el-upload>
</section>
<section class="change-section change-reason-section">
<div class="dialog-section-title">变更内容</div>
<el-form-item prop="changeContent"><el-input v-model="form.changeContent" type="textarea" :rows="3" maxlength="2000" show-word-limit placeholder="请输入变更内容" /></el-form-item>
<div class="dialog-section-title">变更原因</div>
<div class="dialog-section-title is-required">变更原因</div>
<el-form-item prop="changeReason"><el-input v-model="form.changeReason" type="textarea" :rows="3" maxlength="500" show-word-limit placeholder="请输入变更原因" /></el-form-item>
<div class="dialog-section-title">变更材料</div>
<el-table :data="changeMaterials" border class="change-table">
@@ -138,8 +143,17 @@ export default {
mounted() { this.load(); },
watch: { settlementConfigTab(tab, oldTab) { if (tab === oldTab) return; if (oldTab === 'pre') this.preSettlementConfig = { ...this.settlementRule }; else this.formalSettlementConfig = { ...this.settlementRule }; this.settlementRule = { ...(tab === 'pre' ? this.preSettlementConfig : this.formalSettlementConfig) }; } },
methods: {
async load() { const id = this.$route.query.id; if (!id) return; const res = await api.getDetail(id); const data = res.data?.data || res.data || {}; this.form = { ...data, changeContent: '', changeReason: '', changeAttachmentsJson: '', copyCount: normalizeOptionalPositiveInteger(data.copyCount), paymentDays: normalizeOptionalPositiveInteger(data.paymentDays), changeType: '合同信息变更' }; this.changeMaterials = []; this.period = data.startDate && data.endDate ? [data.startDate, data.endDate] : []; this.plans = this.parse(data.billingPlanJson); this.attachments = this.parse(data.attachmentsJson); this.contractFileRows = this.parse(data.contractFileJson); const rules = this.parseObject(data.settlementRuleJson); const pre = this.parseObject(data.preSettlementConfigJson); const formal = this.parseObject(data.formalSettlementConfigJson); const legacy = Object.keys(rules).some(key => !['preSettlementConfig', 'formalSettlementConfig'].includes(key)) ? rules : {}; this.preSettlementConfig = rules.preSettlementConfig || (Object.keys(pre).length ? pre : legacy); this.formalSettlementConfig = rules.formalSettlementConfig || (Object.keys(formal).length ? formal : legacy); this.settlementRule = { ...this.preSettlementConfig }; this.feeGenerationMode = data.feeGenerationMode || (Number(data.billingEnabled) === 0 ? 'manual' : 'system'); this.paymentRatioRows = this.parse(data.paymentRatioJson); },
async load() { const id = this.$route.query.id; if (!id) return; const res = await api.getDetail(id); const data = res.data?.data || res.data || {}; this.form = { ...data, changeContent: '', changeReason: '', changeAttachmentsJson: '', copyCount: normalizeOptionalPositiveInteger(data.copyCount), paymentDays: normalizeOptionalPositiveInteger(data.paymentDays), changeType: '合同信息变更' }; this.changeMaterials = []; this.period = data.startDate && data.endDate ? [data.startDate, data.endDate] : []; this.plans = this.parse(data.billingPlanJson); this.attachments = this.mergeChangeAttachments(this.parse(data.attachmentsJson), this.parse(data.changeAttachmentsJson)); this.contractFileRows = this.parse(data.contractFileJson); const rules = this.parseObject(data.settlementRuleJson); const pre = this.parseObject(data.preSettlementConfigJson); const formal = this.parseObject(data.formalSettlementConfigJson); const legacy = Object.keys(rules).some(key => !['preSettlementConfig', 'formalSettlementConfig'].includes(key)) ? rules : {}; this.preSettlementConfig = rules.preSettlementConfig || (Object.keys(pre).length ? pre : legacy); this.formalSettlementConfig = rules.formalSettlementConfig || (Object.keys(formal).length ? formal : legacy); this.settlementRule = { ...this.preSettlementConfig }; this.feeGenerationMode = data.feeGenerationMode || (Number(data.billingEnabled) === 0 ? 'manual' : 'system'); this.paymentRatioRows = this.parse(data.paymentRatioJson); },
parse(value) { try { const result = JSON.parse(value || '[]'); return Array.isArray(result) ? result : []; } catch { return []; } },
// 审核通过后上一次的变更材料归集到「其它附件」,按文件地址/文件名去重,避免重复展示
mergeChangeAttachments(attachments = [], changeAttachments = []) {
const key = item => this.attachmentUrl(item) || this.attachmentName(item);
const exists = new Set(attachments.map(key));
const merged = changeAttachments
.filter(item => !exists.has(key(item)))
.map(item => ({ ...item, size: /^\d+$/.test(String(item.size ?? '')) ? this.formatFileSize(item.size) : item.size }));
return [...attachments, ...merged];
},
parseObject(value) { try { return { autoGenerate: 1, settlementType: '月结', billCycleType: '固定截单日', billCutoffDay: 25, cycleDays: 15, ...(JSON.parse(value || '{}') || {}) }; } catch { return { autoGenerate: 1, settlementType: '月结', billCycleType: '固定截单日', billCutoffDay: 25, cycleDays: 15 }; } },
positiveIntegerInput(prop, value) { this.form[prop] = String(value ?? '').replace(/\D/g, '').replace(/^0+/, ''); },
addPlan() { this.planEditorIndex = -1; this.planEditor = { planName: `计费方案${this.plans.length + 1}`, defaultPlan: !this.plans.length, remark: '', rules: [{}] }; this.planDialogVisible = true; },
@@ -187,6 +201,7 @@ export default {
.contract-basic-section :deep(.el-date-editor) { width: 360px; max-width: 100%; }
.dialog-section-title { margin-bottom: 18px; font-size: 16px; font-weight: 600; }
.dialog-section-title::before { display: inline-block; width: 4px; height: 16px; margin-right: 8px; vertical-align: -2px; background: #409eff; content: ''; }
.dialog-section-title.is-required::after { margin-left: 4px; color: #f56c6c; content: '*'; }
.section-head { display: flex; align-items: center; justify-content: space-between; }
.change-table { margin: 16px 0; }
.ratio-tip { margin-bottom: 8px; color: #f56c6c; }
+142 -13
View File
@@ -425,10 +425,14 @@
<section class="contract-manage-form__section contract-manage-form__section--panel">
<div class="contract-manage-form__section-head">
<div class="dialog-section-title">付款比例设置</div>
<div class="dialog-section-title">
付款比例设置
<el-tooltip content="非必填配置付款比例时合计必须等于100%" placement="top">
<el-icon style="margin-left: 4px; color: #909399; cursor: pointer"><el-icon-question-filled /></el-icon>
</el-tooltip>
</div>
<el-button type="primary" plain @click="addPaymentRatio">添加</el-button>
</div>
<p class="contract-manage-form__tip">非必填;配置付款比例时,合计必须等于100%。</p>
<el-table :data="paymentRatioRows" border>
<el-table-column type="index" label="序号" width="80" align="center" />
<el-table-column prop="paymentTerm" label="付款笔数" min-width="180" align="center" />
@@ -480,6 +484,20 @@
/>
<el-table-column prop="handlerUserName" label="经办人" min-width="140" align="center" />
<el-table-column prop="changeType" label="变更类型" min-width="160" align="center" />
<el-table-column label="变更内容" min-width="420">
<template #default="{ row }">
<el-tooltip placement="top" :show-after="200">
<template #content>
<div class="contract-change-record-content-tooltip">
{{ formatContractChangeContent(row) }}
</div>
</template>
<span class="contract-change-record-content-cell">{{
formatContractChangeContent(row)
}}</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column
prop="changeReason"
label="变更原因"
@@ -488,8 +506,9 @@
show-overflow-tooltip
/>
<el-table-column prop="statusName" label="状态" min-width="140" align="center" />
<el-table-column label="操作" width="120" align="center" fixed="right">
<el-table-column label="操作" width="150" align="center" fixed="right">
<template #default="{ row }">
<el-link type="primary" @click="openDetailChangeRecord(row)">详情</el-link>
<el-link type="primary" @click="openFlow(row)">流程</el-link>
</template>
</el-table-column>
@@ -725,7 +744,12 @@
</section>
<section class="contract-manage-form__section contract-manage-form__section--panel">
<div class="dialog-section-title">付款比例设置</div>
<div class="dialog-section-title">
付款比例设置
<el-tooltip content="非必填配置付款比例时合计必须等于100%" placement="top">
<el-icon style="margin-left: 4px; color: #909399; cursor: pointer"><el-icon-question-filled /></el-icon>
</el-tooltip>
</div>
<el-table :data="detailPaymentRatioRows" border>
<el-table-column type="index" label="序号" width="80" align="center" />
<el-table-column prop="paymentTerm" label="付款笔数" min-width="180" align="center" />
@@ -759,6 +783,20 @@
/>
<el-table-column prop="handlerUserName" label="经办人" min-width="140" align="center" />
<el-table-column prop="changeType" label="变更类型" min-width="160" align="center" />
<el-table-column label="变更内容" min-width="420">
<template #default="{ row }">
<el-tooltip placement="top" :show-after="200">
<template #content>
<div class="contract-change-record-content-tooltip">
{{ formatContractChangeContent(row) }}
</div>
</template>
<span class="contract-change-record-content-cell">{{
formatContractChangeContent(row)
}}</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column
prop="changeReason"
label="变更原因"
@@ -769,7 +807,7 @@
<el-table-column prop="statusName" label="状态" min-width="140" align="center" />
<el-table-column label="操作" width="120" align="center" fixed="right">
<template #default="{ row }"
><el-link type="primary" @click="openDetailChangeRecord(row)">查看详情</el-link></template
><el-link type="primary" @click="openDetailChangeRecord(row)">详情</el-link></template
>
</el-table-column>
</el-table>
@@ -1790,7 +1828,7 @@ export default {
return Array.isArray(data) ? data : data.records || [];
};
this.settlementCurrencyOptions = records(currencyRes).map(item => ({
label: `${item.dictKey} - ${item.dictValue}`,
label: item.dictValue,
value: item.dictKey,
}));
this.settlementModeDictOptions = records(methodRes).map(item => ({
@@ -2250,12 +2288,73 @@ export default {
.filter(Boolean);
return names.length ? names.join('、') : '空';
},
formatChangeRecordBillingPlans(value) {
const list = Array.isArray(value) ? value : [];
if (!list.length) return '空';
return list
.map(item => {
if (!item || typeof item !== 'object') return String(item ?? '');
const name = item.planName || item.name || '未命名方案';
return item.defaultPlan ? `${name}(默认)` : name;
})
.filter(Boolean)
.join('、');
},
formatChangeRecordPaymentRatios(value) {
const list = Array.isArray(value) ? value : [];
if (!list.length) return '空';
return list
.map(item => {
if (!item || typeof item !== 'object') return String(item ?? '');
const term = item.paymentTerm || '';
const ratio = item.ratioLimit === undefined || item.ratioLimit === null || item.ratioLimit === '' ? '' : `${item.ratioLimit}%`;
return [term, ratio].filter(Boolean).join(' ');
})
.filter(Boolean)
.join('');
},
formatChangeRecordSettlementRule(value) {
const normalized = this.normalizeChangeRecordValue(value);
if (!normalized || typeof normalized !== 'object' || Array.isArray(normalized)) {
return this.isEmptyChangeRecordValue(normalized) ? '空' : String(normalized);
}
const summary = config => {
if (!config || typeof config !== 'object') return '';
const parts = [];
const autoGenerate = config.autoGenerate;
if (autoGenerate !== undefined && autoGenerate !== null && autoGenerate !== '') {
parts.push(`自动生成结算单:${Number(autoGenerate) === 1 ? '开启' : '关闭'}`);
}
if (config.settlementType) parts.push(`结算类型:${config.settlementType}`);
if (config.billCycleType) parts.push(`账单周期类型:${config.billCycleType}`);
if (config.billCutoffDay) parts.push(`账单截单日:${config.billCutoffDay}日`);
if (config.cycleDays) parts.push(`周期天数:${config.cycleDays}天`);
if (config.billStartDate) parts.push(`账单起始日期:${config.billStartDate}`);
return parts.join('');
};
if (normalized.preSettlementConfig || normalized.formalSettlementConfig) {
return [
`预结算:${summary(normalized.preSettlementConfig) || '空'}`,
`正式结算:${summary(normalized.formalSettlementConfig) || '空'}`,
].join('');
}
return summary(normalized) || '空';
},
formatContractChangeValue(field, value) {
const normalized = this.normalizeChangeRecordValue(value);
if (this.isEmptyChangeRecordValue(normalized)) return '空';
if (['contractFileJson', 'attachmentsJson', 'changeAttachmentsJson'].includes(field)) {
return this.formatChangeRecordAttachments(normalized);
}
if (field === 'billingPlanJson') return this.formatChangeRecordBillingPlans(normalized);
if (field === 'paymentRatioJson') return this.formatChangeRecordPaymentRatios(normalized);
if (
['settlementRuleJson', 'preSettlementConfigJson', 'formalSettlementConfigJson'].includes(
field
)
) {
return this.formatChangeRecordSettlementRule(normalized);
}
if (field === 'legalSealFlag') return Number(normalized) === 1 ? '是' : '否';
if (field === 'feeGenerationMode') return normalized === 'manual' ? '手动生成' : '系统生成';
if (field === 'invoiceCycle' || field === 'paymentDays') return `${normalized}天`;
@@ -2264,16 +2363,33 @@ export default {
}
return String(normalized);
},
// 列表「变更内容」列:把变更前后内容拼成一段摘要(参照客商变更记录)
formatContractChangeContent(row = {}) {
const rows = this.buildDetailChangeRecordRows(row).filter(
item => item.field !== '变更原因'
);
return rows
.map(item => `${item.field}:变更前:${item.before} → 变更后:${item.after}`)
.join('');
},
buildDetailChangeRecordRows(row = {}) {
const beforeData = this.parseChangeRecordData(row.beforeData);
const afterData = this.parseChangeRecordData(row.afterData);
const fields = [...new Set([...Object.keys(beforeData), ...Object.keys(afterData)])];
const rows = fields
.filter(
field =>
.filter(field => {
// 前后都为空的字段不展示('' 与 null 序列化不同,单靠 JSON 比对会漏掉)
if (
this.isEmptyChangeRecordValue(beforeData[field]) &&
this.isEmptyChangeRecordValue(afterData[field])
) {
return false;
}
return (
JSON.stringify(this.normalizeChangeRecordValue(beforeData[field])) !==
JSON.stringify(this.normalizeChangeRecordValue(afterData[field]))
)
);
})
.map(field => ({
field: this.getContractChangeFieldLabel(field),
before: this.formatContractChangeValue(field, beforeData[field]),
@@ -2496,6 +2612,21 @@ export default {
}
}
.contract-change-record-content-cell {
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.contract-change-record-content-tooltip {
max-width: 900px;
max-height: 320px;
overflow: auto;
white-space: pre-wrap;
word-break: break-word;
}
.contract-change-record-detail-meta {
display: flex;
flex-wrap: wrap;
@@ -2505,6 +2636,8 @@ export default {
}
:deep(.contract-change-record-detail-dialog .el-dialog__body) {
max-height: 65vh;
overflow: auto;
padding-top: 12px;
}
@@ -2768,8 +2901,4 @@ export default {
white-space: normal;
line-height: 1.2;
}
.contract-manage-form__tip {
color: #ff0000 !important;
font-size: 12px;
}
</style>
+93 -5
View File
@@ -58,6 +58,40 @@
{{ displayStatus(row, 'approvalStatus') }}
</template>
<template #header>
<div class="project-apply-page__risk-search">
<span class="project-apply-page__risk-label">
资金使用风险
<el-tooltip placement="top" effect="dark">
<template #content>
<div>中风险项目资金额度使用率 80%</div>
<div>高风险项目资金额度使用率 90%</div>
<div>使用率 = 已使用资金 / 项目资金使用额度 × 100%</div>
</template>
<i class="el-icon-question project-apply-page__risk-help" />
</el-tooltip>
</span>
<el-check-tag
v-for="item in fundRiskTagOptions"
:key="item.value"
:checked="fundRiskScope === item.value"
@change="changeFundRiskScope(item.value)"
>
{{ item.label }}{{ fundRiskStats[item.statKey] || 0 }}
</el-check-tag>
</div>
</template>
<template #fundUseRisk="{ row }">
<el-tag v-if="row.fundUseRisk === 'high'" type="danger">
{{ row.fundUseRiskName || '高风险' }}
</el-tag>
<el-tag v-else-if="row.fundUseRisk === 'medium'" type="warning">
{{ row.fundUseRiskName || '中风险' }}
</el-tag>
<span v-else class="project-apply-page__risk-none">-</span>
</template>
<template #menu="{ row, index }">
<el-link
type="primary"
@@ -157,7 +191,7 @@
:disabled="isBasicInfoReadonly"
/>
</el-form-item>
<el-form-item label="项目简称" prop="projectShortName" required>
<el-form-item label="项目简称" prop="projectShortName">
<el-input
v-model="form.projectShortName"
placeholder="请填写项目简称"
@@ -376,7 +410,7 @@
<template #suffix>万元</template>
</el-input>
</el-form-item>
<el-form-item label="资金需求" prop="fundDemand">
<el-form-item label="履约保证金" prop="fundDemand">
<el-input
v-model="form.fundDemand"
@input="value => handleNumberInput('fundDemand', value)"
@@ -975,6 +1009,12 @@ export default {
data: [],
query: {},
allDept: 0,
fundRiskScope: '',
fundRiskStats: { high: 0, medium: 0, none: 0 },
fundRiskTagOptions: [
{ label: '高风险', value: 'high', statKey: 'high' },
{ label: '中风险', value: 'medium', statKey: 'medium' },
],
page: {
pageSize: 10,
pageSizes: [10, 20, 50, 100],
@@ -995,6 +1035,7 @@ export default {
{ max: 50, message: '项目名称不能超过50个字符', trigger: 'blur' },
],
projectShortName: [
{ required: true, message: '请输入项目简称', trigger: 'blur' },
{ max: 20, message: '项目简称不能超过20个字符', trigger: 'blur' },
],
businessDeptId: [{ required: true, message: '请选择业务部门', trigger: 'change' }],
@@ -1025,7 +1066,7 @@ export default {
],
projectScale: [{ label: '项目规模', validator: validateAmount, trigger: 'blur' }],
estimatedProfit: [{ label: '预估利润', validator: validateAmount, trigger: 'blur' }],
fundDemand: [{ label: '资金需求', validator: validateAmount, trigger: 'blur' }],
fundDemand: [{ label: '履约保证金', validator: validateAmount, trigger: 'blur' }],
handlerUserId: [
{
required: true,
@@ -1341,12 +1382,14 @@ export default {
...params,
...this.query,
allDept: this.allDept,
...(this.fundRiskScope ? { fundUseRisk: this.fundRiskScope } : {}),
})
.then(res => {
const result = res.data.data || {};
this.page.total = result.total || 0;
this.data = result.records || [];
this.selectionClear();
this.refreshFundRiskStats({ ...params, ...this.query, allDept: this.allDept });
})
.finally(() => {
this.loading = false;
@@ -1354,6 +1397,7 @@ export default {
},
searchReset() {
this.query = {};
this.fundRiskScope = '';
this.page.currentPage = 1;
this.onLoad(this.page);
},
@@ -1363,6 +1407,18 @@ export default {
this.onLoad(this.page, params);
done();
},
// 切换「资金使用风险」快速筛选:再次点击已选中项则取消筛选
changeFundRiskScope(value) {
this.fundRiskScope = this.fundRiskScope === value ? '' : value;
this.page.currentPage = 1;
this.onLoad(this.page, this.query);
},
refreshFundRiskStats(params) {
this.api.getFundRiskStats(params).then(res => {
const stats = res.data?.data || {};
this.fundRiskStats = { ...this.fundRiskStats, ...stats };
});
},
selectionChange(list) {
this.selectionList = list;
},
@@ -2473,8 +2529,40 @@ export default {
.project-apply-page-form {
min-height: 100%;
margin-bottom: 60px;
//padding: 20px 24px 92px;
//background: #f5f6fa;
}
.project-apply-page {
&__risk-search {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 8px;
margin-top: 8px;
margin-bottom: 16px;
:deep(.el-check-tag) {
font-weight: 500;
}
}
&__risk-label {
display: inline-flex;
align-items: center;
color: #606266;
font-weight: 600;
margin-right: 4px;
}
&__risk-help {
margin-left: 4px;
color: #a8abb2;
cursor: help;
font-size: 14px;
}
&__risk-none {
color: #c0c4cc;
}
}
.project-apply-dialog__footer {
@@ -50,11 +50,13 @@
</el-tag>
</template>
<template #projectName-label>项目额度信息</template>
<template #projectName-form>
<el-select
v-model="selectedProjectId"
class="temporary-credit-limit-page__field"
placeholder="请选择项目"
placeholder="请选择"
filterable
clearable
:loading="projectLoading"
@@ -75,7 +77,7 @@
<el-input
v-model="form.applyLimit"
class="temporary-credit-limit-page__field"
placeholder="请输入申请临时额度"
placeholder="请输入"
:disabled="dialogReadonly"
@input="handleAmountInput"
/>
@@ -822,7 +824,7 @@ export default {
.el-form-item__label {
height: auto !important;
line-height: 18px;
padding-top: 7px; // 视觉补偿:让单行 label 仍接近 input 中线
//padding-top: 7px; // 视觉补偿:让单行 label 仍接近 input 中线
}
// 强制必填星号垂直居中于行盒,与第一行汉字字符中心同基线(关键)
@@ -841,4 +843,8 @@ export default {
.el-form-item--default .el-form-item__label {
height: auto !important;
}
.el-dialog .avue-form{
padding: 16px 16px 4px !important;
}
</style>
+35 -35
View File
@@ -179,6 +179,40 @@
</div>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="航区" prop="navigationArea">
<div class="navigation-area-field">
<el-select v-model="shipForm.navigationArea" placeholder="请选择">
<el-option label="A级" value="A级" />
<el-option label="B级" value="B级" />
</el-select>
<el-tooltip effect="light" placement="top" popper-class="ship-navigation-tooltip">
<template #content>
<table class="navigation-cargo-table">
<tbody>
<tr>
<th rowspan="2">参考<br />载货量</th>
<th>航区</th>
<th>A级</th>
<th>B级</th>
<th>FA</th>
<th>FB</th>
</tr>
<tr>
<th>载货量(t)</th>
<td>864.00</td>
<td>864.00</td>
<td>965.00</td>
<td>1015.00</td>
</tr>
</tbody>
</table>
</template>
<el-icon class="navigation-info-icon"><InfoFilled /></el-icon>
</el-tooltip>
</div>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="18">
<el-col :span="6">
@@ -231,40 +265,6 @@
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="航区" prop="navigationArea">
<div class="navigation-area-field">
<el-select v-model="shipForm.navigationArea" placeholder="请选择">
<el-option label="A级" value="A级" />
<el-option label="B级" value="B级" />
</el-select>
<el-tooltip effect="light" placement="top" popper-class="ship-navigation-tooltip">
<template #content>
<table class="navigation-cargo-table">
<tbody>
<tr>
<th rowspan="2">参考<br />载货量</th>
<th>航区</th>
<th>A级</th>
<th>B级</th>
<th>FA</th>
<th>FB</th>
</tr>
<tr>
<th>载货量(t)</th>
<td>864.00</td>
<td>864.00</td>
<td>965.00</td>
<td>1015.00</td>
</tr>
</tbody>
</table>
</template>
<el-icon class="navigation-info-icon"><InfoFilled /></el-icon>
</el-tooltip>
</div>
</el-form-item>
</el-col>
</el-row>
</section-card>
@@ -1351,7 +1351,7 @@ export default {
:deep(.ship-uploader--large) {
display: block;
width: 240px;
width: 248px;
margin: 0;
}
+271 -22
View File
@@ -120,15 +120,252 @@
<vehicle-ledger v-model="vehicleLedgerBox" :vehicle="ledgerVehicle" />
<el-dialog v-model="certificationAuditBox" title="车辆认证审核" width="92%" top="4vh">
<el-descriptions :column="3" border>
<el-descriptions-item v-for="item in auditDetailItems" :key="item.label" :label="item.label">
{{ formatAuditValue(item) }}
</el-descriptions-item>
</el-descriptions>
<el-form v-if="showRejectReason" class="certification-audit__reason" label-position="right" label-width="auto">
<el-dialog
v-model="certificationAuditBox"
title="车辆认证审核"
width="92%"
top="4vh"
class="certification-audit-dialog"
>
<el-form label-position="right" label-width="auto" class="certification-audit archive-form">
<section-card title="基础信息">
<el-row :gutter="18">
<el-col :span="24">
<el-form-item label="所属组织">
<span class="certification-audit__value">{{ auditValue('organizationName') }}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="18">
<el-col :span="8">
<el-form-item label="车牌号">
<span class="certification-audit__value">{{ auditValue('plateNo') }}</span>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="车牌颜色">
<span class="certification-audit__value">{{ auditValue('plateColor') }}</span>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="车辆类型">
<span class="certification-audit__value">{{ auditValue('vehicleType') }}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="18">
<el-col :span="8">
<el-form-item label="业务关系">
<span class="certification-audit__value">{{ auditValue('businessRelation') }}</span>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="能源类型">
<span class="certification-audit__value">{{ auditValue('energyType') }}</span>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="强制报废日期">
<span class="certification-audit__value">
{{ auditValue('compulsoryScrapDate') }}
</span>
</el-form-item>
</el-col>
</el-row>
</section-card>
<section-card title="尺寸重量">
<el-row :gutter="18">
<el-col :span="8">
<el-form-item label="外廓长度(毫米)">
<span class="certification-audit__value">{{ auditValue('outerLength') }}</span>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="外廓宽度(毫米)">
<span class="certification-audit__value">{{ auditValue('outerWidth') }}</span>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="外廓高度(毫米)">
<span class="certification-audit__value">{{ auditValue('outerHeight') }}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="18">
<el-col :span="8">
<el-form-item label="核定载质量(KG">
<span class="certification-audit__value">{{ auditValue('approvedLoadKg') }}</span>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="准牵引总质量(KG">
<span class="certification-audit__value">{{ auditValue('tractionMassKg') }}</span>
</el-form-item>
</el-col>
</el-row>
</section-card>
<section-card title="证件信息">
<el-row :gutter="18">
<el-col :span="8">
<el-form-item label="海关备案号">
<span class="certification-audit__value">{{ auditValue('customsRecordNo') }}</span>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="行驶证档案编号">
<span class="certification-audit__value">{{ auditValue('drivingLicenseNo') }}</span>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="行驶证有效期起">
<span class="certification-audit__value">
{{ auditValue('drivingLicenseStartDate') }}
</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="18">
<el-col :span="8">
<el-form-item label="行驶证有效期止">
<span class="certification-audit__value">
{{ auditValue('drivingLicenseEndDate') }}
</span>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="道路运输证号">
<span class="certification-audit__value">
{{ auditValue('roadTransportCertNo') }}
</span>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="道路运输证有效期起">
<span class="certification-audit__value">
{{ auditValue('roadTransportCertStartDate') }}
</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="18">
<el-col :span="8">
<el-form-item label="道路运输证有效期止">
<span class="certification-audit__value">
{{ auditValue('roadTransportCertEndDate') }}
</span>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="道路运输年审有效期">
<span class="certification-audit__value">
{{ auditValue('annualReviewEndDate') }}
</span>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="机动车登记编号">
<span class="certification-audit__value">{{ auditValue('registrationNo') }}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="18">
<el-col :span="8">
<el-form-item label="机动车登记日期">
<span class="certification-audit__value">{{ auditValue('registrationDate') }}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="18">
<el-col :span="24">
<el-form-item label="备注">
<span class="certification-audit__value">{{ auditValue('remark') }}</span>
</el-form-item>
</el-col>
</el-row>
</section-card>
<section-card title="证件图片">
<el-row :gutter="18">
<el-col :span="8">
<image-upload-field
label="行驶证主页正面"
prop="drivingLicenseImage"
:value="certificationAuditForm.drivingLicenseImage"
readonly
large
class-prefix="vehicle"
/>
</el-col>
<el-col :span="8">
<image-upload-field
label="行驶证主页反面"
prop="drivingLicenseMainBack"
:value="certificationAuditForm.drivingLicenseMainBack"
readonly
large
class-prefix="vehicle"
/>
</el-col>
<el-col :span="8">
<image-upload-field
label="行驶证副页正面"
prop="drivingLicenseViceFront"
:value="certificationAuditForm.drivingLicenseViceFront"
readonly
large
class-prefix="vehicle"
/>
</el-col>
</el-row>
<el-row :gutter="18">
<el-col :span="8">
<image-upload-field
label="行驶证副页反面"
prop="drivingLicenseViceBack"
:value="certificationAuditForm.drivingLicenseViceBack"
readonly
large
class-prefix="vehicle"
/>
</el-col>
<el-col :span="8">
<image-upload-field
label="道路运输证图片"
prop="roadTransportCertImage"
:value="certificationAuditForm.roadTransportCertImage"
readonly
large
class-prefix="vehicle"
/>
</el-col>
<el-col :span="8">
<image-upload-field
label="机动车登记本"
prop="registrationImage"
:value="certificationAuditForm.registrationImage"
readonly
large
class-prefix="vehicle"
/>
</el-col>
</el-row>
</section-card>
</el-form>
<el-form
v-if="showRejectReason"
class="certification-audit__reason"
label-position="right"
label-width="auto"
>
<el-form-item label="驳回原因" required>
<el-input v-model="certificationRejectReason" type="textarea" maxlength="200" show-word-limit />
<el-input
v-model="certificationRejectReason"
type="textarea"
maxlength="200"
show-word-limit
/>
</el-form-item>
</el-form>
<template #footer>
@@ -731,18 +968,6 @@ export default {
}
return this.vehicleForm.id ? '修改车辆' : '新增车辆';
},
auditDetailItems() {
return [
['所属组织', 'organizationName'], ['车牌号', 'plateNo'], ['车牌颜色', 'plateColor'],
['车辆类型', 'vehicleType'], ['外廓长度(mm)', 'outerLength'], ['外廓宽度(mm)', 'outerWidth'],
['外廓高度(mm)', 'outerHeight'], ['核定载质量(KG', 'approvedLoadKg'], ['准牵引总质量(KG', 'tractionMassKg'],
['业务关系', 'businessRelation'], ['能源类型', 'energyType'], ['强制报废日期', 'compulsoryScrapDate'],
['海关备案号', 'customsRecordNo'], ['行驶证档案编号', 'drivingLicenseNo'], ['行驶证有效期起', 'drivingLicenseStartDate'],
['行驶证有效期止', 'drivingLicenseEndDate'], ['道路运输证号', 'roadTransportCertNo'], ['道路运输证有效期起', 'roadTransportCertStartDate'],
['道路运输证有效期止', 'roadTransportCertEndDate'], ['道路运输年审有效期', 'annualReviewEndDate'],
['机动车登记编号', 'registrationNo'], ['机动车登记日期', 'registrationDate'], ['备注', 'remark'],
].map(([label, prop]) => ({ label, prop }));
},
expiryTagOptions() {
return [
{ label: '全部', value: '', statKey: 'total' },
@@ -849,8 +1074,19 @@ export default {
this.certificationAuditBox = true;
});
},
formatAuditValue(item) {
const value = this.certificationAuditForm[item.prop];
auditValue(prop) {
// 长期有效字段:勾选后显示「长期有效」,避免与未填写的「-」混淆
const longTermMap = {
drivingLicenseEndDate: 'drivingLicenseLongTerm',
roadTransportCertEndDate: 'roadTransportCertLongTerm',
annualReviewEndDate: 'annualReviewLongTerm',
compulsoryScrapDate: 'compulsoryScrapLongTerm',
};
const longTermProp = longTermMap[prop];
if (longTermProp && this.certificationAuditForm[longTermProp] === 1) {
return '长期有效';
}
const value = this.certificationAuditForm[prop];
return value === undefined || value === null || value === '' ? '-' : value;
},
handleCertificationApprove() {
@@ -1422,6 +1658,19 @@ export default {
}
}
// 车辆认证审核弹窗:与编辑弹窗一致,灰底 + section-card 白卡分组
.certification-audit {
&__value {
display: block;
color: #303133;
word-break: break-all;
}
&__reason {
margin-top: 12px;
}
}
.vehicle-form {
:deep(.el-date-editor.el-input),
:deep(.el-date-editor.el-input__wrapper),
+19 -29
View File
@@ -1181,24 +1181,25 @@
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="临时额度申请使用期限">
<div class="score-detail-form__range">
<el-date-picker
v-model="currentScore.tempCreditStartDate"
type="date"
value-format="YYYY-MM-DD"
/>
<span>至</span>
<el-date-picker
v-model="currentScore.tempCreditEndDate"
type="date"
value-format="YYYY-MM-DD"
/>
</div>
<el-col :span="6">
<el-form-item label="临时申请额度有效期起">
<el-date-picker
v-model="currentScore.tempCreditStartDate"
type="date"
value-format="YYYY-MM-DD"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-col :span="6">
<el-form-item label="临时申请额度有效期止">
<el-date-picker
v-model="currentScore.tempCreditEndDate"
type="date"
value-format="YYYY-MM-DD"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="评分量化表" required>
<el-select
v-model="currentScore.quantificationId"
@@ -4898,10 +4899,10 @@ export default {
width: 108px !important;
min-width: 108px !important;
color: #70757a;
font-size: 15px;
font-size: 14px;
white-space: normal !important;
word-break: break-all;
line-height: 1.4;
line-height: 1.2;
}
:deep(.el-form-item__content > .el-input),
@@ -4911,17 +4912,6 @@ export default {
}
}
.score-detail-form__range {
display: flex;
align-items: center;
gap: 14px;
:deep(.el-date-editor) {
flex: 1;
min-width: 0;
}
}
.score-category-table {
width: calc(100% - 72px);
margin: 8px 36px 16px;