修复业务模块bug
This commit is contained in:
@@ -42,6 +42,7 @@ export const config = {
|
||||
},
|
||||
excludeVoidedProjects: true,
|
||||
enableAttachmentTable: true,
|
||||
detailAttachmentDescriptionPlain: true,
|
||||
enableTransportPlanForm: true,
|
||||
enableShippingTemplateFreight: true,
|
||||
editableRoadAddress: true,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -127,7 +127,7 @@
|
||||
<el-row :gutter="16">
|
||||
<template v-if="isRoad(route)">
|
||||
<el-col v-if="route.carrierType === '承运商'" :span="6"><el-form-item label="承运商" required><el-select v-model="route.carrierName" filterable remote clearable placeholder="请选择" :remote-method="loadCarrierOptions" :loading="carrierLoading" @visible-change="visible => visible && loadCarrierOptions()"><el-option v-for="item in carrierOptions" :key="carrierOptionKey(item)" :label="carrierOptionLabel(item)" :value="carrierOptionLabel(item)" /></el-select></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="司机" :required="route.carrierType !== '承运商'"><el-select :ref="element => setDriverInput(route.segmentNo, element)" v-model="route.driverName" filterable remote clearable placeholder="请选择" :remote-method="loadDriverOptions" :loading="driverLoading" @visible-change="visible => visible && loadDriverOptions()" @change="value => handleDriverChange(route, value)"><el-option v-for="item in driverOptions" :key="driverOptionKey(item)" :label="driverOptionLabel(item)" :value="driverOptionLabel(item)" /></el-select></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="司机" :required="route.carrierType !== '承运商'"><el-autocomplete :ref="element => setDriverInput(route.segmentNo, element)" v-model="route.driverName" :debounce="300" :fetch-suggestions="fetchDriverSuggestions" clearable placeholder="请输入司机" :loading="driverLoading" @select="item => handleDriverSuggestionSelect(route, item)" /></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item :label="route.carrierType === '承运商' ? '手机号' : '司机手机号'" :required="route.carrierType !== '承运商'"><el-input v-model="route.driverPhone" placeholder="请输入" /></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="车牌号" required><el-input v-model="route.vehicleNo" placeholder="请输入" /></el-form-item></el-col>
|
||||
<el-col v-if="route.carrierType !== '承运商'" :span="6"><el-form-item label="挂车车牌号" required><el-input v-model="route.trailerVehicleNo" placeholder="请输入" /></el-form-item></el-col>
|
||||
@@ -527,7 +527,11 @@ export default {
|
||||
this.carrierLoading = true;
|
||||
try {
|
||||
this.carrierOptions = unwrapRecords(
|
||||
await getCustomerList(1, 20, { customerName: keyword, customerType: '承运商' })
|
||||
await getCustomerList(1, 20, {
|
||||
customerName: keyword,
|
||||
customerType: '承运商',
|
||||
status: 1,
|
||||
})
|
||||
);
|
||||
} finally {
|
||||
this.carrierLoading = false;
|
||||
@@ -541,6 +545,23 @@ export default {
|
||||
this.driverLoading = false;
|
||||
}
|
||||
},
|
||||
fetchDriverSuggestions(queryString, callback) {
|
||||
this.loadDriverOptions(String(queryString || '').trim())
|
||||
.then(() =>
|
||||
callback(
|
||||
this.driverOptions.map(item => ({
|
||||
...item,
|
||||
value: this.driverOptionLabel(item),
|
||||
}))
|
||||
)
|
||||
)
|
||||
.catch(() => callback([]));
|
||||
},
|
||||
handleDriverSuggestionSelect(route, item = {}) {
|
||||
route.driverName = this.driverOptionLabel(item);
|
||||
route.driverId = item.id || item.driverId || '';
|
||||
route.driverPhone = item.mobile || item.driverPhone || item.phone || route.driverPhone || '';
|
||||
},
|
||||
setDriverInput(segmentNo, element) {
|
||||
if (element) this.driverInputs[segmentNo] = element;
|
||||
else delete this.driverInputs[segmentNo];
|
||||
|
||||
@@ -137,21 +137,22 @@
|
||||
label="货物名称"
|
||||
min-width="130"
|
||||
><template #default="{ row }"
|
||||
><el-select
|
||||
><el-autocomplete
|
||||
v-model="row.cargoName"
|
||||
filterable
|
||||
allow-create
|
||||
default-first-option
|
||||
clearable
|
||||
placeholder="请选择或输入"
|
||||
placeholder="请输入货物名称"
|
||||
:debounce="300"
|
||||
:fetch-suggestions="
|
||||
(queryString, callback) => fetchCargoSuggestions(queryString, callback, row.cargoTypePath)
|
||||
"
|
||||
:loading="isCargoOptionsLoading(row.cargoTypePath)"
|
||||
@visible-change="visible => visible && loadCargoOptionsByType(row.cargoTypePath)"
|
||||
@change="selectCargoName(row, $event)"
|
||||
><el-option
|
||||
v-for="cargo in getCargoOptionsByType(row.cargoTypePath)"
|
||||
:key="cargo.id"
|
||||
:label="cargo.cargoName"
|
||||
:value="cargo.cargoName" /></el-select
|
||||
@select="cargo => selectCargoSuggestion(row, cargo)"
|
||||
><template #default="{ item }">
|
||||
<div class="master-editor__cargo-autocomplete-item">
|
||||
<span>{{ item.cargoName || item.name || '' }}</span>
|
||||
<small v-if="item.cargoCode">{{ item.cargoCode }}</small>
|
||||
</div>
|
||||
</template></el-autocomplete
|
||||
></template></el-table-column
|
||||
><el-table-column label="货物类型" min-width="130"
|
||||
><template #default="{ row }"
|
||||
@@ -1062,6 +1063,45 @@ export default {
|
||||
this.cargoOptionsLoadingMap = { ...this.cargoOptionsLoadingMap, [key]: false };
|
||||
}
|
||||
},
|
||||
async fetchCargoSuggestions(queryString, callback, path = []) {
|
||||
const keyword = String(queryString || '').trim();
|
||||
const cargoType = this.getCargoTypeByPath(path);
|
||||
const key = this.getCargoOptionsKey(path);
|
||||
if (!keyword && !cargoType) {
|
||||
callback([]);
|
||||
return;
|
||||
}
|
||||
if (key) this.cargoOptionsLoadingMap = { ...this.cargoOptionsLoadingMap, [key]: true };
|
||||
try {
|
||||
const response = await getCommonCargoList(1, 50, {
|
||||
allDept: 0,
|
||||
...(cargoType
|
||||
? {
|
||||
secondCargoTypeName: cargoType.label,
|
||||
secondCargoTypeCode: cargoType.cargoCode || cargoType.code || '',
|
||||
}
|
||||
: {}),
|
||||
...(keyword ? { cargoName: keyword } : {}),
|
||||
});
|
||||
const options = this.responseRecords(response);
|
||||
if (key) this.cargoOptionsMap = { ...this.cargoOptionsMap, [key]: options };
|
||||
callback(
|
||||
options.map(item => ({
|
||||
...item,
|
||||
value: item.cargoName || item.name || '',
|
||||
}))
|
||||
);
|
||||
} catch (error) {
|
||||
window.console.log(error);
|
||||
callback([]);
|
||||
} finally {
|
||||
if (key) this.cargoOptionsLoadingMap = { ...this.cargoOptionsLoadingMap, [key]: false };
|
||||
}
|
||||
},
|
||||
selectCargoSuggestion(goods, cargo = {}) {
|
||||
goods.cargoName = cargo.cargoName || cargo.name || '';
|
||||
Object.assign(goods, this.normalizeCargoRow(cargo, goods.cargoTypePath));
|
||||
},
|
||||
selectCargoName(goods, cargoName) {
|
||||
if (!cargoName) return;
|
||||
const cargo = this.getCargoOptionsByType(goods.cargoTypePath).find(
|
||||
|
||||
@@ -825,27 +825,15 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="司机" :required="['自运', '网货平台'].includes(dialogForm.carrierType)">
|
||||
<el-select
|
||||
<el-autocomplete
|
||||
v-model="dialogForm.driverName"
|
||||
clearable
|
||||
filterable
|
||||
allow-create
|
||||
default-first-option
|
||||
remote
|
||||
reserve-keyword
|
||||
:remote-method="loadDriverOptions"
|
||||
:debounce="300"
|
||||
:fetch-suggestions="fetchDriverSuggestions"
|
||||
:loading="driverLoading"
|
||||
placeholder="请输入"
|
||||
@change="handleDriverChange"
|
||||
@visible-change="visible => visible && loadDriverOptions(dialogForm.driverName)"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in driverOptions"
|
||||
:key="item.id || item.driverName || item.name"
|
||||
:label="item.driverName || item.name"
|
||||
:value="item.driverName || item.name"
|
||||
/>
|
||||
</el-select>
|
||||
@select="item => handleDriverSuggestionSelect('dialog', item)"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="手机号" :required="['自运', '网货平台'].includes(dialogForm.carrierType)">
|
||||
<el-input v-model="dialogForm.driverPhone" clearable placeholder="请输入" />
|
||||
@@ -2079,6 +2067,26 @@ export default {
|
||||
this.dialogForm.driverPhone = driver.mobile || driver.driverPhone || driver.phone || '';
|
||||
}
|
||||
},
|
||||
fetchDriverSuggestions(queryString, callback) {
|
||||
this.loadDriverOptions(String(queryString || '').trim())
|
||||
.then(() =>
|
||||
callback(
|
||||
this.driverOptions.map(item => ({
|
||||
...item,
|
||||
value: item.driverName || item.name || '',
|
||||
}))
|
||||
)
|
||||
)
|
||||
.catch(() => callback([]));
|
||||
},
|
||||
handleDriverSuggestionSelect(target, item = {}) {
|
||||
const value = item.driverName || item.name || '';
|
||||
if (target === 'dialog') {
|
||||
this.dialogForm.driverName = value;
|
||||
const phone = item.mobile || item.driverPhone || item.phone || '';
|
||||
if (phone) this.dialogForm.driverPhone = phone;
|
||||
}
|
||||
},
|
||||
handleMileageInput(value) {
|
||||
this.dialogForm.mileage = String(value || '').replace(/[^\d.]/g, '');
|
||||
},
|
||||
@@ -2137,7 +2145,11 @@ export default {
|
||||
this.carrierLoading = true;
|
||||
try {
|
||||
this.carrierOptions = unwrapRecords(
|
||||
await getCustomerList(1, 20, { customerName: keyword })
|
||||
await getCustomerList(1, 20, {
|
||||
customerName: keyword,
|
||||
customerType: '承运商',
|
||||
status: 1,
|
||||
})
|
||||
);
|
||||
} finally {
|
||||
this.carrierLoading = false;
|
||||
|
||||
@@ -730,6 +730,33 @@ export default {
|
||||
this.form.projectIds = project ? String(project.id) : '';
|
||||
this.form.projectNames = project ? project.projectName : '';
|
||||
},
|
||||
checkEnabledProjectConfig(projectId, excludeId = '') {
|
||||
if (!projectId) return Promise.resolve(false);
|
||||
return api
|
||||
.getList(1, 100, {
|
||||
projectIds: String(projectId),
|
||||
status: 1,
|
||||
})
|
||||
.then(res => {
|
||||
const data = res?.data?.data || {};
|
||||
const records = Array.isArray(data) ? data : data.records || [];
|
||||
return records.some(item => {
|
||||
const projectIds = String(item.projectIds || '')
|
||||
.split(/[,,]/)
|
||||
.map(value => value.trim())
|
||||
.filter(Boolean);
|
||||
return (
|
||||
String(item.id || '') !== String(excludeId || '') &&
|
||||
Number(item.status) === 1 &&
|
||||
projectIds.includes(String(projectId))
|
||||
);
|
||||
});
|
||||
});
|
||||
},
|
||||
checkEnabledProjectBeforeSubmit(row) {
|
||||
if (row.id || !row.projectIds) return Promise.resolve(false);
|
||||
return this.checkEnabledProjectConfig(row.projectIds);
|
||||
},
|
||||
handleFinishDaysInput(value) {
|
||||
this.form.defaultFinishDays = String(value || '')
|
||||
.replace(/\D/g, '')
|
||||
@@ -895,7 +922,14 @@ export default {
|
||||
this.stopSubmitLoading(loading);
|
||||
return;
|
||||
}
|
||||
this.confirmDuplicateVoucher()
|
||||
this.checkEnabledProjectBeforeSubmit(submitRow)
|
||||
.then(exists => {
|
||||
if (exists) {
|
||||
this.$message.warning('该项目已有启用状态的过程配置,不能重复添加');
|
||||
throw { code: 'enabled-project-config' };
|
||||
}
|
||||
})
|
||||
.then(() => this.confirmDuplicateVoucher())
|
||||
.then(() => api.submit(submitRow))
|
||||
.then(() => {
|
||||
this.onLoad(this.page);
|
||||
@@ -903,7 +937,11 @@ export default {
|
||||
done();
|
||||
})
|
||||
.catch(error => {
|
||||
if (error !== 'cancel' && error !== 'close') {
|
||||
if (
|
||||
error !== 'cancel' &&
|
||||
error !== 'close' &&
|
||||
error?.code !== 'enabled-project-config'
|
||||
) {
|
||||
window.console.log(error);
|
||||
}
|
||||
this.stopSubmitLoading(loading);
|
||||
@@ -1089,8 +1127,28 @@ export default {
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(() => api[action](row.id))
|
||||
.then(() => {
|
||||
if (action !== 'enable') return true;
|
||||
return this.checkEnabledProjectConfig(row.projectIds, row.id)
|
||||
.then(exists => {
|
||||
if (exists) {
|
||||
this.$message.warning('该项目已有其他启用状态的过程配置,不能重复启用');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.catch(error => {
|
||||
window.console.log(error);
|
||||
this.$message.error('检查项目过程配置失败,暂不能启用');
|
||||
return false;
|
||||
});
|
||||
})
|
||||
.then(canProceed => {
|
||||
if (!canProceed) return null;
|
||||
return api[action](row.id);
|
||||
})
|
||||
.then(result => {
|
||||
if (!result) return;
|
||||
this.$message.success(`${actionName}成功`);
|
||||
this.onLoad(this.page, this.query);
|
||||
});
|
||||
|
||||
@@ -819,7 +819,12 @@ const loadProgress = async () => {
|
||||
businessType: 'voucher',
|
||||
});
|
||||
const data = res.data?.data || {};
|
||||
progressRows.value = data.records || [];
|
||||
progressRows.value = (data.records || []).slice().sort((left, right) => {
|
||||
const leftTime = left.createTime ? new Date(left.createTime).getTime() : 0;
|
||||
const rightTime = right.createTime ? new Date(right.createTime).getTime() : 0;
|
||||
if (rightTime !== leftTime) return rightTime - leftTime;
|
||||
return String(right.id || '').localeCompare(String(left.id || ''));
|
||||
});
|
||||
progressPage.total = data.total || 0;
|
||||
};
|
||||
const searchProgress = () => {
|
||||
|
||||
@@ -664,22 +664,19 @@
|
||||
:index="changeRecordIndex"
|
||||
/>
|
||||
<el-table-column label="变更日期" prop="changeTime" min-width="170" sortable />
|
||||
<el-table-column label="变更字段" prop="changedFields" min-width="180" />
|
||||
<el-table-column
|
||||
label="原数据"
|
||||
prop="beforeData"
|
||||
min-width="240"
|
||||
show-overflow-tooltip
|
||||
:formatter="formatChangeData"
|
||||
/>
|
||||
<el-table-column
|
||||
label="修改后数据"
|
||||
prop="afterData"
|
||||
min-width="240"
|
||||
show-overflow-tooltip
|
||||
:formatter="formatChangeData"
|
||||
/>
|
||||
<el-table-column label="变更内容" prop="changeContent" min-width="180" />
|
||||
label="变更内容"
|
||||
min-width="560"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-tooltip placement="top" :show-after="200">
|
||||
<template #content>
|
||||
<div class="change-record-content-tooltip">{{ formatChangeContent(row) }}</div>
|
||||
</template>
|
||||
<span class="change-record-content-cell">{{ formatChangeContent(row) }}</span>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="变更账号" prop="changeUserName" min-width="160" />
|
||||
</el-table>
|
||||
<empty-pagination
|
||||
@@ -1882,17 +1879,98 @@ export default {
|
||||
changeRecordIndex(index) {
|
||||
return (this.changeRecordPage.currentPage - 1) * this.changeRecordPage.pageSize + index + 1;
|
||||
},
|
||||
formatChangeData(row, column, value) {
|
||||
if (!value || value === '-1') return '';
|
||||
parseChangeData(value) {
|
||||
if (!value || value === '-1') return {};
|
||||
if (typeof value === 'object') return this.replaceNegativeOneWithBlank(value);
|
||||
const text = String(value).trim();
|
||||
if (!text || text === '-1') return {};
|
||||
try {
|
||||
const data = this.replaceNegativeOneWithBlank(JSON.parse(value));
|
||||
return Object.entries(data)
|
||||
.map(([field, fieldValue]) => `${field}:${fieldValue ?? ''}`)
|
||||
.join(';');
|
||||
const parsed = JSON.parse(text);
|
||||
return parsed && typeof parsed === 'object'
|
||||
? this.replaceNegativeOneWithBlank(parsed)
|
||||
: { 变更内容: parsed };
|
||||
} catch (error) {
|
||||
return value;
|
||||
return text.split(/[;;]/).reduce((data, item) => {
|
||||
const match = item.trim().match(/^([^::]+)\s*[::]\s*(.*)$/);
|
||||
if (match) data[match[1].trim()] = match[2].trim();
|
||||
return data;
|
||||
}, {});
|
||||
}
|
||||
},
|
||||
getChangeFieldLabel(field) {
|
||||
const fieldLabelMap = {
|
||||
accessType: '准入标准',
|
||||
approvalStatus: '审核状态',
|
||||
currentNode: '当前节点',
|
||||
currentProcessor: '当前处理人',
|
||||
customerCode: '客商编号',
|
||||
shortName: '客商简称',
|
||||
fullName: '客商名称',
|
||||
customerType: '客户类型',
|
||||
customerNature: '客户性质',
|
||||
unifiedCreditCode: '统一信用代码',
|
||||
deptName: '所属组织',
|
||||
approvedTime: '审核通过时间',
|
||||
status: '状态',
|
||||
businessTermType: '营业期限类型',
|
||||
registeredRegionName: '注册地址',
|
||||
registeredDetailAddress: '详细地址',
|
||||
invoiceType: '发票类型',
|
||||
};
|
||||
if (fieldLabelMap[field]) return fieldLabelMap[field];
|
||||
const column = (this.option.column || []).find(item => item.prop === field);
|
||||
return column?.label || field;
|
||||
},
|
||||
formatChangeFieldValue(field, value) {
|
||||
if (value === undefined || value === null || value === '' || value === '-1') return '空';
|
||||
const normalizedField = {
|
||||
准入类型: 'accessType',
|
||||
准入标准: 'accessType',
|
||||
审批状态: 'approvalStatus',
|
||||
审核状态: 'approvalStatus',
|
||||
状态: 'status',
|
||||
客户类型: 'customerType',
|
||||
}[field] || field;
|
||||
const valueMap = {
|
||||
accessType: { temporary: '临时', formal: '正式' },
|
||||
approvalStatus: {
|
||||
draft: '草稿',
|
||||
reviewing: '审核中',
|
||||
approved: '审核通过',
|
||||
rejected: '审核不通过',
|
||||
},
|
||||
status: { 1: '启用', 2: '停用', 0: '停用' },
|
||||
};
|
||||
if (Array.isArray(value)) {
|
||||
return value.map(item => this.formatChangeFieldValue(normalizedField, item)).join('、');
|
||||
}
|
||||
if (valueMap[normalizedField]?.[value] !== undefined) {
|
||||
return valueMap[normalizedField][value];
|
||||
}
|
||||
if (normalizedField === 'customerType') {
|
||||
return String(value)
|
||||
.split(/[,,]/)
|
||||
.map(item => ({ customer: '客户', carrier: '承运商' }[item.trim()] || item.trim()))
|
||||
.filter(Boolean)
|
||||
.join('、');
|
||||
}
|
||||
if (typeof value === 'object') return JSON.stringify(value);
|
||||
return String(value);
|
||||
},
|
||||
formatChangeContent(row) {
|
||||
const beforeData = this.parseChangeData(row.beforeData);
|
||||
const afterData = this.parseChangeData(row.afterData);
|
||||
const fields = [...new Set([...Object.keys(beforeData), ...Object.keys(afterData)])];
|
||||
const details = fields
|
||||
.filter(field => field !== '变更内容')
|
||||
.map(field => {
|
||||
const before = this.formatChangeFieldValue(field, beforeData[field]);
|
||||
const after = this.formatChangeFieldValue(field, afterData[field]);
|
||||
return `${this.getChangeFieldLabel(field)}:变更前:${before} → 变更后:${after}`;
|
||||
});
|
||||
const content = String(row.changeContent || '').trim();
|
||||
return [content, ...details].filter(Boolean).join(';');
|
||||
},
|
||||
emptyContact() {
|
||||
return {
|
||||
contactName: '',
|
||||
@@ -4108,6 +4186,21 @@ export default {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.change-record-content-cell {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.change-record-content-tooltip {
|
||||
max-width: 900px;
|
||||
max-height: 320px;
|
||||
overflow: auto;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
:deep(.archive-dialog .el-dialog__body) {
|
||||
max-height: 72vh;
|
||||
overflow: auto;
|
||||
|
||||
Reference in New Issue
Block a user