@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,263 @@
1
+ import { cloneDeep, isArray, isFunction, isString } from 'lodash-es';
2
+ import type { SearchItemData } from './typing';
3
+ import { termType } from './setting';
4
+ import { SearchProps } from './typing';
5
+
6
+ /**
7
+ * 处理like,nlike特殊值
8
+ * @param v
9
+ */
10
+ export const handleLikeValue = (v: string) => {
11
+ if (isString(v)) {
12
+ return v.split('').reduce((pre: string, next: string) => {
13
+ let _next = next;
14
+ if (next === '\\') {
15
+ _next = '\\\\';
16
+ } else if (next === '%') {
17
+ _next = '\\%';
18
+ }
19
+ return pre + _next;
20
+ }, '');
21
+ }
22
+ return v;
23
+ };
24
+
25
+ const handleItemValue = (item, columnOptionMap) => {
26
+ const _item = columnOptionMap.get(item.column);
27
+
28
+ if (!_item) return item;
29
+ if (_item.rename) {
30
+ item.column = _item.rename;
31
+ }
32
+
33
+ if (_item.handleValue && isFunction(_item.handleValue)) {
34
+ item.value = _item.handleValue(item.value, item);
35
+ }
36
+
37
+ if (['like', 'nlike'].includes(item.termType) && !!item.value) {
38
+ item.value = `%${handleLikeValue(item.value)}%`;
39
+ }
40
+
41
+ return item;
42
+ };
43
+
44
+ const isEmpty = (v) => {
45
+ return (
46
+ v === undefined ||
47
+ v === null ||
48
+ v === '' ||
49
+ (isArray(v) && v.length === 0)
50
+ );
51
+ };
52
+
53
+ const handleArrayToTerms = (terms: any[], columnOptionMap) => {
54
+ return terms
55
+ .map((item) => {
56
+ if (item.terms) {
57
+ const filterTerms = item.terms.filter((filterItem) => {
58
+ return (
59
+ filterItem &&
60
+ !isEmpty(filterItem.value) &&
61
+ filterItem.termType !== undefined &&
62
+ filterItem.column !== undefined
63
+ );
64
+ });
65
+ item.terms = filterTerms.map((result) =>
66
+ handleItemValue(result, columnOptionMap),
67
+ );
68
+ }
69
+ return item;
70
+ })
71
+ .filter((item) => item.terms?.length);
72
+ };
73
+
74
+ /**
75
+ * 处理为外部使用
76
+ * @terms {Array} 表单数据
77
+ * @columnOptionMap {Map} column的Map对象
78
+ */
79
+ export const termsParamsFormat = (
80
+ terms,
81
+ columnOptionMap,
82
+ type: string = 'adv',
83
+ searchType: string = 'terms',
84
+ ) => {
85
+ // 过滤掉terms中value无效的item
86
+ const cloneParams = cloneDeep(terms);
87
+ if (searchType === 'terms') {
88
+ return type === 'adv'
89
+ ? { terms: handleArrayToTerms(cloneParams.terms, columnOptionMap) }
90
+ : cloneParams
91
+ .filter(
92
+ (item) =>
93
+ item &&
94
+ !isEmpty(item.value) &&
95
+ item.column !== undefined,
96
+ )
97
+ .map((item) => handleItemValue(item, columnOptionMap));
98
+ } else if (searchType == 'object') {
99
+ const result = {};
100
+ cloneParams
101
+ .filter(
102
+ (item) => item && item.value !== undefined && item.value !== '',
103
+ )
104
+ .forEach((item) => {
105
+ Object.assign(result, { [item.column]: item.value });
106
+ });
107
+ return result;
108
+ }
109
+ };
110
+
111
+ /**
112
+ * TreeSelect过滤
113
+ * @param value 过滤值
114
+ * @param treeNode
115
+ * @param key
116
+ */
117
+ export const filterTreeSelectNode = (
118
+ value: string,
119
+ treeNode: any,
120
+ key: string = 'name',
121
+ ): boolean => {
122
+ return treeNode[key]?.includes(value);
123
+ };
124
+
125
+ /**
126
+ * Select过滤
127
+ * @param value 过滤值
128
+ * @param option
129
+ * @param key
130
+ */
131
+ export const filterSelectNode = (
132
+ value: string,
133
+ option: any,
134
+ key: string = 'label',
135
+ ): boolean => {
136
+ return option[key]?.includes(value);
137
+ };
138
+
139
+ export const handleQData = (terms: any): any => {
140
+ // 排序, null 往后放
141
+ terms.terms.forEach((a) => {
142
+ for (let i = 0; i < a.terms.length; i++) {
143
+ for (let j = 0; j < a.terms.length - i - 1; j++) {
144
+ if (!a.terms[j] && a.terms[j + 1]) {
145
+ const temp = a.terms[j];
146
+ a.terms[j] = a.terms[j + 1];
147
+ a.terms[j + 1] = temp;
148
+ }
149
+ }
150
+ }
151
+ });
152
+
153
+ return terms;
154
+ };
155
+
156
+ export const hasExpand = (terms): boolean => {
157
+ let itemCount = 0;
158
+ terms.forEach((a) => {
159
+ a.terms.forEach((b) => {
160
+ if (b) {
161
+ itemCount += 1;
162
+ }
163
+ });
164
+ });
165
+ return itemCount >= 2;
166
+ };
167
+
168
+ export const compatibleOldTerms = (q: string) => {
169
+ const _terms = [
170
+ { terms: [null, null, null] },
171
+ { terms: [null, null, null], type: 'and' },
172
+ ];
173
+
174
+ try {
175
+ const terms = JSON.parse(q || '{}');
176
+ terms.terms?.forEach((a, aIndex) => {
177
+ a?.terms?.forEach((b, bIndex) => {
178
+ _terms[aIndex].terms[bIndex] = b;
179
+ });
180
+ if (a.type) {
181
+ _terms[aIndex].type = a.type;
182
+ }
183
+ });
184
+ return { terms: _terms };
185
+ } catch (e) {
186
+ return { terms: _terms };
187
+ }
188
+ };
189
+
190
+ export const handleParamsToString = (
191
+ terms: SearchItemData[] = [],
192
+ type: string = 'and',
193
+ ) => {
194
+ const _terms = [
195
+ { terms: [null, null, null] },
196
+ { terms: [null, null, null], type: type },
197
+ ];
198
+ let termsIndex = 0;
199
+ let termsStar = 0;
200
+ terms.forEach((item, index) => {
201
+ if (index > 2) {
202
+ termsIndex = 1;
203
+ termsStar = 4;
204
+ }
205
+ _terms[termsIndex].terms[index - termsStar] = item;
206
+ });
207
+
208
+ return JSON.stringify({ terms: _terms });
209
+ };
210
+
211
+ export const getTermTypeFn = (type?: SearchProps['type'], column?: string) => {
212
+ // if (column?.includes('id') && type === 'string') {
213
+ // // 默认id为 eq
214
+ // return 'eq';
215
+ // }
216
+
217
+ switch (type) {
218
+ case 'select':
219
+ case 'treeSelect':
220
+ case 'number':
221
+ return 'eq';
222
+ case 'date':
223
+ case 'time':
224
+ return 'gt';
225
+ case 'timeRange':
226
+ case 'rangePicker':
227
+ return 'btw';
228
+ default:
229
+ return 'like';
230
+ }
231
+ };
232
+
233
+ export const getTermTypes = (types: string[]) => {
234
+ return termType.filter((item) => types.includes(item.value));
235
+ };
236
+
237
+ export const getTermOptions = (type?: SearchProps['type'], column?: string) => {
238
+ let keys: string[] = [];
239
+ switch (type) {
240
+ case 'select':
241
+ case 'treeSelect':
242
+ keys = ['not', 'eq', 'in', 'nin'];
243
+ break;
244
+ case 'time':
245
+ case 'date':
246
+ keys = ['gt', 'lt', 'gte', 'lte'];
247
+ break;
248
+ case 'timeRange':
249
+ case 'rangePicker':
250
+ keys = ['btw', 'nbtw'];
251
+ break;
252
+ case 'number':
253
+ keys = ['eq', 'not', 'gt', 'lt', 'gte', 'lte'];
254
+ break;
255
+ default:
256
+ keys = ['like', 'nlike'];
257
+ // column?.includes('id') && type === 'string'
258
+ // ? ['eq']
259
+ // : ['like', 'nlike'];
260
+ break;
261
+ }
262
+ return keys.length ? getTermTypes(keys) : termType;
263
+ };
@@ -1,102 +1,117 @@
1
1
  <!-- 参数类型输入组件 -->
