✨ 结算汇率反算、开票合计填报、配载承运商交集与车辆组织悬停
外币结算按本位币/汇率反算;开票改填合计金额并反算不含税单价;配载展示承运商合同并按乙方交集限选;评分加减分封顶15分;车辆所有组织/使用部门悬停显示完整路径。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -59,7 +59,22 @@
|
||||
</el-button>
|
||||
</template>
|
||||
<template #organizationName="{ row }">
|
||||
{{ String(row.organizationName || '').replace(/^[\s\u3000]+/, '') }}
|
||||
<el-tooltip
|
||||
:content="formatOrgDisplayName(row.organizationName)"
|
||||
placement="top"
|
||||
:disabled="!formatOrgDisplayName(row.organizationName)"
|
||||
>
|
||||
<span class="org-cell-text">{{ formatOrgDisplayName(row.organizationName) }}</span>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
<template #useDepartment="{ row }">
|
||||
<el-tooltip
|
||||
:content="formatOrgDisplayName(row.useDepartment)"
|
||||
placement="top"
|
||||
:disabled="!formatOrgDisplayName(row.useDepartment)"
|
||||
>
|
||||
<span class="org-cell-text">{{ formatOrgDisplayName(row.useDepartment) }}</span>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
<template #status="{ row }">
|
||||
<el-tag :type="row.status === 1 ? 'primary' : 'info'" class="status-text">
|
||||
@@ -315,26 +330,58 @@
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="所有组织" prop="organizationName">
|
||||
<el-cascader
|
||||
v-model="organizationCascaderValue"
|
||||
:options="organizationTreeOptions"
|
||||
:props="organizationCascaderProps"
|
||||
filterable
|
||||
clearable
|
||||
placeholder="请选择"
|
||||
/>
|
||||
<el-tooltip
|
||||
:content="
|
||||
formatOrgCascaderPath(organizationCascaderPath) ||
|
||||
formatOrgDisplayName(vehicleForm.organizationName)
|
||||
"
|
||||
placement="top"
|
||||
:disabled="
|
||||
!(
|
||||
formatOrgCascaderPath(organizationCascaderPath) ||
|
||||
formatOrgDisplayName(vehicleForm.organizationName)
|
||||
)
|
||||
"
|
||||
>
|
||||
<div class="org-cascader-tooltip">
|
||||
<el-cascader
|
||||
v-model="organizationCascaderValue"
|
||||
:options="organizationFormTreeOptions"
|
||||
:props="formOrgCascaderProps"
|
||||
filterable
|
||||
clearable
|
||||
placeholder="请选择"
|
||||
/>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="使用部门" prop="useDepartment">
|
||||
<el-cascader
|
||||
v-model="useDepartmentCascaderValue"
|
||||
:options="organizationTreeOptions"
|
||||
:props="organizationCascaderProps"
|
||||
filterable
|
||||
clearable
|
||||
placeholder="请选择"
|
||||
/>
|
||||
<el-tooltip
|
||||
:content="
|
||||
formatOrgCascaderPath(useDepartmentCascaderPath) ||
|
||||
formatOrgDisplayName(vehicleForm.useDepartment)
|
||||
"
|
||||
placement="top"
|
||||
:disabled="
|
||||
!(
|
||||
formatOrgCascaderPath(useDepartmentCascaderPath) ||
|
||||
formatOrgDisplayName(vehicleForm.useDepartment)
|
||||
)
|
||||
"
|
||||
>
|
||||
<div class="org-cascader-tooltip">
|
||||
<el-cascader
|
||||
v-model="useDepartmentCascaderValue"
|
||||
:options="useDepartmentFormTreeOptions"
|
||||
:props="formOrgCascaderProps"
|
||||
filterable
|
||||
clearable
|
||||
placeholder="请选择"
|
||||
/>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -652,6 +699,17 @@ export default {
|
||||
vehicleCertificateUploads: {},
|
||||
uploadHeaders: getUploadHeaders(),
|
||||
organizationOptions: [],
|
||||
// 表单两个级联各自维护路径,避免名称回写互相覆盖;不要与搜索栏共用同一棵树节点
|
||||
organizationCascaderPath: [],
|
||||
useDepartmentCascaderPath: [],
|
||||
formOrgCascaderProps: {
|
||||
value: 'id',
|
||||
label: 'label',
|
||||
children: 'children',
|
||||
emitPath: true,
|
||||
checkStrictly: true,
|
||||
expandTrigger: 'hover',
|
||||
},
|
||||
vehicleTypeOptions: [
|
||||
{ label: '高栏车', value: '高栏' },
|
||||
{ label: '低栏车', value: '低栏' },
|
||||
@@ -697,22 +755,31 @@ export default {
|
||||
: [{ required: true, message: '请选择行驶证有效期', trigger: 'change' }],
|
||||
};
|
||||
},
|
||||
// 所属组织级联:表单存组织名称,级联控件用 id 路径,两者在此双向转换
|
||||
// 两个级联必须使用克隆后的独立树,否则 checkStrictly 会在节点上互相抢选中态
|
||||
organizationFormTreeOptions() {
|
||||
return this.cloneOrgTree(this.organizationTreeOptions);
|
||||
},
|
||||
useDepartmentFormTreeOptions() {
|
||||
return this.cloneOrgTree(this.organizationTreeOptions);
|
||||
},
|
||||
// 所属组织级联:本地保存 id 路径,名称同步到表单字段供后端使用
|
||||
organizationCascaderValue: {
|
||||
get() {
|
||||
return this.resolveOrgPath(this.vehicleForm.organizationName);
|
||||
return this.organizationCascaderPath;
|
||||
},
|
||||
set(path) {
|
||||
this.vehicleForm.organizationName = this.resolveOrgName(path);
|
||||
this.organizationCascaderPath = Array.isArray(path) ? [...path] : [];
|
||||
this.vehicleForm.organizationName = this.resolveOrgName(this.organizationCascaderPath);
|
||||
},
|
||||
},
|
||||
// 使用部门级联:与所属组织同一套部门树
|
||||
// 使用部门级联:独立路径状态,避免与所属组织共用计算回写导致选不中
|
||||
useDepartmentCascaderValue: {
|
||||
get() {
|
||||
return this.resolveOrgPath(this.vehicleForm.useDepartment);
|
||||
return this.useDepartmentCascaderPath;
|
||||
},
|
||||
set(path) {
|
||||
this.vehicleForm.useDepartment = this.resolveOrgName(path);
|
||||
this.useDepartmentCascaderPath = Array.isArray(path) ? [...path] : [];
|
||||
this.vehicleForm.useDepartment = this.resolveOrgName(this.useDepartmentCascaderPath);
|
||||
},
|
||||
},
|
||||
isAdmin() {
|
||||
@@ -745,10 +812,49 @@ export default {
|
||||
this.initDeptTree();
|
||||
this.loadOrganizationOptions();
|
||||
},
|
||||
watch: {
|
||||
organizationTreeOptions() {
|
||||
if (this.vehicleBox) {
|
||||
this.syncOrgCascaderPaths();
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
hasPermission(code) {
|
||||
return this.isAdmin || this.permission?.[code] === true;
|
||||
},
|
||||
/** 去掉组织名称前导空白,供列表与提示展示 */
|
||||
formatOrgDisplayName(name) {
|
||||
return String(name || '').replace(/^[\s\u3000]+/, '');
|
||||
},
|
||||
/** 级联路径还原完整组织层级文案,悬停展示用 */
|
||||
formatOrgCascaderPath(path) {
|
||||
const ids = Array.isArray(path)
|
||||
? path.filter(item => item !== undefined && item !== null && item !== '')
|
||||
: [];
|
||||
if (!ids.length) return '';
|
||||
const labels = [];
|
||||
let nodes = this.organizationTreeOptions || [];
|
||||
for (const id of ids) {
|
||||
const node = nodes.find(item => String(item.id) === String(id));
|
||||
if (!node) break;
|
||||
labels.push(node.rawLabel || node.label || '');
|
||||
nodes = node.children || [];
|
||||
}
|
||||
return labels.filter(Boolean).join(' / ');
|
||||
},
|
||||
cloneOrgTree(tree = []) {
|
||||
return (tree || []).map(item => ({
|
||||
id: String(item.id),
|
||||
label: item.label,
|
||||
rawLabel: item.rawLabel,
|
||||
children: item.children?.length ? this.cloneOrgTree(item.children) : undefined,
|
||||
}));
|
||||
},
|
||||
syncOrgCascaderPaths() {
|
||||
this.organizationCascaderPath = this.resolveOrgPath(this.vehicleForm.organizationName);
|
||||
this.useDepartmentCascaderPath = this.resolveOrgPath(this.vehicleForm.useDepartment);
|
||||
},
|
||||
initDeptTree() {
|
||||
getDeptTree(this.userInfo.tenantId).then(res => {
|
||||
this.organizationOptions = this.flattenDeptOptions(res.data.data || []);
|
||||
@@ -760,6 +866,9 @@ export default {
|
||||
if (this.vehicleBox && !this.vehicleForm.useDepartment) {
|
||||
this.vehicleForm.useDepartment = this.getCurrentOrganizationName();
|
||||
}
|
||||
if (this.vehicleBox) {
|
||||
this.syncOrgCascaderPaths();
|
||||
}
|
||||
});
|
||||
},
|
||||
flattenDeptOptions(tree = [], level = 0) {
|
||||
@@ -854,6 +963,7 @@ export default {
|
||||
this.vehicleForm = emptyForm();
|
||||
this.vehicleForm.organizationName = this.getCurrentOrganizationName();
|
||||
this.vehicleForm.useDepartment = this.getCurrentOrganizationName();
|
||||
this.syncOrgCascaderPaths();
|
||||
this.syncPlateNo(false);
|
||||
this.vehicleBox = true;
|
||||
return;
|
||||
@@ -867,6 +977,7 @@ export default {
|
||||
if (!this.vehicleForm.useDepartment) {
|
||||
this.vehicleForm.useDepartment = this.getCurrentOrganizationName();
|
||||
}
|
||||
this.syncOrgCascaderPaths();
|
||||
this.splitPlateNo();
|
||||
this.syncPlateNo(false);
|
||||
this.vehicleBox = true;
|
||||
@@ -878,6 +989,8 @@ export default {
|
||||
},
|
||||
resetVehicle() {
|
||||
this.vehicleForm = emptyForm();
|
||||
this.organizationCascaderPath = [];
|
||||
this.useDepartmentCascaderPath = [];
|
||||
this.vehicleCertificateUploads = {};
|
||||
this.readonly = false;
|
||||
this.submitLoading = false;
|
||||
@@ -1530,7 +1643,20 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
.org-cell-text {
|
||||
display: inline-block;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
.vehicle-form {
|
||||
.org-cascader-tooltip {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
:deep(.el-date-editor.el-input),
|
||||
:deep(.el-date-editor.el-input__wrapper),
|
||||
:deep(.el-select),
|
||||
|
||||
Reference in New Issue
Block a user