@sy-common/organize-select-help 1.0.0-beta.65 → 1.0.0-beta.67

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sy-common/organize-select-help",
3
- "version": "1.0.0-beta.65",
3
+ "version": "1.0.0-beta.67",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "author": "lambo",
package/src/index.vue CHANGED
@@ -178,6 +178,71 @@
178
178
  </div>
179
179
  </div>
180
180
  </TabPane>
181
+ <TabPane label="组织选择" name="orgNew" v-if="name.includes('orgNew')">
182
+ <div class="tab org-new-tab">
183
+ <div class="org-new-header">
184
+ <Input v-model="orgNewSearch" @on-enter="searchOrgNew" @on-search="searchOrgNew" search placeholder="搜索组织节点名称(如:办公室)" style="width: 100%;"/>
185
+ <div class="org-new-actions">
186
+ <Button type="default" @click="expandAllOrgNew">展开全部</Button>
187
+ <Button type="default" @click="collapseAllOrgNew">折叠全部</Button>
188
+ <!-- <Button type="default" @click="clearOrgNew">清空</Button>-->
189
+ </div>
190
+ </div>
191
+ <div class="org-new-content">
192
+ <div class="org-card" v-for="(province, index) in filteredOrgNewTree" :key="province.orgUnitId">
193
+ <div class="org-card-header" @click="toggleProvinceExpand(province)">
194
+ <div class="org-card-title" @click.stop="addOrgNewItem(province)">
195
+ <img src="./assets/icon.png" alt="" style="margin-right: 8px; width: 14px; height: 14px;"/>
196
+ {{ province.title }}
197
+ </div>
198
+ <div class="org-card-actions" v-if="province.children && province.children.length > 0">
199
+ <Button type="text" @click.stop="selectAllProvinceOrgNew(province)">全选(包含下级)</Button>
200
+ <Icon :type="province.expand ? 'md-arrow-dropdown' : 'md-arrow-dropright'" style="margin-left: 8px;"/>
201
+ </div>
202
+ </div>
203
+ <div class="org-card-body" v-if="province.expand && province.children && province.children.length > 0">
204
+ <div class="city-card" v-for="city in province.children" :key="city.orgUnitId">
205
+ <div class="city-card-header" @click="toggleCityExpand(city)">
206
+ <div class="city-card-title" @click.stop="addOrgNewItem(city)">
207
+ <img src="./assets/icon.png" alt="" style="margin-right: 8px; width: 14px; height: 14px;"/>
208
+ {{ city.title }}
209
+ </div>
210
+ <div class="city-card-actions" v-if="city.children && city.children.length > 0">
211
+ <Button type="text" @click.stop="selectAllCityOrgNew(city)">全选(包含下级)</Button>
212
+ <!-- <Button type="text" @click.stop="selectAllCityLevelOrgNew(city)">全选市本级</Button>-->
213
+ <Icon :type="city.expand ? 'md-arrow-dropdown' : 'md-arrow-dropright'" style="margin-left: 8px;"/>
214
+ </div>
215
+ </div>
216
+ <div class="city-card-body" v-if="city.expand && city.children && city.children.length > 0">
217
+ <div class="district-grid">
218
+ <div class="district-item" v-for="district in city.children" :key="district.orgUnitId">
219
+ <div class="district-header" @click="toggleDistrictExpand(district)">
220
+ <div class="district-title" @click.stop="addOrgNewItem(district)">
221
+ <img src="./assets/icon.png" alt="" style="margin-right: 8px; width: 14px; height: 14px;"/>
222
+ {{ district.title }}
223
+ </div>
224
+ <div class="district-actions" v-if="district.children && district.children.length > 0">
225
+ <Button type="text" @click.stop="selectAllDistrictOrgNew(district)">全选</Button>
226
+ <Icon :type="district.expand ? 'md-arrow-dropdown' : 'md-arrow-dropright'" style="margin-left: 8px;"/>
227
+ </div>
228
+ </div>
229
+ <div class="district-body" v-if="district.expand && district.children && district.children.length > 0">
230
+ <div class="org-unit-item" v-for="unit in district.children" :key="unit.orgUnitId">
231
+ <div class="unit-title" @click="addOrgNewItem(unit)">
232
+ <img src="./assets/icon.png" alt="" style="margin-right: 8px; width: 14px; height: 14px;"/>
233
+ {{ unit.title }}
234
+ </div>
235
+ </div>
236
+ </div>
237
+ </div>
238
+ </div>
239
+ </div>
240
+ </div>
241
+ </div>
242
+ </div>
243
+ </div>
244
+ </div>
245
+ </TabPane>
181
246
  </Tabs>
182
247
  </div>
183
248
  <div class="form-content">
@@ -214,7 +279,7 @@
214
279
  <!-- 直接选择人员:-->
215
280
  <div v-if="name.includes('staff')">
216
281
  <div class="group-box flex-r-bt">