2
2
  <template>
3
3
  <div class="value-item-warp">
4
- <j-select
4
+ <Select
5
5
  v-if="typeMap.get(itemType) === 'select'"
6
6
  v-model:value="myValue"
7
7
  allowClear
8
- @change="(_, options) => onChange(options)"
9
8
  v-bind="props"
9
+ @change="(_, options) => onChange(options)"
10
10
  />
11
- <j-date-picker
11
+ <DatePicker
12
12
  v-else-if="typeMap.get(itemType) === 'date'"
13
- :valueFormat="valueFormat || 'YYYY-MM-DD HH:mm:ss'"
14
13
  v-model:value="myValue"
14
+ :valueFormat="valueFormat || 'YYYY-MM-DD HH:mm:ss'"
15
15
  allowClear
16
16
  showTime
17
+ v-bind="props"
17
18
  @change="onChange"
18
19
  />
19
- <j-input-number
20
- v-else-if="typeMap.get(itemType) === 'inputNumber'"
21
- v-bind="props"
20
+ <TimePicker
21
+ v-else-if="typeMap.get(itemType) === 'time'"
22
22
  v-model:value="myValue"
23
+ :valueFormat="valueFormat || 'HH:mm:ss'"
23
24
  allowClear
25
+ v-bind="props"
24
26
  @change="onChange"
