更新:登录功能

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,108 @@
@import "../common/abstracts/variable.scss";
@import "../common/abstracts/_mixin.scss";
.wot-theme-dark {
@include b(message-box) {
@include e(body) {
background-color: $-dark-background2;
}
@include e(title) {
color: $-dark-color;
}
@include e(content) {
color: $-dark-color3;
&::-webkit-scrollbar-thumb {
background: $-dark-border-color;
}
}
}
}
:deep(.wd-message-box){
border-radius: $-message-box-radius;
overflow: hidden;
}
@include b(message-box) {
border-radius: $-message-box-radius;
overflow: hidden;
@include e(container) {
width: $-message-box-width;
box-sizing: border-box;
}
@include e(body) {
background-color: $-message-box-bg;
padding: $-message-box-padding;
@include when(no-title) {
padding: 25px 24px 0px;
}
}
@include e(title) {
text-align: center;
font-size: $-message-box-title-fs;
color: $-message-box-title-color;
line-height: 20px;
font-weight: 500;
padding-top: 5px;
padding-bottom: 10px;
}
@include e(content) {
max-height: $-message-box-content-max-height;
color: $-message-box-content-color;
font-size: $-message-box-content-fs;
text-align: center;
overflow: auto;
line-height: 20px;
&::-webkit-scrollbar {
width: $-message-box-content-scrollbar-width;
}
&::-webkit-scrollbar-thumb {
width: $-message-box-content-scrollbar-width;
background: $-message-box-content-scrollbar-color;
border-radius: calc($-message-box-content-scrollbar-width / 2);
}
}
@include e(input-error) {
min-height: 18px;
margin-top: 2px;
color: $-message-box-input-error-color;
text-align: left;
@include when(hidden) {
visibility: hidden;
}
}
@include e(actions) {
padding: 24px;
}
@include edeep(actions-btn) {
&:not(:last-child) {
margin-right: 16px;
}
}
@include e(flex) {
display: flex;
}
@include e(block) {
display: block;
}
@include e(cancel) {
margin-right: 16px;
}
}

View File

@@ -0,0 +1,96 @@
/*
* @Author: weisheng
* @Date: 2022-12-14 17:33:21
* @LastEditTime: 2024-12-05 13:23:17
* @LastEditors: weisheng
* @Description:
* @FilePath: \wot-design-uni\src\uni_modules\wot-design-uni\components\wd-message-box\index.ts
* 记得注释
*/
import { inject, provide, ref } from 'vue'
import type { Message, MessageOptions, MessageOptionsWithCallBack, MessageResult, MessageType } from './types'
import { deepMerge } from '../common/util'
const messageDefaultOptionKey = '__MESSAGE_OPTION__'
const None = Symbol('None')
// 默认模板
export const defaultOptions: MessageOptionsWithCallBack = {
title: '',
showCancelButton: false,
show: false,
closeOnClickModal: true,
msg: '',
type: 'alert',
inputType: 'text',
inputValue: '',
showErr: false,
zIndex: 99,
lazyRender: true,
inputError: ''
}
export function useMessage(selector: string = ''): Message {
const messageOptionKey = selector ? messageDefaultOptionKey + selector : messageDefaultOptionKey
const messageOption = inject(messageOptionKey, ref<MessageOptionsWithCallBack | typeof None>(None)) // Message选项
if (messageOption.value === None) {
messageOption.value = defaultOptions
provide(messageOptionKey, messageOption)
}
const createMethod = (type: MessageType) => {
// 优先级options->MessageOptions->defaultOptions
return (options: MessageOptions | string) => {
const messageOptions = deepMerge({ type: type }, typeof options === 'string' ? { title: options } : options) as MessageOptions
if (messageOptions.type === 'confirm' || messageOptions.type === 'prompt') {
messageOptions.showCancelButton = true
} else {
messageOptions.showCancelButton = false
}
return show(messageOptions)
}
}
const show = (option: MessageOptions | string) => {
// 返回一个promise
return new Promise<MessageResult>((resolve, reject) => {
const options = deepMerge(defaultOptions, typeof option === 'string' ? { title: option } : option)
messageOption.value = deepMerge(options, {
show: true,
success: (res: MessageResult) => {
close()
resolve(res)
},
fail: (res: MessageResult) => {
close()
reject(res)
}
})
})
}
// 打开Alert 弹框
const alert = createMethod('alert')
// 打开Confirm 弹框
const confirm = createMethod('confirm')
// 打开Prompt 弹框
const prompt = createMethod('prompt')
const close = () => {
if (messageOption.value !== None) {
messageOption.value.show = false
}
}
return {
show,
alert,
confirm,
prompt,
close
}
}
export const getMessageDefaultOptionKey = (selector: string) => {
return selector ? `${messageDefaultOptionKey}${selector}` : messageDefaultOptionKey
}

