Merge branch 'dev' into jiez1812/issue187
This commit is contained in:
@@ -9,11 +9,15 @@ interface Props {
|
||||
submitText?: string
|
||||
submitFunc?: () => void
|
||||
cancelFunc?: () => void
|
||||
footer?: null | 'center' | 'left' | 'right'
|
||||
dialogClass?: string // 添加动态class属性
|
||||
}
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
cancelText: i18n.global.t('button.cancel'),
|
||||
submitText: i18n.global.t('button.confirm'),
|
||||
cancelFunc: () => {},
|
||||
footer: 'right',
|
||||
dialogClass: '',
|
||||
})
|
||||
const visible = defineModel('visible', {
|
||||
type: Boolean,
|
||||
@@ -43,7 +47,7 @@ const { title, desc, cancelText, submitText, submitFunc, cancelFunc = defaultCan
|
||||
|
||||
<template>
|
||||
<dialog id="my_modal" ref="dialogRef" class="border-none modal">
|
||||
<div class="modal-box">
|
||||
<div class="modal-box" :class="[dialogClass]">
|
||||
<h3 v-if="title" class="text-lg font-bold">
|
||||
{{ title }}
|
||||
</h3>
|
||||
@@ -53,7 +57,7 @@ const { title, desc, cancelText, submitText, submitFunc, cancelFunc = defaultCan
|
||||
<div>
|
||||
<slot name="content" />
|
||||
</div>
|
||||
<div class="modal-action">
|
||||
<div class="modal-action" :class="{ 'flex justify-center': footer === 'center' }">
|
||||
<form method="dialog" class="flex gap-3">
|
||||
<!-- if there is a button in form, it will close the modal -->
|
||||
<button class="btn" @click="cancelFunc">
|
||||
|
||||
57
src/components/ErrorModal/index.ts
Normal file
57
src/components/ErrorModal/index.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import { createVNode, render } from 'vue'
|
||||
import ErrorModalVue from './index.vue'
|
||||
|
||||
// 定义弹窗调用函数
|
||||
function openModal(options = {}) {
|
||||
// 默认配置
|
||||
const defaultOptions = {
|
||||
title: '提示',
|
||||
desc: '',
|
||||
// 确认按钮回调
|
||||
onConfirm: () => {},
|
||||
// 关闭按钮回调
|
||||
onClose: () => {},
|
||||
}
|
||||
|
||||
// 合并配置
|
||||
const finalOptions = { ...defaultOptions, ...options }
|
||||
|
||||
// 创建容器
|
||||
const container = document.createElement('div')
|
||||
|
||||
// 创建虚拟节点
|
||||
const vnode = createVNode(ErrorModalVue, {
|
||||
'title': finalOptions.title,
|
||||
'desc': finalOptions.desc,
|
||||
'modelValue': true, // 默认打开
|
||||
'onUpdate:modelValue': (val: any) => {
|
||||
if (!val) {
|
||||
// 关闭时销毁组件
|
||||
render(null, container)
|
||||
document.body.removeChild(container)
|
||||
}
|
||||
},
|
||||
'onConfirm': () => {
|
||||
finalOptions.onConfirm()
|
||||
},
|
||||
'onClose': () => {
|
||||
finalOptions.onClose()
|
||||
},
|
||||
})
|
||||
|
||||
// 渲染组件到容器
|
||||
render(vnode, container)
|
||||
|
||||
// 将容器添加到body
|
||||
document.body.appendChild(container)
|
||||
|
||||
// 返回关闭方法(可选)
|
||||
return {
|
||||
close: () => {
|
||||
render(null, container)
|
||||
document.body.removeChild(container)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export default openModal
|
||||
127
src/components/ErrorModal/index.vue
Normal file
127
src/components/ErrorModal/index.vue
Normal file
@@ -0,0 +1,127 @@
|
||||
<script setup>
|
||||
import { Dialog, DialogDescription, DialogPanel, DialogTitle } from '@headlessui/vue'
|
||||
import { CircleAlert } from 'lucide-vue-next'
|
||||
import { defineEmits, defineProps, ref, watch } from 'vue'
|
||||
// 定义组件属性
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '提示',
|
||||
},
|
||||
desc: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
// 控制弹窗显隐
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
})
|
||||
|
||||
// 定义事件
|
||||
const emit = defineEmits(['update:modelValue', 'close'])
|
||||
|
||||
// 内部显隐状态
|
||||
const visible = ref(props.modelValue)
|
||||
|
||||
// 同步外部 modelValue 变化
|
||||
watch(() => props.modelValue, (val) => {
|
||||
visible.value = val
|
||||
})
|
||||
|
||||
// 关闭弹窗
|
||||
function handleClose() {
|
||||
visible.value = false
|
||||
emit('update:modelValue', false)
|
||||
emit('close')
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<teleport to="body">
|
||||
<Dialog :open="visible" class="relative z-50" @close="handleClose">
|
||||
<!-- The backdrop, rendered as a fixed sibling to the panel container -->
|
||||
<div class="fixed inset-0 bg-black/30" aria-hidden="true" />
|
||||
<!-- Full-screen container to center the panel -->
|
||||
<div class="fixed inset-0 flex w-screen items-center justify-center p-4">
|
||||
<DialogPanel class="max-w-sm rounded bg-base-100 w-9/10 p-6 shadow-md">
|
||||
<DialogTitle class="font-bold text-lg">
|
||||
<p class="w-full flex items-center gap-2">
|
||||
<CircleAlert class="text-red-500" />
|
||||
<span>
|
||||
{{ title || '提示' }}
|
||||
</span>
|
||||
</p>
|
||||
</DialogTitle>
|
||||
<DialogDescription class="py-4">
|
||||
{{ desc }}
|
||||
</DialogDescription>
|
||||
<div class="mr-4 mt-4 flex justify-end">
|
||||
<button class="btn" @click="handleClose">
|
||||
确定
|
||||
</button>
|
||||
</div>
|
||||
</DialogPanel>
|
||||
</div>
|
||||
</Dialog>
|
||||
</teleport>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.modal-mask {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.modal-container {
|
||||
width: 400px;
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
border-bottom: 1px solid #eee;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
.modal-header button {
|
||||
background: transparent;
|
||||
border: none;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.modal-footer button {
|
||||
padding: 6px 12px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.modal-footer button:first-child {
|
||||
background: #409eff;
|
||||
color: #fff;
|
||||
border-color: #409eff;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user