wui-components-v2 1.1.65 → 1.1.67

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 (38) hide show
  1. package/components/action-popup/action-popup.vue +4 -4
  2. package/components/add-address-page/add-address-page.vue +20 -20
  3. package/components/card-botom-buttons/card-botom-buttons.vue +58 -35
  4. package/components/custom-select-picker/custom-select-picker.vue +19 -27
  5. package/components/demo-block/demo-block.vue +2 -5
  6. package/components/detail-popup/detail-popup.vue +12 -5
  7. package/components/evaluation-page/evaluation-page.vue +192 -0
  8. package/components/fold-card/fold-card.vue +25 -5
  9. package/components/form-control/form-control.vue +289 -43
  10. package/components/label-value/label-value.vue +1 -1
  11. package/components/list-top-buttons/list-top-buttons.vue +1 -1
  12. package/components/login-form/login-form.vue +31 -26
  13. package/components/mulselect-picker/mulselect-picker.vue +10 -12
  14. package/components/privacy-popup/privacy-popup.vue +13 -0
  15. package/components/product-card/product-card.vue +95 -21
  16. package/components/search/search.vue +23 -22
  17. package/components/tree-select/components/index.vue +1 -1
  18. package/components/wui-edit-page/wui-edit-page-copy.vue +1 -1
  19. package/components/wui-edit-page/wui-edit-page.vue +2 -2
  20. package/components/wui-login/wui-login.vue +3 -3
  21. package/components/wui-login1/wui-login.vue +4 -4
  22. package/components/wui-menus1/components/navbar.vue +1 -1
  23. package/components/wui-menus1/components/quick-panel.vue +3 -3
  24. package/components/wui-menus1/components/section-menus.vue +4 -4
  25. package/components/wui-menus1/wui-menus-top.vue +1 -1
  26. package/components/wui-menus1/wui-menus-top1.vue +1 -1
  27. package/components/wui-menus1/wui-menus.vue +3 -3
  28. package/components/wui-notify-info/wui-notify-info.vue +65 -35
  29. package/components/wui-select-list/wui-select-list.vue +1 -1
  30. package/components/wui-select-popup/wui-select-popup.vue +27 -17
  31. package/components/wui-system-settings/wui-system-settings.vue +31 -24
  32. package/components/wui-tabbar/wui-tabbar.vue +14 -5
  33. package/components/wui-tree-page/components/tree-item.vue +51 -30
  34. package/components/wui-user/wui-user.vue +68 -57
  35. package/index.ts +5 -3
  36. package/package.json +1 -1
  37. package/store/manualThemeStore.ts +7 -7
  38. package/styles/dark-mode.scss +424 -0
@@ -56,7 +56,7 @@ const rightSidebars = computed(() => {
56
56
  return data
57
57
  })
