更新:登录功能

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,153 @@
@import '../../common/abstracts/variable';
@import '../../common/abstracts/mixin';
.wot-theme-dark {
@include b(year) {
@include e(title) {
color: $-dark-color;
}
@include e(months) {
color: $-dark-color;
}
@include e(month) {
@include when(disabled) {
.wd-year__month-text {
color: $-dark-color-gray;
}
}
}
}
}
@include b(year) {
@include e(title) {
display: flex;
align-items: center;
justify-content: center;
height: 45px;
font-size: $-calendar-panel-title-fs;
color: $-calendar-panel-title-color;
}
@include e(months) {
display: flex;
flex-wrap: wrap;
font-size: $-calendar-day-fs;
color: $-calendar-day-color;
}
@include e(month) {
position: relative;
width: 25%;
height: $-calendar-day-height;
line-height: $-calendar-day-height;
text-align: center;
margin-bottom: $-calendar-item-margin-bottom;
@include when(disabled) {
.wd-year__month-text {
color: $-calendar-disabled-color;
}
}
@include when(current) {
color: $-calendar-active-color;
}
@include when(selected) {
color: #fff;
.wd-year__month-text {
border-radius: $-calendar-active-border;
background: $-calendar-active-color;
}
}
@include when(middle) {
background: $-calendar-range-color;
}
@include when(start) {
color: $-calendar-selected-color;
&::after {
position: absolute;
top: 0;
right: 0;
left: 50%;
bottom: 0;
content: '';
background: $-calendar-range-color;
}
.wd-year__month-text {
background: $-calendar-active-color;
border-radius: $-calendar-active-border 0 0 $-calendar-active-border;
}
&.is-without-end::after {
display: none;
}
}
@include when(end) {
color: $-calendar-selected-color;
&::after {
position: absolute;
top: 0;
left: 0;
right: 50%;
bottom: 0;
content: '';
background: $-calendar-range-color;
}
.wd-year__month-text {
background: $-calendar-active-color;
border-radius: 0 $-calendar-active-border $-calendar-active-border 0;
}
}
@include when(same) {
color: $-calendar-selected-color;
.wd-year__month-text {
background: $-calendar-active-color;
border-radius: $-calendar-active-border;
}
}
@include when(last-row){
margin-bottom: 0;
}
}
@include e(month-text) {
width: $-calendar-month-width;
margin: 0 auto;
text-align: center;
}
@include e(month-top) {
position: absolute;
top: 10px;
left: 0;
right: 0;
line-height: 1.1;
font-size: $-calendar-info-fs;
text-align: center;
}
@include e(month-bottom) {
position: absolute;
bottom: 10px;
left: 0;
right: 0;
line-height: 1.1;
font-size: $-calendar-info-fs;
text-align: center;
}
}

View File

@@ -0,0 +1,20 @@
import type { PropType } from 'vue'
import { makeBooleanProp, makeRequiredProp } from '../../common/props'
import type { CalendarFormatter, CalendarType } from '../types'
export const yearProps = {
type: makeRequiredProp(String as PropType<CalendarType>),
date: makeRequiredProp(Number),
value: makeRequiredProp([Number, Array] as PropType<number | (number | null)[] | null>),
minDate: makeRequiredProp(Number),
maxDate: makeRequiredProp(Number),
// 日期格式化函数
formatter: Function as PropType<CalendarFormatter>,
maxRange: Number,
rangePrompt: String,
allowSameDay: makeBooleanProp(false),
defaultTime: {
type: [Array] as PropType<Array<number[]>>
},
showTitle: makeBooleanProp(true)
}

View File

