tang-ui-x 1.3.2 → 1.3.4

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 (155) hide show
  1. package/components/TActionSheet/index.uvue +94 -54
  2. package/components/TActionSheet/type.uts +13 -13
  3. package/components/TAvatar/index.uvue +87 -46
  4. package/components/TAvatar/type.uts +16 -10
  5. package/components/TBadge/index.uvue +73 -64
  6. package/components/TBadge/type.uts +2 -2
  7. package/components/TButton/index.uvue +19 -12
  8. package/components/TButton/type.uts +1 -1
  9. package/components/TCard/index.uvue +69 -50
  10. package/components/TCell/index.uvue +10 -0
  11. package/components/TCell/type.uts +1 -1
  12. package/components/TCheckbox/index.uvue +37 -14
  13. package/components/TCheckbox/type.uts +2 -2
  14. package/components/TCheckboxGroup/index.uvue +64 -39
  15. package/components/TCheckboxGroup/type.uts +2 -2
  16. package/components/TCol/index.uvue +6 -6
  17. package/components/TCol/type.uts +1 -1
  18. package/components/TCollapse/index.uvue +16 -16
  19. package/components/TCollapseItem/index.uvue +12 -12
  20. package/components/TDateTimePicker/index.uvue +281 -137
  21. package/components/TDateTimePicker/type.uts +26 -8
  22. package/components/TDialog/index.uvue +87 -39
  23. package/components/TDivider/index.uvue +21 -17
  24. package/components/TDivider/type.uts +1 -1
  25. package/components/TEmpty/index.uvue +41 -25
  26. package/components/TEmpty/type.uts +1 -1
  27. package/components/TErrorState/index.uvue +4 -4
  28. package/components/TErrorState/type.uts +1 -1
  29. package/components/TForm/index.uvue +374 -157
  30. package/components/TForm/type.uts +9 -9
  31. package/components/TGrid/index.uvue +65 -18
  32. package/components/TGrid/type.uts +1 -1
  33. package/components/TGridItem/index.uvue +94 -39
  34. package/components/TGridItem/type.uts +1 -1
  35. package/components/TIcon/index.uvue +15 -15
  36. package/components/TIcon/type.uts +9 -3
  37. package/components/TImage/index.uvue +58 -43
  38. package/components/TImage/type.uts +19 -14
  39. package/components/TInput/index.uvue +85 -36
  40. package/components/TInput/type.uts +1 -1
  41. package/components/TList/index.uvue +8 -4
  42. package/components/TListItem/index.uvue +58 -38
  43. package/components/TLoading/index.uvue +12 -5
  44. package/components/TNavBar/index.uvue +31 -9
  45. package/components/TNavBar/type.uts +1 -1
  46. package/components/TNoticeBar/index.uvue +30 -22
  47. package/components/TNoticeBar/type.uts +2 -2
  48. package/components/TNumberInput/index.uvue +105 -62
  49. package/components/TNumberInput/type.uts +1 -1
  50. package/components/TPicker/index.uvue +98 -64
  51. package/components/TPicker/type.uts +33 -30
  52. package/components/TPopup/index.uvue +140 -81
  53. package/components/TPopup/type.uts +7 -1
  54. package/components/TProgress/index.uvue +37 -34
  55. package/components/TProgress/type.uts +1 -1
  56. package/components/TRadioButton/index.uvue +87 -40
  57. package/components/TRadioButton/type.uts +4 -3
  58. package/components/TRadioGroup/index.uvue +48 -42
  59. package/components/TRadioGroup/type.uts +7 -7
  60. package/components/TRate/index.uvue +89 -78
  61. package/components/TRate/type.uts +1 -1
  62. package/components/TRow/index.uvue +6 -6
  63. package/components/TRow/type.uts +1 -1
  64. package/components/TSearchBar/index.uvue +92 -60
  65. package/components/TSearchBar/type.uts +18 -17
  66. package/components/TSelect/index.uvue +573 -323
  67. package/components/TSelect/type.uts +4 -4
  68. package/components/TSlider/index.uvue +26 -7
  69. package/components/TSlider/type.uts +1 -1
  70. package/components/TSwiper/index.uvue +25 -20
  71. package/components/TSwitch/index.uvue +46 -22
  72. package/components/TText/README.md +7 -7
  73. package/components/TText/index.uvue +97 -81
  74. package/components/TText/type.uts +6 -6
  75. package/components/TTextarea/index.uvue +53 -33
  76. package/components/TTextarea/type.uts +11 -11
  77. package/components/Tabs/README.md +4 -4
  78. package/components/Tabs/index.uvue +136 -100
  79. package/components/Tabs/type.uts +4 -4
  80. package/components/Tags/README.md +4 -4
  81. package/components/Tags/index.uvue +179 -137
  82. package/components/Tags/type.uts +3 -3
  83. package/composables/i18n/manager.uts +97 -103
  84. package/composables/i18n/types.uts +6 -10
  85. package/composables/useI18n.uts +79 -72
  86. package/composables/useModal.uts +23 -7
  87. package/composables/useTheme.uts +252 -303
  88. package/composables/useToast.uts +169 -151
  89. package/index.uts +1 -2
  90. package/locales/en-US/actionSheet.json +2 -2
  91. package/locales/en-US/common.json +16 -16
  92. package/locales/en-US/dialog.json +4 -4
  93. package/locales/en-US/empty.json +5 -5
  94. package/locales/en-US/errorState.json +4 -4
  95. package/locales/en-US/examplePages.json +15 -12
  96. package/locales/en-US/examples.json +222 -222
  97. package/locales/en-US/form.json +20 -20
  98. package/locales/en-US/input.json +2 -2
  99. package/locales/en-US/list.json +4 -4
  100. package/locales/en-US/loading.json +2 -2
  101. package/locales/en-US/navBar.json +3 -3
  102. package/locales/en-US/noticeBar.json +2 -2
  103. package/locales/en-US/picker.json +4 -4
  104. package/locales/en-US/searchBar.json +3 -3
  105. package/locales/en-US/textarea.json +2 -2
  106. package/locales/en-US/toast.json +5 -5
  107. package/locales/index.uts +75 -76
  108. package/locales/loader.uts +255 -258
  109. package/locales/zh-CN/actionSheet.json +2 -2
  110. package/locales/zh-CN/common.json +16 -16
  111. package/locales/zh-CN/dialog.json +4 -4
  112. package/locales/zh-CN/empty.json +5 -5
  113. package/locales/zh-CN/errorState.json +4 -4
  114. package/locales/zh-CN/examplePages.json +15 -12
  115. package/locales/zh-CN/examples.json +222 -222
  116. package/locales/zh-CN/form.json +20 -20
  117. package/locales/zh-CN/input.json +2 -2
  118. package/locales/zh-CN/list.json +4 -4
  119. package/locales/zh-CN/loading.json +2 -2
  120. package/locales/zh-CN/navBar.json +3 -3
  121. package/locales/zh-CN/noticeBar.json +2 -2
  122. package/locales/zh-CN/picker.json +4 -4
  123. package/locales/zh-CN/searchBar.json +3 -3
  124. package/locales/zh-CN/textarea.json +2 -2
  125. package/locales/zh-CN/toast.json +5 -5
  126. package/locales/zh-TW/actionSheet.json +2 -2
  127. package/locales/zh-TW/common.json +14 -14
  128. package/locales/zh-TW/dialog.json +4 -4
  129. package/locales/zh-TW/empty.json +5 -5
  130. package/locales/zh-TW/errorState.json +4 -4
  131. package/locales/zh-TW/examplePages.json +700 -698
  132. package/locales/zh-TW/examples.json +222 -222
  133. package/locales/zh-TW/form.json +17 -17
  134. package/locales/zh-TW/input.json +2 -2
  135. package/locales/zh-TW/list.json +4 -4
  136. package/locales/zh-TW/loading.json +2 -2
  137. package/locales/zh-TW/navBar.json +3 -3
  138. package/locales/zh-TW/noticeBar.json +2 -2
  139. package/locales/zh-TW/picker.json +4 -4
  140. package/locales/zh-TW/searchBar.json +3 -3
  141. package/locales/zh-TW/textarea.json +2 -2
  142. package/locales/zh-TW/toast.json +5 -5
  143. package/package.json +72 -40
  144. package/static/logo.png +0 -0
  145. package/static/tailwind.css +752 -1550
  146. package/static/theme.scss +35 -197
  147. package/types/index.uts +19 -6
  148. package/uni.scss +0 -2
  149. package/utils/color.uts +0 -92
  150. package/utils/common.uts +0 -245
  151. package/utils/dom.uts +0 -275
  152. package/utils/index.uts +0 -11
  153. package/utils/request/index.uts +0 -375
  154. package/utils/request/type.uts +0 -87
  155. package/utils/validator.uts +0 -155
