diff --git a/src/mixins/organization-search.js b/src/mixins/organization-search.js
index 5842986..fd06b59 100644
--- a/src/mixins/organization-search.js
+++ b/src/mixins/organization-search.js
@@ -12,6 +12,8 @@ import { h } from 'vue';
* 1. 混入本 mixin:mixins: [organizationSearch]
* 2. option 中「所属组织」列加上 searchslot: true(prop 为 organizationName 或 deptName 均可)
* 3. 在 created / 初始化时调用 this.loadOrganizationOptions()
+ * 4. 需要「未分配组织」筛选项的页面在 data 里置 enableUnassignedOrgFilter: true;
+ * 该项只追加进搜索树 organizationSearchTreeOptions,表单级联 organizationTreeOptions 不含哨兵
*
* 说明:
* - 自动识别 organizationName / deptName 两种 prop,并挂载 column.renderSearch
@@ -26,6 +28,12 @@ import { h } from 'vue';
*/
const ORG_PROPS = ['organizationName', 'deptName'];
+// 「未分配组织」筛选项的哨兵值:不是真实组织名,选中后提交给后端的就是这串字面量。
+// 后端 TransportBusiConstant.UNASSIGNED_ORG_FILTER、DriverMapper.xml / TransportVehicleMapper.xml
+// 的 organizationName 分支以及司机、车辆导出查询都按它改判为 organization_name = '';
+// 后端换成空串会让整段组织条件不生效,筛选静默失效。前端与后端这几处必须同步修改。
+const UNASSIGNED_ORG_FILTER = '__UNASSIGNED_ORG__';
+
export default {
data() {
return {
@@ -34,9 +42,18 @@ export default {
organizationTreeOptions: [],
organizationTreeFlatOptions: [],
organizationLoading: false,
+ // 组织筛选是否追加「未分配组织」一项;页面在 data 里覆盖为 true 才生效
+ enableUnassignedOrgFilter: false,
};
},
computed: {
+ // 搜索栏级联的选项:开关打开时在真实组织最前面追加「未分配组织」。
+ // 不能直接改 organizationTreeOptions——司机/车辆页的编辑表单也用这棵树选组织。
+ organizationSearchTreeOptions() {
+ return this.enableUnassignedOrgFilter
+ ? [this.unassignedOrgOption(), ...this.organizationTreeOptions]
+ : this.organizationTreeOptions;
+ },
// 所属组织级联配置:checkStrictly 允许选中任意层级,不必选到末级
organizationCascaderProps() {
return {
@@ -61,7 +78,7 @@ export default {
? this.excludeExternalOrganization(source)
: source;
this.organizationTreeOptions = this.normalizeOrgTree(tree);
- this.organizationTreeFlatOptions = this.flattenOrgTree(this.organizationTreeOptions);
+ this.organizationTreeFlatOptions = this.flattenOrgTree(this.organizationSearchTreeOptions);
const option = this.tableOption || this.option;
if (!option) return;
ORG_PROPS.forEach(prop => {
@@ -100,12 +117,20 @@ export default {
};
});
},
+ // 哨兵节点的 id 与 rawLabel 都取哨兵值,resolveOrgName 取到的仍是哨兵而不是某个真实组织名
+ unassignedOrgOption() {
+ return { id: UNASSIGNED_ORG_FILTER, label: '未分配组织', rawLabel: UNASSIGNED_ORG_FILTER };
+ },
flattenOrgTree(tree = []) {
return (tree || []).flatMap(item => [
{ id: String(item.id), label: item.label, rawLabel: item.rawLabel },
...this.flattenOrgTree(item.children || []),
]);
},
+ // 组织列渲染用:空串或纯空白即「未分配组织」(组织列 NOT NULL,无组织存空串)
+ isBlankOrganizationName(value) {
+ return String(value ?? '').trim() === '';
+ },
// 兼容两种入参:级联路径数组(取末级)或单个部门 id
findOrgById(id) {
const value = Array.isArray(id) ? id.at(-1) : id;
@@ -155,7 +180,7 @@ export default {
// 级联单选:modelValue 必须是 id 路径数组,否则控件内部状态会错乱导致无法再次选中
if (scope.row) scope.row[prop] = Array.isArray(value) ? value : [];
},
- options: this.organizationTreeOptions,
+ options: this.organizationSearchTreeOptions,
props: {
label: 'label',
value: 'id',
diff --git a/src/option/system/mpUser.js b/src/option/system/mpUser.js
index bc06d41..7236a26 100644
--- a/src/option/system/mpUser.js
+++ b/src/option/system/mpUser.js
@@ -133,7 +133,7 @@ export default {
hide: true,
span: 24,
order: 55,
- rules: [{ required: true, message: '请选择所属组织', trigger: 'change' }],
+ // 所属组织可为空:为空表示未分配组织,账号的数据权限为空集
},
{
label: '所属组织',
diff --git a/src/views/system/mp-user.vue b/src/views/system/mp-user.vue
index 072f3d8..bd3505f 100644
--- a/src/views/system/mp-user.vue
+++ b/src/views/system/mp-user.vue
@@ -315,11 +315,6 @@ export default {
},
rowSave(row, done, loading) {
const payload = this.normalizeSubmitRow(row, false);
- if (!payload.deptId) {
- this.$message.warning('请选择所属组织');
- loading();
- return;
- }
if (payload.dataScopeRange === 3 && (!payload.dataScopeDeptIds || !payload.dataScopeDeptIds.length)) {
this.$message.warning('请选择自定义数据权限组织');
loading();
@@ -336,11 +331,6 @@ export default {
},
rowUpdate(row, index, done, loading) {
const payload = this.normalizeSubmitRow(row, true);
- if (!payload.deptId) {
- this.$message.warning('请选择所属组织');
- loading();
- return;
- }
if (payload.dataScopeRange === 3 && (!payload.dataScopeDeptIds || !payload.dataScopeDeptIds.length)) {
this.$message.warning('请选择自定义数据权限组织');
loading();
diff --git a/src/views/transportCapacity/driver.vue b/src/views/transportCapacity/driver.vue
index c4e771b..dbf7be1 100644
--- a/src/views/transportCapacity/driver.vue
+++ b/src/views/transportCapacity/driver.vue
@@ -60,7 +60,11 @@
{{ row.idCardNo || '-' }}
- {{ String(row.organizationName || '').replace(/^[\s\u3000]+/, '') }}
+ 未分配组织
+ {{ String(row.organizationName || '').replace(/^[\s\u3000]+/, '') }}
@@ -596,7 +600,11 @@
{{ row.plateNo || '-' }}
- {{ String(row.organizationName || '').replace(/^[\s\u3000]+/, '') }}
+ 未分配组织
+ {{ String(row.organizationName || '').replace(/^[\s\u3000]+/, '') }}
{{ row.boundDriver || '-' }}
@@ -747,6 +755,8 @@ export default {
expired: 0,
},
driverBox: false,
+ // 搜索栏组织级联追加「未分配组织」一项(哨兵值见 organization-search mixin)
+ enableUnassignedOrgFilter: true,
vehicleSelectorVisible: false,
vehicleSelectorLoading: false,
vehicleSelectorOption,
@@ -861,7 +871,7 @@ export default {
emergencyContactMobile: [
{ required: true, message: '请输入紧急联系人手机号', trigger: 'blur' },
],
- organizationName: [{ required: true, message: '请选择所属组织', trigger: 'change' }],
+ // 后端已允许所属组织为空,这里不做必填校验
idCardFront: [{ required: true, message: '请上传身份证正面照', trigger: 'change' }],
idCardBack: [{ required: true, message: '请上传身份证反面照', trigger: 'change' }],
drivingLicenseFront: [{ required: true, message: '请上传驾驶证主页', trigger: 'change' }],
@@ -1958,6 +1968,11 @@ export default {
}
}
+// 空组织记录在列表里的占位文案
+.organization-name--empty {
+ color: #909399;
+}
+
.driver-page__date-expiring {
color: #d40000;
font-weight: 600;
diff --git a/src/views/transportCapacity/vehicle.vue b/src/views/transportCapacity/vehicle.vue
index 871d3a5..aba1fb1 100644
--- a/src/views/transportCapacity/vehicle.vue
+++ b/src/views/transportCapacity/vehicle.vue
@@ -59,7 +59,11 @@
- {{ String(row.organizationName || '').replace(/^[\s\u3000]+/, '') }}
+ 未分配组织
+ {{ String(row.organizationName || '').replace(/^[\s\u3000]+/, '') }}
@@ -652,6 +656,8 @@ export default {
vehicleCertificateUploads: {},
uploadHeaders: getUploadHeaders(),
organizationOptions: [],
+ // 搜索栏组织级联追加「未分配组织」一项(哨兵值见 organization-search mixin)
+ enableUnassignedOrgFilter: true,
vehicleTypeOptions: [
{ label: '高栏车', value: '高栏' },
{ label: '低栏车', value: '低栏' },
@@ -663,7 +669,7 @@ export default {
businessRelationOptions: ['自有', '管理挂靠', '业务合作'],
energyTypeOptions: ['柴油', '汽油', '新能源', '天然气'],
baseRules: {
- organizationName: [{ required: true, message: '请选择所属组织', trigger: 'change' }],
+ // 所属组织可为空:为空表示未分配组织,数据权限为空集
useDepartment: [{ required: true, message: '请选择使用部门', trigger: 'change' }],
plateNo: [
{ required: true, message: '请输入车牌号', trigger: 'change' },
@@ -1497,6 +1503,11 @@ export default {
}
}
+// 空组织记录在列表里的占位文案
+.organization-name--empty {
+ color: #909399;
+}
+
// 编辑弹窗:灰底 + section-card 白卡分组
.vehicle-form {
:deep(.el-form-item__label) {