yd-admin 0.1.4 → 0.1.7

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.js CHANGED
@@ -1,18 +1,8 @@
1
- import { Fragment, Teleport, Transition, computed, createApp, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, h, inject, isRef, mergeProps, nextTick, normalizeClass, normalizeStyle, onMounted, onUnmounted, openBlock, provide, reactive, ref, renderList, renderSlot, resolveComponent, resolveDynamicComponent, toDisplayString, unref, useSlots, vModelCheckbox, vModelDynamic, vModelText, watch, withCtx, withDirectives, withKeys, withModifiers } from "vue";
1
+ import { t as __exportAll } from "./chunk-pbuEa-1d.js";
2
+ import { Fragment, Teleport, Transition, computed, createApp, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, getCurrentInstance, h, inject, isRef, mergeProps, nextTick, normalizeClass, normalizeStyle, onMounted, onUnmounted, openBlock, provide, reactive, ref, renderList, renderSlot, resolveComponent, resolveDynamicComponent, toDisplayString, unref, useCssVars, useSlots, vModelCheckbox, vModelDynamic, vModelText, watch, withCtx, withDirectives, withKeys, withModifiers } from "vue";
2
3
  import AsyncValidator from "async-validator";
3
4
  import { createI18n } from "vue-i18n";
4
- //#region \0rolldown/runtime.js
5
- var __defProp = Object.defineProperty;
6
- var __exportAll = (all, no_symbols) => {
7
- let target = {};
8
- for (var name in all) __defProp(target, name, {
9
- get: all[name],
10
- enumerable: true
11
- });
12
- if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
13
- return target;
14
- };
15
- //#endregion
5
+ import { createMemoryHistory, createRouter as createVueRouter, createWebHashHistory, createWebHistory } from "vue-router";
16
6
  //#region src/utils/crypto.ts
17
7
  /**
18
8
  * Web Crypto API 加密工具
@@ -83,26 +73,99 @@ async function decrypt(base64Data, key) {
83
73
  return null;
84
74
  }
85
75
  }
86
- //#endregion
87
- //#region src/utils/secure-storage.ts
88
76
  /**
89
- * 安全存储工具
90
- * 混合加密策略:
91
- * - sessionStorage: 使用动态会话密钥 (内存中,刷新即焚)
92
- * - localStorage: 使用 Vite 环境变量密钥 (防普通篡改)
77
+ * 配置文件中的密钥缓存
93
78
  */
79
+ let configLocalStorageKey;
80
+ let configSessionStorageKey;
94
81
  let sessionKey = null;
95
82
  let storageReadyResolve = null;
96
83
  const storageReady = new Promise((resolve) => {
97
84
  storageReadyResolve = resolve;
98
85
  });
86
+ let localStorageKey = null;
99
87
  const ENV_KEY = import.meta.env.VITE_STORAGE_KEY || "yd-admin-default-key";
88
+ const ENV_SESSION_KEY = import.meta.env.VITE_SESSION_STORAGE_KEY || "yd-admin-session-key";
89
+ /**
90
+ * 从配置文件加载密钥
91
+ * @param filePath 配置文件路径,默认 config/storage.json
92
+ */
93
+ async function loadKeyFromConfig(filePath) {
94
+ if (configLocalStorageKey) return {
95
+ local: configLocalStorageKey,
96
+ session: configSessionStorageKey || void 0
97
+ };
98
+ try {
99
+ const response = await fetch(filePath || "config/storage.json", { cache: "no-store" });
100
+ if (response.ok) {
101
+ const config = await response.json();
102
+ if (config.localStorageKey || config.sessionStorageKey || config.storageKey) {
103
+ configLocalStorageKey = config.storageKey || config.localStorageKey || void 0;
104
+ configSessionStorageKey = config.sessionStorageKey || config.storageKey || void 0;
105
+ return {
106
+ local: configLocalStorageKey,
107
+ session: configSessionStorageKey
108
+ };
109
+ }
110
+ }
111
+ } catch {}
112
+ return {};
113
+ }
114
+ /**
115
+ * 解析 localStorage 密钥(按优先级)
116
+ */
117
+ async function resolveLocalKey(config) {
118
+ if (config?.localStorageKey || config?.storageKey) return {
119
+ key: config.localStorageKey || config.storageKey,
120
+ source: "init"
121
+ };
122
+ const configFilePath = config?.configFile;
123
+ const configKeys = await loadKeyFromConfig(configFilePath);
124
+ if (configKeys.local) return {
125
+ key: configKeys.local,
126
+ source: "config"
127
+ };
128
+ if (import.meta.env.VITE_STORAGE_KEY) return {
129
+ key: import.meta.env.VITE_STORAGE_KEY,
130
+ source: "env"
131
+ };
132
+ return {
133
+ key: ENV_KEY,
134
+ source: "default"
135
+ };
136
+ }
137
+ /**
138
+ * 解析 sessionStorage 密钥(按优先级)
139
+ */
140
+ async function resolveSessionKey(config) {
141
+ if (config?.sessionStorageKey || config?.storageKey) return {
142
+ key: config.sessionStorageKey || config.storageKey,
143
+ source: "init"
144
+ };
145
+ const configFilePath = config?.configFile;
146
+ const configKeys = await loadKeyFromConfig(configFilePath);
147
+ if (configKeys.session) return {
148
+ key: configKeys.session,
149
+ source: "config"
150
+ };
151
+ if (import.meta.env.VITE_SESSION_STORAGE_KEY) return {
152
+ key: import.meta.env.VITE_SESSION_STORAGE_KEY,
153
+ source: "env"
154
+ };
155
+ return {
156
+ key: ENV_SESSION_KEY,
157
+ source: "dynamic"
158
+ };
159
+ }
100
160
  /**
101
161
  * 初始化安全存储
102
162
  * 必须在应用启动时调用
163
+ * @param config 可选的初始化配置
103
164
  */
104
- async function initSecureStorage() {
105
- sessionKey = await generateSessionKey();
165
+ async function initSecureStorage(config) {
166
+ localStorageKey = (await resolveLocalKey(config)).key;
167
+ if ((await resolveSessionKey(config)).source === "dynamic") sessionKey = await generateSessionKey();
168
+ else sessionKey = null;
106
169
  if (storageReadyResolve) {
107
170
  storageReadyResolve();
108
171
  storageReadyResolve = null;
@@ -113,32 +176,119 @@ async function initSecureStorage() {
113
176
  */
114
177
  var SecureStorage = class {
115
178
  storage;
116
- key;
179
+ storageType;
117
180
  constructor(type) {
181
+ this.storageType = type;
118
182
  this.storage = type === "local" ? localStorage : sessionStorage;
119
- this.key = type === "session" ? sessionKey : ENV_KEY;
183
+ }
184
+ /**
185
+ * 获取存储类型
186
+ */
187
+ get type() {
188
+ return this.storageType;
189
+ }
190
+ /**
191
+ * 是否就绪
192
+ */
193
+ get ready() {
194
+ return this.storageType === "session" ? !!sessionKey || !!ENV_SESSION_KEY : !!localStorageKey || !!ENV_KEY;
195
+ }
196
+ /**
197
+ * 获取密钥(根据存储类型)
198
+ */
199
+ getCurrentKey() {
200
+ if (this.storageType === "session") {
201
+ if (sessionKey) return sessionKey;
202
+ return ENV_SESSION_KEY;
203
+ }
204
+ return localStorageKey || ENV_KEY;
120
205
  }
121
206
  /**
122
207
  * 异步写入
208
+ * @param key 存储键名
209
+ * @param value 存储值
210
+ * @param options 写入选项(可选)
123
211
  */
124
- async setItem(key, value) {
125
- if (!this.key && this.storage === sessionStorage) return;
212
+ async setItem(key, value, options) {
213
+ const currentKey = this.getCurrentKey();
214
+ if (this.storageType === "session" && !sessionKey && true) {
215
+ console.warn(`[secureStorage] sessionStorage key not ready, write "${key}" skipped`);
216
+ return;
217
+ }
126
218
  try {
127
- const encrypted = await encrypt(JSON.stringify(value), this.key);
219
+ const now = Date.now();
220
+ const stored = {
221
+ data: value,
222
+ createdAt: now,
223
+ expiresAt: options?.expiresIn ? now + options.expiresIn * 1e3 : void 0
224
+ };
225
+ let json = JSON.stringify(stored);
226
+ if (options?.compress) {
227
+ const encoder = new TextEncoder();
228
+ const reader = new ReadableStream({ start(controller) {
229
+ controller.enqueue(encoder.encode(json));
230
+ controller.close();
231
+ } }).pipeThrough(new CompressionStream("gzip")).getReader();
232
+ const chunks = [];
233
+ while (true) {
234
+ const { done, value } = await reader.read();
235
+ if (done) break;
236
+ chunks.push(value);
237
+ }
238
+ const merged = new Uint8Array(chunks.reduce((a, c) => a + c.length, 0));
239
+ let off = 0;
240
+ for (const chunk of chunks) {
241
+ merged.set(chunk, off);
242
+ off += chunk.length;
243
+ }
244
+ json = btoa(String.fromCharCode(...merged));
245
+ }
246
+ const encrypted = await encrypt(json, currentKey);
128
247
  this.storage.setItem(key, encrypted);
129
- } catch {}
248
+ } catch (error) {
249
+ console.warn(`[secureStorage] failed to encrypt "${key}":`, error);
250
+ }
130
251
  }
131
252
  /**
132
253
  * 异步读取
133
254
  */
134
255
  async getItem(key) {
135
- if (!this.key && this.storage === sessionStorage) return null;
256
+ const currentKey = this.getCurrentKey();
136
257
  try {
137
258
  const encrypted = this.storage.getItem(key);
138
259
  if (!encrypted) return null;
139
- const json = await decrypt(encrypted, this.key);
140
- if (!json) return null;
141
- return JSON.parse(json);
260
+ let json = await decrypt(encrypted, currentKey);
261
+ if (!json) {
262
+ this.storage.removeItem(key);
263
+ return null;
264
+ }
265
+ try {
266
+ const decoded = atob(json);
267
+ const bytes = Uint8Array.from(decoded, (c) => c.charCodeAt(0));
268
+ const reader = new ReadableStream({ start(controller) {
269
+ controller.enqueue(bytes);
270
+ controller.close();
271
+ } }).pipeThrough(new DecompressionStream("gzip")).getReader();
272
+ const chunks = [];
273
+ while (true) {
274
+ const { done, value } = await reader.read();
275
+ if (done) break;
276
+ chunks.push(value);
277
+ }
278
+ const merged = new Uint8Array(chunks.reduce((a, c) => a + c.length, 0));
279
+ let off = 0;
280
+ for (const chunk of chunks) {
281
+ merged.set(chunk, off);
282
+ off += chunk.length;
283
+ }
284
+ json = new TextDecoder().decode(merged);
285
+ } catch {}
286
+ const stored = JSON.parse(json);
287
+ if (stored.expiresAt && Date.now() > stored.expiresAt) {
288
+ this.storage.removeItem(key);
289
+ return null;
290
+ }
291
+ return stored.data;
142
292
  } catch {
143
293
  this.storage.removeItem(key);
144
294
  return null;
@@ -160,6 +310,213 @@ var SecureStorage = class {
160
310
  const secureLocal = new SecureStorage("local");
161
311
  const secureSession = new SecureStorage("session");
162
312
  //#endregion
313
+ //#region src/utils/router.ts
314
+ /**
315
+ * 动态路由管理器
316
+ */
317
+ var DynamicRouter = class {
318
+ routes = [];
319
+ routeMap = /* @__PURE__ */ new Map();
320
+ /**
321
+ * 设置路由列表
322
+ */
323
+ setRoutes(routes) {
324
+ this.routes = routes;
325
+ this.buildRouteMap();
326
+ }
327
+ /**
328
+ * 获取路由列表
329
+ */
330
+ getRoutes() {
331
+ return this.routes;
332
+ }
333
+ /**
334
+ * 构建路由映射
335
+ */
336
+ buildRouteMap() {
337
+ this.routeMap.clear();
338
+ const buildMap = (routeList) => {
339
+ for (const route of routeList) {
340
+ this.routeMap.set(route.path, route);
341
+ if (route.children) buildMap(route.children);
342
+ }
343
+ };
344
+ buildMap(this.routes);
345
+ }
346
+ /**
347
+ * 根据路径获取路由
348
+ */
349
+ getRoute(path) {
350
+ return this.routeMap.get(path);
351
+ }
352
+ /**
353
+ * 检查路由是否存在
354
+ */
355
+ hasRoute(path) {
356
+ return this.routeMap.has(path);
357
+ }
358
+ /**
359
+ * 添加路由
360
+ */
361
+ addRoute(route, parentPath = "") {
362
+ const fullPath = parentPath ? `${parentPath}/${route.path}` : route.path;
363
+ const newRoute = {
364
+ ...route,
365
+ path: fullPath
366
+ };
367
+ this.routes.push(newRoute);
368
+ this.routeMap.set(fullPath, newRoute);
369
+ }
370
+ /**
371
+ * 移除路由
372
+ */
373
+ removeRoute(path) {
374
+ const route = this.routeMap.get(path);
375
+ if (!route) return false;
376
+ const index = this.routes.indexOf(route);
377
+ if (index > -1) {
378
+ this.routes.splice(index, 1);
379
+ this.routeMap.delete(path);
380
+ return true;
381
+ }
382
+ return false;
383
+ }
384
+ /**
385
+ * 获取可见路由(根据 meta.hidden)
386
+ */
387
+ getVisibleRoutes() {
388
+ const filterVisible = (list) => {
389
+ return list.filter((r) => !r.meta?.hidden).map((r) => ({
390
+ ...r,
391
+ children: r.children ? filterVisible(r.children) : void 0
392
+ }));
393
+ };
394
+ return filterVisible(this.routes);
395
+ }
396
+ /**
397
+ * 根据权限过滤路由
398
+ */
399
+ filterByRoles(roles) {
400
+ const filterRoles = (list) => {
401
+ return list.filter((r) => {
402
+ const routeRoles = r.meta?.roles;
403
+ if (!routeRoles || routeRoles.length === 0) return true;
404
+ return routeRoles.some((role) => roles.includes(role));
405
+ }).map((r) => ({
406
+ ...r,
407
+ children: r.children ? filterRoles(r.children) : void 0
408
+ }));
409
+ };
410
+ return filterRoles(this.routes);
411
+ }
412
+ /**
413
+ * 扁平化路由
414
+ */
415
+ flattenRoutes(routes = this.routes) {
416
+ const result = [];
417
+ const flatten = (list) => {
418
+ for (const r of list) {
419
+ result.push(r);
420
+ if (r.children && r.children.length > 0) flatten(r.children);
421
+ }
422
+ };
423
+ flatten(routes);
424
+ return result;
425
+ }
426
+ /**
427
+ * 路径匹配
428
+ */
429
+ matchPath(path, pattern) {
430
+ if (typeof pattern === "string") return path === pattern || path.startsWith(pattern + "/");
431
+ return pattern.test(path);
432
+ }
433
+ /**
434
+ * 查找路由名称
435
+ */
436
+ findRouteByName(name) {
437
+ for (const route of this.routeMap.values()) if (route.name === name) return route;
438
+ }
439
+ /**
440
+ * 查找路由路径
441
+ */
442
+ findPathByName(name) {
443
+ return this.findRouteByName(name)?.path ?? null;
444
+ }
445
+ };
446
+ /**
447
+ * 路由工具单例
448
+ */
449
+ const dynamicRouter = new DynamicRouter();
450
+ /**
451
+ * 路径规范化
452
+ */
453
+ function normalizePath(path) {
454
+ return path.replace(/\/+/g, "/").replace(/\/$/, "") || "/";
455
+ }
456
+ /**
457
+ * 路径拼接
458
+ */
459
+ function joinPath(...parts) {
460
+ return normalizePath(parts.filter(Boolean).join("/"));
461
+ }
462
+ /**
463
+ * 路径匹配检查
464
+ */
465
+ function isPathMatch(path, pattern) {
466
+ if (typeof pattern === "string") return path === pattern || path.startsWith(pattern + "/");
467
+ return pattern.test(path);
468
+ }
469
+ /**
470
+ * 路由权限检查
471
+ */
472
+ function checkRoutePermission(route, userRoles) {
473
+ if (!route?.meta?.roles || route.meta.roles.length === 0) return true;
474
+ return route.meta.roles.some((role) => userRoles.includes(role));
475
+ }
476
+ /**
477
+ * 路由标题生成器
478
+ */
479
+ function generateRouteTitle(title, prefix = "") {
480
+ return prefix ? `${prefix} - ${title}` : title;
481
+ }
482
+ /**
483
+ * 构建面包屑
484
+ */
485
+ function buildBreadcrumb(path, routes = dynamicRouter.getRoutes()) {
486
+ const breadcrumb = [];
487
+ const findPath = (list, target) => {
488
+ for (const route of list) {
489
+ if (route.path === target) {
490
+ breadcrumb.push(route);
491
+ return true;
492
+ }
493
+ if (route.children) {
494
+ breadcrumb.push(route);
495
+ if (findPath(route.children, target)) return true;
496
+ breadcrumb.pop();
497
+ }
498
+ }
499
+ return false;
500
+ };
501
+ findPath(routes, path);
502
+ return breadcrumb;
503
+ }
504
+ /**
505
+ * 路由记录类型转换
506
+ */
507
+ function convertToSimpleRoute(route) {
508
+ const simpleRedirect = route.redirect;
509
+ const redirectValue = typeof simpleRedirect === "string" ? simpleRedirect : typeof simpleRedirect === "object" && simpleRedirect !== null ? simpleRedirect.path : void 0;
510
+ return {
511
+ path: route.path,
512
+ name: route.name,
513
+ component: route.component,
514
+ children: route.children?.map(convertToSimpleRoute),
515
+ redirect: redirectValue,
516
+ meta: route.meta
517
+ };
518
+ }
519
+ //#endregion
163
520
  //#region src/utils/index.ts
164
521
  /**
165
522
  * Utility functions
@@ -257,12 +614,12 @@ var export_helper_default = (sfc, props) => {
257
614
  };
258
615
  //#endregion
259
616
  //#region src/components/base/button/button.vue
260
- const _hoisted_1$42 = ["disabled", "type"];
261
- const _hoisted_2$23 = {
617
+ const _hoisted_1$45 = ["disabled", "type"];
618
+ const _hoisted_2$26 = {
262
619
  key: 0,
263
620
  class: "yd-button__loading"
264
621
  };
265
- const _hoisted_3$15 = { class: "yd-button__content" };
622
+ const _hoisted_3$17 = { class: "yd-button__content" };
266
623
  var button_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineComponent({
267
624
  name: "YdButton",
268
625
  __name: "button",
@@ -307,7 +664,7 @@ var button_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defin
307
664
  disabled: __props.disabled || __props.loading,
308
665
  type: __props.nativeType,
309
666
  onClick: handleClick
310
- }, [__props.loading ? (openBlock(), createElementBlock("span", _hoisted_2$23, [..._cache[0] || (_cache[0] = [createElementVNode("svg", {
667
+ }, [__props.loading ? (openBlock(), createElementBlock("span", _hoisted_2$26, [..._cache[0] || (_cache[0] = [createElementVNode("svg", {
311
668
  class: "yd-button__spinner",
312
669
  viewBox: "0 0 24 24"
313
670
  }, [createElementVNode("circle", {
@@ -319,13 +676,92 @@ var button_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defin
319
676
  "stroke-width": "3",
320
677
  "stroke-dasharray": "31.4 31.4",
321
678
  "stroke-linecap": "round"
322
- })], -1)])])) : createCommentVNode("v-if", true), createElementVNode("span", _hoisted_3$15, [renderSlot(_ctx.$slots, "default", {}, void 0, true)])], 10, _hoisted_1$42);
679
+ })], -1)])])) : createCommentVNode("v-if", true), createElementVNode("span", _hoisted_3$17, [renderSlot(_ctx.$slots, "default", {}, void 0, true)])], 10, _hoisted_1$45);
680
+ };
681
+ }
682
+ }), [["__scopeId", "data-v-8a9a80ea"]]);
683
+ //#endregion
684
+ //#region src/components/base/icon/registry.ts
685
+ const iconRegistry = ref({
686
+ check: "<path d=\"M20 6L9 17l-5-5\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>",
687
+ close: "<path d=\"M18 6L6 18M6 6l12 12\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>",
688
+ arrowLeft: "<path d=\"M19 12H5m0 0l7 7m-7-7l7-7\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>",
689
+ arrowRight: "<path d=\"M5 12h14m0 0l-7-7m7 7l-7 7\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>",
690
+ chevronDown: "<path d=\"M6 9l6 6 6-6\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>",
691
+ chevronUp: "<path d=\"M18 15l-6-6-6 6\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>",
692
+ search: "<path d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>",
693
+ menu: "<path d=\"M4 6h16M4 12h16M4 18h16\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>",
694
+ user: "<path d=\"M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><circle cx=\"12\" cy=\"7\" r=\"4\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>",
695
+ settings: "<path d=\"M12 15a3 3 0 100-6 3 3 0 000 6z\" stroke=\"currentColor\" stroke-width=\"2\"/><path d=\"M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 010 2.83 2 2 0 01-2.83 0l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-2 2 2 2 0 01-2-2v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83 0 2 2 0 010-2.83l.06-.06a1.65 1.65 0 00.33-1.82 1.65 1.65 0 00-1.51-1H3a2 2 0 01-2-2 2 2 0 012-2h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 010-2.83 2 2 0 012.83 0l.06.06a1.65 1.65 0 001.82.33H9a1.65 1.65 0 001-1.51V3a2 2 0 012-2 2 2 0 012 2v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 0 2 2 0 010 2.83l-.06.06a1.65 1.65 0 00-.33 1.82V9a1.65 1.65 0 001.51 1H21a2 2 0 012 2 2 2 0 01-2 2h-.09a1.65 1.65 0 00-1.51 1z\" stroke=\"currentColor\" stroke-width=\"2\"/>"
696
+ });
697
+ function registerIcon(name, svg) {
698
+ iconRegistry.value[name] = svg;
699
+ }
700
+ function getIcon(name) {
701
+ return iconRegistry.value[name] || "";
702
+ }
703
+ function getIconRegistry() {
704
+ return iconRegistry.value;
705
+ }
706
+ //#endregion
707
+ //#region src/components/base/icon/icon.vue
708
+ const _hoisted_1$44 = ["innerHTML"];
709
+ var icon_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineComponent({
710
+ name: "YdIcon",
711
+ inheritAttrs: false,
712
+ __name: "icon",
713
+ props: {
714
+ name: { default: "" },
715
+ size: { default: 16 },
716
+ color: { default: "currentColor" },
717
+ rotate: { default: 0 },
718
+ spin: {
719
+ type: Boolean,
720
+ default: false
721
+ }
722
+ },
723
+ emits: ["click"],
724
+ setup(__props, { emit: __emit }) {
725
+ const props = __props;
726
+ const emit = __emit;
727
+ function e(element) {
728
+ return `yd-icon__${element}`;
729
+ }
730
+ const svgContent = computed(() => {
731
+ if (!props.name) return "";
732
+ if (props.name.includes("<svg") || props.name.includes("<path")) return props.name;
733
+ return getIcon(props.name) || "";
734
+ });
735
+ const iconStyle = computed(() => {
736
+ const size = typeof props.size === "number" ? `${props.size}px` : props.size;
737
+ return {
738
+ width: size,
739
+ height: size,
740
+ color: props.color,
741
+ transform: props.rotate ? `rotate(${props.rotate}deg)` : void 0
742
+ };
743
+ });
744
+ function handleClick(event) {
745
+ emit("click", event);
746
+ }
747
+ return (_ctx, _cache) => {
748
+ return openBlock(), createElementBlock("span", mergeProps({
749
+ class: unref(cn)("yd-icon"),
750
+ style: iconStyle.value
751
+ }, _ctx.$attrs, { onClick: handleClick }), [createCommentVNode(" SVG Content "), svgContent.value ? (openBlock(), createElementBlock("svg", {
752
+ key: 0,
753
+ class: normalizeClass(e("svg")),
754
+ viewBox: "0 0 24 24",
755
+ fill: "none",
756
+ xmlns: "http://www.w3.org/2000/svg",
757
+ innerHTML: svgContent.value
758
+ }, null, 10, _hoisted_1$44)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [createCommentVNode(" Slot Fallback "), renderSlot(_ctx.$slots, "default", {}, void 0, true)], 2112))], 16);
323
759
  };
324
760
  }
325
- }), [["__scopeId", "data-v-7c52cbce"]]);
761
+ }), [["__scopeId", "data-v-20774ae9"]]);
326
762
  //#endregion
327
763
  //#region src/components/base/input/input.vue
328
- const _hoisted_1$41 = [
764
+ const _hoisted_1$43 = [
329
765
  "type",
330
766
  "value",
331
767
  "placeholder",
@@ -434,7 +870,7 @@ var input_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
434
870
  onFocus: handleFocus,
435
871
  onBlur: handleBlur,
436
872
  onKeydown: handleKeydown
437
- }, null, 42, _hoisted_1$41),
873
+ }, null, 42, _hoisted_1$43),
438
874
  __props.clearable && __props.modelValue && !__props.disabled ? (openBlock(), createElementBlock("span", {
439
875
  key: 1,
440
876
  class: normalizeClass(e("clear")),
@@ -474,7 +910,7 @@ var input_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
474
910
  }), [["__scopeId", "data-v-9f5a78f3"]]);
475
911
  //#endregion
476
912
  //#region src/components/base/textarea/textarea.vue
477
- const _hoisted_1$40 = [
913
+ const _hoisted_1$42 = [
478
914
  "value",
479
915
  "placeholder",
480
916
  "disabled",
@@ -568,7 +1004,7 @@ var textarea_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ def
568
1004
  onChange: handleChange,
569
1005
  onFocus: handleFocus,
570
1006
  onBlur: handleBlur
571
- }, null, 42, _hoisted_1$40), __props.showWordLimit && __props.maxlength ? (openBlock(), createElementBlock("span", {
1007
+ }, null, 42, _hoisted_1$42), __props.showWordLimit && __props.maxlength ? (openBlock(), createElementBlock("span", {
572
1008
  key: 0,
573
1009
  class: normalizeClass(e("word-limit"))
574
1010
  }, toDisplayString(String(__props.modelValue).length) + "/" + toDisplayString(__props.maxlength), 3)) : createCommentVNode("v-if", true)], 2);
@@ -577,9 +1013,9 @@ var textarea_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ def
577
1013
  }), [["__scopeId", "data-v-13af2da6"]]);
578
1014
  //#endregion
579
1015
  //#region src/components/base/input-number/input-number.vue
580
- const _hoisted_1$39 = ["disabled"];
581
- const _hoisted_2$22 = ["value", "disabled"];
582
- const _hoisted_3$14 = ["disabled"];
1016
+ const _hoisted_1$41 = ["disabled"];
1017
+ const _hoisted_2$25 = ["value", "disabled"];
1018
+ const _hoisted_3$16 = ["disabled"];
583
1019
  var input_number_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineComponent({
584
1020
  name: "YdInputNumber",
585
1021
  __name: "input-number",
@@ -674,7 +1110,7 @@ var input_number_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */
674
1110
  y1: "12",
675
1111
  x2: "19",
676
1112
  y2: "12"
677
- })], -1)])], 10, _hoisted_1$39),
1113
+ })], -1)])], 10, _hoisted_1$41),
678
1114
  createElementVNode("input", {
679
1115
  ref_key: "inputRef",
680
1116
  ref: inputRef,
@@ -685,7 +1121,7 @@ var input_number_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */
685
1121
  onInput: handleInput,
686
1122
  onBlur: handleBlur,
687
1123
  onKeydown: handleKeydown
688
- }, null, 42, _hoisted_2$22),
1124
+ }, null, 42, _hoisted_2$25),
689
1125
  createElementVNode("button", {
690
1126
  class: normalizeClass(e("btn")),
691
1127
  disabled: __props.disabled || __props.modelValue >= __props.max,
@@ -710,7 +1146,7 @@ var input_number_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */
710
1146
  y1: "12",
711
1147
  x2: "19",
712
1148
  y2: "12"
713
- })], -1)])], 10, _hoisted_3$14)
1149
+ })], -1)])], 10, _hoisted_3$16)
714
1150
  ], 2)], 2);
715
1151
  };
716
1152
  }
@@ -762,13 +1198,13 @@ var empty_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
762
1198
  }), [["__scopeId", "data-v-ed413d74"]]);
763
1199
  //#endregion
764
1200
  //#region src/components/base/select/select.vue
765
- const _hoisted_1$38 = [
1201
+ const _hoisted_1$40 = [
766
1202
  "value",
767
1203
  "placeholder",
768
1204
  "disabled"
769
1205
  ];
770
- const _hoisted_2$21 = ["onClick"];
771
- const _hoisted_3$13 = ["onClick"];
1206
+ const _hoisted_2$24 = ["onClick"];
1207
+ const _hoisted_3$15 = ["onClick"];
772
1208
  var select_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineComponent({
773
1209
  name: "YdSelect",
774
1210
  inheritAttrs: false,
@@ -995,7 +1431,7 @@ var select_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defin
995
1431
  onFocus: handleFocus,
996
1432
  onBlur: handleBlur,
997
1433
  onKeydown: _cache[0] || (_cache[0] = withModifiers(() => {}, ["stop"]))
998
- }, null, 42, _hoisted_1$38)) : (openBlock(), createElementBlock("div", {
1434
+ }, null, 42, _hoisted_1$40)) : (openBlock(), createElementBlock("div", {
999
1435
  key: 1,
1000
1436
  class: normalizeClass([e("display"), { [e("display--placeholder")]: !selectedLabel.value }])
1001
1437
  }, toDisplayString(selectedLabel.value || __props.placeholder), 3)),
@@ -1072,7 +1508,7 @@ var select_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defin
1072
1508
  }, [createElementVNode("span", null, toDisplayString(opt.label), 1), isSelected(opt.value) ? (openBlock(), createElementBlock("span", {
1073
1509
  key: 0,
1074
1510
  class: normalizeClass(e("check"))
1075
- }, "✓", 2)) : createCommentVNode("v-if", true)], 10, _hoisted_2$21);
1511
+ }, "✓", 2)) : createCommentVNode("v-if", true)], 10, _hoisted_2$24);
1076
1512
  }), 128))], 2)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [createCommentVNode(" Option "), createElementVNode("div", {
1077
1513
  class: normalizeClass([e("option"), {
1078
1514
  [e("option--active")]: isSelected(option.value),
@@ -1082,7 +1518,7 @@ var select_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defin
1082
1518
  }, [createElementVNode("span", null, toDisplayString(option.label), 1), isSelected(option.value) ? (openBlock(), createElementBlock("span", {
1083
1519
  key: 0,
1084
1520
  class: normalizeClass(e("check"))
1085
- }, "✓", 2)) : createCommentVNode("v-if", true)], 10, _hoisted_3$13)], 2112))], 64);
1521
+ }, "✓", 2)) : createCommentVNode("v-if", true)], 10, _hoisted_3$15)], 2112))], 64);
1086
1522
  }), 128))], 6))], 6)) : createCommentVNode("v-if", true)]),
1087
1523
  _: 1
1088
1524
  })]))
@@ -1092,7 +1528,7 @@ var select_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defin
1092
1528
  }), [["__scopeId", "data-v-bea52552"]]);
