Files
taimed-international-app/uni_modules/wot-design-uni/components/wd-message-box/wd-message-box.vue
2025-11-04 12:37:04 +08:00

292 lines
8.4 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<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>