217
- <div>直接选择人员:</div>
282
+ <div>选择人员:</div>
218
283
  <div class="clear-btn" @click="clearStaff">清除全部</div>
219
284
  </div>
220
285
  <div class="group-list-content">
@@ -222,7 +287,21 @@
222
287
  <span>{{item.name}}</span>
223
288
  <img class="clear-icon" src="./assets/delete.png" alt="" @click="clearStaffByIndex(index)">
224
289
  </p>
225
- <p style="color:#CCCCCC" class="list-item" v-if="!staffList.length">未选择直接选择人员</p>
290
+ <p style="color:#CCCCCC" class="list-item" v-if="!staffList.length">未选择人员</p>
291
+ </div>
292
+ </div>
293
+ <!-- 组织选择(新):-->
294
+ <div v-if="name.includes('orgNew')">
295
+ <div class="group-box flex-r-bt">
296
+ <div>组织选择:</div>
297
+ <div class="clear-btn" @click="clearOrgNewList">清除全部</div>
298
+ </div>
299
+ <div class="group-list-content">
300
+ <p class="list-item flex-r-bt" v-for="(item,index) in orgNewList" :key="item.id">
301
+ <span>{{item.title}}</span>
302
+ <img class="clear-icon" src="./assets/delete.png" alt="" @click="clearOrgNewByIndex(index)">
303
+ </p>
304
+ <p style="color:#CCCCCC" class="list-item" v-if="!orgNewList.length">未选择组织节点</p>
226
305
  </div>
227
306
  </div>
228
307
  </div>
