✨ MK公开页、预结算体验优化、地图选址与认证密码规则完善
This commit is contained in:
@@ -162,9 +162,9 @@
|
||||
v-model="row.billingUnit"
|
||||
clearable
|
||||
filterable
|
||||
:disabled="!row.billingElement"
|
||||
:disabled="!canSelectBillingUnit(row)"
|
||||
:loading="unitLoading"
|
||||
:placeholder="row.billingElement ? '请选择' : '请先选择计费要素'"
|
||||
:placeholder="billingUnitPlaceholder(row)"
|
||||
><el-option
|
||||
v-for="item in unitOptionsFor(row)"
|
||||
:key="item.id || item.value"
|
||||
@@ -381,11 +381,18 @@ import { getDictionary } from '@/api/system/dictbiz';
|
||||
import SectionCard from '@/components/section-card/main.vue';
|
||||
|
||||
const clone = value => JSON.parse(JSON.stringify(value));
|
||||
/** 计费要素与计量单位维度的对应关系 */
|
||||
/** 计费要素与计量单位维度的对应关系(这些要素可选计费单位) */
|
||||
const BILLING_ELEMENT_DIMENSION_MAP = {
|
||||
按重量: '重量',
|
||||
按体积: '体积',
|
||||
按车辆: '数量',
|
||||
按数量: '数量',
|
||||
};
|
||||
const BILLING_UNIT_SELECTABLE_ELEMENTS = Object.keys(BILLING_ELEMENT_DIMENSION_MAP);
|
||||
/** 固定计费单位(不可编辑) */
|
||||
const FIXED_BILLING_UNIT_MAP = {
|
||||
按里程: '公里',
|
||||
'按吨·公里': '吨公里',
|
||||
'固定金额(整单一口价)': '单',
|
||||
};
|
||||
const defaultRule = () => ({
|
||||
feeType: '',
|
||||
@@ -436,7 +443,6 @@ export default {
|
||||
billingElements: [
|
||||
'按重量',
|
||||
'按体积',
|
||||
'按车辆',
|
||||
'按里程',
|
||||
'按吨·公里',
|
||||
'固定金额(整单一口价)',
|
||||
@@ -445,7 +451,6 @@ export default {
|
||||
typeMap: {
|
||||
按重量: ['固定单价', '区间单价', '阶梯单价', '区间阶梯一口价'],
|
||||
按体积: ['固定单价', '区间单价', '阶梯单价', '区间阶梯一口价'],
|
||||
按车辆: ['固定单价'],
|
||||
按里程: ['固定单价', '区间单价', '阶梯单价', '区间阶梯一口价'],
|
||||
'按吨·公里': ['固定单价', '区间单价', '阶梯单价', '区间阶梯一口价'],
|
||||
'固定金额(整单一口价)': ['固定一口价'],
|
||||
@@ -560,6 +565,7 @@ export default {
|
||||
next.limitRanges = next.limitRanges.map(item => ({ ...item, minimumBillingWeight: '' }));
|
||||
this.syncLegacyLimit(next);
|
||||
next.matchCondition = { ...defaultRule().matchCondition, ...(rule.matchCondition || {}) };
|
||||
this.syncBillingUnit(next);
|
||||
return next;
|
||||
},
|
||||
normalizeRanges(row) {
|
||||
@@ -651,7 +657,26 @@ export default {
|
||||
measurementDimension(billingElement) {
|
||||
return BILLING_ELEMENT_DIMENSION_MAP[billingElement] || '';
|
||||
},
|
||||
fixedBillingUnit(billingElement) {
|
||||
return FIXED_BILLING_UNIT_MAP[String(billingElement || '').trim()] || '';
|
||||
},
|
||||
canSelectBillingUnit(row) {
|
||||
return BILLING_UNIT_SELECTABLE_ELEMENTS.includes(String(row?.billingElement || '').trim());
|
||||
},
|
||||
billingUnitPlaceholder(row) {
|
||||
if (!row?.billingElement) return '请先选择计费要素';
|
||||
if (this.fixedBillingUnit(row.billingElement)) return this.fixedBillingUnit(row.billingElement);
|
||||
if (!this.canSelectBillingUnit(row)) return '当前计费要素无需选择';
|
||||
return '请选择';
|
||||
},
|
||||
unitOptionsFor(row) {
|
||||
const fixedUnit = this.fixedBillingUnit(row?.billingElement);
|
||||
if (fixedUnit) {
|
||||
return [{ id: fixedUnit, label: fixedUnit, value: fixedUnit }];
|
||||
}
|
||||
if (!this.canSelectBillingUnit(row)) {
|
||||
return [];
|
||||
}
|
||||
const dimension = this.measurementDimension(row?.billingElement);
|
||||
if (dimension) {
|
||||
return this.measurementUnits
|
||||
@@ -663,15 +688,18 @@ export default {
|
||||
}))
|
||||
.filter(item => item.value);
|
||||
}
|
||||
return (this.unitOptions || [])
|
||||
.map(item => ({
|
||||
id: item.id || item.dictKey || item.dictValue,
|
||||
label: item.dictValue,
|
||||
value: item.dictValue,
|
||||
}))
|
||||
.filter(item => item.value);
|
||||
return [];
|
||||
},
|
||||
syncBillingUnit(row) {
|
||||
const fixedUnit = this.fixedBillingUnit(row?.billingElement);
|
||||
if (fixedUnit) {
|
||||
row.billingUnit = fixedUnit;
|
||||
return;
|
||||
}
|
||||
if (!this.canSelectBillingUnit(row)) {
|
||||
row.billingUnit = '';
|
||||
return;
|
||||
}
|
||||
const options = this.unitOptionsFor(row);
|
||||
if (!options.some(item => String(item.value) === String(row.billingUnit || ''))) {
|
||||
row.billingUnit = '';
|
||||
@@ -892,7 +920,6 @@ export default {
|
||||
['taxRate', '税率'],
|
||||
['billingElement', '计费要素'],
|
||||
['billingType', '计费类型'],
|
||||
['billingUnit', '计费单位'],
|
||||
];
|
||||
for (const [i, row] of this.draft.rules.entries()) {
|
||||
const empty = required.find(
|
||||
@@ -902,6 +929,15 @@ export default {
|
||||
this.$message.warning(`第${i + 1}行${empty[1]}不能为空`);
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
this.canSelectBillingUnit(row) &&
|
||||
(row.billingUnit === undefined ||
|
||||
row.billingUnit === null ||
|
||||
String(row.billingUnit).trim() === '')
|
||||
) {
|
||||
this.$message.warning(`第${i + 1}行计费单位不能为空`);
|
||||
return false;
|
||||
}
|
||||
const feeItem = String(row.feeItem).trim();
|
||||
if (feeItemSet.has(feeItem)) {
|
||||
this.$message.warning(`费用项“${feeItem}”不能重复`);
|
||||
|
||||
@@ -1899,11 +1899,11 @@
|
||||
label-width="auto"
|
||||
class="business-crud-page__module-form business-crud-page__module-form--three"
|
||||
>
|
||||
<el-form-item label="账单起始日期" required :error="settlementRuleErrors.billStartDate">
|
||||
<el-form-item label="账单起始日" required :error="settlementRuleErrors.billStartDate">
|
||||
<el-date-picker
|
||||
v-model="settlementRuleForm.billStartDate"
|
||||
type="date"
|
||||
placeholder="请选择账单起始日期"
|
||||
placeholder="请选择账单起始日"
|
||||
format="YYYY-MM-DD"
|
||||
value-format="YYYY-MM-DD"
|
||||
:disabled="dialogReadonly"
|
||||
@@ -7784,8 +7784,8 @@ export default {
|
||||
const rule = this.normalizeSettlementRule(source);
|
||||
this.settlementRuleErrors = {};
|
||||
if (this.isBillingFieldEmpty(rule.billStartDate)) {
|
||||
this.settlementRuleErrors = { billStartDate: '请选择账单起始日期' };
|
||||
this.$message.warning(`${label}${label ? ':' : ''}请选择账单起始日期`);
|
||||
this.settlementRuleErrors = { billStartDate: '请选择账单起始日' };
|
||||
this.$message.warning(`${label}${label ? ':' : ''}请选择账单起始日`);
|
||||
return false;
|
||||
}
|
||||
if (this.isBillingFieldEmpty(rule.settlementType)) {
|
||||
|
||||
@@ -103,8 +103,13 @@
|
||||
<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="attachmentLocation" disabled style="width: 100%">
|
||||
<el-option :label="attachmentLocation" :value="attachmentLocation" />
|
||||
<el-select v-model="uploadDialogLocation" placeholder="请选择附件位置" style="width: 100%">
|
||||
<el-option
|
||||
v-for="item in resolvedLocationOptions"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="contract-attachment-upload-dialog__field">
|
||||
@@ -273,15 +278,17 @@ export default {
|
||||
markApprovedOnUpload: Boolean,
|
||||
useUploadDialog: Boolean,
|
||||
attachmentLocation: { type: String, default: '合同文件' },
|
||||
attachmentLocationOptions: { type: Array, default: null },
|
||||
preview: { type: Function, default: null },
|
||||
},
|
||||
emits: ['update:rows'],
|
||||
emits: ['update:rows', 'upload-to-location'],
|
||||
data() {
|
||||
return {
|
||||
selected: [],
|
||||
attachmentFileTypes,
|
||||
contractAttachmentTypeOptions: [...defaultContractAttachmentTypeOptions],
|
||||
uploadDialogVisible: false,
|
||||
uploadDialogLocation: '合同文件',
|
||||
uploadDialogType: resolveOtherAttachmentType(defaultContractAttachmentTypeOptions),
|
||||
uploadDialogFiles: [],
|
||||
uploadDialogFileList: [],
|
||||
@@ -300,6 +307,11 @@ export default {
|
||||
defaultAttachmentType() {
|
||||
return resolveOtherAttachmentType(this.contractAttachmentTypeOptions);
|
||||
},
|
||||
resolvedLocationOptions() {
|
||||
const options = (this.attachmentLocationOptions || []).filter(Boolean);
|
||||
if (options.length) return options;
|
||||
return ['合同文件', '其它附件'];
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.loadAttachmentTypeOptions();
|
||||
@@ -340,6 +352,10 @@ export default {
|
||||
this.update([...this.rows]);
|
||||
},
|
||||
openUploadDialog() {
|
||||
const options = this.resolvedLocationOptions;
|
||||
this.uploadDialogLocation = options.includes(this.attachmentLocation)
|
||||
? this.attachmentLocation
|
||||
: options[0] || this.attachmentLocation;
|
||||
this.uploadDialogType = this.defaultAttachmentType;
|
||||
this.uploadDialogFiles = [];
|
||||
this.uploadDialogFileList = [];
|
||||
@@ -348,6 +364,7 @@ export default {
|
||||
resetUploadDialog() {
|
||||
this.uploadDialogFiles = [];
|
||||
this.uploadDialogFileList = [];
|
||||
this.uploadDialogLocation = this.attachmentLocation;
|
||||
this.uploadDialogType = this.defaultAttachmentType;
|
||||
},
|
||||
beforeUpload(file) {
|
||||
@@ -416,6 +433,10 @@ export default {
|
||||
this.$message.warning('请先上传附件');
|
||||
return;
|
||||
}
|
||||
if (!this.uploadDialogLocation) {
|
||||
this.$message.warning('请选择附件位置');
|
||||
return;
|
||||
}
|
||||
if (!this.uploadDialogType) {
|
||||
this.$message.warning('请选择附件类型');
|
||||
return;
|
||||
@@ -430,7 +451,14 @@ export default {
|
||||
uploadTime: row.uploadTime || uploadTime,
|
||||
...(this.markApprovedOnUpload ? { approved: true } : {}),
|
||||
}));
|
||||
this.update([...(this.rows || []), ...appended]);
|
||||
if (this.uploadDialogLocation === this.attachmentLocation) {
|
||||
this.update([...(this.rows || []), ...appended]);
|
||||
} else {
|
||||
this.$emit('upload-to-location', {
|
||||
location: this.uploadDialogLocation,
|
||||
rows: appended,
|
||||
});
|
||||
}
|
||||
this.uploadDialogVisible = false;
|
||||
},
|
||||
handleChange(rows) {
|
||||
|
||||
@@ -1927,7 +1927,8 @@
|
||||
v-if="!waybillIsCarrier(detailRow)"
|
||||
class="waybill-manage-page__waybill-detail-field"
|
||||
>
|
||||
<span>里程(km)</span><strong>{{ detailRow.mileage || '-' }}</strong>
|
||||
<span>里程(km)</span
|
||||
><strong>{{ normalizeMileageValue(detailRow.mileage) || '-' }}</strong>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="waybillIsNonRoadTransport(detailRow)">
|
||||
@@ -2315,7 +2316,7 @@
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div v-if="detailPageLocked" class="waybill-manage-page__detail-footer">
|
||||
<div v-if="detailPageLocked && !isPublicWaybillView" class="waybill-manage-page__detail-footer">
|
||||
<el-button type="primary" @click="closeDetail">关闭</el-button>
|
||||
</div>
|
||||
<template v-if="!detailPageLocked" #footer>
|
||||
@@ -3122,6 +3123,7 @@ import {
|
||||
getVoucherImages as getProcessConfigVoucherImages,
|
||||
} from '@/api/business/process-config';
|
||||
import { getPunchRecords as getWaybillPunchRecords, locateVehicle, trackVehicle } from '@/api/business/waybill-manage';
|
||||
import { getMkPublicDetail } from '@/api/mk-process';
|
||||
import { getList as getDriverList } from '@/api/transportCapacity/driver';
|
||||
import { getDictionary } from '@/api/system/dictbiz';
|
||||
import { getDictionary as getSystemDictionary } from '@/api/system/dict';
|
||||
@@ -3646,6 +3648,7 @@ export default {
|
||||
this.formPageLocked = this.isStandaloneWaybillFormPage;
|
||||
this.detailPageLocked = this.isStandaloneWaybillDetailPage;
|
||||
this.formModeLocked = this.$route.query.mode || '';
|
||||
if (this.isPublicWaybillView) return;
|
||||
if (this.config.enableAllDept && this.isAdmin) {
|
||||
this.allDept = 1;
|
||||
}
|
||||
@@ -3709,8 +3712,14 @@ export default {
|
||||
isStandaloneWaybillFormPage() {
|
||||
return this.isStandaloneWaybillPage && ['add', 'edit'].includes(this.$route.query.mode);
|
||||
},
|
||||
isPublicWaybillView() {
|
||||
return this.$route.path === '/business/waybill-manage/public-view';
|
||||
},
|
||||
isStandaloneWaybillDetailPage() {
|
||||
return this.standaloneDetailPage && this.$route.path === standaloneWaybillDetailRoute;
|
||||
return (
|
||||
(this.standaloneDetailPage && this.$route.path === standaloneWaybillDetailRoute) ||
|
||||
this.isPublicWaybillView
|
||||
);
|
||||
},
|
||||
// 容器形态读实例创建时锁定的标志,不随 $route 翻转(详见 data 中 formPageLocked 的说明)
|
||||
// 当前路由是否仍属于本实例(tab.js 按 fullPath 建实例,一个实例只对应一个 path)。
|
||||
@@ -4591,14 +4600,19 @@ export default {
|
||||
this.waybillVoucherFolder = null;
|
||||
this.waybillVoucherFolderView = false;
|
||||
this.waybillVoucherImagesLoaded = false;
|
||||
const request =
|
||||
typeof this.api.getDetail === 'function'
|
||||
const request = this.isPublicWaybillView
|
||||
? getMkPublicDetail('waybill-manage', row.id)
|
||||
: typeof this.api.getDetail === 'function'
|
||||
? this.api.getDetail(row.id)
|
||||
: Promise.resolve({ data: { data: row } });
|
||||
request
|
||||
.then(res => {
|
||||
const detail = res?.data?.data || res?.data || row;
|
||||
this.detailRow = detail;
|
||||
if (this.isPublicWaybillView) {
|
||||
this.applyFormDetail(detail);
|
||||
return;
|
||||
}
|
||||
this.loadWaybillPunchRecords();
|
||||
this.loadWaybillVoucherImages();
|
||||
if (detail.contractId) {
|
||||
@@ -8560,7 +8574,7 @@ export default {
|
||||
};
|
||||
this.mileageForm = {
|
||||
id: row.id,
|
||||
mileage: row.mileage === null || row.mileage === undefined ? '' : String(row.mileage),
|
||||
mileage: this.normalizeMileageValue(row.mileage),
|
||||
mileageRemark: row.mileageRemark || '',
|
||||
};
|
||||
this.$nextTick(() => this.$refs.mileageFormRef?.clearValidate());
|
||||
|
||||
Reference in New Issue
Block a user