@sy-common/organize-select-help 1.0.0-beta.6 → 1.0.0-beta.63
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 +3 -2
- package/src/index.vue +2079 -208
- package/src/organize-tree.vue +584 -115
package/src/index.vue
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
|
|
2
|
+
<Modal
|
|
3
3
|
title=""
|
|
4
4
|
v-model="modal"
|
|
5
5
|
@on-ok="confirm"
|
|
@@ -7,132 +7,221 @@
|
|
|
7
7
|
width="1180"
|
|
8
8
|
:mask-closable="false"
|
|
9
9
|
class="modal-tree"
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
10
|
+
:fullscreen="true"
|
|
11
|
+
>
|
|
12
|
+
<div slot="header" class="header-text"><Icon type="md-information" class="icon-tip" />人员选择</div>
|
|
13
|
+
<div class="content-container">
|
|
14
|
+
<div class="tree-orig">
|
|
15
|
+
<div class="tab-content-pro">
|
|
16
|
+
<Tabs :value="tabName" @input="handleTabChange">
|
|
17
|
+
<TabPane label="组织选择" name="org" v-if="name.includes('org')">
|
|
18
|
+
<div class="tab">
|
|
19
|
+
<span>组织搜索:</span>
|
|
20
|
+
<Select v-model="orgSearch" filterable :remote-method="getOrgListBySearch" @on-change="getOrgOption" :loading="loadingOrg" placeholder="请输入组织名称" style="width: 600px;" clearable>
|
|
21
|
+
<Option v-for="(option, index) in orgSearchList" :value="option.orgUnitId" :key="index">{{option.name}}</Option>
|
|
22
|
+
</Select>
|
|
23
|
+
<div class="tag-content" v-if="isQuickOpen && orgTagList.length > 0">
|
|
24
|
+
<span>快捷选择:</span>
|
|
25
|
+
<div class="custom-select-wrapper">
|
|
26
|
+
<Select
|
|
27
|
+
v-model="selectedOrgTagKey"
|
|
28
|
+
placeholder="请选择快捷标签"
|
|
29
|
+
transfer
|
|
30
|
+
clearable
|
|
31
|
+
@on-change="handleOrgTagSelect"
|
|
32
|
+
@on-clear="handleOrgTagClear"
|
|
33
|
+
style="width: 600px;"
|
|
34
|
+
:disabled="!orgTagList.length"
|
|
35
|
+
>
|
|
36
|
+
<Option
|
|
37
|
+
v-for="item in orgTagList"
|
|
38
|
+
:value="item.quickPickKey"
|
|
39
|
+
:key="item.quickPickKey"
|
|
40
|
+
:class="{ 'active-option': item.checked }"
|
|
41
|
+
>
|
|
42
|
+
{{ item.quickPickName }}
|
|
43
|
+
</Option>
|
|
44
|
+
<!-- 无数据提示 -->
|
|
45
|
+
<Option value="" v-if="!postTagList.length" disabled>
|
|
46
|
+
暂无快捷标签
|
|
47
|
+
</Option>
|
|
48
|
+
</Select>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
<div class="tree">
|
|
52
|
+
<organizeTree @handleChange="getOrgList" ref="orgTree" :treeList="orgTree"></organizeTree>
|
|
53
|
+
</div>
|
|
54
|
+
<div class="bottom-select">
|
|
55
|
+
<CheckboxGroup v-model="includeLevelOrg">
|
|
56
|
+
<Checkbox label="01">
|
|
57
|
+
<span>包含下级组织节点</span>
|
|
58
|
+
</Checkbox>
|
|
59
|
+
</CheckboxGroup>
|
|
60
|
+
<Button type="primary" icon="md-add" @click="addOrgList">添加节点</Button>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
</TabPane>
|
|
64
|
+
<TabPane label="岗位选择" name="post" v-if="name.includes('post')">
|
|
65
|
+
<div class="tab post">
|
|
66
|
+
<div class="left" style="height: 450px; overflow: hidden; position: relative; z-index: 1;">
|
|
67
|
+
<div class="scroll-container">
|
|
68
|
+
<div class="position-item"
|
|
69
|
+
v-for="item in positiontList"
|
|
70
|
+
:class="[selectedPositionId === item.positionId ? 'active' : '']"
|
|
71
|
+
:key="item.positionId"
|
|
72
|
+
@click="getPosionId(item)">
|
|
73
|
+
{{ item.positionName }} <!-- 无需修改模板,仅通过样式实现自动换行 -->
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
<div class="right">
|
|
78
|
+
<span>组织搜索:</span>
|
|
79
|
+
<Select v-model="postSearch" filterable :remote-method="getPostListBySearch" @on-change="getPostOption" placeholder="组织选择" :loading="loadingPost" clearable @on-clear="handlePostSearchClear" style="width: 365px;">
|
|
80
|
+
<Option v-for="(option, index) in postSearchList" :value="option.orgUnitId" :key="index">{{option.name}}</Option>
|
|
81
|
+
</Select>
|
|
82
|
+
<div class="tag-content" v-if="isQuickOpen && postTagList.length > 0">
|
|
20
83
|
<span>快捷选择:</span>
|
|
21
|
-
<div class="
|
|
22
|
-
<
|
|
84
|
+
<div class="custom-select-wrapper">
|
|
85
|
+
<Select
|
|
86
|
+
v-model="selectedPostTagKey"
|
|
87
|
+
placeholder="请选择快捷标签"
|
|
88
|
+
transfer
|
|
89
|
+
clearable
|
|
90
|
+
@on-change="handlePostTagSelect"
|
|
91
|
+
@on-clear="handlePostTagClear"
|
|
92
|
+
style="width: 365px;"
|
|
93
|
+
:disabled="!postTagList.length"
|
|
94
|
+
>
|
|
95
|
+
<Option
|
|
96
|
+
v-for="item in postTagList"
|
|
97
|
+
:value="item.quickPickKey"
|
|
98
|
+
:key="item.quickPickKey"
|
|
99
|
+
:class="{ 'active-option': item.checked }"
|
|
100
|
+
>
|
|
101
|
+
{{ item.quickPickName }}
|
|
102
|
+
</Option>
|
|
103
|
+
<!-- 无数据提示 -->
|
|
104
|
+
<Option value="" v-if="!postTagList.length" disabled>
|
|
105
|
+
暂无快捷标签
|
|
106
|
+
</Option>
|
|
107
|
+
</Select>
|
|
23
108
|
</div>
|
|
24
109
|
</div>
|
|
25
110
|
<div class="tree">
|
|
26
|
-
<organizeTree @handleChange="
|
|
111
|
+
<organizeTree @handleChange="getPostList" ref="postTree" :treeList="postTree"></organizeTree>
|
|
27
112
|
</div>
|
|
28
113
|
<div class="bottom-select">
|
|
29
|
-
<CheckboxGroup v-model="
|
|
114
|
+
<CheckboxGroup v-model="includeLevelPost">
|
|
30
115
|
<Checkbox label="01">
|
|
31
116
|
<span>包含下级组织节点</span>
|
|
32
117
|
</Checkbox>
|
|
33
118
|
</CheckboxGroup>
|
|
34
|
-
<Button type="primary" icon="md-add" @click="
|
|
119
|
+
<Button type="primary" icon="md-add" @click="addPostList">添加节点</Button>
|
|
35
120
|
</div>
|
|
36
121
|
</div>
|
|
37
|
-
</
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
<div class="
|
|
44
|
-
|
|
45
|
-
<div class="
|
|
46
|
-
<
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
</Checkbox>
|
|
59
|
-
</CheckboxGroup>
|
|
60
|
-
<Button type="primary" icon="md-add" @click="addPostList">添加节点</Button>
|
|
122
|
+
</div>
|
|
123
|
+
</TabPane>
|
|
124
|
+
<TabPane label="选择人员" name="staff" v-if="name.includes('staff')">
|
|
125
|
+
<div class="tab staff-left-right-layout">
|
|
126
|
+
<!-- 左侧:组织选择区域(限制高度) -->
|
|
127
|
+
<div class="staff-left-panel">
|
|
128
|
+
<div class="panel-title">组织选择</div>
|
|
129
|
+
<div class="tree staff-org-tree">
|
|
130
|
+
<div class="tree-scroll-force">
|
|
131
|
+
<organizeTree
|
|
132
|
+
@handleChange="getStaffList"
|
|
133
|
+
ref="staffTree"
|
|
134
|
+
:treeList="staffTree"
|
|
135
|
+
:showCheckbox="true"
|
|
136
|
+
:checkStrictly="true"
|
|
137
|
+
:autoExpandParent="true"
|
|
138
|
+
:isSingleSelect="true"
|
|
139
|
+
:default-org-unit-id="defaultOrgUnitId"
|
|
140
|
+
:is-custom-tree="!!defaultOrgUnitId"
|
|
141
|
+
:disable-lazy-load="false"
|
|
142
|
+
></organizeTree>
|
|
61
143
|
</div>
|
|
62
144
|
</div>
|
|
63
145
|
</div>
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
<
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
146
|
+
|
|
147
|
+
<div class="staff-right-panel">
|
|
148
|
+
<Input v-model="staffSearch" @on-enter="searchStaff" @on-search="searchStaff" search placeholder="搜索人员"/>
|
|
149
|
+
<div style="position:relative;">
|
|
150
|
+
<div class="tree staff-content" @scroll="handleScroll">
|
|
151
|
+
<div :class="['gust-item',item.checked && 'staff-active']"
|
|
152
|
+
v-for="(item, index) in staffAllList"
|
|
153
|
+
:key="`staff_${index}_${item.id}`"
|
|
154
|
+
@click="handlestaff(item)">
|
|
155
|
+
<!-- 移除 Checkbox 组件 -->
|
|
156
|
+
<div class="left-panel-pro">{{item.name && item.name.slice(0,1) || ''}}</div>
|
|
157
|
+
<div class="right-panel-pro">
|
|
158
|
+
<p>{{item.name}}</p>
|
|
159
|
+
<p>{{item.orgNodeName || item.orgUnitName}}</p>
|
|
160
|
+
</div>
|
|
74
161
|
</div>
|
|
75
|
-
<
|
|
162
|
+
<p v-if="staffEnding" style="color:#CCCCCC;text-align: center">---我也是有底线的---</p>
|
|
76
163
|
</div>
|
|
164
|
+
<Spin v-if="loadingStaff" size="large" fix />
|
|
77
165
|
</div>
|
|
78
|
-
<div class="bottom-select"
|
|
79
|
-
<div>当前已选择 <span class="num">{{getCheckedStaff}}</span>人</div
|
|
80
|
-
<Button type="primary" icon="md-add" @click="addStaffList">添加人员</Button
|
|
81
|
-
</div
|
|
82
|
-
</div>
|
|
83
|
-
</TabPane>
|
|
84
|
-
</Tabs>
|
|
85
|
-
</div>
|
|
86
|
-
<div class="form-content">
|
|
87
|
-
<p>已选择条件 <span class="num">({{getCheckTypenum}})</span></p>
|
|
88
|
-
<div class="node-list">
|
|
89
|
-
<!-- 组织节点条件:-->
|
|
90
|
-
<div>
|
|
91
|
-
<div class="group-box flex-r-bt">
|
|
92
|
-
<div>组织节点条件:</div>
|
|
93
|
-
<div class="clear-btn" @click="clearGroup">清除全部</div>
|
|
94
|
-
</div>
|
|
95
|
-
<div class="group-list-content">
|
|
96
|
-
<p class="list-item flex-r-bt" v-for="(item,index) in orgList" :ket="index">
|
|
97
|
-
<span>{{ item.title }}</span>
|
|
98
|
-
<img class="clear-icon" src="./assets/delete.png" alt="" @click="clearOrgByIndex(index)">
|
|
99
|
-
</p>
|
|
100
|
-
<p style="color:#CCCCCC" class="list-item" v-if="!orgList.length">未选择组织节点</p>
|
|
166
|
+
<!-- <div class="bottom-select">-->
|
|
167
|
+
<!-- <div>当前已选择 <span class="num">{{getCheckedStaff}}</span>人</div>-->
|
|
168
|
+
<!-- <Button type="primary" icon="md-add" @click="addStaffList">添加人员</Button>-->
|
|
169
|
+
<!-- </div>-->
|
|
101
170
|
</div>
|
|
102
171
|
</div>
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
<p style="color:#CCCCCC" class="list-item" v-if="!postList.length">未选择组织节点+岗位条件</p>
|
|
115
|
-
</div>
|
|
172
|
+
</TabPane>
|
|
173
|
+
</Tabs>
|
|
174
|
+
</div>
|
|
175
|
+
<div class="form-content">
|
|
176
|
+
<p v-if="name.length > 1">已选择条件 <span class="num">({{getCheckTypenum}})</span></p>
|
|
177
|
+
<div class="node-list">
|
|
178
|
+
<!-- 组织节点条件:-->
|
|
179
|
+
<div v-if="name.includes('org')">
|
|
180
|
+
<div class="group-box flex-r-bt">
|
|
181
|
+
<div>组织节点条件:</div>
|
|
182
|
+
<div class="clear-btn" @click="clearGroup">清除全部</div>
|
|
116
183
|
</div>
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
<
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
184
|
+
<div class="group-list-content">
|
|
185
|
+
<p class="list-item flex-r-bt" v-for="(item,index) in orgList" :ket="index">
|
|
186
|
+
<span>{{ item.title }}</span>
|
|
187
|
+
<img class="clear-icon" src="./assets/delete.png" alt="" @click="clearOrgByIndex(index)">
|
|
188
|
+
</p>
|
|
189
|
+
<p style="color:#CCCCCC" class="list-item" v-if="!orgList.length">未选择组织节点</p>
|
|
190
|
+
</div>
|
|
191
|
+
</div>
|
|
192
|
+
<!-- 组织节点+岗位条件://-->
|
|
193
|
+
<div v-if="name.includes('post')">
|
|
194
|
+
<div class="group-box flex-r-bt">
|
|
195
|
+
<div>岗位条件+组织节点:</div>
|
|
196
|
+
<div class="clear-btn" @click="clearPost">清除全部</div>
|
|
197
|
+
</div>
|
|
198
|
+
<div class="group-list-content">
|
|
199
|
+
<p class="list-item flex-r-bt" v-for="(item,index) in postList">
|
|
200
|
+
<span>{{item.positionName}}-{{item.title}}</span>
|
|
201
|
+
<img class="clear-icon" src="./assets/delete.png" alt="" @click="clearPostByIndex(index)">
|
|
202
|
+
</p>
|
|
203
|
+
<p style="color:#CCCCCC" class="list-item" v-if="!postList.length">未选择岗位条件+组织节点</p>
|
|
204
|
+
</div>
|
|
205
|
+
</div>
|
|
206
|
+
<!-- 直接选择人员:-->
|
|
207
|
+
<div v-if="name.includes('staff')">
|
|
208
|
+
<div class="group-box flex-r-bt">
|
|
209
|
+
<div>直接选择人员:</div>
|
|
210
|
+
<div class="clear-btn" @click="clearStaff">清除全部</div>
|
|
211
|
+
</div>
|
|
212
|
+
<div class="group-list-content">
|
|
213
|
+
<p class="list-item flex-r-bt" v-for="(item,index) in staffList" :key="item.userId">
|
|
214
|
+
<span>{{item.name}}</span>
|
|
215
|
+
<img class="clear-icon" src="./assets/delete.png" alt="" @click="clearStaffByIndex(index)">
|
|
216
|
+
</p>
|
|
217
|
+
<p style="color:#CCCCCC" class="list-item" v-if="!staffList.length">未选择直接选择人员</p>
|
|
130
218
|
</div>
|
|
131
219
|
</div>
|
|
132
220
|
</div>
|
|
133
221
|
</div>
|
|
134
222
|
</div>
|
|
135
|
-
</
|
|
223
|
+
</div>
|
|
224
|
+
</Modal>
|
|
136
225
|
</template>
|
|
137
226
|
<script>
|
|
138
227
|
import organizeTree from './organize-tree.vue'
|
|
@@ -147,44 +236,241 @@ export default {
|
|
|
147
236
|
},
|
|
148
237
|
data:{
|
|
149
238
|
type:Object,
|
|
150
|
-
default:{}
|
|
239
|
+
default:()=>{}
|
|
240
|
+
},
|
|
241
|
+
name:{
|
|
242
|
+
type:Array ,
|
|
243
|
+
default(){return ['org','post','staff']}
|
|
244
|
+
},
|
|
245
|
+
isQuickOpen:{
|
|
246
|
+
type: Boolean,
|
|
247
|
+
default: false
|
|
248
|
+
},
|
|
249
|
+
defaultOrgUnitId:{
|
|
250
|
+
type: String,
|
|
251
|
+
default: ''
|
|
252
|
+
},
|
|
253
|
+
staffSingle:{
|
|
254
|
+
type: Boolean,
|
|
255
|
+
default: false
|
|
151
256
|
}
|
|
152
257
|
},
|
|
153
258
|
data(){
|
|
154
259
|
return {
|
|
260
|
+
tabName:this.name[0],
|
|
155
261
|
modal:false,
|
|
156
|
-
name:'name1',
|
|
157
262
|
dialogOpen:false,
|
|
158
263
|
orgSearch:'',
|
|
159
264
|
//组织--right-form
|
|
160
265
|
proOrgList:[],
|
|
161
266
|
includeLevelOrg:[],
|
|
162
267
|
orgList:[],
|
|
268
|
+
loadingOrg:false,
|
|
269
|
+
orgSearchList:[],
|
|
270
|
+
orgTree:[],
|
|
163
271
|
//岗位--form
|
|
272
|
+
postSearch:'',
|
|
164
273
|
proPostList:[],
|
|
165
274
|
postList:[],
|
|
275
|
+
loadingPost:false,
|
|
276
|
+
postSearchList:[],
|
|
166
277
|
includeLevelPost:[],
|
|
167
278
|
positiontList:[],
|
|
279
|
+
postTree:[],
|
|
168
280
|
//直接人员
|
|
169
281
|
staffSearch:'',
|
|
170
282
|
staffAllList:[],
|
|
171
283
|
staffList:[],
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
284
|
+
loadingStaff:false,
|
|
285
|
+
lastLoadingTime:0,
|
|
286
|
+
offset:0,
|
|
287
|
+
staffEnding:false,
|
|
288
|
+
parentOrgList: [],
|
|
289
|
+
orgTagList:[],
|
|
290
|
+
postTagList:[],
|
|
291
|
+
selectedPositionId: null, // 新增:岗位单选的选中状态存储
|
|
292
|
+
selectedOrgTagKey: '', // 存储选中标签的唯一标识
|
|
293
|
+
selectedPostTagKey: '', // 存储选中标签的唯一标识
|
|
294
|
+
//人员选择
|
|
295
|
+
staffTree:[],
|
|
296
|
+
staffTagList:[],
|
|
297
|
+
staffOrgList:[],
|
|
298
|
+
staffSearchList:[],
|
|
299
|
+
selectedStaffOrgId: '', // 新增:选中的组织节点ID
|
|
300
|
+
proStaffOrgList: [], // 新增:暂存选中的组织节点
|
|
301
|
+
initialDefaultOrgUnitId: '', // 缓存初始defaultOrgUnitId
|
|
302
|
+
staffTreeInited: false, // 组织树初始化完成标记(用于需求3)
|
|
181
303
|
}
|
|
182
304
|
},
|
|
183
305
|
mounted() {
|
|
306
|
+
this.queryTagList()
|
|
184
307
|
this.queryPositionList()
|
|
185
|
-
this.
|
|
308
|
+
// this.loadMore()
|
|
309
|
+
this.initialDefaultOrgUnitId = this.defaultOrgUnitId || ''; // 缓存初始值
|
|
310
|
+
this.initStaffOrgTree()
|
|
186
311
|
},
|
|
312
|
+
|
|
187
313
|
methods:{
|
|
314
|
+
async initStaffOrgTree() {
|
|
315
|
+
try {
|
|
316
|
+
// 关键修复:初始化时重置选中状态
|
|
317
|
+
this.$set(this, 'selectedStaffOrgId', '');
|
|
318
|
+
this.proStaffOrgList = [];
|
|
319
|
+
|
|
320
|
+
const rootOrgId = this.defaultOrgUnitId || '';
|
|
321
|
+
let rootNode = null;
|
|
322
|
+
let treeSourceData = []; // 存储树原始数据,避免后续覆盖
|
|
323
|
+
|
|
324
|
+
if (rootOrgId) {
|
|
325
|
+
const orgDetailRes = await ajax.get(`/pub-manage-server/pub/organ/q/queryOrg`, {
|
|
326
|
+
params: { orgUnitId: rootOrgId }
|
|
327
|
+
});
|
|
328
|
+
if (orgDetailRes.data.code === 1 && orgDetailRes.data.data) {
|
|
329
|
+
const orgData = orgDetailRes.data.data;
|
|
330
|
+
const leafNode = await this.judgeNodeLeafe(rootOrgId);
|
|
331
|
+
rootNode = this.safeDeepCopy({
|
|
332
|
+
...orgData,
|
|
333
|
+
orgNodeName: orgData.orgUnitName || '',
|
|
334
|
+
title: orgData.orgUnitName || `未命名组织(${orgData.orgUnitId || ''})`,
|
|
335
|
+
leafNode,
|
|
336
|
+
expand: true,
|
|
337
|
+
parentOrgUnitId: orgData.parentOrgUnitId || orgData.parentId,
|
|
338
|
+
orgChildrenList: [], // 初始化自定义子节点字段
|
|
339
|
+
children: [] // 关键:初始化 Tree 组件识别的 children 字段
|
|
340
|
+
});
|
|
341
|
+
// 父节点列表同样同步初始化 children 字段
|
|
342
|
+
let parentsList = await this.getParentOrgNodesByOrgUnitId(rootOrgId);
|
|
343
|
+
const safeParents = this.safeDeepCopy(parentsList);
|
|
344
|
+
safeParents.forEach(node => {
|
|
345
|
+
node.expand = true;
|
|
346
|
+
node.parentOrgUnitId = node.parentId;
|
|
347
|
+
node.orgNodeName = node.orgUnitName || node.orgNodeName || '';
|
|
348
|
+
node.title = node.orgUnitName || node.name || `未命名组织(${node.orgUnitId || ''})`;
|
|
349
|
+
node.orgChildrenList = [];
|
|
350
|
+
node.children = []; // 父节点也初始化 children 字段
|
|
351
|
+
node.leafNode = false;
|
|
352
|
+
});
|
|
353
|
+
treeSourceData = [...safeParents, rootNode];
|
|
354
|
+
} else {
|
|
355
|
+
this.$Message.error("根据默认组织ID查询根节点失败!");
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
} else {
|
|
359
|
+
// defaultOrgUnitId为空时,沿用原有接口/pub/personHelpBox/q/getOrgUnitList
|
|
360
|
+
const res = await ajax.get('/pub-manage-server/pub/personHelpBox/q/getOrgUnitList', {
|
|
361
|
+
params: { containsCurLevel: true }
|
|
362
|
+
});
|
|
363
|
+
if (res.data.code === 1) {
|
|
364
|
+
rootNode = res.data.data[0] || null;
|
|
365
|
+
if (rootNode) {
|
|
366
|
+
rootNode.expand = true;
|
|
367
|
+
rootNode.parentOrgUnitId = rootNode.parentId;
|
|
368
|
+
treeSourceData = [rootNode];
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// 构建组织树,且仅赋值一次,避免后续覆盖(需求3)
|
|
374
|
+
if (treeSourceData.length > 0) {
|
|
375
|
+
const tree = this.buildTree(treeSourceData);
|
|
376
|
+
this.staffTree = this.safeDeepCopy(tree);
|
|
377
|
+
// 关键:标记树已初始化完成,防止后续重复构建覆盖
|
|
378
|
+
this.staffTreeInited = true;
|
|
379
|
+
}
|
|
380
|
+
} catch (e) {
|
|
381
|
+
this.$Message.error("人员选择组织树初始化失败!");
|
|
382
|
+
console.error(e);
|
|
383
|
+
}
|
|
384
|
+
},
|
|
385
|
+
handlePostTagSelect(quickPickKey) {
|
|
386
|
+
// 清空暂存列表
|
|
387
|
+
this.proPostList = [];
|
|
388
|
+
// 找到选中的标签对象
|
|
389
|
+
const selectedItem = this.postTagList.find(
|
|
390
|
+
item => item.quickPickKey === quickPickKey
|
|
391
|
+
);
|
|
392
|
+
|
|
393
|
+
if (selectedItem) {
|
|
394
|
+
// 重置其他标签的选中状态
|
|
395
|
+
this.postTagList.forEach(tag => tag.checked = false);
|
|
396
|
+
// 触发原有的处理方法
|
|
397
|
+
this.fastChedkPost(selectedItem);
|
|
398
|
+
// 清空搜索框绑定的值
|
|
399
|
+
this.postSearch = '';
|
|
400
|
+
// 清空搜索结果列表
|
|
401
|
+
this.postSearchList = [];
|
|
402
|
+
}
|
|
403
|
+
},
|
|
404
|
+
handleOrgTagSelect(quickPickKey) {
|
|
405
|
+
// 清空暂存列表
|
|
406
|
+
this.proOrgList = [];
|
|
407
|
+
// 找到选中的标签对象
|
|
408
|
+
const selectedItem = this.orgTagList.find(
|
|
409
|
+
item => item.quickPickKey === quickPickKey
|
|
410
|
+
);
|
|
411
|
+
|
|
412
|
+
if (selectedItem) {
|
|
413
|
+
// 重置其他标签的选中状态
|
|
414
|
+
this.orgTagList.forEach(tag => tag.checked = false);
|
|
415
|
+
// 触发原有的处理方法
|
|
416
|
+
this.fastChedkOrg(selectedItem);
|
|
417
|
+
// 清空搜索框绑定的值
|
|
418
|
+
this.orgSearch = '';
|
|
419
|
+
// 清空搜索结果列表
|
|
420
|
+
this.orgSearchList = [];
|
|
421
|
+
}
|
|
422
|
+
},
|
|
423
|
+
handleOrgTagClear() {
|
|
424
|
+
this.selectedOrgTagKey = '';
|
|
425
|
+
// 重置所有标签的选中状态
|
|
426
|
+
this.orgTagList.forEach(tag => {
|
|
427
|
+
tag.checked = false;
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
// 3. 清空树选择状态和暂存列表
|
|
431
|
+
if (this.$refs.orgTree && this.orgSearchList) {
|
|
432
|
+
this.$refs.orgTree.initData();
|
|
433
|
+
}
|
|
434
|
+
// 4. 可选:添加清空提示
|
|
435
|
+
this.$Message.info("已清空快捷标签选择");
|
|
436
|
+
},
|
|
437
|
+
// 修正清空逻辑方法(与事件名称对应)
|
|
438
|
+
handlePostTagClear() {
|
|
439
|
+
// 1. 重置选中的标签key
|
|
440
|
+
this.selectedPostTagKey = '';
|
|
441
|
+
|
|
442
|
+
// 2. 重置所有标签的选中状态
|
|
443
|
+
this.postTagList.forEach(tag => {
|
|
444
|
+
tag.checked = false;
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
// 3. 清空树选择状态和暂存列表
|
|
448
|
+
if (this.$refs.postTree) {
|
|
449
|
+
this.$refs.postTree.initData();
|
|
450
|
+
this.proPostList = [];
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// 4. 可选:添加清空提示
|
|
454
|
+
this.$Message.info("已清空快捷标签选择");
|
|
455
|
+
},
|
|
456
|
+
handlePostSearchClear() {
|
|
457
|
+
// 清空搜索框绑定的值
|
|
458
|
+
this.postSearch = '';
|
|
459
|
+
|
|
460
|
+
// 清空搜索结果列表
|
|
461
|
+
this.postSearchList = [];
|
|
462
|
+
|
|
463
|
+
// 重置树组件状态(与原有逻辑保持一致)
|
|
464
|
+
if (this.$refs.postTree) {
|
|
465
|
+
this.$refs.postTree.initData();
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
// 清空暂存列表
|
|
469
|
+
this.proPostList = [];
|
|
470
|
+
|
|
471
|
+
// 可选:添加清空提示
|
|
472
|
+
this.$Message.info("已清空组织选择搜索");
|
|
473
|
+
},
|
|
188
474
|
queryPositionList(){
|
|
189
475
|
ajax.get('/pub-manage-server/pub/personHelpBox/q/queryPositionList').then((res)=>{
|
|
190
476
|
if(res.data.code === 1){
|
|
@@ -194,38 +480,409 @@ export default {
|
|
|
194
480
|
}
|
|
195
481
|
})
|
|
196
482
|
},
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
483
|
+
getOrgListBySearch(query){
|
|
484
|
+
if (query !== '') {
|
|
485
|
+
this.loadingOrg = true;
|
|
486
|
+
this.getOrgUnitBySearchTerm(query,(res)=>{
|
|
487
|
+
this.loadingOrg = false
|
|
488
|
+
if(res.data.code === 1){
|
|
489
|
+
let resp = res.data.data?.items??[]
|
|
490
|
+
this.orgSearchList = resp
|
|
491
|
+
}else{
|
|
492
|
+
this.orgSearchList = []
|
|
493
|
+
this.$Message.error("获取组织节点列表失败!")
|
|
494
|
+
}
|
|
495
|
+
})
|
|
496
|
+
}else{
|
|
497
|
+
this.orgSearchList = [];
|
|
498
|
+
}
|
|
499
|
+
},
|
|
500
|
+
getPostListBySearch(query) {
|
|
501
|
+
if (query !== '') {
|
|
502
|
+
this.loadingPost = true;
|
|
503
|
+
this.getOrgUnitBySearchTerm(query, (res) => {
|
|
504
|
+
this.loadingPost = false;
|
|
505
|
+
if (res.data.code === 1) {
|
|
506
|
+
let resp = res.data.data?.items ?? [];
|
|
507
|
+
// 修复:岗位搜索结果深拷贝,避免引用污染
|
|
508
|
+
this.postSearchList = this.safeDeepCopy(resp);
|
|
509
|
+
} else {
|
|
510
|
+
this.postSearchList = [];
|
|
511
|
+
this.$Message.error("获取组织节点列表失败!");
|
|
512
|
+
}
|
|
513
|
+
});
|
|
514
|
+
} else {
|
|
515
|
+
// 修复:清空搜索时,同时清空树数据和暂存列表(与组织Tab一致)
|
|
516
|
+
this.postSearchList = [];
|
|
517
|
+
if (this.$refs.postTree) {
|
|
518
|
+
this.$refs.postTree.initData();
|
|
203
519
|
}
|
|
204
|
-
|
|
520
|
+
this.proPostList = []; // 清空岗位暂存列表
|
|
521
|
+
this.$set(this, 'postTree', []); // 清空岗位树数据
|
|
522
|
+
}
|
|
523
|
+
},
|
|
524
|
+
getOrgUnitBySearchTerm(query,callback){
|
|
525
|
+
ajax.get('/pub-manage-server/pub/personHelpBox/q/getOrgUnitBySearchTerm?searchTerm='+query).then((res)=>{callback(res)})
|
|
526
|
+
},
|
|
527
|
+
async getOrgOption(val) {
|
|
528
|
+
this.selectedOrgTagKey = '';
|
|
529
|
+
this.orgTagList.forEach(tag => {
|
|
530
|
+
tag.checked = false;
|
|
531
|
+
});
|
|
532
|
+
this.proOrgList = [];
|
|
533
|
+
if(!val) return this.$refs.orgTree.initData();
|
|
534
|
+
let item = this.orgSearchList.filter((item)=> item.orgUnitId === val).shift();
|
|
535
|
+
if (!item) return;
|
|
536
|
+
|
|
537
|
+
const leafNode = await this.judgeNodeLeafe(item.orgUnitId);
|
|
538
|
+
const ftem = this.safeDeepCopy({
|
|
539
|
+
...item,
|
|
540
|
+
orgNodeName: item.name,
|
|
541
|
+
parentOrgUnitId: item.parentId,
|
|
542
|
+
leafNode: leafNode
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
try{
|
|
546
|
+
let parentsList = await this.getParentOrgNodesByOrgUnitId(val);
|
|
547
|
+
// 对父节点列表进行安全拷贝
|
|
548
|
+
const safeParents = this.safeDeepCopy(parentsList);
|
|
549
|
+
let tree = this.buildTree([...safeParents, ftem]);
|
|
550
|
+
this.orgTree = this.safeDeepCopy(tree);
|
|
551
|
+
}catch(e){
|
|
552
|
+
this.$Message.error("获取组织节点列表失败!");
|
|
553
|
+
}
|
|
554
|
+
},
|
|
555
|
+
async getPostOption(val) {
|
|
556
|
+
// 1. 重置选中的标签key
|
|
557
|
+
this.selectedPostTagKey = '';
|
|
558
|
+
|
|
559
|
+
// 2. 重置所有标签的选中状态
|
|
560
|
+
this.postTagList.forEach(tag => {
|
|
561
|
+
tag.checked = false;
|
|
562
|
+
});
|
|
563
|
+
if (!val) {
|
|
564
|
+
// 修复:岗位树清空时,同时清空暂存列表和搜索框
|
|
565
|
+
if (this.$refs.postTree) {
|
|
566
|
+
this.$refs.postTree.initData();
|
|
567
|
+
}
|
|
568
|
+
this.proPostList = []; // 清空岗位暂存列表(与组织Tab保持一致)
|
|
569
|
+
this.postSearch = ''; // 清空搜索框
|
|
570
|
+
return;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
let item = this.postSearchList.filter(item => item.orgUnitId === val).shift();
|
|
574
|
+
if (!item) return;
|
|
575
|
+
|
|
576
|
+
const leafNode = await this.judgeNodeLeafe(item.orgUnitId);
|
|
577
|
+
// 修复:岗位节点深拷贝,避免引用污染
|
|
578
|
+
const ftem = this.safeDeepCopy({
|
|
579
|
+
...item,
|
|
580
|
+
orgNodeName: item.name || `未命名组织(${item.orgUnitId})`,
|
|
581
|
+
parentOrgUnitId: item.parentId,
|
|
582
|
+
leafNode: leafNode
|
|
583
|
+
});
|
|
584
|
+
|
|
585
|
+
try {
|
|
586
|
+
let parentsList = await this.getParentOrgNodesByOrgUnitId(val);
|
|
587
|
+
const safeParents = this.safeDeepCopy(parentsList);
|
|
588
|
+
let tree = this.buildTree([...safeParents, ftem]);
|
|
589
|
+
// 修复:用$set确保岗位树数据响应式更新
|
|
590
|
+
this.$set(this, 'postTree', this.safeDeepCopy(tree));
|
|
591
|
+
|
|
592
|
+
// 修复:设置节点展开和选中(与组织Tab逻辑一致)
|
|
593
|
+
this.$nextTick(() => {
|
|
594
|
+
if (this.$refs.postTree && this.$refs.postTree.setCheckedNodes) {
|
|
595
|
+
this.$refs.postTree.setCheckedNodes([val]); // 选中当前节点
|
|
596
|
+
this.proPostList = [ftem]; // 同步暂存列表
|
|
597
|
+
}
|
|
598
|
+
});
|
|
599
|
+
} catch (e) {
|
|
600
|
+
this.$Message.error("获取组织节点列表失败!");
|
|
601
|
+
}
|
|
205
602
|
},
|
|
206
|
-
|
|
207
|
-
this.
|
|
603
|
+
async getStaffOption(val) {
|
|
604
|
+
this.staffOrgList = [];
|
|
605
|
+
if(!val) return this.$refs.staffTree.initData();
|
|
606
|
+
let item = this.staffSearchList.filter((item)=> item.orgUnitId === val).shift();
|
|
607
|
+
if (!item) return;
|
|
608
|
+
|
|
609
|
+
const leafNode = await this.judgeNodeLeafe(item.orgUnitId);
|
|
610
|
+
const ftem = this.safeDeepCopy({
|
|
611
|
+
...item,
|
|
612
|
+
orgNodeName: item.name,
|
|
613
|
+
parentOrgUnitId: item.parentId,
|
|
614
|
+
leafNode: leafNode
|
|
615
|
+
});
|
|
616
|
+
|
|
617
|
+
try{
|
|
618
|
+
let parentsList = await this.getParentOrgNodesByOrgUnitId(val);
|
|
619
|
+
// 对父节点列表进行安全拷贝
|
|
620
|
+
const safeParents = this.safeDeepCopy(parentsList);
|
|
621
|
+
let tree = this.buildTree([...safeParents, ftem]);
|
|
622
|
+
this.staffTree = this.safeDeepCopy(tree);
|
|
623
|
+
}catch(e){
|
|
624
|
+
this.$Message.error("获取组织节点列表失败!");
|
|
625
|
+
}
|
|
208
626
|
},
|
|
209
|
-
|
|
210
|
-
|
|
627
|
+
getParentOrgNodesByOrgUnitId(val){
|
|
628
|
+
return new Promise((resolve,reject)=>{
|
|
629
|
+
ajax.get('/pub-manage-server/pub/personHelpBox/q/getParentOrgNodesByOrgUnitId?orgUnitId='+val).then((res)=>{
|
|
630
|
+
if(res.data.code === 1){
|
|
631
|
+
let parentsList = res.data?.data?.items??[]
|
|
632
|
+
resolve(parentsList)
|
|
633
|
+
}else{
|
|
634
|
+
reject(false)
|
|
635
|
+
}
|
|
636
|
+
})
|
|
637
|
+
})
|
|
211
638
|
},
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
639
|
+
judgeNodeLeafe(orgUnitId){
|
|
640
|
+
return new Promise((resolve,reject)=>{
|
|
641
|
+
ajax.get('/pub-manage-server/pub/personHelpBox/q/getOrgUnitList', { params:{
|
|
642
|
+
containsCurLevel:true,
|
|
643
|
+
orgUnitId:orgUnitId,
|
|
644
|
+
}
|
|
645
|
+
}).then((res)=>{
|
|
646
|
+
if(res.data.code === 1){
|
|
647
|
+
let treeList = res.data.data
|
|
648
|
+
if(treeList && treeList.length){
|
|
649
|
+
resolve(false)
|
|
650
|
+
}else{
|
|
651
|
+
resolve(true)
|
|
652
|
+
}
|
|
653
|
+
}else{
|
|
654
|
+
resolve(false)
|
|
655
|
+
}
|
|
656
|
+
})
|
|
219
657
|
})
|
|
220
|
-
|
|
658
|
+
},
|
|
659
|
+
buildTree(items) {
|
|
660
|
+
const map = {};
|
|
661
|
+
const roots = [];
|
|
662
|
+
const copiedItems = this.safeDeepCopy(items);
|
|
663
|
+
|
|
664
|
+
copiedItems.forEach(item => {
|
|
665
|
+
if (!item.orgUnitId) return;
|
|
666
|
+
map[item.orgUnitId] = this.safeDeepCopy({
|
|
667
|
+
...item,
|
|
668
|
+
orgChildrenList: [],
|
|
669
|
+
children: [], // 强制初始化 children 空数组
|
|
670
|
+
title: item.orgUnitName || item.orgNodeName || item.name || `未命名组织(${item.orgUnitId || ''})`
|
|
671
|
+
});
|
|
672
|
+
});
|
|
673
|
+
|
|
674
|
+
copiedItems.forEach(item => {
|
|
675
|
+
if (!item.orgUnitId || !map[item.orgUnitId]) return;
|
|
676
|
+
|
|
677
|
+
const node = map[item.orgUnitId];
|
|
678
|
+
if (!item.parentOrgUnitId || !map[item.parentOrgUnitId]) {
|
|
679
|
+
roots.push(node);
|
|
680
|
+
} else {
|
|
681
|
+
const parent = map[item.parentOrgUnitId];
|
|
682
|
+
parent.orgChildrenList.push(node);
|
|
683
|
+
parent.children.push(node); // 同步 children 字段
|
|
684
|
+
parent.leafNode = false;
|
|
685
|
+
parent.expand = true;
|
|
686
|
+
}
|
|
687
|
+
});
|
|
688
|
+
return roots;
|
|
689
|
+
},
|
|
690
|
+
|
|
691
|
+
searchStaff(){
|
|
692
|
+
this.staffEnding = false;
|
|
693
|
+
this.offset = 0;
|
|
694
|
+
this.staffAllList = [];
|
|
695
|
+
// 关键修复:50ms延迟,解决极端情况下的异步更新问题
|
|
696
|
+
setTimeout(() => {
|
|
697
|
+
this.loadMore();
|
|
698
|
+
}, 50);
|
|
699
|
+
},
|
|
700
|
+
queryAllStaffList() {
|
|
701
|
+
const params = {
|
|
702
|
+
search: this.staffSearch,
|
|
703
|
+
offset: this.offset,
|
|
704
|
+
limit: 10
|
|
705
|
+
};
|
|
706
|
+
|
|
707
|
+
if (this.selectedStaffOrgId && typeof this.selectedStaffOrgId === 'string' && this.selectedStaffOrgId.trim()) {
|
|
708
|
+
params.orgUnitId = this.selectedStaffOrgId.trim();
|
|
709
|
+
} else if (this.initialDefaultOrgUnitId && this.initialDefaultOrgUnitId.trim()) {
|
|
710
|
+
// 初始化及未选中节点时,使用传入的defaultOrgUnitId
|
|
711
|
+
params.orgUnitId = this.initialDefaultOrgUnitId.trim();
|
|
712
|
+
} else {
|
|
713
|
+
params.orgUnitId = '';
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
console.log('人员查询接口参数:', params);
|
|
717
|
+
|
|
718
|
+
return new Promise((resolve, reject) => {
|
|
719
|
+
ajax.get('/pub-manage-server/pub/personHelpBox/q/queryAllStaffList', {
|
|
720
|
+
params: params
|
|
721
|
+
}).then((res) => {
|
|
722
|
+
if (res.data.code === 1) {
|
|
723
|
+
resolve(res.data.data);
|
|
724
|
+
} else {
|
|
725
|
+
reject(false);
|
|
726
|
+
}
|
|
727
|
+
}).catch((err) => {
|
|
728
|
+
reject(err);
|
|
729
|
+
});
|
|
730
|
+
});
|
|
731
|
+
},
|
|
732
|
+
handleScroll(e){
|
|
733
|
+
const { scrollTop, clientHeight, scrollHeight } = e.target;
|
|
734
|
+
if (scrollHeight - (scrollTop + clientHeight) < 50) {
|
|
735
|
+
this.loadMore();
|
|
736
|
+
}
|
|
737
|
+
},
|
|
738
|
+
async loadMore(){
|
|
739
|
+
if (this.loadingStaff || this.staffEnding) return
|
|
740
|
+
this.loadingStaff = true
|
|
741
|
+
try {
|
|
742
|
+
console.log("--触底加载/强制加载---", new Date().getTime());
|
|
743
|
+
let res = await this.queryAllStaffList()
|
|
744
|
+
let list = res.rows;
|
|
745
|
+
// 移除这行:list.map((item)=>item.checked=false)
|
|
746
|
+
this.staffAllList = this.staffAllList.concat(list)
|
|
747
|
+
this.offset += 10;
|
|
748
|
+
this.loadingStaff = false
|
|
749
|
+
this.lastLoadingTime = Date.now()
|
|
750
|
+
if(res.total===this.staffAllList.length){
|
|
751
|
+
this.staffEnding = true
|
|
752
|
+
}
|
|
753
|
+
}catch (e){
|
|
754
|
+
this.loadingStaff = false
|
|
755
|
+
this.lastLoadingTime = Date.now()
|
|
756
|
+
console.log(e)
|
|
757
|
+
}
|
|
758
|
+
},
|
|
759
|
+
getOrgList(data) {
|
|
760
|
+
const validNodes = Array.isArray(data)
|
|
761
|
+
? data.filter(node => node.orgUnitId)
|
|
762
|
+
: [];
|
|
763
|
+
|
|
764
|
+
// 去重:基于orgUnitId避免重复
|
|
765
|
+
const uniqueNodes = validNodes.filter((node, index, self) =>
|
|
766
|
+
self.findIndex(item => item.orgUnitId === node.orgUnitId) === index
|
|
767
|
+
);
|
|
768
|
+
|
|
769
|
+
|
|
770
|
+
const completeNodes = uniqueNodes.map(node => ({
|
|
771
|
+
...node,
|
|
772
|
+
orgNodeName: node.orgNodeName || node.name || `未命名组织(${node.orgUnitId})`,
|
|
773
|
+
orgUnitName: node.orgNodeName || node.name || `未命名组织(${node.orgUnitId})`
|
|
774
|
+
}));
|
|
775
|
+
|
|
776
|
+
this.proOrgList = this.safeDeepCopy(completeNodes);
|
|
777
|
+
},
|
|
778
|
+
|
|
779
|
+
getPostList(data) {
|
|
780
|
+
// 过滤有效节点:仅要求orgUnitId
|
|
781
|
+
const validNodes = Array.isArray(data)
|
|
782
|
+
? data.filter(node => node.orgUnitId)
|
|
783
|
+
: [];
|
|
784
|
+
|
|
785
|
+
// 去重:基于orgUnitId
|
|
786
|
+
const uniqueNodes = validNodes.filter((node, index, self) =>
|
|
787
|
+
self.findIndex(item => item.orgUnitId === node.orgUnitId) === index
|
|
788
|
+
);
|
|
789
|
+
|
|
790
|
+
// 补全缺失字段
|
|
791
|
+
const completeNodes = uniqueNodes.map(node => ({
|
|
792
|
+
...node,
|
|
793
|
+
orgNodeName: node.orgNodeName || node.name || `未命名组织(${node.orgUnitId})`,
|
|
794
|
+
orgUnitName: node.orgNodeName || node.name || `未命名组织(${node.orgUnitId})`
|
|
795
|
+
}));
|
|
796
|
+
|
|
797
|
+
// 覆盖暂存列表(而非concat,避免累积无效数据)
|
|
798
|
+
this.proPostList = this.safeDeepCopy(completeNodes);
|
|
799
|
+
},
|
|
800
|
+
getStaffList(data) {
|
|
801
|
+
if (!Array.isArray(data) || data.length === 0) {
|
|
802
|
+
this.proStaffOrgList = [];
|
|
803
|
+
// 强制清空并触发响应式更新
|
|
804
|
+
this.$set(this, 'selectedStaffOrgId', '');
|
|
805
|
+
// 立即触发搜索,确保orgUnitId参数实时更新为空
|
|
806
|
+
this.$nextTick(() => this.searchStaff());
|
|
807
|
+
return;
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
// 关键修复1:过滤仅含有效orgUnitId的节点,排除无效数据
|
|
811
|
+
const validNodes = data.filter(node =>
|
|
812
|
+
node.orgUnitId && typeof node.orgUnitId === 'string' // 确保orgUnitId存在且为字符串
|
|
813
|
+
);
|
|
814
|
+
|
|
815
|
+
if (validNodes.length === 0) {
|
|
816
|
+
this.$Message.warning("所选节点无效,请重新选择");
|
|
817
|
+
this.proStaffOrgList = [];
|
|
818
|
+
this.$set(this, 'selectedStaffOrgId', '');
|
|
819
|
+
// 立即触发搜索,更新参数为空
|
|
820
|
+
this.$nextTick(() => this.searchStaff());
|
|
821
|
+
return;
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
// 关键修复2:单选逻辑强化,仅保留最后一个有效选中节点
|
|
825
|
+
const currentNode = validNodes[validNodes.length - 1];
|
|
826
|
+
const currentOrgUnitId = currentNode.orgUnitId.trim(); // 去除空格,避免无效字符串
|
|
827
|
+
|
|
828
|
+
// 补全节点字段,确保orgUnitId绝对存在
|
|
829
|
+
const pureNode = this.safeDeepCopy({
|
|
830
|
+
...currentNode,
|
|
831
|
+
orgNodeName: currentNode.orgNodeName || currentNode.name || `未命名组织(${currentOrgUnitId})`,
|
|
832
|
+
orgUnitName: currentNode.orgNodeName || currentNode.name || `未命名组织(${currentOrgUnitId})`
|
|
833
|
+
});
|
|
834
|
+
|
|
835
|
+
// 清除子节点引用,避免循环引用导致的更新延迟
|
|
836
|
+
if (pureNode.orgChildrenList) pureNode.orgChildrenList = [];
|
|
837
|
+
if (pureNode.children) pureNode.children = [];
|
|
838
|
+
|
|
839
|
+
// 关键修复3:强制响应式更新,避免Vue数据延迟
|
|
840
|
+
this.$set(this, 'proStaffOrgList', [pureNode]);
|
|
841
|
+
this.$set(this, 'selectedStaffOrgId', currentOrgUnitId);
|
|
842
|
+
|
|
843
|
+
// 关键修复4:双重nextTick确保数据完全更新后再查询
|
|
844
|
+
this.$nextTick(() => {
|
|
845
|
+
if (this.selectedStaffOrgId !== currentOrgUnitId) {
|
|
846
|
+
this.$set(this, 'selectedStaffOrgId', currentOrgUnitId);
|
|
847
|
+
this.$nextTick(() => this.searchStaff());
|
|
848
|
+
} else {
|
|
849
|
+
this.searchStaff();
|
|
850
|
+
}
|
|
851
|
+
console.log('人员选择-当前选中orgUnitId:', this.selectedStaffOrgId); // 调试日志
|
|
852
|
+
});
|
|
853
|
+
},
|
|
854
|
+
|
|
855
|
+
addOrgList() {
|
|
856
|
+
// 过滤空节点(仅校验orgUnitId)
|
|
857
|
+
const validOrgList = this.proOrgList.filter(node => node.orgUnitId);
|
|
858
|
+
if (!validOrgList.length) return this.$Message.error("请先选择组织节点!");
|
|
859
|
+
|
|
860
|
+
let proOrgList = deepCopy(validOrgList);
|
|
861
|
+
proOrgList.forEach(item => {
|
|
862
|
+
// 用补全后的orgNodeName,避免空显示
|
|
863
|
+
item.title = this.includeLevelOrg.includes('01')
|
|
864
|
+
? `${item.orgNodeName}(包含下级组织节点)`
|
|
865
|
+
: item.orgNodeName;
|
|
866
|
+
item.id = this.includeLevelOrg.includes('01')
|
|
867
|
+
? (`01-${item.orgUnitId}`)
|
|
868
|
+
: (`00-${item.orgUnitId}`);
|
|
869
|
+
item.includeLevel = this.includeLevelOrg.includes('01');
|
|
870
|
+
});
|
|
871
|
+
|
|
872
|
+
// 去重合并
|
|
873
|
+
let list = this.orgList.concat(proOrgList);
|
|
221
874
|
let uniqueArray = list.filter((item, index, self) =>
|
|
222
|
-
index === self.findIndex(t =>
|
|
223
|
-
t.id === item.id // 基于id属性去重
|
|
224
|
-
))
|
|
875
|
+
index === self.findIndex(t => t.id === item.id)
|
|
225
876
|
);
|
|
226
|
-
this.orgList = uniqueArray
|
|
227
|
-
|
|
228
|
-
|
|
877
|
+
this.orgList = uniqueArray;
|
|
878
|
+
|
|
879
|
+
// 清空选中状态
|
|
880
|
+
if (this.$refs.orgTree && this.$refs.orgTree.clearAllChecked) {
|
|
881
|
+
this.$refs.orgTree.clearAllChecked(this.$refs.orgTree.data);
|
|
882
|
+
this.$refs.orgTree.$emit('handleChange', []);
|
|
883
|
+
}
|
|
884
|
+
this.$refs.orgTree.upDataTree();
|
|
885
|
+
this.proOrgList = [];
|
|
229
886
|
},
|
|
230
887
|
clearGroup(){
|
|
231
888
|
this.orgList = []
|
|
@@ -235,36 +892,47 @@ export default {
|
|
|
235
892
|
},
|
|
236
893
|
//岗位
|
|
237
894
|
getPosionId(item){
|
|
238
|
-
item.checked = !item.checked;
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
if(!
|
|
245
|
-
|
|
246
|
-
let
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
895
|
+
// item.checked = !item.checked;
|
|
896
|
+
this.selectedPositionId = item.positionId
|
|
897
|
+
},
|
|
898
|
+
addPostList() {
|
|
899
|
+
// 过滤空节点
|
|
900
|
+
const validPostList = this.proPostList.filter(node => node.orgUnitId);
|
|
901
|
+
if (!validPostList.length) return this.$Message.error("请选择组织节点!");
|
|
902
|
+
|
|
903
|
+
let checkedPosition = this.positiontList.find(item => item.positionId === this.selectedPositionId);
|
|
904
|
+
if (!checkedPosition) { return this.$Message.error("请选择岗位!"); }
|
|
905
|
+
|
|
906
|
+
let totalList = [];
|
|
907
|
+
validPostList.forEach(item => {
|
|
908
|
+
totalList.push({
|
|
909
|
+
...item,
|
|
910
|
+
...checkedPosition,
|
|
911
|
+
title: `${this.includeLevelPost.length ? (item.orgNodeName + '(包含下级组织节点)') : item.orgNodeName}`,
|
|
912
|
+
includeLevel: this.includeLevelPost.includes('01'),
|
|
913
|
+
id: this.includeLevelPost.includes('01')
|
|
914
|
+
? (`01-${checkedPosition.positionId}-${item.orgUnitId}`)
|
|
915
|
+
: (`00-${checkedPosition.positionId}-${item.orgUnitId}`),
|
|
916
|
+
});
|
|
917
|
+
});
|
|
918
|
+
|
|
919
|
+
// 去重合并
|
|
920
|
+
let list = this.postList.concat(totalList);
|
|
259
921
|
let uniqueArray = list.filter((item, index, self) =>
|
|
260
|
-
index === self.findIndex(t =>
|
|
261
|
-
t.id === item.id // 基于id属性去重
|
|
262
|
-
))
|
|
922
|
+
index === self.findIndex(t => t.id === item.id)
|
|
263
923
|
);
|
|
264
|
-
this.postList = uniqueArray
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
this.
|
|
924
|
+
this.postList = uniqueArray;
|
|
925
|
+
|
|
926
|
+
// 清空选中状态
|
|
927
|
+
if (this.$refs.postTree && this.$refs.postTree.clearAllChecked) {
|
|
928
|
+
this.$refs.postTree.clearAllChecked(this.$refs.postTree.data);
|
|
929
|
+
this.$refs.postTree.$emit('handleChange', []);
|
|
930
|
+
}
|
|
931
|
+
this.$refs.postTree.upDataTree();
|
|
932
|
+
this.proPostList = [];
|
|
933
|
+
this.selectedPositionId = null;
|
|
934
|
+
// this.$refs.postTree.initData();
|
|
935
|
+
this.selectedPostTagKey = '';
|
|
268
936
|
},
|
|
269
937
|
clearPost(){
|
|
270
938
|
this.postList= []
|
|
@@ -273,19 +941,50 @@ export default {
|
|
|
273
941
|
this.postList.splice(index,1)
|
|
274
942
|
},
|
|
275
943
|
//staff
|
|
276
|
-
addStaffList(){
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
944
|
+
// addStaffList(){
|
|
945
|
+
// console.log("this.staffSingle", this.staffSingle)
|
|
946
|
+
// let staffList = this.staffAllList.filter((item)=>item.checked===true);
|
|
947
|
+
//
|
|
948
|
+
// if (!staffList.length) {
|
|
949
|
+
// this.$Message.error("请选择人员");
|
|
950
|
+
// return;
|
|
951
|
+
// }
|
|
952
|
+
// if (this.staffSingle && this.staffList.length >= 1) {
|
|
953
|
+
// this.$Message.error("请先清除已选人员,再重新添加");
|
|
954
|
+
// return;
|
|
955
|
+
// }
|
|
956
|
+
//
|
|
957
|
+
// if(this.staffSingle && staffList.length > 1){
|
|
958
|
+
// this.$Message.error("温馨提示:当前业务暂时只支持选择一位人员");
|
|
959
|
+
// return;
|
|
960
|
+
// }
|
|
961
|
+
//
|
|
962
|
+
// // 基于item.id去重,不修改原数据字段,仅过滤重复项
|
|
963
|
+
// let uniqueStaffList = staffList.filter(newItem =>
|
|
964
|
+
// // 检查右侧条件区域(staffList)是否已有该人员,避免重复添加
|
|
965
|
+
// !this.staffList.some(existItem => existItem.userId === newItem.userId)
|
|
966
|
+
// );
|
|
967
|
+
// // 合并去重后的列表
|
|
968
|
+
// this.staffList = this.staffList.concat(uniqueStaffList);
|
|
969
|
+
// // 清空选中状态
|
|
970
|
+
// this.staffAllList.forEach(item => item.checked = false);
|
|
971
|
+
// },
|
|
287
972
|
handlestaff(item){
|
|
288
|
-
|
|
973
|
+
// 处理单选逻辑
|
|
974
|
+
if (this.staffSingle) {
|
|
975
|
+
// 单选时先清空已选人员
|
|
976
|
+
this.staffList = [];
|
|
977
|
+
}
|
|
978
|
+
// 去重校验:避免重复添加
|
|
979
|
+
const isExist = this.staffList.some(existItem => existItem.userId === item.userId);
|
|
980
|
+
if (!isExist) {
|
|
981
|
+
// 深拷贝防止原数据引用污染
|
|
982
|
+
const newItem = this.safeDeepCopy(item);
|
|
983
|
+
this.staffList.push(newItem);
|
|
984
|
+
this.$Message.success(`已添加【${item.name}】`);
|
|
985
|
+
} else {
|
|
986
|
+
this.$Message.warning(`【${item.name}】已在选择列表中`);
|
|
987
|
+
}
|
|
289
988
|
},
|
|
290
989
|
clearStaff(){
|
|
291
990
|
this.staffList = []
|
|
@@ -294,20 +993,613 @@ export default {
|
|
|
294
993
|
this.staffList.splice(index,1)
|
|
295
994
|
},
|
|
296
995
|
confirm(){
|
|
297
|
-
|
|
996
|
+
const v = {
|
|
298
997
|
orgList:this.orgList,
|
|
299
998
|
postList:this.postList,
|
|
300
999
|
staffList:this.staffList
|
|
301
|
-
}
|
|
1000
|
+
}
|
|
1001
|
+
this.$emit('confirm',deepCopy(v))
|
|
1002
|
+
},
|
|
1003
|
+
visibleChange(val) {
|
|
1004
|
+
this.$emit('input', val);
|
|
1005
|
+
if (val) {
|
|
1006
|
+
this.resetStaffTreeChecked();
|
|
1007
|
+
this.staffEnding = false;
|
|
1008
|
+
this.offset = 0;
|
|
1009
|
+
this.staffAllList = [];
|
|
1010
|
+
this.loadingStaff = false;
|
|
1011
|
+
if (this.tabName === 'staff') {
|
|
1012
|
+
this.loadMore().catch(err => console.log("弹窗打开加载失败:", err));
|
|
1013
|
+
this.$nextTick(() => {
|
|
1014
|
+
setTimeout(() => {
|
|
1015
|
+
this.loadMore();
|
|
1016
|
+
}, 100);
|
|
1017
|
+
});
|
|
1018
|
+
}
|
|
1019
|
+
} else {
|
|
1020
|
+
this.staffEnding = false;
|
|
1021
|
+
this.offset = 0;
|
|
1022
|
+
this.staffAllList = [];
|
|
1023
|
+
this.$set(this, 'selectedStaffOrgId', '');
|
|
1024
|
+
if (this.$refs.staffTree) {
|
|
1025
|
+
this.$refs.staffTree.clearAllChecked(this.$refs.staffTree.data);
|
|
1026
|
+
this.$refs.staffTree.$emit('handleChange', []);
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
},
|
|
1030
|
+
resetStaffTreeChecked() {
|
|
1031
|
+
this.$set(this, 'selectedStaffOrgId', '');
|
|
1032
|
+
this.proStaffOrgList = [];
|
|
1033
|
+
if (this.$refs.staffTree) {
|
|
1034
|
+
this.$refs.staffTree.clearAllChecked(this.$refs.staffTree.data);
|
|
1035
|
+
this.$refs.staffTree.$emit('handleChange', []);
|
|
1036
|
+
}
|
|
1037
|
+
if (this.tabName === 'staff') {
|
|
1038
|
+
this.$nextTick(() => {
|
|
1039
|
+
this.loadMore();
|
|
1040
|
+
});
|
|
1041
|
+
}
|
|
1042
|
+
},
|
|
1043
|
+
|
|
1044
|
+
handleTabChange(tabName) {
|
|
1045
|
+
this.tabName = tabName;
|
|
1046
|
+
|
|
1047
|
+
if (tabName === 'staff') {
|
|
1048
|
+
this.resetStaffTreeChecked();
|
|
1049
|
+
this.staffEnding = false;
|
|
1050
|
+
this.offset = 0;
|
|
1051
|
+
this.staffAllList = [];
|
|
1052
|
+
this.loadingStaff = false;
|
|
1053
|
+
this.loadMore().catch(err => console.log("同步加载失败:", err));
|
|
1054
|
+
this.$nextTick(() => {
|
|
1055
|
+
setTimeout(() => {
|
|
1056
|
+
this.loadMore();
|
|
1057
|
+
}, 100);
|
|
1058
|
+
});
|
|
1059
|
+
} else if (tabName === 'post' && this.$refs.postTree && this.proPostList.length === 0) {
|
|
1060
|
+
this.proPostList = [];
|
|
1061
|
+
this.$refs.postTree.initData();
|
|
1062
|
+
}
|
|
1063
|
+
},
|
|
1064
|
+
initStaffList() {
|
|
1065
|
+
this.staffEnding = false;
|
|
1066
|
+
this.offset = 0;
|
|
1067
|
+
this.staffAllList = [];
|
|
1068
|
+
// 小幅延迟,确保树重置完成后再发起查询(避免时序差)
|
|
1069
|
+
this.$nextTick(() => {
|
|
1070
|
+
setTimeout(() => {
|
|
1071
|
+
this.loadMore();
|
|
1072
|
+
}, 50); // 50ms足够,可根据实际情况调整
|
|
1073
|
+
});
|
|
1074
|
+
},
|
|
1075
|
+
async fastChedkOrg(item) {
|
|
1076
|
+
// 1. 改用组织 Tab 专属标签列表判断
|
|
1077
|
+
if (!this.orgTagList.length) {
|
|
1078
|
+
this.$Message.warning("快捷选择标签正在加载中,请稍后");
|
|
1079
|
+
return;
|
|
1080
|
+
}
|
|
1081
|
+
const treeRef = this.$refs.orgTree;
|
|
1082
|
+
const proListKey = 'proOrgList';
|
|
1083
|
+
const treeDataKey = 'orgTree';
|
|
1084
|
+
this[proListKey] = [];
|
|
1085
|
+
if (treeRef) await treeRef.initData();
|
|
1086
|
+
if (!treeRef) {
|
|
1087
|
+
this.$Message.error("组织树组件未初始化,请稍后再试");
|
|
1088
|
+
item.checked = !item.checked;
|
|
1089
|
+
return;
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
// 2. 清空组织 Tab 标签选中状态(仅操作 orgTagList)
|
|
1093
|
+
this.orgTagList.forEach(tag => {
|
|
1094
|
+
tag.checked = false;
|
|
1095
|
+
});
|
|
1096
|
+
|
|
1097
|
+
// 3. 后续逻辑保持不变,仅操作当前 item(属于 orgTagList)
|
|
1098
|
+
const isCurrentlyChecked = item.checked;
|
|
1099
|
+
if (!isCurrentlyChecked) {
|
|
1100
|
+
item.checked = true;
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
if (!item.checked) {
|
|
1104
|
+
this.$Message.info("已取消该快捷选择");
|
|
1105
|
+
return;
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
try {
|
|
1109
|
+
await this.querySpecificParam(item, true, treeRef, proListKey, treeDataKey);
|
|
1110
|
+
} catch (error) {
|
|
1111
|
+
this.$Message.error(`快捷选择处理失败:${error.message.slice(0, 50)}`);
|
|
1112
|
+
item.checked = !item.checked;
|
|
1113
|
+
}
|
|
1114
|
+
},
|
|
1115
|
+
async fastChedkPost(item) {
|
|
1116
|
+
// 1. 改用岗位 Tab 专属标签列表判断
|
|
1117
|
+
if (!this.postTagList.length) {
|
|
1118
|
+
this.$Message.warning("快捷选择标签正在加载中,请稍后");
|
|
1119
|
+
return;
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
const isOrgTab = this.tabName === 'org';
|
|
1123
|
+
const treeRef = isOrgTab ? this.$refs.orgTree : this.$refs.postTree;
|
|
1124
|
+
const proListKey = isOrgTab ? 'proOrgList' : 'proPostList';
|
|
1125
|
+
const treeDataKey = isOrgTab ? 'orgTree' : 'postTree';
|
|
1126
|
+
|
|
1127
|
+
this[proListKey] = [];
|
|
1128
|
+
const isCurrentlyChecked = item.checked;
|
|
1129
|
+
if (treeRef) await treeRef.initData();
|
|
1130
|
+
|
|
1131
|
+
// 2. 清空岗位 Tab 标签选中状态(仅操作 postTagList)
|
|
1132
|
+
this.postTagList.forEach(tag => {
|
|
1133
|
+
tag.checked = false;
|
|
1134
|
+
});
|
|
1135
|
+
|
|
1136
|
+
// 3. 后续逻辑保持不变,仅操作当前 item(属于 postTagList)
|
|
1137
|
+
if (!isCurrentlyChecked) {
|
|
1138
|
+
item.checked = true;
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
if (!item.checked) {
|
|
1142
|
+
this.$Message.info("已取消该快捷选择");
|
|
1143
|
+
return;
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
try {
|
|
1147
|
+
await this.querySpecificParam(item, isOrgTab, treeRef, proListKey, treeDataKey);
|
|
1148
|
+
} catch (error) {
|
|
1149
|
+
this.$Message.error(`快捷选择处理失败:${error.message.slice(0, 50)}`);
|
|
1150
|
+
item.checked = !item.checked;
|
|
1151
|
+
}
|
|
1152
|
+
},
|
|
1153
|
+
queryTagList() {
|
|
1154
|
+
ajax.get('/pub-manage-server/pub/helpBoxTag/q/queryQuickPickTags').then((res) => {
|
|
1155
|
+
if (res.data.code === 1) {
|
|
1156
|
+
let baseTagList = res.data.data || [];
|
|
1157
|
+
// 组织 Tab 标签:深拷贝并初始化选中状态
|
|
1158
|
+
this.orgTagList = this.safeDeepCopy(baseTagList).map(item => ({
|
|
1159
|
+
...item,
|
|
1160
|
+
checked: false // 独立选中状态
|
|
1161
|
+
}));
|
|
1162
|
+
// 岗位 Tab 标签:深拷贝并初始化选中状态(与组织 Tab 完全独立)
|
|
1163
|
+
this.postTagList = this.safeDeepCopy(baseTagList).map(item => ({
|
|
1164
|
+
...item,
|
|
1165
|
+
checked: false // 独立选中状态
|
|
1166
|
+
}));
|
|
1167
|
+
}
|
|
1168
|
+
});
|
|
1169
|
+
},
|
|
1170
|
+
|
|
1171
|
+
querySpecificParam: function (item, isOrgTab, treeRef, proListKey, treeDataKey) {
|
|
1172
|
+
return new Promise((resolve, reject) => {
|
|
1173
|
+
// 取消选中时处理(仅当手动点击已选中的标签时触发)
|
|
1174
|
+
if (!item.checked) {
|
|
1175
|
+
if (treeRef && treeRef.initData) {
|
|
1176
|
+
treeRef.initData(); // 清空对应树组件
|
|
1177
|
+
}
|
|
1178
|
+
this[proListKey] = []; // 清空对应暂存列表
|
|
1179
|
+
this.$Message.info("已取消该快捷选择");
|
|
1180
|
+
resolve();
|
|
1181
|
+
return;
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
// 请求快捷选择对应的orgUnitId列表
|
|
1185
|
+
ajax.get(`/pub-manage-server/pub/helpBoxTag/q/querySpecificParam?quickPickKey=${item.quickPickKey}`)
|
|
1186
|
+
.then(async (res) => {
|
|
1187
|
+
if (res.data.code !== 1) {
|
|
1188
|
+
this.$Message.error("获取快捷选择配置失败");
|
|
1189
|
+
item.checked = !item.checked;
|
|
1190
|
+
reject(new Error("获取配置失败"));
|
|
1191
|
+
return;
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
const orgUnitIds = res.data.data?.param || [];
|
|
1195
|
+
const safeOrgUnitIds = Array.isArray(orgUnitIds) ? orgUnitIds : [];
|
|
1196
|
+
if (safeOrgUnitIds.length === 0) {
|
|
1197
|
+
this.$Message.warning("该快捷选择未配置任何组织节点");
|
|
1198
|
+
item.checked = !item.checked;
|
|
1199
|
+
reject(new Error("无配置节点"));
|
|
1200
|
+
return;
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
// 校验树组件是否存在(通用校验)
|
|
1204
|
+
if (!treeRef) {
|
|
1205
|
+
this.$Message.error("树组件未初始化");
|
|
1206
|
+
item.checked = !item.checked;
|
|
1207
|
+
reject(new Error("树组件不存在"));
|
|
1208
|
+
return;
|
|
1209
|
+
}
|
|
1210
|
+
const originalTreeData = treeRef.data && treeRef.data.length ? this.safeDeepCopy(treeRef.data) : [];
|
|
1211
|
+
const matchedNodes = [];
|
|
1212
|
+
|
|
1213
|
+
// 批量处理每个orgUnitId(循环逻辑不变,通用处理)
|
|
1214
|
+
for (const orgUnitId of safeOrgUnitIds) {
|
|
1215
|
+
try {
|
|
1216
|
+
// 节点详情查询(复用原有方法)
|
|
1217
|
+
let currentNode = await this.queryOrgNodeDetail(orgUnitId);
|
|
1218
|
+
if (!currentNode || !currentNode.orgUnitId) {
|
|
1219
|
+
this.$Message.warning(`节点【${orgUnitId}】数据异常,跳过处理`);
|
|
1220
|
+
continue;
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
// 循环引用检测与处理(复用原有方法)
|
|
1224
|
+
const cycle = this.detectCircularReferences(currentNode);
|
|
1225
|
+
if (cycle) {
|
|
1226
|
+
this.$Message.warning(`节点【${orgUnitId}】存在循环引用,已自动修复`);
|
|
1227
|
+
currentNode = this.safeDeepCopy(currentNode);
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
// 节点名称默认值处理(复用原有逻辑)
|
|
1231
|
+
currentNode.orgNodeName = currentNode.orgNodeName || currentNode.orgUnitName || `未命名组织(${orgUnitId})`;
|
|
1232
|
+
currentNode.orgUnitName = currentNode.orgNodeName;
|
|
1233
|
+
|
|
1234
|
+
// 节点是否已在树中检测(复用原有方法)
|
|
1235
|
+
const nodeInTree = this.findNodeInTree(originalTreeData, orgUnitId);
|
|
1236
|
+
if (nodeInTree) {
|
|
1237
|
+
if (this.detectCircularReferences(nodeInTree)) {
|
|
1238
|
+
this.$Message.warning(`树中节点【${orgUnitId}】存在循环引用,已跳过`);
|
|
1239
|
+
continue;
|
|
1240
|
+
}
|
|
1241
|
+
matchedNodes.push(nodeInTree);
|
|
1242
|
+
continue;
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
// 父节点追溯与节点链挂载(修复:使用当前Tab的树数据originalTreeData,而非固定orgTree)
|
|
1246
|
+
let targetParent = null;
|
|
1247
|
+
let nodeChain = [currentNode];
|
|
1248
|
+
const MAX_DEPTH = 8;
|
|
1249
|
+
let depth = 0;
|
|
1250
|
+
let lastParentId = '';
|
|
1251
|
+
|
|
1252
|
+
while (!targetParent && depth < MAX_DEPTH) {
|
|
1253
|
+
const parentId = currentNode.parentOrgUnitId;
|
|
1254
|
+
if (!parentId || typeof parentId !== 'string' || parentId === lastParentId) {
|
|
1255
|
+
break;
|
|
1256
|
+
}
|
|
1257
|
+
lastParentId = parentId;
|
|
1258
|
+
|
|
1259
|
+
const parentNode = await this.queryOrgNodeDetail(parentId);
|
|
1260
|
+
if (!parentNode || !parentNode.orgUnitId) {
|
|
1261
|
+
break;
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
if (this.detectCircularReferences(parentNode)) {
|
|
1265
|
+
this.$Message.warning(`父节点【${parentId}】存在循环引用,已跳过`);
|
|
1266
|
+
break;
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
parentNode.orgNodeName = parentNode.orgNodeName || parentNode.orgUnitName || `未命名组织(${parentId})`;
|
|
1270
|
+
// 修复:查询父节点是否在当前Tab的树数据中(originalTreeData),而非固定orgTree
|
|
1271
|
+
const parentInTree = this.findNodeInTree(originalTreeData, parentNode.orgUnitId);
|
|
1272
|
+
|
|
1273
|
+
if (parentInTree) {
|
|
1274
|
+
targetParent = parentInTree;
|
|
1275
|
+
break;
|
|
1276
|
+
}
|
|
1277
|
+
|
|
1278
|
+
nodeChain.unshift(parentNode);
|
|
1279
|
+
currentNode = parentNode;
|
|
1280
|
+
depth++;
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
// 节点链挂载(复用原有方法)
|
|
1284
|
+
if (targetParent) {
|
|
1285
|
+
let currentMountParent = targetParent;
|
|
1286
|
+
for (const node of nodeChain) {
|
|
1287
|
+
const formattedNode = this.safeDeepCopy({
|
|
1288
|
+
...node,
|
|
1289
|
+
leafNode: await this.judgeNodeLeafe(node.orgUnitId),
|
|
1290
|
+
expand: true,
|
|
1291
|
+
checked: false,
|
|
1292
|
+
orgChildrenList: [],
|
|
1293
|
+
children: []
|
|
1294
|
+
});
|
|
1295
|
+
|
|
1296
|
+
if (!Array.isArray(currentMountParent.orgChildrenList)) {
|
|
1297
|
+
currentMountParent.orgChildrenList = [];
|
|
1298
|
+
currentMountParent.children = [];
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
const isDuplicate = currentMountParent.orgChildrenList.some(
|
|
1302
|
+
child => child.orgUnitId === formattedNode.orgUnitId
|
|
1303
|
+
);
|
|
1304
|
+
if (!isDuplicate) {
|
|
1305
|
+
currentMountParent.orgChildrenList.push(formattedNode);
|
|
1306
|
+
currentMountParent.leafNode = false;
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
currentMountParent = currentMountParent.orgChildrenList.find(
|
|
1310
|
+
child => child.orgUnitId === formattedNode.orgUnitId
|
|
1311
|
+
) || formattedNode;
|
|
1312
|
+
}
|
|
1313
|
+
|
|
1314
|
+
const mountedTarget = this.findNodeInTree(originalTreeData, orgUnitId);
|
|
1315
|
+
if (mountedTarget) {
|
|
1316
|
+
matchedNodes.push(mountedTarget);
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1320
|
+
} catch (error) {
|
|
1321
|
+
this.$Message.error(`处理节点【${orgUnitId}】失败:${error.message.slice(0, 50)}`);
|
|
1322
|
+
continue;
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
// 最终数据赋值(根据Tab类型区分,核心统一逻辑)
|
|
1327
|
+
|
|
1328
|
+
if (matchedNodes.length > 0) {
|
|
1329
|
+
// 同步暂存列表(组织proOrgList/岗位proPostList)
|
|
1330
|
+
this[proListKey] = matchedNodes;
|
|
1331
|
+
const finalTreeData = this.safeDeepCopy(originalTreeData);
|
|
1332
|
+
// 响应式更新对应树数据(组织orgTree/岗位postTree)
|
|
1333
|
+
this.$set(this, treeDataKey, finalTreeData);
|
|
1334
|
+
|
|
1335
|
+
await this.$nextTick(async () => {
|
|
1336
|
+
// 更新树组件数据(通用逻辑)
|
|
1337
|
+
if (treeRef.updateTreeData) {
|
|
1338
|
+
treeRef.updateTreeData(this.safeDeepCopy(finalTreeData));
|
|
1339
|
+
} else {
|
|
1340
|
+
treeRef.data = this.safeDeepCopy(finalTreeData);
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
// 设置树选中状态(通用逻辑)
|
|
1344
|
+
const safeNodeIds = matchedNodes.map(node => node.orgUnitId);
|
|
1345
|
+
if (treeRef.setCheckedNodes) {
|
|
1346
|
+
treeRef.setCheckedNodes([]);
|
|
1347
|
+
treeRef.setCheckedNodes(safeNodeIds);
|
|
1348
|
+
treeRef.handleChange(matchedNodes); // 触发子组件选中事件
|
|
1349
|
+
} else {
|
|
1350
|
+
this.updateTreeNodesStatus(
|
|
1351
|
+
finalTreeData,
|
|
1352
|
+
new Set(safeNodeIds),
|
|
1353
|
+
new Set(safeNodeIds)
|
|
1354
|
+
);
|
|
1355
|
+
treeRef.handleChange(matchedNodes);
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1358
|
+
// 提示信息(通用逻辑)
|
|
1359
|
+
this.$Message.success(`成功选中${matchedNodes.length}个组织节点`);
|
|
1360
|
+
});
|
|
1361
|
+
} else {
|
|
1362
|
+
this.$Message.warning("未找到任何可匹配的组织节点");
|
|
1363
|
+
item.checked = !item.checked;
|
|
1364
|
+
}
|
|
1365
|
+
resolve();
|
|
1366
|
+
})
|
|
1367
|
+
.catch((error) => {
|
|
1368
|
+
const errMsg = error.message || '网络异常';
|
|
1369
|
+
this.$Message.error(`快捷选择失败:${errMsg.slice(0, 50)}`);
|
|
1370
|
+
item.checked = !item.checked;
|
|
1371
|
+
reject(error);
|
|
1372
|
+
});
|
|
1373
|
+
});
|
|
1374
|
+
},
|
|
1375
|
+
|
|
1376
|
+
// 新增:移除树数据中的 parent 引用,避免子组件处理时形成循环
|
|
1377
|
+
removeParentReferences(treeData) {
|
|
1378
|
+
if (!Array.isArray(treeData)) return;
|
|
1379
|
+
treeData.forEach(node => {
|
|
1380
|
+
// 删除可能存在的 parent 引用(如果节点有此属性)
|
|
1381
|
+
if (node.parent) delete node.parent;
|
|
1382
|
+
// 递归处理子节点
|
|
1383
|
+
if (Array.isArray(node.orgChildrenList)) {
|
|
1384
|
+
this.removeParentReferences(node.orgChildrenList);
|
|
1385
|
+
}
|
|
1386
|
+
if (Array.isArray(node.children)) {
|
|
1387
|
+
this.removeParentReferences(node.children);
|
|
1388
|
+
}
|
|
1389
|
+
});
|
|
1390
|
+
},
|
|
1391
|
+
// 在 methods 中添加循环引用检测工具函数
|
|
1392
|
+
detectCircularReferences(obj, path = [], visited = new Map()) {
|
|
1393
|
+
if (obj === null || typeof obj !== 'object') return null;
|
|
1394
|
+
|
|
1395
|
+
if (visited.has(obj)) {
|
|
1396
|
+
return { path: [...path, visited.get(obj)], node: obj };
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1399
|
+
visited.set(obj, Array.isArray(obj) ? 'Array' : `Object(${obj.orgUnitId || 'unknown'})`);
|
|
1400
|
+
|
|
1401
|
+
const keys = Array.isArray(obj) ? obj.map((_, i) => i) : Object.keys(obj);
|
|
1402
|
+
for (const key of keys) {
|
|
1403
|
+
const value = obj[key];
|
|
1404
|
+
const newPath = [...path, key];
|
|
1405
|
+
if (value && typeof value === 'object') {
|
|
1406
|
+
const cycle = this.detectCircularReferences(value, newPath, visited);
|
|
1407
|
+
if (cycle) return cycle;
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
visited.delete(obj);
|
|
1412
|
+
return null;
|
|
1413
|
+
},
|
|
1414
|
+
|
|
1415
|
+
// 增强安全深拷贝,主动移除循环引用字段
|
|
1416
|
+
safeDeepCopy(obj, hash = new WeakMap()) {
|
|
1417
|
+
if (obj === null || typeof obj !== 'object') {
|
|
1418
|
+
return obj;
|
|
1419
|
+
}
|
|
1420
|
+
|
|
1421
|
+
// 检测到循环引用时,保留核心字段(orgUnitId必选,其他字段尽可能保留)
|
|
1422
|
+
if (hash.has(obj)) {
|
|
1423
|
+
const safeObj = {
|
|
1424
|
+
orgUnitId: obj.orgUnitId,
|
|
1425
|
+
orgNodeName: obj.orgNodeName || obj.name || `未命名组织(${obj.orgUnitId || 'unknown'})`,
|
|
1426
|
+
orgUnitName: obj.orgUnitName || obj.orgNodeName || obj.name || `未命名组织(${obj.orgUnitId || 'unknown'})`,
|
|
1427
|
+
parentOrgUnitId: obj.parentOrgUnitId || obj.parentId || null
|
|
1428
|
+
};
|
|
1429
|
+
hash.set(obj, safeObj);
|
|
1430
|
+
return safeObj;
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
let copy;
|
|
1434
|
+
if (obj instanceof Array) {
|
|
1435
|
+
copy = [];
|
|
1436
|
+
hash.set(obj, copy);
|
|
1437
|
+
for (let i = 0; i < obj.length; i++) {
|
|
1438
|
+
copy[i] = this.safeDeepCopy(obj[i], hash);
|
|
1439
|
+
}
|
|
1440
|
+
} else if (obj instanceof Object) {
|
|
1441
|
+
copy = {};
|
|
1442
|
+
hash.set(obj, copy);
|
|
1443
|
+
for (let key in obj) {
|
|
1444
|
+
if (obj.hasOwnProperty(key)) {
|
|
1445
|
+
// 仅过滤vue内部字段,保留业务字段
|
|
1446
|
+
if (['__vue__', '__ob__', '$parent', '$children'].includes(key)) {
|
|
1447
|
+
continue;
|
|
1448
|
+
}
|
|
1449
|
+
// 子节点数组特殊处理
|
|
1450
|
+
if (['orgChildrenList', 'children'].includes(key) && Array.isArray(obj[key])) {
|
|
1451
|
+
copy[key] = obj[key].map(child => this.safeDeepCopy(child, hash));
|
|
1452
|
+
} else {
|
|
1453
|
+
// 保留所有业务字段,不额外过滤
|
|
1454
|
+
copy[key] = this.safeDeepCopy(obj[key], hash);
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
} else {
|
|
1459
|
+
copy = obj;
|
|
1460
|
+
}
|
|
1461
|
+
return copy;
|
|
302
1462
|
},
|
|
303
|
-
|
|
304
|
-
|
|
1463
|
+
|
|
1464
|
+
/**
|
|
1465
|
+
* 查询单个节点的原生详情(适配后端接口,返回原生字段)
|
|
1466
|
+
* @param {string} orgUnitId - 节点ID(如11510101)
|
|
1467
|
+
* @returns {Promise<Object|null>} 原生节点详情(无数据返回null)
|
|
1468
|
+
*/
|
|
1469
|
+
getOrgNodeDetail(orgUnitId) {
|
|
1470
|
+
return new Promise((resolve) => {
|
|
1471
|
+
ajax.get(`/pub-manage-server/pub/organ/q/queryOrg`, {
|
|
1472
|
+
params: { orgUnitId: orgUnitId }
|
|
1473
|
+
}).then((res) => {
|
|
1474
|
+
if (res.data.code === 1 && res.data.data) {
|
|
1475
|
+
// 仅保留原生树结构必需字段(过滤业务冗余字段)
|
|
1476
|
+
const { orgUnitId, parentOrgUnitId, orgNodeName, orgChildrenList } = res.data.data;
|
|
1477
|
+
resolve({
|
|
1478
|
+
orgUnitId,
|
|
1479
|
+
parentOrgUnitId,
|
|
1480
|
+
orgNodeName,
|
|
1481
|
+
orgChildrenList: orgChildrenList || [] // 兼容接口返回空的情况
|
|
1482
|
+
});
|
|
1483
|
+
} else {
|
|
1484
|
+
resolve(null);
|
|
1485
|
+
}
|
|
1486
|
+
}).catch(() => {
|
|
1487
|
+
this.$Message.error(`查询节点【${orgUnitId}】详情失败`);
|
|
1488
|
+
resolve(null);
|
|
1489
|
+
});
|
|
1490
|
+
});
|
|
305
1491
|
},
|
|
1492
|
+
|
|
1493
|
+
/**
|
|
1494
|
+
* 迭代查找节点(替代递归,避免栈溢出)
|
|
1495
|
+
* @param {Array} treeData - 树形数据
|
|
1496
|
+
* @param {string} targetOrgUnitId - 目标节点ID
|
|
1497
|
+
* @returns {Object|null} 找到的节点
|
|
1498
|
+
*/
|
|
1499
|
+
findNodeInTree(treeData, targetOrgUnitId) {
|
|
1500
|
+
if (!Array.isArray(treeData) || !targetOrgUnitId || typeof targetOrgUnitId !== 'string') {
|
|
1501
|
+
return null;
|
|
1502
|
+
}
|
|
1503
|
+
|
|
1504
|
+
const queue = [...treeData];
|
|
1505
|
+
while (queue.length > 0) {
|
|
1506
|
+
const currentNode = queue.shift();
|
|
1507
|
+
// 兼容子组件可能的字段映射(orgUnitId可能存储在id字段)
|
|
1508
|
+
const nodeId = currentNode.orgUnitId || currentNode.id || '';
|
|
1509
|
+
if (nodeId === targetOrgUnitId) {
|
|
1510
|
+
return currentNode;
|
|
1511
|
+
}
|
|
1512
|
+
// 兼容children和orgChildrenList两种子节点字段
|
|
1513
|
+
const childNodes = currentNode.orgChildrenList || currentNode.children || [];
|
|
1514
|
+
if (childNodes.length > 0) {
|
|
1515
|
+
queue.push(...childNodes);
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
return null;
|
|
1519
|
+
},
|
|
1520
|
+
|
|
1521
|
+
/**
|
|
1522
|
+
* 辅助方法:查询单个orgUnitId的节点详情
|
|
1523
|
+
* @param {string} orgUnitId - 组织节点ID
|
|
1524
|
+
* @returns {Promise<Object|null>} 节点详情
|
|
1525
|
+
*/
|
|
1526
|
+
queryOrgNodeDetail(orgUnitId) {
|
|
1527
|
+
return new Promise((resolve) => {
|
|
1528
|
+
// 前置校验:避免无效请求
|
|
1529
|
+
if (!orgUnitId || typeof orgUnitId !== 'string') {
|
|
1530
|
+
resolve(null);
|
|
1531
|
+
return;
|
|
1532
|
+
}
|
|
1533
|
+
|
|
1534
|
+
ajax.get(`/pub-manage-server/pub/organ/q/queryOrg?orgUnitId=${orgUnitId}`)
|
|
1535
|
+
.then((res) => {
|
|
1536
|
+
if (res.data.code === 1 && res.data.data && res.data.data.orgUnitId) {
|
|
1537
|
+
// 深拷贝并清理无效字段
|
|
1538
|
+
const node = this.safeDeepCopy(res.data.data);
|
|
1539
|
+
// 核心修复:确保节点名称有默认值,避免空显示
|
|
1540
|
+
const nodeName = node.orgNodeName || node.orgUnitName || node.name || `未命名组织(${orgUnitId})`;
|
|
1541
|
+
node.orgNodeName = nodeName;
|
|
1542
|
+
node.orgUnitName = nodeName; // 同步更新orgUnitName,确保所有使用场景都有值
|
|
1543
|
+
// 确保关键字段存在
|
|
1544
|
+
node.parentOrgUnitId = node.parentOrgUnitId || null;
|
|
1545
|
+
node.orgChildrenList = node.orgChildrenList || [];
|
|
1546
|
+
resolve(node);
|
|
1547
|
+
} else {
|
|
1548
|
+
// 接口返回空时,返回默认结构避免报错
|
|
1549
|
+
resolve({
|
|
1550
|
+
orgUnitId,
|
|
1551
|
+
orgNodeName: `未命名组织(${orgUnitId})`,
|
|
1552
|
+
orgUnitName: `未命名组织(${orgUnitId})`,
|
|
1553
|
+
parentOrgUnitId: null,
|
|
1554
|
+
orgChildrenList: []
|
|
1555
|
+
});
|
|
1556
|
+
}
|
|
1557
|
+
})
|
|
1558
|
+
.catch(() => {
|
|
1559
|
+
// 请求失败时,返回默认结构避免报错
|
|
1560
|
+
resolve({
|
|
1561
|
+
orgUnitId,
|
|
1562
|
+
orgNodeName: `未命名组织(${orgUnitId})`,
|
|
1563
|
+
orgUnitName: `未命名组织(${orgUnitId})`,
|
|
1564
|
+
parentOrgUnitId: null,
|
|
1565
|
+
orgChildrenList: []
|
|
1566
|
+
});
|
|
1567
|
+
});
|
|
1568
|
+
});
|
|
1569
|
+
},
|
|
1570
|
+
|
|
1571
|
+
|
|
1572
|
+
/**
|
|
1573
|
+
* 手动更新树节点状态(如果树组件没有提供update方法)
|
|
1574
|
+
* @param {Array} nodeList - 节点列表
|
|
1575
|
+
* @param {Set} expandIds - 需要展开的节点ID集合
|
|
1576
|
+
* @param {Set} checkedIds - 需要选中的节点ID集合
|
|
1577
|
+
*/
|
|
1578
|
+
updateTreeNodesStatus(nodeList, expandIds, checkedIds) {
|
|
1579
|
+
nodeList.forEach(node => {
|
|
1580
|
+
// 更新展开状态
|
|
1581
|
+
if (expandIds.has(node.orgUnitId)) {
|
|
1582
|
+
node.expand = true;
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1585
|
+
// 更新选中状态
|
|
1586
|
+
if (checkedIds.has(node.orgUnitId)) {
|
|
1587
|
+
node.checked = true;
|
|
1588
|
+
}
|
|
1589
|
+
|
|
1590
|
+
// 递归处理子节点
|
|
1591
|
+
const children = node.children || node.orgChildrenList;
|
|
1592
|
+
if (children && children.length > 0) {
|
|
1593
|
+
this.updateTreeNodesStatus(children, expandIds, checkedIds);
|
|
1594
|
+
}
|
|
1595
|
+
});
|
|
1596
|
+
}
|
|
1597
|
+
|
|
306
1598
|
},
|
|
307
1599
|
computed:{
|
|
308
|
-
getCheckedStaff(){
|
|
309
|
-
|
|
310
|
-
},
|
|
1600
|
+
// getCheckedStaff(){
|
|
1601
|
+
// return this.staffAllList.filter((item)=>item.checked===true).length
|
|
1602
|
+
// },
|
|
311
1603
|
getCheckTypenum(){
|
|
312
1604
|
let l1 = this.orgList.length?1:0;
|
|
313
1605
|
let l2 = this.postList.length?1:0;
|
|
@@ -321,6 +1613,7 @@ export default {
|
|
|
321
1613
|
},
|
|
322
1614
|
data:{
|
|
323
1615
|
handler(val){
|
|
1616
|
+
if(!val) return
|
|
324
1617
|
let map = deepCopy(val)
|
|
325
1618
|
let orgList = map.orgList || []
|
|
326
1619
|
orgList.forEach(item=>{
|
|
@@ -343,7 +1636,433 @@ export default {
|
|
|
343
1636
|
}
|
|
344
1637
|
</script>
|
|
345
1638
|
<style lang="less" scoped>
|
|
1639
|
+
// 新增checkbox样式
|
|
1640
|
+
//.staff-checkbox {
|
|
1641
|
+
// margin-right: 12px;
|
|
1642
|
+
// flex-shrink: 0;
|
|
1643
|
+
//
|
|
1644
|
+
// /deep/ .ivu-checkbox-wrapper {
|
|
1645
|
+
// display: flex;
|
|
1646
|
+
// align-items: center;
|
|
1647
|
+
// cursor: pointer;
|
|
1648
|
+
// }
|
|
1649
|
+
//
|
|
1650
|
+
// /deep/ .ivu-checkbox {
|
|
1651
|
+
// width: 18px;
|
|
1652
|
+
// height: 18px;
|
|
1653
|
+
//
|
|
1654
|
+
// &:checked {
|
|
1655
|
+
// /deep/ .ivu-checkbox-inner {
|
|
1656
|
+
// background-color: var(--primary-color);
|
|
1657
|
+
// border-color: var(--primary-color);
|
|
1658
|
+
// }
|
|
1659
|
+
// }
|
|
1660
|
+
// }
|
|
1661
|
+
//}
|
|
1662
|
+
|
|
1663
|
+
.staff-left-right-layout {
|
|
1664
|
+
display: flex;
|
|
1665
|
+
// 适配全屏:使用视口高度百分比 + 最小高度限制
|
|
1666
|
+
height: calc(100vh - 180px) !important;
|
|
1667
|
+
min-height: 500px !important;
|
|
1668
|
+
gap: 15px;
|
|
1669
|
+
padding: 0 5px;
|
|
1670
|
+
width: 100%;
|
|
1671
|
+
box-sizing: border-box;
|
|
1672
|
+
flex-wrap: nowrap !important;
|
|
1673
|
+
|
|
1674
|
+
// 小屏幕 不改变左右结构
|
|
1675
|
+
@media (max-width: 1200px) {
|
|
1676
|
+
height: calc(100vh - 200px) !important;
|
|
1677
|
+
|
|
1678
|
+
& > .staff-left-panel {
|
|
1679
|
+
width: calc(60% - 7.5px) !important;
|
|
1680
|
+
min-width: 280px !important;
|
|
1681
|
+
max-width: none !important;
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1684
|
+
|
|
1685
|
+
@media (max-width: 768px) {
|
|
1686
|
+
flex-wrap: wrap !important;
|
|
1687
|
+
|
|
1688
|
+
& > .staff-left-panel {
|
|
1689
|
+
width: 100% !important;
|
|
1690
|
+
min-width: 100% !important;
|
|
1691
|
+
max-width: 100% !important;
|
|
1692
|
+
height: 40% !important;
|
|
1693
|
+
margin-bottom: 10px;
|
|
1694
|
+
}
|
|
1695
|
+
|
|
1696
|
+
.staff-right-panel {
|
|
1697
|
+
width: 100% !important;
|
|
1698
|
+
height: 60% !important;
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
|
|
1702
|
+
& > .staff-left-panel {
|
|
1703
|
+
width: calc(60% - 7.5px) !important;
|
|
1704
|
+
min-width: 320px !important;
|
|
1705
|
+
max-width: none !important;
|
|
1706
|
+
display: flex !important;
|
|
1707
|
+
flex-direction: column !important;
|
|
1708
|
+
box-sizing: border-box !important;
|
|
1709
|
+
flex-shrink: 0 !important;
|
|
1710
|
+
flex-grow: 0 !important;
|
|
1711
|
+
height: 100% !important;
|
|
1712
|
+
position: relative !important;
|
|
1713
|
+
|
|
1714
|
+
::v-deep(.panel-title) {
|
|
1715
|
+
all: unset !important;
|
|
1716
|
+
display: flex !important;
|
|
1717
|
+
align-items: center !important;
|
|
1718
|
+
visibility: visible !important;
|
|
1719
|
+
opacity: 1 !important;
|
|
1720
|
+
height: 20px !important;
|
|
1721
|
+
line-height: 20px !important;
|
|
1722
|
+
font-size: 14px !important;
|
|
1723
|
+
font-weight: 500 !important;
|
|
1724
|
+
color: #333 !important;
|
|
1725
|
+
margin-bottom: 8px !important;
|
|
1726
|
+
background: #fff !important;
|
|
1727
|
+
z-index: 999 !important;
|
|
1728
|
+
padding: 0 !important;
|
|
1729
|
+
box-sizing: border-box !important;
|
|
1730
|
+
position: relative !important;
|
|
1731
|
+
width: 100% !important;
|
|
1732
|
+
// 左侧竖条样式
|
|
1733
|
+
&::before {
|
|
1734
|
+
content: '' !important;
|
|
1735
|
+
display: inline-block !important;
|
|
1736
|
+
width: 5px !important; // 竖条宽度
|
|
1737
|
+
height: 16px !important; // 竖条高度(略小于文字行高)
|
|
1738
|
+
background-color: #1890ff !important; // 蓝色竖条
|
|
1739
|
+
margin-right: 8px !important; // 竖条与文字间距
|
|
1740
|
+
//border-radius: 1.5px !important;
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1743
|
+
|
|
1744
|
+
.staff-org-tree {
|
|
1745
|
+
height: calc(100% - 28px - 10px) !important; /* 28=标题高度+间距 + 10px额外缩减,确保按钮可见 */
|
|
1746
|
+
border: 1px solid #EAECF0;
|
|
1747
|
+
border-radius: 4px;
|
|
1748
|
+
padding: 0 !important;
|
|
1749
|
+
box-sizing: border-box;
|
|
1750
|
+
width: 100% !important;
|
|
1751
|
+
overflow-x: auto !important;
|
|
1752
|
+
overflow-y: auto !important;
|
|
1753
|
+
position: relative;
|
|
1754
|
+
flex-shrink: 1;
|
|
1755
|
+
min-height: 0 !important;
|
|
1756
|
+
|
|
1757
|
+
&::-webkit-scrollbar {
|
|
1758
|
+
width: 8px !important;
|
|
1759
|
+
height: 8px !important;
|
|
1760
|
+
background: #f9f9f9 !important;
|
|
1761
|
+
}
|
|
1762
|
+
&::-webkit-scrollbar-thumb {
|
|
1763
|
+
background: #ccc !important;
|
|
1764
|
+
border-radius: 4px !important;
|
|
1765
|
+
}
|
|
1766
|
+
scrollbar-width: thin !important;
|
|
1767
|
+
scrollbar-color: #ccc #f9f9f9 !important;
|
|
1768
|
+
}
|
|
1769
|
+
|
|
1770
|
+
.tree-scroll-force {
|
|
1771
|
+
width: 100% !important;
|
|
1772
|
+
height: 100% !important;
|
|
1773
|
+
margin: 0 !important;
|
|
1774
|
+
padding: 8px !important;
|
|
1775
|
+
box-sizing: border-box;
|
|
1776
|
+
overflow: visible !important;
|
|
1777
|
+
position: relative;
|
|
1778
|
+
}
|
|
1779
|
+
}
|
|
1780
|
+
|
|
1781
|
+
.staff-right-panel {
|
|
1782
|
+
width: calc(40% - 7.5px) !important;
|
|
1783
|
+
min-width: 0 !important;
|
|
1784
|
+
display: flex;
|
|
1785
|
+
flex-direction: column;
|
|
1786
|
+
box-sizing: border-box;
|
|
1787
|
+
gap: 8px; /* 搜索框与列表、列表与底部选择栏的间距统一为8px */
|
|
1788
|
+
padding: 0 5px;
|
|
1789
|
+
flex-shrink: 1 !important;
|
|
1790
|
+
|
|
1791
|
+
// 搜索框:固定高度
|
|
1792
|
+
.ivu-input-wrapper {
|
|
1793
|
+
height: 32px;
|
|
1794
|
+
flex-shrink: 0;
|
|
1795
|
+
}
|
|
1796
|
+
|
|
1797
|
+
// 右侧人员列表容器:适配全屏高度
|
|
1798
|
+
.staff-content {
|
|
1799
|
+
height: calc(100% - 32px - 40px - 16px - 10px) !important;
|
|
1800
|
+
min-height: 200px !important; // 小屏幕最小高度限制
|
|
1801
|
+
border: 1px solid #EAECF0;
|
|
1802
|
+
border-radius: 4px;
|
|
1803
|
+
overflow-x: hidden !important;
|
|
1804
|
+
overflow-y: auto !important;
|
|
1805
|
+
flex-shrink: 1;
|
|
1806
|
+
|
|
1807
|
+
&::-webkit-scrollbar {
|
|
1808
|
+
width: 8px !important;
|
|
1809
|
+
height: 8px !important;
|
|
1810
|
+
background: #f9f9f9 !important;
|
|
1811
|
+
}
|
|
1812
|
+
&::-webkit-scrollbar-thumb {
|
|
1813
|
+
background: #ccc !important;
|
|
1814
|
+
border-radius: 4px !important;
|
|
1815
|
+
}
|
|
1816
|
+
scrollbar-width: thin !important;
|
|
1817
|
+
scrollbar-color: #ccc #f9f9f9 !important;
|
|
1818
|
+
}
|
|
1819
|
+
|
|
1820
|
+
// 底部选择栏:固定高度
|
|
1821
|
+
.bottom-select {
|
|
1822
|
+
height: 40px;
|
|
1823
|
+
flex-shrink: 0;
|
|
1824
|
+
display: flex;
|
|
1825
|
+
align-items: center;
|
|
1826
|
+
justify-content: space-between;
|
|
1827
|
+
padding: 8px 0;
|
|
1828
|
+
background: #fff !important;
|
|
1829
|
+
border-top: 1px solid #f0f0f0;
|
|
1830
|
+
|
|
1831
|
+
//.num {
|
|
1832
|
+
// color: var(--primary-color);
|
|
1833
|
+
//}
|
|
1834
|
+
}
|
|
1835
|
+
}
|
|
1836
|
+
}
|
|
1837
|
+
|
|
1838
|
+
.tab-content-pro {
|
|
1839
|
+
.tab {
|
|
1840
|
+
.tree {
|
|
1841
|
+
// 全屏 使用百分比高度 + 最小高度
|
|
1842
|
+
height: calc(100vh - 340px) !important; // 从300px增加到340px,缩减40px高度
|
|
1843
|
+
min-height: 360px !important; // 降低最小高度,确保按钮可见
|
|
1844
|
+
max-height: none !important; // 移除最大高度限制
|
|
1845
|
+
margin-top:20px;
|
|
1846
|
+
overflow-y: auto !important;
|
|
1847
|
+
overflow-x: auto !important;
|
|
1848
|
+
border: 1px solid #EAECF0;
|
|
1849
|
+
border-radius: 4px;
|
|
1850
|
+
box-sizing: border-box;
|
|
1851
|
+
|
|
1852
|
+
&::-webkit-scrollbar {
|
|
1853
|
+
width: 8px !important;
|
|
1854
|
+
height: 8px !important;
|
|
1855
|
+
display: block !important;
|
|
1856
|
+
background: #f9f9f9 !important;
|
|
1857
|
+
}
|
|
1858
|
+
&::-webkit-scrollbar-thumb {
|
|
1859
|
+
background: #ccc !important;
|
|
1860
|
+
border-radius: 4px !important;
|
|
1861
|
+
}
|
|
1862
|
+
}
|
|
1863
|
+
|
|
1864
|
+
&.post .right .tree {
|
|
1865
|
+
// 岗位树适配全屏(缩减高度确保按钮可见)
|
|
1866
|
+
height: calc(100vh - 430px) !important; // 从400px增加到430px,缩减30px高度
|
|
1867
|
+
min-height: 270px !important; // 降低最小高度,确保按钮可见
|
|
1868
|
+
max-height: none !important;
|
|
1869
|
+
}
|
|
1870
|
+
|
|
1871
|
+
.bottom-select {
|
|
1872
|
+
display:flex;
|
|
1873
|
+
align-items: center;
|
|
1874
|
+
justify-content: space-between;
|
|
1875
|
+
margin-top:15px !important;
|
|
1876
|
+
padding: 8px 0;
|
|
1877
|
+
background: #fff !important;
|
|
1878
|
+
position: relative;
|
|
1879
|
+
z-index: 10;
|
|
1880
|
+
border-top: 1px solid #f0f0f0;
|
|
1881
|
+
.num{
|
|
1882
|
+
color:var(--primary-color);
|
|
1883
|
+
}
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1886
|
+
}
|
|
1887
|
+
|
|
1888
|
+
/deep/ .ivu-tree {
|
|
1889
|
+
width: 100% !important;
|
|
1890
|
+
box-sizing: border-box;
|
|
1891
|
+
}
|
|
1892
|
+
|
|
1893
|
+
/deep/ .ivu-tree-node-content {
|
|
1894
|
+
width: 100% !important;
|
|
1895
|
+
box-sizing: border-box;
|
|
1896
|
+
}
|
|
1897
|
+
|
|
1898
|
+
.gust-item {
|
|
1899
|
+
display: flex;
|
|
1900
|
+
align-items: center;
|
|
1901
|
+
width: 100% !important;
|
|
1902
|
+
padding: 12px 12px;
|
|
1903
|
+
margin-top: 8px;
|
|
1904
|
+
cursor: pointer;
|
|
1905
|
+
box-sizing: border-box;
|
|
1906
|
+
border: none !important;
|
|
1907
|
+
&:hover {
|
|
1908
|
+
background-color: #f2f8ff;
|
|
1909
|
+
border-radius: 4px;
|
|
1910
|
+
}
|
|
1911
|
+
}
|
|
1912
|
+
|
|
1913
|
+
// 滚动条样式
|
|
1914
|
+
.staff-content::-webkit-scrollbar {
|
|
1915
|
+
width: 8px !important;
|
|
1916
|
+
height: 8px;
|
|
1917
|
+
display: block !important;
|
|
1918
|
+
}
|
|
1919
|
+
|
|
1920
|
+
.staff-content::-webkit-scrollbar-thumb {
|
|
1921
|
+
background-color: #ccc !important;
|
|
1922
|
+
border-radius: 4px !important;
|
|
1923
|
+
}
|
|
1924
|
+
|
|
1925
|
+
.staff-content::-webkit-scrollbar-track {
|
|
1926
|
+
background-color: #f9f9f9 !important;
|
|
1927
|
+
}
|
|
1928
|
+
|
|
1929
|
+
.tab.post .left {
|
|
1930
|
+
width: calc(50% - 10px) !important;
|
|
1931
|
+
// 适配全屏高度
|
|
1932
|
+
height: calc(100vh - 380px) !important;
|
|
1933
|
+
min-height: 270px !important;
|
|
1934
|
+
overflow: hidden !important;
|
|
1935
|
+
padding-right: 10px;
|
|
1936
|
+
box-sizing: border-box;
|
|
1937
|
+
|
|
1938
|
+
// 小屏幕仅调整宽度,不改变左右结构
|
|
1939
|
+
@media (max-width: 1200px) {
|
|
1940
|
+
width: calc(50% - 10px) !important;
|
|
1941
|
+
}
|
|
1942
|
+
|
|
1943
|
+
// 超小屏幕
|
|
1944
|
+
@media (max-width: 768px) {
|
|
1945
|
+
width: 100%;
|
|
1946
|
+
margin-bottom: 10px;
|
|
1947
|
+
}
|
|
1948
|
+
}
|
|
1949
|
+
|
|
1950
|
+
.scroll-container {
|
|
1951
|
+
height: 100% !important;
|
|
1952
|
+
overflow-y: auto !important;
|
|
1953
|
+
overflow-x: hidden !important;
|
|
1954
|
+
padding: 8px 0;
|
|
1955
|
+
margin: 0;
|
|
1956
|
+
box-sizing: border-box;
|
|
1957
|
+
}
|
|
1958
|
+
|
|
1959
|
+
.scroll-container::-webkit-scrollbar {
|
|
1960
|
+
width: 8px !important;
|
|
1961
|
+
height: 8px;
|
|
1962
|
+
display: block !important;
|
|
1963
|
+
}
|
|
1964
|
+
|
|
1965
|
+
.scroll-container::-webkit-scrollbar-thumb {
|
|
1966
|
+
background-color: #ccc !important;
|
|
1967
|
+
border-radius: 4px !important;
|
|
1968
|
+
transition: background-color 0.2s;
|
|
1969
|
+
}
|
|
1970
|
+
|
|
1971
|
+
.scroll-container::-webkit-scrollbar-thumb:hover {
|
|
1972
|
+
background-color: #999 !important;
|
|
1973
|
+
}
|
|
1974
|
+
|
|
1975
|
+
.scroll-container::-webkit-scrollbar-track {
|
|
1976
|
+
background-color: #f9f9f9 !important;
|
|
1977
|
+
border-radius: 4px !important;
|
|
1978
|
+
}
|
|
1979
|
+
|
|
1980
|
+
.position-item {
|
|
1981
|
+
border: 1px solid #ddd;
|
|
1982
|
+
margin: 5px 0;
|
|
1983
|
+
padding: 8px 10px;
|
|
1984
|
+
border-radius: 2px;
|
|
1985
|
+
cursor: pointer;
|
|
1986
|
+
transition: background-color 0.2s;
|
|
1987
|
+
white-space: normal !important;
|
|
1988
|
+
overflow: visible !important;
|
|
1989
|
+
text-overflow: clip !important;
|
|
1990
|
+
line-height: 1.4;
|
|
1991
|
+
min-height: 40px;
|
|
1992
|
+
word-wrap: break-word;
|
|
1993
|
+
}
|
|
1994
|
+
|
|
1995
|
+
.position-item.active {
|
|
1996
|
+
border-color: #1890ff;
|
|
1997
|
+
background-color: #e6f7ff;
|
|
1998
|
+
}
|
|
1999
|
+
|
|
2000
|
+
.position-item:hover:not(.active) {
|
|
2001
|
+
background-color: #f5f5f5;
|
|
2002
|
+
}
|
|
2003
|
+
|
|
2004
|
+
.custom-select-wrapper {
|
|
2005
|
+
position: relative;
|
|
2006
|
+
|
|
2007
|
+
/deep/ .ivu-select-clear {
|
|
2008
|
+
right: 32px;
|
|
2009
|
+
color: #999;
|
|
2010
|
+
font-size: 16px;
|
|
2011
|
+
opacity: 1 !important;
|
|
2012
|
+
transition: all 0.2s ease;
|
|
2013
|
+
|
|
2014
|
+
&:hover {
|
|
2015
|
+
color: #ff4d4f;
|
|
2016
|
+
transform: scale(1.1);
|
|
2017
|
+
}
|
|
2018
|
+
}
|
|
2019
|
+
|
|
2020
|
+
/deep/ .ivu-select-arrow {
|
|
2021
|
+
right: 12px;
|
|
2022
|
+
}
|
|
2023
|
+
|
|
2024
|
+
/deep/ .ivu-select-input {
|
|
2025
|
+
padding-right: 45px !important;
|
|
2026
|
+
}
|
|
2027
|
+
|
|
2028
|
+
/deep/ .active-option {
|
|
2029
|
+
background-color: #f2f8ff;
|
|
2030
|
+
color: var(--primary-color);
|
|
2031
|
+
}
|
|
2032
|
+
|
|
2033
|
+
/deep/ .ivu-select-option-disabled {
|
|
2034
|
+
color: #ccc !important;
|
|
2035
|
+
background: #f5f5f5 !important;
|
|
2036
|
+
}
|
|
2037
|
+
}
|
|
2038
|
+
|
|
2039
|
+
.tag-select-container {
|
|
2040
|
+
margin-left: 10px;
|
|
2041
|
+
|
|
2042
|
+
/deep/ .ivu-select-dropdown {
|
|
2043
|
+
max-height: 200px;
|
|
2044
|
+
overflow-y: auto;
|
|
2045
|
+
}
|
|
2046
|
+
|
|
2047
|
+
/deep/ .active-option {
|
|
2048
|
+
background-color: #f2f8ff;
|
|
2049
|
+
color: var(--primary-color);
|
|
2050
|
+
}
|
|
2051
|
+
|
|
2052
|
+
/deep/ .ivu-select-selected-value {
|
|
2053
|
+
max-width: 150px;
|
|
2054
|
+
overflow: hidden;
|
|
2055
|
+
text-overflow: ellipsis;
|
|
2056
|
+
}
|
|
2057
|
+
}
|
|
2058
|
+
|
|
346
2059
|
.modal-tree{
|
|
2060
|
+
// 全屏适配:移除固定宽度限制
|
|
2061
|
+
width: 100% !important;
|
|
2062
|
+
height: 100% !important;
|
|
2063
|
+
max-width: none !important;
|
|
2064
|
+
max-height: none !important;
|
|
2065
|
+
|
|
347
2066
|
.header-text{
|
|
348
2067
|
font-weight: bold;
|
|
349
2068
|
font-size: 16px;
|
|
@@ -352,34 +2071,84 @@ export default {
|
|
|
352
2071
|
.icon-tip{
|
|
353
2072
|
width: 16px;
|
|
354
2073
|
height: 16px;
|
|
355
|
-
background:
|
|
2074
|
+
background: var(--primary-color);
|
|
356
2075
|
border-radius: 50%;
|
|
357
2076
|
color: #fff;
|
|
358
2077
|
line-height: 16px;
|
|
359
2078
|
}
|
|
360
2079
|
.content-container{
|
|
2080
|
+
width: 100%;
|
|
2081
|
+
height: 100%;
|
|
2082
|
+
padding: 10px;
|
|
2083
|
+
box-sizing: border-box;
|
|
361
2084
|
}
|
|
362
2085
|
.tree-orig{
|
|
363
2086
|
width:100%;
|
|
364
2087
|
display: flex;
|
|
365
|
-
|
|
2088
|
+
// 适配全屏高度
|
|
2089
|
+
height: calc(100vh - 80px) !important;
|
|
2090
|
+
min-height: 600px !important;
|
|
366
2091
|
background: #fff;
|
|
2092
|
+
// 强制保留左右结构,仅超小屏幕 换行
|
|
2093
|
+
flex-wrap: nowrap !important;
|
|
2094
|
+
|
|
2095
|
+
:global(.ivu-tabs-ink-bar) {
|
|
2096
|
+
height: 0 !important;
|
|
2097
|
+
display: none !important;
|
|
2098
|
+
width: 0 !important;
|
|
2099
|
+
background: transparent !important;
|
|
2100
|
+
visibility: hidden !important;
|
|
2101
|
+
}
|
|
2102
|
+
|
|
367
2103
|
/deep/.ivu-tabs-nav{
|
|
368
2104
|
font-weight: bold;
|
|
369
2105
|
font-size: 16px;
|
|
370
|
-
}
|
|
371
|
-
/deep/.ivu-tabs-nav{
|
|
372
2106
|
width: 100%;
|
|
373
2107
|
display: flex;
|
|
2108
|
+
margin: 0 !important;
|
|
2109
|
+
padding: 0 !important;
|
|
374
2110
|
}
|
|
375
2111
|
/deep/.ivu-tabs-nav .ivu-tabs-tab{
|
|
376
2112
|
flex:1;
|
|
377
2113
|
text-align: center;
|
|
2114
|
+
background: #F0F2F5 !important;
|
|
2115
|
+
margin: 0 !important;
|
|
2116
|
+
padding: 12px 0 !important;
|
|
2117
|
+
border: none !important;
|
|
2118
|
+
line-height: 1 !important;
|
|
2119
|
+
border-right: 2px solid #E5E6EB !important; // 页签右侧竖线
|
|
2120
|
+
line-height: 1 !important;
|
|
2121
|
+
// 最后一个页签去掉右侧竖线
|
|
2122
|
+
&:last-child {
|
|
2123
|
+
border-right: none !important;
|
|
2124
|
+
}
|
|
2125
|
+
}
|
|
2126
|
+
/deep/.ivu-tabs-nav .ivu-tabs-tab-active {
|
|
2127
|
+
background: #1890FF !important;
|
|
2128
|
+
color: #fff !important;
|
|
2129
|
+
margin: 0 !important;
|
|
2130
|
+
border-right: 1px solid #E5E6EB !important;
|
|
2131
|
+
&:last-child {
|
|
2132
|
+
border-right: none !important;
|
|
2133
|
+
}
|
|
378
2134
|
}
|
|
379
|
-
.tab-content{
|
|
380
|
-
|
|
2135
|
+
.tab-content-pro{
|
|
2136
|
+
// 6:4比例 - 减去gap的一半
|
|
2137
|
+
width: calc(60% - 10px) !important;
|
|
2138
|
+
max-width: none !important; // 取消固定最大宽度,按比例适配
|
|
2139
|
+
flex-shrink: 0 !important; // 禁止压缩
|
|
381
2140
|
border-radius: 8px;
|
|
382
2141
|
border: 1px solid #EAECF0;
|
|
2142
|
+
// 小屏幕保持6:4比例
|
|
2143
|
+
@media (max-width: 1200px) {
|
|
2144
|
+
width: calc(60% - 10px) !important;
|
|
2145
|
+
}
|
|
2146
|
+
// 超小屏幕兜底
|
|
2147
|
+
@media (max-width: 768px) {
|
|
2148
|
+
width: 100% !important;
|
|
2149
|
+
margin-bottom: 10px;
|
|
2150
|
+
}
|
|
2151
|
+
|
|
383
2152
|
.tab{
|
|
384
2153
|
padding:20px;
|
|
385
2154
|
.tag-content{
|
|
@@ -388,9 +2157,32 @@ export default {
|
|
|
388
2157
|
display:flex;
|
|
389
2158
|
align-items: center;
|
|
390
2159
|
}
|
|
391
|
-
.tree{
|
|
392
|
-
height:
|
|
2160
|
+
.tree {
|
|
2161
|
+
height: calc(100vh - 340px) !important; // 缩减40px确保按钮可见
|
|
2162
|
+
min-height: 360px !important; // 降低最小高度
|
|
2163
|
+
max-height: none !important; // 移除最大高度限制
|
|
393
2164
|
margin-top:20px;
|
|
2165
|
+
overflow-y: auto !important; // 纵向溢出时滚动,而非超出
|
|
2166
|
+
overflow-x: auto !important; // 横向溢出时滚动
|
|
2167
|
+
border: 1px solid #EAECF0; // 明确容器边界
|
|
2168
|
+
border-radius: 4px;
|
|
2169
|
+
box-sizing: border-box; // 包含边框/内边距计算
|
|
2170
|
+
// 滚动条样式统一(与人员Tab保持一致)
|
|
2171
|
+
&::-webkit-scrollbar {
|
|
2172
|
+
width: 8px !important;
|
|
2173
|
+
height: 8px !important;
|
|
2174
|
+
display: block !important;
|
|
2175
|
+
background: #f9f9f9 !important;
|
|
2176
|
+
}
|
|
2177
|
+
&::-webkit-scrollbar-thumb {
|
|
2178
|
+
background: #ccc !important;
|
|
2179
|
+
border-radius: 4px !important;
|
|
2180
|
+
}
|
|
2181
|
+
}
|
|
2182
|
+
&.post .right .tree {
|
|
2183
|
+
height: calc(100vh - 430px) !important; // 缩减30px确保按钮可见
|
|
2184
|
+
min-height: 270px !important; // 降低最小高度
|
|
2185
|
+
max-height: none !important;
|
|
394
2186
|
}
|
|
395
2187
|
.staff-content{
|
|
396
2188
|
overflow:auto;
|
|
@@ -399,7 +2191,12 @@ export default {
|
|
|
399
2191
|
display:flex;
|
|
400
2192
|
align-items: center;
|
|
401
2193
|
justify-content: space-between;
|
|
402
|
-
margin-top:
|
|
2194
|
+
margin-top:15px !important; // 增加间距
|
|
2195
|
+
padding: 8px 0; // 内边距提升可读性
|
|
2196
|
+
background: #fff !important; // 白色背景覆盖树溢出内容
|
|
2197
|
+
position: relative;
|
|
2198
|
+
z-index: 10; // 层级高于树容器
|
|
2199
|
+
border-top: 1px solid #f0f0f0; // 视觉分隔
|
|
403
2200
|
.num{
|
|
404
2201
|
color:var(--primary-color);
|
|
405
2202
|
}
|
|
@@ -419,17 +2216,52 @@ export default {
|
|
|
419
2216
|
border: 1px solid #EAECF0;
|
|
420
2217
|
margin-left:10px;
|
|
421
2218
|
font-weight: bold;
|
|
2219
|
+
cursor: pointer;
|
|
422
2220
|
&.active{
|
|
423
|
-
background:
|
|
2221
|
+
background: var(--primary-color);
|
|
424
2222
|
border-radius: 4px;
|
|
425
2223
|
color: #fff;
|
|
426
2224
|
}
|
|
427
2225
|
}
|
|
2226
|
+
.pop-content{
|
|
2227
|
+
display: flex;
|
|
2228
|
+
flex-wrap: wrap;
|
|
2229
|
+
width:500px;
|
|
2230
|
+
.tag{
|
|
2231
|
+
margin-top: 10px;
|
|
2232
|
+
&.active{
|
|
2233
|
+
background: var(--primary-color);
|
|
2234
|
+
border-radius: 4px;
|
|
2235
|
+
color: #fff;
|
|
2236
|
+
}
|
|
2237
|
+
}
|
|
2238
|
+
}
|
|
428
2239
|
.post{
|
|
429
2240
|
display: flex;
|
|
430
2241
|
height: 100%;
|
|
2242
|
+
// 小屏幕仅调整宽度,不改变左右结构
|
|
2243
|
+
@media (max-width: 1200px) {
|
|
2244
|
+
.left {
|
|
2245
|
+
width: calc(50% - 10px) !important; // 同步改为50%
|
|
2246
|
+
}
|
|
2247
|
+
}
|
|
2248
|
+
// 超小屏幕兜底
|
|
2249
|
+
@media (max-width: 768px) {
|
|
2250
|
+
flex-direction: column;
|
|
2251
|
+
|
|
2252
|
+
.left {
|
|
2253
|
+
width: 100%;
|
|
2254
|
+
margin-bottom: 10px;
|
|
2255
|
+
}
|
|
2256
|
+
|
|
2257
|
+
.right {
|
|
2258
|
+
margin-left: 0;
|
|
2259
|
+
width: 100%;
|
|
2260
|
+
}
|
|
2261
|
+
}
|
|
2262
|
+
|
|
431
2263
|
.left{
|
|
432
|
-
width:
|
|
2264
|
+
width: calc(50% - 10px) !important;
|
|
433
2265
|
overflow: auto;
|
|
434
2266
|
>div{
|
|
435
2267
|
background: #FFFFFF;
|
|
@@ -450,7 +2282,8 @@ export default {
|
|
|
450
2282
|
}
|
|
451
2283
|
.right{
|
|
452
2284
|
margin-left:20px;
|
|
453
|
-
|
|
2285
|
+
width: calc(50% - 10px) !important;
|
|
2286
|
+
flex: none !important;
|
|
454
2287
|
}
|
|
455
2288
|
}
|
|
456
2289
|
.gust-item{
|
|
@@ -460,7 +2293,7 @@ export default {
|
|
|
460
2293
|
padding: 15px 10px;
|
|
461
2294
|
margin-top:10px;
|
|
462
2295
|
cursor: pointer;
|
|
463
|
-
.left-panel{
|
|
2296
|
+
.left-panel-pro{
|
|
464
2297
|
background:url("./assets/name-bg.png") no-repeat;
|
|
465
2298
|
width:30px;
|
|
466
2299
|
height:30px;
|
|
@@ -471,7 +2304,7 @@ export default {
|
|
|
471
2304
|
line-height:30px;
|
|
472
2305
|
text-align:center;
|
|
473
2306
|
}
|
|
474
|
-
.right-panel{
|
|
2307
|
+
.right-panel-pro{
|
|
475
2308
|
margin-left:10px;
|
|
476
2309
|
flex:1;
|
|
477
2310
|
>p:first-child{
|
|
@@ -483,24 +2316,40 @@ export default {
|
|
|
483
2316
|
}
|
|
484
2317
|
.checked-icon{
|
|
485
2318
|
margin-left:auto;
|
|
486
|
-
color
|
|
2319
|
+
color:var(--primary-color);
|
|
487
2320
|
font-size:18px;
|
|
488
2321
|
}
|
|
489
2322
|
}
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
2323
|
+
//.staff-active {
|
|
2324
|
+
// background: transparent !important; // 彻底移除背景色
|
|
2325
|
+
// border: none !important; // 彻底移除边框高亮
|
|
2326
|
+
// border-radius: 0 !important; // 移除圆角
|
|
2327
|
+
//
|
|
2328
|
+
// > .right-panel > p:first-child {
|
|
2329
|
+
// color: inherit !important; // 可选:也移除文字颜色变化,仅保留Checkbox选中
|
|
2330
|
+
// // 如果需要保留文字变色,删除上面这行,保留下面注释的行
|
|
2331
|
+
// // color: var(--primary-color);
|
|
2332
|
+
// }
|
|
2333
|
+
//}
|
|
496
2334
|
}
|
|
497
2335
|
.form-content{
|
|
498
|
-
|
|
2336
|
+
// 6:4比例 - 减去gap的一半
|
|
2337
|
+
width: calc(40% - 10px) !important;
|
|
2338
|
+
min-width: 300px !important; // 最小宽度限制
|
|
499
2339
|
overflow: hidden;
|
|
500
2340
|
border-radius: 8px;
|
|
501
2341
|
border: 1px solid #EAECF0;
|
|
502
2342
|
margin-left:20px;
|
|
503
2343
|
padding:10px 20px;
|
|
2344
|
+
height: 100%;
|
|
2345
|
+
flex: none !important; // 取消弹性,固定比例
|
|
2346
|
+
// 超小屏幕
|
|
2347
|
+
@media (max-width: 768px) {
|
|
2348
|
+
margin-left: 0;
|
|
2349
|
+
width: 100%;
|
|
2350
|
+
margin-top: 10px;
|
|
2351
|
+
}
|
|
2352
|
+
|
|
504
2353
|
>p{
|
|
505
2354
|
font-weight: 500;
|
|
506
2355
|
font-size: 16px;
|
|
@@ -559,7 +2408,29 @@ export default {
|
|
|
559
2408
|
justify-content: space-between;
|
|
560
2409
|
}
|
|
561
2410
|
}
|
|
562
|
-
/deep/.ivu-modal-body-no-scrollbar-width :not([class^="ivu-table"])::-webkit-scrollbar{
|
|
563
2411
|
}
|
|
2412
|
+
|
|
2413
|
+
// 超小屏幕适配(手机端)
|
|
2414
|
+
@media (max-width: 768px) {
|
|
2415
|
+
.modal-tree .tree-orig {
|
|
2416
|
+
flex-wrap: wrap !important; // 仅超小屏幕换行
|
|
2417
|
+
height: calc(100vh - 100px) !important;
|
|
2418
|
+
min-height: 400px !important;
|
|
2419
|
+
}
|
|
2420
|
+
|
|
2421
|
+
.tab-content-pro .tab .tree {
|
|
2422
|
+
height: calc(100vh - 380px) !important;
|
|
2423
|
+
min-height: 300px !important;
|
|
2424
|
+
}
|
|
2425
|
+
|
|
2426
|
+
.tab.post .left {
|
|
2427
|
+
height: calc(100vh - 480px) !important;
|
|
2428
|
+
min-height: 200px !important;
|
|
2429
|
+
}
|
|
2430
|
+
|
|
2431
|
+
.staff-left-right-layout {
|
|
2432
|
+
height: calc(100vh - 220px) !important;
|
|
2433
|
+
min-height: 400px !important;
|
|
2434
|
+
}
|
|
564
2435
|
}
|
|
565
2436
|
</style>
|