1093
1529
  //#endregion
1094
1530
  //#region src/components/base/switch/switch.vue
1095
- const _hoisted_1$37 = ["aria-checked", "disabled"];
1531
+ const _hoisted_1$39 = ["aria-checked", "disabled"];
1096
1532
  var switch_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineComponent({
1097
1533
  name: "YdSwitch",
1098
1534
  __name: "switch",
@@ -1128,13 +1564,13 @@ var switch_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defin
1128
1564
  class: normalizeClass(switchClasses.value),
1129
1565
  disabled: __props.disabled,
1130
1566
  onClick: toggle
1131
- }, [createElementVNode("span", { class: normalizeClass(e("thumb")) }, null, 2)], 10, _hoisted_1$37);
1567
+ }, [createElementVNode("span", { class: normalizeClass(e("thumb")) }, null, 2)], 10, _hoisted_1$39);
1132
1568
  };
1133
1569
  }
1134
- }), [["__scopeId", "data-v-3f00ad5e"]]);
1570
+ }), [["__scopeId", "data-v-178da0de"]]);
1135
1571
  //#endregion
1136
1572
  //#region src/components/base/checkbox/checkbox.vue
1137
- const _hoisted_1$36 = [
1573
+ const _hoisted_1$38 = [
1138
1574
  "checked",
1139
1575
  "disabled",
1140
1576
  "value"
@@ -1187,7 +1623,7 @@ var checkbox_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ def
1187
1623
  disabled: __props.disabled,
1188
1624
  value: __props.value,
1189
1625
  onChange: handleChange
1190
- }, null, 42, _hoisted_1$36),
1626
+ }, null, 42, _hoisted_1$38),
1191
1627
  createElementVNode("span", { class: normalizeClass(e("box")) }, [__props.modelValue ? (openBlock(), createElementBlock("svg", {
1192
1628
  key: 0,
1193
1629
  class: normalizeClass(e("icon")),
@@ -1208,7 +1644,7 @@ var checkbox_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ def
1208
1644
  ], 2);
1209
1645
  };
1210
1646
  }
1211
- }), [["__scopeId", "data-v-161dff57"]]);
1647
+ }), [["__scopeId", "data-v-85b4197e"]]);
1212
1648
  var checkbox_group_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineComponent({
1213
1649
  name: "YdCheckboxGroup",
1214
1650
  __name: "checkbox-group",
@@ -1254,7 +1690,7 @@ var checkbox_group_default = /* @__PURE__ */ export_helper_default(/* @__PURE__
1254
1690
  }), [["__scopeId", "data-v-3dce3e2c"]]);
1255
1691
  //#endregion
1256
1692
  //#region src/components/base/radio/radio.vue
1257
- const _hoisted_1$35 = [
1693
+ const _hoisted_1$37 = [
1258
1694
  "checked",
1259
1695
  "disabled",
1260
1696
  "value",
@@ -1310,7 +1746,7 @@ var radio_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
1310
1746
  value: __props.value,
1311
1747
  name: __props.name,
1312
1748
  onChange: handleChange
1313
- }, null, 42, _hoisted_1$35),
1749
+ }, null, 42, _hoisted_1$37),
1314
1750
  createElementVNode("span", { class: normalizeClass(e("dot")) }, null, 2),
1315
1751
  _ctx.$slots.default || __props.label ? (openBlock(), createElementBlock("span", {
1316
1752
  key: 0,
@@ -1427,10 +1863,10 @@ var tag_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineCo
1427
1863
  })], -1)])], 2)) : createCommentVNode("v-if", true)], 2);
1428
1864
  };
1429
1865
  }
1430
- }), [["__scopeId", "data-v-68856db4"]]);
1866
+ }), [["__scopeId", "data-v-ae4235fd"]]);
1431
1867
  //#endregion
1432
1868
  //#region src/components/base/avatar/avatar.vue
1433
- const _hoisted_1$34 = ["src", "alt"];
1869
+ const _hoisted_1$36 = ["src", "alt"];
1434
1870
  var avatar_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineComponent({
1435
1871
  name: "YdAvatar",
1436
1872
  __name: "avatar",
@@ -1458,7 +1894,7 @@ var avatar_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defin
1458
1894
  src: __props.src,
1459
1895
  alt: __props.alt,
1460
1896
  onError: handleError
1461
- }, null, 40, _hoisted_1$34)) : _ctx.$slots.default ? (openBlock(), createElementBlock("span", {
1897
+ }, null, 40, _hoisted_1$36)) : _ctx.$slots.default ? (openBlock(), createElementBlock("span", {
1462
1898
  key: 1,
1463
1899
  class: normalizeClass(e("text"))
1464
1900
  }, [renderSlot(_ctx.$slots, "default", {}, void 0, true)], 2)) : (openBlock(), createElementBlock("span", {
@@ -1515,10 +1951,10 @@ var badge_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
1515
1951
  }, [showNumber.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createTextVNode(toDisplayString(displayValue.value), 1)], 64)) : createCommentVNode("v-if", true)], 6)) : createCommentVNode("v-if", true)], 2);
1516
1952
  };
1517
1953
  }
1518
- }), [["__scopeId", "data-v-bb44e78d"]]);
1954
+ }), [["__scopeId", "data-v-9b63f1ae"]]);
1519
1955
  //#endregion
1520
1956
  //#region src/components/base/rate/rate.vue
1521
- const _hoisted_1$33 = ["onClick", "onMouseenter"];
1957
+ const _hoisted_1$35 = ["onClick", "onMouseenter"];
1522
1958
  var rate_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineComponent({
1523
1959
  name: "YdRate",
1524
1960
  __name: "rate",
@@ -1583,14 +2019,14 @@ var rate_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineC
1583
2019
  viewBox: "0 0 24 24",
1584
2020
  fill: "currentColor",
1585
2021
  stroke: "none"
1586
- }, [..._cache[1] || (_cache[1] = [createElementVNode("polygon", { points: "12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2" }, null, -1)])], 2))], 42, _hoisted_1$33);
2022
+ }, [..._cache[1] || (_cache[1] = [createElementVNode("polygon", { points: "12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2" }, null, -1)])], 2))], 42, _hoisted_1$35);
1587
2023
  }), 128)), __props.showText ? (openBlock(), createElementBlock("span", {
1588
2024
  key: 0,
1589
2025
  class: normalizeClass(e("text"))
1590
2026
  }, toDisplayString(__props.texts[Math.ceil(__props.modelValue) - 1] || `${__props.modelValue}分`), 3)) : createCommentVNode("v-if", true)], 2);
1591
2027
  };
1592
2028
  }
1593
- }), [["__scopeId", "data-v-82987348"]]);
2029
+ }), [["__scopeId", "data-v-52b27a1b"]]);
1594
2030
  var slider_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineComponent({
1595
2031
  name: "YdSlider",
1596
2032
  __name: "slider",
@@ -1669,17 +2105,17 @@ var slider_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defin
1669
2105
  }, toDisplayString(__props.modelValue), 7)) : createCommentVNode("v-if", true)], 2);
1670
2106
  };
1671
2107
  }
1672
- }), [["__scopeId", "data-v-ad53f18b"]]);
2108
+ }), [["__scopeId", "data-v-51e82523"]]);
1673
2109
  //#endregion
1674
2110
  //#region src/components/base/date-picker/date-picker.vue
1675
- const _hoisted_1$32 = [
2111
+ const _hoisted_1$34 = [
1676
2112
  "value",
1677
2113
  "placeholder",
1678
2114
  "disabled"
1679
2115
  ];
1680
- const _hoisted_2$20 = ["onClick"];
1681
- const _hoisted_3$12 = ["onClick"];
1682
- const _hoisted_4$11 = ["disabled", "onClick"];
2116
+ const _hoisted_2$23 = ["onClick"];
2117
+ const _hoisted_3$14 = ["onClick"];
2118
+ const _hoisted_4$13 = ["disabled", "onClick"];
1683
2119
  var date_picker_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineComponent({
1684
2120
  name: "YdDatePicker",
1685
2121
  __name: "date-picker",
@@ -1730,7 +2166,6 @@ var date_picker_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */
1730
2166
  });
1731
2167
  const panelStyle = computed(() => {
1732
2168
  if (!triggerRef.value) return {};
1733
- positionKey.value;
1734
2169
  const rect = triggerRef.value.getBoundingClientRect();
1735
2170
  return {
1736
2171
  position: "fixed",
@@ -1884,7 +2319,7 @@ var date_picker_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */
1884
2319
  disabled: __props.disabled,
1885
2320
  readonly: "",
1886
2321
  onClick: withModifiers(togglePicker, ["stop"])
1887
- }, null, 10, _hoisted_1$32),
2322
+ }, null, 10, _hoisted_1$34),
1888
2323
  createElementVNode("span", {
1889
2324
  class: normalizeClass(e("icon")),
1890
2325
  onClick: withModifiers(togglePicker, ["stop"])
@@ -1908,13 +2343,13 @@ var date_picker_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */
1908
2343
  key: y,
1909
2344
  class: normalizeClass([e("year"), { [e("year--selected")]: selectedYear.value === y }]),
1910
2345
  onClick: withModifiers(($event) => selectYear(y), ["stop"])
1911
- }, toDisplayString(y), 11, _hoisted_2$20);
2346
+ }, toDisplayString(y), 11, _hoisted_2$23);
1912
2347
  }), 128))], 2)], 2)) : view.value === "month" ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [createCommentVNode(" Month selection "), createElementVNode("div", { class: normalizeClass(e("view")) }, [createElementVNode("div", { class: normalizeClass(e("view-header")) }, [createElementVNode("button", { onClick: _cache[0] || (_cache[0] = withModifiers(($event) => view.value = "year", ["stop"])) }, toDisplayString(selectedYear.value), 1)], 2), createElementVNode("div", { class: normalizeClass(e("months")) }, [(openBlock(), createElementBlock(Fragment, null, renderList(months, (m, i) => {
1913
2348
  return createElementVNode("button", {
1914
2349
  key: i,
1915
2350
  class: normalizeClass([e("month"), { [e("month--selected")]: selectedMonth.value === i }]),
1916
2351
  onClick: withModifiers(($event) => selectMonth(i), ["stop"])
1917
- }, toDisplayString(m), 11, _hoisted_3$12);
2352
+ }, toDisplayString(m), 11, _hoisted_3$14);
1918
2353
  }), 64))], 2)], 2)], 2112)) : (openBlock(), createElementBlock(Fragment, { key: 2 }, [createCommentVNode(" Date selection "), createElementVNode("div", { class: normalizeClass(e("view")) }, [
1919
2354
  createElementVNode("div", { class: normalizeClass(e("header")) }, [
1920
2355
  createElementVNode("button", { onClick: withModifiers(prevMonth, ["stop"]) }, "‹"),
@@ -1945,21 +2380,21 @@ var date_picker_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */
1945
2380
  }]),
1946
2381
  disabled: !day.current,
1947
2382
  onClick: withModifiers(($event) => selectDate(day), ["stop"])
1948
- }, toDisplayString(day.date.getDate()), 11, _hoisted_4$11);
2383
+ }, toDisplayString(day.date.getDate()), 11, _hoisted_4$13);
1949
2384
  }), 128))], 2)
1950
2385
  ], 2)], 2112))], 38)) : createCommentVNode("v-if", true)]))
1951
2386
  ], 2);
1952
2387
  };
1953
2388
  }
1954
- }), [["__scopeId", "data-v-7cec74da"]]);
2389
+ }), [["__scopeId", "data-v-6e664fd9"]]);
1955
2390
  //#endregion
1956
2391
  //#region src/components/base/date-picker/date-range-picker.vue
1957
- const _hoisted_1$31 = [
2392
+ const _hoisted_1$33 = [
1958
2393
  "value",
1959
2394
  "placeholder",
1960
2395
  "disabled"
1961
2396
  ];
1962
- const _hoisted_2$19 = [
2397
+ const _hoisted_2$22 = [
1963
2398
  "disabled",
1964
2399
  "onClick",
1965
2400
  "onMouseenter"
@@ -2125,7 +2560,7 @@ var date_range_picker_default = /* @__PURE__ */ export_helper_default(/* @__PURE
2125
2560
  placeholder: __props.placeholder,
2126
2561
  disabled: __props.disabled,
2127
2562
  readonly: ""
2128
- }, null, 10, _hoisted_1$31),
2563
+ }, null, 10, _hoisted_1$33),
2129
2564
  createElementVNode("span", { class: normalizeClass(e("icon")) }, "📅", 2),
2130
2565
  (openBlock(), createBlock(Teleport, { to: "body" }, [visible.value ? (openBlock(), createElementBlock("div", {
2131
2566
  key: 0,
@@ -2163,23 +2598,23 @@ var date_range_picker_default = /* @__PURE__ */ export_helper_default(/* @__PURE
2163
2598
  onClick: withModifiers(($event) => selectDate(day), ["stop"]),
2164
2599
  onMouseenter: ($event) => hoverDate.value = formatDate(day.date),
2165
2600
  onMouseleave: _cache[0] || (_cache[0] = ($event) => hoverDate.value = "")
2166
- }, toDisplayString(day.date.getDate()), 43, _hoisted_2$19);
2601
+ }, toDisplayString(day.date.getDate()), 43, _hoisted_2$22);
2167
2602
  }), 128))], 2)
2168
2603
  ], 6)) : createCommentVNode("v-if", true)]))
2169
2604
  ], 2);
2170
2605
  };
2171
2606
  }
2172
- }), [["__scopeId", "data-v-3a1246c0"]]);
2607
+ }), [["__scopeId", "data-v-c307df48"]]);
2173
2608
  //#endregion
2174
2609
  //#region src/components/base/time-picker/time-picker.vue
2175
- const _hoisted_1$30 = [
2610
+ const _hoisted_1$32 = [
2176
2611
  "value",
2177
2612
  "placeholder",
2178
2613
  "disabled"
2179
2614
  ];
2180
- const _hoisted_2$18 = ["onClick"];
2181
- const _hoisted_3$11 = ["onClick"];
2182
- const _hoisted_4$10 = ["onClick"];
2615
+ const _hoisted_2$21 = ["onClick"];
2616
+ const _hoisted_3$13 = ["onClick"];
2617
+ const _hoisted_4$12 = ["onClick"];
2183
2618
  var time_picker_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineComponent({
2184
2619
  name: "YdTimePicker",
2185
2620
  __name: "time-picker",
@@ -2256,7 +2691,7 @@ var time_picker_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */
2256
2691
  placeholder: __props.placeholder,
2257
2692
  disabled: __props.disabled,
2258
2693
  readonly: ""
2259
- }, null, 10, _hoisted_1$30), (openBlock(), createBlock(Teleport, { to: "body" }, [visible.value ? (openBlock(), createElementBlock("div", {
2694
+ }, null, 10, _hoisted_1$32), (openBlock(), createBlock(Teleport, { to: "body" }, [visible.value ? (openBlock(), createElementBlock("div", {
2260
2695
  key: 0,
2261
2696
  class: normalizeClass(e("panel")),
2262
2697
  style: normalizeStyle(panelStyle.value)
@@ -2266,14 +2701,14 @@ var time_picker_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */
2266
2701
  key: h - 1,
2267
2702
  class: normalizeClass([e("item"), { [e("item--active")]: selectedHour.value === h - 1 }]),
2268
2703
  onClick: ($event) => selectHour(h - 1)
2269
- }, toDisplayString(String(h - 1).padStart(2, "0")), 11, _hoisted_2$18);
2704
+ }, toDisplayString(String(h - 1).padStart(2, "0")), 11, _hoisted_2$21);
2270
2705
  }), 64))], 2),
2271
2706
  createElementVNode("div", { class: normalizeClass(e("column")) }, [(openBlock(), createElementBlock(Fragment, null, renderList(60, (m) => {
2272
2707
  return createElementVNode("div", {
2273
2708
  key: m - 1,
2274
2709
  class: normalizeClass([e("item"), { [e("item--active")]: selectedMinute.value === m - 1 }]),
2275
2710
  onClick: ($event) => selectMinute(m - 1)
2276
- }, toDisplayString(String(m - 1).padStart(2, "0")), 11, _hoisted_3$11);
2711
+ }, toDisplayString(String(m - 1).padStart(2, "0")), 11, _hoisted_3$13);
2277
2712
  }), 64))], 2),
2278
2713
  __props.showSeconds ? (openBlock(), createElementBlock("div", {
2279
2714
  key: 0,
@@ -2283,23 +2718,23 @@ var time_picker_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */
2283
2718
  key: s - 1,
2284
2719
  class: normalizeClass([e("item"), { [e("item--active")]: selectedSecond.value === s - 1 }]),
2285
2720
  onClick: ($event) => selectSecond(s - 1)
2286
- }, toDisplayString(String(s - 1).padStart(2, "0")), 11, _hoisted_4$10);
2721
+ }, toDisplayString(String(s - 1).padStart(2, "0")), 11, _hoisted_4$12);
2287
2722
  }), 64))], 2)) : createCommentVNode("v-if", true)
2288
2723
  ], 2)], 6)) : createCommentVNode("v-if", true)]))], 2);
2289
2724
  };
2290
2725
  }
2291
- }), [["__scopeId", "data-v-71c12ad9"]]);
2726
+ }), [["__scopeId", "data-v-a6fe401a"]]);
2292
2727
  //#endregion
2293
2728
  //#region src/components/base/cascader/cascader.vue
2294
- const _hoisted_1$29 = [
2729
+ const _hoisted_1$31 = [
2295
2730
  "value",
2296
2731
  "placeholder",
2297
2732
  "disabled",
2298
2733
  "readonly"
2299
2734
  ];
2300
- const _hoisted_2$17 = ["onClick"];
2301
- const _hoisted_3$10 = ["onClick"];
2302
- const _hoisted_4$9 = ["onClick"];
2735
+ const _hoisted_2$20 = ["onClick"];
2736
+ const _hoisted_3$12 = ["onClick"];
2737
+ const _hoisted_4$11 = ["onClick"];
2303
2738
  var cascader_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineComponent({
2304
2739
  name: "YdCascader",
2305
2740
  __name: "cascader",
@@ -2363,7 +2798,6 @@ var cascader_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ def
2363
2798
  });
2364
2799
  const dropdownStyle = computed(() => {
2365
2800
  if (!triggerRef.value) return {};
2366
- positionKey.value;
2367
2801
  const rect = triggerRef.value.getBoundingClientRect();
2368
2802
  return {
2369
2803
  position: "fixed",
@@ -2513,7 +2947,7 @@ var cascader_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ def
2513
2947
  onInput: handleSearch,
2514
2948
  onFocus: handleFocus,
2515
2949
  onBlur: handleBlur
2516
- }, null, 42, _hoisted_1$29), (openBlock(), createBlock(Teleport, { to: "body" }, [visible.value ? (openBlock(), createElementBlock("div", {
2950
+ }, null, 42, _hoisted_1$31), (openBlock(), createBlock(Teleport, { to: "body" }, [visible.value ? (openBlock(), createElementBlock("div", {
2517
2951
  key: 0,
2518
2952
  class: normalizeClass(e("dropdown")),
2519
2953
  style: normalizeStyle(dropdownStyle.value),
@@ -2536,7 +2970,7 @@ var cascader_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ def
2536
2970
  }), 128)), __props.multiple ? (openBlock(), createElementBlock("span", {
2537
2971
  key: 0,
2538
2972
  class: normalizeClass(e("checkmark"))
2539
- }, toDisplayString(isPathSelected(item.path) ? "✓" : ""), 3)) : createCommentVNode("v-if", true)], 10, _hoisted_2$17);
2973
+ }, toDisplayString(isPathSelected(item.path) ? "✓" : ""), 3)) : createCommentVNode("v-if", true)], 10, _hoisted_2$20);
2540
2974
  }), 128)), searchResults.value.length === 0 ? (openBlock(), createElementBlock("div", {
2541
2975
  key: 0,
2542
2976
  class: normalizeClass(e("empty"))
@@ -2548,7 +2982,7 @@ var cascader_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ def
2548
2982
  }, [createTextVNode(toDisplayString(option.label) + " ", 1), option.children?.length ? (openBlock(), createElementBlock("span", {
2549
2983
  key: 0,
2550
2984
  class: normalizeClass(e("arrow"))
2551
- }, "›", 2)) : createCommentVNode("v-if", true)], 10, _hoisted_3$10);
2985
+ }, "›", 2)) : createCommentVNode("v-if", true)], 10, _hoisted_3$12);
2552
2986
  }), 128))], 2), (openBlock(true), createElementBlock(Fragment, null, renderList(activePath.value.length, (level) => {
2553
2987
  return openBlock(), createElementBlock(Fragment, { key: level }, [activePath.value[level - 1]?.children?.length ? (openBlock(), createElementBlock("div", {
2554
2988
  key: 0,
@@ -2561,7 +2995,7 @@ var cascader_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ def
2561
2995
  }, [createTextVNode(toDisplayString(option.label) + " ", 1), option.children?.length ? (openBlock(), createElementBlock("span", {
2562
2996
  key: 0,
2563
2997
  class: normalizeClass(e("arrow"))
2564
- }, "›", 2)) : createCommentVNode("v-if", true)], 10, _hoisted_4$9);
2998
+ }, "›", 2)) : createCommentVNode("v-if", true)], 10, _hoisted_4$11);
2565
2999
  }), 128))], 2)) : createCommentVNode("v-if", true)], 64);
2566
3000
  }), 128))], 2)], 2112))], 38)) : createCommentVNode("v-if", true)]))], 2);
2567
3001
  };
@@ -2569,7 +3003,7 @@ var cascader_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ def
2569
3003
  }), [["__scopeId", "data-v-01225c10"]]);
2570
3004
  //#endregion
2571
3005
  //#region src/components/base/auto-complete/auto-complete.vue
2572
- const _hoisted_1$28 = ["onClick", "onMouseenter"];
3006
+ const _hoisted_1$30 = ["onClick", "onMouseenter"];
2573
3007
  var auto_complete_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineComponent({
2574
3008
  name: "YdAutoComplete",
2575
3009
  __name: "auto-complete",
@@ -2653,15 +3087,15 @@ var auto_complete_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ *
2653
3087
  class: normalizeClass([e("option"), { [e("option--active")]: index === activeIndex.value }]),
2654
3088
  onClick: ($event) => selectOption(option),
2655
3089
  onMouseenter: ($event) => activeIndex.value = index
2656
- }, toDisplayString(option.label), 43, _hoisted_1$28);
3090
+ }, toDisplayString(option.label), 43, _hoisted_1$30);
2657
3091
  }), 128))], 6)) : createCommentVNode("v-if", true)]))], 2);
2658
3092
  };
2659
3093
  }
2660
3094
  }), [["__scopeId", "data-v-0251e526"]]);
2661
3095
  //#endregion
2662
3096
  //#region src/components/base/transfer/transfer.vue
2663
- const _hoisted_1$27 = ["onClick"];
2664
- const _hoisted_2$16 = ["onClick"];
3097
+ const _hoisted_1$29 = ["onClick"];
3098
+ const _hoisted_2$19 = ["onClick"];
2665
3099
  var transfer_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineComponent({
2666
3100
  name: "YdTransfer",
2667
3101
  __name: "transfer",
@@ -2736,7 +3170,7 @@ var transfer_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ def
2736
3170
  "model-value",
2737
3171
  "disabled",
2738
3172
  "onChange"
2739
- ])], 10, _hoisted_1$27);
3173
+ ])], 10, _hoisted_1$29);
2740
3174
  }), 128)), sourceOptions.value.length === 0 ? (openBlock(), createBlock(empty_default, {
2741
3175
  key: 0,
2742
3176
  description: "暂无数据"
@@ -2784,7 +3218,7 @@ var transfer_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ def
2784
3218
  "model-value",
2785
3219
  "disabled",
2786
3220
  "onChange"
2787
- ])], 10, _hoisted_2$16);
3221
+ ])], 10, _hoisted_2$19);
2788
3222
  }), 128)), targetOptions.value.length === 0 ? (openBlock(), createBlock(empty_default, {
2789
3223
  key: 0,
2790
3224
  description: "暂无数据"
@@ -2795,7 +3229,7 @@ var transfer_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ def
2795
3229
  }), [["__scopeId", "data-v-a2e1ecd2"]]);
2796
3230
  //#endregion
2797
3231
  //#region src/components/feedback/spin/spin.vue
2798
- const _hoisted_1$26 = ["width", "height"];
3232
+ const _hoisted_1$28 = ["width", "height"];
2799
3233
  var spin_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineComponent({
2800
3234
  name: "YdSpin",
2801
3235
  __name: "spin",
@@ -2833,7 +3267,7 @@ var spin_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineC
2833
3267
  "stroke-width": "2",
2834
3268
  "stroke-linecap": "round",
2835
3269
  "stroke-linejoin": "round"
2836
- }, [..._cache[0] || (_cache[0] = [createElementVNode("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" }, null, -1)])], 8, _hoisted_1$26))], true)], 6), _ctx.$slots.default || __props.tip ? (openBlock(), createElementBlock("div", {
3270
+ }, [..._cache[0] || (_cache[0] = [createElementVNode("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" }, null, -1)])], 8, _hoisted_1$28))], true)], 6), _ctx.$slots.default || __props.tip ? (openBlock(), createElementBlock("div", {
2837
3271
  key: 0,
2838
3272
  class: normalizeClass(e("text"))
2839
3273
  }, [renderSlot(_ctx.$slots, "default", {}, () => [createTextVNode(toDisplayString(__props.tip), 1)], true)], 2)) : createCommentVNode("v-if", true)], 2);
@@ -2842,8 +3276,8 @@ var spin_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineC
2842
3276
  }), [["__scopeId", "data-v-f72fb3d9"]]);
2843
3277
  //#endregion
2844
3278
  //#region src/components/base/upload/upload.vue
2845
- const _hoisted_1$25 = ["onClick"];
2846
- const _hoisted_2$15 = [
3279
+ const _hoisted_1$27 = ["onClick"];
3280
+ const _hoisted_2$18 = [
2847
3281
  "multiple",
2848
3282
  "accept",
2849
3283
  "disabled"
@@ -2882,7 +3316,6 @@ var upload_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defin
2882
3316
  return `yd-upload__${element}`;
2883
3317
  }
2884
3318
  function getFileIcon(name) {
2885
- const ext = name.split(".").pop()?.toLowerCase();
2886
3319
  return {
2887
3320
  jpg: "🖼️",
2888
3321
  jpeg: "🖼️",
@@ -2905,7 +3338,7 @@ var upload_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defin
2905
3338
  mov: "🎬",
2906
3339
  mp3: "🎵",
2907
3340
  wav: "🎵"
2908
- }[ext || ""] || "📎";
3341
+ }[name.split(".").pop()?.toLowerCase() || ""] || "📎";
2909
3342
  }
2910
3343
  function formatSize(bytes) {
2911
3344
  if (bytes < 1024) return `${bytes} B`;
@@ -2976,7 +3409,7 @@ var upload_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defin
2976
3409
  key: 3,
2977
3410
  class: normalizeClass(e("file-remove")),
2978
3411
  onClick: ($event) => handleRemove(index)
2979
- }, "✕", 10, _hoisted_1$25)) : createCommentVNode("v-if", true)
3412
+ }, "✕", 10, _hoisted_1$27)) : createCommentVNode("v-if", true)
2980
3413
  ], 2);
2981
3414
  }), 128))], 2),
2982
3415
  createElementVNode("div", {
@@ -2997,7 +3430,7 @@ var upload_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defin
2997
3430
  disabled: __props.disabled,
2998
3431
  hidden: "",
2999
3432
  onChange: handleFileChange
3000
- }, null, 40, _hoisted_2$15), renderSlot(_ctx.$slots, "default", {}, () => [createElementVNode("div", { class: normalizeClass(e("trigger-content")) }, [_cache[2] || (_cache[2] = createElementVNode("svg", {
3433
+ }, null, 40, _hoisted_2$18), renderSlot(_ctx.$slots, "default", {}, () => [createElementVNode("div", { class: normalizeClass(e("trigger-content")) }, [_cache[2] || (_cache[2] = createElementVNode("svg", {
3001
3434
  xmlns: "http://www.w3.org/2000/svg",
3002
3435
  width: "32",
3003
3436
  height: "32",
@@ -3027,7 +3460,13 @@ var upload_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defin
3027
3460
  }), [["__scopeId", "data-v-30cb3c39"]]);
3028
3461
  //#endregion
3029
3462
  //#region src/components/base/captcha/captcha.vue
3030
- const _hoisted_1$24 = ["width", "height"];
3463
+ const _hoisted_1$26 = ["width", "height"];
3464
+ const _hoisted_2$17 = [
3465
+ "src",
3466
+ "alt",
3467
+ "width",
3468
+ "height"
3469
+ ];
3031
3470
  var captcha_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineComponent({
3032
3471
  name: "YdCaptcha",
3033
3472
  __name: "captcha",
@@ -3036,7 +3475,10 @@ var captcha_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defi
3036
3475
  width: { default: 120 },
3037
3476
  height: { default: 40 },
3038
3477
  fontSize: { default: 24 },
3039
- bgColor: { default: "#f5f5f5" }
3478
+ bgColor: { default: "#f5f5f5" },
3479
+ src: { default: "" },
3480
+ code: { default: "" },
3481
+ mode: { default: "client" }
3040
3482
  },
3041
3483
  emits: ["change"],
3042
3484
  setup(__props, { expose: __expose, emit: __emit }) {
@@ -3046,7 +3488,7 @@ var captcha_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defi
3046
3488
  return `yd-captcha__${element}`;
3047
3489
  }
3048
3490
  const canvasRef = ref();
3049
- const code = ref("");
3491
+ const generatedCode = ref("");
3050
3492
  function randomColor(min, max) {
3051
3493
  return `rgb(${Math.floor(Math.random() * (max - min) + min)},${Math.floor(Math.random() * (max - min) + min)},${Math.floor(Math.random() * (max - min) + min)})`;
3052
3494
  }
@@ -3063,7 +3505,8 @@ var captcha_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defi
3063
3505
  if (!ctx) return;
3064
3506
  const w = props.width;
3065
3507
  const h = props.height;
3066
- code.value = generateCode();
3508
+ const currentCode = props.code || generateCode();
3509
+ generatedCode.value = currentCode;
3067
3510
  ctx.fillStyle = props.bgColor;
3068
3511
  ctx.fillRect(0, 0, w, h);
3069
3512
  for (let i = 0; i < 5; i++) {
@@ -3081,7 +3524,7 @@ var captcha_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defi
3081
3524
  ctx.fill();
3082
3525
  }
3083
3526
  const charWidth = w / (props.length + 1);
3084
- for (let i = 0; i < code.value.length; i++) {
3527
+ for (let i = 0; i < currentCode.length; i++) {
3085
3528
  ctx.save();
3086
3529
  ctx.font = `${props.fontSize}px Arial`;
3087
3530
  ctx.fillStyle = randomColor(50, 120);
@@ -3091,16 +3534,16 @@ var captcha_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defi
3091
3534
  const angle = (Math.random() - .5) * .4;
3092
3535
  ctx.translate(x, y);
3093
3536
  ctx.rotate(angle);
3094
- ctx.fillText(code.value[i], 0, 0);
3537
+ ctx.fillText(currentCode[i], 0, 0);
3095
3538
  ctx.restore();
3096
3539
  }
3097
- emit("change", code.value);
3540
+ emit("change", currentCode);
3098
3541
  }
3099
3542
  function refresh() {
3100
- draw();
3543
+ if (!props.src) draw();
3101
3544
  }
3102
3545
  __expose({
3103
- code,
3546
+ code: generatedCode,
3104
3547
  refresh
3105
3548
  });
3106
3549
  onMounted(() => {
@@ -3110,34 +3553,54 @@ var captcha_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defi
3110
3553
  props.length,
3111
3554
  props.width,
3112
3555
  props.height,
3113
- props.fontSize
3114
- ], draw);
3556
+ props.fontSize,
3557
+ props.src,
3558
+ props.code,
3559
+ props.mode
3560
+ ], () => {
3561
+ if (props.mode === "server") {
3562
+ generatedCode.value = "";
3563
+ return;
3564
+ }
3565
+ if (!props.src) draw();
3566
+ else {
3567
+ generatedCode.value = props.code || "";
3568
+ emit("change", generatedCode.value);
3569
+ }
3570
+ });
3115
3571
  return (_ctx, _cache) => {
3116
3572
  return openBlock(), createElementBlock("div", {
3117
3573
  class: normalizeClass(unref(cn)("yd-captcha")),
3118
3574
  onClick: refresh
3119
- }, [createElementVNode("canvas", {
3575
+ }, [createCommentVNode(" 客户端生成验证码 "), !__props.src ? (openBlock(), createElementBlock("canvas", {
3576
+ key: 0,
3120
3577
  ref_key: "canvasRef",
3121
3578
  ref: canvasRef,
3122
3579
  class: normalizeClass(e("canvas")),
3123
3580
  width: __props.width,
3124
3581
  height: __props.height
3125
- }, null, 10, _hoisted_1$24)], 2);
3582
+ }, null, 10, _hoisted_1$26)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [createCommentVNode(" 后端提供的图片验证码 "), createElementVNode("img", {
3583
+ class: normalizeClass(e("image")),
3584
+ src: __props.src,
3585
+ alt: __props.code || "验证码",
3586
+ width: __props.width,
3587
+ height: __props.height
3588
+ }, null, 10, _hoisted_2$17)], 2112))], 2);
3126
3589
  };
3127
3590
  }
3128
- }), [["__scopeId", "data-v-90356070"]]);
3591
+ }), [["__scopeId", "data-v-0ad64f93"]]);
3129
3592
  //#endregion
