项目初始化
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
package com.jeesite.modules.apps.Module;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class ChartInfo implements Serializable {
|
||||
|
||||
private String key;
|
||||
private String label;
|
||||
private double value;
|
||||
private String color;
|
||||
private String remark;
|
||||
|
||||
public ChartInfo() {
|
||||
}
|
||||
|
||||
public ChartInfo(String key, String label, double value, String color,String remark) {
|
||||
this.key = key;
|
||||
this.label = label;
|
||||
this.value = value;
|
||||
this.color = color;
|
||||
this.remark = remark;
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package com.jeesite.modules.apps.Module;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class HostInfo implements Serializable {
|
||||
private Integer cpuNum;
|
||||
|
||||
|
||||
public HostInfo(){}
|
||||
|
||||
public HostInfo(Integer cpuNum){
|
||||
this.cpuNum = cpuNum;
|
||||
}
|
||||
}
|
||||
@@ -6,10 +6,5 @@ public class Start {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,39 @@
|
||||
package com.jeesite.modules.apps.web;
|
||||
|
||||
import cn.hutool.system.SystemUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.system.oshi.CpuInfo;
|
||||
import cn.hutool.system.oshi.OshiUtil;
|
||||
import com.jeesite.modules.apps.Module.ChartInfo;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Controller
|
||||
@RequestMapping(value = "${adminPath}/sys/analysis")
|
||||
public class SysAnalysisController {
|
||||
|
||||
public void sss(){
|
||||
SystemUtil.getJvmInfo();
|
||||
@RequestMapping(value = "getHostInfo")
|
||||
@ResponseBody
|
||||
public List<ChartInfo> getHostInfo() {
|
||||
List<ChartInfo> chartInfoList = new ArrayList<>();
|
||||
CpuInfo cpuInfo = OshiUtil.getCpuInfo();
|
||||
long uptimeMs = OshiUtil.getOs().getSystemUptime();
|
||||
String runTime = DateUtil.formatBetween(uptimeMs);
|
||||
// 系统使用率(红色)
|
||||
chartInfoList.add(new ChartInfo("sys", "系统使用率", cpuInfo.getSys(), "#F43F5E", runTime));
|
||||
// 用户使用率(蓝色)
|
||||
chartInfoList.add(new ChartInfo("user", "用户使用率", cpuInfo.getUser(), "#3B82F6", runTime));
|
||||
// CPU等待率(橙色)
|
||||
chartInfoList.add(new ChartInfo("wait", "CPU等待率", cpuInfo.getWait(), "#F97316", runTime));
|
||||
// CPU空闲率(绿色)
|
||||
chartInfoList.add(new ChartInfo("free", "CPU空闲率", cpuInfo.getFree(), "#10B981", runTime));
|
||||
// CPU总使用率(粉色)
|
||||
chartInfoList.add(new ChartInfo("used", "CPU总使用率", cpuInfo.getUsed(), "#EC4899", runTime));
|
||||
// 系统运行时间(紫色)
|
||||
chartInfoList.add(new ChartInfo("time", "系统运行时间", 0, "#8B5CF6", runTime));
|
||||
return chartInfoList;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,6 +167,9 @@ public class MyNoticeTodoController extends BaseController {
|
||||
@RequestMapping(value = "fileList")
|
||||
@ResponseBody
|
||||
public List<FileList> fileList(MyNoticeTodo myNoticeTodo) {
|
||||
MyNoticeTodo noticeTodo = myNoticeTodoService.get(myNoticeTodo);
|
||||
noticeTodo.setReadFlag("1");
|
||||
myNoticeTodoService.save(noticeTodo);
|
||||
List<FileList> fileLists = new ArrayList<>();
|
||||
List<FileUpload> fileUploadList = FileUploadUtils.findFileUpload(myNoticeTodo.getId(), "myNoticeTodo_file");
|
||||
for (FileUpload fileUpload : fileUploadList) {
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
package com.jeesite.modules.utils;
|
||||
|
||||
import cn.hutool.system.oshi.CpuInfo;
|
||||
import cn.hutool.system.oshi.OshiUtil;
|
||||
import com.jeesite.modules.apps.Module.HostInfo;
|
||||
|
||||
public class HostUtils {
|
||||
|
||||
|
||||
public static HostInfo getHostInfo() {
|
||||
|
||||
// return "CpuInfo{CPU核心数=" + this.cpuNum + ", CPU总的使用率=" + this.toTal + ",
|
||||
// CPU系统使用率=" + this.sys + ", CPU用户使用率=" + this.user + ", CPU当前等待率=" + this.wait + ",
|
||||
// CPU当前空闲率=" + this.free + ", CPU利用率=" + this.getUsed() + ", CPU型号信息='" + this.cpuModel + '\'' + '}';
|
||||
CpuInfo cpuInfo = OshiUtil.getCpuInfo();
|
||||
|
||||
System.out.println(cpuInfo);
|
||||
|
||||
System.out.println("================");
|
||||
System.out.println(cpuInfo.getCpuNum());
|
||||
System.out.println(cpuInfo.getToTal());
|
||||
System.out.println(cpuInfo.getSys());
|
||||
System.out.println(cpuInfo.getUser());
|
||||
System.out.println(cpuInfo.getWait());
|
||||
System.out.println(cpuInfo.getFree());
|
||||
System.out.println(cpuInfo.getUsed());
|
||||
return new HostInfo();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
getHostInfo();
|
||||
}
|
||||
}
|
||||
20
web-vue/packages/biz/api/biz/myAnalysis.ts
Normal file
20
web-vue/packages/biz/api/biz/myAnalysis.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Copyright (c) 2013-Now https://jeesite.com All rights reserved.
|
||||
* No deletion without permission, or be held responsible to law.
|
||||
* @author gaoxq
|
||||
*/
|
||||
import { defHttp } from '@jeesite/core/utils/http/axios';
|
||||
import { useGlobSetting } from '@jeesite/core/hooks/setting';
|
||||
import { BasicModel } from '@jeesite/core/api/model/baseModel';
|
||||
|
||||
const { adminPath } = useGlobSetting();
|
||||
|
||||
export interface ChartInfo extends BasicModel<ChartInfo> {
|
||||
key: string; // 指标Key
|
||||
label: string; // 指标名称
|
||||
value: number; // 指标数值
|
||||
color: string; // 指标颜色
|
||||
remark?: string; // 运行时长
|
||||
}
|
||||
|
||||
export const HostInfoData = () => defHttp.get<ChartInfo[]>({ url: adminPath + '/sys/analysis/getHostInfo' });
|
||||
@@ -1,12 +1,24 @@
|
||||
<template>
|
||||
<div ref="hostCardRef" class="host-card">
|
||||
<div class="card-title">
|
||||
<span>主机信息</span>
|
||||
<div class="card-title__main">
|
||||
<span>主机信息</span>
|
||||
<el-tooltip v-if="runtimeText" :content="`运行时长:${runtimeText}`" placement="top" :show-after="200">
|
||||
<el-icon class="card-title__tips"><QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</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 v-loading="loading" class="host-overview">
|
||||
<div class="host-gauge-panel">
|
||||
<div ref="chartRef" class="gauge-chart"></div>
|
||||
</div>
|
||||
|
||||
<div class="host-metrics">
|
||||
<div v-for="item in sideMetrics" :key="item.key" class="metric-item">
|
||||
<div class="metric-item__value" :style="{ color: item.color }">{{ item.value }}%</div>
|
||||
<div class="metric-item__label">{{ item.label }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -14,89 +26,157 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted } from 'vue';
|
||||
import { computed, nextTick, onMounted, onUnmounted, ref } from 'vue';
|
||||
import * as echarts from 'echarts';
|
||||
import { QuestionFilled } from '@element-plus/icons-vue';
|
||||
import { ChartInfo, HostInfoData } from '@jeesite/biz/api/biz/myAnalysis';
|
||||
|
||||
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>();
|
||||
const chartRef = ref<HTMLElement>();
|
||||
|
||||
const cpuData = ref<ChartInfo[]>([]);
|
||||
const loading = ref(false);
|
||||
const totalMetric = computed(() => cpuData.value.find((item) => item.key === 'used'));
|
||||
const runtimeText = computed(() => cpuData.value.find((item) => item.key === 'time')?.remark || '');
|
||||
const sideMetrics = computed(() => {
|
||||
const metricOrder = ['sys', 'wait', 'user', 'free'];
|
||||
return metricOrder
|
||||
.map((key) => cpuData.value.find((item) => item.key === key))
|
||||
.filter((item): item is ChartInfo => Boolean(item));
|
||||
});
|
||||
|
||||
let chartInstance: echarts.ECharts | null = null;
|
||||
let resizeObserver: ResizeObserver | null = null;
|
||||
|
||||
function resizeCharts() {
|
||||
chartInstances.forEach((chart) => {
|
||||
chart.resize();
|
||||
async function getList() {
|
||||
loading.value = true;
|
||||
try {
|
||||
const res = await HostInfoData();
|
||||
cpuData.value = res || [];
|
||||
} catch (error) {
|
||||
console.error('获取主机信息失败:', error);
|
||||
cpuData.value = [];
|
||||
} finally {
|
||||
loading.value = false;
|
||||
nextTick(() => {
|
||||
renderChart();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function getTotalValue() {
|
||||
return totalMetric.value?.value || 0;
|
||||
}
|
||||
|
||||
function getTotalLabel() {
|
||||
return totalMetric.value?.label || 'CPU使用率';
|
||||
}
|
||||
|
||||
function getTotalColor() {
|
||||
return totalMetric.value?.color || '#ef4444';
|
||||
}
|
||||
|
||||
function renderChart() {
|
||||
if (!chartRef.value) return;
|
||||
|
||||
if (!chartInstance) {
|
||||
chartInstance = echarts.init(chartRef.value);
|
||||
}
|
||||
|
||||
const totalValue = getTotalValue();
|
||||
const totalLabel = getTotalLabel();
|
||||
const totalColor = getTotalColor();
|
||||
|
||||
chartInstance.setOption({
|
||||
series: [
|
||||
{
|
||||
type: 'gauge',
|
||||
startAngle: 210,
|
||||
endAngle: -30,
|
||||
radius: '72%',
|
||||
center: ['50%', '56%'],
|
||||
min: 0,
|
||||
max: 100,
|
||||
splitNumber: 5,
|
||||
progress: {
|
||||
show: true,
|
||||
width: 10,
|
||||
itemStyle: {
|
||||
color: totalColor,
|
||||
},
|
||||
},
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
width: 10,
|
||||
color: [[1, '#e5e7eb']],
|
||||
},
|
||||
},
|
||||
pointer: {
|
||||
show: true,
|
||||
length: '52%',
|
||||
width: 5,
|
||||
offsetCenter: [0, '0%'],
|
||||
itemStyle: {
|
||||
color: totalColor,
|
||||
},
|
||||
},
|
||||
axisTick: {
|
||||
distance: -10,
|
||||
splitNumber: 4,
|
||||
lineStyle: {
|
||||
width: 1,
|
||||
color: '#cbd5e1',
|
||||
},
|
||||
},
|
||||
splitLine: {
|
||||
distance: -10,
|
||||
length: 7,
|
||||
lineStyle: {
|
||||
width: 2,
|
||||
color: '#94a3b8',
|
||||
},
|
||||
},
|
||||
axisLabel: {
|
||||
distance: -18,
|
||||
color: '#64748b',
|
||||
fontSize: 9,
|
||||
},
|
||||
anchor: {
|
||||
show: true,
|
||||
showAbove: true,
|
||||
size: 8,
|
||||
itemStyle: {
|
||||
color: totalColor,
|
||||
borderWidth: 2,
|
||||
borderColor: '#fff',
|
||||
},
|
||||
},
|
||||
title: {
|
||||
show: true,
|
||||
offsetCenter: [0, '44%'],
|
||||
fontSize: 11,
|
||||
color: '#64748b',
|
||||
},
|
||||
detail: {
|
||||
valueAnimation: true,
|
||||
formatter: '{value}%',
|
||||
color: '#0f172a',
|
||||
fontSize: 22,
|
||||
fontWeight: 'bold',
|
||||
offsetCenter: [0, '2%'],
|
||||
},
|
||||
data: [{ value: totalValue, name: totalLabel }],
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
function setChartRef(el: any, label: string) {
|
||||
if (el) chartRefs.set(label, el);
|
||||
function resizeCharts() {
|
||||
chartInstance?.resize();
|
||||
}
|
||||
|
||||
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);
|
||||
});
|
||||
|
||||
getList();
|
||||
if (hostCardRef.value) {
|
||||
resizeObserver = new ResizeObserver(() => {
|
||||
resizeCharts();
|
||||
@@ -110,13 +190,12 @@
|
||||
onUnmounted(() => {
|
||||
resizeObserver?.disconnect();
|
||||
window.removeEventListener('resize', resizeCharts);
|
||||
chartInstances.forEach((chart) => chart.dispose());
|
||||
chartInstance?.dispose();
|
||||
chartInstance = null;
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@dark-bg: #141414;
|
||||
|
||||
.host-card {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -136,62 +215,180 @@
|
||||
color: rgb(51 65 85);
|
||||
border-bottom: 1px solid rgb(226 232 240);
|
||||
background: transparent;
|
||||
|
||||
&__main {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
&__tips {
|
||||
font-size: 14px;
|
||||
color: rgb(100 116 139);
|
||||
cursor: pointer;
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
|
||||
&__tips:hover {
|
||||
color: rgb(59 130 246);
|
||||
}
|
||||
}
|
||||
|
||||
.card-content {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
padding: 16px;
|
||||
color: rgb(71 85 105);
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
overflow: auto;
|
||||
overflow: hidden;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.gauge-list {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
.host-overview {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 12px;
|
||||
height: 100%;
|
||||
align-items: stretch;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.gauge-item {
|
||||
flex: 1;
|
||||
.host-gauge-panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
justify-content: center;
|
||||
min-width: 0;
|
||||
min-height: 160px;
|
||||
padding: 8px;
|
||||
border-radius: 14px;
|
||||
background: rgb(248, 250, 252);
|
||||
box-shadow: 0 10px 28px rgb(148 163 184 / 16%);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.gauge-chart {
|
||||
width: 100%;
|
||||
height: 140px;
|
||||
max-width: 140px;
|
||||
height: 100%;
|
||||
min-height: 160px;
|
||||
max-width: 280px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.gauge-label {
|
||||
font-size: 11px;
|
||||
color: rgb(100 116 139);
|
||||
text-align: center;
|
||||
.host-metrics {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
grid-template-rows: repeat(2, minmax(0, 1fr));
|
||||
gap: 10px;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.metric-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
padding: 10px 12px;
|
||||
border-radius: 10px;
|
||||
background: rgb(248, 250, 252);
|
||||
box-shadow: 0 8px 24px rgb(148 163 184 / 14%);
|
||||
overflow: hidden;
|
||||
transition:
|
||||
transform 0.2s ease,
|
||||
box-shadow 0.2s ease,
|
||||
background 0.2s ease;
|
||||
|
||||
&__label {
|
||||
margin-top: 8px;
|
||||
color: rgb(71 85 105);
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
text-align: center;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
&__value {
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 12px 28px rgb(96 165 250 / 20%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
html[data-theme='dark'] .host-card {
|
||||
box-shadow: none;
|
||||
|
||||
.card-title {
|
||||
color: rgb(203 213 225);
|
||||
border-bottom-color: rgb(51 65 85);
|
||||
|
||||
&__tips {
|
||||
color: rgb(148 163 184);
|
||||
}
|
||||
|
||||
&__tips:hover {
|
||||
color: rgb(147 197 253);
|
||||
}
|
||||
}
|
||||
|
||||
.card-content {
|
||||
color: rgb(148 163 184);
|
||||
.host-gauge-panel,
|
||||
.host-metrics {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.gauge-label {
|
||||
color: rgb(148 163 184);
|
||||
.host-gauge-panel {
|
||||
background: linear-gradient(180deg, rgb(20, 20, 20) 0%, rgb(28 28 28) 100%);
|
||||
box-shadow: 0 12px 30px rgb(0 0 0 / 28%);
|
||||
}
|
||||
|
||||
.metric-item {
|
||||
background: linear-gradient(180deg, rgb(20, 20, 20) 0%, rgb(28 28 28) 100%);
|
||||
box-shadow: 0 10px 24px rgb(0 0 0 / 24%);
|
||||
|
||||
&__label {
|
||||
color: rgb(148 163 184);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 14px 32px rgb(37 99 235 / 22%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.host-card {
|
||||
.host-overview {
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: auto 1fr;
|
||||
}
|
||||
|
||||
.host-metrics {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
grid-template-rows: repeat(2, minmax(88px, 1fr));
|
||||
}
|
||||
|
||||
.host-gauge-panel {
|
||||
min-height: 160px;
|
||||
}
|
||||
|
||||
.gauge-chart {
|
||||
min-height: 160px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 560px) {
|
||||
.host-card {
|
||||
.host-metrics {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -15,15 +15,27 @@
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div ref="tableWrapRef" class="table-container">
|
||||
<el-table :data="listData" :height="tableHeight" :show-header="true" :border="false">
|
||||
<el-table-column prop="title" label="标题" min-width="120" show-overflow-tooltip="true" />
|
||||
<el-table-column prop="extraDesc" label="待办意见" width="120" show-overflow-tooltip="true" />
|
||||
<el-table-column prop="datetime" label="到期时间" width="180" />
|
||||
<el-table v-loading="tableLoading" :data="listData" :height="tableHeight" :show-header="true" :border="false">
|
||||
<el-table-column prop="title" label="标题" min-width="80" show-overflow-tooltip="true" />
|
||||
<el-table-column prop="type" label="类型" width="60">
|
||||
<template #default="{ row }">
|
||||
{{ formatNoticeType(row.type) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="createTime" label="记录时间" width="150" show-overflow-tooltip="true" />
|
||||
<el-table-column prop="datetime" label="截至时间" width="150" show-overflow-tooltip="true" />
|
||||
<el-table-column prop="createUser" label="发布人员" width="120" show-overflow-tooltip="true" />
|
||||
<el-table-column label="操作" width="90" align="center" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button class="notice-action-button" link type="primary" @click="openNoticeDialog(row)">
|
||||
查看
|
||||
</el-button>
|
||||
<el-tooltip content="查看" placement="top" :show-after="200">
|
||||
<el-button
|
||||
class="notice-action-button"
|
||||
link
|
||||
type="primary"
|
||||
:icon="View"
|
||||
@click="openNoticeDialog(row)"
|
||||
/>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -39,7 +51,7 @@
|
||||
<div class="notice-dialog__time">
|
||||
<div class="notice-dialog__time-left">
|
||||
<span>发布时间:{{ selectedNotice.createTime }}</span>
|
||||
<span>发布人:{{ selectedNotice.createUser }}</span>
|
||||
<span>发布人员:{{ selectedNotice.createUser }}</span>
|
||||
</div>
|
||||
<div class="notice-dialog__time-right">截至时间:{{ selectedNotice.datetime }}</div>
|
||||
</div>
|
||||
@@ -61,13 +73,12 @@
|
||||
<div class="notice-dialog__attachment-actions">
|
||||
<span class="notice-dialog__attachment-size">{{ item.fileSize }}</span>
|
||||
<el-button
|
||||
class="notice-dialog__attachment-download"
|
||||
type="primary"
|
||||
link
|
||||
:icon="Download"
|
||||
class="notice-dialog__attachment-download"
|
||||
@click.stop="handleDownload(item)"
|
||||
>下载</el-button
|
||||
>
|
||||
></el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -79,6 +90,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { View } from '@element-plus/icons-vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { Icon } from '@jeesite/core/components/Icon';
|
||||
import { Document, Download } from '@element-plus/icons-vue';
|
||||
@@ -103,6 +115,7 @@
|
||||
|
||||
const tableWrapRef = ref<HTMLElement>();
|
||||
const tableHeight = ref(0);
|
||||
const tableLoading = ref(false);
|
||||
const dialogVisible = ref(false);
|
||||
const selectedNotice = ref<MyNoticeTodo | null>(null);
|
||||
|
||||
@@ -113,7 +126,16 @@
|
||||
selectedNotice.value = notice;
|
||||
dialogVisible.value = true;
|
||||
}
|
||||
|
||||
|
||||
function formatNoticeType(type?: string | number) {
|
||||
const typeMap: Record<string, string> = {
|
||||
'1': '通知',
|
||||
'2': '消息',
|
||||
'3': '待办',
|
||||
};
|
||||
return typeMap[String(type ?? '')] || '-';
|
||||
}
|
||||
|
||||
async function handleDownload(item: MyFileList) {
|
||||
const { ctxAdminPath } = useGlobSetting();
|
||||
await downloadByUrl({
|
||||
@@ -137,17 +159,19 @@
|
||||
}
|
||||
|
||||
const getDataList = async () => {
|
||||
tableLoading.value = true;
|
||||
try {
|
||||
const reqParams = {
|
||||
type: '1',
|
||||
ustatus: '1',
|
||||
clickClose: '0',
|
||||
ustatus: '1',
|
||||
readFlag: activeTab.value,
|
||||
};
|
||||
const result = await myNoticeTodoListAll(reqParams);
|
||||
listData.value = result || [];
|
||||
} catch (error) {
|
||||
listData.value = [];
|
||||
} finally {
|
||||
tableLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
v-for="item in tabs"
|
||||
:key="item.key"
|
||||
:class="['tab-item', { active: activeTab === item.key }]"
|
||||
@click="activeTab = item.key"
|
||||
@click="handleTabChange(item.key)"
|
||||
>
|
||||
{{ item.label }}
|
||||
</button>
|
||||
@@ -15,18 +15,108 @@
|
||||
</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 v-loading="tableLoading" :data="listData" :height="tableHeight" :show-header="true" :border="false">
|
||||
<el-table-column prop="title" label="标题" min-width="80" show-overflow-tooltip="true" />
|
||||
<el-table-column prop="type" label="类型" width="60">
|
||||
<template #default="{ row }">
|
||||
{{ formatNoticeType(row.type) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="createTime" label="记录时间" width="150" show-overflow-tooltip="true" />
|
||||
<el-table-column prop="datetime" label="截至时间" width="150" show-overflow-tooltip="true" />
|
||||
<el-table-column prop="extraDesc" label="处理意见" width="120" show-overflow-tooltip="true" />
|
||||
<el-table-column label="操作" width="90" align="center" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-tooltip content="编辑" placement="top" :show-after="200">
|
||||
<el-button
|
||||
class="notice-action-button"
|
||||
link
|
||||
type="primary"
|
||||
:icon="Edit"
|
||||
@click="openNoticeDialog(row)"
|
||||
/>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-dialog
|
||||
v-model="dialogVisible"
|
||||
:class="['todo-info-dialog', { 'todo-info-dialog--no-footer': selectedNotice?.clickClose === '1' }]"
|
||||
title="待办详情"
|
||||
width="50%"
|
||||
destroy-on-close
|
||||
>
|
||||
<template v-if="selectedNotice">
|
||||
<div class="todo-dialog">
|
||||
<div class="todo-dialog__header">
|
||||
<div class="todo-dialog__title">{{ selectedNotice.title }}</div>
|
||||
<div class="todo-dialog__header-divider"></div>
|
||||
<div class="todo-dialog__time">
|
||||
<div class="todo-dialog__time-left">
|
||||
<span>创建时间:{{ selectedNotice.createTime || '-' }}</span>
|
||||
<span>创建人:{{ selectedNotice.createUser || '-' }}</span>
|
||||
<span>类型:{{ formatNoticeType(selectedNotice.type) }}</span>
|
||||
</div>
|
||||
<div class="todo-dialog__time-right">截至时间:{{ selectedNotice.datetime || '-' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-divider class="todo-dialog__divider" />
|
||||
|
||||
<div class="todo-dialog__content-panel">
|
||||
<div class="todo-dialog__section-title">待办内容</div>
|
||||
<div class="todo-dialog__content" v-html="selectedNotice.description || '-'"></div>
|
||||
</div>
|
||||
|
||||
<div class="todo-dialog__form-panel">
|
||||
<div class="todo-dialog__section-title">处理意见</div>
|
||||
<el-form label-position="top">
|
||||
<el-form-item class="todo-dialog__form-item">
|
||||
<el-input
|
||||
v-model="opinionForm.extraDesc"
|
||||
class="todo-dialog__textarea"
|
||||
type="textarea"
|
||||
:rows="5"
|
||||
resize="none"
|
||||
maxlength="1000"
|
||||
show-word-limit
|
||||
:readonly="isReadonly"
|
||||
:placeholder="isReadonly ? '暂无处理意见' : '请输入处理意见'"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #footer>
|
||||
<div class="todo-dialog__footer">
|
||||
<div v-if="!isReadonly" class="todo-dialog__button-group">
|
||||
<el-button @click="handleResetOpinion">重置</el-button>
|
||||
<el-button type="primary" :loading="submitLoading" @click="handleSaveOpinion">保存</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, nextTick, onBeforeUnmount, onMounted, ref } from 'vue';
|
||||
import { Edit } from '@element-plus/icons-vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { computed, nextTick, onBeforeUnmount, onMounted, reactive, ref } from 'vue';
|
||||
import { useUserStore } from '@jeesite/core/store/modules/user';
|
||||
import {
|
||||
MyNoticeTodo,
|
||||
myNoticeTodoForm,
|
||||
myNoticeTodoListAll,
|
||||
myNoticeTodoSave,
|
||||
} from '@jeesite/biz/api/biz/myNoticeTodo';
|
||||
|
||||
const userStore = useUserStore();
|
||||
const userinfo = computed(() => userStore.getUserInfo);
|
||||
|
||||
const tabs = [
|
||||
{ key: '0', label: '待办' },
|
||||
@@ -34,26 +124,88 @@
|
||||
];
|
||||
|
||||
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 listData = ref<MyNoticeTodo[]>([]);
|
||||
const tableWrapRef = ref<HTMLElement>();
|
||||
const tableHeight = ref(0);
|
||||
const tableLoading = ref(false);
|
||||
const dialogVisible = ref(false);
|
||||
const submitLoading = ref(false);
|
||||
const selectedNotice = ref<MyNoticeTodo | null>(null);
|
||||
const opinionForm = reactive({
|
||||
extraDesc: '',
|
||||
});
|
||||
|
||||
const isReadonly = computed(() => activeTab.value === '1');
|
||||
|
||||
let resizeObserver: ResizeObserver | null = null;
|
||||
|
||||
function formatNoticeType(type?: string | number) {
|
||||
const typeMap: Record<string, string> = {
|
||||
'1': '通知',
|
||||
'2': '消息',
|
||||
'3': '待办',
|
||||
};
|
||||
return typeMap[String(type ?? '')] || '-';
|
||||
}
|
||||
|
||||
async function openNoticeDialog(notice: MyNoticeTodo) {
|
||||
dialogVisible.value = true;
|
||||
selectedNotice.value = notice;
|
||||
opinionForm.extraDesc = notice.extraDesc || '';
|
||||
|
||||
try {
|
||||
const res = await myNoticeTodoForm({ id: notice.id });
|
||||
const detail = ((res as any)?.myNoticeTodo || res || notice) as MyNoticeTodo;
|
||||
selectedNotice.value = detail;
|
||||
opinionForm.extraDesc = detail.extraDesc || '';
|
||||
} catch (error) {
|
||||
selectedNotice.value = notice;
|
||||
}
|
||||
}
|
||||
|
||||
async function handleSaveOpinion() {
|
||||
if (!selectedNotice.value?.id) return;
|
||||
if (!opinionForm.extraDesc.trim()) {
|
||||
ElMessage.warning('请输入处理意见');
|
||||
return;
|
||||
}
|
||||
|
||||
submitLoading.value = true;
|
||||
try {
|
||||
const data: MyNoticeTodo = {
|
||||
...selectedNotice.value,
|
||||
readFlag: '1',
|
||||
clickClose: '1',
|
||||
extraDesc: opinionForm.extraDesc.trim(),
|
||||
};
|
||||
const params = {
|
||||
isNewRecord: selectedNotice.value.isNewRecord,
|
||||
id: selectedNotice.value.id,
|
||||
};
|
||||
const res = await myNoticeTodoSave(params, data);
|
||||
ElMessage.success((res as any)?.message);
|
||||
|
||||
selectedNotice.value = {
|
||||
...selectedNotice.value,
|
||||
extraDesc: opinionForm.extraDesc.trim(),
|
||||
};
|
||||
|
||||
listData.value = listData.value.map((item) =>
|
||||
item.id === selectedNotice.value?.id ? { ...item, extraDesc: opinionForm.extraDesc.trim() } : item,
|
||||
);
|
||||
getDataList();
|
||||
dialogVisible.value = false;
|
||||
} catch (error) {
|
||||
console.error('保存失败,请稍后重试');
|
||||
} finally {
|
||||
submitLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function handleResetOpinion() {
|
||||
opinionForm.extraDesc = selectedNotice.value?.extraDesc || '';
|
||||
}
|
||||
|
||||
function updateTableHeight() {
|
||||
nextTick(() => {
|
||||
const tableWrapEl = tableWrapRef.value;
|
||||
@@ -62,7 +214,32 @@
|
||||
});
|
||||
}
|
||||
|
||||
function handleTabChange(tabKey: string) {
|
||||
if (activeTab.value === tabKey) return;
|
||||
activeTab.value = tabKey;
|
||||
getDataList();
|
||||
}
|
||||
|
||||
async function getDataList() {
|
||||
tableLoading.value = true;
|
||||
try {
|
||||
const reqParams = {
|
||||
type: '3',
|
||||
ustatus: '1',
|
||||
clickClose: activeTab.value,
|
||||
loginUser: userinfo.value.loginCode,
|
||||
};
|
||||
const result = await myNoticeTodoListAll(reqParams);
|
||||
listData.value = result || [];
|
||||
} catch (error) {
|
||||
listData.value = [];
|
||||
} finally {
|
||||
tableLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getDataList();
|
||||
updateTableHeight();
|
||||
if (tableWrapRef.value) {
|
||||
resizeObserver = new ResizeObserver(() => {
|
||||
@@ -78,8 +255,6 @@
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@dark-bg: #141414;
|
||||
|
||||
.notice-card {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -188,14 +363,207 @@
|
||||
.cell {
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.notice-action-button {
|
||||
padding: 0;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.todo-dialog {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0;
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
&__title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: rgb(30 41 59);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&__header-divider {
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
background: rgb(226 232 240);
|
||||
}
|
||||
|
||||
&__time {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
font-size: 13px;
|
||||
color: rgb(100 116 139);
|
||||
}
|
||||
|
||||
&__time-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
min-width: 0;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
&__time-right {
|
||||
flex-shrink: 0;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
&__divider {
|
||||
margin: 16px 0;
|
||||
}
|
||||
|
||||
&__content-panel,
|
||||
&__form-panel {
|
||||
padding: 2px;
|
||||
border-radius: 8px;
|
||||
background: rgb(248 252 255);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
&__form-panel {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
&__section-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
min-height: 36px;
|
||||
margin-bottom: 12px;
|
||||
padding: 0 12px;
|
||||
border-radius: 6px;
|
||||
background: rgb(239 246 255);
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: rgb(51 65 85);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
&__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;
|
||||
}
|
||||
}
|
||||
|
||||
&__form-item {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&__textarea :deep(.el-textarea__inner) {
|
||||
min-height: 140px !important;
|
||||
padding: 14px 16px;
|
||||
border-radius: 6px;
|
||||
border-color: rgb(191 219 254);
|
||||
background: rgb(255 255 255);
|
||||
color: rgb(51 65 85);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
&__footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding-top: 6px;
|
||||
border-top: 1px solid rgb(226 232 240);
|
||||
}
|
||||
|
||||
&__button-group {
|
||||
:deep(.el-button) {
|
||||
min-width: 72px;
|
||||
}
|
||||
|
||||
:deep(.el-button + .el-button) {
|
||||
margin-left: 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
html[data-theme='dark'] .notice-card {
|
||||
box-shadow: none;
|
||||
.todo-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-dialog__footer {
|
||||
padding: 0 8px 4px;
|
||||
background: rgb(255 255 255) !important;
|
||||
}
|
||||
|
||||
.el-divider {
|
||||
--el-border-color: rgb(226 232 240);
|
||||
}
|
||||
|
||||
&.todo-info-dialog--no-footer {
|
||||
.el-dialog__footer {
|
||||
display: none !important;
|
||||
padding: 0 !important;
|
||||
border: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
html[data-theme='dark'] .notice-card {
|
||||
.card-title {
|
||||
color: rgb(203 213 225);
|
||||
border-bottom-color: rgb(51 65 85);
|
||||
@@ -237,5 +605,166 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.todo-dialog {
|
||||
&__title {
|
||||
color: rgb(226 232 240);
|
||||
}
|
||||
|
||||
&__time {
|
||||
color: rgb(148 163 184);
|
||||
}
|
||||
|
||||
&__header-divider {
|
||||
background: rgb(51 65 85);
|
||||
}
|
||||
|
||||
&__content-panel,
|
||||
&__form-panel,
|
||||
&__content,
|
||||
&__section-title {
|
||||
background: rgb(20, 20, 20);
|
||||
}
|
||||
|
||||
&__content {
|
||||
color: rgb(226 232 240);
|
||||
border-color: rgb(51 65 85);
|
||||
scrollbar-color: rgb(71 85 105) transparent;
|
||||
}
|
||||
|
||||
&__content::-webkit-scrollbar-thumb {
|
||||
background: rgb(71 85 105);
|
||||
}
|
||||
|
||||
&__section-title {
|
||||
color: rgb(226 232 240);
|
||||
}
|
||||
|
||||
&__textarea :deep(.el-textarea__inner) {
|
||||
border: 1px solid rgb(71 85 105) !important;
|
||||
border-color: rgb(71 85 105);
|
||||
background: rgb(20, 20, 20);
|
||||
color: rgb(226 232 240);
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
&__textarea :deep(.el-textarea__inner:focus) {
|
||||
border-color: rgb(96 165 250) !important;
|
||||
}
|
||||
|
||||
&__footer {
|
||||
border-top-color: rgb(51 65 85);
|
||||
}
|
||||
|
||||
&__textarea :deep(.el-textarea__inner::placeholder) {
|
||||
color: rgb(100 116 139);
|
||||
}
|
||||
|
||||
&__textarea :deep(.el-input__count) {
|
||||
color: rgb(148 163 184);
|
||||
background: rgb(20, 20, 20);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
html[data-theme='dark'] .todo-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__body,
|
||||
.el-dialog__footer {
|
||||
background: rgb(20, 20, 20) !important;
|
||||
}
|
||||
|
||||
.el-textarea,
|
||||
.el-textarea__inner,
|
||||
.el-input__wrapper {
|
||||
--el-input-border-color: rgb(71 85 105);
|
||||
--el-input-hover-border-color: rgb(96 165 250);
|
||||
--el-input-focus-border-color: rgb(96 165 250);
|
||||
--el-fill-color-blank: rgb(20, 20, 20);
|
||||
background: rgb(20, 20, 20) !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.el-textarea__inner {
|
||||
border: 1px solid rgb(71 85 105) !important;
|
||||
}
|
||||
|
||||
.el-dialog__title {
|
||||
color: rgb(226 232 240);
|
||||
}
|
||||
|
||||
.el-dialog__headerbtn .el-dialog__close {
|
||||
color: rgb(148 163 184);
|
||||
}
|
||||
|
||||
.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);
|
||||
}
|
||||
|
||||
.el-form-item__label {
|
||||
color: rgb(226 232 240);
|
||||
}
|
||||
|
||||
.todo-dialog__footer {
|
||||
.el-button:not(.el-button--primary) {
|
||||
border-color: rgb(71 85 105);
|
||||
background: rgb(30 41 59);
|
||||
color: rgb(226 232 240);
|
||||
}
|
||||
|
||||
.el-button:not(.el-button--primary):hover {
|
||||
border-color: rgb(96 165 250);
|
||||
background: rgb(37 99 235 / 22%);
|
||||
color: rgb(241 245 249);
|
||||
}
|
||||
|
||||
.el-button--primary {
|
||||
border-color: rgb(59 130 246);
|
||||
background: rgb(37 99 235);
|
||||
color: rgb(248 250 252);
|
||||
}
|
||||
|
||||
.el-button--primary:hover {
|
||||
border-color: rgb(96 165 250);
|
||||
background: rgb(59 130 246);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
html[data-theme='dark'] .todo-info-dialog.todo-info-dialog--no-footer {
|
||||
.el-dialog__footer {
|
||||
display: none !important;
|
||||
padding: 0 !important;
|
||||
border: none !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user