@vrojs/element-plus 0.0.1

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 (88) hide show
  1. package/package.json +56 -0
  2. package/src/index.ts +13 -0
  3. package/src/locale/index.ts +3 -0
  4. package/src/locale/lang/zh-cn.ts +22 -0
  5. package/src/locale/types.ts +8 -0
  6. package/src/locale/useLocale.ts +42 -0
  7. package/src/style/base.scss +2 -0
  8. package/src/style/css.ts +2 -0
  9. package/src/style/deps.ts +9 -0
  10. package/src/style/index.scss +12 -0
  11. package/src/style/index.ts +2 -0
  12. package/src/utils/datePickerValueFormat.ts +6 -0
  13. package/src/utils/index.ts +2 -0
  14. package/src/vro-el-checkbox-group/README.md +83 -0
  15. package/src/vro-el-checkbox-group/index.ts +16 -0
  16. package/src/vro-el-checkbox-group/style/css.ts +2 -0
  17. package/src/vro-el-checkbox-group/style/deps.ts +2 -0
  18. package/src/vro-el-checkbox-group/style/index.scss +1 -0
  19. package/src/vro-el-checkbox-group/style/index.ts +2 -0
  20. package/src/vro-el-checkbox-group/types.ts +18 -0
  21. package/src/vro-el-checkbox-group/vro-el-checkbox-group.vue +33 -0
  22. package/src/vro-el-config-provider/README.md +65 -0
  23. package/src/vro-el-config-provider/index.ts +16 -0
  24. package/src/vro-el-config-provider/style/css.ts +2 -0
  25. package/src/vro-el-config-provider/style/deps.ts +0 -0
  26. package/src/vro-el-config-provider/style/index.scss +0 -0
  27. package/src/vro-el-config-provider/style/index.ts +2 -0
  28. package/src/vro-el-config-provider/types.ts +18 -0
  29. package/src/vro-el-config-provider/vro-el-config-provider.vue +19 -0
  30. package/src/vro-el-file-upload/README.md +89 -0
  31. package/src/vro-el-file-upload/index.ts +17 -0
  32. package/src/vro-el-file-upload/style/css.ts +2 -0
  33. package/src/vro-el-file-upload/style/deps.ts +2 -0
  34. package/src/vro-el-file-upload/style/index.scss +30 -0
  35. package/src/vro-el-file-upload/style/index.ts +2 -0
  36. package/src/vro-el-file-upload/types.ts +50 -0
  37. package/src/vro-el-file-upload/utils.ts +7 -0
  38. package/src/vro-el-file-upload/vro-el-file-upload.vue +95 -0
  39. package/src/vro-el-icon/README.md +68 -0
  40. package/src/vro-el-icon/index.ts +16 -0
  41. package/src/vro-el-icon/style/css.ts +2 -0
  42. package/src/vro-el-icon/style/deps.ts +1 -0
  43. package/src/vro-el-icon/style/index.scss +1 -0
  44. package/src/vro-el-icon/style/index.ts +2 -0
  45. package/src/vro-el-icon/types.ts +12 -0
  46. package/src/vro-el-icon/vro-el-icon.vue +28 -0
  47. package/src/vro-el-image-upload/README.md +99 -0
  48. package/src/vro-el-image-upload/index.ts +17 -0
  49. package/src/vro-el-image-upload/style/css.ts +2 -0
  50. package/src/vro-el-image-upload/style/deps.ts +4 -0
  51. package/src/vro-el-image-upload/style/index.scss +55 -0
  52. package/src/vro-el-image-upload/style/index.ts +2 -0
  53. package/src/vro-el-image-upload/types.ts +42 -0
  54. package/src/vro-el-image-upload/utils.ts +7 -0
  55. package/src/vro-el-image-upload/vro-el-image-upload.vue +134 -0
  56. package/src/vro-el-schema-form-dialog/README.md +64 -0
  57. package/src/vro-el-schema-form-dialog/function-call.ts +12 -0
  58. package/src/vro-el-schema-form-dialog/index.ts +17 -0
  59. package/src/vro-el-schema-form-dialog/style/css.ts +2 -0
  60. package/src/vro-el-schema-form-dialog/style/deps.ts +0 -0
  61. package/src/vro-el-schema-form-dialog/style/index.scss +1 -0
  62. package/src/vro-el-schema-form-dialog/style/index.ts +2 -0
  63. package/src/vro-el-schema-form-dialog/types.ts +5 -0
  64. package/src/vro-el-schema-form-dialog/vro-el-schema-form-dialog.vue +32 -0
  65. package/src/vro-el-select/README.md +83 -0
  66. package/src/vro-el-select/index.ts +16 -0
  67. package/src/vro-el-select/style/css.ts +2 -0
  68. package/src/vro-el-select/style/deps.ts +2 -0
  69. package/src/vro-el-select/style/index.scss +1 -0
  70. package/src/vro-el-select/style/index.ts +2 -0
  71. package/src/vro-el-select/types.ts +18 -0
  72. package/src/vro-el-select/vro-el-select.vue +33 -0
  73. package/src/vro-el-skeleton/README.md +128 -0
  74. package/src/vro-el-skeleton/index.ts +16 -0
  75. package/src/vro-el-skeleton/style/css.ts +3 -0
  76. package/src/vro-el-skeleton/style/deps.ts +3 -0
  77. package/src/vro-el-skeleton/style/index.scss +24 -0
  78. package/src/vro-el-skeleton/style/index.ts +2 -0
  79. package/src/vro-el-skeleton/types.ts +86 -0
  80. package/src/vro-el-skeleton/vro-el-skeleton.vue +73 -0
  81. package/src/vro-el-with-config/README.md +75 -0
  82. package/src/vro-el-with-config/index.ts +16 -0
  83. package/src/vro-el-with-config/style/css.ts +3 -0
  84. package/src/vro-el-with-config/style/deps.ts +2 -0
  85. package/src/vro-el-with-config/style/index.scss +0 -0
  86. package/src/vro-el-with-config/style/index.ts +2 -0
  87. package/src/vro-el-with-config/types.ts +18 -0
  88. package/src/vro-el-with-config/vro-el-with-config.vue +48 -0
