更新:登录功能

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,235 @@
@import '../common/abstracts/variable';
@import '../common/abstracts/mixin';
.wot-theme-dark {
@include b(step) {
@include e(icon) {
background: $-dark-background2;
}
@include e(content){
color: $-dark-color3;
}
@include e(line) {
background: $-dark-color-gray;
}
@include e(dot) {
background: $-dark-color-gray;
}
@include e(description) {
color: $-dark-color3;
}
@include when(wait) {
.wd-step__description {
color: $-dark-color-gray;
}
}
:deep(.wd-step__icon-outer),:deep(.wd-step__icon-inner){
color: $-dark-color3;
border-color: $-dark-color-gray;
}
}
}
@include b(step) {
position: relative;
display: inline-block;
vertical-align: top;
@include e(header) {
position: relative;
font-size: 0;
@include when(dot) {
.wd-step__line {
margin-top: -1px;
}
}
}
@include e(icon) {
display: inline-block;
position: relative;
width: $-steps-icon-size;
height: $-steps-icon-size;
background: #fff;
z-index: 1;
@include when(icon) {
width: $-steps-is-icon-width;
text-align: center;
}
@include when(dot) {
width: $-steps-dot-size;
height: $-steps-dot-size;
border: 1px solid transparent;
margin-left: -1px;
border-radius: 50%;
background: transparent;
}
}
@include edeep(icon-inner) {
font-size: $-steps-icon-size;
color: $-steps-inactive-color;
}
@include e(icon-outer) {
width: calc($-steps-icon-size - 2px);
height: calc($-steps-icon-size - 2px);
border: 1px solid $-steps-inactive-color;
color: $-steps-inactive-color;
text-align: center;
line-height: calc($-steps-icon-size - 2px);
border-radius: 50%;
font-size: $-steps-icon-text-fs;
}
@include e(line) {
position: absolute;
width: 100%;
height: 1px;
background: $-steps-line-color;
transform: scaleY(0.5);
top: 50%;
left: 0;
}
@include e(dot) {
position: relative;
display: block;
width: 100%;
height: 100%;
border-radius: 50%;
background: $-steps-line-color;
}
@include e(content){
margin-top: 7px;
color: $-steps-inactive-color;
font-size: $-steps-label-fs;
}
@include e(title) {
font-weight: $-steps-title-fw;
line-height: 1.43;
@include when(description) {
font-size: $-steps-title-fs;
}
}
@include e(description) {
margin-top: 5px;
padding: 0 2px;
color: $-steps-description-color;
}
@include when(wait) {
.wd-step__description {
color: $-steps-inactive-color;
}
}
@include when(finished) {
:deep(.wd-step__icon-inner) {
color: $-steps-finished-color;
}
.wd-step__icon-outer {
color: $-steps-finished-color;
border-color: $-steps-finished-color;
}
.wd-step__title {
color: $-steps-finished-color;
}
.wd-step__dot {
background: $-steps-finished-color;
}
}
@include when(process) {
.wd-step__icon.is-icon {
:deep(.wd-step__icon-inner) {
color: $-steps-finished-color;
}
}
.wd-step__icon-outer {
color: #fff;
background: $-steps-finished-color;
border-color: $-steps-finished-color;
}
.wd-step__title {
color: $-steps-finished-color;
}
.wd-step__icon {
border-color: $-steps-finished-color;
&.is-dot {
&::after {
position: absolute;
content: '';
width: $-steps-dot-size + 10px;
height: $-steps-dot-size + 10px;
left: -5px;
top: -5px;
border-radius: 50%;
background: $-steps-finished-color;
opacity: 0.2;
}
}
}
.wd-step__dot {
background: $-steps-finished-color;
}
}
@include when(error) {
:deep(.wd-step__icon-inner), .wd-step__title {
color: $-steps-error-color;
}
.wd-step__icon-outer {
color: $-steps-error-color;
border-color: $-steps-error-color;
}
.wd-step__dot {
background: $-steps-error-color;
}
}
@include when(center) {
text-align: center;
.wd-step__line {
left: 50%;
right: -50%;
}
}
@include when(vertical) {
display: block;
.wd-step__header {
position: absolute;
left: 0;
top: 0;
height: 100%;
&.is-dot {
top: 6px;
.wd-step__line {
margin-left: -1px;
margin-top: 0;
}
}
}
.wd-step__content {
margin-left: 30px;
margin-top: 0;
padding-bottom: 20px;
}
.wd-step__line {
top: 0;
left: 50%;
width: 1px;
height: 100%;
transform: scaleX(0.5);
}
.wd-step__icon.is-dot {
margin-left: 0;
margin-top: -1px;
}
}
}