25
27
  />
26
- <j-input
28
+ <InputNumber
29
+ v-else-if="typeMap.get(itemType) === 'inputNumber'"
30
+ v-model:value="myValue"
27
31
  allowClear
28
32
  v-bind="props"
33
+ @change="onChange"
34
+ />
35
+ <Input
29
36
  v-else-if="typeMap.get(itemType) === 'object'"
30
37
  v-model:value="myValue"
38
+ allowClear
39
+ v-bind="props"
31
40
  @change="onChange"
32
41
  >
33
42
  <template #addonAfter>
34
43
  <AIcon type="FormOutlined" @click="modalVisible = true" />
35
44
  </template>
36
- </j-input>
37
- <GeoComponent
38
- v-else-if="typeMap.get(itemType) === 'geoPoint'"
39
- v-model:point="myValue"
40
- @change="onChange"
41
- v-bind="props"
42
- />
43
- <j-input
45
+ </Input>
46
+ <Input
44
47
  v-else-if="typeMap.get(itemType) === 'file'"
45
48
  v-model:value="myValue"
46
- placeholder="请输入链接"
47
49
  allowClear
50
+ placeholder="请输入链接"
51
+ v-bind="props"
48
52
  @change="onChange"
49
53
  >
50
54
  <template #addonAfter>
51
- <j-upload
52
- name="file"
55
+ <Upload
53
56
  :action="action"
54
57
  :headers="headers"
55
58
  :showUploadList="false"
59
+ name="file"
56
60
  @change="handleFileChange"
57
61
  >
58
62
  <AIcon type="UploadOutlined" />
59
- </j-upload>
63
+ </Upload>
60
64
  </template>
61
- </j-input>
62
- <j-input-password
65
+ </Input>
66
+ <InputPassword
63
67
  v-else-if="typeMap.get(itemType) === 'password'"
68
+ v-model:value="myValue"
64
69
  allowClear
