feat(弹窗组件): 新增纯信息弹窗showMessage
This commit is contained in:
parent
7b9472258b
commit
9cf9464d9c
@ -1,19 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="visible" class="modal-overlay" @click="handleOverlayClick">
|
<div v-if="visible" class="modal-overlay" @click="handleOverlayClick">
|
||||||
<div class="modal" :class="[animationClass, modalTypeClass]">
|
<div class="modal" :class="[animationClass, modalTypeClass]">
|
||||||
<!-- 图标 -->
|
<!-- 图标 - simple 类型不显示 -->
|
||||||
<div class="modal-icon">
|
<div class="modal-icon" v-if="!isSimple">
|
||||||
<div class="icon-circle" :class="iconCircleClass">
|
<div class="icon-circle" :class="iconCircleClass">
|
||||||
<span class="icon-symbol" :class="iconSymbolClass">{{ iconSymbol }}</span>
|
<span class="icon-symbol" :class="iconSymbolClass">{{ iconSymbol }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 标题 -->
|
<!-- 标题 - simple 类型不显示 -->
|
||||||
<div class="modal-title" v-if="title">{{ title }}</div>
|
<div class="modal-title" v-if="title && !isSimple">{{ title }}</div>
|
||||||
|
|
||||||
<!-- 消息内容 -->
|
<!-- 消息内容 -->
|
||||||
<div class="modal-message">{{ message }}</div>
|
<div class="modal-message">{{ message }}</div>
|
||||||
|
|
||||||
<!-- 按钮 -->
|
<!-- 按钮 -->
|
||||||
<div class="modal-actions">
|
<div class="modal-actions">
|
||||||
<button class="modal-btn" :class="buttonClass" @click="confirm">{{ confirmText }}</button>
|
<button class="modal-btn" :class="buttonClass" @click="confirm">{{ confirmText }}</button>
|
||||||
@ -28,29 +28,29 @@ import { ref, onMounted, computed } from 'vue'
|
|||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
title: {
|
title: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'Notice'
|
default: 'Notice',
|
||||||
},
|
},
|
||||||
message: {
|
message: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
type: {
|
type: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'error', // 'error' | 'warning' | 'success' | 'info'
|
default: 'error', // 'error' | 'warning' | 'success' | 'info'
|
||||||
validator: (value) => ['error', 'warning', 'success', 'info'].includes(value)
|
validator: (value) => ['error', 'warning', 'success', 'info', 'simple'].includes(value), // 新增 simple
|
||||||
},
|
},
|
||||||
confirmText: {
|
confirmText: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'OK'
|
default: 'OK',
|
||||||
},
|
},
|
||||||
clickToClose: {
|
clickToClose: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true,
|
||||||
},
|
},
|
||||||
duration: {
|
duration: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: null // 自动关闭时间(毫秒)
|
default: null, // 自动关闭时间(毫秒)
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['confirm', 'close'])
|
const emit = defineEmits(['confirm', 'close'])
|
||||||
@ -58,13 +58,16 @@ const emit = defineEmits(['confirm', 'close'])
|
|||||||
const visible = ref(false)
|
const visible = ref(false)
|
||||||
const animationClass = ref('')
|
const animationClass = ref('')
|
||||||
|
|
||||||
|
// 新增计算属性,判断是否显示图标和标题
|
||||||
|
const isSimple = computed(() => props.type === 'simple')
|
||||||
|
|
||||||
// 根据类型计算图标和样式
|
// 根据类型计算图标和样式
|
||||||
const iconSymbol = computed(() => {
|
const iconSymbol = computed(() => {
|
||||||
const symbols = {
|
const symbols = {
|
||||||
error: '✕',
|
error: '✕',
|
||||||
warning: '⚠',
|
warning: '⚠',
|
||||||
success: '✓',
|
success: '✓',
|
||||||
info: 'i'
|
info: 'i',
|
||||||
}
|
}
|
||||||
return symbols[props.type] || symbols.error
|
return symbols[props.type] || symbols.error
|
||||||
})
|
})
|
||||||
@ -80,7 +83,7 @@ const buttonClass = computed(() => `modal-btn-${props.type}`)
|
|||||||
const show = () => {
|
const show = () => {
|
||||||
visible.value = true
|
visible.value = true
|
||||||
animationClass.value = 'modal-enter'
|
animationClass.value = 'modal-enter'
|
||||||
|
|
||||||
// 如果设置了自动关闭时间
|
// 如果设置了自动关闭时间
|
||||||
if (props.duration && props.duration > 0) {
|
if (props.duration && props.duration > 0) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -116,7 +119,7 @@ onMounted(() => {
|
|||||||
// 暴露方法给父组件
|
// 暴露方法给父组件
|
||||||
defineExpose({
|
defineExpose({
|
||||||
show,
|
show,
|
||||||
close
|
close,
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -139,7 +142,9 @@ defineExpose({
|
|||||||
.modal {
|
.modal {
|
||||||
background: white;
|
background: white;
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
box-shadow: 0 20px 25px rgba(0, 0, 0, 0.1), 0 10px 10px rgba(0, 0, 0, 0.04);
|
box-shadow:
|
||||||
|
0 20px 25px rgba(0, 0, 0, 0.1),
|
||||||
|
0 10px 10px rgba(0, 0, 0, 0.04);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 320px;
|
max-width: 320px;
|
||||||
padding: 24px 20px 20px;
|
padding: 24px 20px 20px;
|
||||||
@ -175,7 +180,7 @@ defineExpose({
|
|||||||
.modal-title {
|
.modal-title {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #1F2937;
|
color: #1f2937;
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
}
|
}
|
||||||
@ -183,7 +188,7 @@ defineExpose({
|
|||||||
/* 消息内容 */
|
/* 消息内容 */
|
||||||
.modal-message {
|
.modal-message {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #6B7280;
|
color: #6b7280;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
@ -213,52 +218,52 @@ defineExpose({
|
|||||||
|
|
||||||
/* Error 类型样式 */
|
/* Error 类型样式 */
|
||||||
.modal-error .icon-circle-error {
|
.modal-error .icon-circle-error {
|
||||||
background-color: #FEE2E2;
|
background-color: #fee2e2;
|
||||||
border-color: #FECACA;
|
border-color: #fecaca;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-error .icon-symbol-error {
|
.modal-error .icon-symbol-error {
|
||||||
color: #DC2626;
|
color: #dc2626;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-error .modal-btn-error {
|
.modal-error .modal-btn-error {
|
||||||
background-color: #DC2626;
|
background-color: #dc2626;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-error .modal-btn-error:hover {
|
.modal-error .modal-btn-error:hover {
|
||||||
background-color: #B91C1C;
|
background-color: #b91c1c;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-error .modal-btn-error:active {
|
.modal-error .modal-btn-error:active {
|
||||||
background-color: #991B1B;
|
background-color: #991b1b;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Warning 类型样式 */
|
/* Warning 类型样式 */
|
||||||
.modal-warning .icon-circle-warning {
|
.modal-warning .icon-circle-warning {
|
||||||
background-color: #FEF3C7;
|
background-color: #fef3c7;
|
||||||
border-color: #FDE68A;
|
border-color: #fde68a;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-warning .icon-symbol-warning {
|
.modal-warning .icon-symbol-warning {
|
||||||
color: #D97706;
|
color: #d97706;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-warning .modal-btn-warning {
|
.modal-warning .modal-btn-warning {
|
||||||
background-color: #D97706;
|
background-color: #d97706;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-warning .modal-btn-warning:hover {
|
.modal-warning .modal-btn-warning:hover {
|
||||||
background-color: #B45309;
|
background-color: #b45309;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-warning .modal-btn-warning:active {
|
.modal-warning .modal-btn-warning:active {
|
||||||
background-color: #92400E;
|
background-color: #92400e;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Success 类型样式 */
|
/* Success 类型样式 */
|
||||||
.modal-success .icon-circle-success {
|
.modal-success .icon-circle-success {
|
||||||
background-color: #D1FAE5;
|
background-color: #d1fae5;
|
||||||
border-color: #A7F3D0;
|
border-color: #a7f3d0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-success .icon-symbol-success {
|
.modal-success .icon-symbol-success {
|
||||||
@ -274,29 +279,48 @@ defineExpose({
|
|||||||
}
|
}
|
||||||
|
|
||||||
.modal-success .modal-btn-success:active {
|
.modal-success .modal-btn-success:active {
|
||||||
background-color: #065F46;
|
background-color: #065f46;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Info 类型样式 */
|
/* Info 类型样式 */
|
||||||
.modal-info .icon-circle-info {
|
.modal-info .icon-circle-info {
|
||||||
background-color: #DBEAFE;
|
background-color: #dbeafe;
|
||||||
border-color: #BFDBFE;
|
border-color: #bfdbfe;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-info .icon-symbol-info {
|
.modal-info .icon-symbol-info {
|
||||||
color: #2563EB;
|
color: #2563eb;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-info .modal-btn-info {
|
.modal-info .modal-btn-info {
|
||||||
background-color: #2563EB;
|
background-color: #2563eb;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-info .modal-btn-info:hover {
|
.modal-info .modal-btn-info:hover {
|
||||||
background-color: #1D4ED8;
|
background-color: #1d4ed8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-info .modal-btn-info:active {
|
.modal-info .modal-btn-info:active {
|
||||||
background-color: #1E40AF;
|
background-color: #1e40af;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 新增 simple 类型样式 */
|
||||||
|
.modal-simple .modal-message {
|
||||||
|
font-size: 15px;
|
||||||
|
color: #374151;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-simple .modal-btn {
|
||||||
|
background-color: #2563eb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-simple .modal-btn:hover {
|
||||||
|
background-color: #1d4ed8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-simple .modal-btn:active {
|
||||||
|
background-color: #1e40af;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 动画效果 */
|
/* 动画效果 */
|
||||||
@ -350,20 +374,20 @@ defineExpose({
|
|||||||
max-width: 280px;
|
max-width: 280px;
|
||||||
padding: 20px 16px 16px;
|
padding: 20px 16px 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-circle {
|
.icon-circle {
|
||||||
width: 48px;
|
width: 48px;
|
||||||
height: 48px;
|
height: 48px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-symbol {
|
.icon-symbol {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-title {
|
.modal-title {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-message {
|
.modal-message {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -109,6 +109,15 @@ export const showToast = (message, options = {}) => {
|
|||||||
return errorModal.show(message, defaultOptions)
|
return errorModal.show(message, defaultOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const showMessage = (message, options = {}) => {
|
||||||
|
const defaultOptions = {
|
||||||
|
confirmText: i18n.global.t('ok') || 'OK',
|
||||||
|
type: 'simple',
|
||||||
|
...options,
|
||||||
|
}
|
||||||
|
return errorModal.show(message, defaultOptions)
|
||||||
|
}
|
||||||
|
|
||||||
// 错误处理的专用方法
|
// 错误处理的专用方法
|
||||||
export const handleError = (error) => {
|
export const handleError = (error) => {
|
||||||
let message = i18n.global.t('unknown_error') || 'An unknown error occurred'
|
let message = i18n.global.t('unknown_error') || 'An unknown error occurred'
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user