更新:登录功能

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,206 @@
@import '../common/abstracts/variable.scss';
@import '../common/abstracts/_mixin.scss';
.wot-theme-dark {
@include b(cell) {
background-color: $-dark-background2;
color: $-dark-color;
@include e(value) {
color: $-dark-color;
}
@include e(label) {
color: $-dark-color3;
}
@include when(hover) {
background-color: $-dark-background4;
}
@include when(border) {
.wd-cell__wrapper {
@include halfPixelBorder('top', 0, $-dark-border-color);
}
}
:deep(.wd-cell__arrow-right) {
color: $-dark-color;
}
}
}
@include b(cell) {
position: relative;
padding-left: $-cell-padding;
background-color: $-color-white;
text-decoration: none;
color: $-cell-title-color;
line-height: $-cell-line-height;
-webkit-tap-highlight-color: transparent;
box-sizing: border-box;
width: 100%;
overflow: hidden;
@include when(border) {
.wd-cell__wrapper {
@include halfPixelBorder('top');
}
}
@include e(wrapper) {
position: relative;
display: flex;
padding: $-cell-wrapper-padding $-cell-padding $-cell-wrapper-padding 0;
justify-content: space-between;
align-items: flex-start;
overflow: hidden;
@include when(vertical) {
display: block;
.wd-cell__right {
margin-top: $-cell-vertical-top;
}
.wd-cell__value {
text-align: left;
}
.wd-cell__left {
margin-right: 0;
}
}
@include when(label) {
padding: $-cell-wrapper-padding-with-label $-cell-padding $-cell-wrapper-padding-with-label 0;
}
}
@include e(left) {
position: relative;
flex: 1;
display: flex;
text-align: left;
font-size: $-cell-title-fs;
box-sizing: border-box;
margin-right: $-cell-padding;
}
@include e(right) {
position: relative;
flex: 1;
min-width: 0;
}
@include e(title) {
font-size: $-cell-title-fs;
}
@include e(required) {
font-size: $-cell-required-size;
color: $-cell-required-color;
margin-left: $-cell-required-margin;
@include m(left) {
margin-left: 0;
margin-right: $-cell-required-margin;
}
}
@include e(label) {
margin-top: 2px;
font-size: $-cell-label-fs;
color: $-cell-label-color;
}
@include edeep(icon) {
display: block;
position: relative;
margin-right: $-cell-icon-right;
font-size: $-cell-icon-size;
height: $-cell-line-height;
line-height: $-cell-line-height;
}
@include e(body){
display: flex;
min-width: 0;
}
@include e(value) {
position: relative;
flex: 1;
font-size: $-cell-value-fs;
color: $-cell-value-color;
vertical-align: middle;
@include m(left) {
text-align: left;
}
@include m(right) {
text-align: right;
}
@include m(ellipsis) {
@include lineEllipsis;
min-width: 0;
}
}
@include edeep(arrow-right) {
display: block;
margin-left: 8px;
width: $-cell-arrow-size;
font-size: $-cell-arrow-size;
color: $-cell-arrow-color;
height: $-cell-line-height;
line-height: $-cell-line-height;
}
@include e(error-message){
color: $-form-item-error-message-color;
font-size: $-form-item-error-message-font-size;
line-height: $-form-item-error-message-line-height;
text-align: left;
vertical-align: middle;
}
@include when(link) {
-webkit-tap-highlight-color: $-cell-tap-bg;
}
@include when(hover) {
background-color: $-cell-tap-bg;
}
@include when(large) {
.wd-cell__title {
font-size: $-cell-title-fs-large;
}
.wd-cell__wrapper {
padding-top: $-cell-wrapper-padding-large;
padding-bottom: $-cell-wrapper-padding-large;
}
.wd-cell__label {
font-size: $-cell-label-fs-large;
}
.wd-cell__value {
font-size: $-cell-value-fs-large;
}
:deep(.wd-cell__icon) {
font-size: $-cell-icon-size-large;
}
}
@include when(center) {
.wd-cell__wrapper {
align-items: center;
}
}
}

View File

@@ -0,0 +1,111 @@
import type { ExtractPropTypes } from 'vue'
import { baseProps, makeArrayProp, makeBooleanProp, makeStringProp, makeNumericProp, numericProp } from '../common/props'
import { type FormItemRule } from '../wd-form/types'
export const cellProps = {
...baseProps,
/**
* 标题
*/
title: String,
/**
* 右侧内容
*/
value: makeNumericProp(''),
/**
* 图标类名
*/
icon: String,
/**
* 图标大小
*/
iconSize: numericProp,
/**
* 描述信息
*/
label: String,
/**
* 是否为跳转链接
*/
isLink: makeBooleanProp(false),
/**
* 跳转地址
*/
to: String,
/**
* 跳转时是否替换栈顶页面
*/
replace: makeBooleanProp(false),
/**
* 开启点击反馈is-link 默认开启
*/
clickable: makeBooleanProp(false),
/**
* 设置单元格大小可选值large
*/
size: String,
/**
* 是否展示边框线
*/
border: makeBooleanProp(void 0),
/**
* 设置左侧标题宽度
*/
titleWidth: String,
/**
* 是否垂直居中,默认顶部居中
*/
center: makeBooleanProp(false),
/**
* 是否必填
*/
required: makeBooleanProp(false),
/**
* 表单属性,上下结构
*/
vertical: makeBooleanProp(false),
/**
* 表单域 model 字段名,在使用表单校验功能的情况下,该属性是必填的
*/
prop: String,
/**
* 表单验证规则结合wd-form组件使用
*/
rules: makeArrayProp<FormItemRule>(),
/**
* icon 使用 slot 时的自定义样式
*/
customIconClass: makeStringProp(''),
/**
* label 使用 slot 时的自定义样式
*/
customLabelClass: makeStringProp(''),
/**
* value 使用 slot 时的自定义样式
*/
customValueClass: makeStringProp(''),
/**
* title 使用 slot 时的自定义样式
*/
customTitleClass: makeStringProp(''),
/**
* value 文字对齐方式可选值left、right、center
*/
valueAlign: makeStringProp<'left' | 'right'>('right'),
/**
* 是否超出隐藏,显示省略号
*/
ellipsis: makeBooleanProp(false),
/**
* 是否启用title插槽默认启用用来解决插槽传递时v-slot和v-if冲突问题。
* 问题见https://github.com/dcloudio/uni-app/issues/4847
*/
useTitleSlot: makeBooleanProp(true),
/**
* 必填标记位置可选值before标签前、after标签后
*/
markerSide: makeStringProp<'before' | 'after'>('before')
}
export type CellProps = ExtractPropTypes<typeof cellProps>

