Commit 83aacf1b authored by xinzhedeai's avatar xinzhedeai

add: 新华 剖面 update from liqilin

parent 5afb27b3
ENV = 'development'
# 开发服务器端口配置
VUE_APP_LOCAL_PORT = 8080
VUE_APP_BASE_API = 'http://192.168.2.11:8080'
VUE_APP_LOCAL_API = 'http://192.168.2.37:9003'
\ No newline at end of file
......@@ -19,7 +19,6 @@ selenium-debug.log
*.njsproj
*.sln
*.local
*.env.development
*dist.rar
package-lock.json
......
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- Cesium
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- Cesium
1. CSS
2. JS
-->
<link
rel="stylesheet"
type="text/css"
href="./Cesium/Widgets/widgets.css"
/>
<script type="text/javascript" src="./Cesium/Cesium.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.7.2/proj4.js"></script>
<script src="https://unpkg.com/@turf/turf@6/turf.min.js"></script>
<script src="https://cdn.staticfile.org/echarts/4.3.0/echarts.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<title>露天矿山储量分析系统平台</title>
<style>
body,
div {
padding: 0;
margin: 0;
}
:root {
margin: 0;
padding: 0;
}
#cesiumcontainer {
width: 100vw;
height: 100vh;
position: relative;
overflow: hidden;
}
.btn_h:hover {
border: 1px solid blue;
background-color: rgba(255, 255, 255, 1);
color: blue;
}
.btn_h {
border-radius: 1px !important;
padding: 2.5px 15px !important;
cursor: pointer !important;
}
.btn_point {
position: absolute;
right: 20px;
top: 10px;
z-index: 99999999999999999999;
padding: 0 7px;
font-size: 14px;
cursor: pointer;
border: 1px solid rgba(255, 255, 255, 1);
background-color: blue;
color: #fff;
padding: 3px 15px;
border: 1px solid #fff;
}
.btn_s {
position: absolute;
right: 200px;
top: 10px;
z-index: 99999999999999999999;
padding: 0 7px;
font-size: 14px;
cursor: pointer;
padding: 3px 15px;
border: 1px solid #fff;
font-size: 20px;
background-color: rgba(255, 255, 255, 0.4);
text-decoration: dotted;
box-shadow: 0 0 10px rgba(2558, 2558, 2558, 0.4);
font-weight: 670;
}
.btn_p {
margin: 30px 0;
position: absolute;
right: 20px;
top: 20px;
z-index: 99999999999999999999;
padding: 0 7px;
font-size: 14px;
cursor: pointer;
border: 1px solid rgba(255, 255, 255, 1);
background-color: blue;
color: #fff;
padding: 3px 15px;
border: 1px solid #fff;
}
.btn_r {
margin: 30px 0;
position: absolute;
right: 20px;
top: 60px;
z-index: 99999999999999999999;
padding: 0 7px;
font-size: 14px;
cursor: pointer;
border: 1px solid rgba(255, 255, 255, 1);
background-color: blue;
color: #fff;
padding: 3px 15px;
border: 1px solid #fff;
}
.btn_a {
margin: 30px 0;
position: absolute;
right: 20px;
top: 100px;
z-index: 99999999999999999999;
padding: 0 7px;
font-size: 14px;
cursor: pointer;
border: 1px solid rgba(255, 255, 255, 1);
background-color: blue;
color: #fff;
padding: 3px 15px;
border: 1px solid #fff;
}
.search_box {
margin: 10px 0;
position: absolute;
left: 20px;
top: 10px;
z-index: 99999999999999999999;
padding: 0 7px;
font-size: 14px;
cursor: pointer;
display: flex;
justify-content: start;
}
.btn_ll {
margin: 30px 0;
position: absolute;
right: 20px;
top: 140px;
z-index: 99999999999999999999;
padding: 0 7px;
font-size: 14px;
cursor: pointer;
border: 1px solid rgba(255, 255, 255, 1);
background-color: blue;
color: #fff;
padding: 3px 15px;
border: 1px solid #fff;
}
.btn_lla {
margin: 30px 0;
position: absolute;
right: 20px;
top: 180px;
z-index: 99999999999999999999;
padding: 0 7px;
font-size: 14px;
cursor: pointer;
border: 1px solid rgba(255, 255, 255, 1);
background-color: blue;
color: #fff;
padding: 3px 15px;
border: 1px solid #fff;
}
.cesium-viewer-bottom {
display: none;
}
#_s_btn {
background-color: blue;
color: #fff;
border: none;
cursor: pointer;
font-size: 14px;
margin: 0 10px;
margin-left: 20px;
padding: 3px 15px;
border: 1px solid #fff;
border-radius: 3px;
}
.search_box > div {
display: flex;
justify-content: start;
color: #fff;
align-items: center;
}
.search_box > div > span {
display: flex;
justify-content: start;
margin: 0 10px;
}
.tip_box {
position: sticky;
top: 20px;
height: 20px;
margin: 5px 30px;
background: #000;
border-radius: 15px;
text-align: center;
color: #fff;
}
.echarts_box {
position: fixed;
top: 75px;
left: 35px;
height: 250px;
width: 470px;
z-index: 10000000000000000;
background-color: rgba(0, 0, 0, 0.4);
box-shadow: 0 0 10px #fff;
display: none;
}
.remove {
display: none !important;
}
</style>
</head>
<body>
<div id="cesiumcontainer">
<div></div>
</div>
<script src="./init.js"></script>
<script>
(async () => {
// const _url = "/json_url/static/tileset.json";
const _url = "http://192.168.3.249:8808/static/tileset.json";
const CesiumConfig = {
cesiumcontainer: {
geocoder: false,
homeButton: false,
enableCompass: true, // 启用指南针
animation: false,
enableCompassOuterRing: true, // 启用指南针外环
fullscreenButton: false,
sceneModePicker: false,
timeline: false,
navigationHelpButton: false,
baseLayerPicker: false,
creditContainer: document.createElement("div")
},
defaultAccessToken:
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI2NTE1OTUxOS1jNTc5LTQwNmMtOWU5My1jNTI3NTIyYzAxNTUiLCJpZCI6MjUwODM5LCJpYXQiOjE3Mjk5MjE1MzV9.xromwPD3oA1e0YsWV035DE5KmYvivkC6fxt344vwObA"
};
Cesium.Ion.defaultAccessToken = CesiumConfig.defaultAccessToken;
var subdomains = ["0", "1", "2", "3", "4", "5", "6", "7"];
var viewer = new Cesium.Viewer("cesiumcontainer", {
<link rel="stylesheet" type="text/css" href="./Cesium/Widgets/widgets.css" />
<script type="text/javascript" src="./Cesium/Cesium.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.7.2/proj4.js"></script>
<script src="https://unpkg.com/@turf/turf@6/turf.min.js"></script>
<script src="https://cdn.staticfile.org/echarts/4.3.0/echarts.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<title>露天矿山储量分析系统平台</title>
<style>
body,
div {
padding: 0;
margin: 0;
}
:root {
margin: 0;
padding: 0;
}
#cesiumcontainer {
width: 100vw;
height: 100vh;
position: relative;
overflow: hidden;
}
.btn_h:hover {
border: 1px solid blue;
background-color: rgba(255, 255, 255, 1);
color: blue;
}
.btn_h {
border-radius: 1px !important;
padding: 2.5px 15px !important;
cursor: pointer !important;
}
.btn_point {
position: absolute;
right: 20px;
top: 10px;
z-index: 99999999999999999999;
padding: 0 7px;
font-size: 14px;
cursor: pointer;
border: 1px solid rgba(255, 255, 255, 1);
background-color: blue;
color: #fff;
padding: 3px 15px;
border: 1px solid #fff;
}
.btn_s {
position: absolute;
right: 200px;
top: 10px;
z-index: 99999999999999999999;
padding: 0 7px;
font-size: 14px;
cursor: pointer;
padding: 3px 15px;
border: 1px solid #fff;
font-size: 20px;
background-color: rgba(255, 255, 255, 0.4);
text-decoration: dotted;
box-shadow: 0 0 10px rgba(2558, 2558, 2558, 0.4);
font-weight: 670;
}
.btn_p {
margin: 30px 0;
position: absolute;
right: 20px;
top: 20px;
z-index: 99999999999999999999;
padding: 0 7px;
font-size: 14px;
cursor: pointer;
border: 1px solid rgba(255, 255, 255, 1);
background-color: blue;
color: #fff;
padding: 3px 15px;
border: 1px solid #fff;
}
.btn_r {
margin: 30px 0;
position: absolute;
right: 20px;
top: 60px;
z-index: 99999999999999999999;
padding: 0 7px;
font-size: 14px;
cursor: pointer;
border: 1px solid rgba(255, 255, 255, 1);
background-color: blue;
color: #fff;
padding: 3px 15px;
border: 1px solid #fff;
}
.btn_a {
margin: 30px 0;
position: absolute;
right: 20px;
top: 100px;
z-index: 99999999999999999999;
padding: 0 7px;
font-size: 14px;
cursor: pointer;
border: 1px solid rgba(255, 255, 255, 1);
background-color: blue;
color: #fff;
padding: 3px 15px;
border: 1px solid #fff;
}
.search_box {
margin: 10px 0;
position: absolute;
left: 20px;
top: 10px;
z-index: 99999999999999999999;
padding: 0 7px;
font-size: 14px;
cursor: pointer;
display: flex;
justify-content: start;
}
.btn_ll {
margin: 30px 0;
position: absolute;
right: 20px;
top: 140px;
z-index: 99999999999999999999;
padding: 0 7px;
font-size: 14px;
cursor: pointer;
border: 1px solid rgba(255, 255, 255, 1);
background-color: blue;
color: #fff;
padding: 3px 15px;
border: 1px solid #fff;
}
.btn_lla {
margin: 30px 0;
position: absolute;
right: 20px;
top: 180px;
z-index: 99999999999999999999;
padding: 0 7px;
font-size: 14px;
cursor: pointer;
border: 1px solid rgba(255, 255, 255, 1);
background-color: blue;
color: #fff;
padding: 3px 15px;
border: 1px solid #fff;
}
.cesium-viewer-bottom {
display: none;
}
#_s_btn {
background-color: blue;
color: #fff;
border: none;
cursor: pointer;
font-size: 14px;
margin: 0 10px;
margin-left: 20px;
padding: 3px 15px;
border: 1px solid #fff;
border-radius: 3px;
}
.search_box>div {
display: flex;
justify-content: start;
color: #fff;
align-items: center;
}
.search_box>div>span {
display: flex;
justify-content: start;
margin: 0 10px;
}
.tip_box {
position: sticky;
top: 20px;
height: 20px;
margin: 5px 30px;
background: #000;
border-radius: 15px;
text-align: center;
color: #fff;
}
.echarts_box {
position: fixed;
top: 75px;
left: 35px;
height: 250px;
width: 470px;
z-index: 10000000000000000;
background-color: rgba(0, 0, 0, 0.4);
box-shadow: 0 0 10px #fff;
display: none;
}
.remove {
display: none !important;
}
</style>
</head>
<body>
<div id="cesiumcontainer">
<div></div>
</div>
<script src="./init.js"></script>
<script>
(async () => {
// const _url = "/json_url/static/tileset.json";
const _url = "http://192.168.3.249:8808/static/tileset.json";
const CesiumConfig = {
cesiumcontainer: {
geocoder: false,
homeButton: false,
animation: false,
fullscreenButton: false,
enableCompass: true, // 启用指南针
animation: false,
enableCompassOuterRing: true, // 启用指南针外环
fullscreenButton: false,
sceneModePicker: false,
timeline: false,
navigationHelpButton: false,
baseLayerPicker: false,
enableCompass: true, // 启用指南针
enableZoomControls: false, // 禁用缩放控件
enableDistanceLegend: false // 禁用比例尺
creditContainer: document.createElement("div")
},
defaultAccessToken:
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI2NTE1OTUxOS1jNTc5LTQwNmMtOWU5My1jNTI3NTIyYzAxNTUiLCJpZCI6MjUwODM5LCJpYXQiOjE3Mjk5MjE1MzV9.xromwPD3oA1e0YsWV035DE5KmYvivkC6fxt344vwObA"
};
Cesium.Ion.defaultAccessToken = CesiumConfig.defaultAccessToken;
var subdomains = ["0", "1", "2", "3", "4", "5", "6", "7"];
var viewer = new Cesium.Viewer("cesiumcontainer", {
geocoder: false,
homeButton: false,
animation: false,
fullscreenButton: false,
enableCompass: true, // 启用指南针
enableCompassOuterRing: true, // 启用指南针外环
sceneModePicker: false,
timeline: false,
navigationHelpButton: false,
baseLayerPicker: false,
enableCompass: true, // 启用指南针
enableZoomControls: false, // 禁用缩放控件
enableDistanceLegend: false // 禁用比例尺
});
viewer.scene.globe.depthTestAgainstTerrain = true;
await add3dtiles(viewer);
setTimeout(async () => {
calcTotal();
}, 3000);
const initCesiumMap = () => {
if (!CesiumConfig.defaultAccessToken) return;
};
async function add3dtiles(viewer, url = _url, height = 300) {
const tiles = await Cesium.Cesium3DTileset.fromUrl(url, {
maximumScreenSpaceError: 1,
pickable: true
});
viewer.scene.globe.depthTestAgainstTerrain = true;
await add3dtiles(viewer);
setTimeout(async () => {
calcTotal();
}, 3000);
const initCesiumMap = () => {
if (!CesiumConfig.defaultAccessToken) return;
};
async function add3dtiles(viewer, url = _url, height = 300) {
const tiles = await Cesium.Cesium3DTileset.fromUrl(url, {
maximumScreenSpaceError: 1,
pickable: true
});
// =================================== 乳山露天矿矿山 | S
var boundingSphere = tiles.boundingSphere;
var cartographic = Cesium.Cartographic.fromCartesian(
boundingSphere.center
);
var longitude = cartographic.longitude;
var latitude = cartographic.latitude;
var alt = cartographic.height;
var origin = Cesium.Cartesian3.fromRadians(
cartographic.longitude,
cartographic.latitude,
cartographic.height
);
var alt1 = alt + height;
var offset = Cesium.Cartesian3.fromRadians(longitude, latitude, alt1);
var translate = Cesium.Cartesian3.subtract(
offset,
origin,
new Cesium.Cartesian3()
);
tiles.modelMatrix = Cesium.Matrix4.fromTranslation(translate);
viewer.scene.primitives.add(tiles);
viewer.zoomTo(tiles);
add3dtiles.tiles = tiles;
return tiles;
}
})();
</script>
</body>
</html>
// =================================== 乳山露天矿矿山 | S
var boundingSphere = tiles.boundingSphere;
var cartographic = Cesium.Cartographic.fromCartesian(
boundingSphere.center
);
var longitude = cartographic.longitude;
var latitude = cartographic.latitude;
var alt = cartographic.height;
var origin = Cesium.Cartesian3.fromRadians(
cartographic.longitude,
cartographic.latitude,
cartographic.height
);
var alt1 = alt + height;
var offset = Cesium.Cartesian3.fromRadians(longitude, latitude, alt1);
var translate = Cesium.Cartesian3.subtract(
offset,
origin,
new Cesium.Cartesian3()
);
tiles.modelMatrix = Cesium.Matrix4.fromTranslation(translate);
viewer.scene.primitives.add(tiles);
viewer.zoomTo(tiles);
add3dtiles.tiles = tiles;
return tiles;
}
})();
</script>
</body>
</html>
\ No newline at end of file
......@@ -53,12 +53,12 @@ const formatPos = (arr) => {
for (let i = 0; i < arr.length; i++) {
/**(
*
*
*
*
* 界
* - 清
* - 存
*
*
) */
if (!x) x = arr[i];
......@@ -112,9 +112,9 @@ function calcelatepoduCopy(podupoints) {
/**
* let point1 = podupoints[i];
let point2 = podupoints[i + 1];
*
*
*
*
*
*
* var point1 = turf.point([109.104262, 37.831315]);
var point2 = turf.point([109.104261, 37.831315]);
var bearing = turf.bearing(point1, point2);
......@@ -212,7 +212,7 @@ const initCesiumPoint = (
{ _longitude, _latitude, _height },
{ text, fillColor } = { text: "", fillColor: "" }
) => {
debugger;
if (_height < 15) return;
......@@ -293,7 +293,7 @@ const initCesiumpolyline = (
// if(switchModule.)
const pointConf = {
text: `
text: `
经度 : ${String(_longitude).slice(0, 8)}
纬度 : ${String(_latitude).slice(0, 8)}
高程 : ${String(_height).slice(0, 6)}(米)`,
......@@ -333,8 +333,8 @@ const initCesiumpolyline = (
let { distance, elevationDifference, slopeDegrees, bearing } = opt;
/**
*
*
*
*
* distance: {
name: "距离",
value: distance,
......@@ -351,13 +351,13 @@ const initCesiumpolyline = (
name: "当前轮 - 参数",
value: podupoints,
},
*
*
*
*
*/
/**
*
* text: `
*
* text: `
经度 : ${String(_longitude).slice(0, 8)}
纬度 : ${String(_latitude).slice(0, 8)}
高程 : ${String(_height).slice(0, 6)}(米)`,
......@@ -366,10 +366,9 @@ const initCesiumpolyline = (
const styleOpt = {
text: ` 平距 : ${distance.value}\n 空间距离 : ${Math.sqrt(
distance.value * distance.value +
elevationDifference.value * elevationDifference.value
)}\n 高差 : ${elevationDifference.value}(米)\n 坡度 : ${
slopeDegrees.value
}`,
elevationDifference.value * elevationDifference.value
)}\n 高差 : ${elevationDifference.value}(米)\n 坡度 : ${slopeDegrees.value
}`,
fillColor: Cesium.Color.GREEN,
};
......@@ -432,7 +431,7 @@ const xD = (old, cur) => {
// ================================================================ 模板函数 | S
/**
*
*
// 面
var polyEntity = viewer.entities.add({
name: 'Area Measurement',
......@@ -463,7 +462,7 @@ const xD = (old, cur) => {
}
});
*
*
*/
// ================================================================ 模板函数 | E
......
<!--
<!--
/**
* 表单通用组件
* @example1:
* @example1:
1, 引入
import Slider from '@/components/Slider';
2, 注册
3, 创建
<Carousel
ref="Carousel"
ref="Carousel"
/>
* @author: Kimber
......@@ -19,30 +18,33 @@
*/
-->
<template>
<div class="center-flx">
<nav v-if="list.length > 1">
<a v-for="(child, i) in list" :class="{'actv': viewActive === i}" @click="navEvent(i, child.type)">{{child.sumtitle}}</a>
</nav>
<div class="b2a2_a" id="agentFigure">
<div class="list-wrap" v-for="(child, i) in list" :class="{'show':viewActive === i}">
<div class="b2a2_a1" v-if="child.type === 't_15'" >
<div id="figure" class="figure">
<div class="img-box" id="pictureArea">
<img id="drawingImg">
</div>
<div id="pointsLayer" class="cview_ctn wkk-ctn" :data-index="i" :class="child.className" :data-item="JSON.stringify(child)" :id="child.id">
<ul></ul>
</div>
</div>
</div>
<div v-else>
<div class="cview_ctn ctn-absfull" :data-index="i" :class="child.className" :data-item="JSON.stringify(child)" :id="child.id">
<EZUIKitJs ref="EZUIKit" selectSeat="none" autoPlayer="false"/>
</div>
</div>
</div>
</div>
</div>
<div class="center-flx">
<nav v-if="list.length > 1">
<a v-for="(child, i) in list" :class="{ 'actv': viewActive === i }" @click="navEvent(i, child.type)">{{
child.sumtitle }}</a>
</nav>
<div class="b2a2_a" id="agentFigure">
<div class="list-wrap" v-for="(child, i) in list" :class="{ 'show': viewActive === i }">
<div class="b2a2_a1" v-if="child.type === 't_15'">
<div id="figure" class="figure">
<div class="img-box" id="pictureArea">
<img id="drawingImg">
</div>
<div id="pointsLayer" class="cview_ctn wkk-ctn" :data-index="i" :class="child.className"
:data-item="JSON.stringify(child)" :id="child.id">
<ul></ul>
</div>
</div>
</div>
<div v-else>
<div class="cview_ctn ctn-absfull" :data-index="i" :class="child.className" :data-item="JSON.stringify(child)"
:id="child.id">
<EZUIKitJs ref="EZUIKit" selectSeat="none" autoPlayer="false" />
</div>
</div>
</div>
</div>
</div>
</template>
<script>
//import {Carousel, CarouselItem} from 'element-ui';
......@@ -50,212 +52,506 @@
import EZUIKitJs from '@/components/EZUIKitJs'
export default {
components: { EZUIKitJs },
data() {
return {
list:[],
Cache:{
},
config:{
},
amapinfo:{
zoom:6,
//longitude: 120.651884,
//latitude: 36.962533,
},
viewActive:0,
/* gis:{
isShow:0,
}, */
}
},
props:{
},
beforeCreate(){
},
created(){
},
mounted() {
},
methods: {
createViews(item){
var that = this;
this.list = item.children;this.config.interval = item.interval;
var carouselCtn = this.$el.firstElementChild;
return new Promise((resolve, reject) => {
this.$nextTick(() => {
var chartEls = carouselCtn.querySelectorAll('.cview_ctn');
var panelList = this.setAttribute(chartEls);
resolve(panelList);
});
})
},
setAttribute(charts){
var panelList = [];
for(var el of charts){
var item = JSON.parse(el.dataset.item), type = item.type;
var setData = type === 't_15' ? this.showPointView : this.setPlayInfo;
panelList.push({info:this.Cache[type], el:el, item:item, type:type, setData:setData});
}; return panelList;
},
showPointView(data, Tools, pageApi, initModule){
var that = this;
var agentFigure = this.$el.querySelector("#agentFigure");
this.mapWidget = new qf.UI.pointCharts({
chartsBox:this.$el.querySelector("#figure"),
width:agentFigure.offsetWidth,
height:agentFigure.offsetHeight,
isRelieveAlarm:true,
itemClick: function(id){
var params = {equipno:id};
that.$parent.openRelieveAlarm(params, function(){
initModule()
});
},
});
this.mapWidget.setBackground(data.chart.picture);
this.mapWidget.createPoints(data.points, data.chart);
},
setPlayInfo(param){
var EZUIKit = this.$refs.EZUIKit[0];
EZUIKit.playerToParam(param);
},
navEvent(id, key){
this.viewActive = ~~id;
},
},
components: { EZUIKitJs },
data() {
return {
list: [],
Cache: {
},
config: {
},
amapinfo: {
zoom: 6,
//longitude: 120.651884,
//latitude: 36.962533,
},
viewActive: 0,
/* gis:{
isShow:0,
}, */
}
},
props: {
},
beforeCreate() {
},
created() {
},
mounted() {
},
methods: {
createViews(item) {
var that = this;
this.list = item.children; this.config.interval = item.interval;
var carouselCtn = this.$el.firstElementChild;
return new Promise((resolve, reject) => {
this.$nextTick(() => {
var chartEls = carouselCtn.querySelectorAll('.cview_ctn');
var panelList = this.setAttribute(chartEls);
resolve(panelList);
});
})
},
setAttribute(charts) {
var panelList = [];
for (var el of charts) {
var item = JSON.parse(el.dataset.item), type = item.type;
var setData = type === 't_15' ? this.showPointView : this.setPlayInfo;
panelList.push({ info: this.Cache[type], el: el, item: item, type: type, setData: setData });
}; return panelList;
},
showPointView(data, Tools, pageApi, initModule) {
var that = this;
var agentFigure = this.$el.querySelector("#agentFigure");
this.mapWidget = new qf.UI.pointCharts({
chartsBox: this.$el.querySelector("#figure"),
width: agentFigure.offsetWidth,
height: agentFigure.offsetHeight,
isRelieveAlarm: true,
itemClick: function (id) {
var params = { equipno: id };
that.$parent.openRelieveAlarm(params, function () {
initModule()
});
},
});
this.mapWidget.setBackground(data.chart.picture);
this.mapWidget.createPoints(data.points, data.chart);
},
setPlayInfo(param) {
var EZUIKit = this.$refs.EZUIKit[0];
EZUIKit.playerToParam(param);
},
navEvent(id, key) {
this.viewActive = ~~id;
},
},
}
</script>
<style lang="scss" scope>
.center-flx{
height:100%;width:100%;
display:flex;flex-direction:column;padding:.12rem 0.12rem 0.12rem;
/* padding:0 0.08rem 0.08rem; */
nav{
height:.26rem;text-align:center;color:#89B7C6;font-size:0;user-select:none;margin-top:-0.12rem;
a{
display:inline-block;font-size:.15rem;line-height:.22rem;padding:0 .10rem;
cursor:pointer;border-radius:.05rem .05rem 0 0;
}
.actv{color:#0CE2CE;background-color:#2271C6;};
}
.b2a2_a1{
height:100%;width:100%;position:relative;
>div{
/* display:none; */
}
>div.show{display:block;}
>div:first-child{}
>div:last-child{}
.figure{
position:relative;top:0;left:0;height:100%;width:100%;
user-select:none;font-family:serif;color:#444;
}
.figure{
.img-box{
position:absolute;top:0;left:0;height:100%;width:100%;z-index:10;
img{display:block;border:0;max-height:100%;max-width:100%;}
&:before {
position: absolute;
content: '';
width: 100%;
height: 100%;
top: 0;
left: 0;
box-shadow: inset 0rem 0rem 0.55rem 0.20rem rgba(0,31,60, .8);
}
}
.wkk-ctn{
position:absolute;top:0;left:0;height:100%;width:100%;z-index:20;
}
}
.figure .wkk-ctn{position:absolute;top:0;left:0;height:100%;width:100%;}
.figure .wkk-ctn li{position:absolute;}
.figure .wkk-ctn li::marker{content:close-quote;}
.figure .wkk-ctn li i{
position:absolute;top:0;left:0;height:100%;width:100%;
background-repeat:no-repeat;background-position:center bottom;background-size:contain;
}
.figure .wkk-ctn li.d_01 i{background-image:url('~@/assets/images/icon/d_01.png');}
.figure .wkk-ctn li.d_02 i{background-image:url('~@/assets/images/icon/d_02.png');}
.figure .wkk-ctn li.d_03 i{background-image:url('~@/assets/images/icon/d_03.png');}
.figure .wkk-ctn li.d_04 i{background-image:url('~@/assets/images/icon/d_04.png');}
.figure .wkk-ctn li.d_05 i{background-image:url('~@/assets/images/icon/d_05.png');}
.figure .wkk-ctn li.d_06 i{background-image:url('~@/assets/images/icon/d_06.png');}
.figure .wkk-ctn li.d_07 i{background-image:url('~@/assets/images/icon/d_07.png');}
.figure .wkk-ctn li.d_08 i{background-image:url('~@/assets/images/icon/d_08.png');}
.figure .wkk-ctn li>div{position:absolute;display:flex;align-items:center;justify-content:center;}
.figure .wkk-ctn li>div .text{position:absolute;padding:0.0402rem;background-color:#fff;border-radius:0.0643rem;line-height:1.2;color:#1A688C;font-weight:bold;z-index:1;}
.figure .wkk-ctn .text h4{text-align:center;color:#1284b3;font-weight:normal;}
.figure .wkk-ctn .text dd{display:block;line-height:normal;margin-top:3px;}
.figure .wkk-ctn .text dd:before{font-size:15px;margin-right:3px;}
.figure .wkk-ctn .text .normal:before{font-size:13px;margin-right:1px;}
.figure .wkk-ctn .text .red{background-color:red;color:#fff;}
.figure .wkk-ctn .text .orange{background-color:orange;color:#fff;}
.figure .wkk-ctn .text .yellow{background-color:#e8cb08;color:#fff;}
.figure .wkk-ctn .text .blue{background-color:#0991FF;color:#fff;}
.figure .wkk-ctn .text .relieve{cursor:pointer;}
.figure .wkk-ctn .text .offline{color:#aaa;}
.figure .wkk-ctn .text .online{color:#000;}
/* .figure .wkk-ctn .text .el-icon-info{
animation:twinkle 1100ms infinite;
.center-flx {
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
padding: .12rem 0.12rem 0.12rem;
/* padding:0 0.08rem 0.08rem; */
nav {
height: .26rem;
text-align: center;
color: #89B7C6;
font-size: 0;
user-select: none;
margin-top: -0.12rem;
a {
display: inline-block;
font-size: .15rem;
line-height: .22rem;
padding: 0 .10rem;
cursor: pointer;
border-radius: .05rem .05rem 0 0;
}
.actv {
color: #0CE2CE;
background-color: #2271C6;
}
;
}
.b2a2_a1 {
height: 100%;
width: 100%;
position: relative;
>div {
/* display:none; */
}
>div.show {
display: block;
}
>div:first-child {}
>div:last-child {}
.figure {
position: relative;
top: 0;
left: 0;
height: 100%;
width: 100%;
user-select: none;
font-family: serif;
color: #444;
}
.figure {
.img-box {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
z-index: 10;
img {
display: block;
border: 0;
max-height: 100%;
max-width: 100%;
}
&:before {
position: absolute;
content: '';
width: 100%;
height: 100%;
top: 0;
left: 0;
box-shadow: inset 0rem 0rem 0.55rem 0.20rem rgba(0, 31, 60, .8);
}
}
.wkk-ctn {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
z-index: 20;
}
}
.figure .wkk-ctn {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
}
.figure .wkk-ctn li {
position: absolute;
}
.figure .wkk-ctn li::marker {
content: close-quote;
}
.figure .wkk-ctn li i {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
background-repeat: no-repeat;
background-position: center bottom;
background-size: contain;
}
.figure .wkk-ctn li.d_01 i {
background-image: url('~@/assets/images/icon/d_01.png');
}
.figure .wkk-ctn li.d_02 i {
background-image: url('~@/assets/images/icon/d_02.png');
}
.figure .wkk-ctn li.d_03 i {
background-image: url('~@/assets/images/icon/d_03.png');
}
.figure .wkk-ctn li.d_04 i {
background-image: url('~@/assets/images/icon/d_04.png');
}
.figure .wkk-ctn li.d_05 i {
background-image: url('~@/assets/images/icon/d_05.png');
}
.figure .wkk-ctn li.d_06 i {
background-image: url('~@/assets/images/icon/d_06.png');
}
.figure .wkk-ctn li.d_07 i {
background-image: url('~@/assets/images/icon/d_07.png');
}
.figure .wkk-ctn li.d_08 i {
background-image: url('~@/assets/images/icon/d_08.png');
}
.figure .wkk-ctn li>div {
position: absolute;
display: flex;
align-items: center;
justify-content: center;
}
.figure .wkk-ctn li>div .text {
position: absolute;
padding: 0.0402rem;
background-color: #fff;
border-radius: 0.0643rem;
line-height: 1.2;
color: #1A688C;
font-weight: bold;
z-index: 1;
}
.figure .wkk-ctn .text h4 {
text-align: center;
color: #1284b3;
font-weight: normal;
}
.figure .wkk-ctn .text dd {
display: block;
line-height: normal;
margin-top: 3px;
}
.figure .wkk-ctn .text dd:before {
font-size: 15px;
margin-right: 3px;
}
.figure .wkk-ctn .text .normal:before {
font-size: 13px;
margin-right: 1px;
}
.figure .wkk-ctn .text .red {
background-color: red;
color: #fff;
}
.figure .wkk-ctn .text .orange {
background-color: orange;
color: #fff;
}
.figure .wkk-ctn .text .yellow {
background-color: #e8cb08;
color: #fff;
}
.figure .wkk-ctn .text .blue {
background-color: #0991FF;
color: #fff;
}
.figure .wkk-ctn .text .relieve {
cursor: pointer;
}
.figure .wkk-ctn .text .offline {
color: #aaa;
}
.figure .wkk-ctn .text .online {
color: #000;
}
/* .figure .wkk-ctn .text .el-icon-info{
animation:twinkle 1100ms infinite;
} */
.figure .wkk-ctn li>div .text:before{content:'';position:absolute;height:0;width:0;border-style:solid;border-width:0.0643rem;border-color:transparent;}
.figure .wkk-ctn .up{top:0;left:0;height:0;width:100%;}
.figure .wkk-ctn .up .text{bottom:0.0804rem;width:max-content;}
.figure .wkk-ctn .up .text:before{bottom:-0.1287rem;left:50%;margin-left:-0.0643rem;border-color:#fff transparent transparent transparent;}
.figure .wkk-ctn .down{bottom:0;left:0;height:0;width:100%;}
.figure .wkk-ctn .down .text{top:0.0804rem;width:max-content;}
.figure .wkk-ctn .down .text:before{top:-0.1287rem;left:50%;margin-left:-0.0643rem;border-color:transparent transparent #fff transparent;}
.figure .wkk-ctn .left{top:0;left:0;height:100%;width:0;}
.figure .wkk-ctn .left .text{right:0.0804rem;width:max-content;}
.figure .wkk-ctn .left .text:before{top:50%;right:-0.1287rem;margin-top:-0.0643rem;border-color:transparent transparent transparent #fff;}
.figure .wkk-ctn .right{top:0;right:0;height:100%;width:0;}
.figure .wkk-ctn .right .text{left:0.0804rem;width:max-content;}
.figure .wkk-ctn .right .text:before{top:50%;left:-0.1287rem;margin-top:-0.0643rem;border-color:transparent #fff transparent transparent;}
@keyframes red {
0% {opacity: 1.0;}
12.5% {opacity: 0.2;}
25% {opacity: 1.0;}
}
@keyframes orange {
0% {opacity: 1.0;}
10% {opacity: 0.2;}
20% {opacity: 1.0;}
}
@keyframes yellow {
0% {opacity: 1.0;}
9% {opacity: 0.2;}
18% {opacity: 1.0;}
}
@keyframes blue {
0% {opacity: 1.0;}
7.5% {opacity: 0.2;}
15% {opacity: 1.0;}
}
}
}
div.screenAlart{
.el-message-box__header{
padding:10px 5px 5px 5px;
.el-message-box__headerbtn{color:#eee;top:10px;right:10px;}
}
.kmb-message-box{
background-color:rgba(0,0,0,.7);border:1px solid #00B2FC;
.el-message-box__title{color:#eee;}
.el-message-box__content{color:#ddd;}
}
.alert-ctbox{
.item{line-height:30px;}
span{display:inline-block;width:115px;}
input{height:25px;line-height:25px;outline:none;padding:5px 5px;background:transparent;border:1px solid #aaa;color:#fff;}
input::-webkit-input-placeholder{color:#888;}
}
}
</style>
\ No newline at end of file
.figure .wkk-ctn li>div .text:before {
content: '';
position: absolute;
height: 0;
width: 0;
border-style: solid;
border-width: 0.0643rem;
border-color: transparent;
}
.figure .wkk-ctn .up {
top: 0;
left: 0;
height: 0;
width: 100%;
}
.figure .wkk-ctn .up .text {
bottom: 0.0804rem;
width: max-content;
}
.figure .wkk-ctn .up .text:before {
bottom: -0.1287rem;
left: 50%;
margin-left: -0.0643rem;
border-color: #fff transparent transparent transparent;
}
.figure .wkk-ctn .down {
bottom: 0;
left: 0;
height: 0;
width: 100%;
}
.figure .wkk-ctn .down .text {
top: 0.0804rem;
width: max-content;
}
.figure .wkk-ctn .down .text:before {
top: -0.1287rem;
left: 50%;
margin-left: -0.0643rem;
border-color: transparent transparent #fff transparent;
}
.figure .wkk-ctn .left {
top: 0;
left: 0;
height: 100%;
width: 0;
}
.figure .wkk-ctn .left .text {
right: 0.0804rem;
width: max-content;
}
.figure .wkk-ctn .left .text:before {
top: 50%;
right: -0.1287rem;
margin-top: -0.0643rem;
border-color: transparent transparent transparent #fff;
}
.figure .wkk-ctn .right {
top: 0;
right: 0;
height: 100%;
width: 0;
}
.figure .wkk-ctn .right .text {
left: 0.0804rem;
width: max-content;
}
.figure .wkk-ctn .right .text:before {
top: 50%;
left: -0.1287rem;
margin-top: -0.0643rem;
border-color: transparent #fff transparent transparent;
}
@keyframes red {
0% {
opacity: 1.0;
}
12.5% {
opacity: 0.2;
}
25% {
opacity: 1.0;
}
}
@keyframes orange {
0% {
opacity: 1.0;
}
10% {
opacity: 0.2;
}
20% {
opacity: 1.0;
}
}
@keyframes yellow {
0% {
opacity: 1.0;
}
9% {
opacity: 0.2;
}
18% {
opacity: 1.0;
}
}
@keyframes blue {
0% {
opacity: 1.0;
}
7.5% {
opacity: 0.2;
}
15% {
opacity: 1.0;
}
}
}
}
div.screenAlart {
.el-message-box__header {
padding: 10px 5px 5px 5px;
.el-message-box__headerbtn {
color: #eee;
top: 10px;
right: 10px;
}
}
.kmb-message-box {
background-color: rgba(0, 0, 0, .7);
border: 1px solid #00B2FC;
.el-message-box__title {
color: #eee;
}
.el-message-box__content {
color: #ddd;
}
}
.alert-ctbox {
.item {
line-height: 30px;
}
span {
display: inline-block;
width: 115px;
}
input {
height: 25px;
line-height: 25px;
outline: none;
padding: 5px 5px;
background: transparent;
border: 1px solid #aaa;
color: #fff;
}
input::-webkit-input-placeholder {
color: #888;
}
}
}
</style>
<!--
/**
* 表单通用组件
......@@ -53,75 +52,82 @@
*/
-->
<template>
<!--工具栏-->
<div class="head-container" v-if="form.config.search && form.config.search[0]">
<!-- 搜索 -->
<template v-for="(item, index) in form.config.search">
<label v-if="item.name" class="el-form-item-label">{{item.name}}</label>
<template v-if="item.type==='string'">
<el-input v-model="form.query[item.word]" clearable :placeholder="'请输入'+item.name" :style="'width:'+item.width" @clear="item.clear && item.clear.call(_self.$parent)"/>
</template>
<template v-if="item.type==='select'">
<el-select v-model="form.query[item.word]" :placeholder="'请选择'+item.name" size="small" :style="'width:'+(item.width || 'auto')" :disabled="item.disabled" clearable @change="onEventInfos(item.change)" @clear="item.clear && item.clear.call(_self.$parent)">
<el-option v-for="obj in Dict.selectList[item.word]" :label="obj[item.key] || obj.name" :value="obj[item.val] || obj.value" ></el-option>
</el-select>
</template>
<template v-else-if="item.type === 'checkbox'">
<el-checkbox v-model="form.query[item.word]" :label="item.label"></el-checkbox>
</template>
<template v-else-if="item.type.indexOf('date') > -1">
<el-date-picker
v-model="form.query[item.word]"
:style="'width:'+item.width"
:type="item.type"
:value-format="item.format || 'yyyy-MM-dd'"
:default-time="item.defaultTime"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
clearable
@change="item.change && item.change.call(_self, $event)"
>
</el-date-picker>
</template>
<el-button v-else-if="item.type==='button'" size="mini" :type="item.btntype || 'success'" :icon="item.icon" @click="item.click && item.click.call(_self.$parent, $event)">{{item.label}}</el-button>
</template>
</div>
<!--工具栏-->
<div class="head-container" v-if="form.config.search && form.config.search[0]">
<!-- 搜索 -->
<template v-for="(item, index) in form.config.search">
<label v-if="item.name" class="el-form-item-label">{{ item.name }}</label>
<template v-if="item.type === 'string'">
<el-input v-model="form.query[item.word]" clearable :placeholder="'请输入' + item.name"
:style="'width:' + item.width" @clear="item.clear && item.clear.call(_self.$parent)" />
</template>
<template v-if="item.type === 'select'">
<el-select v-model="form.query[item.word]" :placeholder="'请选择' + item.name" size="small"
:style="'width:' + (item.width || 'auto')" :disabled="item.disabled" clearable
@change="onEventInfos(item.change)" @clear="item.clear && item.clear.call(_self.$parent)">
<el-option v-for="obj in Dict.selectList[item.word]" :label="obj[item.key] || obj.name"
:value="obj[item.val] || obj.value"></el-option>
</el-select>
</template>
<template v-else-if="item.type === 'checkbox'">
<el-checkbox v-model="form.query[item.word]" :label="item.label"></el-checkbox>
</template>
<template v-else-if="item.type.indexOf('date') > -1">
<el-date-picker v-model="form.query[item.word]" :style="'width:' + item.width" :type="item.type"
:value-format="item.format || 'yyyy-MM-dd'" :default-time="item.defaultTime" range-separator="至"
start-placeholder="开始日期" end-placeholder="结束日期" clearable
@change="item.change && item.change.call(_self, $event)">
</el-date-picker>
</template>
<el-button v-else-if="item.type === 'button'" size="mini" :type="item.btntype || 'success'" :icon="item.icon"
@click="item.click && item.click.call(_self.$parent, $event)">{{ item.label }}</el-button>
</template>
</div>
</template>
<script>
export default {
data() {
return {
}
},
props:{
form: {
type: Object,
default: {},
},
Dict: {
type: Object,
default: {},
},
},
beforeCreate(){
},
created(){
},
mounted() {
},
methods: {
onEventInfos:qf.vue.onEventInfos,
},
data() {
return {
}
},
props: {
form: {
type: Object,
default: {},
},
Dict: {
type: Object,
default: {},
},
},
beforeCreate() {
},
created() {
},
mounted() {
},
methods: {
onEventInfos: qf.vue.onEventInfos,
},
}
</script>
<style lang="scss" scope>
.head-container{
.el-form-item-label{
font-weight:500;margin-left:15px;
&:first-child{margin-left:0;}
}
.el-button{margin-left:20px;}
.el-checkbox{margin-right:5px;}
}
.head-container {
.el-form-item-label {
font-weight: 500;
margin-left: 15px;
&:first-child {
margin-left: 0;
}
}
.el-button {
margin-left: 20px;
}
.el-checkbox {
margin-right: 5px;
}
}
</style>
......@@ -8,13 +8,11 @@ import Config from '@/settings'
axios.defaults.withCredentials = true;
//var baseURL = (VUE_APP_API.ServiceURL || process.env.VUE_APP_LOCAL_API) + '/';
var baseURL = process.env.NODE_ENV
=== 'development' ? process.env.VUE_APP_LOCAL_API + '/' : (VUE_APP_API.ServiceURL || process.env.VUE_APP_LOCAL_API) + '/';
var baseURL = process.env.NODE_ENV === 'development' ? process.env.VUE_APP_LOCAL_API + '/' : (process.env.VUE_APP_BASE_API || process.env.VUE_APP_LOCAL_API) + '/';
// 创建axios实例
const service = axios.create({
baseURL: baseURL,
timeout: Config.timeout // 请求超时时间
baseURL: 'http://192.168.2.37:9003',
timeout: Config.timeout // 请求超时时间
})
// request拦截器
......@@ -46,21 +44,21 @@ service.interceptors.response.use(
break
// token 过期
// token 过期
case 401:
Notification({
title: '登录过期,请重新登录',
duration: 2000,
type: 'warning'
})
Notification({
title: '登录过期,请重新登录',
duration: 2000,
type: 'warning'
})
setTimeout(() => {
window.localStorage.removeItem('token')
window.location = '#/';
location.reload()
}, 1000)
setTimeout(() => {
window.localStorage.removeItem('token')
window.location = '#/';
location.reload()
}, 1000)
break
break
default:
break
......
......@@ -60,12 +60,12 @@
import { Tools } from "@/assets/js/common.js";
import { reqApi, Config } from "@/assets/js/httpApi.js";
import { Highchart } from "@/assets/js/chartTemplates.js";
//import cesium from '@/components/Cesium';
import cesium from '@/components/Cesium';
import Carousel from "@/components/Carousel";
import CenterViews from "@/components/CenterViews";
// style
//import '@/../static/js/Cesium/Widgets/widgets.css';
// import '@/../static/js/Cesium/Widgets/widgets.css';
export default {
components: { Carousel, CenterViews },
data() {
......@@ -88,17 +88,17 @@ export default {
var nowTimeEl = this.$el.querySelector("#nowTime");
var Loop1 = qf.Async.intervalLoop(
1000,
function() {
function () {
var dateTime = Tools.Dates.format("yyyy年MM月dd日 HH:mm:ss");
dateTime = dateTime.replace(/年|月|日/g, function(a) {
dateTime = dateTime.replace(/年|月|日/g, function (a) {
return "<span>" + a + "</span>";
});
nowTimeEl.innerHTML = dateTime;
//Loop1.clear();
},
function() {
function () {
var dateTime = Tools.Dates.format("yyyy年MM月dd日 HH:mm:ss");
dateTime = dateTime.replace(/年|月|日/g, function(a) {
dateTime = dateTime.replace(/年|月|日/g, function (a) {
return "<span>" + a + "</span>";
});
nowTimeEl.innerHTML = dateTime;
......@@ -106,7 +106,7 @@ export default {
);
qf(
function() {
function () {
this.initData();
}.bind(this)
);
......@@ -118,7 +118,7 @@ export default {
qf.Async.loopList.call(
this,
list,
function(key, item, next) {
function (key, item, next) {
var alarmDict = [
"",
{ name: "红色报警", color: "red" },
......@@ -146,12 +146,12 @@ export default {
")</div><div>时间:" +
item.time +
'</div><div class="btn-groub" style="margin-top:5px;display:flex;justify-content:center;"><button data-id="0">解除报警</button><button data-id="1" style="margin-left:30px;">关闭报警</button><button data-id="2" style="margin-left:30px;">不再提示</button></div></div>',
onClose: function(v) {
setTimeout(function() {
onClose: function (v) {
setTimeout(function () {
next();
}, ~~(1 + Math.random() * 3) * 1000);
},
onClick: function(tag) {
onClick: function (tag) {
if (tag.nodeName === "BUTTON") {
var self = this,
id = tag.dataset.id;
......@@ -160,11 +160,11 @@ export default {
Notify.pause();
that.openRelieveAlarm(
{ equipno: item.equipno },
function() {
function () {
Notify.close(true);
reqAlarmsPopup();
},
function() {
function () {
Notify.recover();
}
);
......@@ -178,7 +178,7 @@ export default {
width: "350px",
html:
"点击确认后,该条数据仍会处于报警状态,但是不会再提示,您确认要这么做吗?",
confirm: function(el) {
confirm: function (el) {
var parm = { id: item.id };
that.pageApi.alterAbnormal("put", parm).then(res => {
if (res.code === 200) {
......@@ -186,7 +186,7 @@ export default {
}
});
},
close: function() {
close: function () {
Notify.recover();
}
});
......@@ -199,8 +199,8 @@ export default {
}
});
},
function() {
setTimeout(function() {
function () {
setTimeout(function () {
reqAlarmsPopup();
}, 15000);
}
......@@ -223,7 +223,7 @@ export default {
// onload
this.$nextTick(() => {
new qf.Async.intervalLoop(600000, function() {
new qf.Async.intervalLoop(600000, function () {
// 加载数据
self.loadViewData(self.area.views);
});
......@@ -260,7 +260,7 @@ export default {
Tools.asyncLoop.call(
this,
panels,
function(key, panel, next) {
function (key, panel, next) {
var item = panel.item,
param = {
range: item.range,
......@@ -341,13 +341,13 @@ export default {
}
},
/*
plotOptions: {
series: {
stacking: 'normal'
}
}, */
plotOptions: {
series: {
stacking: 'normal'
}
}, */
tooltip: {
formatter: function() {
formatter: function () {
return (
this.series.name +
"" +
......@@ -359,7 +359,7 @@ export default {
}
}
},
callback: function(key, extend, give) {
callback: function (key, extend, give) {
if (
key === "series" &&
give[key].constructor.name === "Array"
......@@ -376,9 +376,9 @@ export default {
}
};
Highchart.template.high(panel.el, data, opts);
// 新增:给图表外围容器添加点击事件
panel.el.addEventListener("click", () => {
// 新增:给图表外围容器添加点击事件
panel.el.addEventListener("click", () => {
const deviceId = panel.item.deviceid;
if (deviceId) {
window.open(
......@@ -530,7 +530,7 @@ export default {
var div = document.createElement("div");
// 2024/8/10(周六) 为了缩减设备名称, 类型名称过长超出边界,添加对类型过滤
var name = types.find(function(val, i) {
var name = types.find(function (val, i) {
if (item.sensroname.includes(val)) {
return 1;
}
......@@ -591,7 +591,7 @@ export default {
}
},
tooltip: {
formatter: function(e) {
formatter: function (e) {
return this.key + ":" + this.y;
}
},
......@@ -710,7 +710,7 @@ export default {
var param = { c: "code", a: "getcode", id: 48, icon: 1, py: city };
reqApi.getWeather(param).then(res => {
var body = document.createElement("div");
setTimeout(function() {
setTimeout(function () {
body.innerHTML = res;
var styles = body.querySelectorAll("link");
for (var style of styles) {
......@@ -772,10 +772,10 @@ export default {
};
initModule();
/* new qf.Async.intervalLoop(30000, function(){
initModule();
}, function(){
initModule();
}) */
initModule();
}, function(){
initModule();
}) */
} else if (type === "t_16") {
// 外坡比
reqApi.common.requstEdge("get", item.requrl, param).then(res => {
......@@ -809,7 +809,7 @@ export default {
const img = document.createElement("img");
img.src = "/static/jrx.png";
img.style.cssText =
"width:100%;height:100%;object-fit:contain;cursor:pointer";
"width:95%;height:95%;object-fit:contain;cursor:pointer;margin: 10px 10px";
img.addEventListener("click", () => {
this.openImagePopup(imgId, img.src);
});
......@@ -818,7 +818,7 @@ export default {
}
next();
},
function() {}
function () { }
);
},
// 点击图片方法
......@@ -828,7 +828,7 @@ export default {
},
cuCharts(ctn, data, opts) {
//
var cuCharts = function(ctn, data, opts) {
var cuCharts = function (ctn, data, opts) {
var ctn = (this.ctn =
typeof element === "string" ? document.getElementById(ctn) : ctn);
if (!ctn)
......@@ -881,11 +881,11 @@ export default {
this.init();
};
cuCharts.prototype = {
init: function() {
init: function () {
this.setModule();
this.onresize();
},
drawAxis: function(color, damHeight) {
drawAxis: function (color, damHeight) {
var lw = this.options.axisLineWidth;
var wHalf = lw / 2;
var initX = this.options.initX;
......@@ -924,7 +924,7 @@ export default {
color: color
});
},
drawSteps: function(ladders) {
drawSteps: function (ladders) {
ladders = ladders || [0];
var initX = this.options.initX,
initY = this.options.initY;
......@@ -1014,7 +1014,7 @@ export default {
var damHeight = (cumulationY - this.options.initY) / pxRetioY;
return (maxStepDepth.damHeight = damHeight), maxStepDepth;
},
drawDevice: function(list) {
drawDevice: function (list) {
var lineW = 4 * this.dpr,
deviceW = 6 * this.dpr,
deviceH = 3 * this.dpr;
......@@ -1078,7 +1078,7 @@ export default {
});
}
},
drawAlarmLine: function(alarms, Steps) {
drawAlarmLine: function (alarms, Steps) {
var alarmValues = alarms.value;
var alarmLevel = alarms.alarmLevel;
var deviceCoords = this.options.deviceCoords || [];
......@@ -1122,10 +1122,10 @@ export default {
}
}
},
getCirHeightDev: function(r, x) {
getCirHeightDev: function (r, x) {
return r - Math.sqrt(Math.pow(r, 2) - Math.pow(x, 2));
},
drawWaterArea: function(depth) {
drawWaterArea: function (depth) {
depth = 100;
var startAngle = this.options.waterArea.startAngle;
var radiusMultiple = this.options.waterArea.radius;
......@@ -1171,7 +1171,7 @@ export default {
ctx.fillStyle = "#00A2E8";
ctx.fill();
},
byAngleAndHeightToCoord: function(angle, height) {
byAngleAndHeightToCoord: function (angle, height) {
var devX = Math.tan(angle * 0.017453293) * height;
var xy = height / Math.cos(angle * 0.017453293);
var devY = height - devX;
......@@ -1197,7 +1197,7 @@ export default {
var averageHeight = (damHeight - sum) / not;
return { averageHeight: averageHeight, damHeight: damHeight };
},
setModule: function() {
setModule: function () {
this.ctx.clearRect(0, 0, this.SumWidth, this.SumHeight);
var canvas = this.canvas;
var SumWidth = (this.SumWidth =
......@@ -1230,7 +1230,7 @@ export default {
this.options["HWRation"] = (endY - top) / (endX - left);
this.drawChart();
},
formatDeviceParam: function(devices) {
formatDeviceParam: function (devices) {
var devices = devices || [];
var arr = [];
for (var item of devices) {
......@@ -1244,7 +1244,7 @@ export default {
}
return arr;
},
getAlarmRealParam: function(aValues) {
getAlarmRealParam: function (aValues) {
var aval = aValues[0];
var coords = this.options.deviceCoords || [];
var valY = aval * this.options.pxRetioY;
......@@ -1259,7 +1259,7 @@ export default {
}
return { ratio: (ey - sy) / (ex - sx), sy: sy, ey: ey };
},
drawChart: function() {
drawChart: function () {
var Steps = this.drawSteps(this.ladders);
this.drawAxis(this.options.axisColor, Steps.damHeight);
var depth = 55;
......@@ -1267,18 +1267,18 @@ export default {
this.drawDevice(this.devices);
this.drawAlarmLine(this.options.alarm, Steps);
},
onresize: function() {
onresize: function () {
qf.resize(() => {
this.setModule();
});
},
updateData: function(data) {
updateData: function (data) {
data = data || {};
this.stations = data.stations || this.stations;
this.points = data.points || this.points;
this.draw(this.cacheX + this.destX, true);
},
drawLiner: function(o) {
drawLiner: function (o) {
var ctx = this.ctx;
ctx.beginPath();
ctx.moveTo(o.sx, o.sy);
......@@ -1287,7 +1287,7 @@ export default {
ctx.strokeStyle = o.color;
ctx.stroke();
},
drawText: function(o) {
drawText: function (o) {
var ctx = this.ctx;
var fontSize = (o.size || 14) * this.dpr;
var text = o.text || "";
......@@ -1339,21 +1339,21 @@ export default {
ctx.fillText(rows[b], ~~lsx + 0.5, y + ~~lsy + 0.5);
}
},
getTextWidth: function(text, fontSize) {
getTextWidth: function (text, fontSize) {
return (
(this.ctx.measureText(text).width / parseInt(this.ctx.font)) *
fontSize
);
},
drawImg: function(img, x, y, w, h) {
drawImg: function (img, x, y, w, h) {
x = x - w / 2;
y = y - h;
ctx.drawImage(img, x, y, w, h);
},
getRandomColor: function() {
getRandomColor: function () {
return "#" + Math.floor(Math.random() * 16777215).toString(16);
},
getEventTarget: function(x, y) {
getEventTarget: function (x, y) {
if (y > bottomReferY - imgA.height - 1 && y < bottomReferY + 1) {
var arr = this.points;
var i = arr.length - 1,
......@@ -1381,7 +1381,7 @@ export default {
}
}
},
xPixelToStepsYPixel: function(x) {
xPixelToStepsYPixel: function (x) {
var ladders = this.Cache.ladders || [],
ladderSY = 0;
for (var ladder of ladders) {
......@@ -1402,7 +1402,7 @@ export default {
return new cuCharts(ctn, data, opts);
},
mapOnload() {},
mapOnload() { },
openRelieveAlarm(params, fn, close) {
var self = this;
......@@ -1412,7 +1412,7 @@ export default {
closeBtnColor: "#eee",
html:
'<div class="item"><span>解除时长(小时):</span><input data-name="jchours" value=12 placeholder="请输入解除时长"/></div><div class="item"><span>报警原因:</span><input data-name="reason" placeholder="报警原因"/></div><div class="item"><span>解除报警原因:</span><input data-name="jcreason" placeholder="解除报警原因"/></div>',
confirm: function(el) {
confirm: function (el) {
var inputs = el.querySelectorAll("input");
for (var el of inputs) {
var key = el.dataset.name;
......@@ -1431,7 +1431,7 @@ export default {
fn && fn();
});
},
close: function() {
close: function () {
close && close();
}
});
......@@ -1445,6 +1445,7 @@ export default {
font-family: "diget year";
src: url("~@/assets/fonts/DS-Digital.ttf");
}
.font_digit {
font-family: diget year;
}
......@@ -1460,24 +1461,27 @@ export default {
.b_0 {
position: absolute;
}
> .actv {
>.actv {
display: block;
}
.a_0 {
top: 0;
left: 0;
height: 100%;
width: 100%;
background: no-repeat center center
url("~@/assets/images/layout/s_bg_min.png");
background: no-repeat center center url("~@/assets/images/layout/s_bg_min.png");
background-size: 100% 100%;
}
.b_0 {
display: flex;
width: 100%;
height: 100%;
padding-top: 0.65rem;
background-color: rgba(0, 0, 0, 0.15);
header {
position: absolute;
top: 0;
......@@ -1487,32 +1491,32 @@ export default {
z-index: 5;
display: flex;
user-select: none;
.b1_a {
position: absolute;
top: 0;
left: 0;
height: 0.64rem;
width: 100%;
background: no-repeat top left
url("~@/assets/images/layout/s_hd_min.png");
background: no-repeat top left url("~@/assets/images/layout/s_hd_min.png");
background-size: 100% auto;
display: flex;
justify-content: center;
align-items: center;
h2 {
font-size: 0.32rem;
line-height: 1;
margin-top: -0.04rem;
background-image: -webkit-linear-gradient(
top,
#fff,
#d5f3fe,
#7adbfe
);
background-image: -webkit-linear-gradient(top,
#fff,
#d5f3fe,
#7adbfe);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
letter-spacing: 0.02rem;
}
.b1_a1 {
position: absolute;
top: 0;
......@@ -1522,10 +1526,12 @@ export default {
display: flex;
align-items: center;
justify-content: left;
.font_digit {
margin-right: 0.2rem;
font-size: 0.28rem;
color: #2ef4ee;
span {
font-family: serif;
font-size: 0.24rem;
......@@ -1533,6 +1539,7 @@ export default {
}
}
}
.b1_a2 {
position: absolute;
top: 0;
......@@ -1540,6 +1547,7 @@ export default {
height: 100%;
display: flex;
align-items: center;
&:before {
content: "";
display: block;
......@@ -1556,6 +1564,7 @@ export default {
flex: 1;
position: relative;
margin: 0 0.08rem;
.b_2a {
position: absolute;
top: 0;
......@@ -1572,17 +1581,20 @@ export default {
.b2_a1,
.b2_a3 {
flex: 1;
> div {
>div {
//background-color:pink;
flex: 1;
}
}
.b2_a1,
.b2_a2,
.b2_a3 {
display: flex;
flex-direction: column;
> div {
>div {
margin-bottom: 0.08rem;
}
}
......@@ -1590,19 +1602,23 @@ export default {
.b2_a2 {
width: 8.84rem;
margin: 0 0.08rem;
> div:first-child {
>div:first-child {
height: 7.52rem;
/* background-color:yellow; */
box-shadow: inset 0rem 0rem 0.15rem 0.24rem rgba(2, 43, 80, 0.8);
}
> div:last-child {
>div:last-child {
//height:2.46rem;
flex: 1;
display: flex;
//height:22.777vh;
> div {
>div {
flex: 1;
margin-right: 0.08rem;
//background-color:pink;
&:last-child {
margin-right: 0;
......@@ -1613,8 +1629,9 @@ export default {
.b2a2_a {
flex: 1;
position: relative;
/* background:no-repeat center center url('~@/assets/images/layout/map_min.png');background-size:100% auto; */
> div {
>div {
display: none;
position: absolute;
top: 0;
......@@ -1622,20 +1639,22 @@ export default {
height: 100%;
width: 100%;
}
> div.show {
>div.show {
display: block;
}
> div:first-child {
}
>div:first-child {}
}
}
.b2_a3 {
}
.b2_a3 {}
.view-item {
border: 1px solid #004a8b;
position: relative;
box-shadow: inset 0rem 0rem 0.15rem 0.04rem rgba(10, 106, 180, 0.8);
&:before,
&:after,
.view-flx:before,
......@@ -1648,18 +1667,22 @@ export default {
border-style: solid;
border-color: #02f6ff;
}
&:before,
&:after {
top: -1px;
}
&:before {
left: -1px;
border-width: 0.02rem 0 0 0.02rem;
}
&:after {
right: -1px;
border-width: 0.02rem 0.02rem 0 0;
}
.view-flx {
position: absolute;
top: 0;
......@@ -1667,14 +1690,17 @@ export default {
height: 100%;
width: 100%;
background-color: rgb(1, 19, 70, 0.3);
&:before,
&:after {
bottom: -1px;
}
&:before {
left: -1px;
border-width: 0 0 0.02rem 0.02rem;
}
&:after {
right: -1px;
border-width: 0 0.02rem 0.02rem 0;
......@@ -1685,34 +1711,42 @@ export default {
.weather {
font-size: 11px;
.mleft {
display: none;
}
.wtpath {
display: none;
}
.mright {
flex: 1;
text-align: center;
}
img {
display: block;
width: 2vw !important;
height: auto !important;
margin: 0 auto;
}
ul {
margin: 5px 0;
color: #d0d2ff;
}
#mobile05 {
display: flex;
position: relative;
padding-top: 5vh !important;
}
#mobile05 > div:last-child {
#mobile05>div:last-child {
display: none;
}
#mright_1 {
position: absolute;
top: 0;
......@@ -1720,18 +1754,22 @@ export default {
height: auto;
width: 100%;
display: flex;
ul {
margin: 0;
color: #03d3fe;
}
.wt {
display: flex;
align-items: center;
margin-left: 140px;
}
.day {
display: none;
}
span:last-child {
display: block;
position: absolute;
......@@ -1740,6 +1778,7 @@ export default {
height: auto;
font-size: 26px;
}
font {
margin: 6px 0 0 10px;
color: #35ecfa;
......
<template>
<div class="common-page qyzz page-t1">
<div class="option page-row">
<table-filter
ref="filter"
:form="form"
:Dict="Dict"
:rules="rules"
:config="form.config"
:loadData="loadData"
/>
<table-filter ref="filter" :form="form" :Dict="Dict" :rules="rules" :config="form.config" :loadData="loadData" />
</div>
<div class="new-container" style="display: flex">
<div class="canvas-wrapper" style="width: 1000px;">
<!-- 替换为 Canvas 元素 -->
<canvas
ref="canvas"
id="mainCanvas"
width="1000"
style="background: #f0f0f0"
></canvas>
<canvas ref="canvas" id="mainCanvas" width="1000" style="background: #f0f0f0"></canvas>
</div>
<div class="chart-wrapper" style="padding-left: 0px;">
<div
ref="chartContainer"
style="width: 870px; height: 550px; margin-bottom: 20px;border:1px solid gainsboro;"
></div>
<div ref="chartContainer" style="width: 870px; height: 550px; margin-bottom: 20px;border:1px solid gainsboro;">
</div>
<div class="chart-btn-group">
<button
size="small"
:type="currentChartType === 'line' ? 'primary' : ''"
@click="switchChartType('line')"
>
<button size="small" :type="currentChartType === 'line' ? 'primary' : ''" @click="switchChartType('line')">
折线图
</button>
<button
size="small"
:type="currentChartType === 'column' ? 'primary' : ''"
@click="switchChartType('column')"
>
<button size="small" :type="currentChartType === 'column' ? 'primary' : ''"
@click="switchChartType('column')">
柱状图
</button>
</div>
......@@ -51,49 +30,24 @@
<div class="content-fix">
<div class="toolbar">
<div>
<el-button
v-for="(item, key) in form.config.otherBtn"
size="mini"
:type="item.type"
:icon="item.icon"
@click="item.callback.call(_self, $event)"
>{{ item.name }}</el-button
>
<el-button v-for="(item, key) in form.config.otherBtn" size="mini" :type="item.type" :icon="item.icon"
@click="item.callback.call(_self, $event)">{{ item.name }}</el-button>
</div>
<div>
<el-button
v-for="(item, key) in form.config.rightBtn"
size="mini"
:type="item.type"
:icon="item.icon"
@click="item.callback.call(_self, $event)"
>{{ item.name }}</el-button
>
<el-button v-for="(item, key) in form.config.rightBtn" size="mini" :type="item.type" :icon="item.icon"
@click="item.callback.call(_self, $event)">{{ item.name }}</el-button>
</div>
</div>
<!-- 表格渲染 -->
<cu-table
ref="cuTable"
:table="table"
:Dict="Dict"
:config="form.config"
:loadData="loadData"
/>
<cu-table ref="cuTable" :table="table" :Dict="Dict" :config="form.config" :loadData="loadData" />
</div>
</div>
</div>
</div>
<!-- 表单渲染 -->
<cu-form
ref="cuForm"
:form="form"
:Dict="Dict"
:rules="rules"
:submit="submitForm"
:cancel="cancelForm"
:watchKeys="['paperfilename']"
/>
<cu-form ref="cuForm" :form="form" :Dict="Dict" :rules="rules" :submit="submitForm" :cancel="cancelForm"
:watchKeys="['paperfilename']" />
</div>
</template>
......@@ -296,9 +250,9 @@ export default {
// 获取选择列表字典
var selectList = this.Dict.selectList;
Tools.asyncLoop.call(this, selectList, function(key, value, next) {
Tools.asyncLoop.call(this, selectList, function (key, value, next) {
if (typeof value === "function") {
value.call(this.Dict).then(function(res) {
value.call(this.Dict).then(function (res) {
selectList[key] = res;
next();
});
......@@ -317,8 +271,8 @@ export default {
});
},
methods: {
getCanvasData(){
getCanvasData() {
const params = {}
request({
url: "tab/jrx/dissect/visual-xinHua",
......@@ -333,74 +287,74 @@ export default {
})
},
handleCanvasData(list = []) {
// 新增:动态调整Canvas尺寸 目前支持7层。
const poCount = list[0].jrxStepsDtoList.length;
const lineCount = 5;
let canvasWidth = 1000; // 默认宽度
let canvasHeight = 600; // 默认高度
if (poCount > 4) {
canvasHeight = poCount * 150; // 高度 = 个数 × 150px
// canvasWidth = 1000 + (poCount - 4) * 150; // 宽度 = 原宽度 + (个数-4)×150px
}
// 新增:动态调整Canvas尺寸 目前支持7层。
const poCount = list[0].jrxStepsDtoList.length;
const lineCount = 5;
let canvasWidth = 1000; // 默认宽度
let canvasHeight = 600; // 默认高度
if (poCount > 4) {
canvasHeight = poCount * 150; // 高度 = 个数 × 150px
// canvasWidth = 1000 + (poCount - 4) * 150; // 宽度 = 原宽度 + (个数-4)×150px
}
// 更新Canvas元素属性和样式
const canvasEl = this.$refs.canvas;
if (canvasEl) {
// 实际绘图区域尺寸(关键属性)
canvasEl.width = canvasWidth;
canvasEl.height = canvasHeight;
// 显示尺寸(与绘图区域保持一致)
canvasEl.style.width = `${canvasWidth}px`;
canvasEl.style.height = `${canvasHeight}px`;
}
// 更新Canvas元素属性和样式
const canvasEl = this.$refs.canvas;
if (canvasEl) {
// 实际绘图区域尺寸(关键属性)
canvasEl.width = canvasWidth;
canvasEl.height = canvasHeight;
// 显示尺寸(与绘图区域保持一致)
canvasEl.style.width = `${canvasWidth}px`;
canvasEl.style.height = `${canvasHeight}px`;
}
// 数据清洗
const po_pad_right = poCount > 4 ? 130 : 180; // 第一个台阶距离画布的距离
const poH = 150;
const line_color = ["red", "yellow", "green", "blue", "white"];
this.canvasData.poConfigs = [];
this.canvasData.guanConfigs = [];
this.canvasData.lineConfigs = [];
for (let index = 0; index < poCount; index++) {
// 坡数据数据格式处理
this.poConfigs.push({
x: 0,
y: canvasHeight - (index + 1) * poH,
width: canvasWidth - (index + 1) * po_pad_right,
height: poH
});
// 管孔数据数据格式处理
this.guanConfigs.push({
x: this.poConfigs[index].width * 0.75,
y: canvasHeight - this.poConfigs[index].height * (index + 1) + 30,
width: 6,
height: index == 0 ? 100 : 200,
image: "guanImage"
});
}
// 数据清洗
const po_pad_right = poCount > 4 ? 130 : 180; // 第一个台阶距离画布的距离
const poH = 150;
const line_color = ["red", "yellow", "green", "blue", "white"];
this.canvasData.poConfigs = [];
this.canvasData.guanConfigs = [];
this.canvasData.lineConfigs = [];
for (let index = 0; index < poCount; index++) {
// 坡数据数据格式处理
this.poConfigs.push({
x: 0,
y: canvasHeight - (index + 1) * poH,
width: canvasWidth - (index + 1) * po_pad_right,
height: poH
});
// 管孔数据数据格式处理
this.guanConfigs.push({
x: this.poConfigs[index].width * 0.75,
y: canvasHeight - this.poConfigs[index].height * (index + 1) + 30,
width: 6,
height: index == 0 ? 100 : 200,
image: "guanImage"
});
}
// 警戒线逻辑- 初始化4条线
for (let index1 = 0; index1 < lineCount; index1++) {
this.lineConfigs.push({
// 设置
points: [],
color: line_color[index1],
lineWidth: 2,
cha: 20 * index1 // 每条线之间的差值
});
}
// 警戒线逻辑- 初始化4条线
for (let index1 = 0; index1 < lineCount; index1++) {
this.lineConfigs.push({
// 设置
points: [],
color: line_color[index1],
lineWidth: 2,
cha: 20 * index1 // 每条线之间的差值
});
}
// 警戒线种类下,根据管孔个数,设定对应的坐标点
this.lineConfigs.forEach((line, index) => {
// 几个管孔几个坐标点
this.guanConfigs.forEach((guan, subindex) => {
line.points.push({
x: guan.x + 1,
y: guan.y + 30 + line.cha
// 警戒线种类下,根据管孔个数,设定对应的坐标点
this.lineConfigs.forEach((line, index) => {
// 几个管孔几个坐标点
this.guanConfigs.forEach((guan, subindex) => {
line.points.push({
x: guan.x + 1,
y: guan.y + 30 + line.cha
});
});
});
});
},
// 处理canvas数据
handleCanvasData1(list = []) {
......@@ -418,7 +372,7 @@ export default {
for (let index = 0; index < tjNumber; index++) {
canvasData.poConfigs.push({
x: 0,
y: 600- (150 * index),
y: 600 - (150 * index),
width: 879 - 250 * index,
height: 150
});
......@@ -850,13 +804,13 @@ export default {
// discern
var levelDist = [
{ color: "red", name: "红色报警线" },
{ color: "orange", name: "橙色报警线" },
{ color: "yellow", name: "黄色报警线" },
{ color: "blue", name: "蓝色报警线" }
],
{ color: "red", name: "红色报警线" },
{ color: "orange", name: "橙色报警线" },
{ color: "yellow", name: "黄色报警线" },
{ color: "blue", name: "蓝色报警线" }
],
alarmLine = {},
setAlarmSerie = function(value, name, color) {
setAlarmSerie = function (value, name, color) {
// 修改蓝色色值
color === "blue" && (color = "#3BAFFB");
var sx = list[0].date,
......@@ -903,16 +857,16 @@ export default {
};
/* 智能报警线
var level = (~~alarms.alarmLevel || levelDist.length+1) - 1;
var nearLevel = level ? level - 1 : level;
var alarm = levelDist[level];
var nearAlarm = levelDist[nearLevel];
nearAlarm.value = value[nearAlarm.color];
alarmLine[nearAlarm.color] = nearAlarm;
if(alarm){
alarm.value = value[alarm.color];
alarmLine[alarm.color] = alarm;
}; */
var level = (~~alarms.alarmLevel || levelDist.length+1) - 1;
var nearLevel = level ? level - 1 : level;
var alarm = levelDist[level];
var nearAlarm = levelDist[nearLevel];
nearAlarm.value = value[nearAlarm.color];
alarmLine[nearAlarm.color] = nearAlarm;
if(alarm){
alarm.value = value[alarm.color];
alarmLine[alarm.color] = alarm;
}; */
// 多条报警线
for (var item of levelDist) {
......@@ -940,7 +894,7 @@ export default {
});
}
},
loadData: function() {
loadData: function () {
console.log(this.form, "form");
this.initChart1();
......@@ -956,6 +910,5 @@ export default {
};
</script>
<style rel="stylesheet/scss" lang="scss" scope>
.qyzz {
}
.qyzz {}
</style>
<template>
<div class="common-page qyzz page-t1">
<div class="option page-row">
<table-filter
ref="filter"
:form="form"
:Dict="Dict"
:rules="rules"
:config="form.config"
:loadData="loadData"
/>
</div>
<div class="new-container" style="display: flex">
<div class="canvas-wrapper" style="width: 1000px">
<!-- 替换为 Canvas 元素 -->
<canvas
ref="canvas"
id="mainCanvas"
width="1000"
style="background: #f0f0f0"
></canvas>
</div>
<div class="chart-wrapper" style="padding-left: 0px">
<div
ref="chartContainer"
style="
width: 870px;
height: 550px;
margin-bottom: 20px;
border: 1px solid gainsboro;
"
></div>
<div class="chart-btn-group">
<button
size="small"
:type="currentChartType === 'line' ? 'primary' : ''"
@click="switchChartType('line')"
>
折线图
</button>
<button
size="small"
:type="currentChartType === 'column' ? 'primary' : ''"
@click="switchChartType('column')"
>
柱状图
</button>
</div>
</div>
</div>
<div class="panel-bottom page-row">
<div class="ctin-box">
<div class="content-within">
<div class="content-fix">
<div class="toolbar">
<div>
<el-button
v-for="(item, key) in form.config.otherBtn"
size="mini"
:type="item.type"
:icon="item.icon"
@click="item.callback.call(_self, $event)"
>{{ item.name }}</el-button
>
</div>
<div>
<el-button
v-for="(item, key) in form.config.rightBtn"
size="mini"
:type="item.type"
:icon="item.icon"
@click="item.callback.call(_self, $event)"
>{{ item.name }}</el-button
>
</div>
</div>
<!-- 表格渲染 -->
<cu-table
ref="cuTable"
:table="table"
:Dict="Dict"
:config="form.config"
:loadData="loadData"
/>
</div>
</div>
</div>
</div>
<!-- 表单渲染 -->
<cu-form
ref="cuForm"
:form="form"
:Dict="Dict"
:rules="rules"
:submit="submitForm"
:cancel="cancelForm"
:watchKeys="['paperfilename']"
/>
</div>
</template>
<script>
import Highcharts from "highcharts";
import { reqApi, Config } from "@/assets/js/httpApi.js";
import { Tools } from "@/assets/js/common.js";
import DateRangePicker from "@/components/DateRangePicker";
import TableFilter from "@/components/TableFilter";
import cuForm from "@/components/cuForm";
import cuTable from "@/components/cuTable";
import request from "@/utils/request";
export default {
name: "Dashboard",
components: {
DateRangePicker,
TableFilter,
cuForm,
cuTable,
},
data() {
return {
chartDataEmpty: false,
canvasDataEmpty: false,
Dict: { selectList: [] },
table: {
page: 1,
size: 10,
total: 0,
loading: false,
dataList: [],
},
rules: {},
form: {
title: "",
visible: false,
reqType: "add",
historyDialog: false,
status: { cu: 0 },
query: {},
search: {},
item: {},
file: 0,
config: {},
},
// 新增图表相关数据
chartVisible: true, // 图表弹窗可见性
deviceList: [{ id: "test001", name: "测试设备1" }], // 设备列表数据
selectedDevice: null, // 选中设备ID
dateRange: [null, null], // 日期范围选择
currentChartType: "line", // 当前图表类型(line/column)
chartLoading: false, // 图表加载状态
chartInstance: null, // Highcharts实例引用
// ...原有data属性保持不变...
canvas: null, // Canvas 实例
ctx: null, // 2D 上下文
bgImage: null, // 背景图对象
waterImage: null, // 新增:water.png 图片对象
poImage: null, // 新增:po.png 图片对象
canvasDataReal: {
// Canvas绘制配置(支持批量扩展)
poConfigs: [
{ x: 0, y: null, width: 879, height: 150 }, // 第一张po.png配置
{ x: 0, y: null, width: 879 - 250, height: 150 }, // 第二张po.png配置(宽度减少250px)
],
poConfigs: [
{ x: null, y: null, width: 6, height: 121, image: "guanImage" }, // 第一张guan0.png
{ x: null, y: null, width: 6, height: 200, image: "guanImage" }, // 第二张guan0.png(高度调整)
],
lineConfigs: [
{ points: [], color: "red", lineWidth: 2 }, // 红色连接线配置
{ points: [], color: "yellow", lineWidth: 2 }, // 黄色连接线配置
],
},
// canvasData: [
// {
// name: "剖面名称",
// height: "剖面高度",
// width: "剖面宽度",
// code: "剖面编号",
// sdeg: "水区扇形起始角度",
// diameter: "总直径",
// jrxStepsDtoList: [
// {
// name: "台阶名称",
// code: "台阶编号",
// height: "高度(米)",
// width: "宽度(米)",
// slope: "坡度(deg)"
// }
// ],
// equipmentDataList: [
// {
// sensorid: "设备id",
// sensorname: "设备名称",
// unit: "设备单位",
// stage: "水位(传感器到水面的距离)",
// depth: "浸润线埋深(水位到管口的距离)(m)",
// smhb: "// 水面海拔",
// time: "时间",
// holeDepth: "孔口高程",
// jrxTrepanning: "浸润线开口深度",
// redAlarm: "红色预警 此预警值针对的是depth 浸润线埋深",
// orangeAlarm: "橙色预警",
// yellowAlarm: "黄色预警",
// blueAlarm: "蓝色预警"
// }
// ]
// }
// ]
};
},
created() {
// 获取基本信息
this.pageApi = Config.getModuleInfo(this);
this.Dict = this.pageApi.Dict;
this.form.config = this.pageApi.config;
this.rules = reqApi.getRules(this.Dict.baseInfo) || this.Dict.rules || {};
this.pageApi.created && this.pageApi.created();
// 新增:获取地址栏deviceId参数并设置到form.query.code
const deviceId = this.$route.query.deviceId;
if (deviceId) {
this.form.query.sensorid = deviceId; // 将deviceId赋值到查询条件的code字段
}
// this.handleCanvasData(this.canvasData);
},
mounted() {
this.$nextTick(() => {
this.loadData();
this.initChart1()
this.getCanvasData();
});
// 获取选择列表字典
var selectList = this.Dict.selectList;
Tools.asyncLoop.call(this, selectList, function (key, value, next) {
if (typeof value === "function") {
value.call(this.Dict).then(function (res) {
selectList[key] = res;
next();
});
} else {
next();
}
});
},
methods: {
/** 绘制文字标注 */
drawText(config) {
this.ctx.save();
this.ctx.setTransform(1, 0, 0, 1, 0, 0); // 恢复默认坐标系(左上角原点)
this.ctx.font = `10px Arial`; // 文字大小8px
this.ctx.fillStyle = "#000"; // 黄色
this.ctx.textAlign = "center"; // 水平居中
this.ctx.textBaseline = "top"; // 垂直顶部对齐
// 绘制文字(考虑Y轴方向转换)
const drawY = this.canvas.height - config.y; // 转换为默认坐标系Y轴
this.ctx.fillText(config.text, config.x, drawY + 5); // Y轴偏移5px避免重叠
this.ctx.restore();
},
/** 清空画布内容及配置 */
clearCanvas() {
if (this.ctx) {
// 清除画布绘制内容(基于当前坐标系)
this.ctx.save();
this.ctx.setTransform(1, 0, 0, 1, 0, 0); // 恢复默认坐标系
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); // 清空整个画布
this.ctx.restore();
}
// 重置配置数据(避免残留)
this.canvasDataReal.poConfigs = [];
this.canvasDataReal.guanConfigs = [];
this.canvasDataReal.lineConfigs = [];
},
getCanvasData() {
const params = { ...this.form.query };
request({
url: "tab/jrx/dissect/visual-xinHua",
method: "get",
params,
}).then(async (res) => {
const data = res.body;
if (!data.length) {
// 数据为空时清空画布
this.clearCanvas();
return;
}
// console.log("剖面接口数据", data);
// console.table(JSON.parse(JSON.stringify(data[0].jrxStepsDtoList)));
// console.table(JSON.parse(JSON.stringify(data[0].equipmentDataList)));
await this.handleCanvasData(data);
this.initCanvas();
});
},
handleCanvasData(list = []) {
return new Promise((resolve) => {
// 新增Promise封装
let canvasWidth = 1000; // 默认宽度
let canvasHeight = 600; // 默认高度
// 更新Canvas元素属性和样式
const canvasEl = this.$refs.canvas;
if (canvasEl) {
// 实际绘图区域尺寸(关键属性)
canvasEl.width = canvasWidth;
canvasEl.height = canvasHeight;
// 显示尺寸(与绘图区域保持一致)
canvasEl.style.width = `${canvasWidth}px`;
canvasEl.style.height = `${canvasHeight}px`;
}
// 数据清洗
const poumian = list[0]; // 坡面数据
const poCount = poumian.jrxStepsDtoList.length;
const lineCount = 5;
const po_pad_right = 180; // poCount > 4 ? 130 : 180; // 第一个台阶距离画布的距离
const poH = 150;
const line_color = ["red", "orange", "yellow", "blue", "white"];
this.canvasDataReal.poConfigs = [];
this.canvasDataReal.guanConfigs = [];
this.canvasDataReal.lineConfigs = [];
//第一层台阶的开孔深度和设备图片相除的系数
const sbHeightModulus =
poumian.equipmentDataList[0].jrxTrepanning / 130;
// 存储设备数据列表(关键新增,用于后续获取depth值)
this.equipmentDataList = poumian.equipmentDataList || [];
// 坡数据数据格式处理
poumian.jrxStepsDtoList.forEach((po, poIndex) => {
this.canvasDataReal.poConfigs.push({
x: 0,
y: canvasHeight - (poIndex + 1) * poH,
width: canvasWidth - (poIndex + 1) * po_pad_right,
height: poH,
});
});
// 管孔数据数据格式处理
poumian.equipmentDataList.forEach((equipment, equipIndex) => {
const po = this.canvasDataReal.poConfigs[equipIndex];
// 管孔数据数据格式处理
this.canvasDataReal.guanConfigs.push({
x: po.width * 0.75 + 50,
y: canvasHeight - po.height * (equipIndex + 1),
width: 6,
height: equipment.jrxTrepanning / sbHeightModulus,
image: "guanImage",
});
});
// 警戒线逻辑- 初始话基本数据结构
for (let index1 = 0; index1 < lineCount; index1++) {
this.canvasDataReal.lineConfigs.push({
// 设置
points: [],
color: line_color[index1],
lineWidth: 2,
cha: 20 * index1, // 每条线之间的差值
});
}
// 警戒线种类下,根据管孔设备个数,设定对应的坐标点point
this.canvasDataReal.lineConfigs.forEach((line, index) => {
let lineValKey =
line.color == "white" ? "depth" : line.color + "Alarm";
// 几个管孔几个坐标点
poumian.equipmentDataList.forEach((equip, subindex) => {
line.points.push({
x: this.canvasDataReal.guanConfigs[subindex].x + 1,
y:
this.canvasDataReal.guanConfigs[subindex].y +
equip[lineValKey] / sbHeightModulus, // 管设备的y坐标+设备的警戒值*系数
});
});
});
// console.log("坡面处理完毕数据", this.canvasDataReal);
// console.table(
// JSON.parse(JSON.stringify(this.canvasDataReal.poConfigs))
// );
// console.table(
// JSON.parse(JSON.stringify(this.canvasDataReal.guanConfigs))
// );
// console.table(
// JSON.parse(JSON.stringify(this.canvasDataReal.lineConfigs))
// );
resolve(); // 数据处理完成后触发resolve
});
},
/** 初始化 Canvas 画布及坐标系 */
initCanvas() {
// 获取 Canvas 元素和上下文
this.canvas = this.$refs.canvas; // document.getElementById('mainCanvas')
if (!this.canvas) {
console.error("Canvas 元素未找到");
return;
}
// console.log(this.canvas, "canvas");
this.ctx = this.canvas.getContext("2d");
// 坐标系变换:将原点移至左下角(默认原点在左上角)
this.ctx.translate(0, this.canvas.height); // 向下移动画布高度
this.ctx.scale(1, -1); // 翻转 Y 轴方向(上为正)
// // 加载背景图并绘制
// this.loadBackgroundImage();
// 加载所有图片并绘制
this.loadAllImages();
},
// 绘制单个po.png(支持配置参数)
drawPoImage(config) {
this.ctx.save();
this.ctx.setTransform(1, 0, 0, 1, 0, 0);
// 动态计算y坐标(若未指定则默认画布底部-高度)
this.ctx.drawImage(
this.poImage,
config.x,
config.y,
config.width,
config.height
);
this.ctx.restore();
},
// 绘制单个guan.png(支持不同图片类型)
drawGuanImage(config) {
this.ctx.save();
this.ctx.setTransform(1, 0, 0, 1, 0, 0);
const targetImage = this[config.image]; // 根据配置获取具体图片对象(如guanImage/guanImage1)
this.ctx.drawImage(
targetImage,
config.x,
config.y,
config.width,
config.height
);
this.ctx.restore();
},
// 绘制连接线(支持多坐标点)
drawLine(config) {
this.ctx.save();
this.ctx.setTransform(1, 0, 0, 1, 0, 0);
this.ctx.strokeStyle = config.color;
this.ctx.lineWidth = config.lineWidth;
this.ctx.beginPath();
config.points.forEach((point, index) => {
index === 0
? this.ctx.moveTo(point.x, point.y)
: this.ctx.lineTo(point.x, point.y);
});
this.ctx.stroke();
this.ctx.restore();
},
// 绘制背景图(独立方法)
drawBackground() {
this.ctx.save();
this.ctx.setTransform(1, 0, 0, 1, 0, 0);
this.ctx.drawImage(
this.bgImage,
0,
0,
this.canvas.width,
this.canvas.height
);
this.ctx.restore();
},
// 绘制water.png(独立方法)
// drawWaterImage() {
// this.ctx.save();
// this.ctx.setTransform(1, 0, 0, 1, 0, 0);
// this.ctx.drawImage(
// this.waterImage,
// 0,
// this.canvas.height - 255,
// 485,
// 255
// );
// this.ctx.restore();
// },
// 重构后的统一绘制入口(通过配置驱动)
drawAllImages() {
// 1. 绘制背景图
this.drawBackground();
// 2. 绘制po.png(遍历配置数组)
// console.log(this.canvasDataReal.poConfigs, "poConfigs");
this.canvasDataReal.poConfigs.forEach((config, index) => {
this.drawPoImage(config);
});
// 3. 绘制guan.png(遍历配置数组)
// console.log(this.canvasDataReal.guanConfigs, "guanConfigs");
this.canvasDataReal.guanConfigs.forEach((config, index) => {
this.drawGuanImage(config);
});
// 4. 绘制连接线(遍历配置数组)
this.canvasDataReal.lineConfigs.forEach((config, index) => {
this.drawLine(config);
});
// 5. 绘制白色警戒线所有点的文字标注(修改部分)
this.canvasDataReal.lineConfigs.forEach((lineConfig) => {
if (lineConfig.color === "white" && lineConfig.points.length > 0) {
// 添加可选链校验
lineConfig.points.forEach((point, subindex) => {
// 遍历所有坐标点
// 获取对应设备的深度值(通过索引对应)
const equipment = this.equipmentDataList[subindex];
const depth = equipment.depth || ""; // 添加空值校验
// 绘制当前点的文字
this.drawText({
x: point.x,
y: this.canvas.height - point.y,
text: `浸润线埋深:${depth}m`,
});
});
}
});
// 新增:绘制白色警戒线下方海蓝色阴影
this.canvasDataReal.lineConfigs.forEach((lineConfig) => {
if (lineConfig.color === 'white' && lineConfig.points.length >= 2) { // 至少需要2个点构成直线
this.ctx.save();
this.ctx.setTransform(1, 0, 0, 1, 0, 0); // 恢复默认坐标系(左上角原点,Y轴向下)
// // 增加测试数据
// lineConfig.points.push({
// x: lineConfig.points[1].x - 150,
// y: lineConfig.points[1].y -150
// })
// 将警戒线坐标转换为默认坐标系(原坐标系Y轴向上)
const canvasHeight = this.canvas.height; // 缓存画布高度
const convertedPoints = lineConfig.points.map(point => ({
x: point.x,
y: point.y // 转换为默认Y轴向下的坐标
}));
// 遍历相邻点对,生成梯形
for (let i = 0; i < convertedPoints.length - 1; i++) {
const start = convertedPoints[i];
const end = convertedPoints[i + 1];
// 构建当前线段对应的梯形四个顶点
const trapezoid = [
start, // 顶部左端点
end, // 顶部右端点
{ x: end.x, y: canvasHeight }, // 底部右端点(垂直投影到底边)
{ x: start.x, y: canvasHeight }, // 底部左端点(垂直投影到底边)
];
// 绘制当前梯形
this.ctx.fillStyle = 'rgba(59, 175, 251, 0.3)'; // 海蓝色,透明度30%
this.ctx.beginPath();
trapezoid.forEach((point, index) => {
index === 0
? this.ctx.moveTo(point.x, point.y)
: this.ctx.lineTo(point.x, point.y);
});
this.ctx.closePath();
this.ctx.fill();
}
this.ctx.restore();
}
});
// 5. 绘制water.png
// this.drawWaterImage();
},
/** 加载所有图片并绘制 */
loadAllImages() {
// 加载背景图(原有)
this.bgImage = new Image();
this.bgImage.src = require("@/assets/images/jrx/bg.png");
// // 加载 water.png
// this.waterImage = new Image();
// this.waterImage.src = require("@/assets/images/jrx/water.png");
// 加载 po.png
this.poImage = new Image();
this.poImage.src = require("@/assets/images/jrx/po.png");
// 加载 guan.png
this.guanImage = new Image();
this.guanImage.src = require("@/assets/images/jrx/guan0.png");
// 等待所有图片加载完成
Promise.all([
new Promise((resolve) => (this.bgImage.onload = resolve)),
// new Promise((resolve) => (this.waterImage.onload = resolve)),
new Promise((resolve) => (this.poImage.onload = resolve)),
new Promise((resolve) => (this.guanImage.onload = resolve)),
])
.then(() => {
// 所有图片加载完成后绘制
this.drawAllImages();
})
.catch(() => {
console.error("部分图片加载失败");
});
},
/** 初始化图表(关键修改:调整图例位置) */
initChart1() {
let params = {
sort: "date,desc",
};
if (this.form.query.daterange) {
params.daterange = this.form.query.daterange.join(",");
}
if (this.form.query.sensorid) {
params.code = this.form.query.sensorid;
}
request({
url: "data/st/imghistory",
method: "get",
params,
}).then((res) => {
const data = res.body;
// const data = this.getChartData().body
// console.log("data", data);
const chartData = this.seriesDataFormat(data, { datekey: "date" });
var warningLine = undefined; // this.form.config.warningLine;
var option = {
valEnabled: true,
opacity: 1,
lineWidth: 3,
};
var alarmData = this.discernValidAlarmValue(
data.alarm,
data.lists,
chartData.series,
warningLine,
option
);
// const chartData = data
// console.log("chartCData", chartData);
Highcharts.setOptions({
global: {
useUTC: false,
},
lang: {
resetZoom: "重置缩放比例",
},
});
this.chartInstance = new Highcharts.chart(this.$refs.chartContainer, {
chart: {
//type: '',
backgroundColor: "transparent",
//marginTop:30,
//marginBottom:30,
//marginLeft:30,
zoomType: "x", // xy
},
valEnabled: true,
opacity: 1,
lineWidth: 3,
title: {
text: "",
},
subtitle: {
text: "",
},
tooltip: {
enabled: false,
borderWidth: 10,
},
xAxis: {
type: "datetime",
// 最为关键的代码:如果为空数组,则导致日期格式化失效!!
categories: chartData.categories[0] && chartData.categories,
lineWidth: 0,
//lineColor:'#ff0000',
gridLineColor: "#aaa",
dateTimeLabelFormats: {
millisecond: "%H:%M:%S.%L",
second: "%H:%M:%S",
minute: "%H:%M",
hour: "%H:%M",
day: "%m-%d",
week: "%m-%d",
month: "%Y-%m",
year: "%Y",
},
},
yAxis: {
title: {
text: "",
},
labels: {
x: -6,
},
gridLineColor: "#aaa",
max: null,
},
plotOptions: {
column: {
borderWidth: 0,
//y:50,
//itemMarginTop:50,
},
bar: {
borderWidth: 0,
},
},
tooltip: {
// {point.y:.4f} // 保留4位小数
//headerFormat: '<span style="font-size:10px">{point.key}</span><table>',
pointFormat:
'<tr><td style="color:{series.color};padding:0">{series.name}:</td>' +
'<td style="padding:0"><b>{point.y}' +
data.danwei +
"</b> </td></tr>",
footerFormat: "</table>",
shared: true,
useHTML: true,
dateTimeLabelFormats: {
millisecond: "%H:%M:%S.%L",
second: "%H:%M:%S",
minute: "%H:%M",
hour: "%H:%M",
day: "%m-%d %H时",
week: "%m-%d",
month: "%Y-%m",
year: "%Y",
},
},
legend: {
enabled: chartData.series.length > 1 ? true : false,
// 图例定位
layout: "horizontal", // 水平布局:“horizontal”, 垂直布局:“vertical”
floating: false, // 图列是否浮动
align: "right",
// 图例容器
//width:'100%', // number || String
padding: 2, // 内边距
margin: 2,
borderRadius: 5,
//borderWidth:1,
verticalAlign: "top",
// 图例项
//itemWidth:120, // 宽度
itemDistance: 10, // 间距 20
y: -10,
itemMarginTop: 2,
itemStyle: {},
itemHoverStyle: {},
},
credits: {
enabled: false,
},
series: chartData.series,
});
});
},
seriesDataFormat(data, opts) {
var names = data.names || [],
list = data.list || data.lists,
series = [],
categories = [],
maxVal = 0;
if (names[0] && list) {
var colors = [
"#7CB5EC",
"#90ED7D",
"#F7A35C",
"#8085E9",
"#F15C80",
"#E4D354",
"#2B908F",
"#F45B5B",
"#91E8E1",
"#0769CB",
"#00ABBD",
"#ffd886",
"#9F2E61",
"#4D670C",
];
var len = names.length;
for (var i = 0; i < len; i++) {
var item = names[i];
var serie = {
name: item.name,
data: [],
key: item.key,
type: data.chartType,
color: colors[i],
};
opts && serie.type && (serie.type = opts.type);
series.push(serie);
}
for (var item of list) {
var values = item.values;
//var datetime = item[opts.datekey || 'dateUnit'];
//var time = datetime.indexOf(' ') > 0 ? datetime.split(' ')[1] : datetime;
var timestamp = item["date"];
//categories.push(timestamp);
for (var serie of series) {
var value = values[serie.key] * 1;
Math.abs(value) > maxVal && (maxVal = Math.abs(value));
serie.data.push([timestamp, value]);
}
}
}
return { series: series, categories: categories, maxVal: maxVal };
},
discernValidAlarmValue(alarms, list, series, direction, opts) {
var xLength = (list || []).length,
maxAlarm = 0,
opts = opts || {};
if (alarms && xLength) {
var value = alarms.value;
// discern
var levelDist = [
{ color: "red", name: "红色报警线" },
{ color: "orange", name: "橙色报警线" },
{ color: "yellow", name: "黄色报警线" },
{ color: "blue", name: "蓝色报警线" },
],
alarmLine = {},
setAlarmSerie = function (value, name, color) {
// 修改蓝色色值
color === "blue" && (color = "#3BAFFB");
var sx = list[0].date,
ex = list[xLength - 1].date;
var serie = {
name: name,
type: "spline",
data: [
{ x: sx, y: value },
{ x: ex, y: value },
],
color: color,
enableMouseTracking: false,
legend: false,
showInLegend: false,
dashStyle: "ShortDot",
lineWidth: opts.lineWidth || 1,
states: {
inactive: {
opacity: opts.opacity,
},
},
dataLabels: {
enabled: opts.valEnabled || false, // 数据值, 2022/11/11(周五) 因多条报警线暂时关闭
//backgroundColor:'red',
verticalAlign: "middle",
padding: 0,
defer: false,
allowOverlap: true,
color: color,
style: {
textOutline: "none",
},
},
tooltip: {
//footerFormat:'',
//pointFormat:'',
headerFormat: "",
//nullFormat:'',
},
marker: {
enabled: false,
},
zIndex: -10,
};
series.push(serie);
};
/* 智能报警线
var level = (~~alarms.alarmLevel || levelDist.length+1) - 1;
var nearLevel = level ? level - 1 : level;
var alarm = levelDist[level];
var nearAlarm = levelDist[nearLevel];
nearAlarm.value = value[nearAlarm.color];
alarmLine[nearAlarm.color] = nearAlarm;
if(alarm){
alarm.value = value[alarm.color];
alarmLine[alarm.color] = alarm;
}; */
// 多条报警线
for (var item of levelDist) {
item.value = value[item.color];
alarmLine[item.color] = item;
}
// add
for (var key in alarmLine) {
var line = alarmLine[key];
line.value > maxAlarm && (maxAlarm = line.value);
setAlarmSerie(line.value, line.name, line.color);
direction && setAlarmSerie(0 - line.value, line.name, line.color);
}
}
return { series, maxAlarm };
},
/** 切换图表类型 */
switchChartType(type) {
this.currentChartType = type;
if (this.chartInstance) {
this.chartInstance.series.forEach((series) => {
series.update({ type: this.currentChartType });
});
}
},
// loadData: function () {
// // console.log(this.form, "form");
// // this.initChart1();
// // this.getCanvasData();
// return reqApi.common.getRequst;
// },
loadData:reqApi.common.getRequst,
cancelForm() {
this.form.visible = false;
},
submitForm(form, item) {
reqApi.common.submitForm.call(this, form, item);
},
},
};
</script>
<style rel="stylesheet/scss" lang="scss" scope>
.qyzz {
}
</style>
<template>
<div class="common-page qyzz page-t1">
<div class="option page-row">
<table-filter
ref="filter"
:form="form"
:Dict="Dict"
:rules="rules"
:config="form.config"
:loadData="loadData"
/>
<table-filter ref="filter" :form="form" :Dict="Dict" :rules="rules" :config="form.config" :loadData="loadData" />
</div>
<div class="new-container" style="display: flex">
<div class="canvas-wrapper" style="width: 1000px">
<!-- 替换为 Canvas 元素 -->
<canvas
ref="canvas"
id="mainCanvas"
width="1000"
style="background: #f0f0f0"
></canvas>
<canvas ref="canvas" id="mainCanvas" width="1000" style="background: #f0f0f0"></canvas>
</div>
<div class="chart-wrapper" style="padding-left: 0px">
<div
ref="chartContainer"
style="
width: 870px;
<div ref="chartContainer" style="
width: 850px;
height: 550px;
margin-bottom: 20px;
margin-left: 10px;
border: 1px solid gainsboro;
"
></div>
<div class="chart-btn-group">
<button
size="small"
:type="currentChartType === 'line' ? 'primary' : ''"
@click="switchChartType('line')"
>
"></div>
<div class="chart-btn-group" style="margin-left: 10px;">
<button size="small" :type="currentChartType === 'line' ? 'primary' : ''" @click="switchChartType('line')">
折线图
</button>
<button
size="small"
:type="currentChartType === 'column' ? 'primary' : ''"
@click="switchChartType('column')"
>
<button size="small" :type="currentChartType === 'column' ? 'primary' : ''"
@click="switchChartType('column')">
柱状图
</button>
</div>
......@@ -56,49 +35,24 @@
<div class="content-fix">
<div class="toolbar">
<div>
<el-button
v-for="(item, key) in form.config.otherBtn"
size="mini"
:type="item.type"
:icon="item.icon"
@click="item.callback.call(_self, $event)"
>{{ item.name }}</el-button
>
<el-button v-for="(item, key) in form.config.otherBtn" size="mini" :type="item.type" :icon="item.icon"
@click="item.callback.call(_self, $event)">{{ item.name }}</el-button>
</div>
<div>
<el-button
v-for="(item, key) in form.config.rightBtn"
size="mini"
:type="item.type"
:icon="item.icon"
@click="item.callback.call(_self, $event)"
>{{ item.name }}</el-button
>
<el-button v-for="(item, key) in form.config.rightBtn" size="mini" :type="item.type" :icon="item.icon"
@click="item.callback.call(_self, $event)">{{ item.name }}</el-button>
</div>
</div>
<!-- 表格渲染 -->
<cu-table
ref="cuTable"
:table="table"
:Dict="Dict"
:config="form.config"
:loadData="loadData"
/>
<cu-table ref="cuTable" :table="table" :Dict="Dict" :config="form.config" :loadData="loadData" />
</div>
</div>
</div>
</div>
<!-- 表单渲染 -->
<cu-form
ref="cuForm"
:form="form"
:Dict="Dict"
:rules="rules"
:submit="submitForm"
:cancel="cancelForm"
:watchKeys="['paperfilename']"
/>
<cu-form ref="cuForm" :form="form" :Dict="Dict" :rules="rules" :submit="submitForm" :cancel="cancelForm"
:watchKeys="['paperfilename']" />
</div>
</template>
......@@ -160,20 +114,41 @@ export default {
bgImage: null, // 背景图对象
waterImage: null, // 新增:water.png 图片对象
poImage: null, // 新增:po.png 图片对象
waterValue: 0, // 新增:水位值
canvasDataReal: {
poConfigsWH: [{ // 基础信息配置对象 用于换算具体画布xy坐标点
xieMianW: 0, // 第一个坡斜面距离第一个坡平面的水平距离。
pingMianW: 0, // 第一个坡平面距离平面宽度。
pingMianH: 0, // 第一个坡平面距离平面高度。
kongW: 0, // 目前设定打孔的位置在坡平面上距离左侧起始点的距离
kongH: 0, // 目前孔的深度
maishen: 0 // 水位到管口的垂直距离
}],
otherConfig: {
gantanW: 0, // 干滩距离水平面的宽度(根据最后一个坡平面坐标点计算xy。)
tuduiW: 0, // 干滩距离水平面中间的土堆
shuiW: 0, // 水平面的宽度
shuiH: 0, // 水平面的高度
},
// Canvas绘制配置(支持批量扩展)
poConfigs: [
{ x: 0, y: null, width: 879, height: 150 }, // 第一张po.png配置
{ x: 0, y: null, width: 879 - 250, height: 150 }, // 第二张po.png配置(宽度减少250px)
poConfigsXY: [ // 根据poConfigsWH 计算具体的xy坐标点,每个对象计算出两对坐标点。分别是斜面和平面点
],
poConfigs: [
{ x: null, y: null, width: 6, height: 121, image: "guanImage" }, // 第一张guan0.png
{ x: null, y: null, width: 6, height: 200, image: "guanImage" }, // 第二张guan0.png(高度调整)
guanConfigsXY: [ // 根据poConfigsXY和poConfigsWH的孔信息 计算具体的xy坐标点,每个对象计算出两对坐标点。分别是孔起始坐标和结束坐标
],
gantanConfigsXY: [
],
jrxConfigsXY: [
],
shuiweiConfigsXY: [
],
tuduiConfigsXY: [
],
jingjiexianConfigsXY: [
],
lineConfigs: [
{ points: [], color: "red", lineWidth: 2 }, // 红色连接线配置
{ points: [], color: "yellow", lineWidth: 2 }, // 黄色连接线配置
// { points: [], color: "red", lineWidth: 2 }, // 红色连接线配置
// { points: [], color: "yellow", lineWidth: 2 }, // 黄色连接线配置
],
},
// canvasData: [
......@@ -250,6 +225,28 @@ export default {
});
},
methods: {
// 最新
// calculateWidth(height, angleDegrees) {
// // 1. 将角度从度转换为弧度(JavaScript的Math.tan()使用弧度)
// const angleRadians = angleDegrees * Math.PI / 180;
// // 2. 计算角度的正切值
// const tanValue = Math.tan(angleRadians);
// // 3. 计算水平距离 L = H / tan(θ)
// const width = height / tanValue;
// return width;
// // 使用示例
// const height = 40; // 垂直高度
// const angle = 25; // 坡度角度(度)
// const result = calculateWidth(height, angle);
// console.log(`宽度 = ${result.toFixed(2)}`);
// // 输出:宽度 = 85.78
// },
/** 绘制文字标注 */
drawText(config) {
this.ctx.save();
......@@ -286,22 +283,18 @@ export default {
params,
}).then(async (res) => {
const data = res.body;
if (!data.length) {
// 数据为空时清空画布
this.clearCanvas();
return;
}
// console.log("剖面接口数据", data);
// console.table(JSON.parse(JSON.stringify(data[0].jrxStepsDtoList)));
// console.table(JSON.parse(JSON.stringify(data[0].equipmentDataList)));
this.waterValue = data[0].wtValue;
await this.handleCanvasData(data);
this.initCanvas();
});
},
handleCanvasData(list = []) {
handleCanvasDataNew(list = []) {
return new Promise((resolve) => {
// 新增Promise封装
let canvasWidth = 1000; // 默认宽度
......@@ -324,6 +317,167 @@ export default {
const po_pad_right = 180; // poCount > 4 ? 130 : 180; // 第一个台阶距离画布的距离
const poH = 150;
const line_color = ["red", "orange", "yellow", "blue", "white"];
//第一层台阶的开孔深度和设备图片相除的系数
const sbHeightModulus =
poumian.equipmentDataList[0].jrxTrepanning / 130;
// 存储设备数据列表(关键新增,用于后续获取depth值)
this.equipmentDataList = poumian.equipmentDataList || [];
// 坡面基本信息获取
for (let index = 0; index < poCount; index++) {
this.poConfigsWH.push({
xieMianW: 10 + index, // 第一个坡斜面距离第一个坡平面的水平距离。
pingMianW: 50 + index, // 第一个坡平面距离平面宽度。
pingMianH: 20 + index, // 第一个坡平面距离平面高度。
kongW: 10 + index, // 目前设定打孔的位置在坡平面上距离左侧起始点的距离
kongH: 20 + index, // 目前孔的深度
jrxTrepanning: 10 + index, // 浸润线开口深度
})
}
// 破平面xy计算
this.poConfigsXY = [{ x: 0, y: 0 }]
this.poConfigsWH.forEach((item) => {
this.poConfigsXY.push({ // 斜坡点
x: this.poConfigsXY[this.poConfigsXY.length - 1].x + item.xieMianW, // 每个斜平坡计算点都根据上一个前面已有的最后一个坐标点进行添加 第一个为x0y0
y: this.poConfigsXY[this.poConfigsXY.length - 1].y + item.pingMianH,
})
this.poConfigsXY.push({ // 平坡点
x: this.poConfigsXY[this.poConfigsXY.length - 1].x + item.pingMianW,
y: this.poConfigsXY[this.poConfigsXY.length - 1].y,
})
// 孔的xy计算
this.guanConfigsXY.push({ // 管的起始点 -2是获取该斜坡点的结束坐标加上孔距离位置=孔在平坡上面的位置
x: this.poConfigsXY[this.poConfigsXY.length - 2].x + item.kongW,
y: this.poConfigsXY[this.poConfigsXY.length - 2].y + 0, // 这里的0为了突出孔的仪器设备 突出坡平面距离。这里先放置0(方便后面浸润线水位的计算),等后面实际画管线的时候临时加上固定值。
})
this.guanConfigsXY.push({ // 管的结束点
x: this.poConfigsXY[this.poConfigsXY.length - 2].x + item.kongW,
y: this.poConfigsXY[this.poConfigsXY.length - 2].y - item.kongH,
maishen: item.depth, // 水位到管口的垂直距离
})
})
this.gantanConfigsXY = [ // 干滩的xy坐标点
{ x: this.poConfigsXY[this.poConfigsXY.length - 1].x, y: this.poConfigsXY[this.poConfigsXY.length - 1].y }, // 干滩的起始点
{
x: this.poConfigsXY[this.poConfigsXY.length - 1].x + this.otherConfig.gantanW,
y: this.poConfigsXY[this.poConfigsXY.length - 1].y - this.otherConfig.shuiH
}, // 干滩的结束点 (最高平坡减去水位高度)
]
this.guanConfigsXY.forEach((item, index) => {
if (index % 2 == 0) { // 偶数为管的起始点
this.jrxConfigsXY.push(
{ x: item.x, y: item.y - item.maishen }, // 浸润线的坐标点是平坡y-埋深的值(水位到平坡的垂直距离)
)
}
})
this.shuiweiConfigsXY = [ // 水位的xy坐标点(画矩形)
{ x: this.gantanConfigsXY[1].x, y: this.gantanConfigsXY[1].y }, // 水位的起始点
{ x: this.gantanConfigsXY[1].x + this.otherConfig.tuduiW, y: this.gantanConfigsXY[1].y }, // 水位的结束点 (最高平坡减去水位高度)
]
this.tuduiConfigsXY = [
{ x: this.gantanConfigsXY[1].x, y: this.gantanConfigsXY[1].y }, // 水位的起始点
{ x: this.gantanConfigsXY[1].x + this.otherConfig.tuduiW, y: 0 }, // 水位的结束点
]
this.jingjiexianConfigsXY = [
{ x: this.gantanConfigsXY[1].x, y: this.gantanConfigsXY[1].y }, // 水位的起始点
{ x: this.gantanConfigsXY[1].x + this.otherConfig.tuduiW, y: 0 }, // 水位的结束点
]
// 警戒线逻辑- 初始话基本数据结构
for (let index1 = 0; index1 < lineCount; index1++) {
this.jingjiexianConfigsXY.push({
// 设置
points: [],
color: line_color[index1],
lineWidth: 2,
cha: 4 * index1, // 每条线之间的差值
});
}
// 警戒线种类下,根据管孔设备个数,设定对应的坐标点point
// this.jingjiexianConfigsXY.forEach((line, index) => {
// let lineValKey = line.color == "white" ? "depth" : line.color + "Alarm";
// // 几个管孔几个坐标点
// poumian.equipmentDataList.forEach((equip, subindex) => {
// line.points.push({
// x: this.canvasDataReal.guanConfigs[subindex].x + 1,
// y:
// this.canvasDataReal.guanConfigs[subindex].y +
// equip[lineValKey], // 管设备的y坐标+设备的警戒值*系数
// });
// });
// });
this.canvasDataReal.lineConfigs.forEach((line, index) => {
let lineValKey = line.color == "white" ? "depth" : line.color + "Alarm";
// 几个管孔几个坐标点
poumian.equipmentDataList.forEach((equip, subindex) => {
line.points.push({
x: this.canvasDataReal.guanConfigs[subindex].x + 1,
y: this.canvasDataReal.guanConfigs[subindex].y + equip[lineValKey] / sbHeightModulus,
});
});
});
// 4. 绘制连接线(遍历配置数组)
this.canvasDataReal.lineConfigs.forEach((config, index) => {
this.drawLine(config);
});
// 5. 绘制白色警戒线所有点的文字标注(修改部分)
this.canvasDataReal.lineConfigs.forEach((lineConfig) => {
if (lineConfig.color === "white" && lineConfig.points.length > 0) {
// 添加可选链校验
lineConfig.points.forEach((point, subindex) => {
// 遍历所有坐标点
// 获取对应设备的深度值(通过索引对应)
const equipment = this.equipmentDataList[subindex];
const depth = equipment.depth || ""; // 添加空值校验
// 绘制当前点的文字
this.drawText({
x: point.x,
y: this.canvas.height - point.y,
text: `浸润线埋深:${depth}m`,
});
});
}
});
resolve(); // 数据处理完成后触发resolve
});
},
handleCanvasData(list = []) {
return new Promise((resolve) => {
// 新增Promise封装
let canvasWidth = 1000; // 默认宽度
let canvasHeight = 600; // 默认高度
// 更新Canvas元素属性和样式
const canvasEl = this.$refs.canvas;
if (canvasEl) {
// 实际绘图区域尺寸(关键属性)
canvasEl.width = canvasWidth;
canvasEl.height = canvasHeight;
// 显示尺寸(与绘图区域保持一致)
canvasEl.style.width = `${canvasWidth}px`;
canvasEl.style.height = `${canvasHeight}px`;
}
// 数据清洗
const poumian = list[0]; // 坡面数据
const poCount = poumian.jrxStepsDtoList.length;
const lineCount = 5;
const po_pad_right = -140; // poCount > 4 ? 130 : 180; // 第一个台阶距离画布的距离
const poH = 450;
const line_color = ["red", "orange", "yellow", "blue", "white"];
this.canvasDataReal.poConfigs = [];
this.canvasDataReal.guanConfigs = [];
this.canvasDataReal.lineConfigs = [];
......@@ -334,13 +488,12 @@ export default {
// 存储设备数据列表(关键新增,用于后续获取depth值)
this.equipmentDataList = poumian.equipmentDataList || [];
// 坡数据数据格式处理
poumian.jrxStepsDtoList.forEach((po, poIndex) => {
this.canvasDataReal.poConfigs.push({
x: 0,
y: canvasHeight - (poIndex + 1) * poH,
width: canvasWidth - (poIndex + 1) * po_pad_right,
x: -140,
y: canvasHeight - (poIndex) * poH,
width: canvasWidth - (poIndex) * po_pad_right,
height: poH,
});
});
......@@ -348,13 +501,23 @@ export default {
poumian.equipmentDataList.forEach((equipment, equipIndex) => {
const po = this.canvasDataReal.poConfigs[equipIndex];
// 管孔数据数据格式处理
this.canvasDataReal.guanConfigs.push({
x: po.width * 0.75 + 50,
y: canvasHeight - po.height * (equipIndex + 1),
width: 6,
height: equipment.jrxTrepanning / sbHeightModulus,
image: "guanImage",
});
if (equipIndex == 1) {
this.canvasDataReal.guanConfigs.push({
x: po.width * 0.234 + 100 * (equipIndex + 1),
y: canvasHeight - po.height + 133,
width: 7, // 可以设置不同的宽度
height: (equipment.jrxTrepanning / sbHeightModulus) * 1.3,
image: "guanImage2", // 使用不同的图片
});
} else {
this.canvasDataReal.guanConfigs.push({
x: po.width * 0.234 + 100 * (equipIndex + 1),
y: canvasHeight - po.height + 208,
width: 7,
height: equipment.jrxTrepanning / sbHeightModulus,
image: "guanImage",
});
}
});
// 警戒线逻辑- 初始话基本数据结构
......@@ -364,36 +527,33 @@ export default {
points: [],
color: line_color[index1],
lineWidth: 2,
cha: 20 * index1, // 每条线之间的差值
cha: 4 * index1,
});
}
// 警戒线种类下,根据管孔设备个数,设定对应的坐标点point
this.canvasDataReal.lineConfigs.forEach((line, index) => {
let lineValKey =
line.color == "white" ? "depth" : line.color + "Alarm";
let lineValKey = line.color == "white" ? "depth" : line.color + "Alarm";
// 几个管孔几个坐标点
poumian.equipmentDataList.forEach((equip, subindex) => {
let xOffset = 0;
let baseY = 0;
// 对于彩色线(非白色),使用统一的计算方式,确保线条是直线
if (line.color !== "white") {
// 对所有彩色线使用相同的计算逻辑,不使用不同的分母
xOffset = line.cha / 20; // 使用统一的分母值
// 直接根据设备数据计算y坐标
baseY = this.canvasDataReal.guanConfigs[subindex].y + equip[lineValKey] / sbHeightModulus;
} else {
baseY = this.canvasDataReal.guanConfigs[subindex].y + this.canvasDataReal.guanConfigs[subindex].height;
}
line.points.push({
x: this.canvasDataReal.guanConfigs[subindex].x + 1,
y:
this.canvasDataReal.guanConfigs[subindex].y +
equip[lineValKey] / sbHeightModulus, // 管设备的y坐标+设备的警戒值*系数
x: this.canvasDataReal.guanConfigs[subindex].x + 1 + xOffset,
y: baseY
});
});
});
// console.log("坡面处理完毕数据", this.canvasDataReal);
// console.table(
// JSON.parse(JSON.stringify(this.canvasDataReal.poConfigs))
// );
// console.table(
// JSON.parse(JSON.stringify(this.canvasDataReal.guanConfigs))
// );
// console.table(
// JSON.parse(JSON.stringify(this.canvasDataReal.lineConfigs))
// );
resolve(); // 数据处理完成后触发resolve
});
},
......@@ -405,7 +565,6 @@ export default {
console.error("Canvas 元素未找到");
return;
}
// console.log(this.canvas, "canvas");
this.ctx = this.canvas.getContext("2d");
// 坐标系变换:将原点移至左下角(默认原点在左上角)
......@@ -418,6 +577,20 @@ export default {
this.loadAllImages();
},
// 绘制water.png(独立方法)
drawWaterImage() {
this.ctx.save();
this.ctx.setTransform(1, 0, 0, 1, 0, 0);
this.ctx.drawImage(
this.waterImage,
500,
this.canvas.height - (180 + this.waterValue * 1.2),
550,
550
);
this.ctx.restore();
},
// 绘制单个po.png(支持配置参数)
drawPoImage(config) {
this.ctx.save();
......@@ -448,18 +621,45 @@ export default {
this.ctx.restore();
},
// 绘制连接线(支持多坐标点)
drawSecondPipeImage(config) {
this.ctx.save();
this.ctx.setTransform(1, 0, 0, 1, 0, 0);
// 可以使用不同的绘制逻辑
const targetImage = this[config.image] || this.guanImage;
this.ctx.drawImage(
targetImage,
config.x,
config.y,
config.width,
config.height
);
this.ctx.restore();
},
// 绘制连接线(支持多坐标点)白色
drawLine(config) {
this.ctx.save();
this.ctx.setTransform(1, 0, 0, 1, 0, 0);
this.ctx.strokeStyle = config.color;
this.ctx.lineWidth = config.lineWidth;
this.ctx.beginPath();
config.points.forEach((point, index) => {
index === 0
? this.ctx.moveTo(point.x, point.y)
: this.ctx.lineTo(point.x, point.y);
});
// 修复语法错误并改进白色线对齐逻辑
if (config.color === 'white' && this.canvasDataReal.guanConfigs.length > 0) {
// 确保至少有两个点可以连接
if (config.points && config.points.length >= 2) {
config.points.forEach((point, index) => {
index === 0 ? this.ctx.moveTo(point.x, point.y) : this.ctx.lineTo(point.x, point.y);
});
}
} else {
config.points.forEach((point, index) => {
// index === 0 ? this.ctx.moveTo(point.x - 400, point.y + 220) : this.ctx.lineTo(point.x, point.y);
// index === 0 ? this.ctx.moveTo(point.x - 400, point.y + 190) : this.ctx.lineTo(point.x, point.y);
});
}
this.ctx.stroke();
this.ctx.restore();
},
......@@ -477,103 +677,219 @@ export default {
);
this.ctx.restore();
},
// 绘制文字 箭头
createCustomLineWithText(config) {
// 配置参数默认值
const defaultConfig = {
points: [],
color: '#000000',
lineWidth: 2,
showLine: true,
text: '',
textPosition: 'middle',
textDirection: 'horizontal',
textAngle: 0,
textOffset: 10,
textColor: '#000000',
fontSize: 10,
showArrow: false,
showArrowAtStart: false,
arrowSize: 8
};
// 绘制water.png(独立方法)
// drawWaterImage() {
// this.ctx.save();
// this.ctx.setTransform(1, 0, 0, 1, 0, 0);
// this.ctx.drawImage(
// this.waterImage,
// 0,
// this.canvas.height - 255,
// 485,
// 255
// );
// this.ctx.restore();
// },
// 合并配置
const finalConfig = { ...defaultConfig, ...config };
if (!this.ctx || !finalConfig.points || finalConfig.points.length < 1) {
console.error('Canvas上下文或坐标点不足');
return;
}
this.ctx.save();
this.ctx.setTransform(1, 0, 0, 1, 0, 0); // 恢复默认坐标系
// 只有当showLine为true且lineWidth大于0时才绘制线条
if (finalConfig.showLine && finalConfig.lineWidth > 0 && finalConfig.points.length >= 2) {
this.ctx.strokeStyle = finalConfig.color;
this.ctx.lineWidth = finalConfig.lineWidth;
this.ctx.beginPath();
finalConfig.points.forEach((point, index) => {
if (index == 0) {
this.ctx.moveTo(point.x, point.y);
} else {
this.ctx.lineTo(point.x, point.y);
}
});
this.ctx.stroke();
// 新增:绘制箭头
if (finalConfig.showArrow && finalConfig.points.length >= 2) {
const points = finalConfig.points;
const lastPoint = points[points.length - 1];
const prevPoint = points[points.length - 2];
// 计算箭头方向
const angle = Math.atan2(lastPoint.y - prevPoint.y, lastPoint.x - prevPoint.x);
// 设置箭头样式
this.ctx.fillStyle = finalConfig.color;
// 绘制箭头三角形
this.ctx.beginPath();
this.ctx.moveTo(lastPoint.x, lastPoint.y);
this.ctx.lineTo(
lastPoint.x - finalConfig.arrowSize * Math.cos(angle - Math.PI / 6),
lastPoint.y - finalConfig.arrowSize * Math.sin(angle - Math.PI / 6)
);
this.ctx.lineTo(
lastPoint.x - finalConfig.arrowSize * Math.cos(angle + Math.PI / 6),
lastPoint.y - finalConfig.arrowSize * Math.sin(angle + Math.PI / 6)
);
this.ctx.closePath();
this.ctx.fill();
}
}
if (finalConfig.showArrowAtStart && finalConfig.points.length >= 2) {
const points = finalConfig.points;
const firstPoint = points[0];
const secondPoint = points[1];
// 计算起点箭头方向(与线段方向相反)
const angle = Math.atan2(secondPoint.y - firstPoint.y, secondPoint.x - firstPoint.x) + Math.PI;
// 设置箭头样式
this.ctx.fillStyle = finalConfig.color;
// 绘制起点箭头三角形
this.ctx.beginPath();
this.ctx.moveTo(firstPoint.x, firstPoint.y);
this.ctx.lineTo(
firstPoint.x - finalConfig.arrowSize * Math.cos(angle - Math.PI / 6),
firstPoint.y - finalConfig.arrowSize * Math.sin(angle - Math.PI / 6)
);
this.ctx.lineTo(
firstPoint.x - finalConfig.arrowSize * Math.cos(angle + Math.PI / 6),
firstPoint.y - finalConfig.arrowSize * Math.sin(angle + Math.PI / 6)
);
this.ctx.closePath();
this.ctx.fill();
}
// 绘制文字
if (finalConfig.text) {
this.ctx.font = `${finalConfig.fontSize}px Arial`;
this.ctx.fillStyle = finalConfig.textColor;
// 计算文字位置
let textX, textY;
const { points } = finalConfig;
switch (finalConfig.textPosition) {
case 'start':
textX = points[0].x;
textY = points[0].y;
break;
case 'end':
textX = points[points.length - 1].x;
textY = points[points.length - 1].y;
break;
default:
if (points.length >= 2) {
const midIndex = Math.floor(points.length / 2);
textX = (points[midIndex - 1].x + points[midIndex].x) / 2;
textY = (points[midIndex - 1].y + points[midIndex].y) / 2;
} else {
textX = points[0].x;
textY = points[0].y;
}
break;
}
// 根据方向调整文字
switch (finalConfig.textDirection) {
case 'vertical':
this.ctx.save();
this.ctx.translate(textX, textY);
this.ctx.rotate(-Math.PI / 2); // 旋转90度
this.ctx.textAlign = 'center';
this.ctx.textBaseline = 'middle';
this.ctx.fillText(finalConfig.text, 0, -finalConfig.textOffset);
this.ctx.restore();
break;
case 'angle':
const angleRad = finalConfig.textAngle * Math.PI / 180;
this.ctx.save();
this.ctx.translate(textX, textY);
this.ctx.rotate(angleRad);
this.ctx.textAlign = 'center';
this.ctx.textBaseline = 'middle';
this.ctx.fillText(finalConfig.text, 0, -finalConfig.textOffset);
this.ctx.restore();
break;
default: // horizontal
this.ctx.textAlign = 'center';
this.ctx.textBaseline = 'bottom';
this.ctx.fillText(finalConfig.text, textX, textY - finalConfig.textOffset);
break;
}
}
this.ctx.restore();
},
// 重构后的统一绘制入口(通过配置驱动)
drawAllImages() {
// 1. 绘制背景图
// 1. 绘制背景图
this.drawBackground();
// 绘制water.png
this.drawWaterImage();
// 2. 绘制po.png(遍历配置数组)
// console.log(this.canvasDataReal.poConfigs, "poConfigs");
this.canvasDataReal.poConfigs.forEach((config, index) => {
this.drawPoImage(config);
});
// 3. 绘制guan.png(遍历配置数组)
// console.log(this.canvasDataReal.guanConfigs, "guanConfigs");
this.canvasDataReal.guanConfigs.forEach((config, index) => {
this.drawGuanImage(config);
});
// 4. 绘制连接线(遍历配置数组)
this.canvasDataReal.lineConfigs.forEach((config, index) => {
this.drawLine(config);
if (index == 1) {
// 执行针对第二个管子的特殊绘制方法
this.drawSecondPipeImage(config);
} else {
// 正常绘制其他管子
this.drawGuanImage(config);
}
});
// 5. 绘制白色警戒线所有点的文字标注(修改部分)
// 修改 drawAllImages 方法中的蓝色阴影绘制部分
this.canvasDataReal.lineConfigs.forEach((lineConfig) => {
if (lineConfig.color === "white" && lineConfig.points.length > 0) {
// 添加可选链校验
lineConfig.points.forEach((point, subindex) => {
// 遍历所有坐标点
// 获取对应设备的深度值(通过索引对应)
const equipment = this.equipmentDataList[subindex];
const depth = equipment.depth || ""; // 添加空值校验
if (lineConfig.color === 'white' && lineConfig.points.length >= 2) {
this.ctx.save();
this.ctx.setTransform(1, 0, 0, 1, 0, 0); // 恢复默认坐标系
// 绘制当前点的文字
this.drawText({
x: point.x,
y: this.canvas.height - point.y,
text: `浸润线埋深:${depth}m`,
});
});
}
});
// 直接使用白色线的原始坐标点,确保完全对齐
const whiteLinePoints = lineConfig.points;
const canvasHeight = this.canvas.height;
// 遍历相邻点对,生成梯形阴影
for (let i = 0; i < whiteLinePoints.length - 1; i++) {
const start = whiteLinePoints[i];
const end = whiteLinePoints[i + 1];
// 新增:绘制白色警戒线下方海蓝色阴影
this.canvasDataReal.lineConfigs.forEach((lineConfig) => {
if (lineConfig.color === 'white' && lineConfig.points.length >= 2) { // 至少需要2个点构成直线
this.ctx.save();
this.ctx.setTransform(1, 0, 0, 1, 0, 0); // 恢复默认坐标系(左上角原点,Y轴向下)
// // 增加测试数据
// lineConfig.points.push({
// x: lineConfig.points[1].x - 150,
// y: lineConfig.points[1].y -150
// })
// 将警戒线坐标转换为默认坐标系(原坐标系Y轴向上)
const canvasHeight = this.canvas.height; // 缓存画布高度
const convertedPoints = lineConfig.points.map(point => ({
x: point.x,
y: point.y // 转换为默认Y轴向下的坐标
}));
// 遍历相邻点对,生成梯形
for (let i = 0; i < convertedPoints.length - 1; i++) {
const start = convertedPoints[i];
const end = convertedPoints[i + 1];
// 构建当前线段对应的梯形四个顶点
// 构建梯形四个顶点(确保与白色线完全重合)
const trapezoid = [
start, // 顶部左端点
end, // 顶部右端点
{ x: end.x, y: canvasHeight }, // 底部右端点(垂直投影到底边)
{ x: start.x, y: canvasHeight }, // 底部左端点(垂直投影到底边)
{ x: start.x, y: start.y }, // 顶部左端点(与白色线起点完全对齐)
{ x: end.x, y: end.y }, // 顶部右端点(与白色线终点完全对齐)
{ x: end.x, y: canvasHeight }, // 底部右端点
{ x: start.x, y: canvasHeight } // 底部左端点
];
// 绘制当前梯形
// 绘制蓝色阴影
this.ctx.fillStyle = 'rgba(59, 175, 251, 0.3)'; // 海蓝色,透明度30%
this.ctx.beginPath();
trapezoid.forEach((point, index) => {
index === 0
? this.ctx.moveTo(point.x, point.y)
: this.ctx.lineTo(point.x, point.y);
index === 0 ? this.ctx.moveTo(point.x, point.y) : this.ctx.lineTo(point.x, point.y);
});
this.ctx.closePath();
this.ctx.fill();
......@@ -583,8 +899,192 @@ export default {
}
});
// 5. 绘制water.png
// this.drawWaterImage();
// 确保在阴影绘制之后再绘制白色线条
this.canvasDataReal.lineConfigs.forEach((config) => {
this.drawLine(config);
});
const colorsToConnect = ['red', 'orange', 'yellow', 'blue'];
// 为每种颜色定义对应的目标位置坐标
const targetPoints = {
'red': { x: 550, y: 304 },
'orange': { x: 560, y: 307 },
'yellow': { x: 570, y: 310 },
'blue': { x: 580, y: 313 }
};
// 第二条 ....
colorsToConnect.forEach(color => {
// 找到对应颜色的线配置
const lineConfig = this.canvasDataReal.lineConfigs.find(config => config.color === color);
if (lineConfig && lineConfig.points.length > 0) {
const lastPoint = lineConfig.points[lineConfig.points.length - 1];
// 获取该颜色对应的目标位置
const targetPoint = targetPoints[color];
// 绘制新的连接线,保持与原线相同的颜色和线宽
this.ctx.save();
this.ctx.setTransform(1, 0, 0, 1, 0, 0);
this.ctx.strokeStyle = color;
this.ctx.lineWidth = lineConfig.lineWidth || 2;
this.ctx.beginPath();
this.ctx.moveTo(lastPoint.x - 500, lastPoint.y + 300);
this.ctx.lineTo(targetPoint.x, targetPoint.y);
this.ctx.stroke();
this.ctx.restore();
}
});
// 5. 绘制白色警戒线所有点的文字标注(修改部分)
this.canvasDataReal.lineConfigs.forEach((lineConfig) => {
if (lineConfig.color === "white" && lineConfig.points.length > 0) {
// 1. 收集所有设备信息,包括设备名称中的数字
const deviceData = [];
lineConfig.points.forEach((point, subindex) => {
const equipment = this.equipmentDataList[subindex];
if (equipment) {
// 提取设备名称中的数字
const deviceNumber = equipment.sensorname ? parseInt(equipment.sensorname.match(/\d+/)[0] || '0') : 0;
deviceData.push({
point,
equipment,
subindex,
deviceNumber,
isOdd: deviceNumber % 2 === 1
});
}
});
// 2. 创建一个新的深度值数组,用于存放交换后的值
const newDepths = new Array(deviceData.length).fill('');
// 3. 实现相邻管子埋深值互换,根据设备名称中的数字奇偶性决定
for (let i = 0; i < deviceData.length - 1; i += 2) {
// 检查当前两个设备
const device1 = deviceData[i];
const device2 = deviceData[i + 1];
if (device1 && device2) {
// 如果第一个设备的编号是单数,则第一个管子的埋深值显示在第二个管子下面
if (device1.isOdd) {
newDepths[device1.subindex] = device1.equipment.depth || '';
newDepths[device2.subindex] = device2.equipment.depth || '';
} else if (!device2.isOdd) {
newDepths[device1.subindex] = device2.equipment.depth || '';
newDepths[device2.subindex] = device1.equipment.depth || '';
}
}
}
// 处理可能的奇数个设备的最后一个设备
if (deviceData.length % 2 === 1) {
const lastDevice = deviceData[deviceData.length - 1];
newDepths[lastDevice.subindex] = lastDevice.equipment.depth || '';
}
// 4. 绘制文本,使用交换后的深度值
deviceData.forEach(device => {
this.drawText({
x: device.point.x,
y: this.canvas.height - device.point.y,
text: `浸润线埋深:${newDepths[device.subindex]}m`,
});
});
}
});
// 浸润线
this.createCustomLineWithText({
points: [
{ x: 350, y: 300 },
{ x: 400, y: 370 },
],
color: '#000',
lineWidth: 1,
text: '浸润线',
textPosition: 'start', // 文字位置:start、middle、end
textDirection: 'horizontal', // 文字方向:horizontal、vertical、angle
textOffset: 9,
textColor: '#000',
fontSize: 14,
showArrow: true,
arrowSize: 8
});
// 正常高水位
this.createCustomLineWithText({
points: [
{ x: 585, y: 285 },
{ x: 585, y: 370 },
],
color: '#000',
lineWidth: 1,
text: '正常高水位',
textPosition: 'end',
textDirection: 'horizontal',
textOffset: -20,
textColor: '#000',
fontSize: 14
});
// 平滩
this.createCustomLineWithText({
points: [
{ x: 587, y: 285 },
{ x: 520, y: 285 },
],
color: '#000',
lineWidth: 1,
text: '干滩',
textPosition: 'middle',
textDirection: 'horizontal',
textOffset: 20,
textColor: 'orange',
fontSize: 15,
showArrow: true,
showArrowAtStart: true,
arrowSize: 7
});
// 大坝库
this.createCustomLineWithText({
points: [
{ x: 750, y: 270 },
{ x: 700, y: 355 },
],
color: '#000',
lineWidth: 1,
text: '大坝库',
textPosition: 'start',
textDirection: 'horizontal',
textOffset: 10,
textColor: '#2c4f7c',
fontSize: 15
});
// 传感器
this.createCustomLineWithText({
points: [
{ x: 300, y: 480 },
{ x: 400, y: 370 },
],
text: '渗压传感器',
showLine: false,
textPosition: 'start',
textDirection: 'horizontal',
textOffset: 15,
textColor: '#000',
fontSize: 11
});
this.createCustomLineWithText({
points: [
{ x: 505, y: 400 },
{ x: 400, y: 370 },
],
text: '渗压传感器',
showLine: false,
textPosition: 'start',
textDirection: 'horizontal',
textOffset: 15,
textColor: '#000',
fontSize: 11
});
},
/** 加载所有图片并绘制 */
loadAllImages() {
......@@ -593,12 +1093,12 @@ export default {
this.bgImage.src = require("@/assets/images/jrx/bg.png");
// // 加载 water.png
// this.waterImage = new Image();
// this.waterImage.src = require("@/assets/images/jrx/water.png");
this.waterImage = new Image();
this.waterImage.src = require("@/assets/images/jrx/shui.png");
// 加载 po.png
// 加载 shan.png
this.poImage = new Image();
this.poImage.src = require("@/assets/images/jrx/po.png");
this.poImage.src = require("@/assets/images/jrx/shan.png");
// 加载 guan.png
this.guanImage = new Image();
......@@ -607,9 +1107,9 @@ export default {
// 等待所有图片加载完成
Promise.all([
new Promise((resolve) => (this.bgImage.onload = resolve)),
// new Promise((resolve) => (this.waterImage.onload = resolve)),
new Promise((resolve) => (this.waterImage.onload = resolve)),
new Promise((resolve) => (this.poImage.onload = resolve)),
new Promise((resolve) => (this.guanImage.onload = resolve)),
new Promise((resolve) => (this.guanImage.onload = resolve))
])
.then(() => {
// 所有图片加载完成后绘制
......@@ -842,11 +1342,11 @@ export default {
// discern
var levelDist = [
{ color: "red", name: "红色报警线" },
{ color: "orange", name: "橙色报警线" },
{ color: "yellow", name: "黄色报警线" },
{ color: "blue", name: "蓝色报警线" },
],
{ color: "red", name: "红色报警线" },
{ color: "orange", name: "橙色报警线" },
{ color: "yellow", name: "黄色报警线" },
{ color: "blue", name: "蓝色报警线" }
],
alarmLine = {},
setAlarmSerie = function (value, name, color) {
// 修改蓝色色值
......@@ -898,16 +1398,16 @@ export default {
};
/* 智能报警线
var level = (~~alarms.alarmLevel || levelDist.length+1) - 1;
var nearLevel = level ? level - 1 : level;
var alarm = levelDist[level];
var nearAlarm = levelDist[nearLevel];
nearAlarm.value = value[nearAlarm.color];
alarmLine[nearAlarm.color] = nearAlarm;
if(alarm){
alarm.value = value[alarm.color];
alarmLine[alarm.color] = alarm;
}; */
var level = (~~alarms.alarmLevel || levelDist.length+1) - 1;
var nearLevel = level ? level - 1 : level;
var alarm = levelDist[level];
var nearAlarm = levelDist[nearLevel];
nearAlarm.value = value[nearAlarm.color];
alarmLine[nearAlarm.color] = nearAlarm;
if(alarm){
alarm.value = value[alarm.color];
alarmLine[alarm.color] = alarm;
}; */
// 多条报警线
for (var item of levelDist) {
......@@ -935,14 +1435,7 @@ export default {
});
}
},
// loadData: function () {
// // console.log(this.form, "form");
// // this.initChart1();
// // this.getCanvasData();
// return reqApi.common.getRequst;
// },
loadData:reqApi.common.getRequst,
loadData: reqApi.common.getRequst,
cancelForm() {
this.form.visible = false;
},
......@@ -953,6 +1446,5 @@ export default {
};
</script>
<style rel="stylesheet/scss" lang="scss" scope>
.qyzz {
}
.qyzz {}
</style>
<template>
<div class="common-page qyzz page-t1">
<div class="option page-row">
<table-filter ref="filter" :form="form" :Dict="Dict" :rules="rules" :config="form.config" :loadData="loadData" />
</div>
<div class="new-container" style="display: flex">
<div class="canvas-wrapper" style="width: 1000px">
<!-- 替换为 Canvas 元素 -->
<canvas ref="canvas" id="mainCanvas" width="1000" style="background: #f0f0f0"></canvas>
</div>
<div class="chart-wrapper" style="padding-left: 0px">
<div ref="chartContainer" style="
width: 870px;
height: 550px;
margin-bottom: 20px;
border: 1px solid gainsboro;
"></div>
<div class="chart-btn-group">
<button size="small" :type="currentChartType === 'line' ? 'primary' : ''" @click="switchChartType('line')">
折线图
</button>
<button size="small" :type="currentChartType === 'column' ? 'primary' : ''"
@click="switchChartType('column')">
柱状图
</button>
</div>
</div>
</div>
<div class="panel-bottom page-row">
<div class="ctin-box">
<div class="content-within">
<div class="content-fix">
<div class="toolbar">
<div>
<el-button v-for="(item, key) in form.config.otherBtn" size="mini" :type="item.type" :icon="item.icon"
@click="item.callback.call(_self, $event)">{{ item.name }}</el-button>
</div>
<div>
<el-button v-for="(item, key) in form.config.rightBtn" size="mini" :type="item.type" :icon="item.icon"
@click="item.callback.call(_self, $event)">{{ item.name }}</el-button>
</div>
</div>
<!-- 表格渲染 -->
<cu-table ref="cuTable" :table="table" :Dict="Dict" :config="form.config" :loadData="loadData" />
</div>
</div>
</div>
</div>
<!-- 表单渲染 -->
<cu-form ref="cuForm" :form="form" :Dict="Dict" :rules="rules" :submit="submitForm" :cancel="cancelForm"
:watchKeys="['paperfilename']" />
</div>
</template>
<script>
import Highcharts from "highcharts";
import { reqApi, Config } from "@/assets/js/httpApi.js";
import { Tools } from "@/assets/js/common.js";
import DateRangePicker from "@/components/DateRangePicker";
import TableFilter from "@/components/TableFilter";
import cuForm from "@/components/cuForm";
import cuTable from "@/components/cuTable";
import request from "@/utils/request";
export default {
name: "Dashboard",
components: {
DateRangePicker,
TableFilter,
cuForm,
cuTable,
},
data() {
return {
chartDataEmpty: false,
canvasDataEmpty: false,
Dict: { selectList: [] },
table: {
page: 1,
size: 10,
total: 0,
loading: false,
dataList: [],
},
rules: {},
form: {
title: "",
visible: false,
reqType: "add",
historyDialog: false,
status: { cu: 0 },
query: {},
search: {},
item: {},
file: 0,
config: {},
},
// 新增图表相关数据
chartVisible: true, // 图表弹窗可见性
deviceList: [{ id: "test001", name: "测试设备1" }], // 设备列表数据
selectedDevice: null, // 选中设备ID
dateRange: [null, null], // 日期范围选择
currentChartType: "line", // 当前图表类型(line/column)
chartLoading: false, // 图表加载状态
chartInstance: null, // Highcharts实例引用
// ...原有data属性保持不变...
canvas: null, // Canvas 实例
ctx: null, // 2D 上下文
bgImage: null, // 背景图对象
waterImage: null, // 新增:water.png 图片对象
poImage: null, // 新增:po.png 图片对象
canvasDataReal: {
poConfigsWH: [{ // 基础信息配置对象 用于换算具体画布xy坐标点
xieMianW: 50, // 第一个坡斜面距离第一个坡平面的水平距离。
pingMianW: 100, // 第一个坡平面距离平面宽度。
pingMianH: 150, // 第一个坡平面距离平面高度。
kongW: 150, // 目前设定打孔的位置在坡平面上距离左侧起始点的距离
kongH: 20, // 目前孔的深度
maishen: 10, // 水位到管口的垂直距离
}],
otherConfig: {
gantanW: 20, // 干滩距离水平面的宽度(根据最后一个坡平面坐标点计算xy。)
tuduiW: 30, // 干滩距离水平面中间的土堆
shuiW: 50, // 水平面的宽度
shuiH: 30, // 水平面的高度
},
// Canvas绘制配置(支持批量扩展)
poConfigsXY: [ // 根据poConfigsWH 计算具体的xy坐标点,每个对象计算出两对坐标点。分别是斜面和平面点
],
guanConfigsXY: [ // 根据poConfigsXY和poConfigsWH的孔信息 计算具体的xy坐标点,每个对象计算出两对坐标点。分别是孔起始坐标和结束坐标
],
gantanConfigsXY: [
],
jrxConfigsXY: [
],
shuiweiConfigsXY: [
],
tuduiConfigsXY: [
],
jingjiexianConfigsXY: [
],
lineConfigs: [
{ points: [], color: "red", lineWidth: 2 }, // 红色连接线配置
{ points: [], color: "yellow", lineWidth: 2 }, // 黄色连接线配置
],
},
// canvasData: [
// {
// name: "剖面名称",
// height: "剖面高度",
// width: "剖面宽度",
// code: "剖面编号",
// sdeg: "水区扇形起始角度",
// diameter: "总直径",
// jrxStepsDtoList: [
// {
// name: "台阶名称",
// code: "台阶编号",
// height: "高度(米)",
// width: "宽度(米)",
// slope: "坡度(deg)"
// }
// ],
// equipmentDataList: [
// {
// sensorid: "设备id",
// sensorname: "设备名称",
// unit: "设备单位",
// stage: "水位(传感器到水面的距离)",
// depth: "浸润线埋深(水位到管口的距离)(m)",
// smhb: "// 水面海拔",
// time: "时间",
// holeDepth: "孔口高程",
// jrxTrepanning: "浸润线开口深度",
// redAlarm: "红色预警 此预警值针对的是depth 浸润线埋深",
// orangeAlarm: "橙色预警",
// yellowAlarm: "黄色预警",
// blueAlarm: "蓝色预警"
// }
// ]
// }
// ]
};
},
created() {
// 获取基本信息
this.pageApi = Config.getModuleInfo(this);
this.Dict = this.pageApi.Dict;
this.form.config = this.pageApi.config;
this.rules = reqApi.getRules(this.Dict.baseInfo) || this.Dict.rules || {};
this.pageApi.created && this.pageApi.created();
// 新增:获取地址栏deviceId参数并设置到form.query.code
const deviceId = this.$route.query.deviceId;
if (deviceId) {
this.form.query.sensorid = deviceId; // 将deviceId赋值到查询条件的code字段
}
// this.handleCanvasData(this.canvasData);
},
mounted() {
this.$nextTick(() => {
this.loadData();
this.initChart1()
this.getCanvasData();
});
// 获取选择列表字典
var selectList = this.Dict.selectList;
Tools.asyncLoop.call(this, selectList, function (key, value, next) {
if (typeof value === "function") {
value.call(this.Dict).then(function (res) {
selectList[key] = res;
next();
});
} else {
next();
}
});
},
methods: {
/** 绘制文字标注 */
drawText(config) {
this.ctx.save();
this.ctx.setTransform(1, 0, 0, 1, 0, 0); // 恢复默认坐标系(左上角原点)
this.ctx.font = `10px Arial`; // 文字大小8px
this.ctx.fillStyle = "#000"; // 黄色
this.ctx.textAlign = "center"; // 水平居中
this.ctx.textBaseline = "top"; // 垂直顶部对齐
// 绘制文字(考虑Y轴方向转换)
const drawY = this.canvas.height - config.y; // 转换为默认坐标系Y轴
this.ctx.fillText(config.text, config.x, drawY + 5); // Y轴偏移5px避免重叠
this.ctx.restore();
},
/** 清空画布内容及配置 */
clearCanvas() {
if (this.ctx) {
// 清除画布绘制内容(基于当前坐标系)
this.ctx.save();
this.ctx.setTransform(1, 0, 0, 1, 0, 0); // 恢复默认坐标系
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); // 清空整个画布
this.ctx.restore();
}
// 重置配置数据(避免残留)
this.canvasDataReal.poConfigs = [];
this.canvasDataReal.guanConfigs = [];
this.canvasDataReal.lineConfigs = [];
},
getCanvasData() {
const params = { ...this.form.query };
request({
url: "tab/jrx/dissect/visual-xinHua",
method: "get",
params,
}).then(async (res) => {
const data = res.body;
if (!data.length) {
// 数据为空时清空画布
this.clearCanvas();
return;
}
// console.log("剖面接口数据", data);
// console.table(JSON.parse(JSON.stringify(data[0].jrxStepsDtoList)));
// console.table(JSON.parse(JSON.stringify(data[0].equipmentDataList)));
await this.handleCanvasData(data);
this.initCanvas();
});
},
handleCanvasDataNew(list = []) {
return new Promise((resolve) => {
// 新增Promise封装
let canvasWidth = 1000; // 默认宽度
let canvasHeight = 600; // 默认高度
// 更新Canvas元素属性和样式
const canvasEl = this.$refs.canvas;
if (canvasEl) {
// 实际绘图区域尺寸(关键属性)
canvasEl.width = canvasWidth;
canvasEl.height = canvasHeight;
// 显示尺寸(与绘图区域保持一致)
canvasEl.style.width = `${canvasWidth}px`;
canvasEl.style.height = `${canvasHeight}px`;
}
// 数据清洗
const poumian = list[0]; // 坡面数据
const poCount = poumian.jrxStepsDtoList.length;
const lineCount = 5;
const po_pad_right = 180; // poCount > 4 ? 130 : 180; // 第一个台阶距离画布的距离
const poH = 150;
const line_color = ["red", "orange", "yellow", "blue", "white"];
this.canvasDataReal.poConfigs = [];
this.canvasDataReal.guanConfigs = [];
this.canvasDataReal.lineConfigs = [];
//第一层台阶的开孔深度和设备图片相除的系数
const sbHeightModulus =
poumian.equipmentDataList[0].jrxTrepanning / 130;
// 存储设备数据列表(关键新增,用于后续获取depth值)
this.equipmentDataList = poumian.equipmentDataList || [];
// 坡面基本信息获取
for (let index = 0; index < poCount; index++) {
this.poConfigsWH.push({
xieMianW: 10 + index, // 第一个坡斜面距离第一个坡平面的水平距离。
pingMianW: 50 + index, // 第一个坡平面距离平面宽度。
pingMianH: 20 + index, // 第一个坡平面距离平面高度。
kongW: 10 + index, // 目前设定打孔的位置在坡平面上距离左侧起始点的距离
kongH: 20 + index, // 目前孔的深度
jrxTrepanning: 10 + index, // 浸润线开口深度
})
}
// 破平面xy计算
this.poConfigsXY = [{ x: 0, y: 0 }]
this.poConfigsWH.forEach((item) => {
this.poConfigsXY.push({ // 斜坡点
x: this.poConfigsXY[this.poConfigsXY.length - 1].x + item.xieMianW, // 每个斜平坡计算点都根据上一个前面已有的最后一个坐标点进行添加 第一个为x0y0
y: this.poConfigsXY[this.poConfigsXY.length - 1].y + item.pingMianH,
})
this.poConfigsXY.push({ // 平坡点
x: this.poConfigsXY[this.poConfigsXY.length - 1].x + item.pingMianW,
y: this.poConfigsXY[this.poConfigsXY.length - 1].y,
})
// 孔的xy计算
this.guanConfigsXY.push({ // 管的起始点 -2是获取该斜坡点的结束坐标加上孔距离位置=孔在平坡上面的位置
x: this.poConfigsXY[this.poConfigsXY.length - 2].x + item.kongW,
y: this.poConfigsXY[this.poConfigsXY.length - 2].y + 0, // 这里的0为了突出孔的仪器设备 突出坡平面距离。这里先放置0(方便后面浸润线水位的计算),等后面实际画管线的时候临时加上固定值。
})
this.guanConfigsXY.push({ // 管的结束点
x: this.poConfigsXY[this.poConfigsXY.length - 2].x + item.kongW,
y: this.poConfigsXY[this.poConfigsXY.length - 2].y - item.kongH,
maishen: item.depth, // 水位到管口的垂直距离
})
})
this.gantanConfigsXY = [ // 干滩的xy坐标点
{ x: this.poConfigsXY[this.poConfigsXY.length - 1].x, y: this.poConfigsXY[this.poConfigsXY.length - 1].y }, // 干滩的起始点
{
x: this.poConfigsXY[this.poConfigsXY.length - 1].x + this.otherConfig.gantanW,
y: this.poConfigsXY[this.poConfigsXY.length - 1].y - this.otherConfig.shuiH
}, // 干滩的结束点 (最高平坡减去水位高度)
]
this.guanConfigsXY.forEach((item, index) => {
if (index % 2 == 0) { // 偶数为管的起始点
this.jrxConfigsXY.push(
{ x: item.x, y: item.y - item.maishen }, // 浸润线的坐标点是平坡y-埋深的值(水位到平坡的垂直距离)
)
}
})
this.shuiweiConfigsXY = [ // 水位的xy坐标点(画矩形)
{ x: this.gantanConfigsXY[1].x, y: this.gantanConfigsXY[1].y }, // 水位的起始点
{ x: this.gantanConfigsXY[1].x + this.otherConfig.tuduiW, y: this.gantanConfigsXY[1].y }, // 水位的结束点 (最高平坡减去水位高度)
]
this.tuduiConfigsXY = [
{ x: this.gantanConfigsXY[1].x, y: this.gantanConfigsXY[1].y }, // 水位的起始点
{ x: this.gantanConfigsXY[1].x + this.otherConfig.tuduiW, y: 0 }, // 水位的结束点
]
this.jingjiexianConfigsXY = [
{ x: this.gantanConfigsXY[1].x, y: this.gantanConfigsXY[1].y }, // 水位的起始点
{ x: this.gantanConfigsXY[1].x + this.otherConfig.tuduiW, y: 0 }, // 水位的结束点
]
// 警戒线逻辑- 初始话基本数据结构
for (let index1 = 0; index1 < lineCount; index1++) {
this.jingjiexianConfigsXY.push({
// 设置
points: [],
color: line_color[index1],
lineWidth: 2,
cha: 20 * index1, // 每条线之间的差值
});
}
// 警戒线种类下,根据管孔设备个数,设定对应的坐标点point
this.jingjiexianConfigsXY.forEach((line, index) => {
let lineValKey =
line.color == "white" ? "depth" : line.color + "Alarm";
// 几个管孔几个坐标点
poumian.equipmentDataList.forEach((equip, subindex) => {
line.points.push({
x: this.canvasDataReal.guanConfigs[subindex].x + 1,
y:
this.canvasDataReal.guanConfigs[subindex].y +
equip[lineValKey] / sbHeightModulus, // 管设备的y坐标+设备的警戒值*系数
});
});
});
// 4. 绘制连接线(遍历配置数组)
this.canvasDataReal.lineConfigs.forEach((config, index) => {
this.drawLine(config);
});
// 5. 绘制白色警戒线所有点的文字标注(修改部分)
this.canvasDataReal.lineConfigs.forEach((lineConfig) => {
if (lineConfig.color === "white" && lineConfig.points.length > 0) {
// 添加可选链校验
lineConfig.points.forEach((point, subindex) => {
// 遍历所有坐标点
// 获取对应设备的深度值(通过索引对应)
const equipment = this.equipmentDataList[subindex];
const depth = equipment.depth || ""; // 添加空值校验
// 绘制当前点的文字
this.drawText({
x: point.x,
y: this.canvas.height - point.y,
text: `浸润线埋深:${depth}m`,
});
});
}
});
resolve(); // 数据处理完成后触发resolve
});
},
handleCanvasData(list = []) {
return new Promise((resolve) => {
// 新增Promise封装
let canvasWidth = 1000; // 默认宽度
let canvasHeight = 600; // 默认高度
// 更新Canvas元素属性和样式
const canvasEl = this.$refs.canvas;
if (canvasEl) {
// 实际绘图区域尺寸(关键属性)
canvasEl.width = canvasWidth;
canvasEl.height = canvasHeight;
// 显示尺寸(与绘图区域保持一致)
canvasEl.style.width = `${canvasWidth}px`;
canvasEl.style.height = `${canvasHeight}px`;
}
// 数据清洗
const poumian = list[0]; // 坡面数据
const poCount = poumian.jrxStepsDtoList.length;
const lineCount = 5;
const po_pad_right = 180; // poCount > 4 ? 130 : 180; // 第一个台阶距离画布的距离
const poH = 150;
const line_color = ["red", "orange", "yellow", "blue", "white"];
this.canvasDataReal.poConfigs = [];
this.canvasDataReal.guanConfigs = [];
this.canvasDataReal.lineConfigs = [];
//第一层台阶的开孔深度和设备图片相除的系数
const sbHeightModulus =
poumian.equipmentDataList[0].jrxTrepanning / 130;
// 存储设备数据列表(关键新增,用于后续获取depth值)
this.equipmentDataList = poumian.equipmentDataList || [];
// 坡数据数据格式处理
poumian.jrxStepsDtoList.forEach((po, poIndex) => {
this.canvasDataReal.poConfigs.push({
x: 0,
y: canvasHeight - (poIndex + 1) * poH,
width: canvasWidth - (poIndex + 1) * po_pad_right,
height: poH,
});
});
// 管孔数据数据格式处理
poumian.equipmentDataList.forEach((equipment, equipIndex) => {
const po = this.canvasDataReal.poConfigs[equipIndex];
// 管孔数据数据格式处理
this.canvasDataReal.guanConfigs.push({
x: po.width * 0.75 + 50,
y: canvasHeight - po.height * (equipIndex + 1),
width: 6,
height: equipment.jrxTrepanning / sbHeightModulus,
image: "guanImage",
});
});
// 警戒线逻辑- 初始话基本数据结构
for (let index1 = 0; index1 < lineCount; index1++) {
this.canvasDataReal.lineConfigs.push({
// 设置
points: [],
color: line_color[index1],
lineWidth: 2,
cha: 20 * index1, // 每条线之间的差值
});
}
// 警戒线种类下,根据管孔设备个数,设定对应的坐标点point
this.canvasDataReal.lineConfigs.forEach((line, index) => {
let lineValKey =
line.color == "white" ? "depth" : line.color + "Alarm";
// 几个管孔几个坐标点
poumian.equipmentDataList.forEach((equip, subindex) => {
line.points.push({
x: this.canvasDataReal.guanConfigs[subindex].x + 1,
y:
this.canvasDataReal.guanConfigs[subindex].y +
equip[lineValKey] / sbHeightModulus, // 管设备的y坐标+设备的警戒值*系数
});
});
});
// console.log("坡面处理完毕数据", this.canvasDataReal);
// console.table(
// JSON.parse(JSON.stringify(this.canvasDataReal.poConfigs))
// );
// console.table(
// JSON.parse(JSON.stringify(this.canvasDataReal.guanConfigs))
// );
// console.table(
// JSON.parse(JSON.stringify(this.canvasDataReal.lineConfigs))
// );
resolve(); // 数据处理完成后触发resolve
});
},
/** 初始化 Canvas 画布及坐标系 */
initCanvas() {
// 获取 Canvas 元素和上下文
this.canvas = this.$refs.canvas; // document.getElementById('mainCanvas')
if (!this.canvas) {
console.error("Canvas 元素未找到");
return;
}
// console.log(this.canvas, "canvas");
this.ctx = this.canvas.getContext("2d");
// 坐标系变换:将原点移至左下角(默认原点在左上角)
this.ctx.translate(0, this.canvas.height); // 向下移动画布高度
this.ctx.scale(1, -1); // 翻转 Y 轴方向(上为正)
// // 加载背景图并绘制
// this.loadBackgroundImage();
// 加载所有图片并绘制
this.loadAllImages();
},
// 绘制单个po.png(支持配置参数)
drawPoImage(config) {
this.ctx.save();
this.ctx.setTransform(1, 0, 0, 1, 0, 0);
// 动态计算y坐标(若未指定则默认画布底部-高度)
this.ctx.drawImage(
this.poImage,
config.x,
config.y,
config.width,
config.height
);
this.ctx.restore();
},
// 绘制单个guan.png(支持不同图片类型)
drawGuanImage(config) {
this.ctx.save();
this.ctx.setTransform(1, 0, 0, 1, 0, 0);
const targetImage = this[config.image]; // 根据配置获取具体图片对象(如guanImage/guanImage1)
this.ctx.drawImage(
targetImage,
config.x,
config.y,
config.width,
config.height
);
this.ctx.restore();
},
// 绘制连接线(支持多坐标点)
drawLine(config) {
this.ctx.save();
this.ctx.setTransform(1, 0, 0, 1, 0, 0);
this.ctx.strokeStyle = config.color;
this.ctx.lineWidth = config.lineWidth;
this.ctx.beginPath();
config.points.forEach((point, index) => {
index === 0
? this.ctx.moveTo(point.x, point.y)
: this.ctx.lineTo(point.x, point.y);
});
this.ctx.stroke();
this.ctx.restore();
},
// 绘制背景图(独立方法)
drawBackground() {
this.ctx.save();
this.ctx.setTransform(1, 0, 0, 1, 0, 0);
this.ctx.drawImage(
this.bgImage,
0,
0,
this.canvas.width,
this.canvas.height
);
this.ctx.restore();
},
// 绘制water.png(独立方法)
drawWaterImage() {
this.ctx.save();
this.ctx.setTransform(0.7, 0, 0, 1, 0, 0);
this.ctx.drawImage(
this.waterImage,
0,
this.canvas.height - 255,
485,
255
);
this.ctx.restore();
},
// 重构后的统一绘制入口(通过配置驱动)
drawAllImages() {
// 1. 绘制背景图
this.drawBackground();
// 2. 绘制po.png(遍历配置数组)
// console.log(this.canvasDataReal.poConfigs, "poConfigs");
this.canvasDataReal.poConfigs.forEach((config, index) => {
this.drawPoImage(config);
});
// 3. 绘制guan.png(遍历配置数组)
// console.log(this.canvasDataReal.guanConfigs, "guanConfigs");
this.canvasDataReal.guanConfigs.forEach((config, index) => {
this.drawGuanImage(config);
});
// 4. 绘制连接线(遍历配置数组)
this.canvasDataReal.lineConfigs.forEach((config, index) => {
this.drawLine(config);
});
// 5. 绘制白色警戒线所有点的文字标注(修改部分)
this.canvasDataReal.lineConfigs.forEach((lineConfig) => {
if (lineConfig.color === "white" && lineConfig.points.length > 0) {
// 添加可选链校验
lineConfig.points.forEach((point, subindex) => {
// 遍历所有坐标点
// 获取对应设备的深度值(通过索引对应)
const equipment = this.equipmentDataList[subindex];
const depth = equipment.depth || ""; // 添加空值校验
// 绘制当前点的文字
this.drawText({
x: point.x,
y: this.canvas.height - point.y,
text: `浸润线埋深:${depth}m`,
});
});
}
});
// 新增:绘制白色警戒线下方海蓝色阴影
this.canvasDataReal.lineConfigs.forEach((lineConfig) => {
if (lineConfig.color === 'white' && lineConfig.points.length >= 2) { // 至少需要2个点构成直线
this.ctx.save();
this.ctx.setTransform(1, 0, 0, 1, 0, 0); // 恢复默认坐标系(左上角原点,Y轴向下)
// // 增加测试数据
// lineConfig.points.push({
// x: lineConfig.points[1].x - 150,
// y: lineConfig.points[1].y -150
// })
// 将警戒线坐标转换为默认坐标系(原坐标系Y轴向上)
const canvasHeight = this.canvas.height; // 缓存画布高度
const convertedPoints = lineConfig.points.map(point => ({
x: point.x,
y: point.y // 转换为默认Y轴向下的坐标
}));
// 遍历相邻点对,生成梯形
for (let i = 0; i < convertedPoints.length - 1; i++) {
const start = convertedPoints[i];
const end = convertedPoints[i + 1];
// 构建当前线段对应的梯形四个顶点
const trapezoid = [
start, // 顶部左端点
end, // 顶部右端点
{ x: end.x, y: canvasHeight }, // 底部右端点(垂直投影到底边)
{ x: start.x, y: canvasHeight }, // 底部左端点(垂直投影到底边)
];
// 绘制当前梯形
this.ctx.fillStyle = 'rgba(59, 175, 251, 0.3)'; // 海蓝色,透明度30%
this.ctx.beginPath();
trapezoid.forEach((point, index) => {
index === 0
? this.ctx.moveTo(point.x, point.y)
: this.ctx.lineTo(point.x, point.y);
});
this.ctx.closePath();
this.ctx.fill();
}
this.ctx.restore();
}
});
// 5. 绘制water.png
// this.drawWaterImage();
},
/** 加载所有图片并绘制 */
loadAllImages() {
// 加载背景图(原有)
this.bgImage = new Image();
this.bgImage.src = require("@/assets/images/jrx/bg.png");
// // 加载 water.png
this.waterImage = new Image();
this.waterImage.src = require("@/assets/images/jrx/water.png");
// 加载 po.png
this.poImage = new Image();
this.poImage.src = require("@/assets/images/jrx/po.png");
// 加载 guan.png
this.guanImage = new Image();
this.guanImage.src = require("@/assets/images/jrx/guan0.png");
// 等待所有图片加载完成
Promise.all([
new Promise((resolve) => (this.bgImage.onload = resolve)),
new Promise((resolve) => (this.waterImage.onload = resolve)),
new Promise((resolve) => (this.poImage.onload = resolve)),
new Promise((resolve) => (this.guanImage.onload = resolve)),
])
.then(() => {
// 所有图片加载完成后绘制
this.drawAllImages();
})
.catch(() => {
console.error("部分图片加载失败");
});
},
/** 初始化图表(关键修改:调整图例位置) */
initChart1() {
let params = {
sort: "date,desc",
};
if (this.form.query.daterange) {
params.daterange = this.form.query.daterange.join(",");
}
if (this.form.query.sensorid) {
params.code = this.form.query.sensorid;
}
request({
url: "data/st/imghistory",
method: "get",
params,
}).then((res) => {
const data = res.body;
// const data = this.getChartData().body
// console.log("data", data);
const chartData = this.seriesDataFormat(data, { datekey: "date" });
var warningLine = undefined; // this.form.config.warningLine;
var option = {
valEnabled: true,
opacity: 1,
lineWidth: 3,
};
var alarmData = this.discernValidAlarmValue(
data.alarm,
data.lists,
chartData.series,
warningLine,
option
);
// const chartData = data
// console.log("chartCData", chartData);
Highcharts.setOptions({
global: {
useUTC: false,
},
lang: {
resetZoom: "重置缩放比例",
},
});
this.chartInstance = new Highcharts.chart(this.$refs.chartContainer, {
chart: {
//type: '',
backgroundColor: "transparent",
//marginTop:30,
//marginBottom:30,
//marginLeft:30,
zoomType: "x", // xy
},
valEnabled: true,
opacity: 1,
lineWidth: 3,
title: {
text: "",
},
subtitle: {
text: "",
},
tooltip: {
enabled: false,
borderWidth: 10,
},
xAxis: {
type: "datetime",
// 最为关键的代码:如果为空数组,则导致日期格式化失效!!
categories: chartData.categories[0] && chartData.categories,
lineWidth: 0,
//lineColor:'#ff0000',
gridLineColor: "#aaa",
dateTimeLabelFormats: {
millisecond: "%H:%M:%S.%L",
second: "%H:%M:%S",
minute: "%H:%M",
hour: "%H:%M",
day: "%m-%d",
week: "%m-%d",
month: "%Y-%m",
year: "%Y",
},
},
yAxis: {
title: {
text: "",
},
labels: {
x: -6,
},
gridLineColor: "#aaa",
max: null,
},
plotOptions: {
column: {
borderWidth: 0,
//y:50,
//itemMarginTop:50,
},
bar: {
borderWidth: 0,
},
},
tooltip: {
// {point.y:.4f} // 保留4位小数
//headerFormat: '<span style="font-size:10px">{point.key}</span><table>',
pointFormat:
'<tr><td style="color:{series.color};padding:0">{series.name}:</td>' +
'<td style="padding:0"><b>{point.y}' +
data.danwei +
"</b> </td></tr>",
footerFormat: "</table>",
shared: true,
useHTML: true,
dateTimeLabelFormats: {
millisecond: "%H:%M:%S.%L",
second: "%H:%M:%S",
minute: "%H:%M",
hour: "%H:%M",
day: "%m-%d %H时",
week: "%m-%d",
month: "%Y-%m",
year: "%Y",
},
},
legend: {
enabled: chartData.series.length > 1 ? true : false,
// 图例定位
layout: "horizontal", // 水平布局:“horizontal”, 垂直布局:“vertical”
floating: false, // 图列是否浮动
align: "right",
// 图例容器
//width:'100%', // number || String
padding: 2, // 内边距
margin: 2,
borderRadius: 5,
//borderWidth:1,
verticalAlign: "top",
// 图例项
//itemWidth:120, // 宽度
itemDistance: 10, // 间距 20
y: -10,
itemMarginTop: 2,
itemStyle: {},
itemHoverStyle: {},
},
credits: {
enabled: false,
},
series: chartData.series,
});
});
},
seriesDataFormat(data, opts) {
var names = data.names || [],
list = data.list || data.lists,
series = [],
categories = [],
maxVal = 0;
if (names[0] && list) {
var colors = [
"#7CB5EC",
"#90ED7D",
"#F7A35C",
"#8085E9",
"#F15C80",
"#E4D354",
"#2B908F",
"#F45B5B",
"#91E8E1",
"#0769CB",
"#00ABBD",
"#ffd886",
"#9F2E61",
"#4D670C",
];
var len = names.length;
for (var i = 0; i < len; i++) {
var item = names[i];
var serie = {
name: item.name,
data: [],
key: item.key,
type: data.chartType,
color: colors[i],
};
opts && serie.type && (serie.type = opts.type);
series.push(serie);
}
for (var item of list) {
var values = item.values;
//var datetime = item[opts.datekey || 'dateUnit'];
//var time = datetime.indexOf(' ') > 0 ? datetime.split(' ')[1] : datetime;
var timestamp = item["date"];
//categories.push(timestamp);
for (var serie of series) {
var value = values[serie.key] * 1;
Math.abs(value) > maxVal && (maxVal = Math.abs(value));
serie.data.push([timestamp, value]);
}
}
}
return { series: series, categories: categories, maxVal: maxVal };
},
discernValidAlarmValue(alarms, list, series, direction, opts) {
var xLength = (list || []).length,
maxAlarm = 0,
opts = opts || {};
if (alarms && xLength) {
var value = alarms.value;
// discern
var levelDist = [
{ color: "red", name: "红色报警线" },
{ color: "orange", name: "橙色报警线" },
{ color: "yellow", name: "黄色报警线" },
{ color: "blue", name: "蓝色报警线" },
],
alarmLine = {},
setAlarmSerie = function (value, name, color) {
// 修改蓝色色值
color === "blue" && (color = "#3BAFFB");
var sx = list[0].date,
ex = list[xLength - 1].date;
var serie = {
name: name,
type: "spline",
data: [
{ x: sx, y: value },
{ x: ex, y: value },
],
color: color,
enableMouseTracking: false,
legend: false,
showInLegend: false,
dashStyle: "ShortDot",
lineWidth: opts.lineWidth || 1,
states: {
inactive: {
opacity: opts.opacity,
},
},
dataLabels: {
enabled: opts.valEnabled || false, // 数据值, 2022/11/11(周五) 因多条报警线暂时关闭
//backgroundColor:'red',
verticalAlign: "middle",
padding: 0,
defer: false,
allowOverlap: true,
color: color,
style: {
textOutline: "none",
},
},
tooltip: {
//footerFormat:'',
//pointFormat:'',
headerFormat: "",
//nullFormat:'',
},
marker: {
enabled: false,
},
zIndex: -10,
};
series.push(serie);
};
/* 智能报警线
var level = (~~alarms.alarmLevel || levelDist.length+1) - 1;
var nearLevel = level ? level - 1 : level;
var alarm = levelDist[level];
var nearAlarm = levelDist[nearLevel];
nearAlarm.value = value[nearAlarm.color];
alarmLine[nearAlarm.color] = nearAlarm;
if(alarm){
alarm.value = value[alarm.color];
alarmLine[alarm.color] = alarm;
}; */
// 多条报警线
for (var item of levelDist) {
item.value = value[item.color];
alarmLine[item.color] = item;
}
// add
for (var key in alarmLine) {
var line = alarmLine[key];
line.value > maxAlarm && (maxAlarm = line.value);
setAlarmSerie(line.value, line.name, line.color);
direction && setAlarmSerie(0 - line.value, line.name, line.color);
}
}
return { series, maxAlarm };
},
/** 切换图表类型 */
switchChartType(type) {
this.currentChartType = type;
if (this.chartInstance) {
this.chartInstance.series.forEach((series) => {
series.update({ type: this.currentChartType });
});
}
},
// loadData: function () {
// // console.log(this.form, "form");
// // this.initChart1();
// // this.getCanvasData();
// return reqApi.common.getRequst;
// },
loadData: reqApi.common.getRequst,
cancelForm() {
this.form.visible = false;
},
submitForm(form, item) {
reqApi.common.submitForm.call(this, form, item);
},
},
};
</script>
<style rel="stylesheet/scss" lang="scss" scope>
.qyzz {}
</style>
......@@ -12,8 +12,8 @@ function resolve(dir) {
};
const name = defaultSettings.title; // 网址标题
const port = process.env.VUE_APP_LOCAL_PORT; // 端口配置
const VUE_APP_BASE_API = process.env.VUE_APP_BASE_API;
const port = 9527; // 端口配置
const VUE_APP_BASE_API = 'http://192.168.2.37:9003';
// All configuration item explanations can be find in https://cli.vuejs.org/config/
module.exports = {
......@@ -63,14 +63,14 @@ module.exports = {
},
proxy: {
'/api': {
target: process.env.VUE_APP_BASE_API,
target: VUE_APP_BASE_API,
changeOrigin: true,
pathRewrite: {
'^/api': 'api'
}
},
'/auth': {
target: process.env.VUE_APP_BASE_API,
target: VUE_APP_BASE_API,
changeOrigin: true,
pathRewrite: {
'^/auth': 'auth'
......
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