mirror of
				https://github.com/bjdgyc/anylink.git
				synced 2025-11-04 11:06:22 +08:00 
			
		
		
		
	首页图表可查看用户组下的在线数、网络吞吐量
This commit is contained in:
		@@ -47,6 +47,16 @@ func GroupNames(w http.ResponseWriter, r *http.Request) {
 | 
				
			|||||||
	RespSucess(w, data)
 | 
						RespSucess(w, data)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GroupNamesIds(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
						var names = dbdata.GetGroupNamesIds()
 | 
				
			||||||
 | 
						data := map[string]interface{}{
 | 
				
			||||||
 | 
							"count":     len(names),
 | 
				
			||||||
 | 
							"page_size": 0,
 | 
				
			||||||
 | 
							"datas":     names,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						RespSucess(w, data)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func GroupDetail(w http.ResponseWriter, r *http.Request) {
 | 
					func GroupDetail(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
	_ = r.ParseForm()
 | 
						_ = r.ParseForm()
 | 
				
			||||||
	idS := r.FormValue("id")
 | 
						idS := r.FormValue("id")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -62,6 +62,7 @@ func StartAdmin() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	r.HandleFunc("/group/list", GroupList)
 | 
						r.HandleFunc("/group/list", GroupList)
 | 
				
			||||||
	r.HandleFunc("/group/names", GroupNames)
 | 
						r.HandleFunc("/group/names", GroupNames)
 | 
				
			||||||
 | 
						r.HandleFunc("/group/names_ids", GroupNamesIds)
 | 
				
			||||||
	r.HandleFunc("/group/detail", GroupDetail)
 | 
						r.HandleFunc("/group/detail", GroupDetail)
 | 
				
			||||||
	r.HandleFunc("/group/set", GroupSet)
 | 
						r.HandleFunc("/group/set", GroupSet)
 | 
				
			||||||
	r.HandleFunc("/group/del", GroupDel)
 | 
						r.HandleFunc("/group/del", GroupDel)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,6 +32,11 @@ type ValData struct {
 | 
				
			|||||||
	Note   string `json:"note"`
 | 
						Note   string `json:"note"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type GroupNameId struct {
 | 
				
			||||||
 | 
						Id   int    `json:"id"`
 | 
				
			||||||
 | 
						Name string `json:"name"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// type Group struct {
 | 
					// type Group struct {
 | 
				
			||||||
// 	Id               int                    `json:"id" xorm:"pk autoincr not null"`
 | 
					// 	Id               int                    `json:"id" xorm:"pk autoincr not null"`
 | 
				
			||||||
// 	Name             string                 `json:"name" xorm:"varchar(60) not null unique"`
 | 
					// 	Name             string                 `json:"name" xorm:"varchar(60) not null unique"`
 | 
				
			||||||
@@ -64,6 +69,20 @@ func GetGroupNames() []string {
 | 
				
			|||||||
	return names
 | 
						return names
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetGroupNamesIds() []GroupNameId {
 | 
				
			||||||
 | 
						var datas []Group
 | 
				
			||||||
 | 
						err := Find(&datas, 0, 0)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							base.Error(err)
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var names []GroupNameId
 | 
				
			||||||
 | 
						for _, v := range datas {
 | 
				
			||||||
 | 
							names = append(names, GroupNameId{Id: v.Id, Name: v.Name})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return names
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func SetGroup(g *Group) error {
 | 
					func SetGroup(g *Group) error {
 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
	if g.Name == "" {
 | 
						if g.Name == "" {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -63,4 +63,10 @@ func TestGetGroupNames(t *testing.T) {
 | 
				
			|||||||
	for _, v := range gs {
 | 
						for _, v := range gs {
 | 
				
			||||||
		ast.Equal(true, utils.InArrStr(gAll, v))
 | 
							ast.Equal(true, utils.InArrStr(gAll, v))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gni := GetGroupNamesIds()
 | 
				
			||||||
 | 
						for _, v := range gni {
 | 
				
			||||||
 | 
							ast.NotEqual(0, v.Id)
 | 
				
			||||||
 | 
							ast.Equal(true, utils.InArrStr(gAll, v.Name))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										55
									
								
								server/dbdata/statsinfo_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								server/dbdata/statsinfo_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,55 @@
 | 
				
			|||||||
 | 
					package dbdata
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/stretchr/testify/assert"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestStatsInfo(t *testing.T) {
 | 
				
			||||||
 | 
						ast := assert.New(t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						preIpData()
 | 
				
			||||||
 | 
						defer closeIpdata()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ast.True(StatsInfoIns.ValidAction("online"))
 | 
				
			||||||
 | 
						ast.False(StatsInfoIns.ValidAction("diskio"))
 | 
				
			||||||
 | 
						ast.True(StatsInfoIns.ValidScope("30d"))
 | 
				
			||||||
 | 
						ast.False(StatsInfoIns.ValidScope("60d"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						up := uint32(100)
 | 
				
			||||||
 | 
						down := uint32(300)
 | 
				
			||||||
 | 
						upGroups := map[int]uint32{1: up}
 | 
				
			||||||
 | 
						downGroups := map[int]uint32{1: down}
 | 
				
			||||||
 | 
						numGroups := map[int]int{1: 5}
 | 
				
			||||||
 | 
						// online
 | 
				
			||||||
 | 
						numData, _ := json.Marshal(numGroups)
 | 
				
			||||||
 | 
						so := &StatsOnline{Num: 1, NumGroups: string(numData)}
 | 
				
			||||||
 | 
						// network
 | 
				
			||||||
 | 
						upData, _ := json.Marshal(upGroups)
 | 
				
			||||||
 | 
						downData, _ := json.Marshal(downGroups)
 | 
				
			||||||
 | 
						sn := &StatsNetwork{Up: up, Down: down, UpGroups: string(upData), DownGroups: string(downData)}
 | 
				
			||||||
 | 
						// cpu
 | 
				
			||||||
 | 
						sc := &StatsCpu{Percent: 0.3}
 | 
				
			||||||
 | 
						// mem
 | 
				
			||||||
 | 
						sm := &StatsMem{Percent: 24.50}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						StatsInfoIns.SetRealTime("online", so)
 | 
				
			||||||
 | 
						StatsInfoIns.GetRealTime("online")
 | 
				
			||||||
 | 
						StatsInfoIns.SaveStatsInfo(so, sn, sc, sm)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var err error
 | 
				
			||||||
 | 
						_, err = StatsInfoIns.GetData("online", "1h")
 | 
				
			||||||
 | 
						ast.Nil(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err = StatsInfoIns.GetData("network", "1h")
 | 
				
			||||||
 | 
						ast.Nil(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err = StatsInfoIns.GetData("cpu", "1h")
 | 
				
			||||||
 | 
						ast.Nil(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err = StatsInfoIns.GetData("mem", "1h")
 | 
				
			||||||
 | 
						ast.Nil(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -22,9 +22,9 @@ func saveStatsInfo() {
 | 
				
			|||||||
		for range tick.C {
 | 
							for range tick.C {
 | 
				
			||||||
			up := uint32(0)
 | 
								up := uint32(0)
 | 
				
			||||||
			down := uint32(0)
 | 
								down := uint32(0)
 | 
				
			||||||
			upGroups := make(map[string]uint32)
 | 
								upGroups := make(map[int]uint32)
 | 
				
			||||||
			downGroups := make(map[string]uint32)
 | 
								downGroups := make(map[int]uint32)
 | 
				
			||||||
			numGroups := make(map[string]int)
 | 
								numGroups := make(map[int]int)
 | 
				
			||||||
			onlineNum := 0
 | 
								onlineNum := 0
 | 
				
			||||||
			sessMux.Lock()
 | 
								sessMux.Lock()
 | 
				
			||||||
			for _, v := range sessions {
 | 
								for _, v := range sessions {
 | 
				
			||||||
@@ -32,12 +32,16 @@ func saveStatsInfo() {
 | 
				
			|||||||
				if v.IsActive {
 | 
									if v.IsActive {
 | 
				
			||||||
					// 在线人数
 | 
										// 在线人数
 | 
				
			||||||
					onlineNum += 1
 | 
										onlineNum += 1
 | 
				
			||||||
					numGroups[v.Group] += 1
 | 
										numGroups[v.CSess.Group.Id] += 1
 | 
				
			||||||
					// 网络吞吐
 | 
										// 网络吞吐
 | 
				
			||||||
					userUp := atomic.LoadUint32(&v.CSess.BandwidthUpPeriod)
 | 
										userUp := atomic.LoadUint32(&v.CSess.BandwidthUpPeriod)
 | 
				
			||||||
					userDown := atomic.LoadUint32(&v.CSess.BandwidthDownPeriod)
 | 
										userDown := atomic.LoadUint32(&v.CSess.BandwidthDownPeriod)
 | 
				
			||||||
					upGroups[v.Group] += userUp
 | 
										if userUp > 0 {
 | 
				
			||||||
					downGroups[v.Group] += userDown
 | 
											upGroups[v.CSess.Group.Id] += userUp
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										if userDown > 0 {
 | 
				
			||||||
 | 
											downGroups[v.CSess.Group.Id] += userDown
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
					up += userUp
 | 
										up += userUp
 | 
				
			||||||
					down += userDown
 | 
										down += userDown
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -46,6 +46,12 @@
 | 
				
			|||||||
    <el-row class="line-chart-box" gutter="20">
 | 
					    <el-row class="line-chart-box" gutter="20">
 | 
				
			||||||
        <el-col :span="12" class="line-chart-col">            
 | 
					        <el-col :span="12" class="line-chart-col">            
 | 
				
			||||||
            <LineChart :chart-data="lineChart.online"/>
 | 
					            <LineChart :chart-data="lineChart.online"/>
 | 
				
			||||||
 | 
					            <div class="chart-group-name">
 | 
				
			||||||
 | 
					                <el-select size="mini" v-model="lineChartGroup.online" @change="lineChartGroupChange('online')">
 | 
				
			||||||
 | 
					                    <el-option v-for="(item,index) in groupNames" :key="index" :label="item.text" :value="item.value">
 | 
				
			||||||
 | 
					                    </el-option>
 | 
				
			||||||
 | 
					                </el-select> 
 | 
				
			||||||
 | 
					            </div>           
 | 
				
			||||||
            <div class="time-range">
 | 
					            <div class="time-range">
 | 
				
			||||||
                <el-radio-group v-model="lineChartScope.online" size="mini" @change="((label)=>{lineChartScopeChange('online', label)})">
 | 
					                <el-radio-group v-model="lineChartScope.online" size="mini" @change="((label)=>{lineChartScopeChange('online', label)})">
 | 
				
			||||||
                    <el-radio-button label="rt" >实时</el-radio-button>
 | 
					                    <el-radio-button label="rt" >实时</el-radio-button>
 | 
				
			||||||
@@ -58,6 +64,12 @@
 | 
				
			|||||||
        </el-col>
 | 
					        </el-col>
 | 
				
			||||||
        <el-col :span="12" class="line-chart-col">
 | 
					        <el-col :span="12" class="line-chart-col">
 | 
				
			||||||
            <LineChart :chart-data="lineChart.network"/>
 | 
					            <LineChart :chart-data="lineChart.network"/>
 | 
				
			||||||
 | 
					            <div class="chart-group-name">
 | 
				
			||||||
 | 
					                <el-select size="mini" v-model="lineChartGroup.network" @change="lineChartGroupChange('network')">
 | 
				
			||||||
 | 
					                    <el-option v-for="(item,index) in groupNames" :key="index" :label="item.text" :value="item.value">
 | 
				
			||||||
 | 
					                    </el-option>
 | 
				
			||||||
 | 
					                </el-select> 
 | 
				
			||||||
 | 
					            </div>            
 | 
				
			||||||
            <div class="time-range">
 | 
					            <div class="time-range">
 | 
				
			||||||
                <el-radio-group v-model="lineChartScope.network" size="mini" @change="((label)=>{lineChartScopeChange('network', label)})">
 | 
					                <el-radio-group v-model="lineChartScope.network" size="mini" @change="((label)=>{lineChartScopeChange('network', label)})">
 | 
				
			||||||
                    <el-radio-button label="rt" >实时</el-radio-button>
 | 
					                    <el-radio-button label="rt" >实时</el-radio-button>
 | 
				
			||||||
@@ -119,6 +131,7 @@ export default {
 | 
				
			|||||||
        group: 0,
 | 
					        group: 0,
 | 
				
			||||||
        ip_map: 0,
 | 
					        ip_map: 0,
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
 | 
					      groupNames:[],
 | 
				
			||||||
      lineChart: {
 | 
					      lineChart: {
 | 
				
			||||||
        online: {
 | 
					        online: {
 | 
				
			||||||
            title: '用户在线数',
 | 
					            title: '用户在线数',
 | 
				
			||||||
@@ -161,6 +174,10 @@ export default {
 | 
				
			|||||||
            cpu : "rt",
 | 
					            cpu : "rt",
 | 
				
			||||||
            mem : "rt"  
 | 
					            mem : "rt"  
 | 
				
			||||||
      }, 
 | 
					      }, 
 | 
				
			||||||
 | 
					      lineChartGroup : {
 | 
				
			||||||
 | 
					            online: "",
 | 
				
			||||||
 | 
					            network: "",
 | 
				
			||||||
 | 
					      }  
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  created() {
 | 
					  created() {
 | 
				
			||||||
@@ -169,6 +186,7 @@ export default {
 | 
				
			|||||||
  },
 | 
					  },
 | 
				
			||||||
  mounted() {
 | 
					  mounted() {
 | 
				
			||||||
    this.getData()
 | 
					    this.getData()
 | 
				
			||||||
 | 
					    this.getGroups()
 | 
				
			||||||
    this.getAllStats() 
 | 
					    this.getAllStats() 
 | 
				
			||||||
    const chartsTimer = setInterval(() => {
 | 
					    const chartsTimer = setInterval(() => {
 | 
				
			||||||
        this.getAllStats()                                      
 | 
					        this.getAllStats()                                      
 | 
				
			||||||
@@ -219,15 +237,22 @@ export default {
 | 
				
			|||||||
    formatOnline(data) {
 | 
					    formatOnline(data) {
 | 
				
			||||||
        let timeFormat = this.getTimeFormat(data.scope)
 | 
					        let timeFormat = this.getTimeFormat(data.scope)
 | 
				
			||||||
        let chartData = this.lineChart[data.action]
 | 
					        let chartData = this.lineChart[data.action]
 | 
				
			||||||
 | 
					        let chooseGroup = this.lineChartGroup[data.action]
 | 
				
			||||||
        let datas = data.datas
 | 
					        let datas = data.datas
 | 
				
			||||||
 | 
					        let xnum = 0     
 | 
				
			||||||
        chartData.xname = []
 | 
					        chartData.xname = []
 | 
				
			||||||
        chartData.xdata["在线人数"] = []
 | 
					        chartData.xdata["在线人数"] = []
 | 
				
			||||||
        for(var i=0; i<datas.length;i++){
 | 
					        for(var i=0; i<datas.length;i++){
 | 
				
			||||||
            chartData.xname[i] = this.dateFormat(datas[i].created_at, timeFormat)  
 | 
					            chartData.xname[i] = this.dateFormat(datas[i].created_at, timeFormat)  
 | 
				
			||||||
            chartData.xdata["在线人数"][i] = datas[i].num
 | 
					            xnum = datas[i].num
 | 
				
			||||||
 | 
					            if (chooseGroup != "" && xnum > 0) {
 | 
				
			||||||
 | 
					                let num_groups = JSON.parse(datas[i].num_groups)
 | 
				
			||||||
 | 
					                xnum = ! num_groups[chooseGroup] ? 0 : num_groups[chooseGroup]
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            chartData.xdata["在线人数"][i] = xnum
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        // 实时更新在线数
 | 
					        // 实时更新在线数
 | 
				
			||||||
        if (data.scope == "rt") {
 | 
					        if (data.scope == "rt" && chooseGroup == "") {
 | 
				
			||||||
            this.counts.online = datas[datas.length - 1].num
 | 
					            this.counts.online = datas[datas.length - 1].num
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        this.lineChart[data.action] = chartData
 | 
					        this.lineChart[data.action] = chartData
 | 
				
			||||||
@@ -235,14 +260,28 @@ export default {
 | 
				
			|||||||
    formatNetwork(data) {
 | 
					    formatNetwork(data) {
 | 
				
			||||||
        let timeFormat = this.getTimeFormat(data.scope)
 | 
					        let timeFormat = this.getTimeFormat(data.scope)
 | 
				
			||||||
        let chartData = this.lineChart[data.action]
 | 
					        let chartData = this.lineChart[data.action]
 | 
				
			||||||
 | 
					        let chooseGroup = this.lineChartGroup[data.action]
 | 
				
			||||||
        let datas = data.datas
 | 
					        let datas = data.datas
 | 
				
			||||||
 | 
					        let xnumUp = 0, xnumDown = 0
 | 
				
			||||||
        chartData.xname = []
 | 
					        chartData.xname = []
 | 
				
			||||||
        chartData.xdata["上行流量"] = []
 | 
					        chartData.xdata["上行流量"] = []
 | 
				
			||||||
        chartData.xdata["下行流量"] = []
 | 
					        chartData.xdata["下行流量"] = []
 | 
				
			||||||
        for(var i=0; i<datas.length;i++){
 | 
					        for(var i=0; i<datas.length;i++){
 | 
				
			||||||
            chartData.xname[i] = this.dateFormat(datas[i].created_at, timeFormat)
 | 
					            chartData.xname[i] = this.dateFormat(datas[i].created_at, timeFormat)
 | 
				
			||||||
            chartData.xdata["上行流量"][i] = this.toMbps(datas[i].up)
 | 
					            xnumUp = datas[i].up
 | 
				
			||||||
            chartData.xdata["下行流量"][i] = this.toMbps(datas[i].down)
 | 
					            xnumDown = datas[i].down             
 | 
				
			||||||
 | 
					            if (chooseGroup != "") {
 | 
				
			||||||
 | 
					                if (xnumUp > 0) {
 | 
				
			||||||
 | 
					                    let upGroups = JSON.parse(datas[i].up_groups)
 | 
				
			||||||
 | 
					                    xnumUp = ! upGroups[chooseGroup] ? 0 : upGroups[chooseGroup]
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                if (xnumDown > 0) {
 | 
				
			||||||
 | 
					                    let downGroups = JSON.parse(datas[i].down_groups)
 | 
				
			||||||
 | 
					                    xnumDown = ! downGroups[chooseGroup] ? 0 : downGroups[chooseGroup]
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            chartData.xdata["上行流量"][i] = this.toMbps(xnumUp)
 | 
				
			||||||
 | 
					            chartData.xdata["下行流量"][i] = this.toMbps(xnumDown)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        this.lineChart[data.action] = chartData
 | 
					        this.lineChart[data.action] = chartData
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
@@ -301,6 +340,23 @@ export default {
 | 
				
			|||||||
    jump(path) {
 | 
					    jump(path) {
 | 
				
			||||||
        this.$router.push(path);
 | 
					        this.$router.push(path);
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    getGroups() {
 | 
				
			||||||
 | 
					      axios.get('/group/names_ids', {}).then(resp => {
 | 
				
			||||||
 | 
					        var data = resp.data.data
 | 
				
			||||||
 | 
					        var groupNames = []
 | 
				
			||||||
 | 
					        groupNames[0] = {text:"全部", value:""}
 | 
				
			||||||
 | 
					        for(var i=0; i<data.datas.length;i++){
 | 
				
			||||||
 | 
					            groupNames[i+1] = {text:data.datas[i].name, value:data.datas[i].id}
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        this.groupNames = groupNames
 | 
				
			||||||
 | 
					      }).catch(error => {
 | 
				
			||||||
 | 
					        this.$message.error('哦,请求出错');
 | 
				
			||||||
 | 
					        console.log(error);
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    }, 
 | 
				
			||||||
 | 
					    lineChartGroupChange(action) {
 | 
				
			||||||
 | 
					        this.getStatsData(action, this.lineChartScope[action]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
@@ -309,6 +365,7 @@ export default {
 | 
				
			|||||||
.panel-group {
 | 
					.panel-group {
 | 
				
			||||||
    margin-bottom: 20px;
 | 
					    margin-bottom: 20px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.card-panel {
 | 
					.card-panel {
 | 
				
			||||||
  display: flex;
 | 
					  display: flex;
 | 
				
			||||||
  border-radius: 12px;
 | 
					  border-radius: 12px;
 | 
				
			||||||
@@ -368,4 +425,17 @@ export default {
 | 
				
			|||||||
    right: 5px;
 | 
					    right: 5px;
 | 
				
			||||||
    top: 5px;
 | 
					    top: 5px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.chart-group-name {
 | 
				
			||||||
 | 
					    position: absolute;
 | 
				
			||||||
 | 
					    left: 110px;
 | 
				
			||||||
 | 
					    top: 5px;
 | 
				
			||||||
 | 
					    width: 130px;
 | 
				
			||||||
 | 
					    font-size: 10px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/deep/ .el-radio-button--mini .el-radio-button__inner {
 | 
				
			||||||
 | 
					    padding: 7px 8px;    
 | 
				
			||||||
 | 
					    font-size: 10px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user