@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,411 @@
1
+ <template>
2
+ <div class="img_upload_box flx-left-center">
3
+ <slot name="upload-left"></slot>
4
+ <el-upload
5
+ v-if="isShow ? _fileList && _fileList.length : true"
6
+ v-model:file-list="_fileList"
7
+ action="#"
8
+ list-type="picture-card"
9
+ :class="[
10
+ 'upload',
11
+ self_disabled ? 'disabled' : '',
12
+ drag ? 'no-border' : '',
13
+ isShow || limit <= _fileList.length ? 'no-upload' : ''
14
+ ]"
15
+ :multiple="true"
16
+ :disabled="self_disabled"
17
+ :limit="isShow ? _fileList.length : limit"
18
+ :http-request="handleHttpUpload"
19
+ :before-upload="beforeUpload"
20
+ :on-exceed="handleExceed"
21
+ :on-success="uploadSuccess"
22
+ :on-error="uploadError"
23
+ :drag="drag"
24
+ :accept="fileType.join(',')"
25
+ >
26
+ <div class="upload-empty">
27
+ <slot name="empty">
28
+ <el-icon><Plus /></el-icon>
29
+ <span>{{ emptyText }}</span>
30
+ </slot>
31
+ </div>
32
+ <template #file="{ file }">
33
+ <img v-if="isFullUrl(file?.url)" :src="file?.isPdf ? pdfCover : file.url" class="upload-image" />
34
+ <div v-else class="upload-image">
35
+ <img :src="file?.isPdf ? pdfCover : file.url" class="upload-image" />
36
+ </div>
37
+ <div v-if="!file?.halfUrl" class="jzt-upload-loading">
38
+ <el-icon class="loading-icon"><Loading /></el-icon>
39
+ </div>
40
+ <div v-else class="upload-handle" @click.stop>
41
+ <div class="handle-icon" @click="handlePictureCardPreview(file as UploadUserFileTypes)">
42
+ <el-icon><ZoomIn /></el-icon>
43
+ <span>查看</span>
44
+ </div>
45
+ <div v-if="!self_disabled" class="handle-icon" @click="handleRemove(file as UploadUserFileTypes)">
46
+ <el-icon><Delete /></el-icon>
47
+ <span>删除</span>
48
+ </div>
49
+ </div>
50
+ </template>
51
+ </el-upload>
52
+ <JztEmpty v-else-if="isShow" emptyText="暂无图片" />
53
+ <div class="el-upload__tip">
54
+ <slot name="tip"></slot>
55
+ </div>
56
+ <JztFilePreview ref="JztFilePreviewRef" title="预览" :show-list="false" />
57
+ <el-image-viewer v-if="imgViewVisible" :url-list="[viewImageUrl]" @close="imgViewVisible = false" />
58
+ </div>
59
+ </template>
60
+
61
+ <script setup lang="ts" name="UploadImgs">
62
+ import { ref, computed, inject, watch } from 'vue'
63
+ import { Plus, Loading } from '@element-plus/icons-vue'
64
+ import { pdfCover } from '@jzt-spd/styles/assets'
65
+ import type { UploadProps, UploadFile, UploadUserFile, UploadRequestOptions } from 'element-plus'
66
+ import { ElNotification, formContextKey, formItemContextKey } from 'element-plus'
67
+ import { useUploadFileHook } from '../hooks/useUploadFileHook'
68
+ import { isFullUrl } from '@jzt-spd/utils'
69
+ import JztEmpty from "../JztEmpty/index.vue";
70
+ import JztFilePreview from "../JztFilePreview/index.vue";
71
+
72
+ const { useBeforeUpload, useRemoveFilterList, useUploadSuccess, useHttpUploadHook, getFileShowList, getFullUrl } =
73
+ useUploadFileHook()
74
+
75
+ interface UploadUserFileTypes extends UploadUserFile {
76
+ halfUrl: string
77
+ isPdf?: boolean
78
+ }
79
+
80
+ interface UploadFileProps {
81
+ fileList: UploadUserFile[] | string[]
82
+ api?: (params: any) => Promise<any> // 上传图片的 api 方法,一般项目上传都是同一个 api 方法,在组件里直接引入即可 ==> 非必传
83
+ drag?: boolean // 是否支持拖拽上传 ==> 非必传(默认为 true)
84
+ disabled?: boolean // 是否禁用上传组件 ==> 非必传(默认为 false)
85
+ limit?: number // 最大图片上传数 ==> 非必传(默认为 5张)
86
+ fileSize?: number // 图片大小限制 ==> 非必传(默认为 5M)
87
+ fileType?: File.ImagePostfixType[] // 图片类型限制 ==> 非必传(默认为 [".jpeg", ".png", ".jpg"])
88
+ height?: string // 组件高度 ==> 非必传(默认为 120px
89
+ width?: string // 组件宽度 ==> 非必传(默认为 120px
90
+ borderRadius?: string // 组件边框圆角 ==> 非必传(默认为 8px)
91
+ // listType?: "text" | "picture" | "picture-card";
92
+ emptyText?: string
93
+ fileName?: string
94
+ isShow?: boolean // 是否是查看模式,没有数据时会展示空图
95
+ }
96
+
97
+ const props = withDefaults(defineProps<UploadFileProps>(), {
98
+ fileList: () => [],
99
+ drag: true,
100
+ disabled: false,
101
+ limit: 5,
102
+ fileSize: 5,
103
+ fileType: () => ['.jpeg', '.png', '.jpg'],
104
+ height: '120px',
105
+ width: '120px',
106
+ borderRadius: '8px',
107
+ // listType: "text",
108
+ emptyText: '请上传图片',
109
+ fileName: 'file',
110
+ isShow: false
111
+ })
112
+
113
+ // 获取 el-form 组件上下文
114
+ const formContext = inject(formContextKey, void 0)
115
+ // 获取 el-form-item 组件上下文
116
+ const formItemContext = inject(formItemContextKey, void 0)
117
+ // 判断是否禁用上传和删除
118
+ const self_disabled = computed(() => {
119
+ return props.disabled || formContext?.disabled
120
+ })
121
+
122
+ const _fileList = ref<UploadUserFileTypes[]>([])
123
+
124
+ // 监听 props.fileList 列表默认值改变
125
+ watch(
126
+ () => props.fileList,
127
+ (fileList: any[]) => {
128
+ const newList = getFileShowList(fileList)
129
+ // 用 halfUrl 匹配已有文件,复用原对象引用,避免所有图片重新加载
130
+ const existingMap = new Map(_fileList.value.filter(f => f.halfUrl).map(f => [f.halfUrl, f]))
131
+ _fileList.value = newList.map(item => {
132
+ const existing = existingMap.get(item.halfUrl)
133
+ if (existing) return existing
134
+ return item
135
+ })
136
+ },
137
+ {
138
+ immediate: true
139
+ }
140
+ )
141
+
142
+ /**
143
+ * @description 文件上传之前判断
144
+ * @param rawFile 选择的文件
145
+ * */
146
+ const beforeUpload: UploadProps['beforeUpload'] = rawFile => {
147
+ return useBeforeUpload({
148
+ rawFile,
149
+ fileSize: props.fileSize,
150
+ fileType: props.fileType
151
+ })
152
+ }
153
+
154
+ /**
155
+ * @description 图片上传
156
+ * @param options upload 所有配置项
157
+ * */
158
+ const handleHttpUpload = async (options: UploadRequestOptions) => {
159
+ // PDF 的 blob URL 无法在 img 中显示,提前替换为封面图
160
+ const file = _fileList.value.find(f => f.uid === options.file.uid)
161
+ if (file && /\.(pdf)$/i.test(options.file.name)) {
162
+ file.url = pdfCover
163
+ file.isPdf = true
164
+ }
165
+ useHttpUploadHook({
166
+ fileName: props.fileName,
167
+ options,
168
+ api: props.api
169
+ })
170
+ }
171
+
172
+ /**
173
+ * @description 图片上传成功
174
+ * @param response 上传响应结果
175
+ * @param uploadFile 上传的文件
176
+ * */
177
+
178
+ const emit = defineEmits<{
179
+ 'update:fileList': [value: UploadUserFile[] | string[]]
180
+ }>()
181
+
182
+ // emit fileList 同步fileList数据
183
+ const setEmit = (halfUrls: string[]) => {
184
+ emit('update:fileList', halfUrls)
185
+ }
186
+ // 上传成功!
187
+ const uploadSuccess = async (response: { fileUrl: string }, uploadFile: UploadUserFile | UploadUserFileTypes) => {
188
+ useUploadSuccess({
189
+ response,
190
+ uploadFile: uploadFile as UploadUserFileTypes,
191
+ _fileList: _fileList.value,
192
+ callback: halfUrls => {
193
+ setEmit(halfUrls)
194
+ },
195
+ formItemContext,
196
+ formContext
197
+ })
198
+ }
199
+
200
+ /**
201
+ * @description 删除图片
202
+ * @param file 删除的文件
203
+ * */
204
+ const handleRemove = (file: UploadFile | UploadUserFileTypes) => {
205
+ const halfUrls = useRemoveFilterList({
206
+ _fileList: _fileList.value,
207
+ file: file as UploadUserFileTypes
208
+ })
209
+ setEmit(halfUrls)
210
+ }
211
+
212
+ /**
213
+ * @description 图片上传错误
214
+ * */
215
+ const uploadError = () => {
216
+ ElNotification({
217
+ title: '温馨提示',
218
+ message: '图片上传失败,请您重新上传!',
219
+ type: 'error'
220
+ })
221
+ }
222
+
223
+ /**
224
+ * @description 文件数超出
225
+ * */
226
+ const handleExceed = () => {
227
+ ElNotification({
228
+ title: '温馨提示',
229
+ message: `当前最多只能上传 ${props.limit} 张图片,请移除后上传!`,
230
+ type: 'warning'
231
+ })
232
+ }
233
+
234
+ /**
235
+ * @description 图片预览
236
+ * @param file 预览的文件
237
+ * */
238
+ const viewImageUrl = ref('')
239
+ const imgViewVisible = ref(false)
240
+ const JztFilePreviewRef = ref()
241
+
242
+ const handlePictureCardPreview = (file: UploadUserFileTypes) => {
243
+ if (file && file.isPdf) {
244
+ // PDF预览功能
245
+ const url = getFullUrl((file as UploadUserFileTypes).halfUrl)
246
+ JztFilePreviewRef.value && JztFilePreviewRef.value.openDialog([url])
247
+ } else {
248
+ viewImageUrl.value = file.url!
249
+ imgViewVisible.value = true
250
+ }
251
+ }
252
+ </script>
253
+
254
+ <style scoped lang="scss">
255
+ .no-upload {
256
+ :deep(.el-upload) {
257
+ display: none;
258
+ }
259
+ }
260
+ .is-error {
261
+ .upload {
262
+ :deep(.el-upload--picture-card),
263
+ :deep(.el-upload-dragger) {
264
+ border: 1px dashed var(--el-color-danger) !important;
265
+ &:hover {
266
+ border-color: var(--el-color-primary) !important;
267
+ }
268
+ }
269
+ }
270
+ }
271
+ :deep(.disabled) {
272
+ .el-upload--picture-card,
273
+ .el-upload-dragger {
274
+ cursor: not-allowed;
275
+ background: var(--el-disabled-bg-color) !important;
276
+ border: 1px dashed var(--el-border-color-darker);
277
+ &:hover {
278
+ border-color: var(--el-border-color-darker) !important;
279
+ }
280
+ }
281
+ }
282
+ //文件上传
283
+ .file_upload_box {
284
+ .upload-btn {
285
+ display: flex;
286
+ align-items: center;
287
+ justify-content: flex-start;
288
+ .el-button {
289
+ margin-right: 10px;
290
+ }
291
+ }
292
+ }
293
+ //图片上传
294
+ .img_upload_box {
295
+ .no-border {
296
+ :deep(.el-upload--picture-card) {
297
+ border: none !important;
298
+ }
299
+ }
300
+ :deep(.upload) {
301
+ .el-upload-dragger {
302
+ display: flex;
303
+ align-items: center;
304
+ justify-content: center;
305
+ width: 100%;
306
+ height: 100%;
307
+ padding: 0;
308
+ overflow: hidden;
309
+ border: 1px dashed var(--el-border-color-darker);
310
+ border-radius: v-bind(borderRadius);
311
+ background-color: #fff !important;
312
+ &:hover {
313
+ border: 1px dashed var(--el-color-primary);
314
+ }
315
+ }
316
+ .el-upload-dragger.is-dragover {
317
+ background-color: var(--el-color-primary-light-9);
318
+ border: 2px dashed var(--el-color-primary) !important;
319
+ }
320
+ .el-upload-list__item,
321
+ .el-upload--picture-card {
322
+ width: v-bind(width);
323
+ height: v-bind(height);
324
+ // background-color: transparent;
325
+ border-radius: v-bind(borderRadius);
326
+ }
327
+ .upload-image {
328
+ width: 100%;
329
+ height: 100%;
330
+ object-fit: cover;
331
+ }
332
+ .upload-handle {
333
+ position: absolute;
334
+ top: 0;
335
+ right: 0;
336
+ box-sizing: border-box;
337
+ display: flex;
338
+ align-items: center;
339
+ justify-content: center;
340
+ width: 100%;
341
+ height: 100%;
342
+ cursor: pointer;
343
+ background: rgb(0 0 0 / 60%);
344
+ opacity: 0;
345
+ transition: var(--el-transition-duration-fast);
346
+ .handle-icon {
347
+ display: flex;
348
+ flex-direction: column;
349
+ align-items: center;
350
+ justify-content: center;
351
+ padding: 0 6%;
352
+ color: aliceblue;
353
+ .el-icon {
354
+ margin-bottom: 15%;
355
+ font-size: 140%;
356
+ }
357
+ span {
358
+ font-size: 100%;
359
+ }
360
+ }
361
+ }
362
+ .el-upload-list__item {
363
+ &:hover {
364
+ .upload-handle {
365
+ opacity: 1;
366
+ }
367
+ }
368
+ }
369
+ .upload-empty {
370
+ display: flex;
371
+ flex-direction: column;
372
+ align-items: center;
373
+ font-size: 12px;
374
+ line-height: 30px;
375
+ color: var(--el-color-info);
376
+ .el-icon {
377
+ font-size: 28px;
378
+ color: var(--el-text-color-secondary);
379
+ }
380
+ }
381
+ }
382
+ .el-upload__tip {
383
+ line-height: 15px;
384
+ text-align: left;
385
+ }
386
+ }
387
+ .jzt-upload-loading {
388
+ position: absolute;
389
+ top: 0;
390
+ right: 0;
391
+ display: flex;
392
+ align-items: center;
393
+ justify-content: center;
394
+ width: 100%;
395
+ height: 100%;
396
+ background: rgb(0 0 0 / 50%);
397
+ .loading-icon {
398
+ font-size: 24px;
399
+ color: #fff;
400
+ animation: rotate 1.5s linear infinite;
401
+ }
402
+ }
403
+ @keyframes rotate {
404
+ from {
405
+ transform: rotate(0deg);
406
+ }
407
+ to {
408
+ transform: rotate(360deg);
409
+ }
410
+ }
411
+ </style>
@@ -0,0 +1,138 @@
1
+ // 公共样式
2
+ .no-upload {
3
+ :deep(.el-upload) {
4
+ display: none;
5
+ }
6
+ }
7
+ .is-error {
8
+ .upload {
9
+ :deep(.el-upload--picture-card),
10
+ :deep(.el-upload-dragger) {
11
+ border: 1px dashed var(--el-color-danger) !important;
12
+ &:hover {
13
+ border-color: var(--el-color-primary) !important;
14
+ }
15
+ }
16
+ }
17
+ }
18
+ :deep(.disabled) {
19
+ .el-upload--picture-card,
20
+ .el-upload-dragger {
21
+ cursor: not-allowed;
22
+ background: var(--el-disabled-bg-color) !important;
23
+ border: 1px dashed var(--el-border-color-darker);
24
+ &:hover {
25
+ border-color: var(--el-border-color-darker) !important;
26
+ }
27
+ }
28
+ }
29
+ .el-upload__tip {
30
+ line-height: 15px;
31
+ text-align: left;
32
+ }
33
+ .upload-empty {
34
+ display: flex;
35
+ flex-direction: column;
36
+ align-items: center;
37
+ font-size: 12px;
38
+ line-height: 30px;
39
+ color: var(--el-color-info);
40
+ .el-icon {
41
+ font-size: 28px;
42
+ color: var(--el-text-color-secondary);
43
+ }
44
+ }
45
+ //文件上传
46
+ .file_upload_box {
47
+ .upload-btn {
48
+ display: flex;
49
+ align-items: center;
50
+ justify-content: flex-start;
51
+ .el-button {
52
+ margin-right: 10px;
53
+ }
54
+ }
55
+ }
56
+ //图片上传
57
+ .img_upload_box {
58
+ .no-border {
59
+ :deep(.el-upload--picture-card) {
60
+ border: none !important;
61
+ }
62
+ }
63
+ :deep(.upload) {
64
+ .el-upload-dragger {
65
+ display: flex;
66
+ align-items: center;
67
+ justify-content: center;
68
+ width: 100%;
69
+ height: 100%;
70
+ padding: 0;
71
+ overflow: hidden;
72
+ border: 1px dashed var(--el-border-color-darker);
73
+ // border-radius: v-bind(borderRadius);
74
+ background-color: #fff !important;
75
+ &:hover {
76
+ border: 1px dashed var(--el-color-primary);
77
+ }
78
+ }
79
+ .el-upload-dragger.is-dragover {
80
+ background-color: var(--el-color-primary-light-9);
81
+ border: 2px dashed var(--el-color-primary) !important;
82
+ }
83
+ // .el-upload-list__item,
84
+ // .el-upload--picture-card {
85
+ // width: v-bind(width);
86
+ // height: v-bind(height);
87
+ // // background-color: transparent;
88
+ // border-radius: v-bind(borderRadius);
89
+ // }
90
+ .upload-image {
91
+ width: 100%;
92
+ height: 100%;
93
+ // object-fit: contain;
94
+ object-fit: cover;
95
+ }
96
+ .upload-handle {
97
+ position: absolute;
98
+ top: 0;
99
+ right: 0;
100
+ box-sizing: border-box;
101
+ display: flex;
102
+ align-items: center;
103
+ justify-content: center;
104
+ width: 100%;
105
+ height: 100%;
106
+ cursor: pointer;
107
+ background: rgb(0 0 0 / 60%);
108
+ opacity: 0;
109
+ transition: var(--el-transition-duration-fast);
110
+ .handle-icon {
111
+ display: flex;
112
+ flex-direction: column;
113
+ align-items: center;
114
+ justify-content: center;
115
+ padding: 0 6%;
116
+ color: aliceblue;
117
+ .el-icon {
118
+ margin-bottom: 15%;
119
+ font-size: 140%;
120
+ }
121
+ span {
122
+ font-size: 100%;
123
+ }
124
+ }
125
+ }
126
+ .el-upload-list__item {
127
+ &:hover {
128
+ .upload-handle {
129
+ opacity: 1;
130
+ }
131
+ }
132
+ }
133
+ }
134
+ .el-upload__tip {
135
+ line-height: 15px;
136
+ text-align: left;
137
+ }
138
+ }
@@ -0,0 +1,22 @@
1
+ // /* FileType */
2
+ // declare namespace File {
3
+ // type ImageMimeType =
4
+ // | 'image/apng'
5
+ // | 'image/bmp'
6
+ // | 'image/gif'
7
+ // | 'image/jpeg'
8
+ // | 'image/pjpeg'
9
+ // | 'image/png'
10
+ // | 'image/svg+xml'
11
+ // | 'image/tiff'
12
+ // | 'image/webp'
13
+ // | 'image/x-icon'
14
+
15
+ // type ExcelMimeType = 'application/vnd.ms-excel' | 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
16
+
17
+ // type FileMimeType = 'image/jpeg' | 'image/pjpeg' | 'image/png' | 'image/webp' | 'image/x-icon' | 'application/pdf'
18
+
19
+ // type FilePostfixType = '.jpeg' | '.png' | '.png' | '.jpg' | '.pdf'
20
+
21
+ // type ImagePostfixType = ' .jpeg' | '.png' | '.png' | '.jpg'
22
+ // }
@@ -0,0 +1,39 @@
1
+ .icon-box {
2
+ width: 100%;
3
+ .el-button {
4
+ display: flex;
5
+ align-items: center;
6
+ justify-content: center;
7
+ font-size: 18px;
8
+ color: var(--el-text-color-regular);
9
+ }
10
+ :deep(.el-dialog__body) {
11
+ padding: 25px 20px 20px;
12
+ .el-input {
13
+ margin-bottom: 10px;
14
+ }
15
+ .icon-list {
16
+ display: grid;
17
+ grid-template-columns: repeat(auto-fill, 115px);
18
+ justify-content: space-evenly;
19
+ max-height: 70vh;
20
+ .icon-item {
21
+ display: flex;
22
+ flex-direction: column;
23
+ align-items: center;
24
+ width: 42px;
25
+ padding: 20px 30px;
26
+ cursor: pointer;
27
+ transition: all 0.2s;
28
+ &:hover {
29
+ transform: scale(1.3);
30
+ }
31
+ span {
32
+ margin-top: 5px;
33
+ line-height: 20px;
34
+ text-align: center;
35
+ }
36
+ }
37
+ }
38
+ }
39
+ }
@@ -0,0 +1,106 @@
1
+ <template>
2
+ <div class="icon-box">
3
+ <el-input
4
+ ref="inputRef"
5
+ v-model="valueIcon"
6
+ v-bind="$attrs"
7
+ :placeholder="placeholder"
8
+ :clearable="clearable"
9
+ @clear="clearIcon"
10
+ @click="openDialog"
11
+ >
12
+ <template #append>
13
+ <el-button :icon="customIcons[iconValue]" />
14
+ </template>
15
+ </el-input>
16
+ <el-dialog
17
+ v-model="dialogVisible"
18
+ :title="placeholder"
19
+ top="50px"
20
+ width="66%"
21
+ >
22
+ <el-input
23
+ v-model="inputValue"
24
+ placeholder="搜索图标"
25
+ size="large"
26
+ :prefix-icon="Icons.Search"
27
+ />
28
+ <el-scrollbar v-if="Object.keys(iconsList).length">
29
+ <div class="icon-list">
30
+ <div
31
+ v-for="item in iconsList"
32
+ :key="item"
33
+ class="icon-item"
34
+ @click="selectIcon(item)"
35
+ >
36
+ <component :is="item"></component>
37
+ <span>{{ item.name }}</span>
38
+ </div>
39
+ </div>
40
+ </el-scrollbar>
41
+ <el-empty v-else description="未搜索到您要找的图标~" />
42
+ </el-dialog>
43
+ </div>
44
+ </template>
45
+
46
+ <script setup lang="ts" name="SelectIcon">
47
+ import { ref, computed } from "vue";
48
+ import * as Icons from "@element-plus/icons-vue";
49
+
50
+ interface SelectIconProps {
51
+ iconValue: string;
52
+ title?: string;
53
+ clearable?: boolean;
54
+ placeholder?: string;
55
+ }
56
+
57
+ const props = withDefaults(defineProps<SelectIconProps>(), {
58
+ iconValue: "",
59
+ title: "请选择图标",
60
+ clearable: true,
61
+ placeholder: "请选择图标",
62
+ });
63
+
64
+ // 重新接收一下,防止打包后 clearable 报错
65
+ const valueIcon = ref(props.iconValue);
66
+
67
+ // open Dialog
68
+ const dialogVisible = ref(false);
69
+ const openDialog = () => (dialogVisible.value = true);
70
+
71
+ // 选择图标(触发更新父组件数据)
72
+ const emit = defineEmits<{
73
+ "update:iconValue": [value: string];
74
+ }>();
75
+ const selectIcon = (item: any) => {
76
+ dialogVisible.value = false;
77
+ valueIcon.value = item.name;
78
+ emit("update:iconValue", item.name);
79
+ setTimeout(() => inputRef.value.blur(), 0);
80
+ };
81
+
82
+ // 清空图标
83
+ const inputRef = ref();
84
+ const clearIcon = () => {
85
+ valueIcon.value = "";
86
+ emit("update:iconValue", "");
87
+ setTimeout(() => inputRef.value.blur(), 0);
88
+ };
89
+
90
+ // 监听搜索框值
91
+ const inputValue = ref("");
92
+ const customIcons: { [key: string]: any } = Icons;
93
+ const iconsList = computed((): { [key: string]: any } => {
94
+ if (!inputValue.value) return Icons;
95
+ let result: { [key: string]: any } = {};
96
+ for (const key in customIcons) {
97
+ if (key.toLowerCase().indexOf(inputValue.value.toLowerCase()) > -1)
98
+ result[key] = customIcons[key];
99
+ }
100
+ return result;
101
+ });
102
+ </script>
103
+
104
+ <style scoped lang="scss">
105
+ @use "./index";
106
+ </style>