调整 合同
This commit is contained in:
@@ -229,32 +229,38 @@
|
||||
</div></template
|
||||
></el-table-column
|
||||
>
|
||||
<el-table-column label="保底计费重量" width="240"
|
||||
<el-table-column width="240"
|
||||
><template #header
|
||||
><span class="billing-plan-editor__column-title"
|
||||
>保底计费重量<el-tooltip content="实际计量值小于保底数值时按保底计费" placement="top"
|
||||
><el-icon class="billing-plan-editor__default-tip"><InfoFilled /></el-icon></el-tooltip></span></template
|
||||
><template #default="{ row }"
|
||||
><div v-if="readonly && usesRangeMinimum(row)" class="limit-list">
|
||||
<span v-for="(item, rangeIndex) in getRanges(row)" :key="rangeIndex">{{
|
||||
displayValue(item.minimumBillingWeight)
|
||||
rangeIndex === 0
|
||||
? displayValue(item.minimumBillingWeight || row.minimumBillingWeight)
|
||||
: ''
|
||||
}}</span>
|
||||
</div>
|
||||
<span v-else-if="readonly">{{ displayValue(row.minimumBillingWeight) }}</span>
|
||||
<div v-else-if="usesRangeMinimum(row)" class="limit-list">
|
||||
<el-input
|
||||
v-for="(item, rangeIndex) in getRanges(row)"
|
||||
:key="rangeIndex"
|
||||
v-model="item.minimumBillingWeight"
|
||||
:disabled="!canEditMinimum(row)"
|
||||
:placeholder="canEditMinimum(row) ? '请输入保底计费重量' : '无需配置'"
|
||||
@input="value => rangeMinimumInput(row, rangeIndex, value)"
|
||||
/>
|
||||
<template v-for="(item, rangeIndex) in getRanges(row)" :key="rangeIndex">
|
||||
<el-input
|
||||
v-if="rangeIndex === 0"
|
||||
v-model="item.minimumBillingWeight"
|
||||
:disabled="!canEditMinimum(row)"
|
||||
:placeholder="canEditMinimum(row) ? '请输入' : '无需配置'"
|
||||
@input="value => rangeMinimumInput(row, rangeIndex, value)"
|
||||
/>
|
||||
<div v-else class="limit-placeholder" />
|
||||
</template>
|
||||
</div>
|
||||
<el-input
|
||||
v-else
|
||||
v-model="row.minimumBillingWeight"
|
||||
:disabled="!canEditMinimum(row)"
|
||||
:placeholder="
|
||||
canEditMinimum(row)
|
||||
? '实际计量值小于保底数值时按保底计费'
|
||||
: '仅按重量、按吨·公里可填写'
|
||||
canEditMinimum(row) ? '请输入' : '仅按重量、按吨·公里可填写'
|
||||
"
|
||||
@input="value => decimalInput(row, 'minimumBillingWeight', value)" /></template
|
||||
></el-table-column>
|
||||
@@ -297,9 +303,6 @@
|
||||
<el-descriptions-item label="目的地">{{
|
||||
displayValue(matchForm.destination)
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="运输方式">{{
|
||||
transportModeLabel(matchForm.transportMode)
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="货物类型">{{
|
||||
displayValue(matchForm.cargoType)
|
||||
}}</el-descriptions-item>
|
||||
@@ -334,21 +337,6 @@
|
||||
@visible-change="v => v && ensureRegions()"
|
||||
@change="v => matchRegionChange('destination', v)" /></el-form-item
|
||||
></el-col>
|
||||
<el-col :span="12"
|
||||
><el-form-item label="运输方式"
|
||||
><el-select
|
||||
v-model="matchForm.transportMode"
|
||||
:loading="transportModeLoading"
|
||||
:disabled="readonly"
|
||||
placeholder="请选择运输方式"
|
||||
clearable
|
||||
filterable
|
||||
><el-option
|
||||
v-for="item in transportModeOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value" /></el-select></el-form-item
|
||||
></el-col>
|
||||
<el-col :span="12"
|
||||
><el-form-item label="货物类型"
|
||||
><el-cascader
|
||||
@@ -560,30 +548,24 @@ export default {
|
||||
return next;
|
||||
},
|
||||
normalizeRanges(row) {
|
||||
const ranges = Array.isArray(row.limitRanges)
|
||||
? row.limitRanges
|
||||
.map(item => ({
|
||||
lowerLimit: item?.lowerLimit ?? '',
|
||||
upperLimit: item?.upperLimit ?? '',
|
||||
unitPrice:
|
||||
item?.unitPrice === undefined || item?.unitPrice === ''
|
||||
? row.unitPrice ?? ''
|
||||
: item.unitPrice,
|
||||
minimumBillingWeight:
|
||||
item?.minimumBillingWeight === undefined || item?.minimumBillingWeight === ''
|
||||
? this.usesRangeMinimum(row)
|
||||
? row.minimumBillingWeight ?? ''
|
||||
: ''
|
||||
: item.minimumBillingWeight,
|
||||
}))
|
||||
.filter(
|
||||
item =>
|
||||
item.lowerLimit !== '' ||
|
||||
item.upperLimit !== '' ||
|
||||
item.unitPrice !== '' ||
|
||||
item.minimumBillingWeight !== ''
|
||||
)
|
||||
: [];
|
||||
const rawRanges = Array.isArray(row.limitRanges) ? row.limitRanges : [];
|
||||
const ranges = rawRanges
|
||||
.map((item, index) => ({
|
||||
lowerLimit: item?.lowerLimit ?? '',
|
||||
upperLimit: item?.upperLimit ?? '',
|
||||
unitPrice:
|
||||
item?.unitPrice === undefined || item?.unitPrice === ''
|
||||
? row.unitPrice ?? ''
|
||||
: item.unitPrice,
|
||||
minimumBillingWeight: this.resolveRangeMinimum(row, item, index),
|
||||
}))
|
||||
.filter(
|
||||
item =>
|
||||
item.lowerLimit !== '' ||
|
||||
item.upperLimit !== '' ||
|
||||
item.unitPrice !== '' ||
|
||||
item.minimumBillingWeight !== ''
|
||||
);
|
||||
if (
|
||||
!ranges.length &&
|
||||
(row.lowerLimit !== '' ||
|
||||
@@ -598,9 +580,23 @@ export default {
|
||||
minimumBillingWeight: this.usesRangeMinimum(row) ? row.minimumBillingWeight ?? '' : '',
|
||||
});
|
||||
return ranges.length
|
||||
? ranges
|
||||
? ranges.map((item, index) => ({
|
||||
...item,
|
||||
minimumBillingWeight: this.usesRangeMinimum(row)
|
||||
? index === 0
|
||||
? item.minimumBillingWeight
|
||||
: ''
|
||||
: '',
|
||||
}))
|
||||
: [{ lowerLimit: '', upperLimit: '', unitPrice: '', minimumBillingWeight: '' }];
|
||||
},
|
||||
resolveRangeMinimum(row, item, index) {
|
||||
if (!this.usesRangeMinimum(row) || index !== 0) return '';
|
||||
if (item?.minimumBillingWeight !== undefined && item?.minimumBillingWeight !== '') {
|
||||
return item.minimumBillingWeight;
|
||||
}
|
||||
return row.minimumBillingWeight ?? '';
|
||||
},
|
||||
syncLegacyLimit(row) {
|
||||
const first = row.limitRanges?.[0] || {};
|
||||
row.lowerLimit = first.lowerLimit ?? '';
|
||||
@@ -803,11 +799,16 @@ export default {
|
||||
if (index === 0) row.unitPrice = target.value;
|
||||
},
|
||||
rangeMinimumInput(row, index, value) {
|
||||
if (index !== 0) return;
|
||||
row.limitRanges = this.getRanges(row);
|
||||
const target = { value };
|
||||
this.decimalInput(target, 'value', value);
|
||||
row.limitRanges[index].minimumBillingWeight = target.value;
|
||||
if (index === 0) row.minimumBillingWeight = target.value;
|
||||
row.limitRanges[0].minimumBillingWeight = target.value;
|
||||
row.minimumBillingWeight = target.value;
|
||||
row.limitRanges = row.limitRanges.map((item, rangeIndex) => ({
|
||||
...item,
|
||||
minimumBillingWeight: rangeIndex === 0 ? target.value : '',
|
||||
}));
|
||||
},
|
||||
addRule() {
|
||||
this.draft.rules.push(defaultRule());
|
||||
@@ -929,15 +930,22 @@ export default {
|
||||
plan.transportModeLabel = transportMode?.label || plan.transportMode;
|
||||
plan.rules = plan.rules.map(rule => {
|
||||
const ranges = this.canEditLimit(rule) ? this.getRanges(rule) : [];
|
||||
const normalizedRanges = ranges.map((item, rangeIndex) => ({
|
||||
...item,
|
||||
minimumBillingWeight:
|
||||
this.usesRangeMinimum(rule) && rangeIndex === 0 ? item.minimumBillingWeight || '' : '',
|
||||
}));
|
||||
return {
|
||||
...rule,
|
||||
unitPrice: this.usesRangeUnitPrice(rule) ? ranges[0]?.unitPrice || '' : rule.unitPrice,
|
||||
limitRanges: ranges,
|
||||
lowerLimit: ranges[0]?.lowerLimit || '',
|
||||
upperLimit: ranges[0]?.upperLimit || '',
|
||||
unitPrice: this.usesRangeUnitPrice(rule)
|
||||
? normalizedRanges[0]?.unitPrice || ''
|
||||
: rule.unitPrice,
|
||||
limitRanges: normalizedRanges,
|
||||
lowerLimit: normalizedRanges[0]?.lowerLimit || '',
|
||||
upperLimit: normalizedRanges[0]?.upperLimit || '',
|
||||
minimumBillingWeight: this.canEditMinimum(rule)
|
||||
? this.usesRangeMinimum(rule)
|
||||
? ranges[0]?.minimumBillingWeight || ''
|
||||
? normalizedRanges[0]?.minimumBillingWeight || ''
|
||||
: rule.minimumBillingWeight
|
||||
: '',
|
||||
};
|
||||
@@ -950,9 +958,6 @@ export default {
|
||||
this.matchIndex = index;
|
||||
this.matchForm = { ...defaultRule().matchCondition, ...(row.matchCondition || {}) };
|
||||
this.matchVisible = true;
|
||||
this.ensureTransportModes().then(() => {
|
||||
this.matchForm.transportMode = this.normalizeTransportMode(this.matchForm.transportMode);
|
||||
});
|
||||
this.ensureRegions();
|
||||
this.ensureCargo().then(() => {
|
||||
const path = this.resolveCargoPath(this.matchForm);
|
||||
@@ -977,21 +982,6 @@ export default {
|
||||
});
|
||||
return this.transportModeRequest;
|
||||
},
|
||||
normalizeTransportMode(value) {
|
||||
const transportMode = String(value || '').trim();
|
||||
if (!transportMode) return '';
|
||||
const option = this.transportModeOptions.find(item => {
|
||||
const optionValue = String(item.value || '').trim();
|
||||
const optionLabel = String(item.label || '').trim();
|
||||
return (
|
||||
optionValue === transportMode ||
|
||||
optionLabel === transportMode ||
|
||||
optionLabel.includes(transportMode) ||
|
||||
transportMode.includes(optionLabel)
|
||||
);
|
||||
});
|
||||
return option?.value || transportMode;
|
||||
},
|
||||
ensureRegions() {
|
||||
if (this.regionOptions.length) return Promise.resolve(this.regionOptions);
|
||||
if (this.regionRequest) return this.regionRequest;
|
||||
@@ -1214,6 +1204,11 @@ export default {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.billing-plan-editor__column-title {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.limit-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -1229,4 +1224,8 @@ export default {
|
||||
.limit-row .el-input {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.limit-placeholder {
|
||||
height: 32px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1927,13 +1927,13 @@
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="showSettlementBillCycleType"
|
||||
label="账单周期类型"
|
||||
label="结算周期"
|
||||
required
|
||||
:error="settlementRuleErrors.billCycleType"
|
||||
>
|
||||
<el-select
|
||||
v-model="settlementRuleForm.billCycleType"
|
||||
placeholder="请选择账单周期类型"
|
||||
placeholder="请选择结算周期"
|
||||
:disabled="dialogReadonly"
|
||||
@change="handleSettlementBillCycleTypeChange"
|
||||
>
|
||||
@@ -1986,6 +1986,59 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div
|
||||
v-if="settlementRuleEnabled && showSettlementCustomPeriods"
|
||||
class="business-crud-page__custom-periods"
|
||||
>
|
||||
<el-table :data="settlementRuleForm.customPeriods || []" border>
|
||||
<el-table-column type="index" label="序号" width="80" align="center" />
|
||||
<el-table-column label="运单区间-开始日" min-width="180" align="center">
|
||||
<template #default="{ row, $index }">
|
||||
<el-select
|
||||
:model-value="row.startDay"
|
||||
placeholder="请选择"
|
||||
clearable
|
||||
:disabled="dialogReadonly"
|
||||
@update:model-value="value => handleCustomPeriodStartDayChange($index, value)"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in billCutoffDayOptions"
|
||||
:key="`start-${item.value}`"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="运单区间-结束日" min-width="200" align="center">
|
||||
<template #default="{ row, $index }">
|
||||
<el-select
|
||||
:model-value="row.endDay"
|
||||
placeholder="请选择"
|
||||
clearable
|
||||
:disabled="dialogReadonly"
|
||||
@update:model-value="value => handleCustomPeriodEndDayChange($index, value)"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in customPeriodEndDayOptions(row)"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="!dialogReadonly" label="操作" width="100" align="center">
|
||||
<template #default="{ $index }">
|
||||
<el-link v-if="$index === 0" type="primary" @click="addCustomPeriodRow">添加</el-link>
|
||||
<el-link v-else type="danger" @click="removeCustomPeriodRow($index)">删除</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<template v-if="!dialogReadonly" #empty>
|
||||
<el-link type="primary" @click="addCustomPeriodRow">添加</el-link>
|
||||
</template>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -5412,13 +5465,19 @@ const defaultBillingPlan = () => ({
|
||||
});
|
||||
|
||||
const defaultSettlementRule = () => ({
|
||||
autoGenerate: 1,
|
||||
autoGenerate: '',
|
||||
billStartDate: '',
|
||||
settlementType: '月结',
|
||||
billCycleType: '固定截单日',
|
||||
billCutoffDay: 25,
|
||||
settlementType: '',
|
||||
billCycleType: '',
|
||||
billCutoffDay: '',
|
||||
cycleDays: '',
|
||||
customPeriods: [],
|
||||
});
|
||||
const normalizeCustomPeriods = (periods = []) =>
|
||||
(periods || []).map(item => ({
|
||||
startDay: Number(item?.startDay) > 0 ? Number(item.startDay) : '',
|
||||
endDay: Number(item?.endDay) > 0 ? Number(item.endDay) : '',
|
||||
}));
|
||||
|
||||
const defaultReconciliation = () => ({
|
||||
skipReconciliation: 1,
|
||||
@@ -5837,7 +5896,7 @@ export default {
|
||||
按数量: ['固定单价', '区间单价', '阶梯单价', '区间阶梯一口价'],
|
||||
},
|
||||
settlementTypeOptions: ['月结', '日结', '周结', '半月结', '固定天数周期结算'],
|
||||
billCycleTypeOptions: ['固定截单日', '自然月'],
|
||||
billCycleTypeOptions: ['固定截单日', '自然月', '自定义多周期'],
|
||||
reconciliationModeOptions: ['明细逐行核对', '按账单汇总核对', '跳过自动核对'],
|
||||
packageOptions,
|
||||
quantityUnitOptions: ['吨', '千克', '立方米', '件', '车', '箱', '托盘'],
|
||||
@@ -6448,6 +6507,11 @@ export default {
|
||||
this.showSettlementBillCycleType && this.settlementRuleForm.billCycleType === '固定截单日'
|
||||
);
|
||||
},
|
||||
showSettlementCustomPeriods() {
|
||||
return (
|
||||
this.showSettlementBillCycleType && this.settlementRuleForm.billCycleType === '自定义多周期'
|
||||
);
|
||||
},
|
||||
showSettlementCycleDays() {
|
||||
return this.settlementRuleForm.settlementType === '固定天数周期结算';
|
||||
},
|
||||
@@ -7025,7 +7089,7 @@ export default {
|
||||
if (!row) return '-';
|
||||
if (prop === 'businessStatus') return this.displayStatus(row, prop);
|
||||
if (prop === 'feeGenerationMode') {
|
||||
return row[prop] === 'manual' ? '手动生成' : '系统生成';
|
||||
return row[prop] === 'manual' ? '账单导入生成' : '系统生成';
|
||||
}
|
||||
const column = this.findColumn(this.option.column, prop);
|
||||
if (column?.formatter) return column.formatter(row, {}, row[prop]);
|
||||
@@ -7566,23 +7630,32 @@ export default {
|
||||
isFixedBillCutoffSettlement(rule = this.settlementRuleForm) {
|
||||
return this.isMonthlySettlement(rule) && rule.billCycleType === '固定截单日';
|
||||
},
|
||||
isCustomMultiPeriodSettlement(rule = this.settlementRuleForm) {
|
||||
return this.isMonthlySettlement(rule) && rule.billCycleType === '自定义多周期';
|
||||
},
|
||||
isFixedCycleSettlement(rule = this.settlementRuleForm) {
|
||||
return rule.settlementType === '固定天数周期结算';
|
||||
},
|
||||
handleSettlementTypeChange(value) {
|
||||
this.clearSettlementRuleError('settlementType');
|
||||
if (value === '月结') {
|
||||
if (!this.settlementRuleForm.billCycleType) {
|
||||
this.settlementRuleForm.billCycleType = '固定截单日';
|
||||
}
|
||||
if (this.settlementRuleForm.billCycleType === '固定截单日') {
|
||||
this.settlementRuleForm.billCutoffDay = this.settlementRuleForm.billCutoffDay || 25;
|
||||
this.settlementRuleForm.customPeriods = [];
|
||||
} else if (this.settlementRuleForm.billCycleType === '自定义多周期') {
|
||||
this.settlementRuleForm.billCutoffDay = '';
|
||||
this.settlementRuleForm.customPeriods = normalizeCustomPeriods(
|
||||
this.settlementRuleForm.customPeriods || []
|
||||
);
|
||||
} else {
|
||||
this.settlementRuleForm.billCutoffDay = '';
|
||||
this.settlementRuleForm.customPeriods = [];
|
||||
}
|
||||
this.settlementRuleForm.cycleDays = '';
|
||||
return;
|
||||
}
|
||||
this.settlementRuleForm.billCycleType = '';
|
||||
this.settlementRuleForm.billCutoffDay = '';
|
||||
this.settlementRuleForm.customPeriods = [];
|
||||
if (value !== '固定天数周期结算') {
|
||||
this.settlementRuleForm.cycleDays = '';
|
||||
}
|
||||
@@ -7590,10 +7663,17 @@ export default {
|
||||
handleSettlementBillCycleTypeChange(value) {
|
||||
this.clearSettlementRuleError('billCycleType');
|
||||
if (value === '固定截单日') {
|
||||
this.settlementRuleForm.billCutoffDay = this.settlementRuleForm.billCutoffDay || 25;
|
||||
this.settlementRuleForm.customPeriods = [];
|
||||
return;
|
||||
}
|
||||
this.settlementRuleForm.billCutoffDay = '';
|
||||
if (value === '自定义多周期') {
|
||||
this.settlementRuleForm.customPeriods = normalizeCustomPeriods(
|
||||
this.settlementRuleForm.customPeriods || []
|
||||
);
|
||||
return;
|
||||
}
|
||||
this.settlementRuleForm.customPeriods = [];
|
||||
},
|
||||
normalizeSettlementRule(rule = this.settlementRuleForm) {
|
||||
const nextRule = {
|
||||
@@ -7603,14 +7683,94 @@ export default {
|
||||
if (!this.isMonthlySettlement(nextRule)) {
|
||||
nextRule.billCycleType = '';
|
||||
nextRule.billCutoffDay = '';
|
||||
nextRule.customPeriods = [];
|
||||
} else if (!this.isFixedBillCutoffSettlement(nextRule)) {
|
||||
nextRule.billCutoffDay = '';
|
||||
}
|
||||
if (this.isCustomMultiPeriodSettlement(nextRule)) {
|
||||
nextRule.customPeriods = normalizeCustomPeriods(
|
||||
Array.isArray(nextRule.customPeriods) ? nextRule.customPeriods : []
|
||||
);
|
||||
} else {
|
||||
nextRule.customPeriods = [];
|
||||
}
|
||||
if (!this.isFixedCycleSettlement(nextRule)) {
|
||||
nextRule.cycleDays = '';
|
||||
}
|
||||
return nextRule;
|
||||
},
|
||||
customPeriodEndDayOptions(row) {
|
||||
const startDay = Number(row?.startDay);
|
||||
if (!Number.isFinite(startDay) || startDay < 1) return this.billCutoffDayOptions;
|
||||
return Array.from({ length: 31 - startDay + 1 }, (_, index) => {
|
||||
const value = startDay + index;
|
||||
return { label: `${value}日`, value };
|
||||
});
|
||||
},
|
||||
handleCustomPeriodStartDayChange(index, value) {
|
||||
const periods = normalizeCustomPeriods(this.settlementRuleForm.customPeriods || []);
|
||||
const row = periods[index];
|
||||
if (!row) return;
|
||||
row.startDay = value || '';
|
||||
const startDay = Number(row.startDay);
|
||||
const endDay = Number(row.endDay);
|
||||
if (
|
||||
Number.isFinite(startDay) &&
|
||||
Number.isFinite(endDay) &&
|
||||
(endDay < startDay || endDay > 31)
|
||||
) {
|
||||
row.endDay = '';
|
||||
}
|
||||
this.settlementRuleForm.customPeriods = periods;
|
||||
},
|
||||
handleCustomPeriodEndDayChange(index, value) {
|
||||
const periods = normalizeCustomPeriods(this.settlementRuleForm.customPeriods || []);
|
||||
const row = periods[index];
|
||||
if (!row) return;
|
||||
row.endDay = value || '';
|
||||
this.settlementRuleForm.customPeriods = periods;
|
||||
},
|
||||
addCustomPeriodRow() {
|
||||
const periods = normalizeCustomPeriods(this.settlementRuleForm.customPeriods || []);
|
||||
periods.push({ startDay: '', endDay: '' });
|
||||
this.settlementRuleForm.customPeriods = periods;
|
||||
},
|
||||
removeCustomPeriodRow(index) {
|
||||
if (index <= 0) return;
|
||||
const periods = [...(this.settlementRuleForm.customPeriods || [])];
|
||||
periods.splice(index, 1);
|
||||
this.settlementRuleForm.customPeriods = normalizeCustomPeriods(periods);
|
||||
},
|
||||
validateCustomPeriods(periods = [], label = '') {
|
||||
const rows = normalizeCustomPeriods(periods);
|
||||
const prefix = label ? `${label}:` : '';
|
||||
if (!rows.length) {
|
||||
this.$message.warning(`${prefix}请至少配置一段自定义周期`);
|
||||
return false;
|
||||
}
|
||||
for (let index = 0; index < rows.length; index += 1) {
|
||||
const row = rows[index];
|
||||
const startDay = Number(row.startDay);
|
||||
const endDay = Number(row.endDay);
|
||||
if (!Number.isFinite(startDay) || startDay < 1 || startDay > 31) {
|
||||
this.$message.warning(`${prefix}请选择第${index + 1}行运单区间开始日`);
|
||||
return false;
|
||||
}
|
||||
if (!Number.isFinite(endDay) || endDay < 1 || endDay > 31) {
|
||||
this.$message.warning(`${prefix}请选择第${index + 1}行运单区间结束日`);
|
||||
return false;
|
||||
}
|
||||
if (endDay < startDay) {
|
||||
this.$message.warning(`${prefix}第${index + 1}行结束日不能早于开始日`);
|
||||
return false;
|
||||
}
|
||||
if (index > 0 && startDay !== Number(rows[index - 1].endDay) + 1) {
|
||||
this.$message.warning(`${prefix}自定义多周期区间必须连续,不允许重叠或存在日期缺口`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
clearSettlementRuleError(field) {
|
||||
if (!this.settlementRuleErrors[field]) return;
|
||||
this.settlementRuleErrors = {
|
||||
@@ -7632,8 +7792,8 @@ export default {
|
||||
return false;
|
||||
}
|
||||
if (this.isMonthlySettlement(rule) && this.isBillingFieldEmpty(rule.billCycleType)) {
|
||||
this.settlementRuleErrors = { billCycleType: '请选择账单周期类型' };
|
||||
this.$message.warning(`${label}${label ? ':' : ''}请选择账单周期类型`);
|
||||
this.settlementRuleErrors = { billCycleType: '请选择结算周期' };
|
||||
this.$message.warning(`${label}${label ? ':' : ''}请选择结算周期`);
|
||||
return false;
|
||||
}
|
||||
if (this.isFixedBillCutoffSettlement(rule)) {
|
||||
@@ -7649,6 +7809,9 @@ export default {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (this.isCustomMultiPeriodSettlement(rule)) {
|
||||
return this.validateCustomPeriods(rule.customPeriods, label);
|
||||
}
|
||||
if (this.isFixedCycleSettlement(rule)) {
|
||||
const cycleDays = Number(rule.cycleDays);
|
||||
if (!Number.isInteger(cycleDays) || cycleDays < 1 || cycleDays > 365) {
|
||||
@@ -11239,8 +11402,10 @@ export default {
|
||||
if (!this.canEditBillingLimit(row)) {
|
||||
continue;
|
||||
}
|
||||
const key = row.billingElement || '';
|
||||
groups[key] = groups[key] || [];
|
||||
const feeItem = String(row.feeItem || '').trim();
|
||||
const billingElement = String(row.billingElement || '').trim();
|
||||
const key = JSON.stringify([feeItem, billingElement]);
|
||||
groups[key] = groups[key] || { feeItem, billingElement, ranges: [] };
|
||||
const ranges = this.getBillingLimitRanges(row);
|
||||
for (const range of ranges) {
|
||||
const lower = Number(range.lowerLimit);
|
||||
@@ -11258,14 +11423,14 @@ export default {
|
||||
this.$message.warning('计费要素下限不能大于上限');
|
||||
return false;
|
||||
}
|
||||
groups[key].push({ lower, upper });
|
||||
groups[key].ranges.push({ lower, upper });
|
||||
}
|
||||
}
|
||||
return this.validateBillingLimitRangeGroups(groups);
|
||||
},
|
||||
validateBillingLimitRangeGroups(groups) {
|
||||
const precision = 0.000001;
|
||||
for (const [billingElement, ranges] of Object.entries(groups)) {
|
||||
for (const { feeItem, billingElement, ranges } of Object.values(groups)) {
|
||||
if (ranges.length <= 1) continue;
|
||||
const sortedRanges = [...ranges].sort((prev, next) => {
|
||||
if (prev.lower !== next.lower) return prev.lower - next.lower;
|
||||
@@ -11275,11 +11440,13 @@ export default {
|
||||
const prevRange = sortedRanges[index - 1];
|
||||
const currentRange = sortedRanges[index];
|
||||
if (currentRange.lower < prevRange.upper - precision) {
|
||||
this.$message.warning(`${billingElement}的计费要素区间不能重叠`);
|
||||
this.$message.warning(`费用项“${feeItem}”${billingElement}的计费要素区间不能重叠`);
|
||||
return false;
|
||||
}
|
||||
if (currentRange.lower > prevRange.upper + precision) {
|
||||
this.$message.warning(`${billingElement}的计费要素区间必须连续,不能存在间隙`);
|
||||
this.$message.warning(
|
||||
`费用项“${feeItem}”${billingElement}的计费要素区间必须连续,不能存在间隙`
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,493 @@
|
||||
<template>
|
||||
<section
|
||||
class="contract-manage-form__section contract-manage-form__section--panel contract-manage-form__section--attachment"
|
||||
>
|
||||
<div class="contract-manage-form__attachment-head">
|
||||
<div class="dialog-section-title">{{ title }}</div>
|
||||
<el-button type="primary" :disabled="!rows.length" @click="batchDownload">批量下载</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
:data="rows"
|
||||
border
|
||||
class="contract-manage-form__attachment-table"
|
||||
@selection-change="selected = $event"
|
||||
>
|
||||
<el-table-column v-if="!readonly" type="selection" width="55" align="center" />
|
||||
<el-table-column type="index" label="序号" width="70" align="center" />
|
||||
<el-table-column v-if="attachmentType" label="附件类型" min-width="160" align="center">
|
||||
<template #default="{ row }">
|
||||
<span v-if="readonly || isRowLocked(row)">{{ row.fileType || '-' }}</span>
|
||||
<el-select
|
||||
v-else
|
||||
:model-value="row.fileType"
|
||||
placeholder="请选择"
|
||||
:teleported="false"
|
||||
:fit-input-width="true"
|
||||
@update:model-value="value => updateRowFileType(row, value)"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in contractAttachmentTypeOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="文件名"
|
||||
min-width="240"
|
||||
align="left"
|
||||
header-align="left"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-link type="primary" @click="preview?.(row, rows)">{{ attachmentName(row) }}</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="description" label="附件描述" min-width="220">
|
||||
<template #default="{ row }">
|
||||
<span v-if="readonly || isRowLocked(row)">{{ row.description || '-' }}</span>
|
||||
<el-input
|
||||
v-else
|
||||
:model-value="row.description"
|
||||
maxlength="200"
|
||||
@update:model-value="value => updateRowDescription(row, value)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="文件大小" width="120" align="center">
|
||||
<template #default="{ row }">{{ formatSize(row.size) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="uploadUserName" label="上传人" width="140" align="center" />
|
||||
<el-table-column prop="uploadTime" label="上传时间" width="180" align="center" sortable />
|
||||
<el-table-column v-if="!readonly" label="操作" width="100" align="center" fixed="right">
|
||||
<template #default="{ row, $index }">
|
||||
<span v-if="isRowLocked(row)">-</span>
|
||||
<el-link v-else type="danger" @click="remove($index)">删除</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<div v-if="!readonly" class="contract-manage-form__attachment-upload">
|
||||
<template v-if="useUploadDialog">
|
||||
<el-button type="primary" plain @click="openUploadDialog">上传附件</el-button>
|
||||
<span class="contract-manage-form__attachment-tip">
|
||||
支持pdf、bmp、jpeg、png、jpg、doc、docx、ppt、pptx、xlsx、xls、eml、msg、zip的文件格式,单个文件不超过50M
|
||||
</span>
|
||||
</template>
|
||||
<vehicle-attachment-upload
|
||||
v-else
|
||||
:model-value="rows"
|
||||
:file-types="attachmentFileTypes"
|
||||
:max-size="50"
|
||||
show-tip
|
||||
tip="支持pdf、bmp、jpeg、png、jpg、doc、docx、ppt、pptx、xlsx、xls、eml、msg、zip的文件格式,单个文件不超过50M"
|
||||
:show-file-list="false"
|
||||
button-text="上传附件"
|
||||
@update:model-value="handleChange"
|
||||
@change="handleChange"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<el-dialog
|
||||
v-model="uploadDialogVisible"
|
||||
title="附件上传"
|
||||
width="560px"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
:close-on-click-modal="false"
|
||||
class="contract-attachment-upload-dialog"
|
||||
@closed="resetUploadDialog"
|
||||
>
|
||||
<div class="contract-attachment-upload-dialog__body">
|
||||
<div class="contract-attachment-upload-dialog__field">
|
||||
<span class="contract-attachment-upload-dialog__label">附件位置</span>
|
||||
<el-select model-value="合同文件" disabled style="width: 100%">
|
||||
<el-option label="合同文件" value="合同文件" />
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="contract-attachment-upload-dialog__field">
|
||||
<span class="contract-attachment-upload-dialog__label">附件类型</span>
|
||||
<el-select v-model="uploadDialogType" placeholder="请选择附件类型" style="width: 100%">
|
||||
<el-option
|
||||
v-for="item in contractAttachmentTypeOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="contract-attachment-upload-dialog__uploader">
|
||||
<el-upload
|
||||
drag
|
||||
multiple
|
||||
:action="uploadAction"
|
||||
:headers="uploadHeaders"
|
||||
:accept="acceptText"
|
||||
:show-file-list="true"
|
||||
:before-upload="beforeUpload"
|
||||
:on-success="handleDialogSuccess"
|
||||
:on-error="handleDialogError"
|
||||
:on-remove="handleDialogRemove"
|
||||
:file-list="uploadDialogFileList"
|
||||
>
|
||||
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
|
||||
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
||||
</el-upload>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="contract-attachment-upload-dialog__footer">
|
||||
<el-button type="primary" @click="confirmUploadDialog">确定</el-button>
|
||||
<el-button type="primary" @click="uploadDialogVisible = false">取消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { UploadFilled } from '@element-plus/icons-vue';
|
||||
import { baseUrl } from '@/config/env';
|
||||
import { getUploadHeaders } from '@/utils/upload';
|
||||
import { downloadFileByUrl } from '@/utils/util';
|
||||
|
||||
const CONTRACT_ATTACHMENT_TYPE_OTHER = '其它文件';
|
||||
export const contractAttachmentTypeOptions = [
|
||||
{ label: '合同文件', value: '合同文件' },
|
||||
{ label: '双章归档文件', value: '双章归档文件' },
|
||||
{ label: '其它文件', value: CONTRACT_ATTACHMENT_TYPE_OTHER },
|
||||
];
|
||||
export const attachmentFileTypes = [
|
||||
'pdf',
|
||||
'bmp',
|
||||
'jpeg',
|
||||
'png',
|
||||
'jpg',
|
||||
'doc',
|
||||
'docx',
|
||||
'ppt',
|
||||
'pptx',
|
||||
'xlsx',
|
||||
'xls',
|
||||
'eml',
|
||||
'msg',
|
||||
'zip',
|
||||
];
|
||||
|
||||
export const attachmentName = row => row?.originalName || row?.name || row?.fileName || '附件';
|
||||
export const attachmentUrl = row =>
|
||||
row?.url || row?.link || row?.fileUrl || row?.downloadUrl || row?.domain || '';
|
||||
export const isAttachmentApproved = row =>
|
||||
row?.approved === true ||
|
||||
row?.approved === 1 ||
|
||||
row?.approved === '1' ||
|
||||
row?.approvalStatus === 'approved';
|
||||
|
||||
const normalizeAttachmentTypeText = value => {
|
||||
let text = String(value || '').split(/[?#]/)[0];
|
||||
try {
|
||||
text = decodeURIComponent(text);
|
||||
} catch (error) {
|
||||
// ignore decode error
|
||||
}
|
||||
return text
|
||||
.replace(/\.[^.\\/]+$/, '')
|
||||
.toLowerCase()
|
||||
.replace(/[\s_\-—–·•()()\[\]【】{}《》<>“”"'、,,。.]/g, '');
|
||||
};
|
||||
|
||||
const attachmentTypeKeywords = fileType => {
|
||||
if (fileType === '双章归档文件') return ['双章归档文件', '双章归档', '双章'];
|
||||
if (fileType === '合同文件') return ['合同文件', '合同'];
|
||||
return [fileType];
|
||||
};
|
||||
|
||||
export const resolveContractAttachmentType = (row = {}) => {
|
||||
const values = contractAttachmentTypeOptions.map(item => item.value);
|
||||
if (values.includes(row.fileType)) return row.fileType;
|
||||
const fileName = normalizeAttachmentTypeText(attachmentName(row));
|
||||
if (!fileName) return CONTRACT_ATTACHMENT_TYPE_OTHER;
|
||||
const matched = contractAttachmentTypeOptions
|
||||
.filter(item => item.value !== CONTRACT_ATTACHMENT_TYPE_OTHER)
|
||||
.flatMap(item =>
|
||||
attachmentTypeKeywords(item.value).map(keyword => ({
|
||||
value: item.value,
|
||||
keyword: normalizeAttachmentTypeText(keyword),
|
||||
}))
|
||||
)
|
||||
.filter(item => item.keyword)
|
||||
.sort((a, b) => b.keyword.length - a.keyword.length)
|
||||
.find(item => fileName.includes(item.keyword));
|
||||
return matched?.value || CONTRACT_ATTACHMENT_TYPE_OTHER;
|
||||
};
|
||||
|
||||
export const normalizeContractFileRows = rows =>
|
||||
(rows || []).map(row => ({
|
||||
...row,
|
||||
fileType: resolveContractAttachmentType(row),
|
||||
description: row.description || '',
|
||||
}));
|
||||
|
||||
export default {
|
||||
name: 'ContractAttachmentSection',
|
||||
components: { UploadFilled },
|
||||
props: {
|
||||
title: { type: String, required: true },
|
||||
rows: { type: Array, default: () => [] },
|
||||
description: Boolean,
|
||||
attachmentType: Boolean,
|
||||
readonly: Boolean,
|
||||
lockApproved: Boolean,
|
||||
markApprovedOnUpload: Boolean,
|
||||
useUploadDialog: Boolean,
|
||||
preview: { type: Function, default: null },
|
||||
},
|
||||
emits: ['update:rows'],
|
||||
data() {
|
||||
return {
|
||||
selected: [],
|
||||
attachmentFileTypes,
|
||||
contractAttachmentTypeOptions,
|
||||
uploadDialogVisible: false,
|
||||
uploadDialogType: CONTRACT_ATTACHMENT_TYPE_OTHER,
|
||||
uploadDialogFiles: [],
|
||||
uploadDialogFileList: [],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
uploadAction() {
|
||||
return `${baseUrl}/blade-resource/oss/endpoint/put-file`;
|
||||
},
|
||||
uploadHeaders() {
|
||||
return getUploadHeaders();
|
||||
},
|
||||
acceptText() {
|
||||
return this.attachmentFileTypes.map(item => `.${item}`).join(',');
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
attachmentName,
|
||||
isRowLocked(row) {
|
||||
return this.lockApproved && isAttachmentApproved(row);
|
||||
},
|
||||
update(rows) {
|
||||
this.$emit('update:rows', rows);
|
||||
},
|
||||
updateRowFileType(row, value) {
|
||||
if (this.isRowLocked(row)) return;
|
||||
row.fileType = value;
|
||||
this.update([...this.rows]);
|
||||
},
|
||||
updateRowDescription(row, value) {
|
||||
if (this.isRowLocked(row)) return;
|
||||
row.description = value;
|
||||
this.update([...this.rows]);
|
||||
},
|
||||
openUploadDialog() {
|
||||
this.uploadDialogType = CONTRACT_ATTACHMENT_TYPE_OTHER;
|
||||
this.uploadDialogFiles = [];
|
||||
this.uploadDialogFileList = [];
|
||||
this.uploadDialogVisible = true;
|
||||
},
|
||||
resetUploadDialog() {
|
||||
this.uploadDialogFiles = [];
|
||||
this.uploadDialogFileList = [];
|
||||
this.uploadDialogType = CONTRACT_ATTACHMENT_TYPE_OTHER;
|
||||
},
|
||||
beforeUpload(file) {
|
||||
const extension = String(file.name || '')
|
||||
.split('.')
|
||||
.pop()
|
||||
?.toLowerCase();
|
||||
if (!this.attachmentFileTypes.includes(extension)) {
|
||||
this.$message.warning('文件类型不符合上传要求');
|
||||
return false;
|
||||
}
|
||||
if (file.size / 1024 / 1024 > 50) {
|
||||
this.$message.warning('单文件大小不能超过 50MB');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
normalizeUploadFile(file, response) {
|
||||
const data = response?.data || file.response?.data || {};
|
||||
const url = data.link || data.url || data.domain || file.url || '';
|
||||
const originalName =
|
||||
data.originalName || file.name || data.name || attachmentName({ url }) || '附件';
|
||||
return {
|
||||
uid: file.uid,
|
||||
originalName,
|
||||
name: originalName,
|
||||
url,
|
||||
link: data.link || url,
|
||||
size: data.size || data.attachSize || file.size || '',
|
||||
};
|
||||
},
|
||||
handleDialogSuccess(response, file, fileList) {
|
||||
if (!response || response.success === false || (response.code && response.code !== 200)) {
|
||||
this.$message.error(response?.msg || '上传失败');
|
||||
this.uploadDialogFileList = (fileList || []).filter(item => item.uid !== file.uid);
|
||||
return;
|
||||
}
|
||||
const normalized = this.normalizeUploadFile(file, response);
|
||||
this.uploadDialogFileList = fileList || [];
|
||||
this.uploadDialogFiles = [
|
||||
...this.uploadDialogFiles.filter(item => String(item.uid) !== String(file.uid)),
|
||||
normalized,
|
||||
];
|
||||
this.uploadDialogType = resolveContractAttachmentType({
|
||||
...normalized,
|
||||
fileType: '',
|
||||
});
|
||||
this.$message.success('上传成功');
|
||||
},
|
||||
handleDialogError() {
|
||||
this.$message.error('上传失败');
|
||||
},
|
||||
handleDialogRemove(file) {
|
||||
this.uploadDialogFiles = this.uploadDialogFiles.filter(
|
||||
item => String(item.uid) !== String(file.uid)
|
||||
);
|
||||
this.uploadDialogFileList = this.uploadDialogFileList.filter(
|
||||
item => String(item.uid) !== String(file.uid)
|
||||
);
|
||||
},
|
||||
confirmUploadDialog() {
|
||||
if (!this.uploadDialogFiles.length) {
|
||||
this.$message.warning('请先上传附件');
|
||||
return;
|
||||
}
|
||||
if (this.attachmentType && !this.uploadDialogType) {
|
||||
this.$message.warning('请选择附件类型');
|
||||
return;
|
||||
}
|
||||
const uploadUserName = this.$store.getters.userInfo?.realName || '';
|
||||
const uploadTime = this.$dayjs().format('YYYY-MM-DD HH:mm:ss');
|
||||
const appended = this.uploadDialogFiles.map(row => ({
|
||||
...row,
|
||||
fileType: this.attachmentType ? this.uploadDialogType : row.fileType,
|
||||
description: row.description || '',
|
||||
uploadUserName: row.uploadUserName || uploadUserName,
|
||||
uploadTime: row.uploadTime || uploadTime,
|
||||
...(this.markApprovedOnUpload ? { approved: true } : {}),
|
||||
}));
|
||||
this.update([...(this.rows || []), ...appended]);
|
||||
this.uploadDialogVisible = false;
|
||||
},
|
||||
handleChange(rows) {
|
||||
const uploadUserName = this.$store.getters.userInfo?.realName || '';
|
||||
const uploadTime = this.$dayjs().format('YYYY-MM-DD HH:mm:ss');
|
||||
const existingRows = this.rows || [];
|
||||
this.update(
|
||||
(rows || []).map(row => {
|
||||
const fileUrl = attachmentUrl(row);
|
||||
const existing = existingRows.find(item => {
|
||||
const sameUid = row.uid && item.uid && String(row.uid) === String(item.uid);
|
||||
const sameUrl = fileUrl && attachmentUrl(item) === fileUrl;
|
||||
return sameUid || sameUrl;
|
||||
});
|
||||
if (existing && this.isRowLocked(existing)) return { ...existing };
|
||||
const next = {
|
||||
...existing,
|
||||
...row,
|
||||
description: row.description || existing?.description || '',
|
||||
uploadUserName: existing?.uploadUserName || row.uploadUserName || uploadUserName,
|
||||
uploadTime: existing?.uploadTime || row.uploadTime || uploadTime,
|
||||
approved: existing?.approved || row.approved || false,
|
||||
};
|
||||
if (this.attachmentType) {
|
||||
next.fileType = resolveContractAttachmentType({
|
||||
...next,
|
||||
fileType: existing?.fileType || row.fileType,
|
||||
});
|
||||
}
|
||||
if (this.markApprovedOnUpload && !existing) next.approved = true;
|
||||
return next;
|
||||
})
|
||||
);
|
||||
},
|
||||
remove(index) {
|
||||
const row = this.rows[index];
|
||||
if (this.isRowLocked(row)) {
|
||||
this.$message.warning('已审核通过的附件不允许删除');
|
||||
return;
|
||||
}
|
||||
const rows = [...this.rows];
|
||||
rows.splice(index, 1);
|
||||
this.update(rows);
|
||||
},
|
||||
download(row) {
|
||||
const url = attachmentUrl(row);
|
||||
if (!url) {
|
||||
this.$message.warning('附件地址为空,无法下载');
|
||||
return;
|
||||
}
|
||||
downloadFileByUrl(url, attachmentName(row));
|
||||
},
|
||||
batchDownload() {
|
||||
(this.selected.length ? this.selected : this.rows).forEach(this.download);
|
||||
},
|
||||
formatSize(size) {
|
||||
const value = Number(size);
|
||||
if (!value) return '';
|
||||
if (value < 1024) return `${value}B`;
|
||||
if (value < 1024 * 1024) return `${(value / 1024).toFixed(1)}KB`;
|
||||
return `${(value / 1024 / 1024).toFixed(1)}MB`;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.contract-manage-form__attachment-tip {
|
||||
margin-left: 30px;
|
||||
color: #909399;
|
||||
font-size: 13px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.contract-attachment-upload-dialog {
|
||||
&__body {
|
||||
padding: 4px 8px 0;
|
||||
}
|
||||
|
||||
&__field {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
&__label {
|
||||
flex: none;
|
||||
width: 72px;
|
||||
color: #606266;
|
||||
text-align: right;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
&__uploader {
|
||||
margin-top: 8px;
|
||||
|
||||
:deep(.el-upload) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
:deep(.el-upload-dragger) {
|
||||
width: 100%;
|
||||
height: 180px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
&__footer {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -4287,7 +4287,7 @@ export default {
|
||||
if (!row) return '-';
|
||||
if (prop === 'businessStatus') return this.displayStatus(row, prop);
|
||||
if (prop === 'feeGenerationMode') {
|
||||
return row[prop] === 'manual' ? '手动生成' : '系统生成';
|
||||
return row[prop] === 'manual' ? '账单导入生成' : '系统生成';
|
||||
}
|
||||
const column = this.findColumn(this.option.column, prop);
|
||||
if (column?.formatter) return column.formatter(row, {}, row[prop]);
|
||||
|
||||
Reference in New Issue
Block a user