3130
3593
  //#region src/components/base/login/login.vue
3131
- const _hoisted_1$23 = ["onClick"];
3132
- const _hoisted_2$14 = ["placeholder"];
3133
- const _hoisted_3$9 = ["type", "placeholder"];
3134
- const _hoisted_4$8 = ["placeholder"];
3135
- const _hoisted_5$5 = ["placeholder"];
3136
- const _hoisted_6$5 = ["placeholder"];
3137
- const _hoisted_7$4 = ["disabled"];
3138
- const _hoisted_8$4 = ["placeholder"];
3139
- const _hoisted_9$4 = ["disabled"];
3140
- const _hoisted_10$4 = ["title", "onClick"];
3594
+ const _hoisted_1$25 = ["onClick"];
3595
+ const _hoisted_2$16 = ["placeholder"];
3596
+ const _hoisted_3$11 = ["type", "placeholder"];
3597
+ const _hoisted_4$10 = ["placeholder"];
3598
+ const _hoisted_5$7 = ["placeholder"];
3599
+ const _hoisted_6$7 = ["placeholder"];
3600
+ const _hoisted_7$6 = ["disabled"];
3601
+ const _hoisted_8$6 = ["placeholder"];
3602
+ const _hoisted_9$6 = ["disabled"];
3603
+ const _hoisted_10$5 = ["title", "onClick"];
3141
3604
  var login_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineComponent({
3142
3605
  name: "YdLogin",
3143
3606
  __name: "login",
@@ -3211,7 +3674,30 @@ var login_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
3211
3674
  type: Boolean,
3212
3675
  default: true
3213
3676
  },
3214
- captchaPlaceholder: { default: "请输入验证码" }
3677
+ captchaPlaceholder: { default: "请输入验证码" },
3678
+ showOptions: {
3679
+ type: Boolean,
3680
+ default: true
3681
+ },
3682
+ showRemember: {
3683
+ type: Boolean,
3684
+ default: true
3685
+ },
3686
+ showForgot: {
3687
+ type: Boolean,
3688
+ default: true
3689
+ },
3690
+ showAccountLogin: {
3691
+ type: Boolean,
3692
+ default: true
3693
+ },
3694
+ showPhoneLogin: {
3695
+ type: Boolean,
3696
+ default: true
3697
+ },
3698
+ captchaSrc: { default: "" },
3699
+ captchaCode: { default: "" },
3700
+ captchaMode: { default: "client" }
3215
3701
  },
3216
3702
  emits: [
3217
3703
  "submit",
@@ -3226,6 +3712,19 @@ var login_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
3226
3712
  function e(element) {
3227
3713
  return `yd-login__${element}`;
3228
3714
  }
3715
+ const availableTabs = computed(() => {
3716
+ return (props.tabs || []).filter((tab) => {
3717
+ if (tab.key === "account") return props.showAccountLogin;
3718
+ if (tab.key === "phone") return props.showPhoneLogin;
3719
+ return true;
3720
+ });
3721
+ });
3722
+ const activeTab = ref(props.tabs?.[0]?.key || "account");
3723
+ watch(() => [props.showAccountLogin, props.showPhoneLogin], () => {
3724
+ const currentAvailable = availableTabs.value;
3725
+ if (currentAvailable.length === 0) return;
3726
+ if (!currentAvailable.find((t) => t.key === activeTab.value)) activeTab.value = currentAvailable[0].key;
3727
+ }, { immediate: true });
3229
3728
  const formData = reactive({
3230
3729
  username: "",
3231
3730
  password: "",
@@ -3235,7 +3734,6 @@ var login_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
3235
3734
  remember: false
3236
3735
  });
3237
3736
  const showPassword = ref(false);
3238
- const activeTab = ref(props.tabs?.[0]?.key || "account");
3239
3737
  const errorMsg = ref(props.error);
3240
3738
  const countdown = ref(0);
3241
3739
  const captchaKey = ref(0);
@@ -3263,14 +3761,22 @@ var login_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
3263
3761
  }
3264
3762
  function handleSubmit() {
3265
3763
  errorMsg.value = "";
3266
- if (props.showCaptcha && !formData.captchaCode) {
3267
- errorMsg.value = "请输入图片验证码";
3268
- return;
3269
- }
3270
- if (props.showCaptcha && formData.captchaCode.toUpperCase() !== captchaCode.value.toUpperCase()) {
3271
- errorMsg.value = "图片验证码错误";
3272
- captchaKey.value++;
3273
- return;
3764
+ if (props.captchaMode === "server") {
3765
+ if (props.showCaptcha && !formData.captchaCode) {
3766
+ errorMsg.value = "请输入图片验证码";
3767
+ return;
3768
+ }
3769
+ } else {
3770
+ if (props.showCaptcha && !formData.captchaCode) {
3771
+ errorMsg.value = "请输入图片验证码";
3772
+ return;
3773
+ }
3774
+ const expectedCode = props.captchaCode || captchaCode.value;
3775
+ if (props.showCaptcha && formData.captchaCode.toUpperCase() !== expectedCode.toUpperCase()) {
3776
+ errorMsg.value = "图片验证码错误";
3777
+ captchaKey.value++;
3778
+ return;
3779
+ }
3274
3780
  }
3275
3781
  if (activeTab.value === "account") {
3276
3782
  if (!formData.username) {
@@ -3316,28 +3822,28 @@ var login_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
3316
3822
  }), 128))], 2)
3317
3823
  ], 2)], 2), createElementVNode("div", { class: normalizeClass(e("form-section")) }, [createElementVNode("div", { class: normalizeClass(e("form-card")) }, [
3318
3824
  createElementVNode("h2", { class: normalizeClass(e("form-title")) }, toDisplayString(__props.formTitle), 3),
3319
- __props.showTabs ? (openBlock(), createElementBlock("div", {
3825
+ __props.showTabs && availableTabs.value.length > 1 ? (openBlock(), createElementBlock("div", {
3320
3826
  key: 0,
3321
3827
  class: normalizeClass(e("tabs"))
3322
- }, [(openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.tabList, (tab) => {
3828
+ }, [(openBlock(true), createElementBlock(Fragment, null, renderList(availableTabs.value, (tab) => {
3323
3829
  return openBlock(), createElementBlock("button", {
3324
3830
  key: tab.key,
3325
3831
  class: normalizeClass([e("tab"), { [e("tab--active")]: activeTab.value === tab.key }]),
3326
3832
  onClick: ($event) => activeTab.value = tab.key
3327
- }, toDisplayString(tab.label), 11, _hoisted_1$23);
3833
+ }, toDisplayString(tab.label), 11, _hoisted_1$25);
3328
3834
  }), 128))], 2)) : createCommentVNode("v-if", true),
3329
3835
  createElementVNode("form", {
3330
3836
  class: normalizeClass(e("form")),
3331
3837
  onSubmit: withModifiers(handleSubmit, ["prevent"])
3332
3838
  }, [
3333
3839
  createCommentVNode(" Account login "),
3334
- activeTab.value === "account" ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
3840
+ __props.showAccountLogin && activeTab.value === "account" ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
3335
3841
  createElementVNode("div", { class: normalizeClass(e("field")) }, [createElementVNode("div", { class: normalizeClass(e("input-wrapper")) }, [createElementVNode("span", { class: normalizeClass(e("input-icon")) }, "👤", 2), withDirectives(createElementVNode("input", {
3336
3842
  "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => formData.username = $event),
3337
3843
  class: normalizeClass(e("input")),
3338
3844
  placeholder: __props.usernamePlaceholder,
3339
3845
  autocomplete: "username"
3340
- }, null, 10, _hoisted_2$14), [[vModelText, formData.username]])], 2)], 2),
3846
+ }, null, 10, _hoisted_2$16), [[vModelText, formData.username]])], 2)], 2),
3341
3847
  createElementVNode("div", { class: normalizeClass(e("field")) }, [createElementVNode("div", { class: normalizeClass(e("input-wrapper")) }, [
3342
3848
  createElementVNode("span", { class: normalizeClass(e("input-icon")) }, "🔒", 2),
3343
3849
  withDirectives(createElementVNode("input", {
@@ -3346,7 +3852,7 @@ var login_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
3346
3852
  class: normalizeClass(e("input")),
3347
3853
  placeholder: __props.passwordPlaceholder,
3348
3854
  autocomplete: "current-password"
3349
- }, null, 10, _hoisted_3$9), [[vModelDynamic, formData.password]]),
3855
+ }, null, 10, _hoisted_3$11), [[vModelDynamic, formData.password]]),
3350
3856
  createElementVNode("button", {
3351
3857
  type: "button",
3352
3858
  class: normalizeClass(e("toggle-pwd")),
@@ -3366,22 +3872,37 @@ var login_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
3366
3872
  type: "text",
3367
3873
  maxlength: "4",
3368
3874
  autocomplete: "off"
3369
- }, null, 10, _hoisted_4$8), [[vModelText, formData.captchaCode]])], 2), (openBlock(), createBlock(captcha_default, {
3875
+ }, null, 10, _hoisted_4$10), [[vModelText, formData.captchaCode]])], 2), (openBlock(), createBlock(captcha_default, {
3370
3876
  class: normalizeClass(e("captcha-img")),
3877
+ src: __props.captchaSrc,
3878
+ code: captchaCode.value,
3879
+ mode: __props.captchaMode,
3371
3880
  key: captchaKey.value,
3372
3881
  onChange: handleCaptchaChange
3373
- }, null, 8, ["class"]))], 2)], 2)) : createCommentVNode("v-if", true),
3374
- createElementVNode("div", { class: normalizeClass(e("options")) }, [createElementVNode("label", { class: normalizeClass(e("remember")) }, [withDirectives(createElementVNode("input", {
3882
+ }, null, 8, [
3883
+ "class",
3884
+ "src",
3885
+ "code",
3886
+ "mode"
3887
+ ]))], 2)], 2)) : createCommentVNode("v-if", true),
3888
+ __props.showOptions ? (openBlock(), createElementBlock("div", {
3889
+ key: 1,
3890
+ class: normalizeClass(e("options"))
3891
+ }, [__props.showRemember ? (openBlock(), createElementBlock("label", {
3892
+ key: 0,
3893
+ class: normalizeClass(e("remember"))
3894
+ }, [withDirectives(createElementVNode("input", {
3375
3895
  type: "checkbox",
3376
3896
  "onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => formData.remember = $event)
3377
- }, null, 512), [[vModelCheckbox, formData.remember]]), createElementVNode("span", null, toDisplayString(__props.rememberText), 1)], 2), createElementVNode("a", {
3897
+ }, null, 512), [[vModelCheckbox, formData.remember]]), createElementVNode("span", null, toDisplayString(__props.rememberText), 1)], 2)) : createCommentVNode("v-if", true), __props.showForgot ? (openBlock(), createElementBlock("a", {
3898
+ key: 1,
3378
3899
  class: normalizeClass(e("forgot")),
3379
3900
  href: "javascript:void(0)",
3380
3901
  onClick: _cache[5] || (_cache[5] = ($event) => _ctx.$emit("forgot-password"))
3381
- }, toDisplayString(__props.forgotText), 3)], 2)
3902
+ }, toDisplayString(__props.forgotText), 3)) : createCommentVNode("v-if", true)], 2)) : createCommentVNode("v-if", true)
3382
3903
  ], 64)) : createCommentVNode("v-if", true),
3383
3904
  createCommentVNode(" Phone login "),
3384
- activeTab.value === "phone" ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [
3905
+ __props.showPhoneLogin && activeTab.value === "phone" ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [
3385
3906
  createElementVNode("div", { class: normalizeClass(e("field")) }, [createElementVNode("div", { class: normalizeClass(e("input-wrapper")) }, [createElementVNode("span", { class: normalizeClass(e("input-icon")) }, "📱", 2), withDirectives(createElementVNode("input", {
3386
3907
  "onUpdate:modelValue": _cache[6] || (_cache[6] = ($event) => formData.phone = $event),
3387
3908
  class: normalizeClass(e("input")),
@@ -3389,7 +3910,7 @@ var login_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
3389
3910
  type: "tel",
3390
3911
  maxlength: "11",
3391
3912
  autocomplete: "tel"
3392
- }, null, 10, _hoisted_5$5), [[vModelText, formData.phone]])], 2)], 2),
3913
+ }, null, 10, _hoisted_5$7), [[vModelText, formData.phone]])], 2)], 2),
3393
3914
  createElementVNode("div", { class: normalizeClass(e("field")) }, [createElementVNode("div", { class: normalizeClass(e("input-wrapper")) }, [
3394
3915
  createElementVNode("span", { class: normalizeClass(e("input-icon")) }, "🔑", 2),
3395
3916
  withDirectives(createElementVNode("input", {
@@ -3399,13 +3920,13 @@ var login_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
3399
3920
  type: "text",
3400
3921
  maxlength: "6",
3401
3922
  autocomplete: "one-time-code"
3402
- }, null, 10, _hoisted_6$5), [[vModelText, formData.code]]),
3923
+ }, null, 10, _hoisted_6$7), [[vModelText, formData.code]]),
3403
3924
  createElementVNode("button", {
3404
3925
  type: "button",
3405
3926
  class: normalizeClass([e("send-code"), { [e("send-code--disabled")]: countdown.value > 0 }]),
3406
3927
  disabled: countdown.value > 0,
3407
3928
  onClick: handleSendCode
3408
- }, toDisplayString(countdown.value > 0 ? `${countdown.value}s` : __props.sendCodeText), 11, _hoisted_7$4)
3929
+ }, toDisplayString(countdown.value > 0 ? `${countdown.value}s` : __props.sendCodeText), 11, _hoisted_7$6)
3409
3930
  ], 2)], 2),
3410
3931
  __props.showCaptcha ? (openBlock(), createElementBlock("div", {
3411
3932
  key: 0,
@@ -3420,19 +3941,34 @@ var login_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
3420
3941
  type: "text",
3421
3942
  maxlength: "4",
3422
3943
  autocomplete: "off"
3423
- }, null, 10, _hoisted_8$4), [[vModelText, formData.captchaCode]])], 2), (openBlock(), createBlock(captcha_default, {
3944
+ }, null, 10, _hoisted_8$6), [[vModelText, formData.captchaCode]])], 2), (openBlock(), createBlock(captcha_default, {
3424
3945
  class: normalizeClass(e("captcha-img")),
3946
+ src: __props.captchaSrc,
3947
+ code: captchaCode.value,
3948
+ mode: __props.captchaMode,
3425
3949
  key: captchaKey.value,
3426
3950
  onChange: handleCaptchaChange
3427
- }, null, 8, ["class"]))], 2)], 2)) : createCommentVNode("v-if", true),
3428
- createElementVNode("div", { class: normalizeClass(e("options")) }, [createElementVNode("label", { class: normalizeClass(e("remember")) }, [withDirectives(createElementVNode("input", {
3951
+ }, null, 8, [
3952
+ "class",
3953
+ "src",
3954
+ "code",
3955
+ "mode"
3956
+ ]))], 2)], 2)) : createCommentVNode("v-if", true),
3957
+ __props.showOptions ? (openBlock(), createElementBlock("div", {
3958
+ key: 1,
3959
+ class: normalizeClass(e("options"))
3960
+ }, [__props.showRemember ? (openBlock(), createElementBlock("label", {
3961
+ key: 0,
3962
+ class: normalizeClass(e("remember"))
3963
+ }, [withDirectives(createElementVNode("input", {
3429
3964
  type: "checkbox",
3430
3965
  "onUpdate:modelValue": _cache[9] || (_cache[9] = ($event) => formData.remember = $event)
3431
- }, null, 512), [[vModelCheckbox, formData.remember]]), createElementVNode("span", null, toDisplayString(__props.rememberText), 1)], 2), createElementVNode("a", {
3966
+ }, null, 512), [[vModelCheckbox, formData.remember]]), createElementVNode("span", null, toDisplayString(__props.rememberText), 1)], 2)) : createCommentVNode("v-if", true), __props.showForgot ? (openBlock(), createElementBlock("a", {
3967
+ key: 1,
3432
3968
  class: normalizeClass(e("forgot")),
3433
3969
  href: "javascript:void(0)",
3434
3970
  onClick: _cache[10] || (_cache[10] = ($event) => _ctx.$emit("forgot-password"))
3435
- }, toDisplayString(__props.forgotText), 3)], 2)
3971
+ }, toDisplayString(__props.forgotText), 3)) : createCommentVNode("v-if", true)], 2)) : createCommentVNode("v-if", true)
3436
3972
  ], 64)) : createCommentVNode("v-if", true),
3437
3973
  errorMsg.value ? (openBlock(), createElementBlock("div", {
3438
3974
  key: 2,
@@ -3445,7 +3981,7 @@ var login_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
3445
3981
  }, [__props.loading ? (openBlock(), createElementBlock("span", {
3446
3982
  key: 0,
3447
3983
  class: normalizeClass(e("spinner"))
3448
- }, null, 2)) : createCommentVNode("v-if", true), createTextVNode(" " + toDisplayString(__props.loading ? __props.loadingText : __props.submitText), 1)], 10, _hoisted_9$4)
3984
+ }, null, 2)) : createCommentVNode("v-if", true), createTextVNode(" " + toDisplayString(__props.loading ? __props.loadingText : __props.submitText), 1)], 10, _hoisted_9$6)
3449
3985
  ], 34),
3450
3986
  __props.showSocial ? (openBlock(), createElementBlock("div", {
3451
3987
  key: 1,
@@ -3460,20 +3996,20 @@ var login_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
3460
3996
  class: normalizeClass(e("social-btn")),
3461
3997
  title: social.label,
3462
3998
  onClick: ($event) => _ctx.$emit("social-login", social.key)
3463
- }, toDisplayString(social.icon), 11, _hoisted_10$4);
3999
+ }, toDisplayString(social.icon), 11, _hoisted_10$5);
3464
4000
  }), 128))], 2)) : createCommentVNode("v-if", true),
3465
4001
  createElementVNode("div", { class: normalizeClass(e("footer-links")) }, [renderSlot(_ctx.$slots, "footer", {}, () => [createElementVNode("span", null, toDisplayString(__props.footerText), 1)], true)], 2)
3466
4002
  ], 2)], 2)], 2)], 2);
3467
4003
  };
3468
4004
  }
3469
- }), [["__scopeId", "data-v-4d9537f6"]]);
4005
+ }), [["__scopeId", "data-v-a965dc29"]]);
3470
4006
  //#endregion
3471
4007
  //#region src/components/base/login/login-centered.vue
