@qynpm/ui 1.1.0 → 1.2.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.
@@ -0,0 +1,957 @@
1
+ import { ElUpload as ft, ElIcon as pt, ElPopover as mt, ElInput as vt, ElImageViewer as gt, ElDialog as yt } from "element-plus/es";
2
+ import { openBlock as m, createElementBlock as h, normalizeStyle as ht, normalizeClass as ge, createElementVNode as w, createVNode as _, createSlots as xt, withCtx as U, withModifiers as v, Fragment as Y, toDisplayString as z, createCommentVNode as x, renderSlot as bt, createBlock as _t, createTextVNode as $, ref as g, onMounted as Me, computed as V, watch as ee, toRaw as ye, nextTick as Ne, onBeforeUnmount as Ke } from "vue";
3
+ import { Delete as wt, ZoomIn as Ut, Document as kt, InfoFilled as Vt, Plus as Dt } from "@element-plus/icons-vue";
4
+ import { useFormDisabled as We, genFileId as he, ElLoading as Xe, ElMessage as k } from "element-plus";
5
+ import { a as Ft } from "./js.cookie-BA-dL3zT.mjs";
6
+ import { _ as Ct } from "./_plugin-vue_export-helper-CHgC5LLL.mjs";
7
+ const Tt = "Admin-Token";
8
+ function Ee(O = Tt) {
9
+ return Ft.get(O);
10
+ }
11
+ const qt = /* @__PURE__ */ Object.assign({
12
+ name: "QyUpload"
13
+ }, {
14
+ __name: "index",
15
+ props: {
16
+ /**
17
+ * 受控值。valueFormat 为 object 时结构为 { files, text },
18
+ * array 时为 string[],string 时为逗号分隔 URL。
19
+ */
20
+ modelValue: { type: [Object, Array, String], default: void 0 },
21
+ /** 已选择的浏览器本地文件,不与上传完成后的远程值混用。 */
22
+ selectedFiles: { type: Array, default: () => [] },
23
+ /** 是否在选择后立即上传;false 时只维护 selectedFiles。 */
24
+ autoUpload: { type: Boolean, default: !0 },
25
+ /** Qy 展示模式:media-card | attachment-card | file-list。 */
26
+ variant: { type: String, default: "media-card" },
27
+ /**
28
+ * 初始值,结构为 { files: '逗号分隔的URL', text: '文字内容' }
29
+ * 非受控模式,仅初始化时读取一次
30
+ */
31
+ defaultValue: { type: Object, default: () => ({ files: "", text: "" }) },
32
+ /** v-model 输出格式:object | array | string */
33
+ valueFormat: { type: String, default: "object" },
34
+ /** 是否显示底部文字备注区 */
35
+ showText: { type: Boolean, default: !0 },
36
+ /** 是否显示纯粘贴输入条,不保存文字,仅用于承接 Ctrl+V 图片 */
37
+ showPasteInput: { type: Boolean, default: !1 },
38
+ /** 文字区占位文案,也用于凭证上传的粘贴提示 */
39
+ pastePlaceholder: { type: String, default: "输入文字" },
40
+ /** 是否多选 */
41
+ multiple: { type: Boolean, default: !0 },
42
+ /** 是否禁用 */
43
+ disabled: { type: Boolean, default: void 0 },
44
+ /** 允许的文件类型后缀(如 ['jpg', 'mp4']) */
45
+ fileType: { type: Array, default: () => [] },
46
+ /** 单个文件大小限制(MB) */
47
+ fileSize: { type: Number, default: 10 },
48
+ /** 文件数量限制 */
49
+ limit: { type: Number, default: 9 },
50
+ /** 是否显示格式/大小提示 */
51
+ isShowTip: { type: Boolean, default: !1 },
52
+ /** 接口路径 */
53
+ api: { type: String, default: "/permission-api/common/uploads" },
54
+ /** FormData 中文件字段名 */
55
+ name: { type: String, default: "file" },
56
+ /** token 读取 key,对应 utils/auth 中的存储字段 */
57
+ tokenKey: { type: String, default: "Admin-Token" },
58
+ /** 是否支持视频模式(强制 limit=1) */
59
+ supportVideo: { type: Boolean, default: !1 },
60
+ /**
61
+ * 卡片尺寸
62
+ * 预设:'large'(160px) | 'default'(140px) | 'small'(80px)
63
+ * 自定义:任意 CSS 单位,如 '60px'、'8vw'
64
+ */
65
+ size: { type: String, default: "default" },
66
+ /** 禁用拖拽(默认在触发区开启) */
67
+ disableDrag: { type: Boolean, default: !1 },
68
+ /** 成功回调(用于复杂业务联动) */
69
+ callBack: { type: Function, default: null },
70
+ /** 上传时附加的额外 FormData 字段 */
71
+ extraData: { type: Object, default: () => ({}) },
72
+ /** 自定义上传请求,用于接入宿主项目 request / 鉴权 / baseURL。 */
73
+ uploadRequest: { type: Function, default: null }
74
+ },
75
+ emits: [
76
+ "update:modelValue",
77
+ "update:selectedFiles",
78
+ "selectedFilesChange",
79
+ "change",
80
+ "success",
81
+ "error",
82
+ "remove",
83
+ "invalid",
84
+ "preview"
85
+ ],
86
+ setup(O, { expose: o, emit: f }) {
87
+ const t = O, p = f, xe = g(null), D = g(null), X = g(null), r = g([]), E = g(null), te = g(null), q = /* @__PURE__ */ new Map(), L = /* @__PURE__ */ new WeakMap();
88
+ let u = Date.now(), R = !1;
89
+ const P = g(!1), ae = g([]), be = g(0), _e = g(!1), we = g(""), Ue = g(""), M = /* @__PURE__ */ new Set(), I = /* @__PURE__ */ new Map();
90
+ function N(e) {
91
+ M.delete(e) && URL.revokeObjectURL(e);
92
+ }
93
+ function ne() {
94
+ for (const e of M) N(e);
95
+ }
96
+ function K(e) {
97
+ const a = I.get(e);
98
+ a && (I.delete(e), a.close());
99
+ }
100
+ function le() {
101
+ for (const e of I.keys()) K(e);
102
+ }
103
+ function ie(e) {
104
+ var a;
105
+ (a = q.get(e)) == null || a();
106
+ }
107
+ function oe() {
108
+ for (const e of q.values()) e();
109
+ }
110
+ const H = g(!1), S = g(""), He = g(!1);
111
+ Me(() => {
112
+ t.modelValue !== void 0 || !t.autoUpload || se(t.defaultValue);
113
+ });
114
+ const Ze = V(() => ({ large: "160px", default: "140px", small: "80px" })[t.size] ?? t.size), F = We(), Je = V(
115
+ () => r.value.some((e) => e.status === "uploading")
116
+ ), Qe = V(
117
+ () => t.variant === "file-list" || t.supportVideo ? "text" : "picture-card"
118
+ ), ke = V(() => t.supportVideo ? 1 : !t.autoUpload && !t.multiple ? 2 : t.limit), Ge = V(
119
+ () => {
120
+ var e;
121
+ return t.isShowTip && (t.fileSize || ((e = C.value) == null ? void 0 : e.length));
122
+ }
123
+ ), C = V(() => {
124
+ var e;
125
+ return (e = t.fileType) != null && e.length ? t.fileType.map((a) => String(a).trim().replace(/^\./, "").toLowerCase()).filter(Boolean) : t.variant === "file-list" ? [] : t.supportVideo ? ["mp4", "mov", "avi"] : ["jpg", "jpeg", "png", "gif", "webp"];
126
+ }), Z = V(() => {
127
+ if (!t.autoUpload && !t.multiple) return !1;
128
+ const e = t.supportVideo ? 1 : t.limit;
129
+ return r.value.length >= e;
130
+ }), Ye = V(
131
+ () => C.value.map((e) => `.${e}`).join(",")
132
+ ), $e = V(() => ({
133
+ "qy-upload--attachment-card": t.variant === "attachment-card",
134
+ "qy-upload--reached-limit": Z.value,
135
+ "qy-upload--disabled": F.value,
136
+ "qy-upload--video": t.supportVideo,
137
+ "qy-upload--without-text": !t.showText && !t.showPasteInput
138
+ }));
139
+ ee(S, () => {
140
+ R || j();
141
+ }), ee(
142
+ () => t.modelValue,
143
+ (e) => {
144
+ t.autoUpload && e !== void 0 && se(e);
145
+ },
146
+ { immediate: !0, deep: !0 }
147
+ ), ee(
148
+ () => [t.autoUpload, t.selectedFiles],
149
+ ([e, a]) => {
150
+ e || (r.value = B(a));
151
+ },
152
+ { immediate: !0, deep: !0 }
153
+ );
154
+ function re(e) {
155
+ return Array.isArray(e) ? e.filter(Boolean) : e ? String(e).split(",").filter(Boolean) : [];
156
+ }
157
+ function Ve(e) {
158
+ return Array.isArray(e) ? { files: e, text: "" } : typeof e == "string" ? { files: re(e), text: "" } : e && typeof e == "object" ? {
159
+ files: re(e.files),
160
+ text: e.text ?? ""
161
+ } : { files: [], text: "" };
162
+ }
163
+ function De(e = []) {
164
+ return e.map((a, n) => ({
165
+ name: (t.variant === "attachment-card" ? String(a).split(/[?#]/, 1)[0] : String(a)).split("/").pop() || `file-${n}`,
166
+ url: a,
167
+ status: "success",
168
+ uid: he()
169
+ }));
170
+ }
171
+ function B(e = []) {
172
+ return e.filter(Boolean).map((a, n) => {
173
+ const l = ye(a);
174
+ return {
175
+ name: l.name,
176
+ raw: l,
177
+ status: "ready",
178
+ uid: Fe(l, n)
179
+ };
180
+ });
181
+ }
182
+ function Fe(e, a) {
183
+ if (e.uid != null) return e.uid;
184
+ const n = L.get(e);
185
+ return n ?? (u += a + 1, L.set(e, u), u);
186
+ }
187
+ function J(e = r.value) {
188
+ return e.map((a) => {
189
+ const n = a.raw ?? (a instanceof File ? a : null);
190
+ return n ? ye(n) : null;
191
+ }).filter(Boolean);
192
+ }
193
+ function W(e) {
194
+ p("update:selectedFiles", e), p("selectedFilesChange", e);
195
+ }
196
+ function et(e, a) {
197
+ if (t.autoUpload) return;
198
+ const n = e == null ? void 0 : e.raw;
199
+ if (n && !Q(n)) {
200
+ r.value = B(t.selectedFiles);
201
+ return;
202
+ }
203
+ const l = J(a);
204
+ n && !l.includes(n) && l.push(n);
205
+ const i = t.multiple ? l : l.slice(-1);
206
+ r.value = B(i), W(i);
207
+ }
208
+ function Ce(e) {
209
+ const a = new Set(e.map((l) => l.url)), n = r.value.filter(
210
+ (l) => (l.status === "ready" || l.status === "uploading") && !a.has(l.url)
211
+ );
212
+ return [...e, ...n];
213
+ }
214
+ function se(e) {
215
+ const a = Ve(e);
216
+ R = !0, S.value = a.text, r.value = Ce(De(a.files)), Ne(() => {
217
+ R = !1;
218
+ });
219
+ }
220
+ function ue(e) {
221
+ return t.valueFormat === "array" ? e.files : t.valueFormat === "string" ? e.files.join(",") : e;
222
+ }
223
+ function tt() {
224
+ var e;
225
+ (e = E.value) == null || e.focus();
226
+ }
227
+ function at(e) {
228
+ e.target.value = "";
229
+ }
230
+ function j(e) {
231
+ const l = { files: (e ?? r.value).filter((i) => i.status === "success" && i.url).map((i) => i.url), text: S.value };
232
+ p("update:modelValue", ue(l)), p("change", l), t.callBack && t.callBack(l);
233
+ }
234
+ function nt(e, a) {
235
+ if (K(e.uid), ie(e.uid), N(e.url), !t.autoUpload) {
236
+ const n = J(a);
237
+ r.value = B(n), W(n), p("remove", e, a);
238
+ return;
239
+ }
240
+ j(a), p("remove", e, a);
241
+ }
242
+ function de(e) {
243
+ var n;
244
+ const a = (e == null ? void 0 : e.name) || "";
245
+ return a.includes(".") && ((n = a.split(".").pop()) == null ? void 0 : n.toLowerCase()) || "";
246
+ }
247
+ function ce(e) {
248
+ var i, s, d;
249
+ const a = ((s = (i = e == null ? void 0 : e.type) == null ? void 0 : i.toLowerCase) == null ? void 0 : s.call(i)) || "", n = {
250
+ "image/jpeg": ["jpg", "jpeg"],
251
+ "image/png": ["png"],
252
+ "image/gif": ["gif"],
253
+ "image/bmp": ["bmp"],
254
+ "image/webp": ["webp"],
255
+ "video/mp4": ["mp4"],
256
+ "video/quicktime": ["mov"],
257
+ "video/x-msvideo": ["avi"],
258
+ "video/webm": ["webm"]
259
+ };
260
+ if (n[a]) return n[a];
261
+ const l = (d = a.split("/")[1]) == null ? void 0 : d.split("+")[0];
262
+ return l ? [l] : [];
263
+ }
264
+ function Te(e) {
265
+ if (!C.value.length) return !0;
266
+ const a = de(e);
267
+ if (t.variant === "attachment-card") return C.value.includes(a);
268
+ const n = ce(e);
269
+ return [a, ...n].some(
270
+ (l) => C.value.includes(l)
271
+ );
272
+ }
273
+ function Q(e) {
274
+ if (t.fileSize > 0 && e.size > t.fileSize * 1024 * 1024) {
275
+ const n = {
276
+ code: "size",
277
+ file: e,
278
+ message: `文件大小不能超过${t.fileSize}M`
279
+ };
280
+ return k.warning(n.message), p("invalid", n), !1;
281
+ }
282
+ if (!Te(e)) {
283
+ const n = {
284
+ code: "extension",
285
+ file: e,
286
+ message: `格式不支持,仅允许: ${C.value.join("/")}`
287
+ };
288
+ return k.warning(n.message), p("invalid", n), !1;
289
+ }
290
+ return !0;
291
+ }
292
+ async function qe(e, a, n, l, i) {
293
+ const s = fe(e), d = { close: () => l.close() };
294
+ I.set(i, d);
295
+ const b = () => I.get(i) === d;
296
+ try {
297
+ const c = await t.uploadRequest({
298
+ file: e,
299
+ formData: s,
300
+ api: t.api,
301
+ name: t.name,
302
+ tokenKey: t.tokenKey,
303
+ extraData: t.extraData
304
+ });
305
+ if (!b()) return;
306
+ const A = Re(c);
307
+ if (!A) {
308
+ const T = new Error("上传失败,未返回文件地址");
309
+ k.error(T.message), p("error", T), n == null || n(T);
310
+ return;
311
+ }
312
+ k.success("上传成功"), a == null || a({ ...typeof c == "object" && c ? c : {}, url: A });
313
+ } catch (c) {
314
+ if (!b()) return;
315
+ k.error("上传失败"), p("error", c), n == null || n(c);
316
+ } finally {
317
+ b() && K(i);
318
+ }
319
+ }
320
+ function fe(e) {
321
+ const a = new FormData();
322
+ return a.append(t.name, e), t.extraData && Object.entries(t.extraData).forEach(([n, l]) => a.append(n, l)), a;
323
+ }
324
+ function Re(e) {
325
+ var l, i;
326
+ if (typeof e == "string") return e;
327
+ const a = e || {}, n = a.urls ?? a.url ?? ((l = a.data) == null ? void 0 : l.urls) ?? ((i = a.data) == null ? void 0 : i.url) ?? "";
328
+ return Array.isArray(n) ? n[0] || "" : n || "";
329
+ }
330
+ function pe(e, a, n, l, i = e.uid) {
331
+ const s = Xe.service({
332
+ target: D.value,
333
+ text: "上传中",
334
+ background: "rgba(255,255,255,0.7)"
335
+ });
336
+ if (t.uploadRequest) {
337
+ qe(e, n, l, s, i);
338
+ return;
339
+ }
340
+ const d = t.api.startsWith("http") ? t.api : window.location.origin + t.api.replace(/^([^/])/, "/$1"), b = fe(e), c = new XMLHttpRequest();
341
+ let A = !1;
342
+ const T = () => A ? !1 : (A = !0, q.delete(i), s.close(), !0);
343
+ q.set(i, () => {
344
+ T() && c.abort();
345
+ }), c.onabort = T, c.open("POST", d);
346
+ const Oe = Ee(t.tokenKey);
347
+ Oe && c.setRequestHeader("Authorization", `Bearer ${Oe}`), c.upload.onprogress = (y) => {
348
+ !A && y.total > 0 && (a == null || a({ percent: y.loaded / y.total * 100 }));
349
+ }, c.onload = () => {
350
+ if (T()) {
351
+ if (c.status < 200 || c.status >= 300) {
352
+ const y = `上传失败 (HTTP ${c.status})`;
353
+ k.error(y), p("error", { msg: y, status: c.status }), l == null || l(new Error(y));
354
+ return;
355
+ }
356
+ try {
357
+ const y = JSON.parse(c.responseText);
358
+ y.code === 200 && y.urls ? (k.success("上传成功"), n == null || n({ ...y, url: y.urls })) : (k.error(y.msg || "上传失败"), p("error", y), l == null || l(y));
359
+ } catch {
360
+ k.error("上传失败,响应格式错误"), p("error", new Error("Response parse error")), l == null || l(new Error("Response parse error"));
361
+ }
362
+ }
363
+ }, c.onerror = () => {
364
+ T() && (k.error("上传失败,网络异常"), p("error", new Error("Network error")), l == null || l(new Error("Network error")));
365
+ }, c.send(b);
366
+ }
367
+ function Se(e) {
368
+ return F.value ? !1 : Q(e);
369
+ }
370
+ function Le(e, a) {
371
+ const n = r.value.find(
372
+ (l) => {
373
+ var i;
374
+ return l.uid === (e == null ? void 0 : e.uid) || ((i = l.raw) == null ? void 0 : i.uid) === (e == null ? void 0 : e.uid);
375
+ }
376
+ );
377
+ n && (n.url = a, n.status = "success");
378
+ }
379
+ function lt(e) {
380
+ pe(
381
+ e.file,
382
+ e.onProgress,
383
+ (a) => {
384
+ Le(e.file, a.url), e.onSuccess(a), j(), p("success", a);
385
+ },
386
+ (a) => e.onError(a)
387
+ );
388
+ }
389
+ function me(e) {
390
+ var n;
391
+ const a = ((n = e.name) == null ? void 0 : n.split(/[?#]/, 1)[0]) || "";
392
+ try {
393
+ return decodeURIComponent(a);
394
+ } catch {
395
+ return a;
396
+ }
397
+ }
398
+ function ve(e) {
399
+ return /\.(?:jpe?g|png|gif|bmp|webp|avif|svg|ico)$/i.test(me(e));
400
+ }
401
+ function it(e) {
402
+ var i;
403
+ if (!e.url) return;
404
+ const a = t.variant === "attachment-card";
405
+ if (a && !ve(e)) {
406
+ p("preview", { url: e.url, name: me(e) });
407
+ return;
408
+ }
409
+ const n = ((i = e.url.split(".").pop()) == null ? void 0 : i.toLowerCase()) || "";
410
+ if (["mp4", "mov", "avi", "webm"].includes(n)) {
411
+ we.value = e.url, Ue.value = e.name || "视频预览", _e.value = !0;
412
+ return;
413
+ }
414
+ const l = r.value.filter(
415
+ (s) => {
416
+ var d;
417
+ return s.status === "success" && s.url && (a ? ve(s) : !["mp4", "mov", "avi", "webm"].includes((d = s.url.split(".").pop()) == null ? void 0 : d.toLowerCase()));
418
+ }
419
+ );
420
+ ae.value = l.map((s) => s.url), be.value = l.findIndex((s) => s.uid === e.uid) || 0, P.value = !0;
421
+ }
422
+ function ot() {
423
+ P.value = !1, ae.value = [];
424
+ }
425
+ function Pe(e, a) {
426
+ if (e.name && de(e)) return e;
427
+ const n = ce(e).find(
428
+ (l) => C.value.includes(l)
429
+ );
430
+ return n ? new File([e], `paste-${Date.now() + a}.${n}`, {
431
+ type: e.type,
432
+ lastModified: e.lastModified
433
+ }) : e;
434
+ }
435
+ function G(e) {
436
+ if (!t.autoUpload) {
437
+ const a = J(), n = e.filter((i) => Q(i));
438
+ if (!n.length) return;
439
+ const l = t.multiple ? [...a, ...n].slice(0, t.limit) : n.slice(-1);
440
+ r.value = B(l), W(l);
441
+ return;
442
+ }
443
+ for (let a = 0; a < e.length && !(r.value.length >= ke.value); a++) {
444
+ const n = Pe(e[a], a);
445
+ if (!Se(n)) continue;
446
+ const l = he(), i = URL.createObjectURL(n);
447
+ M.add(i), r.value.push({
448
+ uid: l,
449
+ name: n.name || `file-${l}`,
450
+ status: "uploading",
451
+ percentage: 0,
452
+ url: i
453
+ }), pe(
454
+ n,
455
+ (s) => {
456
+ const d = r.value.find((b) => b.uid === l);
457
+ d && (d.percentage = s.percent);
458
+ },
459
+ (s) => {
460
+ const d = r.value.find((b) => b.uid === l);
461
+ d && (d.url !== s.url && N(d.url), d.status = "success", d.url = s.url, j(), p("success", s));
462
+ },
463
+ () => Be(l),
464
+ l
465
+ );
466
+ }
467
+ }
468
+ function rt(e) {
469
+ const a = e.target, n = Array.from(a.files || []);
470
+ if (a.value = "", F.value || !n.length) return;
471
+ const l = t.supportVideo || !t.multiple ? n.slice(0, 1) : n;
472
+ G(l);
473
+ }
474
+ function Ie(e) {
475
+ const a = Array.from((e == null ? void 0 : e.files) || []).filter(
476
+ (s) => {
477
+ var d;
478
+ return (d = s.type) == null ? void 0 : d.startsWith("image/");
479
+ }
480
+ );
481
+ if (a.length) return a;
482
+ const n = e == null ? void 0 : e.items;
483
+ if (!n) return [];
484
+ const l = [], i = /* @__PURE__ */ new Set();
485
+ for (let s = 0; s < n.length; s++) {
486
+ const d = n[s];
487
+ if (d.kind === "file" && d.type.startsWith("image/")) {
488
+ const b = d.getAsFile();
489
+ b && !i.has(b) && (i.add(b), l.push(b));
490
+ }
491
+ }
492
+ return l;
493
+ }
494
+ function st(e) {
495
+ if (F.value) return;
496
+ const a = Ie(e.clipboardData);
497
+ a.length && (e.preventDefault(), G(a));
498
+ }
499
+ function ut() {
500
+ F.value || t.disableDrag || (H.value = !0);
501
+ }
502
+ function dt() {
503
+ H.value = !1;
504
+ }
505
+ function ct(e) {
506
+ var n;
507
+ if (H.value = !1, F.value || t.disableDrag || Z.value) return;
508
+ const a = Array.from(((n = e.dataTransfer) == null ? void 0 : n.files) || []);
509
+ a.length && G(a);
510
+ }
511
+ function Be(e) {
512
+ K(e), ie(e);
513
+ const a = r.value.findIndex((n) => n.uid === e);
514
+ a !== -1 && (N(r.value[a].url), r.value.splice(a, 1));
515
+ }
516
+ Ke(() => {
517
+ le(), oe(), ne();
518
+ });
519
+ function je() {
520
+ var e;
521
+ F.value || Z.value || (e = X.value) == null || e.click();
522
+ }
523
+ function Ae() {
524
+ var e;
525
+ le(), oe();
526
+ for (const a of r.value)
527
+ (e = a.url) != null && e.startsWith("blob:") && M.add(a.url);
528
+ ne(), r.value = [], S.value = "", W([]), t.autoUpload && j();
529
+ }
530
+ o({
531
+ /** 主动打开文件选择框,供表单或快捷操作调用 */
532
+ openFileDialog: je,
533
+ /** 获取已上传成功的文件 URL 列表 */
534
+ getPathList: () => r.value.filter((e) => e.status === "success").map((e) => e.url),
535
+ /** 清空文件和文字,并同步 change 事件 */
536
+ clearFiles: Ae,
537
+ /** 获取完整值,结构与 change 事件保持一致 */
538
+ getValue: () => ({
539
+ files: r.value.filter((e) => e.status === "success" && e.url).map((e) => e.url),
540
+ text: S.value
541
+ }),
542
+ /** 获取按 valueFormat 输出的值,便于外部不走 v-model 时读取 */
543
+ getModelValue: () => ue({
544
+ files: r.value.filter((e) => e.status === "success" && e.url).map((e) => e.url),
545
+ text: S.value
546
+ })
547
+ });
548
+ const ze = { props: t, emit: p, uploadRef: xe, rootRef: D, nativeInputRef: X, fileList: r, inputRef: E, pasteInputRef: te, pendingXhrs: q, selectedFileUids: L, get selectedFileUid() {
549
+ return u;
550
+ }, set selectedFileUid(e) {
551
+ u = e;
552
+ }, get syncingFromValue() {
553
+ return R;
554
+ }, set syncingFromValue(e) {
555
+ R = e;
556
+ }, viewerVisible: P, viewerUrlList: ae, viewerIndex: be, videoVisible: _e, videoUrl: we, videoTitle: Ue, objectUrls: M, pendingCustomUploads: I, releaseObjectUrl: N, releaseObjectUrls: ne, cancelCustomUpload: K, cancelCustomUploads: le, cancelXhr: ie, cancelXhrs: oe, isDragOver: H, localText: S, textExpanded: He, sizeValue: Ze, isUploadDisabled: F, isUploading: Je, uploadListType: Qe, effectiveLimit: ke, shouldShowTip: Ge, allowedExtensions: C, isReachedLimit: Z, acceptAttr: Ye, uploadClasses: $e, normalizeFilesInput: re, parseValue: Ve, createFileList: De, createSelectedFileList: B, getSelectedFileUid: Fe, getSelectedRawFiles: J, emitSelectedFiles: W, handleFileChange: et, mergePendingFileList: Ce, syncValueToState: se, formatModelValue: ue, focusTextarea: tt, clearPasteInput: at, handleSyncValue: j, handleRemove: nt, getFileNameExtension: de, getMimeExtensions: ce, isAllowedFileType: Te, validateFile: Q, uploadViaCustomRequest: qe, createUploadFormData: fe, resolveUploadUrl: Re, uploadViaXhr: pe, handleBeforeUpload: Se, applyUploadResultToFile: Le, handleCustomUpload: lt, attachmentName: me, isAttachmentImage: ve, handlePreview: it, closeViewer: ot, createNamedPasteFile: Pe, uploadFiles: G, handleNativeInputChange: rt, collectImageFilesFromClipboard: Ie, handlePaste: st, handleDragOver: ut, handleDragLeave: dt, handleDrop: ct, handleRemoveByUid: Be, openFileDialog: je, clearFiles: Ae, ref: g, computed: V, watch: ee, onMounted: Me, onBeforeUnmount: Ke, nextTick: Ne, toRaw: ye, get Plus() {
557
+ return Dt;
558
+ }, get InfoFilled() {
559
+ return Vt;
560
+ }, get Document() {
561
+ return kt;
562
+ }, get ZoomIn() {
563
+ return Ut;
564
+ }, get Delete() {
565
+ return wt;
566
+ }, get ElMessage() {
567
+ return k;
568
+ }, get ElLoading() {
569
+ return Xe;
570
+ }, get genFileId() {
571
+ return he;
572
+ }, get useFormDisabled() {
573
+ return We;
574
+ }, get getToken() {
575
+ return Ee;
576
+ } };
577
+ return Object.defineProperty(ze, "__isScriptSetup", { enumerable: !1, value: !0 }), ze;
578
+ }
579
+ }), Rt = ["accept", "multiple", "disabled"], St = { class: "qy-upload__attachment" }, Lt = ["src", "alt"], Pt = ["title"], It = {
580
+ key: 2,
581
+ class: "qy-upload__attachment-progress",
582
+ role: "status"
583
+ }, Bt = {
584
+ key: 3,
585
+ class: "qy-upload__attachment-actions"
586
+ }, jt = ["onClick"], At = ["onClick"], zt = ["disabled"], Ot = { class: "qy-upload__hint" }, Mt = ["placeholder", "disabled"], Nt = ["src"], Kt = {
587
+ key: 1,
588
+ class: "qy-upload__tip"
589
+ }, Wt = { class: "error" }, Xt = { class: "error" };
590
+ function Et(O, o, f, t, p, xe) {
591
+ var L;
592
+ const D = pt, X = vt, r = mt, E = ft, te = gt, q = yt;
593
+ return m(), h(
594
+ "div",
595
+ {
596
+ ref: "rootRef",
597
+ class: ge(["qy-upload", t.uploadClasses]),
598
+ style: ht({ "--qy-upload-size": t.sizeValue })
599
+ },
600
+ [
601
+ w("input", {
602
+ ref: "nativeInputRef",
603
+ class: "qy-upload__native-input",
604
+ type: "file",
605
+ accept: t.acceptAttr,
606
+ multiple: f.supportVideo ? !1 : f.multiple,
607
+ disabled: t.isUploadDisabled,
608
+ onChange: t.handleNativeInputChange
609
+ }, null, 40, Rt),
610
+ _(E, {
611
+ ref: "uploadRef",
612
+ "file-list": t.fileList,
613
+ "onUpdate:fileList": o[7] || (o[7] = (u) => t.fileList = u),
614
+ action: "#",
615
+ multiple: f.supportVideo ? !1 : f.multiple,
616
+ limit: t.effectiveLimit,
617
+ "auto-upload": f.autoUpload,
618
+ "list-type": t.uploadListType,
619
+ accept: t.acceptAttr,
620
+ disabled: t.isUploadDisabled,
621
+ "http-request": t.handleCustomUpload,
622
+ "before-upload": t.handleBeforeUpload,
623
+ "on-change": t.handleFileChange,
624
+ "on-preview": t.handlePreview,
625
+ "on-remove": t.handleRemove
626
+ }, xt({
627
+ default: U(() => [
628
+ f.variant !== "file-list" && !t.isReachedLimit ? (m(), h(
629
+ "div",
630
+ {
631
+ key: 0,
632
+ class: ge(["qy-upload__trigger", { "is-dragover": t.isDragOver }]),
633
+ onPaste: t.handlePaste,
634
+ onDragover: v(t.handleDragOver, ["prevent"]),
635
+ onDragleave: v(t.handleDragLeave, ["prevent"]),
636
+ onDrop: v(t.handleDrop, ["prevent"])
637
+ },
638
+ [
639
+ _(D, { class: "qy-upload__icon" }, {
640
+ default: U(() => [
641
+ _(t.Plus)
642
+ ]),
643
+ _: 1
644
+ /* STABLE */
645
+ }),
646
+ f.supportVideo ? (m(), h(
647
+ Y,
648
+ { key: 0 },
649
+ [
650
+ o[10] || (o[10] = w(
651
+ "span",
652
+ { class: "qy-upload__label" },
653
+ "点击上传视频",
654
+ -1
655
+ /* CACHED */
656
+ )),
657
+ w(
658
+ "span",
659
+ Ot,
660
+ "支持 " + z(t.allowedExtensions.join(" / ")) + ",不超过 " + z(f.fileSize) + "MB",
661
+ 1
662
+ /* TEXT */
663
+ )
664
+ ],
665
+ 64
666
+ /* STABLE_FRAGMENT */
667
+ )) : x("v-if", !0),
668
+ x(" 文字输入框:可通过 showText 关闭,凭证上传这类纯图片场景不需要展示 "),
669
+ f.showText ? (m(), h(
670
+ "div",
671
+ {
672
+ key: 1,
673
+ class: "qy-upload__text",
674
+ onClick: o[4] || (o[4] = v(() => {
675
+ }, ["stop"])),
676
+ onPaste: v(t.handlePaste, ["stop"])
677
+ },
678
+ [
679
+ _(r, {
680
+ visible: t.textExpanded,
681
+ "onUpdate:visible": o[3] || (o[3] = (u) => t.textExpanded = u),
682
+ placement: "bottom-start",
683
+ width: 220,
684
+ trigger: "click",
685
+ "popper-class": "qy-upload__text-popover",
686
+ onAfterEnter: t.focusTextarea
687
+ }, {
688
+ reference: U(() => [
689
+ w(
690
+ "div",
691
+ {
692
+ class: ge(["qy-upload__text-preview", { "is-placeholder": !t.localText }])
693
+ },
694
+ z(t.localText || f.pastePlaceholder),
695
+ 3
696
+ /* TEXT, CLASS */
697
+ )
698
+ ]),
699
+ default: U(() => [
700
+ _(X, {
701
+ ref: "inputRef",
702
+ modelValue: t.localText,
703
+ "onUpdate:modelValue": o[1] || (o[1] = (u) => t.localText = u),
704
+ type: "textarea",
705
+ autosize: { minRows: 2, maxRows: 5 },
706
+ placeholder: f.pastePlaceholder,
707
+ disabled: t.isUploadDisabled,
708
+ onBlur: o[2] || (o[2] = (u) => t.textExpanded = !1),
709
+ onPaste: v(t.handlePaste, ["stop"])
710
+ }, null, 8, ["modelValue", "placeholder", "disabled"])
711
+ ]),
712
+ _: 1
713
+ /* STABLE */
714
+ }, 8, ["visible"])
715
+ ],
716
+ 32
717
+ /* NEED_HYDRATION */
718
+ )) : f.showPasteInput ? (m(), h(
719
+ Y,
720
+ { key: 2 },
721
+ [
722
+ x(" 纯粘贴入口:不保存文字,只提供一个可聚焦区域承接 Ctrl+V 图片 "),
723
+ w(
724
+ "div",
725
+ {
726
+ class: "qy-upload__text",
727
+ onClick: o[6] || (o[6] = v(() => {
728
+ }, ["stop"])),
729
+ onPaste: v(t.handlePaste, ["stop"])
730
+ },
731
+ [
732
+ w("input", {
733
+ ref: "pasteInputRef",
734
+ class: "qy-upload__paste-input",
735
+ placeholder: f.pastePlaceholder,
736
+ disabled: t.isUploadDisabled,
737
+ onPaste: v(t.handlePaste, ["stop"]),
738
+ onInput: t.clearPasteInput,
739
+ onClick: o[5] || (o[5] = v(() => {
740
+ }, ["stop"]))
741
+ }, null, 40, Mt)
742
+ ],
743
+ 32
744
+ /* NEED_HYDRATION */
745
+ )
746
+ ],
747
+ 2112
748
+ /* STABLE_FRAGMENT, DEV_ROOT_FRAGMENT */
749
+ )) : x("v-if", !0)
750
+ ],
751
+ 34
752
+ /* CLASS, NEED_HYDRATION */
753
+ )) : x("v-if", !0)
754
+ ]),
755
+ _: 2
756
+ /* DYNAMIC */
757
+ }, [
758
+ f.variant === "attachment-card" ? {
759
+ name: "file",
760
+ fn: U(({ file: u }) => [
761
+ w("div", St, [
762
+ t.isAttachmentImage(u) && u.url ? (m(), h("img", {
763
+ key: 0,
764
+ class: "qy-upload__attachment-image",
765
+ src: u.url,
766
+ alt: t.attachmentName(u)
767
+ }, null, 8, Lt)) : (m(), h("div", {
768
+ key: 1,
769
+ class: "qy-upload__attachment-file",
770
+ title: t.attachmentName(u)
771
+ }, [
772
+ _(D, null, {
773
+ default: U(() => [
774
+ _(t.Document)
775
+ ]),
776
+ _: 1
777
+ /* STABLE */
778
+ }),
779
+ w(
780
+ "span",
781
+ null,
782
+ z(t.attachmentName(u)),
783
+ 1
784
+ /* TEXT */
785
+ )
786
+ ], 8, Pt)),
787
+ u.status === "uploading" ? (m(), h("span", It, "上传中")) : x("v-if", !0),
788
+ u.status === "success" || !t.isUploadDisabled ? (m(), h("div", Bt, [
789
+ u.status === "success" ? (m(), h("button", {
790
+ key: 0,
791
+ type: "button",
792
+ "aria-label": "预览附件",
793
+ onClick: v((R) => t.handlePreview(u), ["stop"])
794
+ }, [
795
+ _(D, null, {
796
+ default: U(() => [
797
+ _(t.ZoomIn)
798
+ ]),
799
+ _: 1
800
+ /* STABLE */
801
+ })
802
+ ], 8, jt)) : x("v-if", !0),
803
+ t.isUploadDisabled ? x("v-if", !0) : (m(), h("button", {
804
+ key: 1,
805
+ type: "button",
806
+ "aria-label": "删除附件",
807
+ onClick: v((R) => {
808
+ var P;
809
+ return (P = t.uploadRef) == null ? void 0 : P.handleRemove(u);
810
+ }, ["stop"])
811
+ }, [
812
+ _(D, null, {
813
+ default: U(() => [
814
+ _(t.Delete)
815
+ ]),
816
+ _: 1
817
+ /* STABLE */
818
+ })
819
+ ], 8, At))
820
+ ])) : x("v-if", !0)
821
+ ])
822
+ ]),
823
+ key: "0"
824
+ } : void 0,
825
+ f.variant === "file-list" ? {
826
+ name: "trigger",
827
+ fn: U(() => [
828
+ w(
829
+ "div",
830
+ {
831
+ class: "qy-upload__file-trigger",
832
+ onClick: o[0] || (o[0] = v(() => {
833
+ }, ["stop"])),
834
+ onDragover: v(t.handleDragOver, ["prevent"]),
835
+ onDragleave: v(t.handleDragLeave, ["prevent"]),
836
+ onDrop: v(t.handleDrop, ["prevent"])
837
+ },
838
+ [
839
+ bt(O.$slots, "trigger", {
840
+ open: t.openFileDialog,
841
+ disabled: t.isUploadDisabled,
842
+ uploading: t.isUploading
843
+ }, () => [
844
+ w("button", {
845
+ class: "qy-upload__file-button",
846
+ type: "button",
847
+ disabled: t.isUploadDisabled,
848
+ onClick: t.openFileDialog
849
+ }, " 选择文件 ", 8, zt)
850
+ ], !0)
851
+ ],
852
+ 32
853
+ /* NEED_HYDRATION */
854
+ )
855
+ ]),
856
+ key: "1"
857
+ } : void 0
858
+ ]), 1032, ["file-list", "multiple", "limit", "auto-upload", "list-type", "accept", "disabled"]),
859
+ t.viewerVisible ? (m(), _t(te, {
860
+ key: 0,
861
+ teleported: f.variant === "attachment-card",
862
+ "url-list": t.viewerUrlList,
863
+ "initial-index": t.viewerIndex,
864
+ onClose: t.closeViewer
865
+ }, null, 8, ["teleported", "url-list", "initial-index"])) : x("v-if", !0),
866
+ x(" 视频预览弹窗 "),
867
+ _(q, {
868
+ modelValue: t.videoVisible,
869
+ "onUpdate:modelValue": o[8] || (o[8] = (u) => t.videoVisible = u),
870
+ title: t.videoTitle,
871
+ width: "640px",
872
+ "append-to-body": "",
873
+ "destroy-on-close": "",
874
+ onClose: o[9] || (o[9] = (u) => t.videoVisible = !1)
875
+ }, {
876
+ default: U(() => [
877
+ t.videoVisible ? (m(), h("video", {
878
+ key: 0,
879
+ src: t.videoUrl,
880
+ controls: "",
881
+ autoplay: "",
882
+ style: { width: "100%", "max-height": "400px", "border-radius": "4px" }
883
+ }, null, 8, Nt)) : x("v-if", !0)
884
+ ]),
885
+ _: 1
886
+ /* STABLE */
887
+ }, 8, ["modelValue", "title"]),
888
+ t.shouldShowTip ? (m(), h("div", Kt, [
889
+ _(D, null, {
890
+ default: U(() => [
891
+ _(t.InfoFilled)
892
+ ]),
893
+ _: 1
894
+ /* STABLE */
895
+ }),
896
+ w("span", null, [
897
+ o[13] || (o[13] = $(
898
+ " 请上传 ",
899
+ -1
900
+ /* CACHED */
901
+ )),
902
+ f.fileSize ? (m(), h(
903
+ Y,
904
+ { key: 0 },
905
+ [
906
+ o[11] || (o[11] = $(
907
+ "大小不超过 ",
908
+ -1
909
+ /* CACHED */
910
+ )),
911
+ w(
912
+ "b",
913
+ Wt,
914
+ z(f.fileSize) + "MB",
915
+ 1
916
+ /* TEXT */
917
+ )
918
+ ],
919
+ 64
920
+ /* STABLE_FRAGMENT */
921
+ )) : x("v-if", !0),
922
+ (L = t.allowedExtensions) != null && L.length ? (m(), h(
923
+ Y,
924
+ { key: 1 },
925
+ [
926
+ o[12] || (o[12] = $(
927
+ ",格式为 ",
928
+ -1
929
+ /* CACHED */
930
+ )),
931
+ w(
932
+ "b",
933
+ Xt,
934
+ z(t.allowedExtensions.join("/")),
935
+ 1
936
+ /* TEXT */
937
+ )
938
+ ],
939
+ 64
940
+ /* STABLE_FRAGMENT */
941
+ )) : x("v-if", !0),
942
+ o[14] || (o[14] = $(
943
+ " 的文件。 ",
944
+ -1
945
+ /* CACHED */
946
+ ))
947
+ ])
948
+ ])) : x("v-if", !0)
949
+ ],
950
+ 6
951
+ /* CLASS, STYLE */
952
+ );
953
+ }
954
+ const $t = /* @__PURE__ */ Ct(qt, [["render", Et], ["__scopeId", "data-v-61da1df2"], ["__file", "/home/runner/work/qy-component/qy-component/packages/ui/lib/upload/index.vue"]]);
955
+ export {
956
+ $t as U
957
+ };