@jetlinks-web/components 1.0.4 → 2.0.0

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 (80) hide show
  1. package/index.ts +54 -15
  2. package/package.json +9 -6
  3. package/src/AMap/Map.vue +110 -107
  4. package/src/BadgeStatus/Badge.vue +41 -40
  5. package/src/BadgeStatus/color.ts +25 -23
  6. package/src/CardSelect/CardSelect.vue +136 -0
  7. package/src/CardSelect/index.ts +3 -0
  8. package/src/CheckButton/CheckButton.vue +146 -0
  9. package/src/CheckButton/index.md +27 -0
  10. package/src/CheckButton/index.ts +3 -0
  11. package/src/ConfigProvider/context.ts +17 -0
  12. package/src/ConfigProvider/index.tsx +42 -0
  13. package/src/Echarts/Echarts.vue +43 -43
  14. package/src/Ellipsis/Ellipsis.vue +182 -0
  15. package/src/Ellipsis/index.ts +3 -0
  16. package/src/Empty/Empty.vue +43 -0
  17. package/src/Empty/image.ts +3 -0
  18. package/src/Empty/index.ts +2 -0
  19. package/src/FullPage/{index.vue → FullPage.vue} +30 -27
  20. package/src/FullPage/index.ts +3 -0
  21. package/src/Icon/icon.tsx +40 -0
  22. package/src/Icon/index.ts +3 -0
  23. package/src/MonacoEditor/Monaco.vue +242 -0
  24. package/src/MonacoEditor/index.md +26 -0
  25. package/src/MonacoEditor/index.ts +2 -0
  26. package/src/PermissionButton/index.tsx +95 -92
  27. package/src/ProLayout/Basic/BasicLayout.less +66 -0
  28. package/src/ProLayout/Basic/BasicLayout.tsx +392 -0
  29. package/src/ProLayout/Basic/Header.less +8 -0
  30. package/src/ProLayout/Basic/Header.tsx +115 -0
  31. package/src/ProLayout/PageContainer/index.less +103 -0
  32. package/src/ProLayout/PageContainer/index.tsx +441 -0
  33. package/src/ProLayout/PageContainer/typings.ts +56 -0
  34. package/src/ProLayout/RouteContext.ts +87 -0
  35. package/src/ProLayout/SiderMenu/BaseMenu.tsx +296 -0
  36. package/src/ProLayout/SiderMenu/SiderMenu.tsx +320 -0
  37. package/src/ProLayout/SiderMenu/index.less +212 -0
  38. package/src/ProLayout/SiderMenu/index.ts +2 -0
  39. package/src/ProLayout/SiderMenu/typings.ts +49 -0
  40. package/src/ProLayout/TopHeader/index.less +174 -0
  41. package/src/ProLayout/TopHeader/index.tsx +210 -0
  42. package/src/ProLayout/defaultSettings.ts +106 -0
  43. package/src/ProLayout/index.ts +6 -0
  44. package/src/ProLayout/style/default.less +4 -0
  45. package/src/ProLayout/style/index.ts +1 -0
  46. package/src/ProLayout/style/style.less +7 -0
  47. package/src/ProLayout/typings.ts +87 -0
  48. package/src/ProLayout/util.ts +64 -0
  49. package/src/ProTable/index.md +53 -0
  50. package/src/ProTable/index.tsx +551 -0
  51. package/src/ProTable/proTableTypes.ts +70 -0
  52. package/src/ProTable/style/index.less +92 -0
  53. package/src/ProTable/style/index.ts +1 -0
  54. package/src/Scrollbar/Bar.vue +75 -0
  55. package/src/Scrollbar/Scrollbar.vue +260 -0
  56. package/src/Scrollbar/Thumb.vue +163 -0
  57. package/src/Scrollbar/constants.ts +10 -0
  58. package/src/Scrollbar/index.ts +4 -0
  59. package/src/Scrollbar/scrollbar.ts +108 -0
  60. package/src/Scrollbar/thumb.ts +16 -0
  61. package/src/Scrollbar/util.ts +38 -0
  62. package/src/Search/Advanced/History.vue +140 -0
  63. package/src/Search/Advanced/SaveHistory.vue +108 -0
  64. package/src/Search/Advanced/index.vue +435 -0
  65. package/src/Search/Item.vue +525 -0
  66. package/src/Search/Search.vue +398 -0
  67. package/src/Search/hooks/index.ts +1 -0
  68. package/src/Search/hooks/useSearchItems.ts +68 -0
  69. package/src/Search/index.md +57 -0
  70. package/src/Search/index.ts +5 -0
  71. package/src/Search/setting.ts +55 -0
  72. package/src/Search/typing.ts +76 -0
  73. package/src/Search/util.ts +263 -0
  74. package/src/ValueItem/ValueItem.vue +50 -35
  75. package/src/ValueItem/util.ts +2 -1
  76. package/src/style/index.ts +3 -0
  77. package/src/style/variable.less +4 -0
  78. package/src/GeoComponent/GeoComponent.vue +0 -139
  79. package/src/GeoComponent/index.ts +0 -3
  80. package/src/PermissionButton/hooks.ts +0 -20
