uview-pro 0.3.16 → 0.4.2

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.
Files changed (140) hide show
  1. package/changelog.md +82 -0
  2. package/components/u-action-sheet-item/u-action-sheet-item.vue +1 -1
  3. package/components/u-alert-tips/u-alert-tips.vue +2 -2
  4. package/components/u-avatar/u-avatar.vue +5 -5
  5. package/components/u-avatar-cropper/u-avatar-cropper.vue +5 -5
  6. package/components/u-avatar-cropper/weCropper.js +1 -1
  7. package/components/u-avatar-cropper/weCropper.ts +1 -1
  8. package/components/u-back-top/types.ts +1 -1
  9. package/components/u-back-top/u-back-top.vue +1 -1
  10. package/components/u-badge/u-badge.vue +1 -31
  11. package/components/u-button/types.ts +1 -1
  12. package/components/u-button/u-button.vue +45 -37
  13. package/components/u-calendar/types.ts +4 -4
  14. package/components/u-calendar/u-calendar.vue +8 -8
  15. package/components/u-car-keyboard/u-car-keyboard.vue +5 -5
  16. package/components/u-card/types.ts +2 -2
  17. package/components/u-card/u-card.vue +3 -3
  18. package/components/u-cell-group/u-cell-group.vue +1 -1
  19. package/components/u-cell-item/u-cell-item.vue +2 -2
  20. package/components/u-checkbox/u-checkbox.vue +7 -7
  21. package/components/u-circle-progress/types.ts +4 -3
  22. package/components/u-circle-progress/u-circle-progress.vue +3 -3
  23. package/components/u-city-select/u-city-select.vue +1 -1
  24. package/components/u-collapse/types.ts +2 -2
  25. package/components/u-collapse/u-collapse.vue +1 -1
  26. package/components/u-collapse-item/u-collapse-item.vue +1 -1
  27. package/components/u-column-notice/u-column-notice.vue +2 -2
  28. package/components/u-config-provider/types.ts +34 -0
  29. package/components/u-config-provider/u-config-provider.vue +141 -0
  30. package/components/u-count-down/types.ts +4 -4
  31. package/components/u-count-down/u-count-down.vue +4 -4
  32. package/components/u-count-to/types.ts +1 -1
  33. package/components/u-count-to/u-count-to.vue +1 -1
  34. package/components/u-divider/types.ts +3 -3
  35. package/components/u-divider/u-divider.vue +4 -4
  36. package/components/u-dropdown/u-dropdown.vue +3 -3
  37. package/components/u-empty/types.ts +2 -2
  38. package/components/u-empty/u-empty.vue +1 -1
  39. package/components/u-field/types.ts +3 -3
  40. package/components/u-field/u-field.vue +6 -6
  41. package/components/u-form-item/u-form-item.vue +1 -1
  42. package/components/u-full-screen/u-full-screen.vue +1 -1
  43. package/components/u-gap/u-gap.vue +2 -2
  44. package/components/u-grid-item/types.ts +1 -1
  45. package/components/u-grid-item/u-grid-item.vue +3 -3
  46. package/components/u-icon/types.ts +2 -2
  47. package/components/u-icon/u-icon.vue +2 -2
  48. package/components/u-image/types.ts +4 -2
  49. package/components/u-image/u-image.vue +7 -2
  50. package/components/u-index-anchor/u-index-anchor.vue +3 -3
  51. package/components/u-index-list/u-index-list.vue +1 -1
  52. package/components/u-input/types.ts +4 -4
  53. package/components/u-input/u-input.vue +7 -7
  54. package/components/u-keyboard/u-keyboard.vue +3 -3
  55. package/components/u-lazy-load/u-lazy-load.vue +1 -1
  56. package/components/u-line/types.ts +1 -1
  57. package/components/u-line/u-line.vue +1 -1
  58. package/components/u-line-progress/types.ts +2 -2
  59. package/components/u-line-progress/u-line-progress.vue +3 -3
  60. package/components/u-link/u-link.vue +1 -1
  61. package/components/u-loading/types.ts +1 -1
  62. package/components/u-loading/u-loading.vue +3 -3
  63. package/components/u-loading-popup/types.ts +1 -1
  64. package/components/u-loading-popup/u-loading-popup.vue +2 -2
  65. package/components/u-loadmore/types.ts +2 -2
  66. package/components/u-loadmore/u-loadmore.vue +6 -6
  67. package/components/u-message-input/u-message-input.vue +5 -5
  68. package/components/u-modal/u-modal.vue +2 -2
  69. package/components/u-navbar/types.ts +4 -4
  70. package/components/u-navbar/u-navbar.vue +27 -20
  71. package/components/u-no-network/u-no-network.vue +2 -2
  72. package/components/u-number-box/types.ts +4 -4
  73. package/components/u-number-box/u-number-box.vue +6 -6
  74. package/components/u-number-keyboard/u-number-keyboard.vue +2 -2
  75. package/components/u-picker/u-picker.vue +4 -4
  76. package/components/u-popup/types.ts +1 -1
  77. package/components/u-popup/u-popup.vue +6 -6
  78. package/components/u-radio/u-radio.vue +7 -7
  79. package/components/u-rate/types.ts +2 -2
  80. package/components/u-rate/u-rate.vue +2 -2
  81. package/components/u-read-more/types.ts +1 -1
  82. package/components/u-row-notice/u-row-notice.vue +2 -2
  83. package/components/u-search/types.ts +4 -4
  84. package/components/u-search/u-search.vue +4 -4
  85. package/components/u-section/types.ts +2 -2
  86. package/components/u-section/u-section.vue +2 -2
  87. package/components/u-select/u-select.vue +6 -6
  88. package/components/u-skeleton/types.ts +2 -2
  89. package/components/u-skeleton/u-skeleton.vue +2 -2
  90. package/components/u-slider/types.ts +1 -1
  91. package/components/u-slider/u-slider.vue +4 -4
  92. package/components/u-step/u-step.vue +4 -4
  93. package/components/u-steps/u-steps.vue +3 -3
  94. package/components/u-sticky/types.ts +1 -1
  95. package/components/u-sticky/u-sticky.vue +1 -1
  96. package/components/u-subsection/types.ts +4 -4
  97. package/components/u-subsection/u-subsection.vue +7 -7
  98. package/components/u-swipe-action/types.ts +1 -1
  99. package/components/u-swipe-action/u-swipe-action.vue +2 -2
  100. package/components/u-swiper/types.ts +1 -1
  101. package/components/u-swiper/u-swiper.vue +1 -1
  102. package/components/u-switch/types.ts +1 -1
  103. package/components/u-switch/u-switch.vue +5 -5
  104. package/components/u-tabbar/types.ts +5 -4
  105. package/components/u-tabbar/u-tabbar.vue +5 -5
  106. package/components/u-table/types.ts +3 -3
  107. package/components/u-table/u-table.vue +3 -3
  108. package/components/u-tabs/types.ts +1 -1
  109. package/components/u-tabs/u-tabs.vue +2 -2
  110. package/components/u-tabs-swiper/types.ts +1 -1
  111. package/components/u-tabs-swiper/u-tabs-swiper.vue +2 -2
  112. package/components/u-tag/u-tag.vue +12 -12
  113. package/components/u-text/types.ts +1 -1
  114. package/components/u-text/u-text.vue +1 -1
  115. package/components/u-textarea/types.ts +1 -1
  116. package/components/u-textarea/u-textarea.vue +6 -6
  117. package/components/u-time-line/u-time-line.vue +1 -1
  118. package/components/u-time-line-item/types.ts +1 -1
  119. package/components/u-time-line-item/u-time-line-item.vue +2 -3
  120. package/components/u-toast/u-toast.vue +8 -8
  121. package/components/u-top-tips/u-top-tips.vue +1 -1
  122. package/components/u-upload/types.ts +2 -2
  123. package/components/u-upload/u-upload.vue +1 -1
  124. package/index.scss +1 -0
  125. package/index.ts +42 -11
  126. package/libs/config/theme-tokens.ts +101 -0
  127. package/libs/css/style.theme.scss +31 -0
  128. package/libs/css/style.vue.scss +1 -1
  129. package/libs/function/clipboard.ts +6 -11
  130. package/libs/function/color.ts +53 -22
  131. package/libs/hooks/index.ts +2 -0
  132. package/libs/hooks/useColor.ts +61 -0
  133. package/libs/hooks/useTheme.ts +162 -0
  134. package/libs/index.ts +4 -3
  135. package/libs/util/config-provider.ts +580 -0
  136. package/libs/util/system-theme.ts +25 -0
  137. package/package.json +5 -5
  138. package/theme.scss +50 -34
  139. package/types/components.d.ts +1 -0
  140. package/types/global.d.ts +47 -2