View File

@@ -0,0 +1,141 @@
/*
* @Author: weisheng
* @Date: 2024-04-08 22:34:01
* @LastEditTime: 2024-12-05 13:26:50
* @LastEditors: weisheng
* @Description:
* @FilePath: \wot-design-uni\src\uni_modules\wot-design-uni\components\wd-message-box\types.ts
* 记得注释
*/
import { baseProps, makeStringProp, makeBooleanProp } from '../common/props'
import type { ButtonProps } from '../wd-button/types'
import { type InputSize, type InputType } from '../wd-input/types'
export type MessageType = 'alert' | 'confirm' | 'prompt'
export type MessageBeforeConfirmOption = {
resolve: (isPass: boolean) => void
}
export type MessageOptions = {
/**
* 标题
*/
title?: string
/**
* 是否展示取消按钮
*/
showCancelButton?: boolean
/**
* 是否支持点击蒙层进行关闭点击蒙层回调传入的action为'modal'
*/
closeOnClickModal?: boolean
/**
* 确定按钮文案
*/
confirmButtonText?: string
/**
* 取消按钮文案
*/
cancelButtonText?: string
/**
* 消息文案
*/
msg?: string
/**
* 弹框类型
*/
type?: MessageType
/**
* 当type为prompt时输入框类型
*/
inputType?: InputType
/**
* 设置输入框大小可选值large
*/
inputSize?: InputSize
/**
* 当type为prompt时输入框初始值
*/
inputValue?: string | number
/**
* 当type为prompt时输入框placeholder
*/
inputPlaceholder?: string
/**
* 当type为prompt时输入框正则校验点击确定按钮时进行校验
*/
inputPattern?: RegExp
/**
* 当type为prompt时输入框校验函数点击确定按钮时进行校验
*/
inputValidate?: InputValidate
/**
* 当type为prompt时输入框检验不通过时的错误提示文案
*/
inputError?: string
/**
* 是否展示错误信息
*/
showErr?: boolean
/**
* 弹窗层级
*/
zIndex?: number
/**
* 弹层内容懒渲染,触发展示时才渲染内容
*/
lazyRender?: boolean
/**
* 确认前钩子
*/
beforeConfirm?: (options: MessageBeforeConfirmOption) => void
/**
* 取消按钮Props
*/
cancelButtonProps?: Partial<ButtonProps>
/**
* 确认按钮Props
*/
confirmButtonProps?: Partial<ButtonProps>
}
export type MessageOptionsWithCallBack = MessageOptions & {
show?: boolean
success?: (res: MessageResult) => void
fail?: (res: MessageResult) => void
}
export type ActionType = 'confirm' | 'cancel' | 'modal'
export type InputValidate = (inputValue: string | number) => boolean
export interface MessageResult {
action: ActionType
value?: string | number
}
export interface Message {
// 打开Message
show(toastOptions: MessageOptions | string): Promise<MessageResult>
// 打开Alert 弹框
alert(toastOptions: MessageOptions | string): Promise<MessageResult>
// 打开Confirm 弹框
confirm(toastOptions: MessageOptions | string): Promise<MessageResult>
// 打开Prompt 弹框
prompt(toastOptions: MessageOptions | string): Promise<MessageResult>
// 关闭Message
close(): void
}
export const messageBoxProps = {
...baseProps,
/**
* 指定唯一标识
*/
selector: makeStringProp(''),
/**
* 是否从页面中脱离出来,用于解决各种 fixed 失效问题 (H5: teleport, APP: renderjs, 小程序: root-portal)
*/
rootPortal: makeBooleanProp(false)
}