3472
- const _hoisted_1$22 = ["fill"];
3473
- const _hoisted_2$13 = ["onClick"];
3474
- const _hoisted_3$8 = ["placeholder"];
3475
- const _hoisted_4$7 = ["type", "placeholder"];
3476
- const _hoisted_5$4 = {
4008
+ const _hoisted_1$24 = ["fill"];
4009
+ const _hoisted_2$15 = ["onClick"];
4010
+ const _hoisted_3$10 = ["placeholder"];
4011
+ const _hoisted_4$9 = ["type", "placeholder"];
4012
+ const _hoisted_5$6 = {
3477
4013
  key: 0,
3478
4014
  width: "18",
3479
4015
  height: "18",
@@ -3482,7 +4018,7 @@ const _hoisted_5$4 = {
3482
4018
  stroke: "currentColor",
3483
4019
  "stroke-width": "2"
3484
4020
  };
3485
- const _hoisted_6$4 = {
4021
+ const _hoisted_6$6 = {
3486
4022
  key: 1,
3487
4023
  width: "18",
3488
4024
  height: "18",
@@ -3491,12 +4027,12 @@ const _hoisted_6$4 = {
3491
4027
  stroke: "currentColor",
3492
4028
  "stroke-width": "2"
3493
4029
  };
3494
- const _hoisted_7$3 = ["placeholder"];
3495
- const _hoisted_8$3 = ["placeholder"];
3496
- const _hoisted_9$3 = ["disabled"];
3497
- const _hoisted_10$3 = ["placeholder"];
3498
- const _hoisted_11$3 = ["disabled"];
3499
- const _hoisted_12$3 = ["title", "onClick"];
4030
+ const _hoisted_7$5 = ["placeholder"];
4031
+ const _hoisted_8$5 = ["placeholder"];
4032
+ const _hoisted_9$5 = ["disabled"];
4033
+ const _hoisted_10$4 = ["placeholder"];
4034
+ const _hoisted_11$4 = ["disabled"];
4035
+ const _hoisted_12$4 = ["title", "onClick"];
3500
4036
  var login_centered_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineComponent({
3501
4037
  name: "YdLoginCentered",
3502
4038
  __name: "login-centered",
@@ -3710,7 +4246,7 @@ var login_centered_default = /* @__PURE__ */ export_helper_default(/* @__PURE__
3710
4246
  height: "40",
3711
4247
  rx: "8",
3712
4248
  fill: __props.theme === "dark" ? "#6366f1" : "#4f46e5"
3713
- }, null, 8, _hoisted_1$22), _cache[8] || (_cache[8] = createElementVNode("path", {
4249
+ }, null, 8, _hoisted_1$24), _cache[8] || (_cache[8] = createElementVNode("path", {
3714
4250
  d: "M12 20L18 26L28 14",
3715
4251
  stroke: "#fff",
3716
4252
  "stroke-width": "3",
@@ -3728,7 +4264,7 @@ var login_centered_default = /* @__PURE__ */ export_helper_default(/* @__PURE__
3728
4264
  key: tab.key,
3729
4265
  class: normalizeClass([e("tab"), { [e("tab--active")]: activeTab.value === tab.key }]),
3730
4266
  onClick: ($event) => activeTab.value = tab.key
3731
- }, toDisplayString(tab.label), 11, _hoisted_2$13);
4267
+ }, toDisplayString(tab.label), 11, _hoisted_2$15);
3732
4268
  }), 128))], 2)) : createCommentVNode("v-if", true),
3733
4269
  createElementVNode("form", {
3734
4270
  class: normalizeClass(e("form")),
@@ -3751,7 +4287,7 @@ var login_centered_default = /* @__PURE__ */ export_helper_default(/* @__PURE__
3751
4287
  class: normalizeClass(e("input")),
3752
4288
  placeholder: __props.usernamePlaceholder,
3753
4289
  autocomplete: "username"
3754
- }, null, 10, _hoisted_3$8), [[vModelText, formData.username]])], 2)], 2), createElementVNode("div", { class: normalizeClass(e("field")) }, [createElementVNode("label", { class: normalizeClass(e("label")) }, toDisplayString(__props.passwordLabel), 3), createElementVNode("div", { class: normalizeClass(e("input-group")) }, [
4290
+ }, null, 10, _hoisted_3$10), [[vModelText, formData.username]])], 2)], 2), createElementVNode("div", { class: normalizeClass(e("field")) }, [createElementVNode("label", { class: normalizeClass(e("label")) }, toDisplayString(__props.passwordLabel), 3), createElementVNode("div", { class: normalizeClass(e("input-group")) }, [
3755
4291
  createElementVNode("span", { class: normalizeClass(e("input-prefix")) }, [..._cache[10] || (_cache[10] = [createElementVNode("svg", {
3756
4292
  width: "18",
3757
4293
  height: "18",
@@ -3773,16 +4309,16 @@ var login_centered_default = /* @__PURE__ */ export_helper_default(/* @__PURE__
3773
4309
  class: normalizeClass(e("input")),
3774
4310
  placeholder: __props.passwordPlaceholder,
3775
4311
  autocomplete: "current-password"
3776
- }, null, 10, _hoisted_4$7), [[vModelDynamic, formData.password]]),
4312
+ }, null, 10, _hoisted_4$9), [[vModelDynamic, formData.password]]),
3777
4313
  createElementVNode("button", {
3778
4314
  type: "button",
3779
4315
  class: normalizeClass(e("input-suffix")),
3780
4316
  onClick: _cache[2] || (_cache[2] = ($event) => showPassword.value = !showPassword.value)
3781
- }, [!showPassword.value ? (openBlock(), createElementBlock("svg", _hoisted_5$4, [..._cache[11] || (_cache[11] = [createElementVNode("path", { d: "M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" }, null, -1), createElementVNode("circle", {
4317
+ }, [!showPassword.value ? (openBlock(), createElementBlock("svg", _hoisted_5$6, [..._cache[11] || (_cache[11] = [createElementVNode("path", { d: "M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" }, null, -1), createElementVNode("circle", {
3782
4318
  cx: "12",
3783
4319
  cy: "12",
3784
4320
  r: "3"
3785
- }, null, -1)])])) : (openBlock(), createElementBlock("svg", _hoisted_6$4, [..._cache[12] || (_cache[12] = [createElementVNode("path", { d: "M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24" }, null, -1), createElementVNode("line", {
4321
+ }, null, -1)])])) : (openBlock(), createElementBlock("svg", _hoisted_6$6, [..._cache[12] || (_cache[12] = [createElementVNode("path", { d: "M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24" }, null, -1), createElementVNode("line", {
3786
4322
  x1: "1",
3787
4323
  y1: "1",
3788
4324
  x2: "23",
@@ -3816,7 +4352,7 @@ var login_centered_default = /* @__PURE__ */ export_helper_default(/* @__PURE__
3816
4352
  type: "tel",
3817
4353
  maxlength: "11",
3818
4354
  autocomplete: "tel"
3819
- }, null, 10, _hoisted_7$3), [[vModelText, formData.phone]])], 2)], 2), createElementVNode("div", { class: normalizeClass(e("field")) }, [createElementVNode("label", { class: normalizeClass(e("label")) }, toDisplayString(__props.codeLabel), 3), createElementVNode("div", { class: normalizeClass(e("input-group")) }, [
4355
+ }, null, 10, _hoisted_7$5), [[vModelText, formData.phone]])], 2)], 2), createElementVNode("div", { class: normalizeClass(e("field")) }, [createElementVNode("label", { class: normalizeClass(e("label")) }, toDisplayString(__props.codeLabel), 3), createElementVNode("div", { class: normalizeClass(e("input-group")) }, [
3820
4356
  createElementVNode("span", { class: normalizeClass(e("input-prefix")) }, [..._cache[14] || (_cache[14] = [createElementVNode("svg", {
3821
4357
  width: "18",
3822
4358
  height: "18",
@@ -3839,13 +4375,13 @@ var login_centered_default = /* @__PURE__ */ export_helper_default(/* @__PURE__
3839
4375
  type: "text",
3840
4376
  maxlength: "6",
3841
4377
  autocomplete: "one-time-code"
3842
- }, null, 10, _hoisted_8$3), [[vModelText, formData.code]]),
4378
+ }, null, 10, _hoisted_8$5), [[vModelText, formData.code]]),
3843
4379
  createElementVNode("button", {
3844
4380
  type: "button",
3845
4381
  class: normalizeClass([e("send-code"), { [e("send-code--disabled")]: countdown.value > 0 }]),
3846
4382
  disabled: countdown.value > 0,
3847
4383
  onClick: handleSendCode
3848
- }, toDisplayString(countdown.value > 0 ? `${countdown.value}s` : __props.sendCodeText), 11, _hoisted_9$3)
4384
+ }, toDisplayString(countdown.value > 0 ? `${countdown.value}s` : __props.sendCodeText), 11, _hoisted_9$5)
3849
4385
  ], 2)], 2)], 64)) : createCommentVNode("v-if", true),
3850
4386
  createCommentVNode(" Captcha (shared) "),
3851
4387
  __props.showCaptcha ? (openBlock(), createElementBlock("div", {
@@ -3867,7 +4403,7 @@ var login_centered_default = /* @__PURE__ */ export_helper_default(/* @__PURE__
3867
4403
  type: "text",
3868
4404
  maxlength: "4",
3869
4405
  autocomplete: "off"
3870
- }, null, 10, _hoisted_10$3), [[vModelText, formData.captchaCode]]),
4406
+ }, null, 10, _hoisted_10$4), [[vModelText, formData.captchaCode]]),
3871
4407
  (openBlock(), createBlock(captcha_default, {
3872
4408
  class: normalizeClass(e("captcha-img")),
3873
4409
  key: captchaKey.value,
@@ -3919,7 +4455,7 @@ var login_centered_default = /* @__PURE__ */ export_helper_default(/* @__PURE__
3919
4455
  }, [__props.loading ? (openBlock(), createElementBlock("span", {
3920
4456
  key: 0,
3921
4457
  class: normalizeClass(e("spinner"))
3922
- }, null, 2)) : createCommentVNode("v-if", true), createTextVNode(" " + toDisplayString(__props.loading ? __props.loadingText : __props.submitText), 1)], 10, _hoisted_11$3)
4458
+ }, null, 2)) : createCommentVNode("v-if", true), createTextVNode(" " + toDisplayString(__props.loading ? __props.loadingText : __props.submitText), 1)], 10, _hoisted_11$4)
3923
4459
  ], 34),
3924
4460
  __props.showSocial ? (openBlock(), createElementBlock("div", {
3925
4461
  key: 1,
@@ -3930,16 +4466,16 @@ var login_centered_default = /* @__PURE__ */ export_helper_default(/* @__PURE__
3930
4466
  class: normalizeClass(e("social-icon")),
3931
4467
  title: social.label,
3932
4468
  onClick: ($event) => _ctx.$emit("social-login", social.key)
3933
- }, [(openBlock(), createBlock(resolveDynamicComponent(social.icon)))], 10, _hoisted_12$3);
4469
+ }, [(openBlock(), createBlock(resolveDynamicComponent(social.icon)))], 10, _hoisted_12$4);
3934
4470
  }), 128))], 2)], 2)) : createCommentVNode("v-if", true),
3935
4471
  createElementVNode("div", { class: normalizeClass(e("footer-text")) }, [renderSlot(_ctx.$slots, "footer", {}, () => [createTextVNode(toDisplayString(__props.footerText), 1)], true)], 2)
3936
4472
  ], 2)], 2);
3937
4473
  };
3938
4474
  }
3939
- }), [["__scopeId", "data-v-51d3fc32"]]);
4475
+ }), [["__scopeId", "data-v-be643e6b"]]);
3940
4476
  //#endregion
3941
4477
  //#region src/components/base/pin-input/pin-input.vue
3942
- const _hoisted_1$21 = [
4478
+ const _hoisted_1$23 = [
3943
4479
  "value",
3944
4480
  "disabled",
3945
4481
  "onInput",
@@ -4049,7 +4585,7 @@ var pin_input_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ de
4049
4585
  onFocus: ($event) => focusedIndex.value = i - 1,
4050
4586
  onBlur: _cache[0] || (_cache[0] = ($event) => focusedIndex.value = -1),
4051
4587
  onPaste: handlePaste
4052
- }, null, 42, _hoisted_1$21);
4588
+ }, null, 42, _hoisted_1$23);
4053
4589
  }), 128))], 2), __props.error ? (openBlock(), createElementBlock("div", {
4054
4590
  key: 0,
4055
4591
  class: normalizeClass(e("error"))
@@ -4058,15 +4594,1113 @@ var pin_input_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ de
4058
4594
  }
4059
4595
  }), [["__scopeId", "data-v-fd187d50"]]);
4060
4596
  //#endregion
4061
- //#region src/composables/use-form-validate.ts
4062
- /**
4063
- * 获取 AsyncValidator 构造函数
4064
- * 处理 ES Module default export 和 CommonJS 两种导出方式
4065
- */
4066
- function getAsyncValidatorSchema() {
4067
- if (typeof AsyncValidator === "object" && AsyncValidator !== null && "default" in AsyncValidator) return AsyncValidator.default;
4068
- return AsyncValidator;
4069
- }
4597
+ //#region src/components/base/tree-select/tree-select.vue
4598
+ const _hoisted_1$22 = [
4599
+ "value",
4600
+ "placeholder",
4601
+ "disabled"
4602
+ ];
4603
+ const _hoisted_2$14 = ["onClick"];
4604
+ const _hoisted_3$9 = ["onClick"];
4605
+ const _hoisted_4$8 = ["onClick"];
4606
+ const _hoisted_5$5 = [
4607
+ "checked",
4608
+ "indeterminate",
4609
+ "disabled"
4610
+ ];
4611
+ const _hoisted_6$5 = ["onClick"];
4612
+ const _hoisted_7$4 = ["onClick"];
4613
+ const _hoisted_8$4 = ["onClick"];
4614
+ const _hoisted_9$4 = [
4615
+ "checked",
4616
+ "indeterminate",
4617
+ "disabled"
4618
+ ];
4619
+ const _hoisted_10$3 = ["onClick"];
4620
+ const _hoisted_11$3 = ["onClick"];
4621
+ const _hoisted_12$3 = ["onClick"];
4622
+ const _hoisted_13$2 = [
4623
+ "checked",
4624
+ "indeterminate",
4625
+ "disabled"
4626
+ ];
4627
+ var tree_select_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineComponent({
4628
+ name: "YdTreeSelect",
4629
+ inheritAttrs: false,
4630
+ __name: "tree-select",
4631
+ props: {
4632
+ modelValue: { default: "" },
4633
+ placeholder: { default: "请选择" },
4634
+ disabled: {
4635
+ type: Boolean,
4636
+ default: false
4637
+ },
4638
+ multiple: {
4639
+ type: Boolean,
4640
+ default: false
4641
+ },
4642
+ size: { default: "md" },
4643
+ variant: { default: "default" },
4644
+ label: { default: "" },
4645
+ required: {
4646
+ type: Boolean,
4647
+ default: false
4648
+ },
4649
+ error: { default: "" },
4650
+ hint: { default: "" },
4651
+ treeData: { default: () => [] },
4652
+ defaultExpandedKeys: { default: () => [] },
4653
+ defaultCheckedKeys: { default: () => [] },
4654
+ checkable: {
4655
+ type: Boolean,
4656
+ default: false
4657
+ },
4658
+ filterable: {
4659
+ type: Boolean,
4660
+ default: false
4661
+ },
4662
+ clearable: {
4663
+ type: Boolean,
4664
+ default: false
4665
+ },
4666
+ dropdownHeight: { default: 240 },
4667
+ virtualScroll: {
4668
+ type: Boolean,
4669
+ default: false
4670
+ },
4671
+ rowHeight: { default: 32 },
4672
+ overscan: { default: 5 }
4673
+ },
4674
+ emits: [
4675
+ "update:modelValue",
4676
+ "change",
4677
+ "focus",
4678
+ "blur",
4679
+ "check"
4680
+ ],
4681
+ setup(__props, { emit: __emit }) {
4682
+ useCssVars((_ctx) => ({ "v23cc09d6": _ctx.dropdownHeight + "px" }));
4683
+ const props = __props;
4684
+ const emit = __emit;
4685
+ const selectRef = ref();
4686
+ const visible = ref(false);
4687
+ const searchText = ref("");
4688
+ const expandedKeys = ref(props.defaultExpandedKeys);
4689
+ const checkedKeys = ref([...props.defaultCheckedKeys]);
4690
+ const indeterminateKeys = ref([]);
4691
+ const scrollTop = ref(0);
4692
+ const cachedDropdownStyle = ref({});
4693
+ function updateDropdownPosition() {
4694
+ if (!selectRef.value || !visible.value) return;
4695
+ const rect = selectRef.value.getBoundingClientRect();
4696
+ cachedDropdownStyle.value = {
4697
+ position: "fixed",
4698
+ top: `${rect.bottom + 4}px`,
4699
+ left: `${rect.left}px`,
4700
+ width: `${rect.width}px`,
4701
+ zIndex: "2000",
4702
+ willChange: "transform"
4703
+ };
4704
+ }
4705
+ function handleWindowScroll() {
4706
+ if (visible.value) updateDropdownPosition();
4707
+ }
4708
+ function handleWindowResize() {
4709
+ if (visible.value) updateDropdownPosition();
4710
+ }
4711
+ const flattenTree = (nodes, level = 0) => {
4712
+ const result = [];
4713
+ for (const node of nodes) {
4714
+ result.push({
4715
+ ...node,
4716
+ level
4717
+ });
4718
+ if (node.children && expandedKeys.value.includes(node.key)) result.push(...flattenTree(node.children, level + 1));
4719
+ }
4720
+ return result;
4721
+ };
4722
+ const flatNodes = computed(() => flattenTree(props.treeData));
4723
+ const totalHeight = computed(() => flatNodes.value.length * props.rowHeight);
4724
+ const startIndex = computed(() => {
4725
+ if (!props.virtualScroll) return 0;
4726
+ return Math.max(0, Math.floor(scrollTop.value / props.rowHeight) - props.overscan);
4727
+ });
4728
+ const visibleCount = computed(() => {
4729
+ if (!props.virtualScroll) return flatNodes.value.length;
4730
+ return Math.ceil(props.dropdownHeight / props.rowHeight) + props.overscan * 2;
4731
+ });
4732
+ const visibleNodes = computed(() => {
4733
+ if (!props.virtualScroll) return flatNodes.value;
4734
+ return flatNodes.value.slice(startIndex.value, startIndex.value + visibleCount.value);
4735
+ });
4736
+ function handleScroll(e) {
4737
+ scrollTop.value = e.target.scrollTop;
4738
+ }
4739
+ const virtualHeight = computed(() => `${props.dropdownHeight}px`);
4740
+ const wrapperClasses = computed(() => cn("yd-tree-select-wrapper", `yd-tree-select-wrapper--${props.size}`, `yd-tree-select-wrapper--${props.variant}`, props.disabled && "yd-tree-select-wrapper--disabled", props.error && "yd-tree-select-wrapper--error"));
4741
+ const dropdownStyle = computed(() => cachedDropdownStyle.value);
4742
+ const displayPlaceholder = computed(() => {
4743
+ if (props.multiple) return selectedTitles.value.length > 0 ? selectedTitles.value.join(", ") : props.placeholder;
4744
+ return selectedTitle.value || props.placeholder;
4745
+ });
4746
+ const hasValue = computed(() => {
4747
+ if (props.multiple) return Array.isArray(props.modelValue) && props.modelValue.length > 0;
4748
+ return props.modelValue !== "" && props.modelValue !== void 0;
4749
+ });
4750
+ const selectedTitle = computed(() => {
4751
+ if (props.multiple) return "";
4752
+ return findNodeTitle(props.treeData, String(props.modelValue));
4753
+ });
4754
+ const selectedTitles = computed(() => {
4755
+ if (!props.multiple || !Array.isArray(props.modelValue)) return [];
4756
+ return props.modelValue.map((v) => findNodeTitle(props.treeData, String(v)));
4757
+ });
4758
+ function findNodeTitle(nodes, key) {
4759
+ for (const node of nodes) {
4760
+ if (node.key === key) return node.title;
4761
+ if (node.children) {
4762
+ const found = findNodeTitle(node.children, key);
4763
+ if (found) return found;
4764
+ }
4765
+ }
4766
+ return "";
4767
+ }
4768
+ const filteredNodes = computed(() => {
4769
+ if (!props.filterable || !searchText.value) return props.treeData;
4770
+ const query = searchText.value.toLowerCase();
4771
+ return filterNodes(props.treeData, query);
4772
+ });
4773
+ function filterNodes(nodes, query) {
4774
+ const result = [];
4775
+ for (const node of nodes) {
4776
+ const titleMatch = node.title.toLowerCase().includes(query);
4777
+ const children = node.children ? filterNodes(node.children, query) : [];
4778
+ if (titleMatch || children.length > 0) result.push({
4779
+ ...node,
4780
+ children: children.length > 0 ? children : node.children
4781
+ });
4782
+ }
4783
+ return result;
4784
+ }
4785
+ function e(element) {
4786
+ return `yd-tree-select__${element}`;
4787
+ }
4788
+ function hasChildren(node) {
4789
+ return !!(node.children && node.children.length > 0) && node.isLeaf !== true;
4790
+ }
4791
+ function nodeClasses(node) {
4792
+ const isSelected = props.multiple ? Array.isArray(props.modelValue) && props.modelValue.includes(node.key) : props.modelValue === node.key;
4793
+ return [e("node"), {
4794
+ [e("node--selected")]: isSelected,
4795
+ [e("node--disabled")]: node.disabled
4796
+ }];
4797
+ }
4798
+ function handleNodeClick(node) {
4799
+ if (node.disabled) return;
4800
+ if (props.checkable) {
4801
+ handleCheck(node);
4802
+ return;
4803
+ }
4804
+ if (props.multiple) {
4805
+ const current = Array.isArray(props.modelValue) ? [...props.modelValue] : [];
4806
+ const idx = current.indexOf(node.key);
4807
+ if (idx > -1) current.splice(idx, 1);
4808
+ else current.push(node.key);
4809
+ emit("update:modelValue", current);
4810
+ emit("change", current);
4811
+ } else {
4812
+ emit("update:modelValue", node.key);
4813
+ emit("change", node.key);
4814
+ visible.value = false;
4815
+ searchText.value = "";
4816
+ }
4817
+ }
4818
+ function handleToggle(node) {
4819
+ const idx = expandedKeys.value.indexOf(node.key);
4820
+ if (idx > -1) expandedKeys.value.splice(idx, 1);
4821
+ else expandedKeys.value.push(node.key);
4822
+ }
4823
+ function handleCheck(node) {
4824
+ if (node.disabled) return;
4825
+ const idx = checkedKeys.value.indexOf(node.key);
4826
+ if (idx > -1) {
4827
+ checkedKeys.value.splice(idx, 1);
4828
+ uncheckDescendants(node);
4829
+ } else {
4830
+ checkedKeys.value.push(node.key);
4831
+ checkDescendants(node);
4832
+ }
4833
+ updateParentCheckState();
4834
+ emit("update:modelValue", props.multiple ? [...checkedKeys.value] : checkedKeys.value[0] || "");
4835
+ emit("change", props.multiple ? [...checkedKeys.value] : checkedKeys.value[0] || "");
4836
+ emit("check", [...checkedKeys.value]);
4837
+ }
4838
+ function checkDescendants(node) {
4839
+ if (!node.children) return;
4840
+ for (const child of node.children) {
4841
+ if (!checkedKeys.value.includes(child.key)) checkedKeys.value.push(child.key);
4842
+ checkDescendants(child);
4843
+ }
4844
+ }
4845
+ function uncheckDescendants(node) {
4846
+ if (!node.children) return;
4847
+ for (const child of node.children) {
4848
+ const idx = checkedKeys.value.indexOf(child.key);
4849
+ if (idx > -1) checkedKeys.value.splice(idx, 1);
4850
+ uncheckDescendants(child);
4851
+ }
4852
+ }
4853
+ function updateParentCheckState() {
4854
+ indeterminateKeys.value = [];
4855
+ }
4856
+ function handleClear() {
4857
+ if (props.multiple) {
4858
+ emit("update:modelValue", []);
4859
+ emit("change", []);
4860
+ } else {
4861
+ emit("update:modelValue", "");
4862
+ emit("change", "");
4863
+ }
4864
+ checkedKeys.value = [];
4865
+ searchText.value = "";
4866
+ }
4867
+ function toggleDropdown() {
4868
+ if (props.disabled) return;
4869
+ visible.value = !visible.value;
4870
+ if (visible.value) {
4871
+ searchText.value = "";
4872
+ if (!props.multiple && expandedKeys.value.length === 0) expandedKeys.value = props.treeData.map((n) => n.key);
4873
+ nextTick(() => {
4874
+ updateDropdownPosition();
4875
+ selectRef.value?.querySelector("input")?.focus();
4876
+ });
4877
+ }
4878
+ }
4879
+ const debouncedFilter = debounce(() => {}, 300);
4880
+ function handleSearch(event) {
4881
+ searchText.value = event.target.value;
4882
+ debouncedFilter();
4883
+ if (!visible.value) visible.value = true;
4884
+ }
4885
+ function handleFocus(event) {
4886
+ emit("focus", event);
4887
+ }
4888
+ function handleBlur(event) {
4889
+ if (props.multiple) return;
4890
+ setTimeout(() => {
4891
+ visible.value = false;
4892
+ }, 200);
4893
+ emit("blur", event);
4894
+ }
4895
+ function handleClickOutside(event) {
4896
+ if (selectRef.value && !selectRef.value.contains(event.target)) visible.value = false;
4897
+ }
4898
+ onMounted(() => {
4899
+ document.addEventListener("click", handleClickOutside);
4900
+ window.addEventListener("scroll", handleWindowScroll, true);
4901
+ window.addEventListener("resize", handleWindowResize);
4902
+ });
4903
+ onUnmounted(() => {
4904
+ document.removeEventListener("click", handleClickOutside);
4905
+ window.removeEventListener("scroll", handleWindowScroll, true);
4906
+ window.removeEventListener("resize", handleWindowResize);
4907
+ });
4908
+ return (_ctx, _cache) => {
4909
+ return openBlock(), createElementBlock("div", {
4910
+ ref_key: "selectRef",
4911
+ ref: selectRef,
4912
+ class: normalizeClass(wrapperClasses.value),
4913
+ onClick: toggleDropdown
4914
+ }, [
4915
+ __props.label ? (openBlock(), createElementBlock("div", {
4916
+ key: 0,
4917
+ class: normalizeClass(e("label"))
4918
+ }, [createElementVNode("label", null, toDisplayString(__props.label), 1), __props.required ? (openBlock(), createElementBlock("span", {
4919
+ key: 0,
4920
+ class: normalizeClass(e("required"))
4921
+ }, "*", 2)) : createCommentVNode("v-if", true)], 2)) : createCommentVNode("v-if", true),
4922
+ createElementVNode("div", { class: normalizeClass(e("control")) }, [
4923
+ __props.filterable ? (openBlock(), createElementBlock("input", {
4924
+ key: 0,
4925
+ class: normalizeClass(e("input")),
4926
+ value: searchText.value,
4927
+ placeholder: displayPlaceholder.value,
4928
+ disabled: __props.disabled,
4929
+ onInput: handleSearch,
4930
+ onFocus: handleFocus,
4931
+ onBlur: handleBlur,
4932
+ onKeydown: _cache[0] || (_cache[0] = withModifiers(() => {}, ["stop"]))
4933
+ }, null, 42, _hoisted_1$22)) : (openBlock(), createElementBlock("div", {
4934
+ key: 1,
4935
+ class: normalizeClass([e("display"), { [e("display--placeholder")]: !selectedTitle.value }])
4936
+ }, toDisplayString(selectedTitle.value || __props.placeholder), 3)),
4937
+ __props.clearable && hasValue.value && !__props.disabled ? (openBlock(), createElementBlock("span", {
4938
+ key: 2,
4939
+ class: normalizeClass(e("clear")),
4940
+ onClick: withModifiers(handleClear, ["stop"])
4941
+ }, [..._cache[2] || (_cache[2] = [createElementVNode("svg", {
4942
+ xmlns: "http://www.w3.org/2000/svg",
4943
+ width: "14",
4944
+ height: "14",
4945
+ viewBox: "0 0 24 24",
4946
+ fill: "none",
4947
+ stroke: "currentColor",
4948
+ "stroke-width": "2",
4949
+ "stroke-linecap": "round",
4950
+ "stroke-linejoin": "round"
4951
+ }, [createElementVNode("line", {
4952
+ x1: "18",
4953
+ y1: "6",
4954
+ x2: "6",
4955
+ y2: "18"
4956
+ }), createElementVNode("line", {
4957
+ x1: "6",
4958
+ y1: "6",
4959
+ x2: "18",
4960
+ y2: "18"
4961
+ })], -1)])], 2)) : createCommentVNode("v-if", true),
4962
+ createElementVNode("span", { class: normalizeClass(e("arrow")) }, [..._cache[3] || (_cache[3] = [createElementVNode("svg", {
4963
+ xmlns: "http://www.w3.org/2000/svg",
4964
+ width: "12",
4965
+ height: "12",
4966
+ viewBox: "0 0 24 24",
4967
+ fill: "none",
4968
+ stroke: "currentColor",
4969
+ "stroke-width": "2",
4970
+ "stroke-linecap": "round",
4971
+ "stroke-linejoin": "round"
4972
+ }, [createElementVNode("polyline", { points: "6 9 12 15 18 9" })], -1)])], 2)
4973
+ ], 2),
4974
+ __props.error || __props.hint ? (openBlock(), createElementBlock("div", {
4975
+ key: 1,
4976
+ class: normalizeClass([e("message"), { [e("message--error")]: __props.error }])
4977
+ }, toDisplayString(__props.error || __props.hint), 3)) : createCommentVNode("v-if", true),
4978
+ createCommentVNode(" Dropdown "),
4979
+ (openBlock(), createBlock(Teleport, { to: "body" }, [createVNode(Transition, { name: "yd-tree-select-dropdown" }, {
4980
+ default: withCtx(() => [visible.value ? (openBlock(), createElementBlock("div", {
4981
+ key: 0,
4982
+ class: normalizeClass(e("dropdown")),
4983
+ style: normalizeStyle(dropdownStyle.value),
4984
+ onClick: _cache[1] || (_cache[1] = withModifiers(() => {}, ["stop"]))
4985
+ }, [createCommentVNode(" Virtual scroll wrapper "), __props.virtualScroll ? (openBlock(), createElementBlock("div", {
4986
+ key: 0,
4987
+ class: normalizeClass(e("virtual-wrapper")),
4988
+ style: normalizeStyle({ height: virtualHeight.value })
4989
+ }, [createElementVNode("div", {
4990
+ class: normalizeClass(e("tree-container")),
4991
+ style: normalizeStyle({ height: `${totalHeight.value}px` }),
4992
+ onScroll: handleScroll
4993
+ }, [(openBlock(true), createElementBlock(Fragment, null, renderList(visibleNodes.value, (node, index) => {
4994
+ return openBlock(), createElementBlock("div", {
4995
+ key: node.key,
4996
+ class: normalizeClass(nodeClasses(node)),
4997
+ style: normalizeStyle({
4998
+ position: "absolute",
4999
+ top: `${index * __props.rowHeight}px`,
5000
+ height: `${__props.rowHeight}px`,
5001
+ paddingLeft: `${node.level * 20 + 8}px`
5002
+ }),
5003
+ onClick: withModifiers(($event) => handleNodeClick(node), ["stop"])
5004
+ }, [
5005
+ hasChildren(node) ? (openBlock(), createElementBlock("span", {
5006
+ key: 0,
5007
+ class: normalizeClass(e("node-toggle")),
5008
+ onClick: withModifiers(($event) => handleToggle(node), ["stop"])
5009
+ }, toDisplayString(expandedKeys.value.includes(node.key) ? "▾" : "▸"), 11, _hoisted_3$9)) : (openBlock(), createElementBlock("span", {
5010
+ key: 1,
5011
+ class: normalizeClass(e("node-leaf"))
5012
+ }, "•", 2)),
5013
+ __props.checkable ? (openBlock(), createElementBlock("span", {
5014
+ key: 2,
5015
+ class: normalizeClass(e("node-checkbox")),
5016
+ onClick: withModifiers(($event) => handleCheck(node), ["stop"])
5017
+ }, [createElementVNode("input", {
5018
+ type: "checkbox",
5019
+ checked: checkedKeys.value.includes(node.key),
5020
+ indeterminate: indeterminateKeys.value.includes(node.key),
5021
+ disabled: node.disabled
5022
+ }, null, 8, _hoisted_5$5)], 10, _hoisted_4$8)) : createCommentVNode("v-if", true),
5023
+ createElementVNode("span", { class: normalizeClass(e("node-title")) }, toDisplayString(node.title), 3)
5024
+ ], 14, _hoisted_2$14);
5025
+ }), 128))], 38)], 6)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [createCommentVNode(" Normal mode "), createElementVNode("div", { class: normalizeClass(e("tree-container")) }, [(openBlock(true), createElementBlock(Fragment, null, renderList(filteredNodes.value, (node) => {
5026
+ return openBlock(), createElementBlock("div", {
5027
+ key: node.key,
5028
+ class: normalizeClass(nodeClasses(node)),
5029
+ onClick: withModifiers(($event) => handleNodeClick(node), ["stop"])
5030
+ }, [
5031
+ hasChildren(node) ? (openBlock(), createElementBlock("span", {
5032
+ key: 0,
5033
+ class: normalizeClass(e("node-toggle")),
5034
+ onClick: withModifiers(($event) => handleToggle(node), ["stop"])
5035
+ }, toDisplayString(expandedKeys.value.includes(node.key) ? "▾" : "▸"), 11, _hoisted_7$4)) : (openBlock(), createElementBlock("span", {
5036
+ key: 1,
5037
+ class: normalizeClass(e("node-leaf"))
5038
+ }, "•", 2)),
5039
+ __props.checkable ? (openBlock(), createElementBlock("span", {
5040
+ key: 2,
5041
+ class: normalizeClass(e("node-checkbox")),
5042
+ onClick: withModifiers(($event) => handleCheck(node), ["stop"])
5043
+ }, [createElementVNode("input", {
5044
+ type: "checkbox",
5045
+ checked: checkedKeys.value.includes(node.key),
5046
+ indeterminate: indeterminateKeys.value.includes(node.key),
5047
+ disabled: node.disabled
5048
+ }, null, 8, _hoisted_9$4)], 10, _hoisted_8$4)) : createCommentVNode("v-if", true),
5049
+ createElementVNode("span", { class: normalizeClass(e("node-title")) }, toDisplayString(node.title), 3),
5050
+ hasChildren(node) && expandedKeys.value.includes(node.key) ? (openBlock(), createElementBlock("div", {
5051
+ key: 3,
5052
+ class: normalizeClass(e("node-children"))
5053
+ }, [(openBlock(true), createElementBlock(Fragment, null, renderList(node.children, (child) => {
5054
+ return openBlock(), createElementBlock("div", {
5055
+ key: child.key,
5056
+ class: normalizeClass(nodeClasses(child)),
5057
+ onClick: withModifiers(($event) => handleNodeClick(child), ["stop"])
5058
+ }, [
5059
+ hasChildren(child) ? (openBlock(), createElementBlock("span", {
5060
+ key: 0,
5061
+ class: normalizeClass(e("node-toggle")),
5062
+ onClick: withModifiers(($event) => handleToggle(child), ["stop"])
5063
+ }, toDisplayString(expandedKeys.value.includes(child.key) ? "▾" : "▸"), 11, _hoisted_11$3)) : (openBlock(), createElementBlock("span", {
5064
+ key: 1,
5065
+ class: normalizeClass(e("node-leaf"))
5066
+ }, "•", 2)),
5067
+ __props.checkable ? (openBlock(), createElementBlock("span", {
5068
+ key: 2,
5069
+ class: normalizeClass(e("node-checkbox")),
5070
+ onClick: withModifiers(($event) => handleCheck(child), ["stop"])
5071
+ }, [createElementVNode("input", {
5072
+ type: "checkbox",
5073
+ checked: checkedKeys.value.includes(child.key),
5074
+ indeterminate: indeterminateKeys.value.includes(child.key),
5075
+ disabled: child.disabled
5076
+ }, null, 8, _hoisted_13$2)], 10, _hoisted_12$3)) : createCommentVNode("v-if", true),
5077
+ createElementVNode("span", { class: normalizeClass(e("node-title")) }, toDisplayString(child.title), 3)
5078
+ ], 10, _hoisted_10$3);
5079
+ }), 128))], 2)) : createCommentVNode("v-if", true)
5080
+ ], 10, _hoisted_6$5);
5081
+ }), 128)), filteredNodes.value.length === 0 ? (openBlock(), createBlock(empty_default, {
5082
+ key: 0,
5083
+ description: "暂无数据"
5084
+ })) : createCommentVNode("v-if", true)], 2)], 2112))], 6)) : createCommentVNode("v-if", true)]),
5085
+ _: 1
5086
+ })]))
5087
+ ], 2);
5088
+ };
5089
+ }
5090
+ }), [["__scopeId", "data-v-f36bc312"]]);
5091
+ //#endregion
5092
+ //#region src/components/base/color-picker/color-picker.vue
5093
+ const _hoisted_1$21 = [
5094
+ "value",
5095
+ "placeholder",
5096
+ "disabled"
5097
+ ];
5098
+ const _hoisted_2$13 = {
5099
+ xmlns: "http://www.w3.org/2000/svg",
5100
+ width: "14",
5101
+ height: "14",
5102
+ viewBox: "0 0 24 24",
5103
+ fill: "none",
5104
+ stroke: "currentColor",
5105
+ "stroke-width": "2"
5106
+ };
5107
+ const _hoisted_3$8 = ["fill"];
5108
+ const _hoisted_4$7 = ["value"];
5109
+ const _hoisted_5$4 = ["value"];
5110
+ const _hoisted_6$4 = ["value"];
5111
+ const _hoisted_7$3 = ["value"];
5112
+ const _hoisted_8$3 = ["value"];
5113
+ const _hoisted_9$3 = ["onClick"];
5114
+ var color_picker_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineComponent({
5115
+ name: "YdColorPicker",
5116
+ inheritAttrs: false,
5117
+ __name: "color-picker",
5118
+ props: {
5119
+ modelValue: { default: "" },
5120
+ placeholder: { default: "#ffffff" },
5121
+ disabled: {
5122
+ type: Boolean,
5123
+ default: false
5124
+ },
5125
+ size: { default: "md" },
5126
+ variant: { default: "default" },
5127
+ label: { default: "" },
5128
+ required: {
5129
+ type: Boolean,
5130
+ default: false
5131
+ },
5132
+ error: { default: "" },
5133
+ hint: { default: "" },
5134
+ showAlpha: {
5135
+ type: Boolean,
5136
+ default: false
5137
+ },
5138
+ showPreset: {
5139
+ type: Boolean,
5140
+ default: true
5141
+ },
5142
+ showPreview: {
5143
+ type: Boolean,
5144
+ default: true
5145
+ },
5146
+ editable: {
5147
+ type: Boolean,
5148
+ default: true
5149
+ },
5150
+ clearable: {
5151
+ type: Boolean,
5152
+ default: true
5153
+ },
5154
+ presetColors: { default: () => [
5155
+ "#ffffff",
5156
+ "#000000",
5157
+ "#FF4500",
5158
+ "#FF8C00",
5159
+ "#FFD700",
5160
+ "#9ACD32",
5161
+ "#00FF00",
5162
+ "#00CED1",
5163
+ "#1E90FF",
5164
+ "#0000FF",
5165
+ "#8B008B",
5166
+ "#FF1493"
5167
+ ] }
5168
+ },
5169
+ emits: [
5170
+ "update:modelValue",
5171
+ "change",
5172
+ "focus",
5173
+ "blur"
5174
+ ],
5175
+ setup(__props, { emit: __emit }) {
5176
+ const props = __props;
5177
+ const emit = __emit;
5178
+ const pickerRef = ref();
5179
+ const saturationRef = ref();
5180
+ const hueRef = ref();
5181
+ const alphaRef = ref();
5182
+ const visible = ref(false);
5183
+ const hueValue = ref(0);
5184
+ const saturationValue = ref(100);
5185
+ const brightnessValue = ref(100);
5186
+ const alphaValue = ref(1);
5187
+ const cachedDropdownStyle = ref({});
5188
+ watch(() => props.modelValue, (val) => {
5189
+ if (val) {
5190
+ const parsed = parseColor(val);
5191
+ if (parsed) {
5192
+ hueValue.value = parsed.h;
5193
+ saturationValue.value = parsed.s;
5194
+ brightnessValue.value = parsed.b;
5195
+ alphaValue.value = parsed.a;
5196
+ }
5197
+ }
5198
+ }, { immediate: true });
5199
+ function parseColor(color) {
5200
+ if (!color) return null;
5201
+ if (color.startsWith("#")) {
5202
+ const hex = color.slice(1);
5203
+ let r, g, b, a = 1;
5204
+ if (hex.length === 3) {
5205
+ r = parseInt(hex[0] + hex[0], 16);
5206
+ g = parseInt(hex[1] + hex[1], 16);
5207
+ b = parseInt(hex[2] + hex[2], 16);
5208
+ } else if (hex.length === 6) {
5209
+ r = parseInt(hex.slice(0, 2), 16);
5210
+ g = parseInt(hex.slice(2, 4), 16);
5211
+ b = parseInt(hex.slice(4, 6), 16);
5212
+ } else if (hex.length === 8) {
5213
+ r = parseInt(hex.slice(0, 2), 16);
5214
+ g = parseInt(hex.slice(2, 4), 16);
5215
+ b = parseInt(hex.slice(4, 6), 16);
5216
+ a = parseInt(hex.slice(6, 8), 16) / 255;
5217
+ } else return null;
5218
+ const [h, s, v] = rgbToHsv(r, g, b);
5219
+ return {
5220
+ h,
5221
+ s: s * 100,
5222
+ b: v * 100,
5223
+ a
5224
+ };
5225
+ }
5226
+ return null;
5227
+ }
5228
+ function rgbToHsv(r, g, b) {
5229
+ r /= 255;
5230
+ g /= 255;
5231
+ b /= 255;
5232
+ const max = Math.max(r, g, b);
5233
+ const min = Math.min(r, g, b);
5234
+ const d = max - min;
5235
+ let h = 0;
5236
+ const s = max === 0 ? 0 : d / max;
5237
+ const v = max;
5238
+ if (max !== min) {
5239
+ switch (max) {
5240
+ case r:
5241
+ h = (g - b) / d + (g < b ? 6 : 0);
5242
+ break;
5243
+ case g:
5244
+ h = (b - r) / d + 2;
5245
+ break;
5246
+ case b:
5247
+ h = (r - g) / d + 4;
5248
+ break;
5249
+ }
5250
+ h /= 6;
5251
+ }
5252
+ return [
5253
+ h * 360,
5254
+ s,
5255
+ v
5256
+ ];
5257
+ }
5258
+ function hsvToRgb(h, s, v) {
5259
+ h /= 360;
5260
+ s /= 100;
5261
+ v /= 100;
5262
+ let r = 0, g = 0, b = 0;
5263
+ const i = Math.floor(h * 6);
5264
+ const f = h * 6 - i;
5265
+ const p = v * (1 - s);
5266
+ const q = v * (1 - f * s);
5267
+ const t = v * (1 - (1 - f) * s);
5268
+ switch (i % 6) {
5269
+ case 0:
5270
+ r = v;
5271
+ g = t;
5272
+ b = p;
5273
+ break;
5274
+ case 1:
5275
+ r = q;
5276
+ g = v;
5277
+ b = p;
5278
+ break;
5279
+ case 2:
5280
+ r = p;
5281
+ g = v;
5282
+ b = t;
5283
+ break;
5284
+ case 3:
5285
+ r = p;
5286
+ g = q;
5287
+ b = v;
5288
+ break;
5289
+ case 4:
5290
+ r = t;
5291
+ g = p;
5292
+ b = v;
5293
+ break;
5294
+ case 5:
5295
+ r = v;
5296
+ g = p;
5297
+ b = q;
5298
+ break;
5299
+ }
5300
+ return [
5301
+ Math.round(r * 255),
5302
+ Math.round(g * 255),
5303
+ Math.round(b * 255)
5304
+ ];
5305
+ }
5306
+ const hexValue = computed(() => {
5307
+ const [r, g, b] = hsvToRgb(hueValue.value, saturationValue.value, brightnessValue.value);
5308
+ return `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`.toUpperCase();
5309
+ });
5310
+ const rgbValue = computed(() => {
5311
+ const [r, g, b] = hsvToRgb(hueValue.value, saturationValue.value, brightnessValue.value);
5312
+ return {
5313
+ r,
5314
+ g,
5315
+ b
5316
+ };
5317
+ });
5318
+ const displayValue = computed(() => {
5319
+ const hex = hexValue.value;
5320
+ if (props.showAlpha && alphaValue.value < 1) return `rgba(${parseInt(hex.slice(1, 3), 16)}, ${parseInt(hex.slice(3, 5), 16)}, ${parseInt(hex.slice(5, 7), 16)}, ${alphaValue.value})`;
5321
+ return hex;
5322
+ });
5323
+ const hueColor = computed(() => {
5324
+ return `hsl(${hueValue.value}, 100%, 50%)`;
5325
+ });
5326
+ const saturationPosition = computed(() => ({
5327
+ x: saturationValue.value,
5328
+ y: 100 - brightnessValue.value
5329
+ }));
5330
+ function updateDropdownPosition() {
5331
+ if (!pickerRef.value || !visible.value) return;
5332
+ const rect = pickerRef.value.getBoundingClientRect();
5333
+ cachedDropdownStyle.value = {
5334
+ position: "fixed",
5335
+ top: `${rect.bottom + 4}px`,
5336
+ left: `${rect.left}px`,
5337
+ zIndex: "2000"
5338
+ };
5339
+ }
5340
+ function handleWindowScroll() {
5341
+ if (visible.value) updateDropdownPosition();
5342
+ }
5343
+ function handleWindowResize() {
5344
+ if (visible.value) updateDropdownPosition();
5345
+ }
5346
+ const wrapperClasses = computed(() => cn("yd-color-picker-wrapper", `yd-color-picker-wrapper--${props.size}`, `yd-color-picker-wrapper--${props.variant}`, props.disabled && "yd-color-picker-wrapper--disabled", props.error && "yd-color-picker-wrapper--error"));
5347
+ const dropdownStyle = computed(() => cachedDropdownStyle.value);
5348
+ function e(element) {
5349
+ return `yd-color-picker__${element}`;
5350
+ }
5351
+ function emitColor() {
5352
+ let color = hexValue.value;
5353
+ if (props.showAlpha && alphaValue.value < 1) {
5354
+ const r = parseInt(color.slice(1, 3), 16);
5355
+ const g = parseInt(color.slice(3, 5), 16);
5356
+ const b = parseInt(color.slice(5, 7), 16);
5357
+ const a = Math.round(alphaValue.value * 255).toString(16).padStart(2, "0");
5358
+ color = `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}${a}`;
5359
+ }
5360
+ emit("update:modelValue", color);
5361
+ emit("change", color);
5362
+ }
5363
+ function handleInput(event) {
5364
+ const value = event.target.value;
5365
+ const parsed = parseColor(value);
5366
+ if (parsed) {
5367
+ hueValue.value = parsed.h;
5368
+ saturationValue.value = parsed.s;
5369
+ brightnessValue.value = parsed.b;
5370
+ emitColor();
5371
+ }
5372
+ }
5373
+ function handleHexInput(event) {
5374
+ const value = event.target.value;
5375
+ const parsed = parseColor(value);
5376
+ if (parsed) {
5377
+ hueValue.value = parsed.h;
5378
+ saturationValue.value = parsed.s;
5379
+ brightnessValue.value = parsed.b;
5380
+ emitColor();
5381
+ }
5382
+ }
5383
+ function handleRgbInput(channel, event) {
5384
+ const value = parseInt(event.target.value) || 0;
5385
+ const newRgb = {
5386
+ ...rgbValue.value,
5387
+ [channel]: Math.min(255, Math.max(0, value))
5388
+ };
5389
+ const [h, s, v] = rgbToHsv(newRgb.r, newRgb.g, newRgb.b);
5390
+ hueValue.value = h;
5391
+ saturationValue.value = s * 100;
5392
+ brightnessValue.value = v * 100;
5393
+ emitColor();
5394
+ }
5395
+ function handleAlphaInput(event) {
5396
+ alphaValue.value = Math.min(100, Math.max(0, parseInt(event.target.value) || 0)) / 100;
5397
+ emitColor();
5398
+ }
5399
+ function handlePresetClick(color) {
5400
+ const parsed = parseColor(color);
5401
+ if (parsed) {
5402
+ hueValue.value = parsed.h;
5403
+ saturationValue.value = parsed.s;
5404
+ brightnessValue.value = parsed.b;
5405
+ alphaValue.value = parsed.a;
5406
+ emitColor();
5407
+ }
5408
+ }
5409
+ function handleClear() {
5410
+ emit("update:modelValue", "");
5411
+ emit("change", "");
5412
+ }
5413
+ function togglePicker() {
5414
+ if (props.disabled) return;
5415
+ visible.value = !visible.value;
5416
+ if (visible.value) nextTick(() => updateDropdownPosition());
5417
+ }
5418
+ function handleFocus(event) {
5419
+ emit("focus", event);
5420
+ }
5421
+ function handleBlur(event) {
5422
+ emit("blur", event);
5423
+ }
5424
+ let isDraggingSaturation = false;
5425
+ function handleSaturationStart(e) {
5426
+ isDraggingSaturation = true;
5427
+ updateSaturation(e);
5428
+ document.addEventListener("mousemove", handleSaturationMove);
5429
+ document.addEventListener("mouseup", handleSaturationEnd);
5430
+ }
5431
+ function handleSaturationMove(e) {
5432
+ if (isDraggingSaturation) updateSaturation(e);
5433
+ }
5434
+ function handleSaturationEnd() {
5435
+ isDraggingSaturation = false;
5436
+ document.removeEventListener("mousemove", handleSaturationMove);
5437
+ document.removeEventListener("mouseup", handleSaturationEnd);
5438
+ }
5439
+ function updateSaturation(e) {
5440
+ if (!saturationRef.value) return;
5441
+ const rect = saturationRef.value.getBoundingClientRect();
5442
+ const x = Math.min(100, Math.max(0, (e.clientX - rect.left) / rect.width * 100));
5443
+ const y = Math.min(100, Math.max(0, (e.clientY - rect.top) / rect.height * 100));
5444
+ saturationValue.value = x;
5445
+ brightnessValue.value = 100 - y;
5446
+ emitColor();
5447
+ }
5448
+ let isDraggingHue = false;
5449
+ function handleHueStart(e) {
5450
+ isDraggingHue = true;
5451
+ updateHue(e);
5452
+ document.addEventListener("mousemove", handleHueMove);
5453
+ document.addEventListener("mouseup", handleHueEnd);
5454
+ }
5455
+ function handleHueMove(e) {
5456
+ if (isDraggingHue) updateHue(e);
5457
+ }
5458
+ function handleHueEnd() {
5459
+ isDraggingHue = false;
5460
+ document.removeEventListener("mousemove", handleHueMove);
5461
+ document.removeEventListener("mouseup", handleHueEnd);
5462
+ }
5463
+ function updateHue(e) {
5464
+ if (!hueRef.value) return;
5465
+ const rect = hueRef.value.getBoundingClientRect();
5466
+ hueValue.value = Math.min(100, Math.max(0, (e.clientX - rect.left) / rect.width * 100)) * 3.6;
5467
+ emitColor();
5468
+ }
5469
+ let isDraggingAlpha = false;
5470
+ function handleAlphaStart(e) {
5471
+ isDraggingAlpha = true;
5472
+ updateAlpha(e);
5473
+ document.addEventListener("mousemove", handleAlphaMove);
5474
+ document.addEventListener("mouseup", handleAlphaEnd);
5475
+ }
5476
+ function handleAlphaMove(e) {
5477
+ if (isDraggingAlpha) updateAlpha(e);
5478
+ }
5479
+ function handleAlphaEnd() {
5480
+ isDraggingAlpha = false;
5481
+ document.removeEventListener("mousemove", handleAlphaMove);
5482
+ document.removeEventListener("mouseup", handleAlphaEnd);
5483
+ }
5484
+ function updateAlpha(e) {
5485
+ if (!alphaRef.value) return;
5486
+ const rect = alphaRef.value.getBoundingClientRect();
5487
+ alphaValue.value = Math.min(100, Math.max(0, (e.clientX - rect.left) / rect.width * 100)) / 100;
5488
+ emitColor();
5489
+ }
5490
+ function handleClickOutside(event) {
5491
+ if (pickerRef.value && !pickerRef.value.contains(event.target)) visible.value = false;
5492
+ }
5493
+ onMounted(() => {
5494
+ document.addEventListener("click", handleClickOutside);
5495
+ window.addEventListener("scroll", handleWindowScroll, true);
5496
+ window.addEventListener("resize", handleWindowResize);
5497
+ });
5498
+ onUnmounted(() => {
5499
+ document.removeEventListener("click", handleClickOutside);
5500
+ window.removeEventListener("scroll", handleWindowScroll, true);
5501
+ window.removeEventListener("resize", handleWindowResize);
5502
+ });
5503
+ return (_ctx, _cache) => {
5504
+ return openBlock(), createElementBlock("div", {
5505
+ ref_key: "pickerRef",
5506
+ ref: pickerRef,
5507
+ class: normalizeClass(wrapperClasses.value),
5508
+ onClick: togglePicker
5509
+ }, [
5510
+ __props.label ? (openBlock(), createElementBlock("div", {
5511
+ key: 0,
5512
+ class: normalizeClass(e("label"))
5513
+ }, [createElementVNode("label", null, toDisplayString(__props.label), 1), __props.required ? (openBlock(), createElementBlock("span", {
5514
+ key: 0,
5515
+ class: normalizeClass(e("required"))
5516
+ }, "*", 2)) : createCommentVNode("v-if", true)], 2)) : createCommentVNode("v-if", true),
5517
+ createElementVNode("div", { class: normalizeClass(e("control")) }, [
5518
+ createCommentVNode(" Color preview "),
5519
+ __props.showPreview ? (openBlock(), createElementBlock("div", {
5520
+ key: 0,
5521
+ class: normalizeClass(e("preview")),
5522
+ style: normalizeStyle({ backgroundColor: displayValue.value })
5523
+ }, null, 6)) : createCommentVNode("v-if", true),
5524
+ createCommentVNode(" Input "),
5525
+ __props.editable ? (openBlock(), createElementBlock("input", {
5526
+ key: 1,
5527
+ class: normalizeClass(e("input")),
5528
+ value: __props.modelValue,
5529
+ placeholder: __props.placeholder,
5530
+ disabled: __props.disabled,
5531
+ onInput: handleInput,
5532
+ onFocus: handleFocus,
5533
+ onBlur: handleBlur
5534
+ }, null, 42, _hoisted_1$21)) : createCommentVNode("v-if", true),
5535
+ createCommentVNode(" Clear button "),
5536
+ __props.clearable && __props.modelValue && !__props.disabled ? (openBlock(), createElementBlock("span", {
5537
+ key: 2,
5538
+ class: normalizeClass(e("clear")),
5539
+ onClick: withModifiers(handleClear, ["stop"])
5540
+ }, [..._cache[4] || (_cache[4] = [createElementVNode("svg", {
5541
+ xmlns: "http://www.w3.org/2000/svg",
5542
+ width: "14",
5543
+ height: "14",
5544
+ viewBox: "0 0 24 24",
5545
+ fill: "none",
5546
+ stroke: "currentColor",
5547
+ "stroke-width": "2",
5548
+ "stroke-linecap": "round",
5549
+ "stroke-linejoin": "round"
5550
+ }, [createElementVNode("line", {
5551
+ x1: "18",
5552
+ y1: "6",
5553
+ x2: "6",
5554
+ y2: "18"
5555
+ }), createElementVNode("line", {
5556
+ x1: "6",
5557
+ y1: "6",
5558
+ x2: "18",
5559
+ y2: "18"
5560
+ })], -1)])], 2)) : createCommentVNode("v-if", true),
5561
+ createCommentVNode(" Trigger button "),
5562
+ createElementVNode("span", { class: normalizeClass(e("trigger")) }, [(openBlock(), createElementBlock("svg", _hoisted_2$13, [_cache[5] || (_cache[5] = createElementVNode("circle", {
5563
+ cx: "12",
5564
+ cy: "12",
5565
+ r: "10"
5566
+ }, null, -1)), createElementVNode("path", {
5567
+ d: "M12 2a10 10 0 0 1 0 20",
5568
+ fill: __props.modelValue || "#ffffff"
5569
+ }, null, 8, _hoisted_3$8)]))], 2)
5570
+ ], 2),
5571
+ __props.error || __props.hint ? (openBlock(), createElementBlock("div", {
5572
+ key: 1,
5573
+ class: normalizeClass([e("message"), { [e("message--error")]: __props.error }])
5574
+ }, toDisplayString(__props.error || __props.hint), 3)) : createCommentVNode("v-if", true),
5575
+ createCommentVNode(" Picker dropdown "),
5576
+ (openBlock(), createBlock(Teleport, { to: "body" }, [createVNode(Transition, { name: "yd-color-picker-dropdown" }, {
5577
+ default: withCtx(() => [visible.value ? (openBlock(), createElementBlock("div", {
5578
+ key: 0,
5579
+ class: normalizeClass(e("dropdown")),
5580
+ style: normalizeStyle(dropdownStyle.value),
5581
+ onClick: _cache[3] || (_cache[3] = withModifiers(() => {}, ["stop"]))
5582
+ }, [
5583
+ createCommentVNode(" Saturation/Brightness area "),
5584
+ createElementVNode("div", {
5585
+ ref_key: "saturationRef",
5586
+ ref: saturationRef,
5587
+ class: normalizeClass(e("saturation")),
5588
+ style: normalizeStyle({ backgroundColor: hueColor.value }),
5589
+ onMousedown: handleSaturationStart
5590
+ }, [
5591
+ createElementVNode("div", { class: normalizeClass(e("saturation-white")) }, null, 2),
5592
+ createElementVNode("div", { class: normalizeClass(e("saturation-black")) }, null, 2),
5593
+ createElementVNode("div", {
5594
+ class: normalizeClass(e("saturation-cursor")),
5595
+ style: normalizeStyle({
5596
+ left: `${saturationPosition.value.x}%`,
5597
+ top: `${saturationPosition.value.y}%`
5598
+ })
5599
+ }, null, 6)
5600
+ ], 38),
5601
+ createCommentVNode(" Hue slider "),
5602
+ createElementVNode("div", {
5603
+ ref_key: "hueRef",
5604
+ ref: hueRef,
5605
+ class: normalizeClass(e("hue")),
5606
+ onMousedown: handleHueStart
5607
+ }, [createElementVNode("div", {
5608
+ class: normalizeClass(e("hue-cursor")),
5609
+ style: normalizeStyle({ left: `${hueValue.value / 360 * 100}%` })
5610
+ }, null, 6)], 34),
5611
+ createCommentVNode(" Alpha slider "),
5612
+ __props.showAlpha ? (openBlock(), createElementBlock("div", {
5613
+ key: 0,
5614
+ ref_key: "alphaRef",
5615
+ ref: alphaRef,
5616
+ class: normalizeClass(e("alpha")),
5617
+ onMousedown: handleAlphaStart
5618
+ }, [
5619
+ createElementVNode("div", { class: normalizeClass(e("alpha-bg")) }, null, 2),
5620
+ createElementVNode("div", {
5621
+ class: normalizeClass(e("alpha-fill")),
5622
+ style: normalizeStyle({
5623
+ width: `${alphaValue.value * 100}%`,
5624
+ backgroundColor: `hsl(${hueValue.value}, 100%, 50%)`
5625
+ })
5626
+ }, null, 6),
5627
+ createElementVNode("div", {
5628
+ class: normalizeClass(e("alpha-cursor")),
5629
+ style: normalizeStyle({ left: `${alphaValue.value * 100}%` })
5630
+ }, null, 6)
5631
+ ], 34)) : createCommentVNode("v-if", true),
5632
+ createCommentVNode(" Color values "),
5633
+ createElementVNode("div", { class: normalizeClass(e("values")) }, [
5634
+ createElementVNode("div", { class: normalizeClass(e("value-item")) }, [createElementVNode("span", { class: normalizeClass(e("value-label")) }, "HEX", 2), createElementVNode("input", {
5635
+ class: normalizeClass(e("value-input")),
5636
+ value: hexValue.value,
5637
+ onInput: handleHexInput
5638
+ }, null, 42, _hoisted_4$7)], 2),
5639
+ createElementVNode("div", { class: normalizeClass(e("value-item")) }, [createElementVNode("span", { class: normalizeClass(e("value-label")) }, "R", 2), createElementVNode("input", {
5640
+ class: normalizeClass(e("value-input")),
5641
+ type: "number",
5642
+ min: 0,
5643
+ max: 255,
5644
+ value: rgbValue.value.r,
5645
+ onInput: _cache[0] || (_cache[0] = (e) => handleRgbInput("r", e))
5646
+ }, null, 42, _hoisted_5$4)], 2),
5647
+ createElementVNode("div", { class: normalizeClass(e("value-item")) }, [createElementVNode("span", { class: normalizeClass(e("value-label")) }, "G", 2), createElementVNode("input", {
5648
+ class: normalizeClass(e("value-input")),
5649
+ type: "number",
5650
+ min: 0,
5651
+ max: 255,
5652
+ value: rgbValue.value.g,
5653
+ onInput: _cache[1] || (_cache[1] = (e) => handleRgbInput("g", e))
5654
+ }, null, 42, _hoisted_6$4)], 2),
5655
+ createElementVNode("div", { class: normalizeClass(e("value-item")) }, [createElementVNode("span", { class: normalizeClass(e("value-label")) }, "B", 2), createElementVNode("input", {
5656
+ class: normalizeClass(e("value-input")),
5657
+ type: "number",
5658
+ min: 0,
5659
+ max: 255,
5660
+ value: rgbValue.value.b,
5661
+ onInput: _cache[2] || (_cache[2] = (e) => handleRgbInput("b", e))
5662
+ }, null, 42, _hoisted_7$3)], 2),
5663
+ __props.showAlpha ? (openBlock(), createElementBlock("div", {
5664
+ key: 0,
5665
+ class: normalizeClass(e("value-item"))
5666
+ }, [createElementVNode("span", { class: normalizeClass(e("value-label")) }, "A", 2), createElementVNode("input", {
5667
+ class: normalizeClass(e("value-input")),
5668
+ type: "number",
5669
+ min: 0,
5670
+ max: 100,
5671
+ value: Math.round(alphaValue.value * 100),
5672
+ onInput: handleAlphaInput
5673
+ }, null, 42, _hoisted_8$3)], 2)) : createCommentVNode("v-if", true)
5674
+ ], 2),
5675
+ createCommentVNode(" Preset colors "),
5676
+ __props.showPreset ? (openBlock(), createElementBlock("div", {
5677
+ key: 1,
5678
+ class: normalizeClass(e("presets"))
5679
+ }, [(openBlock(true), createElementBlock(Fragment, null, renderList(__props.presetColors, (color, index) => {
5680
+ return openBlock(), createElementBlock("div", {
5681
+ key: index,
5682
+ class: normalizeClass(e("preset-item")),
5683
+ style: normalizeStyle({ backgroundColor: color }),
5684
+ onClick: ($event) => handlePresetClick(color)
5685
+ }, null, 14, _hoisted_9$3);
5686
+ }), 128))], 2)) : createCommentVNode("v-if", true)
5687
+ ], 6)) : createCommentVNode("v-if", true)]),
5688
+ _: 1
5689
+ })]))
5690
+ ], 2);
5691
+ };
5692
+ }
5693
+ }), [["__scopeId", "data-v-24772c45"]]);
5694
+ //#endregion
5695
+ //#region src/composables/use-form-validate.ts
5696
+ /**
5697
+ * 获取 AsyncValidator 构造函数
5698
+ * 处理 ES Module default export 和 CommonJS 两种导出方式
5699
+ */
5700
+ function getAsyncValidatorSchema() {
5701
+ if (typeof AsyncValidator === "object" && AsyncValidator !== null && "default" in AsyncValidator) return AsyncValidator.default;
5702
+ return AsyncValidator;
5703
+ }
4070
5704
  const Schema = getAsyncValidatorSchema();
4071
5705
  /**
4072
5706
  * 表单校验 composable
@@ -4275,6 +5909,350 @@ var form_item_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ de
4275
5909
  };
4276
5910
  }
4277
5911
  }), [["__scopeId", "data-v-cab13fdb"]]);
5912
+ //#endregion
5913
+ //#region src/components/form/useFormSchema.ts
5914
+ /**
5915
+ * 解析schema中的条件表达式
5916
+ */
5917
+ /**
5918
+ * 安全地解析条件表达式
5919
+ * 支持简单的比较和逻辑运算: a > 0, b === 'yes', a && b, a || !c
5920
+ * 使用 Function 构造函数是合理的,因为我们已经清理了表达式
5921
+ */
5922
+ function parseCondition(condition, values) {
5923
+ const ALLOWED_KEYWORDS = new Set([
5924
+ "true",
5925
+ "false",
5926
+ "null",
5927
+ "undefined"
5928
+ ]);
5929
+ try {
5930
+ const trimmed = condition.trim();
5931
+ if (trimmed === "true") return true;
5932
+ if (trimmed === "false") return false;
5933
+ function getValue(name) {
5934
+ if (ALLOWED_KEYWORDS.has(name)) return void 0;
5935
+ return values[name];
5936
+ }
5937
+ if (/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(trimmed)) return !!getValue(trimmed);
5938
+ if (/^![a-zA-Z_][a-zA-Z0-9_]*$/.test(trimmed)) return !getValue(trimmed.slice(1));
5939
+ return new Function("values", "getValue", "undefined", `return !!( (${trimmed}) )`)(values, getValue, void 0);
5940
+ } catch {
5941
+ return true;
5942
+ }
5943
+ }
5944
+ function evalCondition(condition, values) {
5945
+ if (typeof condition === "function") return condition(values);
5946
+ return parseCondition(condition, values);
5947
+ }
5948
+ /**
5949
+ * 判断是否是GroupSchema
5950
+ */
5951
+ function isGroupSchema(item) {
5952
+ return "type" in item && item.type === "group";
5953
+ }
5954
+ /**
5955
+ * 判断是否是RowSchema
5956
+ */
5957
+ function isRowSchema(item) {
5958
+ return "type" in item && item.type === "row";
5959
+ }
5960
+ /**
5961
+ * 判断是否是SlotSchema
5962
+ */
5963
+ function isSlotSchema(item) {
5964
+ return "type" in item && item.type === "slot";
5965
+ }
5966
+ /**
5967
+ * 过滤字段 - 处理if和dependencies条件
5968
+ */
5969
+ function filterFields(schema, values) {
5970
+ const result = [];
5971
+ for (const item of schema) {
5972
+ if (isGroupSchema(item)) {
5973
+ const filteredChildren = filterFields(item.children, values);
5974
+ result.push({
5975
+ ...item,
5976
+ children: filteredChildren
5977
+ });
5978
+ continue;
5979
+ }
5980
+ if (isRowSchema(item)) {
5981
+ const filteredChildren = filterFields(item.children, values);
5982
+ result.push({
5983
+ ...item,
5984
+ children: filteredChildren
5985
+ });
5986
+ continue;
5987
+ }
5988
+ if (isSlotSchema(item)) {
5989
+ result.push(item);
5990
+ continue;
5991
+ }
5992
+ const field = item;
5993
+ if (field.if !== void 0) {
5994
+ if (field.dependencies?.length) {
5995
+ if (!field.dependencies.every((dep) => dep in values)) {
5996
+ result.push(field);
5997
+ continue;
5998
+ }
5999
+ }
6000
+ if (!evalCondition(field.if, values)) continue;
6001
+ }
6002
+ result.push(field);
6003
+ }
6004
+ return result;
6005
+ }
6006
+ /**
6007
+ * 构建默认初始值
6008
+ */
6009
+ function buildInitialValues(schema, initialValues) {
6010
+ const values = { ...initialValues };
6011
+ function traverse(items) {
6012
+ for (const item of items) {
6013
+ if (isGroupSchema(item) || isRowSchema(item)) {
6014
+ traverse(item.children);
6015
+ continue;
6016
+ }
6017
+ if (isSlotSchema(item)) continue;
6018
+ const field = item;
6019
+ if (field.name && field.defaultValue !== void 0 && !(field.name in values)) values[field.name] = field.defaultValue;
6020
+ }
6021
+ }
6022
+ traverse(schema);
6023
+ return values;
6024
+ }
6025
+ /**
6026
+ * useFormSchema - Schema驱动的表单生成
6027
+ */
6028
+ function useFormSchema(schema, initialValues) {
6029
+ const modelValue = buildInitialValues(schema, initialValues);
6030
+ let filteredSchema = filterFields(schema, modelValue);
6031
+ const actions = {
6032
+ getValues: () => ({ ...modelValue }),
6033
+ setFieldValue: (name, value) => {
6034
+ modelValue[name] = value;
6035
+ },
6036
+ resetFields: () => {
6037
+ const newValues = buildInitialValues(schema, initialValues);
6038
+ Object.keys(modelValue).forEach((key) => {
6039
+ if (key in newValues) modelValue[key] = newValues[key];
6040
+ else delete modelValue[key];
6041
+ });
6042
+ },
6043
+ validate: async () => {
6044
+ return {
6045
+ valid: true,
6046
+ errors: []
6047
+ };
6048
+ },
6049
+ scrollToField: (name) => {
6050
+ document.querySelector(`[data-field="${name}"]`)?.scrollIntoView({
6051
+ behavior: "smooth",
6052
+ block: "center"
6053
+ });
6054
+ },
6055
+ submit: async () => {
6056
+ await actions.validate();
6057
+ return actions.getValues();
6058
+ }
6059
+ };
6060
+ return {
6061
+ modelValue,
6062
+ schema: filteredSchema,
6063
+ actions
6064
+ };
6065
+ }
6066
+ var SchemaForm_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineComponent({
6067
+ name: "YdSchemaForm",
6068
+ __name: "SchemaForm",
6069
+ props: {
6070
+ schema: {},
6071
+ modelValue: { default: () => ({}) },
6072
+ labelWidth: { default: "100px" },
6073
+ layout: { default: "vertical" },
6074
+ labelPosition: { default: "top" },
6075
+ disabled: {
6076
+ type: Boolean,
6077
+ default: false
6078
+ }
6079
+ },
6080
+ emits: [
6081
+ "update:modelValue",
6082
+ "change",
6083
+ "submit",
6084
+ "reset"
6085
+ ],
6086
+ setup(__props, { expose: __expose, emit: __emit }) {
6087
+ const props = __props;
6088
+ const emit = __emit;
6089
+ const formRef = ref();
6090
+ const localModel = computed({
6091
+ get: () => ({ ...props.modelValue }),
6092
+ set: (val) => emit("update:modelValue", val)
6093
+ });
6094
+ const { modelValue, schema: computedSchema, actions } = useFormSchema(props.schema, props.modelValue);
6095
+ watch(() => props.schema, (newSchema) => {
6096
+ computedSchema.splice(0, computedSchema.length, ...newSchema);
6097
+ });
6098
+ const visibleFields = computed(() => computedSchema);
6099
+ const rules = computed(() => {
6100
+ const r = {};
6101
+ for (const field of computedSchema) if (isFieldSchema(field) && field.rules?.length) r[field.name] = field.rules;
6102
+ return r;
6103
+ });
6104
+ const componentMap = {
6105
+ Input: input_default,
6106
+ Textarea: textarea_default,
6107
+ Select: select_default,
6108
+ RadioGroup: radio_group_default,
6109
+ CheckboxGroup: checkbox_group_default,
6110
+ Switch: switch_default,
6111
+ DatePicker: date_picker_default
6112
+ };
6113
+ function isGroupSchema(item) {
6114
+ return "type" in item && item.type === "group";
6115
+ }
6116
+ function isRowSchema(item) {
6117
+ return "type" in item && item.type === "row";
6118
+ }
6119
+ function isSlotSchema(item) {
6120
+ return "type" in item && item.type === "slot";
6121
+ }
6122
+ function isFieldSchema(item) {
6123
+ return !("type" in item);
6124
+ }
6125
+ function getComponent(field) {
6126
+ return componentMap[field.component || "Input"];
6127
+ }
6128
+ function hasRequiredRule(field) {
6129
+ return field.rules?.some((r) => r.required);
6130
+ }
6131
+ function handleChange(name, value) {
6132
+ localModel.value = {
6133
+ ...localModel.value,
6134
+ [name]: value
6135
+ };
6136
+ emit("change", name, value);
6137
+ }
6138
+ function handleSubmit() {
6139
+ actions.submit().then((values) => {
6140
+ emit("submit", values);
6141
+ });
6142
+ }
6143
+ function e(element) {
6144
+ return `yd-schema-form__${element}`;
6145
+ }
6146
+ __expose({
6147
+ validate: actions.validate,
6148
+ resetFields: actions.resetFields,
6149
+ scrollToField: actions.scrollToField
6150
+ });
6151
+ return (_ctx, _cache) => {
6152
+ return openBlock(), createBlock(form_default, {
6153
+ ref_key: "formRef",
6154
+ ref: formRef,
6155
+ modelValue: localModel.value,
6156
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => localModel.value = $event),
6157
+ rules: rules.value,
6158
+ layout: __props.layout,
6159
+ "label-width": __props.labelWidth,
6160
+ "label-position": __props.labelPosition,
6161
+ disabled: __props.disabled,
6162
+ onSubmit: handleSubmit
6163
+ }, {
6164
+ default: withCtx(() => [
6165
+ (openBlock(true), createElementBlock(Fragment, null, renderList(visibleFields.value, (field) => {
6166
+ return openBlock(), createElementBlock(Fragment, { key: field.name }, [createCommentVNode(" Group "), isGroupSchema(field) ? (openBlock(), createElementBlock("fieldset", {
6167
+ key: 0,
6168
+ class: normalizeClass(e("group"))
6169
+ }, [
6170
+ field.title ? (openBlock(), createElementBlock("legend", {
6171
+ key: 0,
6172
+ class: normalizeClass(e("group-title"))
6173
+ }, toDisplayString(field.title), 3)) : createCommentVNode("v-if", true),
6174
+ field.description ? (openBlock(), createElementBlock("p", {
6175
+ key: 1,
6176
+ class: normalizeClass(e("group-desc"))
6177
+ }, toDisplayString(field.description), 3)) : createCommentVNode("v-if", true),
6178
+ renderSlot(_ctx.$slots, `group-${field.title}`, {}, void 0, true)
6179
+ ], 2)) : isRowSchema(field) ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [createCommentVNode(" Row "), createElementVNode("div", {
6180
+ class: normalizeClass(e("row")),
6181
+ style: normalizeStyle({ gap: `${field.gutter || 16}px` })
6182
+ }, [(openBlock(true), createElementBlock(Fragment, null, renderList(field.children, (child) => {
6183
+ return openBlock(), createElementBlock(Fragment, { key: child.name }, [isFieldSchema(child) ? (openBlock(), createBlock(form_item_default, {
6184
+ key: 0,
6185
+ prop: child.name,
6186
+ label: child.label,
6187
+ required: hasRequiredRule(child),
6188
+ "data-field": child.name
6189
+ }, {
6190
+ default: withCtx(() => [renderSlot(_ctx.$slots, child.name, {}, () => [(openBlock(), createBlock(resolveDynamicComponent(getComponent(child)), mergeProps({
6191
+ modelValue: localModel.value[child.name],
6192
+ "onUpdate:modelValue": ($event) => localModel.value[child.name] = $event
6193
+ }, { ref_for: true }, child.componentProps, {
6194
+ placeholder: child.placeholder,
6195
+ disabled: child.disabled,
6196
+ options: child.options,
6197
+ "onUpdate:modelValue": (v) => handleChange(child.name, v)
6198
+ }), null, 16, [
6199
+ "modelValue",
6200
+ "onUpdate:modelValue",
6201
+ "placeholder",
6202
+ "disabled",
6203
+ "options"
6204
+ ]))], true)]),
6205
+ _: 2
6206
+ }, 1032, [
6207
+ "prop",
6208
+ "label",
6209
+ "required",
6210
+ "data-field"
6211
+ ])) : createCommentVNode("v-if", true)], 64);
6212
+ }), 128))], 6)], 64)) : isSlotSchema(field) ? (openBlock(), createElementBlock(Fragment, { key: 2 }, [createCommentVNode(" Slot "), renderSlot(_ctx.$slots, field.name, {}, void 0, true)], 64)) : isFieldSchema(field) ? (openBlock(), createElementBlock(Fragment, { key: 3 }, [createCommentVNode(" Field "), createVNode(form_item_default, {
6213
+ prop: field.name,
6214
+ label: field.label,
6215
+ required: hasRequiredRule(field),
6216
+ "data-field": field.name
6217
+ }, {
6218
+ default: withCtx(() => [renderSlot(_ctx.$slots, field.name, {}, () => [(openBlock(), createBlock(resolveDynamicComponent(getComponent(field)), mergeProps({
6219
+ modelValue: localModel.value[field.name],
6220
+ "onUpdate:modelValue": ($event) => localModel.value[field.name] = $event
6221
+ }, { ref_for: true }, field.componentProps, {
6222
+ placeholder: field.placeholder,
6223
+ disabled: field.disabled,
6224
+ options: field.options,
6225
+ "onUpdate:modelValue": (v) => handleChange(field.name, v)
6226
+ }), null, 16, [
6227
+ "modelValue",
6228
+ "onUpdate:modelValue",
6229
+ "placeholder",
6230
+ "disabled",
6231
+ "options"
6232
+ ]))], true)]),
6233
+ _: 2
6234
+ }, 1032, [
6235
+ "prop",
6236
+ "label",
6237
+ "required",
6238
+ "data-field"
6239
+ ])], 64)) : createCommentVNode("v-if", true)], 64);
6240
+ }), 128)),
6241
+ createCommentVNode(" Default slot for custom content "),
6242
+ renderSlot(_ctx.$slots, "default", {}, void 0, true)
6243
+ ]),
6244
+ _: 3
6245
+ }, 8, [
6246
+ "modelValue",
6247
+ "rules",
6248
+ "layout",
6249
+ "label-width",
6250
+ "label-position",
6251
+ "disabled"
6252
+ ]);
6253
+ };
6254
+ }
6255
+ }), [["__scopeId", "data-v-624e5d24"]]);
4278
6256
  var space_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineComponent({
4279
6257
  name: "YdSpace",
4280
6258
  __name: "space",
@@ -4290,11 +6268,11 @@ var space_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
4290
6268
  setup(__props) {
4291
6269
  const props = __props;
4292
6270
  const sizeMap = {
4293
- xs: "4px",
4294
- sm: "8px",
4295
- md: "12px",
4296
- lg: "16px",
4297
- xl: "24px"
6271
+ xs: "var(--yd-spacing-xs)",
6272
+ sm: "var(--yd-spacing-sm)",
6273
+ md: "var(--yd-spacing-md)",
6274
+ lg: "var(--yd-spacing-base)",
6275
+ xl: "var(--yd-spacing-xl)"
4298
6276
  };
4299
6277
  const spaceClasses = computed(() => cn("yd-space", `yd-space--${props.direction}`, props.wrap && "yd-space--wrap", props.align && `yd-space--align-${props.align}`));
4300
6278
  const spaceStyle = computed(() => {
@@ -4312,7 +6290,7 @@ var space_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
4312
6290
  }, [renderSlot(_ctx.$slots, "default", {}, void 0, true)], 6);
4313
6291
  };
4314
6292
  }
4315
- }), [["__scopeId", "data-v-b4fe0afb"]]);
6293
+ }), [["__scopeId", "data-v-e6e2e015"]]);
4316
6294
  var divider_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineComponent({
4317
6295
  name: "YdDivider",
4318
6296
  __name: "divider",
@@ -4330,14 +6308,13 @@ var divider_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defi
4330
6308
  const props = __props;
4331
6309
  const dividerClasses = computed(() => cn("yd-divider", `yd-divider--${props.direction}`, `yd-divider--${props.type}`, `yd-divider--${props.orientation}`, `yd-divider--${props.variant}`, props.dashed && "yd-divider--dashed"));
4332
6310
  const dividerStyle = computed(() => {
4333
- const colors = {
6311
+ return { "--divider-color": {
4334
6312
  default: "var(--yd-color-border)",
4335
6313
  primary: "var(--yd-color-primary-500)",
4336
6314
  success: "var(--yd-color-success)",
4337
6315
  warning: "var(--yd-color-warning)",
4338
6316
  error: "var(--yd-color-error)"
4339
- };
4340
- return { "--divider-color": colors[props.variant] };
6317
+ }[props.variant] };
4341
6318
  });
4342
6319
  function e(element) {
4343
6320
  return `yd-divider__${element}`;
@@ -4409,6 +6386,26 @@ var menu_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineC
4409
6386
  },
4410
6387
  emits: ["update:modelValue", "select"],
4411
6388
  setup(__props, { emit: __emit }) {
6389
+ const instance = getCurrentInstance();
6390
+ /**
6391
+ * 渲染图标 - 支持字符串图标和组件图标
6392
+ */
6393
+ function renderIcon(icon) {
6394
+ if (!icon) return null;
6395
+ if (typeof icon === "object" && "component" in icon) {
6396
+ const componentName = icon.component;
6397
+ const iconProps = icon.props || {};
6398
+ const globalComp = instance?.appContext.config.globalProperties.$[componentName];
6399
+ if (globalComp) return () => h(globalComp, iconProps);
6400
+ const app = instance?.appContext.app;
6401
+ if (app) {
6402
+ const comp = app.config.globalProperties[componentName];
6403
+ if (comp) return () => h(comp, iconProps);
6404
+ }
6405
+ return () => componentName;
6406
+ }
6407
+ return () => icon;
6408
+ }
4412
6409
  const props = __props;
4413
6410
  const emit = __emit;
4414
6411
  const activeSubmenu = ref(null);
@@ -4592,10 +6589,10 @@ var menu_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineC
4592
6589
  onClick: ($event) => toggleSubmenu(item.key),
4593
6590
  onKeydown: [withKeys(($event) => toggleSubmenu(item.key), ["enter"]), withKeys(($event) => handleSubmenuLeave(item.key), ["esc"])]
4594
6591
  }, [
4595
- item.icon ? (openBlock(), createElementBlock("span", {
6592
+ item.icon ? (openBlock(), createBlock(resolveDynamicComponent(renderIcon(item.icon)), {
4596
6593
  key: 0,
4597
6594
  class: normalizeClass(e("icon"))
4598
- }, toDisplayString(item.icon), 3)) : createCommentVNode("v-if", true),
6595
+ }, null, 8, ["class"])) : createCommentVNode("v-if", true),
4599
6596
  createElementVNode("span", { class: normalizeClass(e("label")) }, toDisplayString(item.label), 3),
4600
6597
  createElementVNode("span", {
4601
6598
  class: normalizeClass(e("arrow")),
@@ -4798,7 +6795,142 @@ var menu_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineC
4798
6795
  }), 128))], 10, _hoisted_1$20);
4799
6796
  };
4800
6797
  }
