Merge branch 'dev' of https://git.mesalab.cn/cyber-narrator/cn-ui into dev
# Conflicts: # src/views/charts/Chart2.vue
This commit is contained in:
@@ -115,6 +115,86 @@
|
||||
left: 0;
|
||||
top: -1px;
|
||||
}
|
||||
.header__operations {
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
align-items: center;
|
||||
|
||||
.header__operation-btn {
|
||||
margin-left: 12px;
|
||||
cursor: pointer;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.header__operation.header__operation--table {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 22px;
|
||||
margin-left: 10px;
|
||||
color: $--color-primary;
|
||||
border: 1px solid $--color-primary;
|
||||
border-radius: $--border-radius-primary;
|
||||
|
||||
.option__button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
padding: 0 5px;
|
||||
cursor: pointer;
|
||||
background-color: white;
|
||||
transition: all linear .2s;
|
||||
}
|
||||
.option__button:hover {
|
||||
background-color: #EFF2F5;
|
||||
}
|
||||
.option__button.icon-group-item:first-of-type:not(:last-of-type) {
|
||||
padding: 0 5px 0 0;
|
||||
}
|
||||
.option__button.icon-group-item:last-of-type:not(:first-of-type) {
|
||||
padding: 0 0 0 5px;
|
||||
}
|
||||
.option__select {
|
||||
.el-input__inner {
|
||||
width: 80px;
|
||||
padding-right: 20px;
|
||||
border: none;
|
||||
height: 100%;
|
||||
line-height: 20px;
|
||||
color: $--color-primary;
|
||||
}
|
||||
.el-input__prefix > div {
|
||||
font-weight: normal;
|
||||
line-height: 19px;
|
||||
color: $--color-primary;
|
||||
}
|
||||
.el-input__suffix {
|
||||
display: flex;
|
||||
.el-input__suffix-inner {
|
||||
line-height: 14px;
|
||||
.el-select__caret {
|
||||
line-height: 14px;
|
||||
width: 16px;
|
||||
color: $--color-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.option__select.select-column {
|
||||
.el-input__inner {
|
||||
width: 86px;
|
||||
padding-left: 8px;
|
||||
}
|
||||
}
|
||||
.icon-group-divide {
|
||||
height: 14px;
|
||||
width: 1px;
|
||||
background-color: $--color-primary;
|
||||
}
|
||||
i {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&>.cn-chart {
|
||||
position: relative;
|
||||
@@ -419,7 +499,7 @@
|
||||
height: calc(100% - 40px);
|
||||
}
|
||||
}
|
||||
&>.cn-chart__table {
|
||||
&>.cn-chart__table, {
|
||||
.cn-chart__header {
|
||||
border-bottom: 1px solid $--content-right-background-color;
|
||||
.header__operations {
|
||||
@@ -832,3 +912,16 @@
|
||||
content: "!";
|
||||
font-weight:normal;
|
||||
}
|
||||
.ip-detail-as {
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.option-popper {
|
||||
.el-select-dropdown__item {
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,10 @@ export default {
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
const _this = this
|
||||
this.emitter.on('chart-pageNo', function () {
|
||||
_this.resetPageNo()
|
||||
})
|
||||
this.$el.querySelector('.el-pagination__jump').childNodes[0].nodeValue = ''
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ import 'highlight.js/styles/color-brewer.css'
|
||||
import '@/assets/css/main.scss' // 样式入口
|
||||
import VueGridLayout from 'vue-grid-layout'
|
||||
import ElementPlus from 'element-plus'
|
||||
import bus from 'tiny-emitter'
|
||||
const emitter = new bus()
|
||||
import dayjs from 'dayjs'
|
||||
import utc from 'dayjs/plugin/utc' // dependent on utc plugin
|
||||
import timezone from 'dayjs/plugin/timezone'
|
||||
@@ -54,4 +56,6 @@ app.component('time-refresh', TimeRefresh)
|
||||
app.component('panel-chart-list', PanelChartList)
|
||||
|
||||
app.mount('#app')
|
||||
|
||||
app.config.globalProperties.emitter = emitter
|
||||
export default app
|
||||
|
||||
@@ -68,6 +68,16 @@
|
||||
:query-params="queryParams"
|
||||
@showLoading="showLoading"
|
||||
></chart-category-bar>
|
||||
|
||||
<chart-table
|
||||
v-else-if="isTable"
|
||||
:chart-info="chartInfo"
|
||||
:chart-data="chartData"
|
||||
:table="table"
|
||||
:query-params="queryParams"
|
||||
@showLoading="showLoading"
|
||||
></chart-table>
|
||||
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
@@ -83,6 +93,7 @@ import IpBasicInfo from '@/views/charts/charts/IpBasicInfo'
|
||||
import ChartEchartLine from './charts/ChartEchartLine'
|
||||
import ChartTimeBar from './charts/ChartTimeBar'
|
||||
import ChartCategoryBar from './charts/ChartCategoryBar'
|
||||
import ChartTable from "./charts/ChartTable";
|
||||
import {
|
||||
isEcharts,
|
||||
isEchartsLine,
|
||||
@@ -119,6 +130,7 @@ import _ from 'lodash'
|
||||
export default {
|
||||
name: 'chart',
|
||||
components: {
|
||||
ChartTable,
|
||||
IpBasicInfo,
|
||||
ChartSingleValue,
|
||||
Loading,
|
||||
@@ -140,7 +152,8 @@ export default {
|
||||
loading: Boolean,
|
||||
panelLock: Boolean,
|
||||
entity: Object,
|
||||
isError: Boolean
|
||||
isError: Boolean,
|
||||
table: Object
|
||||
},
|
||||
computed: {
|
||||
isNoData () {
|
||||
|
||||
@@ -1,8 +1,54 @@
|
||||
<template>
|
||||
<div class="chart-header" :class="{'chart-header--title-chart': isTitle}">
|
||||
<div class="chart-header__title" :class="{'chart-header__title--block': isBlock}">{{chartInfo.name}}</div>
|
||||
<div class="chart-header__title" v-if="!isTable" :class="{'chart-header__title--block': isBlock}">{{chartInfo.name}}</div>
|
||||
<template v-if="isTable">
|
||||
<div class="chart-header__title">
|
||||
<span :title="chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name">{{chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name}}</span>
|
||||
<span
|
||||
v-if="chartInfo.params && chartInfo.params.as"
|
||||
class="ip-detail-as"
|
||||
>
|
||||
as <span style="text-transform: capitalize">{{chartInfo.params.as}}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="header__operations">
|
||||
<el-popover trigger="hover" placement="top" :content="chartInfo.remark" v-if="chartInfo.remark">
|
||||
<template>
|
||||
<span class="header__operation-btn"><i class="cn-icon el-icon-info"></i></span>
|
||||
</template>
|
||||
</el-popover>
|
||||
<div class="header__operation header__operation--table">
|
||||
<el-select
|
||||
size="mini"
|
||||
v-model="table.limit"
|
||||
class="option__select select-topn"
|
||||
placeholder=""
|
||||
popper-class="option-popper"
|
||||
@change="tableLimitChange"
|
||||
>
|
||||
<el-option v-for="item in chartTableTopOptions" :key="item" :value="item">TOP {{item}}</el-option>
|
||||
<template #prefix>TOP </template>
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="header__operation header__operation--table">
|
||||
<el-select
|
||||
size="mini"
|
||||
v-model="table.orderBy"
|
||||
class="option__select select-column"
|
||||
:placeholder="$t('overall.field')"
|
||||
popper-class="option-popper"
|
||||
@change="tableLimitChange"
|
||||
>
|
||||
<template v-for="(item, index) in table.tableColumns" :key="item.prop">
|
||||
<el-option v-if="index > 0" :value="item.prop">{{item.prop}}</el-option>
|
||||
</template>
|
||||
</el-select>
|
||||
</div>
|
||||
<span class="header__operation-btn" @click="refresh"><i class="cn-icon cn-icon-refresh"></i></span>
|
||||
</div>
|
||||
</template>
|
||||
<chart-error :isError="isError" :errorInfo="errorInfo"></chart-error>
|
||||
<div class="chart-header__tools" v-if="!isTitle && !isTabs">
|
||||
<div class="chart-header__tools" v-if="!isTitle && !isTabs && !isTable">
|
||||
<div class="panel__time" v-if="chartInfo.params && chartInfo.params.showTimeTool">
|
||||
<date-time-range class="date-time-range" :start-time="chartTimeFilter.startTime" :end-time="chartTimeFilter.endTime" ref="dateTimeRange" @change="reload"/>
|
||||
<time-refresh class="date-time-range" @change="timeRefreshChange" :end-time="chartTimeFilter.endTime"/>
|
||||
@@ -20,10 +66,11 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { isTitle, isTabs, isBlock } from './charts/tools'
|
||||
import { isTitle, isTabs, isBlock, isTable } from './charts/tools'
|
||||
import ChartError from '@/components/charts/ChartError'
|
||||
import { getNowTime } from '@/utils/date-util'
|
||||
import { ref } from 'vue'
|
||||
import {chartTableTopOptions} from "@/utils/constants";
|
||||
|
||||
export default {
|
||||
name: 'ChartHeader',
|
||||
@@ -36,7 +83,8 @@ export default {
|
||||
isError: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
table: Object
|
||||
},
|
||||
components: {
|
||||
ChartError
|
||||
@@ -62,6 +110,9 @@ export default {
|
||||
},
|
||||
dateTimeRangeChange (s, e, v) {
|
||||
this.chartTimeFilter = { startTime: s, endTime: e, dateRangeValue: v }
|
||||
},
|
||||
tableLimitChange () {
|
||||
this.$emit('tableChange')
|
||||
}
|
||||
},
|
||||
setup (props) {
|
||||
@@ -71,9 +122,11 @@ export default {
|
||||
const chartTimeFilter = ref({ startTime, endTime, dateRangeValue })
|
||||
return {
|
||||
chartTimeFilter,
|
||||
chartTableTopOptions,
|
||||
isTitle: isTitle(props.chartInfo.type),
|
||||
isBlock: isBlock(props.chartInfo.type),
|
||||
isTabs: isTabs(props.chartInfo.type)
|
||||
isTabs: isTabs(props.chartInfo.type),
|
||||
isTable: isTable(props.chartInfo.type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,9 +12,11 @@
|
||||
:error-info="errorInfo"
|
||||
:chart-data="chartData"
|
||||
:chart-info="chartInfo"
|
||||
:table="table"
|
||||
@loadMore="loadMore"
|
||||
@refresh="refresh"
|
||||
@showFullscreen="showFullscreen"
|
||||
@tableChange="tableChange"
|
||||
></chart-header>
|
||||
<!-- chart -->
|
||||
<!-- 数据查询后传入chart组件,chart组件内不查询,只根据接传递的数据来渲染 -->
|
||||
@@ -29,6 +31,7 @@
|
||||
:is-error="isError"
|
||||
:loading="loading"
|
||||
:entity="entity"
|
||||
:table="table"
|
||||
:is-fullscreen="isFullscreen"
|
||||
@showLoading="showLoading"
|
||||
></chart>
|
||||
@@ -141,7 +144,10 @@ export default {
|
||||
table: {
|
||||
pageSize: chartTableDefaultPageSize,
|
||||
limit: chartTableTopOptions[0], // top-n
|
||||
orderBy: 'sessions'
|
||||
orderBy: 'sessions',
|
||||
tableColumns: [], // table字段
|
||||
tableData: [], // table的所有数据
|
||||
currentPageData: [] // table当前页的数据
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -186,6 +192,9 @@ export default {
|
||||
}
|
||||
if (response.code === 200) {
|
||||
this.chartData = response.data.result
|
||||
this.table.tableData = response.data.result
|
||||
this.table.tableColumns = this.getTableTitle(response.data.result)
|
||||
this.table.currentPageData = this.getTargetPageData(1, this.table.pageSize, this.table.tableData)
|
||||
this.resultType = response.data.resultType
|
||||
this.isError = false
|
||||
} else {
|
||||
@@ -230,6 +239,7 @@ export default {
|
||||
this.standaloneTimeRange.use = true
|
||||
this.standaloneTimeRange.startTime = myStartTime
|
||||
this.standaloneTimeRange.endTime = myEndTime
|
||||
this.emitter.emit('chart-pageNo')
|
||||
this.getChartData(null, {}, true)
|
||||
},
|
||||
showFullscreen (show) {
|
||||
@@ -284,6 +294,13 @@ export default {
|
||||
},
|
||||
showLoading (show) {
|
||||
this.loading = show
|
||||
},
|
||||
tableChange () {
|
||||
this.emitter.emit('chart-pageNo')
|
||||
this.getChartData()
|
||||
},
|
||||
getTargetPageData (pageNum, pageSize, tableData) {
|
||||
return this.$_.slice(tableData, (pageNum - 1) * pageSize, pageNum * pageSize)
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<div class="cn-chart__single-value chart-header-position" :class="singleValueClass(type)" :style="{backgroundColor:color}">
|
||||
<div class="single-value-icon__box" v-if="chartInfo.type != 54">
|
||||
<div class="single-value-icon__box" v-if="type !== 54">
|
||||
<div class="single-value__icon"><i :class="icon"></i></div>
|
||||
</div>
|
||||
<div class="single-value__content" v-if="chartInfo.type == 51">
|
||||
<div class="single-value__content" v-if="type === 51">
|
||||
<div class="content__data">
|
||||
<span>{{handleSingleValue[0] || handleSingleValue[0] === 0 ? handleSingleValue[0] : '-'}}</span>
|
||||
<span class="single-value__unit">{{handleSingleValue[1]}}</span>
|
||||
@@ -12,9 +12,12 @@
|
||||
<span :title="chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name">{{chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="single-value__content single-value__content--with-chart" v-if="chartInfo.type == 52">
|
||||
<div class="single-value__content single-value__content--with-chart" v-if="type === 52">
|
||||
<div class="content__title">
|
||||
<span :title="chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name">{{chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name}}</span>
|
||||
<span v-if="chartInfo.params && chartInfo.params.as" class="ip-detail-as">
|
||||
as <span style="text-transform: capitalize">{{chartInfo.params.as}}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="content__data">
|
||||
<span>{{handleSingleValue[0] || handleSingleValue[0] === 0 ? handleSingleValue[0] : '-'}}</span>
|
||||
@@ -24,7 +27,7 @@
|
||||
<div class="chart-drawing" :id="`chart${chartInfo.id}`"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="single-value__content" v-if="chartInfo.type == 53">
|
||||
<div class="single-value__content" v-if="type === 53">
|
||||
<div class="content__title">
|
||||
<span :title="chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name">{{chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name}}</span>
|
||||
</div>
|
||||
@@ -33,7 +36,7 @@
|
||||
<span class="single-value__unit">{{handleSingleValue[1]}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="single-value__content" v-if="chartInfo.type == 54" >
|
||||
<div class="single-value__content" v-if="type === 54" >
|
||||
<div class="single-value-icon__box" >
|
||||
<div class="single-value__icon">
|
||||
<!-- 使用图标-->
|
||||
@@ -86,7 +89,7 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
handleSingleValue () {
|
||||
const value = this.chartData ? this.chartData.value: ''
|
||||
const value = this.chartData ? this.chartData : ''
|
||||
const unitType = this.chartInfo.params.unitType
|
||||
const result = unitConvert(value, unitType)
|
||||
switch (unitType) {
|
||||
|
||||
79
src/views/charts/charts/ChartTable.vue
Normal file
79
src/views/charts/charts/ChartTable.vue
Normal file
@@ -0,0 +1,79 @@
|
||||
<template>
|
||||
<div class="cn-chart__table">
|
||||
<div class="cn-chart__body">
|
||||
<el-table
|
||||
style="width: 100%"
|
||||
tooltip-effect="light"
|
||||
:data="table.currentPageData"
|
||||
>
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="#"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-for="(c, i) in table.tableColumns"
|
||||
show-overflow-tooltip
|
||||
:key="i"
|
||||
:label="c.label"
|
||||
:prop="c.prop"
|
||||
>
|
||||
<template #header>{{$t(c.label)}}</template>
|
||||
<template #default="{ row }">
|
||||
<span v-if="c.prop === 'bytes'">
|
||||
{{unitConvert(row[c.prop], unitTypes.byte).join(' ')}}
|
||||
</span>
|
||||
<span v-else-if="c.prop === 'packets' || c.prop === 'sessions'">
|
||||
{{unitConvert(row[c.prop], unitTypes.number).join(' ')}}
|
||||
</span>
|
||||
<span v-else>
|
||||
{{row[c.prop]}}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<div class="cn-chart__footer">
|
||||
<chart-table-pagination
|
||||
ref="tablePagination"
|
||||
:total="table.tableData.length"
|
||||
@pageJump="pageJump"
|
||||
></chart-table-pagination>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {unitTypes} from '@/utils/constants'
|
||||
import unitConvert from '@/utils/unit-convert'
|
||||
import ChartTablePagination from '@/components/charts/ChartTablePagination'
|
||||
export default {
|
||||
name: "ChartTable",
|
||||
components: {
|
||||
ChartTablePagination
|
||||
},
|
||||
props: {
|
||||
chartInfo: Object,
|
||||
chartData: [Array, Object],
|
||||
queryParams: Object,
|
||||
table: Object
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
unitConvert,
|
||||
unitTypes
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
pageJump (val) {
|
||||
this.table.currentPageData = this.getTargetPageData(val, this.table.pageSize, this.table.tableData)
|
||||
},
|
||||
getTargetPageData (pageNum, pageSize, tableData) {
|
||||
return this.$_.slice(tableData, (pageNum - 1) * pageSize, pageNum * pageSize)
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user