更新:登录功能
This commit is contained in:
96
uni_modules/wot-design-uni/components/wd-skeleton/index.scss
Normal file
96
uni_modules/wot-design-uni/components/wd-skeleton/index.scss
Normal file
@@ -0,0 +1,96 @@
|
||||
@import '../common/abstracts/variable';
|
||||
@import '../common/abstracts/mixin';
|
||||
|
||||
.wot-theme-dark {
|
||||
@include b(skeleton) {
|
||||
@include e(col) {
|
||||
background-color: $-dark-background4;
|
||||
}
|
||||
}
|
||||
}
|
||||
@include b(skeleton) {
|
||||
box-sizing: border-box;
|
||||
|
||||
@include e(row) {
|
||||
justify-content: space-between;
|
||||
margin-bottom: $-skeleton-row-margin-bottom;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&:only-child,
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
@include e(col) {
|
||||
border-radius: $-skeleton-border-radius-text;
|
||||
background-color: $-skeleton-background-color;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
&:first-child:last-child,
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
@include m(type) {
|
||||
&-text {
|
||||
width: 100%;
|
||||
height: $-skeleton-text-height-default;
|
||||
border-radius: $-skeleton-border-radius-text;
|
||||
}
|
||||
|
||||
&-rect {
|
||||
width: 100%;
|
||||
height: $-skeleton-rect-height-default;
|
||||
border-radius: $-skeleton-border-radius-rect;
|
||||
}
|
||||
|
||||
&-circle {
|
||||
flex-shrink: 0;
|
||||
width: $-skeleton-circle-height-default;
|
||||
height: $-skeleton-circle-height-default;
|
||||
border-radius: $-skeleton-border-radius-circle;
|
||||
}
|
||||
}
|
||||
@include m(animation) {
|
||||
&-gradient {
|
||||
position: relative;
|
||||
overflow-x: hidden;
|
||||
|
||||
&::after {
|
||||
content: ' ';
|
||||
position: absolute;
|
||||
animation: wd-skeleton-gradient 1.5s linear 2s infinite;
|
||||
background: linear-gradient(90deg, rgba(255, 255, 255, 0), $-skeleton-animation-gradient, rgba(255, 255, 255, 0));
|
||||
inset: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&-flashed {
|
||||
animation: wd-skeleton-flashed 2s linear 2s infinite;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes wd-skeleton-gradient {
|
||||
0% {
|
||||
transform: translateX(-100%) skewX(-15deg);
|
||||
}
|
||||
100% {
|
||||
transform: translateX(100%) skewX(-15deg);
|
||||
}
|
||||
}
|
||||
@keyframes wd-skeleton-flashed {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.3;
|
||||
background-color: $-skeleton-animation-flashed;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export type { SkeletonThemeVars } from './types'
|
||||
69
uni_modules/wot-design-uni/components/wd-skeleton/types.ts
Normal file
69
uni_modules/wot-design-uni/components/wd-skeleton/types.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import type { PropType, ExtractPropTypes, CSSProperties } from 'vue'
|
||||
import { makeArrayProp, makeBooleanProp, makeStringProp } from '../common/props'
|
||||
|
||||
export type SkeletonTheme = 'text' | 'avatar' | 'paragraph' | 'image'
|
||||
export type SkeletonAnimation = 'gradient' | 'flashed'
|
||||
export type SkeletonRowColObj = {
|
||||
[key: string]: any
|
||||
type?: 'rect' | 'circle' | 'text'
|
||||
size?: string | number
|
||||
width?: string | number
|
||||
height?: string | number
|
||||
margin?: string | number
|
||||
background?: string
|
||||
marginLeft?: string | number
|
||||
marginRight?: string | number
|
||||
borderRadius?: string | number
|
||||
backgroundColor?: string
|
||||
}
|
||||
export type SkeletonRowCol = number | SkeletonRowColObj | Array<SkeletonRowColObj>
|
||||
export type SkeletonThemeVars = {
|
||||
notifyPadding?: string
|
||||
notifyFontSize?: string
|
||||
notifyTextColor?: string
|
||||
notifyLineHeight?: number | string
|
||||
notifyDangerBackground?: string
|
||||
notifyPrimaryBackground?: string
|
||||
notifySuccessBackground?: string
|
||||
notifyWarningBackground?: string
|
||||
}
|
||||
export const skeletonProps = {
|
||||
/**
|
||||
* 骨架图风格,有基础、头像组合等两大类
|
||||
*/
|
||||
theme: makeStringProp<SkeletonTheme>('text'),
|
||||
/**
|
||||
* 用于设置行列数量、宽度高度、间距等。
|
||||
* @example
|
||||
* 【示例一】,`[1, 1, 2]` 表示输出三行骨架图,第一行一列,第二行一列,第三行两列。
|
||||
* 【示例二】,`[1, 1, { width: '100px' }]` 表示自定义第三行的宽度为 `100px`。
|
||||
* 【示例三】,`[1, 2, [{ width, height }, { width, height, marginLeft }]]` 表示第三行有两列,且自定义宽度、高度和间距
|
||||
*/
|
||||
rowCol: makeArrayProp<SkeletonRowCol>(),
|
||||
/**
|
||||
* 是否为加载状态,如果是则显示骨架图,如果不是则显示加载完成的内容
|
||||
* @default true
|
||||
*/
|
||||
loading: makeBooleanProp(true),
|
||||
/**
|
||||
* 动画效果,有「渐变加载动画」和「闪烁加载动画」两种。值为空则表示没有动画
|
||||
*/
|
||||
animation: {
|
||||
type: String as PropType<SkeletonAnimation>,
|
||||
default: ''
|
||||
},
|
||||
// 自定义类名
|
||||
customClass: {
|
||||
type: [String, Array, Object],
|
||||
default: ''
|
||||
},
|
||||
// 自定义样式
|
||||
customStyle: {
|
||||
type: Object as PropType<CSSProperties>,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export type SkeletonProps = ExtractPropTypes<typeof skeletonProps>
|
||||
@@ -0,0 +1,119 @@
|
||||
<!--
|
||||
* @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>
|
||||
Reference in New Issue
Block a user