@peng_kai/kit 0.3.0-beta.32 → 0.3.0-beta.34
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.
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { default as Settings } from './src/Settings.vue';
|
|
2
|
-
export { default as SchemaForm, type IConfigDetail } from './src/SchemaForm.vue';
|
|
2
|
+
export { default as SchemaForm, type IConfigDetail, FormTypes } from './src/SchemaForm.vue';
|
|
@@ -4,6 +4,7 @@ import { CheckboxGroup, DatePicker, type DatePickerProps, Form, FormItem, Input,
|
|
|
4
4
|
import { computed, toRef } from 'vue';
|
|
5
5
|
import dayjs from '../../../../libs/dayjs';
|
|
6
6
|
import { type ItemSchema, useAntdForm } from '../../../../antd';
|
|
7
|
+
import { PictureCardUpload } from '../../../components/upload';
|
|
7
8
|
|
|
8
9
|
export interface IConfigDetail {
|
|
9
10
|
category_id: number
|
|
@@ -19,7 +20,7 @@ export interface IConfigDetail {
|
|
|
19
20
|
value: any
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
enum FormTypes {
|
|
23
|
+
export enum FormTypes {
|
|
23
24
|
/** 数字输入框 */
|
|
24
25
|
NUMBER_INPUT = 0,
|
|
25
26
|
/** 文本输入框 */
|
|
@@ -36,6 +37,8 @@ enum FormTypes {
|
|
|
36
37
|
SINGLE_SELECT = 6,
|
|
37
38
|
/** 多选下拉选择器 */
|
|
38
39
|
MULTIPLE_SELECT = 7,
|
|
40
|
+
/** 图片上传 */
|
|
41
|
+
IMAGE_UPLOAD = 8,
|
|
39
42
|
/** 单一日期选择器 */
|
|
40
43
|
SINGLE_DATE_PICKER = 13,
|
|
41
44
|
/** 日期范围选择器 */
|
|
@@ -81,6 +84,10 @@ const antdPropsResolvers: Record<number, (config: IConfigDetail) => IConfigDetai
|
|
|
81
84
|
[FormTypes.MULTIPLE_SELECT](config) {
|
|
82
85
|
return this[FormTypes.CHECKBOX](config);
|
|
83
86
|
},
|
|
87
|
+
[FormTypes.IMAGE_UPLOAD](config) {
|
|
88
|
+
config.value = config.value.split(',');
|
|
89
|
+
return config;
|
|
90
|
+
},
|
|
84
91
|
[FormTypes.SINGLE_DATE_PICKER](config) {
|
|
85
92
|
const props: DatePickerProps = {};
|
|
86
93
|
|
|
@@ -130,9 +137,11 @@ const antdValueResolvers: Record<number, (value: any) => any> = {
|
|
|
130
137
|
[FormTypes.MULTIPLE_SELECT](value) {
|
|
131
138
|
if (Array.isArray(value))
|
|
132
139
|
return value.join(',');
|
|
133
|
-
|
|
134
140
|
return value;
|
|
135
141
|
},
|
|
142
|
+
[FormTypes.IMAGE_UPLOAD](value) {
|
|
143
|
+
return value.join(',');
|
|
144
|
+
},
|
|
136
145
|
[FormTypes.SINGLE_DATE_PICKER](value) {
|
|
137
146
|
if (dayjs.isDayjs(value))
|
|
138
147
|
return value.format('YYYY-MM-DD');
|
|
@@ -151,9 +160,11 @@ const antdValueResolvers: Record<number, (value: any) => any> = {
|
|
|
151
160
|
<script setup lang="ts">
|
|
152
161
|
const props = withDefaults(defineProps<{
|
|
153
162
|
formConfig: IConfigDetail[]
|
|
163
|
+
formsOptions?: Partial<Record<FormTypes, any>>;
|
|
154
164
|
disabled?: boolean
|
|
155
165
|
}>(), {
|
|
156
166
|
disabled: false,
|
|
167
|
+
formsOptions: () => ({} as any),
|
|
157
168
|
});
|
|
158
169
|
|
|
159
170
|
const configList = computed(() => {
|
|
@@ -268,6 +279,10 @@ defineExpose({ reset, validate });
|
|
|
268
279
|
<Select v-model:value="settingForm.state[item.key]" v-bind="item.options" mode="multiple" />
|
|
269
280
|
</slot>
|
|
270
281
|
|
|
282
|
+
<slot v-else-if="item.form_type === FormTypes.IMAGE_UPLOAD" :name="FormTypes.IMAGE_UPLOAD">
|
|
283
|
+
<PictureCardUpload v-model:urls="settingForm.state[item.key]" useUrl v-bind="{ ...formsOptions[item.form_type], ...item.options}" />
|
|
284
|
+
</slot>
|
|
285
|
+
|
|
271
286
|
<slot v-else-if="item.form_type === FormTypes.SINGLE_DATE_PICKER" :name="FormTypes.SINGLE_DATE_PICKER">
|
|
272
287
|
<DatePicker v-model:value="settingForm.state[item.key]" v-bind="item.options" />
|
|
273
288
|
</slot>
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import { Image as AImage, ImagePreviewGroup as AImagePreviewGroup, Upload as AUpload, message } from 'ant-design-vue';
|
|
3
3
|
import type { UploadProps } from 'ant-design-vue';
|
|
4
4
|
import type { PreviewGroupPreview } from 'ant-design-vue/es/vc-image/src/PreviewGroup';
|
|
5
|
-
import {
|
|
6
|
-
import { ref } from 'vue';
|
|
5
|
+
import { ref, customRef, nextTick, triggerRef } from 'vue';
|
|
7
6
|
import type { AwsS3 } from '../../../../utils/upload';
|
|
8
7
|
import { createAwsS3Request } from './customRequests';
|
|
8
|
+
import { urlToUploadFile } from './helpers';
|
|
9
9
|
|
|
10
10
|
type UploadFile = Parameters<NonNullable<UploadProps['onPreview']>>['0'];
|
|
11
11
|
</script>
|
|
@@ -13,8 +13,12 @@ type UploadFile = Parameters<NonNullable<UploadProps['onPreview']>>['0'];
|
|
|
13
13
|
<script lang="ts" setup>
|
|
14
14
|
const props = withDefaults(
|
|
15
15
|
defineProps<{
|
|
16
|
-
/**
|
|
16
|
+
/** 上传图片的数组 */
|
|
17
17
|
modelValue?: UploadFile[]
|
|
18
|
+
/** 上传图片的 url 数组 */
|
|
19
|
+
urls?: string[]
|
|
20
|
+
/** 是否使用 url 数组 */
|
|
21
|
+
useUrl?: boolean
|
|
18
22
|
/** awsS3 实例对象 */
|
|
19
23
|
awsS3: AwsS3
|
|
20
24
|
/** 根目录 */
|
|
@@ -27,6 +31,8 @@ const props = withDefaults(
|
|
|
27
31
|
cardSize?: string
|
|
28
32
|
/** 允许的图片后缀 */
|
|
29
33
|
allowExts?: string[]
|
|
34
|
+
/** 允许的图片大小,单位为字节 */
|
|
35
|
+
maxSize?: number
|
|
30
36
|
/** 禁用 */
|
|
31
37
|
disabled?: boolean
|
|
32
38
|
}>(),
|
|
@@ -36,14 +42,47 @@ const props = withDefaults(
|
|
|
36
42
|
rowCount: 'auto-fill',
|
|
37
43
|
cardSize: '90px',
|
|
38
44
|
allowExts: () => ['jpg', 'jpeg', 'png', 'gif', 'apng', 'webp', 'svg'],
|
|
45
|
+
maxSize: 1024 * 1024 * 2,
|
|
39
46
|
disabled: false,
|
|
47
|
+
useUrl: false,
|
|
40
48
|
},
|
|
41
49
|
);
|
|
42
50
|
const emits = defineEmits<{
|
|
43
51
|
(e: 'update:modelValue', value: UploadFile[]): void
|
|
52
|
+
(e: 'update:urls', value: string[]): void
|
|
44
53
|
}>();
|
|
45
54
|
|
|
46
|
-
const fileList =
|
|
55
|
+
const fileList = customRef<any>((track, trigger) => {
|
|
56
|
+
let tempValue: any[] = [];
|
|
57
|
+
let isAllDone = true;
|
|
58
|
+
return {
|
|
59
|
+
get() {
|
|
60
|
+
track();
|
|
61
|
+
if (props.useUrl) {
|
|
62
|
+
return isAllDone ? urlToUploadFile(props.urls || []) : tempValue;
|
|
63
|
+
}
|
|
64
|
+
return props.modelValue || [];
|
|
65
|
+
},
|
|
66
|
+
set(v: any) {
|
|
67
|
+
if (props.useUrl) {
|
|
68
|
+
isAllDone = (v || []).every((x: any) => typeof x === 'string' || x.status === 'done');
|
|
69
|
+
if (isAllDone) {
|
|
70
|
+
const urls = (v || []).map((x: any) => typeof x === 'string' ? x : x.response?.url);
|
|
71
|
+
emits('update:urls', urls);
|
|
72
|
+
tempValue = [];
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
tempValue = v;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
emits('update:modelValue', v);
|
|
80
|
+
}
|
|
81
|
+
trigger();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
})
|
|
85
|
+
|
|
47
86
|
const preview = ref<PreviewGroupPreview>({
|
|
48
87
|
visible: false,
|
|
49
88
|
onVisibleChange(value) {
|
|
@@ -54,36 +93,33 @@ const preview = ref<PreviewGroupPreview>({
|
|
|
54
93
|
function handlePreview(file: UploadFile) {
|
|
55
94
|
preview.value.src = file.url || file.thumbUrl;
|
|
56
95
|
preview.value.visible = true;
|
|
57
|
-
preview.value.current = fileList.value?.findIndex(
|
|
96
|
+
preview.value.current = fileList.value?.findIndex((x: any) => preview.value.src === (x.url || x.thumbUrl)) ?? 0;
|
|
58
97
|
}
|
|
59
98
|
|
|
60
99
|
function beforeUpload(file: UploadFile) {
|
|
61
100
|
const isImg = props.allowExts.some(item => String(file.type).toLowerCase().includes(item));
|
|
62
|
-
|
|
101
|
+
const isSizeValid = !!(props.maxSize && file.size && file.size <= props.maxSize);
|
|
63
102
|
if (!isImg)
|
|
64
103
|
message.error(`${file.name} 不是图片 (${props.allowExts.join(',')})`);
|
|
65
|
-
|
|
66
|
-
|
|
104
|
+
if (!isSizeValid)
|
|
105
|
+
message.error(`${file.name} 大小不能超过 ${props.maxSize / 1024 / 1024}MB`);
|
|
106
|
+
|
|
107
|
+
return isImg && isSizeValid;
|
|
67
108
|
}
|
|
68
109
|
</script>
|
|
69
110
|
|
|
70
111
|
<template>
|
|
71
112
|
<div :class="{ 'w-fit': typeof props.rowCount === 'number' }">
|
|
72
|
-
<AUpload
|
|
73
|
-
|
|
74
|
-
:
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
<i v-if="fileList.length < props.maxCount" class="i-ant-design:plus-outlined text-26px text-$antd-colorTextTertiary" />
|
|
113
|
+
<AUpload v-model:fileList="fileList" class="pic-card-upload" listType="picture-card" multiple
|
|
114
|
+
:maxCount="$props.maxCount" :disabled="props.disabled" :beforeUpload="beforeUpload"
|
|
115
|
+
:customRequest="createAwsS3Request($props.awsS3, $props.rootDir)" @preview="handlePreview">
|
|
116
|
+
<i v-if="fileList.length < props.maxCount"
|
|
117
|
+
class="i-ant-design:plus-outlined text-[26px] text-$antd-colorTextTertiary" />
|
|
78
118
|
</AUpload>
|
|
79
119
|
|
|
80
120
|
<div style="display: none">
|
|
81
121
|
<AImagePreviewGroup :preview="preview">
|
|
82
|
-
<AImage
|
|
83
|
-
v-for="item of fileList"
|
|
84
|
-
:key="item.uid"
|
|
85
|
-
:src="item.url || item.thumbUrl"
|
|
86
|
-
/>
|
|
122
|
+
<AImage v-for="item of fileList" :key="item.uid" :src="item.url || item.thumbUrl" />
|
|
87
123
|
</AImagePreviewGroup>
|
|
88
124
|
</div>
|
|
89
125
|
</div>
|
|
@@ -117,7 +153,7 @@ function beforeUpload(file: UploadFile) {
|
|
|
117
153
|
margin: 0;
|
|
118
154
|
}
|
|
119
155
|
|
|
120
|
-
:deep(.ant-upload-list.ant-upload-list-picture-card .ant-upload-list-item::before
|
|
156
|
+
:deep(.ant-upload-list.ant-upload-list-picture-card .ant-upload-list-item::before) {
|
|
121
157
|
width: 100%;
|
|
122
158
|
height: 100%;
|
|
123
159
|
}
|