@@ -296,7 +375,7 @@ export default {
296
375
  parentOrgList: [],
297
376
  orgTagList:[],
298
377
  postTagList:[],
299
- selectedPositionId: null, // 新增:岗位单选的选中状态存储
378
+ selectedPositionId: null, // 岗位单选的选中状态存储
300
379
  selectedOrgTagKey: '', // 存储选中标签的唯一标识
301
380
  selectedPostTagKey: '', // 存储选中标签的唯一标识
302
381
  //人员选择
@@ -304,8 +383,8 @@ export default {
304
383
  staffTagList:[],
305
384
  staffOrgList:[],
306
385
  staffSearchList:[],
307
- selectedStaffOrgId: '', // 新增:选中的组织节点ID
308
- proStaffOrgList: [], // 新增:暂存选中的组织节点
386
+ selectedStaffOrgId: '', // 选中的组织节点ID
387
+ proStaffOrgList: [], // 暂存选中的组织节点
309
388
  initialDefaultOrgUnitId: '', // 缓存初始defaultOrgUnitId
310
389
  // staffTreeInited: false, // 组织树初始化完成标记
311
390
  // 树加载完成标记
@@ -315,6 +394,13 @@ export default {
315
394
  // 缓存原始组织树/岗位树数据
316
395
  originalOrgTree: [], // 组织Tab原始树缓存
317
396
  originalPostTree: [], // 岗位Tab原始树缓存
397
+ staffTreeInited: false, // 组织树初始化完成标记(用于需求3)
398
+ //组织选择(新)
399
+ orgNewSearch: '',
400
+ orgNewTree: [],
401
+ proOrgNewList: [],
402
+ includeLevelOrgNew: [],
403
+ orgNewList: []
318
404
  }
319
405
  },
320
406
  mounted() {
@@ -325,6 +411,7 @@ export default {
325
411
  this.initOrgOrgTree()
326
412
  this.initPostOrgTree()
327
413
  this.initStaffOrgTree()
414
+ this.initOrgNewTree()
328
415
  },
329
416
 
330
417
  methods:{
@@ -1266,11 +1353,18 @@ export default {
1266
1353
  clearStaffByIndex(index){
1267
1354
  this.staffList.splice(index,1)
1268
1355
  },
1356
+ clearOrgNewList(){
1357
+ this.orgNewList = []
1358
+ },
1359
+ clearOrgNewByIndex(index){
1360
+ this.orgNewList.splice(index,1)
1361
+ },
1269
1362
  confirm(){
1270
1363
  const v = {
1271
1364
  orgList:this.orgList,
1272
1365
  postList:this.postList,
1273
- staffList:this.staffList
1366
+ staffList:this.staffList,
1367
+ orgNewList:this.orgNewList
1274
1368
  }
1275
1369
  this.$emit('confirm',deepCopy(v))
1276
1370
  },
@@ -1517,7 +1611,7 @@ export default {
1517
1611
  continue;
1518
1612
  }
1519
1613
 
1520
- // 父节点追溯与节点链挂载(修复:使用当前Tab的树数据originalTreeData,而非固定orgTree)
1614
+ // 父节点追溯与节点链挂载(使用当前Tab的树数据originalTreeData,而非固定orgTree)
1521
1615
  let targetParent = null;
1522
1616
  let nodeChain = [currentNode];
1523
1617
  const MAX_DEPTH = 8;
@@ -1542,7 +1636,7 @@ export default {
1542
1636
  }
1543
1637
 
1544
1638
  parentNode.orgNodeName = parentNode.orgNodeName || parentNode.orgUnitName || `未命名组织(${parentId})`;
1545
- // 修复:查询父节点是否在当前Tab的树数据中(originalTreeData),而非固定orgTree
1639
+ // 查询父节点是否在当前Tab的树数据中(originalTreeData),而非固定orgTree
1546
1640
  const parentInTree = this.findNodeInTree(originalTreeData, parentNode.orgUnitId);
1547
1641
 
1548
1642
  if (parentInTree) {
@@ -1629,7 +1723,7 @@ export default {
1629
1723
  treeRef.handleChange(matchedNodes);
1630
1724
  }
1631
1725
 
1632
- // 提示信息(通用逻辑)
1726
+ // 提示信息
1633
1727
  this.$Message.success(`成功选中${matchedNodes.length}个组织节点`);
1634
1728
  });
1635
1729
  } else {
@@ -1647,11 +1741,10 @@ export default {
1647
1741
  });
1648
1742
  },
1649
1743
 
1650
- // 新增:移除树数据中的 parent 引用,避免子组件处理时形成循环
1744
+ // 移除树数据中的 parent 引用,避免子组件处理时形成循环
1651
1745
  removeParentReferences(treeData) {
1652
1746
  if (!Array.isArray(treeData)) return;
1653
1747
  treeData.forEach(node => {
1654
- // 删除可能存在的 parent 引用(如果节点有此属性)
1655
1748
  if (node.parent) delete node.parent;
1656
1749
  // 递归处理子节点
1657
1750
  if (Array.isArray(node.orgChildrenList)) {
@@ -1686,7 +1779,6 @@ export default {
1686
1779
  return null;
1687
1780
  },
1688
1781
 
1689
- // 增强安全深拷贝,主动移除循环引用字段
1690
1782
  safeDeepCopy(obj, hash = new WeakMap()) {
1691
1783
  if (obj === null || typeof obj !== 'object') {
1692
1784
  return obj;
@@ -1715,15 +1807,12 @@ export default {
1715
1807
  hash.set(obj, copy);
1716
1808
  for (let key in obj) {
1717
1809
  if (obj.hasOwnProperty(key)) {
1718
- // 仅过滤vue内部字段,保留业务字段
1719
1810
  if (['__vue__', '__ob__', '$parent', '$children'].includes(key)) {
1720
1811
  continue;
1721
1812
  }
1722
- // 子节点数组特殊处理
1723
1813
  if (['orgChildrenList', 'children'].includes(key) && Array.isArray(obj[key])) {
1724
1814
  copy[key] = obj[key].map(child => this.safeDeepCopy(child, hash));
1725
1815
  } else {
1726
- // 保留所有业务字段,不额外过滤
1727
1816
  copy[key] = this.safeDeepCopy(obj[key], hash);
1728
1817
  }
1729
1818
  }
@@ -1735,9 +1824,9 @@ export default {
1735
1824
  },
1736
1825
 
1737
1826
  /**
1738
- * 查询单个节点的原生详情(适配后端接口,返回原生字段)
1739
- * @param {string} orgUnitId - 节点ID(如11510101)
1740
- * @returns {Promise<Object|null>} 原生节点详情(无数据返回null)
1827
+ * 查询单个节点的原生详情
1828
+ * @param {string} orgUnitId
1829
+ * @returns {Promise<Object|null>}
1741
1830
  */
1742
1831
  getOrgNodeDetail(orgUnitId) {
1743
1832
  return new Promise((resolve) => {
@@ -1745,13 +1834,12 @@ export default {
1745
1834
  params: { orgUnitId: orgUnitId }
1746
1835
  }).then((res) => {
1747
1836
  if (res.data.code === 1 && res.data.data) {
1748
- // 仅保留原生树结构必需字段(过滤业务冗余字段)
1749
1837
  const { orgUnitId, parentOrgUnitId, orgNodeName, orgChildrenList } = res.data.data;
1750
1838
  resolve({
1751
1839
  orgUnitId,
1752
1840
  parentOrgUnitId,
1753
1841
  orgNodeName,
1754
- orgChildrenList: orgChildrenList || [] // 兼容接口返回空的情况
1842
+ orgChildrenList: orgChildrenList || []
1755
1843
  });
1756
1844
  } else {
1757
1845
  resolve(null);
@@ -1764,7 +1852,7 @@ export default {
1764
1852
  },
1765
1853
 
1766
1854
  /**
1767
- * 迭代查找节点(替代递归,避免栈溢出)
1855
+ * 迭代查找节点
1768
1856
  * @param {Array} treeData - 树形数据
1769
1857
  * @param {string} targetOrgUnitId - 目标节点ID
1770
1858
  * @returns {Object|null} 找到的节点
@@ -1777,7 +1865,6 @@ export default {
1777
1865
  const queue = [...treeData];
1778
1866
  while (queue.length > 0) {
1779
1867
  const currentNode = queue.shift();
1780
- // 兼容子组件可能的字段映射(orgUnitId可能存储在id字段)
1781
1868
  const nodeId = currentNode.orgUnitId || currentNode.id || '';
1782
1869
  if (nodeId === targetOrgUnitId) {
1783
1870
  return currentNode;
@@ -1866,6 +1953,256 @@ export default {
1866
1953
  this.updateTreeNodesStatus(children, expandIds, checkedIds);
1867
1954
  }
1868
1955
  });
1956
+ },
1957
+ // 组织选择(新)相关方法
1958
+ async initOrgNewTree() {
1959
+ try {
1960
+ const res = await ajax.get('/pub-manage-server/pub/personHelpBox/q/getFullOrgUnitTree');
1961
+ if (res.data.code === 1) {
1962
+ // 直接使用返回的完整树形结构
1963
+ const treeData = res.data.data || [];
1964
+ // 处理树形数据,添加必要的字段
1965
+ const processedTree = this.processOrgNewTree(treeData);
1966
+ this.orgNewTree = this.safeDeepCopy(processedTree);
1967
+ }
1968
+ } catch (e) {
1969
+ this.$Message.error("组织选择(新)树初始化失败!");
1970
+ console.error(e);
1971
+ }
1972
+ },
1973
+ buildOrgNewTree(items) {
1974
+ const map = {};
1975
+ const roots = [];
1976
+ const copiedItems = this.safeDeepCopy(items);
1977
+
1978
+ copiedItems.forEach(item => {
1979
+ if (!item.orgUnitId) return;
1980
+ map[item.orgUnitId] = this.safeDeepCopy({
1981
+ ...item,
1982
+ orgChildrenList: [],
1983
+ children: [],
1984
+ title: item.orgUnitName || item.orgNodeName || item.name || `未命名组织(${item.orgUnitId || ''})`,
1985
+ expand: false,
1986
+ checked: false
1987
+ });
1988
+ });
1989
+
1990
+ copiedItems.forEach(item => {
1991
+ if (!item.orgUnitId || !map[item.orgUnitId]) return;
1992
+
1993
+ const node = map[item.orgUnitId];
1994
+ if (!item.parentOrgUnitId || !map[item.parentOrgUnitId]) {
1995
+ node.expand = true;
1996
+ roots.push(node);
1997
+ } else {
1998
+ const parent = map[item.parentOrgUnitId];
1999
+ parent.orgChildrenList.push(node);
2000
+ parent.children.push(node);
2001
+ parent.leafNode = false;
2002
+ }
2003
+ });
2004
+ return roots;
2005
+ },
2006
+ // 处理新接口返回的组织树数据
2007
+ processOrgNewTree(treeData) {
2008
+ if (!Array.isArray(treeData)) return [];
2009
+
2010
+ return treeData.map(node => {
2011
+ // 添加必要的字段
2012
+ const processedNode = {
2013
+ ...node,
2014
+ title: node.orgNodeName || node.orgUnitName || `未命名组织(${node.orgUnitId || ''})`,
2015
+ expand: false,
2016
+ checked: false,
2017
+ orgChildrenList: node.children || []
2018
+ };
2019
+
2020
+ // 递归处理子节点
2021
+ if (processedNode.children && processedNode.children.length > 0) {
2022
+ processedNode.children = this.processOrgNewTree(processedNode.children);
2023
+ processedNode.expand = true; // 默认展开有子节点的节点
2024
+ }
2025
+
2026
+ return processedNode;
2027
+ });
2028
+ },
2029
+ searchOrgNew() {
2030
+ // 搜索功能已通过计算属性实现,这里可以添加额外的逻辑
2031
+ },
2032
+ toggleProvinceExpand(province) {
2033
+ // 只有有子节点时才允许展开/折叠
2034
+ if (province.children && province.children.length > 0) {
2035
+ province.expand = !province.expand;
2036
+ }
2037
+ },
2038
+ toggleCityExpand(city) {
2039
+ // 只有有子节点时才允许展开/折叠
2040
+ if (city.children && city.children.length > 0) {
2041
+ city.expand = !city.expand;
2042
+ }
2043
+ },
2044
+ toggleDistrictExpand(district) {
2045
+ // 只有有子节点时才允许展开/折叠
2046
+ if (district.children && district.children.length > 0) {
2047
+ district.expand = !district.expand;
2048
+ }
2049
+ },
2050
+ selectAllProvinceOrgNew(province) {
2051
+ // 全选并添加到已选择条件框,包含下级节点
2052
+ this.addOrgNewItemWithChildren(province, true);
2053
+ },
2054
+ selectAllCityOrgNew(city) {
2055
+ // 全选并添加到已选择条件框,包含下级节点
2056
+ this.addOrgNewItemWithChildren(city, true);
2057
+ },
2058
+ selectAllCityLevelOrgNew(city) {
2059
+ // 全选市本级并添加到已选择条件框,包含下级节点
2060
+ if (city.children && city.children.length > 0) {
2061
+ const cityLevel = city.children[0];
2062
+ this.addOrgNewItemWithChildren(cityLevel, true);
2063
+ }
2064
+ },
2065
+ selectAllDistrictOrgNew(district) {
2066
+ // 全选并添加到已选择条件框,包含下级节点
2067
+ this.addOrgNewItemWithChildren(district, true);
2068
+ },
2069
+ addOrgNewItemWithChildren(node, includeLevel) {
2070
+ if (!node.orgUnitId) return this.$Message.error("组织节点无效!");
2071
+
2072
+ // 检查是否已存在
2073
+ const id = includeLevel ? `01-${node.orgUnitId}` : `00-${node.orgUnitId}`;
2074
+ const existingIndex = this.orgNewList.findIndex(item => item.id === id);
2075
+ if (existingIndex > -1) {
2076
+ this.$Message.warning(`【${node.title}】已在选择列表中`);
2077
+ return;
2078
+ }
2079
+
2080
+ // 创建组织条件项
2081
+ const orgItem = {
2082
+ ...node,
2083
+ title: includeLevel ? `${node.title}(包含下级组织节点)` : node.title,
2084
+ id: id,
2085
+ includeLevel: includeLevel,
2086
+ orgNodeName: node.orgNodeName || node.title
2087
+ };
2088
+
2089
+ // 添加到已选择列表
2090
+ this.orgNewList.push(orgItem);
2091
+ this.$Message.success(`已添加【${orgItem.title}】`);
2092
+ },
2093
+ isProvinceAllSelected(province) {
2094
+ if (!province.children || province.children.length === 0) return false;
2095
+ return province.children.every(city => this.isCityAllSelected(city));
2096
+ },
2097
+ isCityAllSelected(city) {
2098
+ if (!city.children || city.children.length === 0) return false;
2099
+ return city.children.every(district => this.isDistrictAllSelected(district));
2100
+ },
2101
+ isCityLevelAllSelected(city) {
2102
+ // 检查市本级是否全选
2103
+ if (!city.children || city.children.length === 0) return false;
2104
+ // 假设第一个子节点是市本级
2105
+ const cityLevel = city.children[0];
2106
+ return this.isDistrictAllSelected(cityLevel);
2107
+ },
2108
+ isDistrictAllSelected(district) {
2109
+ if (!district.children || district.children.length === 0) return false;
2110
+ return district.children.every(unit => unit.checked);
2111
+ },
2112
+ setProvinceChecked(province, checked) {
2113
+ if (province.children) {
2114
+ province.children.forEach(city => {
2115
+ this.setCityChecked(city, checked);
2116
+ });
2117
+ }
2118
+ },
2119
+ setCityChecked(city, checked) {
2120
+ if (city.children) {
2121
+ city.children.forEach(district => {
2122
+ this.setDistrictChecked(district, checked);
2123
+ });
2124
+ }
2125
+ },
2126
+ setCityLevelChecked(city, checked) {
2127
+ if (city.children && city.children.length > 0) {
2128
+ // 只设置市本级(第一个子节点)
2129
+ const cityLevel = city.children[0];
2130
+ this.setDistrictChecked(cityLevel, checked);
2131
+ }
2132
+ },
2133
+ setDistrictChecked(district, checked) {
2134
+ if (district.children) {
2135
+ district.children.forEach(unit => {
2136
+ unit.checked = checked;
2137
+ });
2138
+ }
2139
+ },
2140
+ handleOrgNewUnitChange(unit) {
2141
+ // 处理组织单位选择变化
2142
+ this.collectOrgNewCheckedUnits();
2143
+ },
2144
+ collectOrgNewCheckedUnits() {
2145
+ this.proOrgNewList = [];
2146
+ this.collectCheckedUnits(this.orgNewTree);
2147
+ },
2148
+ collectCheckedUnits(nodeList) {
2149
+ if (!Array.isArray(nodeList)) return;
2150
+ nodeList.forEach(node => {
2151
+ if (node.checked) {
2152
+ this.proOrgNewList.push({
2153
+ ...node,
2154
+ orgNodeName: node.orgNodeName || node.title || `未命名组织(${node.orgUnitId})`
2155
+ });
2156
+ }
2157
+ if (node.children && node.children.length > 0) {
2158
+ this.collectCheckedUnits(node.children);
2159
+ }
2160
+ });
2161
+ },
2162
+ expandAllOrgNew() {
2163
+ this.setAllExpand(this.orgNewTree, true);
2164
+ },
2165
+ collapseAllOrgNew() {
2166
+ this.setAllExpand(this.orgNewTree, false);
2167
+ },
2168
+ setAllExpand(nodeList, expand) {
2169
+ if (!Array.isArray(nodeList)) return;
2170
+ nodeList.forEach(node => {
2171
+ node.expand = expand;
2172
+ if (node.children && node.children.length > 0) {
2173
+ this.setAllExpand(node.children, expand);
2174
+ }
2175
+ });
2176
+ },
2177
+ clearOrgNew() {
2178
+ this.clearAllCheckedOrgNew(this.orgNewTree);
2179
+ this.proOrgNewList = [];
2180
+ this.orgNewSearch = '';
2181
+ },
2182
+ clearAllCheckedOrgNew(nodeList) {
2183
+ if (!Array.isArray(nodeList)) return;
2184
+ nodeList.forEach(node => {
2185
+ node.checked = false;
2186
+ if (node.children && node.children.length > 0) {
2187
+ this.clearAllCheckedOrgNew(node.children);
2188
+ }
2189
+ });
2190
+ },
2191
+ addOrgNewItem(node) {
2192
+ // 调用通用方法,不包含下级节点
2193
+ this.addOrgNewItemWithChildren(node, false);
2194
+ },
2195
+ addOrgNewList() {
2196
+ const validOrgList = this.proOrgNewList.filter(node => node.orgUnitId);
2197
+ if (!validOrgList.length) return this.$Message.error("请先选择组织节点!");
2198
+
2199
+ validOrgList.forEach(node => {
2200
+ this.addOrgNewItemWithChildren(node, false);
2201
+ });
2202
+
2203
+ // 清空选中状态
2204
+ this.clearAllCheckedOrgNew(this.orgNewTree);
2205
+ this.proOrgNewList = [];
1869
2206
  }
1870
2207
 
1871
2208
  },
@@ -1877,7 +2214,43 @@ export default {
1877
2214
  let l1 = this.orgList.length?1:0;
1878
2215
  let l2 = this.postList.length?1:0;
1879
2216
  let l3 = this.staffList.length?1:0;
1880
- return l1+l2+l3
2217
+ let l4 = this.orgNewList.length?1:0;
2218
+ return l1+l2+l3+l4
2219
+ },
2220
+ filteredOrgNewTree() {
2221
+ // 前端过滤,模糊匹配
2222
+ const searchTerm = this.orgNewSearch.toLowerCase().trim();
2223
+ if (!searchTerm) {
2224
+ return this.orgNewTree;
2225
+ }
2226
+
2227
+ // 递归过滤函数
2228
+ const filterTree = (nodes) => {
2229
+ return nodes.map(node => {
2230
+ // 检查当前节点是否匹配
2231
+ const isMatch = node.title.toLowerCase().includes(searchTerm);
2232
+
2233
+ // 递归过滤子节点
2234
+ let filteredChildren = [];
2235
+ if (node.children && node.children.length > 0) {
2236
+ filteredChildren = filterTree(node.children);
2237
+ }
2238
+
2239
+ // 如果当前节点匹配或有匹配的子节点,则保留该节点
2240
+ if (isMatch || filteredChildren.length > 0) {
2241
+ return {
2242
+ ...node,
2243
+ expand: true, // 自动展开匹配的节点
2244
+ children: filteredChildren
2245
+ };
2246
+ }
2247
+
2248
+ // 不匹配且没有匹配的子节点,则过滤掉
2249
+ return null;
2250
+ }).filter(Boolean); // 过滤掉null值
2251
+ };
2252
+
2253
+ return filterTree(this.orgNewTree);
1881
2254
  }
1882
2255
  },
1883
2256
  watch:{
@@ -1901,6 +2274,12 @@ export default {
1901
2274
  })
1902
2275
  this.postList = postList
1903
2276
  this.staffList = map.staffList || []
2277
+ let orgNewList = map.orgNewList || []
2278
+ orgNewList.forEach(item=>{
2279
+ item.title = item.includeLevel?`${item.orgNodeName}(包含下级组织节点)`:item.orgNodeName
2280
+ item.id = item.includeLevel?('01'+'-' + item.orgUnitId):('00'+'-'+item.orgUnitId)
2281
+ })
2282
+ this.orgNewList = orgNewList
1904
2283
  },
1905
2284
  deep: true,
1906
2285
  immediate: true,
@@ -2294,6 +2673,241 @@ export default {
2294
2673
  background-color: #f5f5f5;
2295
2674
  }
2296
2675
 
2676
+ /* 组织选择(新)样式 */
2677
+ .org-new-tab {
2678
+ .org-new-header {
2679
+ display: flex;
2680
+ justify-content: space-between;
2681
+ align-items: center;
2682
+ margin-bottom: 16px;
2683
+ flex-wrap: wrap;
2684
+ gap: 10px;
2685
+ }
2686
+
2687
+ .org-new-actions {
2688
+ display: flex;
2689
+ gap: 10px;
2690
+ }
2691
+
2692
+ .org-new-content {
2693
+ max-height: 500px;
2694
+ overflow-y: auto;
2695
+ border: 1px solid #EAECF0;
2696
+ border-radius: 4px;
2697
+ padding: 16px;
2698
+ margin-bottom: 16px;
2699
+ }
2700
+
2701
+ .org-card {
2702
+ border: 1px solid #EAECF0;
2703
+ border-radius: 4px;
2704
+ margin-bottom: 16px;
2705
+ overflow: hidden;
2706
+
2707
+ .org-card-header {
2708
+ display: flex;
2709
+ justify-content: space-between;
2710
+ align-items: center;
2711
+ padding: 12px 16px;
2712
+ background-color: #f9fafb;
2713
+ cursor: pointer;
2714
+ border-bottom: 1px solid #EAECF0;
2715
+
2716
+ &:hover {
2717
+ background-color: #f3f4f6;
2718
+ }
2719
+
2720
+ .org-card-title {
2721
+ display: flex;
2722
+ align-items: center;
2723
+ font-weight: 500;
2724
+ }
2725
+
2726
+ .org-card-actions {
2727
+ display: flex;
2728
+ align-items: center;
2729
+ gap: 10px;
2730
+
2731
+ .ivu-btn-text {
2732
+ color: #1890ff;
2733
+ font-weight: 500;
2734
+ transition: all 0.2s;
2735
+
2736
+ &:hover {
2737
+ color: #40a9ff;
2738
+ text-decoration: underline;
2739
+ transform: translateY(-1px);
2740
+ }
2741
+
2742
+ &:active {
2743
+ color: #096dd9;
2744
+ transform: translateY(0);
2745
+ }
2746
+ }
2747
+ }
2748
+ }
2749
+
2750
+ .org-card-body {
2751
+ padding: 16px;
2752
+ }
2753
+ }
2754
+
2755
+ .city-card {
2756
+ border: 1px solid #EAECF0;
2757
+ border-radius: 4px;
2758
+ margin-bottom: 12px;
2759
+ overflow: hidden;
2760
+
2761
+ .city-card-header {
2762
+ display: flex;
2763
+ justify-content: space-between;
2764
+ align-items: center;
2765
+ padding: 10px 14px;
2766
+ background-color: #f9fafb;
2767
+ cursor: pointer;
2768
+ border-bottom: 1px solid #EAECF0;
2769
+
2770
+ &:hover {
2771
+ background-color: #f3f4f6;
2772
+ }
2773
+
2774
+ .city-card-title {
2775
+ display: flex;
2776
+ align-items: center;
2777
+ font-weight: 500;
2778
+ }
2779
+
2780
+ .city-card-actions {
2781
+ display: flex;
2782
+ align-items: center;
2783
+ gap: 10px;
2784
+
2785
+ .ivu-btn-text {
2786
+ color: #1890ff;
2787
+ font-weight: 500;
2788
+ transition: all 0.2s;
2789
+
2790
+ &:hover {
2791
+ color: #40a9ff;
2792
+ text-decoration: underline;
2793
+ transform: translateY(-1px);
2794
+ }
2795
+
2796
+ &:active {
2797
+ color: #096dd9;
2798
+ transform: translateY(0);
2799
+ }
2800
+ }
2801
+ }
2802
+ }
2803
+
2804
+ .city-card-body {
2805
+ padding: 14px;
2806
+ }
2807
+ }
2808
+
2809
+ .district-grid {
2810
+ display: grid;
2811
+ grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
2812
+ gap: 12px;
2813
+ }
2814
+
2815
+ .district-item {
2816
+ border: 1px solid #EAECF0;
2817
+ border-radius: 4px;
2818
+ overflow: hidden;
2819
+
2820
+ .district-header {
2821
+ display: flex;
2822
+ justify-content: space-between;
2823
+ align-items: center;
2824
+ padding: 8px 12px;
2825
+ background-color: #f9fafb;
2826
+ cursor: pointer;
2827
+ border-bottom: 1px solid #EAECF0;
2828
+
2829
+ &:hover {
2830
+ background-color: #f3f4f6;
2831
+ }
2832
+
2833
+ .district-title {
2834
+ display: flex;
2835
+ align-items: center;
2836
+ font-weight: 500;
2837
+ }
2838
+
2839
+ .district-actions {
2840
+ display: flex;
2841
+ align-items: center;
2842
+ gap: 10px;
2843
+
2844
+ .ivu-btn-text {
2845
+ color: #1890ff;
2846
+ font-weight: 500;
2847
+ transition: all 0.2s;
2848
+
2849
+ &:hover {
2850
+ color: #40a9ff;
2851
+ text-decoration: underline;
2852
+ transform: translateY(-1px);
2853
+ }
2854
+
2855
+ &:active {
2856
+ color: #096dd9;
2857
+ transform: translateY(0);
2858
+ }
2859
+ }
2860
+ }
2861
+ }
2862
+
2863
+ .district-body {
2864
+ padding: 12px;
2865
+ }
2866
+ }
2867
+
2868
+ .org-unit-item {
2869
+ margin-bottom: 8px;
2870
+
2871
+ &:last-child {
2872
+ margin-bottom: 0;
2873
+ }
2874
+ }
2875
+
2876
+ .unit-title {
2877
+ display: flex;
2878
+ align-items: center;
2879
+ padding: 4px 0;
2880
+ cursor: pointer;
2881
+
2882
+ &:hover {
2883
+ color: #1890ff;
2884
+ }
2885
+ }
2886
+
2887
+ .org-card-title,
2888
+ .city-card-title,
2889
+ .district-title {
2890
+ cursor: pointer;
2891
+
2892
+ &:hover {
2893
+ color: #1890ff;
2894
+ }
2895
+ }
2896
+
2897
+ .org-new-footer {
2898
+ display: flex;
2899
+ justify-content: space-between;
2900
+ align-items: center;
2901
+ padding-top: 16px;
2902
+ border-top: 1px solid #f0f0f0;
2903
+ }
2904
+
2905
+ .include-level {
2906
+ display: flex;
2907
+ align-items: center;
2908
+ }
2909
+ }
2910
+
2297
2911
  .custom-select-wrapper {
2298
2912
  position: relative;
2299
2913
 
@@ -201,7 +201,7 @@ export default {
201
201
  },
202
202
 
203
203
  async loadData(item, callback) {
204
- // 核心修改:即使禁用懒加载,也允许加载已有子节点
204
+ // 即使禁用懒加载,也允许加载已有子节点
205
205
  if (this.disableLazyLoad) {
206
206
  let children = item.orgChildrenList || item.children || [];
207
207
  const formattedChildren = this.safeDeepCopy(children).map(child => ({
@@ -305,7 +305,7 @@ export default {
305
305
  return;
306
306
  }
307
307
 
308
- // 单选逻辑强化:清空所有选中状态
308
+ // 单选,清空所有选中状态
309
309
  this.clearAllChecked(this.data);
310
310
 
311
311
  const targetList = this.isSingleSelect
@@ -412,34 +412,27 @@ export default {
412
412
  }
413
413
  return null;
414
414
  },
415
- // organize-tree.vue - 重构 initTree 方法,确保递归处理所有层级
415
+
416
416
  initTree(treeList) {
417
417
  // 递归处理节点的内部方法
418
418
  const recursiveInitNode = (node) => {
419
- // 1. 统一节点标题(优先级:orgUnitName > orgNodeName > name > 兜底)
420
419
  node.title = node.orgUnitName || node.orgNodeName || node.name || `未命名组织(${node.orgUnitId || node.id || ''})`;
421
- // 2. 初始化基础字段
422
420
  node.loading = false;
423
421
  node.expand = false;
424
422
  node.checked = false;
425
- // 3. 关键:无论是否有子节点,先初始化 children 空数组(让 Tree 组件识别可懒加载)
426
423
  node.children = node.children || [];
427
- // 4. 同步 orgChildrenList 和 children(双向绑定,避免字段不一致)
428
424
  node.orgChildrenList = node.orgChildrenList || node.children || [];
429
- // 5. 禁用状态处理
430
425
  if (this.disabled) {
431
426
  node.disabled = true;
432
427
  }
433
- // 6. 叶子节点判断:如果明确标记为 leafNode,删除 loading 和 children(禁止展开)
434
428
  if (node.leafNode) {
435
429
  delete node.loading;
436
430
  delete node.children;
437
431
  delete node.orgChildrenList;
438
432
  } else {
439
- // 7. 非叶子节点:递归处理已有子节点(确保下级节点也完成初始化)
440
433
  if (Array.isArray(node.orgChildrenList) && node.orgChildrenList.length > 0) {
441
434
  node.children = node.orgChildrenList.map(child => recursiveInitNode(child));
442
- node.expand = true; // 默认展开已有子节点的节点
435
+ node.expand = true;
443
436
  }
444
437
  }
445
438
  return node;
@@ -509,18 +502,16 @@ export default {
509
502
  flex: 1,
510
503
  pointerEvents: 'none',
511
504
  userSelect: 'none',
512
- // 新增:防止文字溢出导致的截断(可选,解决orgUnitId显示不全问题)
513
505
  whiteSpace: 'normal',
514
506
  wordWrap: 'break-word'
515
507
  }
516
- }, nodeText) // 使用调整优先级后的节点文字
508
+ }, nodeText)
517
509
  ]);
518
510
  },
519
511
  collectCurrentCheckedNodes(nodeList) {
520
512
  let checkedNodes = [];
521
513
  nodeList.forEach(node => {
522
514
  if (node.checked) {
523
- // 强制补全orgUnitId,过滤无效节点
524
515
  const nodeId = node.orgUnitId || node.id || '';
525
516
  if (nodeId && typeof nodeId === 'string' && nodeId.trim()) {
526
517
  const validNode = {
@@ -551,7 +542,6 @@ export default {
551
542
  watch: {
552
543
  'treeList': {
553
544
  handler(val) {
554
- // 自定义树场景:直接使用父组件传递的树数据,不初始化旧接口
555
545
  if (this.isCustomTree || this.isDisableLazyLoad) {
556
546
  let tree = this.safeDeepCopy(val);
557
547
  this.initTree(tree);