Files
taimed-international-app/uni_modules/wot-design-uni/components/wd-skeleton/wd-skeleton.vue
2025-11-04 12:37:04 +08:00

120 lines
3.1 KiB
Vue

<!--
* @Author: weisheng
* @Date: 2024-03-15 11:36:12
* @LastEditTime: 2024-04-01 20:24:22
* @LastEditors: weisheng
* @Description:
* @FilePath: /wot-design-uni/src/uni_modules/wot-design-uni/components/wd-skeleton/wd-skeleton.vue
* 记得注释
-->
<template>
<view :class="`wd-skeleton ${customClass}`" :style="customStyle">
<view class="wd-skeleton__content" v-if="show">
<view class="wd-skeleton__row" v-for="(row, index) of parsedRowCols" :key="`row-${index}`">
<view v-for="(col, idx) of row" :key="`col-${idx}`" :class="col.class" :style="col.style" />
</view>
</view>
<view v-else>
<slot />
</view>
</view>
</template>
<script lang="ts">
export default {
// #ifdef H5
name: 'wd-skeleton',
// #endif
options: { virtualHost: true, addGlobalClass: true, styleIsolation: 'shared' }
}
</script>
<script lang="ts" setup>
import type { CSSProperties } from 'vue'
import { ref, computed, watch } from 'vue'
import type { SkeletonRowCol, SkeletonRowColObj } from './types'
import { skeletonProps } from './types'
import { isNumber, addUnit } from '../common/util'
const themeMap = {
avatar: [{ type: 'circle', height: '64px', width: '64px' }],
image: [{ type: 'rect', height: '64px', width: '64px' }],
text: [
1,
[
{ width: '24%', height: '16px', marginRight: '16px' },
{ width: '76%', height: '16px' }
]
],
paragraph: [1, 1, 1, { width: '55%' }]
}
const props = defineProps(skeletonProps)
const rowCols = ref<SkeletonRowCol[]>([])
const parsedRowCols = computed(() => {
return rowCols.value.map((item) => {
if (isNumber(item)) {
return [
{
class: getColItemClass({ type: 'text' }),
style: {}
}
]
}
if (Array.isArray(item)) {
return item.map((col) => {
return {
...col,
class: getColItemClass(col),
style: getColItemStyle(col)
}
})
}
const nItem = item as SkeletonRowColObj
return [
{
...nItem,
class: getColItemClass(nItem),
style: getColItemStyle(nItem)
}
]
})
})
function getColItemClass(rowCol: SkeletonRowColObj) {
return ['wd-skeleton__col', `wd-skeleton--type-${rowCol.type || 'text'}`, { [`wd-skeleton--animation-${props.animation}`]: props.animation }]
}
function getColItemStyle(rowCol: SkeletonRowColObj) {
const style: CSSProperties = {}
const styleName = ['size', 'width', 'height', 'margin', 'background', 'marginLeft', 'marginRight', 'borderRadius', 'backgroundColor']
for (const name of styleName) {
if (Object.prototype.hasOwnProperty.call(rowCol, name)) {
const px = addUnit(rowCol[name])
if (name === 'size') {
style.width = px
style.height = px
} else {
;(style as any)[name] = px
}
}
}
return style
}
watch(
() => props.rowCol,
(rowCol) => {
rowCols.value = [...(Array.isArray(rowCol) && rowCol.length ? props.rowCol : themeMap[props.theme])]
},
{ immediate: true }
)
const show = computed(() => props.loading == undefined || props.loading === true)
</script>
<style lang="scss" scoped>
@import './index.scss';
</style>