@jzt-packages/components 1.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 (145) hide show
  1. package/package.json +68 -0
  2. package/src/JztBackTop/index.vue +255 -0
  3. package/src/JztButtonList/index.vue +88 -0
  4. package/src/JztChart/index.vue +95 -0
  5. package/src/JztCharts/index.vue +317 -0
  6. package/src/JztClassTabs/index.vue +156 -0
  7. package/src/JztDateSelect/dateSelect.vue +186 -0
  8. package/src/JztDateSelect/dateType.vue +54 -0
  9. package/src/JztDateSelect/index.ts +135 -0
  10. package/src/JztDateSelect/interface/index.ts +13 -0
  11. package/src/JztDialog/index.vue +249 -0
  12. package/src/JztEllipsisTooltip/index.vue +61 -0
  13. package/src/JztEmpty/index.vue +45 -0
  14. package/src/JztErrorPage/403.vue +30 -0
  15. package/src/JztErrorPage/404.vue +19 -0
  16. package/src/JztErrorPage/500.vue +18 -0
  17. package/src/JztErrorPage/assets/401.png +0 -0
  18. package/src/JztErrorPage/assets/403.png +0 -0
  19. package/src/JztErrorPage/assets/404.png +0 -0
  20. package/src/JztErrorPage/assets/500.png +0 -0
  21. package/src/JztErrorPage/index.scss +35 -0
  22. package/src/JztErrorPage/index.vue +35 -0
  23. package/src/JztFilePreview/components/pdfViewer.vue +221 -0
  24. package/src/JztFilePreview/hooks/useImageMethod.ts +256 -0
  25. package/src/JztFilePreview/index.scss +171 -0
  26. package/src/JztFilePreview/index.vue +68 -0
  27. package/src/JztFilePreview/interface/index.ts +18 -0
  28. package/src/JztFilePreview/previewFile.vue +371 -0
  29. package/src/JztFormGrid/README.md +520 -0
  30. package/src/JztFormGrid/components/formItem.vue +209 -0
  31. package/src/JztFormGrid/components/formItemValue.vue +384 -0
  32. package/src/JztFormGrid/components/showDetailForm.vue +172 -0
  33. package/src/JztFormGrid/index.scss +60 -0
  34. package/src/JztFormGrid/index.vue +513 -0
  35. package/src/JztFormGrid/interface/index.ts +106 -0
  36. package/src/JztGrid/components/GridItem.vue +68 -0
  37. package/src/JztGrid/index.vue +179 -0
  38. package/src/JztGrid/interface/index.ts +6 -0
  39. package/src/JztImportExcel/assets/delete.png +0 -0
  40. package/src/JztImportExcel/index.scss +46 -0
  41. package/src/JztImportExcel/index.vue +430 -0
  42. package/src/JztImportExcel/interface/index.ts +25 -0
  43. package/src/JztLabelTitle/index.vue +65 -0
  44. package/src/JztLeftRightMode/components/CollapseButton.vue +80 -0
  45. package/src/JztLeftRightMode/components/LeftCard.vue +203 -0
  46. package/src/JztLeftRightMode/components/LeftLayout.vue +173 -0
  47. package/src/JztLeftRightMode/components/RightHeader.vue +186 -0
  48. package/src/JztLeftRightMode/components/RightLayout.vue +235 -0
  49. package/src/JztLeftRightMode/components/RightTableHeader.vue +43 -0
  50. package/src/JztLeftRightMode/hooks/useCollapse.ts +17 -0
  51. package/src/JztLeftRightMode/hooks/useDefaultProps.ts +19 -0
  52. package/src/JztLeftRightMode/hooks/useLeftLayout.ts +201 -0
  53. package/src/JztLeftRightMode/hooks/useMode.ts +20 -0
  54. package/src/JztLeftRightMode/hooks/usePrevNext.ts +60 -0
  55. package/src/JztLeftRightMode/hooks/useRightLayout.ts +215 -0
  56. package/src/JztLeftRightMode/hooks/useSlots.ts +15 -0
  57. package/src/JztLeftRightMode/index.ts +3 -0
  58. package/src/JztLeftRightMode/index.vue +494 -0
  59. package/src/JztLeftRightMode/types/index.ts +457 -0
  60. package/src/JztLoading/fullScreen.ts +45 -0
  61. package/src/JztLoading/index.scss +67 -0
  62. package/src/JztLoading/index.vue +18 -0
  63. package/src/JztLogin/components/LoginFooter.vue +17 -0
  64. package/src/JztLogin/components/LoginForm.vue +99 -0
  65. package/src/JztLogin/hooks/useLogin.ts +186 -0
  66. package/src/JztLogin/index.scss +142 -0
  67. package/src/JztLogin/index.vue +31 -0
  68. package/src/JztLogin/interface/index.ts +47 -0
  69. package/src/JztNumericalRange/index.vue +81 -0
  70. package/src/JztPageCard/comm/datePicker.vue +151 -0
  71. package/src/JztPageCard/comm/details.vue +60 -0
  72. package/src/JztPageCard/comm/export.vue +24 -0
  73. package/src/JztPageCard/comm/tabs.vue +94 -0
  74. package/src/JztPageCard/comm/tooltip.vue +31 -0
  75. package/src/JztPageCard/index.vue +287 -0
  76. package/src/JztPagination/index.vue +70 -0
  77. package/src/JztProductInfo/components/imagePreview.vue +275 -0
  78. package/src/JztProductInfo/components/qxUnique.vue +101 -0
  79. package/src/JztProductInfo/components/records.vue +265 -0
  80. package/src/JztProductInfo/hooks/useParams.ts +143 -0
  81. package/src/JztProductInfo/hooks/useQxUnique.tsx +466 -0
  82. package/src/JztProductInfo/images/defaultProduct.png +0 -0
  83. package/src/JztProductInfo/index.ts +116 -0
  84. package/src/JztProductInfo/index.vue +108 -0
  85. package/src/JztProductInfo/interface/index.ts +15 -0
  86. package/src/JztQueryDetailTable/index.scss +100 -0
  87. package/src/JztQueryDetailTable/index.vue +400 -0
  88. package/src/JztQueryDetailTable/interface/index.ts +10 -0
  89. package/src/JztQueryTable/QueryTable /345/212/237/350/203/275.md" +1580 -0
  90. package/src/JztQueryTable/README.md +567 -0
  91. package/src/JztQueryTable/components/ColSetting.vue +67 -0
  92. package/src/JztQueryTable/components/ColumnsSetting.vue +404 -0
  93. package/src/JztQueryTable/components/ColumnsSetting1.vue +220 -0
  94. package/src/JztQueryTable/components/DeployToAccountLevelSetting.vue +351 -0
  95. package/src/JztQueryTable/components/Pagination.vue +54 -0
  96. package/src/JztQueryTable/components/TableColumn.vue +109 -0
  97. package/src/JztQueryTable/const.ts +1 -0
  98. package/src/JztQueryTable/hooks/useQueryTable.ts +194 -0
  99. package/src/JztQueryTable/hooks/useSelection.ts +47 -0
  100. package/src/JztQueryTable/hooks/useTableSetting.ts +197 -0
  101. package/src/JztQueryTable/hooks/useTemplate.ts +127 -0
  102. package/src/JztQueryTable/index.scss +91 -0
  103. package/src/JztQueryTable/index.vue +1445 -0
  104. package/src/JztQueryTable/interface/index.ts +185 -0
  105. package/src/JztRegionSelect/index.vue +134 -0
  106. package/src/JztSearchForm/components/SearchFormItem.vue +473 -0
  107. package/src/JztSearchForm/index.vue +530 -0
  108. package/src/JztSearchForm/interface/index.ts +100 -0
  109. package/src/JztSelectFilter/index.scss +63 -0
  110. package/src/JztSelectFilter/index.vue +110 -0
  111. package/src/JztSelectTable/index.vue +257 -0
  112. package/src/JztTable/index.scss +72 -0
  113. package/src/JztTable/index.vue +353 -0
  114. package/src/JztTable/interface/index.ts +1 -0
  115. package/src/JztTime/comm/agencySelect.vue +112 -0
  116. package/src/JztTime/comm/collapseRow.vue +132 -0
  117. package/src/JztTime/comm/dateSelect.vue +292 -0
  118. package/src/JztTime/comm/deptSelect.vue +193 -0
  119. package/src/JztTime/comm/typeSelect.vue +97 -0
  120. package/src/JztTime/index.ts +216 -0
  121. package/src/JztTime/index.vue +303 -0
  122. package/src/JztTime/interface/index.ts +23 -0
  123. package/src/JztTreeFilter/index.scss +44 -0
  124. package/src/JztTreeFilter/index.vue +177 -0
  125. package/src/JztUploadFile/interface/index.ts +21 -0
  126. package/src/JztUploadFile/multiple.scss +215 -0
  127. package/src/JztUploadFile/multiple.vue +318 -0
  128. package/src/JztUploadFile/single.scss +226 -0
  129. package/src/JztUploadFile/single.vue +274 -0
  130. package/src/JztUploadImg/Img.vue +294 -0
  131. package/src/JztUploadImg/Imgs.vue +411 -0
  132. package/src/JztUploadImg/index.scss +138 -0
  133. package/src/JztUploadImg/interface/index.ts +22 -0
  134. package/src/SelectIcon/index.scss +39 -0
  135. package/src/SelectIcon/index.vue +106 -0
  136. package/src/SvgIcon/index.vue +22 -0
  137. package/src/hooks/useAuthButtons.ts +58 -0
  138. package/src/hooks/useFormByUserType.ts +90 -0
  139. package/src/hooks/useTableEvents.ts +30 -0
  140. package/src/hooks/useUploadFileHook.ts +262 -0
  141. package/src/index.ts +91 -0
  142. package/src/typings/global.d.ts +101 -0
  143. package/src/utils/index.ts +107 -0
  144. package/src/utils/tree.ts +57 -0
  145. package/tsconfig.json +45 -0