65
- v-bind="props"
66
70
  type="password"
67
- v-model:value="myValue"
71
+ v-bind="props"
68
72
  @change="onChange"
69
73
  />
70
- <j-input
74
+ <Input
71
75
  v-else
76
+ v-model:value="myValue"
72
77
  allowClear
73
- v-bind="props"
74
78
  type="text"
75
- v-model:value="myValue"
79
+ v-bind="props"
76
80
  @change="onChange"
77
81
  />
78
82
 
79
83
  <!-- 代码编辑器弹窗 -->
80
- <j-modal
81
- title="编辑"
82
- ok-text="确认"
83
- cancel-text="取消"
84
+ <Modal
84
85
  v-model:visible="modalVisible"
86
+ :zIndex="1100"
87
+ cancel-text="取消"
88
+ ok-text="确认"
89
+ title="编辑"
85
90
  width="700px"
86
91
  @cancel="modalVisible = false"
87
92
  @ok="handleItemModalSubmit"
88
- :zIndex="1100"
89
93
  >
90
94
  <div style="width: 100%; height: 300px">
91
- <JMonacoEditor v-model:modelValue="objectValue" />
95
+ <MonacoEditor v-model:modelValue="objectValue" />
92
96
  </div>
93
- </j-modal>
97
+ </Modal>
94
98
  </div>
95
99
  </template>
96
100
 
97
- <script setup lang="ts">
101
+ <script lang="ts" setup>
98
102
  import { CSSProperties, PropType, ref, watch } from 'vue'
99
103
  import { componentsType } from './util'
104
+ import { MonacoEditor } from '../../'
105
+ import {
106
+ Select,
107
+ DatePicker,
108
+ TimePicker,
109
+ Input,
110
+ InputNumber,
111
+ InputPassword,
112
+ Upload,
113
+ Modal,
114
+ } from 'ant-design-vue'
100
115
 