4801
- }), [["__scopeId", "data-v-78398467"]]);
6798
+ }), [["__scopeId", "data-v-9dfb9940"]]);
6799
+ //#endregion
6800
+ //#region src/composables/use-menu.ts
6801
+ /**
6802
+ * 检查用户是否有权限访问菜单项
6803
+ */
6804
+ function hasPermission$1(menuPermission, userPermissions) {
6805
+ if (!menuPermission) return true;
6806
+ const perms = Array.isArray(menuPermission) ? menuPermission : [menuPermission];
6807
+ const userPerms = userPermissions.permissions || [];
6808
+ return perms.some((p) => userPerms.includes(p));
6809
+ }
6810
+ /**
6811
+ * 检查用户是否有角色访问菜单项
6812
+ */
6813
+ function hasRole(menuRoles, userPermissions) {
6814
+ if (!menuRoles) return true;
6815
+ const roles = Array.isArray(menuRoles) ? menuRoles : [menuRoles];
6816
+ const userRoles = userPermissions.roles || [];
6817
+ return roles.some((r) => userRoles.includes(r));
6818
+ }
6819
+ /**
6820
+ * 过滤菜单项(根据权限和隐藏状态)
6821
+ */
6822
+ function filterMenuItems(items, userPermissions) {
6823
+ if (!items) return [];
6824
+ const result = [];
6825
+ for (const item of items) {
6826
+ if (item.hidden) continue;
6827
+ if (userPermissions) {
6828
+ if (!hasPermission$1(item.permission, userPermissions)) continue;
6829
+ if (!hasRole(item.roles, userPermissions)) continue;
6830
+ }
6831
+ const filteredChildren = item.children ? filterMenuItems(item.children, userPermissions) : void 0;
6832
+ if (!item.children || filteredChildren && filteredChildren.length > 0) result.push({
6833
+ ...item,
6834
+ children: filteredChildren
6835
+ });
6836
+ }
6837
+ return result;
6838
+ }
6839
+ /**
6840
+ * 根据菜单生成路由配置
6841
+ */
6842
+ function menuToRoutes(items, basePath = "") {
6843
+ const routes = [];
6844
+ for (const item of items) {
6845
+ if (item.hidden) continue;
6846
+ const routePath = item.path || item.key;
6847
+ const fullPath = basePath ? `${basePath}/${routePath}` : routePath;
6848
+ routes.push({
6849
+ path: fullPath,
6850
+ name: item.key,
6851
+ meta: {
6852
+ title: item.label,
6853
+ icon: item.icon,
6854
+ permission: item.permission,
6855
+ roles: item.roles,
6856
+ ...typeof item.route === "object" ? item.route : {}
6857
+ }
6858
+ });
6859
+ if (item.children && item.children.length > 0) routes.push(...menuToRoutes(item.children, fullPath));
6860
+ }
6861
+ return routes;
6862
+ }
6863
+ /**
6864
+ * 从当前激活菜单 key 获取面包屑路径
6865
+ */
6866
+ function getBreadcrumbPaths(items, activeKey, currentPath = []) {
6867
+ for (const item of items) {
6868
+ if (item.key === activeKey) return [...currentPath, item];
6869
+ if (item.children && item.children.length > 0) {
6870
+ const found = getBreadcrumbPaths(item.children, activeKey, [...currentPath, item]);
6871
+ if (found.length > 0) return found;
6872
+ }
6873
+ }
6874
+ return [];
6875
+ }
6876
+ /**
6877
+ * 从菜单 key 查找菜单项
6878
+ */
6879
+ function findMenuItem(items, key) {
6880
+ for (const item of items) {
6881
+ if (item.key === key) return item;
6882
+ if (item.children && item.children.length > 0) {
6883
+ const found = findMenuItem(item.children, key);
6884
+ if (found) return found;
6885
+ }
6886
+ }
6887
+ }
6888
+ /**
6889
+ * 查找菜单项的完整路径
6890
+ */
6891
+ function findMenuPath(items, key, parents = []) {
6892
+ for (const item of items) {
6893
+ if (item.key === key) return [...parents, item];
6894
+ if (item.children && item.children.length > 0) {
6895
+ const found = findMenuPath(item.children, key, [...parents, item]);
6896
+ if (found.length > 0) return found;
6897
+ }
6898
+ }
6899
+ return [];
6900
+ }
6901
+ /**
6902
+ * 搜索菜单项(模糊搜索,支持权限过滤)
6903
+ */
6904
+ function searchMenuItems(items, query, userPermissions) {
6905
+ if (!query || !query.trim()) return filterMenuItems(items, userPermissions);
6906
+ const searchTerm = query.trim().toLowerCase();
6907
+ const result = [];
6908
+ for (const item of items) {
6909
+ if (item.hidden) continue;
6910
+ if (userPermissions) {
6911
+ if (!hasPermission$1(item.permission, userPermissions)) continue;
6912
+ if (!hasRole(item.roles, userPermissions)) continue;
6913
+ }
6914
+ const labelMatch = item.label.toLowerCase().includes(searchTerm);
6915
+ const matchedChildren = item.children ? searchMenuItems(item.children, query, userPermissions) : [];
6916
+ if (labelMatch || matchedChildren.length > 0) result.push({
6917
+ ...item,
6918
+ children: matchedChildren.length > 0 ? matchedChildren : item.children
6919
+ });
6920
+ }
6921
+ return result;
6922
+ }
6923
+ /**
6924
+ * 获取菜单项的扁平化列表(用于搜索)
6925
+ */
6926
+ function flattenMenuItems(items) {
6927
+ const result = [];
6928
+ for (const item of items) {
6929
+ result.push(item);
6930
+ if (item.children && item.children.length > 0) result.push(...flattenMenuItems(item.children));
6931
+ }
6932
+ return result;
6933
+ }
4802
6934
  //#endregion