@@ -0,0 +1,513 @@
1
+ <template>
2
+ <div v-if="queryItemList && queryItemList.length" :class="[isShow ? 'show-form-content' : 'form-content-box']">
3
+ <el-form ref="formRef" :label-width="labelWidth" v-bind="formProps" :model="queryFrom" :disabled="disabled">
4
+ <el-row class="form_card_content">
5
+ <template v-for="(item, index) in queryItemList" :key="item.prop + 'group_' + index">
6
+ <!-- 表单分组 -->
7
+ <template v-if="item.groupTitle && item.children">
8
+ <div :class="[isCard ? 'group_card' : 'noTitle_card', border ? 'border_card' : '', 'form_card']">
9
+ <div class="flx-between-center group-header-box" @click="showCollapsed ? changeCollapse(item) : ''">
10
+ <JztLabelTitle :title="item.groupTitle" :isLabel="!isCard" v-bind="groupProps"/>
11
+ <!-- <div class="collapse-title flx-left-center">
12
+ <span class="label"></span>
13
+ <span>{{ item.groupTitle }}</span>
14
+ </div> -->
15
+ <div v-if="showCollapsed">
16
+ <el-icon :size="18">
17
+ <ArrowUp v-if="item.collapse" />
18
+ <ArrowDown v-else />
19
+ </el-icon>
20
+ </div>
21
+ <slot v-else name="header_right"></slot>
22
+ </div>
23
+
24
+ <el-row v-if="!item.collapse && item.children && item.children.length" class="form_child_card_content">
25
+ <slot :name="item.slotName"></slot>
26
+ <template v-for="(child, childIndex) in item.children" :key="String(child.prop) + index + childIndex">
27
+ <div v-if="child?.el === 'JztTable'" class="table-box">
28
+ <JztTable
29
+ ref="jztTableRef"
30
+ :table-data="ruleForm[item.prop as string] || []"
31
+ :table-config="child?.props?.tableConfig"
32
+ :pagination="false"
33
+ :toolButton="false"
34
+ />
35
+ </div>
36
+ <form-item
37
+ v-else-if="child.hideFun ? !child.hideFun() : true"
38
+ :key="String(child.prop) + index + '_item_' + childIndex"
39
+ :item="child"
40
+ :ruleForm="queryFrom"
41
+ :props="props"
42
+ :isShow="isShow"
43
+ :border="border"
44
+ :is-detail="child.isDetail ?? isDetail"
45
+ :infoEmptyText="infoEmptyText"
46
+ :showOverflowTooltip="showOverflowTooltip"
47
+ @formOperationFn="formOperationFn"
48
+ @getCascaderValue="getCascaderValue"
49
+ >
50
+ <template #[child.slotName] :key="child.prop + index + '_template_' + childIndex">
51
+ <slot :name="child.slotName"></slot>
52
+ </template>
53
+ </form-item>
54
+ </template>
55
+ </el-row>
56
+ </div>
57
+ </template>
58
+ <!-- 表单无分组 -->
59
+ <template v-else-if="item.hideFun ? !item.hideFun() : true">
60
+ <form-item
61
+ :item="item"
62
+ :showOverflowTooltip="showOverflowTooltip"
63
+ :ruleForm="queryFrom"
64
+ :isShow="isShow"
65
+ :border="border"
66
+ :is-detail="item.isDetail ?? isDetail"
67
+ :infoEmptyText="infoEmptyText"
68
+ @formOperationFn="formOperationFn"
69
+ @getCascaderValue="getCascaderValue"
70
+ >
71
+ <template #[item.slotName] :key="item.props + index">
72
+ <slot :name="item.slotName"></slot>
73
+ </template>
74
+ </form-item>
75
+ </template>
76
+ </template>
77
+ </el-row>
78
+ </el-form>
79
+ <slot name="footer"></slot>
80
+ </div>
81
+ <div v-else></div>
82
+ </template>
83
+ <script setup lang="ts" name="SearchForm">
84
+ import { JztLabelTitle, JztTable } from '@jzt-spd/components'
85
+ import { isEmpty } from '@jzt-spd/utils'
86
+ import { GUIDNoneValue } from '@jzt-spd/utils/consts'
87
+ import type { FormInstance } from 'element-plus'
88
+ import { cloneDeep } from 'lodash-es'
89
+ import { computed, onMounted, provide, ref, watch } from 'vue'
90
+ import formItem from './components/formItem.vue'
91
+ import { FormItemsProps } from './interface/index'
92
+ // import JztTable
93
+ import { useSetCascaderEnumMap, useSetEnumMap } from '../hooks/useFormByUserType'
94
+
95
+ interface ProTableProps {
96
+ showOverflowTooltip?: boolean // 是否显示超出部分提示
97
+ queryItems: FormItemsProps[] // 搜索配置列
98
+ ruleForm?: { [key: string]: any } // 搜索参数
99
+ isShow?: boolean // 是否是查看模式
100
+ disabled?: boolean // 是否表单禁用
101
+ formProps?: Record<string, any>
102
+ infoEmptyText?: string
103
+ showCollapsed?: boolean
104
+ isCard?: boolean
105
+ isDetail?: boolean
106
+ border?: boolean // 是否显示边框
107
+ labelWidth?: number | string // 整体表单label宽度
108
+ // formDict?: Record<string, any>; // 表单枚举字典
109
+ groupProps?: { [key: string]: any }
110
+ }
111
+
112
+ // 默认值
113
+ const props = withDefaults(defineProps<ProTableProps>(), {
114
+ queryItems: () => [],
115
+ ruleForm: () => ({}),
116
+ isShow: false, // 是否是查看模式
117
+ disabled: false, // 是否表单禁用
118
+ infoEmptyText: '-',
119
+ showCollapsed: true, // 是否需要折叠功能
120
+ isCard: false, // 是否需要阴影样式
121
+ border: false,
122
+ isDetail: false,
123
+ labelWidth: 'auto', // 整体表单label宽度
124
+ // formDict: () => ({}),
125
+ groupProps: () => ({}),
126
+ })
127
+
128
+ const queryItemList = ref<FormItemsProps[]>([])
129
+ // cloneDeep 是为了解决打开折叠 互相影响
130
+ onMounted(() => {
131
+ queryItemList.value = cloneDeep(props.queryItems)
132
+ })
133
+
134
+ // const emit = defineEmits(['formOperationFn', 'update:ruleForm'])
135
+
136
+ // 定义 enumMap 存储 enum 值(避免异步请求无法格式化单元格内容 || 无法填充搜索下拉选择)
137
+ const enumMap = ref(new Map<string, { [key: string]: any }[]>())
138
+ // watch(
139
+ // () => props.formDict,
140
+ // (val) => {
141
+ // console.log("val----->", val, isObject(val), !isEmpty(val));
142
+ // if (isObject(val) && !isEmpty(val)) {
143
+ // Object.keys(props.formDict).forEach((key) => {
144
+ // enumMap.value.set(key, props.formDict[key]);
145
+ // });
146
+ // }
147
+ // },
148
+ // { deep: true, immediate: true }
149
+ // );
150
+
151
+ // 查询表单实例
152
+ const formRef = ref()
153
+
154
+ // 获取枚举字典集合
155
+ // const setEnumMap = async ({ prop, isAwait, enum: enumValue, isSetFirstValue, fieldNames }: FormItemsProps) => {
156
+ // if (!enumValue) return
157
+ // if (isAwait) return
158
+
159
+ // // 如果当前 enumMap 存在相同的值 return
160
+ // if (enumMap.value.has(prop!) && (typeof enumValue === 'function' || enumMap.value.get(prop!) === enumValue)) return
161
+
162
+ // // 当前 enum 为静态数据,则直接存储到 enumMap
163
+ // if (typeof enumValue !== 'function') return enumMap.value.set(prop!, unref(enumValue!))
164
+
165
+ // // 为了防止接口执行慢,而存储慢,导致重复请求,所以预先存储为[],接口返回后再二次存储
166
+ // enumMap.value.set(prop!, [])
167
+
168
+ // // 当前 enum 为后台数据需要请求数据,则调用该请求接口,并存储到 enumMap
169
+ // const { data, result } = await enumValue()
170
+ // let list = data || result || []
171
+ // enumMap.value.set(prop!, list)
172
+ // if (useFormSetByUserType(isSetFirstValue, prop)) {
173
+ // setSelectFirstValue(prop, list[0], fieldNames)
174
+ // }
175
+ // }
176
+ // change 获取接口数据
177
+ // const setCascaderEnumMap = async (
178
+ // prop,
179
+ // { enum: enumValue, isSetFirstValue, fieldNames }: FormItemsProps,
180
+ // val: string
181
+ // ) => {
182
+ // if (!enumValue) return
183
+
184
+ // // 如果当前 enumMap 存在相同的值 也不return 根据change实时获取
185
+ // // 为了防止接口执行慢,而存储慢,导致重复请求,所以预先存储为[],接口返回后再二次存储
186
+ // if (typeof enumValue !== 'function') return enumMap.value.set(prop!, unref(enumValue!))
187
+ // enumMap.value.set(prop!, [])
188
+
189
+ // // 当前 enum 为后台数据需要请求数据,则调用该请求接口,并存储到 enumMap
190
+ // const { data, result } = await enumValue(val)
191
+ // let list = data || result || []
192
+ // enumMap.value.set(prop!, list)
193
+ // if (useFormSetByUserType(isSetFirstValue, prop)) {
194
+ // setSelectFirstValue(prop, list[0], fieldNames)
195
+ // }
196
+ // }
197
+ // 处理默认选中第一条数据
198
+ const setSelectFirstValue = (prop, firstItem, fieldNames) => {
199
+ if (prop && firstItem) {
200
+ const itemValue = fieldNames?.value || 'value'
201
+ props.ruleForm[prop] = firstItem[itemValue]
202
+ // emit('update:searchParam', props.ruleForm)
203
+ }
204
+ }
205
+ const allFlatQuery = ref<FormItemsProps[]>([])
206
+
207
+ /* 格式化初始化表单数据
208
+ 1、 空值默认值 GUIDNoneValue,不展示
209
+ 2、处理数组字段合并(例如时间范围)
210
+ */
211
+ const queryFrom = computed(() => {
212
+ const form = props.ruleForm
213
+ allFlatQuery.value.forEach(item => {
214
+ if (item.isSetEmptyData && form[item.prop as keyof typeof form] === GUIDNoneValue) {
215
+ form[item.prop as keyof typeof form] = item.emptyNullValue ?? ''
216
+ }
217
+ if (item && item.startField && item.endField) {
218
+ const { startField, endField } = item
219
+ if (form[startField] || form[endField]) {
220
+ form[item.prop as keyof typeof form] = [form[startField] || '', form[endField] || '']
221
+ }
222
+ }
223
+ })
224
+ return form
225
+ })
226
+ /* 格式化处理数据
227
+ 1、空值默认值 GUIDNoneValue
228
+ 2、处理数组字段切割(例如时间范围)
229
+ */
230
+ const getFormatForm = form => {
231
+ const endForm = cloneDeep(form)
232
+ allFlatQuery.value.forEach(item => {
233
+ if (item.isSetEmptyData && isEmpty(endForm[item.prop])) {
234
+ endForm[item.prop] = item.emptyNullValue || GUIDNoneValue
235
+ }
236
+ if (item && item.startField && item.endField) {
237
+ const { startField, endField } = item
238
+ const timeList = endForm[item.prop] || []
239
+ endForm[startField] = timeList[0] ?? ''
240
+ endForm[endField] = timeList[1] ?? ''
241
+ delete endForm[item.prop]
242
+ }
243
+ })
244
+ return endForm
245
+ }
246
+
247
+ // 扁平化 columns 的方法 处理字典数据 、 过滤表格部分渲染数据
248
+ const flatColumnsFunc = (columns: FormItemsProps[], flatArr: FormItemsProps[] = []) => {
249
+ columns.forEach(async col => {
250
+ if (col.children?.length) {
251
+ flatArr.push(...flatColumnsFunc(col.children))
252
+ }
253
+ if (col.prop) {
254
+ flatArr.push(col)
255
+ // 设置 enumMap
256
+ // await setEnumMap(col)
257
+ // 数据回显的时候反向获取下拉数据
258
+ const index = columns.findIndex(cols => cols.cascader && cols.cascader.includes(col.prop))
259
+ let parentItem = {}
260
+ if (index > -1) {
261
+ parentItem = columns[index]
262
+ }
263
+
264
+ await useSetEnumMap({
265
+ queryItem: col,
266
+ enumMap,
267
+ callBack: setSelectFirstValue,
268
+ queryFrom: queryFrom.value,
269
+ parentItem: parentItem
270
+ })
271
+ }
272
+ })
273
+
274
+ return flatArr.filter(item => !item.children?.length)
275
+ }
276
+ allFlatQuery.value = flatColumnsFunc(props.queryItems)
277
+
278
+ // 操作列点击操作
279
+ const formOperationFn = async (item: any) => {
280
+ // 获取结果数据
281
+ if (item.id === 'confirm') {
282
+ await onConfirm(item.fun)
283
+ } else if (item.id === 'reset') {
284
+ await onReset(item.fun)
285
+ } else {
286
+ const form = getFormatForm(queryFrom.value)
287
+ item.fun(form)
288
+ }
289
+ }
290
+
291
+ // 获取getCascader数据
292
+ const getCascaderValue = (val, isClear: boolean = false) => {
293
+ if (val.cascader && val.cascader.length) {
294
+ val.cascader?.forEach(cascader => {
295
+ if (isClear) {
296
+ // 递归处理需要清除的数据
297
+ clearNextItem(cascader)
298
+ } else if (props.ruleForm[val.prop]) {
299
+ const index = allFlatQuery.value.findIndex(item => item.prop === cascader)
300
+ if (index === -1) return
301
+ const queryItem = allFlatQuery.value[index]
302
+ // 有值才会去掉接口,处理clearable 不清空问题
303
+ useSetCascaderEnumMap({
304
+ prevProp: val.prop,
305
+ queryItem,
306
+ enumMap,
307
+ searchParam: props.ruleForm,
308
+ callBack: setSelectFirstValue
309
+ })
310
+ // setCascaderEnumMap(queryItem.prop, queryItem, props.ruleForm[val.prop])
311
+ }
312
+ })
313
+ }
314
+ }
315
+ // 递归处理需要清除的数据(例如省市区三级的情况,清空/更改省->清空:市与区)
316
+ const clearNextItem = cascader => {
317
+ if (!cascader || !cascader.length) return
318
+ const index = allFlatQuery.value.findIndex(item => item.prop === cascader)
319
+ if (index === -1) return
320
+ const queryItem = allFlatQuery.value[index]
321
+ props.ruleForm[queryItem.prop as keyof typeof queryItem] = null // 让下一级的表单数据为空
322
+ enumMap.value.set(queryItem.prop as keyof typeof queryItem, []) // 让下一级的下拉数据清空
323
+ if (queryItem.cascader && queryItem.cascader.length) {
324
+ queryItem.cascader.forEach(item => {
325
+ clearNextItem(item)
326
+ })
327
+ }
328
+ }
329
+ // 注入 enumMap
330
+ provide('fromEnumMap', enumMap)
331
+ // 确定提交
332
+ const onConfirm = async (callback?: (valid, form) => any) => {
333
+ try {
334
+ // 获取结果数据
335
+ const valid = await validateForm()
336
+ const endForm = getFormatForm(queryFrom.value)
337
+ return callback && callback(valid, endForm)
338
+ } catch (error) {
339
+ return false
340
+ }
341
+ }
342
+
343
+ // 重置表单
344
+ const onReset = async (callback?: () => void) => {
345
+ const formEl = formRef.value as FormInstance | undefined
346
+ if (!formEl) return
347
+ formEl.resetFields()
348
+ callback && callback()
349
+ }
350
+ // 效验表单
351
+ const validateForm = async () => {
352
+ const formEl = formRef.value as FormInstance | undefined
353
+ if (!formEl) return true
354
+ try {
355
+ await formEl.validate()
356
+ return true
357
+ } catch (error) {
358
+ return false
359
+ }
360
+ }
361
+
362
+ // 清除校验结果
363
+ const clearValidateForm = async () => {
364
+ const formEl = formRef.value as FormInstance | undefined
365
+ if (!formEl) return
366
+ formEl.clearValidate()
367
+ }
368
+
369
+ // 效验表单的部分字段
370
+ const validateFields = async (fields: string | string[]) => {
371
+ if (!fields) return true
372
+ const formEl = formRef.value as FormInstance | undefined
373
+ if (!formEl) return true
374
+ try {
375
+ const valid = await formEl.validateField(fields)
376
+ return valid
377
+ } catch (error) {
378
+ return false
379
+ }
380
+ }
381
+ const changeCollapse = item => {
382
+ item.collapse = !item.collapse
383
+ }
384
+
385
+ // 监听queryItems变化
386
+ watch(
387
+ () => props.queryItems,
388
+ newValue => {
389
+ queryItemList.value = cloneDeep(newValue)
390
+ },
391
+ { deep: true }
392
+ )
393
+
394
+ defineExpose({
395
+ onConfirm,
396
+ onReset,
397
+ validateForm,
398
+ validateFields,
399
+ clearValidateForm,
400
+ formRef,
401
+ getFormatForm
402
+ })
403
+ </script>
404
+
405
+ <style lang="scss" scoped>
406
+ //展示样式
407
+ .show-form-content {
408
+ :deep(.el-form-item) {
409
+ margin-bottom: 0px !important;
410
+ height: 100%;
411
+ .el-form-item__label,
412
+ .el-space {
413
+ height: 100%;
414
+ height: unset !important;
415
+ }
416
+ .el-form-item__content {
417
+ line-height: 30px;
418
+ }
419
+ .el-space__item {
420
+ line-height: 30px;
421
+ }
422
+ }
423
+ :deep(.group-header) {
424
+ flex: 1;
425
+ padding: 0 10px;
426
+ }
427
+ .noTitle_card {
428
+ margin-bottom: 8px;
429
+ }
430
+ .form_card_content .form_child_card_content {
431
+ margin-bottom: 0;
432
+ }
433
+ // 边框 展示样式
434
+ .border_card {
435
+ margin-bottom: 12px !important;
436
+ :deep(.group-header) {
437
+ flex: 1;
438
+ padding: 0 10px 10px 0;
439
+ }
440
+ :deep(.el-space__item) {
441
+ padding-left: 4px;
442
+ }
443
+ }
444
+ }
445
+ .form-content-box {
446
+ :deep(.group-header) {
447
+ flex: 1;
448
+ padding: 4px 10px;
449
+ }
450
+ .form_card_content .form_child_card_content {
451
+ padding-bottom: 0;
452
+ }
453
+ }
454
+
455
+ .form_card.border_card {
456
+ margin-bottom: 0;
457
+ .form_child_card_content {
458
+ padding: 0;
459
+ border-left: 1px solid #ebeef5;
460
+ border-top: 1px solid #ebeef5;
461
+ border-radius: 6px;
462
+ overflow: hidden;
463
+ }
464
+ .form_card {
465
+ margin-bottom: 0;
466
+ }
467
+ }
468
+ .form_card_content {
469
+ width: 100%;
470
+ box-sizing: border-box;
471
+ // margin-bottom: 8px;
472
+
473
+ .form_child_card_content {
474
+ width: 100%;
475
+ box-sizing: border-box;
476
+ padding: 8px;
477
+ // margin-bottom: 12px;
478
+
479
+ .table-box {
480
+ width: 100%;
481
+ max-height: 400px;
482
+ }
483
+ .spd-card {
484
+ padding: 0;
485
+ }
486
+ }
487
+ }
488
+ .form_card {
489
+ width: 100%;
490
+ border-radius: 4px;
491
+ // margin-bottom: 12px;
492
+ }
493
+
494
+ .noTitle_card {
495
+ width: calc(100% - 10px);
496
+ }
497
+ .group-header-box {
498
+ width: 100%;
499
+ padding-right: 6px;
500
+ box-sizing: border-box;
501
+ }
502
+ // 卡片模式
503
+ .group_card {
504
+ border: 1px solid #e9e9e9;
505
+ margin-bottom: 12px;
506
+ .group-header-box {
507
+ background: var(--el-fill-color-light);
508
+ }
509
+ :deep(.group-header) {
510
+ padding: 8px 10px;
511
+ }
512
+ }
513
+ </style>
@@ -0,0 +1,106 @@
1
+ import { Ref, VNode } from 'vue'
2
+
3
+ import { EnumProps } from '../../JztQueryTable/interface/index'
4
+
5
+ import type { FormInstance } from 'element-plus'
6
+
7
+ export type JztFormInstance = {
8
+ onConfirm(callback?: () => void): void
9
+ onReset(callback?: () => void): void
10
+ validateFields(fields: string | string[]): boolean
11
+ formRef: FormInstance
12
+ }
13
+ export type FieldNamesProps = {
14
+ label: string
15
+ value: string
16
+ children?: string
17
+ }
18
+ export type ElType =
19
+ | 'el-input'
20
+ | 'el-input-number'
21
+ | 'el-select'
22
+ | 'el-select-v2'
23
+ | 'el-tree-select'
24
+ | 'el-cascader'
25
+ | 'el-date-picker'
26
+ | 'el-time-picker'
27
+ | 'el-time-select'
28
+ | 'el-switch'
29
+ | 'el-slider'
30
+ | 'el-radio-group'
31
+ | 'el-checkbox-group'
32
+ | 'JztUploadMultipleImgs'
33
+ | 'JztUploadImg'
34
+ | 'JztUploadMultipleFiles'
35
+ | 'JztUploadSingleFile'
36
+ | 'JztDictionary'
37
+ | 'JztTable'
38
+ | 'JztRegionSelect'
39
+
40
+ export interface FormItemsProps<T = any> {
41
+ label?: string
42
+ key?: string
43
+ labelRender?: () => VNode | string // 自定义单元格标题渲染(tsx语法)
44
+ prop: keyof T
45
+ enumKey?: keyof T // 用于多字段公用同一个enum
46
+ formItemProps?: Record<string, any>
47
+ el?: ElType // 组件
48
+ span?: number // 列宽度
49
+ className?: string // className
50
+ // type?: TypeProps; // 列类型
51
+ // isHide?: boolean; // 是否隐藏
52
+ enum?: EnumProps[] | Ref<EnumProps[]> | ((params?: any) => Promise<any>) // 枚举字典
53
+ // enumCallBack?: (params?: any) => Promise<any>; // 处理接口返回的字典的回调
54
+ fieldNames?: FieldNamesProps // 指定 label && value && children 的 key 值
55
+ render?: () => VNode | string // 内容渲染(tsx语法)
56
+ showRender?: () => VNode | string // 内容渲染 isDetail 详情页使用 showRender>render
57
+ outerRender?: () => VNode | string // 外部在 formItem同层级渲染(tsx语法)
58
+ rightRender?: () => VNode | string // 内部右侧渲染 tsx语法)
59
+ rules?: any[]
60
+ btnLList?: any[]
61
+ // ! 注意: precision: true|数字值, 1️⃣ true:启用配置中的精度位数,2️⃣number:指定精度位数(数字值)
62
+ props?: any // 搜索项参数,根据 element plus 官方文档来传递,该属性所有值会透传到组件
63
+ events?:any; // 搜索项事件,根据 element plus 官方文档来传递,该属性所有值会透传到组件
64
+ // options?: any[] // 固定的下拉数据(废弃)
65
+ slotName?: string // 插槽、
66
+ tooltip?: string
67
+ groupTitle?: string // 表单分组标题
68
+ children?: FormItemsProps[]
69
+ collapse?: boolean // 是否折叠
70
+ /** 隐藏函数 */
71
+ hideFun?: Function //是否隐藏
72
+ disabledFn?: Function /** 禁用函数 */
73
+ cascader?: string[]
74
+ isAwait?: boolean // 是否需要等待请求接口
75
+ options?: Record<string, any>
76
+ dictType?: string | number // 字典ID
77
+ isSetEmptyData?: boolean // 是否设置空数据 适用场景例如:供应商 不选择时:页面为空,实际接口需要默认传 GUIDNoneValue: 00000000-0000-0000-0000-000000000000
78
+ emptyNullValue?: any // 空数据默认值,初始化默认是'', 结果默认值是GUIDNoneValue
79
+ startField?: string // 数组开始字段
80
+ endField?: string // 数组结束字段
81
+ change?: (scope: any) => any // change事件事件
82
+ isSetFirstValue?: boolean // 是否需要默认选中第一个数据
83
+ labelWidth?: string | number // labelWidth
84
+ allowCheckLevel?: number // 允许都选的长度层级,未达到的话,就说明此条数没有固定的子节点,场景: 医疗机构->仓库->科室,只允许选择科室,但是没有科室的医疗机构仓库 会正常返回,此时就不允许选择 第一层,第二层
85
+ fields?: string[] // 目前JztRegionSelect 专用 - [省 市 区]
86
+ hasCheckbox?: boolean // 是否显示全选反选
87
+ // field2?: string; // JztRegionSelect 专用 - 市
88
+ // field3?: string; // JztRegionSelect 专用 - 区
89
+ isDetail?: boolean // 是否是详情展示模式
90
+ detailProps?: DetailFormItemsProp
91
+ valueLeftRender?: () => VNode | string // 详情模式 value 内部右侧渲染 tsx语法)
92
+ valueRightRender?: () => VNode | string // 详情模式 value 内部右侧渲染 tsx语法
93
+ tooltipProps?: TooltipProps
94
+ }
95
+
96
+ export interface DetailFormItemsProp {
97
+ showProp?: string // 展示时的字段key 如果没有就会取FormItemsProps.prop 这个是为了防止详情和编辑的时候的字段不一致,编辑是id 展示是name
98
+ showOverflowTooltip?: boolean // 详情模式 value 显示超出Tooltip
99
+ }
100
+
101
+ export interface TooltipProps {
102
+ iconColor?: string
103
+ placement?: string
104
+ effect: string
105
+ content: string
106
+ }
@@ -0,0 +1,68 @@
1
+ <template>
2
+ <div v-show="isShow" :style="style">
3
+ <slot></slot>
4
+ </div>
5
+ </template>
6
+ <script setup lang="ts" name="GridItem">
7
+ import { ref, Ref, inject, watch, useAttrs, computed } from 'vue'
8
+ import { BreakPoint, Responsive } from '../interface/index'
9
+
10
+ type Props = {
11
+ offset?: number
12
+ span?: number
13
+ suffix?: boolean
14
+ xs?: Responsive
15
+ sm?: Responsive
16
+ md?: Responsive
17
+ lg?: Responsive
18
+ xl?: Responsive
19
+ }
20
+
21
+ const props = withDefaults(defineProps<Props>(), {
22
+ offset: 0,
23
+ span: 1,
24
+ suffix: false,
25
+ xs: undefined,
26
+ sm: undefined,
27
+ md: undefined,
28
+ lg: undefined,
29
+ xl: undefined
30
+ })
31
+
32
+ const attrs = useAttrs() as { index: string }
33
+ const isShow = ref(true)
34
+
35
+ // 注入断点
36
+ const breakPoint = inject<Ref<BreakPoint>>('breakPoint', ref('xl'))
37
+ const shouldHiddenIndex = inject<Ref<number>>('shouldHiddenIndex', ref(-1))
38
+ watch(
39
+ () => [shouldHiddenIndex.value, breakPoint.value],
40
+ n => {
41
+ if (!!attrs.index) {
42
+ isShow.value = !(n[0] !== -1 && parseInt(attrs.index) >= Number(n[0]))
43
+ }
44
+ },
45
+ { immediate: true }
46
+ )
47
+
48
+ const gap = inject('gap', 0)
49
+ const cols = inject('cols', ref(4))
50
+ const style = computed(() => {
51
+ let span = props[breakPoint.value]?.span ?? props.span
52
+ let offset = props[breakPoint.value]?.offset ?? props.offset
53
+ if (props.suffix) {
54
+ return {
55
+ gridColumnStart: cols.value - span - offset + 1,
56
+ gridColumnEnd: `span ${span + offset}`,
57
+ marginLeft: offset !== 0 ? `calc(((100% + ${gap}px) / ${span + offset}) * ${offset})` : 'unset'
58
+ }
59
+ } else {
60
+ return {
61
+ gridColumn: `span ${span + offset > cols.value ? cols.value : span + offset}/span ${
62
+ span + offset > cols.value ? cols.value : span + offset
63
+ }`,
64
+ marginLeft: offset !== 0 ? `calc(((100% + ${gap}px) / ${span + offset}) * ${offset})` : 'unset'
65
+ }
66
+ }
67
+ })
68
+ </script>