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.
- package/components/TActionSheet/index.uvue +94 -54
- package/components/TActionSheet/type.uts +13 -13
- package/components/TAvatar/index.uvue +87 -46
- package/components/TAvatar/type.uts +16 -10
- package/components/TBadge/index.uvue +73 -64
- package/components/TBadge/type.uts +2 -2
- package/components/TButton/index.uvue +19 -12
- package/components/TButton/type.uts +1 -1
- package/components/TCard/index.uvue +69 -50
- package/components/TCell/index.uvue +10 -0
- package/components/TCell/type.uts +1 -1
- package/components/TCheckbox/index.uvue +37 -14
- package/components/TCheckbox/type.uts +2 -2
- package/components/TCheckboxGroup/index.uvue +64 -39
- package/components/TCheckboxGroup/type.uts +2 -2
- package/components/TCol/index.uvue +6 -6
- package/components/TCol/type.uts +1 -1
- package/components/TCollapse/index.uvue +16 -16
- package/components/TCollapseItem/index.uvue +12 -12
- package/components/TDateTimePicker/index.uvue +281 -137
- package/components/TDateTimePicker/type.uts +26 -8
- package/components/TDialog/index.uvue +87 -39
- package/components/TDivider/index.uvue +21 -17
- package/components/TDivider/type.uts +1 -1
- package/components/TEmpty/index.uvue +41 -25
- package/components/TEmpty/type.uts +1 -1
- package/components/TErrorState/index.uvue +4 -4
- package/components/TErrorState/type.uts +1 -1
- package/components/TForm/index.uvue +374 -157
- package/components/TForm/type.uts +9 -9
- package/components/TGrid/index.uvue +65 -18
- package/components/TGrid/type.uts +1 -1
- package/components/TGridItem/index.uvue +94 -39
- package/components/TGridItem/type.uts +1 -1
- package/components/TIcon/index.uvue +15 -15
- package/components/TIcon/type.uts +9 -3
- package/components/TImage/index.uvue +58 -43
- package/components/TImage/type.uts +19 -14
- package/components/TInput/index.uvue +85 -36
- package/components/TInput/type.uts +1 -1
- package/components/TList/index.uvue +8 -4
- package/components/TListItem/index.uvue +58 -38
- package/components/TLoading/index.uvue +12 -5
- package/components/TNavBar/index.uvue +31 -9
- package/components/TNavBar/type.uts +1 -1
- package/components/TNoticeBar/index.uvue +30 -22
- package/components/TNoticeBar/type.uts +2 -2
- package/components/TNumberInput/index.uvue +105 -62
- package/components/TNumberInput/type.uts +1 -1
- package/components/TPicker/index.uvue +98 -64
- package/components/TPicker/type.uts +33 -30
- package/components/TPopup/index.uvue +140 -81
- package/components/TPopup/type.uts +7 -1
- package/components/TProgress/index.uvue +37 -34
- package/components/TProgress/type.uts +1 -1
- package/components/TRadioButton/index.uvue +87 -40
- package/components/TRadioButton/type.uts +4 -3
- package/components/TRadioGroup/index.uvue +48 -42
- package/components/TRadioGroup/type.uts +7 -7
- package/components/TRate/index.uvue +89 -78
- package/components/TRate/type.uts +1 -1
- package/components/TRow/index.uvue +6 -6
- package/components/TRow/type.uts +1 -1
- package/components/TSearchBar/index.uvue +92 -60
- package/components/TSearchBar/type.uts +18 -17
- package/components/TSelect/index.uvue +573 -323
- package/components/TSelect/type.uts +4 -4
- package/components/TSlider/index.uvue +26 -7
- package/components/TSlider/type.uts +1 -1
- package/components/TSwiper/index.uvue +25 -20
- package/components/TSwitch/index.uvue +46 -22
- package/components/TText/README.md +7 -7
- package/components/TText/index.uvue +97 -81
- package/components/TText/type.uts +6 -6
- package/components/TTextarea/index.uvue +53 -33
- package/components/TTextarea/type.uts +11 -11
- package/components/Tabs/README.md +4 -4
- package/components/Tabs/index.uvue +136 -100
- package/components/Tabs/type.uts +4 -4
- package/components/Tags/README.md +4 -4
- package/components/Tags/index.uvue +179 -137
- package/components/Tags/type.uts +3 -3
- package/composables/i18n/manager.uts +97 -103
- package/composables/i18n/types.uts +6 -10
- package/composables/useI18n.uts +79 -72
- package/composables/useModal.uts +23 -7
- package/composables/useTheme.uts +252 -303
- package/composables/useToast.uts +169 -151
- package/index.uts +1 -2
- package/locales/en-US/actionSheet.json +2 -2
- package/locales/en-US/common.json +16 -16
- package/locales/en-US/dialog.json +4 -4
- package/locales/en-US/empty.json +5 -5
- package/locales/en-US/errorState.json +4 -4
- package/locales/en-US/examplePages.json +15 -12
- package/locales/en-US/examples.json +222 -222
- package/locales/en-US/form.json +20 -20
- package/locales/en-US/input.json +2 -2
- package/locales/en-US/list.json +4 -4
- package/locales/en-US/loading.json +2 -2
- package/locales/en-US/navBar.json +3 -3
- package/locales/en-US/noticeBar.json +2 -2
- package/locales/en-US/picker.json +4 -4
- package/locales/en-US/searchBar.json +3 -3
- package/locales/en-US/textarea.json +2 -2
- package/locales/en-US/toast.json +5 -5
- package/locales/index.uts +75 -76
- package/locales/loader.uts +255 -258
- package/locales/zh-CN/actionSheet.json +2 -2
- package/locales/zh-CN/common.json +16 -16
- package/locales/zh-CN/dialog.json +4 -4
- package/locales/zh-CN/empty.json +5 -5
- package/locales/zh-CN/errorState.json +4 -4
- package/locales/zh-CN/examplePages.json +15 -12
- package/locales/zh-CN/examples.json +222 -222
- package/locales/zh-CN/form.json +20 -20
- package/locales/zh-CN/input.json +2 -2
- package/locales/zh-CN/list.json +4 -4
- package/locales/zh-CN/loading.json +2 -2
- package/locales/zh-CN/navBar.json +3 -3
- package/locales/zh-CN/noticeBar.json +2 -2
- package/locales/zh-CN/picker.json +4 -4
- package/locales/zh-CN/searchBar.json +3 -3
- package/locales/zh-CN/textarea.json +2 -2
- package/locales/zh-CN/toast.json +5 -5
- package/locales/zh-TW/actionSheet.json +2 -2
- package/locales/zh-TW/common.json +14 -14
- package/locales/zh-TW/dialog.json +4 -4
- package/locales/zh-TW/empty.json +5 -5
- package/locales/zh-TW/errorState.json +4 -4
- package/locales/zh-TW/examplePages.json +700 -698
- package/locales/zh-TW/examples.json +222 -222
- package/locales/zh-TW/form.json +17 -17
- package/locales/zh-TW/input.json +2 -2
- package/locales/zh-TW/list.json +4 -4
- package/locales/zh-TW/loading.json +2 -2
- package/locales/zh-TW/navBar.json +3 -3
- package/locales/zh-TW/noticeBar.json +2 -2
- package/locales/zh-TW/picker.json +4 -4
- package/locales/zh-TW/searchBar.json +3 -3
- package/locales/zh-TW/textarea.json +2 -2
- package/locales/zh-TW/toast.json +5 -5
- package/package.json +72 -40
- package/static/logo.png +0 -0
- package/static/tailwind.css +752 -1550
- package/static/theme.scss +35 -197
- package/types/index.uts +19 -6
- package/uni.scss +0 -2
- package/utils/color.uts +0 -92
- package/utils/common.uts +0 -245
- package/utils/dom.uts +0 -275
- package/utils/index.uts +0 -11
- package/utils/request/index.uts +0 -375
- package/utils/request/type.uts +0 -87
- package/utils/validator.uts +0 -155
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
<script setup lang="uts">
|
|
2
|
-
import { computed } from 'vue'
|
|
3
|
-
import
|
|
4
|
-
import
|
|
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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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 (
|
|
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="
|
|
79
|
-
<text v-if="
|
|
80
|
-
<text v-if="
|
|
81
|
-
</view>
|
|
82
|
-
|
|
83
|
-
<!-- 操作列表 -->
|
|
84
|
-
<view class="t-action-sheet__actions max-h-
|
|
85
|
-
<view
|
|
86
|
-
v-for="(action, index) in actions"
|
|
87
|
-
:key="index"
|
|
88
|
-
class="
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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-
|
|
106
|
-
<text class="t-action-sheet__cancel-text text-base 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
|
|
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
|
|
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
|
|
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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
|
|
35
|
-
|
|
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
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
|
52
|
-
|
|
53
|
-
if (props.shape
|
|
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 (!
|
|
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 (
|
|
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="
|
|
121
|
-
class="t-avatar__image h-full w-full"
|
|
122
|
-
:src="
|
|
123
|
-
:mode="fit"
|
|
124
|
-
@error="
|
|
125
|
-
/>
|
|
126
|
-
<text v-else-if="
|
|
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 "
|
|
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: ()
|
|
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
|
|
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-
|
|
44
|
-
]
|
|
45
|
-
|
|
46
|
-
if (props.isDot) {
|
|
47
|
-
classes.push('h-2 w-2 rounded-full p-0')
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
case '
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
default:
|
|
64
|
-
|
|
65
|
-
|
|
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
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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
|
|
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="
|
|
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>
|