项目初始化

This commit is contained in:
2026-03-25 17:47:51 +08:00
parent 754c9992eb
commit 39db00e022
4 changed files with 1229 additions and 15 deletions

View File

@@ -0,0 +1,197 @@
<template>
<div ref="hostCardRef" class="host-card">
<div class="card-title">
<span>主机信息</span>
</div>
<div class="card-content">
<div class="gauge-list">
<div v-for="item in gauges" :key="item.label" class="gauge-item">
<div :ref="(el) => setChartRef(el, item.label)" class="gauge-chart"></div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';
import * as echarts from 'echarts';
const gauges = ref([
{ label: 'CPU系统使用率', value: 79, color: '#3b82f6' },
{ label: 'CPU用户使用率', value: 68, color: '#10b981' },
{ label: 'CPU利用率', value: 82, color: '#ef4444' },
]);
const chartInstances = new Map();
const chartRefs = new Map();
const hostCardRef = ref<HTMLElement>();
let resizeObserver: ResizeObserver | null = null;
function resizeCharts() {
chartInstances.forEach((chart) => {
chart.resize();
});
}
function setChartRef(el: any, label: string) {
if (el) chartRefs.set(label, el);
}
onMounted(() => {
gauges.value.forEach((item) => {
const el = chartRefs.get(item.label);
if (!el) return;
const chart = echarts.init(el);
chart.setOption({
series: [
{
type: 'gauge',
startAngle: 200,
endAngle: -20,
radius: '75%',
center: ['50%', '50%'],
min: 0,
max: 100,
splitNumber: 5,
axisLine: {
lineStyle: {
width: 10,
color: [
[item.value / 100, item.color],
[1, '#e5e7eb'],
],
},
},
pointer: {
length: '55%',
width: 4,
itemStyle: { color: item.color },
},
axisTick: { show: false },
splitLine: {
length: 8,
lineStyle: { color: '#fff', width: 2 },
},
axisLabel: {
show: false,
},
title: {
show: true,
offsetCenter: [0, '120%'],
fontSize: 11,
color: '#666',
},
detail: {
valueAnimation: true,
formatter: '{value}%',
color: item.color,
fontSize: 16,
fontWeight: 'bold',
offsetCenter: [0, '0%'],
},
data: [{ value: item.value, name: item.label }],
},
],
});
chartInstances.set(item.label, chart);
});
if (hostCardRef.value) {
resizeObserver = new ResizeObserver(() => {
resizeCharts();
});
resizeObserver.observe(hostCardRef.value);
}
window.addEventListener('resize', resizeCharts);
});
onUnmounted(() => {
resizeObserver?.disconnect();
window.removeEventListener('resize', resizeCharts);
chartInstances.forEach((chart) => chart.dispose());
});
</script>
<style lang="less">
@dark-bg: #141414;
.host-card {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
box-sizing: border-box;
overflow: hidden;
.card-title {
display: flex;
align-items: center;
justify-content: space-between;
padding: 8px 16px;
font-size: 14px;
font-weight: 500;
line-height: 20px;
color: rgb(51 65 85);
border-bottom: 1px solid rgb(226 232 240);
background: transparent;
}
.card-content {
flex: 1;
min-height: 0;
padding: 16px;
color: rgb(71 85 105);
font-size: 14px;
line-height: 22px;
overflow: auto;
background: transparent;
}
.gauge-list {
display: flex;
justify-content: space-around;
align-items: center;
gap: 12px;
height: 100%;
}
.gauge-item {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
}
.gauge-chart {
width: 100%;
height: 140px;
max-width: 140px;
}
.gauge-label {
font-size: 11px;
color: rgb(100 116 139);
text-align: center;
}
}
html[data-theme='dark'] .host-card {
box-shadow: none;
.card-title {
color: rgb(203 213 225);
border-bottom-color: rgb(51 65 85);
}
.card-content {
color: rgb(148 163 184);
}
.gauge-label {
color: rgb(148 163 184);
}
}
</style>

View File

