更新:登录功能

This commit is contained in:
2025-11-04 12:37:04 +08:00
commit a21fb92916
897 changed files with 51500 additions and 0 deletions

View 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;
}
}
}

View File

@@ -0,0 +1 @@
export type { SkeletonThemeVars } from './types'

View 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>

View File

@@ -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>