@@ -0,0 +1,525 @@
1
+ <template>
2
+ <div class="JSearch-item">
3
+ <template v-if="!onlyValue">
4
+ <div v-if="expand" class="JSearch-item--type">
5
+ <Select
6
+ v-if="index !== 1 && index !== 4"
7
+ v-model:value="termsModel.type"
8
+ :options="typeOptions"
9
+ style="width: 100%"
10
+ @change="valueChange"
11
+ />
12
+ <span v-else>
13
+ {{ index === 1 ? '第一组' : '第二组' }}
14
+ </span>
15
+ </div>
16
+ <Select
17
+ v-model:value="termsModel.column"
18
+ placeholder="请选择"
19
+ class="JSearch-item--column"
20
+ :options="columnOptions"
21
+ @change="columnChange"
22
+ />
23
+ <Select
24
+ v-model:value="termsModel.termType"
25
+ placeholder="请选择"
26
+ class="JSearch-item--termType"
27
+ :options="termTypeOptions.option"
28
+ @change="termTypeChange"
29
+ />
30
+ </template>
31
+ <template v-else>
32
+ <div
33
+ class="JSearch-item--label"
34
+ :style="{ minWidth: `${labelWidth}px` }"
35
+ >
36
+ {{
37
+ columnOptions.length ? columnOptions[index - 1]?.label : ''
38
+ }}
39
+ </div>
40
+ </template>
41
+ <div class="JSearch-item--value">
42
+ <FormItem no-style>
43
+ <Input
44
+ v-if="component === componentType.input"
45
+ v-model:value="termsModel.value"
46
+ allow-clear
47
+ v-bind="cProps"
48
+ style="width: 100%"
49
+ @change="valueChange"
50
+ />
51
+ <Select
52
+ v-else-if="component === componentType.select"
53
+ v-model:value="termsModel.value"
54
+ allow-clear
55
+ show-search
56
+ :mode="isBtw ? 'multiple' : 'combobox'"
57
+ v-bind="cProps"
58
+ style="width: 100%; min-width: 80px"
59
+ :loading="optionLoading"
60
+ :options="options"
61
+ :filter-option="
62
+ (v, option) => filterSelectNode(v, option, 'label')
63
+ "
64
+ @change="valueChange"
65
+ />
66
+ <InputNumber
67
+ v-else-if="component === componentType.inputNumber"
68
+ v-model:value="termsModel.value"
69
+ allow-clear
70
+ v-bind="cProps"
71
+ style="width: 100%"
72
+ @change="valueChange"
73
+ />
74
+ <InputPassword
75
+ v-else-if="component === componentType.password"
76
+ v-model:value="termsModel.value"
77
+ allow-clear
78
+ v-bind="cProps"
79
+ style="width: 100%"
80
+ @change="valueChange"
81
+ />
82
+ <TimePicker
83
+ v-else-if="component === componentType.time"
84
+ v-model:value="termsModel.value"
85
+ allow-clear
86
+ value-format="HH:mm:ss"
87
+ style="width: 100%"
88
+ v-bind="cProps"
89
+ @change="valueChange"
90
+ />
91
+ <TimeRangePicker
92
+ v-else-if="component === componentType.timeRange"
93
+ v-model:value="termsModel.value"
94
+ allow-clear
95
+ value-format="HH:mm:ss"
96
+ style="width: 100%"
97
+ v-bind="cProps"
98
+ @change="valueChange"
99
+ />
100
+ <DatePicker
101
+ v-else-if="component === componentType.date"
102
+ v-model:value="termsModel.value"
103
+ allow-clear
104
+ show-time
105
+ value-format="YYYY-MM-DD HH:mm:ss"
106
+ style="width: 100%"
107
+ v-bind="cProps"
108
+ @change="valueChange"
109
+ />
110
+ <RangePicker
111
+ v-else-if="component === componentType.rangePicker"
112
+ v-model:value="termsModel.value"
113
+ allow-clear
114
+ show-time
115
+ value-format="YYYY-MM-DD HH:mm:ss"
116
+ style="width: 100%"
117
+ v-bind="cProps"
118
+ @change="valueChange"
119
+ />
120
+ <TreeSelect
121
+ v-else-if="component === componentType.treeSelect"
122
+ v-model:value="termsModel.value"
123
+ allow-clear
124
+ show-search
125
+ style="width: 100%"
126
+ :height="350"
127
+ :field-names="{ label: 'name', value: 'id' }"
128
+ :multiple="isBtw"
129
+ :filter-tree-node="
130
+ (v, option) => filterTreeSelectNode(v, option)
131
+ "
132
+ v-bind="cProps"
133
+ :tree-data="options"
134
+ @change="valueChange"
135
+ />
136
+ <component
137
+ :is="componentName"
138
+ v-else-if="
139
+ component === componentType.component && componentName
140
+ "
141
+ v-bind="cProps"
142
+ v-model:value="termsModel.value"
143
+ @change="valueChange"
144
+ />
145
+ </FormItem>
146
+ </div>
147
+ </div>
148
+ </template>
149
+
150
+ <script setup lang="ts" name="SearchItem">
151
+ import { typeOptions, termType, componentType, optionsMapKey } from './setting';
152
+ import type { PropType } from 'vue';
153
+ import { ref, reactive, nextTick, watch, computed, inject } from 'vue';
154
+ import type { SearchItemData, SearchProps } from './typing';
155
+ import { cloneDeep, debounce, isArray, isFunction, omit } from 'lodash-es';
156
+ import {
157
+ filterTreeSelectNode,
158
+ filterSelectNode,
159
+ getTermTypeFn,
160
+ getTermOptions,
161
+ getTermTypes,
162
+ } from './util';
163
+ import {
164
+ TreeSelect,
165
+ Select,
166
+ Input,
167
+ InputNumber,
168
+ DatePicker,
169
+ TimePicker,
170
+ InputPassword,
171
+ RangePicker,
172
+ TimeRangePicker,
173
+ FormItem
174
+ } from 'ant-design-vue'
175
+ import { isPromise } from '@jetlinks-web/utils';
176
+
177
+ type ItemType = SearchProps['type'];
178
+
179
+ type UrlParam = {
180
+ q: string | null;
181
+ target: string | null;
182
+ };
183
+
184
+ interface Emit {
185
+ (e: 'change', data: SearchItemData): void;
186
+ }
187
+
188
+ const props = defineProps({
189
+ columns: {
190
+ type: Array as PropType<SearchProps[]>,
191
+ default: () => [],
192
+ required: true,
193
+ },
194
+ index: {
195
+ type: Number,
196
+ default: 1,
197
+ },
198
+ expand: {
199
+ type: Boolean,
200
+ default: false,
201
+ },
202
+ termsItem: {
203
+ type: Object as PropType<SearchItemData>,
204
+ default: () => ({}),
205
+ },
206
+ componentProps: {
207
+ type: Object,
208
+ default: () => ({}),
209
+ },
210
+ onlyValue: {
211
+ type: Boolean,
212
+ default: false,
213
+ },
214
+ reset: {
215
+ type: Number,
216
+ default: 1,
217
+ },
218
+ labelWidth: {
219
+ type: Number,
220
+ default: 40,
221
+ },
222
+ });
223
+
224
+ type optionItemType = { label: string; value: any };
225
+
226
+ const emit = defineEmits<Emit>();
227
+
228
+ const termsModel = reactive<SearchItemData>({
229
+ type: props.termsItem?.type || 'or',
230
+ value: props.termsItem?.value || '',
231
+ termType: props.termsItem?.termType || 'like',
232
+ column: props.termsItem?.column || undefined,
233
+ });
234
+
235
+ const isBtw = computed(() => {
236
+ return ['in', 'nin'].includes(termsModel.termType);
237
+ });
238
+
239
+ const component = ref(componentType.input);
240
+ const componentName = ref();
241
+ const cProps = ref({});
242
+
243
+ const options = ref<any[]>([]);
244
+
245
+ const columnOptions = ref<optionItemType[]>([]);
246
+ const columnOptionMap = inject(optionsMapKey, new Map());
247
+
248
+ const termTypeOptions = reactive({option: termType});
249
+
250
+ const optionLoading = ref(false);
251
+
252
+ /**
253
+ * 根据类型切换默termType值
254
+ * @param type {}
255
+ * @param column {}
256
+ * @param options {}
257
+ * @param defaultTermType {}
258
+ */
259
+ const getTermType = (
260
+ type?: ItemType,
261
+ column?: string,
262
+ options?: string[],
263
+ defaultTermType?: string,
264
+ termFilter?: string[],
265
+ ) => {
266
+ termTypeOptions.option = options?.length
267
+ ? getTermTypes(options)
268
+ : getTermOptions(type, column);
269
+ if (termFilter?.length) {
270
+ termTypeOptions.option = termTypeOptions.option.filter(
271
+ (item) => !termFilter.includes(item.value),
272
+ );
273
+ }
274
+ return defaultTermType || options?.length
275
+ ? termTypeOptions.option[0].value
276
+ : getTermTypeFn(type, column);
277
+ };
278
+
279
+ /**
280
+ * 根据类型返回组件
281
+ * @param type
282
+ */
283
+ const getComponent = (type?: ItemType) => {
284
+ switch (type) {
285
+ case 'select':
286
+ component.value = componentType.select;
287
+ break;
288
+ case 'treeSelect':
289
+ component.value = componentType.treeSelect;
290
+ break;
291
+ case 'date':
292
+ component.value = componentType.date;
293
+ break;
294
+ case 'time':
295
+ component.value = componentType.time;
296
+ break;
297
+ case 'number':
298
+ component.value = componentType.inputNumber;
299
+ break;
300
+ case 'timeRange':
301
+ component.value = componentType.timeRange;
302
+ break;
303
+ case 'rangePicker':
304
+ component.value = componentType.rangePicker;
305
+ break;
306
+ case 'component':
307
+ component.value = componentType.component;
308
+ break;
309
+ default:
310
+ component.value = componentType.input;
311
+ break;
312
+ }
313
+ };
314
+
315
+ const removeOptionByKey = (options: any[]): any[] => {
316
+ return options.map((item) => {
317
+ if (item.children) {
318
+ item.children = removeOptionByKey(item.children);
319
+ }
320
+ return omit(item, ['key']);
321
+ });
322
+ };
323
+
324
+ const handleItemOptions = debounce((option?: any[] | Function) => {
325
+ options.value = [];
326
+ if (isArray(option)) {
327
+ options.value = option;
328
+ } else if (isFunction(option)) {
329
+ optionLoading.value = true;
330
+ const fn = option();
331
+ if (isPromise(fn)) {
332
+ (fn as Promise<any>)
333
+ .then((res: any[]) => {
334
+ optionLoading.value = false;
335
+ options.value = removeOptionByKey(res);
336
+ })
337
+ .catch((_: any) => {
338
+ optionLoading.value = false;
339
+ });
340
+ } else {
341
+ optionLoading.value = false;
342
+ options.value = removeOptionByKey(fn || []);
343
+ }
344
+ }
345
+ }, 100);
346
+
347
+ const initModel = () => {
348
+ termsModel.type = 'or';
349
+ termsModel.column = undefined;
350
+ termsModel.value = undefined;
351
+ termsModel.termType = undefined;
352
+ termTypeOptions.option = termType;
353
+ };
354
+ const columnChange = (
355
+ value: string,
356
+ isChange: boolean,
357
+ changeValue: boolean = true,
358
+ ) => {
359
+ const item = columnOptionMap.value?.get(value);
360
+
361
+ if (!item) {
362
+ initModel();
363
+ return;
364
+ }
365
+ cProps.value = item.componentProps;
366
+ optionLoading.value = false;
367
+ // 设置value为undefined
368
+ termsModel.column = value;
369
+ getComponent(item.type); // 处理Item的组件类型
370
+ componentName.value = item.components;
371
+
372
+ // 处理options 以及 request
373
+
374
+ if ('options' in item) {
375
+ handleItemOptions(item.options);
376
+ }
377
+
378
+ const termsTypeValue = getTermType(
379
+ item.type,
380
+ value,
381
+ item.termOptions,
382
+ item.defaultTermType,
383
+ item.termFilter,
384
+ );
385
+
386
+ if (changeValue) {
387
+ termsModel.value = undefined;
388
+ termsModel.termType = termsTypeValue;
389
+ }
390
+
391
+ if (isChange) {
392
+ valueChange();
393
+ }
394
+ };
395
+
396
+ const handleItem = () => {
397
+ columnOptions.value = [];
398
+ if (!props.columns.length) return;
399
+ columnOptions.value = props.columns.map((item) => {
400
+ // 对columns进行Map处理以及值处理
401
+ return {
402
+ label: item.title,
403
+ value: item.column,
404
+ };
405
+ });
406
+ console.log(props.onlyValue);
407
+ if (!props.onlyValue) {
408
+ // 获取第一个值
409
+ const sortColumn = cloneDeep(props.columns);
410
+ sortColumn?.sort((a, b) => a.sortIndex! - b.sortIndex!);
411
+
412
+ const _index =
413
+ props.index > sortColumn.length
414
+ ? sortColumn.length - 1
415
+ : props.index;
416
+
417
+ if (props.index <= sortColumn.length) {
418
+ const _itemColumn = sortColumn[_index - 1];
419
+ columnChange(_itemColumn.column as string, false);
420
+ } else {
421
+ columnChange(null, false);
422
+ }
423
+ } else {
424
+ columnChange(props.columns[props.index - 1]?.column as string, false);
425
+ }
426
+ };
427
+
428
+ const termTypeChange = (v) => {
429
+ const isOldValueMultiple = ['in', 'nin'].includes(
430
+ props.termsItem?.termType,
431
+ );
432
+ const isValueMultiple = ['in', 'nin'].includes(v);
433
+
434
+ if (isOldValueMultiple !== isValueMultiple) {
435
+ termsModel.value = isValueMultiple ? [] : undefined;
436
+ }
437
+ valueChange();
438
+ };
439
+
440
+ const valueChange = () => {
441
+ emit('change', {
442
+ type: props.onlyValue ? 'and' : termsModel.type || 'or',
443
+ value: termsModel.value,
444
+ termType: termsModel.termType || 'like',
445
+ column: termsModel.column,
446
+ });
447
+ };
448
+
449
+ const reset = () => {
450
+ termsModel.value = undefined;
451
+ };
452
+
453
+ watch(
454
+ () => props.columns,
455
+ () => {
456
+ console.log(props.columns);
457
+ if (props.columns) {
458
+ handleItem();
459
+ }
460
+ },
461
+ {immediate: true, deep: true},
462
+ );
463
+
464
+ watch(
465
+ () => props.termsItem,
466
+ (val, oldVal) => {
467
+ if (val?.column) {
468
+ nextTick(() => {
469
+ Object.keys(props.termsItem).forEach((key) => {
470
+ termsModel[key] = props.termsItem[key];
471
+ if (key === 'column' && val?.column !== oldVal?.column) {
472
+ columnChange(
473
+ props.termsItem.column as string,
474
+ false,
475
+ false,
476
+ );
477
+ }
478
+ });
479
+ });
480
+ } else {
481
+ handleItem();
482
+ }
483
+ },
484
+ {immediate: true, deep: true},
485
+ );
486
+ </script>
487
+
488
+ <style scoped lang="less">
489
+ .JSearch-item {
490
+ display: flex;
491
+ gap: 16px;
492
+ align-items: center;
493
+
494
+ .JSearch-item--type {
495
+ width: 90px;
496
+ min-width: 0;
497
+
498
+ > span {
499
+ line-height: 34px;
500
+ font-weight: bold;
501
+ }
502
+ }
503
+
504
+ .JSearch-item--column {
505
+ width: 130px;
506
+ min-width: 0;
507
+ }
508
+
509
+ .JSearch-item--termType {
510
+ width: 110px;
511
+ min-width: 0;
512
+ }
513
+
514
+ .JSearch-item--label {
515
+ min-width: 40px;
516
+ }
517
+
518
+ .JSearch-item--value {
519
+ display: flex;
520
+ width: 0;
521
+ flex-grow: 1;
522
+ }
523
+ }
524
+
525
+ </style>