vue文件,用于编写弹窗组件样式
html
<template>
<div class='custom_pop_container'>
<!-- 遮罩层 -->
<div class='mask_layer'></div>
<!-- 弹窗内容 -->
<div class="custom_pop_content">
<!-- 标题 -->
<div class="custom_pop_title">
<img :src="iconUrl" class="pop_icon_box">
{{ title }}
</div>
<!-- 内容 -->
<div class="custom_pop_content_text">{{ content }}</div>
<!-- 按钮 -->
<div class="custom_pop_content_buttons">
<button class="cancel_button button_style" @click="onCancel">{{ cancelButtonText }}</button>
<button class="confirm_button button_style" @click="onConfirm">{{ confirmButtonText }}</button>
</div>
</div>
</div>
</template>
<script setup lang='ts'>
// 响应式数据
import { getAssetsFile } from '@/utils/utils';
import { ref, reactive, computed, watch } from 'vue'
interface IProps {
title: string;
content: string;
iconUrl?: string;
confirmButtonText?: string;
cancelButtonText?: string;
showFooter?: boolean;
onConfirm?: () => void;
onCancel?: () => void;
}
const props = withDefaults(defineProps<IProps>(), {
content: '',
iconUrl: getAssetsFile('chat/pop_icon.png'),
confirmButtonText: '确认',
cancelButtonText: '取消',
showFooter: true,
onConfirm: () => { },
onCancel: () => { },
})
</script>
<style scoped lang='scss'>
.custom_pop_container {
width: 100vw;
height: 100vh;
position: fixed;
top: 0;
left: 0;
z-index: 1000;
.mask_layer {
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.4);
position: absolute;
top: 0;
left: 0;
}
.custom_pop_content {
width: 418px;
background-color: #F8F9FB;
border-radius: 12px;
padding: 24px 20px 20px 20px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
.custom_pop_title {
display: flex;
align-items: center;
font-weight: 500;
font-size: 16px;
color: #303133;
line-height: 24px;
margin-bottom: 20px;
.pop_icon_box {
width: 16px;
height: 16px;
object-fit: cover;
margin-right: 4px;
}
}
.custom_pop_content_text {
font-weight: 400;
font-size: 14px;
color: #303133;
line-height: 22px;
}
.custom_pop_content_buttons {
display: flex;
justify-content: flex-end;
column-gap: 12px;
margin-top: 40px;
.button_style {
display: inline-flex;
justify-content: center;
align-items: center;
width: 68px;
height: 32px;
padding: 8px 15px;
font-size: 14px;
font-weight: 500;
line-height: 1;
border-radius: 4px;
border: 1px solid;
cursor: pointer;
outline: none;
transition: 0.1s;
appearance: none;
-webkit-appearance: none;
box-sizing: border-box;
}
.cancel_button {
color: #606266;
background-color: #fff;
border-color: #dcdfe6;
&:hover {
color: #409eff;
border-color: #c6e2ff;
background-color: #ecf5ff;
}
&:active {
color: #3a8ee6;
border-color: #3a8ee6;
background-color: #d9ecff;
}
}
.confirm_button {
color: #fff;
background-color: #409eff;
border-color: #409eff;
&:hover {
background-color: #66b1ff;
border-color: #66b1ff;
}
&:active {
background-color: #3a8ee6;
border-color: #3a8ee6;
}
}
}
}
}
</style>
ts文件,把弹窗组件渲染出来
typescript
import CustomPopCom from './CustomPopCom.vue';
import { createVNode, render } from 'vue';
let customPopDom = null;
export const useCustomPop = (userOptions: any) => {
let options = {
...userOptions,
}
options.onCancel = () => {
userOptions.onCancel && userOptions.onCancel(); //用户的关闭函数
closeCustomPop();
}
options.onConfirm = () => {
userOptions.onConfirm && userOptions.onConfirm(); //用户的确认函数
closeCustomPop();
}
// 获取到虚拟dom
const vnode = createVNode(CustomPopCom, options);
customPopDom = document.createElement('div');
render(vnode, customPopDom);
// 渲染到body中
document.body.appendChild(customPopDom);
}
export const closeCustomPop = () => {
customPopDom && document.body.removeChild(customPopDom);
}
在vue文件中使用
typescript
useCustomPop({
title: '删除会话',
content: '删除后无法恢复,是否继续删除?',
confirmButtonText: '确定',
cancelButtonText: '取消',
onConfirm: () => {
deleteAgentChat({
user_id: userStore.userInfo?.id,
session_id: item.session_id,
}).then(res => {
ElMessage.success("删除会话成功");
getGroupChatListFun();
})
},
})