tang-ui-x 1.3.3 → 1.3.5

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 (170) hide show
  1. package/components/TActionSheet/index.uvue +80 -56
  2. package/components/TActionSheet/type.uts +13 -13
  3. package/components/TAvatar/index.uvue +60 -33
  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 +31 -12
  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 +282 -145
  21. package/components/TDateTimePicker/type.uts +26 -8
  22. package/components/TDialog/index.uvue +86 -50
  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 +420 -243
  30. package/components/TForm/type.uts +3 -3
  31. package/components/TGrid/index.uvue +65 -18
  32. package/components/TGrid/type.uts +1 -1
  33. package/components/TGridItem/index.uvue +108 -77
  34. package/components/TGridItem/type.uts +1 -1
  35. package/components/TIcon/index.uvue +6 -6
  36. package/components/TIcon/type.uts +9 -3
  37. package/components/TImage/index.uvue +69 -58
  38. package/components/TImage/type.uts +19 -14
  39. package/components/TInput/index.uvue +127 -106
  40. package/components/TInput/type.uts +1 -1
  41. package/components/TList/index.uvue +3 -3
  42. package/components/TListItem/index.uvue +31 -31
  43. package/components/TLoading/index.uvue +16 -13
  44. package/components/TNavBar/index.uvue +22 -10
  45. package/components/TNavBar/type.uts +1 -1
  46. package/components/TNoticeBar/index.uvue +33 -33
  47. package/components/TNoticeBar/type.uts +2 -2
  48. package/components/TNumberInput/index.uvue +106 -72
  49. package/components/TNumberInput/type.uts +1 -1
  50. package/components/TPicker/index.uvue +101 -72
  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 +73 -43
  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 +86 -82
  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 +574 -340
  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 +61 -53
  76. package/components/TTextarea/type.uts +11 -11
  77. package/components/Tabs/README.md +4 -4
  78. package/components/Tabs/index.uvue +125 -101
  79. package/components/Tabs/type.uts +4 -4
  80. package/components/Tags/README.md +4 -4
  81. package/components/Tags/index.uvue +163 -133
  82. package/components/Tags/type.uts +3 -3
  83. package/composables/i18n/manager.uts +97 -103
  84. package/composables/i18n/types.uts +5 -5
  85. package/composables/useI18n.uts +78 -71
  86. package/composables/useModal.uts +21 -5
  87. package/composables/useTheme.uts +264 -296
  88. package/composables/useToast.uts +165 -147
  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 +227 -217
  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 +227 -217
  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 +227 -217
  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 +47 -15
  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/functions/index.uts +1 -0
  150. package/utils/functions/modules/clipboard.uts +113 -0
  151. package/utils/functions/modules/date.uts +13 -0
  152. package/utils/functions/modules/function.uts +42 -0
  153. package/utils/functions/modules/index.uts +10 -0
  154. package/utils/functions/modules/number.uts +44 -0
  155. package/utils/functions/modules/object.uts +74 -0
  156. package/utils/functions/modules/storage.uts +91 -0
  157. package/utils/functions/modules/string.uts +38 -0
  158. package/utils/functions/modules/type.uts +47 -0
  159. package/utils/functions/modules/upload.uts +130 -0
  160. package/utils/functions/modules/validate.uts +461 -0
  161. package/utils/request/index.uts +198 -179
  162. package/utils/request/type.uts +46 -26
  163. package/utils/storage/config.uts +233 -0
  164. package/utils/storage/index.uts +602 -0
  165. package/utils/storage/types.uts +119 -0
  166. package/utils/color.uts +0 -92
  167. package/utils/common.uts +0 -245
  168. package/utils/dom.uts +0 -275
  169. package/utils/index.uts +0 -11
  170. 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]
