更新:登录功能
This commit is contained in:
108
uni_modules/wot-design-uni/components/wd-message-box/index.scss
Normal file
108
uni_modules/wot-design-uni/components/wd-message-box/index.scss
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
141
uni_modules/wot-design-uni/components/wd-message-box/types.ts
Normal file
141
uni_modules/wot-design-uni/components/wd-message-box/types.ts
Normal 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)
|
||||
}
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user