1bbc97758d
- 解决图标夹在开启/关闭 radio 按钮之间,开启按钮右侧多余间距问题 - 清除开启 radio 默认 margin-right,调整提示图标左右间距 - 提示图标紧靠开启按钮一侧,关闭按钮保持较大间距 - 优化样式,使布局更美观一致
257 lines
28 KiB
Vue
257 lines
28 KiB
Vue
<template>
|
||
<basic-container class="contract-change-page">
|
||
<el-form ref="formRef" :model="form" :rules="rules" label-position="right" label-width="auto" class="contract-change-form">
|
||
<section class="change-section contract-basic-section">
|
||
<div class="dialog-section-title">基本信息</div>
|
||
<div class="contract-basic-section__grid">
|
||
<el-form-item label="变更类型" class="contract-basic-section__change-type"><el-radio-group v-model="form.changeType"><el-radio label="合同信息变更" /><el-radio label="终止合同" /></el-radio-group></el-form-item>
|
||
<el-form-item label="合同编号"><el-input v-model="form.contractNo" disabled /></el-form-item>
|
||
<el-form-item label="合同名称" prop="contractName"><el-input v-model="form.contractName" /></el-form-item>
|
||
<el-form-item label="合同类型"><el-select v-model="form.contractCategory" disabled><el-option label="客户合同" value="客户合同" /><el-option label="承运商合同" value="承运商合同" /></el-select></el-form-item>
|
||
<el-form-item label="甲方"><el-input v-model="form.partyA" disabled /></el-form-item>
|
||
<el-form-item label="乙方"><el-input v-model="form.partyB" disabled /></el-form-item>
|
||
<el-form-item label="所属项目"><el-input v-model="form.projectName" disabled /></el-form-item>
|
||
<el-form-item label="合同期限">
|
||
<div class="contract-basic-section__date-range">
|
||
<el-date-picker v-model="period[0]" type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD" placeholder="YYYY-MM-DD" />
|
||
<span>至</span>
|
||
<el-date-picker v-model="period[1]" type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD" placeholder="YYYY-MM-DD" />
|
||
</div>
|
||
</el-form-item>
|
||
<el-form-item label="所属组织"><el-input v-model="form.organizationName" disabled /></el-form-item>
|
||
<el-form-item label="签订日期"><el-date-picker v-model="form.signDate" type="date" value-format="YYYY-MM-DD" disabled /></el-form-item>
|
||
<el-form-item label="合同格式"><el-select v-model="form.contractFormat"><el-option label="电子合同" value="电子合同" /><el-option label="纸质合同" value="纸质合同" /></el-select></el-form-item>
|
||
<el-form-item label="结算方式"><el-input v-model="form.settlementMode" /></el-form-item>
|
||
<el-form-item label="是否需要加盖法人章"><el-select v-model="form.legalSealFlag"><el-option label="是" :value="1" /><el-option label="否" :value="0" /></el-select></el-form-item>
|
||
<el-form-item label="一式(份)"><el-input v-model="form.copyCount" inputmode="numeric" maxlength="9" placeholder="请输入" @input="value => positiveIntegerInput('copyCount', value)" /></el-form-item>
|
||
<el-form-item label="回款账期"><el-input v-model="form.paymentDays" inputmode="numeric" maxlength="9" placeholder="请输入" @input="value => positiveIntegerInput('paymentDays', value)" /></el-form-item>
|
||
</div>
|
||
<el-form-item label="备注" class="contract-basic-section__remark"><el-input v-model="form.remark" type="textarea" :rows="2" maxlength="2000" show-word-limit placeholder="请输入备注" /></el-form-item>
|
||
</section>
|
||
|
||
<section class="change-section">
|
||
<div class="section-head">
|
||
<div class="dialog-section-title">合同文件</div>
|
||
<el-button type="primary" :disabled="!contractFileRows.length" @click="handleContractFileBatchDownload">批量下载</el-button>
|
||
</div>
|
||
<el-table :data="contractFileRows" border class="change-table" @selection-change="selectedContractFiles = $event"><el-table-column type="selection" width="55" /><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, contractFileRows)">{{ row.originalName || row.name }}</el-link></template></el-table-column><el-table-column label="文件大小" width="120"><template #default="{ row }">{{ formatFileSize(row.size) }}</template></el-table-column><el-table-column prop="uploadUserName" label="上传人" width="140" /><el-table-column prop="uploadTime" label="上传时间" width="170" /><el-table-column label="操作" width="100"><template #default="{ $index }"><el-link type="danger" @click="removeContractFile($index)">删除</el-link></template></el-table-column></el-table>
|
||
<div class="attachment-upload">
|
||
<vehicle-attachment-upload v-model="contractFileRows" :readonly="false" :file-types="attachmentFileTypes" :max-size="50" :show-file-list="false" button-text="上传附件" @change="handleContractFileChange" />
|
||
</div>
|
||
</section>
|
||
|
||
<section class="change-section">
|
||
<div class="section-head"><div class="dialog-section-title">计费信息</div><el-button type="primary" plain @click="addPlan">添加</el-button></div>
|
||
<el-radio-group v-model="feeGenerationMode"><el-radio label="system">系统生成</el-radio><el-radio label="manual">手动生成</el-radio></el-radio-group>
|
||
<el-table :data="plans" border class="change-table"><el-table-column type="index" label="序号" width="70" /><el-table-column prop="planName" label="方案名称" min-width="220" /><el-table-column label="默认方案" min-width="120"><template #default="{ row }">{{ row.defaultPlan ? '是' : '否' }}</template></el-table-column><el-table-column prop="remark" label="备注" min-width="260" /><el-table-column label="操作" width="180"><template #default="{ row, $index }"><el-link type="primary" @click="editPlan(row, $index)">编辑</el-link><el-link type="danger" @click="plans.splice($index, 1)">删除</el-link></template></el-table-column></el-table>
|
||
</section>
|
||
|
||
<section class="change-section">
|
||
<div class="dialog-section-title">结算单规则</div>
|
||
<el-tabs v-model="settlementConfigTab">
|
||
<el-tab-pane label="预结算配置" name="pre" />
|
||
<el-tab-pane label="正式结算配置" name="formal" />
|
||
</el-tabs>
|
||
<div class="settlement-switch">
|
||
<span>自动生成结算单</span>
|
||
<el-radio-group v-model="settlementRule.autoGenerate">
|
||
<el-radio :label="1">开启</el-radio>
|
||
<el-tooltip content="开启时,系统根据配置规则归集运单,定时生成结算单" placement="top">
|
||
<el-icon class="settlement-switch-tip"><QuestionFilled /></el-icon>
|
||
</el-tooltip>
|
||
<el-radio :label="0">关闭</el-radio>
|
||
</el-radio-group>
|
||
</div>
|
||
<el-form v-if="settlementRule.autoGenerate === 1" :model="settlementRule" label-position="right" label-width="auto" class="settlement-form">
|
||
<el-form-item label="账单起始日期" required><el-date-picker v-model="settlementRule.billStartDate" type="date" placeholder="请选择账单起始日期" format="YYYY-MM-DD" value-format="YYYY-MM-DD" /></el-form-item>
|
||
<el-form-item label="结算类型" required><el-select v-model="settlementRule.settlementType" placeholder="请选择结算类型" @change="handleSettlementTypeChange"><el-option v-for="item in settlementTypeOptions" :key="item" :label="item" :value="item" /></el-select></el-form-item>
|
||
<el-form-item v-if="showSettlementBillCycleType" label="账单周期类型" required><el-select v-model="settlementRule.billCycleType" placeholder="请选择账单周期类型" @change="handleCycleTypeChange"><el-option v-for="item in billCycleTypeOptions" :key="item" :label="item" :value="item" /></el-select></el-form-item>
|
||
<el-form-item v-if="showSettlementBillCutoffDay" label="账单截单日" required><el-select v-model="settlementRule.billCutoffDay" placeholder="请选择账单截单日"><el-option v-for="item in billCutoffDayOptions" :key="item.value" :label="item.label" :value="item.value" /></el-select></el-form-item>
|
||
<el-form-item v-if="showSettlementCycleDays" label="周期天数" required><el-select v-model="settlementRule.cycleDays" placeholder="请选择周期天数"><el-option v-for="item in cycleDayOptions" :key="item.value" :label="item.label" :value="item.value" /></el-select></el-form-item>
|
||
</el-form>
|
||
</section>
|
||
|
||
<section class="change-section">
|
||
<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" />
|
||
<el-table-column label="付款比例上限(%)" min-width="220"><template #default="{ row }"><el-input-number v-model="row.ratioLimit" :min="0" :max="100" :precision="2" controls-position="right" /></template></el-table-column>
|
||
<el-table-column label="备注" min-width="220"><template #default="{ row }"><el-input v-model="row.remark" maxlength="200" /></template></el-table-column>
|
||
<el-table-column label="操作" width="100"><template #default="{ $index }"><el-link type="danger" @click="paymentRatioRows.splice($index, 1)">删除</el-link></template></el-table-column>
|
||
</el-table>
|
||
<el-button type="primary" plain @click="addPaymentRatioRow">添加</el-button>
|
||
</section>
|
||
|
||
<billing-plan-editor v-model="planDialogVisible" :value="planEditor" :index="planEditorIndex" @save="savePlan" />
|
||
|
||
<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 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 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">
|
||
<el-table-column type="index" label="序号" width="70" />
|
||
<el-table-column label="文件名" min-width="240"><template #default="{ row }">{{ row.originalName || row.name }}</template></el-table-column>
|
||
<el-table-column label="文件大小" width="120"><template #default="{ row }">{{ formatFileSize(row.size) }}</template></el-table-column>
|
||
<el-table-column label="操作" width="100"><template #default="{ $index }"><el-link type="danger" @click="changeMaterials.splice($index, 1)">删除</el-link></template></el-table-column>
|
||
</el-table>
|
||
<div class="attachment-upload"><vehicle-attachment-upload v-model="changeMaterials" :readonly="false" :file-types="attachmentFileTypes" :max-size="50" :show-file-list="false" button-text="上传变更材料" /></div>
|
||
</section>
|
||
<div class="page-footer">
|
||
<el-button @click="$router.back()">取消</el-button>
|
||
<el-button type="primary" @click="submit">提交</el-button>
|
||
</div>
|
||
</el-form>
|
||
|
||
<el-dialog v-model="documentPreviewVisible" :title="previewFile.name || '附件预览'" append-to-body destroy-on-close width="90%" top="4vh">
|
||
<open-file-viewer v-if="documentPreviewVisible && previewFile.url" :file="previewFile.url" :file-name="previewFile.name" :mime-type="previewFile.mimeType" width="100%" height="72vh" fit="contain" theme="auto" locale="zh-CN" :toolbar="viewerToolbar" :plugins="viewerPlugins" @unsupported="handlePreviewUnsupported" @error="handlePreviewError" />
|
||
</el-dialog>
|
||
<el-image-viewer v-if="imagePreviewVisible" :url-list="imagePreviewUrls" :initial-index="imagePreviewIndex" @close="imagePreviewVisible = false" />
|
||
</basic-container>
|
||
</template>
|
||
|
||
<script>
|
||
import * as api from '@/api/business/contract-manage';
|
||
import BillingPlanEditor from './components/billing-plan-editor.vue';
|
||
import { ElImageViewer } from 'element-plus';
|
||
import { OpenFileViewer } from '@open-file-viewer/vue';
|
||
import { fallbackPlugin, imagePlugin, officePlugin, pdfPlugin, textPlugin } from '@open-file-viewer/core';
|
||
import '@open-file-viewer/core/style.css';
|
||
import pdfWorkerSrc from 'pdfjs-dist/build/pdf.worker.mjs?url';
|
||
|
||
const viewerPlugins = [
|
||
imagePlugin(),
|
||
pdfPlugin({ workerSrc: pdfWorkerSrc, useFetchData: true }),
|
||
officePlugin({ pdf: { workerSrc: pdfWorkerSrc, useFetchData: true } }),
|
||
textPlugin(),
|
||
fallbackPlugin(),
|
||
];
|
||
const normalizeOptionalPositiveInteger = value => {
|
||
if (value === undefined || value === null || value === '') return null;
|
||
const number = Number(value);
|
||
return Number.isInteger(number) && number > 0 ? number : null;
|
||
};
|
||
|
||
export default {
|
||
components: { BillingPlanEditor, ElImageViewer, OpenFileViewer },
|
||
data() { return { form: {}, period: [], plans: [], attachments: [], contractFiles: [], contractFileRows: [], selectedContractFiles: [], paymentRatioRows: [], settlementConfigTab: 'pre', changeMaterials: [], imagePreviewVisible: false, imagePreviewUrls: [], imagePreviewIndex: 0, documentPreviewVisible: false, previewFile: {}, viewerPlugins, viewerToolbar: { zoom: true, rotate: true, download: true, fullscreen: true }, feeGenerationMode: 'system', settlementRule: { autoGenerate: 1, settlementType: '月结', billCycleType: '固定截单日', billCutoffDay: 25, cycleDays: '' }, preSettlementConfig: {}, formalSettlementConfig: {}, settlementTypeOptions: ['月结','日结','周结','半月结','固定天数周期结算'], billCycleTypeOptions: ['固定截单日','自然月'], billCutoffDayOptions: Array.from({ length: 31 }, (_, index) => ({ label: `${index + 1}日`, value: index + 1 })), cycleDayOptions: [7,15,30,60].map(value => ({ label: `${value}天`, value })), planDialogVisible: false, planEditor: { planName: '', defaultPlan: false, remark: '', rules: [] }, planEditorIndex: -1, billingElements: ['按重量','按体积','按车辆','按里程','按吨·公里','固定金额(整单一口价)','按数量'], attachmentFileTypes: ['pdf','bmp','jpeg','png','jpg','doc','docx','ppt','pptx','xlsx','xls','eml','msg','zip'], rules: { contractName: [{ required: true, message: '请输入合同名称', trigger: 'blur' }], changeReason: [{ required: true, message: '请输入变更原因', trigger: 'blur' }] } }; },
|
||
computed: { showSettlementBillCycleType() { return this.settlementRule.settlementType === '月结'; }, showSettlementBillCutoffDay() { return this.showSettlementBillCycleType && this.settlementRule.billCycleType === '固定截单日'; }, showSettlementCycleDays() { return this.settlementRule.settlementType === '固定天数周期结算'; } },
|
||
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.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; },
|
||
editPlan(row, index) { this.planEditorIndex = index; this.planEditor = JSON.parse(JSON.stringify(row)); this.planDialogVisible = true; },
|
||
toggleDefaultPlan(value) { if (value) this.plans.forEach(item => { item.defaultPlan = false; }); },
|
||
savePlan(value, index) { if (index < 0) this.plans.push(value); else this.plans.splice(index, 1, value); if (value.defaultPlan) this.plans.forEach((item, current) => { if (current !== (index < 0 ? this.plans.length - 1 : index)) item.defaultPlan = false; }); },
|
||
handleSettlementTypeChange(value) { if (value !== '月结') { this.settlementRule.billCycleType = ''; this.settlementRule.billCutoffDay = ''; } else if (!this.settlementRule.billCycleType) this.settlementRule.billCycleType = '固定截单日'; if (value !== '固定天数周期结算') this.settlementRule.cycleDays = ''; },
|
||
handleCycleTypeChange(value) { if (value === '固定截单日' && !this.settlementRule.billCutoffDay) this.settlementRule.billCutoffDay = 25; if (value !== '固定截单日') this.settlementRule.billCutoffDay = ''; },
|
||
handleAttachment(event) { const raw = event.raw; if (!raw) return; if (raw.size > 50 * 1024 * 1024) { this.$message.warning('单个文件大小不能超过50M'); return; } this.attachments.push({ name: raw.name, size: `${Math.ceil(raw.size / 1024)}KB`, uploadTime: this.$dayjs().format('YYYY-MM-DD HH:mm:ss') }); },
|
||
handleContractFileChange(list) { this.contractFileRows = (list || []).map(item => ({ ...item, uploadTime: item.uploadTime || this.$dayjs().format('YYYY-MM-DD HH:mm:ss') })); },
|
||
attachmentUrl(row = {}) { return row.url || row.link || row.fileUrl || row.downloadUrl || row.domain || ''; },
|
||
attachmentName(row = {}) { return row.originalName || row.name || row.fileName || '附件'; },
|
||
attachmentExtension(row = {}) { const source = String(this.attachmentName(row) || this.attachmentUrl(row)).split('?')[0]; const index = source.lastIndexOf('.'); return index > -1 ? source.slice(index + 1).toLowerCase() : ''; },
|
||
isAttachmentImage(row) { return ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'].includes(this.attachmentExtension(row)); },
|
||
previewAttachment(row, rows = this.attachments) { const url = this.attachmentUrl(row); if (!url) { this.$message.warning('附件地址为空,无法预览'); return; } if (this.isAttachmentImage(row)) { this.imagePreviewUrls = (rows || []).filter(item => this.isAttachmentImage(item) && this.attachmentUrl(item)).map(item => this.attachmentUrl(item)); this.imagePreviewIndex = Math.max(this.imagePreviewUrls.indexOf(url), 0); this.imagePreviewVisible = true; return; } this.previewFile = { name: this.attachmentName(row), url, mimeType: row.mimeType || row.contentType || '' }; this.documentPreviewVisible = true; },
|
||
handlePreviewUnsupported() { this.$message.warning('当前文件暂不支持在线预览'); },
|
||
handlePreviewError() { this.$message.error('附件预览失败'); },
|
||
removeContractFile(index) { this.contractFileRows.splice(index, 1); },
|
||
handleContractFileBatchDownload() { (this.selectedContractFiles.length ? this.selectedContractFiles : this.contractFileRows).forEach(row => { if (row.url) window.open(row.url, '_blank'); }); },
|
||
formatFileSize(value) { const size = Number(value || 0); return size > 1024 * 1024 ? `${(size / 1024 / 1024).toFixed(2)}MB` : `${Math.max(1, Math.ceil(size / 1024))}KB`; },
|
||
addPaymentRatioRow() { this.paymentRatioRows.push({ paymentTerm: `第${this.paymentRatioRows.length + 1}笔`, ratioLimit: '', remark: '' }); },
|
||
async submit() { await this.$refs.formRef.validate(); const total = this.paymentRatioRows.reduce((sum, row) => sum + Number(row.ratioLimit || 0), 0); if (this.paymentRatioRows.length && Math.abs(total - 100) > 0.0001) { this.$message.warning('付款比例上限合计必须等于100%'); return; } const settlementRule = { preSettlementConfig: this.preSettlementConfig, formalSettlementConfig: this.formalSettlementConfig }; await api.submitChange({ ...this.form, settlementCurrency: String(this.form.settlementCurrency || '').trim() || 'RMB', copyCount: normalizeOptionalPositiveInteger(this.form.copyCount), paymentDays: normalizeOptionalPositiveInteger(this.form.paymentDays), startDate: this.period[0], endDate: this.period[1], feeGenerationMode: this.feeGenerationMode, billingEnabled: this.feeGenerationMode === 'system' ? 1 : 0, billingPlanJson: JSON.stringify(this.plans), settlementRuleJson: JSON.stringify(settlementRule), preSettlementConfigJson: JSON.stringify(this.preSettlementConfig), formalSettlementConfigJson: JSON.stringify(this.formalSettlementConfig), paymentRatioJson: JSON.stringify(this.paymentRatioRows), contractFileJson: JSON.stringify(this.contractFileRows), attachmentsJson: JSON.stringify(this.attachments), changeContent: this.form.changeContent, changeReason: this.form.changeReason, changeAttachmentsJson: JSON.stringify(this.changeMaterials) }); this.$message.success('变更已提交'); this.$router.back(); },
|
||
},
|
||
};
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.contract-change-page { min-height: 100%; padding-bottom: 72px; background: #f5f6fa; }
|
||
.contract-change-page :deep(.basic-container__card) { border: 0; background: transparent; box-shadow: none; }
|
||
.contract-change-form { background: #f5f6fa; }
|
||
.change-section { padding: 20px 24px; background: #fff; border-bottom: 1px solid #eff1f7; margin-top: 12px; }
|
||
.contract-basic-section { margin-bottom: 12px; padding: 14px 16px 16px; overflow: hidden; background: #fff; border-bottom: 0; border-radius: 6px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04); }
|
||
.contract-basic-section > .dialog-section-title { margin-bottom: 20px; color: #303133; }
|
||
.contract-basic-section__grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); column-gap: 48px; }
|
||
.contract-basic-section__change-type { grid-column: 1 / -1; }
|
||
.contract-basic-section__remark { width: 100%; margin-bottom: 0 !important; }
|
||
.contract-basic-section__date-range { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: center; gap: 8px; width: 360px; max-width: 100%; }
|
||
.contract-basic-section__date-range span { color: #606266; }
|
||
.contract-basic-section__date-range :deep(.el-date-editor) { width: auto; min-width: 0; }
|
||
.contract-basic-section :deep(.el-form-item) { align-items: center; margin-bottom: 16px; }
|
||
.contract-basic-section :deep(.el-form-item__label) { flex: 0 0 96px !important; width: 96px !important; height: auto; padding-right: 12px; white-space: normal; word-break: break-all; line-height: 18px; }
|
||
.contract-basic-section :deep(.el-form-item__content) { min-width: 0; }
|
||
.contract-basic-section :deep(.el-input),
|
||
.contract-basic-section :deep(.el-select),
|
||
.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; }
|
||
.unit { margin-left: 8px; }
|
||
.attachment-upload { display: flex; justify-content: flex-start; margin-top: 12px; }
|
||
.attachment-upload .vehicle-attachment-upload { width: auto; }
|
||
.attachment-upload .el-upload { display: inline-flex; }
|
||
.settlement-switch { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; }
|
||
// 问号提示图标紧靠「开启」一侧:清掉开启 radio 自带的右间距,图标与「关闭」之间留大间距
|
||
.settlement-switch :deep(.el-radio:first-child) { margin-right: 0; }
|
||
.settlement-switch-tip { margin: 0 32px 0 8px; color: #a8abb2; cursor: help; font-size: 14px; }
|
||
.settlement-form { display: grid; grid-template-columns: repeat(3, minmax(240px, 1fr)); gap: 8px 28px; }
|
||
.change-reason-section { margin: 20px 0; }
|
||
.page-footer {
|
||
position: fixed;
|
||
right: 0;
|
||
bottom: 0;
|
||
left: 230px;
|
||
z-index: 20;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: flex-end;
|
||
min-height: 64px;
|
||
box-sizing: border-box;
|
||
padding: 12px 24px;
|
||
background: #fff;
|
||
border-top: 1px solid #eff1f7;
|
||
box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.06);
|
||
|
||
// 统一 12px 间距,与全站底部操作栏(去 gap,由相邻按钮 margin 提供)一致
|
||
.el-button + .el-button {
|
||
margin-left: 12px;
|
||
}
|
||
}
|
||
:global(.avue--collapse .page-footer) {
|
||
left: 60px;
|
||
}
|
||
:global(.avue-layout--horizontal .page-footer) {
|
||
left: 0;
|
||
}
|
||
@media (max-width: 1200px) { .contract-basic-section__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 32px; } }
|
||
@media (max-width: 768px) { .contract-basic-section__grid { grid-template-columns: 1fr; } }
|
||
</style>
|