hbte-saas-ui 0.0.2 → 1.0.2
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/README.md +8 -1
- package/lib/hbte-ui.common.js +31 -10
- package/lib/hbte-ui.umd.js +31 -10
- package/lib/hbte-ui.umd.min.js +1 -1
- package/package.json +8 -2
- package/.browserslistrc +0 -3
- package/.editorconfig +0 -7
- package/.env.development +0 -1
- package/.env.lib +0 -1
- package/.eslintrc.js +0 -14
- package/.prettierrc +0 -3
- package/babel.config.js +0 -3
- package/docs/.vuepress/config.js +0 -23
- package/docs/.vuepress/styles/index.styl +0 -4
- package/docs/AdvQuery.md +0 -26
- package/docs/CustomQuery.md +0 -21
- package/docs/EditArea.md +0 -16
- package/docs/FilterDrop.md +0 -29
- package/docs/FullTable.md +0 -68
- package/docs/Pagination.md +0 -22
- package/docs/QueryForm.md +0 -27
- package/docs/README.md +0 -17
- package/docs/Table.md +0 -58
- package/docs/ToolGroup.md +0 -32
- package/examples/App.vue +0 -97
- package/examples/image/hb-image-viewer/3k.jpg +0 -0
- package/examples/image/hb-image-viewer/a.jpg +0 -0
- package/examples/image/hb-image-viewer/b.jpg +0 -0
- package/examples/main.js +0 -39
- package/examples/mock/authority.js +0 -1108
- package/examples/mock/dept.js +0 -4001
- package/examples/mock/fulltable.js +0 -407
- package/examples/mock/organizeData.js +0 -18965
- package/examples/router/index.js +0 -111
- package/examples/views/ElementCpTest.vue +0 -299
- package/examples/views/Fragment.vue +0 -196
- package/examples/views/HBAdvQuery.vue +0 -150
- package/examples/views/HBAuthority.vue +0 -339
- package/examples/views/HBDialog.vue +0 -39
- package/examples/views/HBEditarea.vue +0 -350
- package/examples/views/HBFilterDrop.vue +0 -72
- package/examples/views/HBFloatFooter.vue +0 -42
- package/examples/views/HBFullTable.vue +0 -751
- package/examples/views/HBImageViewer.vue +0 -57
- package/examples/views/HBNavMenu.vue +0 -37
- package/examples/views/HBOrganizeDialog.vue +0 -133
- package/examples/views/HBPagination.vue +0 -80
- package/examples/views/HBSelectVague.vue +0 -57
- package/examples/views/HBToolgroup.vue +0 -29
- package/examples/views/HBTopBar.vue +0 -16
- package/packages/adv-query/index.js +0 -5
- package/packages/adv-query/src/main.vue +0 -294
- package/packages/area-select/index.js +0 -7
- package/packages/area-select/src/main.vue +0 -37
- package/packages/authority/index.js +0 -5
- package/packages/authority/src/main.vue +0 -606
- package/packages/config.js +0 -3
- package/packages/custom-query/index.js +0 -5
- package/packages/custom-query/src/main.vue +0 -80
- package/packages/dialog/index.js +0 -7
- package/packages/dialog/src/main.vue +0 -176
- package/packages/edit-area/index.js +0 -13
- package/packages/edit-area/src/config.js +0 -3
- package/packages/edit-area/src/main.vue +0 -304
- package/packages/edit-area/src/simulateEvent.js +0 -219
- package/packages/filter-drop/index.js +0 -6
- package/packages/filter-drop/src/main.vue +0 -107
- package/packages/float-footer/index.js +0 -7
- package/packages/float-footer/src/main.vue +0 -40
- package/packages/fragment/index.js +0 -7
- package/packages/fragment/src/main.vue +0 -74
- package/packages/fragment/src/old.vue +0 -144
- package/packages/full-table/index.js +0 -6
- package/packages/full-table/src/config.js +0 -14
- package/packages/full-table/src/main.vue +0 -141
- package/packages/image-viewer/index.js +0 -8
- package/packages/image-viewer/src/main.js +0 -14
- package/packages/image-viewer/src/main.vue +0 -138
- package/packages/image-viewer/src/svg/cancel.svg +0 -2
- package/packages/image-viewer/src/svg/delete.svg +0 -2
- package/packages/image-viewer/src/svg/download.svg +0 -2
- package/packages/image-viewer/src/svg/rotate.svg +0 -77
- package/packages/image-viewer/src/svg/scaledown.svg +0 -71
- package/packages/image-viewer/src/svg/scaleup.svg +0 -72
- package/packages/index.js +0 -43
- package/packages/nav-menu/index.js +0 -7
- package/packages/nav-menu/src/main.vue +0 -277
- package/packages/organize-dialog/index.js +0 -5
- package/packages/organize-dialog/src/main.vue +0 -427
- package/packages/pagination/index.js +0 -6
- package/packages/pagination/src/main.vue +0 -146
- package/packages/query-form/index.js +0 -5
- package/packages/query-form/src/main.vue +0 -142
- package/packages/select-vague/index.js +0 -5
- package/packages/select-vague/src/main.vue +0 -80
- package/packages/table/index.js +0 -5
- package/packages/table/src/main.vue +0 -265
- package/packages/theme-chalk/adv-query.scss +0 -107
- package/packages/theme-chalk/authority.scss +0 -103
- package/packages/theme-chalk/common/elementCover.scss +0 -722
- package/packages/theme-chalk/common/flex.scss +0 -66
- package/packages/theme-chalk/common/global.scss +0 -147
- package/packages/theme-chalk/common/reset.scss +0 -92
- package/packages/theme-chalk/common/var.scss +0 -46
- package/packages/theme-chalk/custom-query.scss +0 -10
- package/packages/theme-chalk/dialog.scss +0 -9
- package/packages/theme-chalk/edit-area.scss +0 -119
- package/packages/theme-chalk/filter-drop.scss +0 -81
- package/packages/theme-chalk/float-footer.scss +0 -14
- package/packages/theme-chalk/fonts/iconfont.ttf +0 -0
- package/packages/theme-chalk/fragment.scss +0 -51
- package/packages/theme-chalk/full-table.scss +0 -40
- package/packages/theme-chalk/icon.scss +0 -96
- package/packages/theme-chalk/image-viewer.scss +0 -94
- package/packages/theme-chalk/images/company-logo--default.png +0 -0
- package/packages/theme-chalk/images/nodata.png +0 -0
- package/packages/theme-chalk/images/user-logo--default.png +0 -0
- package/packages/theme-chalk/index.scss +0 -21
- package/packages/theme-chalk/nav-menu.scss +0 -205
- package/packages/theme-chalk/organize-dialog.scss +0 -170
- package/packages/theme-chalk/pagination.scss +0 -91
- package/packages/theme-chalk/select.scss +0 -8
- package/packages/theme-chalk/table.scss +0 -102
- package/packages/theme-chalk/tool-group.scss +0 -105
- package/packages/theme-chalk/top-bar.scss +0 -195
- package/packages/tool-group/index.js +0 -13
- package/packages/tool-group/src/config.js +0 -40
- package/packages/tool-group/src/main.vue +0 -93
- package/packages/top-bar/index.js +0 -7
- package/packages/top-bar/src/main.vue +0 -280
- package/public/index.html +0 -20
- package/vue.config.js +0 -6
|
@@ -1,277 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div
|
|
3
|
-
class="hb-navmenu"
|
|
4
|
-
:class="[
|
|
5
|
-
isAbsolute ? (isCollapse ? 'hb-navmenu--open' : '') : '',
|
|
6
|
-
isTransition ? 'hb-navmenu--transition' : '',
|
|
7
|
-
]"
|
|
8
|
-
>
|
|
9
|
-
<nav class="hb-navmenu-main">
|
|
10
|
-
<slot name="logo"></slot>
|
|
11
|
-
<div
|
|
12
|
-
:class="
|
|
13
|
-
isActive(index)
|
|
14
|
-
? 'hb-navmenu-main__item hb-navmenu-main__item--isactive'
|
|
15
|
-
: 'hb-navmenu-main__item'
|
|
16
|
-
"
|
|
17
|
-
v-for="(item, index) in data"
|
|
18
|
-
:key="index"
|
|
19
|
-
@click="navigatToPath(item)"
|
|
20
|
-
>
|
|
21
|
-
<i :class="item[props.icon]"></i>
|
|
22
|
-
<p class="hb-navmenu-main__explain">
|
|
23
|
-
{{ item[props.label] }}
|
|
24
|
-
</p>
|
|
25
|
-
</div>
|
|
26
|
-
</nav>
|
|
27
|
-
<div
|
|
28
|
-
:class="[
|
|
29
|
-
isCollapse ? 'hb-navmenu-sub' : 'hb-navmenu-sub hb-navmenu-sub--closed',
|
|
30
|
-
isTransition ? 'hb-navmenu-sub--transition' : '',
|
|
31
|
-
]"
|
|
32
|
-
>
|
|
33
|
-
<i
|
|
34
|
-
class="hbui-shouqi hb-navmenu--collapse"
|
|
35
|
-
v-if="isCollapseShowIcon"
|
|
36
|
-
@click="changecollapse"
|
|
37
|
-
></i>
|
|
38
|
-
<i
|
|
39
|
-
class="hbui-zhankai hb-navmenu--collapse-closed"
|
|
40
|
-
v-else
|
|
41
|
-
@click="changecollapse"
|
|
42
|
-
></i>
|
|
43
|
-
<div class="hb-navmenu-sub-hide">
|
|
44
|
-
<div class="hb-navmenu-sub-content">
|
|
45
|
-
<p class="hb-navmenu-sub-content__title">
|
|
46
|
-
{{ navMenuTitle }}
|
|
47
|
-
</p>
|
|
48
|
-
<div
|
|
49
|
-
:class="
|
|
50
|
-
subIsActive(index)
|
|
51
|
-
? 'hb-navmenu-sub-content--active hb-navmenu-sub-item'
|
|
52
|
-
: 'hb-navmenu-sub-item'
|
|
53
|
-
"
|
|
54
|
-
v-for="(item, index) in subNnavMenuList"
|
|
55
|
-
:key="index"
|
|
56
|
-
@click="navigatToPath(item, false)"
|
|
57
|
-
>
|
|
58
|
-
<i :class="item[props.icon]"></i>
|
|
59
|
-
{{ item[props.label] }}
|
|
60
|
-
</div>
|
|
61
|
-
</div>
|
|
62
|
-
</div>
|
|
63
|
-
</div>
|
|
64
|
-
</div>
|
|
65
|
-
</template>
|
|
66
|
-
|
|
67
|
-
<script>
|
|
68
|
-
//用props传数据!!!!
|
|
69
|
-
export default {
|
|
70
|
-
name: "HbNavmenu",
|
|
71
|
-
componentName: "HbNavmenu",
|
|
72
|
-
props: {
|
|
73
|
-
data: {
|
|
74
|
-
type: Array,
|
|
75
|
-
default: () => [],
|
|
76
|
-
},
|
|
77
|
-
/**
|
|
78
|
-
* 菜单id用于当前选中高亮,不传时采用path字段来判断,需要每个path都存在且不重复
|
|
79
|
-
*/
|
|
80
|
-
props: {
|
|
81
|
-
type: Object,
|
|
82
|
-
default: () => ({
|
|
83
|
-
icon: "icon",
|
|
84
|
-
label: "label",
|
|
85
|
-
path: "path",
|
|
86
|
-
children: "children",
|
|
87
|
-
id: "",
|
|
88
|
-
}),
|
|
89
|
-
},
|
|
90
|
-
//路由跳转方式path或name
|
|
91
|
-
pushWay: {
|
|
92
|
-
type: String,
|
|
93
|
-
default: "path",
|
|
94
|
-
},
|
|
95
|
-
// 路由base
|
|
96
|
-
baseUrl: {
|
|
97
|
-
type: String,
|
|
98
|
-
},
|
|
99
|
-
//子菜单是否占用组件宽度
|
|
100
|
-
isAbsolute: {
|
|
101
|
-
type: Boolean,
|
|
102
|
-
default: true,
|
|
103
|
-
},
|
|
104
|
-
isTransition: {
|
|
105
|
-
type: Boolean,
|
|
106
|
-
default: false,
|
|
107
|
-
},
|
|
108
|
-
},
|
|
109
|
-
data() {
|
|
110
|
-
return {
|
|
111
|
-
isCollapse: true,
|
|
112
|
-
isCollapseShowIcon: true,
|
|
113
|
-
navMenuTitle: "",
|
|
114
|
-
subNnavMenuList: [],
|
|
115
|
-
checked: [],
|
|
116
|
-
};
|
|
117
|
-
},
|
|
118
|
-
created() {
|
|
119
|
-
this.selectPath();
|
|
120
|
-
},
|
|
121
|
-
watch: {
|
|
122
|
-
data: {
|
|
123
|
-
deep: true,
|
|
124
|
-
immediate: true,
|
|
125
|
-
handler(newRouter, oldRouter) {
|
|
126
|
-
if (newRouter != oldRouter) {
|
|
127
|
-
this.selectPath();
|
|
128
|
-
}
|
|
129
|
-
},
|
|
130
|
-
},
|
|
131
|
-
currentPath: {
|
|
132
|
-
immediate: true,
|
|
133
|
-
handler(newRouter, oldRouter) {
|
|
134
|
-
if (newRouter != oldRouter) {
|
|
135
|
-
this.selectPath();
|
|
136
|
-
}
|
|
137
|
-
},
|
|
138
|
-
},
|
|
139
|
-
//抛出菜单宽度更改
|
|
140
|
-
isCollapse(newV) {
|
|
141
|
-
this.$emit("changeWidth", newV);
|
|
142
|
-
},
|
|
143
|
-
},
|
|
144
|
-
computed: {
|
|
145
|
-
// 当前系统路由跳转Key
|
|
146
|
-
routerKey() {
|
|
147
|
-
return this.props.path;
|
|
148
|
-
},
|
|
149
|
-
currentPath() {
|
|
150
|
-
if (this.baseUrl) {
|
|
151
|
-
return (this.$route[this.pushWay] || "").split(this.baseUrl)[1] || "/";
|
|
152
|
-
} else {
|
|
153
|
-
// 适应于不属于微服务的情况下 处理高亮
|
|
154
|
-
return this.$route[this.pushWay];
|
|
155
|
-
}
|
|
156
|
-
},
|
|
157
|
-
},
|
|
158
|
-
methods: {
|
|
159
|
-
isActive(index) {
|
|
160
|
-
return index == this.checked[0];
|
|
161
|
-
},
|
|
162
|
-
subIsActive(index) {
|
|
163
|
-
return this.checked[1] == index;
|
|
164
|
-
},
|
|
165
|
-
// 导航栏展开与关闭
|
|
166
|
-
changecollapse() {
|
|
167
|
-
this.isCollapse = !this.isCollapse;
|
|
168
|
-
if (!this.isTransition) {
|
|
169
|
-
this.isCollapseShowIcon = this.isCollapse;
|
|
170
|
-
} else {
|
|
171
|
-
setTimeout(() => {
|
|
172
|
-
this.isCollapseShowIcon = this.isCollapse;
|
|
173
|
-
}, 100);
|
|
174
|
-
}
|
|
175
|
-
this.$emit("changeCollapse", this.isCollapse);
|
|
176
|
-
},
|
|
177
|
-
// 获取路由地址,设置一二级导航高亮
|
|
178
|
-
selectPath() {
|
|
179
|
-
if (!this.data.length) return;
|
|
180
|
-
let Fn = (list, parent = [], checked = []) => {
|
|
181
|
-
for (let index = 0; index < list.length; index++) {
|
|
182
|
-
const current = list[index];
|
|
183
|
-
let Path = current[this.routerKey];
|
|
184
|
-
let match = Path?.match(/\/:(.)*/g);
|
|
185
|
-
let newPath = Path?.replace(/\/:(.)*/g, "");
|
|
186
|
-
if (match?.length && this.currentPath.indexOf(newPath) == 0) {
|
|
187
|
-
return {
|
|
188
|
-
parent: [...parent, current],
|
|
189
|
-
checked: [...checked, index],
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
if (Path == this.currentPath) {
|
|
193
|
-
return {
|
|
194
|
-
parent: [...parent, current],
|
|
195
|
-
checked: [...checked, index],
|
|
196
|
-
};
|
|
197
|
-
} else {
|
|
198
|
-
let result = Fn(
|
|
199
|
-
current[this.props.children] || [],
|
|
200
|
-
[...parent, current],
|
|
201
|
-
[...checked, index]
|
|
202
|
-
);
|
|
203
|
-
if (result) {
|
|
204
|
-
return result;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
};
|
|
209
|
-
const routeObj = Fn(this.data);
|
|
210
|
-
if (routeObj) {
|
|
211
|
-
this.navMenuTitle = routeObj.parent[0][this.props.label];
|
|
212
|
-
this.subNnavMenuList = routeObj.parent[0][this.props.children] || [];
|
|
213
|
-
//取消三级高亮判断
|
|
214
|
-
this.checked = routeObj.checked;
|
|
215
|
-
this.changecollapseCreated();
|
|
216
|
-
} else {
|
|
217
|
-
this.navMenuTitle = "";
|
|
218
|
-
this.checked = [];
|
|
219
|
-
this.subNnavMenuList = [];
|
|
220
|
-
this.changecollapseCreated();
|
|
221
|
-
}
|
|
222
|
-
},
|
|
223
|
-
// 侧边导航栏路由跳转
|
|
224
|
-
navigatToPath(item, flag = true) {
|
|
225
|
-
let addBase = this.pushWay != "name";
|
|
226
|
-
if (flag) {
|
|
227
|
-
this.navMenuTitle = item[this.props.label];
|
|
228
|
-
this.subNnavMenuList = item[this.props.children] || [];
|
|
229
|
-
if (!this.subNnavMenuList.length) {
|
|
230
|
-
this.$router.push({
|
|
231
|
-
[this.pushWay]: `${addBase ? this.baseUrl : ""}${
|
|
232
|
-
item[this.routerKey]
|
|
233
|
-
}`,
|
|
234
|
-
});
|
|
235
|
-
} else {
|
|
236
|
-
this.$router.push({
|
|
237
|
-
[this.pushWay]: `${addBase ? this.baseUrl : ""}${
|
|
238
|
-
this.subNnavMenuList[0][this.routerKey]
|
|
239
|
-
}`,
|
|
240
|
-
});
|
|
241
|
-
}
|
|
242
|
-
this.checked = [];
|
|
243
|
-
} else {
|
|
244
|
-
if (this.currentPath === item[this.routerKey]) {
|
|
245
|
-
this.selectPath();
|
|
246
|
-
}
|
|
247
|
-
this.$router.push({
|
|
248
|
-
[this.pushWay]: `${addBase ? this.baseUrl : ""}${
|
|
249
|
-
item[this.routerKey]
|
|
250
|
-
}`,
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
this.changecollapseCreated();
|
|
254
|
-
// 抛出事件传递一个布尔值,false表示子导航收起,true表示子导航展开
|
|
255
|
-
},
|
|
256
|
-
|
|
257
|
-
// 判断子导航展开与否
|
|
258
|
-
changecollapseCreated() {
|
|
259
|
-
if (this.subNnavMenuList.length <= 0) {
|
|
260
|
-
this.isCollapse = false;
|
|
261
|
-
} else {
|
|
262
|
-
this.isCollapse = true;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
if (!this.isTransition) {
|
|
266
|
-
this.isCollapseShowIcon = this.isCollapse;
|
|
267
|
-
} else {
|
|
268
|
-
setTimeout(() => {
|
|
269
|
-
this.isCollapseShowIcon = this.isCollapse;
|
|
270
|
-
}, 100);
|
|
271
|
-
}
|
|
272
|
-
this.$emit("changeCollapse", this.isCollapse);
|
|
273
|
-
},
|
|
274
|
-
},
|
|
275
|
-
};
|
|
276
|
-
</script>
|
|
277
|
-
|
|
@@ -1,427 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="hb-organizedialog">
|
|
3
|
-
<el-dialog
|
|
4
|
-
:title="deptOnly ? '选择部门' : '选择部门和人员'"
|
|
5
|
-
v-bind="$attrs"
|
|
6
|
-
:visible.sync="visible"
|
|
7
|
-
:close-on-click-modal="false"
|
|
8
|
-
:close-on-press-escape="false"
|
|
9
|
-
:destroy-on-close="true"
|
|
10
|
-
width="700px"
|
|
11
|
-
@closed="clear"
|
|
12
|
-
>
|
|
13
|
-
<div v-if="loading" class="hb-organizedialog__loading">数据加载中...</div>
|
|
14
|
-
<div v-else class="content hb-organizedialog__wrapper">
|
|
15
|
-
<!-- 左侧已选择 -->
|
|
16
|
-
<div class="hb-organizedialog__part hb-organizedialog__choosed">
|
|
17
|
-
<div class="hb-organizedialog__choosed-wrapper">
|
|
18
|
-
<div class="hb-organizedialog__choosed-list">
|
|
19
|
-
<!-- 远程已选择 -->
|
|
20
|
-
<div
|
|
21
|
-
class="hb-organizedialog__choosed-list--origin item"
|
|
22
|
-
:class="{ allowed: cancelAble }"
|
|
23
|
-
v-for="item in checkedData.originChecked"
|
|
24
|
-
:key="item.id + item.isDept"
|
|
25
|
-
>
|
|
26
|
-
{{ item.name }}
|
|
27
|
-
<i
|
|
28
|
-
class="el-icon-close"
|
|
29
|
-
v-if="cancelAble"
|
|
30
|
-
@click="removecheckedData(item)"
|
|
31
|
-
></i>
|
|
32
|
-
</div>
|
|
33
|
-
<!-- 本地已选择 -->
|
|
34
|
-
<div
|
|
35
|
-
class="hb-organizedialog__choosed-list--local item"
|
|
36
|
-
v-for="item in checkedData.localChecked"
|
|
37
|
-
:key="item.id + item.isDept"
|
|
38
|
-
>
|
|
39
|
-
{{ item.name }}
|
|
40
|
-
<i class="el-icon-close" @click="removecheckedData(item)"></i>
|
|
41
|
-
</div>
|
|
42
|
-
</div>
|
|
43
|
-
</div>
|
|
44
|
-
<!-- 搜索 -->
|
|
45
|
-
<div class="hb-organizedialog__search">
|
|
46
|
-
<el-input
|
|
47
|
-
size="small"
|
|
48
|
-
@focus="keywordsChange($event.target.value)"
|
|
49
|
-
@input="keywordsChange"
|
|
50
|
-
v-model="keyWords"
|
|
51
|
-
placeholder="支持全拼或首拼检索"
|
|
52
|
-
/>
|
|
53
|
-
<el-dropdown
|
|
54
|
-
trigger="click"
|
|
55
|
-
ref="searchBox"
|
|
56
|
-
@command="chooseSearchResult"
|
|
57
|
-
>
|
|
58
|
-
<span></span>
|
|
59
|
-
<el-dropdown-menu
|
|
60
|
-
slot="dropdown"
|
|
61
|
-
class="hb-organizedialog__organization"
|
|
62
|
-
>
|
|
63
|
-
<template v-if="searchData.length">
|
|
64
|
-
<el-dropdown-item
|
|
65
|
-
v-for="item in searchData"
|
|
66
|
-
:key="item.id"
|
|
67
|
-
:command="item"
|
|
68
|
-
:disabled="item.checked"
|
|
69
|
-
>
|
|
70
|
-
<span><img class="avatar" :src="item.logo" alt="" /></span>
|
|
71
|
-
<span v-html="item.html"></span>
|
|
72
|
-
</el-dropdown-item>
|
|
73
|
-
</template>
|
|
74
|
-
<template v-else>
|
|
75
|
-
<el-dropdown-item
|
|
76
|
-
><span>没有搜到任何结果</span></el-dropdown-item
|
|
77
|
-
>
|
|
78
|
-
</template>
|
|
79
|
-
</el-dropdown-menu>
|
|
80
|
-
</el-dropdown>
|
|
81
|
-
</div>
|
|
82
|
-
<!-- 底部按钮 -->
|
|
83
|
-
<div class="hb-organizedialog__foot">
|
|
84
|
-
<el-button
|
|
85
|
-
type="primary"
|
|
86
|
-
@click="confirm"
|
|
87
|
-
:disabled="!checkedNodesNumber"
|
|
88
|
-
size="small"
|
|
89
|
-
>
|
|
90
|
-
确定
|
|
91
|
-
<span v-if="!deptOnly">
|
|
92
|
-
{{
|
|
93
|
-
"( " +
|
|
94
|
-
checkedNodesNumber +
|
|
95
|
-
" / " +
|
|
96
|
-
countMembers(fullTreeData) +
|
|
97
|
-
" )"
|
|
98
|
-
}}
|
|
99
|
-
</span>
|
|
100
|
-
</el-button>
|
|
101
|
-
<el-button size="small" @click="close">取消</el-button>
|
|
102
|
-
</div>
|
|
103
|
-
</div>
|
|
104
|
-
|
|
105
|
-
<!-- 右侧tree -->
|
|
106
|
-
<div class="hb-organizedialog__part hb-organizedialog__tree">
|
|
107
|
-
<!-- 公司 -->
|
|
108
|
-
<div class="hb-organizedialog__tree-company">{{ company }}</div>
|
|
109
|
-
<!-- 组织路径 -->
|
|
110
|
-
<div class="hb-organizedialog__nav">
|
|
111
|
-
<div
|
|
112
|
-
class="hb-organizedialog__nav-item"
|
|
113
|
-
v-for="(item, index) in navPathData"
|
|
114
|
-
:key="item.id"
|
|
115
|
-
:class="{ 'not-allow': item.active }"
|
|
116
|
-
@click="positionDept(index)"
|
|
117
|
-
>
|
|
118
|
-
{{ item.name }}
|
|
119
|
-
</div>
|
|
120
|
-
</div>
|
|
121
|
-
<!-- 组织树 -->
|
|
122
|
-
<div class="hb-organizedialog__tree-wrapper">
|
|
123
|
-
<el-checkbox v-model="allChecked" @change="chooseAll"
|
|
124
|
-
>全选</el-checkbox
|
|
125
|
-
>
|
|
126
|
-
<div
|
|
127
|
-
class="hb-organizedialog__tree-item"
|
|
128
|
-
v-for="item in renderData"
|
|
129
|
-
:key="item.id + item.isDept"
|
|
130
|
-
>
|
|
131
|
-
<el-checkbox
|
|
132
|
-
v-model="item.checked"
|
|
133
|
-
:disabled="item.disabled && !cancelAble"
|
|
134
|
-
@change="
|
|
135
|
-
(boolean) => {
|
|
136
|
-
chooseMember(item, fullTreeData, boolean);
|
|
137
|
-
isAllChecked();
|
|
138
|
-
}
|
|
139
|
-
"
|
|
140
|
-
>
|
|
141
|
-
<!-- 头像 -->
|
|
142
|
-
<span v-if="item.isDept === '0'"
|
|
143
|
-
><img :src="item.logo" class="avatar" alt=""
|
|
144
|
-
/></span>
|
|
145
|
-
<!-- 名称 -->
|
|
146
|
-
<span>{{ item.name }}</span>
|
|
147
|
-
<!-- 人数 -->
|
|
148
|
-
<span v-if="item.isDept === '1' && !deptOnly">{{
|
|
149
|
-
" (" + item.members + ") "
|
|
150
|
-
}}</span>
|
|
151
|
-
</el-checkbox>
|
|
152
|
-
<el-button
|
|
153
|
-
class="subordinate-btn"
|
|
154
|
-
v-if="item.isDept === '1' && item.children.length"
|
|
155
|
-
@click="unfold(item)"
|
|
156
|
-
:disabled="item.checked"
|
|
157
|
-
:class="{ 'not-allow': item.checked }"
|
|
158
|
-
>
|
|
159
|
-
下级
|
|
160
|
-
</el-button>
|
|
161
|
-
</div>
|
|
162
|
-
</div>
|
|
163
|
-
</div>
|
|
164
|
-
</div>
|
|
165
|
-
</el-dialog>
|
|
166
|
-
</div>
|
|
167
|
-
</template>
|
|
168
|
-
<script>
|
|
169
|
-
import { cloneDeep } from "lodash";
|
|
170
|
-
import pinyinMatch from "pinyin-match";
|
|
171
|
-
export default {
|
|
172
|
-
name: "HbOrganizeDialog",
|
|
173
|
-
componentName: "HbOrganizeDialog",
|
|
174
|
-
data() {
|
|
175
|
-
return {
|
|
176
|
-
visible: false,
|
|
177
|
-
loading: true,
|
|
178
|
-
company: "",
|
|
179
|
-
fullTreeData: [], //完整的已加工的树形数据
|
|
180
|
-
disableData: [], //远程已选中的项(禁用状态)
|
|
181
|
-
renderData: [], //当前渲染的项
|
|
182
|
-
navPathData: [], //组织树路径
|
|
183
|
-
searchData: [], //搜索结果项集合
|
|
184
|
-
keyWords: "",
|
|
185
|
-
allChecked: false,
|
|
186
|
-
timer: null, //模糊搜索节流
|
|
187
|
-
};
|
|
188
|
-
},
|
|
189
|
-
computed: {
|
|
190
|
-
checkedData() {
|
|
191
|
-
let originChecked = [];
|
|
192
|
-
let localChecked = [];
|
|
193
|
-
chooseNodes(this.fullTreeData, this);
|
|
194
|
-
function chooseNodes(nodes, _this) {
|
|
195
|
-
nodes.forEach((node) => {
|
|
196
|
-
if (node.checked && node.disabled) {
|
|
197
|
-
let isSameNode = originChecked.some((i) =>
|
|
198
|
-
_this.isSameNode(i, node)
|
|
199
|
-
);
|
|
200
|
-
!isSameNode && originChecked.push(node);
|
|
201
|
-
} else if (node.checked && !node.disabled) {
|
|
202
|
-
let isSameNode = localChecked.some((i) =>
|
|
203
|
-
_this.isSameNode(i, node)
|
|
204
|
-
);
|
|
205
|
-
!isSameNode && localChecked.push(node);
|
|
206
|
-
}
|
|
207
|
-
chooseNodes(node.children, _this);
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
return {
|
|
211
|
-
originChecked,
|
|
212
|
-
localChecked,
|
|
213
|
-
};
|
|
214
|
-
},
|
|
215
|
-
checkedNodesNumber() {
|
|
216
|
-
return (
|
|
217
|
-
this.checkedData.localChecked.length +
|
|
218
|
-
(this.cancelAble ? this.checkedData.originChecked.length : 0)
|
|
219
|
-
);
|
|
220
|
-
},
|
|
221
|
-
},
|
|
222
|
-
methods: {
|
|
223
|
-
open() {
|
|
224
|
-
this.visible = true;
|
|
225
|
-
},
|
|
226
|
-
close() {
|
|
227
|
-
this.visible = false;
|
|
228
|
-
},
|
|
229
|
-
clear() {
|
|
230
|
-
this.loading = true;
|
|
231
|
-
this.company = "";
|
|
232
|
-
this.disableData = [];
|
|
233
|
-
this.renderData = [];
|
|
234
|
-
this.navPathData = [];
|
|
235
|
-
this.searchData = [];
|
|
236
|
-
this.keyWords = "";
|
|
237
|
-
this.allChecked = false;
|
|
238
|
-
this.timer = null;
|
|
239
|
-
},
|
|
240
|
-
//初始化界面
|
|
241
|
-
init(originData = {}, disableData = []) {
|
|
242
|
-
if (!originData.children) {
|
|
243
|
-
return;
|
|
244
|
-
}
|
|
245
|
-
// 初始化公司名
|
|
246
|
-
this.company = originData.name;
|
|
247
|
-
// 初始化组织树数据
|
|
248
|
-
this.disableData = disableData;
|
|
249
|
-
this.fullTreeData = this.factoryTreeData(cloneDeep(originData.children));
|
|
250
|
-
// 初始化组织路径
|
|
251
|
-
this.navPathData.push({
|
|
252
|
-
id: originData.id,
|
|
253
|
-
name: originData.name,
|
|
254
|
-
children: this.fullTreeData,
|
|
255
|
-
active: true,
|
|
256
|
-
});
|
|
257
|
-
this.renderTree();
|
|
258
|
-
// 组织树数据初始化完成
|
|
259
|
-
this.loading = false;
|
|
260
|
-
},
|
|
261
|
-
//check节点时,因可能存在相同的节点,需要全部选中(人员出现在多个部门,部门出现在不同分组中)
|
|
262
|
-
chooseMember(target, nodes, boolean) {
|
|
263
|
-
nodes.forEach((node) => {
|
|
264
|
-
this.isSameNode(target, node) && (node.checked = boolean);
|
|
265
|
-
this.chooseMember(target, node.children, boolean);
|
|
266
|
-
});
|
|
267
|
-
},
|
|
268
|
-
factoryTreeData(originData, parentName = this.company) {
|
|
269
|
-
originData.forEach((node) => {
|
|
270
|
-
//是否远程已选
|
|
271
|
-
let target = this.disableData.find((i) => this.isSameNode(i, node));
|
|
272
|
-
//将远程已选数据的额外字段合并到treeNode数据上
|
|
273
|
-
target && Object.assign(node, target);
|
|
274
|
-
node.checked = node.disabled = Boolean(target);
|
|
275
|
-
node.members = this.deptOnly ? 0 : this.countMembers(node.children);
|
|
276
|
-
node.parentName = parentName;
|
|
277
|
-
this.factoryTreeData(node.children, node.name);
|
|
278
|
-
});
|
|
279
|
-
return originData;
|
|
280
|
-
},
|
|
281
|
-
//初始化组织树数据
|
|
282
|
-
renderTree(nodes = this.fullTreeData) {
|
|
283
|
-
this.renderData = nodes;
|
|
284
|
-
this.isAllChecked();
|
|
285
|
-
},
|
|
286
|
-
//全选
|
|
287
|
-
chooseAll(boolean) {
|
|
288
|
-
this.renderData.forEach((node) => {
|
|
289
|
-
if (this.cancelAble) {
|
|
290
|
-
node.checked = boolean;
|
|
291
|
-
this.chooseMember(node, this.fullTreeData, boolean);
|
|
292
|
-
} else {
|
|
293
|
-
if (!node.disabled) {
|
|
294
|
-
node.checked = boolean;
|
|
295
|
-
this.chooseMember(node, this.fullTreeData, boolean);
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
});
|
|
299
|
-
this.isAllChecked();
|
|
300
|
-
},
|
|
301
|
-
//移除已选择的选项
|
|
302
|
-
removecheckedData(node) {
|
|
303
|
-
this.chooseMember(node, this.fullTreeData, false);
|
|
304
|
-
this.isAllChecked();
|
|
305
|
-
},
|
|
306
|
-
//判断是否形成全选,并处理全选按钮
|
|
307
|
-
isAllChecked() {
|
|
308
|
-
this.allChecked = this.renderData.every((node) => node.checked);
|
|
309
|
-
},
|
|
310
|
-
//判断是不是同一个节点
|
|
311
|
-
isSameNode(reference, target) {
|
|
312
|
-
return reference.id === target.id && reference.isDept === target.isDept;
|
|
313
|
-
},
|
|
314
|
-
//计算原始数据成员数
|
|
315
|
-
countMembers(subNodes, prevnum = []) {
|
|
316
|
-
subNodes.forEach((item) => {
|
|
317
|
-
item.isDept === "0" && prevnum.push(item.id);
|
|
318
|
-
});
|
|
319
|
-
subNodes.forEach((item) => {
|
|
320
|
-
if (item.isDept === "1" && item.children.length) {
|
|
321
|
-
this.countMembers(item.children, prevnum);
|
|
322
|
-
}
|
|
323
|
-
});
|
|
324
|
-
return [...new Set(prevnum)].length;
|
|
325
|
-
},
|
|
326
|
-
//展开此组织层级
|
|
327
|
-
unfold(node) {
|
|
328
|
-
//更新组织树路径
|
|
329
|
-
this.navPathData.forEach((item) => (item.active = false));
|
|
330
|
-
this.navPathData.push({
|
|
331
|
-
id: node.id,
|
|
332
|
-
name: node.name,
|
|
333
|
-
active: true,
|
|
334
|
-
children: node.children,
|
|
335
|
-
});
|
|
336
|
-
//渲染新的组织树节点
|
|
337
|
-
this.renderTree(node.children);
|
|
338
|
-
//判断是否全选
|
|
339
|
-
this.isAllChecked();
|
|
340
|
-
},
|
|
341
|
-
//切换到指定组织
|
|
342
|
-
positionDept(num) {
|
|
343
|
-
// 修改组织路径
|
|
344
|
-
this.navPathData = this.navPathData.filter((item, index) => index <= num);
|
|
345
|
-
this.navPathData.forEach((item, index) => {
|
|
346
|
-
item.active = num === index;
|
|
347
|
-
});
|
|
348
|
-
// 初始化组织树数据
|
|
349
|
-
this.renderTree(this.navPathData[num].children);
|
|
350
|
-
//判断是否全选
|
|
351
|
-
this.isAllChecked();
|
|
352
|
-
},
|
|
353
|
-
confirm() {
|
|
354
|
-
this.$emit("confirm", this.checkedData);
|
|
355
|
-
},
|
|
356
|
-
//输入搜索关键字(节流)
|
|
357
|
-
keywordsChange(value) {
|
|
358
|
-
if (this.timer) {
|
|
359
|
-
clearTimeout(this.timer);
|
|
360
|
-
}
|
|
361
|
-
this.timer = setTimeout(() => {
|
|
362
|
-
value = value.trim();
|
|
363
|
-
if (value) {
|
|
364
|
-
this.$refs.searchBox.show();
|
|
365
|
-
this.searchData = [];
|
|
366
|
-
this.vagueSearch(value);
|
|
367
|
-
//如果有结果,高亮关键字
|
|
368
|
-
this.highlightWords();
|
|
369
|
-
this.searchData.sort((a, b) => a.isDept - b.isDept);
|
|
370
|
-
} else {
|
|
371
|
-
this.$refs.searchBox.hide();
|
|
372
|
-
}
|
|
373
|
-
}, 500);
|
|
374
|
-
},
|
|
375
|
-
//从搜索结果中选取节点
|
|
376
|
-
chooseSearchResult(node) {
|
|
377
|
-
this.keyWords = "";
|
|
378
|
-
this.chooseMember(node, this.fullTreeData, true);
|
|
379
|
-
this.isAllChecked();
|
|
380
|
-
},
|
|
381
|
-
//模糊搜索(支持拼音)
|
|
382
|
-
vagueSearch(value, originData = this.fullTreeData) {
|
|
383
|
-
originData.forEach((node) => {
|
|
384
|
-
let matched = pinyinMatch.match(node.name, value);
|
|
385
|
-
if (matched) {
|
|
386
|
-
//去重
|
|
387
|
-
let isInCludes = this.searchData.some((i) =>
|
|
388
|
-
this.isSameNode(i, node)
|
|
389
|
-
);
|
|
390
|
-
if (!isInCludes) {
|
|
391
|
-
this.searchData.push(node);
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
if (node.children.length) {
|
|
395
|
-
this.vagueSearch(value, node.children);
|
|
396
|
-
}
|
|
397
|
-
});
|
|
398
|
-
},
|
|
399
|
-
//高亮匹配的搜索关键字
|
|
400
|
-
highlightWords() {
|
|
401
|
-
if (this.searchData.length) {
|
|
402
|
-
let keyWordsArr = this.keyWords.split("");
|
|
403
|
-
this.searchData.forEach((item) => {
|
|
404
|
-
let targetArr = item.name.split("");
|
|
405
|
-
targetArr.forEach((word, index, self) => {
|
|
406
|
-
let include = keyWordsArr.includes(word);
|
|
407
|
-
self[index] = include ? `<i>${word}</i>` : word;
|
|
408
|
-
});
|
|
409
|
-
item.html =
|
|
410
|
-
(item.isDept === "1" ? `${item.parentName} / ` : "") +
|
|
411
|
-
targetArr.join("");
|
|
412
|
-
});
|
|
413
|
-
}
|
|
414
|
-
},
|
|
415
|
-
},
|
|
416
|
-
props: {
|
|
417
|
-
deptOnly: {
|
|
418
|
-
type: Boolean,
|
|
419
|
-
default: false,
|
|
420
|
-
},
|
|
421
|
-
cancelAble: {
|
|
422
|
-
type: Boolean,
|
|
423
|
-
default: false,
|
|
424
|
-
},
|
|
425
|
-
},
|
|
426
|
-
};
|
|
427
|
-
</script>
|