Commit 76268767 authored by ninglx's avatar ninglx

wj-smartcity 快照周期转向导出接口联调

parent 9474a287
...@@ -79,6 +79,21 @@ export const exportLane = (data) => request({ ...@@ -79,6 +79,21 @@ export const exportLane = (data) => request({
responseType: "blob", responseType: "blob",
}) })
// 周期 转向 导出
export const exportTurn = (data) => request({
url:`${baseUrl}/trend/periodTurnExcel`,
method: 'post',
data: data,
responseType: "blob",
})
export const exportSnapshot = (data) => request({
url:`${baseUrl}/trend/laneSnapshotExcel`,
method: 'post',
data: data,
responseType: "blob",
})
// 数据查询 车道快照指标 // 数据查询 车道快照指标
export const getLaneSnapshotIndex = (data) => request({ export const getLaneSnapshotIndex = (data) => request({
url:`${baseUrl}/trend/laneSnapshotIndex`, url:`${baseUrl}/trend/laneSnapshotIndex`,
......
<template> <template>
<div class="full-w-h cycleDataContainer"> <div class="full-w-h cycleDataContainer">
<div style="margin-bottom: 10px;margin-top: 10px" class="custom-form"> <div style="margin-bottom: 10px; margin-top: 10px" class="custom-form">
<label class="custom-form-label">时段选择: </label> <label class="custom-form-label">时段选择: </label>
<el-date-picker <el-date-picker
:clearable="false" :clearable="false"
...@@ -9,28 +9,43 @@ ...@@ -9,28 +9,43 @@
type="datetimerange" type="datetimerange"
range-separator="至" range-separator="至"
start-placeholder="开始日期" start-placeholder="开始日期"
end-placeholder="结束日期"> end-placeholder="结束日期"
>
</el-date-picker> </el-date-picker>
<label class="custom-form-label">位置: </label> <label class="custom-form-label">位置: </label>
<el-select @change="getData" style="margin-right: 10px" v-model="locationType1" <el-select
placeholder="请选择"> @change="getData"
style="margin-right: 10px"
v-model="locationType1"
placeholder="请选择"
>
<el-option <el-option
v-for="item in locationOptions1" v-for="item in locationOptions1"
:key="item.value" :key="item.value"
:label="item.label" :label="item.label"
:value="item.value"> :value="item.value"
>
</el-option> </el-option>
</el-select> </el-select>
<el-select style="margin-right: 10px" multiple collapse-tags @change="filterTable1" v-model="value1" <el-select
placeholder="请选择"> style="margin-right: 10px"
multiple
collapse-tags
@change="filterTable1"
v-model="value1"
placeholder="请选择"
>
<el-option <el-option
v-for="item in options1" v-for="item in options1"
:key="item" :key="item"
:label="item" :label="item"
:value="item"> :value="item"
>
</el-option> </el-option>
</el-select> </el-select>
<div>(备注:{{ locationType1 === 'laneSort' ? '车道' : '转向' }}可多选)</div> <div>
(备注:{{ locationType1 === "laneSort" ? "车道" : "转向" }}可多选)
</div>
<div class="rightExport" @click="exportLaneExcel()">导出</div> <div class="rightExport" @click="exportLaneExcel()">导出</div>
</div> </div>
<div style="margin-bottom: 10px" class="custom-table"> <div style="margin-bottom: 10px" class="custom-table">
...@@ -46,70 +61,81 @@ ...@@ -46,70 +61,81 @@
:data="listDataCopy" :data="listDataCopy"
:row-class-name="getRowClassName" :row-class-name="getRowClassName"
style="width: 100%" style="width: 100%"
height="100%"> height="100%"
>
<el-table-column <el-table-column
v-for="(it,index) of laneTableColumn" v-for="(it, index) of laneTableColumn"
:key="index" :key="index"
:fixed="index===0" :fixed="index === 0"
align="center" align="center"
:width="index===0?'150':'auto'" :width="index === 0 ? '150' : 'auto'"
:prop="it.prop" :prop="it.prop"
:label="it.label" show-overflow-tooltip> :label="it.label"
show-overflow-tooltip
>
<template slot-scope="scope"> <template slot-scope="scope">
{{ occupancyValue(scope.row[it.prop]) }} {{ occupancyValue(scope.row[it.prop]) }}
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
</div> </div>
<div class="chartContainer"> <div class="chartContainer">
<v-chart v-loading="loading" <v-chart
v-loading="loading"
element-loading-text="数据加载中..." element-loading-text="数据加载中..."
element-loading-spinner="el-icon-loading" element-loading-spinner="el-icon-loading"
element-loading-background="rgba(0, 0, 0, 0.4)" :option="option" autoresize> element-loading-background="rgba(0, 0, 0, 0.4)"
:option="option"
autoresize
>
</v-chart> </v-chart>
<el-select class="indexOptionSelector" multiple collapse-tags @change="filterIndexChange" <el-select
class="indexOptionSelector"
multiple
collapse-tags
@change="filterIndexChange"
v-model="indexOptionValue" v-model="indexOptionValue"
placeholder="请选择"> placeholder="请选择"
>
<el-option <el-option
v-for="item of computedLaneTableColumn" v-for="item of computedLaneTableColumn"
:key="item.prop" :key="item.prop"
:label="item.label" :label="item.label"
:value="item.prop"> :value="item.prop"
>
</el-option> </el-option>
</el-select> </el-select>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import {noDataTitle} from "@/utils/chartStyle"; import { noDataTitle } from "@/utils/chartStyle";
import {getFontSize} from "@/config/holo/fontSize"; import { getFontSize } from "@/config/holo/fontSize";
import {getLanePeriodTurnData, getLaneTrafficIndex, exportLane} from "@/dao/optApi"; import {
import {occupancyValue} from "../../../utils"; getLanePeriodTurnData,
getLaneTrafficIndex,
exportLane,
exportTurn
} from "@/dao/optApi";
import { occupancyValue } from "../../../utils";
export default { export default {
name: 'cycleData', name: "cycleData",
props: ['crossData'], props: ["crossData"],
data() { data() {
return { return {
loading: true, loading: true,
laneTableColumn: [], laneTableColumn: [],
locationType1: 'laneSort', locationType1: "laneSort",
locationOptions1: [ locationOptions1: [
{value: 'laneSort', label: '车道级'}, { value: "laneSort", label: "车道级" },
{value: 'turn', label: '转向级'}, { value: "turn", label: "转向级" },
], ],
value1: [], value1: [],
options1: [], options1: [],
indexOptionValue: [], indexOptionValue: [],
tabs: [ tabs: [{ 1: "周期数据" }, { 2: "快照数据" }, { 3: "事件数据" }],
{'1': '周期数据'},
{'2': '快照数据'},
{'3': '事件数据'},
],
listDataCopy: [], listDataCopy: [],
dateTimeRange: [], dateTimeRange: [],
xData: [], xData: [],
...@@ -117,209 +143,241 @@ export default { ...@@ -117,209 +143,241 @@ export default {
tableData: [], tableData: [],
option: {}, option: {},
laneTableColumn1: [ laneTableColumn1: [
{label: '时间', prop: 'time'}, { label: "时间", prop: "time" },
{label: '方向', prop: 'dirName'}, { label: "方向", prop: "dirName" },
{label: '车道号', prop: 'laneSort'}, { label: "车道号", prop: "laneSort" },
{label: '总流量', prop: 'allFlow'}, { label: "总流量", prop: "allFlow" },
{label: '行人流量', prop: 'pedFlow'}, { label: "行人流量", prop: "pedFlow" },
{label: '非机动车流量', prop: 'nonMotorFlow'}, { label: "非机动车流量", prop: "nonMotorFlow" },
{label: '小车流量', prop: 'trafficFlowC'}, { label: "小车流量", prop: "trafficFlowC" },
{label: '中车流量', prop: 'trafficFlowB'}, { label: "中车流量", prop: "trafficFlowB" },
{label: '大车流量', prop: 'trafficFlowA'}, { label: "大车流量", prop: "trafficFlowA" },
{label: '平均速度', prop: 'speed'}, { label: "平均速度", prop: "speed" },
{label: '时间占有率', prop: 'timeOccupancy'}, { label: "时间占有率", prop: "timeOccupancy" },
{label: '平均车头时距', prop: 'vehheadTime'}, { label: "平均车头时距", prop: "vehheadTime" },
{label: '平均车身间距', prop: 'vehheadDist'}, { label: "平均车身间距", prop: "vehheadDist" },
{label: '85位速度', prop: 'v85'}, { label: "85位速度", prop: "v85" },
{label: '车辆总和', prop: 'allVehiceleFlow'}, { label: "车辆总和", prop: "allVehiceleFlow" },
{label: '平均空间占有率', prop: 'vehicleNumsRatioMean'}, { label: "平均空间占有率", prop: "vehicleNumsRatioMean" },
{label: '最大排队长度', prop: 'queueLength'}, { label: "最大排队长度", prop: "queueLength" },
{label: '平均停车次数', prop: 'stopTimes'}, { label: "平均停车次数", prop: "stopTimes" },
{label: '平均延误', prop: 'delayTime'}, { label: "平均延误", prop: "delayTime" },
], ],
laneTableColumn2: [ laneTableColumn2: [
{label: '时间', prop: 'windowEndTime'}, { label: "时间", prop: "windowEndTime" },
{label: '方向', prop: 'fRidDirTranslate'}, { label: "方向", prop: "fRidDirTranslate" },
{label: '总流量', prop: 'allFlow'}, { label: "总流量", prop: "allFlow" },
{label: '平均速度', prop: 'avgSpeed'}, { label: "平均速度", prop: "avgSpeed" },
{label: '左转流量', prop: 'flow1'}, { label: "左转流量", prop: "flow1" },
{label: '左转车辆平均速度', prop: 'speed1'}, { label: "左转车辆平均速度", prop: "speed1" },
{label: '直行流量', prop: 'flow2'}, { label: "直行流量", prop: "flow2" },
{label: '直行车辆平均速度', prop: 'speed2'}, { label: "直行车辆平均速度", prop: "speed2" },
{label: '右转流量', prop: 'flow3'}, { label: "右转流量", prop: "flow3" },
{label: '右转车辆平均速度', prop: 'speed3'}, { label: "右转车辆平均速度", prop: "speed3" },
], ],
includeIndex1: ['allFlow', 'allVehiceleFlow', 'delayTime', 'nonMotorFlow', includeIndex1: [
'pedFlow', 'queueLength', 'speed', 'stopTimes', 'timeOccupancy', 'trafficFlowA', 'trafficFlowB', 'trafficFlowC', "allFlow",
'v85', 'vehheadDist', 'vehheadTime', 'vehicleNumsRatioMean' "allVehiceleFlow",
"delayTime",
"nonMotorFlow",
"pedFlow",
"queueLength",
"speed",
"stopTimes",
"timeOccupancy",
"trafficFlowA",
"trafficFlowB",
"trafficFlowC",
"v85",
"vehheadDist",
"vehheadTime",
"vehicleNumsRatioMean",
], ],
includeIndex2: ['flow1', 'flow2', 'flow3', 'speed1', 'speed2', 'speed3', 'allFlow', 'avgSpeed'] includeIndex2: [
} "flow1",
"flow2",
"flow3",
"speed1",
"speed2",
"speed3",
"allFlow",
"avgSpeed",
],
};
}, },
computed: { computed: {
computedLaneTableColumn() { computedLaneTableColumn() {
if (this.locationType1 === 'laneSort') { if (this.locationType1 === "laneSort") {
return this.laneTableColumn1.filter(item => { return this.laneTableColumn1.filter((item) => {
return this.includeIndex1.includes(item.prop) return this.includeIndex1.includes(item.prop);
}) });
} else { } else {
return this.laneTableColumn2.filter(item => { return this.laneTableColumn2.filter((item) => {
return this.includeIndex2.includes(item.prop) return this.includeIndex2.includes(item.prop);
}) });
}
} }
}, },
},
mounted() { mounted() {
if (time_config.dataQuery_cycleTime) { if (time_config.dataQuery_cycleTime) {
this.dateTimeRange = [ this.dateTimeRange = [
new Date(time_config.dataQuery_cycleTime[0]), new Date(time_config.dataQuery_cycleTime[0]),
new Date(time_config.dataQuery_cycleTime[1]) new Date(time_config.dataQuery_cycleTime[1]),
]; ];
} else { } else {
this.dateTimeRange = [ this.dateTimeRange = [
new Date( new Date(new Date().setTime(new Date().getTime() - 3600 * 1000 * 24)),
new Date().setTime(new Date().getTime() - 3600 * 1000 * 24) new Date(),
),
new Date()
]; ];
} }
if (this.crossData.crossId) { if (this.crossData.crossId) {
this.getData() this.getData();
} }
}, },
methods: { methods: {
exportLaneExcel() { downloadFileExcel(response){
// 车道级excel导出下载 let blob = new Blob([response.data], { type: "application/x-xls" });
if (this.locationType1 === 'laneSort') {
exportLane({
"crossId": this.crossData.crossId,
"end": this.dateTimeRange[1].toLocaleString().replaceAll('/', '-'),
"start": this.dateTimeRange[0].toLocaleString().replaceAll('/', '-')
// "end": '2024-02-01 00:00:00',
// "start": '2024-02-01 10:00:00',
}).then(response => {
let blob = new Blob([response.data], {type: "application/x-xls"});
let a = document.createElement("a"); let a = document.createElement("a");
a.href = URL.createObjectURL(blob); a.href = URL.createObjectURL(blob);
let fileName = response.headers['content-disposition'].split('=')[1] let fileName = response.headers["content-disposition"].split("=")[1];
fileName = decodeURI(fileName) fileName = decodeURI(fileName);
// fileName = fileName+'.xls'
a.download = fileName; //文件名称 a.download = fileName; //文件名称
a.style.display = "none"; a.style.display = "none";
document.body.appendChild(a); document.body.appendChild(a);
a.click(); a.click();
a.remove(); a.remove();
}) },
exportLaneExcel() {
// 车道级excel导出下载
if (this.locationType1 === "laneSort") {
exportLane({
crossId: this.crossData.crossId,
end: this.dateTimeRange[1].toLocaleString().replaceAll("/", "-"),
start: this.dateTimeRange[0].toLocaleString().replaceAll("/", "-"),
}).then((response) => {
this.downloadFileExcel(response)
});
}
// 转向级
else{
exportTurn({
crossId: this.crossData.crossId,
end: this.dateTimeRange[1].toLocaleString().replaceAll("/", "-"),
start: this.dateTimeRange[0].toLocaleString().replaceAll("/", "-"),
}).then((response) => {
this.downloadFileExcel(response)
});
} }
}, },
filterIndexChange() { filterIndexChange() {
if (this.locationType1 === 'laneSort') { if (this.locationType1 === "laneSort") {
this.renderFilterData1() this.renderFilterData1();
} else { } else {
this.renderFilterData2() this.renderFilterData2();
} }
}, },
occupancyValue, occupancyValue,
initSelectAndFilterTable1() { initSelectAndFilterTable1() {
this.value1 = [] this.value1 = [];
console.log('before sort...', this.tableData) console.log("before sort...", this.tableData);
this.options1 = this.tableData.sort((a, b) => { this.options1 = this.tableData
return Number(a.dir) - Number(b.dir) .sort((a, b) => {
}).reduce((a, b) => { return Number(a.dir) - Number(b.dir);
})
.reduce((a, b) => {
if (!a.includes(b.laneSort)) { if (!a.includes(b.laneSort)) {
a.push(b.laneSort) a.push(b.laneSort);
} }
return a return a;
}, []) }, []);
if (this.options1.length) { if (this.options1.length) {
this.value1.push(...this.options1) this.value1.push(...this.options1);
} }
this.filterTable1() this.filterTable1();
}, },
initSelectAndFilterTable2() { initSelectAndFilterTable2() {
this.value1 = [] this.value1 = [];
this.options1 = this.tableData.reduce((a, b) => { this.options1 = this.tableData.reduce((a, b) => {
if (!a.includes(b.fRidDirTranslate)) { if (!a.includes(b.fRidDirTranslate)) {
a.push(b.fRidDirTranslate) a.push(b.fRidDirTranslate);
} }
return a return a;
}, []) }, []);
if (this.options1.length) { if (this.options1.length) {
// this.value1.push(this.options1[0]) // this.value1.push(this.options1[0])
this.value1.push(...this.options1) this.value1.push(...this.options1);
} }
this.filterTable1() this.filterTable1();
}, },
filterTable1() { filterTable1() {
if (this.locationType1 === 'laneSort') { if (this.locationType1 === "laneSort") {
this.listDataCopy = this.tableData.filter(item => { this.listDataCopy = this.tableData.filter((item) => {
return this.value1.includes(item.laneSort) return this.value1.includes(item.laneSort);
}) });
// this.listDataCopy = this.tableData // this.listDataCopy = this.tableData
this.renderFilterData1() this.renderFilterData1();
} else { } else {
this.listDataCopy = this.tableData.filter(item => { this.listDataCopy = this.tableData.filter((item) => {
return this.value1.includes(item.fRidDirTranslate) return this.value1.includes(item.fRidDirTranslate);
}) });
// this.listDataCopy = this.tableData // this.listDataCopy = this.tableData
this.renderFilterData2() this.renderFilterData2();
} }
}, },
// 根据筛选后的数据渲染echarts // 根据筛选后的数据渲染echarts
renderFilterData1() { renderFilterData1() {
this.xData = this.listDataCopy.reduce((a, b) => { this.xData = this.listDataCopy.reduce((a, b) => {
if (!a.includes(b.time)) { if (!a.includes(b.time)) {
a.push(b.time) a.push(b.time);
} }
return a return a;
}, []) }, []);
this.yDatas = [] this.yDatas = [];
let yObj = this.listDataCopy.reduce((a, b) => { let yObj = this.listDataCopy.reduce((a, b) => {
for (let key in b) { for (let key in b) {
if ( if (
this.includeIndex1.includes(key) this.includeIndex1.includes(key) &&
&& this.indexOptionValue.includes(key) this.indexOptionValue.includes(key)
) { ) {
let wholeKey = `${b.laneSort}-${key}` let wholeKey = `${b.laneSort}-${key}`;
if (a[wholeKey]) { if (a[wholeKey]) {
a[wholeKey].push(b[key]) a[wholeKey].push(b[key]);
} else { } else {
a[wholeKey] = [b[key]] a[wholeKey] = [b[key]];
} }
} }
} }
return a return a;
}, {}) }, {});
for (let key in yObj) { for (let key in yObj) {
this.yDatas.push({ this.yDatas.push({
name: key, name: key,
list: yObj[key] list: yObj[key],
}) });
} }
// --- // ---
let title = { let title = {
show: false show: false,
} };
if (!this.xData.length) { if (!this.xData.length) {
title = noDataTitle title = noDataTitle;
} }
let series = [] let series = [];
let selected = {} let selected = {};
for (let [i, item] of this.yDatas.entries()) { for (let [i, item] of this.yDatas.entries()) {
let valueArr = item.name.split('-') let valueArr = item.name.split("-");
let value = valueArr[valueArr.length - 1] let value = valueArr[valueArr.length - 1];
let realIndex = this.laneTableColumn.find(columnIndex => { let realIndex = this.laneTableColumn.find((columnIndex) => {
return columnIndex.prop === value return columnIndex.prop === value;
})?.label })?.label;
let nameReal = item.name.replace(value, realIndex) let nameReal = item.name.replace(value, realIndex);
if (value !== 'allFlow') { if (value !== "allFlow") {
selected[nameReal] = false selected[nameReal] = false;
} }
series.push({ series.push({
name: nameReal, name: nameReal,
type: "line", type: "line",
symbol: 'none', symbol: "none",
smooth: true, smooth: true,
label: { label: {
show: false, show: false,
...@@ -328,7 +386,7 @@ export default { ...@@ -328,7 +386,7 @@ export default {
focus: "series", focus: "series",
}, },
data: item.list.reverse(), data: item.list.reverse(),
}) });
} }
this.option = { this.option = {
title, title,
...@@ -336,11 +394,11 @@ export default { ...@@ -336,11 +394,11 @@ export default {
type: "inside", type: "inside",
}, },
tooltip: { tooltip: {
backgroundColor: 'rgba(0,0,0,0.6)', backgroundColor: "rgba(0,0,0,0.6)",
borderWidth: 0, borderWidth: 0,
textStyle: { textStyle: {
fontSize: getFontSize(12), fontSize: getFontSize(12),
color: 'white', color: "white",
}, },
enterable: true, enterable: true,
trigger: "axis", trigger: "axis",
...@@ -350,9 +408,11 @@ export default { ...@@ -350,9 +408,11 @@ export default {
for (let i = 0; i < params.length; i++) { for (let i = 0; i < params.length; i++) {
str += `<p>${params[i].seriesName}&nbsp;&nbsp;:&nbsp;&nbsp;${params[i].value}</p>`; str += `<p>${params[i].seriesName}&nbsp;&nbsp;:&nbsp;&nbsp;${params[i].value}</p>`;
} }
return '<div style="max-height:200px;overflow-y:auto;padding: 2px 8px 2px 2px;">' + return (
'<div style="max-height:200px;overflow-y:auto;padding: 2px 8px 2px 2px;">' +
str + str +
"</div>"; "</div>"
);
} }
}, },
axisPointer: { axisPointer: {
...@@ -361,7 +421,7 @@ export default { ...@@ -361,7 +421,7 @@ export default {
confine: true, confine: true,
}, },
legend: { legend: {
inactiveColor: 'rgba(255,255,255,0.7)', inactiveColor: "rgba(255,255,255,0.7)",
left: 0, left: 0,
padding: [7, 200, 0, 0], padding: [7, 200, 0, 0],
// selected, // selected,
...@@ -398,8 +458,8 @@ export default { ...@@ -398,8 +458,8 @@ export default {
color: "rgba(126, 139, 166, 1)", color: "rgba(126, 139, 166, 1)",
}, },
axisPointer: { axisPointer: {
type: 'line' type: "line",
} },
}, },
yAxis: { yAxis: {
axisTick: { axisTick: {
...@@ -422,7 +482,7 @@ export default { ...@@ -422,7 +482,7 @@ export default {
}, },
}, },
series: series, series: series,
} };
// --- // ---
}, },
...@@ -430,59 +490,59 @@ export default { ...@@ -430,59 +490,59 @@ export default {
renderFilterData2() { renderFilterData2() {
this.xData = this.listDataCopy.reduce((a, b) => { this.xData = this.listDataCopy.reduce((a, b) => {
if (!a.includes(b.windowEndTime)) { if (!a.includes(b.windowEndTime)) {
a.push(b.windowEndTime) a.push(b.windowEndTime);
} }
return a return a;
}, []) }, []);
this.yDatas = [] this.yDatas = [];
let yObj = this.listDataCopy.reduce((a, b) => { let yObj = this.listDataCopy.reduce((a, b) => {
for (let key in b) { for (let key in b) {
if ( if (
this.includeIndex2.includes(key) this.includeIndex2.includes(key) &&
&& this.indexOptionValue.includes(key) this.indexOptionValue.includes(key)
) { ) {
let wholeKey = `${b.fRidDirTranslate}-${key}` let wholeKey = `${b.fRidDirTranslate}-${key}`;
if (a[wholeKey]) { if (a[wholeKey]) {
a[wholeKey].push(b[key]) a[wholeKey].push(b[key]);
} else { } else {
a[wholeKey] = [b[key]] a[wholeKey] = [b[key]];
} }
} }
} }
return a return a;
}, {}) }, {});
for (let key in yObj) { for (let key in yObj) {
this.yDatas.push({ this.yDatas.push({
name: key, name: key,
list: yObj[key] list: yObj[key],
}) });
} }
console.log('yDatas', this.yDatas) console.log("yDatas", this.yDatas);
// --- // ---
let title = { let title = {
show: false show: false,
} };
if (!this.xData.length) { if (!this.xData.length) {
title = noDataTitle title = noDataTitle;
} }
let series = [] let series = [];
let selected = {} let selected = {};
for (let [i, item] of this.yDatas.entries()) { for (let [i, item] of this.yDatas.entries()) {
// let nameReal = this.$store.state.dicts.Direction.find((item) => { // let nameReal = this.$store.state.dicts.Direction.find((item) => {
// return item.code == key; // return item.code == key;
// }).name // }).name
let value = item.name.split('-')[1] let value = item.name.split("-")[1];
let realIndex = this.laneTableColumn.find(columnIndex => { let realIndex = this.laneTableColumn.find((columnIndex) => {
return columnIndex.prop === value return columnIndex.prop === value;
})?.label })?.label;
let nameReal = item.name.replace(value, realIndex) let nameReal = item.name.replace(value, realIndex);
if (value !== 'allFlow') { if (value !== "allFlow") {
selected[nameReal] = false selected[nameReal] = false;
} }
series.push({ series.push({
name: nameReal, name: nameReal,
type: "line", type: "line",
symbol: 'none', symbol: "none",
smooth: true, smooth: true,
// areaStyle: { // areaStyle: {
// color: new echarts.graphic.LinearGradient( // color: new echarts.graphic.LinearGradient(
...@@ -510,16 +570,16 @@ export default { ...@@ -510,16 +570,16 @@ export default {
focus: "series", focus: "series",
}, },
data: item.list.reverse(), data: item.list.reverse(),
}) });
} }
this.option = { this.option = {
title, title,
tooltip: { tooltip: {
backgroundColor: 'rgba(0,0,0,0.6)', backgroundColor: "rgba(0,0,0,0.6)",
borderWidth: 0, borderWidth: 0,
textStyle: { textStyle: {
fontSize: getFontSize(12), fontSize: getFontSize(12),
color: 'white', color: "white",
}, },
formatter: function (params) { formatter: function (params) {
if (params && params.length) { if (params && params.length) {
...@@ -527,9 +587,11 @@ export default { ...@@ -527,9 +587,11 @@ export default {
for (let i = 0; i < params.length; i++) { for (let i = 0; i < params.length; i++) {
str += `<p>${params[i].seriesName}&nbsp;&nbsp;:&nbsp;&nbsp;${params[i].value}</p>`; str += `<p>${params[i].seriesName}&nbsp;&nbsp;:&nbsp;&nbsp;${params[i].value}</p>`;
} }
return '<div style="max-height:200px;overflow-y:auto;padding: 2px 8px 2px 2px;">' + return (
'<div style="max-height:200px;overflow-y:auto;padding: 2px 8px 2px 2px;">' +
str + str +
"</div>"; "</div>"
);
} }
}, },
enterable: true, enterable: true,
...@@ -540,7 +602,7 @@ export default { ...@@ -540,7 +602,7 @@ export default {
confine: true, confine: true,
}, },
legend: { legend: {
inactiveColor: 'rgba(255,255,255,0.7)', inactiveColor: "rgba(255,255,255,0.7)",
padding: [7, 200, 0, 0], padding: [7, 200, 0, 0],
left: 0, left: 0,
// selected, // selected,
...@@ -577,8 +639,8 @@ export default { ...@@ -577,8 +639,8 @@ export default {
color: "rgba(126, 139, 166, 1)", color: "rgba(126, 139, 166, 1)",
}, },
axisPointer: { axisPointer: {
type: 'line' type: "line",
} },
}, },
yAxis: { yAxis: {
axisTick: { axisTick: {
...@@ -601,90 +663,100 @@ export default { ...@@ -601,90 +663,100 @@ export default {
}, },
}, },
series: series, series: series,
} };
// --- // ---
}, },
getData() { getData() {
this.loading = true this.loading = true;
this.indexOptionValue = ['allFlow'] this.indexOptionValue = ["allFlow"];
let params = { let params = {
"crossId": this.crossData.crossId, crossId: this.crossData.crossId,
"end": this.dateTimeRange[1].toLocaleString().replaceAll('/', '-'), end: this.dateTimeRange[1].toLocaleString().replaceAll("/", "-"),
"start": this.dateTimeRange[0].toLocaleString().replaceAll('/', '-'), start: this.dateTimeRange[0].toLocaleString().replaceAll("/", "-"),
"granularity": "1h" granularity: "1h",
} };
// 车道级数据 // 车道级数据
if (this.locationType1 === 'laneSort') { if (this.locationType1 === "laneSort") {
this.laneTableColumn = this.laneTableColumn1 this.laneTableColumn = this.laneTableColumn1;
getLaneTrafficIndex(params).then(res => { getLaneTrafficIndex(params).then((res) => {
console.log('res1', res) console.log("res1", res);
this.loading = false this.loading = false;
this.tableData = res.content this.tableData = res.content;
this.tableData.map(item => { this.tableData.map((item) => {
item.dirName = this.$store.state.dicts.Direction.find(dict => { item.dirName = this.$store.state.dicts.Direction.find((dict) => {
return dict.code == item.dir return dict.code == item.dir;
})?.name })?.name;
}) });
this.listDataCopy = JSON.parse(JSON.stringify(this.tableData)) this.listDataCopy = JSON.parse(JSON.stringify(this.tableData));
this.initSelectAndFilterTable1() this.initSelectAndFilterTable1();
this.$nextTick(() => { this.$nextTick(() => {
this.$refs.table.doLayout() this.$refs.table.doLayout();
}) });
});
})
} }
// 转向级数据 // 转向级数据
else { else {
this.laneTableColumn = this.laneTableColumn2 this.laneTableColumn = this.laneTableColumn2;
getLanePeriodTurnData(params).then(res => { getLanePeriodTurnData(params).then((res) => {
console.log('转向级', res) console.log("转向级", res);
this.loading = false this.loading = false;
this.tableData = res.content.reduce((a, b) => { this.tableData = res.content.reduce((a, b) => {
b.windowEndTime = b.windowEndTime.slice(0, 19) b.windowEndTime = b.windowEndTime.slice(0, 19);
let haveFlag = false let haveFlag = false;
for (let i = 0; i < a.length; i++) { for (let i = 0; i < a.length; i++) {
if (a[i].crossId === b.crossId && a[i].fRidDir === b.fRidDir && a[i].windowEndTime === b.windowEndTime) { if (
haveFlag = true a[i].crossId === b.crossId &&
a[i][`flow${b.turnDirNo}`] = b.flow a[i].fRidDir === b.fRidDir &&
a[i][`speed${b.turnDirNo}`] = b.speed a[i].windowEndTime === b.windowEndTime
) {
haveFlag = true;
a[i][`flow${b.turnDirNo}`] = b.flow;
a[i][`speed${b.turnDirNo}`] = b.speed;
} }
} }
if (!haveFlag) { if (!haveFlag) {
let externalObj = {} let externalObj = {};
externalObj[`flow${b.turnDirNo}`] = b.flow externalObj[`flow${b.turnDirNo}`] = b.flow;
externalObj[`speed${b.turnDirNo}`] = b.speed externalObj[`speed${b.turnDirNo}`] = b.speed;
let finalSinglaObj = Object.assign({}, b, externalObj) let finalSinglaObj = Object.assign({}, b, externalObj);
delete finalSinglaObj.speed delete finalSinglaObj.speed;
a.push(finalSinglaObj) a.push(finalSinglaObj);
} }
return a return a;
}, []) }, []);
for (let i = 0; i < this.tableData.length; i++) { for (let i = 0; i < this.tableData.length; i++) {
this.tableData[i].allFlow = (this.tableData[i].flow1 || 0) + (this.tableData[i].flow2 || 0) + (this.tableData[i].flow3 || 0) this.tableData[i].allFlow =
let speedNum = 0 (this.tableData[i].flow1 || 0) +
(this.tableData[i].flow2 || 0) +
(this.tableData[i].flow3 || 0);
let speedNum = 0;
for (let key in this.tableData[i]) { for (let key in this.tableData[i]) {
if (key.includes('speed')) { if (key.includes("speed")) {
speedNum += 1 speedNum += 1;
} }
} }
this.tableData[i].fRidDirTranslate = this.$store.state.dicts.Direction.find((item) => { this.tableData[i].fRidDirTranslate =
this.$store.state.dicts.Direction.find((item) => {
return item.code == this.tableData[i].fRidDir; return item.code == this.tableData[i].fRidDir;
}).name }).name;
this.tableData[i].avgSpeed = (((this.tableData[i].speed1 || 0) + (this.tableData[i].speed2 || 0) + (this.tableData[i].speed3 || 0)) / speedNum).toFixed(2) this.tableData[i].avgSpeed = (
} ((this.tableData[i].speed1 || 0) +
console.log('this.tableData 转向', this.tableData) (this.tableData[i].speed2 || 0) +
this.listDataCopy = JSON.parse(JSON.stringify(this.tableData)) (this.tableData[i].speed3 || 0)) /
this.initSelectAndFilterTable2() speedNum
).toFixed(2);
}
console.log("this.tableData 转向", this.tableData);
this.listDataCopy = JSON.parse(JSON.stringify(this.tableData));
this.initSelectAndFilterTable2();
this.$nextTick(() => { this.$nextTick(() => {
this.$refs.table.doLayout() this.$refs.table.doLayout();
}) });
});
})
} }
}, },
rowClick(e) { rowClick(e) {
console.log('row', e) console.log("row", e);
}, },
getRowClassName(e) { getRowClassName(e) {
if (e.rowIndex % 2 !== 0) { if (e.rowIndex % 2 !== 0) {
...@@ -693,8 +765,8 @@ export default { ...@@ -693,8 +765,8 @@ export default {
return "row-even"; return "row-even";
} }
}, },
} },
} };
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
...@@ -714,11 +786,11 @@ export default { ...@@ -714,11 +786,11 @@ export default {
//table fixed 列样式 end //table fixed 列样式 end
::v-deep .el-input__inner { ::v-deep .el-input__inner {
border: 1px solid rgba(90, 144, 238, 0.34); border: 1px solid rgba(90, 144, 238, 0.34);
color: white color: white;
} }
::v-deep .el-range-separator { ::v-deep .el-range-separator {
color: white color: white;
} }
label { label {
......
<template> <template>
<div class="full-w-h eventDataContainer"> <div class="full-w-h eventDataContainer">
<div style="margin-bottom: 10px;margin-top: 10px" class="custom-form"> <div style="margin-bottom: 10px; margin-top: 10px" class="custom-form">
<label class="custom-form-label">时段选择: </label> <label class="custom-form-label">时段选择: </label>
<el-date-picker <el-date-picker
style="margin-right: 10px" style="margin-right: 10px"
...@@ -10,19 +10,31 @@ ...@@ -10,19 +10,31 @@
type="datetimerange" type="datetimerange"
range-separator="至" range-separator="至"
start-placeholder="开始日期" start-placeholder="开始日期"
end-placeholder="结束日期"> end-placeholder="结束日期"
>
</el-date-picker> </el-date-picker>
<label class="custom-form-label">事件类型: </label> <label class="custom-form-label">事件类型: </label>
<el-select class="custom-select" style="margin-right: 10px" v-model="eventTypeValue" <el-select
placeholder="请选择"> class="custom-select"
style="margin-right: 10px"
v-model="eventTypeValue"
placeholder="请选择"
>
<el-option <el-option
v-for="item in eventTypeOptions" v-for="item in eventTypeOptions"
:key="item.value" :key="item.value"
:label="item.label" :label="item.label"
:value="item.value"> :value="item.value"
>
</el-option> </el-option>
</el-select> </el-select>
<el-button @click="exportLaneExcel()" size="mini" type="primary" class="custom-export-button">导出</el-button> <el-button
@click="exportLaneExcel()"
size="mini"
type="primary"
class="custom-export-button"
>导出</el-button
>
</div> </div>
<div class="event-type"> <div class="event-type">
<div class="table-title"> <div class="table-title">
...@@ -37,80 +49,91 @@ ...@@ -37,80 +49,91 @@
header-cell-class-name="custom-table-header-cell" header-cell-class-name="custom-table-header-cell"
:data="stopTableData" :data="stopTableData"
:row-class-name="getRowClassName" :row-class-name="getRowClassName"
style="width: 100%"> style="width: 100%"
<el-table-column >
align="center" <el-table-column align="center" label="序号" show-overflow-tooltip>
label="序号" show-overflow-tooltip>
<template slot-scope="scope"> <template slot-scope="scope">
{{ occupancyValue(scope.row.xxx) }} {{ occupancyValue(scope.row.xxx) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
align="center" align="center"
label="停车类型" show-overflow-tooltip> label="停车类型"
show-overflow-tooltip
>
<template slot-scope="scope"> <template slot-scope="scope">
{{ occupancyValue(scope.row.xxx) }} {{ occupancyValue(scope.row.xxx) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
align="center" align="center"
label="开始时间" show-overflow-tooltip> label="开始时间"
show-overflow-tooltip
>
<template slot-scope="scope"> <template slot-scope="scope">
{{ occupancyValue(scope.row.xxx) }} {{ occupancyValue(scope.row.xxx) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
align="center" align="center"
label="结束时间" show-overflow-tooltip> label="结束时间"
show-overflow-tooltip
>
<template slot-scope="scope"> <template slot-scope="scope">
{{ occupancyValue(scope.row.xxx) }} {{ occupancyValue(scope.row.xxx) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
align="center" align="center"
label="持续时长" show-overflow-tooltip> label="持续时长"
show-overflow-tooltip
>
<template slot-scope="scope"> <template slot-scope="scope">
{{ occupancyValue(scope.row.xxx) }} {{ occupancyValue(scope.row.xxx) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column align="center" label="位置" show-overflow-tooltip>
align="center"
label="位置" show-overflow-tooltip>
<template slot-scope="scope"> <template slot-scope="scope">
{{ occupancyValue(scope.row.xxx) }} {{ occupancyValue(scope.row.xxx) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
align="center" align="center"
label="车辆类型" show-overflow-tooltip> label="车辆类型"
show-overflow-tooltip
>
<template slot-scope="scope"> <template slot-scope="scope">
{{ occupancyValue(scope.row.xxx) }} {{ occupancyValue(scope.row.xxx) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
align="center" align="center"
label="车辆颜色" show-overflow-tooltip> label="车辆颜色"
show-overflow-tooltip
>
<template slot-scope="scope"> <template slot-scope="scope">
{{ occupancyValue(scope.row.xxx) }} {{ occupancyValue(scope.row.xxx) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
align="center" align="center"
label="车牌类型" show-overflow-tooltip> label="车牌类型"
show-overflow-tooltip
>
<template slot-scope="scope"> <template slot-scope="scope">
{{ occupancyValue(scope.row.xxx) }} {{ occupancyValue(scope.row.xxx) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
align="center" align="center"
label="车牌号码" show-overflow-tooltip> label="车牌号码"
show-overflow-tooltip
>
<template slot-scope="scope"> <template slot-scope="scope">
{{ occupancyValue(scope.row.xxx) }} {{ occupancyValue(scope.row.xxx) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column align="center" label="操作" show-overflow-tooltip>
align="center"
label="操作" show-overflow-tooltip>
<template slot-scope="scope"> <template slot-scope="scope">
<a>回放</a> <a>回放</a>
</template> </template>
...@@ -131,73 +154,82 @@ ...@@ -131,73 +154,82 @@
header-cell-class-name="custom-table-header-cell" header-cell-class-name="custom-table-header-cell"
:data="overTableData" :data="overTableData"
:row-class-name="getRowClassName" :row-class-name="getRowClassName"
style="width: 100%"> style="width: 100%"
<el-table-column >
align="center" <el-table-column align="center" label="序号" show-overflow-tooltip>
label="序号" show-overflow-tooltip>
<template slot-scope="scope"> <template slot-scope="scope">
{{ occupancyValue(scope.row.xxx) }} {{ occupancyValue(scope.row.xxx) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
align="center" align="center"
label="开始时间" show-overflow-tooltip> label="开始时间"
show-overflow-tooltip
>
<template slot-scope="scope"> <template slot-scope="scope">
{{ occupancyValue(scope.row.xxx) }} {{ occupancyValue(scope.row.xxx) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
align="center" align="center"
label="结束时间" show-overflow-tooltip> label="结束时间"
show-overflow-tooltip
>
<template slot-scope="scope"> <template slot-scope="scope">
{{ occupancyValue(scope.row.xxx) }} {{ occupancyValue(scope.row.xxx) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
align="center" align="center"
label="持续时长" show-overflow-tooltip> label="持续时长"
show-overflow-tooltip
>
<template slot-scope="scope"> <template slot-scope="scope">
{{ occupancyValue(scope.row.xxx) }} {{ occupancyValue(scope.row.xxx) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column align="center" label="位置" show-overflow-tooltip>
align="center"
label="位置" show-overflow-tooltip>
<template slot-scope="scope"> <template slot-scope="scope">
{{ occupancyValue(scope.row.xxx) }} {{ occupancyValue(scope.row.xxx) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
align="center" align="center"
label="溢出区编号" show-overflow-tooltip> label="溢出区编号"
show-overflow-tooltip
>
<template slot-scope="scope"> <template slot-scope="scope">
{{ occupancyValue(scope.row.xxx) }} {{ occupancyValue(scope.row.xxx) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
align="center" align="center"
label="溢出区车辆数" show-overflow-tooltip> label="溢出区车辆数"
show-overflow-tooltip
>
<template slot-scope="scope"> <template slot-scope="scope">
{{ occupancyValue(scope.row.xxx) }} {{ occupancyValue(scope.row.xxx) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
align="center" align="center"
label="平均速度" show-overflow-tooltip> label="平均速度"
show-overflow-tooltip
>
<template slot-scope="scope"> <template slot-scope="scope">
{{ occupancyValue(scope.row.xxx) }} {{ occupancyValue(scope.row.xxx) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
align="center" align="center"
label="空间占有率" show-overflow-tooltip> label="空间占有率"
show-overflow-tooltip
>
<template slot-scope="scope"> <template slot-scope="scope">
{{ occupancyValue(scope.row.xxx) }} {{ occupancyValue(scope.row.xxx) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column align="center" label="操作" show-overflow-tooltip>
align="center"
label="操作" show-overflow-tooltip>
<template slot-scope="scope"> <template slot-scope="scope">
<a>回放</a> <a>回放</a>
</template> </template>
...@@ -209,39 +241,37 @@ ...@@ -209,39 +241,37 @@
</template> </template>
<script> <script>
import {getHoloEventList, initLaneSort} from "@/dao/optApi"; import { getHoloEventList, initLaneSort } from "@/dao/optApi";
import {occupancyValue} from "../../../utils"; import { occupancyValue } from "../../../utils";
export default { export default {
name: 'eventData', name: "eventData",
data() { data() {
return { return {
dateTimeRange: [], dateTimeRange: [],
eventTypeValue: '', eventTypeValue: "",
eventTypeOptions: [ eventTypeOptions: [
{value: '1', label: '停车事件'}, { value: "1", label: "停车事件" },
{value: '2', label: '溢出事件'}, { value: "2", label: "溢出事件" },
], ],
stopTableData: [], stopTableData: [],
overTableData: [], overTableData: [],
} };
}, },
mounted() { mounted() {
if (time_config.dataQuery_snapshotTime) { if (time_config.dataQuery_snapshotTime) {
this.dateTimeRange = [ this.dateTimeRange = [
new Date(time_config.dataQuery_snapshotTime[0]), new Date(time_config.dataQuery_snapshotTime[0]),
new Date(time_config.dataQuery_snapshotTime[1]) new Date(time_config.dataQuery_snapshotTime[1]),
]; ];
} else { } else {
this.dateTimeRange = [ this.dateTimeRange = [
new Date( new Date(new Date().setTime(new Date().getTime() - 1000 * 60 * 60)),
new Date().setTime(new Date().getTime() - 1000 * 60 * 60) new Date(),
),
new Date()
]; ];
} }
if (this.crossData.crossId) { if (this.crossData.crossId) {
this.getData() this.getData();
} }
}, },
methods: { methods: {
...@@ -271,13 +301,11 @@ export default { ...@@ -271,13 +301,11 @@ export default {
getData() { getData() {
getHoloEventList({ getHoloEventList({
crossId: this.crossData.id, crossId: this.crossData.id,
"end": this.dateTimeRange[1].toLocaleString().replaceAll('/', '-'), end: this.dateTimeRange[1].toLocaleString().replaceAll("/", "-"),
"start": this.dateTimeRange[0].toLocaleString().replaceAll('/', '-'), start: this.dateTimeRange[0].toLocaleString().replaceAll("/", "-"),
}).then(res => { }).then((res) => {
console.log( console.log("event list...", res);
'event list...',res });
)
})
}, },
getRowClassName(e) { getRowClassName(e) {
if (e.rowIndex % 2 !== 0) { if (e.rowIndex % 2 !== 0) {
...@@ -286,8 +314,8 @@ export default { ...@@ -286,8 +314,8 @@ export default {
return "row-even"; return "row-even";
} }
}, },
} },
} };
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
...@@ -296,7 +324,7 @@ export default { ...@@ -296,7 +324,7 @@ export default {
display: flex; display: flex;
align-items: center; align-items: center;
position: relative; position: relative;
.custom-export-button{ .custom-export-button {
position: absolute; position: absolute;
right: 0; right: 0;
border-radius: 0; border-radius: 0;
...@@ -308,14 +336,14 @@ export default { ...@@ -308,14 +336,14 @@ export default {
font-size: 14px; font-size: 14px;
height: 28px; height: 28px;
} }
.custom-export-button:hover{ .custom-export-button:hover {
background-color: #355287; background-color: #355287;
} }
} }
::v-deep .el-input__inner { ::v-deep .el-input__inner {
border: 1px solid rgba(90, 144, 238, 0.34); border: 1px solid rgba(90, 144, 238, 0.34);
color: white color: white;
} }
.custom-form-label { .custom-form-label {
...@@ -343,19 +371,22 @@ export default { ...@@ -343,19 +371,22 @@ export default {
width: 236px; width: 236px;
padding-left: 8px; padding-left: 8px;
height: 100%; height: 100%;
background: linear-gradient(270deg, rgba(33, 209, 255, 0) 0%, rgba(0, 153, 255, 0.5) 100%); background: linear-gradient(
270deg,
rgba(33, 209, 255, 0) 0%,
rgba(0, 153, 255, 0.5) 100%
);
display: flex; display: flex;
align-items: center; align-items: center;
} }
} }
;
.custom-table-container { .custom-table-container {
flex: 1; flex: 1;
} }
} }
.eventDataContainer{ .eventDataContainer {
display: flex; flex-direction: column; display: flex;
flex-direction: column;
padding: 0 10px; padding: 0 10px;
} }
</style> </style>
<template> <template>
<div class="full-w-h snapshotDataContainer"> <div class="full-w-h snapshotDataContainer">
<div style="margin-bottom: 10px;margin-top: 10px" class="custom-form"> <div style="margin-bottom: 10px; margin-top: 10px" class="custom-form">
<label class="custom-form-label">时段选择: </label> <label class="custom-form-label">时段选择: </label>
<el-date-picker <el-date-picker
:clearable="false" :clearable="false"
...@@ -9,26 +9,38 @@ ...@@ -9,26 +9,38 @@
type="datetimerange" type="datetimerange"
range-separator="至" range-separator="至"
start-placeholder="开始日期" start-placeholder="开始日期"
end-placeholder="结束日期"> end-placeholder="结束日期"
>
</el-date-picker> </el-date-picker>
<label class="custom-form-label">车道: </label> <label class="custom-form-label">车道: </label>
<el-select class="custom-select" style="margin-right: 10px" multiple collapse-tags @change="lineChangeGetData()" <el-select
class="custom-select"
style="margin-right: 10px"
multiple
collapse-tags
@change="lineChangeGetData()"
v-model="value1" v-model="value1"
placeholder="请选择"> placeholder="请选择"
>
<el-option <el-option
v-for="item in options1" v-for="item in options1"
:key="item.laneId" :key="item.laneId"
:label="item.aliasName" :label="item.aliasName"
:value="item.laneId"> :value="item.laneId"
>
</el-option> </el-option>
</el-select> </el-select>
<div class="custom-form-label">(备注:车道可多选)</div> <div class="custom-form-label">(备注:车道可多选)</div>
<div class="rightExport" @click="exportLaneExcel()">导出</div> <div class="rightExport" @click="exportLaneExcel()">导出</div>
</div> </div>
<div v-loading="loading" <div
v-loading="loading"
element-loading-text="数据加载中..." element-loading-text="数据加载中..."
element-loading-spinner="el-icon-loading" element-loading-spinner="el-icon-loading"
element-loading-background="rgba(0, 0, 0, 0.4)" style="margin-bottom: 10px" class="custom-table"> element-loading-background="rgba(0, 0, 0, 0.4)"
style="margin-bottom: 10px"
class="custom-table"
>
<div class="custom-elTable"> <div class="custom-elTable">
<el-table <el-table
ref="table" ref="table"
...@@ -38,13 +50,16 @@ ...@@ -38,13 +50,16 @@
@row-click="rowClick" @row-click="rowClick"
:data="listDataCopy" :data="listDataCopy"
:row-class-name="getRowClassName" :row-class-name="getRowClassName"
style="width: 100%"> style="width: 100%"
>
<el-table-column <el-table-column
:width="index===0?'150':'auto'" :width="index === 0 ? '150' : 'auto'"
:key="index" :key="index"
v-for="(it,index) of laneTableColumn" v-for="(it, index) of laneTableColumn"
align="center" align="center"
:label="it.label" show-overflow-tooltip> :label="it.label"
show-overflow-tooltip
>
<template slot-scope="scope"> <template slot-scope="scope">
{{ occupancyValue(scope.row[it.prop], it.prop) }} {{ occupancyValue(scope.row[it.prop], it.prop) }}
</template> </template>
...@@ -55,63 +70,93 @@ ...@@ -55,63 +70,93 @@
<div class="custom-nextPre"> <div class="custom-nextPre">
<div>500 条/页</div> <div>500 条/页</div>
<div>当前第 {{ currentPage + 1 }} 页</div> <div>当前第 {{ currentPage + 1 }} 页</div>
<div @click="lineChangeGetData('pre')"><i class="el-icon-arrow-left"/> 上一页</div> <div @click="lineChangeGetData('pre')">
<div @click="lineChangeGetData('next')">下一页 <i class="el-icon-arrow-right"/></div> <i class="el-icon-arrow-left" /> 上一页
</div>
<div @click="lineChangeGetData('next')">
下一页 <i class="el-icon-arrow-right" />
</div>
</div> </div>
</div> </div>
<div class="chartContainer"> <div class="chartContainer">
<v-chart v-loading="loading" <v-chart
v-loading="loading"
element-loading-text="数据加载中..." element-loading-text="数据加载中..."
element-loading-spinner="el-icon-loading" element-loading-spinner="el-icon-loading"
element-loading-background="rgba(0, 0, 0, 0.4)" :option="option" autoresize></v-chart> element-loading-background="rgba(0, 0, 0, 0.4)"
<el-select class="indexOptionSelector" multiple collapse-tags @change="filterIndexChange" :option="option"
autoresize
></v-chart>
<el-select
class="indexOptionSelector"
multiple
collapse-tags
@change="filterIndexChange"
v-model="indexOptionValue" v-model="indexOptionValue"
placeholder="请选择"> placeholder="请选择"
>
<el-option <el-option
v-for="item of computedLaneTableColumn" v-for="item of computedLaneTableColumn"
:key="item.prop" :key="item.prop"
:label="item.label" :label="item.label"
:value="item.prop"> :value="item.prop"
>
</el-option> </el-option>
</el-select> </el-select>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import {noDataTitle} from "@/utils/chartStyle"; import { noDataTitle } from "@/utils/chartStyle";
import {getFontSize} from "@/config/holo/fontSize"; import { getFontSize } from "@/config/holo/fontSize";
import {exportLane, getLaneSnapshotIndex, initLaneSort} from "@/dao/optApi"; import {
import {occupancyValue} from "../../../utils"; exportLane,
getLaneSnapshotIndex,
initLaneSort,
exportSnapshot,
} from "@/dao/optApi";
import { occupancyValue } from "../../../utils";
export default { export default {
name: 'snapshotData', name: "snapshotData",
props: ['crossData'], props: ["crossData"],
data() { data() {
return { return {
currentPage: 0, currentPage: 0,
indexOptionValue: [], indexOptionValue: [],
loading: true, loading: true,
laneTableColumn: [ laneTableColumn: [
{label: '时间', prop: 'time'}, { label: "时间", prop: "time" },
{label: '方向', prop: 'dirName'}, { label: "方向", prop: "dirName" },
{label: '车道号', prop: 'laneSort'}, { label: "车道号", prop: "laneSort" },
{label: '排队长度', prop: 'queueLength'}, { label: "排队长度", prop: "queueLength" },
{label: '队首距离', prop: 'teamHeadDistance'}, { label: "队首距离", prop: "teamHeadDistance" },
{label: '队尾距离', prop: 'teamTailDistance'}, { label: "队尾距离", prop: "teamTailDistance" },
{label: '排队车辆数', prop: 'queueNums'}, { label: "排队车辆数", prop: "queueNums" },
{label: '车道内车辆数', prop: 'carNums'}, { label: "车道内车辆数", prop: "carNums" },
{label: '空间占有率', prop: 'vehicleLengthRatio'}, { label: "空间占有率", prop: "vehicleLengthRatio" },
{label: '平均速度', prop: 'speed'}, { label: "平均速度", prop: "speed" },
{label: '车辆分布情况', prop: 'stdSpaceHeadway'}, { label: "车辆分布情况", prop: "stdSpaceHeadway" },
{label: '头车速度', prop: 'headSpeed'}, { label: "头车速度", prop: "headSpeed" },
{label: '末车速度', prop: 'mailSpeed'}, { label: "末车速度", prop: "mailSpeed" },
{label: '头车位置', prop: 'firstCarPosition'}, { label: "头车位置", prop: "firstCarPosition" },
{label: '末车位置', prop: 'endCarPosition'}, { label: "末车位置", prop: "endCarPosition" },
],
includeIndex: [
"queueLength",
"teamHeadDistance",
"teamTailDistance",
"queueNums",
"carNums",
"vehicleLengthRatio",
"speed",
"stdSpaceHeadway",
"headSpeed",
"mailSpeed",
"firstCarPosition",
"endCarPosition",
], ],
includeIndex: ['queueLength', 'teamHeadDistance', 'teamTailDistance', 'queueNums', 'carNums', 'vehicleLengthRatio', 'speed',
'stdSpaceHeadway', 'headSpeed', 'mailSpeed', 'firstCarPosition', 'endCarPosition'],
value1: [], value1: [],
options1: [], options1: [],
listDataCopy: [], listDataCopy: [],
...@@ -120,40 +165,40 @@ export default { ...@@ -120,40 +165,40 @@ export default {
yDatas: [], yDatas: [],
tableData: [], tableData: [],
finalXData: [], finalXData: [],
} };
}, },
computed: { computed: {
computedLaneTableColumn() { computedLaneTableColumn() {
return this.laneTableColumn.filter(item => { return this.laneTableColumn.filter((item) => {
return this.includeIndex.includes(item.prop) return this.includeIndex.includes(item.prop);
}) });
}, },
option() { option() {
let title = { let title = {
show: false show: false,
} };
if (!this.finalXData.length) { if (!this.finalXData.length) {
title = noDataTitle title = noDataTitle;
} }
let series = [] let series = [];
let selected = {} let selected = {};
console.log('1111111111', this.finalXData, this.yDatas) console.log("1111111111", this.finalXData, this.yDatas);
for (let [i, item] of this.yDatas.entries()) { for (let [i, item] of this.yDatas.entries()) {
// let nameReal = this.$store.state.dicts.Direction.find((item) => { // let nameReal = this.$store.state.dicts.Direction.find((item) => {
// return item.code == key; // return item.code == key;
// }).name // }).name
let value = item.name.split('-')[2] let value = item.name.split("-")[2];
let realIndex = this.laneTableColumn.find(columnIndex => { let realIndex = this.laneTableColumn.find((columnIndex) => {
return columnIndex.prop === value return columnIndex.prop === value;
})?.label })?.label;
let nameReal = item.name.replace(value, realIndex) let nameReal = item.name.replace(value, realIndex);
if (value !== 'allFlow') { if (value !== "allFlow") {
selected[nameReal] = false selected[nameReal] = false;
} }
series.push({ series.push({
name: nameReal, name: nameReal,
type: "line", type: "line",
symbol: 'none', symbol: "none",
smooth: true, smooth: true,
// areaStyle: { // areaStyle: {
// color: new echarts.graphic.LinearGradient( // color: new echarts.graphic.LinearGradient(
...@@ -181,7 +226,7 @@ export default { ...@@ -181,7 +226,7 @@ export default {
focus: "series", focus: "series",
}, },
data: item.list.reverse(), data: item.list.reverse(),
}) });
} }
return { return {
title, title,
...@@ -189,11 +234,11 @@ export default { ...@@ -189,11 +234,11 @@ export default {
type: "inside", type: "inside",
}, },
tooltip: { tooltip: {
backgroundColor: 'rgba(0,0,0,0.6)', backgroundColor: "rgba(0,0,0,0.6)",
borderWidth: 0, borderWidth: 0,
textStyle: { textStyle: {
fontSize: getFontSize(12), fontSize: getFontSize(12),
color: 'white', color: "white",
}, },
formatter: function (params) { formatter: function (params) {
if (params && params.length) { if (params && params.length) {
...@@ -201,9 +246,11 @@ export default { ...@@ -201,9 +246,11 @@ export default {
for (let i = 0; i < params.length; i++) { for (let i = 0; i < params.length; i++) {
str += `<p>${params[i].seriesName}&nbsp;&nbsp;:&nbsp;&nbsp;${params[i].value}</p>`; str += `<p>${params[i].seriesName}&nbsp;&nbsp;:&nbsp;&nbsp;${params[i].value}</p>`;
} }
return '<div style="max-height:200px;overflow-y:auto;background-color:rgba(0,0,0,0.6);color:white ">' + return (
'<div style="max-height:200px;overflow-y:auto;background-color:rgba(0,0,0,0.6);color:white ">' +
str + str +
"</div>"; "</div>"
);
} }
}, },
enterable: true, enterable: true,
...@@ -214,7 +261,7 @@ export default { ...@@ -214,7 +261,7 @@ export default {
confine: true, confine: true,
}, },
legend: { legend: {
inactiveColor: 'rgba(255,255,255,0.7)', inactiveColor: "rgba(255,255,255,0.7)",
// selected, // selected,
left: 0, left: 0,
padding: [7, 200, 0, 0], padding: [7, 200, 0, 0],
...@@ -249,9 +296,10 @@ export default { ...@@ -249,9 +296,10 @@ export default {
axisLabel: { axisLabel: {
fontSize: getFontSize(12), fontSize: getFontSize(12),
color: "rgba(126, 139, 166, 1)", color: "rgba(126, 139, 166, 1)",
}, axisPointer: { },
type: 'line' axisPointer: {
} type: "line",
},
}, },
yAxis: { yAxis: {
axisTick: { axisTick: {
...@@ -274,131 +322,130 @@ export default { ...@@ -274,131 +322,130 @@ export default {
}, },
}, },
series: series, series: series,
} };
} },
}, },
mounted() { mounted() {
if (time_config.dataQuery_snapshotTime) { if (time_config.dataQuery_snapshotTime) {
this.dateTimeRange = [ this.dateTimeRange = [
new Date(time_config.dataQuery_snapshotTime[0]), new Date(time_config.dataQuery_snapshotTime[0]),
new Date(time_config.dataQuery_snapshotTime[1]) new Date(time_config.dataQuery_snapshotTime[1]),
]; ];
} else { } else {
this.dateTimeRange = [ this.dateTimeRange = [
new Date( new Date(new Date().setTime(new Date().getTime() - 1000 * 60 * 60)),
new Date().setTime(new Date().getTime() - 1000 * 60 * 60) new Date(),
),
new Date()
]; ];
} }
this.getData() this.getData();
}, },
methods: { methods: {
downloadFileExcel(response) {
let blob = new Blob([response.data], { type: "application/x-xls" });
let a = document.createElement("a");
a.href = URL.createObjectURL(blob);
let fileName = response.headers["content-disposition"].split("=")[1];
fileName = decodeURI(fileName);
a.download = fileName; //文件名称
a.style.display = "none";
document.body.appendChild(a);
a.click();
a.remove();
},
exportLaneExcel() { exportLaneExcel() {
// excel导出下载 // excel导出下载
// exportLane({ exportSnapshot({
// "crossId": this.crossData.crossId, crossId: this.crossData.crossId,
// "end": this.dateTimeRange[1].toLocaleString().replaceAll('/', '-'), end: this.dateTimeRange[1].toLocaleString().replaceAll("/", "-"),
// "start": this.dateTimeRange[0].toLocaleString().replaceAll('/', '-') start: this.dateTimeRange[0].toLocaleString().replaceAll("/", "-"),
// // "end": '2024-02-01 00:00:00', laneId: this.value1.join(","),
// // "start": '2024-02-01 10:00:00', }).then((response) => {
// }).then(response => { this.downloadFileExcel(response);
// let blob = new Blob([response.data], {type: "application/x-xls"}); });
// let a = document.createElement("a");
// a.href = URL.createObjectURL(blob);
// let fileName = response.headers['content-disposition'].split('=')[1]
// fileName = decodeURI(fileName)
// // fileName = fileName+'.xls'
// a.download = fileName; //文件名称
// a.style.display = "none";
// document.body.appendChild(a);
// a.click();
// a.remove();
// })
}, },
lineChangeGetData(isNextPage) { lineChangeGetData(isNextPage) {
this.loading = true this.loading = true;
if (this.value1.length) { if (this.value1.length) {
this.indexOptionValue = ['queueLength'] this.indexOptionValue = ["queueLength"];
let params = { let params = {
"crossId": this.crossData.crossId, crossId: this.crossData.crossId,
"end": this.dateTimeRange[1].toLocaleString().replaceAll('/', '-'), end: this.dateTimeRange[1].toLocaleString().replaceAll("/", "-"),
"start": this.dateTimeRange[0].toLocaleString().replaceAll('/', '-'), start: this.dateTimeRange[0].toLocaleString().replaceAll("/", "-"),
"laneId": this.value1.join(','), laneId: this.value1.join(","),
} };
let optionFlag = '' let optionFlag = "";
if (isNextPage) { if (isNextPage) {
if (isNextPage === 'pre') { if (isNextPage === "pre") {
params = {...params, pageNum: this.currentPage - 1} params = { ...params, pageNum: this.currentPage - 1 };
optionFlag = 'pre' optionFlag = "pre";
} else { } else {
params = {...params, pageNum: this.currentPage + 1} params = { ...params, pageNum: this.currentPage + 1 };
optionFlag = 'next' optionFlag = "next";
} }
} else { } else {
params = {...params, pageNum: 0} params = { ...params, pageNum: 0 };
} }
// 车道级数据 // 车道级数据
getLaneSnapshotIndex(params).then(res => { getLaneSnapshotIndex(params).then((res) => {
console.log('res1快照', res) console.log("res1快照", res);
this.loading = false this.loading = false;
if (res.content && res.content.length) { if (res.content && res.content.length) {
if (optionFlag === 'pre') { if (optionFlag === "pre") {
this.currentPage -= 1 this.currentPage -= 1;
} }
if (optionFlag === 'next') { if (optionFlag === "next") {
this.currentPage += 1 this.currentPage += 1;
} }
this.tableData = res.content.map(row => { this.tableData = res.content.map((row) => {
row.teamHeadDistance = row.teamHeadDistance < 0 ? '--' : row.teamHeadDistance row.teamHeadDistance =
row.teamTailDistance = row.teamTailDistance < 0 ? '--' : row.teamTailDistance row.teamHeadDistance < 0 ? "--" : row.teamHeadDistance;
row.dirName = this.$store.state.dicts.Direction.find(dict => { row.teamTailDistance =
return dict.code == row.dir row.teamTailDistance < 0 ? "--" : row.teamTailDistance;
})?.name row.dirName = this.$store.state.dicts.Direction.find((dict) => {
return row return dict.code == row.dir;
}) })?.name;
this.listDataCopy = JSON.parse(JSON.stringify(this.tableData)) return row;
this.initSelectAndFilterTable1() });
this.listDataCopy = JSON.parse(JSON.stringify(this.tableData));
this.initSelectAndFilterTable1();
this.$nextTick(() => { this.$nextTick(() => {
this.$refs.table.doLayout() this.$refs.table.doLayout();
}) });
} else { } else {
let msg = '' let msg = "";
if (optionFlag === 'pre') { if (optionFlag === "pre") {
msg = '已经是第一页' msg = "已经是第一页";
} }
if (optionFlag === 'next') { if (optionFlag === "next") {
msg = '已经是最后一页' msg = "已经是最后一页";
} }
if (msg) { if (msg) {
this.$message(msg) this.$message(msg);
} else { } else {
this.tableData = res.content this.tableData = res.content;
this.listDataCopy = JSON.parse(JSON.stringify(this.tableData)) this.listDataCopy = JSON.parse(JSON.stringify(this.tableData));
this.initSelectAndFilterTable1() this.initSelectAndFilterTable1();
this.$nextTick(() => { this.$nextTick(() => {
this.$refs.table.doLayout() this.$refs.table.doLayout();
}) });
} }
} }
}) });
} else { } else {
this.loading = false this.loading = false;
this.tableData = [] this.tableData = [];
this.listDataCopy = [] this.listDataCopy = [];
this.initSelectAndFilterTable1() this.initSelectAndFilterTable1();
this.$nextTick(() => { this.$nextTick(() => {
this.$refs.table.doLayout() this.$refs.table.doLayout();
}) });
} }
}, },
// getLaneName(aliasName){ // getLaneName(aliasName){
// let [] aliasName.split('-') // let [] aliasName.split('-')
// }, // },
filterIndexChange() { filterIndexChange() {
this.renderFilterData1() this.renderFilterData1();
}, },
occupancyValue, occupancyValue,
initSelectAndFilterTable1() { initSelectAndFilterTable1() {
...@@ -412,71 +459,75 @@ export default { ...@@ -412,71 +459,75 @@ export default {
// if (this.options1.length) { // if (this.options1.length) {
// this.value1.push(this.options1[0]) // this.value1.push(this.options1[0])
// } // }
this.filterTable1() this.filterTable1();
}, },
filterTable1() { filterTable1() {
this.listDataCopy = this.tableData.filter(item => { this.listDataCopy = this.tableData.filter((item) => {
return this.value1.includes(item.laneId) return this.value1.includes(item.laneId);
}) });
this.renderFilterData1() this.renderFilterData1();
}, },
// 根据筛选后的数据渲染echarts // 根据筛选后的数据渲染echarts
renderFilterData1() { renderFilterData1() {
this.xData = this.listDataCopy.reduce((a, b) => { this.xData = this.listDataCopy.reduce((a, b) => {
// if (!a.includes(b.time)) { // if (!a.includes(b.time)) {
a.push(b.time) a.push(b.time);
// } // }
return a return a;
}, []) }, []);
this.yDatas = [] this.yDatas = [];
let yObj = this.listDataCopy.reduce((a, b) => { let yObj = this.listDataCopy.reduce((a, b) => {
for (let key in b) { for (let key in b) {
if (this.includeIndex.includes(key) && this.indexOptionValue.includes(key)) { if (
let wholeKey = `${b.dirName}-${b.laneSort}-${key}` this.includeIndex.includes(key) &&
this.indexOptionValue.includes(key)
) {
let wholeKey = `${b.dirName}-${b.laneSort}-${key}`;
if (a[wholeKey]) { if (a[wholeKey]) {
a[wholeKey].push(b[key]) a[wholeKey].push(b[key]);
} else { } else {
a[wholeKey] = [b[key]] a[wholeKey] = [b[key]];
} }
} }
} }
return a return a;
}, {}) }, {});
for (let key in yObj) { for (let key in yObj) {
this.yDatas.push({ this.yDatas.push({
name: key, name: key,
list: yObj[key] list: yObj[key],
}) });
} }
// 将x轴时间 等比例缩放为数据点数组长度 // 将x轴时间 等比例缩放为数据点数组长度
let xStart = this.xData[0] let xStart = this.xData[0];
let xEnd = this.xData[this.xData.length - 1] let xEnd = this.xData[this.xData.length - 1];
let rangeAllTime = new Date(xEnd).getTime() - new Date(xStart).getTime() let rangeAllTime = new Date(xEnd).getTime() - new Date(xStart).getTime();
let stepNum = this.xData.length / this.yDatas.length let stepNum = this.xData.length / this.yDatas.length;
let onStepTime = rangeAllTime / stepNum let onStepTime = rangeAllTime / stepNum;
console.log('range', rangeAllTime, stepNum, onStepTime) console.log("range", rangeAllTime, stepNum, onStepTime);
this.finalXData = [] this.finalXData = [];
for (let i = 0; i < stepNum; i++) { for (let i = 0; i < stepNum; i++) {
this.finalXData.push(new Date((new Date(xStart).getTime() + onStepTime * i)).toLocaleString()) this.finalXData.push(
new Date(new Date(xStart).getTime() + onStepTime * i).toLocaleString()
);
} }
}, },
getData() { getData() {
this.value1 = [] this.value1 = [];
if (this.crossData.crossId) { if (this.crossData.crossId) {
// todo 获取当前路口所有车道 根据车道 getData // todo 获取当前路口所有车道 根据车道 getData
initLaneSort({crossId: this.crossData.crossId}).then(res => { initLaneSort({ crossId: this.crossData.crossId }).then((res) => {
this.options1 = res.content this.options1 = res.content;
for (let item of this.options1) { for (let item of this.options1) {
this.value1.push(item.laneId) this.value1.push(item.laneId);
} }
this.lineChangeGetData() this.lineChangeGetData();
}) });
} }
}, },
rowClick(e) { rowClick(e) {
console.log('row', e) console.log("row", e);
}, },
getRowClassName(e) { getRowClassName(e) {
if (e.rowIndex % 2 !== 0) { if (e.rowIndex % 2 !== 0) {
...@@ -485,13 +536,13 @@ export default { ...@@ -485,13 +536,13 @@ export default {
return "row-even"; return "row-even";
} }
}, },
} },
} };
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.custom-select { .custom-select {
width: 280px width: 280px;
} }
.custom-form-label { .custom-form-label {
...@@ -500,11 +551,11 @@ export default { ...@@ -500,11 +551,11 @@ export default {
::v-deep .el-input__inner { ::v-deep .el-input__inner {
border: 1px solid rgba(90, 144, 238, 0.34); border: 1px solid rgba(90, 144, 238, 0.34);
color: white color: white;
} }
::v-deep .el-range-separator { ::v-deep .el-range-separator {
color: white color: white;
} }
label { label {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment