376 lines
7.5 KiB
Vue
Raw Normal View History

2026-04-03 18:08:42 +08:00
<template>
<div
v-if="props.visible"
class="base-dialog-overlay"
:style="{ zIndex: props.zIndex }"
@click="handleOverlayClick"
>
<div class="base-dialog" @click.stop :style="{ maxWidth: `${props.maxWidth}px` }">
<!-- 四个角的装饰 -->
<div class="corner corner-top-left"></div>
<div class="corner corner-top-right"></div>
<div class="corner corner-bottom-left"></div>
<div class="corner corner-bottom-right"></div>
<!-- 标题栏 -->
<div class="dialog-header">
<div class="header-title">{{ props.title }}</div>
<div class="close-btn" @click="handleClose">
<el-icon><Close /></el-icon>
</div>
</div>
<!-- 标题栏下方自定义插槽 -->
<div class="header-slot">
<slot name="header"></slot>
</div>
<!-- 筛选区域 -->
<div class="filter-section" v-if="props.showFilter">
<slot name="filter"></slot>
</div>
<!-- 数据表格 -->
<div class="table-section" v-if="props.tableData.length > 0">
<el-table
:data="props.tableData"
:height="props.tableHeight"
style="width: 100%"
:header-cell-style="headerCellStyle"
:cell-style="cellStyle"
size="small"
>
<el-table-column
v-for="column in props.tableColumns"
:key="column.prop"
:prop="column.prop"
:label="column.label"
>
<template v-if="column.slot" #default="{ row }">
<slot :name="column.slot" :row="row"></slot>
</template>
</el-table-column>
</el-table>
</div>
<!-- 分页 -->
<div class="pagination" v-if="props.showPagination && props.tableData.length > 0">
<el-pagination
:current-page="props.currentPage"
:page-size="props.pageSize"
:page-sizes="props.pageSizes"
:total="props.total"
background
layout="prev, pager, next, jumper, ->, total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</div>
</div>
</template>
<script setup>
import { ref, watch } from "vue";
import { Close } from "@element-plus/icons-vue";
import { ElTable, ElTableColumn, ElPagination } from "element-plus";
const props = defineProps({
visible: {
type: Boolean,
default: false,
},
title: {
type: String,
default: "弹窗标题",
},
zIndex: {
type: Number,
default: 1000,
},
maxWidth: {
type: Number,
default: 1000,
},
showFilter: {
type: Boolean,
default: true,
},
showPagination: {
type: Boolean,
default: true,
},
tableData: {
type: Array,
default: () => [],
},
tableColumns: {
type: Array,
default: () => [],
},
tableHeight: {
type: Number,
default: 300,
},
currentPage: {
type: Number,
default: 1,
},
pageSize: {
type: Number,
default: 10,
},
pageSizes: {
type: Array,
default: () => [10, 20, 30, 40],
},
total: {
type: Number,
default: 0,
},
});
const emit = defineEmits(["update:visible", "close", "size-change", "current-change", "update:current-page", "update:page-size"]);
// 关闭对话框
const handleClose = () => {
emit("update:visible", false);
emit("close");
};
// 点击遮罩关闭
const handleOverlayClick = () => {
handleClose();
};
// 监听visible变化
watch(
() => props.visible,
(newVal) => {
if (newVal) {
// 弹窗打开时的逻辑
}
},
);
// 分页操作
const handleSizeChange = (val) => {
emit("update:page-size", val);
emit("size-change", val);
};
const handleCurrentChange = (val) => {
emit("update:current-page", val);
emit("current-change", val);
};
// 表格样式
const headerCellStyle = () => {
return {
backgroundColor: "#1D5194",
color: "#fff",
fontSize: "14px",
fontWeight: "500",
textAlign: "center",
padding: "5px 0px",
border: "none",
};
};
const cellStyle = () => {
return {
backgroundColor: "#16334E",
color: "rgba(255, 255, 255, 0.85)",
fontSize: "13px",
textAlign: "center",
padding: "5px 0px",
border: "none",
};
};
</script>
<style lang="scss" scoped>
.base-dialog-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.6);
display: flex;
align-items: center;
justify-content: center;
}
:deep(.el-table--small) {
background: #16334E;
}
.base-dialog {
width: 80vw;
max-height: 80vh;
position: relative;
background: #16334e;
border: 1px solid rgba(64, 169, 255, 0.3);
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
// 四个角的装饰
.corner {
position: absolute;
width: 20px;
height: 20px;
border: 1px solid #40a9ff;
z-index: 100;
pointer-events: none;
&.corner-top-left {
top: 0;
left: 0;
border-right: none;
border-bottom: none;
}
&.corner-top-right {
top: 0;
right: 0;
border-left: none;
border-bottom: none;
}
&.corner-bottom-left {
bottom: 0;
left: 0;
border-right: none;
border-top: none;
}
&.corner-bottom-right {
bottom: 0;
right: 0;
border-left: none;
border-top: none;
}
}
}
// 标题栏
.dialog-header {
display: flex;
align-items: center;
justify-content: center;
position: relative;
margin-bottom: 20px;
width: 100%;
.header-title {
background-image: url("../../../assets/RiskWarning_img/标题@2x.png");
background-size: 100% 100%;
background-position: right;
font-size: 18px;
font-weight: 600;
color: #fff;
width: 50%;
text-align: center;
padding: 12px 0;
}
.close-btn {
position: absolute;
right: 0;
top: 0;
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
color: rgba(255, 255, 255, 0.7);
cursor: pointer;
font-size: 20px;
transition: color 0.3s;
&:hover {
color: #fff;
}
}
}
// 标题栏下方自定义插槽
.header-slot {
margin-bottom: 20px;
padding: 0 24px;
overflow-y: auto;
max-height: 70vh;
scrollbar-width: none;
-ms-overflow-style: none;
&::-webkit-scrollbar {
display: none;
}
}
// 筛选区域
.filter-section {
margin-bottom: 16px;
padding: 0 24px;
}
// 表格区域
.table-section {
width: 100%;
padding: 0 24px;
background: #16334E
}
// 分页
.pagination {
display: flex;
align-items: center;
justify-content: flex-end;
gap: 16px;
padding: 12px;
background: #16334E;
:deep(.el-pagination) {
background: #16334E;
.el-pagination__total {
color: rgba(255, 255, 255, 0.6);
}
.el-pagination__sizes .el-input__inner {
background: #16334E;
border: 1px solid rgba(64, 169, 255, 0.3);
color: #fff;
}
.el-pagination__btn {
background: #16334E;
border: 1px solid rgba(64, 169, 255, 0.3);
color: rgba(255, 255, 255, 0.8);
&:hover:not(.is-disabled) {
background: rgba(64, 169, 255, 0.2);
}
}
.el-pagination__item {
background: #16334E;
border: 1px solid rgba(64, 169, 255, 0.3);
color: rgba(255, 255, 255, 0.8);
&:hover:not(.is-disabled) {
background: rgba(64, 169, 255, 0.2);
}
&.is-active {
background: #40a9ff;
border-color: #40a9ff;
}
}
.el-pagination__jump .el-input__inner {
background: #16334E;
border: 1px solid rgba(64, 169, 255, 0.3);
color: #fff;
}
}
}
</style>