qidian-vue-ui 1.4.0 → 1.5.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.
- package/dist/components/config-provider/index.d.ts +6 -3
- package/dist/components/config-provider/types.d.ts +2 -1
- package/dist/components/config-provider/useConfig.d.ts +4 -0
- package/dist/components/service/table/index.css +10 -10
- package/dist/components/service/table/index.vue.mjs +1 -1
- package/dist/components/service/table/index.vue2.mjs +91 -10
- package/dist/components/upload/index.css +33 -33
- package/dist/components/upload/index.vue.mjs +1 -1
- package/dist/components/upload/index.vue2.mjs +144 -23
- package/dist/components/upload/props.d.ts +1 -4
- package/dist/components/upload/props.mjs +1 -4
- package/dist/components/upload/request.d.ts +21 -0
- package/dist/components/upload/request.mjs +132 -0
- package/dist/components/upload/types.d.ts +1 -0
- package/dist/locales/en-US.d.ts +1 -0
- package/dist/locales/en-US.mjs +1 -0
- package/dist/locales/zh-CN.d.ts +1 -0
- package/dist/locales/zh-CN.mjs +1 -0
- package/dist/locales/zh-TW.d.ts +1 -0
- package/dist/locales/zh-TW.mjs +1 -0
- package/dist/utils/tools.d.ts +5 -0
- package/dist/utils/tools.mjs +2 -2
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@ export declare const QdConfigProvider: import("vue").DefineComponent<{
|
|
|
2
2
|
locale?: string | undefined;
|
|
3
3
|
user?: import("./types").QdUser | undefined;
|
|
4
4
|
dict?: import("../..").QdDictBaseOptions | undefined;
|
|
5
|
-
upload?: Pick<import("..").QdUploadProps, "action" | "headers" | "isBatchUpload" | "method" | "name" | "requestMethod" | "listOssByIds" | "listOssByUrls" | "del"> | undefined;
|
|
5
|
+
upload?: Pick<import("..").QdUploadProps, "action" | "headers" | "isBatchUpload" | "method" | "name" | "requestMethod" | "listOssByIds" | "listOssByUrls" | "data" | "withCredentials" | "formatRequest" | "useMockProgress" | "mockProgressDuration" | "onProgress" | "del"> | undefined;
|
|
6
6
|
avatar?: import("../..").QdAvatarBaseOptions | undefined;
|
|
7
7
|
agentChat?: Pick<import("../..").UseAgentChatOptions, "getSessionId" | "getUrl"> | undefined;
|
|
8
8
|
org?: {
|
|
@@ -56,6 +56,7 @@ export declare const QdConfigProvider: import("vue").DefineComponent<{
|
|
|
56
56
|
sameNameMessage?: string;
|
|
57
57
|
fileSizeExceedsLimit?: string;
|
|
58
58
|
fileUploadFailed?: string;
|
|
59
|
+
fileUploadTimeout?: string;
|
|
59
60
|
viewFileText?: string;
|
|
60
61
|
};
|
|
61
62
|
chat?: NonNullable<import("tdesign-vue-next").TdConfigProviderProps["globalConfig"]>["chat"] & {
|
|
@@ -131,7 +132,7 @@ export declare const QdConfigProvider: import("vue").DefineComponent<{
|
|
|
131
132
|
locale?: string | undefined;
|
|
132
133
|
user?: import("./types").QdUser | undefined;
|
|
133
134
|
dict?: import("../..").QdDictBaseOptions | undefined;
|
|
134
|
-
upload?: Pick<import("..").QdUploadProps, "action" | "headers" | "isBatchUpload" | "method" | "name" | "requestMethod" | "listOssByIds" | "listOssByUrls" | "del"> | undefined;
|
|
135
|
+
upload?: Pick<import("..").QdUploadProps, "action" | "headers" | "isBatchUpload" | "method" | "name" | "requestMethod" | "listOssByIds" | "listOssByUrls" | "data" | "withCredentials" | "formatRequest" | "useMockProgress" | "mockProgressDuration" | "onProgress" | "del"> | undefined;
|
|
135
136
|
avatar?: import("../..").QdAvatarBaseOptions | undefined;
|
|
136
137
|
agentChat?: Pick<import("../..").UseAgentChatOptions, "getSessionId" | "getUrl"> | undefined;
|
|
137
138
|
org?: {
|
|
@@ -185,6 +186,7 @@ export declare const QdConfigProvider: import("vue").DefineComponent<{
|
|
|
185
186
|
sameNameMessage?: string;
|
|
186
187
|
fileSizeExceedsLimit?: string;
|
|
187
188
|
fileUploadFailed?: string;
|
|
189
|
+
fileUploadTimeout?: string;
|
|
188
190
|
viewFileText?: string;
|
|
189
191
|
};
|
|
190
192
|
chat?: NonNullable<import("tdesign-vue-next").TdConfigProviderProps["globalConfig"]>["chat"] & {
|
|
@@ -299,6 +301,7 @@ export declare const QdConfigProvider: import("vue").DefineComponent<{
|
|
|
299
301
|
sameNameMessage?: string;
|
|
300
302
|
fileSizeExceedsLimit?: string;
|
|
301
303
|
fileUploadFailed?: string;
|
|
304
|
+
fileUploadTimeout?: string;
|
|
302
305
|
viewFileText?: string;
|
|
303
306
|
};
|
|
304
307
|
chat?: NonNullable<import("tdesign-vue-next").TdConfigProviderProps["globalConfig"]>["chat"] & {
|
|
@@ -368,7 +371,7 @@ export declare const QdConfigProvider: import("vue").DefineComponent<{
|
|
|
368
371
|
closeText?: string;
|
|
369
372
|
};
|
|
370
373
|
}) | undefined;
|
|
371
|
-
upload: Pick<import("..").QdUploadProps<import("tdesign-vue-next").UploadFile, unknown, string | number | (string | number)[], string | number | (string | number)[], unknown, string | string[], string | string[], unknown, string | number | (string | number)[], string | number | (string | number)[]>, "name" | "del" | "action" | "headers" | "method" | "isBatchUpload" | "requestMethod" | "listOssByIds" | "listOssByUrls"> | undefined;
|
|
374
|
+
upload: Pick<import("..").QdUploadProps<import("tdesign-vue-next").UploadFile, unknown, string | number | (string | number)[], string | number | (string | number)[], unknown, string | string[], string | string[], unknown, string | number | (string | number)[], string | number | (string | number)[]>, "data" | "name" | "del" | "onProgress" | "action" | "headers" | "method" | "formatRequest" | "isBatchUpload" | "mockProgressDuration" | "requestMethod" | "useMockProgress" | "withCredentials" | "listOssByIds" | "listOssByUrls"> | undefined;
|
|
372
375
|
office: {
|
|
373
376
|
pdfSandboxUrl?: string | undefined;
|
|
374
377
|
pdfWorkerUrl?: string | undefined;
|
|
@@ -15,7 +15,7 @@ export interface QdConfigProviderProps {
|
|
|
15
15
|
locale?: string;
|
|
16
16
|
user?: QdUser;
|
|
17
17
|
dict?: QdDictBaseOptions;
|
|
18
|
-
upload?: Pick<QdUploadProps, 'action' | 'headers' | 'isBatchUpload' | 'method' | 'name' | 'requestMethod' | 'listOssByIds' | 'listOssByUrls' | 'del'>;
|
|
18
|
+
upload?: Pick<QdUploadProps, 'action' | 'headers' | 'isBatchUpload' | 'method' | 'name' | 'requestMethod' | 'listOssByIds' | 'listOssByUrls' | 'data' | 'withCredentials' | 'formatRequest' | 'useMockProgress' | 'mockProgressDuration' | 'onProgress' | 'del'>;
|
|
19
19
|
avatar?: QdAvatarBaseOptions;
|
|
20
20
|
agentChat?: Pick<UseAgentChatOptions, 'getSessionId' | 'getUrl'>;
|
|
21
21
|
org?: {
|
|
@@ -71,6 +71,7 @@ export interface QdConfigProviderProps {
|
|
|
71
71
|
sameNameMessage?: string;
|
|
72
72
|
fileSizeExceedsLimit?: string;
|
|
73
73
|
fileUploadFailed?: string;
|
|
74
|
+
fileUploadTimeout?: string;
|
|
74
75
|
viewFileText?: string;
|
|
75
76
|
};
|
|
76
77
|
chat?: NonNullable<TdConfigProviderProps['globalConfig']>['chat'] & {
|
|
@@ -44,6 +44,7 @@ export declare function useConfig<T extends keyof NonNullable<QdConfigProviderPr
|
|
|
44
44
|
sameNameMessage?: string;
|
|
45
45
|
fileSizeExceedsLimit?: string;
|
|
46
46
|
fileUploadFailed?: string;
|
|
47
|
+
fileUploadTimeout?: string;
|
|
47
48
|
viewFileText?: string;
|
|
48
49
|
};
|
|
49
50
|
chat?: NonNullable<import("tdesign-vue-next").TdConfigProviderProps["globalConfig"]>["chat"] & {
|
|
@@ -156,6 +157,7 @@ export declare function useConfig<T extends keyof NonNullable<QdConfigProviderPr
|
|
|
156
157
|
sameNameMessage?: string;
|
|
157
158
|
fileSizeExceedsLimit?: string;
|
|
158
159
|
fileUploadFailed?: string;
|
|
160
|
+
fileUploadTimeout?: string;
|
|
159
161
|
viewFileText?: string;
|
|
160
162
|
};
|
|
161
163
|
chat?: NonNullable<import("tdesign-vue-next").TdConfigProviderProps["globalConfig"]>["chat"] & {
|
|
@@ -268,6 +270,7 @@ export declare function useConfig<T extends keyof NonNullable<QdConfigProviderPr
|
|
|
268
270
|
sameNameMessage?: string;
|
|
269
271
|
fileSizeExceedsLimit?: string;
|
|
270
272
|
fileUploadFailed?: string;
|
|
273
|
+
fileUploadTimeout?: string;
|
|
271
274
|
viewFileText?: string;
|
|
272
275
|
};
|
|
273
276
|
chat?: NonNullable<import("tdesign-vue-next").TdConfigProviderProps["globalConfig"]>["chat"] & {
|
|
@@ -381,6 +384,7 @@ export declare function useConfig<T extends keyof NonNullable<QdConfigProviderPr
|
|
|
381
384
|
sameNameMessage?: string;
|
|
382
385
|
fileSizeExceedsLimit?: string;
|
|
383
386
|
fileUploadFailed?: string;
|
|
387
|
+
fileUploadTimeout?: string;
|
|
384
388
|
viewFileText?: string;
|
|
385
389
|
};
|
|
386
390
|
chat?: NonNullable<import("tdesign-vue-next").TdConfigProviderProps["globalConfig"]>["chat"] & {
|
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
.qd-service-table[data-v-
|
|
1
|
+
.qd-service-table[data-v-c2177f89] {
|
|
2
2
|
height: 100%;
|
|
3
3
|
display: flex;
|
|
4
4
|
flex-direction: column;
|
|
5
5
|
}
|
|
6
|
-
.qd-service-table[data-v-
|
|
6
|
+
.qd-service-table[data-v-c2177f89] > .t-table__content {
|
|
7
7
|
flex: 1;
|
|
8
8
|
}
|
|
9
|
-
.qd-service-table[data-v-
|
|
9
|
+
.qd-service-table[data-v-c2177f89] .t-table__tree-col:not(:has(.t-table__tree-op-icon)) {
|
|
10
10
|
margin-left: calc(var(--td-font-size-body-large) + var(--td-comp-margin-s));
|
|
11
11
|
}
|
|
12
|
-
.qd-service-table[data-v-
|
|
12
|
+
.qd-service-table[data-v-c2177f89] .t-table__tree-leaf-node .t-table__tree-op-icon:empty {
|
|
13
13
|
width: calc(var(--td-font-size-body-large) + var(--td-comp-margin-s));
|
|
14
14
|
}
|
|
15
|
-
.qd-service-table[data-v-
|
|
16
|
-
transform: var(--
|
|
15
|
+
.qd-service-table[data-v-c2177f89] .t-affix {
|
|
16
|
+
transform: var(--v072441ea);
|
|
17
17
|
}
|
|
18
|
-
.qd-service-table--ps-x-fixed[data-v-
|
|
18
|
+
.qd-service-table--ps-x-fixed[data-v-c2177f89] .ps__rail-x {
|
|
19
19
|
position: fixed;
|
|
20
|
-
left: var(--
|
|
21
|
-
bottom: var(--
|
|
20
|
+
left: var(--ac91cc66) !important;
|
|
21
|
+
bottom: var(--v79d9a896) !important;
|
|
22
22
|
}
|
|
23
|
-
.qd-service-table--disable-horizontal-scroll[data-v-
|
|
23
|
+
.qd-service-table--disable-horizontal-scroll[data-v-c2177f89] colgroup > col {
|
|
24
24
|
width: auto !important;
|
|
25
25
|
}
|
|
@@ -2,7 +2,7 @@ import './index.css'
|
|
|
2
2
|
import _sfc_main from "./index.vue2.mjs";
|
|
3
3
|
/* empty css */
|
|
4
4
|
import _export_sfc from "../../../_virtual/_plugin-vue_export-helper.mjs";
|
|
5
|
-
const QdServiceTable = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-
|
|
5
|
+
const QdServiceTable = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-c2177f89"]]);
|
|
6
6
|
export {
|
|
7
7
|
QdServiceTable as default
|
|
8
8
|
};
|
|
@@ -307,9 +307,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
307
307
|
emit: __emit
|
|
308
308
|
}) {
|
|
309
309
|
useCssVars((_ctx) => ({
|
|
310
|
-
"
|
|
311
|
-
"
|
|
312
|
-
"
|
|
310
|
+
"v072441ea": affixedHeaderTransform.value,
|
|
311
|
+
"ac91cc66": tableContentLeft.value,
|
|
312
|
+
"v79d9a896": outsideBottom.value
|
|
313
313
|
}));
|
|
314
314
|
const props = __props;
|
|
315
315
|
const emit = __emit;
|
|
@@ -357,17 +357,22 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
357
357
|
const tableContentRect = reactive(useElementBounding(tableContentEl));
|
|
358
358
|
const tableContentLeft = computed(() => `${tableContentRect.left - affixedRailOffsetX.value}px`);
|
|
359
359
|
const outsideScrollRect = reactive(useElementBounding(outsideScrollEl));
|
|
360
|
-
const
|
|
360
|
+
const affixBottomOffset = ref(0);
|
|
361
|
+
let probeRafId = 0;
|
|
362
|
+
let animatingAncestorCleanup = null;
|
|
363
|
+
const outsideBottom = computed(() => {
|
|
364
|
+
if (!outsideScrollEl.value) return "0";
|
|
365
|
+
return `${Math.max(0, window.innerHeight - outsideScrollRect.bottom + affixBottomOffset.value)}px`;
|
|
366
|
+
});
|
|
361
367
|
const tableHeaderHalfVisible = computed(() => {
|
|
362
368
|
if (!tableContentVisible.value) return false;
|
|
363
369
|
return tableContentRect.top + tableHeaderH.value * 0.5 <= outsideScrollRect.bottom;
|
|
364
370
|
});
|
|
365
371
|
const tableContentFullVisible = computed(() => {
|
|
366
372
|
if (!tableContentVisible.value) return false;
|
|
367
|
-
|
|
368
|
-
const containerBottom = outsideScrollRect.bottom;
|
|
369
|
-
return contentBottom <= containerBottom;
|
|
373
|
+
return tableContentRect.bottom <= outsideScrollRect.bottom - affixBottomOffset.value;
|
|
370
374
|
});
|
|
375
|
+
const isPsXFixed = computed(() => tableContentVisible.value && tableHeaderHalfVisible.value && !tableContentFullVisible.value);
|
|
371
376
|
const {
|
|
372
377
|
ps: tablePs
|
|
373
378
|
} = usePerfectScrollbar(tableContentEl, {
|
|
@@ -827,11 +832,15 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
827
832
|
return keys;
|
|
828
833
|
}, []);
|
|
829
834
|
}
|
|
835
|
+
function refreshAffixedMetrics() {
|
|
836
|
+
tableContentRect.update();
|
|
837
|
+
outsideScrollRect.update();
|
|
838
|
+
affixedRailOffsetX.value = getTransformOffset(affixBaseEl.value).x;
|
|
839
|
+
}
|
|
830
840
|
function onResize(entries) {
|
|
831
841
|
const el = entries[0].target;
|
|
832
842
|
outsideScrollEl.value = getScrollEl(el);
|
|
833
|
-
|
|
834
|
-
affixedRailOffsetX.value = getTransformOffset(affixBaseEl.value).x;
|
|
843
|
+
refreshAffixedMetrics();
|
|
835
844
|
const headerEl = el.querySelector(".t-table__header");
|
|
836
845
|
tableHeaderEl.value = headerEl;
|
|
837
846
|
let headerH = 0;
|
|
@@ -839,6 +848,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
839
848
|
tableHeaderH.value = headerH;
|
|
840
849
|
const contentEl = el.querySelector(".t-table__content");
|
|
841
850
|
tableContentEl.value = contentEl;
|
|
851
|
+
probeBottomBlockHeight();
|
|
842
852
|
}
|
|
843
853
|
function isTransformAnimating(node) {
|
|
844
854
|
return node.getAnimations().length > 0;
|
|
@@ -853,6 +863,23 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
853
863
|
}
|
|
854
864
|
return null;
|
|
855
865
|
}
|
|
866
|
+
function watchAnimatingTransformAncestor() {
|
|
867
|
+
animatingAncestorCleanup?.();
|
|
868
|
+
const animatingNode = findAnimatingTransformAncestor(affixBaseEl.value);
|
|
869
|
+
if (!animatingNode) return;
|
|
870
|
+
const cleanup = () => {
|
|
871
|
+
animatingNode.removeEventListener("transitionend", onEnd);
|
|
872
|
+
animatingNode.removeEventListener("animationend", onEnd);
|
|
873
|
+
animatingAncestorCleanup = null;
|
|
874
|
+
};
|
|
875
|
+
const onEnd = () => {
|
|
876
|
+
cleanup();
|
|
877
|
+
refreshAffixedMetrics();
|
|
878
|
+
};
|
|
879
|
+
animatingNode.addEventListener("transitionend", onEnd);
|
|
880
|
+
animatingNode.addEventListener("animationend", onEnd);
|
|
881
|
+
animatingAncestorCleanup = cleanup;
|
|
882
|
+
}
|
|
856
883
|
async function applyAffixedTransform() {
|
|
857
884
|
const el = affixBaseEl.value;
|
|
858
885
|
if (!el) return;
|
|
@@ -863,6 +890,33 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
863
890
|
});
|
|
864
891
|
affixedHeaderTransform.value = `translateY(-${y}px)`;
|
|
865
892
|
}
|
|
893
|
+
function scheduleProbeBottomBlock() {
|
|
894
|
+
if (probeRafId) return;
|
|
895
|
+
probeRafId = requestAnimationFrame(() => {
|
|
896
|
+
probeRafId = 0;
|
|
897
|
+
probeBottomBlockHeight();
|
|
898
|
+
});
|
|
899
|
+
}
|
|
900
|
+
function probeBottomBlockHeight() {
|
|
901
|
+
const scrollEl = outsideScrollEl.value;
|
|
902
|
+
const tableEl = tableRef.value?.$el;
|
|
903
|
+
if (!scrollEl || !tableEl) return;
|
|
904
|
+
const sRect = scrollEl.getBoundingClientRect();
|
|
905
|
+
const stack = document.elementsFromPoint(sRect.left + sRect.width / 2, sRect.bottom - 1);
|
|
906
|
+
let blockHeight = 0;
|
|
907
|
+
for (const el of stack) {
|
|
908
|
+
if (tableEl.contains(el)) continue;
|
|
909
|
+
if (el === scrollEl || el.contains(scrollEl)) continue;
|
|
910
|
+
const {
|
|
911
|
+
position
|
|
912
|
+
} = getComputedStyle(el);
|
|
913
|
+
if (position !== "fixed" && position !== "sticky") continue;
|
|
914
|
+
const rect = el.getBoundingClientRect();
|
|
915
|
+
if (rect.top < sRect.top) continue;
|
|
916
|
+
blockHeight = Math.max(blockHeight, sRect.bottom - rect.top);
|
|
917
|
+
}
|
|
918
|
+
affixBottomOffset.value = blockHeight;
|
|
919
|
+
}
|
|
866
920
|
watch(columnControllerVisible, (visible) => {
|
|
867
921
|
const {
|
|
868
922
|
columns
|
|
@@ -881,6 +935,31 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
881
935
|
requestAnimationFrame(() => {
|
|
882
936
|
tablePs.value?.update();
|
|
883
937
|
});
|
|
938
|
+
watchAnimatingTransformAncestor();
|
|
939
|
+
nextTick(() => {
|
|
940
|
+
setTimeout(refreshAffixedMetrics, 320);
|
|
941
|
+
});
|
|
942
|
+
});
|
|
943
|
+
watch(isOutsideTableContent, (outside) => {
|
|
944
|
+
if (outside) return;
|
|
945
|
+
refreshAffixedMetrics();
|
|
946
|
+
});
|
|
947
|
+
watch(outsideScrollEl, (el, _old, onCleanup) => {
|
|
948
|
+
if (!el) return;
|
|
949
|
+
probeBottomBlockHeight();
|
|
950
|
+
const onScroll = () => scheduleProbeBottomBlock();
|
|
951
|
+
el.addEventListener("scroll", onScroll, {
|
|
952
|
+
passive: true
|
|
953
|
+
});
|
|
954
|
+
onCleanup(() => {
|
|
955
|
+
el.removeEventListener("scroll", onScroll);
|
|
956
|
+
if (probeRafId) {
|
|
957
|
+
cancelAnimationFrame(probeRafId);
|
|
958
|
+
probeRafId = 0;
|
|
959
|
+
}
|
|
960
|
+
});
|
|
961
|
+
}, {
|
|
962
|
+
immediate: true
|
|
884
963
|
});
|
|
885
964
|
onActivated(() => {
|
|
886
965
|
setScrollElTo();
|
|
@@ -892,6 +971,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
892
971
|
onBeforeUnmount(() => {
|
|
893
972
|
tableContentStop();
|
|
894
973
|
outsideTableContentStop();
|
|
974
|
+
if (probeRafId) cancelAnimationFrame(probeRafId);
|
|
975
|
+
animatingAncestorCleanup?.();
|
|
895
976
|
});
|
|
896
977
|
__expose(createExposeProxy({
|
|
897
978
|
data,
|
|
@@ -919,7 +1000,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
919
1000
|
return (_ctx, _cache) => {
|
|
920
1001
|
return withDirectives((openBlock(), createBlock(resolveDynamicComponent(reProps.value.tableOptions.tree ? unref(EnhancedTable) : unref(Table)), mergeProps({
|
|
921
1002
|
ref: "table",
|
|
922
|
-
class: ["qd-service-table", __props.headerBg ? "" : "t-table--header-bg-inherit", unref(isOutsideTableContent) ? "" : "qd-service-table--inside-table-content",
|
|
1003
|
+
class: ["qd-service-table", __props.headerBg ? "" : "t-table--header-bg-inherit", unref(isOutsideTableContent) ? "" : "qd-service-table--inside-table-content", isPsXFixed.value ? "qd-service-table--ps-x-fixed" : "", __props.disableHorizontalScroll ? "qd-service-table--disable-horizontal-scroll" : ""],
|
|
923
1004
|
"selected-row-keys": unref(selectedRowKeys),
|
|
924
1005
|
"onUpdate:selectedRowKeys": _cache[0] || (_cache[0] = ($event) => isRef(selectedRowKeys) ? selectedRowKeys.value = $event : null),
|
|
925
1006
|
"active-row-keys": unref(activeRowKeys),
|
|
@@ -1,97 +1,97 @@
|
|
|
1
|
-
.qd-upload[data-v-
|
|
1
|
+
.qd-upload[data-v-b860b275] {
|
|
2
2
|
width: 100%;
|
|
3
3
|
outline: none;
|
|
4
4
|
}
|
|
5
|
-
.qd-upload[data-v-
|
|
5
|
+
.qd-upload[data-v-b860b275] .t-image-viewer__trigger {
|
|
6
6
|
display: none;
|
|
7
7
|
}
|
|
8
|
-
.qd-upload[data-v-
|
|
8
|
+
.qd-upload[data-v-b860b275] .t-upload__dragger {
|
|
9
9
|
min-width: auto;
|
|
10
10
|
min-height: 144px;
|
|
11
11
|
width: 100%;
|
|
12
12
|
height: 100%;
|
|
13
13
|
}
|
|
14
|
-
.qd-upload[data-v-
|
|
14
|
+
.qd-upload[data-v-b860b275] .t-upload__flow {
|
|
15
15
|
width: 100%;
|
|
16
16
|
min-width: auto;
|
|
17
17
|
max-width: 100%;
|
|
18
18
|
}
|
|
19
|
-
.qd-upload[data-v-
|
|
19
|
+
.qd-upload[data-v-b860b275] .t-upload__flow-empty {
|
|
20
20
|
height: auto;
|
|
21
21
|
min-height: 144px;
|
|
22
22
|
}
|
|
23
|
-
.qd-upload[data-v-
|
|
24
|
-
.qd-upload[data-v-
|
|
23
|
+
.qd-upload[data-v-b860b275] .t-upload__flow-card-area,
|
|
24
|
+
.qd-upload[data-v-b860b275] .t-upload__flow-table {
|
|
25
25
|
margin-top: var(--td-comp-margin-s);
|
|
26
26
|
}
|
|
27
|
-
.qd-upload[data-v-
|
|
27
|
+
.qd-upload[data-v-b860b275] .t-upload__file-name__container {
|
|
28
28
|
display: flex;
|
|
29
29
|
align-items: center;
|
|
30
30
|
}
|
|
31
|
-
.qd-upload[data-v-
|
|
31
|
+
.qd-upload[data-v-b860b275] .t-upload__file-name-text {
|
|
32
32
|
cursor: pointer;
|
|
33
33
|
}
|
|
34
|
-
.qd-upload[data-v-
|
|
34
|
+
.qd-upload[data-v-b860b275] .t-upload__file-thumbnail {
|
|
35
35
|
width: var(--td-comp-size-m);
|
|
36
36
|
height: var(--td-comp-size-m);
|
|
37
37
|
}
|
|
38
|
-
.qd-upload[data-v-
|
|
38
|
+
.qd-upload[data-v-b860b275] .t-upload__card-image {
|
|
39
39
|
width: 100%;
|
|
40
40
|
height: 100%;
|
|
41
41
|
}
|
|
42
|
-
.qd-upload__popup-upload[data-v-
|
|
42
|
+
.qd-upload__popup-upload[data-v-b860b275] .t-image-viewer__trigger {
|
|
43
43
|
display: none;
|
|
44
44
|
}
|
|
45
|
-
.qd-upload__popup-upload[data-v-
|
|
45
|
+
.qd-upload__popup-upload[data-v-b860b275] .t-upload__flow-table {
|
|
46
46
|
margin-top: 0;
|
|
47
47
|
}
|
|
48
|
-
.qd-upload__popup-upload[data-v-
|
|
48
|
+
.qd-upload__popup-upload[data-v-b860b275] .t-upload__file-name__container {
|
|
49
49
|
display: flex;
|
|
50
50
|
align-items: center;
|
|
51
51
|
}
|
|
52
|
-
.qd-upload__popup-upload[data-v-
|
|
52
|
+
.qd-upload__popup-upload[data-v-b860b275] .t-upload__file-name-text {
|
|
53
53
|
cursor: pointer;
|
|
54
54
|
}
|
|
55
|
-
.qd-upload__popup-upload[data-v-
|
|
55
|
+
.qd-upload__popup-upload[data-v-b860b275] .t-upload__file-thumbnail {
|
|
56
56
|
width: var(--td-comp-size-m);
|
|
57
57
|
height: var(--td-comp-size-m);
|
|
58
58
|
}
|
|
59
|
-
.qd-upload__popup-upload[data-v-
|
|
59
|
+
.qd-upload__popup-upload[data-v-b860b275] .t-upload__card-image {
|
|
60
60
|
width: 100%;
|
|
61
61
|
height: 100%;
|
|
62
62
|
}
|
|
63
|
-
.qd-upload__popup-upload--disabled[data-v-
|
|
64
|
-
.qd-upload__popup-upload--disabled[data-v-
|
|
63
|
+
.qd-upload__popup-upload--disabled[data-v-b860b275] .t-upload__flow-table th:last-child,
|
|
64
|
+
.qd-upload__popup-upload--disabled[data-v-b860b275] .t-upload__flow-table td:last-child {
|
|
65
65
|
display: none;
|
|
66
66
|
}
|
|
67
|
-
.qd-upload[data-v-
|
|
68
|
-
.qd-upload[data-v-
|
|
67
|
+
.qd-upload[data-v-b860b275]:focus .t-upload__flow-card-area,
|
|
68
|
+
.qd-upload[data-v-b860b275]:focus .t-upload__flow-table {
|
|
69
69
|
border-color: var(--td-brand-color);
|
|
70
70
|
}
|
|
71
|
-
.qd-upload--only-view[data-v-
|
|
72
|
-
.qd-upload--only-view[data-v-
|
|
71
|
+
.qd-upload--only-view[data-v-b860b275] .t-upload__flow-empty,
|
|
72
|
+
.qd-upload--only-view[data-v-b860b275] .t-upload__card-mask-item-divider {
|
|
73
73
|
display: none;
|
|
74
74
|
}
|
|
75
|
-
.qd-upload--only-view[data-v-
|
|
75
|
+
.qd-upload--only-view[data-v-b860b275] .t-upload__flow-card-area {
|
|
76
76
|
border-color: var(--td-component-border);
|
|
77
77
|
}
|
|
78
|
-
.qd-upload--only-view[data-v-
|
|
79
|
-
.qd-upload--only-view[data-v-
|
|
80
|
-
.qd-upload--only-view[data-v-
|
|
78
|
+
.qd-upload--only-view[data-v-b860b275]:not(.qd-upload--btn-image-popup):not(.qd-upload--btn-file-popup) .t-upload__flow-op,
|
|
79
|
+
.qd-upload--only-view[data-v-b860b275]:not(.qd-upload--btn-image-popup):not(.qd-upload--btn-file-popup) .t-upload__trigger,
|
|
80
|
+
.qd-upload--only-view[data-v-b860b275]:not(.qd-upload--btn-image-popup):not(.qd-upload--btn-file-popup) .t-upload__flow-bottom {
|
|
81
81
|
display: none;
|
|
82
82
|
}
|
|
83
|
-
.qd-upload--only-view[data-v-
|
|
84
|
-
.qd-upload--only-view[data-v-
|
|
83
|
+
.qd-upload--only-view[data-v-b860b275]:not(.qd-upload--btn-image-popup):not(.qd-upload--btn-file-popup) .t-upload__flow-table,
|
|
84
|
+
.qd-upload--only-view[data-v-b860b275]:not(.qd-upload--btn-image-popup):not(.qd-upload--btn-file-popup) .t-upload__flow-card-area {
|
|
85
85
|
margin-top: 0;
|
|
86
86
|
}
|
|
87
|
-
.qd-upload--hide-manual-upload[data-v-
|
|
87
|
+
.qd-upload--hide-manual-upload[data-v-b860b275] .t-upload__flow-bottom {
|
|
88
88
|
display: none;
|
|
89
89
|
margin-top: 0;
|
|
90
90
|
}
|
|
91
|
-
.qd-upload--hide-progress[data-v-
|
|
92
|
-
.qd-upload--hide-progress[data-v-
|
|
91
|
+
.qd-upload--hide-progress[data-v-b860b275] .t-upload__flow-table th:last-child,
|
|
92
|
+
.qd-upload--hide-progress[data-v-b860b275] .t-upload__flow-table td:last-child {
|
|
93
93
|
display: none;
|
|
94
94
|
}
|
|
95
|
-
.qd-upload--disabled[data-v-
|
|
95
|
+
.qd-upload--disabled[data-v-b860b275] .t-upload__flow-card-area {
|
|
96
96
|
border-color: var(--td-component-border);
|
|
97
97
|
}
|
|
@@ -2,7 +2,7 @@ import './index.css'
|
|
|
2
2
|
import _sfc_main from "./index.vue2.mjs";
|
|
3
3
|
/* empty css */
|
|
4
4
|
import _export_sfc from "../../_virtual/_plugin-vue_export-helper.mjs";
|
|
5
|
-
const QdUpload = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-
|
|
5
|
+
const QdUpload = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-b860b275"]]);
|
|
6
6
|
export {
|
|
7
7
|
QdUpload as default
|
|
8
8
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import './index.css'
|
|
2
|
-
import { defineComponent, mergeDefaults, computed, inject, useTemplateRef, ref, watch, onMounted, createBlock, openBlock, unref, mergeProps, isRef, createSlots, withCtx, createCommentVNode, createTextVNode, toDisplayString, createVNode, withModifiers, normalizeClass, createElementVNode, renderList, renderSlot, normalizeProps, guardReactiveProps } from "vue";
|
|
2
|
+
import { defineComponent, mergeDefaults, computed, inject, useTemplateRef, ref, watch, onUnmounted, onMounted, createBlock, openBlock, unref, mergeProps, isRef, createSlots, withCtx, createCommentVNode, createTextVNode, toDisplayString, createVNode, withModifiers, normalizeClass, createElementVNode, renderList, renderSlot, normalizeProps, guardReactiveProps, nextTick } from "vue";
|
|
3
3
|
import { useVModels } from "../../node_modules/.pnpm/@vueuse_core@14.2.0_vue@3.5.26_typescript@5.9.3_/node_modules/@vueuse/core/dist/index.mjs";
|
|
4
4
|
import dayjs from "../../_virtual/dayjs.min.mjs";
|
|
5
5
|
import { isEmpty, useTimer, easyCopy, checkSameObject, to, filterSlots, isTypeByName, suspectedWrapperPromise } from "qidian-shared";
|
|
@@ -10,6 +10,7 @@ import { useConfig } from "../config-provider/useConfig.mjs";
|
|
|
10
10
|
import { qdDictConvStrSeparator } from "../dict/tag/props.mjs";
|
|
11
11
|
import { qdUploadAcceptMap } from "./config.mjs";
|
|
12
12
|
import { qdUploadSizeLimit, qdUploadProps } from "./props.mjs";
|
|
13
|
+
import { uploadByXhr, calcUploadTimeout } from "./request.mjs";
|
|
13
14
|
import { PROVIDE_FORM_ADD_BEFORE_SUBMIT_QUEUE, PROVIDE_FORM_ADD_AFTER_SUBMIT_QUEUE, PROVIDE_FORM_RESET_QUEUE } from "../form/config.mjs";
|
|
14
15
|
import { useReadonly } from "../../hooks/useReadonly.mjs";
|
|
15
16
|
import { useDisabled } from "../../hooks/useDisabled.mjs";
|
|
@@ -19,6 +20,7 @@ import _sfc_main$3 from "../multi-file-viewer/index.vue.mjs";
|
|
|
19
20
|
/* empty css */
|
|
20
21
|
import _sfc_main$4 from "./image-flow-file-list-display/index.vue.mjs";
|
|
21
22
|
import { useModal } from "../../hooks/useModal.mjs";
|
|
23
|
+
const tempOssIdPrefix = "__qd_upload_temp_";
|
|
22
24
|
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
23
25
|
...{
|
|
24
26
|
name: "QdUpload"
|
|
@@ -28,6 +30,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
28
30
|
modelValue: {},
|
|
29
31
|
action: { type: [String, Function] },
|
|
30
32
|
bucketConfigKey: {},
|
|
33
|
+
timeout: {},
|
|
31
34
|
convStr: { type: [Boolean, String] },
|
|
32
35
|
valueMode: {},
|
|
33
36
|
theme: {},
|
|
@@ -132,6 +135,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
132
135
|
const { msgError, msgWarning } = useModal();
|
|
133
136
|
const uploadRef = useTemplateRef("upload");
|
|
134
137
|
const { timer: uploadTimer, clearTimer: clearUploadTimer } = useTimer("interval");
|
|
138
|
+
let isSyncingUploadModelValue = false;
|
|
139
|
+
const tempUrlMap = /* @__PURE__ */ new WeakMap();
|
|
140
|
+
const tempModelValueSet = /* @__PURE__ */ new Set();
|
|
135
141
|
const delList = ref([]);
|
|
136
142
|
const popupFileList = computed(() => [...fileList.value]);
|
|
137
143
|
const popupVisible = ref(false);
|
|
@@ -171,6 +177,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
171
177
|
del,
|
|
172
178
|
action,
|
|
173
179
|
bucketConfigKey,
|
|
180
|
+
timeout,
|
|
174
181
|
showImageFileName,
|
|
175
182
|
showUploadProgress,
|
|
176
183
|
showThumbnail,
|
|
@@ -183,6 +190,49 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
183
190
|
const globalUploadPropsV = globalUploadProps.value;
|
|
184
191
|
const reAction = action || globalUploadPropsV?.action;
|
|
185
192
|
const actionUrl = typeof reAction === "string" ? reAction : reAction?.(bucketConfigKey);
|
|
193
|
+
const useUploadTimeout = timeout === void 0 || timeout > 0;
|
|
194
|
+
const baseTimeout = timeout ?? 1e3 * 30;
|
|
195
|
+
const customRequestMethod = props.requestMethod ?? globalUploadPropsV?.requestMethod;
|
|
196
|
+
const useRequestMethod = !customRequestMethod && useUploadTimeout && !!actionUrl;
|
|
197
|
+
const uploadMethod = props.method ?? globalUploadPropsV?.method;
|
|
198
|
+
const uploadName = props.name ?? globalUploadPropsV?.name;
|
|
199
|
+
const uploadWithCredentials = props.withCredentials ?? globalUploadPropsV?.withCredentials;
|
|
200
|
+
const uploadUseMockProgress = props.useMockProgress ?? globalUploadPropsV?.useMockProgress;
|
|
201
|
+
const uploadMockProgressDuration = props.mockProgressDuration ?? globalUploadPropsV?.mockProgressDuration;
|
|
202
|
+
const uploadHeaders = props.headers ?? globalUploadPropsV?.headers;
|
|
203
|
+
const uploadData = props.data ?? globalUploadPropsV?.data;
|
|
204
|
+
const uploadFormatRequest = props.formatRequest ?? globalUploadPropsV?.formatRequest;
|
|
205
|
+
const uploadOnProgress = props.onProgress ?? globalUploadPropsV?.onProgress;
|
|
206
|
+
const reRequestMethod = useRequestMethod ? (files2) => {
|
|
207
|
+
const fileArr = Array.isArray(files2) ? files2 : [files2];
|
|
208
|
+
const totalSize = fileArr.reduce(
|
|
209
|
+
(sum, file) => sum + (file.raw?.size ?? file.size ?? 0),
|
|
210
|
+
0
|
|
211
|
+
);
|
|
212
|
+
return uploadByXhr(fileArr, {
|
|
213
|
+
method: uploadMethod,
|
|
214
|
+
action: actionUrl,
|
|
215
|
+
withCredentials: uploadWithCredentials,
|
|
216
|
+
headers: uploadHeaders,
|
|
217
|
+
data: uploadData,
|
|
218
|
+
name: uploadName,
|
|
219
|
+
formatRequest: uploadFormatRequest,
|
|
220
|
+
useMockProgress: uploadUseMockProgress,
|
|
221
|
+
mockProgressDuration: uploadMockProgressDuration,
|
|
222
|
+
onProgress: uploadOnProgress,
|
|
223
|
+
timeout: calcUploadTimeout(baseTimeout, totalSize)
|
|
224
|
+
}).then((result) => {
|
|
225
|
+
if (result.status === "success") {
|
|
226
|
+
const response = result.response;
|
|
227
|
+
return {
|
|
228
|
+
status: "success",
|
|
229
|
+
response: { ...response, url: response?.url ?? response?.data?.url }
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
const errorMsg = result.error === "timeout" ? t("fileUploadTimeout") : t("fileUploadFailed");
|
|
233
|
+
return { status: "fail", error: errorMsg, response: {} };
|
|
234
|
+
});
|
|
235
|
+
} : void 0;
|
|
186
236
|
const reSizeLimit = easyCopy(qdUploadSizeLimit);
|
|
187
237
|
if (reSizeLimit) {
|
|
188
238
|
if (typeof sizeLimit === "number") {
|
|
@@ -238,15 +288,17 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
238
288
|
};
|
|
239
289
|
const reOnSuccess = (context) => {
|
|
240
290
|
onSuccess?.(context);
|
|
241
|
-
|
|
291
|
+
revokeTempUrl(context.file);
|
|
292
|
+
updateTempModelValue(fileList.value);
|
|
242
293
|
};
|
|
243
294
|
const reOnRemove = (context) => {
|
|
244
295
|
onRemove?.(context);
|
|
296
|
+
revokeTempUrl(context.file);
|
|
245
297
|
const { ossId } = context.file?.response || {};
|
|
246
298
|
if (ossId) {
|
|
247
299
|
addDel(ossId);
|
|
248
300
|
}
|
|
249
|
-
|
|
301
|
+
updateTempModelValue(fileList.value);
|
|
250
302
|
};
|
|
251
303
|
const reOnPreview = ({ file, index, e }) => {
|
|
252
304
|
popupVisible.value = false;
|
|
@@ -266,11 +318,12 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
266
318
|
onWaitingUploadFilesChange?.(context);
|
|
267
319
|
if (context.trigger === "validate" && context.files.length) {
|
|
268
320
|
onValidateSuccess?.(context.files);
|
|
321
|
+
nextTick(() => updateTempModelValue(fileList.value));
|
|
269
322
|
}
|
|
270
323
|
};
|
|
271
324
|
const reUploadOptions = {
|
|
272
325
|
...uploadOptions,
|
|
273
|
-
action: actionUrl,
|
|
326
|
+
...useRequestMethod ? { requestMethod: reRequestMethod } : { action: actionUrl },
|
|
274
327
|
theme: ["custom", "file", "file-input", "file-flow", "image", "image-flow"].includes(theme) ? theme : "custom",
|
|
275
328
|
sizeLimit: reSizeLimit,
|
|
276
329
|
accept: acceptStr,
|
|
@@ -335,13 +388,18 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
335
388
|
});
|
|
336
389
|
const expose = {};
|
|
337
390
|
const uploadFiles = (options) => {
|
|
391
|
+
fileList.value.forEach((file) => {
|
|
392
|
+
if (file.status === "fail" && file.response) {
|
|
393
|
+
delete file.response.error;
|
|
394
|
+
}
|
|
395
|
+
});
|
|
338
396
|
uploadRef.value?.uploadFiles(options?.files);
|
|
339
397
|
return new Promise((resolve, reject) => {
|
|
340
398
|
uploadTimer.value = setInterval(() => {
|
|
341
399
|
const isFinished = fileList.value.every((item) => item.status !== "progress");
|
|
342
400
|
if (!isFinished) return;
|
|
343
401
|
clearUploadTimer();
|
|
344
|
-
|
|
402
|
+
updateTempModelValue(fileList.value);
|
|
345
403
|
const errorList = fileList.value.filter((item) => item.status === "fail");
|
|
346
404
|
if (errorList.length) {
|
|
347
405
|
const msg = `${errorList.map((item) => item.name).join(",")} ${t("fileUploadFailed")}`;
|
|
@@ -355,13 +413,52 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
355
413
|
}, 100);
|
|
356
414
|
});
|
|
357
415
|
};
|
|
358
|
-
function
|
|
416
|
+
function isTempModelValue(value) {
|
|
417
|
+
return value.startsWith(tempOssIdPrefix) || tempModelValueSet.has(value);
|
|
418
|
+
}
|
|
419
|
+
function genTempValue(file) {
|
|
420
|
+
if (!file.uid) {
|
|
421
|
+
file.uid = `qd_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
|
|
422
|
+
}
|
|
423
|
+
if (reProps.value.valueMode === "url") {
|
|
424
|
+
if (file.raw) {
|
|
425
|
+
let tempUrl = tempUrlMap.get(file);
|
|
426
|
+
if (!tempUrl) {
|
|
427
|
+
tempUrl = URL.createObjectURL(file.raw);
|
|
428
|
+
tempUrlMap.set(file, tempUrl);
|
|
429
|
+
}
|
|
430
|
+
tempModelValueSet.add(tempUrl);
|
|
431
|
+
return tempUrl;
|
|
432
|
+
}
|
|
433
|
+
return file.url || file.uid;
|
|
434
|
+
}
|
|
435
|
+
return `${tempOssIdPrefix}${file.uid}`;
|
|
436
|
+
}
|
|
437
|
+
function updateTempModelValue(files) {
|
|
359
438
|
const tempModelValue = [];
|
|
360
439
|
files.forEach((item) => {
|
|
361
|
-
if (item.status
|
|
362
|
-
|
|
440
|
+
if (item.status === "success") {
|
|
441
|
+
tempModelValue.push(item.response[reProps.value.valueMode]);
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
tempModelValue.push(genTempValue(item));
|
|
363
445
|
});
|
|
446
|
+
isSyncingUploadModelValue = true;
|
|
364
447
|
reModelValue.value = tempModelValue;
|
|
448
|
+
nextTick(() => {
|
|
449
|
+
isSyncingUploadModelValue = false;
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
function revokeTempUrl(file) {
|
|
453
|
+
if (!file) return;
|
|
454
|
+
const tempUrl = tempUrlMap.get(file);
|
|
455
|
+
if (!tempUrl) return;
|
|
456
|
+
URL.revokeObjectURL(tempUrl);
|
|
457
|
+
tempUrlMap.delete(file);
|
|
458
|
+
tempModelValueSet.delete(tempUrl);
|
|
459
|
+
}
|
|
460
|
+
function revokeAllTempUrls() {
|
|
461
|
+
fileList.value.forEach((file) => revokeTempUrl(file));
|
|
365
462
|
}
|
|
366
463
|
async function handleDel(ossId, showErrorMessage) {
|
|
367
464
|
const { del } = reProps.value;
|
|
@@ -456,40 +553,64 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
456
553
|
return true;
|
|
457
554
|
}
|
|
458
555
|
function clear() {
|
|
556
|
+
revokeAllTempUrls();
|
|
459
557
|
reModelValue.value = [];
|
|
460
558
|
fileList.value = [];
|
|
461
559
|
}
|
|
462
560
|
formAddBeforeSubmitQueue?.(uploadBeforeFormSubmit);
|
|
463
561
|
formAddAfterSubmitQueue?.(delBeforeFormSubmit);
|
|
464
562
|
formResetQueue?.(clear);
|
|
563
|
+
function getFileModelValue(file) {
|
|
564
|
+
if (file.status === "success") {
|
|
565
|
+
return file.response?.[reProps.value.valueMode];
|
|
566
|
+
}
|
|
567
|
+
return genTempValue(file);
|
|
568
|
+
}
|
|
569
|
+
function buildFileListByModelValue(modelValue2, ossList) {
|
|
570
|
+
const { valueMode } = reProps.value;
|
|
571
|
+
const ossMap = new Map(ossList.map((item) => [item[valueMode], item]));
|
|
572
|
+
return modelValue2.flatMap((value) => {
|
|
573
|
+
if (isTempModelValue(value)) {
|
|
574
|
+
const localFile = fileList.value.find((f) => getFileModelValue(f) === value);
|
|
575
|
+
return localFile ? [localFile] : [];
|
|
576
|
+
}
|
|
577
|
+
const item = ossMap.get(value);
|
|
578
|
+
if (!item) return [];
|
|
579
|
+
const { url, ossId, originalName, fileSize, contentType, createTime } = item;
|
|
580
|
+
return [
|
|
581
|
+
{
|
|
582
|
+
url,
|
|
583
|
+
uid: ossId,
|
|
584
|
+
name: originalName,
|
|
585
|
+
size: fileSize,
|
|
586
|
+
type: contentType,
|
|
587
|
+
uploadTime: createTime,
|
|
588
|
+
response: { status: "success", url, ossId, name: originalName, uploadTime: createTime },
|
|
589
|
+
status: "success"
|
|
590
|
+
}
|
|
591
|
+
];
|
|
592
|
+
});
|
|
593
|
+
}
|
|
465
594
|
watch(
|
|
466
595
|
reModelValue,
|
|
467
596
|
async (newVal, oldVal) => {
|
|
468
|
-
if (
|
|
597
|
+
if (isSyncingUploadModelValue) return;
|
|
598
|
+
const reNewVal = newVal.filter((item) => !isTempModelValue(item));
|
|
599
|
+
const reOldVal = oldVal?.filter((item) => !isTempModelValue(item));
|
|
469
600
|
if (!newVal.length) {
|
|
470
601
|
fileList.value = [];
|
|
471
602
|
return;
|
|
472
603
|
}
|
|
604
|
+
if (!reNewVal.length || checkSameObject(reNewVal, reOldVal)) return;
|
|
473
605
|
const { valueMode } = reProps.value;
|
|
474
606
|
const apiFn = valueMode === "url" ? getOssByUrls : getOssByIds;
|
|
475
|
-
const [err, res] = await to(apiFn(
|
|
607
|
+
const [err, res] = await to(apiFn(reNewVal));
|
|
476
608
|
if (err) return;
|
|
477
|
-
fileList.value = res
|
|
478
|
-
const { url, ossId, originalName, fileSize, contentType, createTime } = item;
|
|
479
|
-
return {
|
|
480
|
-
url,
|
|
481
|
-
uid: ossId,
|
|
482
|
-
name: originalName,
|
|
483
|
-
size: fileSize,
|
|
484
|
-
type: contentType,
|
|
485
|
-
uploadTime: createTime,
|
|
486
|
-
response: { status: "success", url, ossId, name: originalName, uploadTime: createTime },
|
|
487
|
-
status: "success"
|
|
488
|
-
};
|
|
489
|
-
});
|
|
609
|
+
fileList.value = buildFileListByModelValue(newVal, res);
|
|
490
610
|
},
|
|
491
611
|
{ deep: true, immediate: true }
|
|
492
612
|
);
|
|
613
|
+
onUnmounted(revokeAllTempUrls);
|
|
493
614
|
onMounted(() => {
|
|
494
615
|
Object.assign(expose, uploadRef.value, { uploadFiles, clear });
|
|
495
616
|
});
|
|
@@ -9,16 +9,13 @@ export declare const qdUploadProps: {
|
|
|
9
9
|
readonly allowUploadDuplicateFile: true;
|
|
10
10
|
readonly isBatchUpload: false;
|
|
11
11
|
readonly uploadAllFilesInOneRequest: false;
|
|
12
|
-
readonly method: "POST";
|
|
13
12
|
readonly multiple: undefined;
|
|
14
|
-
readonly name: "file";
|
|
15
13
|
readonly disabled: undefined;
|
|
16
14
|
readonly showImageFileName: true;
|
|
17
15
|
readonly showThumbnail: true;
|
|
18
16
|
readonly showUploadProgress: true;
|
|
19
17
|
readonly uploadPastedFiles: true;
|
|
20
|
-
readonly
|
|
21
|
-
readonly withCredentials: false;
|
|
18
|
+
readonly timeout: undefined;
|
|
22
19
|
readonly showManualButton: false;
|
|
23
20
|
readonly del: undefined;
|
|
24
21
|
};
|
|
@@ -9,16 +9,13 @@ const qdUploadProps = {
|
|
|
9
9
|
allowUploadDuplicateFile: true,
|
|
10
10
|
isBatchUpload: false,
|
|
11
11
|
uploadAllFilesInOneRequest: false,
|
|
12
|
-
method: "POST",
|
|
13
12
|
multiple: void 0,
|
|
14
|
-
name: "file",
|
|
15
13
|
disabled: void 0,
|
|
16
14
|
showImageFileName: true,
|
|
17
15
|
showThumbnail: true,
|
|
18
16
|
showUploadProgress: true,
|
|
19
17
|
uploadPastedFiles: true,
|
|
20
|
-
|
|
21
|
-
withCredentials: false,
|
|
18
|
+
timeout: void 0,
|
|
22
19
|
showManualButton: false,
|
|
23
20
|
del: void 0
|
|
24
21
|
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { TdUploadProps, UploadFile } from 'tdesign-vue-next';
|
|
2
|
+
export interface QdUploadXhrOptions {
|
|
3
|
+
method?: string;
|
|
4
|
+
action: string;
|
|
5
|
+
withCredentials?: boolean;
|
|
6
|
+
headers?: Record<string, string>;
|
|
7
|
+
data?: Record<string, any> | ((files: UploadFile[]) => Record<string, any>);
|
|
8
|
+
name?: string;
|
|
9
|
+
formatRequest?: (requestData: Record<string, any>) => Record<string, any>;
|
|
10
|
+
useMockProgress?: boolean;
|
|
11
|
+
mockProgressDuration?: number;
|
|
12
|
+
timeout: number;
|
|
13
|
+
onProgress?: TdUploadProps['onProgress'];
|
|
14
|
+
}
|
|
15
|
+
export interface QdUploadRequestResult {
|
|
16
|
+
status: 'success' | 'fail';
|
|
17
|
+
error?: 'timeout' | 'error' | 'fail';
|
|
18
|
+
response: Record<string, any>;
|
|
19
|
+
}
|
|
20
|
+
export declare function calcUploadTimeout(baseTimeout: number, size: number): number;
|
|
21
|
+
export declare function uploadByXhr(files: UploadFile[], options: QdUploadXhrOptions): Promise<QdUploadRequestResult>;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import isFunction from "../../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/isFunction.mjs";
|
|
2
|
+
function calcUploadTimeout(baseTimeout, size) {
|
|
3
|
+
const fileSizeMB = Math.max(Math.ceil(size / 1024 / 1024), 1);
|
|
4
|
+
return Math.max(Math.round(baseTimeout + (fileSizeMB - 1) * (baseTimeout / 3)), 1e3 * 20);
|
|
5
|
+
}
|
|
6
|
+
function uploadByXhr(files, options) {
|
|
7
|
+
const {
|
|
8
|
+
method = "POST",
|
|
9
|
+
action,
|
|
10
|
+
withCredentials = false,
|
|
11
|
+
headers = {},
|
|
12
|
+
data = {},
|
|
13
|
+
name = "file",
|
|
14
|
+
formatRequest,
|
|
15
|
+
useMockProgress = true,
|
|
16
|
+
mockProgressDuration = 300,
|
|
17
|
+
timeout,
|
|
18
|
+
onProgress
|
|
19
|
+
} = options;
|
|
20
|
+
return new Promise((resolve) => {
|
|
21
|
+
const xhr = new XMLHttpRequest();
|
|
22
|
+
if (withCredentials) xhr.withCredentials = true;
|
|
23
|
+
let percent = 0;
|
|
24
|
+
let mockTimer;
|
|
25
|
+
let mockDelayTimer;
|
|
26
|
+
let settled = false;
|
|
27
|
+
const finish = (result) => {
|
|
28
|
+
if (settled) return;
|
|
29
|
+
settled = true;
|
|
30
|
+
clearInterval(mockTimer);
|
|
31
|
+
clearTimeout(mockDelayTimer);
|
|
32
|
+
resolve(result);
|
|
33
|
+
};
|
|
34
|
+
if (useMockProgress && files[0]?.status === "progress") {
|
|
35
|
+
mockDelayTimer = setTimeout(() => {
|
|
36
|
+
mockTimer = setInterval(() => {
|
|
37
|
+
if (percent + 10 < 100) {
|
|
38
|
+
percent = Math.max(percent + 10, percent);
|
|
39
|
+
if (files[0] && percent !== files[0].percent) {
|
|
40
|
+
files.forEach((file) => {
|
|
41
|
+
file.percent = percent;
|
|
42
|
+
});
|
|
43
|
+
onProgress?.({
|
|
44
|
+
file: files[0],
|
|
45
|
+
currentFiles: files,
|
|
46
|
+
percent,
|
|
47
|
+
type: "mock",
|
|
48
|
+
XMLHttpRequest: xhr
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
} else {
|
|
52
|
+
clearInterval(mockTimer);
|
|
53
|
+
}
|
|
54
|
+
}, mockProgressDuration);
|
|
55
|
+
clearTimeout(mockDelayTimer);
|
|
56
|
+
}, mockProgressDuration);
|
|
57
|
+
}
|
|
58
|
+
let requestData = {};
|
|
59
|
+
const extraData = isFunction(data) ? data(files) : data;
|
|
60
|
+
Object.assign(requestData, extraData);
|
|
61
|
+
files.forEach((file, index) => {
|
|
62
|
+
const fileField = files.length > 1 ? `${name}[${index}]` : name;
|
|
63
|
+
requestData[fileField] = file.raw;
|
|
64
|
+
});
|
|
65
|
+
requestData[name] = files.length === 1 ? files[0].raw : files.map((file) => file.raw);
|
|
66
|
+
requestData.length = files.length;
|
|
67
|
+
if (formatRequest) requestData = formatRequest(requestData);
|
|
68
|
+
const formData = new FormData();
|
|
69
|
+
Object.keys(requestData).forEach((key) => {
|
|
70
|
+
const value = requestData[key];
|
|
71
|
+
if (Array.isArray(value)) {
|
|
72
|
+
value.forEach((item) => formData.append(key, item));
|
|
73
|
+
} else {
|
|
74
|
+
formData.append(key, value);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
xhr.open(method, action, true);
|
|
78
|
+
Object.keys(headers).forEach((key) => {
|
|
79
|
+
xhr.setRequestHeader(key, headers[key]);
|
|
80
|
+
});
|
|
81
|
+
if (timeout > 0) xhr.timeout = timeout;
|
|
82
|
+
xhr.ontimeout = () => {
|
|
83
|
+
finish({ status: "fail", error: "timeout", response: {} });
|
|
84
|
+
};
|
|
85
|
+
xhr.onerror = () => {
|
|
86
|
+
finish({ status: "fail", error: "error", response: {} });
|
|
87
|
+
};
|
|
88
|
+
if (xhr.upload) {
|
|
89
|
+
xhr.upload.onprogress = (event) => {
|
|
90
|
+
let realPercent = 0;
|
|
91
|
+
if (event.total > 0) realPercent = Math.round(event.loaded / event.total * 100);
|
|
92
|
+
percent = Math.max(realPercent, percent);
|
|
93
|
+
if (files[0]?.percent !== percent) {
|
|
94
|
+
files.forEach((file) => {
|
|
95
|
+
file.percent = percent;
|
|
96
|
+
});
|
|
97
|
+
onProgress?.({
|
|
98
|
+
e: event,
|
|
99
|
+
file: files[0],
|
|
100
|
+
currentFiles: files,
|
|
101
|
+
percent,
|
|
102
|
+
type: "real",
|
|
103
|
+
XMLHttpRequest: xhr
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
xhr.onload = () => {
|
|
109
|
+
const isFail = xhr.status < 200 || xhr.status >= 300;
|
|
110
|
+
const text = xhr.responseText || xhr.response;
|
|
111
|
+
if (isFail) {
|
|
112
|
+
finish({ status: "fail", error: "fail", response: {} });
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
let response = {};
|
|
116
|
+
try {
|
|
117
|
+
response = JSON.parse(text);
|
|
118
|
+
} catch {
|
|
119
|
+
response = text;
|
|
120
|
+
}
|
|
121
|
+
files.forEach((file) => {
|
|
122
|
+
file.percent = 100;
|
|
123
|
+
});
|
|
124
|
+
finish({ status: "success", response });
|
|
125
|
+
};
|
|
126
|
+
xhr.send(formData);
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
export {
|
|
130
|
+
calcUploadTimeout,
|
|
131
|
+
uploadByXhr
|
|
132
|
+
};
|
|
@@ -15,6 +15,7 @@ export interface QdUploadProps<F extends UploadFile = UploadFile, OR = unknown,
|
|
|
15
15
|
modelValue?: string | string[];
|
|
16
16
|
action?: string | ((bucketConfigKey?: string) => string);
|
|
17
17
|
bucketConfigKey?: string;
|
|
18
|
+
timeout?: number;
|
|
18
19
|
convStr?: boolean | string;
|
|
19
20
|
valueMode?: 'ossId' | 'url';
|
|
20
21
|
theme?: TdUploadProps['theme'] | 'btn-file-popup' | 'btn-image-popup';
|
package/dist/locales/en-US.d.ts
CHANGED
package/dist/locales/en-US.mjs
CHANGED
|
@@ -47,6 +47,7 @@ const enUS = merge(enUS$1, {
|
|
|
47
47
|
sameNameMessage: "Uploading files with the same name is not allowed",
|
|
48
48
|
fileSizeExceedsLimit: "File size exceeded limit, automatically filtered",
|
|
49
49
|
fileUploadFailed: "File upload failed",
|
|
50
|
+
fileUploadTimeout: "Upload timed out, please retry",
|
|
50
51
|
viewFileText: "View file"
|
|
51
52
|
},
|
|
52
53
|
chat: {
|
package/dist/locales/zh-CN.d.ts
CHANGED
package/dist/locales/zh-CN.mjs
CHANGED
package/dist/locales/zh-TW.d.ts
CHANGED
package/dist/locales/zh-TW.mjs
CHANGED
package/dist/utils/tools.d.ts
CHANGED
|
@@ -33,6 +33,11 @@ export declare function getTransformOffset(el?: HTMLElement | null, options?: {
|
|
|
33
33
|
}): {
|
|
34
34
|
x: number;
|
|
35
35
|
y: number;
|
|
36
|
+
node: HTMLElement;
|
|
37
|
+
} | {
|
|
38
|
+
x: number;
|
|
39
|
+
y: number;
|
|
40
|
+
node: null | undefined;
|
|
36
41
|
};
|
|
37
42
|
export declare const IMAGE_REGEXP: RegExp;
|
|
38
43
|
export declare function isImage(value: string): boolean;
|
package/dist/utils/tools.mjs
CHANGED
|
@@ -13,11 +13,11 @@ function getTransformOffset(el, options) {
|
|
|
13
13
|
while (node) {
|
|
14
14
|
if (getComputedStyle(node).transform !== "none" && !skip?.(node)) {
|
|
15
15
|
const { x, y } = node.getBoundingClientRect();
|
|
16
|
-
return { x, y };
|
|
16
|
+
return { x, y, node };
|
|
17
17
|
}
|
|
18
18
|
node = node.parentElement;
|
|
19
19
|
}
|
|
20
|
-
return { x: 0, y: 0 };
|
|
20
|
+
return { x: 0, y: 0, node };
|
|
21
21
|
}
|
|
22
22
|
const IMAGE_REGEXP = /(.png|.jpg|.jpeg|.jpe|.webp|.avif|.heic|.heif|.svg|.gif|.bmp)/i;
|
|
23
23
|
function isImage(value) {
|