cnhis-design-vue 2.1.106 → 2.1.109

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.
Files changed (48) hide show
  1. package/CHANGELOG.md +16 -2
  2. package/es/age/index.js +2 -2
  3. package/es/big-table/index.js +188 -182
  4. package/es/big-table/style.css +1 -1
  5. package/es/button/index.js +2 -2
  6. package/es/captcha/index.js +3 -3
  7. package/es/card-reader-sdk/index.js +1 -1
  8. package/es/checkbox/index.js +1 -1
  9. package/es/color-picker/index.js +1 -1
  10. package/es/drag-layout/index.js +3 -3
  11. package/es/editor/index.js +1 -1
  12. package/es/ellipsis/index.js +1 -1
  13. package/es/fabric-chart/index.js +9 -9
  14. package/es/form-table/index.js +20 -20
  15. package/es/index/index.js +899 -339
  16. package/es/index/style.css +1 -1
  17. package/es/input/index.js +1 -1
  18. package/es/map/index.js +1 -1
  19. package/es/multi-chat/index.js +25 -25
  20. package/es/multi-chat-client/index.js +19 -19
  21. package/es/multi-chat-history/index.js +4 -4
  22. package/es/multi-chat-record/index.js +4 -4
  23. package/es/multi-chat-setting/index.js +20 -20
  24. package/es/multi-chat-sip/index.js +1 -1
  25. package/es/radio/index.js +1 -1
  26. package/es/scale-container/index.js +1 -1
  27. package/es/scale-view/index.js +27 -27
  28. package/es/select/index.js +4 -4
  29. package/es/select-label/index.js +3 -3
  30. package/es/select-person/index.js +2 -2
  31. package/es/select-tag/index.js +4 -4
  32. package/es/shortcut-setter/index.js +2 -2
  33. package/es/slider-tree/index.js +1064 -0
  34. package/es/slider-tree/style.css +1 -0
  35. package/es/table-filter/index.js +30 -30
  36. package/es/tag/index.js +1 -1
  37. package/es/verification-code/index.js +2 -2
  38. package/lib/cui.common.js +940 -404
  39. package/lib/cui.umd.js +940 -404
  40. package/lib/cui.umd.min.js +124 -124
  41. package/package.json +1 -1
  42. package/packages/big-table/src/components/edit-form/EditForm.vue +8 -3
  43. package/packages/big-table/src/components/edit-form/edit-component/mixins/search.js +214 -259
  44. package/packages/index.js +6 -3
  45. package/packages/slider-tree/hooks/useAsyncData.js +53 -0
  46. package/packages/slider-tree/index.js +7 -0
  47. package/packages/slider-tree/index.vue +439 -0
  48. package/packages/slider-tree/utils/index.js +10 -0
package/packages/index.js CHANGED
@@ -90,7 +90,8 @@ import { default as ShortcutSetter } from './shortcut-setter';
90
90
  import { default as Ellipsis } from './ellipsis';
91
91
  import { default as ScaleContainer } from './scale-container';
92
92
  import { default as ShortcutProvider } from './shortcut-provider';
93
- // import flexibleResize from '@/directive/flexibleResize';
93
+ import { default as SliderTree } from './slider-tree';
94
+
94
95
 
95
96
  const req = require.context('ant-design-vue/es/locale', true, /.js$/);
96
97
  const locales = {};
@@ -190,7 +191,8 @@ const components = [
190
191
  ShortcutSetter,
191
192
  Ellipsis,
192
193
  ScaleContainer,
193
- ShortcutProvider
194
+ ShortcutProvider,
195
+ SliderTree
194
196
  ];
195
197
 
196
198
  // 定义 install 方法,接收 Vue 作为参数。如果使用 use 注册插件,则所有的组件都将被注册
@@ -308,7 +310,8 @@ export {
308
310
  ShortcutSetter,
309
311
  Ellipsis,
310
312
  ScaleContainer,
311
- ShortcutProvider
313
+ ShortcutProvider,
314
+ SliderTree
312
315
  };
313
316
 
