@deot/vc-components 1.0.24 → 1.0.25
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.
- package/dist/index.cjs +561 -42
- package/dist/index.d.ts +384 -54
- package/dist/index.iife.js +18800 -9241
- package/dist/index.js +562 -43
- package/dist/index.style.css +1 -1
- package/dist/index.umd.cjs +18800 -9241
- package/package.json +3 -2
package/dist/index.cjs
CHANGED
|
@@ -12,6 +12,7 @@ const vcHooks = require('@deot/vc-hooks');
|
|
|
12
12
|
const helperWheel = require('@deot/helper-wheel');
|
|
13
13
|
const helperValidator = require('@deot/helper-validator');
|
|
14
14
|
const helperCache = require('@deot/helper-cache');
|
|
15
|
+
const PhotoSwipeLightbox = require('photoswipe/lightbox');
|
|
15
16
|
const Load = require('@deot/helper-load');
|
|
16
17
|
const helperScheduler = require('@deot/helper-scheduler');
|
|
17
18
|
const lodash = require('lodash');
|
|
@@ -1087,7 +1088,7 @@ const Button = /* @__PURE__ */ vue.defineComponent({
|
|
|
1087
1088
|
slots
|
|
1088
1089
|
}) {
|
|
1089
1090
|
const vm = vue.getCurrentInstance();
|
|
1090
|
-
const
|
|
1091
|
+
const isHover = vue.ref(false);
|
|
1091
1092
|
const isLoading = vue.ref(false);
|
|
1092
1093
|
const group = vue.inject('vc-button-group', {
|
|
1093
1094
|
size: 'medium',
|
|
@@ -1096,10 +1097,11 @@ const Button = /* @__PURE__ */ vue.defineComponent({
|
|
|
1096
1097
|
});
|
|
1097
1098
|
const classes = vue.computed(() => ({
|
|
1098
1099
|
'is-circle': props.circle || group.circle,
|
|
1099
|
-
'is-alone': !
|
|
1100
|
+
'is-alone': !slots?.default,
|
|
1100
1101
|
'is-round': props.round,
|
|
1101
1102
|
'is-long': props.long,
|
|
1102
1103
|
'is-disabled': props.disabled,
|
|
1104
|
+
'is-hover': isHover.value,
|
|
1103
1105
|
[`is-${props.size}`]: true,
|
|
1104
1106
|
[`is-${props.type}`]: true
|
|
1105
1107
|
}));
|
|
@@ -1112,9 +1114,6 @@ const Button = /* @__PURE__ */ vue.defineComponent({
|
|
|
1112
1114
|
});
|
|
1113
1115
|
}
|
|
1114
1116
|
};
|
|
1115
|
-
vue.onMounted(() => {
|
|
1116
|
-
hasSlot.value = slots.default !== undefined;
|
|
1117
|
-
});
|
|
1118
1117
|
return () => {
|
|
1119
1118
|
return vue.createVNode(Debounce, {
|
|
1120
1119
|
"tag": props.tag,
|
|
@@ -1125,15 +1124,19 @@ const Button = /* @__PURE__ */ vue.defineComponent({
|
|
|
1125
1124
|
"wait": props.wait,
|
|
1126
1125
|
"disabled": props.disabled,
|
|
1127
1126
|
"type": props.htmlType,
|
|
1128
|
-
"onClick": handleClick
|
|
1127
|
+
"onClick": handleClick,
|
|
1128
|
+
"onMouseenter": () => isHover.value = true,
|
|
1129
|
+
"onMouseleave": () => isHover.value = false
|
|
1129
1130
|
}, {
|
|
1130
1131
|
default: () => [props.icon && vue.createVNode(Icon, {
|
|
1131
1132
|
"type": props.icon
|
|
1132
|
-
}, null),
|
|
1133
|
+
}, null), slots.icon && slots?.icon?.({
|
|
1134
|
+
hover: isHover.value
|
|
1135
|
+
}), isLoading.value && vue.createVNode(Spin, {
|
|
1133
1136
|
"size": 12,
|
|
1134
1137
|
"foreground": props.type === 'default' ? '#ccc' : '#fff',
|
|
1135
1138
|
"class": "vc-button__loading"
|
|
1136
|
-
}, null),
|
|
1139
|
+
}, null), slots?.default && vue.createVNode("span", null, [slots?.default?.()])]
|
|
1137
1140
|
});
|
|
1138
1141
|
};
|
|
1139
1142
|
}
|
|
@@ -1549,7 +1552,8 @@ const useCheckbox = () => {
|
|
|
1549
1552
|
"is-indeterminate": props.indeterminate,
|
|
1550
1553
|
"is-checked": checked.value,
|
|
1551
1554
|
"is-disabled": props.disabled,
|
|
1552
|
-
"is-focus": isFocus.value
|
|
1555
|
+
"is-focus": isFocus.value,
|
|
1556
|
+
"is-error": !!formItem?.message?.value
|
|
1553
1557
|
};
|
|
1554
1558
|
});
|
|
1555
1559
|
vue.watch(
|
|
@@ -3200,7 +3204,8 @@ const useInput = (input) => {
|
|
|
3200
3204
|
const classes = vue.computed(() => {
|
|
3201
3205
|
return {
|
|
3202
3206
|
"is-focus": isFocus.value,
|
|
3203
|
-
"is-disabled": props.disabled
|
|
3207
|
+
"is-disabled": props.disabled,
|
|
3208
|
+
"is-error": !!formItem?.message?.value
|
|
3204
3209
|
};
|
|
3205
3210
|
});
|
|
3206
3211
|
const currentMaxlength = vue.computed(() => {
|
|
@@ -8721,7 +8726,7 @@ const Drawer$ = new Portal(DrawerView, {
|
|
|
8721
8726
|
multiple: true
|
|
8722
8727
|
});
|
|
8723
8728
|
const destroy$3 = () => Drawer$.destroy();
|
|
8724
|
-
const open$
|
|
8729
|
+
const open$2 = (options) => {
|
|
8725
8730
|
const leaf = Drawer$.popup({
|
|
8726
8731
|
...options,
|
|
8727
8732
|
onFulfilled: options.onClose,
|
|
@@ -8731,7 +8736,7 @@ const open$1 = (options) => {
|
|
|
8731
8736
|
leaf.wrapper.toggle?.(true);
|
|
8732
8737
|
return leaf;
|
|
8733
8738
|
};
|
|
8734
|
-
const Drawer = Object.assign(DrawerView, { open: open$
|
|
8739
|
+
const Drawer = Object.assign(DrawerView, { open: open$2, destroy: destroy$3 });
|
|
8735
8740
|
|
|
8736
8741
|
const MDrawer = Drawer;
|
|
8737
8742
|
const MDrawerView = DrawerView;
|
|
@@ -8830,7 +8835,7 @@ const useForm = (expose, options = {}) => {
|
|
|
8830
8835
|
const instance = vue.getCurrentInstance();
|
|
8831
8836
|
const props = instance.props;
|
|
8832
8837
|
const fields = [];
|
|
8833
|
-
vue.provide("form", {
|
|
8838
|
+
vue.provide("vc-form", {
|
|
8834
8839
|
props,
|
|
8835
8840
|
add: (field) => {
|
|
8836
8841
|
field && fields.push(field);
|
|
@@ -8978,8 +8983,7 @@ const props$L = {
|
|
|
8978
8983
|
default: false
|
|
8979
8984
|
},
|
|
8980
8985
|
labelPosition: {
|
|
8981
|
-
type: String
|
|
8982
|
-
default: "right"
|
|
8986
|
+
type: String
|
|
8983
8987
|
},
|
|
8984
8988
|
contentStyle: [Object, String],
|
|
8985
8989
|
contentClass: [Object, String],
|
|
@@ -8997,7 +9001,7 @@ const toRules = (rules) => {
|
|
|
8997
9001
|
return rules instanceof Array ? rules : rules ? [rules] : [];
|
|
8998
9002
|
};
|
|
8999
9003
|
const useFormItem = (expose) => {
|
|
9000
|
-
const form = vue.inject("form");
|
|
9004
|
+
const form = vue.inject("vc-form");
|
|
9001
9005
|
const instance = vue.getCurrentInstance();
|
|
9002
9006
|
const props = instance.props;
|
|
9003
9007
|
const { slots } = instance;
|
|
@@ -9510,7 +9514,7 @@ const ObjectFit = {
|
|
|
9510
9514
|
FILL: 'fill',
|
|
9511
9515
|
SCALE_DOWN: 'scale-down'
|
|
9512
9516
|
};
|
|
9513
|
-
const Image = /* @__PURE__ */ vue.defineComponent({
|
|
9517
|
+
const Image$1 = /* @__PURE__ */ vue.defineComponent({
|
|
9514
9518
|
name: COMPONENT_NAME$W,
|
|
9515
9519
|
inheritAttrs: false,
|
|
9516
9520
|
props: props$H,
|
|
@@ -9705,7 +9709,7 @@ const Image = /* @__PURE__ */ vue.defineComponent({
|
|
|
9705
9709
|
}
|
|
9706
9710
|
});
|
|
9707
9711
|
|
|
9708
|
-
const MImage = Image;
|
|
9712
|
+
const MImage = Image$1;
|
|
9709
9713
|
|
|
9710
9714
|
const props$G = {
|
|
9711
9715
|
tag: {
|
|
@@ -9743,7 +9747,7 @@ const props$F = {
|
|
|
9743
9747
|
/** @jsxImportSource vue */
|
|
9744
9748
|
|
|
9745
9749
|
const COMPONENT_NAME$U = 'vc-image-preview';
|
|
9746
|
-
const ImagePreview = /* @__PURE__ */ vue.defineComponent({
|
|
9750
|
+
const ImagePreview$1 = /* @__PURE__ */ vue.defineComponent({
|
|
9747
9751
|
name: COMPONENT_NAME$U,
|
|
9748
9752
|
props: props$F,
|
|
9749
9753
|
setup(props, {
|
|
@@ -9757,6 +9761,81 @@ const ImagePreview = /* @__PURE__ */ vue.defineComponent({
|
|
|
9757
9761
|
}
|
|
9758
9762
|
});
|
|
9759
9763
|
|
|
9764
|
+
const MAX_WIDTH = window.innerWidth;
|
|
9765
|
+
const MAX_HEIGHT = window.innerHeight;
|
|
9766
|
+
const getFitSize = (src) => {
|
|
9767
|
+
return new Promise((resolve) => {
|
|
9768
|
+
const img = new Image();
|
|
9769
|
+
let width;
|
|
9770
|
+
let height;
|
|
9771
|
+
img.onload = () => {
|
|
9772
|
+
const owidth = img.naturalWidth || img.width;
|
|
9773
|
+
const oheight = img.naturalHeight || img.height;
|
|
9774
|
+
if (owidth > oheight) {
|
|
9775
|
+
width = Math.min(MAX_WIDTH, owidth);
|
|
9776
|
+
height = width / owidth * oheight;
|
|
9777
|
+
resolve({
|
|
9778
|
+
width,
|
|
9779
|
+
height
|
|
9780
|
+
});
|
|
9781
|
+
} else {
|
|
9782
|
+
height = Math.min(MAX_HEIGHT, oheight);
|
|
9783
|
+
width = height / oheight * owidth;
|
|
9784
|
+
resolve({
|
|
9785
|
+
width,
|
|
9786
|
+
height
|
|
9787
|
+
});
|
|
9788
|
+
}
|
|
9789
|
+
};
|
|
9790
|
+
img.onerror = () => resolve({});
|
|
9791
|
+
img.src = src;
|
|
9792
|
+
});
|
|
9793
|
+
};
|
|
9794
|
+
const open$1 = async (options) => {
|
|
9795
|
+
const e = VcInstance.globalEvent;
|
|
9796
|
+
const data = options.data.map((i) => {
|
|
9797
|
+
if (typeof i === "string") {
|
|
9798
|
+
return {
|
|
9799
|
+
src: i
|
|
9800
|
+
};
|
|
9801
|
+
}
|
|
9802
|
+
return {
|
|
9803
|
+
...i,
|
|
9804
|
+
src: i.source || i.src
|
|
9805
|
+
};
|
|
9806
|
+
});
|
|
9807
|
+
for (let i = 0; i < data.length; i++) {
|
|
9808
|
+
if (!data[i].width) {
|
|
9809
|
+
data[i] = {
|
|
9810
|
+
...data[i],
|
|
9811
|
+
...await getFitSize(data[i].src)
|
|
9812
|
+
};
|
|
9813
|
+
}
|
|
9814
|
+
}
|
|
9815
|
+
const lightbox = new PhotoSwipeLightbox({
|
|
9816
|
+
pswpModule: () => import('photoswipe'),
|
|
9817
|
+
closeTitle: "关闭(Esc)",
|
|
9818
|
+
zoomTitle: "缩放",
|
|
9819
|
+
arrowPrevTitle: "上一张",
|
|
9820
|
+
arrowNextTitle: "下一张",
|
|
9821
|
+
errorMsg: "网络异常 图片加载失败",
|
|
9822
|
+
indexIndicatorSep: " / ",
|
|
9823
|
+
initialZoomLevel: "fit"
|
|
9824
|
+
});
|
|
9825
|
+
lightbox.init();
|
|
9826
|
+
lightbox.loadAndOpen(
|
|
9827
|
+
options.current || 0,
|
|
9828
|
+
data,
|
|
9829
|
+
// 下面无效,需要给官方支持
|
|
9830
|
+
{
|
|
9831
|
+
x: e?.clientX,
|
|
9832
|
+
y: e?.clientY
|
|
9833
|
+
}
|
|
9834
|
+
);
|
|
9835
|
+
};
|
|
9836
|
+
|
|
9837
|
+
const ImagePreview = Object.assign(ImagePreview$1, { open: open$1 });
|
|
9838
|
+
|
|
9760
9839
|
const MImagePreview = ImagePreview;
|
|
9761
9840
|
|
|
9762
9841
|
const props$E = {
|
|
@@ -10363,9 +10442,8 @@ const props$z = {
|
|
|
10363
10442
|
type: [String, Boolean],
|
|
10364
10443
|
default: "取消"
|
|
10365
10444
|
},
|
|
10366
|
-
wrapperStyle:
|
|
10367
|
-
|
|
10368
|
-
},
|
|
10445
|
+
wrapperStyle: [String, Object],
|
|
10446
|
+
wrapperClass: [String, Object],
|
|
10369
10447
|
footer: {
|
|
10370
10448
|
type: Boolean,
|
|
10371
10449
|
default: true
|
|
@@ -10419,6 +10497,7 @@ const ModalView = /* @__PURE__ */ vue.defineComponent({
|
|
|
10419
10497
|
|
|
10420
10498
|
// 注: 服务端渲染为0, 在客服端激活前,展示端存在问题【高度不定】
|
|
10421
10499
|
const MAX_HEIGHT = vcShared.IS_SERVER ? 0 : window.innerHeight - 20;
|
|
10500
|
+
const MAX_WIDTH = vcShared.IS_SERVER ? 0 : window.innerWidth - 20;
|
|
10422
10501
|
const defaultSize = vue.computed(() => {
|
|
10423
10502
|
let width = 0;
|
|
10424
10503
|
let height = 0;
|
|
@@ -10437,7 +10516,7 @@ const ModalView = /* @__PURE__ */ vue.defineComponent({
|
|
|
10437
10516
|
break;
|
|
10438
10517
|
}
|
|
10439
10518
|
return {
|
|
10440
|
-
width: props.width || width,
|
|
10519
|
+
width: Math.min(props.width || width, MAX_WIDTH),
|
|
10441
10520
|
height: Math.min(props.height || height, MAX_HEIGHT)
|
|
10442
10521
|
};
|
|
10443
10522
|
});
|
|
@@ -10673,7 +10752,7 @@ const ModalView = /* @__PURE__ */ vue.defineComponent({
|
|
|
10673
10752
|
"style": [props.wrapperStyle || {}, props.draggable ? {
|
|
10674
10753
|
top: 0
|
|
10675
10754
|
} : {}],
|
|
10676
|
-
"class":
|
|
10755
|
+
"class": [props.wrapperClass, 'vc-modal__wrapper'],
|
|
10677
10756
|
"onClick": e => handleClose(e, false)
|
|
10678
10757
|
}, [vue.createVNode(TransitionScale, {
|
|
10679
10758
|
"mode": "part",
|
|
@@ -12340,8 +12419,12 @@ const Progress = /* @__PURE__ */ vue.defineComponent({
|
|
|
12340
12419
|
setup(props, {
|
|
12341
12420
|
slots
|
|
12342
12421
|
}) {
|
|
12422
|
+
const currentPercent = vue.computed(() => {
|
|
12423
|
+
const v = Number(props.percent);
|
|
12424
|
+
return v >= 100 ? 100 : v;
|
|
12425
|
+
});
|
|
12343
12426
|
const currentStatus = vue.computed(() => {
|
|
12344
|
-
if (
|
|
12427
|
+
if (currentPercent.value === 100) {
|
|
12345
12428
|
return 'success';
|
|
12346
12429
|
}
|
|
12347
12430
|
return props.status;
|
|
@@ -12353,6 +12436,7 @@ const Progress = /* @__PURE__ */ vue.defineComponent({
|
|
|
12353
12436
|
const binds = vue.computed(() => {
|
|
12354
12437
|
return {
|
|
12355
12438
|
...props,
|
|
12439
|
+
percent: currentPercent.value,
|
|
12356
12440
|
status: currentStatus.value,
|
|
12357
12441
|
color: currentColor.value
|
|
12358
12442
|
};
|
|
@@ -12430,7 +12514,8 @@ const useRadio = () => {
|
|
|
12430
12514
|
return {
|
|
12431
12515
|
"is-checked": checked.value,
|
|
12432
12516
|
"is-disabled": isDisabled.value,
|
|
12433
|
-
"is-focus": isFocus.value
|
|
12517
|
+
"is-focus": isFocus.value,
|
|
12518
|
+
"is-error": !!formItem?.message?.value
|
|
12434
12519
|
};
|
|
12435
12520
|
});
|
|
12436
12521
|
vue.watch(
|
|
@@ -12614,8 +12699,7 @@ const RadioGroup = /* @__PURE__ */ vue.defineComponent({
|
|
|
12614
12699
|
return () => {
|
|
12615
12700
|
if (props.fragment) return slots.default?.();
|
|
12616
12701
|
return vue.createVNode("div", {
|
|
12617
|
-
"class":
|
|
12618
|
-
"style": classes.value,
|
|
12702
|
+
"class": [classes.value, 'vc-radio-group'],
|
|
12619
12703
|
"name": props.name
|
|
12620
12704
|
}, [slots?.default?.()]);
|
|
12621
12705
|
};
|
|
@@ -16935,7 +17019,11 @@ const props$a = {
|
|
|
16935
17019
|
closable: {
|
|
16936
17020
|
type: Boolean,
|
|
16937
17021
|
default: false
|
|
16938
|
-
}
|
|
17022
|
+
},
|
|
17023
|
+
barStyle: [Object, String],
|
|
17024
|
+
contentStyle: [Object, String],
|
|
17025
|
+
barClass: [Object, String],
|
|
17026
|
+
contentClass: [Object, String]
|
|
16939
17027
|
};
|
|
16940
17028
|
|
|
16941
17029
|
const useTabs = (options = {}) => {
|
|
@@ -17188,10 +17276,10 @@ const Tabs = /* @__PURE__ */ vue.defineComponent({
|
|
|
17188
17276
|
"class": "vc-tabs__extra"
|
|
17189
17277
|
}, [slots.extra?.()]), vue.createVNode("div", {
|
|
17190
17278
|
"ref": wrapper,
|
|
17191
|
-
"style": {
|
|
17279
|
+
"style": [props.barStyle, {
|
|
17192
17280
|
padding: tabs.scrollable.value ? '0 24px' : 0
|
|
17193
|
-
},
|
|
17194
|
-
"class":
|
|
17281
|
+
}],
|
|
17282
|
+
"class": [props.barClass, 'vc-tabs__bar']
|
|
17195
17283
|
}, [tabs.scrollable.value && vue.createVNode(Icon, {
|
|
17196
17284
|
"class": "vc-tabs__icon is-left",
|
|
17197
17285
|
"type": "left",
|
|
@@ -17231,8 +17319,8 @@ const Tabs = /* @__PURE__ */ vue.defineComponent({
|
|
|
17231
17319
|
}, null)]);
|
|
17232
17320
|
})])])]), vue.createVNode("div", {
|
|
17233
17321
|
"ref": content,
|
|
17234
|
-
"style": tabs.contentStyle.value,
|
|
17235
|
-
"class":
|
|
17322
|
+
"style": [props.contentStyle, tabs.contentStyle.value],
|
|
17323
|
+
"class": [props.contentClass, 'vc-tabs__content']
|
|
17236
17324
|
}, [slots.default?.()])]);
|
|
17237
17325
|
};
|
|
17238
17326
|
}
|
|
@@ -17847,7 +17935,8 @@ const useTextarea = (textarea, expose) => {
|
|
|
17847
17935
|
const classes = vue.computed(() => {
|
|
17848
17936
|
return {
|
|
17849
17937
|
"is-focus": isFocus.value,
|
|
17850
|
-
"is-disabled": props.disabled
|
|
17938
|
+
"is-disabled": props.disabled,
|
|
17939
|
+
"is-error": !!formItem?.message?.value
|
|
17851
17940
|
};
|
|
17852
17941
|
});
|
|
17853
17942
|
const listeners = vue.computed(() => {
|
|
@@ -18765,10 +18854,342 @@ const Upload = vue.defineComponent({
|
|
|
18765
18854
|
const MUpload = Upload;
|
|
18766
18855
|
|
|
18767
18856
|
const props = {
|
|
18768
|
-
|
|
18769
|
-
type:
|
|
18770
|
-
default: "
|
|
18771
|
-
}
|
|
18857
|
+
picker: {
|
|
18858
|
+
type: Array,
|
|
18859
|
+
default: () => ["image"]
|
|
18860
|
+
},
|
|
18861
|
+
sortable: {
|
|
18862
|
+
type: Boolean,
|
|
18863
|
+
default: false
|
|
18864
|
+
},
|
|
18865
|
+
mask: {
|
|
18866
|
+
type: Boolean,
|
|
18867
|
+
default: false
|
|
18868
|
+
},
|
|
18869
|
+
/**
|
|
18870
|
+
* vc-upload组件的属性
|
|
18871
|
+
*/
|
|
18872
|
+
uploadOptions: {
|
|
18873
|
+
type: Object,
|
|
18874
|
+
default() {
|
|
18875
|
+
return {};
|
|
18876
|
+
}
|
|
18877
|
+
},
|
|
18878
|
+
/**
|
|
18879
|
+
* 数据源['xxx.jpg', ....]
|
|
18880
|
+
*/
|
|
18881
|
+
modelValue: {
|
|
18882
|
+
type: [String, Array, Object],
|
|
18883
|
+
// { value: '', label: '' }
|
|
18884
|
+
default: () => []
|
|
18885
|
+
},
|
|
18886
|
+
// 数据字典
|
|
18887
|
+
keyValue: {
|
|
18888
|
+
type: Object,
|
|
18889
|
+
default: () => {
|
|
18890
|
+
return {
|
|
18891
|
+
label: "label",
|
|
18892
|
+
value: "value"
|
|
18893
|
+
};
|
|
18894
|
+
}
|
|
18895
|
+
},
|
|
18896
|
+
output: {
|
|
18897
|
+
type: [String, Function],
|
|
18898
|
+
default: "object",
|
|
18899
|
+
validator: (v) => /(string|object)/.test(v)
|
|
18900
|
+
},
|
|
18901
|
+
/**
|
|
18902
|
+
* 可上传的最大值,跟upload内的Max不同,有可能是对象类型,对应的Upload做限制
|
|
18903
|
+
*/
|
|
18904
|
+
max: {
|
|
18905
|
+
type: [Number, Object],
|
|
18906
|
+
default: Number.MAX_SAFE_INTEGER
|
|
18907
|
+
},
|
|
18908
|
+
disabled: {
|
|
18909
|
+
type: Boolean,
|
|
18910
|
+
default: false
|
|
18911
|
+
},
|
|
18912
|
+
/**
|
|
18913
|
+
* 上传成功后对数据的格式化
|
|
18914
|
+
*/
|
|
18915
|
+
formatter: Function,
|
|
18916
|
+
// TODO 下面两个重复了,需删除
|
|
18917
|
+
/**
|
|
18918
|
+
* 盒子className
|
|
18919
|
+
*/
|
|
18920
|
+
boxClass: String,
|
|
18921
|
+
imagePreviewOptions: {
|
|
18922
|
+
type: Object,
|
|
18923
|
+
default: () => ({})
|
|
18924
|
+
},
|
|
18925
|
+
imageClass: String,
|
|
18926
|
+
videoClass: String,
|
|
18927
|
+
audioClass: String,
|
|
18928
|
+
fileClass: String,
|
|
18929
|
+
compressOptions: {
|
|
18930
|
+
type: Object,
|
|
18931
|
+
default: () => {
|
|
18932
|
+
return {
|
|
18933
|
+
compress: false,
|
|
18934
|
+
// 是否开启图片压缩
|
|
18935
|
+
width: 0,
|
|
18936
|
+
// 图片缩放最大宽度,为0默认源图片宽度
|
|
18937
|
+
height: 0,
|
|
18938
|
+
// 图片缩放最大高度,为0默认源图片高度
|
|
18939
|
+
filetype: "image/jpeg",
|
|
18940
|
+
// 文件类型
|
|
18941
|
+
encoderOptions: 0.92
|
|
18942
|
+
// 在指定图片格式为 image/jpeg 或 image/webp的情况下,可以从 0 到 1 的区间内选择图片的质量。如果超出取值范围,使用默认值 0.92
|
|
18943
|
+
};
|
|
18944
|
+
}
|
|
18945
|
+
},
|
|
18946
|
+
showMessage: Boolean,
|
|
18947
|
+
gallery: Boolean
|
|
18948
|
+
};
|
|
18949
|
+
|
|
18950
|
+
const recognizer = (url) => {
|
|
18951
|
+
const reg = /\.(jpe?g|png|gif|bmp|webp|image|heic|mp4|mov|avi|mpg|mpeg|rmvb)/ig;
|
|
18952
|
+
const result = url.match(reg);
|
|
18953
|
+
return result && result.length ? /.(jpe?g|png|gif|bmp|webp|image|heic)/ig.test(result[result.length - 1]) ? "image" : "video" : "file";
|
|
18954
|
+
};
|
|
18955
|
+
const FILE_ACCEPT_MAP = {
|
|
18956
|
+
DOC_ACCEPTS: ".doc,.docx,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
18957
|
+
EXCEL_ACCEPTS: ".csv,.xls,.xlsx,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
18958
|
+
PPT_ACCEPTS: ".ppt,.pptx,application/vnd.ms-powerpoint,application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
18959
|
+
PDF_ACCEPTS: ".pdf,application/pdf",
|
|
18960
|
+
TXT_ACCEPTS: "text/plain",
|
|
18961
|
+
HTML_ACCEPTS: "text/html"
|
|
18962
|
+
};
|
|
18963
|
+
|
|
18964
|
+
const {
|
|
18965
|
+
DOC_ACCEPTS,
|
|
18966
|
+
EXCEL_ACCEPTS,
|
|
18967
|
+
PPT_ACCEPTS,
|
|
18968
|
+
PDF_ACCEPTS,
|
|
18969
|
+
TXT_ACCEPTS,
|
|
18970
|
+
HTML_ACCEPTS
|
|
18971
|
+
} = FILE_ACCEPT_MAP;
|
|
18972
|
+
const usePicker = (expose) => {
|
|
18973
|
+
const instance = vue.getCurrentInstance();
|
|
18974
|
+
const props = instance.props;
|
|
18975
|
+
const { emit } = instance;
|
|
18976
|
+
const formItem = vue.inject("vc-form-item", {});
|
|
18977
|
+
const allowKeepString = vue.computed(() => {
|
|
18978
|
+
return typeof props.modelValue === "string";
|
|
18979
|
+
});
|
|
18980
|
+
const allowKeepObject = vue.computed(() => {
|
|
18981
|
+
const v = props.modelValue;
|
|
18982
|
+
return props.output === "object" && props.max === 1 && !Array.isArray(v) && typeof v === "object";
|
|
18983
|
+
});
|
|
18984
|
+
const currentValue = vue.ref({
|
|
18985
|
+
image: [],
|
|
18986
|
+
video: [],
|
|
18987
|
+
audio: [],
|
|
18988
|
+
file: []
|
|
18989
|
+
});
|
|
18990
|
+
const currentUploadOptions = vue.ref({
|
|
18991
|
+
image: {
|
|
18992
|
+
accept: "image/gif,image/jpeg,image/jpg,image/png",
|
|
18993
|
+
...props.uploadOptions.image || {}
|
|
18994
|
+
},
|
|
18995
|
+
video: {
|
|
18996
|
+
accept: "video/*",
|
|
18997
|
+
...props.uploadOptions.video || {}
|
|
18998
|
+
},
|
|
18999
|
+
audio: {
|
|
19000
|
+
accept: "audio/*",
|
|
19001
|
+
...props.uploadOptions.audio || {}
|
|
19002
|
+
},
|
|
19003
|
+
file: {
|
|
19004
|
+
accept: `${DOC_ACCEPTS},${EXCEL_ACCEPTS},${PPT_ACCEPTS},${PDF_ACCEPTS},${TXT_ACCEPTS},${HTML_ACCEPTS}`,
|
|
19005
|
+
...props.uploadOptions.file || {}
|
|
19006
|
+
}
|
|
19007
|
+
});
|
|
19008
|
+
const dynamicMax = vue.computed(() => {
|
|
19009
|
+
const image = currentValue.value.image || [];
|
|
19010
|
+
const video = currentValue.value.video || [];
|
|
19011
|
+
const audio = currentValue.value.audio || [];
|
|
19012
|
+
const file = currentValue.value.file || [];
|
|
19013
|
+
const imageCount = image.length || 0;
|
|
19014
|
+
const videoCount = video.length || 0;
|
|
19015
|
+
const audioCount = audio.length || 0;
|
|
19016
|
+
const fileCount = file.length || 0;
|
|
19017
|
+
if (typeof props.max === "number") {
|
|
19018
|
+
const curNum = imageCount + videoCount + audioCount + fileCount;
|
|
19019
|
+
const leftNum = props.max - curNum;
|
|
19020
|
+
return {
|
|
19021
|
+
image: leftNum,
|
|
19022
|
+
video: leftNum,
|
|
19023
|
+
audio: leftNum,
|
|
19024
|
+
file: leftNum
|
|
19025
|
+
};
|
|
19026
|
+
} else if (typeof props.max === "object") {
|
|
19027
|
+
const {
|
|
19028
|
+
image: $image,
|
|
19029
|
+
video: $video,
|
|
19030
|
+
audio: $audio,
|
|
19031
|
+
file: $file
|
|
19032
|
+
} = props.max;
|
|
19033
|
+
const max = {};
|
|
19034
|
+
$image && (max.image = $image - imageCount);
|
|
19035
|
+
$video && (max.video = $video - videoCount);
|
|
19036
|
+
$audio && (max.audio = $audio - audioCount);
|
|
19037
|
+
$file && (max.file = $file - fileCount);
|
|
19038
|
+
return max;
|
|
19039
|
+
}
|
|
19040
|
+
return {};
|
|
19041
|
+
});
|
|
19042
|
+
const sync = () => {
|
|
19043
|
+
let v = props.picker.reduce((pre, cur) => pre.concat(currentValue.value[cur] || []), []).filter((i) => !i.errorFlag).map((i) => {
|
|
19044
|
+
if (props.output === "string") return i[props.keyValue.value];
|
|
19045
|
+
if (typeof props.output === "function") return props.output(i) || i;
|
|
19046
|
+
return i;
|
|
19047
|
+
});
|
|
19048
|
+
if (allowKeepString.value) {
|
|
19049
|
+
v = v.map((i) => i[props.keyValue.value] || i).join(",");
|
|
19050
|
+
} else if (allowKeepObject.value) {
|
|
19051
|
+
v = v[0] || null;
|
|
19052
|
+
}
|
|
19053
|
+
emit("update:modelValue", v);
|
|
19054
|
+
emit("change", v);
|
|
19055
|
+
formItem.change?.(v);
|
|
19056
|
+
};
|
|
19057
|
+
const handleFileBefore = async (vFile, fileList, type) => {
|
|
19058
|
+
if (props?.compressOptions?.compress && type === "image") ;
|
|
19059
|
+
const onFileBefore = instance.vnode.props?.onFileBefore || (() => {
|
|
19060
|
+
});
|
|
19061
|
+
return await onFileBefore(vFile, fileList, type) || vFile;
|
|
19062
|
+
};
|
|
19063
|
+
const handleFileStart = (vFile, type) => {
|
|
19064
|
+
currentValue.value[type].push(vFile);
|
|
19065
|
+
emit("file-start", vFile, type);
|
|
19066
|
+
};
|
|
19067
|
+
const handleFileProgress = (e, vFile, type) => {
|
|
19068
|
+
if (parseInt(e.percent, 10) <= 100) {
|
|
19069
|
+
currentValue.value[type] = currentValue.value[type].map((item) => {
|
|
19070
|
+
if (vFile.uploadId === item.uploadId) {
|
|
19071
|
+
return {
|
|
19072
|
+
...item,
|
|
19073
|
+
percent: e.percent
|
|
19074
|
+
};
|
|
19075
|
+
}
|
|
19076
|
+
return item;
|
|
19077
|
+
});
|
|
19078
|
+
}
|
|
19079
|
+
};
|
|
19080
|
+
const handleFileSuccess = (response, vFile, cycle, type) => {
|
|
19081
|
+
currentValue.value[type] = currentValue.value[type].map((item) => {
|
|
19082
|
+
if (item.uploadId === vFile.uploadId) {
|
|
19083
|
+
return {
|
|
19084
|
+
type,
|
|
19085
|
+
[props.keyValue.label]: vFile.name,
|
|
19086
|
+
// 外部需要满足response中带source
|
|
19087
|
+
[props.keyValue.value]: response.source
|
|
19088
|
+
};
|
|
19089
|
+
}
|
|
19090
|
+
return item;
|
|
19091
|
+
});
|
|
19092
|
+
emit("file-success", response, vFile, cycle, type);
|
|
19093
|
+
};
|
|
19094
|
+
const handleError = (err, type) => {
|
|
19095
|
+
props.showMessage && err.message && Message.error(err.message);
|
|
19096
|
+
emit("error", err, type);
|
|
19097
|
+
};
|
|
19098
|
+
const handleFileError = (response, vFile, cycle, type) => {
|
|
19099
|
+
currentValue.value[type] = currentValue.value[type].map((item) => {
|
|
19100
|
+
if (item.uploadId === vFile.uploadId) {
|
|
19101
|
+
return {
|
|
19102
|
+
...item,
|
|
19103
|
+
...response,
|
|
19104
|
+
// 文件基础信息
|
|
19105
|
+
type,
|
|
19106
|
+
[props.keyValue.label]: vFile.name,
|
|
19107
|
+
errorFlag: (/* @__PURE__ */ new Date()).getTime()
|
|
19108
|
+
};
|
|
19109
|
+
}
|
|
19110
|
+
return item;
|
|
19111
|
+
});
|
|
19112
|
+
emit("file-error", response, vFile, cycle, type);
|
|
19113
|
+
};
|
|
19114
|
+
const handleFileComplete = (response, type) => {
|
|
19115
|
+
sync();
|
|
19116
|
+
emit("complete", response, type);
|
|
19117
|
+
};
|
|
19118
|
+
const handleDelete = async (index, type) => {
|
|
19119
|
+
const onRemoveBefore = instance.vnode.props?.onRemoveBefore || (() => {
|
|
19120
|
+
});
|
|
19121
|
+
await onRemoveBefore(index, type);
|
|
19122
|
+
const target = currentValue.value[type];
|
|
19123
|
+
const item = target[index];
|
|
19124
|
+
if (!item) {
|
|
19125
|
+
console.error("【vc-upload-picker】: 没有找到要删除的元素");
|
|
19126
|
+
return;
|
|
19127
|
+
}
|
|
19128
|
+
if (item.errorFlag) {
|
|
19129
|
+
currentValue.value[type] = target.filter(
|
|
19130
|
+
(it) => it.uploadId != item.uploadId
|
|
19131
|
+
);
|
|
19132
|
+
return;
|
|
19133
|
+
}
|
|
19134
|
+
target.splice(index, 1);
|
|
19135
|
+
sync();
|
|
19136
|
+
};
|
|
19137
|
+
const parseModelValue = (v) => {
|
|
19138
|
+
const initialData = { image: [], video: [], audio: [], file: [] };
|
|
19139
|
+
if (allowKeepString.value) {
|
|
19140
|
+
v = (props.max === 1 ? [v] : v.split(",")).filter((i) => !!i);
|
|
19141
|
+
} else if (allowKeepObject.value) {
|
|
19142
|
+
v = [v].filter((i) => i && !!i[props.keyValue.value]);
|
|
19143
|
+
}
|
|
19144
|
+
if (!Array.isArray(v) || !v.length) return initialData;
|
|
19145
|
+
return v.reduce((pre, cur) => {
|
|
19146
|
+
const value = cur[props.keyValue.value] || (typeof cur === "object" ? "" : cur);
|
|
19147
|
+
const label = cur[props.keyValue.label] || value.replace(/^.*\/([^/]+)$/, "$1");
|
|
19148
|
+
const type = cur.type || (props.picker.length === 1 ? props.picker[0] : recognizer(value));
|
|
19149
|
+
switch (type) {
|
|
19150
|
+
case "image":
|
|
19151
|
+
case "video":
|
|
19152
|
+
case "audio":
|
|
19153
|
+
case "file":
|
|
19154
|
+
pre[type].push({
|
|
19155
|
+
// 文件类型
|
|
19156
|
+
type,
|
|
19157
|
+
// 文件名
|
|
19158
|
+
[props.keyValue.label]: label,
|
|
19159
|
+
// 源文件地址
|
|
19160
|
+
[props.keyValue.value]: value,
|
|
19161
|
+
// 上传进度
|
|
19162
|
+
percent: null,
|
|
19163
|
+
// 错误标记
|
|
19164
|
+
errorFlag: false
|
|
19165
|
+
});
|
|
19166
|
+
return pre;
|
|
19167
|
+
default:
|
|
19168
|
+
return pre;
|
|
19169
|
+
}
|
|
19170
|
+
}, initialData);
|
|
19171
|
+
};
|
|
19172
|
+
vue.watch(
|
|
19173
|
+
() => props.modelValue,
|
|
19174
|
+
(v) => {
|
|
19175
|
+
currentValue.value = parseModelValue(v);
|
|
19176
|
+
},
|
|
19177
|
+
{ immediate: true }
|
|
19178
|
+
);
|
|
19179
|
+
expose();
|
|
19180
|
+
return {
|
|
19181
|
+
currentValue,
|
|
19182
|
+
currentUploadOptions,
|
|
19183
|
+
dynamicMax,
|
|
19184
|
+
handleDelete,
|
|
19185
|
+
handleFileBefore,
|
|
19186
|
+
handleFileStart,
|
|
19187
|
+
handleFileProgress,
|
|
19188
|
+
handleFileSuccess,
|
|
19189
|
+
handleFileError,
|
|
19190
|
+
handleError,
|
|
19191
|
+
handleFileComplete
|
|
19192
|
+
};
|
|
18772
19193
|
};
|
|
18773
19194
|
|
|
18774
19195
|
/** @jsxImportSource vue */
|
|
@@ -18777,13 +19198,111 @@ const COMPONENT_NAME = 'vc-upload-picker';
|
|
|
18777
19198
|
const UploadPicker = /* @__PURE__ */ vue.defineComponent({
|
|
18778
19199
|
name: COMPONENT_NAME,
|
|
18779
19200
|
props: props,
|
|
19201
|
+
emits: ['update:modelValue', 'file-success', 'file-start', 'success', 'error', 'complete', 'change', 'remove-before'],
|
|
18780
19202
|
setup(props, {
|
|
18781
|
-
slots
|
|
19203
|
+
slots,
|
|
19204
|
+
expose
|
|
18782
19205
|
}) {
|
|
19206
|
+
const instance = vue.getCurrentInstance();
|
|
19207
|
+
const currentPicker = vue.computed(() => {
|
|
19208
|
+
return props.picker.reduce((pre, cur) => {
|
|
19209
|
+
switch (cur) {
|
|
19210
|
+
case 'image':
|
|
19211
|
+
pre.push({
|
|
19212
|
+
type: cur,
|
|
19213
|
+
item: 'div'
|
|
19214
|
+
// item: ImageItem
|
|
19215
|
+
});
|
|
19216
|
+
return pre;
|
|
19217
|
+
case 'video':
|
|
19218
|
+
pre.push({
|
|
19219
|
+
type: cur,
|
|
19220
|
+
item: 'div'
|
|
19221
|
+
// item: VideoItem
|
|
19222
|
+
});
|
|
19223
|
+
return pre;
|
|
19224
|
+
case 'audio':
|
|
19225
|
+
pre.push({
|
|
19226
|
+
type: cur,
|
|
19227
|
+
item: 'div'
|
|
19228
|
+
// item: AudioItem
|
|
19229
|
+
});
|
|
19230
|
+
return pre;
|
|
19231
|
+
case 'file':
|
|
19232
|
+
pre.push({
|
|
19233
|
+
type: cur,
|
|
19234
|
+
item: 'div'
|
|
19235
|
+
// item: FileItem
|
|
19236
|
+
});
|
|
19237
|
+
return pre;
|
|
19238
|
+
default:
|
|
19239
|
+
return pre;
|
|
19240
|
+
}
|
|
19241
|
+
}, []);
|
|
19242
|
+
});
|
|
19243
|
+
const handleClick = (e, type) => {
|
|
19244
|
+
const options = VcInstance.options.UploadPicker || {};
|
|
19245
|
+
if (typeof props.gallery === 'function' || props.gallery && options.gallery) {
|
|
19246
|
+
const fn = typeof props.gallery === 'function' ? props.gallery : options.gallery;
|
|
19247
|
+
|
|
19248
|
+
// 阻止原生事件,如video, file不走gallery, 可以跳过;
|
|
19249
|
+
fn(instance, type) && e.stopPropagation();
|
|
19250
|
+
}
|
|
19251
|
+
};
|
|
19252
|
+
const base = usePicker(expose);
|
|
18783
19253
|
return () => {
|
|
18784
19254
|
return vue.createVNode("div", {
|
|
18785
19255
|
"class": "vc-upload-picker"
|
|
18786
|
-
}, [
|
|
19256
|
+
}, [currentPicker.value.map((picker, $index) => {
|
|
19257
|
+
return vue.createVNode(vue.Fragment, {
|
|
19258
|
+
"key": `${picker}-${$index}`
|
|
19259
|
+
}, [base.currentValue.value[picker.type].map((item, index) => {
|
|
19260
|
+
const Item = picker.item;
|
|
19261
|
+
return vue.createVNode(Item, {
|
|
19262
|
+
"key": typeof item === 'object' ? item.uid : item,
|
|
19263
|
+
"it": item,
|
|
19264
|
+
"disabled": props.disabled,
|
|
19265
|
+
"image-preview-options": props.imagePreviewOptions,
|
|
19266
|
+
"imageClass": props.imageClass,
|
|
19267
|
+
"videoClass": props.videoClass,
|
|
19268
|
+
"audioClass": props.audioClass,
|
|
19269
|
+
"fileClass": props.fileClass,
|
|
19270
|
+
"index": index,
|
|
19271
|
+
"data": item,
|
|
19272
|
+
"class": "vc-upload-picker__item",
|
|
19273
|
+
"onDelete": () => base.handleDelete(index, picker.type)
|
|
19274
|
+
}, {
|
|
19275
|
+
default: scopeData => {
|
|
19276
|
+
return slots.default ? slots.default({
|
|
19277
|
+
it: scopeData?.it,
|
|
19278
|
+
current: scopeData?.current,
|
|
19279
|
+
index,
|
|
19280
|
+
name: picker.type
|
|
19281
|
+
}) : scopeData;
|
|
19282
|
+
}
|
|
19283
|
+
});
|
|
19284
|
+
}), vue.withDirectives(vue.createVNode(Upload, vue.mergeProps(base.currentUploadOptions.value[picker.type], {
|
|
19285
|
+
"max": base.dynamicMax[picker.type],
|
|
19286
|
+
"class": "vc-upload-picker__upload",
|
|
19287
|
+
"onFileBefore": (vFile, fileList) => base.handleFileBefore(vFile, fileList, picker.type),
|
|
19288
|
+
"onFileStart": vFile => base.handleFileStart(vFile, picker.type),
|
|
19289
|
+
"onFileProgress": (e, vFile) => base.handleFileProgress(e, vFile, picker.type),
|
|
19290
|
+
"onFileSuccess": (response, vFile, cycle) => base.handleFileSuccess(response, vFile, cycle, picker.type),
|
|
19291
|
+
"onFileError": (response, vFile, cycle) => base.handleFileError(response, vFile, cycle, picker.type),
|
|
19292
|
+
"onError": e => base.handleError(e, picker.type),
|
|
19293
|
+
"onComplete": response => base.handleFileComplete(response, picker.type)
|
|
19294
|
+
}), {
|
|
19295
|
+
default: () => [slots?.[`${picker.type}-upload`] ? slots[`${picker.type}-upload`]?.() : vue.createVNode("div", {
|
|
19296
|
+
"class": [props.boxClass, 'vc-upload-picker__box'],
|
|
19297
|
+
"onClick": e => handleClick(e, picker.type)
|
|
19298
|
+
}, [vue.createVNode(Icon, {
|
|
19299
|
+
"type": "mini-plus",
|
|
19300
|
+
"class": "vc-upload-picker__plus-icon"
|
|
19301
|
+
}, null), vue.createVNode("span", {
|
|
19302
|
+
"style": "margin-top: 8px"
|
|
19303
|
+
}, [vue.createTextVNode("\u4E0A\u4F20")])])]
|
|
19304
|
+
}), [[vue.vShow, !props.disabled && base.dynamicMax.value[picker.type] >= 1]])]);
|
|
19305
|
+
})]);
|
|
18787
19306
|
};
|
|
18788
19307
|
}
|
|
18789
19308
|
});
|
|
@@ -18822,7 +19341,7 @@ exports.Fragment = Fragment;
|
|
|
18822
19341
|
exports.HTMLToImage = HTMLToImage;
|
|
18823
19342
|
exports.Icon = Icon;
|
|
18824
19343
|
exports.IconManager = IconManager;
|
|
18825
|
-
exports.Image = Image;
|
|
19344
|
+
exports.Image = Image$1;
|
|
18826
19345
|
exports.ImageCrop = ImageCrop;
|
|
18827
19346
|
exports.ImagePreview = ImagePreview;
|
|
18828
19347
|
exports.ImageProcessing = ImageProcessing;
|