yd-admin 0.1.10 → 0.1.11

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/README.md CHANGED
@@ -332,6 +332,11 @@ vp test
332
332
 
333
333
  ## 📋 更新日志
334
334
 
335
+ ### v0.1.11
336
+
337
+ - **release**: 版本号更新至 v0.1.11
338
+ - **enhancement**: 优化构建配置
339
+
335
340
  ### v0.1.9
336
341
 
337
342
  - **feat(AI Chat)**: AI 聊天页面组件 (YdChatPage) - 支持会话列表、模型选择、流式输出
package/dist/index.js CHANGED
@@ -25,7 +25,8 @@ var __exportAll = (all, no_symbols) => {
25
25
  */
26
26
  const encoder = new TextEncoder();
27
27
  const decoder = new TextDecoder();
28
- const CRYPTO_SALT = import.meta.env.VITE_CRYPTO_SALT || "yd-admin-salt-fixed";
28
+ const CRYPTO_SALT = import.meta.env.VITE_CRYPTO_SALT;
29
+ if (!CRYPTO_SALT) throw new Error("[crypto] VITE_CRYPTO_SALT 环境变量未配置。请在 .env 文件中设置 VITE_CRYPTO_SALT");
29
30
  /**
30
31
  * 密钥派生缓存
31
32
  * 避免每次加密/解密都重新派生密钥 (PBKDF2 100000 次迭代开销较大)
@@ -110,11 +111,33 @@ async function decrypt(base64Data, key) {
110
111
  return null;
111
112
  }
112
113
  }
114
+ //#endregion
115
+ //#region src/utils/secure-storage.ts
116
+ /**
117
+ * 安全存储工具
118
+ * 混合加密策略:
119
+ * - sessionStorage: 使用动态会话密钥 (内存中,刷新即焚)
120
+ * - localStorage: 使用 Vite 环境变量密钥 (防普通篡改)
121
+ *
122
+ * 密钥来源优先级:
123
+ * localStorage: 配置文件 → 运行时 → init配置 → 环境变量 VITE_STORAGE_KEY
124
+ * sessionStorage: 运行时 → init配置 → 动态生成(每次会话)
125
+ */
126
+ /**
127
+ * 全局密钥存储(用于运行时/API注入)
128
+ */
129
+ let globalLocalStorageKey = null;
130
+ let globalSessionStorageKey = null;
113
131
  /**
114
132
  * 配置文件中的密钥缓存
115
133
  */
116
134
  let configLocalStorageKey;
117
135
  let configSessionStorageKey;
136
+ /**
137
+ * 密钥来源追踪
138
+ */
139
+ let localKeySource = "default";
140
+ let sessionKeySource = "dynamic";
118
141
  let sessionKey = null;
119
142
  let sessionKeyIsString = false;
120
143
  let storageReadyResolve = null;
@@ -122,8 +145,57 @@ const storageReady = new Promise((resolve) => {
122
145
  storageReadyResolve = resolve;
123
146
  });
124
147
  let localStorageKey = null;
125
- const ENV_KEY = import.meta.env.VITE_STORAGE_KEY || "yd-admin-default-key";
126
- const ENV_SESSION_KEY = import.meta.env.VITE_SESSION_STORAGE_KEY || "yd-admin-session-key";
148
+ const ENV_KEY = import.meta.env.VITE_STORAGE_KEY;
149
+ const ENV_SESSION_KEY = import.meta.env.VITE_SESSION_STORAGE_KEY;
150
+ if (import.meta.env.PROD) {
151
+ if (!ENV_KEY) throw new Error("[secure-storage] 生产环境必须配置 VITE_STORAGE_KEY 环境变量");
152
+ if (!ENV_SESSION_KEY) throw new Error("[secure-storage] 生产环境必须配置 VITE_SESSION_STORAGE_KEY 环境变量");
153
+ }
154
+ /**
155
+ * 设置 localStorage 运行时密钥
156
+ * @param key 加密密钥
157
+ */
158
+ function setStorageEncryptionKey(key) {
159
+ globalLocalStorageKey = key;
160
+ localKeySource = "runtime";
161
+ }
162
+ /**
163
+ * 设置 sessionStorage 运行时密钥
164
+ * @param key 加密密钥
165
+ */
166
+ function setSessionStorageEncryptionKey(key) {
167
+ globalSessionStorageKey = key;
168
+ sessionKeySource = "runtime";
169
+ }
170
+ /**
171
+ * 获取密钥来源
172
+ * @param type 存储类型
173
+ * @returns 密钥来源
174
+ */
175
+ function getKeySource(type) {
176
+ return type === "local" ? localKeySource : sessionKeySource;
177
+ }
178
+ /**
179
+ * 重置密钥
180
+ * @param type 存储类型
181
+ */
182
+ function resetStorageKey(type) {
183
+ if (type === "local") {
184
+ globalLocalStorageKey = null;
185
+ localKeySource = "dynamic";
186
+ } else {
187
+ globalSessionStorageKey = null;
188
+ sessionKeySource = "dynamic";
189
+ sessionKey = null;
190
+ }
191
+ }
192
+ /**
193
+ * 检查存储是否就绪
194
+ * @returns 是否就绪
195
+ */
196
+ function isStorageReady() {
197
+ return !!localStorageKey || !!sessionKey || !!globalLocalStorageKey || !!globalSessionStorageKey;
198
+ }
127
199
  /**
128
200
  * 从配置文件加载密钥
129
201
  * @param filePath 配置文件路径,默认 config/storage.json
@@ -153,6 +225,10 @@ async function loadKeyFromConfig(filePath) {
153
225
  * 解析 localStorage 密钥(按优先级)
154
226
  */
155
227
  async function resolveLocalKey(config) {
228
+ if (globalLocalStorageKey) return {
229
+ key: globalLocalStorageKey,
230
+ source: "runtime"
231
+ };
156
232
  if (config?.localStorageKey || config?.storageKey) return {
157
233
  key: config.localStorageKey || config.storageKey,
158
234
  source: "init"
@@ -168,7 +244,7 @@ async function resolveLocalKey(config) {
168
244
  source: "env"
169
245
  };
170
246
  return {
171
- key: ENV_KEY,
247
+ key: (import.meta.env.DEV ? "yd-admin-dev-local-key" : "") || ENV_KEY,
172
248
  source: "default"
173
249
  };
174
250
  }
@@ -176,6 +252,10 @@ async function resolveLocalKey(config) {
176
252
  * 解析 sessionStorage 密钥(按优先级)
177
253
  */
178
254
  async function resolveSessionKey(config) {
255
+ if (globalSessionStorageKey) return {
256
+ key: globalSessionStorageKey,
257
+ source: "runtime"
258
+ };
179
259
  if (config?.sessionStorageKey || config?.storageKey) return {
180
260
  key: config.sessionStorageKey || config.storageKey,
181
261
  source: "init"
@@ -192,7 +272,7 @@ async function resolveSessionKey(config) {
192
272
  source: "env"
193
273
  };
194
274
  return {
195
- key: ENV_SESSION_KEY,
275
+ key: (import.meta.env.DEV ? "yd-admin-dev-session-key" : "") || ENV_SESSION_KEY,
196
276
  source: "dynamic"
197
277
  };
198
278
  }
@@ -202,14 +282,18 @@ async function resolveSessionKey(config) {
202
282
  * @param config 可选的初始化配置
203
283
  */
204
284
  async function initSecureStorage(config) {
205
- localStorageKey = (await resolveLocalKey(config)).key;
206
- if ((await resolveSessionKey(config)).source === "dynamic") {
285
+ const localResolved = await resolveLocalKey(config);
286
+ localStorageKey = localResolved.key;
287
+ localKeySource = localResolved.source;
288
+ const sessionResolved = await resolveSessionKey(config);
289
+ if (sessionResolved.source === "dynamic") {
207
290
  sessionKey = await generateSessionKey();
208
291
  sessionKeyIsString = false;
209
292
  } else {
210
293
  sessionKey = null;
211
294
  sessionKeyIsString = true;
212
295
  }
296
+ sessionKeySource = sessionResolved.source;
213
297
  if (storageReadyResolve) {
214
298
  storageReadyResolve();
215
299
  storageReadyResolve = null;
@@ -235,7 +319,7 @@ var SecureStorage = class {
235
319
  * 是否就绪
236
320
  */
237
321
  get ready() {
238
- return this.storageType === "session" ? !!sessionKey || !!ENV_SESSION_KEY : !!localStorageKey || !!ENV_KEY;
322
+ return this.storageType === "session" ? !!sessionKey || !!globalSessionStorageKey || !!ENV_SESSION_KEY : !!localStorageKey || !!ENV_KEY;
239
323
  }
240
324
  /**
241
325
  * 获取密钥(根据存储类型)
@@ -245,6 +329,7 @@ var SecureStorage = class {
245
329
  if (this.storageType === "session") {
246
330
  if (sessionKey) return sessionKey;
247
331
  if (sessionKeyIsString) {
332
+ if (globalSessionStorageKey) return globalSessionStorageKey;
248
333
  if (import.meta.env.VITE_SESSION_STORAGE_KEY) return import.meta.env.VITE_SESSION_STORAGE_KEY;
249
334
  }
250
335
  return ENV_SESSION_KEY;
@@ -259,7 +344,7 @@ var SecureStorage = class {
259
344
  */
260
345
  async setItem(key, value, options) {
261
346
  const currentKey = this.getCurrentKey();
262
- if (this.storageType === "session" && !sessionKey && true) {
347
+ if (this.storageType === "session" && !sessionKey && !globalSessionStorageKey) {
263
348
  console.warn(`[secureStorage] sessionStorage key not ready, write "${key}" skipped`);
264
349
  return;
265
350
  }
@@ -355,8 +440,90 @@ var SecureStorage = class {
355
440
  this.storage.clear();
356
441
  }
357
442
  };
443
+ /**
444
+ * 创建独立的 SecureStorage 实例
445
+ * @param type 存储类型
446
+ * @param key 可选的独立密钥
447
+ * @returns SecureStorage 实例
448
+ */
449
+ function createSecureStorage(type, key) {
450
+ const instance = new SecureStorage(type);
451
+ if (key) if (type === "local") setStorageEncryptionKey(key);
452
+ else setSessionStorageEncryptionKey(key);
453
+ return instance;
454
+ }
358
455
  const secureLocal = new SecureStorage("local");
359
456
  const secureSession = new SecureStorage("session");
457
+ /**
458
+ * 密钥轮换
459
+ * @param type 存储类型
460
+ * @param newKey 新密钥
461
+ */
462
+ async function rotateStorageKey(type, newKey) {
463
+ const storage = type === "local" ? localStorage : sessionStorage;
464
+ const keys = [];
465
+ for (let i = 0; i < storage.length; i++) keys.push(storage.key(i));
466
+ if (type === "local") {
467
+ const oldKey = globalLocalStorageKey || localStorageKey || ENV_KEY;
468
+ globalLocalStorageKey = newKey;
469
+ localKeySource = "runtime";
470
+ for (const key of keys) try {
471
+ const encrypted = storage.getItem(key);
472
+ if (!encrypted) continue;
473
+ const decrypted = await decrypt(encrypted, oldKey);
474
+ if (!decrypted) continue;
475
+ const reEncrypted = await encrypt(decrypted, newKey);
476
+ storage.setItem(key, reEncrypted);
477
+ } catch {}
478
+ } else {
479
+ const oldKey = globalSessionStorageKey || ENV_SESSION_KEY;
480
+ globalSessionStorageKey = newKey;
481
+ sessionKeySource = "runtime";
482
+ for (const key of keys) try {
483
+ const encrypted = storage.getItem(key);
484
+ if (!encrypted) continue;
485
+ const decrypted = await decrypt(encrypted, oldKey);
486
+ if (!decrypted) continue;
487
+ const reEncrypted = await encrypt(decrypted, newKey);
488
+ storage.setItem(key, reEncrypted);
489
+ } catch {}
490
+ }
491
+ }
492
+ /**
493
+ * 生成 HMAC 签名
494
+ * @param data 数据字符串
495
+ * @param key 密钥
496
+ * @returns 签名
497
+ */
498
+ async function signData(data, key) {
499
+ const encoder = new TextEncoder();
500
+ const keyData = await crypto.subtle.importKey("raw", encoder.encode(key), {
501
+ name: "HMAC",
502
+ hash: "SHA-256"
503
+ }, false, ["sign"]);
504
+ const signature = await crypto.subtle.sign("HMAC", keyData, encoder.encode(data));
505
+ return btoa(String.fromCharCode(...new Uint8Array(signature)));
506
+ }
507
+ /**
508
+ * 验证签名
509
+ * @param data 数据字符串
510
+ * @param signature 签名
511
+ * @param key 密钥
512
+ * @returns 是否有效
513
+ */
514
+ async function verifyData(data, signature, key) {
515
+ try {
516
+ const encoder = new TextEncoder();
517
+ const keyData = await crypto.subtle.importKey("raw", encoder.encode(key), {
518
+ name: "HMAC",
519
+ hash: "SHA-256"
520
+ }, false, ["verify"]);
521
+ const signatureBytes = Uint8Array.from(atob(signature), (c) => c.charCodeAt(0));
522
+ return crypto.subtle.verify("HMAC", keyData, signatureBytes, encoder.encode(data));
523
+ } catch {
524
+ return false;
525
+ }
526
+ }
360
527
  //#endregion
361
528
  //#region src/utils/router.ts
362
529
  /**
@@ -797,9 +964,20 @@ var icon_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineC
797
964
  function e(element) {
798
965
  return `yd-icon__${element}`;
799
966
  }
967
+ /**
968
+ * 清理 SVG 内容以防止 XSS 攻击
969
+ * 移除 script 标签、事件处理器等危险内容
970
+ */
971
+ function sanitizeSvg(svg) {
972
+ let cleaned = svg.replace(/<script[\s\S]*?<\/script>/gi, "");
973
+ cleaned = cleaned.replace(/\s*on\w+\s*=\s*(["'])[^"']*\1/gi, "");
974
+ cleaned = cleaned.replace(/javascript:/gi, "");
975
+ cleaned = cleaned.replace(/data:/gi, "");
976
+ return cleaned;
977
+ }
800
978
  const svgContent = computed(() => {
801
979
  if (!props.name) return "";
802
- if (props.name.includes("<svg") || props.name.includes("<path")) return props.name;
980
+ if (props.name.includes("<svg") || props.name.includes("<path")) return sanitizeSvg(props.name);
803
981
  return getIcon(props.name) || "";
804
982
  });
805
983
  const iconStyle = computed(() => {
@@ -828,7 +1006,7 @@ var icon_default = /* @__PURE__ */ export_helper_default(/* @__PURE__ */ defineC
828
1006
  }, null, 10, _hoisted_1$56)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [createCommentVNode(" Slot Fallback "), renderSlot(_ctx.$slots, "default", {}, void 0, true)], 2112))], 16);
829
1007
  };
830
1008
  }
831
- }), [["__scopeId", "data-v-20774ae9"]]);
1009
+ }), [["__scopeId", "data-v-bb6b8302"]]);
832
1010
  //#endregion
833
1011
  //#region src/components/base/input/input.vue
834
1012
  const _hoisted_1$55 = [
@@ -15795,17 +15973,19 @@ function createPermissionGuard(options) {
15795
15973
  * @returns 角色守卫函数
15796
15974
  */
15797
15975
  function createRoleGuard(options) {
15798
- const { checker, forbiddenPath = "/403" } = options;
15976
+ const { checker, forbiddenPath = "/403", getUserPermissions } = options;
15799
15977
  return async (to, _from, next) => {
15800
15978
  const requiredRoles = to.meta?.roles;
15801
15979
  if (!requiredRoles || requiredRoles.length === 0) {
15802
15980
  next();
15803
15981
  return;
15804
15982
  }
15805
- if (!await checker(requiredRoles, {
15983
+ let userPermissions = {
15806
15984
  roles: [],
15807
15985
  permissions: []
15808
- })) {
15986
+ };
15987
+ if (getUserPermissions) userPermissions = await getUserPermissions() ?? userPermissions;
15988
+ if (!await checker(requiredRoles, userPermissions)) {
15809
15989
  next({ path: forbiddenPath });
15810
15990
  return;
15811
15991
  }
@@ -16057,4 +16237,4 @@ var router_exports = /* @__PURE__ */ __exportAll({
16057
16237
  setRouter: () => setRouter
16058
16238
  });
16059
16239
  //#endregion
16060
- export { ANIMATION_DURATION, COMPONENT_PREFIX, CSS_PREFIX, DEBOUNCE_DEFAULTS, DEBOUNCE_DELAY, DEFAULT_LAYOUT_SIZE, Message, Notification, THROTTLE_DEFAULTS, THROTTLE_DELAY, YdAdminResolver, ai_loader_default as YdAiLoader, 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, calendar_default as YdCalendar, captcha_default as YdCaptcha, card_default as YdCard, cascader_default as YdCascader, chat_bubble_default as YdChatBubble, chat_page_default as YdChatPage, checkbox_default as YdCheckbox, checkbox_group_default as YdCheckboxGroup, code_block_default as YdCodeBlock, collapse_default as YdCollapse, color_picker_default as YdColorPicker, config_provider_default as YdConfigProvider, context_menu_default as YdContextMenu, conversation_default as YdConversation, crud_page_default as YdCrudPage, 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, flow_chart_default as YdFlowChart, 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, model_selector_default as YdModelSelector, pagination_default as YdPagination, pin_input_default as YdPinInput, popconfirm_default as YdPopconfirm, progress_default as YdProgress, prompt_input_default as YdPromptInput, radio_default as YdRadio, radio_group_default as YdRadioGroup, rate_default as YdRate, reasoning_default as YdReasoning, result_default as YdResult, router_exports as YdRouter, SchemaForm_default as YdSchemaForm, select_default as YdSelect, skeleton_default as YdSkeleton, slider_default as YdSlider, sources_default as YdSources, space_default as YdSpace, spin_default as YdSpin, statistic_default as YdStatistic, stepper_default as YdStepper, steps_default as YdSteps, streaming_text_default as YdStreamingText, suggestion_default as YdSuggestion, 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, watermark_default as YdWatermark, Z_INDEX, buildBreadcrumb, changeLocale, checkRoutePermission, clearKeyCache, cn, convertToSimpleRoute, createWatermark, 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, removeWatermark, searchMenuItems, secureLocal, secureSession, secureStoragePlugin, setLocale, setupI18n, supportedLocales, t, tc, themes, throttle, useConfig, useFormSchema, useFormValidate, useLoading, useLoadingBar, useLoginForm, useNamespace };
16240
+ export { ANIMATION_DURATION, COMPONENT_PREFIX, CSS_PREFIX, DEBOUNCE_DEFAULTS, DEBOUNCE_DELAY, DEFAULT_LAYOUT_SIZE, Message, Notification, THROTTLE_DEFAULTS, THROTTLE_DELAY, YdAdminResolver, ai_loader_default as YdAiLoader, 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, calendar_default as YdCalendar, captcha_default as YdCaptcha, card_default as YdCard, cascader_default as YdCascader, chat_bubble_default as YdChatBubble, chat_page_default as YdChatPage, checkbox_default as YdCheckbox, checkbox_group_default as YdCheckboxGroup, code_block_default as YdCodeBlock, collapse_default as YdCollapse, color_picker_default as YdColorPicker, config_provider_default as YdConfigProvider, context_menu_default as YdContextMenu, conversation_default as YdConversation, crud_page_default as YdCrudPage, 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, flow_chart_default as YdFlowChart, 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, model_selector_default as YdModelSelector, pagination_default as YdPagination, pin_input_default as YdPinInput, popconfirm_default as YdPopconfirm, progress_default as YdProgress, prompt_input_default as YdPromptInput, radio_default as YdRadio, radio_group_default as YdRadioGroup, rate_default as YdRate, reasoning_default as YdReasoning, result_default as YdResult, router_exports as YdRouter, SchemaForm_default as YdSchemaForm, select_default as YdSelect, skeleton_default as YdSkeleton, slider_default as YdSlider, sources_default as YdSources, space_default as YdSpace, spin_default as YdSpin, statistic_default as YdStatistic, stepper_default as YdStepper, steps_default as YdSteps, streaming_text_default as YdStreamingText, suggestion_default as YdSuggestion, 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, watermark_default as YdWatermark, Z_INDEX, buildBreadcrumb, changeLocale, checkRoutePermission, clearKeyCache, cn, convertToSimpleRoute, createSecureStorage, createWatermark, debounce, decrypt, deepClone, dt, dynamicRouter, encrypt, filterMenuItems, findMenuItem, findMenuPath, flattenMenuItems, generateId, generateRouteTitle, generateSessionKey, getBreadcrumbPaths, getCurrentLocale, getIcon, getIconRegistry, getKeySource, i18n, initSecureStorage, isArray, isDate, isEmpty, isEmptyObject, isFunction, isObject, isPathMatch, isPromise, isStorageReady, joinPath, loadingBar, menuToRoutes, nf, normalizePath, registerIcon, registerLazyLocale, removeWatermark, resetStorageKey, rotateStorageKey, searchMenuItems, secureLocal, secureSession, secureStoragePlugin, setLocale, setSessionStorageEncryptionKey, setStorageEncryptionKey, setupI18n, signData, storageReady, supportedLocales, t, tc, themes, throttle, useConfig, useFormSchema, useFormValidate, useLoading, useLoadingBar, useLoginForm, useNamespace, verifyData };
package/dist/style.css CHANGED
@@ -113,24 +113,24 @@
113
113
  animation: yd-spin 1s linear infinite;
114
114
  }
115
115
 
116
- .yd-icon[data-v-20774ae9] {
116
+ .yd-icon[data-v-bb6b8302] {
117
117
  display: inline-flex;
118
118
  align-items: center;
119
119
  justify-content: center;
120
120
  vertical-align: middle;
121
121
  line-height: 1;
122
122
  }
123
- .yd-icon__svg[data-v-20774ae9] {
123
+ .yd-icon__svg[data-v-bb6b8302] {
124
124
  width: 100%;
125
125
  height: 100%;
126
126
  fill: none;
127
127
  }
128
128
  /* Spin animation */
129
- .yd-icon[style*="animation"] .yd-icon__svg[data-v-20774ae9],
130
- .yd-icon__svg--spin[data-v-20774ae9] {
131
- animation: yd-icon-spin-20774ae9 1s linear infinite;
129
+ .yd-icon[style*="animation"] .yd-icon__svg[data-v-bb6b8302],
130
+ .yd-icon__svg--spin[data-v-bb6b8302] {
131
+ animation: yd-icon-spin-bb6b8302 1s linear infinite;
132
132
  }
133
- @keyframes yd-icon-spin-20774ae9 {
133
+ @keyframes yd-icon-spin-bb6b8302 {
134
134
  from {
135
135
  transform: rotate(0deg);
136
136
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yd-admin",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "description": "基于 Vue 3 的后台管理框架通用组件库 - 轻量、高效、主题可定制",
5
5
  "keywords": [
6
6
  "admin",