@kine-design/crud 0.0.1-beta.24 → 0.0.1-beta.26

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.
@@ -12,6 +12,7 @@
12
12
 
13
13
  import { ref, reactive, computed, onMounted, type Ref } from 'vue';
14
14
  import { useRoute, useRouter } from 'vue-router';
15
+ import { getActiveLocaleMessages } from '@kine-design/core';
15
16
  import { useRequestClient } from '../../setup';
16
17
  import type { FormFieldConfig } from './types';
17
18
 
@@ -114,7 +115,8 @@ export function useFormPage(options: UseFormPageOptions): UseFormPageReturn {
114
115
  // 必填校验
115
116
  if (field.required) {
116
117
  if (value === undefined || value === null || value === '') {
117
- const msg = `请输入${field.label}`;
118
+ const t = getActiveLocaleMessages();
119
+ const msg = t.form.inputPlaceholder(field.label);
118
120
  errors.value[param] = msg;
119
121
  return msg;
120
122
  }
@@ -66,4 +66,6 @@ export interface CrudPageConfig {
66
66
  detailPath?: string;
67
67
  /** 图片列 src 转换函数,将原始值转为可访问 URL */
68
68
  imageResolver?: (raw: string) => string;
69
+ /** 默认查询参数,始终附带在请求中(用户选择的 filter 值会覆盖同名参数) */
70
+ defaultParams?: Record<string, unknown>;
69
71
  }
@@ -43,6 +43,7 @@ export function useCrudPage(config: CrudPageConfig, tableBodyRef?: Ref<HTMLEleme
43
43
  loading.value = true;
44
44
  try {
45
45
  const params: Record<string, unknown> = {
46
+ ...config.defaultParams,
46
47
  page: page.value,
47
48
  pageSize: pageSize.value,
48
49
  };
@@ -21,6 +21,7 @@ import type {
21
21
  } from './types';
22
22
  import { BusinessError, NetworkRequestError } from './types';
23
23
  import { buildCacheKey, ControlGate } from './controlGate';
24
+ import { getActiveLocaleMessages } from '@kine-design/core';
24
25
 
25
26
  // ────────────────────────────────────────────────────────────────────────────
26
27
  // 内部:缓存存储
@@ -89,6 +90,7 @@ function toQueryString(params: Record<string, unknown>): string {
89
90
  async function unwrapResponse<T>(
90
91
  response: { status: number; statusText: string; headers: Record<string, string>; text(): Promise<string>; json<R>(): Promise<R> },
91
92
  ): Promise<T> {
93
+ const t = getActiveLocaleMessages();
92
94
  // HTTP 错误
93
95
  if (response.status < 200 || response.status >= 300) {
94
96
  // 4xx/5xx:尝试解析 body,提取业务错误信息
@@ -98,7 +100,7 @@ async function unwrapResponse<T>(
98
100
  try {
99
101
  const json = await response.json<WrappedResponse<unknown>>();
100
102
  if (isWrappedResponse(json) && !json.success) {
101
- throw new BusinessError(json.message || `请求失败(${response.status})`);
103
+ throw new BusinessError(json.message || t.request.failedWithStatus(response.status));
102
104
  }
103
105
  } catch (e) {
104
106
  if (e instanceof BusinessError) throw e;
@@ -121,7 +123,7 @@ async function unwrapResponse<T>(
121
123
  // 检查是否为 WrappedResponse 结构
122
124
  if (isWrappedResponse<T>(json)) {
123
125
  if (!json.success) {
124
- throw new BusinessError(json.message || '请求失败');
126
+ throw new BusinessError(json.message || t.request.failed);
125
127
  }
126
128
  return json.data;
127
129
  }
@@ -277,6 +279,7 @@ export class RequestBuilder {
277
279
  // ── 执行 ────────────────────────────────────────────────────────────────
278
280
 
279
281
  async execute<T>(): Promise<T> {
282
+ const t = getActiveLocaleMessages();
280
283
  const { transport, controlGate, baseURL, defaultHeaders, getToken, onUnauthorized, responseInterceptor, registerAbort } = this.context;
281
284
 
282
285
  // 构建完整 URL
@@ -364,7 +367,7 @@ export class RequestBuilder {
364
367
 
365
368
  // 写操作成功后自动反馈
366
369
  if (this.context.feedback && ['POST', 'PUT', 'PATCH', 'DELETE'].includes(this.method)) {
367
- this.context.feedback.showSuccess('操作成功');
370
+ this.context.feedback.showSuccess(t.request.success);
368
371
  }
369
372
 
370
373
  return finalResult as T;
@@ -376,8 +379,8 @@ export class RequestBuilder {
376
379
  // 写操作失败自动反馈错误信息
377
380
  if (this.context.feedback) {
378
381
  const msg = error instanceof BusinessError ? error.message
379
- : error instanceof NetworkRequestError ? `请求失败: ${error.message}`
380
- : '操作失败';
382
+ : error instanceof NetworkRequestError ? t.request.failedWithMsg(error.message)
383
+ : t.request.opFailed;
381
384
  this.context.feedback.showError(msg);
382
385
  }
383
386
  throw error;
@@ -7,6 +7,7 @@
7
7
  * 江湖的业务千篇一律,复杂的代码好几百行。
8
8
  */
9
9
 
10
+ import { getActiveLocaleMessages } from '@kine-design/core';
10
11
  import type { Transport, TransportRequest, TransportResponse } from '../types';
11
12
 
12
13
  /** 解析 XHR 响应头字符串为 Record */
@@ -27,6 +28,7 @@ function parseResponseHeaders(rawHeaders: string): Record<string, string> {
27
28
 
28
29
  export class XhrTransport implements Transport {
29
30
  send(request: TransportRequest): Promise<TransportResponse> {
31
+ const t = getActiveLocaleMessages();
30
32
  return new Promise((resolve, reject) => {
31
33
  const xhr = new XMLHttpRequest();
32
34
 
@@ -83,7 +85,7 @@ export class XhrTransport implements Transport {
83
85
  };
84
86
 
85
87
  xhr.onerror = () => {
86
- reject({ type: 'unknown' as const, error: new Error('网络错误') });
88
+ reject({ type: 'unknown' as const, error: new Error(t.request.networkError) });
87
89
  };
88
90
 
89
91
  xhr.ontimeout = () => {
@@ -7,6 +7,8 @@
7
7
  * 江湖的业务千篇一律,复杂的代码好几百行。
8
8
  */
9
9
 
10
+ import { getActiveLocaleMessages } from '@kine-design/core';
11
+
10
12
  // ────────────────────────────────────────────────────────────────────────────
11
13
  // 请求方法
12
14
  // ────────────────────────────────────────────────────────────────────────────
@@ -111,13 +113,14 @@ export class NetworkRequestError extends Error {
111
113
  }
112
114
 
113
115
  function networkErrorMessage(e: NetworkError): string {
116
+ const t = getActiveLocaleMessages();
114
117
  switch (e.type) {
115
- case 'invalidURL': return `无效的 URL: ${e.url}`;
116
- case 'timeout': return '请求超时';
118
+ case 'invalidURL': return t.request.invalidUrl(e.url);
119
+ case 'timeout': return t.request.timeout;
117
120
  case 'httpError': return `HTTP ${e.status} ${e.statusText}`;
118
- case 'decodingFailed': return `解码失败: ${e.reason}`;
119
- case 'aborted': return '请求已取消';
120
- case 'unknown': return `未知错误: ${String(e.error)}`;
121
+ case 'decodingFailed': return t.request.decodeFailed(e.reason);
122
+ case 'aborted': return t.request.canceled;
123
+ case 'unknown': return t.request.unknownError(String(e.error));
121
124
  }
122
125
  }
123
126
 
@@ -8,6 +8,7 @@
8
8
  */
9
9
 
10
10
  import { ref, type Ref } from 'vue';
11
+ import { getActiveLocaleMessages } from '@kine-design/core';
11
12
  import type { UploaderOptions, UploadOptions, WrappedResponse } from './types';
12
13
  import { BusinessError, NetworkRequestError } from './types';
13
14
  import { XhrTransport } from './transport/xhrTransport';
@@ -55,6 +56,7 @@ export function createUploader(uploaderOptions: UploaderOptions = {}): Uploader
55
56
  }
56
57
 
57
58
  function doUpload<T>(formData: FormData, options: UploadOptions): UploadHandle<T> {
59
+ const t = getActiveLocaleMessages();
58
60
  const progress = ref(0);
59
61
  const abortController = new AbortController();
60
62
 
@@ -83,7 +85,7 @@ export function createUploader(uploaderOptions: UploaderOptions = {}): Uploader
83
85
  if (contentType.includes('application/json')) {
84
86
  const json = await response.json<WrappedResponse<T> | T>();
85
87
  if (isWrappedResponse<T>(json)) {
86
- if (!json.success) throw new BusinessError(json.message || '上传失败');
88
+ if (!json.success) throw new BusinessError(json.message || t.request.uploadFailed);
87
89
  return json.data;
88
90
  }
89
91
  return json as T;
@@ -94,7 +96,7 @@ export function createUploader(uploaderOptions: UploaderOptions = {}): Uploader
94
96
 
95
97
  return {
96
98
  progress,
97
- abort: () => abortController.abort('上传已取消'),
99
+ abort: () => abortController.abort(t.request.uploadCanceled),
98
100
  promise,
99
101
  };
100
102
  }
@@ -7,6 +7,7 @@
7
7
  * 江湖的业务千篇一律,复杂的代码好几百行。
8
8
  */
9
9
 
10
+ import { getActiveLocaleMessages } from '@kine-design/core';
10
11
  import type { CrudRouteConfig, CrudRouteRecord } from './types';
11
12
 
12
13
  // ────────────────────────────────────────────────────────────────────────────
@@ -62,15 +63,16 @@ interface OpSpec {
62
63
  export function defineCrudRoutes(config: CrudRouteConfig): CrudRouteRecord[] {
63
64
  const { name, path, permission, title, icon } = config;
64
65
  const resource = permission ?? name.toLowerCase();
66
+ const t = getActiveLocaleMessages();
65
67
 
66
68
  // 规范化 basePath,确保以 / 开头、不以 / 结尾
67
69
  const basePath = path.replace(/\/+$/, '');
68
70
 
69
71
  const opSpecs: OpSpec[] = [
70
72
  { op: 'list', suffix: '', action: 'read', component: config.list, titleSuffix: '', keepAlive: true, hidden: false },
71
- { op: 'new', suffix: '/new', action: 'create', component: config.new, titleSuffix: ' - 新建', keepAlive: false, hidden: true },
72
- { op: 'modify', suffix: '/:id/edit', action: 'update', component: config.modify, titleSuffix: ' - 编辑', keepAlive: false, hidden: true },
73
- { op: 'detail', suffix: '/:id', action: 'read', component: config.detail, titleSuffix: ' - 详情', keepAlive: false, hidden: true },
73
+ { op: 'new', suffix: '/new', action: 'create', component: config.new, titleSuffix: t.routes.createSuffix, keepAlive: false, hidden: true },
74
+ { op: 'modify', suffix: '/:id/edit', action: 'update', component: config.modify, titleSuffix: t.routes.editSuffix, keepAlive: false, hidden: true },
75
+ { op: 'detail', suffix: '/:id', action: 'read', component: config.detail, titleSuffix: t.routes.detailSuffix, keepAlive: false, hidden: true },
74
76
  ];
75
77
 
76
78
  const routes: CrudRouteRecord[] = [];
@@ -60,12 +60,12 @@ declare const _default: import('vue').DefineComponent<import('vue').ExtractPropT
60
60
  /** 汇总行标签 */
61
61
  summaryLabel: {
62
62
  type: StringConstructor;
63
- default: string;
63
+ default: undefined;
64
64
  };
65
65
  /** 新增行按钮文本 */
66
66
  addText: {
67
67
  type: StringConstructor;
68
- default: string;
68
+ default: undefined;
69
69
  };
70
70
  /** 是否可新增 */
71
71
  addable: {
@@ -77,7 +77,7 @@ declare const _default: import('vue').DefineComponent<import('vue').ExtractPropT
77
77
  type: StringConstructor;
78
78
  default: string;
79
79
  };
80
- }>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, ("add" | "update:modelValue" | "remove")[], "add" | "update:modelValue" | "remove", import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
80
+ }>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, ("update:modelValue" | "add" | "remove")[], "update:modelValue" | "add" | "remove", import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
81
81
  /** 列定义 */
82
82
  columns: {
83
83
  type: PropType<EditableColumn[]>;
@@ -111,12 +111,12 @@ declare const _default: import('vue').DefineComponent<import('vue').ExtractPropT
111
111
  /** 汇总行标签 */
112
112
  summaryLabel: {
113
113
  type: StringConstructor;
114
- default: string;
114
+ default: undefined;
115
115
  };
116
116
  /** 新增行按钮文本 */
117
117
  addText: {
118
118
  type: StringConstructor;
119
- default: string;
119
+ default: undefined;
120
120
  };
121
121
  /** 是否可新增 */
122
122
  addable: {
@@ -68,4 +68,6 @@ export interface CrudPageConfig {
68
68
  detailPath?: string;
69
69
  /** 图片列 src 转换函数,将原始值转为可访问 URL */
70
70
  imageResolver?: (raw: string) => string;
71
+ /** 默认查询参数,始终附带在请求中(用户选择的 filter 值会覆盖同名参数) */
72
+ defaultParams?: Record<string, unknown>;
71
73
  }
package/dist/crud.css CHANGED
@@ -315,11 +315,11 @@
315
315
 
316
316
  /* 行 hover 效果 */
317
317
  .k-tbody .k-tr {
318
- transition: background var(--kine-motion-duration-fast);
318
+ transition: background var(--kine-interaction-transition-duration);
319
319
  }
320
320
 
321
321
  .k-tbody .k-tr:hover {
322
- background: var(--kine-color-bg-hover);
322
+ background: var(--kine-color-neutral-3);
323
323
  }
324
324
 
325
325
  /* 空数据占位 */
@@ -397,23 +397,23 @@
397
397
  border: 1px solid transparent;
398
398
  color: var(--kine-color-text-secondary);
399
399
  cursor: pointer;
400
- transition: background var(--kine-motion-duration-fast), color var(--kine-motion-duration-fast);
400
+ transition: background var(--kine-interaction-transition-duration), color var(--kine-interaction-transition-duration);
401
401
  }
402
402
 
403
403
  .k-pager:hover {
404
- background: var(--kine-color-bg-hover);
404
+ background: var(--kine-color-neutral-3);
405
405
  color: var(--kine-color-text-primary);
406
406
  }
407
407
 
408
408
  /* 当前页高亮 */
409
409
  .k-pager-current {
410
410
  color: var(--kine-color-accent-default);
411
- background: color-mix(in srgb, var(--kine-color-accent-default) 10%, transparent);
412
- border-color: color-mix(in srgb, var(--kine-color-accent-default) 30%, transparent);
411
+ background: var(--kine-color-accent-light);
412
+ border-color: color-mix(in srgb, var(--kine-color-accent-default) var(--kine-interaction-focus-glow), transparent);
413
413
  }
414
414
 
415
415
  .k-pager-current:hover {
416
- background: color-mix(in srgb, var(--kine-color-accent-default) 15%, transparent);
416
+ background: color-mix(in srgb, var(--kine-color-accent-default) var(--kine-interaction-hover-intensity), transparent);
417
417
  color: var(--kine-color-accent-hover);
418
418
  }
419
419
 
@@ -440,12 +440,12 @@
440
440
  color: var(--kine-color-text-secondary);
441
441
  font-size: var(--kine-font-size-2xl);
442
442
  cursor: pointer;
443
- transition: background var(--kine-motion-duration-fast), color var(--kine-motion-duration-fast);
443
+ transition: background var(--kine-interaction-transition-duration), color var(--kine-interaction-transition-duration);
444
444
  }
445
445
 
446
446
  .k-page-prev:hover,
447
447
  .k-page-next:hover {
448
- background: var(--kine-color-bg-hover);
448
+ background: var(--kine-color-neutral-3);
449
449
  color: var(--kine-color-text-primary);
450
450
  }
451
451
 
@@ -485,7 +485,7 @@
485
485
  color: var(--kine-color-text-primary);
486
486
  cursor: pointer;
487
487
  outline: none;
488
- transition: all var(--kine-motion-duration-fast) var(--kine-motion-easing-default);
488
+ transition: all var(--kine-interaction-transition-duration) var(--kine-motion-easing-default);
489
489
  user-select: none;
490
490
  display: inline-flex;
491
491
  align-items: center;
@@ -494,31 +494,31 @@
494
494
 
495
495
  /* === default hover/active === */
496
496
  .k-button:hover {
497
- background: var(--kine-color-bg-hover);
498
- border-color: var(--kine-color-text-secondary);
499
- color: #ffffff;
497
+ background: var(--kine-color-neutral-3);
498
+ border-color: var(--kine-color-neutral-5);
499
+ color: var(--kine-color-text-inverse);
500
500
  }
501
501
 
502
502
  .k-button:active {
503
- background: var(--kine-color-border-subtle);
503
+ background: var(--kine-color-neutral-4);
504
504
  }
505
505
 
506
506
  /* === primary === */
507
507
  .k-button-primary {
508
- background: color-mix(in srgb, var(--kine-color-accent-default) 10%, var(--kine-color-bg-tertiary));
508
+ background: var(--kine-color-accent-light);
509
509
  border-color: var(--kine-color-accent-default);
510
510
  color: var(--kine-color-accent-default);
511
511
  }
512
512
 
513
513
  .k-button-primary:hover {
514
- background: color-mix(in srgb, var(--kine-color-accent-default) 18%, var(--kine-color-bg-primary));
514
+ background: color-mix(in srgb, var(--kine-color-accent-default) var(--kine-interaction-hover-intensity), var(--kine-color-bg-primary));
515
515
  border-color: var(--kine-color-accent-hover);
516
516
  color: var(--kine-color-accent-hover);
517
- text-shadow: 0 0 6px color-mix(in srgb, var(--kine-color-accent-default) 50%, transparent);
517
+ text-shadow: 0 0 6px color-mix(in srgb, var(--kine-color-accent-default) var(--kine-interaction-text-glow), transparent);
518
518
  }
519
519
 
520
520
  .k-button-primary:active {
521
- background: color-mix(in srgb, var(--kine-color-accent-default) 25%, var(--kine-color-bg-primary));
521
+ background: color-mix(in srgb, var(--kine-color-accent-default) var(--kine-interaction-active-intensity), var(--kine-color-bg-primary));
522
522
  }
523
523
 
524
524
  /* === success === */
@@ -528,14 +528,14 @@
528
528
  }
529
529
 
530
530
  .k-button-success:hover {
531
- background: color-mix(in srgb, var(--kine-color-semantic-success) 12%, var(--kine-color-bg-primary));
531
+ background: color-mix(in srgb, var(--kine-color-semantic-success) var(--kine-interaction-hover-intensity), var(--kine-color-bg-primary));
532
532
  border-color: var(--kine-color-semantic-success-hover);
533
533
  color: var(--kine-color-semantic-success-hover);
534
- text-shadow: 0 0 6px color-mix(in srgb, var(--kine-color-semantic-success) 50%, transparent);
534
+ text-shadow: 0 0 6px color-mix(in srgb, var(--kine-color-semantic-success) var(--kine-interaction-text-glow), transparent);
535
535
  }
536
536
 
537
537
  .k-button-success:active {
538
- background: color-mix(in srgb, var(--kine-color-semantic-success) 20%, var(--kine-color-bg-primary));
538
+ background: color-mix(in srgb, var(--kine-color-semantic-success) var(--kine-interaction-active-intensity), var(--kine-color-bg-primary));
539
539
  }
540
540
 
541
541
  /* === warning === */
@@ -545,14 +545,14 @@
545
545
  }
546
546
 
547
547
  .k-button-warning:hover {
548
- background: color-mix(in srgb, var(--kine-color-semantic-warning) 12%, var(--kine-color-bg-primary));
548
+ background: color-mix(in srgb, var(--kine-color-semantic-warning) var(--kine-interaction-hover-intensity), var(--kine-color-bg-primary));
549
549
  border-color: var(--kine-color-semantic-warning-hover);
550
550
  color: var(--kine-color-semantic-warning-hover);
551
- text-shadow: 0 0 6px color-mix(in srgb, var(--kine-color-semantic-warning) 50%, transparent);
551
+ text-shadow: 0 0 6px color-mix(in srgb, var(--kine-color-semantic-warning) var(--kine-interaction-text-glow), transparent);
552
552
  }
553
553
 
554
554
  .k-button-warning:active {
555
- background: color-mix(in srgb, var(--kine-color-semantic-warning) 20%, var(--kine-color-bg-primary));
555
+ background: color-mix(in srgb, var(--kine-color-semantic-warning) var(--kine-interaction-active-intensity), var(--kine-color-bg-primary));
556
556
  }
557
557
 
558
558
  /* === danger === */
@@ -562,31 +562,31 @@
562
562
  }
563
563
 
564
564
  .k-button-danger:hover {
565
- background: color-mix(in srgb, var(--kine-color-semantic-error) 12%, var(--kine-color-bg-primary));
565
+ background: color-mix(in srgb, var(--kine-color-semantic-error) var(--kine-interaction-hover-intensity), var(--kine-color-bg-primary));
566
566
  border-color: var(--kine-color-semantic-error-hover);
567
567
  color: var(--kine-color-semantic-error-hover);
568
- text-shadow: 0 0 6px color-mix(in srgb, var(--kine-color-semantic-error) 50%, transparent);
568
+ text-shadow: 0 0 6px color-mix(in srgb, var(--kine-color-semantic-error) var(--kine-interaction-text-glow), transparent);
569
569
  }
570
570
 
571
571
  .k-button-danger:active {
572
- background: color-mix(in srgb, var(--kine-color-semantic-error) 20%, var(--kine-color-bg-primary));
572
+ background: color-mix(in srgb, var(--kine-color-semantic-error) var(--kine-interaction-active-intensity), var(--kine-color-bg-primary));
573
573
  }
574
574
 
575
575
  /* === info === */
576
576
  .k-button-info {
577
- border-color: var(--kine-color-semantic-info, #64748b);
578
- color: var(--kine-color-semantic-info, #64748b);
577
+ border-color: var(--kine-color-semantic-info);
578
+ color: var(--kine-color-semantic-info);
579
579
  }
580
580
 
581
581
  .k-button-info:hover {
582
- background: color-mix(in srgb, var(--kine-color-semantic-info, #64748b) 12%, var(--kine-color-bg-primary));
583
- border-color: var(--kine-color-semantic-info-hover, #94a3b8);
584
- color: var(--kine-color-semantic-info-hover, #94a3b8);
585
- text-shadow: 0 0 6px color-mix(in srgb, var(--kine-color-semantic-info, #64748b) 50%, transparent);
582
+ background: color-mix(in srgb, var(--kine-color-semantic-info) var(--kine-interaction-hover-intensity), var(--kine-color-bg-primary));
583
+ border-color: var(--kine-color-semantic-info-hover);
584
+ color: var(--kine-color-semantic-info-hover);
585
+ text-shadow: 0 0 6px color-mix(in srgb, var(--kine-color-semantic-info) var(--kine-interaction-text-glow), transparent);
586
586
  }
587
587
 
588
588
  .k-button-info:active {
589
- background: color-mix(in srgb, var(--kine-color-semantic-info, #64748b) 20%, var(--kine-color-bg-primary));
589
+ background: color-mix(in srgb, var(--kine-color-semantic-info) var(--kine-interaction-active-intensity), var(--kine-color-bg-primary));
590
590
  }
591
591
 
592
592
  /* === disabled === */
@@ -626,13 +626,13 @@
626
626
  }
627
627
 
628
628
  .k-button-plain:hover {
629
- background: var(--kine-color-bg-hover);
629
+ background: var(--kine-color-neutral-3);
630
630
  border-color: transparent;
631
- color: #ffffff;
631
+ color: var(--kine-color-text-inverse);
632
632
  }
633
633
 
634
634
  .k-button-plain:active {
635
- background: var(--kine-color-border-subtle);
635
+ background: var(--kine-color-neutral-4);
636
636
  }
637
637
 
638
638
  /* === link === */
@@ -648,7 +648,7 @@
648
648
  color: var(--kine-color-accent-hover);
649
649
  border-color: transparent;
650
650
  background: transparent;
651
- text-shadow: 0 0 6px color-mix(in srgb, var(--kine-color-accent-default) 50%, transparent);
651
+ text-shadow: 0 0 6px color-mix(in srgb, var(--kine-color-accent-default) var(--kine-interaction-text-glow), transparent);
652
652
  }
653
653
 
654
654
  /* === size variants === */
@@ -819,31 +819,31 @@
819
819
  .k-tag-primary {
820
820
  border-color: var(--kine-color-accent-default);
821
821
  color: var(--kine-color-accent-default);
822
- background: color-mix(in srgb, var(--kine-color-accent-default) 10%, var(--kine-color-bg-tertiary));
822
+ background: var(--kine-color-accent-light);
823
823
  }
824
824
 
825
825
  .k-tag-success {
826
826
  border-color: var(--kine-color-semantic-success);
827
827
  color: var(--kine-color-semantic-success);
828
- background: color-mix(in srgb, var(--kine-color-semantic-success) 10%, var(--kine-color-bg-tertiary));
828
+ background: var(--kine-color-semantic-success-light);
829
829
  }
830
830
 
831
831
  .k-tag-warning {
832
832
  border-color: var(--kine-color-semantic-warning);
833
833
  color: var(--kine-color-semantic-warning);
834
- background: color-mix(in srgb, var(--kine-color-semantic-warning) 10%, var(--kine-color-bg-tertiary));
834
+ background: var(--kine-color-semantic-warning-light);
835
835
  }
836
836
 
837
837
  .k-tag-danger {
838
838
  border-color: var(--kine-color-semantic-error);
839
839
  color: var(--kine-color-semantic-error);
840
- background: color-mix(in srgb, var(--kine-color-semantic-error) 10%, var(--kine-color-bg-tertiary));
840
+ background: var(--kine-color-semantic-error-light);
841
841
  }
842
842
 
843
843
  .k-tag-info {
844
844
  border-color: var(--kine-color-semantic-info);
845
845
  color: var(--kine-color-semantic-info);
846
- background: color-mix(in srgb, var(--kine-color-semantic-info) 10%, var(--kine-color-bg-tertiary));
846
+ background: var(--kine-color-semantic-info-light);
847
847
  }
848
848
 
849
849
  /* === 尺寸变体 === */
@@ -874,12 +874,12 @@
874
874
  cursor: pointer;
875
875
  opacity: 0.6;
876
876
  border-radius: 50%;
877
- transition: opacity var(--kine-motion-duration-fast), background var(--kine-motion-duration-fast);
877
+ transition: opacity var(--kine-interaction-transition-duration), background var(--kine-interaction-transition-duration);
878
878
  }
879
879
 
880
880
  .k-tag-close:hover {
881
881
  opacity: 1;
882
- background: color-mix(in srgb, currentColor 20%, transparent);
882
+ background: color-mix(in srgb, currentColor var(--kine-interaction-active-intensity), transparent);
883
883
  }
884
884
 
885
885
  /* === 禁用状态 === */
@@ -989,7 +989,7 @@
989
989
  max-height: 85vh;
990
990
  object-fit: contain;
991
991
  border-radius: var(--kine-radius-xs);
992
- box-shadow: 0 0 40px color-mix(in srgb, var(--kine-color-accent-default) 20%, transparent);
992
+ box-shadow: 0 0 40px color-mix(in srgb, var(--kine-color-accent-default) var(--kine-interaction-active-intensity), transparent);
993
993
  transition: transform var(--kine-motion-duration-fast) var(--kine-motion-easing-default);
994
994
  user-select: none;
995
995
  }
@@ -1024,18 +1024,18 @@
1024
1024
  font-size: 16px;
1025
1025
  cursor: pointer;
1026
1026
  transition:
1027
- color var(--kine-motion-duration-fast) var(--kine-motion-easing-default),
1028
- background var(--kine-motion-duration-fast) var(--kine-motion-easing-default);
1027
+ color var(--kine-interaction-transition-duration) var(--kine-motion-easing-default),
1028
+ background var(--kine-interaction-transition-duration) var(--kine-motion-easing-default);
1029
1029
  }
1030
1030
 
1031
1031
  .k-image-preview-btn:hover {
1032
1032
  color: var(--kine-color-text-primary);
1033
- background: color-mix(in srgb, var(--kine-color-accent-default) 15%, transparent);
1033
+ background: color-mix(in srgb, var(--kine-color-accent-default) var(--kine-interaction-hover-intensity), transparent);
1034
1034
  }
1035
1035
 
1036
1036
  .k-image-preview-close:hover {
1037
1037
  color: var(--kine-color-semantic-error);
1038
- background: color-mix(in srgb, var(--kine-color-semantic-error) 15%, transparent);
1038
+ background: color-mix(in srgb, var(--kine-color-semantic-error) var(--kine-interaction-hover-intensity), transparent);
1039
1039
  }
1040
1040
 
1041
1041
  /* 当前缩放比例显示 */
@@ -1063,8 +1063,8 @@
1063
1063
  font-size: 26px;
1064
1064
  cursor: pointer;
1065
1065
  transition:
1066
- background var(--kine-motion-duration-fast) var(--kine-motion-easing-default),
1067
- border-color var(--kine-motion-duration-fast) var(--kine-motion-easing-default);
1066
+ background var(--kine-interaction-transition-duration) var(--kine-motion-easing-default),
1067
+ border-color var(--kine-interaction-transition-duration) var(--kine-motion-easing-default);
1068
1068
  }
1069
1069
 
1070
1070
  .k-image-preview-arrow:hover {
@@ -1126,7 +1126,7 @@
1126
1126
 
1127
1127
  .k-input:focus {
1128
1128
  border-color: var(--kine-color-accent-default);
1129
- box-shadow: 0 0 var(--kine-shadow-glow-radius) color-mix(in srgb, var(--kine-color-accent-default) 30%, transparent);
1129
+ box-shadow: 0 0 var(--kine-shadow-glow-radius) color-mix(in srgb, var(--kine-color-accent-default) var(--kine-interaction-focus-glow), transparent);
1130
1130
  }
1131
1131
 
1132
1132
  .k-input-disabled {
@@ -1222,7 +1222,7 @@ textarea.k-input {
1222
1222
 
1223
1223
  .k-select-trigger:focus-within {
1224
1224
  border-color: var(--kine-color-accent-default);
1225
- box-shadow: 0 0 var(--kine-shadow-glow-radius) color-mix(in srgb, var(--kine-color-accent-default) 30%, transparent);
1225
+ box-shadow: 0 0 var(--kine-shadow-glow-radius) color-mix(in srgb, var(--kine-color-accent-default) var(--kine-interaction-focus-glow), transparent);
1226
1226
  }
1227
1227
 
1228
1228
  .k-select-trigger-multiple {
@@ -1340,16 +1340,16 @@ textarea.k-input {
1340
1340
  }
1341
1341
 
1342
1342
  .k-select-dropdown .m-option:hover {
1343
- background-color: var(--kine-color-bg-hover);
1343
+ background-color: var(--kine-color-neutral-3);
1344
1344
  }
1345
1345
 
1346
1346
  .k-select-dropdown .m-option-selected {
1347
1347
  color: var(--kine-color-accent-default);
1348
- background-color: color-mix(in srgb, var(--kine-color-accent-default) 10%, transparent);
1348
+ background-color: var(--kine-color-accent-light);
1349
1349
  }
1350
1350
 
1351
1351
  .k-select-dropdown .m-option-selected:hover {
1352
- background-color: color-mix(in srgb, var(--kine-color-accent-default) 16%, transparent);
1352
+ background-color: color-mix(in srgb, var(--kine-color-accent-default) var(--kine-interaction-hover-intensity), transparent);
1353
1353
  }
1354
1354
 
1355
1355
  .k-select-dropdown .m-option-disabled {