@@ -34,39 +43,58 @@ const emit = defineEmits<{
34
43
  // 使用 i18n
35
44
  const { $t } = useI18n()
36
45
 
37
- const hasTextValue = (value: string | null | undefined): boolean => {
38
- return value !== undefined && value !== null && value !== ''
46
+ const hasTextValue = (value: string | null): boolean => {
47
+ return value !== null && value !== ''
39
48
  }
40
49
 
41
- const hasTitle = computed(() => {
50
+ const hasTitle = computed((): boolean => {
42
51
  return hasTextValue(props.title)
43
52
  })
44
53
 
45
- const hasDescription = computed(() => {
54
+ const hasDescription = computed((): boolean => {
46
55
  return hasTextValue(props.description)
47
56
  })
48
57
 
49
- const showHeader = computed(() => {
58
+ const showHeader = computed((): boolean => {
50
59
  return hasTitle.value || hasDescription.value
51
60
  })
52
-
53
- // 优先使用用户传入的值,否则使用翻译
54
- const displayCancelText = computed(() => {
55
- // 如果用户明确传入了 cancelText(即使是空字符串),使用用户的值
56
- // 否则使用翻译
57
- return props.cancelText !== undefined && props.cancelText !== ''
58
- ? props.cancelText
59
- : $t('actionSheet.cancelText')
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
+ }
61
89
 
62
90
  const handleSelect = (action: ActionSheetAction, index: number): void => {
63
- if (action.disabled || action.loading) return
64
-
65
- emit('select', action, index)
66
- if (props.closeOnClickAction) {
67
- visible.value = false
68
- }
69
- }
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
+ }
70
98
 
71
99
  const handleCancel = (): void => {
72
100
  emit('cancel')
@@ -91,36 +119,32 @@ const handleClose = (): void => {
91
119
  >
92
120
  <view class="t-action-sheet bg-transparent p-0" :class="customClass" :style="customStyle">
93
121
  <!-- 头部:标题和描述 -->
94
- <view v-if="showHeader" class="t-action-sheet__header border-b border-[#ebedf0] p-4 text-center">
95
- <text v-if="hasTitle" class="t-action-sheet__title mb-2 block text-base font-medium text-[#323233]">{{ title }}</text>
96
- <text v-if="hasDescription" class="t-action-sheet__description block text-sm text-[#969799]">{{ description }}</text>
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>
97
125
  </view>
98
-
99
- <!-- 操作列表 -->
100
- <view class="t-action-sheet__actions max-h-[400px] overflow-y-auto">
101
- <view
102
- v-for="(action, index) in actions"
103
- :key="index"
104
- class="t-action-sheet__action flex items-center justify-center border-b border-[#ebedf0] p-4 text-center active:bg-[#f5f5f5]"
105
- :class="{
106
- 'opacity-50 cursor-not-allowed': action.disabled,
107
- 'opacity-50': action.loading
108
- }"
109
- @click="() => handleSelect(action, index)"
110
- >
111
- <text
112
- class="t-action-sheet__action-text text-base text-[#323233]"
113
- :style="action.color ? `color: ${action.color}` : ''"
114
- >
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
+ >
115
139
  {{ action.name }}
116
140
  </text>
117
141
  </view>
118
142
  </view>
119
-
120
- <!-- 取消按钮 -->
121
- <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">
122
- <text class="t-action-sheet__cancel-text text-base text-[#323233]">{{ displayCancelText }}</text>
123
- </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>
124
148
  </view>
125
149
  </TPopup>
126
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,48 +24,62 @@ const emit = defineEmits<{
23
24
  click: []
24
25
  error: []
25
26
  }>()
26
-
27
+
27
28
  // 图片加载失败标记
28
29
  const hasLoadError = ref(false)
30
+ const hasErrorImageLoadError = ref(false)
29
31
 
30
- const hasTextValue = (value: string | null | undefined): boolean => {
31
- return value !== undefined && value !== null && value !== ''
32
+ const hasTextValue = (value: string | null): boolean => {
33
+ return value !== null && value !== ''
32
34
  }
33
35
 
34
36
  const hasSrc = computed(() => {
35
37
  return hasTextValue(props.src)
36
38
  })
37
39
 
40
+ const hasErrorImage = computed(() => {
41
+ return hasTextValue(props.errorImage)
42
+ })
43
+
38
44
  const hasAlt = computed(() => {
39
45
  return hasTextValue(props.alt)
40
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
+ })
41
61
 
42
62
  /**
43
63
  * 计算头像大小
44
64
  */
45
- const avatarSize = computed(() => {
46
- if (typeof props.size === 'number') {
47
- return props.size
48
- }
49
-
50
- const sizeMap = {
51
- small: 32,
52
- medium: 40,
53
- large: 56
65
+ const avatarSize = computed((): number => {
66
+ const size = props.size
67
+ if (typeof size === 'number') {
68
+ return size as number
54
69
  }
55
-
56
- if (props.size === 'small') return sizeMap.small
57
- if (props.size === 'large') return sizeMap.large
58
- return sizeMap.medium
70
+
71
+ if (size == 'small') return 32
72
+ if (size == 'large') return 56
73
+ return 40
59
74
  })
60
75
 
61
76
  /**
62
77
  * 计算头像样式类
63
78
  */
64
- const avatarClass = computed(() => {
65
- const classes: string[] = ['t-avatar inline-flex items-center justify-center overflow-hidden relative cursor-pointer']
66
-
67
- 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') {
68
83
  classes.push('rounded')
69
84
  } else {
70
85
  classes.push('rounded-full')
@@ -83,7 +98,7 @@ const avatarStyle = computed(() => {
83
98
  styles.push(`width: ${size}px`)
84
99
  styles.push(`height: ${size}px`)
85
100
 
86
- if (!hasSrc.value || hasLoadError.value) {
101
+ if (!hasDisplaySrc.value) {
87
102
  styles.push(`background-color: ${props.bgColor}`)
88
103
  }
89
104
 
@@ -112,10 +127,22 @@ const handleClick = (): void => {
112
127
  /**
113
128
  * 处理图片加载失败
114
129
  */
115
- const handleError = (): void => {
116
- hasLoadError.value = true
117
- emit('error')
118
- }
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
+ }
119
146
 
120
147
  /**
121
148
  * 获取显示的文字(取首字符)
@@ -131,11 +158,11 @@ const displayText = computed(() => {
131
158
  <template>
132
159
  <view :class="avatarClass" :style="avatarStyle" @click="handleClick">
133
160
  <image
134
- v-if="hasSrc && !hasLoadError"
161
+ v-if="hasDisplaySrc"
135
162
  class="t-avatar__image h-full w-full"
136
- :src="src"
163
+ :src="displaySrc"
137
164
  :mode="fit"
138
- @error="handleError"
165
+ @error="handleImageError"
139
166
  />
140
167
  <text v-else-if="hasAlt" class="t-avatar__text text-center font-medium" :style="textStyle">
141
168
  {{ displayText }}
@@ -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
+ }
@@ -51,7 +51,7 @@ const buttonClasses = computed((): string => {
51
51
 
52
52
  switch (props.shape) {
53
53
  case 'round':
54
- classes.push('rounded-[999px]')
54
+ classes.push('rounded-full')
55
55
  break
56
56
  case 'circle':
57
57
  classes.push('rounded-full p-0')
@@ -87,40 +87,40 @@ const buttonClasses = computed((): string => {
87
87
  case 'primary':
88
88
  classes.push(
89
89
  props.plain
90
- ? 'border-[#b3d8ff] bg-[#ecf5ff] text-[#409eff]'
91
- : 'border-[#409eff] bg-[#409eff] text-white'
90
+ ? 'border-blue-200 bg-blue-50 text-blue-500'
91
+ : 'border-blue-500 bg-blue-500 text-white'
92
92
  )
93
93
  break
94
94
  case 'success':
95
95
  classes.push(
96
96
  props.plain
97
- ? 'border-[#c2e7b0] bg-[#f0f9ff] text-[#67c23a]'
98
- : 'border-[#67c23a] bg-[#67c23a] text-white'
97
+ ? 'border-green-200 bg-green-50 text-green-500'
98
+ : 'border-green-500 bg-green-500 text-white'
99
99
  )
100
100
  break
101
101
  case 'warning':
102
102
  classes.push(
103
103
  props.plain
104
- ? 'border-[#f5dab1] bg-[#fdf6ec] text-[#e6a23c]'
105
- : 'border-[#e6a23c] bg-[#e6a23c] text-white'
104
+ ? 'border-orange-200 bg-orange-50 text-orange-400'
105
+ : 'border-orange-400 bg-orange-400 text-white'
106
106
  )
107
107
  break
108
108
  case 'danger':
109
109
  classes.push(
110
110
  props.plain
111
- ? 'border-[#fbc4c4] bg-[#fef0f0] text-[#f56c6c]'
112
- : 'border-[#f56c6c] bg-[#f56c6c] text-white'
111
+ ? 'border-red-200 bg-red-50 text-red-400'
112
+ : 'border-red-400 bg-red-400 text-white'
113
113
  )
114
114
  break
115
115
  case 'info':
116
116
  classes.push(
117
117
  props.plain
118
- ? 'border-[#d3d4d6] bg-[#f4f4f5] text-[#909399]'
119
- : 'border-[#909399] bg-[#909399] text-white'
118
+ ? 'border-zinc-300 bg-zinc-100 text-zinc-400'
119
+ : 'border-zinc-400 bg-zinc-400 text-white'
120
120
  )
121
121
  break
122
122
  default:
123
- classes.push('border-[#dcdfe6] bg-white text-[#606266]')
123
+ classes.push('border-gray-300 bg-white text-gray-600')
124
124
  break
125
125
  }
126
126
 
@@ -185,3 +185,10 @@ const handleClick = () => {
185
185
  </view>
186
186
  </button>
187
187
  </template>
188
+
189
+ <style>
190
+ .transition-all {
191
+ transition-property: all;
192
+ transition-duration: 300ms;
193
+ }
194
+ </style>
@@ -20,7 +20,7 @@ export type ButtonShape = 'square' | 'round' | 'circle'
20
20
  /**
21
21
  * 按钮 Props 接口
22
22
  */
23
- export interface TButtonProps {
23
+ export type TButtonProps = {
24
24
  /**
25
25
  * 按钮类型
26
26
  * @default 'default'