4803
6935
  //#region src/components/layout/layout/layout-sidebar.vue
4804
6936
  const _hoisted_1$19 = ["src", "alt"];
@@ -4829,12 +6961,18 @@ var layout_sidebar_default = /* @__PURE__ */ export_helper_default(/* @__PURE__
4829
6961
  default: false
4830
6962
  },
4831
6963
  popupAlign: { default: "trigger" },
4832
- footerText: { default: "" }
6964
+ footerText: { default: "" },
6965
+ searchable: {
6966
+ type: Boolean,
6967
+ default: false
6968
+ },
6969
+ roles: { default: [] }
4833
6970
  },
4834
6971
  emits: [
4835
6972
  "collapse",
4836
6973
  "menu-click",
4837
- "width-change"
6974
+ "width-change",
6975
+ "path-change"
4838
6976
  ],
4839
6977
  setup(__props, { emit: __emit }) {
4840
6978
  const props = __props;
@@ -4869,6 +7007,38 @@ var layout_sidebar_default = /* @__PURE__ */ export_helper_default(/* @__PURE__
4869
7007
  watch(() => props.expandedWidth, (val) => {
4870
7008
  if (val && val !== localWidth.value) localWidth.value = val;
4871
7009
  });
7010
+ const searchQuery = ref("");
7011
+ ref(null);
7012
+ function handleSearch() {}
7013
+ function clearSearch() {
7014
+ searchQuery.value = "";
7015
+ }
7016
+ function filterItemsByRole(items, roles) {
7017
+ if (!items || roles.length === 0) return items;
7018
+ const result = [];
7019
+ for (const item of items) {
7020
+ if (item.hidden) continue;
7021
+ if (item.roles && item.roles.length > 0) {
7022
+ if (!item.roles.some((r) => roles.includes(r))) continue;
7023
+ }
7024
+ const filteredChildren = item.children ? filterItemsByRole(item.children, roles) : void 0;
7025
+ if (!item.children || filteredChildren && filteredChildren.length > 0) result.push({
7026
+ ...item,
7027
+ children: filteredChildren
7028
+ });
7029
+ }
7030
+ return result;
7031
+ }
7032
+ const displayMenuItems = computed(() => {
7033
+ let items = props.menuItems || [];
7034
+ const userRoles = props.roles;
7035
+ if (userRoles && (Array.isArray(userRoles) ? userRoles.length > 0 : userRoles)) items = filterItemsByRole(items, Array.isArray(userRoles) ? userRoles : [userRoles]);
7036
+ if (!searchQuery.value || !searchQuery.value.trim()) return items;
7037
+ return searchMenuItems(items, searchQuery.value.trim());
7038
+ });
7039
+ watch(() => props.collapsed, () => {
7040
+ if (props.collapsed) searchQuery.value = "";
7041
+ });
4872
7042
  const isMobileExpanded = computed(() => props.isMobile && !props.collapsed);
4873
7043
  const sidebarClasses = computed(() => cn("yd-layout-sidebar", `yd-layout-sidebar--${props.theme}`, props.collapsed && "yd-layout-sidebar--collapsed", isMobileExpanded.value && "yd-layout-sidebar--fixed"));
4874
7044
  function el(name) {
@@ -4876,8 +7046,7 @@ var layout_sidebar_default = /* @__PURE__ */ export_helper_default(/* @__PURE__
4876
7046
  }
4877
7047
  const sidebarStyle = computed(() => {
4878
7048
  const isMobileMode = props.isMobile && !props.collapsed;
4879
- const currentWidth = props.resizable && !props.collapsed && !isMobileMode ? localWidth.value : props.expandedWidth;
4880
- const width = props.collapsed ? `${props.collapsedWidth}px` : isMobileMode ? "100%" : `${currentWidth}px`;
7049
+ const width = props.collapsed ? `${props.collapsedWidth}px` : isMobileMode ? "100%" : `${props.resizable && !props.collapsed && !isMobileMode ? localWidth.value : props.expandedWidth}px`;
4881
7050
  const style = {
4882
7051
  width,
4883
7052
  flex: isMobileMode ? "none" : `0 0 ${width}`
@@ -4891,9 +7060,13 @@ var layout_sidebar_default = /* @__PURE__ */ export_helper_default(/* @__PURE__
4891
7060
  }
4892
7061
  return style;
4893
7062
  });
4894
- function handleMenuClick(item) {
4895
- if (item.disabled) return;
4896
- emit("menu-click", item.key);
7063
+ function handleMenuClick(keyOrItem) {
7064
+ const key = typeof keyOrItem === "string" ? keyOrItem : keyOrItem.key;
7065
+ const item = typeof keyOrItem === "string" ? findMenuItem(props.menuItems || [], keyOrItem) : keyOrItem;
7066
+ if (!item || item.disabled) return;
7067
+ const pathLabels = findMenuPath(props.menuItems || [], key).map((p) => p.label);
7068
+ emit("menu-click", key, item);
7069
+ emit("path-change", pathLabels);
4897
7070
  }
4898
7071
  return (_ctx, _cache) => {
4899
7072
  return openBlock(), createElementBlock("aside", {
@@ -4912,7 +7085,7 @@ var layout_sidebar_default = /* @__PURE__ */ export_helper_default(/* @__PURE__
4912
7085
  }, null, 10, _hoisted_1$19)) : (openBlock(), createElementBlock("div", {
4913
7086
  key: 1,
4914
7087
  class: normalizeClass(el("logo-icon").value)
4915
- }, [..._cache[1] || (_cache[1] = [createElementVNode("svg", {
7088
+ }, [..._cache[2] || (_cache[2] = [createElementVNode("svg", {
4916
7089
  xmlns: "http://www.w3.org/2000/svg",
4917
7090
  width: "28",
4918
7091
  height: "28",
@@ -4950,11 +7123,26 @@ var layout_sidebar_default = /* @__PURE__ */ export_helper_default(/* @__PURE__
4950
7123
  }, toDisplayString(__props.title), 3)) : createCommentVNode("v-if", true)]),
4951
7124
  _: 1
4952
7125
  })], 2),
7126
+ createCommentVNode(" 搜索框 "),
7127
+ __props.searchable && !__props.collapsed ? (openBlock(), createElementBlock("div", {
7128
+ key: 0,
7129
+ class: normalizeClass(el("search").value)
7130
+ }, [withDirectives(createElementVNode("input", {
7131
+ "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => searchQuery.value = $event),
7132
+ type: "text",
7133
+ class: normalizeClass(el("search-input").value),
7134
+ placeholder: "搜索菜单...",
7135
+ onInput: handleSearch
7136
+ }, null, 34), [[vModelText, searchQuery.value]]), searchQuery.value ? (openBlock(), createElementBlock("span", {
7137
+ key: 0,
7138
+ class: normalizeClass(el("search-clear").value),
7139
+ onClick: clearSearch
7140
+ }, "×", 2)) : createCommentVNode("v-if", true)], 2)) : createCommentVNode("v-if", true),
4953
7141
  createCommentVNode(" 菜单区域 "),
4954
- createElementVNode("div", { class: normalizeClass(el("menu-wrapper").value) }, [renderSlot(_ctx.$slots, "sider", {}, () => [__props.menuItems.length > 0 ? (openBlock(), createBlock(unref(menu_default), {
7142
+ createElementVNode("div", { class: normalizeClass(el("menu-wrapper").value) }, [renderSlot(_ctx.$slots, "sider", {}, () => [displayMenuItems.value.length > 0 ? (openBlock(), createBlock(unref(menu_default), {
4955
7143
  key: 0,
4956
7144
  "model-value": __props.activeKey,
4957
- items: __props.menuItems,
7145
+ items: displayMenuItems.value,
4958
7146
  mode: "vertical",
4959
7147
  collapsed: __props.collapsed,
4960
7148
  waterfall: __props.waterfall,
@@ -4968,22 +7156,25 @@ var layout_sidebar_default = /* @__PURE__ */ export_helper_default(/* @__PURE__
4968
7156
  "waterfall",
4969
7157
  "popup-align",
4970
7158
  "dropdown-theme"
4971
- ])) : createCommentVNode("v-if", true)], true)], 2),
7159
+ ])) : searchQuery.value && displayMenuItems.value.length === 0 ? (openBlock(), createElementBlock("div", {
7160
+ key: 1,
7161
+ class: normalizeClass(el("search-empty").value)
7162
+ }, " 无匹配结果 ", 2)) : createCommentVNode("v-if", true)], true)], 2),
4972
7163
  createCommentVNode(" 底部支持信息 "),
4973
7164
  __props.footerText && !__props.collapsed ? (openBlock(), createElementBlock("div", {
4974
- key: 0,
7165
+ key: 1,
4975
7166
  class: normalizeClass(el("footer").value)
4976
7167
  }, [createElementVNode("div", { class: normalizeClass(el("footer-content").value) }, toDisplayString(__props.footerText), 3)], 2)) : createCommentVNode("v-if", true),
4977
7168
  createCommentVNode(" 拖拽调整手柄 "),
4978
7169
  __props.resizable && !__props.collapsed && !__props.isMobile ? (openBlock(), createElementBlock("div", {
4979
- key: 1,
7170
+ key: 2,
4980
7171
  class: normalizeClass(el("resize-handle").value),
4981
7172
  onMousedown: handleDragStart
4982
7173
  }, null, 34)) : createCommentVNode("v-if", true)
4983
7174
  ], 6);
4984
7175
  };
4985
7176
  }
4986
- }), [["__scopeId", "data-v-11c3fb43"]]);
7177
+ }), [["__scopeId", "data-v-38d5b5bc"]]);
4987
7178
  //#endregion
4988
7179
  //#region src/components/navigation/tabs/tabs.vue
4989
7180
  const _hoisted_1$18 = [
@@ -5596,7 +7787,7 @@ var tabs_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineC
5596
7787
  ], 2);
5597
7788
  };
5598
7789
  }
5599
- }), [["__scopeId", "data-v-4f0651bb"]]);
7790
+ }), [["__scopeId", "data-v-65b74196"]]);
5600
7791
  //#endregion
5601
7792
  //#region src/components/navigation/dropdown/dropdown.vue
5602
7793
  const _hoisted_1$17 = [
@@ -5630,7 +7821,6 @@ var dropdown_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ def
5630
7821
  const positionKey = ref(0);
5631
7822
  const menuStyle = computed(() => {
5632
7823
  if (!triggerRef.value) return {};
5633
- positionKey.value;
5634
7824
  const rect = triggerRef.value.getBoundingClientRect();
5635
7825
  const menuRect = menuRef.value?.getBoundingClientRect();
5636
7826
  const menuHeight = menuRect?.height || 0;
@@ -6315,7 +8505,7 @@ var drawer_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defin
6315
8505
  })], 8, ["disabled"]);
6316
8506
  };
6317
8507
  }
6318
- }), [["__scopeId", "data-v-3cbd3e99"]]);
8508
+ }), [["__scopeId", "data-v-94becd9a"]]);
6319
8509
  //#endregion
6320
8510
  //#region src/components/layout/layout/layout-types.ts
6321
8511
  /** 默认尺寸 */
@@ -6810,7 +9000,7 @@ var card_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineC
6810
9000
  ], 16);
6811
9001
  };
6812
9002
  }
6813
- }), [["__scopeId", "data-v-ab14db69"]]);
9003
+ }), [["__scopeId", "data-v-264319fe"]]);
6814
9004
  var tooltip_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineComponent({
6815
9005
  name: "YdTooltip",
6816
9006
  __name: "tooltip",
@@ -6906,29 +9096,43 @@ var tooltip_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defi
6906
9096
  //#endregion
6907
9097
  //#region src/components/data-display/table/table.vue
6908
9098
  const _hoisted_1$13 = { key: 0 };
6909
- const _hoisted_2$8 = ["onClick"];
9099
+ const _hoisted_2$8 = [
9100
+ "draggable",
9101
+ "onDragstart",
9102
+ "onDragover",
9103
+ "onDrop"
9104
+ ];
6910
9105
  const _hoisted_3$5 = ["onClick"];
6911
- const _hoisted_4$4 = ["onClick"];
6912
- const _hoisted_5$1 = [
9106
+ const _hoisted_4$4 = ["onMousedown"];
9107
+ const _hoisted_5$1 = ["onClick"];
9108
+ const _hoisted_6$1 = ["onClick"];
9109
+ const _hoisted_7 = [
6913
9110
  "title",
6914
9111
  "onMouseenter",
6915
9112
  "onMouseleave"
6916
9113
  ];
6917
- const _hoisted_6$1 = ["colspan"];
6918
- const _hoisted_7 = ["onClick"];
6919
- const _hoisted_8 = ["onClick"];
6920
- const _hoisted_9 = ["onClick"];
6921
- const _hoisted_10 = [
9114
+ const _hoisted_8 = ["colspan"];
9115
+ const _hoisted_9 = [
9116
+ "draggable",
9117
+ "onDragstart",
9118
+ "onDragover",
9119
+ "onDrop"
9120
+ ];
9121
+ const _hoisted_10 = ["onClick"];
9122
+ const _hoisted_11 = ["onMousedown"];
9123
+ const _hoisted_12 = ["onClick"];
9124
+ const _hoisted_13 = ["onClick"];
9125
+ const _hoisted_14 = [
6922
9126
  "title",
6923
9127
  "onMouseenter",
6924
9128
  "onMouseleave"
6925
9129
  ];
6926
- const _hoisted_11 = ["colspan"];
6927
- const _hoisted_12 = { key: 0 };
6928
- const _hoisted_13 = ["colspan"];
6929
- const _hoisted_14 = ["disabled"];
6930
- const _hoisted_15 = ["onClick"];
6931
- const _hoisted_16 = ["disabled"];
9130
+ const _hoisted_15 = ["colspan"];
9131
+ const _hoisted_16 = { key: 0 };
9132
+ const _hoisted_17 = ["colspan"];
9133
+ const _hoisted_18 = ["disabled"];
9134
+ const _hoisted_19 = ["onClick"];
9135
+ const _hoisted_20 = ["disabled"];
6932
9136
  var table_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineComponent({
6933
9137
  name: "YdTable",
6934
9138
  __name: "table",
@@ -6986,17 +9190,31 @@ var table_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
6986
9190
  type: Boolean,
6987
9191
  default: false
6988
9192
  },
6989
- exportFilename: { default: "table-data" }
9193
+ exportFilename: { default: "table-data" },
9194
+ remote: {
9195
+ type: Boolean,
9196
+ default: false
9197
+ },
9198
+ total: { default: 0 },
9199
+ loadMore: {
9200
+ type: Boolean,
9201
+ default: false
9202
+ }
6990
9203
  },
6991
9204
  emits: [
6992
9205
  "sort",
9206
+ "sort-change",
6993
9207
  "page-change",
6994
9208
  "row-click",
6995
- "expand"
9209
+ "expand",
9210
+ "scroll-end",
9211
+ "column-resize",
9212
+ "column-reorder"
6996
9213
  ],
6997
9214
  setup(__props, { expose: __expose, emit: __emit }) {
6998
9215
  const props = __props;
6999
9216
  const emit = __emit;
9217
+ const sortStates = ref([]);
7000
9218
  const sortKey = ref("");
7001
9219
  const sortOrder = ref("asc");
7002
9220
  const currentPage = ref(1);
@@ -7007,6 +9225,8 @@ var table_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
7007
9225
  const tooltipVisible = ref(false);
7008
9226
  const tooltipStyle = ref({});
7009
9227
  let tooltipTimer = null;
9228
+ const draggedColumnIndex = ref(null);
9229
+ const draggedOverColumnIndex = ref(null);
7010
9230
  const throttledUpdateTooltip = throttle((event, content) => {
7011
9231
  const target = event.currentTarget;
7012
9232
  if (!target) return;
@@ -7056,6 +9276,23 @@ var table_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
7056
9276
  });
7057
9277
  const tableClasses = computed(() => cn("yd-table-wrapper", props.bordered && "yd-table-wrapper--bordered"));
7058
9278
  const sortedData = computed(() => {
9279
+ if (props.remote) return [...props.dataSource];
9280
+ if (sortStates.value.length > 0) {
9281
+ const data = [...props.dataSource];
9282
+ data.sort((a, b) => {
9283
+ for (const state of sortStates.value) {
9284
+ if (!state.key || state.order === null) continue;
9285
+ const aVal = a[state.key];
9286
+ const bVal = b[state.key];
9287
+ let result = 0;
9288
+ if (aVal < bVal) result = -1;
9289
+ else if (aVal > bVal) result = 1;
9290
+ if (result !== 0) return state.order === "asc" ? result : -result;
9291
+ }
9292
+ return 0;
9293
+ });
9294
+ return data;
9295
+ }
7059
9296
  if (!sortKey.value) return [...props.dataSource];
7060
9297
  const data = [...props.dataSource];
7061
9298
  data.sort((a, b) => {
@@ -7067,9 +9304,13 @@ var table_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
7067
9304
  });
7068
9305
  return data;
7069
9306
  });
7070
- const total = computed(() => sortedData.value.length);
9307
+ const total = computed(() => {
9308
+ if (props.remote) return props.total;
9309
+ return sortedData.value.length;
9310
+ });
7071
9311
  const totalPages = computed(() => Math.ceil(total.value / props.pageSize));
7072
9312
  const displayData = computed(() => {
9313
+ if (props.remote) return sortedData.value;
7073
9314
  if (!props.pagination) return sortedData.value;
7074
9315
  const start = (currentPage.value - 1) * props.pageSize;
7075
9316
  return sortedData.value.slice(start, start + props.pageSize);
@@ -7090,8 +9331,7 @@ var table_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
7090
9331
  });
7091
9332
  const visibleCount = computed(() => {
7092
9333
  if (!props.virtualScroll) return displayData.value.length;
7093
- const containerHeight = scrollContainer.value?.clientHeight || 400;
7094
- return Math.ceil(containerHeight / props.rowHeight) + props.overscan * 2;
9334
+ return Math.ceil((scrollContainer.value?.clientHeight || 400) / props.rowHeight) + props.overscan * 2;
7095
9335
  });
7096
9336
  const visibleRows = computed(() => {
7097
9337
  if (!props.virtualScroll) return displayData.value;
@@ -7104,20 +9344,107 @@ var table_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
7104
9344
  return `yd-table__${element}`;
7105
9345
  }
7106
9346
  function handleScroll() {
7107
- if (scrollContainer.value) scrollTop.value = scrollContainer.value.scrollTop;
9347
+ if (scrollContainer.value) {
9348
+ scrollTop.value = scrollContainer.value.scrollTop;
9349
+ if (props.remote && props.virtualScroll && props.loadMore) {
9350
+ const { scrollTop: st, scrollHeight, clientHeight } = scrollContainer.value;
9351
+ if (scrollHeight - st - clientHeight < 50) emit("scroll-end");
9352
+ }
9353
+ }
7108
9354
  }
7109
- function handleSort(key) {
7110
- if (sortKey.value === key) sortOrder.value = sortOrder.value === "asc" ? "desc" : "asc";
7111
- else {
7112
- sortKey.value = key;
7113
- sortOrder.value = "asc";
9355
+ function handleSort(key, event) {
9356
+ if (event?.shiftKey) {
9357
+ const existingIndex = sortStates.value.findIndex((s) => s.key === key);
9358
+ if (existingIndex >= 0) {
9359
+ const existing = sortStates.value[existingIndex];
9360
+ if (existing.order === null) sortStates.value[existingIndex].order = "asc";
9361
+ else if (existing.order === "asc") sortStates.value[existingIndex].order = "desc";
9362
+ else sortStates.value.splice(existingIndex, 1);
9363
+ } else sortStates.value.push({
9364
+ key,
9365
+ order: "asc",
9366
+ priority: sortStates.value.length + 1
9367
+ });
9368
+ emit("sort-change", sortStates.value);
9369
+ } else {
9370
+ if (sortKey.value === key) sortOrder.value = sortOrder.value === "asc" ? "desc" : "asc";
9371
+ else {
9372
+ sortKey.value = key;
9373
+ sortOrder.value = "asc";
9374
+ sortStates.value = [];
9375
+ }
9376
+ emit("sort", key, sortOrder.value);
9377
+ emit("sort-change", sortKey.value ? [{
9378
+ key: sortKey.value,
9379
+ order: sortOrder.value,
9380
+ priority: 1
9381
+ }] : []);
9382
+ }
9383
+ }
9384
+ function handlePageChange(page) {
9385
+ if (page < 1 || page > totalPages.value) return;
9386
+ currentPage.value = page;
9387
+ emit("page-change", page);
9388
+ }
9389
+ function isColumnSorted(key) {
9390
+ return sortStates.value.some((s) => s.key === key && s.order !== null) || sortKey.value === key && sortStates.value.length === 0;
9391
+ }
9392
+ function getSortOrder(key) {
9393
+ return sortStates.value.find((s) => s.key === key)?.order || null;
9394
+ }
9395
+ function getSortPriority(key) {
9396
+ const index = sortStates.value.findIndex((s) => s.key === key && s.order !== null);
9397
+ return index >= 0 ? index + 1 : 0;
9398
+ }
9399
+ const columnWidths = ref({});
9400
+ let resizeStartX = 0;
9401
+ let resizeColumnKey = "";
9402
+ function startResize(event, key) {
9403
+ resizeStartX = event.clientX;
9404
+ resizeColumnKey = key;
9405
+ document.addEventListener("mousemove", handleResizeMove);
9406
+ document.addEventListener("mouseup", stopResize);
9407
+ event.preventDefault();
9408
+ }
9409
+ function handleResizeMove(event) {
9410
+ if (!resizeColumnKey) return;
9411
+ const delta = event.clientX - resizeStartX;
9412
+ const currentWidth = parseFloat(columnWidths.value[resizeColumnKey] || props.columns.find((c) => c.key === resizeColumnKey)?.width?.replace("px", "") || "100");
9413
+ const newWidth = Math.max(50, currentWidth + delta);
9414
+ columnWidths.value[resizeColumnKey] = `${newWidth}px`;
9415
+ resizeStartX = event.clientX;
9416
+ }
9417
+ function stopResize() {
9418
+ document.removeEventListener("mousemove", handleResizeMove);
9419
+ document.removeEventListener("mouseup", stopResize);
9420
+ if (resizeColumnKey && columnWidths.value[resizeColumnKey]) emit("column-resize", resizeColumnKey, columnWidths.value[resizeColumnKey]);
9421
+ resizeColumnKey = "";
9422
+ }
9423
+ function handleColumnDragStart(event, index) {
9424
+ if (!props.columns[index]?.draggable) return;
9425
+ draggedColumnIndex.value = index;
9426
+ if (event.dataTransfer) {
9427
+ event.dataTransfer.effectAllowed = "move";
9428
+ event.dataTransfer.setData("text/plain", String(index));
7114
9429
  }
7115
- emit("sort", key, sortOrder.value);
7116
9430
  }
7117
- function handlePageChange(page) {
7118
- if (page < 1 || page > totalPages.value) return;
7119
- currentPage.value = page;
7120
- emit("page-change", page);
9431
+ function handleColumnDragOver(event, index) {
9432
+ event.preventDefault();
9433
+ if (draggedColumnIndex.value !== null && draggedColumnIndex.value !== index) draggedOverColumnIndex.value = index;
9434
+ }
9435
+ function handleColumnDragLeave() {
9436
+ draggedOverColumnIndex.value = null;
9437
+ }
9438
+ function handleColumnDrop(event, toIndex) {
9439
+ event.preventDefault();
9440
+ const fromIndex = draggedColumnIndex.value;
9441
+ if (fromIndex !== null && fromIndex !== toIndex) emit("column-reorder", fromIndex, toIndex);
9442
+ draggedColumnIndex.value = null;
9443
+ draggedOverColumnIndex.value = null;
9444
+ }
9445
+ function handleColumnDragEnd() {
9446
+ draggedColumnIndex.value = null;
9447
+ draggedOverColumnIndex.value = null;
7121
9448
  }
7122
9449
  function handleRowClick(row) {
7123
9450
  emit("row-click", row);
@@ -7252,24 +9579,42 @@ var table_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
7252
9579
  }, [createElementVNode("span", {
7253
9580
  class: normalizeClass(e("expand-all")),
7254
9581
  onClick: toggleExpandAll
7255
- }, toDisplayString(isAllExpanded.value ? "▾" : "▸"), 3)], 2)) : createCommentVNode("v-if", true), (openBlock(true), createElementBlock(Fragment, null, renderList(__props.columns, (col) => {
9582
+ }, toDisplayString(isAllExpanded.value ? "▾" : "▸"), 3)], 2)) : createCommentVNode("v-if", true), (openBlock(true), createElementBlock(Fragment, null, renderList(__props.columns, (col, colIndex) => {
7256
9583
  return openBlock(), createElementBlock("div", {
7257
9584
  key: col.key,
7258
9585
  class: normalizeClass([
7259
9586
  e("th"),
7260
9587
  col.align && e(`th--${col.align}`),
7261
- col.fixed && e(`th--fixed-${col.fixed}`)
9588
+ col.fixed && e(`th--fixed-${col.fixed}`),
9589
+ col.resizable && e("th--resizable"),
9590
+ col.draggable && e("th--draggable"),
9591
+ draggedColumnIndex.value === colIndex && e("th--dragging"),
9592
+ draggedOverColumnIndex.value === colIndex && e("th--drag-over")
7262
9593
  ]),
9594
+ draggable: col.draggable,
7263
9595
  style: normalizeStyle(col.width ? {
7264
9596
  width: col.width,
7265
- minWidth: col.width,
9597
+ minWidth: col.minWidth || col.width,
7266
9598
  flexShrink: 0
7267
- } : {})
7268
- }, [createElementVNode("div", { class: normalizeClass(e("th-content")) }, [createElementVNode("span", null, toDisplayString(col.title), 1), col.sortable ? (openBlock(), createElementBlock("button", {
7269
- key: 0,
7270
- class: normalizeClass(e("sort-btn")),
7271
- onClick: ($event) => handleSort(col.key)
7272
- }, [createElementVNode("span", { class: normalizeClass([e("sort-icon"), { [e("sort-icon--active")]: sortKey.value === col.key }]) }, toDisplayString(sortKey.value === col.key ? sortOrder.value === "asc" ? "↑" : "↓" : "↕"), 3)], 10, _hoisted_2$8)) : createCommentVNode("v-if", true)], 2)], 6);
9599
+ } : { flex: 1 }),
9600
+ onDragstart: ($event) => handleColumnDragStart($event, colIndex),
9601
+ onDragover: ($event) => handleColumnDragOver($event, colIndex),
9602
+ onDragleave: handleColumnDragLeave,
9603
+ onDrop: ($event) => handleColumnDrop($event, colIndex),
9604
+ onDragend: handleColumnDragEnd
9605
+ }, [
9606
+ createElementVNode("div", { class: normalizeClass(e("th-content")) }, [createElementVNode("span", null, toDisplayString(col.title), 1), col.sortable || col.multipleSortable ? (openBlock(), createElementBlock("button", {
9607
+ key: 0,
9608
+ class: normalizeClass(e("sort-btn")),
9609
+ onClick: ($event) => handleSort(col.key, $event)
9610
+ }, [createElementVNode("span", { class: normalizeClass([e("sort-icon"), { [e("sort-icon--active")]: isColumnSorted(col.key) }]) }, [getSortPriority(col.key) > 0 ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createTextVNode(toDisplayString(getSortPriority(col.key)), 1)], 64)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [createTextVNode(toDisplayString(isColumnSorted(col.key) ? getSortOrder(col.key) === "asc" ? "↑" : "↓" : "↕"), 1)], 64))], 2)], 10, _hoisted_3$5)) : createCommentVNode("v-if", true)], 2),
9611
+ createCommentVNode(" Resize handle "),
9612
+ col.resizable ? (openBlock(), createElementBlock("div", {
9613
+ key: 0,
9614
+ class: normalizeClass(e("resize-handle")),
9615
+ onMousedown: withModifiers(($event) => startResize($event, col.key), ["stop"])
9616
+ }, null, 42, _hoisted_4$4)) : createCommentVNode("v-if", true)
9617
+ ], 46, _hoisted_2$8);
7273
9618
  }), 128))], 2)) : createCommentVNode("v-if", true),
