[update] add chart series
This commit is contained in:
@@ -22,6 +22,7 @@ module.exports = {
|
||||
],
|
||||
|
||||
rules: {
|
||||
'@typescript-eslint/no-empty-interface': 0,
|
||||
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
|
||||
'prettier/prettier': ['warn', {}, { usePrettierrc: true }],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<va-card class="h-200px overflow-auto">
|
||||
<va-card>
|
||||
<va-card-content>
|
||||
<va-button @click="showModal">FILE</va-button>
|
||||
<p>X: {{ channelStore.xAxisSelected.name }} Y: {{ channelStore.yAxisSelected.name }}</p>
|
||||
@@ -18,7 +18,7 @@
|
||||
</template>
|
||||
</va-list>
|
||||
<Suspense>
|
||||
<FileModal ref="file_modal_ref"></FileModal>
|
||||
<FileView ref="file_modal_ref"></FileView>
|
||||
</Suspense>
|
||||
</va-card-content>
|
||||
</va-card>
|
||||
@@ -28,14 +28,14 @@
|
||||
import { ref, reactive } from 'vue'
|
||||
import { useChannelStore } from '@/stores/data-analysis/channel'
|
||||
import { useFileViewStore } from '@/stores/data-analysis/file-view'
|
||||
import FileModal from '@/components/data-analysis/FileModal.vue'
|
||||
import FileView from '@/components/data-analysis/FileView.vue'
|
||||
|
||||
const channelStore = useChannelStore()
|
||||
const fileViewStore = useFileViewStore()
|
||||
const selectedFiles = reactive(fileViewStore.filesSelected)
|
||||
|
||||
/* File Modal Handling */
|
||||
let file_modal_ref = ref<InstanceType<typeof FileModal> | null>(null)
|
||||
let file_modal_ref = ref<InstanceType<typeof FileView> | null>(null)
|
||||
const showModal = function () {
|
||||
file_modal_ref.value?.showModal()
|
||||
}
|
||||
|
||||
+41
-30
@@ -2,8 +2,6 @@
|
||||
<slideout v-model="showSlideOut" title="The title" :size="'120%'" dock="left" resizable>
|
||||
<ChannelSelector></ChannelSelector>
|
||||
<div class="pa-1 d-flex align-center">
|
||||
<!-- <va-input v-model="filter" placeholder="Filter..." class="mr-3" style="flex: 0 200px" clearable />
|
||||
<va-checkbox v-model="isFilterCaseSensitive" class="mr-3" label="Case sensitive" /> -->
|
||||
<va-button-group class="mr-1">
|
||||
<va-button @click="changeViewFormat(0)">Table</va-button>
|
||||
<va-button disabled @click="changeViewFormat(1)">Tree</va-button>
|
||||
@@ -21,24 +19,34 @@
|
||||
<!-- <div v-if="loading">Loading...</div> -->
|
||||
<va-inner-loading :loading="loading">
|
||||
<div>
|
||||
<TableFormat v-if="viewFormat === 0" ref="table_format_ref" :columns="columns" :rows="rows"></TableFormat>
|
||||
<TableFormat
|
||||
v-if="viewFormat === 0"
|
||||
ref="table_format_ref"
|
||||
:columns="columns"
|
||||
:rows="rows"
|
||||
@on-select="onSelect"
|
||||
></TableFormat>
|
||||
<TreeFormat v-if="viewFormat === 1" ref="table_format_ref" :columns="columns" :rows="rows"></TreeFormat>
|
||||
</div>
|
||||
</va-inner-loading>
|
||||
</slideout>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive } from 'vue'
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { useFileViewStore } from '@/stores/data-analysis/file-view'
|
||||
import { useChannelStore } from '@/stores/data-analysis/channel'
|
||||
import { MetaFile } from '@/utils/file'
|
||||
import TableFormat from './TableFormat.vue'
|
||||
import TreeFormat from './TreeFormat.vue'
|
||||
import ChannelSelector from './ChannelSelector.vue'
|
||||
import configTable from '@/data/config-table'
|
||||
|
||||
const table_format_ref = ref<InstanceType<typeof TableFormat> | null>(null)
|
||||
|
||||
const fileViewStore = useFileViewStore()
|
||||
const channelStore = useChannelStore()
|
||||
const fileView = reactive(fileViewStore.fileView)
|
||||
const table_format_ref = ref<InstanceType<typeof TableFormat> | null>(null)
|
||||
const rows: any = fileView.children
|
||||
fileView.appendChildren()
|
||||
const columns = reactive([
|
||||
{
|
||||
label: 'Name',
|
||||
@@ -60,32 +68,10 @@
|
||||
const showSlideOut = ref(false)
|
||||
const showModal = function () {
|
||||
showSlideOut.value = !showSlideOut.value
|
||||
// initLoad()
|
||||
console.log('fileView', fileView.getChildren())
|
||||
console.log('rows', rows)
|
||||
|
||||
setTimeout(() => {
|
||||
loading.value = false
|
||||
}, 1500)
|
||||
}
|
||||
|
||||
const initLoad = async function () {
|
||||
// rows.length = 0
|
||||
// rows.push(...fileView.getChildren())
|
||||
// if (rows.length < fileView.children.length) {
|
||||
// rows.push(...fileView.children.slice(rows.length, fileView.children.length - 1))
|
||||
// }
|
||||
// for (const index in rows) {
|
||||
// console.log(index, rows[index].children.length, fileView.children[index].children.length)
|
||||
// if (rows[index].children.length < fileView.children[index].children.length) {
|
||||
// rows[index].children.push(
|
||||
// ...fileView.children[index].children.slice(
|
||||
// rows[index].children.length,
|
||||
// fileView.children[index].children.length - 1,
|
||||
// ),
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
}, 500)
|
||||
}
|
||||
|
||||
const viewFormat = ref(0)
|
||||
@@ -96,7 +82,6 @@
|
||||
const changeFileView = async function (view: string) {
|
||||
fileView.changeView(view)
|
||||
await fileView.appendChildren(1)
|
||||
// initLoad()
|
||||
}
|
||||
|
||||
const expandAll = function (expandOrNot: boolean) {
|
||||
@@ -104,6 +89,32 @@
|
||||
if (expandOrNot === false) table_format_ref.value?.collapseAll()
|
||||
}
|
||||
|
||||
const onSelect = function (selectedFile: MetaFile[]) {
|
||||
fileViewStore.filesSelected.length = 0
|
||||
fileViewStore.filesSelected.push(...selectedFile)
|
||||
|
||||
if (fileViewStore.filesSelected.length > 0) {
|
||||
// TODO get all selected library
|
||||
const config: any = configTable.getModeConfig(
|
||||
fileViewStore.filesSelected[0].device.library_name,
|
||||
fileViewStore.filesSelected[0].parameter.MODE,
|
||||
)
|
||||
const channel = Object.values(config.channels)
|
||||
const channelOptions = channel.map((v: any, idx) => {
|
||||
v.id = idx
|
||||
return v
|
||||
})
|
||||
channelStore.xAxisOptions.length = 0
|
||||
channelStore.xAxisOptions.push(...channelOptions)
|
||||
channelStore.yAxisOptions.length = 0
|
||||
channelStore.yAxisOptions.push(...channelOptions)
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fileView.appendChildren()
|
||||
})
|
||||
|
||||
defineExpose({
|
||||
showModal,
|
||||
})
|
||||
@@ -2,18 +2,27 @@
|
||||
<div>
|
||||
<va-card class="h-full">
|
||||
<va-card-content class="h-full w-full">
|
||||
<EChart ref="chart_ref" :option="option" :autoresize="true" :loading="loading" />
|
||||
<EChart ref="chart_ref" :option="chart" :autoresize="true" :loading="loading" />
|
||||
</va-card-content>
|
||||
</va-card>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import LineChart from '@/data/echart/composables/LineChart'
|
||||
import { EChartsCoreOption } from 'echarts'
|
||||
import { ref } from 'vue'
|
||||
import { ECharts, EChartsCoreOption } from 'echarts'
|
||||
import { ref, reactive, watch } from 'vue'
|
||||
import { useFileViewStore } from '@/stores/data-analysis/file-view'
|
||||
import { MetaFile } from '@/utils/file'
|
||||
|
||||
const loading = ref(false)
|
||||
const { chart_ref, option } = LineChart()
|
||||
const props = defineProps({
|
||||
chart: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {}
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const chart_ref = ref<ECharts | null>(null)
|
||||
|
||||
const setOption = function (option: EChartsCoreOption) {
|
||||
chart_ref.value?.setOption(option)
|
||||
@@ -44,14 +53,37 @@
|
||||
})
|
||||
}
|
||||
|
||||
// Loading
|
||||
const loading = ref(false)
|
||||
const startLoading = function () {
|
||||
loading.value = true
|
||||
}
|
||||
|
||||
const stopLoading = function () {
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
// change when file selected
|
||||
const fileViewStore = useFileViewStore()
|
||||
const fileSelected = reactive(fileViewStore.filesSelected)
|
||||
const selectionSave: never | MetaFile[] = reactive([])
|
||||
|
||||
watch(
|
||||
fileSelected,
|
||||
(data) => {
|
||||
const unSelectFiles = selectionSave.filter((ele) => data.findIndex((ele2) => ele.id === ele2.id) === -1)
|
||||
for (const meta of unSelectFiles) {
|
||||
props.chart.seriesManager.delSeries({ id: meta.id, name: meta.name })
|
||||
}
|
||||
selectionSave.length = 0
|
||||
selectionSave.push(...data)
|
||||
for (const meta of data) {
|
||||
props.chart.seriesManager.addSeries({ id: meta.id, name: meta.name })
|
||||
}
|
||||
chart_ref.value?.setOption(props.chart, true)
|
||||
},
|
||||
{ deep: true },
|
||||
)
|
||||
|
||||
defineExpose({
|
||||
startLoading,
|
||||
stopLoading,
|
||||
|
||||
@@ -10,17 +10,19 @@
|
||||
collapsable: true,
|
||||
rowKey: 'id',
|
||||
}"
|
||||
@selected-rows-change="selectionChanged"
|
||||
@selected-rows-change="select"
|
||||
>
|
||||
</VueGoodTable>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, watch, watchEffect, toRef } from 'vue'
|
||||
import { useFileViewStore } from '@/stores/data-analysis/file-view'
|
||||
import { useChannelStore } from '@/stores/data-analysis/channel'
|
||||
import configTable from '@/data/config-table/index'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { MetaFile } from '@/utils/file'
|
||||
|
||||
const props = defineProps({
|
||||
// emit
|
||||
const emit = defineEmits(['onSelect'])
|
||||
|
||||
// props
|
||||
defineProps({
|
||||
columns: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
@@ -35,10 +37,8 @@
|
||||
},
|
||||
})
|
||||
|
||||
const fileViewStore = useFileViewStore()
|
||||
const channelStore = useChannelStore()
|
||||
// ref
|
||||
const vue_good_table_refs = ref()
|
||||
// const vue_good_table_refs = ref<InstanceType<typeof VueGoodTable> | null>(null)
|
||||
|
||||
const expandAll = function () {
|
||||
vue_good_table_refs.value.expandAll()
|
||||
@@ -46,37 +46,19 @@
|
||||
const collapseAll = function () {
|
||||
vue_good_table_refs.value.collapseAll()
|
||||
}
|
||||
const selectionChanged = function (params: any) {
|
||||
fileViewStore.filesSelected.length = 0
|
||||
fileViewStore.filesSelected.push(...params.selectedRows)
|
||||
|
||||
if (fileViewStore.filesSelected.length > 0) {
|
||||
const config: any = configTable.getModeConfig(
|
||||
fileViewStore.filesSelected[0].device.library_name,
|
||||
fileViewStore.filesSelected[0].parameter.MODE,
|
||||
)
|
||||
const channel = Object.values(config.channels)
|
||||
const channelOptions = channel.map((v: any, idx) => {
|
||||
v.id = idx
|
||||
return v
|
||||
})
|
||||
channelStore.xAxisOptions.length = 0
|
||||
channelStore.xAxisOptions.push(...channelOptions)
|
||||
channelStore.yAxisOptions.length = 0
|
||||
channelStore.yAxisOptions.push(...channelOptions)
|
||||
}
|
||||
console.log('vue_good_table_refs.value', vue_good_table_refs.value)
|
||||
const select = function (params: { selectedRows: MetaFile[] }) {
|
||||
emit('onSelect', params.selectedRows)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// Due to "vue_good_table" package error, need to fix group select by reassign function
|
||||
vue_good_table_refs.value.toggleSelectGroup = function (event: { checked: any }, headerRow: { children: any[] }) {
|
||||
console.log(event, headerRow)
|
||||
headerRow.children.forEach((row: { [x: string]: any }) => {
|
||||
row['vgtSelected'] = event.checked
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
defineExpose({ selectionChanged, expandAll, collapseAll })
|
||||
defineExpose({ expandAll, collapseAll })
|
||||
</script>
|
||||
<style></style>
|
||||
|
||||
@@ -2,13 +2,15 @@
|
||||
<div class="h-[88vh] grid grid-cols-3 gap-6">
|
||||
<div class="h-full col-span-1">
|
||||
<div class="h-1/3">
|
||||
<FileContainer class="h-9/10"></FileContainer>
|
||||
<FileContainer class="h-225px overflow-auto"></FileContainer>
|
||||
</div>
|
||||
<div class="h-2/3">
|
||||
<ControlPanel class="h-9/10" @filter-data="filterData"></ControlPanel>
|
||||
<ControlPanel class="h-[100%]" @filter-data="filterData"></ControlPanel>
|
||||
</div>
|
||||
</div>
|
||||
<LineChartContainer ref="linechart_ref" class="h-[50%] col-span-2"></LineChartContainer>
|
||||
<template v-for="chart in chartManager.children" :key="chart.id">
|
||||
<LineChartContainer ref="linechart_ref" :chart="chart" class="h-[100%] col-span-2"></LineChartContainer>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -17,7 +19,11 @@
|
||||
import FileContainer from '@/components/data-analysis/FileContainer.vue'
|
||||
import ControlPanel from '@/components/data-analysis/ControlPanel.vue'
|
||||
import LineChartContainer from '@/components/data-analysis/LineChartContainer.vue'
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { useChartStore } from '@/stores/data-analysis/chart'
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
|
||||
// reference
|
||||
const linechart_ref = ref()
|
||||
|
||||
// mqtt init
|
||||
const { startMqtt, publish } = useMqtt()
|
||||
@@ -25,9 +31,48 @@
|
||||
|
||||
// define subscribe and callback
|
||||
startMqtt(`${controllerID}/data_analysis/#`, (topic: string, message: ArrayBuffer) => {
|
||||
// [data, data, ceiling, ground]
|
||||
// [metaID, xData, yData, horizontalLine, twoPointLine]
|
||||
const msg = JSON.parse(message.toString())
|
||||
console.log('msg', msg)
|
||||
|
||||
// reformat data
|
||||
for (const info of msg) {
|
||||
const metaID = info[0]
|
||||
const xData = info[1]
|
||||
const yData = info[2]
|
||||
const horizontal = info[3]
|
||||
const line = info[4]
|
||||
const groupData = []
|
||||
for (let i = 0; i < xData.length; i++) {
|
||||
groupData.push([xData[i], yData[i]])
|
||||
}
|
||||
|
||||
for (const chart of chartManager.children) {
|
||||
const seriesIndex = chart.seriesManager.findSeries({ id: metaID })
|
||||
// append Data
|
||||
if (seriesIndex !== -1) {
|
||||
linechart_ref.value[0]?.appendData(seriesIndex, groupData)
|
||||
}
|
||||
// draw line
|
||||
let yAxis_list = horizontal.map((x: any) => ({ yAxis: x }))
|
||||
let coord_list = [{ coord: [line[0][0], line[0][1]] }, { coord: [line[1][0], line[1][1]] }]
|
||||
yAxis_list.push(coord_list)
|
||||
linechart_ref.value[0].setOption({
|
||||
series: [
|
||||
{
|
||||
markLine: {
|
||||
data: yAxis_list,
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// stop loading
|
||||
linechart_ref.value[0]?.stopLoading()
|
||||
|
||||
// download file
|
||||
const name = 'test'
|
||||
const url = `http://192.168.2.1:3000/api/analysis/get/csv?name=${name}`
|
||||
const a = document.createElement('a')
|
||||
@@ -36,52 +81,21 @@
|
||||
document.body.appendChild(a)
|
||||
a.click()
|
||||
document.body.removeChild(a)
|
||||
|
||||
// try draw line
|
||||
// msg.push(1500000, -1500000)
|
||||
|
||||
// reformat data
|
||||
const _msg = []
|
||||
for (let i = 0; i < msg[0].length; i++) {
|
||||
_msg.push([msg[0][i], msg[1][i]])
|
||||
}
|
||||
|
||||
// append Data
|
||||
linechart_ref.value?.appendData(0, _msg)
|
||||
|
||||
// stop loading
|
||||
linechart_ref.value?.stopLoading()
|
||||
|
||||
// draw line
|
||||
// draw line
|
||||
if (msg.length < 3) return true
|
||||
let yAxis_list = msg[2].map((x: any) => ({ yAxis: x }))
|
||||
let coord_list = [{ coord: [msg[3][0][0], msg[3][0][1]] }, { coord: [msg[3][1][0], msg[3][1][1]] }]
|
||||
// yAxis_list.append([{ coord:[ msg[3][0][0],msg[3][0][1]]},{ coord:[ msg[3][1][0], msg[3][1][1]]}])
|
||||
yAxis_list.push(coord_list)
|
||||
console.log('yAxis_list', yAxis_list)
|
||||
linechart_ref.value.setOption({
|
||||
series: [
|
||||
{
|
||||
markLine: {
|
||||
data: yAxis_list,
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
// reference
|
||||
const linechart_ref = ref()
|
||||
|
||||
// ControlPanel handling
|
||||
const filterData = function (e: any) {
|
||||
linechart_ref.value?.startLoading()
|
||||
console.log(linechart_ref)
|
||||
console.log(e)
|
||||
linechart_ref.value[0]?.startLoading()
|
||||
publish(`${controllerID}_data_analysis/get_analysis_data`, JSON.stringify({ e }))
|
||||
}
|
||||
|
||||
const chartStore = useChartStore()
|
||||
const chartManager = reactive(chartStore.chart)
|
||||
onMounted(() => {
|
||||
if (chartManager.children.length === 0) {
|
||||
chartManager.addChart()
|
||||
}
|
||||
})
|
||||
defineExpose({ linechart_ref, filterData })
|
||||
</script>
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import ChartManager from '@/utils/chart/chartManager'
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
export const useChartStore = defineStore('data-analysis-chart', {
|
||||
state: () => ({
|
||||
chart: new ChartManager(),
|
||||
}),
|
||||
// could also be defined as
|
||||
// state: () => ({ count: 0 })
|
||||
getters: {},
|
||||
actions: {},
|
||||
})
|
||||
|
||||
@@ -10,7 +10,10 @@ class Series {
|
||||
this.data = []
|
||||
this.silent = false
|
||||
this.animation = false
|
||||
this.markLine = {}
|
||||
this.markLine = {
|
||||
symbol: ['none', 'none'],
|
||||
data: [],
|
||||
}
|
||||
}
|
||||
|
||||
setOption(options: seriesOption) {
|
||||
|
||||
@@ -8,8 +8,10 @@ class SeriesManager {
|
||||
}
|
||||
|
||||
addSeries(option: seriesOption) {
|
||||
const newSeries = new Series(option)
|
||||
this.children.push(newSeries)
|
||||
if (this.findSeries(option) === -1) {
|
||||
const newSeries = new Series(option)
|
||||
this.children.push(newSeries)
|
||||
}
|
||||
}
|
||||
|
||||
getSeries(target: seriesTarget): Series | Series[] {
|
||||
@@ -39,7 +41,7 @@ class SeriesManager {
|
||||
|
||||
delSeries(target: seriesTarget) {
|
||||
const deleteIdx = this.findSeries(target)
|
||||
if (deleteIdx) {
|
||||
if (deleteIdx !== undefined) {
|
||||
this.children.splice(deleteIdx, 1)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -13,21 +13,21 @@ class Chart {
|
||||
legend: any
|
||||
// tooltip: any
|
||||
// grid: any
|
||||
// dataZoom: any
|
||||
dataZoom: any
|
||||
seriesManager: SeriesManager
|
||||
series: any
|
||||
// gridManager: GridManager
|
||||
constructor() {
|
||||
this.title = { text: 'Gradient along the y axis' }
|
||||
// this.title = { text: 'Gradient along the y axis' }
|
||||
this.seriesManager = new SeriesManager()
|
||||
// this.gridManager = new GridManager()
|
||||
this.legend = {}
|
||||
this.legend = { type: 'scroll' }
|
||||
// this.tooltip = new Tooltip()
|
||||
this.xAxis = {}
|
||||
this.yAxis = {}
|
||||
this.xAxis = { scale: true }
|
||||
this.yAxis = { scale: true }
|
||||
// this.grid = this.gridManager.getGrid()
|
||||
this.series = this.seriesManager.getSeries({})
|
||||
// this.dataZoom = [{}]
|
||||
this.dataZoom = [{ type: 'inside' }, { type: 'slider' }]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import Chart from './chart'
|
||||
|
||||
class ChartManager {
|
||||
children: Chart[]
|
||||
constructor() {
|
||||
this.children = []
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
addChart(idx?: number) {
|
||||
const newChart = new Chart()
|
||||
this.children.push(newChart)
|
||||
}
|
||||
switchChart() {
|
||||
return
|
||||
}
|
||||
clearChart() {
|
||||
return
|
||||
}
|
||||
delChart() {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
export default ChartManager
|
||||
Reference in New Issue
Block a user