Commit c6aabfe9 by 周海峰

Merge branch 'master' of https://code.palacesun.com/wuchao/nse-ui

parents f4f5f2e0 a3381a28
<script setup name="ProjectHome">
import { ref, toRefs, reactive, getCurrentInstance, proxyRefs, onMounted } from 'vue'
import { useDict } from '@/utils/dict'
import { changeRoute } from '@/utils/switchRoute'
import biao from '@/assets/images/project/biao.png'
import jiamibiao from '@/assets/images/project/jiamibiao.png'
import jiamiziduan from '@/assets/images/project/jiamiziduan.png'
import shujuyuan from '@/assets/images/project/shujuyuan.png'
import yingyong from '@/assets/images/project/yingyong.png'
import ziduan from '@/assets/images/project/ziduan.png'
import cpu from '@/assets/images/project/cpu.png'
import neicun from '@/assets/images/project/neicun.png'
import rateChart from './modules/rateChart.vue'
import DiskUsageChart from './modules/DiskUsageChart.vue'
<script setup name="Index">
import { onMounted, ref, reactive } from 'vue'
import { CountUp } from 'view-ui-plus';
import { useRouter } from 'vue-router'
import useAppStore from '@/store/modules/app'
import usePermissionStore from '@/store/modules/permission'
const appStore = useAppStore()
const permissionStore = usePermissionStore()
import { changeRoute } from '@/utils/switchRoute'
import img from '@/assets/images/index/index.js'
import HomeCharts from '@/components/HomeCharts/index.vue'
import { getHomePage } from '@/api/home'
const router = useRouter()
const { proxy } = getCurrentInstance()
// const { eo_province, eo_city, eo_district, invoice_type, tax_rate, plan_type, invoice_status } = useDict('eo_province', 'eo_city', 'eo_district', 'invoice_type', 'tax_rate', 'plan_type', 'invoice_status')
const detailLoading = ref(false)
function getInfo() {
detailLoading.value = true
// console.log(props.projectId)
setTimeout(() => {
detailLoading.value = false
}, 3000);
}
const projectId = ref('')
onMounted(()=>{
projectId.value =proxy.$route.query.projectId
console.log('projectId',projectId.value)
})
// const props = defineProps({
// projectId: String, // 主键
// })
const stats = ref([
{ label: '应用', value: 1,url: yingyong },
{ label: '数据源', value: 10, url: shujuyuan},
{ label: '表', value: 340, url:biao },
{ label: '字段', value: 4043, url: ziduan},
{ label: '加密表数量', value: 0, url: jiamibiao},
{ label: '加密字段数量', value: 0, url:jiamiziduan }
const projectId = ref(sessionStorage.getItem('projectId')) // 项目id
// 首页统计数据
const topList = ref([
{
name: '数据源',
icon: img.icon2,
num: 0,
unit: '个'
},
{
name: '表',
icon: img.icon3,
num: 0,
unit: '个'
},
{
name: '字段',
icon: img.icon4,
num: 0,
unit: '个'
},
{
name: '加密表数量',
icon: img.icon5,
num: 0,
unit: '个'
},
{
name: '加密字段数量',
icon: img.icon6,
num: 0,
unit: '个'
}
])
const cpuData = reactive({
cpuUsage: 0,
value: 8
})
// 系统资源数据
const dataObj = ref({
cpuCount: 0,
percentCpuLoad: 0,
totalvirtualMemory: 0,
percentMemoryLoad: 0,
})
const neicunData = reactive({
cpuUsage: 77,
value: 16
// 磁盘空间图表数据
const homeChartData = reactive({
xList: [],
yList1: [],
yList2: [],
})
provide('homeChartData', homeChartData)
const diskData = ref([
{ name: '/run/user/0', total: 100, used: 10 },
{ name: '/boot/efi', total: 100, used: 20 },
{ name: '/boot', total: 100, used: 30 },
{ name: '/run/lock', total: 100, used: 5 },
{ name: '/dev/shm', total: 100, used: 15 },
{ name: '/', total: 100, used: 90 },
{ name: '/run', total: 100, used: 25 }
])
// 获取首页数据
const getHomePageFunc = () => {
getHomePage({projectid: projectId.value}).then(res => {
const { data } = res
dataObj.value = data
topList.value[0].num = data.dataBaseNum
topList.value[1].num = data.tableNum
topList.value[2].num = data.fieldNum
topList.value[3].num = data.encryptTableCount
topList.value[4].num = data.encryptColumnCount
getInfo()
function pageProjectManage() {
if(!data.space) return
homeChartData.xList = data.space.map(item => item.path)
homeChartData.yList1 = data.space.map(item => item.usedpace)
homeChartData.yList2 = data.space.map(item => item.freespace)
})
}
// 返回主页面
const pageProjectManage = () => {
changeRoute()
router.push({
path: '/project/Project'
})
}
defineExpose({
// handleRedInk,
// handleVoid
onMounted(() => {
getHomePageFunc()
})
</script>
<template>
<div class="app-container scroller">
<PageTitle :back="true" @back="pageProjectManage" >
<div class="app-container home scroller">
<PageTitle :back="true" @back="pageProjectManage">
<template #title>
返回项目管理
</template>
</PageTitle>
<div class="app-container__body">
<el-card class="image-card">
<template #header>
<div class="card-header">
<span>数据统计</span>
<el-card class="box-card mt20" :body-style="{ padding: '0' }">
<div class="title">数据统计</div>
<div class="top">
<div class="topItem" v-for="(item, index) in topList" :key="index">
<img class="icon" :src="item.icon" alt="">
<div class="name">{{ item.name }}</div>
<div class="num">
<div>
<CountUp :end="item.num" :duration="3" />
</div>
<div class="unit">{{ item.unit }}</div>
</div>
</template>
<div class="card-content">
<!-- <img src="您的图片路径" alt="数据统计" /> -->
<el-row :gutter="20">
<el-col :span="4" v-for="(item,index) in stats">
<div class="stats-content">
<img class="stats-img" :src="item.url" alt="">
<div class="stats-title">{{item.label}}</div>
<div class="stats-value">{{ item.value }}</div>
</div>
</el-col>
</el-row>
</div>
</el-card>
<el-card class="image-card">
<template #header>
<div class="card-header">
<span>系统资源</span>
</div>
</el-card>
<el-card class="box-card mt20" :body-style="{ padding: '0' }">
<div class="title">系统资源</div>
<div class="bottom" v-if="dataObj">
<div class="bottomItem">
<img class="icon" :src="img.img1" alt="">
<div class="name name1">
<div>
<CountUp :end="dataObj.cpuCount" :duration="2" />
</div>
<div class="unit"></div>
</div>
</template>
<div class="card-content">
<!-- <img src="您的图片路径" alt="数据统计" /> -->
<el-row :gutter="20">
<el-col :span="8">
<div class="chart-content">
<img class="chart-logo" :src="cpu" alt="">
<div class="chart-text">
<div class="value color-blue">{{ cpuData.value }}</div>
<div class="unit color-blue"></div>
</div>
<div class="chart-title">
cpu
</div>
<div class="chart-container">
<rateChart :usage="cpuData.cpuUsage" color="#1890ff"/>
</div>
</div>
</el-col>
<el-col :span="8">
<div class="chart-content">
<img class="chart-logo" :src="neicun" alt="">
<div class="chart-text">
<div class="value color-yellowred">{{ neicunData.value }}</div>
<div class="unit color-yellowred">G</div>
</div>
<div class="chart-title">
内存
</div>
<div class="chart-container">
<rateChart :usage="neicunData.cpuUsage" color="#fa7257"/>
</div>
</div>
</el-col>
<el-col :span="8">
<div class="chart-content">
<div class="chart-container">
<DiskUsageChart :disk-data="diskData" />
</div>
</div>
</el-col>
</el-row>
<div class="type">CPU</div>
<el-progress type="circle" width="140" :indeterminate="true" :percentage="dataObj.percentCpuLoad">
<div class="circle">
<span class="name1">
<CountUp :end="dataObj.percentCpuLoad" :duration="3" />%
</span>
<div>使用率</div>
</div>
</el-progress>
</div>
<div class="line"></div>
<div class="bottomItem">
<img class="icon" :src="img.img2" alt="">
<div class="name name2">
<div>
<CountUp :end="dataObj.totalvirtualMemory" :duration="2" />
</div>
<div class="unit">G</div>
</div>
<div class="type">内存</div>
<el-progress type="circle" width="140" color="rgb(250, 114, 86)" :indeterminate="true" :percentage="dataObj.percentMemoryLoad">
<div class="circle">
<span class="name2">
<CountUp :end="dataObj.percentMemoryLoad" :duration="3" />%
</span>
<div>使用率</div>
</div>
</el-progress>
</div>
<div class="line"></div>
<div class="bottomItem">
<HomeCharts />
</div>
</el-card>
</div>
</div>
</el-card>
</div>
</template>
<style lang="scss" scoped>
.image-card {
width: 100%;
// max-width: 800px;
margin: 20px auto;
}
.card-header {
font-size: 18px;
font-weight: bold;
padding: 15px;
}
.card-content {
padding: 40px 0;
.stats-content {
width: 100%;
<style scoped lang="scss">
.home {
.title {
height: 80px;
line-height: 80px;
border-bottom: 3px solid #f3f5fa;
padding-left: 50px;
font-size: 18px;
color: #333;
font-weight: 700;
}
.top {
display: flex;
flex-direction: column;
justify-content: space-around;
padding: 40px 20px;
align-items: center;
.stats-img {
height: 64px;
width: 64px;
}
.stats-title {
font-size: 16px;
color: #999;
margin-top: 20px;
}
.stats-value {
font-size: 20px;
font-weight: bold;
color: #333;
margin-top: 20px;
height: calc(400px - 120px - 25px);
.topItem {
width: calc(100% / 6);
display: flex;
flex-direction: column;
align-items: center;
.icon {
width: 90px;
height: 90px;
}
.name {
margin-top: -10px;
margin-bottom: 5px;
font-size: 12px;
color: #7a8495;
text-align: center;
}
.num {
display: flex;
align-items: center;
font-size: 18px;
color: #666;
.unit {
margin-left: 5px;
font-size: calc(0.46875vw);
}
}
}
}
.chart-content {
height: 300px;
.bottom {
display: flex;
flex-direction: column;
align-items: center;
.chart-logo {
height: 64px;
width: 64px;
}
.chart-text {
margin-top: 10px;
padding: 20px;
height: 304px;
.bottomItem {
width: calc(((100% - 2px) / 3) - 50px);
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
.name {
display: flex;
align-items: flex-end;
.value {
font-size: 20px;
font-weight: bold;
align-items: center;
font-size: 30px;
.unit {
margin-top: 5px;
margin-left: 3px;
font-weight: bold;
font-size: 18px;
}
}
.unit{
font-size: 14px;
margin-left: 2px;
.name1 {
color: rgb(31, 133, 223);
}
.name2 {
color: rgb(250, 114, 86);
}
.type {
font-size: 16px;
padding-bottom: 15px;
color: #7a8495;
}
.circle {
span {
font-size: 16px;
font-weight: bold;
}
div {
line-height: 20px;
font-size: 14px;
}
}
}
.chart-title {
font-size: 14px;
color: #999;
margin-top: 5px;
.bottomItem:last-child {
padding: 0 50px;
width: calc(((100% - 2px) / 3) + 100px);
}
.chart-container {
flex: 1;
width: 100%;
.line {
background: #dfe1e3;
height: 150px;
width: 1px;
}
}
}
.color-blue{
color: #1890ff;
}
.color-yellowred {
color: #fa7257;
}
</style>
<template>
<div class="disk-chart" ref="chartRef"></div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
import * as echarts from 'echarts'
const colorPalette = [
'#FF6384', '#36A2EB', '#FFCE56', '#4BC0C0', '#9966FF',
'#FF9F40', '#8AC24A', '#F06292', '#7986CB', '#E57373',
'#BA68C8', '#64B5F6', '#4DB6AC', '#81C784', '#FFD54F',
'#FF8A65', '#A1887F', '#90A4AE', '#9575CD', '#4DD0E1'
]
const props = defineProps({
diskData: {
type: Array,
default: () => [
{ name: '/run/user/0', total: 100, used: 10 },
{ name: '/boot/efi', total: 100, used: 20 },
{ name: '/boot', total: 100, used: 30 },
{ name: '/run/lock', total: 100, used: 5 },
{ name: '/dev/shm', total: 100, used: 15 },
{ name: '/', total: 100, used: 90 },
{ name: '/run', total: 100, used: 25 }
]
}
})
const getDiskColor = (index) => {
return colorPalette[index % colorPalette.length]
}
const chartRef = ref(null)
let chartInstance = null
const initChart = () => {
if (!chartRef.value) return
chartInstance = echarts.init(chartRef.value)
const option = {
title: {
text: '磁盘空间',
left: 'center',
textStyle: {
color: '#333',
fontSize: 16,
fontWeight: 'bold'
}
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
},
formatter: function(params) {
return `${params[0].name}<br/>
已使用: ${params[0].value}G<br/>
总容量: ${params[1].value}G`
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'value',
boundaryGap: [0, 0.01],
axisLabel: {
formatter: '{value}G'
},
max: 100,
splitLine: {
show: true,
lineStyle: {
color: '#eee'
}
}
},
yAxis: {
type: 'category',
data: props.diskData.map(item => item.name),
axisLine: {
show: true,
lineStyle: {
color: '#999'
}
},
axisTick: {
show: false
}
},
series: [
{
name: '总容量',
type: 'bar',
data: props.diskData.map(item => item.total),
itemStyle: {
color: '#f5f5f5', // 浅灰色表示总容量
borderWidth: 1,
borderColor: '#d9d9d9'
},
barGap: '-100%', // 让总容量条在已使用条后面
silent: true, // 不响应鼠标事件
label: {
show: false
},
barWidth: '60%'
},
{
name: '已使用',
type: 'bar',
data: props.diskData.map((item, index) => ({
value: item.used,
itemStyle: { color: getDiskColor(index) }
})),
label: {
show: true,
position: 'right',
formatter: '{c}G',
color: '#1890ff',
fontWeight: 'bold'
},
barWidth: '60%'
},
]
}
chartInstance.setOption(option)
}
// 监听窗口变化自动调整图表大小
const resizeHandler = () => {
chartInstance?.resize()
}
// 监听props变化更新图表
watch(() => props.diskData, (newVal) => {
if (chartInstance) {
chartInstance.setOption({
yAxis: {
data: newVal.map(item => item.name)
},
series: [
{
data: newVal.map(item => item.used)
},
{
data: newVal.map(item => item.total)
}
]
})
}
}, { deep: true })
onMounted(() => {
initChart()
window.addEventListener('resize', resizeHandler)
})
onBeforeUnmount(() => {
window.removeEventListener('resize', resizeHandler)
chartInstance?.dispose()
})
</script>
<style scoped>
.disk-chart {
width: 100%;
height: 100%;
background-color: white;
border: 1px solid #f0f0f0;
border-radius: 4px;
padding: 10px;
}
</style>
\ No newline at end of file
<template>
<div class="cpu-usage-chart" ref="chartRef"></div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
import * as echarts from 'echarts'
const props = defineProps({
usage: {
type: Number,
default: 0
},
color: {
type: String,
default: '#1890ff'
}
})
const chartRef = ref(null)
let chartInstance = null
const initChart = () => {
if (!chartRef.value) return
chartInstance = echarts.init(chartRef.value)
const option = {
series: [{
type: 'gauge',
startAngle: 90,
endAngle: -270,
pointer: { show: false },
progress: {
show: true,
overlap: false,
roundCap: true,
clip: false,
itemStyle: {
color: props.color // 进度条颜色 - 蓝色
}
},
axisLine: {
lineStyle: {
width: 10,
color: [[1, '#f0f0f0']] // 背景环颜色 - 浅灰色
}
},
axisTick: { show: false },
splitLine: { show: false },
axisLabel: { show: false },
detail: {
valueAnimation: true,
offsetCenter: [0, '0%'],
formatter: '{value}%',
color: props.color, // 百分比数字颜色 - 蓝色
fontSize: 24,
fontWeight: 'bold'
},
title: {
offsetCenter: [0, '30%'],
color: '#666', // "使用率"文字颜色 - 灰色
fontSize: 14
},
data: [{
value: props.usage,
name: '使用率'
}]
}],
// title: {
// text: 'cpu',
// left: 'center',
// top: '10%',
// textStyle: {
// color: '#666', // "cpu"文字颜色 - 灰色
// fontSize: 14
// }
// }
}
chartInstance.setOption(option)
}
// 监听窗口变化自动调整图表大小
const resizeHandler = () => {
chartInstance?.resize()
}
// 监听props变化更新图表
watch(() => props.usage, (newVal) => {
if (chartInstance) {
chartInstance.setOption({
series: [{
data: [{
value: newVal,
name: '使用率'
}]
}]
})
}
})
onMounted(() => {
initChart()
window.addEventListener('resize', resizeHandler)
})
onBeforeUnmount(() => {
window.removeEventListener('resize', resizeHandler)
chartInstance?.dispose()
})
</script>
<style scoped>
.cpu-usage-chart {
width: 100%;
height: 100%;
background-color: white; /* 白色背景 */
}
</style>
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论