View File

@@ -0,0 +1,33 @@
import type { PropType } from 'vue'
import { baseProps, makeBooleanProp } from '../common/props'
export type StepStatus = 'finished' | 'process' | 'error'
export const stepProps = {
...baseProps,
/**
* 步骤标题,如果没有则使用默认文案。
* 当只有标题而没有描述时标题的字号会小2号。
* 类型: string
*/
title: String,
/**
* 步骤描述。
* 类型: string
*/
description: String,
/**
* 步骤图标。
* 类型: string
*/
icon: String,
/**
* 步骤状态,可选值为 'finished'(已完成)、'process'(进行中)、'error'(出错)。
* 类型: string
*/
status: String as PropType<StepStatus>
}

View File

@@ -0,0 +1,150 @@
<template>
<view
v-if="currentStatus"
:class="`wd-step ${customClass} ${currentStatus ? 'is-' + currentStatus : ''} ${canAlignCenter ? 'is-center' : ''} ${
vertical ? 'is-vertical' : ''
}`"
:style="rootStyle"
>
<view :class="`wd-step__header ${dot ? 'is-dot' : ''}`">
<view :class="`wd-step__icon ${dot ? 'is-dot' : !!icon || $slots.icon ? 'is-icon' : 'is-text'}`">
<view v-if="dot" class="wd-step__dot"></view>
<slot v-else-if="$slots.icon" name="icon" />
<wd-icon v-else-if="icon" custom-class="wd-step__icon-inner" :name="icon" />
<view v-else class="wd-step__icon-outer">
<wd-icon v-if="currentStatus === 'finished'" name="check-bold" />
<wd-icon v-else-if="currentStatus === 'error'" name="close-bold" />
<text v-else>{{ index + 1 }}</text>
</view>
</view>
<view v-if="index < childrenLength - 1" class="wd-step__line"></view>
</view>
<view class="wd-step__content">
<view :class="`wd-step__title ${$slots.description || description ? 'is-description' : ''}`">
<slot v-if="$slots.title" name="title" />
<text v-else>{{ currentTitle }}</text>
</view>
<view v-if="$slots.description || description" class="wd-step__description">
<slot v-if="$slots.description" name="description" />
<text v-else>{{ description }}</text>
</view>
</view>
</view>
</template>
<script lang="ts">
export default {
name: 'wd-step',
options: {
addGlobalClass: true,
virtualHost: true,
styleIsolation: 'shared'
}
}
</script>
<script lang="ts" setup>
import wdIcon from '../wd-icon/wd-icon.vue'
import { computed } from 'vue'
import { useParent } from '../composables/useParent'
import { STEPS_KEY } from '../wd-steps/types'
import { isDef, objToStyle } from '../common/util'
import { useTranslate } from '../composables/useTranslate'
import { stepProps } from './types'
import type { CSSProperties } from 'vue'
const props = defineProps(stepProps)
const { parent: steps, index } = useParent(STEPS_KEY)
const { translate } = useTranslate('steps')
const currentStatus = computed(() => {
return getCurrentStatus(index.value)
})
const currentTitle = computed(() => {
return getCurrentTitle(currentStatus.value)
})
const rootStyle = computed(() => {
const style: CSSProperties = {}
if (steps) {
const { vertical, space } = steps.props
if (vertical) {
if (isDef(space)) {
style['height'] = space
}
} else {
style['width'] = space || 100 / steps.children.length + '%'
}
}
return `${objToStyle(style)}${props.customStyle}`
})
const canAlignCenter = computed(() => {
if (isDef(steps)) {
const { vertical, alignCenter } = steps.props
return Boolean(!vertical && alignCenter)
} else {
return false
}
})
const vertical = computed(() => {
if (isDef(steps)) {
return Boolean(steps.props.vertical)
} else {
return false
}
})
const dot = computed(() => {
if (isDef(steps)) {
return Boolean(steps.props.dot)
} else {
return false
}
})
const childrenLength = computed(() => {
if (isDef(steps)) {
return Number(steps.children.length)
} else {
return 0
}
})
function getCurrentStatus(index: number) {
if (props.status) {
return props.status
}
if (steps) {
const { active } = steps.props
if (Number(active) > index) {
return 'finished'
} else if (Number(active) === index) {
return 'process'
} else {
return 'wait'
}
} else {
return 'wait'
}
}
function getCurrentTitle(currentStatus: string) {
if (props.title) return props.title
switch (currentStatus) {
case 'finished':
return translate('finished')
case 'error':
return translate('failed')
case 'process':
return translate('process')
case 'wait':
default:
return translate('wait')
}
}
</script>
<style lang="scss" scoped>
@import './index.scss';
</style>