WIP: 绘制Data Recevice status Monitoring弹窗内容(进行中)
This commit is contained in:
parent
1ccf2c12db
commit
12f010ecb8
|
@ -22,6 +22,7 @@
|
|||
"cron-parser": "^2.10.0",
|
||||
"dayjs": "^1.8.0",
|
||||
"dom-align": "1.12.0",
|
||||
"echarts": "^4.9.0",
|
||||
"enquire.js": "^2.1.6",
|
||||
"js-cookie": "^2.2.0",
|
||||
"lodash.get": "^4.4.2",
|
||||
|
|
BIN
src/assets/images/station-operation/toggle-2.png
Normal file
BIN
src/assets/images/station-operation/toggle-2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
26
src/components/CustomChart/index.vue
Normal file
26
src/components/CustomChart/index.vue
Normal file
|
@ -0,0 +1,26 @@
|
|||
<template>
|
||||
<div class="custom-chart" ref="containerRef"></div>
|
||||
</template>
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
export default {
|
||||
props: {
|
||||
option : {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
mounted() {
|
||||
this.chart = echarts.init(this.$refs.containerRef)
|
||||
this.chart.setOption(this.option)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.custom-chart {
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<a-select v-bind="$attrs" v-model="innerValue" show-arrow>
|
||||
<a-select v-bind="$attrs" v-model="innerValue" show-arrow @change="onChange">
|
||||
<img slot="suffixIcon" src="@/assets/images/global/select-down.png" alt="" />
|
||||
</a-select>
|
||||
</template>
|
||||
|
@ -16,12 +16,15 @@ export default {
|
|||
innerValue: this.value
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onChange(val) {
|
||||
this.$emit('input', val)
|
||||
this.$emit('change', val)
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value () {
|
||||
this.innerValue = this.value
|
||||
},
|
||||
innerValue () {
|
||||
this.$emit('input', this.innerValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
79
src/components/CustomTree/index.vue
Normal file
79
src/components/CustomTree/index.vue
Normal file
|
@ -0,0 +1,79 @@
|
|||
<template>
|
||||
<a-tree class="custom-tree" v-model="checkedKeys" checkable :selectedKeys="[]" :tree-data="treeData" @select="onTreeSelect">
|
||||
<a-icon slot="switcherIcon" type="down" />
|
||||
</a-tree>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
treeData: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
value: {
|
||||
type: Array
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
checkedKeys: [] // 选中的树节点
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onTreeSelect(_, { node }) {
|
||||
const selectedKey = node.eventKey
|
||||
const parentKey = node.$parent.eventKey
|
||||
|
||||
const findIndex = this.checkedKeys.findIndex(key => key == selectedKey)
|
||||
|
||||
if (parentKey) {
|
||||
// 选中的是子级节点
|
||||
if (-1 == findIndex) {
|
||||
// 选中了
|
||||
this.checkedKeys.push(selectedKey)
|
||||
|
||||
const parentNode = this.treeData.find(tree => tree.key == parentKey) // 找到树列表中的父节点
|
||||
const childrenKeys = parentNode.children.map(child => child.key)
|
||||
if (childrenKeys.every(key => this.checkedKeys.includes(key))) {
|
||||
// 如果子列表每一个都能在选中的列表中找到,则是全选
|
||||
this.checkedKeys.push(parentKey)
|
||||
}
|
||||
} else {
|
||||
// 取消了
|
||||
this.checkedKeys.splice(findIndex, 1)
|
||||
|
||||
const findParent = this.checkedKeys.findIndex(key => key == parentKey)
|
||||
if (-1 !== findParent) {
|
||||
this.checkedKeys.splice(findParent, 1)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//选中的是父级节点
|
||||
const parentNode = this.treeData.find(tree => tree.key == selectedKey)
|
||||
const childrenKeys = parentNode.children.map(child => child.key)
|
||||
|
||||
const findParent = this.checkedKeys.findIndex(key => key == selectedKey)
|
||||
if (-1 == findParent) {
|
||||
// 未选中父节点,则将子节点都选中
|
||||
this.checkedKeys.push(selectedKey)
|
||||
this.checkedKeys.push(...childrenKeys)
|
||||
} else {
|
||||
// 已经选中了父节点,则将子节点都取消选中
|
||||
this.checkedKeys = this.checkedKeys.filter(key => key !== selectedKey && !childrenKeys.includes(key))
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value() {
|
||||
this.checkedKeys = this.value
|
||||
},
|
||||
checkedKeys() {
|
||||
this.$emit('input', this.checkedKeys)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style></style>
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div ref="containerRef" class="scroll-container" :class="{ 'scroll-end': scrollEnd }" @scroll="onScroll">
|
||||
<div ref="containerRef" class="scroll-container" :class="{ 'scroll-end': scrollEnd }">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -8,32 +8,42 @@ export default {
|
|||
props: {
|
||||
direction: {
|
||||
type: String,
|
||||
default: 'horizontal', // horizontal | vertical
|
||||
default: 'horizontal' // horizontal | vertical
|
||||
},
|
||||
scrollContainer: {
|
||||
type: Function
|
||||
}
|
||||
},
|
||||
data() {
|
||||
this.isCustomContainer = this.scrollContainer && typeof this.scrollContainer == 'function' // 是自定义的容器
|
||||
return {
|
||||
scrollEnd: false,
|
||||
scrollEnd: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.onScroll()
|
||||
window.addEventListener('resize', this.onScroll)
|
||||
},
|
||||
destroyed() {
|
||||
window.removeEventListener('resize', this.onScroll)
|
||||
this.containerEle = this.isCustomContainer ? this.scrollContainer() : this.$refs.containerRef
|
||||
this.containerEle.addEventListener('scroll', () => {
|
||||
this.checkScrollEnd()
|
||||
})
|
||||
|
||||
this.containerEle.addEventListener('transitionend', () => { // 如果有过渡动画,则在过渡动画结束后触发
|
||||
this.checkScrollEnd()
|
||||
})
|
||||
},
|
||||
|
||||
methods: {
|
||||
onScroll() {
|
||||
const ele = this.$refs.containerRef
|
||||
/**
|
||||
* 检查是否滚动到尾部
|
||||
*/
|
||||
checkScrollEnd() {
|
||||
if (this.direction == 'horizontal') {
|
||||
this.scrollEnd = ele.scrollLeft + ele.offsetWidth == ele.scrollWidth
|
||||
this.scrollEnd = this.containerEle.scrollLeft + this.containerEle.offsetWidth == this.containerEle.scrollWidth
|
||||
} else {
|
||||
this.scrollEnd = ele.scrollTop + ele.offsetHeight == ele.scrollHeight
|
||||
this.scrollEnd = this.containerEle.scrollTop + this.containerEle.offsetHeight == this.containerEle.scrollHeight
|
||||
}
|
||||
this.$emit('scrollEnd', this.scrollEnd)
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
|
@ -42,4 +52,4 @@ export default {
|
|||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
@ -93,9 +93,9 @@
|
|||
val = e
|
||||
}
|
||||
console.log(val);
|
||||
this.$emit('change', val);
|
||||
this.$emit('change', val? val: undefined);
|
||||
//LOWCOD-2146 【菜单】数据规则,选择自定义SQL 规则值无法输入空格
|
||||
this.$emit('input', val);
|
||||
this.$emit('input', val? val: undefined);
|
||||
},
|
||||
setCurrentDictOptions(dictOptions){
|
||||
this.dictOptions = dictOptions
|
||||
|
|
|
@ -57,6 +57,8 @@ import CustomModal from '@/components/CustomModal'
|
|||
import CustomDatePicker from '@/components/CustomDatePicker'
|
||||
import CustomMonthPicker from '@/components/CustomMonthPicker'
|
||||
import CustomEmpty from '@/components/CustomEmpty'
|
||||
import CustomChart from '@/components/CustomChart'
|
||||
console.log('%c [ CustomChart ]-61', 'font-size:13px; background:pink; color:#bf2c9f;', CustomChart)
|
||||
|
||||
|
||||
Vue.prototype.rules = rules
|
||||
|
@ -79,6 +81,7 @@ Vue.component('custom-modal', CustomModal)
|
|||
Vue.component('custom-date-picker', CustomDatePicker)
|
||||
Vue.component('custom-month-picker', CustomMonthPicker)
|
||||
Vue.component('custom-empty', CustomEmpty)
|
||||
Vue.component('custom-chart', CustomChart)
|
||||
|
||||
SSO.init(() => {
|
||||
main()
|
||||
|
|
|
@ -286,7 +286,7 @@ body {
|
|||
}
|
||||
|
||||
&-table {
|
||||
background-color: #06282A !important;
|
||||
background-color: #06282a !important;
|
||||
}
|
||||
|
||||
&-tbody {
|
||||
|
@ -334,6 +334,49 @@ body {
|
|||
}
|
||||
}
|
||||
|
||||
// 数字输入框
|
||||
@input-number-handler-active-bg: #06404c;
|
||||
@input-number-handler-hover-bg: #06404c;
|
||||
@input-number-handler-bg: #06404c;
|
||||
@input-number-handler-border-color: transparent;
|
||||
|
||||
.ant-input-number {
|
||||
border-radius: 0;
|
||||
border: 1px solid #0b8c82;
|
||||
&-handler {
|
||||
height: 50% !important;
|
||||
&:hover {
|
||||
height: 50% !important;
|
||||
}
|
||||
|
||||
.anticon {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
// 数组输入框右侧的上下箭头
|
||||
&::after {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border: 5px solid transparent;
|
||||
border-left-width: 4px;
|
||||
border-right-width: 4px;
|
||||
border-bottom-color: #4b859e;
|
||||
position: relative;
|
||||
top: -1px;
|
||||
}
|
||||
|
||||
&-down {
|
||||
border-top: none;
|
||||
&::after {
|
||||
transform: rotate(180deg);
|
||||
top: 1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 单选样式
|
||||
.ant-radio {
|
||||
&-wrapper {
|
||||
|
|
|
@ -86,7 +86,6 @@ export default {
|
|||
|
||||
// 设置地图缩放级别
|
||||
setZoom(zoom) {
|
||||
console.log('%c [ zoom ]-89', 'font-size:13px; background:pink; color:#bf2c9f;', zoom)
|
||||
if (zoom < this.minZoom) {
|
||||
zoom = this.minZoom
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
<div class="map-pane-operators-main-operator">
|
||||
<div>
|
||||
<img v-if="analyzeModalVisible" src="@/assets/images/station-operation/analyze-active.png" />
|
||||
<img v-if="dataStatusModalVisible" src="@/assets/images/station-operation/analyze-active.png" />
|
||||
<img v-else src="@/assets/images/station-operation/analyze.png" @click="handleOpenAnalyzeModal" />
|
||||
</div>
|
||||
<div>
|
||||
|
@ -54,13 +54,7 @@
|
|||
|
||||
<!-- 站点选择树 -->
|
||||
<div class="station-list-tree">
|
||||
<a-tree
|
||||
v-model="checkedKeys"
|
||||
:selectedKeys="[]"
|
||||
:tree-data="treeData"
|
||||
checkable
|
||||
@select="onTreeSelect"
|
||||
></a-tree>
|
||||
<custom-tree v-model="checkedKeys" :tree-data="treeData"></custom-tree>
|
||||
</div>
|
||||
<!-- 站点选择树 结束 -->
|
||||
</div>
|
||||
|
@ -125,16 +119,84 @@
|
|||
</div>
|
||||
<!-- 主体部分结束 -->
|
||||
|
||||
<!-- 分析弹窗开始 -->
|
||||
<custom-modal v-model="analyzeModalVisible" enableFullScreen title="Data Recevice status Monitoring" width="64%" :showFooter="false">
|
||||
分析弹窗内容
|
||||
<!-- 数据监控状态弹窗开始 -->
|
||||
<custom-modal
|
||||
v-model="dataStatusModalVisible"
|
||||
enableFullScreen
|
||||
:bodyStyle="{ padding: '15px 0 10px' }"
|
||||
title="Data Recevice status Monitoring"
|
||||
:width="1230"
|
||||
:showFooter="false"
|
||||
>
|
||||
<div class="data-receive-status">
|
||||
<!-- 左侧配置栏 -->
|
||||
<div class="data-receive-status-list" :class="{ open: leftPaneShow }">
|
||||
<div class="data-receive-status-list-container">
|
||||
<div class="data-receive-status-list-item">
|
||||
<div class="title">
|
||||
<span>
|
||||
Particulate Station
|
||||
</span>
|
||||
<img src="@/assets/images/station-operation/toggle.png" @click="leftPaneShow = !leftPaneShow" />
|
||||
</div>
|
||||
<div class="content">
|
||||
<custom-tree v-model="dataStatusCheckedKeys" :tree-data="treeData"></custom-tree>
|
||||
</div>
|
||||
</div>
|
||||
<div class="data-receive-status-list-item">
|
||||
<div class="title">
|
||||
<span>
|
||||
Attribute Configuration
|
||||
</span>
|
||||
<img src="@/assets/images/station-operation/toggle.png" @click="leftPaneShow = !leftPaneShow" />
|
||||
</div>
|
||||
<div class="content">
|
||||
<a-form-model class="attribute-form" layout="vertical">
|
||||
<a-form-model-item label="Cache time">
|
||||
<a-input-number type="number"></a-input-number>
|
||||
<span>day</span>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="Scale interval">
|
||||
<a-input-number type="number"></a-input-number>
|
||||
<span>min</span>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="Timeline length">
|
||||
<a-input-number type="number"></a-input-number>
|
||||
<span>min</span>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="Update interval time">
|
||||
<a-input-number type="number"></a-input-number>
|
||||
<span>min</span>
|
||||
</a-form-model-item>
|
||||
<div class="attribute-form-footer">
|
||||
<a-button type="primary">SAVE</a-button>
|
||||
</div>
|
||||
</a-form-model>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="data-receive-status-list-toggle-show-btn" v-if="!leftPaneShow">
|
||||
<img src="@/assets/images/station-operation/toggle-2.png" @click="leftPaneShow = true" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- 左侧配置栏结束 -->
|
||||
|
||||
<!-- 右侧图表展示栏 -->
|
||||
<div class="data-receive-status-chart" :class="{ 'on-screen': !leftPaneShow }">
|
||||
<custom-chart :option="option"></custom-chart>
|
||||
</div>
|
||||
<!-- 右侧图表展示栏结束 -->
|
||||
</div>
|
||||
</custom-modal>
|
||||
<!-- 分析弹窗结束 -->
|
||||
<!-- 数据监控状态弹窗结束 -->
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import CustomModal from '@/components/CustomModal/index.vue'
|
||||
import FilterImage from './filterImage'
|
||||
import CustomTree from '@/components/CustomTree/index.vue'
|
||||
import * as echarts from 'echarts'
|
||||
|
||||
// Filter中的筛选列表
|
||||
const filterList = [
|
||||
|
@ -277,6 +339,123 @@ const dataSource = [
|
|||
}
|
||||
]
|
||||
|
||||
var data = []
|
||||
var dataCount = 10
|
||||
var startTime = +new Date()
|
||||
var categories = ['categoryA', 'categoryB', 'categoryC']
|
||||
var types = [
|
||||
{ name: 'JS Heap', color: '#7b9ce1' },
|
||||
{ name: 'Documents', color: '#bd6d6c' },
|
||||
{ name: 'Nodes', color: '#75d874' },
|
||||
{ name: 'Listeners', color: '#e0bc78' },
|
||||
{ name: 'GPU Memory', color: '#dc77dc' },
|
||||
{ name: 'GPU', color: '#72b362' }
|
||||
]
|
||||
|
||||
// Generate mock data
|
||||
categories.forEach(function(category, index) {
|
||||
var baseTime = startTime
|
||||
for (var i = 0; i < dataCount; i++) {
|
||||
var typeItem = types[Math.round(Math.random() * (types.length - 1))]
|
||||
var duration = Math.round(Math.random() * 10000)
|
||||
data.push({
|
||||
name: typeItem.name,
|
||||
value: [index, baseTime, (baseTime += duration), duration],
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: typeItem.color
|
||||
}
|
||||
}
|
||||
})
|
||||
baseTime += Math.round(Math.random() * 2000)
|
||||
}
|
||||
})
|
||||
|
||||
function renderItem(params, api) {
|
||||
var categoryIndex = api.value(0)
|
||||
var start = api.coord([api.value(1), categoryIndex])
|
||||
var end = api.coord([api.value(2), categoryIndex])
|
||||
var height = api.size([0, 1])[1] * 0.6
|
||||
|
||||
var rectShape = echarts.graphic.clipRectByRect(
|
||||
{
|
||||
x: start[0],
|
||||
y: start[1] - height / 2,
|
||||
width: end[0] - start[0],
|
||||
height: height
|
||||
},
|
||||
{
|
||||
x: params.coordSys.x,
|
||||
y: params.coordSys.y,
|
||||
width: params.coordSys.width,
|
||||
height: params.coordSys.height
|
||||
}
|
||||
)
|
||||
|
||||
return (
|
||||
rectShape && {
|
||||
type: 'rect',
|
||||
transition: ['shape'],
|
||||
shape: rectShape,
|
||||
style: api.style()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const option = {
|
||||
tooltip: {
|
||||
formatter: function(params) {
|
||||
return params.marker + params.name + ': ' + params.value[3] + ' ms'
|
||||
}
|
||||
},
|
||||
title: {
|
||||
text: '2021-9-10 性能分析',
|
||||
left: 'center'
|
||||
},
|
||||
dataZoom: [
|
||||
{
|
||||
type: 'slider',
|
||||
filterMode: 'weakFilter',
|
||||
showDataShadow: false,
|
||||
top: 10,
|
||||
labelFormatter: ''
|
||||
},
|
||||
{
|
||||
type: 'inside',
|
||||
filterMode: 'weakFilter'
|
||||
}
|
||||
],
|
||||
grid: {
|
||||
height: 300
|
||||
},
|
||||
xAxis: {
|
||||
min: startTime,
|
||||
scale: true,
|
||||
axisLabel: {
|
||||
formatter: function(val) {
|
||||
return Math.max(0, val - startTime) + 'ms'
|
||||
}
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
data: categories
|
||||
},
|
||||
series: [
|
||||
{
|
||||
type: 'custom',
|
||||
renderItem: renderItem,
|
||||
itemStyle: {
|
||||
opacity: 0.8
|
||||
},
|
||||
encode: {
|
||||
x: [1, 2],
|
||||
y: 0
|
||||
},
|
||||
data: data
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
export default {
|
||||
props: {
|
||||
panMovePix: {
|
||||
|
@ -289,21 +468,28 @@ export default {
|
|||
}
|
||||
},
|
||||
components: {
|
||||
CustomModal
|
||||
CustomModal,
|
||||
CustomTree
|
||||
},
|
||||
data() {
|
||||
this.columns = columns
|
||||
return {
|
||||
active: 1,
|
||||
isFullScreen: false, // 是否处于全屏状态
|
||||
analyzeModalVisible: false, // 分析弹窗是否可见
|
||||
|
||||
checkedKeys: [], // 选中的树节点
|
||||
|
||||
filterList, // 筛选类型列表
|
||||
stateList, // 状态类型列表
|
||||
|
||||
dataSource: dataSource // Infomation Radius 表格数据源
|
||||
dataSource: dataSource, // Infomation Radius 表格数据源
|
||||
|
||||
dataStatusModalVisible: true, // 分析弹窗是否可见
|
||||
dataStatusCheckedKeys: [], // 分析弹窗-左侧树选中的
|
||||
|
||||
leftPaneShow: true, // 左侧抽屉
|
||||
|
||||
option // echarts配置
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
@ -326,51 +512,6 @@ export default {
|
|||
this.isFullScreen = false
|
||||
},
|
||||
|
||||
// Stations 树选中
|
||||
onTreeSelect(_, { node }) {
|
||||
const selectedKey = node.eventKey
|
||||
const parentKey = node.$parent.eventKey
|
||||
|
||||
const findIndex = this.checkedKeys.findIndex(key => key == selectedKey)
|
||||
|
||||
if (parentKey) {
|
||||
// 选中的是子级节点
|
||||
if (-1 == findIndex) {
|
||||
// 选中了
|
||||
this.checkedKeys.push(selectedKey)
|
||||
|
||||
const parentNode = this.treeData.find(tree => tree.key == parentKey) // 找到树列表中的父节点
|
||||
const childrenKeys = parentNode.children.map(child => child.key)
|
||||
if (childrenKeys.every(key => this.checkedKeys.includes(key))) {
|
||||
// 如果子列表每一个都能在选中的列表中找到,则是全选
|
||||
this.checkedKeys.push(parentKey)
|
||||
}
|
||||
} else {
|
||||
// 取消了
|
||||
this.checkedKeys.splice(findIndex, 1)
|
||||
|
||||
const findParent = this.checkedKeys.findIndex(key => key == parentKey)
|
||||
if (-1 !== findParent) {
|
||||
this.checkedKeys.splice(findParent, 1)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//选中的是父级节点
|
||||
const parentNode = this.treeData.find(tree => tree.key == selectedKey)
|
||||
const childrenKeys = parentNode.children.map(child => child.key)
|
||||
|
||||
const findParent = this.checkedKeys.findIndex(key => key == selectedKey)
|
||||
if (-1 == findParent) {
|
||||
// 未选中父节点,则将子节点都选中
|
||||
this.checkedKeys.push(selectedKey)
|
||||
this.checkedKeys.push(...childrenKeys)
|
||||
} else {
|
||||
// 已经选中了父节点,则将子节点都取消选中
|
||||
this.checkedKeys = this.checkedKeys.filter(key => key !== selectedKey && !childrenKeys.includes(key))
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 选中全部
|
||||
handleSelectAll() {
|
||||
this.checkedKeys = this.treeData.reduce((prev, curr) => {
|
||||
|
@ -387,7 +528,7 @@ export default {
|
|||
|
||||
// 打开分析弹窗
|
||||
handleOpenAnalyzeModal() {
|
||||
this.analyzeModalVisible = true
|
||||
this.dataStatusModalVisible = true
|
||||
},
|
||||
|
||||
// 地图放大
|
||||
|
@ -423,6 +564,7 @@ export default {
|
|||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
// 地图右侧操作栏
|
||||
.map-pane {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
|
@ -656,4 +798,141 @@ export default {
|
|||
}
|
||||
}
|
||||
}
|
||||
// 地图右侧操作栏结束
|
||||
|
||||
// 弹窗
|
||||
.data-receive-status {
|
||||
height: 700px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
@borderColor: rgba(65, 111, 127, 0.5);
|
||||
&-list {
|
||||
float: left;
|
||||
width: 230px;
|
||||
height: 100%;
|
||||
margin-left: 15px;
|
||||
transform: translateX(-245px);
|
||||
transition: transform 0.3s cubic-bezier(0.075, 0.82, 0.165, 1);
|
||||
|
||||
&.open {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
&-container {
|
||||
height: 100%;
|
||||
border: 1px solid @borderColor;
|
||||
border-top: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
&-item {
|
||||
&:first-child {
|
||||
height: calc(100% - 305px);
|
||||
.content {
|
||||
height: calc(100% - 50px);
|
||||
overflow: auto;
|
||||
margin: 7px;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&:nth-child(2) {
|
||||
.content {
|
||||
padding-left: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
height: 37px;
|
||||
line-height: 37px;
|
||||
padding-left: 18px;
|
||||
background-color: #08363c;
|
||||
border-top: 1px solid @borderColor;
|
||||
border-bottom: 1px solid @borderColor;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding-right: 10px;
|
||||
user-select: none;
|
||||
img {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-toggle-show-btn {
|
||||
position: absolute;
|
||||
right: -13px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.attribute-form {
|
||||
.ant-input-number {
|
||||
width: 173px;
|
||||
height: 24px;
|
||||
::v-deep {
|
||||
.ant-input-number-input {
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep {
|
||||
.ant-form-item {
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
|
||||
&-label {
|
||||
padding-top: 7px;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
&-children {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
> span {
|
||||
margin-left: 7px;
|
||||
color: #5b9cba;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-footer {
|
||||
margin-top: 9px;
|
||||
text-align: center;
|
||||
.ant-btn {
|
||||
width: 120px;
|
||||
background-color: #00bded;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-chart {
|
||||
position: absolute;
|
||||
right: 15px;
|
||||
width: calc(100% - 270px);
|
||||
height: 100%;
|
||||
border: 1px solid @borderColor;
|
||||
transition: width 0.3s cubic-bezier(0.075, 0.82, 0.165, 1);
|
||||
|
||||
&.on-screen {
|
||||
width: calc(100% - 30px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fullscreen {
|
||||
.data-receive-status {
|
||||
height: calc(100vh - 70px);
|
||||
}
|
||||
}
|
||||
// 弹窗结束
|
||||
</style>
|
||||
|
|
|
@ -22,30 +22,64 @@
|
|||
|
||||
<!-- 头部操作栏 -->
|
||||
<div class="title-operator">
|
||||
<a-popover v-model="searchVisible" trigger="click" placement="bottom">
|
||||
<div @click.stop="searchVisible = !searchVisible">
|
||||
<img src="@/assets/images/station-operation/search.png" alt="" />
|
||||
</div>
|
||||
<template slot="content">
|
||||
<a-input-search placeholder="input search text" @search="onSearch">
|
||||
<img slot="enterButton" src="@/assets/images/station-operation/search.png" alt="" />
|
||||
</a-input-search>
|
||||
</template>
|
||||
</a-popover>
|
||||
<a-popover trigger="click" placement="bottom">
|
||||
<div @click.stop>
|
||||
<img src="@/assets/images/station-operation/filter.png" alt="" />
|
||||
</div>
|
||||
<template slot="content">
|
||||
<div>筛选</div>
|
||||
</template>
|
||||
</a-popover>
|
||||
<div @click.stop="handleShowSearch">
|
||||
<img src="@/assets/images/station-operation/search.png" alt="" />
|
||||
</div>
|
||||
<div @click.stop="handleShowFilter">
|
||||
<img src="@/assets/images/station-operation/filter.png" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- 头部操作栏结束 -->
|
||||
</div>
|
||||
</template>
|
||||
<ScrollContainer direction="verticle" class="date-list">
|
||||
<div class="date-list-content">
|
||||
<ScrollContainer
|
||||
ref="scrollContainerRef"
|
||||
direction="verticle"
|
||||
:scrollContainer="getScrollContainer"
|
||||
class="date-list has-search"
|
||||
:class="{
|
||||
'show-search': searchPlacementVisible
|
||||
}"
|
||||
>
|
||||
<div class="search-filter-placement">
|
||||
<!-- 搜索 -->
|
||||
<a-input-search
|
||||
v-if="searchVisible"
|
||||
placeholder="Input Search Text"
|
||||
v-model="filter.searchText"
|
||||
allow-clear
|
||||
@search="onFilterChange"
|
||||
>
|
||||
<img slot="enterButton" src="@/assets/images/station-operation/search.png" alt="" />
|
||||
</a-input-search>
|
||||
<!-- 搜索结束 -->
|
||||
|
||||
<!-- 筛选 -->
|
||||
<a-row v-if="filterVisible" :gutter="10" style="width: 100%">
|
||||
<a-col :span="12">
|
||||
<j-dict-select-tag
|
||||
v-model="filter.status"
|
||||
:getPopupContainer="getDictSelectTagContainer"
|
||||
placeholder="Select Status"
|
||||
dictCode="STATION_STATUS"
|
||||
style="width: 100%"
|
||||
@change="onFilterChange"
|
||||
></j-dict-select-tag>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<custom-select
|
||||
v-model="filter.type"
|
||||
:options="stationTypeList"
|
||||
allow-clear
|
||||
show-search
|
||||
@change="onFilterChange"
|
||||
placeholder="Select Type"
|
||||
></custom-select>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<!-- 筛选结束 -->
|
||||
</div>
|
||||
<div ref="customScrollContainerRef" class="date-list-content">
|
||||
<a-spin v-if="isGettingDateList"></a-spin>
|
||||
<template v-else>
|
||||
<div class="date-list-item" v-for="item of dateList" :key="item.id">
|
||||
|
@ -168,6 +202,7 @@ import MapMarker from './components/MapMarker.vue'
|
|||
import MapPane from './components/MapPane.vue'
|
||||
import ScrollContainer from '@/components/ScrollContainer/index.vue'
|
||||
import { getAction } from '../../api/manage'
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
@ -179,13 +214,28 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
activeKey: '1',
|
||||
|
||||
isGettingDateList: false,
|
||||
dateList: [],
|
||||
searchVisible: false
|
||||
|
||||
searchPlacementVisible: false, // 搜索栏占位是否显示
|
||||
|
||||
searchVisible: false, // 搜索组件是否显示
|
||||
|
||||
filter: {
|
||||
searchText: undefined,
|
||||
status: undefined,
|
||||
type: undefined
|
||||
},
|
||||
|
||||
filterVisible: false, // 筛选组件是否显示
|
||||
|
||||
stationTypeList: []
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getStationList()
|
||||
this.getStationTypeList()
|
||||
},
|
||||
methods: {
|
||||
// 获取站点列表
|
||||
|
@ -197,6 +247,7 @@ export default {
|
|||
result: { records }
|
||||
} = await getAction('/gardsStations/findPage?pageIndex=1&pageSize=999')
|
||||
if (success) {
|
||||
this.originalDateList = cloneDeep(records)
|
||||
this.dateList = records
|
||||
}
|
||||
} catch (error) {
|
||||
|
@ -206,13 +257,67 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
// 左侧 All Date 查询
|
||||
onSearch() {
|
||||
this.searchVisible = false
|
||||
// 获取站点类型
|
||||
async getStationTypeList() {
|
||||
try {
|
||||
const res = await getAction('/gardsStations/findType')
|
||||
this.stationTypeList = res.filter(item => item).map(item => ({ label: item, value: item }))
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
},
|
||||
|
||||
handleShowSearch() {
|
||||
if (this.filterVisible) {
|
||||
this.searchVisible = true
|
||||
this.filterVisible = false
|
||||
this.searchPlacementVisible = true
|
||||
} else {
|
||||
this.searchPlacementVisible = !this.searchPlacementVisible
|
||||
if (this.searchPlacementVisible) {
|
||||
this.searchVisible = true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 显示筛选栏
|
||||
handleShowFilter() {
|
||||
if (this.searchVisible) {
|
||||
this.searchVisible = false
|
||||
this.filterVisible = true
|
||||
this.searchPlacementVisible = true
|
||||
} else {
|
||||
this.searchPlacementVisible = !this.searchPlacementVisible
|
||||
if (this.searchPlacementVisible) {
|
||||
this.filterVisible = true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 左侧 All Date 筛选
|
||||
onFilter() {}
|
||||
onFilterChange() {
|
||||
this.dateList = this.originalDateList.filter(dateItem => {
|
||||
const filterSearchText =
|
||||
!this.filter.searchText ||
|
||||
-1 !== dateItem.stationCode.toLowerCase().indexOf(this.filter.searchText.toLowerCase())
|
||||
const filterStatus = !this.filter.status || this.filter.status == dateItem.status
|
||||
const filterType = !this.filter.type || this.filter.type == dateItem.type
|
||||
|
||||
return filterSearchText && filterStatus && filterType
|
||||
})
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.$refs.scrollContainerRef.checkScrollEnd()
|
||||
})
|
||||
},
|
||||
|
||||
getScrollContainer() {
|
||||
return this.$refs.customScrollContainerRef
|
||||
},
|
||||
|
||||
getDictSelectTagContainer() {
|
||||
return document.body
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -248,6 +353,8 @@ export default {
|
|||
border-top: 1px solid rgba(12, 235, 201, 0.3);
|
||||
border-bottom: 4px solid rgba(12, 235, 201, 0.2);
|
||||
height: auto;
|
||||
background-color: rgba(1, 18, 20, 0.6);
|
||||
|
||||
.ant-collapse-arrow {
|
||||
right: 9px;
|
||||
transition: transform 0.24s;
|
||||
|
@ -281,7 +388,6 @@ export default {
|
|||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #0cebc9;
|
||||
background-color: rgba(1, 18, 20, 0.6);
|
||||
|
||||
&-text {
|
||||
padding-left: 20px;
|
||||
|
@ -356,6 +462,15 @@ export default {
|
|||
padding: 2px 0 10px 7px;
|
||||
overflow: auto;
|
||||
|
||||
@searchHeight: 45px;
|
||||
.search-filter-placement {
|
||||
height: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
transition: height 0.3s ease-in-out;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
&-content {
|
||||
.ant-spin {
|
||||
width: 100%;
|
||||
|
@ -365,6 +480,24 @@ export default {
|
|||
}
|
||||
}
|
||||
|
||||
&.has-search {
|
||||
.date-list-content {
|
||||
transition: height 0.3s ease-in-out;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
|
||||
&.show-search {
|
||||
.search-filter-placement {
|
||||
height: @searchHeight;
|
||||
}
|
||||
|
||||
.date-list-content {
|
||||
height: calc(100% - @searchHeight);
|
||||
}
|
||||
}
|
||||
|
||||
&-item {
|
||||
width: 322px;
|
||||
&-title {
|
||||
|
|
Loading…
Reference in New Issue
Block a user