View File

@@ -0,0 +1,291 @@
<template>
<view>
<wd-popup
transition="zoom-in"
v-model="messageState.show"
:close-on-click-modal="messageState.closeOnClickModal"
:lazy-render="messageState.lazyRender"
custom-class="wd-message-box"
@click-modal="toggleModal('modal')"
:z-index="messageState.zIndex"
:duration="200"
:root-portal="rootPortal"
>
<view :class="rootClass">
<view :class="bodyClass">
<view v-if="messageState.title" class="wd-message-box__title">
{{ messageState.title }}
</view>
<view class="wd-message-box__content">
<block v-if="messageState.type === 'prompt'">
<wd-input
v-model="messageState.inputValue"
:type="messageState.inputType"
:size="messageState.inputSize"
:placeholder="messageState.inputPlaceholder"
@input="inputValChange"
/>
<view v-if="messageState.showErr" class="wd-message-box__input-error">
{{ messageState.inputError || translate('inputNoValidate') }}
</view>
</block>
<slot>{{ messageState.msg }}</slot>
</view>
</view>
<view :class="`wd-message-box__actions ${messageState.showCancelButton ? 'wd-message-box__flex' : 'wd-message-box__block'}`">
<wd-button v-bind="customCancelProps" v-if="messageState.showCancelButton" @click="toggleModal('cancel')">
{{ messageState.cancelButtonText || translate('cancel') }}
</wd-button>
<wd-button v-bind="customConfirmProps" @click="toggleModal('confirm')">
{{ messageState.confirmButtonText || translate('confirm') }}
</wd-button>
</view>
</view>
</wd-popup>
</view>
</template>
<script lang="ts">
export default {
name: 'wd-message-box',
options: {
virtualHost: true,
addGlobalClass: true,
styleIsolation: 'shared'
}
}
</script>
<script lang="ts" setup>
import wdPopup from '../wd-popup/wd-popup.vue'
import wdButton from '../wd-button/wd-button.vue'
import wdInput from '../wd-input/wd-input.vue'
import { computed, inject, reactive, ref, watch } from 'vue'
import { messageBoxProps, type MessageOptionsWithCallBack, type MessageResult } from './types'
import { defaultOptions, getMessageDefaultOptionKey } from '.'
import { deepAssign, isDef, isFunction, isUndefined, omitBy } from '../common/util'
import { useTranslate } from '../composables/useTranslate'
import type { ButtonProps } from '../wd-button/types'
const props = defineProps(messageBoxProps)
const { translate } = useTranslate('message-box')
const rootClass = computed(() => {
return `wd-message-box__container ${props.customClass}`
})
const bodyClass = computed(() => {
return `wd-message-box__body ${!messageState.title ? 'is-no-title' : ''} ${messageState.type === 'prompt' ? 'is-prompt' : ''}`
})
const messageOptionKey = getMessageDefaultOptionKey(props.selector)
const messageOption = inject(messageOptionKey, ref<MessageOptionsWithCallBack>(defaultOptions)) // message选项
const messageState = reactive<MessageOptionsWithCallBack>({
msg: '', // 消息内容
show: false, // 是否显示弹框
title: '', // 标题
showCancelButton: false, // 是否展示取消按钮
closeOnClickModal: true, // 是否支持点击蒙层关闭
confirmButtonText: '', // 确定按钮文案
cancelButtonText: '', // 取消按钮文案
type: 'alert', // 弹框类型
inputType: 'text', // 输入框类型
inputValue: '', // 输入框初始值
inputPlaceholder: '', // 输入框placeholder
inputError: '', // 输入框错误提示文案
showErr: false, // 是否显示错误提示
zIndex: 99, // 弹窗层级
lazyRender: true // 弹层内容懒渲染
})
/**
* 确认按钮属性
*/
const customConfirmProps = computed(() => {
const buttonProps: Partial<ButtonProps> = deepAssign(
{
block: true
},
isDef(messageState.confirmButtonProps) ? omitBy(messageState.confirmButtonProps, isUndefined) : {}
)
buttonProps.customClass = `${buttonProps.customClass || ''} wd-message-box__actions-btn`
return buttonProps
})
/**
* 取消按钮属性
*/
const customCancelProps = computed(() => {
const buttonProps: Partial<ButtonProps> = deepAssign(
{
block: true,
type: 'info'
},
isDef(messageState.cancelButtonProps) ? omitBy(messageState.cancelButtonProps, isUndefined) : {}
)
buttonProps.customClass = `${buttonProps.customClass || ''} wd-message-box__actions-btn`
return buttonProps
})
// 监听options变化展示
watch(
() => messageOption.value,
(newVal: MessageOptionsWithCallBack) => {
reset(newVal)
},
{
deep: true,
immediate: true
}
)
watch(
() => messageState.show,
(newValue) => {
resetErr(!!newValue)
},
{
deep: true,
immediate: true
}
)
/**
* 点击操作
* @param action
*/
function toggleModal(action: 'confirm' | 'cancel' | 'modal') {
if (action === 'modal' && !messageState.closeOnClickModal) {
return
}
if (messageState.type === 'prompt' && action === 'confirm' && !validate()) {
return
}
switch (action) {
case 'confirm':
if (messageState.beforeConfirm) {
messageState.beforeConfirm({
resolve: (isPass) => {
if (isPass) {
handleConfirm({
action: action,
value: messageState.inputValue
})
}
}
})
} else {
handleConfirm({
action: action,
value: messageState.inputValue
})
}
break
case 'cancel':
handleCancel({
action: action
})
break
default:
handleCancel({
action: 'modal'
})
break
}
}
/**
* 确认回调
* @param result
*/
function handleConfirm(result: MessageResult) {
messageState.show = false
if (isFunction(messageState.success)) {
messageState.success(result)
}
}
/**
* 取消回调
* @param result
*/
function handleCancel(result: MessageResult) {
messageState.show = false
if (isFunction(messageState.fail)) {
messageState.fail(result)
}
}
/**
* 如果存在校验规则行为,则进行判断校验是否通过规则。默认不存在校验直接铜鼓。
*/
function validate() {
if (messageState.inputPattern && !messageState.inputPattern.test(String(messageState.inputValue))) {
messageState.showErr = true
return false
}
if (typeof messageState.inputValidate === 'function') {
const validateResult = messageState.inputValidate(messageState.inputValue!)
if (!validateResult) {
messageState.showErr = true
return false
}
}
messageState.showErr = false
return true
}
/**
* @description show关闭时销毁错误提示
* @param val
*/
function resetErr(val: boolean) {
if (val === false) {
messageState.showErr = false
}
}
function inputValChange({ value }: { value: string | number }) {
if (value === '') {
messageState.showErr = false
return
}
messageState.inputValue = value
}
/**
* 重置message选项值
* @param option message选项值
*/
function reset(option: MessageOptionsWithCallBack) {
if (option) {
messageState.title = isDef(option.title) ? option.title : ''
messageState.showCancelButton = isDef(option.showCancelButton) ? option.showCancelButton : false
messageState.show = option.show
messageState.closeOnClickModal = option.closeOnClickModal
messageState.confirmButtonText = option.confirmButtonText
messageState.cancelButtonText = option.cancelButtonText
messageState.msg = option.msg
messageState.type = option.type
messageState.inputType = option.inputType
messageState.inputSize = option.inputSize
messageState.inputValue = option.inputValue
messageState.inputPlaceholder = option.inputPlaceholder
messageState.inputPattern = option.inputPattern!
messageState.inputValidate = option.inputValidate
messageState.success = option.success
messageState.fail = option.fail
messageState.beforeConfirm = option.beforeConfirm
messageState.inputError = option.inputError
messageState.showErr = option.showErr
messageState.zIndex = option.zIndex
messageState.lazyRender = option.lazyRender
messageState.confirmButtonProps = option.confirmButtonProps
messageState.cancelButtonProps = option.cancelButtonProps
}
}
</script>
<style lang="scss" scoped>
@import './index.scss';
</style>