View File

@@ -0,0 +1,140 @@
<template>
<view
:class="['wd-cell', isBorder ? 'is-border' : '', size ? 'is-' + size : '', center ? 'is-center' : '', customClass]"
:style="customStyle"
:hover-class="isLink || clickable ? 'is-hover' : 'none'"
:hover-stay-time="70"
@click="onClick"
>
<view :class="['wd-cell__wrapper', vertical ? 'is-vertical' : '']">
<view v-if="showLeft" class="wd-cell__left" :style="titleWidth ? 'min-width:' + titleWidth + ';max-width:' + titleWidth + ';' : ''">
<text v-if="isRequired && markerSide === 'before'" class="wd-cell__required wd-cell__required--left">*</text>
<!--左侧icon部位-->
<slot name="icon">
<wd-icon v-if="icon" :name="icon" :size="iconSize" :custom-class="`wd-cell__icon ${customIconClass}`"></wd-icon>
</slot>
<view class="wd-cell__title">
<!--title BEGIN-->
<slot v-if="useTitleSlot && $slots.title" name="title"></slot>
<text v-else-if="title" :class="customTitleClass">{{ title }}</text>
<!--title END-->
<!--label BEGIN-->
<slot name="label">
<view v-if="label" :class="`wd-cell__label ${customLabelClass}`">{{ label }}</view>
</slot>
<!--label END-->
</view>
<text v-if="isRequired && markerSide === 'after'" class="wd-cell__required">*</text>
</view>
<!--right content BEGIN-->
<view class="wd-cell__right">
<view class="wd-cell__body">
<!--文案内容-->
<view :class="`wd-cell__value ${customValueClass} wd-cell__value--${valueAlign} ${ellipsis ? 'wd-cell__value--ellipsis' : ''}`">
<slot>{{ value }}</slot>
</view>
<!--箭头-->
<wd-icon v-if="isLink" custom-class="wd-cell__arrow-right" name="arrow-right" />
<slot v-else name="right-icon" />
</view>
<view v-if="errorMessage" class="wd-cell__error-message">{{ errorMessage }}</view>
</view>
<!--right content END-->
</view>
</view>
</template>
<script lang="ts">
export default {
name: 'wd-cell',
options: {
addGlobalClass: true,
virtualHost: true,
styleIsolation: 'shared'
}
}
</script>
<script lang="ts" setup>
import wdIcon from '../wd-icon/wd-icon.vue'
import { computed, useSlots } from 'vue'
import { useCell } from '../composables/useCell'
import { useParent } from '../composables/useParent'
import { FORM_KEY } from '../wd-form/types'
import { cellProps } from './types'
import { isDef } from '../common/util'
const props = defineProps(cellProps)
const emit = defineEmits(['click'])
// 获取插槽
const slots = useSlots()
const cell = useCell()
const isBorder = computed(() => {
return Boolean(isDef(props.border) ? props.border : cell.border.value)
})
const { parent: form } = useParent(FORM_KEY)
const errorMessage = computed(() => {
if (form && props.prop && form.errorMessages && form.errorMessages[props.prop]) {
return form.errorMessages[props.prop]
} else {
return ''
}
})
// 是否展示必填
const isRequired = computed(() => {
let formRequired = false
if (form && form.props.rules) {
const rules = form.props.rules
for (const key in rules) {
if (Object.prototype.hasOwnProperty.call(rules, key) && key === props.prop && Array.isArray(rules[key])) {
formRequired = rules[key].some((rule) => rule.required)
}
}
}
return props.required || props.rules.some((rule) => rule.required) || formRequired
})
// 是否展示左侧部分
const showLeft = computed(() => {
// 插槽优先级高于props
// 有icon插槽或icon属性
const hasIcon = slots.icon || props.icon
// 有title插槽或title属性
const hasTitle = (slots.title && props.useTitleSlot) || props.title
// 有label插槽或label属性
const hasLabel = slots.label || props.label
return hasIcon || hasTitle || hasLabel
})
/**
* @description 点击cell的handle
*/
function onClick() {
const url = props.to
if (props.clickable || props.isLink) {
emit('click')
}
if (url && props.isLink) {
if (props.replace) {
uni.redirectTo({ url })
} else {
uni.navigateTo({ url })
}
}
}
</script>
<style lang="scss" scoped>
@import './index.scss';
</style>