@@ -0,0 +1,50 @@
1
+ import type { ExtractPropTypes, PropType } from 'vue'
2
+
3
+ export interface VroElFileUploadCallback<T = any> {
4
+ (
5
+ files: File[],
6
+ options: {
7
+ params: T
8
+ },
9
+ ): Promise<string[]>
10
+ }
11
+
12
+ export const vroElFileUploadProps = {
13
+ /**
14
+ * 绑定值。单文件时可传字符串,多文件时传字符串数组。
15
+ */
16
+ modelValue: {
17
+ type: [String, Array] as PropType<string | string[]>,
18
+ default: '',
19
+ },
20
+
21
+ /**
22
+ * 原生文件选择 accept 属性。
23
+ */
24
+ accept: String,
25
+
26
+ /**
27
+ * 最大上传数量。
28
+ */
29
+ max: {
30
+ type: Number,
31
+ default: 1,
32
+ },
33
+
34
+ /**
35
+ * 是否禁用上传和删除。
36
+ */
37
+ disabled: Boolean,
38
+
39
+ /**
40
+ * 上传时透传给 upload 回调的自定义参数。
41
+ */
42
+ params: Object as PropType<Record<string, any>>,
43
+
44
+ /**
45
+ * 上传回调,接收本次选择的文件列表,返回文件访问地址列表。
46
+ */
47
+ upload: Function as PropType<VroElFileUploadCallback>,
48
+ }
49
+
50
+ export type VroElFileUploadProps = ExtractPropTypes<typeof vroElFileUploadProps>
@@ -0,0 +1,7 @@
1
+ import { createFactory } from '@daysnap/utils'
2
+
3
+ import type { VroElFileUploadProps } from './types'
4
+
5
+ export const [setVroElFileUploadOptions, getVroElFileUploadOptions] = createFactory<
6
+ Partial<Pick<VroElFileUploadProps, 'upload'>>
7
+ >({})
@@ -0,0 +1,95 @@
1
+ <template>
2
+ <div class="vro-el-file-upload">
3
+ <el-button
4
+ v-if="computeValue.length < max && !disabled"
5
+ class="vro-el-file-upload-btn"
6
+ :loading="loading"
7
+ :disabled="disabled"
8
+ type="primary"
9
+ icon="upload"
10
+ >
11
+ {{ t('fileUpload.btnText') }}
12
+ <input type="file" :accept="accept" :multiple="max > 1" @change="handleUpload" />
13
+ </el-button>
14
+
15
+ <ul class="vro-el-file-upload-content">
16
+ <li class="vro-el-file-upload-item" v-for="(item, index) in computeValue" :key="index">
17
+ <a :href="item" target="_blank">{{ item }}</a>
18
+ <el-icon v-if="!disabled" @click="handleDelete(index)">
19
+ <circle-close-filled />
20
+ </el-icon>
21
+ </li>
22
+ </ul>
23
+ </div>
24
+ </template>
25
+
26
+ <script setup lang="ts">
27
+ import { isArray, isUndefined, omitBy } from '@daysnap/utils'
28
+ import { CircleCloseFilled } from '@element-plus/icons-vue'
29
+ import { useAsyncTask } from '@vrojs/use'
30
+ import { ElButton, ElIcon } from 'element-plus'
31
+ import { computed } from 'vue'
32
+
33
+ import { useLocale } from '../locale'
34
+ import { type VroElFileUploadProps, vroElFileUploadProps } from './types'
35
+ import { getVroElFileUploadOptions } from './utils'
36
+
37
+ defineOptions({ name: 'VroElFileUpload' })
38
+
39
+ const emit = defineEmits<{
40
+ (event: 'update:modelValue', value: string | string[]): void
41
+ }>()
42
+
43
+ const rawProps = defineProps(vroElFileUploadProps)
44
+
45
+ const { t } = useLocale()
46
+
47
+ const props = computed(() => {
48
+ return {
49
+ ...getVroElFileUploadOptions(),
50
+ ...omitBy(rawProps, isUndefined),
51
+ } as VroElFileUploadProps
52
+ })
53
+
54
+ const computeValue = computed(() => {
55
+ const { modelValue } = props.value
56
+ return isArray(modelValue) ? modelValue : modelValue ? [modelValue] : []
57
+ })
58
+
59
+ const handleDelete = (index: number) => {
60
+ let value: string | string[] = ''
61
+ if (isArray(props.value.modelValue)) {
62
+ value = [...props.value.modelValue]
63
+ value.splice(index, 1)
64
+ }
65
+ emit('update:modelValue', value)
66
+ }
67
+
68
+ const { loading, trigger: handleUpload } = useAsyncTask(
69
+ async (event: Event) => {
70
+ const target = event.target as HTMLInputElement
71
+ const files = Array.from(target.files ?? [])
72
+ target.value = ''
73
+ if (!files?.length) {
74
+ return
75
+ }
76
+
77
+ const { modelValue, max, upload, params } = props.value
78
+
79
+ if (!upload) {
80
+ throw new Error('not set upload')
81
+ }
82
+
83
+ const res = await upload(files.slice(0, max - computeValue.value.length), { params })
84
+
85
+ let value: string | string[] = res[0]
86
+ if (isArray(modelValue)) {
87
+ value = [...modelValue, ...res]
88
+ }
89
+ emit('update:modelValue', value)
90
+ },
91
+ {
92
+ throwError: true,
93
+ },
94
+ )
95
+ </script>
@@ -0,0 +1,68 @@
1
+ # VroElIcon
2
+
3
+ ### 介绍
4
+
5
+ 基于 `ElIcon` 的图标封装。`name` 传入 Element Plus 图标组件或大写组件名时按组件渲染,传入普通字符串时按 `iconfont` 类名渲染。
6
+
7
+ ## 代码演示
8
+
9
+ ### 基础用法
10
+
11
+ ```html
12
+ <template>
13
+ <vro-el-icon :name="Search" />
14
+ <vro-el-icon name="icon-search" />
15
+ </template>
16
+
17
+ <script setup lang="ts">
18
+ import { Search } from '@element-plus/icons-vue'
19
+ </script>
20
+ ```
21
+
22
+ ### 使用插槽
23
+
24
+ ```html
25
+ <vro-el-icon>
26
+ <search />
27
+ </vro-el-icon>
28
+ ```
29
+
30
+ ## API
31
+
32
+ ### 属性 Props
33
+
34
+ <table>
35
+ <tbody>
36
+ <tr>
37
+ <td>名称</td>
38
+ <td>类型</td>
39
+ <td>默认值</td>
40
+ </tr>
41
+ <tr v-for="(item, key) in vroElIconProps" :key="key">
42
+ <td>{{ key }}</td>
43
+ <td>{{ parseType(item.type || item) }}</td>
44
+ <td>{{ reserve(item.default, '-') }}</td>
45
+ </tr>
46
+ </tbody>
47
+ </table>
48
+
49
+ ### 插槽 Slots
50
+
51
+ <table>
52
+ <tbody>
53
+ <tr>
54
+ <td>名称</td>
55
+ <td>说明</td>
56
+ </tr>
57
+ <tr>
58
+ <td>default</td>
59
+ <td>自定义图标内容</td>
60
+ </tr>
61
+ </tbody>
62
+ </table>
63
+
64
+ <script setup lang="ts">
65
+ import { reserve } from '@daysnap/utils'
66
+ import { VroElIcon, vroElIconProps } from '.'
67
+ import { parseType } from '../utils'
68
+ </script>
@@ -0,0 +1,16 @@
1
+ import { withInstall } from '@vrojs/base'
2
+
3
+ import Component from './vro-el-icon.vue'
4
+
5
+ export * from './types'
6
+
7
+ export const VroElIcon = withInstall<typeof Component>(Component)
8
+ export default VroElIcon
9
+
10
+ export type VroElIconInstance = InstanceType<typeof VroElIcon>
11
+
12
+ declare module 'vue' {
13
+ export interface GlobalComponents {
14
+ VroElIcon: typeof VroElIcon
15
+ }
16
+ }
@@ -0,0 +1,2 @@
1
+ import '../../style/base.scss'
2
+ import './index.scss'
@@ -0,0 +1 @@
1
+ import 'element-plus/es/components/icon/style/css'
@@ -0,0 +1 @@
1
+ .vro-el-icon { }
@@ -0,0 +1,2 @@
1
+ import './deps'
2
+ import './css'
@@ -0,0 +1,12 @@
1
+ import { iconProps } from 'element-plus'
2
+ import type { ExtractPropTypes, PropType, Raw } from 'vue'
3
+
4
+ export const vroElIconProps = {
5
+ ...iconProps,
6
+ name: {
7
+ type: [String, Object] as PropType<string | Raw<object>>,
8
+ default: '',
9
+ },
10
+ }
11
+
12
+ export type VroElIconProps = ExtractPropTypes<typeof vroElIconProps>
@@ -0,0 +1,28 @@
1
+ <template>
2
+ <el-icon class="vro-el-icon" v-bind="props">
3
+ <slot>
4
+ <component v-if="isElement" :is="name" />
5
+ <i v-else class="iconfont" :class="[name]"></i>
6
+ </slot>
7
+ </el-icon>
8
+ </template>
9
+
10
+ <script setup lang="ts">
11
+ import { isString } from '@daysnap/utils'
12
+ import { ElIcon } from 'element-plus'
13
+ import { computed } from 'vue'
14
+
15
+ import { vroElIconProps } from './types'
16
+
17
+ defineOptions({ name: 'VroElIcon' })
18
+ const props = defineProps(vroElIconProps)
19
+
20
+ const isElement = computed(() => {
21
+ const { name } = props
22
+ if (isString(name)) {
23
+ const char = name.substring(0, 1)
24
+ return char >= 'A' && char <= 'Z'
25
+ }
26
+ return true
27
+ })
28
+ </script>
@@ -0,0 +1,99 @@
1
+ # VroElImageUpload
2
+
3
+ ### 介绍
4
+
5
+ 基于 Element Plus Image 的图片上传组件。组件负责图片选择、预览、删除和拖拽排序,实际上传逻辑由 `upload` 回调提供。
6
+
7
+ ## 代码演示
8
+
9
+ ### 基础用法
10
+
11
+ ```html
12
+ <template>
13
+ <vro-el-image-upload v-model="value" :upload="upload" />
14
+ </template>
15
+
16
+ <script setup lang="ts">
17
+ import { ref } from 'vue'
18
+
19
+ const value = ref('')
20
+
21
+ const upload = async (files: File[]) => {
22
+ return files.map((file) => URL.createObjectURL(file))
23
+ }
24
+ </script>
25
+ ```
26
+
27
+ ### 多图上传
28
+
29
+ ```html
30
+ <vro-el-image-upload v-model="value" :max="3" :upload="upload" />
31
+ ```
32
+
33
+ ### 图片压缩
34
+
35
+ ```html
36
+ <vro-el-image-upload v-model="value" compressible :upload="upload" />
37
+ ```
38
+
39
+ ### 全局上传配置
40
+
41
+ ```ts
42
+ import { setVroElImageUploadOptions } from '@vrojs/element-plus'
43
+
44
+ setVroElImageUploadOptions({
45
+ compressible: false,
46
+ imageProps: {
47
+ fit: 'cover',
48
+ },
49
+ upload: async (files, { compress, params }) => {
50
+ return files.map((file) => `${params.domain}/${compress ? 'compressed' : 'raw'}/${file.name}`)
51
+ },
52
+ })
53
+ ```
54
+
55
+ ## API
56
+
57
+ ### 属性 Props
58
+
59
+ <table>
60
+ <tbody>
61
+ <tr>
62
+ <td>名称</td>
63
+ <td>类型</td>
64
+ <td>默认值</td>
65
+ </tr>
66
+ <tr v-for="(item, key) in vroElImageUploadProps" :key="key">
67
+ <td>{{ key }}</td>
68
+ <td>{{ parseType(item.type || item) }}</td>
69
+ <td>{{ reserve(item.default, '-') }}</td>
70
+ </tr>
71
+ </tbody>
72
+ </table>
73
+
74
+ ### 插槽 Slots
75
+
76
+ 暂无。
77
+
78
+ ### 事件 Events
79
+
80
+ <table>
81
+ <tbody>
82
+ <tr>
83
+ <td>名称</td>
84
+ <td>参数</td>
85
+ <td>说明</td>
86
+ </tr>
87
+ <tr>
88
+ <td>update:modelValue</td>
89
+ <td>value: string | string[]</td>
90
+ <td>上传、删除或排序后触发</td>
91
+ </tr>
92
+ </tbody>
93
+ </table>
94
+
95
+ <script setup lang="ts">
96
+ import { reserve } from '@daysnap/utils'
97
+ import { VroElImageUpload, vroElImageUploadProps } from '.'
98
+ import { parseType } from '../utils'
99
+ </script>
@@ -0,0 +1,17 @@
1
+ import { withInstall } from '@vrojs/base'
2
+
3
+ import Component from './vro-el-image-upload.vue'
4
+
5
+ export * from './types'
6
+ export * from './utils'
7
+
8
+ export const VroElImageUpload = withInstall<typeof Component>(Component)
9
+ export default VroElImageUpload
10
+
11
+ export type VroElImageUploadInstance = InstanceType<typeof VroElImageUpload>
12
+
13
+ declare module 'vue' {
14
+ export interface GlobalComponents {
15
+ VroElImageUpload: typeof VroElImageUpload
16
+ }
17
+ }
@@ -0,0 +1,2 @@
1
+ import '../../style/base.scss'
2
+ import './index.scss'
@@ -0,0 +1,4 @@
1
+ import 'element-plus/es/components/checkbox/style/css'
2
+ import 'element-plus/es/components/icon/style/css'
3
+ import 'element-plus/es/components/image/style/css'
4
+ import 'element-plus/es/components/loading/style/css'
@@ -0,0 +1,55 @@
1
+ .vro-el-image-upload-content {
2
+ display: flex;
3
+ flex-wrap: wrap;
4
+ margin-top: -10px;
5
+ }
6
+ .vro-el-image-upload-item {
7
+ cursor: pointer;
8
+ position: relative;
9
+ box-sizing: border-box;
10
+ display: flex;
11
+ align-items: center;
12
+ justify-content: center;
13
+ margin-top: 10px;
14
+ margin-right: 10px;
15
+ font-size: 24px;
16
+ border-radius: 4px;
17
+ width: 100px;
18
+ height: 100px;
19
+ border: 1px #ccc dashed;
20
+ .vro-el-image-upload-image,
21
+ img {
22
+ position: absolute;
23
+ width: 100%;
24
+ height: 100%;
25
+ top: 0;
26
+ left: 0;
27
+ object-position: center;
28
+ object-fit: cover;
29
+ border-radius: 4px;
30
+ transform: translate3d(0, 0, 0);
31
+ background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAAAXNSR0IB2cksfwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAlQTFRFyMjI////1tbWF77ztQAAABZJREFUeJxjYGAIDWUggggNbWAgggAA918Ooanz2WEAAAAASUVORK5CYII=)
32
+ center !important;
33
+ background-size: j(8) !important;
34
+ }
35
+ input {
36
+ cursor: pointer;
37
+ position: absolute;
38
+ top: 0;
39
+ left: 0;
40
+ width: 100%;
41
+ height: 100%;
42
+ border-radius: 4px;
43
+ opacity: 0;
44
+ }
45
+ }
46
+ .vro-el-image-upload-clear {
47
+ position: absolute;
48
+ color: #fff;
49
+ border-radius: 50%;
50
+ cursor: pointer;
51
+ font-size: 20px;
52
+ right: -6px;
53
+ top: -6px;
54
+ background: red;
55
+ }
@@ -0,0 +1,2 @@
1
+ import './deps'
2
+ import './css'
@@ -0,0 +1,42 @@
1
+ import type { ElImage } from 'element-plus'
2
+ import type { ExtractPropTypes, PropType } from 'vue'
3
+
4
+ export type VroElImageUploadImageProps = InstanceType<typeof ElImage>['$props']
5
+
6
+ export interface VroElImageUploadCallback<T = any> {
7
+ (
8
+ /** 当前待上传的图片文件列表 */
9
+ files: File[],
10
+ options: {
11
+ /** 是否开启压缩 */
12
+ compress: boolean
13
+ /** 上传时透传的自定义参数 */
14
+ params: T
15
+ },
16
+ ): Promise<string[]>
17
+ }
18
+
19
+ export const vroElImageUploadProps = {
20
+ /** 绑定值,字符串为单图模式,数组为多图模式 */
21
+ modelValue: {
22
+ type: [String, Array] as PropType<string | string[]>,
23
+ default: '',
24
+ },
25
+ /** 最多可上传的图片数量 */
26
+ max: {
27
+ type: Number,
28
+ default: 1,
29
+ },
30
+ /** 是否禁用上传、删除和排序 */
31
+ disabled: Boolean,
32
+ /** 是否显示压缩开关,传入对象时可作为响应式默认值 */
33
+ compressible: [Boolean, Object] as PropType<boolean | { value: boolean }>,
34
+ /** 上传时透传给 upload 回调的自定义参数 */
35
+ params: Object as PropType<Record<string, any>>,
36
+ /** 透传给 Element Plus Image 的属性 */
37
+ imageProps: Object as PropType<Partial<VroElImageUploadImageProps>>,
38
+ /** 自定义上传方法,需要返回图片访问地址列表 */
39
+ upload: Function as PropType<VroElImageUploadCallback>,
40
+ }
41
+
42
+ export type VroElImageUploadProps = ExtractPropTypes<typeof vroElImageUploadProps>
@@ -0,0 +1,7 @@
1
+ import { createFactory } from '@daysnap/utils'
2
+
3
+ import type { VroElImageUploadProps } from './types'
4
+
5
+ export const [setVroElImageUploadOptions, getVroElImageUploadOptions] = createFactory<
6
+ Partial<Pick<VroElImageUploadProps, 'compressible' | 'upload' | 'imageProps'>>
7
+ >({})
@@ -0,0 +1,134 @@
1
+ <template>
2
+ <div class="vro-el-image-upload">
3
+ <vue-draggable
4
+ class="vro-el-image-upload-content"
5
+ :disabled="props.disabled || props.max <= 1"
6
+ :animation="150"
7
+ :model-value="computeValue"
8
+ filter=".vro-el-image-upload-btn"
9
+ @update:model-value="handleUpdate"
10
+ >
11
+ <div class="vro-el-image-upload-item" v-for="(item, index) in computeValue" :key="item">
12
+ <el-image
13
+ class="vro-el-image-upload-image"
14
+ v-bind="props.imageProps"
15
+ :src="item"
16
+ :preview-src-list="computeValue"
17
+ :initial-index="index"
18
+ />
19
+ <el-icon
20
+ v-if="!props.disabled"
21
+ class="vro-el-image-upload-clear"
22
+ @click="handleDelete(index)"
23
+ >
24
+ <circle-close-filled />
25
+ </el-icon>
26
+ </div>
27
+ <div
28
+ v-if="computeValue.length < props.max && !props.disabled"
29
+ v-loading="loading"
30
+ class="vro-el-image-upload-item vro-el-image-upload-btn"
31
+ >
32
+ <el-icon class="vro-el-image-upload-add"><plus /></el-icon>
33
+ <input type="file" accept="image/*" :multiple="props.max > 1" @change="handleUpload" />
34
+ </div>
35
+ </vue-draggable>
36
+ <el-checkbox v-if="!props.disabled && props.compressible" v-model="compress">
37
+ {{ t('imageUpload.compressText') }}
38
+ </el-checkbox>
39
+ </div>
40
+ </template>
41
+
42
+ <script setup lang="ts">
43
+ import { isArray, isBoolean, isUndefined, omitBy } from '@daysnap/utils'
44
+ import { CircleCloseFilled, Plus } from '@element-plus/icons-vue'
45
+ import { useAsyncTask } from '@vrojs/use'
46
+ import { ElCheckbox, ElIcon, ElImage, ElLoading } from 'element-plus'
47
+ import { computed, ref } from 'vue'
48
+ import { VueDraggable } from 'vue-draggable-plus'
49
+
50
+ import { useLocale } from '../locale'
51
+ import { type VroElImageUploadProps, vroElImageUploadProps } from './types'
52
+ import { getVroElImageUploadOptions } from './utils'
53
+
54
+ defineOptions({ name: 'VroElImageUpload' })
55
+
56
+ const emit = defineEmits<{
57
+ 'update:modelValue': [value: string | string[]]
58
+ }>()
59
+ const rawProps = defineProps(vroElImageUploadProps)
60
+ const { t } = useLocale()
61
+
62
+ const props = computed(() => {
63
+ const {
64
+ compressible = false,
65
+ upload,
66
+ ...rest
67
+ } = {
68
+ ...getVroElImageUploadOptions(),
69
+ ...omitBy(rawProps, isUndefined),
70
+ } as VroElImageUploadProps
71
+
72
+ return {
73
+ upload,
74
+ compressible,
75
+ compress: isBoolean(compressible) ? compressible : compressible.value,
76
+ ...rest,
77
+ }
78
+ })
79
+
80
+ const vLoading = ElLoading.directive
81
+ const compress = ref(props.value.compress)
82
+
83
+ const computeValue = computed(() => {
84
+ const { modelValue } = props.value
85
+ return isArray(modelValue) ? modelValue : modelValue ? [modelValue] : []
86
+ })
87
+
88
+ const handleUpdate = (value: string[]) => {
89
+ if (isArray(props.value.modelValue)) {
90
+ emit('update:modelValue', value)
91
+ }
92
+ }
93
+
94
+ const handleDelete = (index: number) => {
95
+ let value: string | string[] = ''
96
+ if (isArray(props.value.modelValue)) {
97
+ value = [...props.value.modelValue]
98
+ value.splice(index, 1)
99
+ }
100
+ emit('update:modelValue', value)
101
+ }
102
+
103
+ const { loading, trigger: handleUpload } = useAsyncTask(
104
+ async (event: Event) => {
105
+ const target = event.target as HTMLInputElement
106
+ const files = Array.from(target.files ?? [])
107
+
108
+ target.value = ''
109
+ if (!files?.length) {
110
+ return
111
+ }
112
+
113
+ const { max, upload, params } = props.value
114
+
115
+ if (!upload) {
116
+ throw new Error('not set upload')
117
+ }
118
+
119
+ const res = await upload(files.slice(0, max - computeValue.value.length), {
120
+ compress: compress.value,
121
+ params,
122
+ })
123
+
124
+ let value: string | string[] = res[0]
125
+ if (isArray(props.value.modelValue)) {
126
+ value = [...props.value.modelValue, ...res]
127
+ }
128
+ emit('update:modelValue', value)
129
+ },
130
+ {
131
+ throwError: true,
132
+ },
133
+ )
134
+ </script>