@@ -1,7 +1,8 @@
1
- <script setup lang="uts">
2
- import { computed } from 'vue'
3
- import TPopup from '../TPopup/index.uvue'
4
- import type { ActionSheetAction, TActionSheetProps } from './type.uts'
1
+ <script setup lang="uts">
2
+ import { computed } from 'vue'
3
+ import type { Ref } from 'vue'
4
+ import TPopup from '../TPopup/index.uvue'
5
+ import type { ActionSheetAction } from './type.uts'
5
6
  import { useI18n } from '../../composables/useI18n.uts'
6
7
 
7
8
  /**
@@ -9,10 +10,18 @@ import { useI18n } from '../../composables/useI18n.uts'
9
10
  * @description 底部弹出的动作菜单,基于 TPopup 组件实现
10
11
  */
11
12
 
12
- // Props 定义 (从 type.uts 导入,排除 show)
13
- type Props = Omit<TActionSheetProps, 'show'>
14
-
15
- const props = withDefaults(defineProps<Props>(), {
13
+ type ActionSheetViewProps = {
14
+ actions?: ActionSheetAction[]
15
+ title?: string
16
+ description?: string
17
+ cancelText?: string
18
+ closeOnClickAction?: boolean
19
+ closeOnClickOverlay?: boolean
20
+ customClass?: string
21
+ customStyle?: string
22
+ }
23
+
24
+ const props = withDefaults(defineProps<ActionSheetViewProps>(), {
16
25
  actions: () => [] as ActionSheetAction[],
17
26
  title: '',
18
27
  description: '',
@@ -22,8 +31,8 @@ const props = withDefaults(defineProps<Props>(), {
22
31
  customStyle: ''
23
32
  })
24
33
 
25
- // 使用 defineModel 管理显示状态 (v-model)
26
- const visible = defineModel({ default: false })
34
+ // 使用 defineModel 管理显示状态 (v-model)
35
+ const visible = defineModel({ default: false }) as Ref<boolean>
27
36
 
28
37
  const emit = defineEmits<{
29
38
  select: [action: ActionSheetAction, index: number]
@@ -31,26 +40,61 @@ const emit = defineEmits<{
31
40
  close: []
32
41
  }>()
33
42
 
34
- // 使用 i18n
35
- const { $t } = useI18n()
36
-
37
- // 优先使用用户传入的值,否则使用翻译
38
- const displayCancelText = computed(() => {
39
- // 如果用户明确传入了 cancelText(即使是空字符串),使用用户的值
40
- // 否则使用翻译
41
- return props.cancelText !== undefined && props.cancelText !== ''
42
- ? props.cancelText
43
- : $t('actionSheet.cancelText')
44
- })
43
+ // 使用 i18n
44
+ const { $t } = useI18n()
45
+
46
+ const hasTextValue = (value: string | null): boolean => {
47
+ return value !== null && value !== ''
48
+ }
49
+
50
+ const hasTitle = computed((): boolean => {
51
+ return hasTextValue(props.title)
52
+ })
53
+
54
+ const hasDescription = computed((): boolean => {
55
+ return hasTextValue(props.description)
56
+ })
57
+
58
+ const showHeader = computed((): boolean => {
59
+ return hasTitle.value || hasDescription.value
60
+ })
61
+
62
+ // 优先使用用户传入的值,否则使用翻译
63
+ const displayCancelText = computed((): string => {
64
+ // 如果用户明确传入了 cancelText(即使是空字符串),使用用户的值
65
+ // 否则使用翻译
66
+ return props.cancelText !== null && props.cancelText !== ''
67
+ ? props.cancelText as string
68
+ : $t('actionSheet.cancelText', {})
69
+ })
70
+
71
+ const canCloseOnClickAction = computed((): boolean => {
72
+ return props.closeOnClickAction == true
73
+ })
74
+
75
+ const getActionClass = (action: ActionSheetAction): string => {
76
+ let className = 't-action-sheet__action flex items-center justify-center border-b border-border-soft p-4 text-center'
77
+ if (action.disabled == true || action.loading == true) {
78
+ className = className + ' opacity-50'
79
+ }
80
+ return className
81
+ }
82
+
83
+ const getActionTextStyle = (action: ActionSheetAction): string => {
84
+ if (action.color !== null && action.color !== '') {
85
+ return `color: ${action.color}`
86
+ }
87
+ return ''
88
+ }
45
89
 
46
90
  const handleSelect = (action: ActionSheetAction, index: number): void => {
47
- if (action.disabled || action.loading) return
48
-
49
- emit('select', action, index)
50
- if (props.closeOnClickAction) {
51
- visible.value = false
52
- }
53
- }
91
+ if (action.disabled == true || action.loading == true) return
92
+
93
+ emit('select', action, index)
94
+ if (canCloseOnClickAction.value) {
95
+ visible.value = false
96
+ }
97
+ }
54
98
 
55
99
  const handleCancel = (): void => {
56
100
  emit('cancel')
@@ -75,36 +119,32 @@ const handleClose = (): void => {
75
119
  >
76
120
  <view class="t-action-sheet bg-transparent p-0" :class="customClass" :style="customStyle">
77
121
  <!-- 头部:标题和描述 -->
78
- <view v-if="title || description" class="t-action-sheet__header border-b border-[#ebedf0] p-4 text-center">
79
- <text v-if="title" class="t-action-sheet__title mb-2 block text-base font-medium text-[#323233]">{{ title }}</text>
80
- <text v-if="description" class="t-action-sheet__description block text-sm text-[#969799]">{{ description }}</text>
81
- </view>
82
-
83
- <!-- 操作列表 -->
84
- <view class="t-action-sheet__actions max-h-[400px] overflow-y-auto">
85
- <view
86
- v-for="(action, index) in actions"
87
- :key="index"
88
- class="t-action-sheet__action flex items-center justify-center border-b border-[#ebedf0] p-4 text-center active:bg-[#f5f5f5]"
89
- :class="{
90
- 'opacity-50 cursor-not-allowed': action.disabled,
91
- 'opacity-50': action.loading
92
- }"
93
- @click="() => handleSelect(action, index)"
94
- >
95
- <text
96
- class="t-action-sheet__action-text text-base text-[#323233]"
97
- :style="action.color ? `color: ${action.color}` : ''"
98
- >
122
+ <view v-if="showHeader" class="t-action-sheet__header border-b border-border-soft p-4 text-center">
123
+ <text v-if="hasTitle" class="t-action-sheet__title mb-2 text-base font-medium text-title">{{ title }}</text>
124
+ <text v-if="hasDescription" class="t-action-sheet__description text-sm text-desc">{{ description }}</text>
125
+ </view>
126
+
127
+ <!-- 操作列表 -->
128
+ <view class="t-action-sheet__actions max-h-actions overflow-y-auto">
129
+ <view
130
+ v-for="(action, index) in actions"
131
+ :key="index"
132
+ :class="getActionClass(action)"
133
+ @click="handleSelect(action, index)"
134
+ >
135
+ <text
136
+ class="t-action-sheet__action-text text-base text-title"
137
+ :style="getActionTextStyle(action)"
138
+ >
99
139
  {{ action.name }}
100
140
  </text>
101
141
  </view>
102
142
  </view>
103
-
104
- <!-- 取消按钮 -->
105
- <view class="t-action-sheet__cancel flex items-center justify-center border-t-[8px] border-[#f5f5f5] p-4 text-center active:bg-[#f5f5f5]" @click="handleCancel">
106
- <text class="t-action-sheet__cancel-text text-base text-[#323233]">{{ displayCancelText }}</text>
107
- </view>
143
+
144
+ <!-- 取消按钮 -->
145
+ <view class="t-action-sheet__cancel flex items-center justify-center border-t-8 border-action-divider p-4 text-center" @click="handleCancel">
146
+ <text class="t-action-sheet__cancel-text text-base text-title">{{ displayCancelText }}</text>
147
+ </view>
108
148
  </view>
109
149
  </TPopup>
110
150
  </template>
@@ -2,14 +2,14 @@
2
2
  * TActionSheet 组件类型定义
3
3
  */
4
4
 
5
- export interface ActionSheetAction {
6
- name: string
7
- color?: string
8
- disabled?: boolean
9
- loading?: boolean
10
- }
5
+ export type ActionSheetAction = {
6
+ name: string
7
+ color?: string
8
+ disabled?: boolean
9
+ loading?: boolean
10
+ }
11
11
 
12
- export interface TActionSheetProps {
12
+ export type TActionSheetProps = {
13
13
  show?: boolean
14
14
  actions?: ActionSheetAction[]
15
15
  title?: string
@@ -21,9 +21,9 @@ export interface TActionSheetProps {
21
21
  customStyle?: string
22
22
  }
23
23
 
24
- export interface TActionSheetEmits {
25
- 'update:show': (value: boolean) => void
26
- select: (action: ActionSheetAction, index: number) => void
27
- cancel: () => void
28
- close: () => void
29
- }
24
+ export type TActionSheetEmits = {
25
+ 'update:show': (value: boolean) => void
26
+ select: (action: ActionSheetAction, index: number) => void
27
+ cancel: () => void
28
+ close: () => void
29
+ }
@@ -8,11 +8,12 @@ import type { TAvatarProps } from './type.uts'
8
8
  */
9
9
 
10
10
  // 定义 props
11
- const props = withDefaults(defineProps<TAvatarProps>(), {
12
- src: '',
13
- size: 'medium',
14
- shape: 'circle',
15
- alt: '',
11
+ const props = withDefaults(defineProps<TAvatarProps>(), {
12
+ src: '',
13
+ errorImage: '',
14
+ size: 'medium',
15
+ shape: 'circle',
16
+ alt: '',
16
17
  bgColor: 'var(--tui-border-strong)',
17
18
  color: 'var(--tui-text-inverse)',
18
19
  fit: 'cover'
@@ -23,34 +24,62 @@ const emit = defineEmits<{
23
24
  click: []
24
25
  error: []
25
26
  }>()
26
-
27
- // 图片加载失败标记
28
- const hasLoadError = ref(false)
27
+
28
+ // 图片加载失败标记
29
+ const hasLoadError = ref(false)
30
+ const hasErrorImageLoadError = ref(false)
31
+
32
+ const hasTextValue = (value: string | null): boolean => {
33
+ return value !== null && value !== ''
34
+ }
35
+
36
+ const hasSrc = computed(() => {
37
+ return hasTextValue(props.src)
38
+ })
39
+
40
+ const hasErrorImage = computed(() => {
41
+ return hasTextValue(props.errorImage)
42
+ })
43
+
44
+ const hasAlt = computed(() => {
45
+ return hasTextValue(props.alt)
46
+ })
47
+
48
+ const displaySrc = computed((): string => {
49
+ if (hasSrc.value && !hasLoadError.value) {
50
+ return props.src
51
+ }
52
+ if (hasErrorImage.value && !hasErrorImageLoadError.value) {
53
+ return props.errorImage
54
+ }
55
+ return ''
56
+ })
57
+
58
+ const hasDisplaySrc = computed((): boolean => {
59
+ return hasTextValue(displaySrc.value)
60
+ })
29
61
 
30
62
  /**
31
63
  * 计算头像大小
32
64
  */
33
- const avatarSize = computed(() => {
34
- if (typeof props.size === 'number') {
35
- return props.size
36
- }
65
+ const avatarSize = computed((): number => {
66
+ const size = props.size
67
+ if (typeof size === 'number') {
68
+ return size as number
69
+ }
37
70
 
38
- const sizeMap = {
39
- small: 32,
40
- medium: 40,
41
- large: 56
42
- }
43
-
44
- return sizeMap[props.size] || 40
45
- })
71
+ if (size == 'small') return 32
72
+ if (size == 'large') return 56
73
+ return 40
74
+ })
46
75
 
47
76
  /**
48
77
  * 计算头像样式类
49
78
  */
50
- const avatarClass = computed(() => {
51
- const classes: string[] = ['t-avatar inline-flex items-center justify-center overflow-hidden relative cursor-pointer']
52
-
53
- if (props.shape === 'square') {
79
+ const avatarClass = computed((): string => {
80
+ const classes: string[] = ['t-avatar flex items-center justify-center overflow-hidden relative']
81
+
82
+ if (props.shape == 'square') {
54
83
  classes.push('rounded')
55
84
  } else {
56
85
  classes.push('rounded-full')
@@ -69,9 +98,9 @@ const avatarStyle = computed(() => {
69
98
  styles.push(`width: ${size}px`)
70
99
  styles.push(`height: ${size}px`)
71
100
 
72
- if (!props.src || hasLoadError.value) {
73
- styles.push(`background-color: ${props.bgColor}`)
74
- }
101
+ if (!hasDisplaySrc.value) {
102
+ styles.push(`background-color: ${props.bgColor}`)
103
+ }
75
104
 
76
105
  return styles.join('; ')
77
106
  })
@@ -98,34 +127,46 @@ const handleClick = (): void => {
98
127
  /**
99
128
  * 处理图片加载失败
100
129
  */
101
- const handleError = (): void => {
102
- hasLoadError.value = true
103
- emit('error')
104
- }
130
+ const handleError = (): void => {
131
+ hasLoadError.value = true
132
+ emit('error')
133
+ }
134
+
135
+ const handleErrorImageError = (): void => {
136
+ hasErrorImageLoadError.value = true
137
+ }
138
+
139
+ const handleImageError = (): void => {
140
+ if (hasLoadError.value) {
141
+ handleErrorImageError()
142
+ } else {
143
+ handleError()
144
+ }
145
+ }
105
146
 
106
147
  /**
107
148
  * 获取显示的文字(取首字符)
108
149
  */
109
- const displayText = computed(() => {
110
- if (props.alt) {
111
- return props.alt.charAt(0).toUpperCase()
112
- }
113
- return ''
150
+ const displayText = computed(() => {
151
+ if (hasAlt.value) {
152
+ return props.alt.charAt(0).toUpperCase()
153
+ }
154
+ return ''
114
155
  })
115
156
  </script>
116
157
 
117
158
  <template>
118
159
  <view :class="avatarClass" :style="avatarStyle" @click="handleClick">
119
- <image
120
- v-if="src && !hasLoadError"
121
- class="t-avatar__image h-full w-full"
122
- :src="src"
123
- :mode="fit"
124
- @error="handleError"
125
- />
126
- <text v-else-if="alt" class="t-avatar__text text-center font-medium" :style="textStyle">
127
- {{ displayText }}
128
- </text>
160
+ <image
161
+ v-if="hasDisplaySrc"
162
+ class="t-avatar__image h-full w-full"
163
+ :src="displaySrc"
164
+ :mode="fit"
165
+ @error="handleImageError"
166
+ />
167
+ <text v-else-if="hasAlt" class="t-avatar__text text-center font-medium" :style="textStyle">
168
+ {{ displayText }}
169
+ </text>
129
170
  <slot v-else></slot>
130
171
  </view>
131
172
  </template>
@@ -2,15 +2,21 @@
2
2
  * TAvatar 头像组件属性类型定义
3
3
  */
4
4
  export type TAvatarProps = {
5
- /**
6
- * 头像图片地址
7
- */
8
- src?: string
9
-
10
- /**
11
- * 头像大小
12
- * @default "medium"
13
- */
5
+ /**
6
+ * 头像图片地址
7
+ */
8
+ src?: string
9
+
10
+ /**
11
+ * 图片加载失败时显示的兜底图片地址
12
+ * @default ""
13
+ */
14
+ errorImage?: string
15
+
16
+ /**
17
+ * 头像大小
18
+ * @default "medium"
19
+ */
14
20
  size?: 'small' | 'medium' | 'large' | number
15
21
 
16
22
  /**
@@ -51,4 +57,4 @@ export type TAvatarEmits = {
51
57
  * 图片加载失败时触发
52
58
  */
53
59
  error: () => void
54
- }
60
+ }
@@ -16,14 +16,14 @@ const props = withDefaults(defineProps<TBadgeProps>(), {
16
16
  type: 'danger',
17
17
  bgColor: '',
18
18
  color: '',
19
- offset: () => [0, 0] as [number, number]
19
+ offset: () : number[] => [0, 0]
20
20
  })
21
21
 
22
22
  /**
23
23
  * 计算显示的内容
24
24
  */
25
- const displayValue = computed(() => {
26
- if (props.isDot) {
25
+ const displayValue = computed((): string => {
26
+ if (props.isDot == true) {
27
27
  return ''
28
28
  }
29
29
 
@@ -32,82 +32,91 @@ const displayValue = computed(() => {
32
32
  return `${props.max}+`
33
33
  }
34
34
 
35
- return String(val)
35
+ return val !== null ? val.toString() : ''
36
36
  })
37
37
 
38
38
  /**
39
39
  * 计算徽标样式类
40
40
  */
41
- const badgeClass = computed(() => {
42
- const classes: string[] = [
43
- 't-badge__content absolute right-0 -top-3 z-[1] translate-x-1/2 -translate-y-1/2 whitespace-nowrap rounded-[10px] px-1.5 py-0.5 text-xs leading-[1.2]',
44
- ]
45
-
46
- if (props.isDot) {
47
- classes.push('h-2 w-2 rounded-full p-0')
48
- }
49
-
50
- switch (props.type) {
51
- case 'primary':
52
- classes.push('bg-[#409eff] text-white')
53
- break
54
- case 'success':
55
- classes.push('bg-[#67c23a] text-white')
56
- break
57
- case 'warning':
58
- classes.push('bg-[#e6a23c] text-white')
59
- break
60
- case 'info':
61
- classes.push('bg-[#909399] text-white')
62
- break
63
- default:
64
- classes.push('bg-[#f56c6c] text-white')
65
- break
66
- }
67
-
68
- return classes.join(' ')
69
- })
41
+ const badgeClass = computed((): string => {
42
+ const classes: string[] = [
43
+ 't-badge__content absolute right-0 -top-3 z-10 translate-x-1/2 -translate-y-1/2 whitespace-nowrap rounded-lg px-2 py-1 text-xs leading-relaxed',
44
+ ]
45
+
46
+ if (props.isDot == true) {
47
+ classes.push('h-2 w-2 rounded-full p-0')
48
+ }
49
+
50
+ return classes.join(' ')
51
+ })
52
+
53
+ const getTypeBackgroundColor = (): string => {
54
+ switch (props.type) {
55
+ case 'primary':
56
+ return '#3b82f6'
57
+ case 'success':
58
+ return '#22c55e'
59
+ case 'warning':
60
+ return '#fb923c'
61
+ case 'info':
62
+ return '#909399'
63
+ default:
64
+ return '#f87171'
65
+ }
66
+ }
70
67
 
71
68
  /**
72
69
  * 计算徽标样式
73
70
  */
74
- const badgeStyle = computed(() => {
75
- const styles: string[] = []
76
-
77
- if (props.bgColor != '') {
78
- styles.push(`background-color: ${props.bgColor}`)
79
- }
80
-
81
- if (props.color != '') {
82
- styles.push(`color: ${props.color}`)
83
- }
84
-
85
- if (props.offset && props.offset.length === 2) {
86
- const [x, y] = props.offset
87
- if (x !== 0) {
88
- styles.push(`right: ${-x}px`)
89
- }
90
- if (y !== 0) {
91
- styles.push(`top: ${y}px`)
92
- }
93
- }
94
-
95
- return styles.join('; ')
96
- })
71
+ const badgeStyle = computed((): string => {
72
+ const styles: string[] = []
73
+
74
+ if (props.bgColor != '') {
75
+ styles.push(`background-color: ${props.bgColor}`)
76
+ } else {
77
+ styles.push(`background-color: ${getTypeBackgroundColor()}`)
78
+ }
79
+
80
+ if (props.color != '') {
81
+ styles.push(`color: ${props.color}`)
82
+ } else {
83
+ styles.push('color: #ffffff')
84
+ }
85
+
86
+ if (props.offset != null && props.offset.length == 2) {
87
+ const x = props.offset[0] as number
88
+ const y = props.offset[1] as number
89
+ if (x != 0) {
90
+ styles.push(`right: ${-x}px`)
91
+ }
92
+ if (y != 0) {
93
+ styles.push(`top: ${y}px`)
94
+ }
95
+ }
96
+
97
+ return styles.join('; ')
98
+ })
99
+
100
+ const badgeTextStyle = computed((): string => {
101
+ if (props.color != '') {
102
+ return `color: ${props.color}`
103
+ }
104
+ return 'color: #ffffff'
105
+ })
97
106
 
98
107
  /**
99
108
  * 是否显示徽标
100
109
  */
101
- const showBadge = computed(() => {
102
- return !props.hidden && (props.isDot || props.value !== '' && props.value !== 0)
103
- })
110
+ const showBadge = computed((): boolean => {
111
+ return props.hidden != true && (props.isDot == true || (props.value != '' && props.value != 0))
112
+ })
104
113
  </script>
105
114
 
106
115
  <template>
107
116
  <view class="t-badge relative inline-block overflow-visible">
108
117
  <slot></slot>
109
- <view v-if="showBadge" :class="badgeClass" :style="badgeStyle">
110
- <text v-if="!isDot" class="t-badge__text text-xs">{{ displayValue }}</text>
111
- </view>
112
- </view>
113
- </template>
118
+ <view v-if="showBadge" :class="badgeClass" :style="badgeStyle">
119
+ <text v-if="isDot != true" class="t-badge__text text-xs" :style="badgeTextStyle">{{ displayValue }}</text>
120
+ </view>
121
+ </view>
122
+ </template>
@@ -44,5 +44,5 @@ export type TBadgeProps = {
44
44
  /**
45
45
  * 偏移量 [x, y]
46
46
  */
47
- offset?: [number, number]
48
- }
47
+ offset?: number[]
48
+ }