feat(organization): 全站所属组织搜索统一为树形下拉并修复项目部门宽度

- 新增复用 mixin organization-search.js,封装树形组织搜索功能,自动识别不同架构
- 替换合同管理、运输能力(司机/车辆/船舶)、费用模块的所属组织搜索使用树形下拉组件
- 将自定义搜索表单中所属组织 input 替换为 el-tree-select,支持树节点选中并写回名称
- 防止不同页面间组织数据相互覆盖,mixin 内部树数据命名为 organizationTreeOptions
- 修复项目补录页面业务部门错用全宽样式,恢复半宽显示,调整注释避免误读
- 各相关页面组件中引入并使用 mixin,调用接口加载组织树数据,保障搜索功能一致性
This commit is contained in:
2026-08-28 16:00:53 +08:00
parent d7ac4e4045
commit b6fed6892a
8 changed files with 89 additions and 7 deletions
+3 -3
View File
@@ -165,7 +165,7 @@
:disabled="isBasicInfoReadonly"
/>
</el-form-item>
<el-form-item label="业务部门" prop="businessDeptId" class="project-apply-form__item--full">
<el-form-item label="业务部门" prop="businessDeptId">
<el-tree-select
v-model="form.businessDeptId"
:data="businessDeptTreeOptions"
@@ -211,7 +211,7 @@
</el-select>
</el-form-item>
<el-form-item label="项目由来说明" prop="sourceRemark" class="project-apply-form__item--full">
<el-input v-model="form.sourceRemark" maxlength="300" :disabled="isBasicInfoReadonly" />
<el-input v-model="form.sourceRemark" type="textarea" rows="2" maxlength="300" :disabled="isBasicInfoReadonly" />
</el-form-item>
</div>
@@ -2190,7 +2190,7 @@ export default {
white-space: normal;
}
// 占满整行的表单项(业务部门 / 项目由来说明
// 占满整行的表单项(如项目由来说明等多行文本字段
:deep(.project-apply-form__item--full) {
grid-column: 1 / -1;
@@ -6,7 +6,19 @@
<el-input v-model="query.paymentNo" clearable placeholder="请输入" />
</el-form-item>
<el-form-item label="使用部门">
<el-input v-model="query.deptName" clearable placeholder="请输入" />
<el-tree-select
:model-value="query.deptName"
:data="organizationTreeOptions"
node-key="id"
check-strictly
filterable
clearable
render-after-expand
style="width: 100%"
placeholder="请选择 所属组织"
:props="{ label: 'label', value: 'id', children: 'children' }"
@update:model-value="val => { query.deptName = findOrgById(val)?.rawLabel || val }"
/>
</el-form-item>
<el-form-item label="付款日期">
<el-date-picker
@@ -47,9 +59,11 @@
<script>
import { ArrowDown, ArrowUp } from '@element-plus/icons-vue';
import { approvalStatusOptions } from '@/api/payment/billPayment';
import organizationSearch from '@/mixins/organization-search';
export default {
name: 'BillPaymentSearch',
mixins: [organizationSearch],
props: {
query: { type: Object, required: true },
loading: { type: Boolean, default: false },
@@ -58,6 +72,9 @@ export default {
data() {
return { ArrowDown, ArrowUp, expanded: false, approvalStatusOptions };
},
mounted() {
this.loadOrganizationOptions();
},
};
</script>
+16 -1
View File
@@ -10,7 +10,19 @@
<el-input v-model="query.projectName" clearable placeholder="请输入" />
</el-form-item>
<el-form-item label="所属组织">
<el-input v-model="query.deptName" clearable placeholder="请输入" />
<el-tree-select
:model-value="query.deptName"
:data="organizationTreeOptions"
node-key="id"
check-strictly
filterable
clearable
render-after-expand
style="width: 100%"
placeholder="请选择 所属组织"
:props="{ label: 'label', value: 'id', children: 'children' }"
@update:model-value="val => { query.deptName = findOrgById(val)?.rawLabel || val }"
/>
</el-form-item>
<el-form-item class="invoice-kingdee-item" label="金蝶单据状态">
<el-select v-model="query.kingdeeStatus" clearable placeholder="请选择">
@@ -234,6 +246,7 @@ import * as XLSX from 'xlsx';
import * as api from '@/api/payment/invoiceApplication';
import * as formalSettlementApi from '@/api/settlement/formalSettlement';
import { invoiceApplicationTableColumns } from '@/option/payment/invoiceApplication';
import organizationSearch from '@/mixins/organization-search';
const emptyQuery = () => ({
applicationNo: '',
@@ -245,6 +258,7 @@ const emptyQuery = () => ({
export default {
name: 'InvoiceApplication',
mixins: [organizationSearch],
data() {
return {
ArrowDown,
@@ -266,6 +280,7 @@ export default {
...mapGetters(['permission']),
},
mounted() {
this.loadOrganizationOptions();
this.loadTable();
},
methods: {
+16 -1
View File
@@ -19,7 +19,19 @@
<el-input v-model="query.projectName" clearable placeholder="请输入" />
</el-form-item>
<el-form-item label="所属组织">
<el-input v-model="query.deptName" clearable placeholder="请输入" />
<el-tree-select
:model-value="query.deptName"
:data="organizationTreeOptions"
node-key="id"
check-strictly
filterable
clearable
render-after-expand
style="width: 100%"
placeholder="请选择 所属组织"
:props="{ label: 'label', value: 'id', children: 'children' }"
@update:model-value="val => { query.deptName = findOrgById(val)?.rawLabel || val }"
/>
</el-form-item>
<el-form-item v-if="searchExpanded" label="审核状态">
<el-select v-model="query.approvalStatus" clearable placeholder="请选择">
@@ -226,6 +238,7 @@ import { mapGetters } from 'vuex';
import * as XLSX from 'xlsx';
import * as api from '@/api/payment/invoiceReceipt';
import { invoiceReceiptTableColumns } from '@/option/payment/invoiceReceipt';
import organizationSearch from '@/mixins/organization-search';
const emptyQuery = () => ({
invoiceNo: '',
@@ -238,6 +251,7 @@ const emptyQuery = () => ({
export default {
name: 'InvoiceReceipt',
mixins: [organizationSearch],
data() {
return {
ArrowDown,
@@ -259,6 +273,7 @@ export default {
...mapGetters(['permission']),
},
mounted() {
this.loadOrganizationOptions();
this.loadTable();
},
methods: {
+15 -1
View File
@@ -23,7 +23,18 @@
/></el-form-item>
<template v-if="searchExpanded">
<el-form-item label="所属组织"
><el-input v-model="query.deptName" clearable
><el-tree-select
:model-value="query.deptName"
:data="organizationTreeOptions"
node-key="id"
check-strictly
filterable
clearable
render-after-expand
style="width: 100%"
placeholder="请选择 所属组织"
:props="{ label: 'label', value: 'id', children: 'children' }"
@update:model-value="val => { query.deptName = findOrgById(val)?.rawLabel || val }"
/></el-form-item>
<el-form-item label="关联结算单"
><el-input v-model="query.settlementNo" clearable
@@ -224,6 +235,7 @@ import { ArrowDown, ArrowUp, Refresh } from '@element-plus/icons-vue';
import { mapGetters } from 'vuex';
import * as api from '@/api/payment/paymentApplication';
import { paymentApplicationTableColumns } from '@/option/payment/paymentApplication';
import organizationSearch from '@/mixins/organization-search';
const emptyQuery = () => ({
paymentNo: '',
@@ -238,6 +250,7 @@ const emptyQuery = () => ({
});
export default {
name: 'PaymentApplication',
mixins: [organizationSearch],
data() {
return {
ArrowDown,
@@ -263,6 +276,7 @@ export default {
},
},
mounted() {
this.loadOrganizationOptions();
this.loadTable();
},
methods: {
+3
View File
@@ -591,6 +591,7 @@ import {
} from '@/api/transportCapacity/driver';
import { getList as getVehicleList } from '@/api/transportCapacity/transport-vehicle';
import { getDeptTree } from '@/api/system/dept';
import organizationSearch from '@/mixins/organization-search';
import { getDictionary } from '@/api/system/dictbiz';
import { getLazyTree } from '@/api/base/region';
import { exportBlob } from '@/api/common';
@@ -661,6 +662,7 @@ export default {
components: {
ImageUploadField,
},
mixins: [organizationSearch],
data() {
return {
option,
@@ -849,6 +851,7 @@ export default {
},
created() {
this.initDeptTree();
this.loadOrganizationOptions();
this.initRegionOptions();
this.initQualificationTypeOptions();
},
+3
View File
@@ -574,6 +574,7 @@ import { ElLoading } from 'element-plus';
import { InfoFilled } from '@element-plus/icons-vue';
import { option } from '@/option/transportCapacity/transport-ship';
import { getDeptTree } from '@/api/system/dept';
import organizationSearch from '@/mixins/organization-search';
import {
getList,
getDetail,
@@ -639,6 +640,7 @@ const emptyForm = () => ({
export default {
components: { ImageUploadField, InfoFilled, ShipLedger },
mixins: [organizationSearch],
data() {
return {
option,
@@ -731,6 +733,7 @@ export default {
},
created() {
this.initDeptTree();
this.loadOrganizationOptions();
},
methods: {
hasPermission(code) {