101
116
  type Emits = {
102
117
  (e: 'update:modelValue', data: string | number | boolean): void
@@ -9,7 +9,8 @@ export const componentsType = {
9
9
  enum: 'select',
10
10
  boolean: 'select',
11
11
  date: 'date',
12
+ time: 'time',
12
13
  object: 'object',
13
14
  geoPoint: 'geoPoint',
14
15
  file: 'file',
15
- }
16
+ }
@@ -0,0 +1,3 @@
1
+ import '../ProLayout/style'
2
+ import '../ProTable/style'
3
+ import '../ProLayout/style'
@@ -0,0 +1,4 @@
1
+ @import 'ant-design-vue/lib/style/themes/index.less';
2
+
3
+ @text-color-title: #000;
4
+ @text-color-subtitle: #263237;
@@ -1,139 +0,0 @@
1
- <!-- 坐标点拾取组件 -->
2
- <template>
3
- <div class="page-container">
4
- <j-input allowClear v-bind="props" v-model:value="inputPoint">
5
- <template #addonAfter>
6
- <AIcon type="EnvironmentOutlined" @click="modalVisible = true" />
7
- </template>
8
- </j-input>
9
- <j-modal
10
- title="地理位置"
11
- ok-text="确认"
12
- cancel-text="取消"
13
- v-model:visible="modalVisible"
14
- width="700px"
15
- @cancel="modalVisible = false"
16
- @ok="handleModalSubmit"
17
- destroyOnClose
18
- >
19
- <div style="width: 100%; height: 400px">
20
- <div style="margin-bottom: 10px;">地理位置:{{ mapPoint }}</div>
21
- <el-amap
22
- :center="_center"
23
- :zoom="_zoom"
24
- @init="initMap"
25
- @click="clickMap"
26
- >
27
- <el-amap-search-box visible @select="selectPosition" />
28
- <el-amap-marker :position="position" />
29
- </el-amap>
30
- </div>
31
- </j-modal>
32
- </div>
33
- </template>
34
-
35
- <script setup lang="ts">
36
- import { store } from '@jetlinks-web/stores'
37
- import { initAMapApiLoader } from '@vuemap/vue-amap'
38
- import '@vuemap/vue-amap/dist/style.css'
39
- import { computed, CSSProperties, PropType, ref } from 'vue'
40
-
41
- interface AMapProps {
42
- style?: CSSProperties
43
- class?: string
44
- AMapUI?: string | boolean
45
- plugins?: string[]
46
- }
47
-
48
- const systemStore = store.SystemStore
49
-
50
- const amapKey = systemStore.systemInfo.apiKey
51
-
52
- interface EmitProps {
53
- (e: 'update:point', data: string): void
54
- (e: 'change', data: string): void
55
- }
56
- const props = defineProps({
57
- style: Object as PropType<AMapProps['style']>,
58
- class: String as PropType<AMapProps['class']>,
59
- AMapUI: [String, Boolean],
60
- center: Array as PropType<number[]>,
61
- plugin: Array,
62
- zoom: {
63
- type: Number,
64
- default: 12,
65
- },
66
- securityJsCode: String,
67
- point: { type: [Number, String], default: '' },
68
- })
69
- const emit = defineEmits<EmitProps>()
70
-
71
-
72
- initAMapApiLoader({
73
- key: amapKey,
74
- securityJsCode: props.securityJsCode
75
- })
76
-
77
- // 手动输入的坐标点(经纬度字符串)
78
- const inputPoint = computed({
79
- get: () => {
80
- return props.point
81
- },
82
- set: (val: any) => {
83
- mapPoint.value = val
84
- emit('update:point', val)
85
- emit('change', val)
86
- },
87
- })
88
-
89
- // 地图弹窗
90
- const modalVisible = ref<boolean>(false)
91
-
92
- const handleModalSubmit = () => {
93
- inputPoint.value = mapPoint.value
94
- modalVisible.value = false
95
- }
96
-
97
- // 地图拾取的坐标点(经纬度字符串)
98
- const mapPoint = ref('')
99
-
100
- const _zoom = ref<number>(props.zoom)
101
- const _center = ref<number[]>(props?.center || [])
102
- let map: any = null
103
-
104
- // 地图经纬度
105
- const position = ref<number[] | string[]>([])
106
-
107
- /**
108
- * 地图初始化
109
- * @param e
110
- */
111
- const initMap = (e: any) => {
112
- map = e
113
-
114
- const pointStr = mapPoint.value as string
115
- position.value = pointStr ? pointStr.split(',') : _center.value
116
- }
117
-
118
- /**
119
- * 地图点击
120
- * @param e
121
- */
122
- const clickMap = (e: any) => {
123
- mapPoint.value = `${e.lnglat.lng},${e.lnglat.lat}`
124
- position.value = [e.lnglat.lng, e.lnglat.lat]
125
- }
126
-
127
- /**
128
- * 选择搜索结果
129
- * @param e
130
- */
131
- const selectPosition = (e: any) => {
132
- const selectPoint = [e.poi.location.lng, e.poi.location.lat]
133
- map.setCenter(selectPoint)
134
- mapPoint.value = selectPoint.join(',')
135
- position.value = selectPoint
136
- }
137
- </script>
138
-
139
- <style lang="less" scoped></style>
@@ -1,3 +0,0 @@
1
- import GeoComponent from './GeoComponent.vue'
2
-
3
- export default GeoComponent
@@ -1,20 +0,0 @@
1
- import {watch, ref} from 'vue'
2
- import type { Ref } from 'vue'
3
- import { store } from '@jetlinks-web/stores'
4
- import {isBoolean} from "lodash-es";
5
-
6
- export const usePermission = (code?: string | string[] | boolean): {
7
- hasPerm: Ref<boolean>
8
- } => {
9
- const hasPerm = ref(false)
10
-
11
- watch(() => code, () => {
12
- if (code) {
13
- hasPerm.value = isBoolean(code) ? code : store.AuthStore.hasPermission(code)
14
- }
15
- }, { immediate: true })
16
-
17
- return {
18
- hasPerm
19
- }
20
- }