mirror of
https://gitee.com/dromara/mayfly-go
synced 2026-04-22 12:15:17 +08:00
feat: 新增机器状态查看&机器状态等
This commit is contained in:
176
mayfly_go_web/src/common/echarts/theme.json
Normal file
176
mayfly_go_web/src/common/echarts/theme.json
Normal file
@@ -0,0 +1,176 @@
|
||||
{
|
||||
"seriesCnt": "4",
|
||||
"backgroundColor": "rgba(0,0,0,0)",
|
||||
"titleColor": "#008acd",
|
||||
"subtitleColor": "#aaaaaa",
|
||||
"textColorShow": false,
|
||||
"textColor": "#333",
|
||||
"markTextColor": "#eeeeee",
|
||||
"color": [
|
||||
"#2ec7c9",
|
||||
"#b6a2de",
|
||||
"#5ab1ef",
|
||||
"#ffb980",
|
||||
"#d87a80",
|
||||
"#8d98b3",
|
||||
"#e5cf0d",
|
||||
"#97b552",
|
||||
"#95706d",
|
||||
"#dc69aa",
|
||||
"#07a2a4",
|
||||
"#9a7fd1",
|
||||
"#588dd5",
|
||||
"#f5994e",
|
||||
"#c05050",
|
||||
"#59678c",
|
||||
"#c9ab00",
|
||||
"#7eb00a",
|
||||
"#6f5553",
|
||||
"#c14089"
|
||||
],
|
||||
"borderColor": "#ccc",
|
||||
"borderWidth": 0,
|
||||
"visualMapColor": [
|
||||
"#5ab1ef",
|
||||
"#e0ffff"
|
||||
],
|
||||
"legendTextColor": "#333333",
|
||||
"kColor": "#d87a80",
|
||||
"kColor0": "#2ec7c9",
|
||||
"kBorderColor": "#d87a80",
|
||||
"kBorderColor0": "#2ec7c9",
|
||||
"kBorderWidth": 1,
|
||||
"lineWidth": 2,
|
||||
"symbolSize": 3,
|
||||
"symbol": "emptyCircle",
|
||||
"symbolBorderWidth": 1,
|
||||
"lineSmooth": true,
|
||||
"graphLineWidth": 1,
|
||||
"graphLineColor": "#aaaaaa",
|
||||
"mapLabelColor": "#d87a80",
|
||||
"mapLabelColorE": "rgb(100,0,0)",
|
||||
"mapBorderColor": "#eeeeee",
|
||||
"mapBorderColorE": "#444",
|
||||
"mapBorderWidth": 0.5,
|
||||
"mapBorderWidthE": 1,
|
||||
"mapAreaColor": "#dddddd",
|
||||
"mapAreaColorE": "rgba(254,153,78,1)",
|
||||
"axes": [
|
||||
{
|
||||
"type": "all",
|
||||
"name": "通用坐标轴",
|
||||
"axisLineShow": true,
|
||||
"axisLineColor": "#eeeeee",
|
||||
"axisTickShow": true,
|
||||
"axisTickColor": "#eeeeee",
|
||||
"axisLabelShow": true,
|
||||
"axisLabelColor": "#eeeeee",
|
||||
"splitLineShow": true,
|
||||
"splitLineColor": [
|
||||
"#aaaaaa"
|
||||
],
|
||||
"splitAreaShow": false,
|
||||
"splitAreaColor": [
|
||||
"#eeeeee"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"name": "类目坐标轴",
|
||||
"axisLineShow": true,
|
||||
"axisLineColor": "#008acd",
|
||||
"axisTickShow": true,
|
||||
"axisTickColor": "#333",
|
||||
"axisLabelShow": true,
|
||||
"axisLabelColor": "#333",
|
||||
"splitLineShow": false,
|
||||
"splitLineColor": [
|
||||
"#eee"
|
||||
],
|
||||
"splitAreaShow": false,
|
||||
"splitAreaColor": [
|
||||
"rgba(250,250,250,0.3)",
|
||||
"rgba(200,200,200,0.3)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "value",
|
||||
"name": "数值坐标轴",
|
||||
"axisLineShow": true,
|
||||
"axisLineColor": "#008acd",
|
||||
"axisTickShow": true,
|
||||
"axisTickColor": "#333",
|
||||
"axisLabelShow": true,
|
||||
"axisLabelColor": "#333",
|
||||
"splitLineShow": true,
|
||||
"splitLineColor": [
|
||||
"#eee"
|
||||
],
|
||||
"splitAreaShow": true,
|
||||
"splitAreaColor": [
|
||||
"rgba(250,250,250,0.3)",
|
||||
"rgba(200,200,200,0.3)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "log",
|
||||
"name": "对数坐标轴",
|
||||
"axisLineShow": true,
|
||||
"axisLineColor": "#008acd",
|
||||
"axisTickShow": true,
|
||||
"axisTickColor": "#333",
|
||||
"axisLabelShow": true,
|
||||
"axisLabelColor": "#333",
|
||||
"splitLineShow": true,
|
||||
"splitLineColor": [
|
||||
"#eee"
|
||||
],
|
||||
"splitAreaShow": true,
|
||||
"splitAreaColor": [
|
||||
"rgba(250,250,250,0.3)",
|
||||
"rgba(200,200,200,0.3)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "time",
|
||||
"name": "时间坐标轴",
|
||||
"axisLineShow": true,
|
||||
"axisLineColor": "#008acd",
|
||||
"axisTickShow": true,
|
||||
"axisTickColor": "#333",
|
||||
"axisLabelShow": true,
|
||||
"axisLabelColor": "#333",
|
||||
"splitLineShow": true,
|
||||
"splitLineColor": [
|
||||
"#eee"
|
||||
],
|
||||
"splitAreaShow": false,
|
||||
"splitAreaColor": [
|
||||
"rgba(250,250,250,0.3)",
|
||||
"rgba(200,200,200,0.3)"
|
||||
]
|
||||
}
|
||||
],
|
||||
"axisSeperateSetting": true,
|
||||
"toolboxColor": "#2ec7c9",
|
||||
"toolboxEmphasisColor": "#18a4a6",
|
||||
"tooltipAxisColor": "#008acd",
|
||||
"tooltipAxisWidth": "1",
|
||||
"timelineLineColor": "#008acd",
|
||||
"timelineLineWidth": 1,
|
||||
"timelineItemColor": "#008acd",
|
||||
"timelineItemColorE": "#a9334c",
|
||||
"timelineCheckColor": "#2ec7c9",
|
||||
"timelineCheckBorderColor": "#2ec7c9",
|
||||
"timelineItemBorderWidth": 1,
|
||||
"timelineControlColor": "#008acd",
|
||||
"timelineControlBorderColor": "#008acd",
|
||||
"timelineControlBorderWidth": 0.5,
|
||||
"timelineLabelColor": "#008acd",
|
||||
"datazoomBackgroundColor": "rgba(47,69,84,0)",
|
||||
"datazoomDataColor": "#efefff",
|
||||
"datazoomFillColor": "rgba(182,162,222,0.2)",
|
||||
"datazoomHandleColor": "#008acd",
|
||||
"datazoomHandleWidth": "100",
|
||||
"datazoomLabelColor": "#333333"
|
||||
}
|
||||
7
mayfly_go_web/src/common/echarts/useEcharts.ts
Normal file
7
mayfly_go_web/src/common/echarts/useEcharts.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import * as echarts from 'echarts'
|
||||
|
||||
export default function(dom: any, theme: any = null, option: any) {
|
||||
let chart = echarts.init(dom, theme);
|
||||
chart.setOption(option);
|
||||
return chart;
|
||||
}
|
||||
@@ -1,32 +1,53 @@
|
||||
import type { App } from 'vue';
|
||||
import { store } from '@/store/index.ts';
|
||||
import { judementSameArr } from '@/common/utils/arrayOperation.ts';
|
||||
import { auth, auths, authAll } from './authFunction'
|
||||
|
||||
// 用户权限指令
|
||||
export function authDirective(app: App) {
|
||||
// 单个权限验证(v-auth="xxx")
|
||||
app.directive('auth', {
|
||||
mounted(el, binding) {
|
||||
if (!store.state.userInfos.userInfos.permissions.some((v: any) => v === binding.value)) el.parentNode.removeChild(el);
|
||||
if (!auth(binding.value)) {
|
||||
parseNoAuth(el, binding);
|
||||
};
|
||||
},
|
||||
});
|
||||
// 多个权限验证,满足一个则显示(v-auths="[xxx,xxx]")
|
||||
app.directive('auths', {
|
||||
mounted(el, binding) {
|
||||
let flag = false;
|
||||
store.state.userInfos.userInfos.permissions.map((val: any) => {
|
||||
binding.value.map((v: any) => {
|
||||
if (val === v) flag = true;
|
||||
});
|
||||
});
|
||||
if (!flag) el.parentNode.removeChild(el);
|
||||
if (!auths(binding.value)) {
|
||||
parseNoAuth(el, binding);
|
||||
}
|
||||
},
|
||||
});
|
||||
// 多个权限验证,全部满足则显示(v-auth-all="[xxx,xxx]")
|
||||
app.directive('auth-all', {
|
||||
mounted(el, binding) {
|
||||
const flag = judementSameArr(binding.value, store.state.userInfos.userInfos.permissions);
|
||||
if (!flag) el.parentNode.removeChild(el);
|
||||
if (!authAll(binding.value)) {
|
||||
parseNoAuth(el, binding);
|
||||
};
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理没有权限场景
|
||||
*
|
||||
* @param el 元素
|
||||
* @param binding 绑定至
|
||||
*/
|
||||
const parseNoAuth = (el: any, binding: any) => {
|
||||
const { arg } = binding;
|
||||
// 如果是禁用模式,则将元素禁用
|
||||
if (arg == 'disabled') {
|
||||
el.setAttribute('disabled', true);
|
||||
el.classList.add('is-disabled');
|
||||
el.addEventListener('click', disableClickFn, true);
|
||||
} else {
|
||||
// 移除该元素
|
||||
el.parentNode.removeChild(el);
|
||||
}
|
||||
}
|
||||
|
||||
const disableClickFn = (event: any) => {
|
||||
event && event.stopImmediatePropagation();
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
<template>
|
||||
<div class="active-plate-main">
|
||||
<ul class="active-list">
|
||||
<li class="item" v-for="item in infoList" :key="item.title">
|
||||
<p class="num" :style="{color:item.color}">{{item.count}}</p>
|
||||
<p class="desc">{{item.title}}</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'activePlate',
|
||||
components: {},
|
||||
props: {
|
||||
// 需要展示的数据集合
|
||||
infoList: {
|
||||
type: Array,
|
||||
require: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.active-plate-main {
|
||||
width: 100%;
|
||||
height: 130px;
|
||||
.active-list {
|
||||
display: flex;
|
||||
list-style: none;
|
||||
padding-top: 15px;
|
||||
.item {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
.num {
|
||||
font-size: 42px;
|
||||
font-weight: bold;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
.desc {
|
||||
font-size: 16px;
|
||||
}
|
||||
&::after {
|
||||
position: absolute;
|
||||
top: 18px;
|
||||
right: 0;
|
||||
content: '';
|
||||
display: block;
|
||||
width: 1px;
|
||||
height: 56px;
|
||||
background: #e7eef0;
|
||||
}
|
||||
&:nth-last-of-type(1) {
|
||||
&::after {
|
||||
background: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,39 +0,0 @@
|
||||
<template>
|
||||
<div class="base-chart" id="box" ref="dom"></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
import tdTheme from './theme.json'
|
||||
import { on, off } from './onoff'
|
||||
echarts.registerTheme('tdTheme', tdTheme)
|
||||
export default {
|
||||
props: {
|
||||
option: Object,
|
||||
},
|
||||
mounted() {
|
||||
this.initChart()
|
||||
},
|
||||
methods: {
|
||||
resize() {
|
||||
this.dom.resize()
|
||||
},
|
||||
initChart() {
|
||||
this.$nextTick(() => {
|
||||
this.dom = echarts.init(this.$refs.dom, 'tdTheme')
|
||||
this.dom.setOption(this.option)
|
||||
on(window, 'resize', this.resize)
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.base-chart {
|
||||
width: 100%;
|
||||
height: 360px;
|
||||
padding: 28px;
|
||||
background: #fff;
|
||||
}
|
||||
</style>
|
||||
@@ -1,43 +0,0 @@
|
||||
<template>
|
||||
<div class="card-main">
|
||||
<div class="title">
|
||||
{{title}}
|
||||
<span>{{desc}}</span>
|
||||
</div>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: '标题'
|
||||
},
|
||||
desc: {
|
||||
type: String,
|
||||
default: '描述'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang='scss'>
|
||||
.card-main {
|
||||
border-radius: 8px;
|
||||
background: #fff;
|
||||
margin-bottom: 20px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.title {
|
||||
color: #060606;
|
||||
font-size: 16px;
|
||||
padding: 20px 32px;
|
||||
span {
|
||||
padding-left: 17px;
|
||||
font-size: 12px;
|
||||
color: #dededf;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,138 +0,0 @@
|
||||
<template>
|
||||
<div class="bar-main" id="box" ref="dom"></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
import tdTheme from './theme.json'
|
||||
import { on, off } from './onoff'
|
||||
echarts.registerTheme('tdTheme', tdTheme)
|
||||
export default {
|
||||
props: {
|
||||
value: Object,
|
||||
text: String,
|
||||
subtext: String
|
||||
},
|
||||
mounted() {
|
||||
this.initChart()
|
||||
},
|
||||
methods: {
|
||||
resize() {
|
||||
this.dom.resize()
|
||||
},
|
||||
initChart() {
|
||||
this.$nextTick(() => {
|
||||
const xAxisData = Object.keys(this.value)
|
||||
const seriesData = Object.values(this.value)
|
||||
const option = {
|
||||
grid: {
|
||||
left: '1%',
|
||||
right: '1%',
|
||||
top: '2%',
|
||||
bottom: '1%',
|
||||
containLabel: true
|
||||
},
|
||||
title: {
|
||||
text: this.text,
|
||||
subtext: this.subtext,
|
||||
x: 'center'
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: '{c}人',
|
||||
// position: ['30%', '90%'],
|
||||
position: 'top',
|
||||
backgroundColor: '#FAFBFE',
|
||||
textStyle: {
|
||||
fontSize: 14,
|
||||
color: '#6d6d6d'
|
||||
}
|
||||
},
|
||||
xAxis: {
|
||||
// show: false,
|
||||
type: 'category',
|
||||
data: xAxisData,
|
||||
splitLine: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
yAxis: [
|
||||
{
|
||||
// show: false,
|
||||
type: 'value',
|
||||
splitLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
// 设置刻度线粗度(粗的宽度)
|
||||
width: 1,
|
||||
// 颜色数组,数组数量要比刻度线数量大才能不循环使用
|
||||
color: [
|
||||
'rgba(0, 0, 0, 0)',
|
||||
'#eee',
|
||||
'#eee',
|
||||
'#eee',
|
||||
'#eee',
|
||||
'#eee',
|
||||
'#eee',
|
||||
'#eee',
|
||||
'#eee'
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
series: [
|
||||
{
|
||||
data: seriesData,
|
||||
type: 'bar',
|
||||
barWidth: 36,
|
||||
areaStyle: {
|
||||
normal: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: '#f2f5ff' },
|
||||
{ offset: 1, color: '#fff' }
|
||||
])
|
||||
}
|
||||
},
|
||||
itemStyle: {
|
||||
normal: {
|
||||
barBorderRadius: [50],
|
||||
color: new echarts.graphic.LinearGradient(
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
[
|
||||
{
|
||||
offset: 0,
|
||||
color: '#3AA1FF' // 0% 处的颜色
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: '#36CBCB' // 100% 处的颜色
|
||||
}
|
||||
],
|
||||
false
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
this.dom = echarts.init(this.$refs.dom, 'tdTheme')
|
||||
this.dom.setOption(option)
|
||||
on(window, 'resize', this.resize)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.bar-main {
|
||||
width: 100%;
|
||||
height: 360px;
|
||||
padding: 28px;
|
||||
background: #fff;
|
||||
}
|
||||
</style>
|
||||
@@ -1,92 +0,0 @@
|
||||
<template>
|
||||
<div class="line-main" id="box" ref="dom"></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
import tdTheme from './theme.json'
|
||||
import { on, off } from './onoff'
|
||||
echarts.registerTheme('tdTheme', tdTheme)
|
||||
export default {
|
||||
props: {
|
||||
value: Array,
|
||||
title: String,
|
||||
subtext: String,
|
||||
},
|
||||
mounted() {
|
||||
this.initChart()
|
||||
},
|
||||
methods: {
|
||||
resize() {
|
||||
this.dom.resize()
|
||||
},
|
||||
initChart() {
|
||||
this.$nextTick(() => {
|
||||
const dateList = this.value.map(function (item) {
|
||||
return item[0]
|
||||
})
|
||||
const valueList = this.value.map(function (item) {
|
||||
return item[1]
|
||||
})
|
||||
|
||||
const option = {
|
||||
// Make gradient line here
|
||||
visualMap: [
|
||||
{
|
||||
show: false,
|
||||
type: 'continuous',
|
||||
seriesIndex: 0,
|
||||
min: 0,
|
||||
max: 400,
|
||||
}
|
||||
],
|
||||
|
||||
title: [
|
||||
{
|
||||
left: 'center',
|
||||
text: this.title,
|
||||
}
|
||||
],
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
},
|
||||
xAxis: [
|
||||
{
|
||||
data: dateList,
|
||||
}
|
||||
],
|
||||
yAxis: [
|
||||
{
|
||||
splitLine: { show: false },
|
||||
},
|
||||
],
|
||||
grid: [
|
||||
{
|
||||
|
||||
},
|
||||
],
|
||||
series: [
|
||||
{
|
||||
type: 'line',
|
||||
showSymbol: false,
|
||||
data: valueList,
|
||||
},
|
||||
],
|
||||
}
|
||||
this.dom = echarts.init(this.$refs.dom, 'tdTheme')
|
||||
this.dom.setOption(option)
|
||||
on(window, 'resize', this.resize)
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.line-main {
|
||||
width: 100%;
|
||||
height: 360px;
|
||||
padding: 28px;
|
||||
background: #fff;
|
||||
}
|
||||
</style>
|
||||
@@ -1,104 +0,0 @@
|
||||
<template>
|
||||
<div class="funnel-main" id="box" ref="dom"></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
import tdTheme from './theme.json'
|
||||
import { on, off } from './onoff'
|
||||
echarts.registerTheme('tdTheme', tdTheme)
|
||||
export default {
|
||||
props: {
|
||||
value: Array,
|
||||
text: String,
|
||||
subtext: String
|
||||
},
|
||||
mounted() {
|
||||
this.initChart()
|
||||
},
|
||||
methods: {
|
||||
resize() {
|
||||
this.dom.resize()
|
||||
},
|
||||
initChart() {
|
||||
this.$nextTick(() => {
|
||||
const legend = this.value.map(_ => _.name)
|
||||
const option = {
|
||||
grid: {
|
||||
left: '1%',
|
||||
right: '1%',
|
||||
top: '2%',
|
||||
bottom: '1%',
|
||||
containLabel: true
|
||||
},
|
||||
title: {
|
||||
text: this.text,
|
||||
subtext: this.subtext,
|
||||
x: 'center'
|
||||
},
|
||||
tooltip: {
|
||||
show: false,
|
||||
trigger: 'item',
|
||||
formatter: '{c} ({d}%)',
|
||||
// position: ['30%', '90%'],
|
||||
position: 'right',
|
||||
backgroundColor: 'transparent',
|
||||
textStyle: {
|
||||
fontSize: 14,
|
||||
color: '#666'
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
left: 'right',
|
||||
bottom: 0,
|
||||
|
||||
// data: legend,
|
||||
backgroundColor: 'transparent',
|
||||
icon: 'circle'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '访问来源',
|
||||
type: 'funnel',
|
||||
radius: ['50%', '65%'],
|
||||
avoidLabelOverlap: false,
|
||||
label: {
|
||||
normal: {
|
||||
show: false,
|
||||
position: 'right',
|
||||
formatter: '{c} ({d}%)'
|
||||
}
|
||||
},
|
||||
// labelLine: {
|
||||
// normal: {
|
||||
// show: false
|
||||
// }
|
||||
// },
|
||||
data: [
|
||||
{ value: 400, name: '交易完成' },
|
||||
{ value: 300, name: '支付订单' },
|
||||
{ value: 200, name: '生成订单' },
|
||||
{ value: 100, name: '放入购物车' },
|
||||
{ value: 100, name: '浏览网站' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
this.dom = echarts.init(this.$refs.dom, 'tdTheme')
|
||||
this.dom.setOption(option)
|
||||
on(window, 'resize', this.resize)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.funnel-main {
|
||||
width: 100%;
|
||||
height: 295px;
|
||||
padding: 28px;
|
||||
background: #fff;
|
||||
}
|
||||
</style>
|
||||
@@ -1,89 +0,0 @@
|
||||
<template>
|
||||
<div class="gauge-main" id="box" ref="dom"></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
import tdTheme from './theme.json'
|
||||
import { on, off } from './onoff'
|
||||
echarts.registerTheme('tdTheme', tdTheme)
|
||||
export default {
|
||||
props: {
|
||||
value: Object,
|
||||
text: String,
|
||||
subtext: String
|
||||
},
|
||||
mounted() {
|
||||
this.initChart()
|
||||
},
|
||||
methods: {
|
||||
resize() {
|
||||
this.dom.resize()
|
||||
},
|
||||
initChart() {
|
||||
this.$nextTick(() => {
|
||||
const option = {
|
||||
grid: {
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: 0,
|
||||
bottom: 0
|
||||
// containLabel: true
|
||||
},
|
||||
tooltip: {
|
||||
formatter: '{a} <br/>{b} : {c}%'
|
||||
},
|
||||
toolbox: {},
|
||||
series: [
|
||||
{
|
||||
name: '业务指标',
|
||||
startAngle: 195,
|
||||
endAngle: -15,
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: [
|
||||
[0.6, '#4ECB73'],
|
||||
[0.8, '#FBD437'],
|
||||
[1, '#F47F92']
|
||||
],
|
||||
width: 16
|
||||
}
|
||||
},
|
||||
pointer: {
|
||||
length: '80%',
|
||||
width: 3,
|
||||
color: 'auto'
|
||||
},
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
splitLine: { show: false },
|
||||
type: 'gauge',
|
||||
detail: {
|
||||
formatter: '{value}%',
|
||||
textStyle: {
|
||||
color: '#595959',
|
||||
fontSize: 32
|
||||
}
|
||||
},
|
||||
data: [{ value: 10 }]
|
||||
}
|
||||
]
|
||||
}
|
||||
this.dom = echarts.init(this.$refs.dom, 'tdTheme')
|
||||
this.dom.setOption(option)
|
||||
on(window, 'resize', this.resize)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.gauge-main {
|
||||
width: 100%;
|
||||
height: 360px;
|
||||
background: #fff;
|
||||
}
|
||||
</style>
|
||||
@@ -1,121 +0,0 @@
|
||||
<template>
|
||||
<div class="line-main" id="box" ref="dom"></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
import tdTheme from './theme.json'
|
||||
import { on, off } from './onoff'
|
||||
echarts.registerTheme('tdTheme', tdTheme)
|
||||
export default {
|
||||
props: {
|
||||
value: Object,
|
||||
text: String,
|
||||
subtext: String
|
||||
},
|
||||
mounted() {
|
||||
this.initChart()
|
||||
},
|
||||
methods: {
|
||||
resize() {
|
||||
this.dom.resize()
|
||||
},
|
||||
initChart() {
|
||||
this.$nextTick(() => {
|
||||
const xAxisData = Object.keys(this.value)
|
||||
const seriesData = Object.values(this.value)
|
||||
const option = {
|
||||
grid: {
|
||||
left: '1%',
|
||||
right: '1%',
|
||||
top: '2%',
|
||||
bottom: '1%',
|
||||
containLabel: true
|
||||
},
|
||||
title: {
|
||||
text: this.text,
|
||||
subtext: this.subtext,
|
||||
x: 'center'
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: '{c}人',
|
||||
// position: ['30%', '90%'],
|
||||
position: 'top',
|
||||
backgroundColor: '#387DE1',
|
||||
textStyle: {
|
||||
fontSize: 18,
|
||||
color: '#fff'
|
||||
}
|
||||
},
|
||||
xAxis: {
|
||||
// show: false,
|
||||
type: 'category',
|
||||
data: xAxisData,
|
||||
splitLine: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
yAxis: [
|
||||
{
|
||||
// show: false,
|
||||
type: 'value',
|
||||
splitLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
// 设置刻度线粗度(粗的宽度)
|
||||
width: 1,
|
||||
// 颜色数组,数组数量要比刻度线数量大才能不循环使用
|
||||
color: [
|
||||
'rgba(0, 0, 0, 0)',
|
||||
'#eee',
|
||||
'#eee',
|
||||
'#eee',
|
||||
'#eee',
|
||||
'#eee',
|
||||
'#eee',
|
||||
'#eee',
|
||||
'#eee'
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
series: [
|
||||
{
|
||||
data: seriesData,
|
||||
type: 'line',
|
||||
areaStyle: {
|
||||
normal: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: '#f2f5ff' },
|
||||
{ offset: 1, color: '#fff' }
|
||||
])
|
||||
}
|
||||
},
|
||||
lineStyle: {
|
||||
normal: {
|
||||
width: 5,
|
||||
color: '#36CBCB'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
this.dom = echarts.init(this.$refs.dom, 'tdTheme')
|
||||
this.dom.setOption(option)
|
||||
on(window, 'resize', this.resize)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.line-main {
|
||||
width: 100%;
|
||||
height: 360px;
|
||||
padding: 28px;
|
||||
background: #fff;
|
||||
}
|
||||
</style>
|
||||
@@ -1,111 +0,0 @@
|
||||
<template>
|
||||
<div class="pie-main" id="box" ref="dom"></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
import tdTheme from './theme.json'
|
||||
import { on, off } from './onoff'
|
||||
echarts.registerTheme('tdTheme', tdTheme)
|
||||
export default {
|
||||
props: {
|
||||
value: Array,
|
||||
text: String,
|
||||
subtext: String,
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
handler: function (val, oldval) {
|
||||
this.value = val
|
||||
this.initChart()
|
||||
},
|
||||
deep: true, //对象内部的属性监听,也叫深度监听
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.initChart()
|
||||
},
|
||||
methods: {
|
||||
resize() {
|
||||
this.dom.resize()
|
||||
},
|
||||
initChart() {
|
||||
this.$nextTick(() => {
|
||||
const legend = this.value.map((_) => _.name)
|
||||
const option = {
|
||||
title: {
|
||||
text: this.text,
|
||||
subtext: this.subtext,
|
||||
x: 'center',
|
||||
},
|
||||
position: {
|
||||
top: 40,
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: '{c} ({d}%)',
|
||||
// position: ['30%', '90%'],
|
||||
position: function (point, params, dom, rect, size) {
|
||||
console.log(size)
|
||||
const leftWidth = size.viewSize[0] / 2 - size.contentSize[0] / 2
|
||||
console.log(leftWidth)
|
||||
return { left: leftWidth, bottom: 0 }
|
||||
},
|
||||
backgroundColor: 'transparent',
|
||||
textStyle: {
|
||||
fontSize: 24,
|
||||
color: '#666',
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
// orient: 'vertical',
|
||||
top: 0,
|
||||
data: legend,
|
||||
backgroundColor: 'transparent',
|
||||
icon: 'circle',
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '访问来源',
|
||||
type: 'pie',
|
||||
radius: ['45%', '60%'],
|
||||
center: ['50%', '52%'],
|
||||
avoidLabelOverlap: false,
|
||||
label: {
|
||||
normal: {
|
||||
show: false,
|
||||
position: 'center',
|
||||
},
|
||||
emphasis: {
|
||||
show: true,
|
||||
textStyle: {
|
||||
fontSize: '24',
|
||||
},
|
||||
},
|
||||
},
|
||||
labelLine: {
|
||||
normal: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
data: this.value,
|
||||
},
|
||||
],
|
||||
}
|
||||
this.dom = echarts.init(this.$refs.dom, 'tdTheme')
|
||||
this.dom.setOption(option)
|
||||
on(window, 'resize', this.resize)
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.pie-main {
|
||||
width: 100%;
|
||||
height: 360px;
|
||||
padding: 28px;
|
||||
background: #fff;
|
||||
}
|
||||
</style>
|
||||
@@ -1,37 +0,0 @@
|
||||
/**
|
||||
* @description 绑定事件 on(element, event, handler)
|
||||
*/
|
||||
export const on = (function () {
|
||||
if (document.addEventListener != null) {
|
||||
return function (element, event, handler) {
|
||||
if (element && event && handler) {
|
||||
element.addEventListener(event, handler, false);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return function (element, event, handler) {
|
||||
if (element && event && handler) {
|
||||
element.attachEvent('on' + event, handler);
|
||||
}
|
||||
};
|
||||
}
|
||||
})();
|
||||
|
||||
/**
|
||||
* @description 解绑事件 off(element, event, handler)
|
||||
*/
|
||||
export const off = (function () {
|
||||
if (document.removeEventListener != null) {
|
||||
return function (element, event, handler) {
|
||||
if (element && event) {
|
||||
element.removeEventListener(event, handler, false);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return function (element, event, handler) {
|
||||
if (element && event) {
|
||||
element.detachEvent('on' + event, handler);
|
||||
}
|
||||
};
|
||||
}
|
||||
})();
|
||||
@@ -1,490 +0,0 @@
|
||||
{
|
||||
"color": [
|
||||
"#2d8cf0",
|
||||
"#19be6b",
|
||||
"#ff9900",
|
||||
"#E46CBB",
|
||||
"#9A66E4",
|
||||
"#ed3f14"
|
||||
],
|
||||
"backgroundColor": "rgba(0,0,0,0)",
|
||||
"textStyle": {},
|
||||
"title": {
|
||||
"textStyle": {
|
||||
"color": "#516b91"
|
||||
},
|
||||
"subtextStyle": {
|
||||
"color": "#93b7e3"
|
||||
}
|
||||
},
|
||||
"line": {
|
||||
"itemStyle": {
|
||||
"normal": {
|
||||
"borderWidth": "2"
|
||||
}
|
||||
},
|
||||
"lineStyle": {
|
||||
"normal": {
|
||||
"width": "2"
|
||||
}
|
||||
},
|
||||
"symbolSize": "6",
|
||||
"symbol": "emptyCircle",
|
||||
"smooth": true
|
||||
},
|
||||
"radar": {
|
||||
"itemStyle": {
|
||||
"normal": {
|
||||
"borderWidth": "2"
|
||||
}
|
||||
},
|
||||
"lineStyle": {
|
||||
"normal": {
|
||||
"width": "2"
|
||||
}
|
||||
},
|
||||
"symbolSize": "6",
|
||||
"symbol": "emptyCircle",
|
||||
"smooth": true
|
||||
},
|
||||
"bar": {
|
||||
"itemStyle": {
|
||||
"normal": {
|
||||
"barBorderWidth": 0,
|
||||
"barBorderColor": "#ccc"
|
||||
},
|
||||
"emphasis": {
|
||||
"barBorderWidth": 0,
|
||||
"barBorderColor": "#ccc"
|
||||
}
|
||||
}
|
||||
},
|
||||
"pie": {
|
||||
"itemStyle": {
|
||||
"normal": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
},
|
||||
"emphasis": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
}
|
||||
}
|
||||
},
|
||||
"scatter": {
|
||||
"itemStyle": {
|
||||
"normal": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
},
|
||||
"emphasis": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
}
|
||||
}
|
||||
},
|
||||
"boxplot": {
|
||||
"itemStyle": {
|
||||
"normal": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
},
|
||||
"emphasis": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parallel": {
|
||||
"itemStyle": {
|
||||
"normal": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
},
|
||||
"emphasis": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sankey": {
|
||||
"itemStyle": {
|
||||
"normal": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
},
|
||||
"emphasis": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
}
|
||||
}
|
||||
},
|
||||
"funnel": {
|
||||
"itemStyle": {
|
||||
"normal": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
},
|
||||
"emphasis": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
}
|
||||
}
|
||||
},
|
||||
"gauge": {
|
||||
"itemStyle": {
|
||||
"normal": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
},
|
||||
"emphasis": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
}
|
||||
}
|
||||
},
|
||||
"candlestick": {
|
||||
"itemStyle": {
|
||||
"normal": {
|
||||
"color": "#edafda",
|
||||
"color0": "transparent",
|
||||
"borderColor": "#d680bc",
|
||||
"borderColor0": "#8fd3e8",
|
||||
"borderWidth": "2"
|
||||
}
|
||||
}
|
||||
},
|
||||
"graph": {
|
||||
"itemStyle": {
|
||||
"normal": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
}
|
||||
},
|
||||
"lineStyle": {
|
||||
"normal": {
|
||||
"width": 1,
|
||||
"color": "#aaa"
|
||||
}
|
||||
},
|
||||
"symbolSize": "6",
|
||||
"symbol": "emptyCircle",
|
||||
"smooth": true,
|
||||
"color": [
|
||||
"#2d8cf0",
|
||||
"#19be6b",
|
||||
"#f5ae4a",
|
||||
"#9189d5",
|
||||
"#56cae2",
|
||||
"#cbb0e3"
|
||||
],
|
||||
"label": {
|
||||
"normal": {
|
||||
"textStyle": {
|
||||
"color": "#eee"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"map": {
|
||||
"itemStyle": {
|
||||
"normal": {
|
||||
"areaColor": "#f3f3f3",
|
||||
"borderColor": "#516b91",
|
||||
"borderWidth": 0.5
|
||||
},
|
||||
"emphasis": {
|
||||
"areaColor": "rgba(165,231,240,1)",
|
||||
"borderColor": "#516b91",
|
||||
"borderWidth": 1
|
||||
}
|
||||
},
|
||||
"label": {
|
||||
"normal": {
|
||||
"textStyle": {
|
||||
"color": "#000"
|
||||
}
|
||||
},
|
||||
"emphasis": {
|
||||
"textStyle": {
|
||||
"color": "rgb(81,107,145)"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"geo": {
|
||||
"itemStyle": {
|
||||
"normal": {
|
||||
"areaColor": "#f3f3f3",
|
||||
"borderColor": "#516b91",
|
||||
"borderWidth": 0.5
|
||||
},
|
||||
"emphasis": {
|
||||
"areaColor": "rgba(165,231,240,1)",
|
||||
"borderColor": "#516b91",
|
||||
"borderWidth": 1
|
||||
}
|
||||
},
|
||||
"label": {
|
||||
"normal": {
|
||||
"textStyle": {
|
||||
"color": "#000"
|
||||
}
|
||||
},
|
||||
"emphasis": {
|
||||
"textStyle": {
|
||||
"color": "rgb(81,107,145)"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"categoryAxis": {
|
||||
"axisLine": {
|
||||
"show": true,
|
||||
"lineStyle": {
|
||||
"color": "#cccccc"
|
||||
}
|
||||
},
|
||||
"axisTick": {
|
||||
"show": false,
|
||||
"lineStyle": {
|
||||
"color": "#333"
|
||||
}
|
||||
},
|
||||
"axisLabel": {
|
||||
"show": true,
|
||||
"textStyle": {
|
||||
"color": "#999999"
|
||||
}
|
||||
},
|
||||
"splitLine": {
|
||||
"show": true,
|
||||
"lineStyle": {
|
||||
"color": [
|
||||
"#eeeeee"
|
||||
]
|
||||
}
|
||||
},
|
||||
"splitArea": {
|
||||
"show": false,
|
||||
"areaStyle": {
|
||||
"color": [
|
||||
"rgba(250,250,250,0.05)",
|
||||
"rgba(200,200,200,0.02)"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"valueAxis": {
|
||||
"axisLine": {
|
||||
"show": true,
|
||||
"lineStyle": {
|
||||
"color": "#cccccc"
|
||||
}
|
||||
},
|
||||
"axisTick": {
|
||||
"show": false,
|
||||
"lineStyle": {
|
||||
"color": "#333"
|
||||
}
|
||||
},
|
||||
"axisLabel": {
|
||||
"show": true,
|
||||
"textStyle": {
|
||||
"color": "#999999"
|
||||
}
|
||||
},
|
||||
"splitLine": {
|
||||
"show": true,
|
||||
"lineStyle": {
|
||||
"color": [
|
||||
"#eeeeee"
|
||||
]
|
||||
}
|
||||
},
|
||||
"splitArea": {
|
||||
"show": false,
|
||||
"areaStyle": {
|
||||
"color": [
|
||||
"rgba(250,250,250,0.05)",
|
||||
"rgba(200,200,200,0.02)"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"logAxis": {
|
||||
"axisLine": {
|
||||
"show": true,
|
||||
"lineStyle": {
|
||||
"color": "#cccccc"
|
||||
}
|
||||
},
|
||||
"axisTick": {
|
||||
"show": false,
|
||||
"lineStyle": {
|
||||
"color": "#333"
|
||||
}
|
||||
},
|
||||
"axisLabel": {
|
||||
"show": true,
|
||||
"textStyle": {
|
||||
"color": "#999999"
|
||||
}
|
||||
},
|
||||
"splitLine": {
|
||||
"show": true,
|
||||
"lineStyle": {
|
||||
"color": [
|
||||
"#eeeeee"
|
||||
]
|
||||
}
|
||||
},
|
||||
"splitArea": {
|
||||
"show": false,
|
||||
"areaStyle": {
|
||||
"color": [
|
||||
"rgba(250,250,250,0.05)",
|
||||
"rgba(200,200,200,0.02)"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"timeAxis": {
|
||||
"axisLine": {
|
||||
"show": true,
|
||||
"lineStyle": {
|
||||
"color": "#cccccc"
|
||||
}
|
||||
},
|
||||
"axisTick": {
|
||||
"show": false,
|
||||
"lineStyle": {
|
||||
"color": "#333"
|
||||
}
|
||||
},
|
||||
"axisLabel": {
|
||||
"show": true,
|
||||
"textStyle": {
|
||||
"color": "#999999"
|
||||
}
|
||||
},
|
||||
"splitLine": {
|
||||
"show": true,
|
||||
"lineStyle": {
|
||||
"color": [
|
||||
"#eeeeee"
|
||||
]
|
||||
}
|
||||
},
|
||||
"splitArea": {
|
||||
"show": false,
|
||||
"areaStyle": {
|
||||
"color": [
|
||||
"rgba(250,250,250,0.05)",
|
||||
"rgba(200,200,200,0.02)"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"toolbox": {
|
||||
"iconStyle": {
|
||||
"normal": {
|
||||
"borderColor": "#999"
|
||||
},
|
||||
"emphasis": {
|
||||
"borderColor": "#666"
|
||||
}
|
||||
}
|
||||
},
|
||||
"legend": {
|
||||
"textStyle": {
|
||||
"color": "#999999"
|
||||
}
|
||||
},
|
||||
"tooltip": {
|
||||
"axisPointer": {
|
||||
"lineStyle": {
|
||||
"color": "#ccc",
|
||||
"width": 1
|
||||
},
|
||||
"crossStyle": {
|
||||
"color": "#ccc",
|
||||
"width": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"timeline": {
|
||||
"lineStyle": {
|
||||
"color": "#8fd3e8",
|
||||
"width": 1
|
||||
},
|
||||
"itemStyle": {
|
||||
"normal": {
|
||||
"color": "#8fd3e8",
|
||||
"borderWidth": 1
|
||||
},
|
||||
"emphasis": {
|
||||
"color": "#8fd3e8"
|
||||
}
|
||||
},
|
||||
"controlStyle": {
|
||||
"normal": {
|
||||
"color": "#8fd3e8",
|
||||
"borderColor": "#8fd3e8",
|
||||
"borderWidth": 0.5
|
||||
},
|
||||
"emphasis": {
|
||||
"color": "#8fd3e8",
|
||||
"borderColor": "#8fd3e8",
|
||||
"borderWidth": 0.5
|
||||
}
|
||||
},
|
||||
"checkpointStyle": {
|
||||
"color": "#8fd3e8",
|
||||
"borderColor": "rgba(138,124,168,0.37)"
|
||||
},
|
||||
"label": {
|
||||
"normal": {
|
||||
"textStyle": {
|
||||
"color": "#8fd3e8"
|
||||
}
|
||||
},
|
||||
"emphasis": {
|
||||
"textStyle": {
|
||||
"color": "#8fd3e8"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"visualMap": {
|
||||
"color": [
|
||||
"#516b91",
|
||||
"#59c4e6",
|
||||
"#a5e7f0"
|
||||
]
|
||||
},
|
||||
"dataZoom": {
|
||||
"backgroundColor": "rgba(0,0,0,0)",
|
||||
"dataBackgroundColor": "rgba(255,255,255,0.3)",
|
||||
"fillerColor": "rgba(167,183,204,0.4)",
|
||||
"handleColor": "#a7b7cc",
|
||||
"handleSize": "100%",
|
||||
"textStyle": {
|
||||
"color": "#333"
|
||||
}
|
||||
},
|
||||
"markPoint": {
|
||||
"label": {
|
||||
"normal": {
|
||||
"textStyle": {
|
||||
"color": "#eee"
|
||||
}
|
||||
},
|
||||
"emphasis": {
|
||||
"textStyle": {
|
||||
"color": "#eee"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="home-container">
|
||||
<el-row :gutter="15">
|
||||
<el-col :sm="6" class="mb15">
|
||||
<div class="home-card-item home-card-first">
|
||||
<div @click="toPage({ id: 'personal' })" class="home-card-item home-card-first">
|
||||
<div class="flex-margin flex">
|
||||
<img :src="getUserInfos.photo" />
|
||||
<div class="home-card-first-right ml15">
|
||||
@@ -14,81 +14,15 @@
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :sm="3" class="mb15" v-for="(v, k) in topCardItemList" :key="k">
|
||||
<div class="home-card-item home-card-item-box" :style="{ background: v.color }">
|
||||
<div @click="toPage(v)" class="home-card-item home-card-item-box" :style="{ background: v.color }">
|
||||
<div class="home-card-item-flex">
|
||||
<div class="home-card-item-title pb3">{{ v.title }}</div>
|
||||
<div class="home-card-item-title-num pb6" :id="v.id"></div>
|
||||
<!-- <div class="home-card-item-tip pb3">{{ v.tip }}</div>
|
||||
<div class="home-card-item-tip-num" :id="`tipNum${k + 1}`"></div> -->
|
||||
</div>
|
||||
<i :class="v.icon" :style="{ color: v.iconColor }"></i>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!-- <el-row :gutter="15">
|
||||
<el-col :xs="24" :sm="14" :md="14" :lg="16" :xl="16" class="mb15">
|
||||
<el-card shadow="hover" header="商品销售情况">
|
||||
<div style="height: 200px" ref="homeLaboratoryRef"></div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="10" :md="10" :lg="8" :xl="8">
|
||||
<el-card shadow="hover" header="环境监测">
|
||||
<div class="home-monitor">
|
||||
<div class="flex-warp">
|
||||
<div class="flex-warp-item" v-for="(v, k) in environmentList" :key="k">
|
||||
<div class="flex-warp-item-box">
|
||||
<i :class="v.icon" :style="{ color: v.iconColor }"></i>
|
||||
<span class="pl5">{{ v.label }}</span>
|
||||
<div class="mt10">{{ v.value }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="15">
|
||||
<el-col :xs="24" :sm="14" :md="14" :lg="16" :xl="16" class="home-warning-media">
|
||||
<el-card shadow="hover" header="布局配置" class="home-warning-card">
|
||||
<el-table :data="tableData.data" style="width: 100%" stripe>
|
||||
<el-table-column prop="date" label="时间"></el-table-column>
|
||||
<el-table-column prop="name" label="实验室名称"></el-table-column>
|
||||
<el-table-column prop="address" label="报警内容"></el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="10" :md="10" :lg="8" :xl="8" class="home-dynamic-media">
|
||||
<el-card shadow="hover" header="动态信息">
|
||||
<div class="home-dynamic">
|
||||
<el-scrollbar>
|
||||
<div class="home-dynamic-item" v-for="(v, k) in activitiesList" :key="k">
|
||||
<div class="home-dynamic-item-left">
|
||||
<div class="home-dynamic-item-left-time1 mb5">{{ v.time1 }}</div>
|
||||
<div class="home-dynamic-item-left-time2">{{ v.time2 }}</div>
|
||||
</div>
|
||||
<div class="home-dynamic-item-line">
|
||||
<i class="iconfont icon-fangkuang"></i>
|
||||
</div>
|
||||
<div class="home-dynamic-item-right">
|
||||
<div class="home-dynamic-item-right-title mb5">
|
||||
<i class="el-icon-s-comment"></i>
|
||||
<span>{{ v.title }}</span>
|
||||
</div>
|
||||
<div class="home-dynamic-item-right-label">{{ v.label }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mt15">
|
||||
<el-card shadow="hover" header="履约超时预警">
|
||||
<div style="height: 200px" ref="homeOvertimeRef"></div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -99,35 +33,36 @@ import { useStore } from '@/store/index.ts';
|
||||
import { CountUp } from 'countup.js';
|
||||
import { formatAxis } from '@/common/utils/formatTime.ts';
|
||||
import { indexApi } from './api';
|
||||
import { topCardItemList, environmentList, activitiesList } from './mock.ts';
|
||||
import { useRouter } from 'vue-router';
|
||||
export default {
|
||||
name: 'Home',
|
||||
name: 'HomePage',
|
||||
setup() {
|
||||
// const { proxy } = getCurrentInstance() as any;
|
||||
const router = useRouter();
|
||||
const store = useStore();
|
||||
const state = reactive({
|
||||
topCardItemList,
|
||||
environmentList,
|
||||
activitiesList,
|
||||
tableData: {
|
||||
data: [
|
||||
{
|
||||
date: '2016-05-02',
|
||||
name: '1号实验室',
|
||||
address: '烟感2.1%OBS/M',
|
||||
},
|
||||
{
|
||||
date: '2016-05-04',
|
||||
name: '2号实验室',
|
||||
address: '温度30℃',
|
||||
},
|
||||
{
|
||||
date: '2016-05-01',
|
||||
name: '3号实验室',
|
||||
address: '湿度57%RH',
|
||||
},
|
||||
],
|
||||
},
|
||||
topCardItemList: [
|
||||
{
|
||||
title: '项目数',
|
||||
id: 'projectNum',
|
||||
color: '#FEBB50',
|
||||
},
|
||||
{
|
||||
title: 'Linux机器数',
|
||||
id: 'machineNum',
|
||||
color: '#F95959',
|
||||
},
|
||||
{
|
||||
title: '数据库总数',
|
||||
id: 'dbNum',
|
||||
color: '#8595F4',
|
||||
},
|
||||
{
|
||||
title: 'redis总数',
|
||||
id: 'redisNum',
|
||||
color: '#1abc9c',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
// 当前时间提示语
|
||||
@@ -137,7 +72,7 @@ export default {
|
||||
|
||||
// 初始化数字滚动
|
||||
const initNumCountUp = async () => {
|
||||
const res: any = await indexApi.getIndexCount.request()
|
||||
const res: any = await indexApi.getIndexCount.request();
|
||||
nextTick(() => {
|
||||
new CountUp('projectNum', res.projectNum).start();
|
||||
new CountUp('machineNum', res.machineNum).start();
|
||||
@@ -146,104 +81,31 @@ export default {
|
||||
});
|
||||
};
|
||||
|
||||
// // 实验室使用情况
|
||||
// const initHomeLaboratory = () => {
|
||||
// const myChart = echarts.init(proxy.$refs.homeLaboratoryRef);
|
||||
// const option = {
|
||||
// grid: {
|
||||
// top: 50,
|
||||
// right: 20,
|
||||
// bottom: 30,
|
||||
// left: 30,
|
||||
// },
|
||||
// tooltip: {
|
||||
// trigger: 'axis',
|
||||
// },
|
||||
// legend: {
|
||||
// data: ['预购队列', '最新成交价'],
|
||||
// right: 13,
|
||||
// },
|
||||
// xAxis: {
|
||||
// data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子'],
|
||||
// },
|
||||
// yAxis: [
|
||||
// {
|
||||
// type: 'value',
|
||||
// name: '价格',
|
||||
// },
|
||||
// ],
|
||||
// series: [
|
||||
// {
|
||||
// name: '预购队列',
|
||||
// type: 'bar',
|
||||
// data: [5, 20, 36, 10, 10, 20],
|
||||
// },
|
||||
// {
|
||||
// name: '最新成交价',
|
||||
// type: 'line',
|
||||
// data: [15, 20, 16, 20, 30, 8],
|
||||
// },
|
||||
// ],
|
||||
// };
|
||||
// myChart.setOption(option);
|
||||
// window.addEventListener('resize', () => {
|
||||
// myChart.resize();
|
||||
// });
|
||||
// };
|
||||
// // 履约超时预警
|
||||
// const initHomeOvertime = () => {
|
||||
// const myChart = echarts.init(proxy.$refs.homeOvertimeRef);
|
||||
// const option = {
|
||||
// grid: {
|
||||
// top: 50,
|
||||
// right: 20,
|
||||
// bottom: 30,
|
||||
// left: 30,
|
||||
// },
|
||||
// tooltip: {
|
||||
// trigger: 'axis',
|
||||
// },
|
||||
// legend: {
|
||||
// data: ['订单数量', '超时数量', '在线数量', '预警数量'],
|
||||
// right: 13,
|
||||
// },
|
||||
// xAxis: {
|
||||
// data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
|
||||
// },
|
||||
// yAxis: [
|
||||
// {
|
||||
// type: 'value',
|
||||
// name: '数量',
|
||||
// },
|
||||
// ],
|
||||
// series: [
|
||||
// {
|
||||
// name: '订单数量',
|
||||
// type: 'bar',
|
||||
// data: [5, 20, 36, 10, 10, 20, 11, 13, 10, 9, 17, 19],
|
||||
// },
|
||||
// {
|
||||
// name: '超时数量',
|
||||
// type: 'bar',
|
||||
// data: [15, 12, 26, 15, 11, 16, 31, 13, 5, 16, 13, 15],
|
||||
// },
|
||||
// {
|
||||
// name: '在线数量',
|
||||
// type: 'line',
|
||||
// data: [15, 20, 16, 20, 30, 8, 16, 19, 12, 18, 19, 14],
|
||||
// },
|
||||
// {
|
||||
// name: '预警数量',
|
||||
// type: 'line',
|
||||
// data: [10, 10, 13, 12, 15, 18, 19, 10, 12, 15, 11, 17],
|
||||
// },
|
||||
// ],
|
||||
// };
|
||||
// myChart.setOption(option);
|
||||
// window.addEventListener('resize', () => {
|
||||
// myChart.resize();
|
||||
// });
|
||||
// };
|
||||
const toPage = (item: any) => {
|
||||
switch (item.id) {
|
||||
case 'personal': {
|
||||
router.push('/personal');
|
||||
break;
|
||||
}
|
||||
case 'projectNum': {
|
||||
router.push('/ops/projects');
|
||||
break;
|
||||
}
|
||||
case 'machineNum': {
|
||||
router.push('/ops/machines');
|
||||
break;
|
||||
}
|
||||
case 'dbNum': {
|
||||
router.push('/ops/dbms/dbs');
|
||||
break;
|
||||
}
|
||||
case 'redisNum': {
|
||||
router.push('/ops/redis/manage');
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
initNumCountUp();
|
||||
@@ -255,9 +117,11 @@ export default {
|
||||
const getUserInfos = computed(() => {
|
||||
return store.state.userInfos.userInfos;
|
||||
});
|
||||
|
||||
return {
|
||||
getUserInfos,
|
||||
currentTime,
|
||||
toPage,
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
@@ -273,6 +137,7 @@ export default {
|
||||
background: gray;
|
||||
border-radius: 4px;
|
||||
transition: all ease 0.3s;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
|
||||
transition: all ease 0.3s;
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
// 最顶部 card
|
||||
export const topCardItemList = [
|
||||
{
|
||||
title: '项目数',
|
||||
id: 'projectNum',
|
||||
num: '123',
|
||||
tip: '通过人数',
|
||||
tipNum: '911',
|
||||
color: '#FEBB50',
|
||||
iconColor: '#FDC566',
|
||||
icon: 'el-icon-histogram',
|
||||
},
|
||||
{
|
||||
title: 'Linux机器数',
|
||||
id: 'machineNum',
|
||||
num: '123',
|
||||
tip: '在场人数',
|
||||
tipNum: '911',
|
||||
color: '#F95959',
|
||||
iconColor: '#F86C6B',
|
||||
icon: 'iconfont icon-jinridaiban',
|
||||
},
|
||||
{
|
||||
title: '数据库总数',
|
||||
id: "dbNum",
|
||||
num: '123',
|
||||
tip: '使用中',
|
||||
tipNum: '611',
|
||||
color: '#8595F4',
|
||||
iconColor: '#92A1F4',
|
||||
icon: 'iconfont icon-AIshiyanshi',
|
||||
},
|
||||
{
|
||||
title: 'redis总数',
|
||||
id: 'redisNum',
|
||||
num: '123',
|
||||
tip: '通过人数',
|
||||
tipNum: '911',
|
||||
color: '#1abc9c',
|
||||
iconColor: '#FDC566',
|
||||
icon: 'iconfont icon-shenqingkaiban',
|
||||
},
|
||||
];
|
||||
|
||||
// 环境监测
|
||||
export const environmentList = [
|
||||
{
|
||||
icon: 'iconfont icon-yangan',
|
||||
label: '烟感',
|
||||
value: '2.1%OBS/M',
|
||||
iconColor: '#F72B3F',
|
||||
},
|
||||
{
|
||||
icon: 'iconfont icon-wendu',
|
||||
label: '温度',
|
||||
value: '30℃',
|
||||
iconColor: '#91BFF8',
|
||||
},
|
||||
{
|
||||
icon: 'iconfont icon-shidu',
|
||||
label: '湿度',
|
||||
value: '57%RH',
|
||||
iconColor: '#88D565',
|
||||
},
|
||||
{
|
||||
icon: 'iconfont icon-zaosheng',
|
||||
label: '噪声',
|
||||
value: '57DB',
|
||||
iconColor: '#FBD4A0',
|
||||
},
|
||||
];
|
||||
|
||||
// 动态信息
|
||||
export const activitiesList = [
|
||||
{
|
||||
time1: '今天',
|
||||
time2: '12:20:30',
|
||||
title: '更名',
|
||||
label: '正式更名为 vue-next-admin',
|
||||
},
|
||||
{
|
||||
time1: '02-17',
|
||||
time2: '12:20:30',
|
||||
title: '页面',
|
||||
label: '完成对首页的开发',
|
||||
},
|
||||
{
|
||||
time1: '02-14',
|
||||
time2: '12:20:30',
|
||||
title: '页面',
|
||||
label: '新增个人中心',
|
||||
},
|
||||
];
|
||||
@@ -62,7 +62,7 @@ import { formatAxis } from '@/common/utils/formatTime.ts';
|
||||
import openApi from '@/common/openApi';
|
||||
import { letterAvatar } from '@/common/utils/string';
|
||||
export default defineComponent({
|
||||
name: 'Account',
|
||||
name: 'AccountLogin',
|
||||
setup() {
|
||||
const store = useStore();
|
||||
const route = useRoute();
|
||||
@@ -33,7 +33,7 @@
|
||||
<script lang="ts">
|
||||
import { toRefs, reactive, defineComponent } from 'vue';
|
||||
export default defineComponent({
|
||||
name: 'login',
|
||||
name: 'MobileLogin',
|
||||
setup() {
|
||||
const state = reactive({
|
||||
ruleForm: {
|
||||
@@ -33,12 +33,11 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { toRefs, reactive, computed } from 'vue';
|
||||
import Account from '@/views/login/component/Account.vue';
|
||||
import Mobile from '@/views/login/component/mobile.vue';
|
||||
import Account from '@/views/login/component/AccountLogin.vue';
|
||||
import { useStore } from '@/store/index.ts';
|
||||
export default {
|
||||
name: 'login',
|
||||
components: { Account, Mobile },
|
||||
name: 'LoginPage',
|
||||
components: { Account },
|
||||
setup() {
|
||||
const store = useStore();
|
||||
const state = reactive({
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog :title="title" v-model="dialogVisible" :show-close="false" :before-close="cancel" width="35%">
|
||||
<el-dialog :title="title" v-model="dialogVisible" :before-close="cancel" :close-on-click-modal="false" width="35%">
|
||||
<el-form :model="form" ref="dbForm" :rules="rules" label-width="85px">
|
||||
<el-form-item prop="projectId" label="项目:" required>
|
||||
<el-select style="width: 100%" v-model="form.projectId" placeholder="请选择项目" @change="changeProject" filterable>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog :title="title" v-model="dialogVisible" :show-close="false" :before-close="cancel" width="35%">
|
||||
<el-dialog :title="title" v-model="dialogVisible" :close-on-click-modal="false" :destroy-on-close="true" :before-close="cancel" width="35%">
|
||||
<el-form :model="form" ref="machineForm" :rules="rules" label-width="85px" >
|
||||
<el-form-item prop="projectId" label="项目:" required>
|
||||
<el-select style="width: 100%" v-model="form.projectId" placeholder="请选择项目" @change="changeProject" filterable>
|
||||
|
||||
@@ -15,14 +15,28 @@
|
||||
<el-button v-auth="'machine:del'" :disabled="currentId == null" @click="deleteMachine(currentId)" type="danger" icon="delete"
|
||||
>删除</el-button
|
||||
>
|
||||
<el-button v-auth="'machine:file'" type="success" icon="files" :disabled="currentId == null" @click="fileManage(currentData)" plain
|
||||
<el-button
|
||||
v-auth="'machine:file'"
|
||||
type="success"
|
||||
icon="files"
|
||||
:disabled="currentId == null || currentData.status == -1"
|
||||
@click="fileManage(currentData)"
|
||||
plain
|
||||
>文件</el-button
|
||||
>
|
||||
<div style="float: right">
|
||||
<el-select v-model="params.projectId" placeholder="请选择项目" @clear="search" filterable clearable>
|
||||
<el-option v-for="item in projects" :key="item.id" :label="`${item.name} [${item.remark}]`" :value="item.id"> </el-option>
|
||||
</el-select>
|
||||
<el-input class="ml5" placeholder="请输入名称" style="width: 150px" v-model="params.name" @clear="search" plain clearable></el-input>
|
||||
<el-input
|
||||
class="ml5"
|
||||
placeholder="请输入名称"
|
||||
style="width: 150px"
|
||||
v-model="params.name"
|
||||
@clear="search"
|
||||
plain
|
||||
clearable
|
||||
></el-input>
|
||||
<el-input class="ml5" placeholder="请输入ip" style="width: 150px" v-model="params.ip" @clear="search" plain clearable></el-input>
|
||||
<el-button class="ml5" @click="search" type="success" icon="search"></el-button>
|
||||
</div>
|
||||
@@ -37,30 +51,66 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="name" label="名称" min-width="130" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="ip" label="ip:port" min-width="130">
|
||||
<el-table-column prop="ip" label="ip:port" min-width="140">
|
||||
<template #default="scope">
|
||||
{{ `${scope.row.ip}:${scope.row.port}` }}
|
||||
<el-link :disabled="scope.row.status == -1" @click="showMachineStats(scope.row)" type="primary" :underline="false">{{
|
||||
`${scope.row.ip}:${scope.row.port}`
|
||||
}}</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="username" label="用户名" min-width="75"></el-table-column>
|
||||
<el-table-column prop="status" label="状态" min-width="60">
|
||||
<template #default="scope">
|
||||
<el-switch
|
||||
v-auth:disabled="'machine:update'"
|
||||
:width="47"
|
||||
v-model="scope.row.status"
|
||||
:active-value="1"
|
||||
:inactive-value="-1"
|
||||
active-color="#13ce66"
|
||||
inactive-color="#ff4949"
|
||||
inline-prompt
|
||||
active-text="启用"
|
||||
inactive-text="停用"
|
||||
@change="changeStatus(scope.row)"
|
||||
></el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="username" label="用户名" min-width="90"></el-table-column>
|
||||
<el-table-column prop="projectName" label="项目" min-width="120"></el-table-column>
|
||||
<el-table-column prop="ip" label="hasCli" width="70">
|
||||
<template #default="scope">
|
||||
{{ `${scope.row.hasCli ? '是' : '否'}` }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="createTime" label="创建时间" width="165">
|
||||
<el-table-column prop="createTime" label="创建时间" min-width="165">
|
||||
<template #default="scope">
|
||||
{{ $filters.dateFormat(scope.row.createTime) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="creator" label="创建者" min-width="60"></el-table-column>
|
||||
<el-table-column label="操作" min-width="260" fixed="right">
|
||||
<el-table-column prop="creator" label="创建者" min-width="80"></el-table-column>
|
||||
<el-table-column label="操作" min-width="280" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button type="success" @click="serviceManager(scope.row)" plain size="small">脚本</el-button>
|
||||
<el-button v-auth="'machine:terminal'" type="primary" @click="showTerminal(scope.row)" plain size="small">终端</el-button>
|
||||
<el-button @click="showProcess(scope.row)" plain size="small">进程</el-button>
|
||||
<el-button :disabled="!scope.row.hasCli" type="danger" @click="closeCli(scope.row)" plain size="small">关闭连接</el-button>
|
||||
<el-button :disabled="scope.row.status == -1" type="success" @click="serviceManager(scope.row)" plain size="small"
|
||||
>脚本</el-button
|
||||
>
|
||||
<el-button
|
||||
v-auth="'machine:terminal'"
|
||||
:disabled="scope.row.status == -1"
|
||||
type="primary"
|
||||
@click="showTerminal(scope.row)"
|
||||
plain
|
||||
size="small"
|
||||
>终端</el-button
|
||||
>
|
||||
<el-button @click="showProcess(scope.row)" :disabled="scope.row.status == -1" plain size="small">进程</el-button>
|
||||
<el-button
|
||||
:disabled="!scope.row.hasCli || scope.row.status == -1"
|
||||
type="danger"
|
||||
@click="closeCli(scope.row)"
|
||||
plain
|
||||
size="small"
|
||||
>关闭连接</el-button
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -84,15 +134,17 @@
|
||||
@valChange="submitSuccess"
|
||||
></machine-edit>
|
||||
|
||||
<!-- <el-dialog @close="closeMonitor" title="监控信息" v-model="monitorDialog.visible" width="60%">
|
||||
<monitor ref="monitorDialogRef" :machineId="monitorDialog.machineId" />
|
||||
</el-dialog> -->
|
||||
|
||||
<process-list v-model:visible="processDialog.visible" v-model:machineId="processDialog.machineId" />
|
||||
|
||||
<service-manage :title="serviceDialog.title" v-model:visible="serviceDialog.visible" v-model:machineId="serviceDialog.machineId" />
|
||||
|
||||
<file-manage :title="fileDialog.title" v-model:visible="fileDialog.visible" v-model:machineId="fileDialog.machineId" />
|
||||
|
||||
<machine-stats
|
||||
v-model:visible="machineStatsDialog.visible"
|
||||
:machineId="machineStatsDialog.machineId"
|
||||
:title="machineStatsDialog.title"
|
||||
></machine-stats>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -100,13 +152,13 @@
|
||||
import { toRefs, reactive, onMounted, defineComponent } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
// import Monitor from './Monitor.vue';
|
||||
import { machineApi } from './api';
|
||||
import { projectApi } from '../project/api.ts';
|
||||
import ServiceManage from './ServiceManage.vue';
|
||||
import FileManage from './FileManage.vue';
|
||||
import MachineEdit from './MachineEdit.vue';
|
||||
import ProcessList from './ProcessList.vue';
|
||||
import MachineStats from './MachineStats.vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'MachineList',
|
||||
@@ -115,11 +167,13 @@ export default defineComponent({
|
||||
ProcessList,
|
||||
FileManage,
|
||||
MachineEdit,
|
||||
MachineStats,
|
||||
},
|
||||
setup() {
|
||||
const router = useRouter();
|
||||
const state = reactive({
|
||||
projects: [],
|
||||
stats: '',
|
||||
params: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
@@ -152,8 +206,10 @@ export default defineComponent({
|
||||
machineId: 0,
|
||||
title: '',
|
||||
},
|
||||
monitorDialog: {
|
||||
machineStatsDialog: {
|
||||
visible: false,
|
||||
stats: null,
|
||||
title: '',
|
||||
machineId: 0,
|
||||
},
|
||||
machineEditDialog: {
|
||||
@@ -176,22 +232,6 @@ export default defineComponent({
|
||||
state.currentData = item;
|
||||
};
|
||||
|
||||
// const monitor = (id: number) => {
|
||||
// state.monitorDialog.machineId = id;
|
||||
// state.monitorDialog.visible = true;
|
||||
// // 如果重复打开同一个则开启定时任务
|
||||
// const md: any = monitorDialogRef;
|
||||
// if (md) {
|
||||
// md.startInterval();
|
||||
// }
|
||||
// };
|
||||
|
||||
// const closeMonitor = () => {
|
||||
// // 关闭窗口,取消定时任务
|
||||
// const md: any = monitorDialogRef;
|
||||
// md.cancelInterval();
|
||||
// };
|
||||
|
||||
const showTerminal = (row: any) => {
|
||||
const { href } = router.resolve({
|
||||
path: `/machine/terminal`,
|
||||
@@ -244,6 +284,22 @@ export default defineComponent({
|
||||
state.serviceDialog.title = `${row.name} => ${row.ip}`;
|
||||
};
|
||||
|
||||
/**
|
||||
* 调整机器状态
|
||||
*/
|
||||
const changeStatus = async (row: any) => {
|
||||
await machineApi.changeStatus.request({ id: row.id, status: row.status });
|
||||
};
|
||||
|
||||
/**
|
||||
* 显示机器状态统计信息
|
||||
*/
|
||||
const showMachineStats = async (machine: any) => {
|
||||
state.machineStatsDialog.machineId = machine.id;
|
||||
state.machineStatsDialog.title = `机器状态: ${machine.name} => ${machine.ip}`;
|
||||
state.machineStatsDialog.visible = true;
|
||||
};
|
||||
|
||||
const submitSuccess = () => {
|
||||
state.currentId = null;
|
||||
state.currentData = null;
|
||||
@@ -281,7 +337,9 @@ export default defineComponent({
|
||||
deleteMachine,
|
||||
closeCli,
|
||||
serviceManager,
|
||||
showMachineStats,
|
||||
showProcess,
|
||||
changeStatus,
|
||||
submitSuccess,
|
||||
fileManage,
|
||||
search,
|
||||
|
||||
322
mayfly_go_web/src/views/ops/machine/MachineStats.vue
Normal file
322
mayfly_go_web/src/views/ops/machine/MachineStats.vue
Normal file
@@ -0,0 +1,322 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog :title="title" v-model="dialogVisible" :close-on-click-modal="true" :destroy-on-close="true" :before-close="cancel" width="980px">
|
||||
<el-row :gutter="20">
|
||||
<el-col :lg="10" :md="10">
|
||||
<el-descriptions size="small" title="基础信息" :column="2" border>
|
||||
<template #extra>
|
||||
<el-link @click="onRefresh" icon="refresh" :underline="false" type="success"></el-link>
|
||||
</template>
|
||||
<el-descriptions-item label="主机名">
|
||||
{{ stats.Hostname }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="运行时间">
|
||||
{{ stats.Uptime }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="总任务">
|
||||
{{ stats.TotalProcs }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="运行中任务">
|
||||
{{ stats.RunningProcs }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="负载"> {{ stats.Load1 }} {{ stats.Load5 }} {{ stats.Load10 }} </el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-col>
|
||||
|
||||
<el-col :lg="7" :md="7">
|
||||
<div class="card-item-chart" ref="memRef"></div>
|
||||
</el-col>
|
||||
|
||||
<el-col :lg="7" :md="7">
|
||||
<div class="card-item-chart" ref="cpuRef"></div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :lg="8" :md="8">
|
||||
<span style="font-size: 16px; font-weight: 700">磁盘</span>
|
||||
<el-table :data="stats.FSInfos" stripe max-height="250" style="width: 100%" border>
|
||||
<el-table-column prop="MountPoint" label="挂载点" min-width="100" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="Used" label="可使用" min-width="70" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
{{ formatByteSize(scope.row.Free) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="Used" label="已使用" min-width="70" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
{{ formatByteSize(scope.row.Used) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-col>
|
||||
|
||||
<el-col :lg="16" :md="16">
|
||||
<span style="font-size: 16px; font-weight: 700">网卡</span>
|
||||
<el-table :data="netInter" stripe max-height="250" style="width: 100%" border>
|
||||
<el-table-column prop="name" label="网卡" min-width="120" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="IPv4" label="IPv4" min-width="130" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="IPv6" label="IPv6" min-width="130" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="Rx" label="接收(rx)" min-width="110" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
{{ formatByteSize(scope.row.Rx) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="Tx" label="发送(tx)" min-width="110" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
{{ formatByteSize(scope.row.Tx) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { toRefs, reactive, watch, defineComponent, ref, nextTick } from 'vue';
|
||||
import useEcharts from '@/common/echarts/useEcharts.ts';
|
||||
import tdTheme from '@/common/echarts/theme.json';
|
||||
import { formatByteSize } from '@/common/utils/format';
|
||||
import { machineApi } from './api';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'MachineStats',
|
||||
components: {},
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
},
|
||||
stats: {
|
||||
type: Object,
|
||||
},
|
||||
machineId: {
|
||||
type: Number,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
},
|
||||
},
|
||||
setup(props: any, { emit }) {
|
||||
const cpuRef: any = ref();
|
||||
const memRef: any = ref();
|
||||
|
||||
let cpuChart: any = null;
|
||||
let memChart: any = null;
|
||||
|
||||
const state = reactive({
|
||||
dialogVisible: false,
|
||||
charts: [] as any,
|
||||
stats: {} as any,
|
||||
netInter: [] as any,
|
||||
});
|
||||
|
||||
watch(props, async (newValue) => {
|
||||
const visible = newValue.visible;
|
||||
if (visible) {
|
||||
await setStats();
|
||||
}
|
||||
state.dialogVisible = visible;
|
||||
if (visible) {
|
||||
initCharts();
|
||||
}
|
||||
});
|
||||
|
||||
const setStats = async () => {
|
||||
state.stats = await machineApi.stats.request({ id: props.machineId });
|
||||
};
|
||||
|
||||
const onRefresh = async () => {
|
||||
await setStats();
|
||||
initCharts();
|
||||
};
|
||||
|
||||
const initMemStats = () => {
|
||||
const data = [
|
||||
{ name: '可用内存', value: state.stats.MemAvailable },
|
||||
{
|
||||
name: '已用内存',
|
||||
value: state.stats.MemTotal - state.stats.MemAvailable,
|
||||
},
|
||||
];
|
||||
const option = {
|
||||
title: {
|
||||
text: '内存',
|
||||
x: 'left',
|
||||
textStyle: { fontSize: 15 },
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
valueFormatter: formatByteSize,
|
||||
},
|
||||
legend: {
|
||||
top: '15%',
|
||||
orient: 'vertical',
|
||||
left: 'left',
|
||||
textStyle: { fontSize: 12 },
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '内存',
|
||||
type: 'pie',
|
||||
radius: ['30%', '60%'], // 饼图内圈和外圈大小
|
||||
center: ['60%', '50%'], // 饼图位置,0: 左右;1: 上下
|
||||
avoidLabelOverlap: false,
|
||||
label: {
|
||||
show: false,
|
||||
position: 'center',
|
||||
},
|
||||
emphasis: {
|
||||
label: {
|
||||
show: true,
|
||||
fontSize: '15',
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
},
|
||||
labelLine: {
|
||||
show: false,
|
||||
},
|
||||
data: data,
|
||||
},
|
||||
],
|
||||
};
|
||||
if (memChart) {
|
||||
memChart.setOption(option, true);
|
||||
return;
|
||||
}
|
||||
const chart: any = useEcharts(memRef.value, tdTheme, option);
|
||||
memChart = chart;
|
||||
state.charts.push(chart);
|
||||
};
|
||||
|
||||
const initCpuStats = () => {
|
||||
const cpu = state.stats.CPU;
|
||||
const data = [
|
||||
{ name: 'Idle', value: cpu.Idle },
|
||||
{
|
||||
name: 'Iowait',
|
||||
value: cpu.Iowait,
|
||||
},
|
||||
{
|
||||
name: 'System',
|
||||
value: cpu.System,
|
||||
},
|
||||
{
|
||||
name: 'User',
|
||||
value: cpu.User,
|
||||
},
|
||||
];
|
||||
const option = {
|
||||
title: {
|
||||
text: 'CPU使用率',
|
||||
x: 'left',
|
||||
textStyle: { fontSize: 15 },
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
valueFormatter: (value: any) => value + '%',
|
||||
},
|
||||
legend: {
|
||||
top: '15%',
|
||||
orient: 'vertical',
|
||||
left: 'left',
|
||||
textStyle: { fontSize: 12 },
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: 'CPU',
|
||||
type: 'pie',
|
||||
radius: ['30%', '60%'], // 饼图内圈和外圈大小
|
||||
center: ['60%', '50%'], // 饼图位置,0: 左右;1: 上下
|
||||
avoidLabelOverlap: false,
|
||||
label: {
|
||||
show: false,
|
||||
position: 'center',
|
||||
},
|
||||
emphasis: {
|
||||
label: {
|
||||
show: true,
|
||||
fontSize: '15',
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
},
|
||||
labelLine: {
|
||||
show: false,
|
||||
},
|
||||
data: data,
|
||||
},
|
||||
],
|
||||
};
|
||||
if (cpuChart) {
|
||||
cpuChart.setOption(option, true);
|
||||
return;
|
||||
}
|
||||
const chart: any = useEcharts(cpuRef.value, tdTheme, option);
|
||||
cpuChart = chart;
|
||||
state.charts.push(chart);
|
||||
};
|
||||
|
||||
const initCharts = () => {
|
||||
nextTick(() => {
|
||||
initMemStats();
|
||||
initCpuStats();
|
||||
});
|
||||
parseNetInter();
|
||||
initEchartsResize();
|
||||
};
|
||||
|
||||
const initEchartResizeFun = () => {
|
||||
nextTick(() => {
|
||||
for (let i = 0; i < state.charts.length; i++) {
|
||||
setTimeout(() => {
|
||||
state.charts[i].resize();
|
||||
}, i * 1000);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const initEchartsResize = () => {
|
||||
window.addEventListener('resize', initEchartResizeFun);
|
||||
};
|
||||
|
||||
const parseNetInter = () => {
|
||||
state.netInter = [];
|
||||
const netInter = state.stats.NetIntf;
|
||||
const keys = Object.keys(netInter);
|
||||
const values = Object.values(netInter);
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
// 需要使用属性拷贝,否则会再次触发watch
|
||||
let value: any = values[i];
|
||||
// 将网卡名称赋值新属性值name
|
||||
value.name = keys[i];
|
||||
state.netInter.push(value);
|
||||
}
|
||||
};
|
||||
|
||||
const cancel = () => {
|
||||
emit('update:visible', false);
|
||||
emit('cancel');
|
||||
|
||||
setTimeout(() => {
|
||||
cpuChart = null;
|
||||
memChart = null;
|
||||
}, 200);
|
||||
};
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
cpuRef,
|
||||
memRef,
|
||||
cancel,
|
||||
formatByteSize,
|
||||
onRefresh,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.card-item-chart {
|
||||
height: 200px;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -1,208 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-row>
|
||||
<el-col>
|
||||
<HomeCard desc="Base info" title="基础信息">
|
||||
<ActivePlate :infoList="infoCardData" />
|
||||
</HomeCard>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :lg="6" :md="24">
|
||||
<HomeCard desc="Task info" title="任务">
|
||||
<ChartPie v-model:value="taskData" />
|
||||
</HomeCard>
|
||||
</el-col>
|
||||
<el-col :lg="6" :md="24">
|
||||
<HomeCard desc="Mem info" title="内存">
|
||||
<ChartPie v-model:value="memData" />
|
||||
</HomeCard>
|
||||
</el-col>
|
||||
<el-col :lg="6" :md="24">
|
||||
<HomeCard desc="Swap info" title="CPU">
|
||||
<ChartPie v-model:value="cpuData" />
|
||||
</HomeCard>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- <el-row :gutter="20">
|
||||
<el-col :lg="18" :md="24">
|
||||
<HomeCard desc="User active" title="每周用户活跃量">
|
||||
<ChartLine :value="lineData" />
|
||||
</HomeCard>
|
||||
</el-col>
|
||||
</el-row>-->
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :lg="12" :md="24">
|
||||
<ChartContinuou :value="this.data" title="内存" />
|
||||
</el-col>
|
||||
<el-col :lg="12" :md="24">
|
||||
<ChartContinuou :value="this.data" title="CPU" />
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :lg="12" :md="24">
|
||||
<HomeCard desc="load info" title="负载情况">
|
||||
<BaseChart :option="this.loadChartOption" />
|
||||
</HomeCard>
|
||||
</el-col>
|
||||
<el-col :lg="12" :md="24">
|
||||
<ChartContinuou :value="this.data" title="磁盘IO" />
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { ref, toRefs, reactive, watch, defineComponent, onBeforeUnmount, onMounted } from 'vue';
|
||||
import ActivePlate from '@/components/chart/ActivePlate.vue';
|
||||
import HomeCard from '@/components/chart/Card.vue';
|
||||
import ChartPie from '@/components/chart/ChartPie.vue';
|
||||
import ChartLine from '@/components/chart/ChartLine.vue';
|
||||
import ChartGauge from '@/components/chart/ChartGauge.vue';
|
||||
import ChartBar from '@/components/chart/ChartBar.vue';
|
||||
import ChartFunnel from '@/components/chart/ChartFunnel.vue';
|
||||
import ChartContinuou from '@/components/chart/ChartContinuou.vue';
|
||||
import BaseChart from '@/components/chart/BaseChart.vue';
|
||||
import { machineApi } from './api';
|
||||
export default defineComponent({
|
||||
name: 'Monitor',
|
||||
components: {
|
||||
HomeCard,
|
||||
ActivePlate,
|
||||
ChartPie,
|
||||
ChartFunnel,
|
||||
ChartLine,
|
||||
ChartGauge,
|
||||
ChartBar,
|
||||
ChartContinuou,
|
||||
BaseChart,
|
||||
},
|
||||
props: {
|
||||
machineId: {
|
||||
type: Number,
|
||||
},
|
||||
},
|
||||
setup(props: any) {
|
||||
let timer = 0;
|
||||
|
||||
const state = reactive({
|
||||
infoCardData: [
|
||||
{
|
||||
title: 'total task',
|
||||
icon: 'md-person-add',
|
||||
count: 0,
|
||||
color: '#11A0F8',
|
||||
},
|
||||
{ title: '总内存', icon: 'md-locate', count: '', color: '#FFBB44 ' },
|
||||
{
|
||||
title: '可用内存',
|
||||
icon: 'md-help-circle',
|
||||
count: '',
|
||||
color: '#7ACE4C',
|
||||
},
|
||||
{ title: '空闲交换空间', icon: 'md-share', count: 657, color: '#11A0F8' },
|
||||
{
|
||||
title: '使用中交换空间',
|
||||
icon: 'md-chatbubbles',
|
||||
count: 12,
|
||||
color: '#91AFC8',
|
||||
},
|
||||
],
|
||||
taskData: [
|
||||
{ value: 0, name: '运行中', color: '#3AA1FFB' },
|
||||
{ value: 0, name: '睡眠中', color: '#36CBCB' },
|
||||
{ value: 0, name: '结束', color: '#4ECB73' },
|
||||
{ value: 0, name: '僵尸', color: '#F47F92' },
|
||||
],
|
||||
|
||||
memData: [
|
||||
{ value: 0, name: '空闲', color: '#3AA1FFB' },
|
||||
{ value: 0, name: '使用中', color: '#36CBCB' },
|
||||
{ value: 0, name: '缓存', color: '#4ECB73' },
|
||||
],
|
||||
|
||||
swapData: [
|
||||
{ value: 0, name: '空闲', color: '#3AA1FFB' },
|
||||
{ value: 0, name: '使用中', color: '#36CBCB' },
|
||||
],
|
||||
|
||||
cpuData: [
|
||||
{ value: 0, name: '用户空间', color: '#3AA1FFB' },
|
||||
{ value: 0, name: '内核空间', color: '#36CBCB' },
|
||||
{ value: 0, name: '改变优先级', color: '#4ECB73' },
|
||||
{ value: 0, name: '空闲率', color: '#4ECB73' },
|
||||
{ value: 0, name: '等待IO', color: '#4ECB73' },
|
||||
{ value: 0, name: '硬中断', color: '#4ECB73' },
|
||||
{ value: 0, name: '软中断', color: '#4ECB73' },
|
||||
{ value: 0, name: '虚拟机', color: '#4ECB73' },
|
||||
],
|
||||
});
|
||||
|
||||
watch(props, (newValue, oldValue) => {
|
||||
if (newValue.machineId) {
|
||||
intervalGetTop();
|
||||
}
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
intervalGetTop();
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
cancelInterval();
|
||||
});
|
||||
|
||||
const cancelInterval = () => {
|
||||
clearInterval(timer);
|
||||
timer = 0;
|
||||
};
|
||||
|
||||
const startInterval = () => {
|
||||
if (!timer) {
|
||||
timer = setInterval(getTop, 3000) as any;
|
||||
}
|
||||
};
|
||||
|
||||
const intervalGetTop = () => {
|
||||
getTop();
|
||||
startInterval();
|
||||
};
|
||||
|
||||
const getTop = async () => {
|
||||
const topInfo = await machineApi.top.request({ id: props.machineId });
|
||||
state.infoCardData[0].count = topInfo.totalTask;
|
||||
state.infoCardData[1].count = Math.round(topInfo.totalMem / 1024) + 'M';
|
||||
state.infoCardData[2].count = Math.round(topInfo.availMem / 1024) + 'M';
|
||||
state.infoCardData[3].count = Math.round(topInfo.freeSwap / 1024) + 'M';
|
||||
state.infoCardData[4].count = Math.round(topInfo.usedSwap / 1024) + 'M';
|
||||
|
||||
state.taskData[0].value = topInfo.runningTask;
|
||||
state.taskData[1].value = topInfo.sleepingTask;
|
||||
state.taskData[2].value = topInfo.stoppedTask;
|
||||
state.taskData[3].value = topInfo.zombieTask;
|
||||
|
||||
state.memData[0].value = Math.round(topInfo.freeMem / 1024);
|
||||
state.memData[1].value = Math.round(topInfo.usedMem / 1024);
|
||||
state.memData[2].value = Math.round(topInfo.cacheMem / 1024);
|
||||
|
||||
state.cpuData[0].value = topInfo.cpuUs;
|
||||
state.cpuData[1].value = topInfo.cpuSy;
|
||||
state.cpuData[2].value = topInfo.cpuNi;
|
||||
state.cpuData[3].value = topInfo.cpuId;
|
||||
state.cpuData[4].value = topInfo.cpuWa;
|
||||
state.cpuData[5].value = topInfo.cpuHi;
|
||||
state.cpuData[6].value = topInfo.cpuSi;
|
||||
state.cpuData[7].value = topInfo.cpuSt;
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.count-style {
|
||||
font-size: 50px;
|
||||
}
|
||||
</style>
|
||||
@@ -11,6 +11,8 @@ export const machineApi = {
|
||||
closeCli: Api.create("/machines/{id}/close-cli", 'delete'),
|
||||
// 保存按钮
|
||||
saveMachine: Api.create("/machines", 'post'),
|
||||
// 调整状态
|
||||
changeStatus: Api.create("/machines/{id}/{status}", 'put'),
|
||||
// 删除机器
|
||||
del: Api.create("/machines/{id}", 'delete'),
|
||||
scripts: Api.create("/machines/{machineId}/scripts", 'get'),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog :title="title" v-model="dialogVisible" :show-close="false" :before-close="cancel" width="35%">
|
||||
<el-dialog :title="title" v-model="dialogVisible" :before-close="cancel" :close-on-click-modal="false" width="35%">
|
||||
<el-form :model="form" ref="redisForm" :rules="rules" label-width="85px">
|
||||
<el-form-item prop="projectId" label="项目:" required>
|
||||
<el-select style="width: 100%" v-model="form.projectId" placeholder="请选择项目" @change="changeProject" filterable>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="role-dialog">
|
||||
<el-dialog :title="title" v-model="_visible" :show-close="false" :before-close="cancel" width="500px">
|
||||
<el-dialog :title="title" v-model="dvisible" :show-close="false" :before-close="cancel" width="500px">
|
||||
<el-form :model="form" label-width="90px">
|
||||
<el-form-item prop="name" label="角色名称:" required>
|
||||
<el-input v-model="form.name" auto-complete="off"></el-input>
|
||||
@@ -41,7 +41,7 @@ export default defineComponent({
|
||||
},
|
||||
setup(props: any, { emit }) {
|
||||
const state = reactive({
|
||||
_visible: false,
|
||||
dvisible: false,
|
||||
form: {
|
||||
id: null,
|
||||
name: '',
|
||||
@@ -52,7 +52,7 @@ export default defineComponent({
|
||||
});
|
||||
|
||||
watch(props, (newValue) => {
|
||||
state._visible = newValue.visible;
|
||||
state.dvisible = newValue.visible;
|
||||
if (newValue.data) {
|
||||
state.form = { ...newValue.data };
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user