7274
9619
  createCommentVNode(" Visible rows "),
7275
9620
  (openBlock(true), createElementBlock(Fragment, null, renderList(visibleRows.value, (row, index) => {
@@ -7297,7 +9642,7 @@ var table_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
7297
9642
  }, [createElementVNode("span", {
7298
9643
  class: normalizeClass([e("expand-icon"), { [e("expand-icon--expanded")]: expandedRows.value.has(startIndex.value + index) }]),
7299
9644
  onClick: withModifiers(($event) => toggleExpand(startIndex.value + index), ["stop"])
7300
- }, toDisplayString(expandedRows.value.has(startIndex.value + index) ? "▾" : "▸"), 11, _hoisted_4$4)], 2)) : createCommentVNode("v-if", true), (openBlock(true), createElementBlock(Fragment, null, renderList(__props.columns, (col) => {
9645
+ }, toDisplayString(expandedRows.value.has(startIndex.value + index) ? "▾" : "▸"), 11, _hoisted_6$1)], 2)) : createCommentVNode("v-if", true), (openBlock(true), createElementBlock(Fragment, null, renderList(__props.columns, (col) => {
7301
9646
  return openBlock(), createElementBlock("div", {
7302
9647
  key: col.key,
7303
9648
  class: normalizeClass([
@@ -7318,8 +9663,8 @@ var table_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
7318
9663
  row,
7319
9664
  column: col,
7320
9665
  index: startIndex.value + index
7321
- }, () => [createTextVNode(toDisplayString(row[col.key]), 1)], true)], 46, _hoisted_5$1);
7322
- }), 128))], 14, _hoisted_3$5),
9666
+ }, () => [createTextVNode(toDisplayString(row[col.key]), 1)], true)], 46, _hoisted_7);
9667
+ }), 128))], 14, _hoisted_5$1),
7323
9668
  createCommentVNode(" Expand row "),
7324
9669
  __props.expandable && expandedRows.value.has(startIndex.value + index) ? (openBlock(), createElementBlock("div", {
7325
9670
  key: 0,
@@ -7335,7 +9680,7 @@ var table_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
7335
9680
  }, [renderSlot(_ctx.$slots, "expand", {
7336
9681
  row,
7337
9682
  index: startIndex.value + index
7338
- }, void 0, true)], 10, _hoisted_6$1)], 6)) : createCommentVNode("v-if", true)
9683
+ }, void 0, true)], 10, _hoisted_8)], 6)) : createCommentVNode("v-if", true)
7339
9684
  ], 64);
7340
9685
  }), 128)),
7341
9686
  displayData.value.length === 0 && !__props.loading ? (openBlock(), createElementBlock("div", {
@@ -7352,23 +9697,41 @@ var table_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
7352
9697
  }, [createElementVNode("span", {
7353
9698
  class: normalizeClass(e("expand-all")),
7354
9699
  onClick: toggleExpandAll
7355
- }, toDisplayString(isAllExpanded.value ? "▾" : "▸"), 3)], 2)) : createCommentVNode("v-if", true), (openBlock(true), createElementBlock(Fragment, null, renderList(__props.columns, (col) => {
9700
+ }, toDisplayString(isAllExpanded.value ? "▾" : "▸"), 3)], 2)) : createCommentVNode("v-if", true), (openBlock(true), createElementBlock(Fragment, null, renderList(__props.columns, (col, colIndex) => {
7356
9701
  return openBlock(), createElementBlock("th", {
7357
9702
  key: col.key,
7358
9703
  class: normalizeClass([
7359
9704
  e("th"),
7360
9705
  col.align && e(`th--${col.align}`),
7361
- col.fixed && e(`th--fixed-${col.fixed}`)
9706
+ col.fixed && e(`th--fixed-${col.fixed}`),
9707
+ col.resizable && e("th--resizable"),
9708
+ col.draggable && e("th--draggable"),
9709
+ draggedColumnIndex.value === colIndex && e("th--dragging"),
9710
+ draggedOverColumnIndex.value === colIndex && e("th--drag-over")
7362
9711
  ]),
9712
+ draggable: col.draggable,
7363
9713
  style: normalizeStyle(col.width ? {
7364
9714
  width: col.width,
7365
- minWidth: col.width
7366
- } : {})
7367
- }, [createElementVNode("div", { class: normalizeClass(e("th-content")) }, [createElementVNode("span", null, toDisplayString(col.title), 1), col.sortable ? (openBlock(), createElementBlock("button", {
7368
- key: 0,
7369
- class: normalizeClass(e("sort-btn")),
7370
- onClick: ($event) => handleSort(col.key)
7371
- }, [createElementVNode("span", { class: normalizeClass([e("sort-icon"), { [e("sort-icon--active")]: sortKey.value === col.key }]) }, toDisplayString(sortKey.value === col.key ? sortOrder.value === "asc" ? "↑" : "↓" : "↕"), 3)], 10, _hoisted_7)) : createCommentVNode("v-if", true)], 2)], 6);
9715
+ minWidth: col.minWidth || col.width
9716
+ } : {}),
9717
+ onDragstart: ($event) => handleColumnDragStart($event, colIndex),
9718
+ onDragover: ($event) => handleColumnDragOver($event, colIndex),
9719
+ onDragleave: handleColumnDragLeave,
9720
+ onDrop: ($event) => handleColumnDrop($event, colIndex),
9721
+ onDragend: handleColumnDragEnd
9722
+ }, [
9723
+ createElementVNode("div", { class: normalizeClass(e("th-content")) }, [createElementVNode("span", null, toDisplayString(col.title), 1), col.sortable || col.multipleSortable ? (openBlock(), createElementBlock("button", {
9724
+ key: 0,
9725
+ class: normalizeClass(e("sort-btn")),
9726
+ onClick: ($event) => handleSort(col.key, $event)
9727
+ }, [createElementVNode("span", { class: normalizeClass([e("sort-icon"), { [e("sort-icon--active")]: isColumnSorted(col.key) }]) }, [getSortPriority(col.key) > 0 ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createTextVNode(toDisplayString(getSortPriority(col.key)), 1)], 64)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [createTextVNode(toDisplayString(isColumnSorted(col.key) ? getSortOrder(col.key) === "asc" ? "↑" : "↓" : "↕"), 1)], 64))], 2)], 10, _hoisted_10)) : createCommentVNode("v-if", true)], 2),
9728
+ createCommentVNode(" Resize handle "),
9729
+ col.resizable ? (openBlock(), createElementBlock("div", {
9730
+ key: 0,
9731
+ class: normalizeClass(e("resize-handle")),
9732
+ onMousedown: withModifiers(($event) => startResize($event, col.key), ["stop"])
9733
+ }, null, 42, _hoisted_11)) : createCommentVNode("v-if", true)
9734
+ ], 46, _hoisted_9);
7372
9735
  }), 128))])], 2), createElementVNode("tbody", null, [(openBlock(true), createElementBlock(Fragment, null, renderList(displayData.value, (row, index) => {
7373
9736
  return openBlock(), createElementBlock(Fragment, { key: index }, [
7374
9737
  createElementVNode("tr", {
@@ -7384,7 +9747,7 @@ var table_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
7384
9747
  }, [createElementVNode("span", {
7385
9748
  class: normalizeClass([e("expand-icon"), { [e("expand-icon--expanded")]: expandedRows.value.has(index) }]),
7386
9749
  onClick: withModifiers(($event) => toggleExpand(index), ["stop"])
7387
- }, toDisplayString(expandedRows.value.has(index) ? "▾" : "▸"), 11, _hoisted_9)], 2)) : createCommentVNode("v-if", true), (openBlock(true), createElementBlock(Fragment, null, renderList(__props.columns, (col) => {
9750
+ }, toDisplayString(expandedRows.value.has(index) ? "▾" : "▸"), 11, _hoisted_13)], 2)) : createCommentVNode("v-if", true), (openBlock(true), createElementBlock(Fragment, null, renderList(__props.columns, (col) => {
7388
9751
  return openBlock(), createElementBlock("td", {
7389
9752
  key: col.key,
7390
9753
  class: normalizeClass([
@@ -7400,8 +9763,8 @@ var table_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
7400
9763
  row,
7401
9764
  column: col,
7402
9765
  index
7403
- }, () => [createTextVNode(toDisplayString(row[col.key]), 1)], true)], 42, _hoisted_10);
7404
- }), 128))], 10, _hoisted_8),
9766
+ }, () => [createTextVNode(toDisplayString(row[col.key]), 1)], true)], 42, _hoisted_14);
9767
+ }), 128))], 10, _hoisted_12),
7405
9768
  createCommentVNode(" Expand row "),
7406
9769
  __props.expandable && expandedRows.value.has(index) ? (openBlock(), createElementBlock("tr", {
7407
9770
  key: 0,
@@ -7412,12 +9775,12 @@ var table_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
7412
9775
  }, [renderSlot(_ctx.$slots, "expand", {
7413
9776
  row,
7414
9777
  index
7415
- }, void 0, true)], 10, _hoisted_11)], 2)) : createCommentVNode("v-if", true)
9778
+ }, void 0, true)], 10, _hoisted_15)], 2)) : createCommentVNode("v-if", true)
7416
9779
  ], 64);
7417
- }), 128)), displayData.value.length === 0 && !__props.loading ? (openBlock(), createElementBlock("tr", _hoisted_12, [createElementVNode("td", {
9780
+ }), 128)), displayData.value.length === 0 && !__props.loading ? (openBlock(), createElementBlock("tr", _hoisted_16, [createElementVNode("td", {
7418
9781
  class: normalizeClass(e("empty")),
7419
9782
  colspan: __props.columns.length + (__props.expandable ? 1 : 0)
7420
- }, [renderSlot(_ctx.$slots, "empty", {}, () => [createVNode(empty_default, { description: __props.emptyText }, null, 8, ["description"])], true)], 10, _hoisted_13)])) : createCommentVNode("v-if", true)])], 2)], 64))], 38),
9783
+ }, [renderSlot(_ctx.$slots, "empty", {}, () => [createVNode(empty_default, { description: __props.emptyText }, null, 8, ["description"])], true)], 10, _hoisted_17)])) : createCommentVNode("v-if", true)])], 2)], 64))], 38),
7421
9784
  createCommentVNode(" Export toolbar "),
7422
9785
  __props.exportable ? (openBlock(), createElementBlock("div", {
7423
9786
  key: 2,
@@ -7445,7 +9808,7 @@ var table_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
7445
9808
  class: normalizeClass(e("page-btn")),
7446
9809
  disabled: currentPage.value === 1,
7447
9810
  onClick: _cache[3] || (_cache[3] = ($event) => handlePageChange(currentPage.value - 1))
7448
- }, " ‹ ", 10, _hoisted_14),
9811
+ }, " ‹ ", 10, _hoisted_18),
7449
9812
  (openBlock(true), createElementBlock(Fragment, null, renderList(visiblePages.value, (page) => {
7450
9813
  return openBlock(), createElementBlock(Fragment, { key: page }, [page === "..." ? (openBlock(), createElementBlock("button", {
7451
9814
  key: 0,
@@ -7455,13 +9818,13 @@ var table_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
7455
9818
  key: 1,
7456
9819
  class: normalizeClass([e("page-btn"), { [e("page-btn--active")]: page === currentPage.value }]),
7457
9820
  onClick: ($event) => handlePageChange(page)
7458
- }, toDisplayString(page), 11, _hoisted_15))], 64);
9821
+ }, toDisplayString(page), 11, _hoisted_19))], 64);
7459
9822
  }), 128)),
7460
9823
  createElementVNode("button", {
7461
9824
  class: normalizeClass(e("page-btn")),
7462
9825
  disabled: currentPage.value === totalPages.value,
7463
9826
  onClick: _cache[4] || (_cache[4] = ($event) => handlePageChange(currentPage.value + 1))
7464
- }, " › ", 10, _hoisted_16),
9827
+ }, " › ", 10, _hoisted_20),
7465
9828
  createElementVNode("span", { class: normalizeClass(e("page-info")) }, "共 " + toDisplayString(total.value) + " 条", 3)
7466
9829
  ], 2)) : createCommentVNode("v-if", true),
7467
9830
  createCommentVNode(" Cell overflow tooltip "),
@@ -7476,7 +9839,7 @@ var table_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
7476
9839
  ], 2);
7477
9840
  };
7478
9841
  }
7479
- }), [["__scopeId", "data-v-c276ac4a"]]);
9842
+ }), [["__scopeId", "data-v-0736270c"]]);
7480
9843
  //#endregion
7481
9844
  //#region src/components/data-display/progress/progress.vue
7482
9845
  const _hoisted_1$12 = ["stroke-width"];
@@ -7814,8 +10177,7 @@ var tree_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineC
7814
10177
  });
7815
10178
  const visibleCount = computed(() => {
7816
10179
  if (!props.virtualScroll) return flatNodes.value.length;
7817
- const containerHeight = scrollContainer.value?.clientHeight || 400;
7818
- return Math.ceil(containerHeight / props.rowHeight) + props.overscan * 2;
10180
+ return Math.ceil((scrollContainer.value?.clientHeight || 400) / props.rowHeight) + props.overscan * 2;
7819
10181
  });
7820
10182
  const visibleNodes = computed(() => {
7821
10183
  if (!props.virtualScroll) return flatNodes.value;
@@ -8649,7 +11011,7 @@ var pagination_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ d
8649
11011
  ], 2);
8650
11012
  };
8651
11013
  }
8652
- }), [["__scopeId", "data-v-f4020c55"]]);
11014
+ }), [["__scopeId", "data-v-9e7079e4"]]);
8653
11015
  //#endregion
8654
11016
  //#region src/components/navigation/steps/steps.vue
8655
11017
  const _hoisted_1$7 = { key: 0 };
@@ -8915,7 +11277,7 @@ var modal_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ define
8915
11277
  })], 8, ["disabled"]);
8916
11278
  };
8917
11279
  }
8918
- }), [["__scopeId", "data-v-770df8cd"]]);
11280
+ }), [["__scopeId", "data-v-9c8fa661"]]);
8919
11281
  //#endregion
8920
11282
  //#region src/components/feedback/message/message.vue
8921
11283
  const _hoisted_1$4 = {
@@ -9744,6 +12106,78 @@ var context_menu_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */
9744
12106
  };
9745
12107
  }
9746
12108
  }), [["__scopeId", "data-v-5a5029b0"]]);
12109
+ var loading_bar_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineComponent({
12110
+ name: "YdLoadingBar",
12111
+ __name: "loading-bar",
12112
+ props: {
12113
+ percent: { default: 0 },
12114
+ status: { default: "normal" },
12115
+ size: { default: "md" },
12116
+ duration: { default: 200 },
12117
+ color: { default: "" }
12118
+ },
12119
+ setup(__props, { expose: __expose }) {
12120
+ const props = __props;
12121
+ const visible = ref(false);
12122
+ const currentPercent = ref(0);
12123
+ const loadingBarClasses = computed(() => cn("yd-loading-bar", `yd-loading-bar--${props.status}`, `yd-loading-bar--${props.size}`));
12124
+ const loadingBarStyle = computed(() => ({ "--yd-loading-bar-duration": `${props.duration}ms` }));
12125
+ const innerStyle = computed(() => {
12126
+ const width = `${currentPercent.value}%`;
12127
+ let background = props.color;
12128
+ if (!background) if (props.status === "success") background = "var(--yd-color-success)";
12129
+ else if (props.status === "error") background = "var(--yd-color-error)";
12130
+ else background = "var(--yd-color-primary-500)";
12131
+ return {
12132
+ width,
12133
+ background
12134
+ };
12135
+ });
12136
+ watch(() => props.percent, (newPercent) => {
12137
+ currentPercent.value = Math.min(100, Math.max(0, newPercent));
12138
+ });
12139
+ function start() {
12140
+ visible.value = true;
12141
+ currentPercent.value = 0;
12142
+ }
12143
+ function finish() {
12144
+ currentPercent.value = 100;
12145
+ setTimeout(() => {
12146
+ visible.value = false;
12147
+ setTimeout(() => {
12148
+ currentPercent.value = 0;
12149
+ }, props.duration);
12150
+ }, props.duration);
12151
+ }
12152
+ function setPercent(value) {
12153
+ visible.value = true;
12154
+ currentPercent.value = Math.min(100, Math.max(0, value));
12155
+ }
12156
+ function error() {
12157
+ visible.value = true;
12158
+ currentPercent.value = 100;
12159
+ }
12160
+ __expose({
12161
+ start,
12162
+ finish,
12163
+ setPercent,
12164
+ error
12165
+ });
12166
+ return (_ctx, _cache) => {
12167
+ return openBlock(), createBlock(Teleport, { to: "body" }, [createVNode(Transition, { name: "yd-loading-bar" }, {
12168
+ default: withCtx(() => [visible.value ? (openBlock(), createElementBlock("div", {
12169
+ key: 0,
12170
+ class: normalizeClass(loadingBarClasses.value),
12171
+ style: normalizeStyle(loadingBarStyle.value)
12172
+ }, [createElementVNode("div", {
12173
+ class: normalizeClass(_ctx.e("inner")),
12174
+ style: normalizeStyle(innerStyle.value)
12175
+ }, null, 6)], 6)) : createCommentVNode("v-if", true)]),
12176
+ _: 1
12177
+ })]);
12178
+ };
12179
+ }
12180
+ }), [["__scopeId", "data-v-a2e1e011"]]);
9747
12181
  //#endregion
9748
12182
  //#region src/components/config-provider/config-provider.vue
9749
12183
  const _hoisted_1 = ["data-theme"];
@@ -9821,7 +12255,7 @@ const DEFAULT_FORM = {
9821
12255
  * 登录表单逻辑
9822
12256
  */
9823
12257
  function useLoginForm(options = {}) {
9824
- const { showCaptcha = false, captchaCode, captchaKey, defaultTab = "account", onSendCode } = options;
12258
+ const { showCaptcha = false, captchaCode, captchaKey, defaultTab = "account", onSendCode, captchaAnswer, captchaMode = "client" } = options;
9825
12259
  const formData = reactive({ ...DEFAULT_FORM });
9826
12260
  const activeTab = ref(defaultTab);
9827
12261
  const errorMsg = ref("");
@@ -9852,8 +12286,13 @@ function useLoginForm(options = {}) {
9852
12286
  }
9853
12287
  },
9854
12288
  captcha: () => {
12289
+ if (captchaMode === "server") {
12290
+ if (showCaptcha && !formData.captchaCode) return "请输入图片验证码";
12291
+ return "";
12292
+ }
9855
12293
  if (showCaptcha && !formData.captchaCode) return "请输入图片验证码";
9856
- if (showCaptcha && formData.captchaCode.toUpperCase() !== captchaCode?.value.toUpperCase()) return "图片验证码错误";
12294
+ const expectedCode = captchaAnswer?.value || captchaCode?.value;
12295
+ if (showCaptcha && formData.captchaCode.toUpperCase() !== expectedCode?.toUpperCase()) return "图片验证码错误";
9857
12296
  return "";
9858
12297
  }
9859
12298
  };