@@ -0,0 +1,725 @@
<template>
<div class="notice-card">
<div class="card-title">
<span>通知消息</span>
<div class="card-tabs">
<button
v-for="item in tabs"
:key="item.key"
:class="['tab-item', { active: activeTab === item.key }]"
@click="activeTab = item.key"
>
{{ item.label }}
</button>
</div>
</div>
<div class="card-content">
<div ref="tableWrapRef" class="table-container">
<el-table :data="currentList" :height="tableHeight" :show-header="true" :border="false">
<el-table-column prop="title" label="标题" min-width="120">
<template #default="{ row }">
<el-button class="notice-title-button" link type="primary" @click="openNoticeDialog(row)">
{{ row.title }}
</el-button>
</template>
</el-table-column>
<el-table-column prop="time" label="时间" width="180" />
<el-table-column prop="content" label="内容" min-width="200" show-overflow-tooltip="true" />
</el-table>
</div>
</div>
<el-dialog v-model="dialogVisible" class="notice-info-dialog" title="通知详情" width="60%" destroy-on-close>
<template v-if="selectedNotice">
<div class="notice-dialog">
<div class="notice-dialog__header">
<div class="notice-dialog__title">{{ selectedNotice.title }}</div>
<div class="notice-dialog__header-divider"></div>
<div class="notice-dialog__time">{{ selectedNotice.time }}</div>
</div>
<el-divider class="notice-dialog__divider" />
<div class="notice-dialog__content-panel">
<div class="notice-dialog__content" v-html="selectedNotice.content"></div>
</div>
<div v-if="selectedNotice.attachments?.length" class="notice-dialog__attachments-panel">
<div class="notice-dialog__attachments-title">附件区域</div>
<div class="notice-dialog__attachments-list">
<div
v-for="attachment in selectedNotice.attachments"
:key="attachment"
class="notice-dialog__attachment-item"
>
<div class="notice-dialog__attachment-meta">
<el-icon class="notice-dialog__attachment-icon"><Document /></el-icon>
<span class="notice-dialog__attachment-name">{{ attachment }}</span>
</div>
<div class="notice-dialog__attachment-actions">
<span class="notice-dialog__attachment-size">{{ getAttachmentSize(attachment) }}</span>
<el-button
class="notice-dialog__attachment-download"
type="primary"
link
:icon="Download"
@click.stop="handleAttachmentDownload(attachment)"
>下载</el-button
>
</div>
</div>
</div>
</div>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { ElMessage } from 'element-plus';
import { Document, Download } from '@element-plus/icons-vue';
import { computed, nextTick, onBeforeUnmount, onMounted, ref } from 'vue';
interface NoticeItem {
title: string;
time: string;
content: string;
attachments?: string[];
}
const tabs = [
{ key: '0', label: '未读' },
{ key: '1', label: '已读' },
];
const activeTab = ref('0');
const noticeData: Record<string, NoticeItem[]> = {
0: [
{
title: '系统升级通知',
time: '2025-03-25 10:00',
content: '<p>系统将于今晚进行升级维护,请提前保存工作内容。</p><p><strong>维护时间:</strong>23:00 - 02:00</p>',
attachments: [
'升级说明.pdf',
'影响范围清单.xlsx',
'系统切换流程.docx',
'升级回退预案.pdf',
'服务影响通知单.xls',
'值班安排表.doc',
'数据库检查项.txt',
],
},
{
title: '安全检查提醒',
time: '2025-03-25 09:30',
content:
'<p>请及时完成本周安全检查任务,确保系统运行稳定。</p><ul><li>检查设备运行状态</li><li>确认日志采集是否正常</li></ul>',
attachments: ['安全检查模板.docx', '巡检项清单.pdf', '整改说明.docx', '告警记录.xlsx'],
},
{
title: '备份任务完成',
time: '2025-03-25 08:15',
content: '<p>数据库备份任务已完成,备份文件已存储至指定位置。</p>',
attachments: [],
},
],
1: [
{
title: '巡检报告提交',
time: '2025-03-24 16:20',
content: '<p>昨日巡检报告已提交并审核通过。</p><p>请相关负责人及时查看结果。</p>',
attachments: ['巡检报告-0324.pdf'],
},
{
title: '权限变更通知',
time: '2025-03-24 14:10',
content: '<p>用户权限调整已生效,请相关人员知悉。</p>',
attachments: [],
},
],
};
const currentList = computed(() => noticeData[activeTab.value] || []);
const tableWrapRef = ref<HTMLElement>();
const tableHeight = ref(0);
const dialogVisible = ref(false);
const selectedNotice = ref<NoticeItem | null>(null);
let resizeObserver: ResizeObserver | null = null;
function openNoticeDialog(notice: NoticeItem) {
selectedNotice.value = notice;
dialogVisible.value = true;
}
function handleAttachmentDownload(attachment: string) {
ElMessage.info(`待接入下载地址:${attachment}`);
}
function getAttachmentSize(attachment: string) {
const seed = attachment.split('').reduce((total, char) => total + char.charCodeAt(0), 0);
return `${((seed % 9000) / 100 + 0.8).toFixed(2)} MB`;
}
function updateTableHeight() {
nextTick(() => {
const tableWrapEl = tableWrapRef.value;
if (!tableWrapEl) return;
tableHeight.value = Math.max(tableWrapEl.clientHeight, 0);
});
}
onMounted(() => {
updateTableHeight();
if (tableWrapRef.value) {
resizeObserver = new ResizeObserver(() => {
updateTableHeight();
});
resizeObserver.observe(tableWrapRef.value);
}
});
onBeforeUnmount(() => {
resizeObserver?.disconnect();
});
</script>
<style lang="less">
@dark-bg: #141414;
.notice-card {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
box-sizing: border-box;
overflow: hidden;
.card-title {
display: flex;
align-items: center;
justify-content: space-between;
padding: 8px 16px;
font-size: 14px;
font-weight: 500;
line-height: 20px;
color: rgb(51 65 85);
border-bottom: 1px solid rgb(226 232 240);
background: transparent;
}
.card-tabs {
display: flex;
gap: 8px;
}
.tab-item {
position: relative;
padding: 4px 8px;
border: none;
background: transparent;
color: rgb(100 116 139);
font-size: 12px;
cursor: pointer;
transition: all 0.2s;
&.active {
color: rgb(30 41 59);
&::after {
content: '';
position: absolute;
left: 0;
right: 0;
bottom: -2px;
height: 2px;
background: rgb(59 130 246);
}
}
}
.card-content {
flex: 1;
min-height: 0;
padding: 8px 12px 12px;
color: rgb(71 85 105);
font-size: 14px;
line-height: 22px;
overflow: hidden;
background: transparent;
display: flex;
flex-direction: column;
.table-container {
flex: 1;
min-height: 0;
width: 100%;
height: 100%;
overflow: hidden;
display: flex;
flex-direction: column;
.el-table {
width: 100%;
--el-table-border-color: transparent;
--el-table-header-bg-color: rgb(248, 250, 252);
--el-table-tr-bg-color: transparent;
--el-table-row-hover-bg-color: rgb(241 245 249);
--el-table-text-color: rgb(71 85 105);
--el-table-header-text-color: rgb(51 65 85);
background: transparent;
&::before,
&::after,
.el-table__inner-wrapper::before,
.el-table__border-left-patch {
display: none;
}
th.el-table__cell,
td.el-table__cell {
border-right: none;
border-left: none;
border-bottom: 1px solid rgb(226 232 240);
}
th.el-table__cell {
background: rgb(248, 250, 252);
}
td.el-table__cell,
th.el-table__cell {
padding: 8px 0;
}
.cell {
line-height: 20px;
}
.notice-title-button {
padding: 0;
font-weight: 500;
text-align: left;
white-space: normal;
word-break: break-all;
}
}
}
}
.notice-dialog {
display: flex;
flex-direction: column;
gap: 0;
&__header {
display: flex;
flex-direction: column;
gap: 8px;
}
&__header-divider {
width: 100%;
height: 1px;
background: rgb(226 232 240);
}
&__divider {
margin: 16px 0;
}
&__content-panel,
&__attachments-panel {
padding: 2px;
border: none;
border-radius: 8px;
background: rgb(248 252 255);
box-sizing: border-box;
}
&__attachments-panel {
margin-top: 16px;
padding: 12px;
border: 1px solid rgb(219 234 254);
background: rgb(248 252 255);
}
&__title {
font-size: 18px;
font-weight: 600;
color: rgb(30 41 59);
text-align: center;
}
&__time {
font-size: 13px;
color: rgb(100 116 139);
text-align: right;
}
&__content {
min-height: 220px;
max-height: 320px;
padding: 14px 16px;
border: 1px solid rgb(191 219 254);
border-radius: 6px;
background: rgb(255 255 255);
font-size: 14px;
line-height: 24px;
color: rgb(51 65 85);
overflow-y: auto;
scrollbar-width: thin;
scrollbar-color: rgb(191 219 254) transparent;
white-space: pre-wrap;
word-break: break-all;
&::-webkit-scrollbar {
width: 6px;
}
&::-webkit-scrollbar-track {
background: transparent;
}
&::-webkit-scrollbar-thumb {
border-radius: 999px;
background: rgb(191 219 254);
}
:deep(p) {
margin: 0 0 8px;
}
:deep(ul) {
margin: 0;
padding-left: 20px;
}
:deep(li) {
margin: 4px 0;
}
}
&__attachments {
margin-top: 0;
}
&__attachments-title {
display: flex;
align-items: center;
width: 100%;
min-height: 36px;
margin-bottom: 12px;
padding: 0 12px;
border: none;
border-radius: 6px;
background: rgb(239 246 255);
font-size: 14px;
font-weight: 600;
color: rgb(51 65 85);
box-sizing: border-box;
}
&__attachments-list {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 8px;
max-height: 132px;
overflow-y: auto;
padding-right: 2px;
scrollbar-width: thin;
scrollbar-color: rgb(191 219 254) transparent;
}
&__attachments-list::-webkit-scrollbar {
width: 6px;
}
&__attachments-list::-webkit-scrollbar-track {
background: transparent;
}
&__attachments-list::-webkit-scrollbar-thumb {
border-radius: 999px;
background: rgb(191 219 254);
}
&__attachment-item,
&__attachments-empty {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
padding: 10px 12px;
border: 1px solid rgb(219 234 254);
border-radius: 6px;
background: linear-gradient(180deg, rgb(255 255 255) 0%, rgb(248 250 252) 100%);
box-shadow: 0 6px 16px rgb(148 163 184 / 12%);
font-size: 13px;
color: rgb(71 85 105);
transition:
transform 0.2s ease,
box-shadow 0.2s ease,
border-color 0.2s ease,
background 0.2s ease,
color 0.2s ease;
}
&__attachment-name {
flex: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
&__attachment-meta {
display: flex;
align-items: center;
gap: 8px;
flex: 1;
min-width: 0;
}
&__attachment-icon {
flex-shrink: 0;
font-size: 16px;
color: rgb(59 130 246);
}
&__attachment-download {
flex-shrink: 0;
padding: 0;
}
&__attachment-actions {
display: flex;
align-items: center;
gap: 10px;
flex-shrink: 0;
margin-left: 12px;
}
&__attachment-size {
font-size: 12px;
color: rgb(100 116 139);
white-space: nowrap;
}
&__attachment-item:hover {
transform: translateY(-2px);
border-color: rgb(147 197 253);
background: linear-gradient(180deg, rgb(239 246 255) 0%, rgb(219 234 254) 100%);
box-shadow: 0 10px 22px rgb(96 165 250 / 18%);
color: rgb(30 41 59);
}
&__attachment-item:hover :deep(.el-button) {
color: rgb(29 78 216);
}
}
}
.notice-info-dialog {
.el-dialog {
background: rgb(255 255 255) !important;
--el-dialog-bg-color: rgb(255 255 255);
--el-bg-color: rgb(255 255 255);
box-shadow: 0 12px 32px rgb(15 23 42 / 18%);
}
.el-dialog__header {
margin-right: 0;
padding: 12px 12px 10px;
border-bottom: 1px solid rgb(226 232 240) !important;
background: rgb(255 255 255) !important;
}
.el-dialog__body {
padding: 2px;
background: rgb(255 255 255) !important;
}
.el-divider {
--el-border-color: rgb(226 232 240);
}
}
html[data-theme='dark'] .notice-card {
box-shadow: none;
.card-title {
color: rgb(203 213 225);
border-bottom-color: rgb(51 65 85);
}
.tab-item {
color: rgb(148 163 184);
&.active {
color: rgb(226 232 240);
&::after {
background: rgb(96 165 250);
}
}
}
.card-content {
color: rgb(148 163 184);
.table-container {
.el-table {
--el-table-border-color: transparent;
--el-table-header-bg-color: rgb(20, 20, 20);
--el-table-tr-bg-color: transparent;
--el-table-row-hover-bg-color: rgb(30 41 59);
--el-table-text-color: rgb(148 163 184);
--el-table-header-text-color: rgb(226 232 240);
background: transparent;
th.el-table__cell {
background: rgb(20, 20, 20);
}
th.el-table__cell,
td.el-table__cell {
border-bottom-color: rgb(51 65 85);
}
}
}
}
.notice-dialog {
&__title {
color: rgb(226 232 240);
}
&__time {
color: rgb(148 163 184);
}
&__header-divider {
background: rgb(51 65 85);
}
&__content-panel,
&__attachments-panel {
background: rgb(20, 20, 20);
}
&__attachments-panel {
border-color: rgb(51 65 85);
background: rgb(20, 20, 20);
}
&__content {
color: rgb(226 232 240);
background: rgb(20, 20, 20);
border-color: rgb(51 65 85);
}
&__attachment-item,
&__attachments-empty {
border-color: rgb(71 85 105);
background: rgb(20, 20, 20);
box-shadow: 0 6px 16px rgb(2 6 23 / 26%);
color: rgb(226 232 240);
}
&__attachment-icon {
color: rgb(147 197 253);
}
&__attachment-size {
color: rgb(148 163 184);
}
&__attachment-download:deep(.el-button) {
color: rgb(147 197 253);
}
&__attachment-item:hover {
border-color: rgb(96 165 250);
background: rgb(37 99 235 / 22%);
box-shadow: 0 10px 24px rgb(59 130 246 / 20%);
color: rgb(241 245 249);
}
&__attachment-item:hover :deep(.el-button) {
color: rgb(191 219 254);
}
}
}
html[data-theme='dark'] .notice-info-dialog {
--el-bg-color: rgb(20, 20, 20);
--el-dialog-bg-color: rgb(20, 20, 20);
--el-fill-color-blank: rgb(20, 20, 20);
.el-dialog {
background: rgb(20, 20, 20) !important;
--el-dialog-bg-color: rgb(20, 20, 20);
--el-bg-color: rgb(20, 20, 20);
--el-fill-color-blank: rgb(20, 20, 20);
box-shadow: 0 14px 36px rgb(0 0 0 / 42%);
}
.el-dialog__wrapper,
.el-overlay-dialog,
.el-dialog__content {
background: rgb(20, 20, 20) !important;
}
.el-dialog__header {
border-bottom: 1px solid rgb(51 65 85) !important;
background: rgb(20, 20, 20) !important;
}
.el-dialog__title {
color: rgb(226 232 240);
}
.el-dialog__headerbtn .el-dialog__close {
color: rgb(148 163 184);
}
.el-dialog__body {
background: rgb(20, 20, 20) !important;
}
.el-dialog__header,
.el-dialog__body,
.el-dialog__footer {
--el-bg-color: rgb(20, 20, 20);
--el-fill-color-blank: rgb(20, 20, 20);
}
.el-divider {
--el-border-color: rgb(51 65 85);
}
.notice-dialog {
&__attachments-title {
background: rgb(20, 20, 20);
color: rgb(226 232 240);
}
&__content {
scrollbar-color: rgb(71 85 105) transparent;
}
&__content::-webkit-scrollbar-thumb {
background: rgb(71 85 105);
}
&__attachments-list {
scrollbar-color: rgb(71 85 105) transparent;
}
&__attachments-list::-webkit-scrollbar-thumb {
background: rgb(71 85 105);
}
}
}
</style>

View File

@@ -0,0 +1,241 @@
<template>
<div class="notice-card">
<div class="card-title">
<span>待办信息</span>
<div class="card-tabs">
<button
v-for="item in tabs"
:key="item.key"
:class="['tab-item', { active: activeTab === item.key }]"
@click="activeTab = item.key"
>
{{ item.label }}
</button>
</div>
</div>
<div class="card-content">
<div ref="tableWrapRef" class="table-container">
<el-table :data="currentList" :height="tableHeight" :show-header="true" :border="false">
<el-table-column prop="title" label="标题" min-width="120" />
<el-table-column prop="time" label="时间" width="180" />
<el-table-column prop="content" label="内容" min-width="200" show-overflow-tooltip="true" />
</el-table>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { computed, nextTick, onBeforeUnmount, onMounted, ref } from 'vue';
const tabs = [
{ key: '0', label: '待办' },
{ key: '1', label: '已办' },
];
const activeTab = ref('0');
const noticeData = {
0: [
{ title: '系统升级通知', time: '2025-03-25 10:00', content: '系统将于今晚进行升级维护,请提前保存工作内容。' },
{ title: '安全检查提醒', time: '2025-03-25 09:30', content: '请及时完成本周安全检查任务,确保系统运行稳定。' },
{ title: '备份任务完成', time: '2025-03-25 08:15', content: '数据库备份任务已完成,备份文件已存储至指定位置。' },
],
1: [
{ title: '巡检报告提交', time: '2025-03-24 16:20', content: '昨日巡检报告已提交并审核通过。' },
{ title: '权限变更通知', time: '2025-03-24 14:10', content: '用户权限调整已生效,请相关人员知悉。' },
],
};
const currentList = computed(() => noticeData[activeTab.value] || []);
const tableWrapRef = ref<HTMLElement>();
const tableHeight = ref(0);
let resizeObserver: ResizeObserver | null = null;
function updateTableHeight() {
nextTick(() => {
const tableWrapEl = tableWrapRef.value;
if (!tableWrapEl) return;
tableHeight.value = Math.max(tableWrapEl.clientHeight, 0);
});
}
onMounted(() => {
updateTableHeight();
if (tableWrapRef.value) {
resizeObserver = new ResizeObserver(() => {
updateTableHeight();
});
resizeObserver.observe(tableWrapRef.value);
}
});
onBeforeUnmount(() => {
resizeObserver?.disconnect();
});
</script>
<style lang="less">
@dark-bg: #141414;
.notice-card {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
box-sizing: border-box;
overflow: hidden;
.card-title {
display: flex;
align-items: center;
justify-content: space-between;
padding: 8px 16px;
font-size: 14px;
font-weight: 500;
line-height: 20px;
color: rgb(51 65 85);
border-bottom: 1px solid rgb(226 232 240);
background: transparent;
}
.card-tabs {
display: flex;
gap: 8px;
}
.tab-item {
position: relative;
padding: 4px 8px;
border: none;
background: transparent;
color: rgb(100 116 139);
font-size: 12px;
cursor: pointer;
transition: all 0.2s;
&.active {
color: rgb(30 41 59);
&::after {
content: '';
position: absolute;
left: 0;
right: 0;
bottom: -2px;
height: 2px;
background: rgb(59 130 246);
}
}
}
.card-content {
flex: 1;
min-height: 0;
padding: 8px 12px 12px;
color: rgb(71 85 105);
font-size: 14px;
line-height: 22px;
overflow: hidden;
background: transparent;
display: flex;
flex-direction: column;
.table-container {
flex: 1;
min-height: 0;
width: 100%;
height: 100%;
overflow: hidden;
display: flex;
flex-direction: column;
.el-table {
width: 100%;
--el-table-border-color: transparent;
--el-table-header-bg-color: rgb(248, 250, 252);
--el-table-tr-bg-color: transparent;
--el-table-row-hover-bg-color: rgb(241 245 249);
--el-table-text-color: rgb(71 85 105);
--el-table-header-text-color: rgb(51 65 85);
background: transparent;
&::before,
&::after,
.el-table__inner-wrapper::before,
.el-table__border-left-patch {
display: none;
}
th.el-table__cell,
td.el-table__cell {
border-right: none;
border-left: none;
border-bottom: 1px solid rgb(226 232 240);
}
th.el-table__cell {
background: rgb(248, 250, 252);
}
td.el-table__cell,
th.el-table__cell {
padding: 8px 0;
}
.cell {
line-height: 20px;
}
}
}
}
}
html[data-theme='dark'] .notice-card {
box-shadow: none;
.card-title {
color: rgb(203 213 225);
border-bottom-color: rgb(51 65 85);
}
.tab-item {
color: rgb(148 163 184);
&.active {
color: rgb(226 232 240);
&::after {
background: rgb(96 165 250);
}
}
}
.card-content {
color: rgb(148 163 184);
.table-container {
.el-table {
--el-table-border-color: transparent;
--el-table-header-bg-color: rgb(20, 20, 20);
--el-table-tr-bg-color: transparent;
--el-table-row-hover-bg-color: rgb(30 41 59);
--el-table-text-color: rgb(148 163 184);
--el-table-header-text-color: rgb(226 232 240);
background: transparent;
th.el-table__cell {
background: rgb(20, 20, 20);
}
th.el-table__cell,
td.el-table__cell {
border-bottom-color: rgb(51 65 85);
}
}
}
}
}
</style>

View File

@@ -1,22 +1,68 @@
<template>
<div class="mySpring-analysis">
<div class="analysis-layout">
<div class="analysis-left">
<section class="analysis-panel">左上</section>
<section class="analysis-panel">左中</section>
<section class="analysis-panel">左下</section>
</div>
<div class="analysis-right">
<section class="analysis-panel">右上</section>
<section class="analysis-panel">右下</section>
<PageWrapper
:contentFullHeight="true"
title="false"
contentClass="analysis-page-wrapper"
>
<div class="analysis-page">
<div class="mySpring-analysis">
<div class="analysis-layout">
<div class="analysis-left">
<section class="analysis-panel">
<TodoInfo />
</section>
<section class="analysis-panel">
<NoticeInfo />
</section>
<section class="analysis-panel">
<HostInfo />
</section>
</div>
<div class="analysis-right">
<section class="analysis-panel">右上</section>
<section class="analysis-panel">右下</section>
</div>
</div>
</div>
</div>
</div>
</PageWrapper>
</template>
<script lang="ts" setup name="Analysis"></script>
<script lang="ts" setup name="Analysis">
import { PageWrapper } from '@jeesite/core/components/Page';
import HostInfo from './components/HostInfo.vue';
import TodoInfo from './components/TodoInfo.vue';
import NoticeInfo from './components/NoticeInfo.vue';
</script>
<style lang="less">
@dark-bg: #141414;
.analysis-page-wrapper {
display: flex;
flex-direction: column;
height: 100%;
min-height: 0;
padding: 0 !important;
margin-bottom: 0 !important;
overflow: hidden !important;
background: transparent !important;
}
.analysis-page {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
min-height: 0;
overflow: hidden;
background: transparent;
}
.mySpring-analysis {
flex: 1;
min-height: 0;
overflow: hidden;
}
.mySpring-analysis .ant-card {
border-radius: 10px !important;
}
@@ -33,6 +79,7 @@
display: flex;
width: 100%;
height: 100%;
max-height: 100%;
min-height: 0;
gap: 12px;
padding: 4px;
@@ -47,6 +94,7 @@
display: grid;
min-width: 0;
height: 100%;
max-height: 100%;
min-height: 0;
gap: 12px;
box-sizing: border-box;
@@ -63,14 +111,17 @@
}
.mySpring-analysis .analysis-panel {
display: flex;
flex-direction: column;
min-height: 0;
height: 100%;
min-width: 0;
padding: 0;
border-radius: 10px;
border: 1px solid rgb(226 232 240);
background: rgb(248 250 252);
box-shadow: 0 1px 3px rgb(15 23 42 / 0.06);
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
color: rgb(71 85 105);
font-size: 16px;
}