@@ -0,0 +1,202 @@
<template>
<wd-toast selector="wd-year" />
<view class="wd-year year">
<view class="wd-year__title" v-if="showTitle">{{ yearTitle(date) }}</view>
<view class="wd-year__months">
<view
v-for="(item, index) in months"
:key="index"
:class="`wd-year__month ${item.disabled ? 'is-disabled' : ''} ${item.isLastRow ? 'is-last-row' : ''} ${
item.type ? monthTypeClass(item.type) : ''
}`"
@click="handleDateClick(index)"
>
<view class="wd-year__month-top">{{ item.topInfo }}</view>
<view class="wd-year__month-text">{{ getMonthLabel(item.date) }}</view>
<view class="wd-year__month-bottom">{{ item.bottomInfo }}</view>
</view>
</view>
</view>
</template>
<script lang="ts">
export default {
options: {
addGlobalClass: true,
virtualHost: true,
styleIsolation: 'shared'
}
}
</script>
<script lang="ts" setup>
import wdToast from '../../wd-toast/wd-toast.vue'
import { computed, ref, watch } from 'vue'
import { deepClone, isArray, isFunction } from '../../common/util'
import { compareMonth, formatYearTitle, getDateByDefaultTime, getItemClass, getMonthByOffset, getMonthOffset } from '../utils'
import { useToast } from '../../wd-toast'
import { useTranslate } from '../../composables/useTranslate'
import dayjs from '../../../dayjs'
import { yearProps } from './types'
import type { CalendarDayItem, CalendarDayType } from '../types'
const props = defineProps(yearProps)
const emit = defineEmits(['change'])
const toast = useToast('wd-year')
const { translate } = useTranslate('calendar-view')
const months = ref<CalendarDayItem[]>([])
const monthTypeClass = computed(() => {
return (monthType: CalendarDayType) => {
return getItemClass(monthType, props.value, props.type)
}
})
const yearTitle = computed(() => {
return (date: number) => {
return formatYearTitle(date)
}
})
watch(
[() => props.type, () => props.date, () => props.value, () => props.minDate, () => props.maxDate, () => props.formatter],
() => {
setMonths()
},
{
deep: true,
immediate: true
}
)
function getMonthLabel(date: number) {
return dayjs(date).format(translate('month', date))
}
function setMonths() {
const monthList: CalendarDayItem[] = []
const date = new Date(props.date)
const year = date.getFullYear()
const value = props.value
if (props.type.indexOf('range') > -1 && value && !isArray(value)) {
console.error('[wot-design] value should be array when type is range')
return
}
for (let month = 0; month < 12; month++) {
const date = new Date(year, month, 1).getTime()
let type: CalendarDayType = getMonthType(date)
if (!type && compareMonth(date, Date.now()) === 0) {
type = 'current'
}
const monthObj = getFormatterDate(date, month, type)
monthList.push(monthObj)
}
months.value = deepClone(monthList)
}
function getMonthType(date: number) {
if (props.type === 'monthrange' && isArray(props.value)) {
const [startDate, endDate] = props.value || []
if (startDate && compareMonth(date, startDate) === 0) {
if (endDate && compareMonth(startDate, endDate) === 0) {
return 'same'
}
return 'start'
} else if (endDate && compareMonth(date, endDate) === 0) {
return 'end'
} else if (startDate && endDate && compareMonth(date, startDate) === 1 && compareMonth(date, endDate) === -1) {
return 'middle'
} else {
return ''
}
} else {
if (props.value && compareMonth(date, props.value as number) === 0) {
return 'selected'
} else {
return ''
}
}
}
function handleDateClick(index: number) {
const date = months.value[index]
if (date.disabled) return
switch (props.type) {
case 'month':
handleMonthChange(date)
break
case 'monthrange':
handleMonthRangeChange(date)
break
default:
handleMonthChange(date)
}
}
function getDate(date: number) {
return props.defaultTime && props.defaultTime.length > 0 ? getDateByDefaultTime(date, props.defaultTime[0]) : date
}
function handleMonthChange(date: CalendarDayItem) {
if (date.type !== 'selected') {
emit('change', {
value: getDate(date.date)
})
}
}
function handleMonthRangeChange(date: CalendarDayItem) {
let value: (number | null)[] = []
const [startDate, endDate] = isArray(props.value) ? props.value || [] : []
const compare = compareMonth(date.date, startDate!)
// 禁止选择同个日期
if (!props.allowSameDay && !endDate && compare === 0) return
if (startDate && !endDate && compare > -1) {
if (props.maxRange && getMonthOffset(date.date, startDate) > props.maxRange) {
const maxEndDate = getMonthByOffset(startDate, props.maxRange - 1)
value = [startDate, getDate(maxEndDate)]
toast.show({
msg: props.rangePrompt || translate('rangePromptMonth', props.maxRange)
})
} else {
value = [startDate, getDate(date.date)]
}
} else {
value = [getDate(date.date), null]
}
emit('change', {
value
})
}
function getFormatterDate(date: number, month: number, type?: CalendarDayType) {
let monthObj: CalendarDayItem = {
date: date,
text: month + 1,
topInfo: '',
bottomInfo: '',
type,
disabled: compareMonth(date, props.minDate) === -1 || compareMonth(date, props.maxDate) === 1,
isLastRow: month >= 8
}
if (props.formatter) {
if (isFunction(props.formatter)) {
monthObj = props.formatter(monthObj)
} else {
console.error('[wot-design] error(wd-calendar-view): the formatter prop of wd-calendar-view should be a function')
}
}
return monthObj
}
</script>
<style lang="scss" scoped>
@import './index.scss';
</style>