@@ -9943,6 +12382,92 @@ function useLoginForm(options = {}) {
9943
12382
  };
9944
12383
  }
9945
12384
  //#endregion
12385
+ //#region src/composables/use-loading-bar.ts
12386
+ let loadingBarApp = null;
12387
+ let loadingBarInstance = null;
12388
+ const mountingContainer = ref(null);
12389
+ /**
12390
+ * 创建 LoadingBar 实例
12391
+ */
12392
+ function createLoadingBarInstance() {
12393
+ if (loadingBarApp) return loadingBarInstance;
12394
+ const container = document.createElement("div");
12395
+ container.id = "yd-loading-bar-container";
12396
+ document.body.appendChild(container);
12397
+ mountingContainer.value = container;
12398
+ loadingBarApp = createApp({ render() {
12399
+ return h(loading_bar_default);
12400
+ } });
12401
+ loadingBarInstance = loadingBarApp.mount(container);
12402
+ return loadingBarInstance;
12403
+ }
12404
+ /**
12405
+ * LoadingBar 组合式函数
12406
+ * 提供全局加载进度条控制方法
12407
+ * @returns LoadingBar 控制函数
12408
+ */
12409
+ function useLoadingBar() {
12410
+ /**
12411
+ * 开始加载
12412
+ * @param options - 配置选项
12413
+ */
12414
+ const start = (options) => {
12415
+ const instance = createLoadingBarInstance();
12416
+ if (instance) {
12417
+ instance.start();
12418
+ if (options?.size) instance.size = options.size;
12419
+ if (options?.color) instance.color = options.color;
12420
+ }
12421
+ };
12422
+ /**
12423
+ * 完成加载
12424
+ */
12425
+ const finish = () => {
12426
+ if (loadingBarInstance) loadingBarInstance.finish();
12427
+ };
12428
+ /**
12429
+ * 设置进度百分比
12430
+ * @param percent - 进度百分比 (0-100)
12431
+ */
12432
+ const setPercent = (percent) => {
12433
+ if (loadingBarInstance) loadingBarInstance.setPercent(percent);
12434
+ };
12435
+ /**
12436
+ * 显示错误状态
12437
+ */
12438
+ const error = () => {
12439
+ if (loadingBarInstance) loadingBarInstance.error();
12440
+ };
12441
+ return {
12442
+ start,
12443
+ finish,
12444
+ setPercent,
12445
+ error
12446
+ };
12447
+ }
12448
+ const loadingBar = {
12449
+ start: (options) => {
12450
+ const instance = createLoadingBarInstance();
12451
+ if (instance) {
12452
+ instance.start();
12453
+ if (options?.size) instance.size = options.size;
12454
+ if (options?.color) instance.color = options.color;
12455
+ }
12456
+ },
12457
+ finish: () => {
12458
+ const instance = createLoadingBarInstance();
12459
+ if (instance) instance.finish();
12460
+ },
12461
+ setPercent: (percent) => {
12462
+ const instance = createLoadingBarInstance();
12463
+ if (instance) instance.setPercent(percent);
12464
+ },
12465
+ error: () => {
12466
+ const instance = createLoadingBarInstance();
12467
+ if (instance) instance.error();
12468
+ }
12469
+ };
12470
+ //#endregion
9946
12471
  //#region src/hooks/use-loading.ts
9947
12472
  /**
9948
12473
  * Loading 状态管理 hook
@@ -9978,6 +12503,25 @@ function useLoading(initialValue = false) {
9978
12503
  };
9979
12504
  }
9980
12505
  //#endregion
12506
+ //#region src/types/index.ts
12507
+ /** 是否为数组 */
12508
+ const isArray = Array.isArray;
12509
+ /** 是否为对象 */
12510
+ const isObject = (val) => val !== null && typeof val === "object" && !isArray(val);
12511
+ /** 是否为日期 */
12512
+ const isDate = (val) => val instanceof Date;
12513
+ /** 是否为函数 */
12514
+ const isFunction = (val) => typeof val === "function";
12515
+ /** 是否为空 */
12516
+ const isEmpty = (val) => {
12517
+ if (val === null || val === void 0) return true;
12518
+ if (isArray(val) || typeof val === "string") return val.length === 0;
12519
+ if (isObject(val)) return Object.keys(val).length === 0;
12520
+ return false;
12521
+ };
12522
+ /** 是否为 Promise */
12523
+ const isPromise = (val) => val instanceof Promise || typeof val === "object" && typeof val?.["then"] === "function";
12524
+ //#endregion
9981
12525
  //#region src/styles/themes/index.ts
9982
12526
  /**
9983
12527
  * Theme definitions
@@ -10050,8 +12594,7 @@ function secureStoragePlugin({ store }) {
10050
12594
  if (isSession) storageReady.then(restore);
10051
12595
  else restore();
10052
12596
  store.$subscribe(async () => {
10053
- const plainState = { ...store.$state };
10054
- await storage.setItem(store.$id, plainState);
12597
+ await storage.setItem(store.$id, { ...store.$state });
10055
12598
  });
10056
12599
  }
10057
12600
  //#endregion
@@ -10496,6 +13039,7 @@ const modules = /* @__PURE__ */ Object.assign({
10496
13039
  "./langs/en-US.json": en_US_exports,
10497
13040
  "./langs/zh-CN.json": zh_CN_exports
10498
13041
  });
13042
+ const lazyLocales = /* @__PURE__ */ new Map();
10499
13043
  /**
10500
13044
  * 支持的语言
10501
13045
  */
@@ -10507,6 +13051,12 @@ const supportedLocales = [{
10507
13051
  value: "en-US"
10508
13052
  }];
10509
13053
  /**
13054
+ * 注册懒加载的 locale 文件
13055
+ */
13056
+ function registerLazyLocale(locale, loader) {
13057
+ lazyLocales.set(locale, loader);
13058
+ }
13059
+ /**
10510
13060
  * 获取 locale 消息
10511
13061
  */
10512
13062
  function getLocaleMessages() {
@@ -10528,10 +13078,23 @@ function setLocale(locale) {
10528
13078
  document?.querySelector("html")?.setAttribute("lang", locale);
10529
13079
  }
10530
13080
  /**
13081
+ * 获取当前语言
13082
+ */
13083
+ function getCurrentLocale() {
13084
+ return unref(i18n.global.locale);
13085
+ }
13086
+ /**
10531
13087
  * 初始化 i18n
10532
13088
  */
10533
13089
  async function setupI18n(app, options = {}) {
10534
- const { defaultLocale = "zh-CN" } = options;
13090
+ const { defaultLocale = "zh-CN", lazy = false } = options;
13091
+ if (lazy) {
13092
+ const supported = supportedLocales.map((l) => l.value);
13093
+ for (const locale of supported) if (!lazyLocales.has(locale)) try {
13094
+ const module = await import(`./langs/${locale}.json`);
13095
+ lazyLocales.set(locale, () => Promise.resolve(module.default));
13096
+ } catch {}
13097
+ }
10535
13098
  const messages = getLocaleMessages();
10536
13099
  i18n.global.setLocaleMessage(defaultLocale, messages[defaultLocale] || {});
10537
13100
  const fallbackLocale = defaultLocale === "zh-CN" ? "en-US" : "zh-CN";
@@ -10547,6 +13110,13 @@ async function setupI18n(app, options = {}) {
10547
13110
  */
10548
13111
  async function changeLocale(locale) {
10549
13112
  if (unref(i18n.global.locale) === locale) return;
13113
+ const lazyLoader = lazyLocales.get(locale);
13114
+ if (lazyLoader) {
13115
+ const messages = await lazyLoader();
13116
+ i18n.global.setLocaleMessage(locale, messages);
13117
+ setLocale(locale);
13118
+ return;
13119
+ }
10550
13120
  const messages = getLocaleMessages();
10551
13121
  if (!messages[locale]) {
10552
13122
  console.warn(`[yd-admin] Locale '${locale}' not found`);
@@ -10555,5 +13125,464 @@ async function changeLocale(locale) {
10555
13125
  i18n.global.setLocaleMessage(locale, messages[locale]);
10556
13126
  setLocale(locale);
10557
13127
  }
13128
+ /**
13129
+ * 获取翻译文本
13130
+ */
13131
+ function t(key, params) {
13132
+ const msg = i18n.global.t(key, params);
13133
+ return typeof msg === "string" ? msg : key;
13134
+ }
13135
+ /**
13136
+ * 获取翻译文本(复数形式)- 使用 'one' 和 'other' 选择器
13137
+ */
13138
+ function tc(key, choice, params) {
13139
+ const msg = i18n.global.t(`${key}.${choice === 1 ? "one" : "other"}`, params);
13140
+ return typeof msg === "string" ? msg : key;
13141
+ }
13142
+ /**
13143
+ * 获取日期时间格式化
13144
+ */
13145
+ function dt(value, options, locale) {
13146
+ const currentLocale = locale || unref(i18n.global.locale);
13147
+ return new Intl.DateTimeFormat(currentLocale, options).format(new Date(value));
13148
+ }
13149
+ /**
13150
+ * 获取数字格式化
13151
+ */
13152
+ function nf(value, options, locale) {
13153
+ const currentLocale = locale || unref(i18n.global.locale);
13154
+ return new Intl.NumberFormat(currentLocale, options).format(value);
13155
+ }
13156
+ //#endregion
13157
+ //#region src/resolver/index.ts
13158
+ /**
13159
+ * YdAdmin 组件库解析器
13160
+ * 将 YdXxx 组件自动映射到 yd-admin 包
13161
+ */
13162
+ function YdAdminResolver() {
13163
+ return (componentName) => {
13164
+ if (componentName.startsWith("Yd")) return {
13165
+ name: componentName,
13166
+ from: "yd-admin"
13167
+ };
13168
+ if (componentName === "Message" || componentName === "Notification") return {
13169
+ name: componentName,
13170
+ from: "yd-admin"
13171
+ };
13172
+ };
13173
+ }
13174
+ //#endregion
13175
+ //#region src/router/create-router.ts
13176
+ /**
13177
+ * Create Router - 路由工厂
13178
+ * 创建配置化的 Vue Router 实例
13179
+ */
13180
+ /**
13181
+ * 安装路由守卫
13182
+ */
13183
+ function setupGuards(router, guards) {
13184
+ const toGuardArray = (guard) => {
13185
+ return Array.isArray(guard) ? guard : [guard];
13186
+ };
13187
+ if (guards.beforeEach) {
13188
+ const guardArray = toGuardArray(guards.beforeEach);
13189
+ router.beforeEach(async (to, from, next) => {
13190
+ for (const guard of guardArray) await guard(to, from, next);
13191
+ });
13192
+ }
13193
+ if (guards.afterEach) {
13194
+ const guardArray = toGuardArray(guards.afterEach);
13195
+ router.afterEach((to, from) => {
13196
+ for (const guard of guardArray) guard(to, from, () => {});
13197
+ });
13198
+ }
13199
+ if (guards.beforeResolve) {
13200
+ const guardArray = toGuardArray(guards.beforeResolve);
13201
+ router.beforeResolve(async (to, from, next) => {
13202
+ for (const guard of guardArray) await guard(to, from, next);
13203
+ });
13204
+ }
13205
+ }
13206
+ /**
13207
+ * 创建路由历史
13208
+ */
13209
+ function createRouterHistory(mode, base) {
13210
+ switch (mode) {
13211
+ case "hash": return createWebHashHistory(base);
13212
+ case "memory": return createMemoryHistory(base);
13213
+ default: return createWebHistory(base);
13214
+ }
13215
+ }
13216
+ /**
13217
+ * 创建路由实例
13218
+ * @param options 路由选项
13219
+ * @returns Vue Router 实例
13220
+ */
13221
+ function createAppRouter(options = {}) {
13222
+ const { history = "html5", base, routes = [], guards = {}, strict = false, sensitive = false } = options;
13223
+ const router = createVueRouter({
13224
+ history: createRouterHistory(history, base),
13225
+ routes,
13226
+ strict,
13227
+ sensitive
13228
+ });
13229
+ setupGuards(router, guards);
13230
+ return router;
13231
+ }
13232
+ /**
13233
+ * 获取默认路由配置
13234
+ * @returns 默认路由数组
13235
+ */
13236
+ function getDefaultRoutes() {
13237
+ return [{
13238
+ path: "/",
13239
+ redirect: "/dashboard",
13240
+ meta: { ignoreAuth: true }
13241
+ }];
13242
+ }
13243
+ /**
13244
+ * 获取 404 路由
13245
+ * @param path 404 页面路径
13246
+ * @returns 404 路由配置
13247
+ */
13248
+ function getNotFoundRoute(path = "/404") {
13249
+ return {
13250
+ path: "/:pathMatch(.*)*",
13251
+ redirect: path,
13252
+ meta: { ignoreAuth: true }
13253
+ };
13254
+ }
13255
+ //#endregion
13256
+ //#region src/router/guards/auth.ts
13257
+ /**
13258
+ * 创建认证守卫
13259
+ * @param options 认证守卫选项
13260
+ * @returns 认证守卫函数
13261
+ */
13262
+ function createAuthGuard(options) {
13263
+ const { checker, loginName = "Login", ignore } = options;
13264
+ return async (to, _from, next) => {
13265
+ if (ignore?.(to)) {
13266
+ next();
13267
+ return;
13268
+ }
13269
+ if (to.meta?.requiresAuth === false || to.meta?.ignoreAuth === true) {
13270
+ next();
13271
+ return;
13272
+ }
13273
+ if (!await checker()) {
13274
+ const redirect = to.fullPath;
13275
+ next({
13276
+ name: loginName,
13277
+ query: { redirect }
13278
+ });
13279
+ return;
13280
+ }
13281
+ next();
13282
+ };
13283
+ }
13284
+ /**
13285
+ * 默认认证守卫选项
13286
+ */
13287
+ const defaultAuthGuardOptions = {
13288
+ loginPath: "/login",
13289
+ loginName: "Login",
13290
+ ignore: (to) => Boolean(to.meta?.ignoreAuth)
13291
+ };
13292
+ //#endregion
13293
+ //#region src/router/guards/permission.ts
13294
+ /**
13295
+ * 创建权限守卫
13296
+ * @param options 权限守卫选项
13297
+ * @returns 权限守卫函数
13298
+ */
13299
+ function createPermissionGuard(options) {
13300
+ const { checker, forbiddenName = "Forbidden" } = options;
13301
+ return async (to, _from, next) => {
13302
+ const requiredPermission = to.meta?.permission;
13303
+ if (!requiredPermission) {
13304
+ next();
13305
+ return;
13306
+ }
13307
+ const userPermissions = {
13308
+ roles: [],
13309
+ permissions: []
13310
+ };
13311
+ if (requiredPermission) {
13312
+ if (!await checker(requiredPermission, userPermissions)) {
13313
+ next({ name: forbiddenName });
13314
+ return;
13315
+ }
13316
+ }
13317
+ next();
13318
+ };
13319
+ }
13320
+ /**
13321
+ * 创建角色守卫
13322
+ * @param options 角色守卫选项
13323
+ * @returns 角色守卫函数
13324
+ */
13325
+ function createRoleGuard(options) {
13326
+ const { checker, forbiddenPath = "/403" } = options;
13327
+ return async (to, _from, next) => {
13328
+ const requiredRoles = to.meta?.roles;
13329
+ if (!requiredRoles || requiredRoles.length === 0) {
13330
+ next();
13331
+ return;
13332
+ }
13333
+ if (!await checker(requiredRoles, {
13334
+ roles: [],
13335
+ permissions: []
13336
+ })) {
13337
+ next({ path: forbiddenPath });
13338
+ return;
13339
+ }
13340
+ next();
13341
+ };
13342
+ }
13343
+ //#endregion
13344
+ //#region src/router/composables/use-dynamic-route.ts
13345
+ /**
13346
+ * Use Dynamic Route - 动态路由管理组合式函数
13347
+ * 提供动态添加/移除路由的能力
13348
+ */
13349
+ /** 路由实例 ref - 使用 any 类型避免 Vue Router 5 类型不兼容问题 */
13350
+ const routerInstance = ref(null);
13351
+ /**
13352
+ * 设置路由实例
13353
+ * @param router Vue Router 实例
13354
+ */
13355
+ function setRouter(router) {
13356
+ routerInstance.value = router;
13357
+ }
13358
+ /**
13359
+ * 获取当前路由实例
13360
+ */
13361
+ function getRouterInstance() {
13362
+ return routerInstance.value;
13363
+ }
13364
+ /**
13365
+ * 添加单条路由
13366
+ * @param route 路由配置
13367
+ * @param options 添加选项
13368
+ * @returns 是否成功
13369
+ */
13370
+ function addRoute(route, options = {}) {
13371
+ const router = routerInstance.value;
13372
+ if (!router) {
13373
+ console.warn("[useDynamicRoute] Router not initialized");
13374
+ return false;
13375
+ }
13376
+ const { parentName, overwrite = false } = options;
13377
+ try {
13378
+ if (parentName) router.addRoute(parentName, route);
13379
+ else if (overwrite) router.addRoute(route);
13380
+ else if (!router.getRoutes().find((r) => r.name === route.name)) router.addRoute(route);
13381
+ return true;
13382
+ } catch (error) {
13383
+ console.error("[useDynamicRoute] Failed to add route:", error);
13384
+ return false;
13385
+ }
13386
+ }
13387
+ /**
13388
+ * 批量添加路由
13389
+ * @param routes 路由数组
13390
+ * @param options 添加选项
13391
+ * @returns 成功数量
13392
+ */
13393
+ function addRoutes(routes, options = {}) {
13394
+ let successCount = 0;
13395
+ for (const route of routes) if (addRoute(route, options)) successCount++;
13396
+ return successCount;
13397
+ }
13398
+ /**
13399
+ * 移除路由
13400
+ * @param name 路由名称
13401
+ * @returns 是否成功
13402
+ */
13403
+ function removeRoute(name) {
13404
+ const router = routerInstance.value;
13405
+ if (!router) return false;
13406
+ try {
13407
+ router.removeRoute(name);
13408
+ return true;
13409
+ } catch {
13410
+ return false;
13411
+ }
13412
+ }
13413
+ /**
13414
+ * 获取所有路由
13415
+ */
13416
+ function getRoutes() {
13417
+ return routerInstance.value?.getRoutes() ?? [];
13418
+ }
13419
+ /**
13420
+ * 获取当前路由信息
13421
+ */
13422
+ function getCurrentRoute() {
13423
+ return routerInstance.value?.currentRoute;
13424
+ }
13425
+ /**
13426
+ * 获取当前路径
13427
+ */
13428
+ function getCurrentPath() {
13429
+ return routerInstance.value?.currentRoute?.fullPath;
13430
+ }
13431
+ /**
13432
+ * 获取当前路由名称
13433
+ */
13434
+ function getCurrentName() {
13435
+ const name = routerInstance.value?.currentRoute.name;
13436
+ return typeof name === "string" ? name : void 0;
13437
+ }
13438
+ /**
13439
+ * 导航到指定路径
13440
+ * @param path 路径
13441
+ * @param query 查询参数
13442
+ */
13443
+ function push(path, query) {
13444
+ return routerInstance.value?.push({
13445
+ path,
13446
+ query
13447
+ });
13448
+ }
13449
+ /**
13450
+ * 替换当前路径
13451
+ * @param path 路径
13452
+ */
13453
+ function replace(path) {
13454
+ return routerInstance.value?.replace({ path });
13455
+ }
13456
+ //#endregion
13457
+ //#region src/router/utils/route-helpers.ts
13458
+ /**
13459
+ * 过滤菜单项(根据权限)
13460
+ * @param items 菜单项数组
13461
+ * @param permissions 用户权限
13462
+ * @returns 过滤后的菜单项
13463
+ */
13464
+ function filterMenuItems$1(items, permissions) {
13465
+ if (!permissions) return items;
13466
+ const { roles = [], permissions: perms = [] } = permissions;
13467
+ return items.filter((item) => {
13468
+ if (item.roles && item.roles.length > 0) {
13469
+ if (!item.roles.some((role) => roles.includes(role))) return false;
13470
+ }
13471
+ if (item.permission) {
13472
+ if (!(Array.isArray(item.permission) ? item.permission : [item.permission]).some((p) => perms.includes(p))) return false;
13473
+ }
13474
+ if (item.children && item.children.length > 0) item.children = filterMenuItems$1(item.children, permissions);
13475
+ return true;
13476
+ });
13477
+ }
13478
+ /**
13479
+ * 将 MenuItem 数组转换为路由记录
13480
+ * @param items 菜单项数组
13481
+ * @param options 选项
13482
+ * @returns 路由记录数组
13483
+ */
13484
+ function menuToRoutes$1(items, options = {}) {
13485
+ const { basePath = "", userPermissions } = options;
13486
+ return (userPermissions ? filterMenuItems$1(items, userPermissions) : items).map((item) => {
13487
+ const route = {
13488
+ path: item.path || item.key,
13489
+ name: item.key,
13490
+ meta: {
13491
+ title: item.label,
13492
+ icon: item.icon,
13493
+ permission: item.permission,
13494
+ roles: item.roles,
13495
+ keepAlive: true
13496
+ }
13497
+ };
13498
+ if (item.children && item.children.length > 0) route.children = menuToRoutes$1(item.children, {
13499
+ basePath: `${basePath}/${route.path}`,
13500
+ userPermissions
13501
+ });
13502
+ return route;
13503
+ });
13504
+ }
13505
+ /**
13506
+ * 检查路由是否需要认证
13507
+ * @param route 路由记录
13508
+ * @returns 是否需要认证
13509
+ */
13510
+ function requiresAuth(route) {
13511
+ return route.meta?.requiresAuth !== false;
13512
+ }
13513
+ /**
13514
+ * 检查路由是否有权限
13515
+ * @param route 路由记录
13516
+ * @param permissions 用户权限
13517
+ * @returns 是否有权限
13518
+ */
13519
+ function hasPermission(route, permissions) {
13520
+ const meta = route.meta;
13521
+ if (meta?.permission) {
13522
+ const required = Array.isArray(meta.permission) ? meta.permission : [meta.permission];
13523
+ const userPerms = permissions?.permissions || [];
13524
+ return required.some((p) => userPerms.includes(p));
13525
+ }
13526
+ if (meta?.roles) {
13527
+ const required = meta.roles;
13528
+ const userRoles = permissions?.roles || [];
13529
+ return required.some((r) => userRoles.includes(r));
13530
+ }
13531
+ return true;
13532
+ }
13533
+ /**
13534
+ * 生成面包屑
13535
+ * @param routes 路由数组
13536
+ * @param currentPath 当前路径
13537
+ * @returns 面包屑数组
13538
+ */
13539
+ function generateBreadcrumbs(routes, currentPath) {
13540
+ const breadcrumbs = [];
13541
+ const findRoute = (routeList, path) => {
13542
+ for (const route of routeList) {
13543
+ if (route.path === path) return route;
13544
+ if (route.children) {
13545
+ const found = findRoute(route.children, path);
13546
+ if (found) return found;
13547
+ }
13548
+ }
13549
+ };
13550
+ const route = findRoute(routes, currentPath);
13551
+ if (route) breadcrumbs.push({
13552
+ label: route.meta?.title || route.name || "",
13553
+ path: route.path
13554
+ });
13555
+ return breadcrumbs;
13556
+ }
13557
+ //#endregion
13558
+ //#region src/router/index.ts
13559
+ var router_exports = /* @__PURE__ */ __exportAll({
13560
+ addRoute: () => addRoute,
13561
+ addRoutes: () => addRoutes,
13562
+ createAppRouter: () => createAppRouter,
13563
+ createAuthGuard: () => createAuthGuard,
13564
+ createMemoryHistory: () => createMemoryHistory,
13565
+ createPermissionGuard: () => createPermissionGuard,
13566
+ createRoleGuard: () => createRoleGuard,
13567
+ createWebHashHistory: () => createWebHashHistory,
13568
+ createWebHistory: () => createWebHistory,
13569
+ defaultAuthGuardOptions: () => defaultAuthGuardOptions,
13570
+ filterMenuItems: () => filterMenuItems$1,
13571
+ generateBreadcrumbs: () => generateBreadcrumbs,
13572
+ getCurrentName: () => getCurrentName,
13573
+ getCurrentPath: () => getCurrentPath,
13574
+ getCurrentRoute: () => getCurrentRoute,
13575
+ getDefaultRoutes: () => getDefaultRoutes,
13576
+ getNotFoundRoute: () => getNotFoundRoute,
13577
+ getRouterInstance: () => getRouterInstance,
13578
+ getRoutes: () => getRoutes,
13579
+ hasPermission: () => hasPermission,
13580
+ menuToRoutes: () => menuToRoutes$1,
13581
+ push: () => push,
13582
+ removeRoute: () => removeRoute,
13583
+ replace: () => replace,
13584
+ requiresAuth: () => requiresAuth,
13585
+ setRouter: () => setRouter
13586
+ });
10558
13587
  //#endregion
10559
- export { ANIMATION_DURATION, COMPONENT_PREFIX, CSS_PREFIX, DEBOUNCE_DEFAULTS, DEBOUNCE_DELAY, DEFAULT_LAYOUT_SIZE, Message, Notification, THROTTLE_DEFAULTS, THROTTLE_DELAY, anchor_default as YdAnchor, auto_complete_default as YdAutoComplete, avatar_default as YdAvatar, badge_default as YdBadge, breadcrumb_default as YdBreadcrumb, button_default as YdButton, captcha_default as YdCaptcha, card_default as YdCard, cascader_default as YdCascader, checkbox_default as YdCheckbox, checkbox_group_default as YdCheckboxGroup, collapse_default as YdCollapse, config_provider_default as YdConfigProvider, context_menu_default as YdContextMenu, date_picker_default as YdDatePicker, date_range_picker_default as YdDateRangePicker, divider_default as YdDivider, drawer_default as YdDrawer, dropdown_default as YdDropdown, empty_default as YdEmpty, form_default as YdForm, form_item_default as YdFormItem, image_default as YdImage, image_preview_group_default as YdImagePreviewGroup, input_default as YdInput, input_number_default as YdInputNumber, layout_default as YdLayout, layout_content_default as YdLayoutContent, layout_header_default as YdLayoutHeader, layout_sidebar_default as YdLayoutSidebar, list_default as YdList, login_default as YdLogin, login_centered_default as YdLoginCentered, menu_default as YdMenu, modal_default as YdModal, pagination_default as YdPagination, pin_input_default as YdPinInput, popconfirm_default as YdPopconfirm, progress_default as YdProgress, radio_default as YdRadio, radio_group_default as YdRadioGroup, rate_default as YdRate, result_default as YdResult, select_default as YdSelect, skeleton_default as YdSkeleton, slider_default as YdSlider, space_default as YdSpace, spin_default as YdSpin, statistic_default as YdStatistic, steps_default as YdSteps, switch_default as YdSwitch, table_default as YdTable, tabs_default as YdTabs, tag_default as YdTag, textarea_default as YdTextarea, time_picker_default as YdTimePicker, timeline_default as YdTimeline, tooltip_default as YdTooltip, transfer_default as YdTransfer, tree_default as YdTree, upload_default as YdUpload, Z_INDEX, changeLocale, cn, debounce, decrypt, deepClone, encrypt, generateId, generateSessionKey, i18n, initSecureStorage, isEmptyObject, secureLocal, secureSession, secureStoragePlugin, setLocale, setupI18n, supportedLocales, themes, throttle, useFormValidate, useLoading, useLoginForm, useNamespace };
13588
+ export { ANIMATION_DURATION, COMPONENT_PREFIX, CSS_PREFIX, DEBOUNCE_DEFAULTS, DEBOUNCE_DELAY, DEFAULT_LAYOUT_SIZE, Message, Notification, THROTTLE_DEFAULTS, THROTTLE_DELAY, YdAdminResolver, anchor_default as YdAnchor, auto_complete_default as YdAutoComplete, avatar_default as YdAvatar, badge_default as YdBadge, breadcrumb_default as YdBreadcrumb, button_default as YdButton, captcha_default as YdCaptcha, card_default as YdCard, cascader_default as YdCascader, checkbox_default as YdCheckbox, checkbox_group_default as YdCheckboxGroup, collapse_default as YdCollapse, color_picker_default as YdColorPicker, config_provider_default as YdConfigProvider, context_menu_default as YdContextMenu, date_picker_default as YdDatePicker, date_range_picker_default as YdDateRangePicker, divider_default as YdDivider, drawer_default as YdDrawer, dropdown_default as YdDropdown, empty_default as YdEmpty, form_default as YdForm, form_item_default as YdFormItem, icon_default as YdIcon, image_default as YdImage, image_preview_group_default as YdImagePreviewGroup, input_default as YdInput, input_number_default as YdInputNumber, layout_default as YdLayout, layout_content_default as YdLayoutContent, layout_header_default as YdLayoutHeader, layout_sidebar_default as YdLayoutSidebar, list_default as YdList, loading_bar_default as YdLoadingBar, login_default as YdLogin, login_centered_default as YdLoginCentered, menu_default as YdMenu, modal_default as YdModal, pagination_default as YdPagination, pin_input_default as YdPinInput, popconfirm_default as YdPopconfirm, progress_default as YdProgress, radio_default as YdRadio, radio_group_default as YdRadioGroup, rate_default as YdRate, result_default as YdResult, router_exports as YdRouter, SchemaForm_default as YdSchemaForm, select_default as YdSelect, skeleton_default as YdSkeleton, slider_default as YdSlider, space_default as YdSpace, spin_default as YdSpin, statistic_default as YdStatistic, steps_default as YdSteps, switch_default as YdSwitch, table_default as YdTable, tabs_default as YdTabs, tag_default as YdTag, textarea_default as YdTextarea, time_picker_default as YdTimePicker, timeline_default as YdTimeline, tooltip_default as YdTooltip, transfer_default as YdTransfer, tree_default as YdTree, tree_select_default as YdTreeSelect, upload_default as YdUpload, Z_INDEX, buildBreadcrumb, changeLocale, checkRoutePermission, cn, convertToSimpleRoute, debounce, decrypt, deepClone, dt, dynamicRouter, encrypt, filterMenuItems, findMenuItem, findMenuPath, flattenMenuItems, generateId, generateRouteTitle, generateSessionKey, getBreadcrumbPaths, getCurrentLocale, getIcon, getIconRegistry, i18n, initSecureStorage, isArray, isDate, isEmpty, isEmptyObject, isFunction, isObject, isPathMatch, isPromise, joinPath, loadingBar, menuToRoutes, nf, normalizePath, registerIcon, registerLazyLocale, searchMenuItems, secureLocal, secureSession, secureStoragePlugin, setLocale, setupI18n, supportedLocales, t, tc, themes, throttle, useConfig, useFormSchema, useFormValidate, useLoading, useLoadingBar, useLoginForm, useNamespace };