2025/2/8第一次更新

This commit is contained in:
爱吃咸鱼小猫咪
2025-02-08 18:50:38 +08:00
commit d7af560866
26519 changed files with 5046029 additions and 0 deletions
@@ -0,0 +1,119 @@
import { computed } from 'vue'
import {
useComponentColor,
useComponentSize,
useNamespace,
} from '../../../../hooks'
import { formatDomSizeValue } from '../../../../utils'
import { useAvatarProps } from './use-avatar-props'
import type { CSSProperties, Ref } from 'vue'
import type { AvatarProps } from '../avatar'
export const useAvatarCustomStyle = (
props: AvatarProps,
groupIndex: Ref<number>,
avatarWidth: Ref<number>
) => {
const ns = useNamespace('avatar')
const {
type,
size,
shape,
bgColor,
border,
borderColor,
shadow,
shadowColor,
avatarGap,
} = useAvatarProps(props)
// 解析背景颜色
const [bgColorClass, bgColorStyle] = useComponentColor(bgColor, 'bg')
// 解析边框颜色
const [borderColorClass, borderColorStyle] = useComponentColor(
borderColor,
'border'
)
// 解析阴影颜色
const [shadowColorClass] = useComponentColor(shadowColor, 'shadow')
// 解析头像尺寸
const { sizeType } = useComponentSize(size.value)
// 头像动态类
const avatarClass = computed<string>(() => {
const cls: string[] = []
cls.push(ns.b())
// 设置头像颜色类型
if (type.value) cls.push(`tn-type-${type.value}_bg`)
// 设置背景颜色
if (!type.value && bgColorClass.value) cls.push(bgColorClass.value)
// 设置头像尺寸
if (sizeType.value === 'inner') cls.push(ns.m(size.value as string))
// 设置头像形状
if (shape.value) cls.push(ns.m(shape.value))
// 设置边框
if (border.value) {
cls.push('tn-border')
// 设置边框颜色
if (borderColorClass.value) cls.push(borderColorClass.value)
}
// 设置阴影
if (shadow.value) {
cls.push('tn-shadow')
// 设置阴影颜色
if (shadowColorClass.value) cls.push(shadowColorClass.value)
}
return cls.join(' ')
})
// 头像动态样式
const avatarStyle = computed<CSSProperties>(() => {
const style: CSSProperties = {}
// 设置头像尺寸
if (sizeType.value === 'custom') {
style.width = formatDomSizeValue(size.value)
style.height = style.width
}
// 设置背景颜色
if (bgColorStyle.value) style.backgroundColor = bgColorStyle.value
// 设置边框颜色
if (border.value && borderColorStyle.value)
style.borderColor = borderColorStyle.value
// 如果是头像组,设置头像间距
if (groupIndex.value != -1) {
style.zIndex = groupIndex.value + 1
// style.transform = `translateX(calc(${
// (groupAvatarCount.value - groupIndex.value - 1) * 100
// }% * ${avatarGap.value}))`
if (groupIndex.value > 0) {
style.marginLeft = `calc(-${avatarWidth.value * avatarGap.value}px)`
} else {
style.marginLeft = '0px'
}
}
return style
})
return {
ns,
avatarClass,
avatarStyle,
}
}
@@ -0,0 +1,6 @@
export * from './use-avatar-icon-props'
export * from './use-avatar-props'
export * from './avatar-custom'
export * from './use-avatar'
export * from './use-avatar-group'
export * from './use-avatar-badge-props'
@@ -0,0 +1,120 @@
import { computed, inject } from 'vue'
import { avatarGroupContextKey } from '../../../../tokens'
import { isEmptyDoubleVariableInDefault } from '../../../../utils'
import type { AvatarProps } from '../avatar'
import type { BadgeProps } from '../../../badge'
export const useAvatarBadgeProps = (props: AvatarProps) => {
const avatarGroup = inject(avatarGroupContextKey, undefined)
// 徽标最大值
const max = computed<BadgeProps['max']>(() => {
return isEmptyDoubleVariableInDefault(
props?.badgeConfig?.max,
avatarGroup?.badgeConfig?.max
)
})
// 徽标类型
const type = computed<BadgeProps['type']>(() => {
return isEmptyDoubleVariableInDefault(
props?.badgeConfig?.type,
avatarGroup?.badgeConfig?.type,
'primary'
)
})
// 徽标背景颜色
const bgColor = computed<BadgeProps['bgColor']>(() => {
return isEmptyDoubleVariableInDefault(
props?.badgeConfig?.bgColor,
avatarGroup?.badgeConfig?.bgColor
)
})
// 徽标文本颜色
const textColor = computed<BadgeProps['textColor']>(() => {
return isEmptyDoubleVariableInDefault(
props?.badgeConfig?.textColor,
avatarGroup?.badgeConfig?.textColor
)
})
// 徽标字体大小
const fontSize = computed<BadgeProps['fontSize']>(() => {
return isEmptyDoubleVariableInDefault(
props?.badgeConfig?.fontSize,
avatarGroup?.badgeConfig?.fontSize
)
})
// 徽标大小
const size = computed<BadgeProps['size']>(() => {
return isEmptyDoubleVariableInDefault(
props?.badgeConfig?.size,
avatarGroup?.badgeConfig?.size
)
})
// 徽标加粗
const bold = computed<BadgeProps['bold']>(() => {
return isEmptyDoubleVariableInDefault(
props?.badgeConfig?.bold,
avatarGroup?.badgeConfig?.bold,
false
)
})
// 设置点徽标
const dot = computed<BadgeProps['dot']>(() => {
return isEmptyDoubleVariableInDefault(
props?.badgeConfig?.dot,
avatarGroup?.badgeConfig?.dot,
false
)
})
// 设置徽标的位置
const absolutePosition = computed<BadgeProps['absolutePosition']>(() => {
return isEmptyDoubleVariableInDefault(
props?.badgeConfig?.absolutePosition,
avatarGroup?.badgeConfig?.absolutePosition,
{}
)
})
// 设置徽标是否居中
const absoluteCenter = computed<BadgeProps['absoluteCenter']>(() => {
return isEmptyDoubleVariableInDefault(
props?.badgeConfig?.absoluteCenter,
avatarGroup?.badgeConfig?.absoluteCenter,
true
)
})
// 徽标配置
const badgeConfig = computed<BadgeProps>(() => {
return {
value: props.badge,
max: max.value,
type: type.value,
bgColor: bgColor.value,
textColor: textColor.value,
fontSize: fontSize.value,
size: size.value,
bold: bold.value,
customClass: '',
customStyle: {},
dot: dot.value,
absolute: true,
absolutePosition: absolutePosition.value,
absoluteCenter: absoluteCenter.value,
index: '',
}
})
return {
badgeConfig,
}
}
@@ -0,0 +1,36 @@
import { provide, reactive, toRefs } from 'vue'
import { avatarGroupContextKey } from '../../../../tokens'
import { useOrderedChildren } from '../../../../hooks'
import type { SetupContext } from 'vue'
import type { AvatarContext } from '../../../../tokens'
import type { AvatarGroupEmits, AvatarGroupProps } from '../avatar-group'
export const useAvatarGroup = (
props: AvatarGroupProps,
emits: SetupContext<AvatarGroupEmits>['emit']
) => {
const {
children: avatarItems,
addChild: addItem,
removeChild: removeItem,
} = useOrderedChildren<AvatarContext>()
const handleItemClick = (uid: number) => {
// 查找出对应头像的索引
const index = avatarItems.value.findIndex((item) => item.uid === uid)
emits('click', index)
}
provide(
avatarGroupContextKey,
reactive({
...toRefs(props),
avatarItems,
addItem,
removeItem,
handleItemClick,
})
)
}
@@ -0,0 +1,29 @@
import { computed, inject } from 'vue'
import { avatarGroupContextKey } from '../../../../tokens'
import type { AvatarProps } from '../avatar'
export const useAvatarIconConfig = (config: AvatarProps['iconConfig']) => {
const avatarGroup = inject(avatarGroupContextKey, undefined)
// 图标颜色
const iconColor = computed<string>(() => {
return config?.color || avatarGroup?.iconConfig?.color || ''
})
// 图标大小
const iconSize = computed<string | number>(() => {
return config?.size || avatarGroup?.iconConfig?.size || ''
})
// 图标加粗
const iconBold = computed<boolean>(() => {
return config?.bold || avatarGroup?.iconConfig?.bold || false
})
return {
iconColor,
iconSize,
iconBold,
}
}
@@ -0,0 +1,116 @@
import { computed, inject } from 'vue'
import { avatarGroupContextKey } from '../../../../tokens'
import {
isEmptyDoubleVariableInDefault,
isEmptyVariableInDefault,
} from '../../../../utils'
import type { AvatarProps } from '../avatar'
export const useAvatarProps = (props: AvatarProps) => {
const avatarGroup = inject(avatarGroupContextKey, undefined)
// 头像颜色类型
const type = computed<string>(() => {
return isEmptyDoubleVariableInDefault(props?.type, avatarGroup?.type, '')
})
// 头像尺寸
const size = computed<string | number>(() => {
return isEmptyDoubleVariableInDefault(props?.size, avatarGroup?.size, '')
})
// 头像形状
const shape = computed<string>(() => {
return isEmptyDoubleVariableInDefault(
props?.shape,
avatarGroup?.shape,
'circle'
)
})
// 头像图片模式
const imgMode = computed<string>(() => {
return isEmptyDoubleVariableInDefault(
props?.imgMode,
avatarGroup?.imgMode,
'aspectFill'
)
})
// 背景颜色
const bgColor = computed<string>(() => {
return isEmptyDoubleVariableInDefault(
props?.bgColor,
avatarGroup?.bgColor,
'tn-gray-light'
)
})
// 显示边框
const border = computed<boolean>(() => {
return isEmptyDoubleVariableInDefault(
props?.border,
avatarGroup?.border,
false
)
})
// 边框颜色
const borderColor = computed<string>(() => {
return isEmptyDoubleVariableInDefault(
props?.borderColor,
avatarGroup?.borderColor,
''
)
})
// 是否加粗边框
const borderBold = computed<boolean>(() => {
return isEmptyDoubleVariableInDefault(
props?.borderBold,
avatarGroup?.borderBold,
false
)
})
// 显示阴影
const shadow = computed<boolean>(() => {
return isEmptyDoubleVariableInDefault(
props?.shadow,
avatarGroup?.shadow,
false
)
})
// 阴影颜色
const shadowColor = computed<string>(() => {
return isEmptyDoubleVariableInDefault(
props?.shadowColor,
avatarGroup?.shadowColor,
''
)
})
// 头像间的间距
const avatarGap = computed<number>(() => {
let gap = Number(isEmptyVariableInDefault(avatarGroup?.gap, 0))
if (gap < 0) gap = 0
if (gap > 1) gap = 1
return gap
})
return {
type,
size,
shape,
imgMode,
bgColor,
border,
borderColor,
borderBold,
shadow,
shadowColor,
avatarGap,
}
}
@@ -0,0 +1,97 @@
import {
computed,
getCurrentInstance,
inject,
nextTick,
onUnmounted,
ref,
} from 'vue'
import { avatarGroupContextKey } from '../../../../tokens'
import { useSelectorQuery } from '../../../../hooks'
import {
debugWarn,
generateId,
isEmptyVariableInDefault,
} from '../../../../utils'
import type { SetupContext } from 'vue'
import type { AvatarEmits, AvatarProps } from '../avatar'
export const useAvatar = (
props: AvatarProps,
emits: SetupContext<AvatarEmits>['emit']
) => {
const instance = getCurrentInstance()
if (!instance) {
debugWarn('TnAvatarGroup', '请在 setup 中使用 useAvatarGroup')
}
const { uid } = instance!
const avatarGroup = inject(avatarGroupContextKey, undefined)
avatarGroup?.addItem({ uid })
const componentId = `ta-${generateId()}`
const { getSelectorNodeInfo } = useSelectorQuery(instance)
// 头像组头像数量
const groupAvatarCount = computed<number>(() => {
return isEmptyVariableInDefault(avatarGroup?.avatarItems.length, 0)
})
const avatarGroupIndex = ref<number>(-1)
nextTick(() => {
// 获取当前头像的索引
const avatarIndex = avatarGroup?.avatarItems.findIndex(
(item) => item.uid === uid
)
avatarGroupIndex.value = isEmptyVariableInDefault(avatarIndex, -1)
if (!avatarWidth.value && avatarGroupIndex.value !== -1) {
getAvatarWidthNodeInfo()
}
})
// 头像宽度信息
const avatarWidth = ref<number>(0)
// 获取头像的宽度信息
let initCount = 0
const getAvatarWidthNodeInfo = async () => {
try {
const rectInfo = await getSelectorNodeInfo(`#${componentId}`)
if (!rectInfo.width) {
throw new Error('获取头像宽度信息失败')
}
avatarWidth.value = rectInfo.width || 0
} catch (err) {
if (initCount > 10) {
initCount = 0
debugWarn('TnAvatar', `获取头像宽度信息失败:${err}`)
return
}
initCount++
setTimeout(() => {
getAvatarWidthNodeInfo()
}, 150)
}
}
const avatarClick = () => {
avatarGroup?.handleItemClick(uid)
emits('click')
}
onUnmounted(() => {
avatarGroup?.removeItem(uid)
})
return {
componentId,
groupAvatarCount,
avatarGroupIndex,
avatarWidth,
avatarClick,
}
}