314
317
  export default {
@@ -0,0 +1,53 @@
1
+ export default function useAsyncData() {
2
+
3
+ async function handleGetConfigApi(params, key, filterApiConfig) {
4
+ try {
5
+ // TODO: 判断 fn 是异步函数还是同步
6
+ const fn = filterApiConfig[key] || null;
7
+ if (typeof fn === 'function') {
8
+ const res = await fn(params);
9
+ return Promise.resolve(res);
10
+ } else {
11
+ return Promise.reject(new Error(`${key} Is not a function`));
12
+ }
13
+ } catch (error) {
14
+ return Promise.reject(error);
15
+ }
16
+ }
17
+
18
+ // 根据机构id查本身及下级机构,平级返回 /corp-center/iho/org/manage/getChildrenByOrgPartenId
19
+ async function getChildrenByOrgPartenId(params, filterApiConfig) {
20
+ return await handleGetConfigApi(params, 'getChildrenByOrgPartenId', filterApiConfig);
21
+ }
22
+
23
+ // 员工左侧树搜索,接口/corp-center/iho/dept/selectOrgBck1TreeByParam
24
+ async function searchEmpTreeData(params, filterApiConfig) {
25
+ return await handleGetConfigApi(params, 'searchEmpTreeData', filterApiConfig);
26
+ }
27
+
28
+ // 拖动修改科室的排序,接口/corp-center/iho/dept/updateSort
29
+ async function updateDeptSort(params, filterApiConfig) {
30
+ return await handleGetConfigApi(params, 'updateDeptSort', filterApiConfig);
31
+ }
32
+
33
+ // 获取科室管理科室列表,接口/corp-center/iho/dept/selectBck1ListByParam
34
+ async function getDeptList(params, filterApiConfig) {
35
+ return await handleGetConfigApi(params, 'getDeptList', filterApiConfig);
36
+ }
37
+
38
+ // 删除科室,接口/corp-center/iho/dept/deleteBck1
39
+ // async function deleteDept(params, filterApiConfig) {
40
+ // return await handleGetConfigApi(params, 'deleteDept', filterApiConfig);
41
+ // }
42
+
43
+
44
+
45
+
46
+ return {
47
+ getChildrenByOrgPartenId,
48
+ searchEmpTreeData,
49
+ updateDeptSort,
50
+ getDeptList,
51
+ // deleteDept
52
+ }
53
+ }
@@ -0,0 +1,7 @@
1
+ import SliderTree from './index.vue';
2
+
3
+ SliderTree.install = function(Vue){
4
+ Vue.component(SliderTree.name, SliderTree);
5
+ }
6
+
7
+ export default SliderTree;
@@ -0,0 +1,439 @@
1
+ <template>
2
+ <div
3
+ class="left-tree-wrap"
4
+ ref="left"
5
+ :style = "{
6
+ width: flexWidth + 'px',
7
+ }"
8
+ v-flexible-resize="{
9
+ mode: 'VR',
10
+ onMove: changeWidth,
11
+ onEnd: saveWidth
12
+ }"
13
+ >
14
+ <div class="search-groups">
15
+ <a-input-search
16
+ placeholder="搜索关键字"
17
+ v-model="searchValue"
18
+ @change="onSearch"
19
+ @search="onSearch"
20
+ allowClear
21
+ />
22
+ <!-- 按钮插槽 -->
23
+ <slot name="buttons"></slot>
24
+ </div>
25
+
26
+ <!-- 标签tab插槽 -->
27
+ <slot name="tabs"></slot>
28
+
29
+ <div class="tree-wrap">
30
+ <a-tree
31
+ :tree-data="treeData"
32
+ :replaceFields="treeRenderConfig.replaceFields"
33
+ :expanded-keys="expandedKeys"
34
+ :selectedKeys="selectedKeys"
35
+ :showIcon="true"
36
+ :draggable="isDraggable"
37
+ :loadedKeys="loadedKeys"
38
+ :load-data="onLoadData"
39
+ @expand="onExpand"
40
+ @select="onNodeSelect"
41
+ @dragenter="onDragEnter"
42
+ @drop="onDrop"
43
+ >
44
+ <template slot="title" slot-scope="node">
45
+ <!-- 图标插槽 -->
46
+ <div class="tree-left">
47
+ <slot name="icons" :node="node"></slot>
48
+ <span class="dept-name" v-if="node.name.indexOf(searchValue.trim()) > -1" :title="node.name">
49
+ {{ node.name.substr(0, node.name.indexOf(searchValue.trim())) }}
50
+ <span style="color: #2563F4">{{ searchValue.trim() }}</span>
51
+ {{
52
+ node.name.substr(
53
+ node.name.indexOf(searchValue.trim()) + searchValue.trim().length
54
+ )
55
+ }}
56
+ </span>
57
+ <span v-else :title="node.name">{{ node.name }}</span>
58
+ </div>
59
+
60
+ <!-- 操作插槽 -->
61
+ <slot name="operate" :node="node"></slot>
62
+ </template>
63
+ </a-tree>
64
+ <a-empty description="暂无数据"/>
65
+ </div>
66
+
67
+ <div class="table-footer-wrap">
68
+ <slot name="output"></slot>
69
+ </div>
70
+ </div>
71
+ </template>
72
+
73
+ <script>
74
+ /* eslint-disable no-async-promise-executor */
75
+
76
+ import { Tree, Input, Empty } from 'ant-design-vue';
77
+ import flexibleResize from '@/directive/flexibleResize';
78
+ import useAsyncData from './hooks/useAsyncData.js';
79
+ import { traversalData } from './utils'
80
+ const {
81
+ getChildrenByOrgPartenId,
82
+ searchEmpTreeData,
83
+ updateDeptSort,
84
+ getDeptList,
85
+ } = useAsyncData();
86
+ import create from '@/core/create';
87
+
88
+ const isMatchFn = (node, keyword) => {
89
+ keyword = keyword?.toLowerCase();
90
+ let { name = "", abbrp = "", abbrw = "", code } = node;
91
+ const nameMatch = name?.toLowerCase()?.indexOf(keyword) > -1; // 名字匹配
92
+ const codeMatch = code?.toLowerCase()?.indexOf(keyword) > -1; // 编码匹配
93
+ const pyCodeMatch = abbrp?.toLowerCase()?.indexOf(keyword) > -1; // 拼音匹配
94
+ const wbCodeMatch = abbrw?.toLowerCase()?.indexOf(keyword) > -1; // 五笔匹配
95
+ if (nameMatch || pyCodeMatch || wbCodeMatch || codeMatch) {
96
+ return true;
97
+ } else {
98
+ return false;
99
+ }
100
+ };
101
+
102
+ export default create({
103
+ name: 'slider-tree',
104
+ directives: {
105
+ flexibleResize
106
+ },
107
+ components: {
108
+ [Tree.name]: Tree,
109
+ [Empty.name]: Tree,
110
+ [Input.Search.name]: Input.Search,
111
+ },
112
+ props: {
113
+ // 回调对象集合
114
+ treeSearchApiConfig: {
115
+ type: Object,
116
+ default: () => ({})
117
+ },
118
+ // 树节点渲染配置
119
+ treeRenderConfig: {
120
+ type: Object,
121
+ default: () => ({
122
+ replaceFields: {
123
+ children: "childrenList",
124
+ title: "name",
125
+ key: "code"
126
+ },
127
+ title: 'bck03',
128
+ key: 'bck02'
129
+ })
130
+ },
131
+ // 是否需要拖拽树节点
132
+ isDraggable: {
133
+ type: Boolean,
134
+ default: true
135
+ },
136
+ // 是否需要更新数据
137
+ isRefresh: {
138
+ type: Boolean,
139
+ default: false
140
+ }
141
+ },
142
+ data() {
143
+ return {
144
+ // 初始宽度
145
+ flexWidth: 260,
146
+ // 搜索关键词
147
+ searchValue: "",
148
+ treeData: [],
149
+ // replaceFields: {
150
+ // children: "childrenList",
151
+ // title: "name",
152
+ // key: "code"
153
+ // },
154
+ expandedKeys: [],
155
+ selectedKeys: [],
156
+ // 选中的左侧树节点
157
+ selectNode: {},
158
+ loadedKeys: [],
159
+ // 拖拽的数据
160
+ dragData: {}
161
+ };
162
+ },
163
+ async mounted() {
164
+ await this.init();
165
+ },
166
+ watch: {
167
+ isRefresh(val) {
168
+ if (val) {
169
+ this.refreshTreeData();
170
+ }
171
+ }
172
+ },
173
+ methods: {
174
+ // 更新treeData数据,在拖拽节点和删除节点的时候使用
175
+ async refreshTreeData() {
176
+ await this.getChildrenByOrgPartenId();
177
+ // 更新完成
178
+ this.$emit("refreshEnd", true);
179
+ if (!this.treeData.length) return;
180
+ },
181
+ // 初始化节点数据
182
+ async init() {
183
+ await this.getChildrenByOrgPartenId();
184
+ if (!this.treeData.length) return;
185
+ this.expandedKeys = [this.treeData[0].code];
186
+ this.selectedKeys = [this.treeData[0].code];
187
+ this.selectNode = this.treeData[0];
188
+ this.$emit("select", JSON.parse(JSON.stringify(this.treeData[0])));
189
+ },
190
+ onExpand(expandedKeys) {
191
+ this.expandedKeys = expandedKeys;
192
+ },
193
+ // 选中树节点
194
+ onNodeSelect(selectedKeys = [], { node }) {
195
+ if (selectedKeys.length) {
196
+ // 选中
197
+ this.expandedKeys = [...this.expandedKeys, ...selectedKeys];
198
+ } else {
199
+ // 取消选中
200
+ this.expandedKeys = this.expandedKeys.filter(
201
+ key => key !== this.selectedKeys[0]
202
+ );
203
+ }
204
+ this.selectedKeys = selectedKeys;
205
+ this.$emit("select", node.dataRef);
206
+ const data = Object.create(node.dataRef);
207
+ this.selectNode = data;
208
+ },
209
+ async onSearch() {
210
+ const searchValue = this.searchValue.trim();
211
+ if (searchValue) {
212
+ const {
213
+ data, success
214
+ } = await searchEmpTreeData({
215
+ search: searchValue
216
+ }, this.treeSearchApiConfig);
217
+ if (success) {
218
+ data.forEach(org => {
219
+ org.childrenList = this.handleDeptData(
220
+ org.bck1TreeManageRespDTO || []
221
+ );
222
+ org.isLeaf = org.childrenList.length ? false : true;
223
+ org.isOrg = true;
224
+ });
225
+ this.treeData = data;
226
+ this.expandedKeys = this.getExpandKeys(data);
227
+ }
228
+ } else {
229
+ this.reset();
230
+ }
231
+ },
232
+ async reset(flag, selectOrgId) {
233
+ await this.getChildrenByOrgPartenId();
234
+ let orgId = this.treeData[0].orgId;
235
+ let setIndex = 0;
236
+ if (flag) {
237
+ orgId = selectOrgId;
238
+ setIndex = this.treeData.findIndex(org => org.orgId === orgId);
239
+ }
240
+ const data = await this.getDeptData(orgId);
241
+ if (data) {
242
+ this.$set(this.treeData, setIndex, data);
243
+ }
244
+ },
245
+ onDragEnter(info) {
246
+ console.log(info, "drag enter info");
247
+ },
248
+ async onDrop(info) {
249
+ const { dragNode, node } = info;
250
+ const { dataRef: dragData } = dragNode;
251
+ const { dataRef: dropData } = node;
252
+ if (dragData.isOrg) {
253
+ this.$message.error("机构不能拖动排序");
254
+ return;
255
+ }
256
+ if (dragData.orgId !== dropData.orgId) {
257
+ this.$message.error("不能跨机构移动科室");
258
+ return;
259
+ }
260
+ if (dragData.bck01a !== dropData.bck01a) {
261
+ this.$message.error("仅允许同层级科室排序");
262
+ return;
263
+ }
264
+ this.dragData = dragData;
265
+ const params = {
266
+ bck01: dragData.bck01,
267
+ moveTobck01: dropData.bck01,
268
+ orgId: dragData.orgId
269
+ };
270
+ const {
271
+ success
272
+ } = await updateDeptSort(params, this.treeSearchApiConfig);
273
+ if (success) {
274
+ this.$message.success("排序成功");
275
+ this.reset(true, dragData.orgId);
276
+ this.$emit("dropEnd", params);
277
+ }
278
+ },
279
+ // 获取科室管理科室列表
280
+ async getDeptData(orgId) {
281
+ const {
282
+ data,
283
+ success
284
+ } = await getDeptList({ orgId }, this.treeSearchApiConfig);
285
+ if (success) {
286
+ const temp = this.treeData.find(org => org.orgId === orgId);
287
+ temp.childrenList = this.handleDeptData(data);
288
+ return temp;
289
+ }
290
+ },
291
+ handleDeptData(data) {
292
+ for (const item of traversalData(data, "childrenList")) {
293
+ item.name = item[this.treeRenderConfig.title];
294
+ item.code = item[this.treeRenderConfig.key];
295
+ item.isLeaf =
296
+ item.childrenList && item.childrenList.length ? false : true;
297
+ }
298
+ return data;
299
+ },
300
+ // 根据机构id查本身及下级机构
301
+ async getChildrenByOrgPartenId() {
302
+ const {
303
+ success, data
304
+ } = await getChildrenByOrgPartenId(null, this.treeSearchApiConfig);
305
+ if (success) {
306
+ data.forEach(org => {
307
+ org.isOrg = true;
308
+ org.isLeaf = !org.existBck1;
309
+ });
310
+ this.treeData = data;
311
+ }
312
+ },
313
+ // 更新树节点信息
314
+ onLoadData(treeNode) {
315
+ return new Promise(async resolve => {
316
+ if (treeNode.dataRef.isOrg && !treeNode.dataRef.children) {
317
+ const data = await this.getDeptData(treeNode.dataRef.orgId);
318
+ if (data) {
319
+ treeNode.dataRef.children = data;
320
+ }
321
+ resolve();
322
+ return;
323
+ }
324
+ resolve();
325
+ });
326
+ },
327
+ // 获取展开的key
328
+ getExpandKeys(data) {
329
+ const expandKeys = [];
330
+ for (const item of traversalData(data, "childrenList")) {
331
+ // 有子级匹配就展开
332
+ let hasChildMatch = false;
333
+ for (const subItem of traversalData(
334
+ item.childrenList,
335
+ "childrenList"
336
+ )) {
337
+ if (isMatchFn(subItem, this.searchValue)) {
338
+ hasChildMatch = true;
339
+ }
340
+ }
341
+ if (hasChildMatch) {
342
+ expandKeys.push(item.code);
343
+ }
344
+ }
345
+ return expandKeys;
346
+ },
347
+
348
+ changeWidth({ distance }) {
349
+ const w = this.flexWidth + distance;
350
+ this.flexWidth = Math.min(Math.max(w, 50), 1000);
351
+ },
352
+ // 保存拖动的宽度
353
+ saveWidth() {
354
+ this.$emit("saveWidth", this.flexWidth);
355
+ }
356
+ }
357
+ });
358
+ </script>
359
+ <style lang="less" scoped>
360
+ .left-tree-wrap {
361
+ display: flex;
362
+ flex-direction: column;
363
+ position: relative;
364
+ height: 100%;
365
+ padding: 8px;
366
+ box-sizing: border-box;
367
+ background: #fff;
368
+ border-right: 1px solid rgba(0, 0, 0, 0.1);
369
+ .search-groups{
370
+ display: flex;
371
+ align-items: center;
372
+ .ant-input-search{
373
+ flex: 1;
374
+ }
375
+ }
376
+ .tree-wrap{
377
+ margin-top: 8px;
378
+ flex: 1;
379
+ overflow-y: auto;
380
+ /deep/.ant-tree {
381
+ flex: 1;
382
+ overflow-y: auto;
383
+ .ant-tree-switcher {
384
+ width: 10px;
385
+ }
386
+ .ant-tree-title{
387
+ display: flex;
388
+ align-items: center;
389
+ justify-content: space-between;
390
+ width: 100%;
391
+ .tree-left{
392
+ display: flex;
393
+ align-items: center;
394
+ flex: 1;
395
+ .dept-name{
396
+ text-overflow: ellipsis;
397
+ white-space: nowrap;
398
+ overflow: hidden;
399
+ }
400
+ }
401
+ }
402
+ .ant-tree-node-content-wrapper {
403
+ position: relative;
404
+ width: calc(100% - 24px);
405
+ overflow: hidden;
406
+ white-space: nowrap;
407
+ text-overflow: ellipsis;
408
+ .node-action {
409
+ position: absolute;
410
+ right: 0;
411
+ top: 0;
412
+ z-index: 9;
413
+ display: none;
414
+ }
415
+ &:hover .node-action {
416
+ display: block;
417
+ }
418
+ }
419
+ li span[draggable],
420
+ .ant-tree li span[draggable] {
421
+ border: none;
422
+ }
423
+ }
424
+ }
425
+ .table-footer-wrap{
426
+ margin-top: 8px;
427
+ }
428
+ .resizable {
429
+ position: absolute;
430
+ right: -7px;
431
+ bottom: 0;
432
+ width: 14px;
433
+ height: 100%;
434
+ text-align: center;
435
+ z-index: 1;
436
+ cursor: col-resize;
437
+ }
438
+ }
439
+ </style>
@@ -0,0 +1,10 @@
1
+ export function* traversalData(data, children = "children") {
2
+ if (!data || !Array.isArray(data)) return;
3
+ for (let i = 0; i < data.length; i++) {
4
+ yield data[i];
5
+ if (data[i][children]) {
6
+ yield* traversalData(data[i][children], children);
7
+ }
8
+ }
9
+ }
10
+