@@ -0,0 +1,101 @@
1
+ import type { Theme, ThemeColor } from '../../types/global';
2
+
3
+ const lightPalette: ThemeColor = {
4
+ primary: '#2979ff',
5
+ primaryDark: '#2b85e4',
6
+ primaryDisabled: '#a0cfff',
7
+ primaryLight: '#ecf5ff',
8
+ success: '#19be6b',
9
+ successDark: '#18b566',
10
+ successDisabled: '#71d5a1',
11
+ successLight: '#dbf1e1',
12
+ warning: '#ff9900',
13
+ warningDark: '#f29100',
14
+ warningDisabled: '#fcbd71',
15
+ warningLight: '#fdf6ec',
16
+ error: '#fa3534',
17
+ errorDark: '#dd6161',
18
+ errorDisabled: '#fab6b6',
19
+ errorLight: '#fef0f0',
20
+ info: '#909399',
21
+ infoDark: '#82848a',
22
+ infoDisabled: '#c8c9cc',
23
+ infoLight: '#f4f4f5',
24
+ whiteColor: '#ffffff',
25
+ blackColor: '#000000',
26
+ mainColor: '#303133',
27
+ contentColor: '#606266',
28
+ tipsColor: '#909399',
29
+ lightColor: '#c0c4cc',
30
+ borderColor: '#dcdfe6',
31
+ dividerColor: '#e4e7ed',
32
+ maskColor: 'rgba(0, 0, 0, 0.4)',
33
+ shadowColor: 'rgba(0, 0, 0, 0.1)',
34
+ bgColor: '#f3f4f6',
35
+ bgWhite: '#ffffff',
36
+ bgGrayLight: '#f5f7fa',
37
+ bgGrayDark: '#2f343c',
38
+ bgBlack: '#000000'
39
+ };
40
+
41
+ const darkPalette: ThemeColor = {
42
+ primary: '#8ab4ff',
43
+ primaryDark: '#5f8dff',
44
+ primaryDisabled: '#3d4f74',
45
+ primaryLight: '#1d273f',
46
+ success: '#4ade80',
47
+ successDark: '#1f9d57',
48
+ successDisabled: '#2f4d3d',
49
+ successLight: '#10291f',
50
+ warning: '#fbbf24',
51
+ warningDark: '#c88f00',
52
+ warningDisabled: '#4a3b17',
53
+ warningLight: '#2b1f05',
54
+ error: '#ff6b6b',
55
+ errorDark: '#d83a3a',
56
+ errorDisabled: '#4f2323',
57
+ errorLight: '#2d1414',
58
+ info: '#a0a7b8',
59
+ infoDark: '#7c8394',
60
+ infoDisabled: '#3b3f4c',
61
+ infoLight: '#1d2029',
62
+ whiteColor: '#f5f6f7',
63
+ blackColor: '#f5f6f7',
64
+ mainColor: '#f5f6f7',
65
+ contentColor: '#cfd3dc',
66
+ tipsColor: '#9aa1af',
67
+ lightColor: '#6b7082',
68
+ borderColor: '#3a4251',
69
+ dividerColor: '#3a4251',
70
+ maskColor: 'rgba(0, 0, 0, 0.6)',
71
+ shadowColor: 'rgba(0, 0, 0, 0.3)',
72
+ bgColor: '#111827',
73
+ bgWhite: '#000000',
74
+ bgGrayLight: '#1a1a1a',
75
+ bgGrayDark: '#f5f7fa',
76
+ bgBlack: '#ffffff'
77
+ };
78
+
79
+ const lightCss: Record<string, string> = {
80
+ '--u-background': '#ffffff',
81
+ '--u-surface': '#f7f8fa',
82
+ '--u-text': '#303133'
83
+ };
84
+
85
+ const darkCss: Record<string, string> = {
86
+ '--u-background': '#0f1115',
87
+ '--u-surface': '#1c2233',
88
+ '--u-text': '#f5f6f7'
89
+ };
90
+
91
+ export const defaultThemes: Theme[] = [
92
+ {
93
+ name: 'uviewpro',
94
+ label: '默认蓝',
95
+ description: 'uView Pro 默认主题,支持亮色与暗黑模式',
96
+ color: lightPalette,
97
+ darkColor: darkPalette,
98
+ css: lightCss,
99
+ darkCss: darkCss
100
+ }
101
+ ];
@@ -0,0 +1,31 @@
1
+ :root {
2
+ color-scheme: light;
3
+ }
4
+
5
+ :root.u-theme-dark,
6
+ :root[data-u-theme-mode='dark'] {
7
+ color-scheme: dark;
8
+ }
9
+
10
+ page {
11
+ color: $u-main-color;
12
+ background-color: $u-bg-color;
13
+ font-size: 28rpx;
14
+ }
15
+
16
+ page.u-theme-dark,
17
+ :root.u-theme-dark page,
18
+ :root[data-u-theme-mode='dark'] page {
19
+ background-color: $u-bg-color;
20
+ color: $u-main-color;
21
+ }
22
+
23
+ .u-config-provider {
24
+ color: $u-main-color;
25
+ background-color: var(--u-bg-white, #ffffff);
26
+ }
27
+
28
+ .u-config-provider.u-theme-dark {
29
+ background-color: var(--u-bg-white, #0f1115);
30
+ color: $u-main-color;
31
+ }
@@ -33,7 +33,7 @@ page {
33
33
  }
34
34
 
35
35
  .u-cell-hover {
36
- background-color: #f7f8f9 !important;
36
+ background-color: $u-bg-gray-light !important;
37
37
  }
38
38
  /* end--各种hover点击反馈相关的类名--end */
39
39
 
@@ -48,7 +48,6 @@ function H5Copy(text: string, config: TClipboardOptions) {
48
48
 
49
49
  function UniCopy(text: string, config: TClipboardOptions) {
50
50
  const opt = Object.assign({ data: text }, config);
51
- console.log(opt);
52
51
  uni.setClipboardData(opt);
53
52
  }
54
53
 
@@ -56,17 +55,13 @@ type TClipboardOptions = Omit<UniNamespace.SetClipboardDataOptions, 'data'>;
56
55
 
57
56
  export function clipboard(content: string, options?: TClipboardOptions) {
58
57
  const text = String(content);
59
- const showToast = typeof options.showToast === 'boolean' ? options.showToast : true;
60
- const copySuccessCb = typeof options.success === 'function' ? options.success : () => {};
61
- const copyFailCb = typeof options.success === 'function' ? options.fail : () => {};
62
- const copyCompleteCb = typeof options.complete === 'function' ? options.complete : () => {};
63
-
64
- let config: TClipboardOptions = {
65
- showToast,
66
- success: copySuccessCb,
67
- fail: copyFailCb,
68
- complete: copyCompleteCb
58
+ const defaultOpt = {
59
+ showToast: true,
60
+ success: () => {},
61
+ fail: () => {},
62
+ complete: () => {}
69
63
  };
64
+ const config = Object.assign(defaultOpt, options);
70
65
 
71
66
  // #ifdef H5
72
67
  H5Copy(text, config);
@@ -1,46 +1,77 @@
1
+ import { reactive } from 'vue';
1
2
  import type { ColorType, ThemeColor } from '../../types/global';
2
3
 
3
- // 使用 reactive 包装颜色对象,使其在运行时可被响应式读取与更新
4
- const color: ThemeColor = {
4
+ // 默认颜色值(作为初始值)
5
+ const defaultColor: ThemeColor = {
5
6
  primary: '#2979ff',
6
7
  primaryDark: '#2b85e4',
7
8
  primaryDisabled: '#a0cfff',
8
9
  primaryLight: '#ecf5ff',
9
- bgColor: '#f3f4f6',
10
-
11
- info: '#909399',
12
- infoDark: '#82848a',
13
- infoDisabled: '#c8c9cc',
14
- infoLight: '#f4f4f5',
15
-
10
+ success: '#19be6b',
11
+ successDark: '#18b566',
12
+ successDisabled: '#71d5a1',
13
+ successLight: '#dbf1e1',
16
14
  warning: '#ff9900',
17
15
  warningDark: '#f29100',
18
16
  warningDisabled: '#fcbd71',
19
17
  warningLight: '#fdf6ec',
20
-
21
18
  error: '#fa3534',
22
19
  errorDark: '#dd6161',
23
20
  errorDisabled: '#fab6b6',
24
21
  errorLight: '#fef0f0',
25
-
26
- success: '#19be6b',
27
- successDark: '#18b566',
28
- successDisabled: '#71d5a1',
29
- successLight: '#dbf1e1',
30
-
22
+ info: '#909399',
23
+ infoDark: '#82848a',
24
+ infoDisabled: '#c8c9cc',
25
+ infoLight: '#f4f4f5',
26
+ whiteColor: '#ffffff',
27
+ blackColor: '#000000',
31
28
  mainColor: '#303133',
32
29
  contentColor: '#606266',
33
30
  tipsColor: '#909399',
34
31
  lightColor: '#c0c4cc',
35
- borderColor: '#e4e7ed'
32
+ borderColor: '#dcdfe6',
33
+ dividerColor: '#e4e7ed',
34
+ maskColor: 'rgba(0, 0, 0, 0.4)',
35
+ shadowColor: 'rgba(0, 0, 0, 0.1)',
36
+ bgColor: '#f3f4f6',
37
+ bgWhite: '#ffffff',
38
+ bgGrayLight: '#f5f7fa',
39
+ bgGrayDark: '#2f343c',
40
+ bgBlack: '#000000'
36
41
  };
37
42
 
38
- export function getColor(name: ColorType) {
39
- // 延迟获取,确保在组件实例化时获取当前主题颜色
40
- if (typeof uni !== 'undefined' && uni.$u) {
41
- return uni.$u.color[name];
43
+ // 使用 reactive 包装颜色对象,使其在运行时可被响应式读取与更新
44
+ // 这个对象会被 configProvider 在主题切换时更新
45
+ export const color = reactive<ThemeColor>({ ...defaultColor });
46
+
47
+ /**
48
+ * 获取颜色值(响应式)
49
+ * 优先从 configProvider 获取当前主题颜色,否则返回默认值
50
+ * @param name 颜色名称
51
+ * @returns 颜色值
52
+ */
53
+ export function getColor(name: ColorType): string {
54
+ // // 优先从 configProvider 获取当前主题颜色
55
+ // const currentTheme = configProvider.getCurrentTheme();
56
+ // if (currentTheme) {
57
+ // const isDark = configProvider.isInDarkMode();
58
+ // const palette =
59
+ // isDark && currentTheme.darkColor && Object.keys(currentTheme.darkColor).length
60
+ // ? currentTheme.darkColor
61
+ // : currentTheme.color || {};
62
+
63
+ // if (palette[name]) {
64
+ // return palette[name] as string;
65
+ // }
66
+ // }
67
+
68
+ // 从响应式 color 对象获取(会被 configProvider 更新)
69
+ if (color[name]) {
70
+ return color[name] as string;
42
71
  }
43
- return color[name] || '';
72
+
73
+ // 兜底返回默认值
74
+ return defaultColor[name] || '';
44
75
  }
45
76
 
46
77
  export default color;
@@ -1,3 +1,5 @@
1
1
  export * from './useEmitter';
2
2
  export * from './useRect';
3
3
  export * from './useCompRelation';
4
+ export * from './useTheme';
5
+ export * from './useColor';
@@ -0,0 +1,61 @@
1
+ /**
2
+ * 响应式颜色管理 composable
3
+ * 提供响应式的颜色访问,支持主题切换和暗黑模式
4
+ *
5
+ * 使用方式:
6
+ * const { color, getColor } = useColor()
7
+ * // color 是响应式的,可以直接在模板中使用
8
+ * // getColor('primary') 返回响应式的颜色值
9
+ */
10
+
11
+ import { computed, type ComputedRef } from 'vue';
12
+ import type { ColorType } from '../../types/global';
13
+ import configProvider from '../util/config-provider';
14
+
15
+ /**
16
+ * 响应式颜色 composable
17
+ * 返回响应式的颜色对象和获取颜色的方法
18
+ */
19
+ export function useColor() {
20
+ // 从 configProvider 获取当前主题的响应式引用
21
+ const currentTheme = configProvider.currentThemeRef;
22
+ const darkModeRef = configProvider.darkModeRef;
23
+
24
+ /**
25
+ * 获取当前激活模式下的颜色对象(响应式)
26
+ */
27
+ const color = computed(() => {
28
+ const theme = currentTheme.value;
29
+ if (!theme) return {} as Record<ColorType, string>;
30
+
31
+ const isDark = configProvider.isInDarkMode();
32
+ const palette =
33
+ isDark && theme.darkColor && Object.keys(theme.darkColor).length ? theme.darkColor : theme.color || {};
34
+
35
+ // 合并默认值,确保所有颜色都有值
36
+ const defaultPalette = isDark
37
+ ? (configProvider as any).baseDarkColorTokens || {}
38
+ : (configProvider as any).baseColorTokens || {};
39
+
40
+ return {
41
+ ...defaultPalette,
42
+ ...palette
43
+ } as Record<ColorType, string>;
44
+ });
45
+
46
+ /**
47
+ * 获取指定颜色(响应式)
48
+ * @param name 颜色名称
49
+ * @returns 颜色值
50
+ */
51
+ const getColor = (name: ColorType): ComputedRef<string> => {
52
+ return computed(() => {
53
+ return color.value[name] || '';
54
+ });
55
+ };
56
+
57
+ return {
58
+ color,
59
+ getColor
60
+ };
61
+ }
@@ -0,0 +1,162 @@
1
+ /**
2
+ * 主题管理 composable
3
+ * 提供主题切换、持久化、CSS 变量注入、暗黑模式等功能
4
+ *
5
+ * 使用方式:
6
+ * const { currentTheme, themes, setTheme, getDarkMode, setDarkMode, isInDarkMode, getAvailableThemes, initTheme } = useTheme()
7
+ */
8
+
9
+ import type { DarkMode, Theme } from '../../types/global';
10
+ import configProvider from '../util/config-provider';
11
+ import { defaultThemes } from '../config/theme-tokens';
12
+
13
+ const THEME_STORAGE_KEY = 'uview-pro-theme';
14
+ const DARK_MODE_STORAGE_KEY = 'uview-pro-dark-mode';
15
+ const themesRef = configProvider.themesRef;
16
+ const currentTheme = configProvider.currentThemeRef;
17
+ const darkModeRef = configProvider.darkModeRef;
18
+
19
+ /**
20
+ * 保存主题到 Storage
21
+ */
22
+ function saveThemeToStorage(themeName: string) {
23
+ try {
24
+ uni.setStorageSync(THEME_STORAGE_KEY, themeName);
25
+ } catch (e) {
26
+ console.warn('[useTheme] failed to write storage', e);
27
+ }
28
+ }
29
+
30
+ /**
31
+ * 保存暗黑模式设置到 Storage
32
+ */
33
+ function saveDarkModeToStorage(mode: DarkMode) {
34
+ try {
35
+ uni.setStorageSync(DARK_MODE_STORAGE_KEY, mode);
36
+ } catch (e) {
37
+ console.warn('[useTheme] failed to write storage', e);
38
+ }
39
+ }
40
+
41
+ /**
42
+ * 设置主题
43
+ */
44
+ function setTheme(themeName: string) {
45
+ configProvider.setTheme(themeName);
46
+ currentTheme.value = configProvider.getCurrentTheme();
47
+ saveThemeToStorage(themeName);
48
+ }
49
+
50
+ /**
51
+ * 获取当前主题
52
+ */
53
+ function getCurrentTheme(): Theme | null {
54
+ return currentTheme.value || configProvider.getCurrentTheme();
55
+ }
56
+
57
+ /**
58
+ * 获取所有可用主题
59
+ */
60
+ function getAvailableThemes() {
61
+ return configProvider.getThemes();
62
+ }
63
+
64
+ /**
65
+ * 初始化主题系统
66
+ * @param themes 可选的主题列表,如果未提供则尝试从 uni.$u.themes 读取
67
+ * @param defaultThemeName 可选的默认主题名
68
+ */
69
+ export function initTheme(themes?: any[], defaultThemeName?: string) {
70
+ // 如果有传入主题列表,使用传入的
71
+ if (Array.isArray(themes) && themes.length > 0) {
72
+ configProvider.init(themes, defaultThemeName);
73
+ return;
74
+ }
75
+
76
+ // 若已通过插件或其他方式完成初始化,则不再覆盖,最多按需切换默认主题
77
+ const existingThemes = configProvider.getThemes();
78
+ if (existingThemes.length > 0) {
79
+ if (defaultThemeName) {
80
+ configProvider.setTheme(defaultThemeName);
81
+ } else if (!configProvider.getCurrentTheme()) {
82
+ configProvider.setTheme(existingThemes[0].name);
83
+ } else {
84
+ // 触发一次 apply,便于初始化 CSS 变量
85
+ configProvider.setTheme(configProvider.getCurrentTheme()!.name);
86
+ }
87
+ return;
88
+ }
89
+
90
+ // 初始化 configProvider(如果运行时提供了内置主题)
91
+ try {
92
+ const builtin = (typeof uni !== 'undefined' && (uni as any).$u && (uni as any).$u.themes) || [];
93
+ if (Array.isArray(builtin) && builtin.length > 0) {
94
+ configProvider.init(builtin as Theme[], defaultThemeName);
95
+ return;
96
+ }
97
+ } catch (e) {
98
+ // ignore
99
+ }
100
+
101
+ // 回退到内置默认主题
102
+ configProvider.init(defaultThemes as Theme[], defaultThemeName);
103
+ }
104
+
105
+ /**
106
+ * 获取当前暗黑模式设置
107
+ */
108
+ function getDarkMode(): DarkMode {
109
+ return configProvider.getDarkMode();
110
+ }
111
+
112
+ /**
113
+ * 设置暗黑模式
114
+ * @param mode 'auto' (跟随系统) | 'light' (强制亮色) | 'dark' (强制暗黑)
115
+ */
116
+ function setDarkMode(mode: DarkMode) {
117
+ configProvider.setDarkMode(mode);
118
+ darkModeRef.value = mode;
119
+ saveDarkModeToStorage(mode);
120
+ }
121
+
122
+ /**
123
+ * 检查当前是否处于暗黑模式
124
+ */
125
+ function isInDarkMode(): boolean {
126
+ return configProvider.isInDarkMode();
127
+ }
128
+
129
+ /**
130
+ * 切换暗黑模式(在当前模式的基础上切换)
131
+ */
132
+ function toggleDarkMode() {
133
+ const current = getDarkMode();
134
+ const nextMode = current === 'dark' ? 'light' : 'dark';
135
+ setDarkMode(nextMode);
136
+ }
137
+
138
+ /**
139
+ * 使用主题的 composable
140
+ * 返回所有主题相关的响应式引用和方法
141
+ */
142
+ export function useTheme() {
143
+ return {
144
+ // 响应式引用
145
+ currentTheme,
146
+ themes: themesRef,
147
+ darkMode: darkModeRef,
148
+ cssVars: configProvider.cssVarsRef,
149
+
150
+ // 主题相关方法
151
+ setTheme,
152
+ getCurrentTheme,
153
+ getAvailableThemes,
154
+ initTheme,
155
+
156
+ // 暗黑模式相关方法
157
+ getDarkMode,
158
+ setDarkMode,
159
+ isInDarkMode,
160
+ toggleDarkMode
161
+ };
162
+ }
package/libs/index.ts CHANGED
@@ -248,7 +248,7 @@ export function kebabCase(word: string): string {
248
248
  * 运行时设置主题颜色(就地合并到 reactive 的 $u.color)
249
249
  * @param theme Partial<ThemeColor>
250
250
  */
251
- function setTheme(theme: Partial<ThemeColor> | undefined) {
251
+ function setColor(theme: Partial<ThemeColor> | undefined) {
252
252
  if (!theme) return;
253
253
  try {
254
254
  const merged = deepMerge($u.color, theme);
@@ -291,7 +291,7 @@ export {
291
291
  config,
292
292
  zIndex,
293
293
  mitt,
294
- setTheme
294
+ setColor
295
295
  };
296
296
 
297
297
  export const $u = {
@@ -334,7 +334,7 @@ export const $u = {
334
334
  addStyle,
335
335
  toStyle,
336
336
  kebabCase,
337
- setTheme
337
+ setColor
338
338
  };
339
339
 
340
340
  // 颜色相关方法单独导出
@@ -353,3 +353,4 @@ export {
353
353
  export * from './hooks';
354
354
 
355
355
  export * from './util/logger';
356
+ export * from './util/config-provider';