58
58
  const sources = computed(() => {
59
- return rightSidebars.value.map((item) => {
59
+ return rightSidebars.value.map(item => {
60
60
  return {
61
61
  id: item.id,
62
62
  title: item.title,
@@ -69,41 +69,49 @@ async function getEnums(sourceId: string, config: Config) {
69
69
  const params: string[] = []
70
70
  const criterias = config?.criterias ?? []
71
71
  const columns = config?.columns ?? []
72
- const writes = config?.rowActions?.reduce((acc: any, cur: any) => {
73
- return [...acc, ...cur.writes]
74
- }, []) || []
72
+ const writes =
73
+ config?.rowActions?.reduce((acc: any, cur: any) => {
74
+ return [...acc, ...cur.writes]
75
+ }, []) || []
75
76
  columns.forEach((item: any) => {
76
- if (ControlTypeSupportor.getControlType(item) === 'select' || ControlTypeSupportor.getControlType(item) === 'multiselect') {
77
+ if (
78
+ ControlTypeSupportor.getControlType(item) === 'select' ||
79
+ ControlTypeSupportor.getControlType(item) === 'multiselect'
80
+ ) {
77
81
  params.push(`mstrucIds=${item.mstrucId}`)
78
82
  }
79
83
  })
80
84
  criterias.forEach((item: any) => {
81
- if (ControlTypeSupportor.getControlType(item) === 'select' || ControlTypeSupportor.getControlType(item) === 'multiselect') {
85
+ if (
86
+ ControlTypeSupportor.getControlType(item) === 'select' ||
87
+ ControlTypeSupportor.getControlType(item) === 'multiselect'
88
+ ) {
82
89
  params.push(`mstrucIds=${item.mstrucId}`)
83
90
  }
84
91
  })
85
92
  writes.forEach((item: any) => {
86
- if (ControlTypeSupportor.getControlType(item) === 'select' || ControlTypeSupportor.getControlType(item) === 'multiselect') {
93
+ if (
94
+ ControlTypeSupportor.getControlType(item) === 'select' ||
95
+ ControlTypeSupportor.getControlType(item) === 'multiselect'
96
+ ) {
87
97
  params.push(`mstrucIds=${item.mstrucId}`)
88
98
  }
89
99
  })
90
- if (!params.length)
91
- return
100
+ if (!params.length) return
92
101
  const res = await enums(params.join('&'))
93
102
  enumColumn.value[sourceId] = res.enumMap || {}
94
- }
95
- catch (error) {
103
+ } catch (error) {
96
104
  console.log('error:', error)
97
105
  }
98
106
  }
99
107
  // 获取数据
100
- async function queryList(source: { id: string, title: string }): Promise<Notification | null> {
108
+ async function queryList(source: { id: string; title: string }): Promise<Notification | null> {
101
109
  try {
102
110
  const res = await pageConfig(source.id)
103
111
  dtmplConfig.value[source.id] = res.ltmplConfig
104
112
  getEnums(source.id, res.ltmplConfig)
105
- const res1 = await pageKey(source.id, '', '')// 获取key
106
- const data = await listData(res1.key, 1, 10)// 获取数据
113
+ const res1 = await pageKey(source.id, '', '') // 获取key
114
+ const data = await listData(res1.key, 1, 10) // 获取数据
107
115
  return {
108
116
  id: source.id,
109
117
  title: source.title,
@@ -125,8 +133,7 @@ async function queryList(source: { id: string, title: string }): Promise<Notific
125
133
  }
126
134
  }),
127
135
  }
128
- }
129
- catch (error) {
136
+ } catch (error) {
130
137
  console.error(error)
131
138
  return null
132
139
  }
@@ -148,10 +155,14 @@ watch(sources, () => {
148
155
 
149
156
  function getIconColor(type: string) {
150
157
  switch (type) {
151
- case 'system': return 'bg-blue-500'
152
- case 'department': return 'bg-amber-500'
153
- case 'colleague': return 'bg-purple-500'
154
- default: return 'bg-slate-500'
158
+ case 'system':
159
+ return 'bg-blue-500'
160
+ case 'department':
161
+ return 'bg-amber-500'
162
+ case 'colleague':
163
+ return 'bg-purple-500'
164
+ default:
165
+ return 'bg-slate-500'
155
166
  }
156
167
  }
157
168
 
@@ -190,22 +201,30 @@ function gotoDetailPage(item: Data) {
190
201
  <template>
191
202
  <view v-if="notifications && notifications.length > 0" class="mb-6 mt-6">
192
203
  <view class="mb-4 flex items-center justify-between">
193
- <text class="text-base text-slate-800 font-semibold .dark:text-white">
204
+ <text class="text-base text-slate-800 font-semibold dark:text-white">
194
205
  {{ languageStore.t('最新消息') }}
195
206
  </text>
196
207
  </view>
197
208
 
198
209
  <view v-for="notification in notifications" :key="notification.id" class="space-y-3">
199
- <view class="mt-2 flex justify-between text-size-3 color-gray .dark:text-white">
210
+ <view class="mt-2 flex justify-between text-size-3 color-gray dark:text-white">
200
211
  <view>{{ languageStore.t(notification.title) }}</view>
201
- <view @click="() => { gotoPage(notification) }">
212
+ <view
213
+ @click="
214
+ () => {
215
+ gotoPage(notification)
216
+ }
217
+ "
218
+ >
202
219
  {{ languageStore.t('查看全部') }}
203
220
  </view>
204
221
  </view>
205
222
  <button
206
- v-for="item in notification.data" :key="item.id"
207
- class="w-full flex cursor-pointer items-start gap-3 rounded-xl bg-white p-4 text-left shadow-[0_4px_16px_rgba(99,102,241,0.1)] transition-all duration-200 .dark:bg-black hover:shadow-md"
208
- :class="{ 'opacity-60': item.read }" @click="handleNotificationClick(item)"
223
+ v-for="item in notification.data"
224
+ :key="item.id"
225
+ class="w-full flex cursor-pointer items-start gap-3 rounded-xl bg-white p-4 text-left shadow-[0_4px_16px_rgba(99,102,241,0.1)] transition-all duration-200 dark:bg-black hover:shadow-md"
226
+ :class="{ 'opacity-60': item.read }"
227
+ @click="handleNotificationClick(item)"
209
228
  >
210
229
  <view
211
230
  :class="getIconColor(item.type)"
@@ -216,20 +235,31 @@ function gotoDetailPage(item: Data) {
216
235
 
217
236
  <view class="min-w-0 flex-1">
218
237
  <view class="flex justify-between gap-1">
219
- <span class="text-sm text-slate-800 font-medium .dark:text-white">{{ formatItemData(item.primaryColumn,
220
- ControlTypeSupportor.getControlType(item.primaryColumnConfig)) }}</span>
221
- <span class="whitespace-nowrap text-xs text-slate-400 .dark:text-white">{{
222
- formatItemData(item.primaryColumnLabel,
223
- ControlTypeSupportor.getControlType(item.primaryColumnLabelConfig)) }}</span>
238
+ <span class="text-sm text-slate-800 font-medium dark:text-white">
239
+ {{ formatItemData(item.primaryColumn, ControlTypeSupportor.getControlType(item.primaryColumnConfig)) }}
240
+ </span>
241
+ <span class="whitespace-nowrap text-xs text-slate-400 dark:text-gray-300">
242
+ {{
243
+ formatItemData(
244
+ item.primaryColumnLabel,
245
+ ControlTypeSupportor.getControlType(item.primaryColumnLabelConfig)
246
+ )
247
+ }}
248
+ </span>
224
249
  </view>
225
- <p class="line-clamp-2 mt-1 text-sm text-slate-500 .dark:text-white">
250
+ <p class="line-clamp-2 mt-1 text-sm text-slate-500 dark:text-gray-400">
226
251
  <text class="mr-1">
227
- {{ formatItemData(item.secondColumn, ControlTypeSupportor.getControlType(item.secondColumnConfig || {}))
252
+ {{
253
+ formatItemData(item.secondColumn, ControlTypeSupportor.getControlType(item.secondColumnConfig || {}))
228
254
  }}
229
255
  </text>
230
256
  <text>
231
- {{ formatItemData(item.secondColumnLabel,
232
- ControlTypeSupportor.getControlType(item.secondColumnLabelConfig || {})) }}
257
+ {{
258
+ formatItemData(
259
+ item.secondColumnLabel,
260
+ ControlTypeSupportor.getControlType(item.secondColumnLabelConfig || {})
261
+ )
262
+ }}
233
263
  </text>
234
264
  </p>
235
265
  </view>
@@ -298,7 +298,7 @@ onUnmounted(() => {
298
298
 
299
299
  <template #bottom>
300
300
  <slot name="bottom">
301
- <view class="flex justify-between gap-1 p-2 .dark:bg-gray-900 .light:bg-white">
301
+ <view class="flex justify-between gap-1 p-2 bg-white dark:bg-[var(--wot-dark-background)]">
302
302
  <!-- <wd-button class="flex-1" type="info" @click="cancel">
303
303
  取消
304
304
  </wd-button> -->
@@ -35,7 +35,7 @@ const props = withDefaults(
35
35
  defaultSelectFirst: false,
36
36
  }
37
37
  )
38
-
38
+ console.log(props, '3333333333333333333')
39
39
  const emit = defineEmits<{
40
40
  (e: 'update:modelValue', value: string | string[]): void
41
41
  (e: 'confirm', value: string | string[]): void
@@ -161,6 +161,8 @@ const formatAddress = (value: string) => {
161
161
  const isConfigLoaded = ref(false)
162
162
  // ★ 防止重复加载
163
163
  const isLoading = ref(false)
164
+ // ★ 防止 z-paging 初始化时与手动 reload 重复请求
165
+ const hasInitialized = ref(false)
164
166
 
165
167
  // ★ 是否已完成默认首项选中
166
168
  const hasDefaultSelected = ref(false)
@@ -217,8 +219,17 @@ async function getEnums() {
217
219
 
218
220
  // 查询列表数据(完整流程:config -> key -> data)
219
221
  async function queryList(pageNo: number, pageSize: number) {
220
- // ★ 首次加载时防重复(分页加载不拦截,pageNo > 1 时放行)
222
+ // ★ 只防正在进行的重复请求(分页不拦截)
221
223
  if (pageNo === 1 && isLoading.value) return
224
+
225
+ // ★ z-paging 组件初始化时自动触发 @query,popup 未打开时跳过
226
+ // (只跳过第一次,后续打开 popup 后的查询正常放行)
227
+ if (!show.value && !hasInitialized.value) {
228
+ hasInitialized.value = true
229
+ Zpaging.value.complete([])
230
+ return
231
+ }
232
+
222
233
  if (pageNo === 1) isLoading.value = true
223
234
 
224
235
  try {
@@ -344,9 +355,10 @@ function openPopup(e?: any) {
344
355
  watch(show, async val => {
345
356
  console.log('[WuiSelectPopup] 📢 show 状态变化:', val)
346
357
  if (val) {
347
- if (isLoading.value) return // ★ 防重复
348
- isConfigLoaded.value = false
358
+ if (isLoading.value) return // ★ 防重复(正在请求中不重复触发)
349
359
  await nextTick()
360
+ // ★ 不重置 isConfigLoaded(配置只需加载一次)
361
+ hasInitialized.value = false // ★ 允许 reload 触发查询
350
362
  if (Zpaging.value) {
351
363
  Zpaging.value.reload()
352
364
  } else {
@@ -364,7 +376,8 @@ function handleRefresh(refreshSourceId: string) {
364
376
  if (refreshSourceId !== props.sourceId) return
365
377
  console.log('[WuiSelectPopup] 🔄 收到刷新信号,重新加载数据')
366
378
  if (show.value && Zpaging.value && !isLoading.value) {
367
- isConfigLoaded.value = false
379
+ isConfigLoaded.value = false // ★ 刷新时重新加载配置
380
+ hasInitialized.value = false // ★ 允许 reload 触发
368
381
  Zpaging.value.reload()
369
382
  }
370
383
  }
@@ -391,18 +404,18 @@ defineExpose({
391
404
  </script>
392
405
 
393
406
  <template>
394
- <view class="wui-select-popup-wrapper">
407
+ <view class="wui-select-popup-wrapper dark:bg-[var(--wot-dark-background)]">
395
408
  <!-- ★ 触发区域 - 原生表单样式(左标签 + 中内容 + 右箭头) -->
396
409
  <view v-if="!show" class="trigger-cell" @click="openPopup">
397
410
  <!-- 左侧标签 -->
398
- <text v-if="label" class="cell-label">
411
+ <text v-if="label" class="cell-label dark:text-white">
399
412
  {{ label }}
400
413
  </text>
401
414
 
402
415
  <!-- 中间内容区 -->
403
- <view class="cell-content">
404
- <text v-if="displayValue" class="cell-value">
405
- {{ displayValue }}
416
+ <view class="cell-content dark:text-white">
417
+ <text v-if="displayValue && displayValue !== 'null'" class="cell-value">
418
+ {{ displayValue || '' }}
406
419
  </text>
407
420
  <text v-else class="cell-placeholder">
408
421
  {{ placeholder || `请选择${title || label}` }}
@@ -422,6 +435,7 @@ defineExpose({
422
435
  position="bottom"
423
436
  :z-index="999999"
424
437
  custom-style="border-radius: 24rpx 24rpx 0 0; overflow: hidden;"
438
+ class="dark:bg-[#1b1b1e]"
425
439
  safe-area-inset-bottom
426
440
  @close="
427
441
  () => {
@@ -429,10 +443,10 @@ defineExpose({
429
443
  }
430
444
  "
431
445
  >
432
- <view class="select-popup-container">
446
+ <view class="select-popup-container dark:bg-[#1b1b1e]">
433
447
  <!-- 标题栏 - 固定高度不参与滚动 -->
434
448
  <view
435
- class="popup-header flex items-center justify-between px-4 py-3 border-b border-gray-200 bg-white shrink-0"
449
+ class="popup-header flex items-center justify-between px-4 py-3 border-b border-gray-200 shrink-0 dark:text-white"
436
450
  >
437
451
  <text class="text-base font-bold">选择{{ title }}</text>
438
452
  <wd-icon name="close-circle" size="16px" @click="cancel" />
@@ -491,7 +505,7 @@ defineExpose({
491
505
  </foldCard>
492
506
 
493
507
  <template #bottom>
494
- <view class="popup-footer flex justify-center gap-4 p-4 bg-white border-t border-gray-200">
508
+ <view class="popup-footer flex justify-center gap-4 p-4 border-t border-gray-200">
495
509
  <wd-button plain custom-class="flex-1" @click="cancel">取消</wd-button>
496
510
  <wd-button type="primary" custom-class="flex-1" @click="confirm">确定</wd-button>
497
511
  </view>
@@ -514,7 +528,6 @@ defineExpose({
514
528
  display: flex;
515
529
  align-items: center;
516
530
  justify-content: space-between;
517
- background-color: #fff;
518
531
  cursor: pointer;
519
532
  position: relative;
520
533
  transition: background-color 0.2s;
@@ -526,7 +539,6 @@ defineExpose({
526
539
  // 左侧标签 - 固定宽度,不换行
527
540
  .cell-label {
528
541
  flex-shrink: 0;
529
- color: #333;
530
542
  margin-right: 24rpx;
531
543
  white-space: nowrap;
532
544
  }
@@ -537,7 +549,6 @@ defineExpose({
537
549
  min-width: 0; // 允许文本溢出省略
538
550
 
539
551
  .cell-value {
540
- color: #333;
541
552
  text-align: left;
542
553
  overflow: hidden;
543
554
  text-overflow: ellipsis;
@@ -571,7 +582,6 @@ defineExpose({
571
582
  flex-direction: column;
572
583
  height: 75vh; // 固定高度
573
584
  max-height: 80vh; // 最大高度
574
- background-color: #fff;
575
585
  overflow: hidden; // 防止内容溢出
576
586
  }
577
587
 
@@ -36,6 +36,17 @@ const isDark = computed({
36
36
  toggleTheme()
37
37
  },
38
38
  })
39
+
40
+ // Cell / CellGroup 暗黑内联样式
41
+ const settingsCellStyle = computed(() => ({
42
+ backgroundColor: isDark.value ? '#161616' : '#fff',
43
+ borderBottom: isDark.value ? '1px solid rgba(255,255,255,0.04)' : 'none',
44
+ }))
45
+
46
+ const settingsGroupStyle = computed(() => ({
47
+ backgroundColor: isDark.value ? '#111111' : 'transparent',
48
+ borderRadius: isDark.value ? '10px' : '0',
49
+ }))
39
50
  // 处理主题色选择
40
51
  function handleThemeColorSelect(option: ThemeColorOption) {
41
52
  selectThemeColor(option)
@@ -48,25 +59,31 @@ function handleLanguageSelect(option: LocaleOption) {
48
59
  </script>
49
60
 
50
61
  <template>
51
- <view>
52
- <!-- <view class="color-black">{{ languageStore.t('PC新增') }}</view> -->
62
+ <view class="settings-page" :style="{ backgroundColor: isDark ? '#1B1B1E' : '#F8F9FB' }">
53
63
  <demo-block :title="languageStore.t('系统设置')" transparent>
54
- <wd-cell-group border custom-class="rounded-2! overflow-hidden">
55
- <wd-cell :title="languageStore.t('暗黑模式')">
64
+ <wd-cell-group border custom-class="rounded-2! overflow-hidden" :custom-style="settingsGroupStyle">
65
+ <wd-cell :title="languageStore.t('暗黑模式')" :custom-style="settingsCellStyle">
56
66
  <wd-switch v-model="isDark" size="18px" />
57
67
  </wd-cell>
58
- <wd-cell :title="languageStore.t('选择主题色')" is-link @click="openThemeColorPicker">
68
+ <wd-cell
69
+ :title="languageStore.t('选择主题色')"
70
+ is-link
71
+ @click="openThemeColorPicker"
72
+ :custom-style="settingsCellStyle"
73
+ >
59
74
  <view class="flex items-center justify-end gap-2">
60
- <view
61
- class="h-4 w-4 rounded-full"
62
- :style="{ backgroundColor: currentThemeColor.primary }"
63
- />
64
- <text>{{ currentThemeColor.name }}</text>
75
+ <view class="h-4 w-4 rounded-full" :style="{ backgroundColor: currentThemeColor.primary }" />
76
+ <text :style="{ color: isDark ? '#e8e8e8' : '#333' }">{{ currentThemeColor.name }}</text>
65
77
  </view>
66
78
  </wd-cell>
67
- <wd-cell :title="languageStore.t('选择语言')" is-link @click="openLanguagePicker">
79
+ <wd-cell
80
+ :title="languageStore.t('选择语言')"
81
+ is-link
82
+ @click="openLanguagePicker"
83
+ :custom-style="settingsCellStyle"
84
+ >
68
85
  <view class="flex items-center justify-end gap-2">
69
- <text>{{ currentLocale.name }}</text>
86
+ <text :style="{ color: isDark ? '#e8e8e8' : '#333' }">{{ currentLocale.name }}</text>
70
87
  </view>
71
88
  </wd-cell>
72
89
  </wd-cell-group>
@@ -94,12 +111,7 @@ function handleLanguageSelect(option: LocaleOption) {
94
111
  {{ option.name }}
95
112
  </text>
96
113
  </view>
97
- <wd-icon
98
- v-if="currentThemeColor.value === option.value"
99
- name="check"
100
- :color="option.primary"
101
- size="20px"
102
- />
114
+ <wd-icon v-if="currentThemeColor.value === option.value" name="check" :color="option.primary" size="20px" />
103
115
  </view>
104
116
  </view>
105
117
  <wd-gap :height="50" />
@@ -123,12 +135,7 @@ function handleLanguageSelect(option: LocaleOption) {
123
135
  {{ option.name }}
124
136
  </text>
125
137
  </view>
126
- <wd-icon
127
- v-if="currentLocale.value === option.value"
128
- name="check"
129
- :color="primary"
130
- size="20px"
131
- />
138
+ <wd-icon v-if="currentLocale.value === option.value" name="check" :color="primary" size="20px" />
132
139
  </view>
133
140
  </view>
134
141
  <wd-gap :height="50" />
@@ -55,13 +55,22 @@ export default {
55
55
  <wd-config-provider :theme-vars="themeVars" :custom-class="`page-wraper ${theme}`" :theme="theme">
56
56
  <slot />
57
57
  <wd-tabbar
58
- :model-value="activeTabbar.name" bordered safe-area-inset-bottom placeholder fixed custom-class="z-14!"
58
+ :model-value="activeTabbar.name"
59
+ bordered
60
+ safe-area-inset-bottom
61
+ placeholder
62
+ fixed
63
+ custom-class="z-14!"
59
64
  :active-color="currentThemeColor.primary"
60
65
  @change="handleTabbarChange"
61
66
  >
62
67
  <wd-tabbar-item
63
- v-for="(item, index) in tabbarList" :key="index" :name="item.name"
64
- :value="getTabbarItemValue(item.name)" :title="item.title" :icon="item.icon"
68
+ v-for="(item, index) in tabbarList"
69
+ :key="index"
70
+ :name="item.name"
71
+ :value="getTabbarItemValue(item.name)"
72
+ :title="item.title"
73
+ :icon="item.icon"
65
74
  >
66
75
  <!-- 使用 icon 插槽自定义图标 -->
67
76
  <template v-if="item.activeIcon" #icon="{ active }">
@@ -84,11 +93,11 @@ export default {
84
93
  .page-wraper {
85
94
  min-height: calc(100vh - var(--window-top));
86
95
  box-sizing: border-box;
87
- background: #F8F9FB;
96
+ background: #f8f9fb;
88
97
  }
89
98
 
90
99
  .wot-theme-dark.page-wraper {
91
- background: #222;
100
+ background: #1b1b1e;
92
101
  }
93
102
  .custom-icon {
94
103
  width: 52rpx;
@@ -25,9 +25,7 @@ const props = defineProps({
25
25
  },
26
26
  })
27
27
  const emit = defineEmits(['addBranch', 'addLeaf', 'remove', 'update', 'toggleExpand'])
28
- const {
29
- currentThemeColor,
30
- } = useManualTheme()
28
+ const { currentThemeColor } = useManualTheme()
31
29
  interface TreeNode {
32
30
  id: string
33
31
  label: string
@@ -45,8 +43,7 @@ const hasChildren = computed(() => {
45
43
 
46
44
  // 计算是否需要高亮
47
45
  const isHighlight = computed(() => {
48
- if (!props.searchKeyword)
49
- return false
46
+ if (!props.searchKeyword) return false
50
47
  return props.node.label.toLowerCase().includes(props.searchKeyword.toLowerCase())
51
48
  })
52
49
 
@@ -92,20 +89,32 @@ function emitUpdate(e: TreeNode) {
92
89
  <template>
93
90
  <view class="tree-node">
94
91
  <!-- 节点内容行 -->
95
- <view class="node-content bg-#fff .dark:bg-#222222" :style="{ paddingLeft: `${level * 30}rpx` }">
92
+ <view class="node-content bg-white dark:bg-[#1B1B1E]" :style="{ paddingLeft: `${level * 30}rpx` }">
96
93
  <!-- 展开/收起图标 -->
97
- <view class="icon-area" @click.stop="() => { toggleExpand() }">
94
+ <view
95
+ class="icon-area"
96
+ @click.stop="
97
+ () => {
98
+ toggleExpand()
99
+ }
100
+ "
101
+ >
98
102
  <text v-if="node.type !== 'leaf'" class="arrow" :class="{ rotated: node.expanded }">
99
103
  <wd-loading v-if="node.loading" size="16" />
100
104
  <wd-icon v-else name="arrow-right" size="18px" />
101
105
  </text>
102
- <text v-else class="dot .dark:color-#fff">
103
-
104
- </text>
106
+ <text v-else class="dot dark:text-white">•</text>
105
107
  </view>
106
108
 
107
109
  <!-- 节点名称 (支持搜索高亮) -->
108
- <view class="label-area color-#333 .dark:color-#fff" @click.stop="() => { toggleExpand() }">
110
+ <view
111
+ class="label-area text-gray-800 dark:text-white"
112
+ @click.stop="
113
+ () => {
114
+ toggleExpand()
115
+ }
116
+ "
117
+ >
109
118
  <text :class="{ highlight: isHighlight }">
110
119
  {{ node.label }}
111
120
  </text>
@@ -113,34 +122,46 @@ function emitUpdate(e: TreeNode) {
113
122
 
114
123
  <!-- 操作按钮区域 -->
115
124
  <view class="action-area">
116
- <view v-if="(node.type === 'branch' || node.type === 'root') && leafRatmplId" class="btn" :style="{ backgroundColor: desaturateColor(currentThemeColor.primary) }" @click.stop="onAddLeaf">
117
- <text
118
- :style="{ color: currentThemeColor.primary }"
119
- >
120
- +
121
- </text>
125
+ <view
126
+ v-if="(node.type === 'branch' || node.type === 'root') && leafRatmplId"
127
+ class="btn"
128
+ :style="{ backgroundColor: desaturateColor(currentThemeColor.primary) }"
129
+ @click.stop="onAddLeaf"
130
+ >
131
+ <text :style="{ color: currentThemeColor.primary }">+</text>
122
132
  </view>
123
- <view v-if="node.type === 'branch' || node.type === 'root'" class="btn" :style="{ backgroundColor: desaturateColor(currentThemeColor.primary) }" @click.stop="onAddBranch">
124
- <text
125
- class="i-carbon:decision-tree text-3"
126
- :style="{ color: currentThemeColor.primary }"
127
- />
133
+ <view
134
+ v-if="node.type === 'branch' || node.type === 'root'"
135
+ class="btn"
136
+ :style="{ backgroundColor: desaturateColor(currentThemeColor.primary) }"
137
+ @click.stop="onAddBranch"
138
+ >
139
+ <text class="i-carbon:decision-tree text-3" :style="{ color: currentThemeColor.primary }" />
128
140
  </view>
129
141
  <wd-icon
130
- class="btn" name="edit" size="28rpx"
131
- :style="{ backgroundColor: desaturateColor(currentThemeColor.primary), color: currentThemeColor.primary }" @click.stop="handleEdit"
142
+ class="btn"
143
+ name="edit"
144
+ size="28rpx"
145
+ :style="{ backgroundColor: desaturateColor(currentThemeColor.primary), color: currentThemeColor.primary }"
146
+ @click.stop="handleEdit"
132
147
  />
133
- <text class="btn del" @click.stop="onRemove">
134
-
135
- </text>
148
+ <text class="btn del" @click.stop="onRemove">-</text>
136
149
  </view>
137
150
  </view>
138
151
 
139
152
  <!-- 递归渲染子节点 -->
140
153
  <view v-if="hasChildren && node.expanded" class="children-container">
141
154
  <tree-item
142
- v-for="child in node.children" :key="child.id" :node="child" :level="level + 1" :leaf-ratmpl-id="props.leafRatmplId"
143
- :search-keyword="searchKeyword" @add-leaf="emitAddLeaf" @add-branch="emitAddBranch" @remove="emitRemove" @update="emitUpdate"
155
+ v-for="child in node.children"
156
+ :key="child.id"
157
+ :node="child"
158
+ :level="level + 1"
159
+ :leaf-ratmpl-id="props.leafRatmplId"
160
+ :search-keyword="searchKeyword"
161
+ @add-leaf="emitAddLeaf"
162
+ @add-branch="emitAddBranch"
163
+ @remove="emitRemove"
164
+ @update="emitUpdate"
144
165
  @toggle-expand="toggleExpand"
145
166
  />
146
167
  </view>
@@ -179,7 +200,7 @@ function emitUpdate(e: TreeNode) {
179
200
  }
180
201
 
181
202
  .dot {
182
- font-size:60rpx;
203
+ font-size: 60rpx;
183
204
  color: #ddd;
184
205
  }
185
206