207版本:canvas电流流向功能,海外自定义电价功能

This commit is contained in:
huangjp
2025-10-10 09:27:34 +08:00
parent de8e81a5e2
commit 59954beeca
15 changed files with 1567 additions and 298 deletions

View File

@ -462,6 +462,9 @@ const install = (Vue, vm) => {
// 查询区域
GetIndustrialElecRegionList: (params = {}) => vm.$u.post(config.adminPath +
"/business/industrialElecRegion/list", params),
/** 查询自定义电价*/
GetCustomElecPricePage: (params = {}) => vm.$u.post(config.adminPath +
"/business/elecPriceCurve/all", params),
/** 查询所有代理电价-分页*/
GetIndustrialElecPricePage: (params = {}) => vm.$u.post(config.adminPath +
"/business/industrialElecPrice/page", params),

View File

@ -30,6 +30,7 @@ export default {
name:'China Station'
},{
name:'Overseas Station'
}]
},
}],
useElecPrice: 'Electricity prices'
}
}

View File

@ -30,6 +30,7 @@ export default {
name:'中国站'
},{
name:'海外站'
}]
}],
useElecPrice:'用电价格'
}
};

View File

@ -64,14 +64,10 @@
methods: {
getSystemInfo() {
const self = this
// 获取屏幕尺寸
uni.getSystemInfo({
success: (res) => {
this.windowWidth = res.windowWidth
},
})
uni.getSystemInfo({
success: function(res) {
// 获取屏幕尺寸
self.windowWidth = res.windowWidth
// const platform = res.hostName.toLowerCase()
if (res.uniPlatform || res.uniPlatform === 'app') {
self.type = 'app'
@ -87,20 +83,25 @@
})
},
clear() {
// if (this.type === 'wx') {
// this.ctx.globalCompositeOperation = 'destination-out';
// this.ctx.beginPath();
// this.ctx.fillStyle = 'red';
// this.ctx.fillRect(0, 0, 8000, 80000);
// this.ctx.fill();
// this.ctx.globalCompositeOperation = 'source-over';
// // this.ctx.draw();
// } else {
// // this.ctx.clearRect(2000, 2000, 2000, 2000);
// // this.ctx.fillStyle = '#ffffff'
// // this.ctx.draw(true);
// }
if (this.type === 'wx') {
this.ctx.globalCompositeOperation = 'destination-out';
this.ctx.beginPath();
this.ctx.fillStyle = 'red';
this.ctx.fillRect(0, 0, 8000, 80000);
this.ctx.fill();
this.ctx.globalCompositeOperation = 'source-over';
// this.ctx.draw();
this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
} else {
// this.ctx.clearRect(2000, 2000, 2000, 2000);
// this.ctx.fillStyle = '#ffffff'
// this.ctx.draw(true);
// App 平台
this.ctx.clearRect(0, 0, 8000, 8000);
}
},
//获取app的canvas DOM
getAppDom() {
@ -216,22 +217,22 @@
},
countChineseAndEnglishCharacters(str, x) {
var chineseCount = str.match(/[\u4e00-\u9fa5]/g)
? str.match(/[\u4e00-\u9fa5]/g).length
: 0;
var englishCount = str.match(/[a-zA-Z]/g)
? str.match(/[a-zA-Z]/g).length
: 0;
var otherCount = str.length - chineseCount - englishCount;
const obj = {
otherCount: otherCount,
chineseCount: chineseCount,
englishCount: englishCount,
};
return (
obj.englishCount * 6 + obj.chineseCount * 12 + obj.otherCount * 7.5 + x
);
},
var chineseCount = str.match(/[\u4e00-\u9fa5]/g) ?
str.match(/[\u4e00-\u9fa5]/g).length :
0;
var englishCount = str.match(/[a-zA-Z]/g) ?
str.match(/[a-zA-Z]/g).length :
0;
var otherCount = str.length - chineseCount - englishCount;
const obj = {
otherCount: otherCount,
chineseCount: chineseCount,
englishCount: englishCount,
};
return (
obj.englishCount * 6 + obj.chineseCount * 12 + obj.otherCount * 7.5 + x
);
},
drawText(draw) {
draw.forEach((item, index) => {
@ -244,8 +245,10 @@
this.ctx.fontSize = item2.size
}
this.ctx.fillStyle = item2.color
const x = this.countChineseAndEnglishCharacters(item.font[0].text,item.coord[0][0])
this.ctx.fillText(item2.text, this.fitSize( index2 === 1 ? x : item.coord[0][0]), this.fitSize(item.coord[0][1]))
const x = this.countChineseAndEnglishCharacters(item.font[0].text, item
.coord[0][0])
this.ctx.fillText(item2.text, this.fitSize(index2 === 1 ? x : item.coord[0]
[0]), this.fitSize(item.coord[0][1]))
this.ctx.closePath()
})
} else {

View File

@ -11,7 +11,7 @@
export default {
data () {
return {
stationName: '所有电站',
stationName: '',
selectStaion: false,
StationShow: [],
defaultArr: [],

View File

@ -83,6 +83,7 @@ export default {
elePriceQuery: 'Electricity Price Query',
queryCriteria: 'Query criteria',
sift: 'sift',
station: 'Station',
provinceRegion: 'Province Region',
selectProvinceRegion: 'Please select province region',
customerType: 'Electricity Customer',
@ -96,6 +97,7 @@ export default {
noData: 'No Data',
eleLevel: 'Electricity Price Level',
fsdd: 'The price of time-of-use electricity',
useElecPrice: 'Electricity prices',
dietailUnit: '(RMB/kWh)',
eleprice: 'The price of electricity and electricity',
nonTime: 'Non-time-of-use Electricity Price',

View File

@ -83,6 +83,8 @@ export default {
elePriceQuery: '电价查询',
queryCriteria: '查询条件',
sift: '筛选',
station: '电站',
selectStation: '请选择电站',
provinceRegion: '省市区域',
selectProvinceRegion: '请选择省市区域',
customerType: '用电客户',
@ -96,6 +98,7 @@ export default {
noData: '数据为空',
eleLevel: '电价水平',
fsdd: '分时电度用电价格',
useElecPrice:'用电价格',
dietailUnit: '(元/千瓦时)',
eleprice: '电度用电价格',
nonTime: '非分时电价',

View File

@ -2,8 +2,8 @@
"name" : "StoraSmart",
"appid" : "__UNI__86592F3",
"description" : "Zetatech",
"versionName" : "2.0.0",
"versionCode" : 205,
"versionName" : "2.0.2",
"versionCode" : 207,
"transformPx" : false,
"app-plus" : {
"compatible" : {
@ -15,6 +15,7 @@
},
"safearea" : {
"bottom" : {
"bottom" : "auto",
"offset" : "none"
}
},
@ -55,33 +56,33 @@
},
"icons" : {
"android" : {
"hdpi" : "C:/Users/46254/Desktop/mipmap-hdpi/72x72.png",
"xhdpi" : "C:/Users/46254/Desktop/mipmap-xhdpi/96x96.png",
"xxhdpi" : "C:/Users/46254/Desktop/mipmap-xxhdpi/144x144.png",
"xxxhdpi" : "C:/Users/46254/Desktop/mipmap-xxxhdpi/1024x1024.png"
"hdpi" : "D:/zhuomian/mipmap-hdpi/72x72.png",
"xhdpi" : "D:/zhuomian/mipmap-xhdpi/96x96.png",
"xxhdpi" : "D:/zhuomian/mipmap-xxhdpi/144x144.png",
"xxxhdpi" : "D:/zhuomian/mipmap-xxxhdpi/1024x1024.png"
},
"ios" : {
"appstore" : "C:/Users/46254/Desktop/1/1024x1024.png",
"appstore" : "D:/zhuomian/1/1024x1024.png",
"ipad" : {
"app" : "C:/Users/46254/Desktop/申请邓白氏编码资料表/mipmap-mdpi/76x76.png",
"app@2x" : "C:/Users/46254/Desktop/申请邓白氏编码资料表/mipmap-xhdpi/152x152.png",
"notification" : "C:/Users/46254/Desktop/mipmap-mdpi/20x20.png",
"notification@2x" : "C:/Users/46254/Desktop/mipmap-mdpi/40x40.png",
"proapp@2x" : "C:/Users/46254/Desktop/申请邓白氏编码资料表/mipmap-xhdpi/167x167.png",
"settings" : "C:/Users/46254/Desktop/mipmap-mdpi/29x29.png",
"settings@2x" : "C:/Users/46254/Desktop/mipmap-xhdpi/58x58.png",
"spotlight" : "C:/Users/46254/Desktop/mipmap-mdpi/40x40.png",
"spotlight@2x" : "C:/Users/46254/Desktop/mipmap-xxxhdpi/80x80.png"
"app" : "D:/zhuomian/申请邓白氏编码资料表/mipmap-mdpi/76x76.png",
"app@2x" : "D:/zhuomian/申请邓白氏编码资料表/mipmap-xhdpi/152x152.png",
"notification" : "D:/zhuomian/mipmap-mdpi/20x20.png",
"notification@2x" : "D:/zhuomian/mipmap-mdpi/40x40.png",
"proapp@2x" : "D:/zhuomian/申请邓白氏编码资料表/mipmap-xhdpi/167x167.png",
"settings" : "D:/zhuomian/mipmap-mdpi/29x29.png",
"settings@2x" : "D:/zhuomian/mipmap-xhdpi/58x58.png",
"spotlight" : "D:/zhuomian/mipmap-mdpi/40x40.png",
"spotlight@2x" : "D:/zhuomian/mipmap-xxxhdpi/80x80.png"
},
"iphone" : {
"app@2x" : "C:/Users/46254/Desktop/mipmap-xhdpi/120x120.png",
"app@3x" : "C:/Users/46254/Desktop/mipmap-xxhdpi/180x180.png",
"notification@2x" : "C:/Users/46254/Desktop/mipmap-xhdpi/40x40.png",
"notification@3x" : "C:/Users/46254/Desktop/mipmap-xxhdpi/60x60.png",
"settings@2x" : "C:/Users/46254/Desktop/mipmap-xhdpi/58x58.png",
"settings@3x" : "C:/Users/46254/Desktop/mipmap-xxhdpi/87x87.png",
"spotlight@2x" : "C:/Users/46254/Desktop/mipmap-xxxhdpi/80x80.png",
"spotlight@3x" : "C:/Users/46254/Desktop/mipmap-xhdpi/120x120.png"
"app@2x" : "D:/zhuomian/mipmap-xhdpi/120x120.png",
"app@3x" : "D:/zhuomian/mipmap-xxhdpi/180x180.png",
"notification@2x" : "D:/zhuomian/mipmap-xhdpi/40x40.png",
"notification@3x" : "D:/zhuomian/mipmap-xxhdpi/60x60.png",
"settings@2x" : "D:/zhuomian/mipmap-xhdpi/58x58.png",
"settings@3x" : "D:/zhuomian/mipmap-xxhdpi/87x87.png",
"spotlight@2x" : "D:/zhuomian/mipmap-xxxhdpi/80x80.png",
"spotlight@3x" : "D:/zhuomian/mipmap-xhdpi/120x120.png"
}
}
},
@ -89,9 +90,9 @@
"androidStyle" : "default",
"androidTranslucent" : true,
"android" : {
"hdpi" : "C:/Users/46254/Desktop/3.png",
"xhdpi" : "C:/Users/46254/Desktop/2.png",
"xxhdpi" : "C:/Users/46254/Desktop/1.png"
"hdpi" : "D:/zhuomian/3.png",
"xhdpi" : "D:/zhuomian/2.png",
"xxhdpi" : "D:/zhuomian/1.png"
},
"iosStyle" : "common",
"ios" : {
@ -145,7 +146,13 @@
"enable" : false
}
},
"title" : "uView UI"
"title" : "uView UI",
"devServer" : {
"host" : "0.0.0.0",
"port" : 8080,
"useLocalIp" : true,
"disableHostCheck" : true
}
},
"locale" : "en"
}

View File

@ -190,10 +190,10 @@
.then((res) => {
self.panelData = res.data?.packData
self.initVolChart(res.data?.voltageList);
this.VolNumber = res.data.voltageList.length ? this.VolNumber + `(${res.data.voltageList.length})` : '单体电压柱状图'
this.VolNumber = res.data.voltageList.length ? this.VolNumber + `(${res.data.voltageList.length})` : this.VolNumber
self.initTemChart(res.data?.temperatureList)
this.TemNumber = res.data.temperatureList.length ? this.TemNumber + `(${res.data.temperatureList.length})` : '单体温度柱状图'
this.TemNumber = res.data.temperatureList.length ? this.TemNumber + `(${res.data.temperatureList.length})` : this.TemNumber
resolve(res);
})
.finally((err) => {

View File

@ -23,9 +23,9 @@
<view v-if="!loading" class="detail-box">
<u-form :model="formInfo" ref="uForm" :label-width="200">
<u-form-item :label="$t('homePage.policy.planCurveTem')"><u-input v-model="formInfo.temName" type="select"
<u-form-item :label="$t('homePage.policy.planCurveTem')"><u-input :placeholder="$t('homePage.policy.selectPlanCurveTem')" v-model="formInfo.temName" type="select"
@click="openSelectTemplate" input-align="right" /></u-form-item>
<u-form-item :label="$t('homePage.policy.IssueDevice')"><u-input v-model="formInfo.srcName" type="select"
<u-form-item :label="$t('homePage.policy.IssueDevice')"><u-input :placeholder="$t('homePage.policy.selectIssueDevice')" v-model="formInfo.srcName" type="select"
@click="openSelectDevice" input-align="right" /></u-form-item>
<u-form-item :label="$t('homePage.policy.operateOrNot')"><u-radio-group active-color="#009458"

View File

@ -1,6 +1,6 @@
<template>
<view class="warp">
<topoCanvas cId="secondcanvas" :width="'100%'" :height="'100%'" :canvas-data="canvasData" :noloading="noloading"/>
<topoCanvas ref="topoCanvasRef" cId="secondcanvas" :width="'100%'" :height="'100%'" :canvas-data="canvasData" :noloading="noloading"/>
</view>
</template>
<script>
@ -266,7 +266,175 @@
isMove: false,
r: 3,
},
]
],
animationId: null, // requestAnimationFrame ID
movingPoints: [
// 点1左上角 → 向右移动
{
x: 60,
y: 30,
path: [{
x: 60,
y: 30
}, // 起点
{
x: 240,
y: 30
} // 终点
],
currentStep: 0, // 当前在路径的哪一步
isActive: false, // 标识动画是否激活
id: 'point-1'
},
// 点2左上角 → 向右 → 向下
{
x: 60,
y: 30,
path: [{
x: 60,
y: 30
},
{
x: 110,
y: 30
},
{
x: 110,
y: 85
}
],
currentStep: 0,
isActive: false, // 标识动画是否激活
id: 'point-2'
},
// 点3中间下 → 向下 → 向左 → 向下
{
x: 110,
y: 127,
path: [{
x: 110,
y: 127
},
{
x: 110,
y: 150
},
{
x: 60,
y: 150
},
{
x: 60,
y: 190
}
],
currentStep: 0,
isActive: false, // 标识动画是否激活
id: 'point-3'
},
// 点5中间下 → 向下 → 向右 → 向下
{
x: 110,
y: 127,
path: [{
x: 110,
y: 127
},
{
x: 110,
y: 150
},
{
x: 270,
y: 150
},
{
x: 270,
y: 190
}
],
currentStep: 0,
isActive: false, // 标识动画是否激活
id: 'point-5'
},
// 点6中间上 → 向上 → 向右
{
x: 110,
y: 85,
path: [{
x: 110,
y: 85
},
{
x: 110,
y: 30
},
{
x: 240,
y: 30
} // 终点
],
currentStep: 0,
isActive: false, // 标识动画是否激活
id: 'point-6'
},
// 点7左下角 → 向上 → 向右 → 向上
{
x: 60,
y: 190,
path: [{
x: 60,
y: 190
},
{
x: 60,
y: 150
},
{
x: 110,
y: 150
},
{
x: 110,
y: 127
}
],
currentStep: 0,
isActive: false, // 标识动画是否激活
id: 'point-7'
},
// 点9右下角 → 向上 → 向左 → 向上
{
x: 270,
y: 190,
path: [{
x: 270,
y: 190
},
{
x: 270,
y: 150
},
{
x: 110,
y: 150
},
{
x: 110,
y: 127
}
],
currentStep: 0,
isActive: false, // 标识动画是否激活
id: 'point-9'
}
],
pointSpeed: 1.5, // 移动速度(像素/帧)
kWValues: {
left: null, // 存储 getLeftPcs 的 kW 值
right: null // 存储 getRightPcs 的 kW 值
}
}
},
computed: {
@ -274,8 +442,117 @@
return this.vuex_currentStation;
},
},
beforeDestroy() {
// 强制取消动画帧
if (this.animationId) {
if (typeof requestAnimationFrame !== 'undefined') {
cancelAnimationFrame(this.animationId);
} else {
clearTimeout(this.animationId);
}
this.animationId = null; // 重置ID
}
// 重置所有动态点状态
this.movingPoints.forEach(point => {
point.isActive = false;
point.currentStep = 0;
point.x = point.path[0].x;
point.y = point.path[0].y;
});
// 清空canvasData
this.canvasData = [];
},
watch:{
stationId(newVal,oldVal){
if (newVal) {
this.getData(newVal);
}
}
},
methods: {
// 启动动画
startAnimation() {
const canvasRef = this.$refs.topoCanvasRef;
if (!canvasRef) return;
// 清除旧动画
if (this.animationId !== null) {
if (requestAnimationFrame && this.animationId) {
cancelAnimationFrame(this.animationId);
} else {
clearTimeout(this.animationId);
}
this.animationId = null;
}
// 直接启动新动画
this.animate();
},
animate() {
const canvasRef = this.$refs.topoCanvasRef;
if (!canvasRef) return;
const animateFrame = () => {
// 1. 更新移动点的位置
this.movingPoints.forEach(point => {
if (!point.isActive) return;
const currentIndex = point.currentStep;
const nextTarget = point.path[currentIndex + 1];
if (!nextTarget) {
point.x = point.path[0].x;
point.y = point.path[0].y;
point.currentStep = 0;
return;
}
const dx = nextTarget.x - point.x;
const dy = nextTarget.y - point.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < this.pointSpeed) {
point.x = nextTarget.x;
point.y = nextTarget.y;
point.currentStep++;
} else {
point.x += (dx / distance) * this.pointSpeed;
point.y += (dy / distance) * this.pointSpeed;
}
});
// 2. 更新 canvasData 中的动态点
this.updateMovingPoints();
// 3. 清除并重绘
canvasRef.clear();
canvasRef.draw(null);
// 4. 继续下一帧(✅ 安全判断)
if (typeof requestAnimationFrame !== 'undefined') {
this.animationId = requestAnimationFrame(animateFrame);
} else {
this.animationId = setTimeout(animateFrame, 16);
}
};
// 启动第一帧(✅ 安全判断)
if (typeof requestAnimationFrame !== 'undefined') {
requestAnimationFrame(animateFrame);
} else {
setTimeout(animateFrame, 16);
}
},
updateMovingPoints() {
this.movingPoints.forEach(point => {
const dataIndex = this.canvasData.findIndex(item => item.id === point.id);
if (dataIndex !== -1) {
this.canvasData[dataIndex].coord = [
[point.x, point.y]
];
}
});
},
changeEnglish(){
this.textCanvasData = [
{
@ -332,14 +609,66 @@
},
getData(val){
// 彻底重置画布数据
this.canvasData = [];
// 重置所有点状态
this.movingPoints.forEach(point => (point.isActive = false,point.isMove = false,point.currentStep = 0,point.x = point.path[0].x,point.y = point.path[0].y));
this.stationId = val
this.textCanvasData.splice(3)
const api = [this.getLeftPcs(),this.getRightPcs(),this.getAmmeter()]
Promise.all(api).finally((result) => {
// 获取三个 kW 值
const {
left,
right
} = this.kWValues;
const values = [left, right];
const allZero = values.every(v => v === 0);
const anyPositive = values.some(v => v > 0);
const anyNegative = values.some(v => v < 0);
// 重置所有点(确保干净)
this.movingPoints.forEach(p => (p.isActive = false));
// 条件3全部为0 → 只显示点1
if (allZero) {
this.movingPoints.find(p => p.id === 'point-1').isActive = true;
}
// 否则按原逻辑处理
else {
// 条件1任一大于0 → 点6运动
if (anyPositive) {
this.movingPoints.find(p => p.id === 'point-1').isActive = true;
this.movingPoints.find(p => p.id === 'point-2').isActive = true;
}
// 条件2任一小于0 → 点1和点2运动
if (anyNegative) {
this.movingPoints.find(p => p.id === 'point-6').isActive = true;
}
// 再设置点3~9的显示逻辑
this.updatePcsPoints();
}
this.canvasData = [...this.textCanvasData, ...this.imageCanvasData, ...this
.lineCanvasData, ...this.circleCanvasData
]
// 动态添加 movingPoints
this.movingPoints.forEach(point => {
this.canvasData.push({
type: "circle",
id: point.id,
coord: [
[point.x, point.y]
],
color: "#3AECA1",
r: 3,
isMove: true
});
});
this.noloading = true
this.$nextTick(() => {
this.startAnimation();
});
});
},
countChineseAndEnglishCharacters(str, x) {
@ -406,7 +735,10 @@
.then((res) => {
if(res.data && res.data.length){
res.data.forEach((item,index) => {
if (item.name.includes('kW')) { // 检查是否包含'kW'
const value = parseFloat(item.value);
this.kWValues.left = value; // 只记录
}
this.textCanvasData.push(
{
type: "text",
@ -435,9 +767,13 @@
)
})
} else {
this.kWValues.left = 0; // 没数据视为 0
}
resolve()
}).catch(() => {
this.kWValues.left = 0; // 出错也视为 0
resolve();
})
})
@ -453,7 +789,10 @@
.then((res) => {
if(res.data && res.data.length){
res.data.forEach((item,index) => {
if (item.name.includes('kW')) { // 检查是否包含'kW'
const value = parseFloat(item.value);
this.kWValues.right = value;
}
this.textCanvasData.push(
{
type: "text",
@ -482,12 +821,49 @@
)
})
} else {
this.kWValues.right = 0;
}
resolve()
})
}).catch(() => {
this.kWValues.right = 0;
resolve();
})
})
},
updatePcsPoints() {
const { left, right } = this.kWValues;
// 处理左边点3 和 点7
const point3 = this.movingPoints.find(p => p.id === 'point-3');
const point7 = this.movingPoints.find(p => p.id === 'point-7');
if (left === 0) {
point3.isActive = false;
point7.isActive = false;
} else if (left > 0) {
point3.isActive = true;
point7.isActive = false;
} else if (left < 0) {
point3.isActive = false;
point7.isActive = true;
}
// 处理右边点5 和 点9
const point5 = this.movingPoints.find(p => p.id === 'point-5');
const point9 = this.movingPoints.find(p => p.id === 'point-9');
if (right === 0) {
point5.isActive = false;
point9.isActive = false;
} else if (right > 0) {
point5.isActive = true;
point9.isActive = false;
} else if (right < 0) {
point5.isActive = false;
point9.isActive = true;
}
}
}

View File

@ -1,6 +1,6 @@
<template>
<view class="warp">
<topoCanvas :cId="canvasId" :width="'100%'" :height="'100%'" :canvas-data="canvasData" :noloading="noloading" />
<topoCanvas ref="topoCanvasRef" :cId="canvasId" :width="'100%'" :height="'100%'" :canvas-data="canvasData" :noloading="noloading" />
</view>
</template>
<script>
@ -214,7 +214,65 @@
r: 3
},
]
],
animationId: null, // requestAnimationFrame ID
movingPoints: [
// 点1左上角 → 向右移动
{
x: 50,
y: 110,
path: [{
x: 50,
y: 110
}, // 起点
{
x: 140,
y: 110
} // 终点
],
currentStep: 0, // 当前在路径的哪一步
isActive: false, // 标识动画是否激活
id: 'point-1'
},
// 点2左上角 → 向右移动
{
x: 185,
y: 110,
path: [{
x: 185,
y: 110
}, // 起点
{
x: 260,
y: 110
} // 终点
],
currentStep: 0, // 当前在路径的哪一步
isActive: false, // 标识动画是否激活
id: 'point-2'
},
// 点3左上角 → 向右移动
{
x: 260,
y: 110,
path: [{
x: 260,
y: 110
}, // 起点
{
x: 185,
y: 110
} // 终点
],
currentStep: 0, // 当前在路径的哪一步
isActive: false, // 标识动画是否激活
id: 'point-3'
}
],
pointSpeed: 1.5, // 移动速度(像素/帧)
kWValues: {
right: null // 存储 getRightPcs 的 kW 值
}
}
},
computed: {
@ -222,8 +280,119 @@
return this.vuex_currentStation;
},
},
beforeDestroy() {
// 强制取消动画帧
if (this.animationId) {
if (typeof requestAnimationFrame !== 'undefined') {
cancelAnimationFrame(this.animationId);
} else {
clearTimeout(this.animationId);
}
this.animationId = null; // 重置ID
}
// 重置所有动态点状态
this.movingPoints.forEach(point => {
point.isActive = false;
point.currentStep = 0;
point.x = point.path[0].x;
point.y = point.path[0].y;
});
// 清空canvasData
this.canvasData = [];
},
watch:{
stationId(newVal,oldVal){
console.log(newVal,oldVal);
if (newVal) {
this.getData(newVal);
}
}
},
methods: {
// 启动动画
startAnimation() {
const canvasRef = this.$refs.topoCanvasRef;
if (!canvasRef) return;
// 清除旧动画
if (this.animationId !== null) {
if (requestAnimationFrame && this.animationId) {
cancelAnimationFrame(this.animationId);
} else {
clearTimeout(this.animationId);
}
this.animationId = null;
}
// 直接启动新动画
this.animate();
},
animate() {
const canvasRef = this.$refs.topoCanvasRef;
if (!canvasRef) return;
const animateFrame = () => {
// 1. 更新移动点的位置
this.movingPoints.forEach(point => {
if (!point.isActive) return;
const currentIndex = point.currentStep;
const nextTarget = point.path[currentIndex + 1];
if (!nextTarget) {
point.x = point.path[0].x;
point.y = point.path[0].y;
point.currentStep = 0;
return;
}
const dx = nextTarget.x - point.x;
const dy = nextTarget.y - point.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < this.pointSpeed) {
point.x = nextTarget.x;
point.y = nextTarget.y;
point.currentStep++;
} else {
point.x += (dx / distance) * this.pointSpeed;
point.y += (dy / distance) * this.pointSpeed;
}
});
// 2. 更新 canvasData 中的动态点
this.updateMovingPoints();
// 3. 清除并重绘
canvasRef.clear();
canvasRef.draw(null);
// 4. 继续下一帧(✅ 安全判断)
if (typeof requestAnimationFrame !== 'undefined') {
this.animationId = requestAnimationFrame(animateFrame);
} else {
this.animationId = setTimeout(animateFrame, 16);
}
};
// 启动第一帧(✅ 安全判断)
if (typeof requestAnimationFrame !== 'undefined') {
requestAnimationFrame(animateFrame);
} else {
setTimeout(animateFrame, 16);
}
},
updateMovingPoints() {
this.movingPoints.forEach(point => {
const dataIndex = this.canvasData.findIndex(item => item.id === point.id);
if (dataIndex !== -1) {
this.canvasData[dataIndex].coord = [
[point.x, point.y]
];
}
});
},
changeEnglish() {
this.textCanvasData = [
// 并网柜--0
@ -351,17 +520,42 @@
]
},
getData(val) {
// 彻底重置画布数据
this.canvasData = [];
// 重置所有点状态
this.movingPoints.forEach(point => (point.isActive = false,point.isMove = false,point.currentStep = 0,point.x = point.path[0].x,point.y = point.path[0].y));
this.stationId = val
this.clearData()
const api = [
this.getMiddleData()
];
Promise.all(api).finally((result) => {
// 重置所有点(确保干净)
this.movingPoints.forEach(p => (p.isActive = false));
this.movingPoints.find(p => p.id === 'point-1').isActive = true;
// 再设置点2-3的显示逻辑
this.updatePcsPoints();
this.canvasData = [...this.textCanvasData, ...this.imageCanvasData, ...this
.lineCanvasData, ...this.circleCanvasData
]
// 动态添加 movingPoints
this.movingPoints.forEach(point => {
this.canvasData.push({
type: "circle",
id: point.id,
coord: [
[point.x, point.y]
],
color: "#3AECA1",
r: 3,
isMove: true
});
});
this.noloading = true
this.$nextTick(() => {
this.startAnimation();
});
});
},
workStatus(val, data) {
@ -401,18 +595,45 @@
stationId: this.stationId
})
.then(res => {
this.textCanvasData[3].font[1].text = this.workStatus(res.data.activePowerPCS, res
.data.flowDirection)
this.textCanvasData[4].font[1].text = res.data.activePowerPCS !== null ? res.data
.activePowerPCS + '' : ''
this.textCanvasData[5].font[1].text = res.data.soc !== null ? res.data.soc + '' :
''
this.textCanvasData[6].font[1].text = res.data.soh !== null ? res.data.soh + '' :
''
if (res.data) {
const value = parseFloat(res.data.activePowerPCS);
this.kWValues.right = value;
this.textCanvasData[3].font[1].text = this.workStatus(res.data.activePowerPCS, res
.data.flowDirection)
this.textCanvasData[4].font[1].text = res.data.activePowerPCS !== null ? res.data
.activePowerPCS + '' : ''
this.textCanvasData[5].font[1].text = res.data.soc !== null ? res.data.soc + '' :
''
this.textCanvasData[6].font[1].text = res.data.soh !== null ? res.data.soh + '' :
''
} else {
this.kWValues.right = 0;
}
resolve()
}).catch(() => {
this.kWValues.right = 0;
resolve();
})
})
}
},
updatePcsPoints() {
const { right } = this.kWValues;
// 处理右边点5 和 点9
const point2 = this.movingPoints.find(p => p.id === 'point-2');
const point3 = this.movingPoints.find(p => p.id === 'point-3');
if (right === 0) {
point2.isActive = false;
point3.isActive = false;
} else if (right > 0) {
point2.isActive = true;
point3.isActive = false;
} else if (right < 0) {
point2.isActive = false;
point3.isActive = true;
}
}
}
}

View File

@ -1,6 +1,7 @@
<template>
<view class="warp">
<topoCanvas cId="thirdcanvas" :width="'100%'" :height="'100%'" :canvas-data="canvasData" :noloading="noloading"/>
<topoCanvas ref="topoCanvasRef" cId="thirdcanvas" :width="'100%'" :height="'100%'" :canvas-data="canvasData"
:noloading="noloading" />
</view>
</template>
<script>
@ -13,10 +14,9 @@
return {
canvasData: [],
partList: {},
noloading:false,
noloading: false,
// 文字
textCanvasData: [
{
textCanvasData: [{
type: "text",
coord: [
[260, 65]
@ -81,8 +81,7 @@
],
// 图片
imageCanvasData: [
{
imageCanvasData: [{
//负载
type: "image",
url: "/static/topology/load.png",
@ -92,65 +91,64 @@
],
},
{
//电网
type: "image",
url: "/static/topology/dianwang.png",
coord: [
[15, 10],
[40, 40],
],
//电网
type: "image",
url: "/static/topology/dianwang.png",
coord: [
[15, 10],
[40, 40],
],
},
{
//一体舱
type: "image",
url: "/static/topology/yiticang.png",
coord: [
[45, 195],
[30, 40],
],
//一体舱
type: "image",
url: "/static/topology/yiticang.png",
coord: [
[45, 195],
[30, 40],
],
},
{
//一体舱
type: "image",
url: "/static/topology/yiticang.png",
coord: [
[145, 195],
[30, 40],
],
//一体舱
type: "image",
url: "/static/topology/yiticang.png",
coord: [
[145, 195],
[30, 40],
],
},
{
//一体舱
type: "image",
url: "/static/topology/yiticang.png",
coord: [
[255, 195],
[30, 40],
],
//一体舱
type: "image",
url: "/static/topology/yiticang.png",
coord: [
[255, 195],
[30, 40],
],
},
{
//电表
type: "image",
url: "/static/topology/ammeter.png",
coord: [
[170, 35],
[30, 30],
],
//电表
type: "image",
url: "/static/topology/ammeter.png",
coord: [
[170, 35],
[30, 30],
],
},
{
//sts
type: "image",
url: "/static/topology/yitigui.png",
coord: [
[95, 85],
[30, 40],
],
//sts
type: "image",
url: "/static/topology/yitigui.png",
coord: [
[95, 85],
[30, 40],
],
},
],
// 线
lineCanvasData: [
{
lineCanvasData: [{
type: "line",
coord: [
[60, 30],
@ -233,8 +231,7 @@
],
// 点
circleCanvasData: [
{
circleCanvasData: [{
type: "circle",
coord: [
[60, 30]
@ -306,8 +303,227 @@
color: "#3AECA1",
isMove: false,
r: 3,
}
],
animationId: null, // requestAnimationFrame ID
movingPoints: [
// 点1左上角 → 向右移动
{
x: 60,
y: 30,
path: [{
x: 60,
y: 30
}, // 起点
{
x: 240,
y: 30
} // 终点
],
currentStep: 0, // 当前在路径的哪一步
isActive: false, // 标识动画是否激活
id: 'point-1'
},
]
// 点2左上角 → 向右 → 向下
{
x: 60,
y: 30,
path: [{
x: 60,
y: 30
},
{
x: 110,
y: 30
},
{
x: 110,
y: 85
}
],
currentStep: 0,
isActive: false, // 标识动画是否激活
id: 'point-2'
},
// 点3中间下 → 向下 → 向左 → 向下
{
x: 110,
y: 127,
path: [{
x: 110,
y: 127
},
{
x: 110,
y: 150
},
{
x: 60,
y: 150
},
{
x: 60,
y: 190
}
],
currentStep: 0,
isActive: false, // 标识动画是否激活
id: 'point-3'
},
// 点4中间下 → 向下 → 向右 → 向下
{
x: 110,
y: 127,
path: [{
x: 110,
y: 127
},
{
x: 110,
y: 150
},
{
x: 160,
y: 150
},
{
x: 160,
y: 190
}
],
currentStep: 0,
isActive: false, // 标识动画是否激活
id: 'point-4'
},
// 点5中间下 → 向下 → 向右 → 向下
{
x: 110,
y: 127,
path: [{
x: 110,
y: 127
},
{
x: 110,
y: 150
},
{
x: 270,
y: 150
},
{
x: 270,
y: 190
}
],
currentStep: 0,
isActive: false, // 标识动画是否激活
id: 'point-5'
},
// 点6中间上 → 向上 → 向右
{
x: 110,
y: 85,
path: [{
x: 110,
y: 85
},
{
x: 110,
y: 30
},
{
x: 240,
y: 30
} // 终点
],
currentStep: 0,
isActive: false, // 标识动画是否激活
id: 'point-6'
},
// 点7左下角 → 向上 → 向右 → 向上
{
x: 60,
y: 190,
path: [{
x: 60,
y: 190
},
{
x: 60,
y: 150
},
{
x: 110,
y: 150
},
{
x: 110,
y: 127
}
],
currentStep: 0,
isActive: false, // 标识动画是否激活
id: 'point-7'
},
// 点8底部中间 → 向上 → 向左 → 向上
{
x: 160,
y: 190,
path: [{
x: 160,
y: 190
},
{
x: 160,
y: 150
},
{
x: 110,
y: 150
},
{
x: 110,
y: 127
}
],
currentStep: 0,
isActive: false, // 标识动画是否激活
id: 'point-8'
},
// 点9右下角 → 向上 → 向左 → 向上
{
x: 270,
y: 190,
path: [{
x: 270,
y: 190
},
{
x: 270,
y: 150
},
{
x: 110,
y: 150
},
{
x: 110,
y: 127
}
],
currentStep: 0,
isActive: false, // 标识动画是否激活
id: 'point-9'
}
],
pointSpeed: 1.5, // 移动速度(像素/帧)
kWValues: {
left: null, // 存储 getLeftPcs 的 kW 值
center: null, // 存储 getCenterPcs 的 kW 值
right: null // 存储 getRightPcs 的 kW 值
}
}
},
computed: {
@ -315,11 +531,119 @@
return this.vuex_currentStation;
},
},
beforeDestroy() {
// 强制取消动画帧
if (this.animationId) {
if (typeof requestAnimationFrame !== 'undefined') {
cancelAnimationFrame(this.animationId);
} else {
clearTimeout(this.animationId);
}
this.animationId = null; // 重置ID
}
// 重置所有动态点状态
this.movingPoints.forEach(point => {
point.isActive = false;
point.currentStep = 0;
point.x = point.path[0].x;
point.y = point.path[0].y;
});
// 清空canvasData
this.canvasData = [];
},
watch: {
stationId(newVal, oldVal) {
if (newVal) {
this.getData(newVal);
}
}
},
methods: {
changeEnglish(){
this.textCanvasData = [
{
// 启动动画
startAnimation() {
const canvasRef = this.$refs.topoCanvasRef;
if (!canvasRef) return;
// 清除旧动画
if (this.animationId !== null) {
if (requestAnimationFrame && this.animationId) {
cancelAnimationFrame(this.animationId);
} else {
clearTimeout(this.animationId);
}
this.animationId = null;
}
// 直接启动新动画
this.animate();
},
animate() {
const canvasRef = this.$refs.topoCanvasRef;
if (!canvasRef) return;
const animateFrame = () => {
// 1. 更新移动点的位置
this.movingPoints.forEach(point => {
if (!point.isActive) return;
const currentIndex = point.currentStep;
const nextTarget = point.path[currentIndex + 1];
if (!nextTarget) {
point.x = point.path[0].x;
point.y = point.path[0].y;
point.currentStep = 0;
return;
}
const dx = nextTarget.x - point.x;
const dy = nextTarget.y - point.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < this.pointSpeed) {
point.x = nextTarget.x;
point.y = nextTarget.y;
point.currentStep++;
} else {
point.x += (dx / distance) * this.pointSpeed;
point.y += (dy / distance) * this.pointSpeed;
}
});
// 2. 更新 canvasData 中的动态点
this.updateMovingPoints();
// 3. 清除并重绘
canvasRef.clear();
canvasRef.draw(null);
// 4. 继续下一帧(✅ 安全判断)
if (typeof requestAnimationFrame !== 'undefined') {
this.animationId = requestAnimationFrame(animateFrame);
} else {
this.animationId = setTimeout(animateFrame, 16);
}
};
// 启动第一帧(✅ 安全判断)
if (typeof requestAnimationFrame !== 'undefined') {
requestAnimationFrame(animateFrame);
} else {
setTimeout(animateFrame, 16);
}
},
updateMovingPoints() {
this.movingPoints.forEach(point => {
const dataIndex = this.canvasData.findIndex(item => item.id === point.id);
if (dataIndex !== -1) {
this.canvasData[dataIndex].coord = [
[point.x, point.y]
];
}
});
},
changeEnglish() {
this.textCanvasData = [{
type: "text",
coord: [
[260, 65]
@ -383,37 +707,104 @@
]
},
getData(val){
this.stationId = val
this.textCanvasData.splice(5)
const api = [this.getLeftPcs(),this.getRightPcs(),this.getCenterPcs(),this.getAmmeter()]
Promise.all(api).finally((result) => {
this.canvasData = [...this.textCanvasData, ...this.imageCanvasData, ...this
.lineCanvasData, ...this.circleCanvasData
]
this.noloading = true
getData(val) {
// 彻底重置画布数据
this.canvasData = [];
// 重置所有点状态
this.movingPoints.forEach(point => (point.isActive = false, point.isMove = false, point.currentStep = 0,
point.x = point.path[0].x, point.y = point.path[0].y));
this.stationId = val;
this.textCanvasData.splice(5); // 清除文本数据
const api = [this.getLeftPcs(), this.getCenterPcs(), this.getRightPcs(), this.getAmmeter()];
Promise.all(api).finally(() => {
// 获取三个 kW 值
const {
left,
center,
right
} = this.kWValues;
const values = [left, center, right];
const allZero = values.every(v => v === 0);
const anyPositive = values.some(v => v > 0);
const anyNegative = values.some(v => v < 0);
// 重置所有点(确保干净)
this.movingPoints.forEach(p => (p.isActive = false));
// 条件3全部为0 → 只显示点1
if (allZero) {
this.movingPoints.find(p => p.id === 'point-1').isActive = true;
}
// 否则按原逻辑处理
else {
// 条件1任一大于0 → 点6运动
if (anyPositive) {
this.movingPoints.find(p => p.id === 'point-1').isActive = true;
this.movingPoints.find(p => p.id === 'point-2').isActive = true;
}
// 条件2任一小于0 → 点1和点2运动
if (anyNegative) {
this.movingPoints.find(p => p.id === 'point-6').isActive = true;
}
// 再设置点3~9的显示逻辑
this.updatePcsPoints();
}
// 重新构建 canvasData
this.canvasData = [
...this.textCanvasData,
...this.imageCanvasData,
...this.lineCanvasData,
...this.circleCanvasData
];
// 动态添加 movingPoints
this.movingPoints.forEach(point => {
this.canvasData.push({
type: "circle",
id: point.id,
coord: [
[point.x, point.y]
],
color: "#3AECA1",
r: 3,
isMove: true
});
});
this.noloading = true;
this.$nextTick(() => {
this.startAnimation();
});
});
},
countChineseAndEnglishCharacters(str, x) {
var chineseCount = str.match(/[\u4e00-\u9fa5]/g) ? str.match(/[\u4e00-\u9fa5]/g).length : 0
var englishCount = str.match(/[a-zA-Z]/g) ? str.match(/[a-zA-Z]/g).length : 0
var otherCount = str.length - chineseCount - englishCount
const obj = { otherCount: otherCount, chineseCount: chineseCount, englishCount: englishCount }
return (obj.englishCount * 4) + (obj.chineseCount * 10 ) + (obj.otherCount * 8) + x
},
getAmmeter(){
var chineseCount = str.match(/[\u4e00-\u9fa5]/g) ? str.match(/[\u4e00-\u9fa5]/g).length : 0
var englishCount = str.match(/[a-zA-Z]/g) ? str.match(/[a-zA-Z]/g).length : 0
var otherCount = str.length - chineseCount - englishCount
const obj = {
otherCount: otherCount,
chineseCount: chineseCount,
englishCount: englishCount
}
return (obj.englishCount * 4) + (obj.chineseCount * 10) + (obj.otherCount * 8) + x
},
getAmmeter() {
let self = this;
return new Promise((resolve, reject) => {
self.$u.api.homePageData
.GetDynamicConfig({
stationId: this.stationId,
pageLocation:'triad-ammeter'
pageLocation: 'triad-ammeter'
})
.then((res) => {
if(res.data && res.data.length){
res.data.forEach((item,index) => {
this.textCanvasData.push(
{
if (res.data && res.data.length) {
res.data.forEach((item, index) => {
this.textCanvasData.push({
type: "text",
coord: [
[120, 80 + index * 15]
@ -424,11 +815,11 @@
color: "#666666",
width: 50,
}]
},
{
}, {
type: "text",
coord: [
[this.countChineseAndEnglishCharacters(item.name,130), 80 + index * 15]
[this.countChineseAndEnglishCharacters(item
.name, 130), 80 + index * 15]
],
font: [{
text: `${item.value}`,
@ -436,60 +827,62 @@
color: "#666666",
width: 50,
}]
},
)
}, )
})
}
resolve()
})
})
})
},
getLeftPcs() {
let self = this;
return new Promise((resolve, reject) => {
self.$u.api.homePageData
.GetDynamicConfig({
stationId: this.stationId,
pageLocation:'triad-pcs-left'
})
.then((res) => {
if(res.data && res.data.length){
res.data.forEach((item,index) => {
this.textCanvasData.push(
{
type: "text",
coord: [
[0, 265 + index * 15]
],
font: [{
text: `${item.name}`,
size: 12,
color: "#666666",
width: 50,
}]
},
{
type: "text",
coord: [
[this.countChineseAndEnglishCharacters(item.name,0), 265 + index * 15]
],
font: [{
text: `${item.value}`,
size: 12,
color: "#666666",
width: 50,
}]
},
)
})
}
resolve()
self.$u.api.homePageData.GetDynamicConfig({
stationId: this.stationId,
pageLocation: 'triad-pcs-left'
}).then((res) => {
if (res.data && res.data.length) {
res.data.forEach((item, index) => {
if (item.name.includes('kW')) { // 检查是否包含'kW'
const value = parseFloat(item.value);
this.kWValues.left = value; // 只记录
}
this.textCanvasData.push({
type: "text",
coord: [
[0, 265 + index * 15]
],
font: [{
text: `${item.name}`,
size: 12,
color: "#666666",
width: 50,
}]
}, {
type: "text",
coord: [
[this.countChineseAndEnglishCharacters(item
.name, 0), 265 + index * 15]
],
font: [{
text: `${item.value}`,
size: 12,
color: "#666666",
width: 50,
}]
}, )
})
} else {
this.kWValues.left = 0; // 没数据视为 0
}
resolve()
}).catch(() => {
this.kWValues.left = 0; // 出错也视为 0
resolve();
})
})
@ -500,14 +893,16 @@
self.$u.api.homePageData
.GetDynamicConfig({
stationId: this.stationId,
pageLocation:'triad-pcs-center'
pageLocation: 'triad-pcs-center'
})
.then((res) => {
if(res.data && res.data.length){
res.data.forEach((item,index) => {
this.textCanvasData.push(
{
if (res.data && res.data.length) {
res.data.forEach((item, index) => {
if (item.name.includes('kW')) { // 检查是否包含'kW'
const value = parseFloat(item.value);
this.kWValues.center = value;
}
this.textCanvasData.push({
type: "text",
coord: [
[110, 265 + index * 15]
@ -518,11 +913,11 @@
color: "#666666",
width: 50,
}]
},
{
}, {
type: "text",
coord: [
[this.countChineseAndEnglishCharacters(item.name,110), 265 + index * 15]
[this.countChineseAndEnglishCharacters(item
.name, 110), 265 + index * 15]
],
font: [{
text: `${item.value}`,
@ -530,16 +925,20 @@
color: "#666666",
width: 50,
}]
},
)
}, )
})
} else {
this.kWValues.center = 0;
}
resolve()
})
}).catch(() => {
this.kWValues.center = 0;
resolve();
})
})
},
getRightPcs() {
let self = this;
@ -547,14 +946,16 @@
self.$u.api.homePageData
.GetDynamicConfig({
stationId: this.stationId,
pageLocation:'triad-pcs-right'
pageLocation: 'triad-pcs-right'
})
.then((res) => {
if(res.data && res.data.length){
res.data.forEach((item,index) => {
this.textCanvasData.push(
{
if (res.data && res.data.length) {
res.data.forEach((item, index) => {
if (item.name.includes('kW')) { // 检查是否包含'kW'
const value = parseFloat(item.value);
this.kWValues.right = value;
}
this.textCanvasData.push({
type: "text",
coord: [
[220, 265 + index * 15]
@ -565,11 +966,11 @@
color: "#666666",
width: 50,
}]
},
{
}, {
type: "text",
coord: [
[this.countChineseAndEnglishCharacters(item.name,220), 265 + index * 15]
[this.countChineseAndEnglishCharacters(item
.name, 220), 265 + index * 15]
],
font: [{
text: `${item.value}`,
@ -577,17 +978,74 @@
color: "#666666",
width: 50,
}]
},
)
}, )
})
} else {
this.kWValues.right = 0;
}
resolve()
})
}).catch(() => {
this.kWValues.right = 0;
resolve();
})
})
},
updatePcsPoints() {
const {
left,
center,
right
} = this.kWValues;
// 处理左边点3 和 点7
const point3 = this.movingPoints.find(p => p.id === 'point-3');
const point7 = this.movingPoints.find(p => p.id === 'point-7');
if (left === 0) {
point3.isActive = false;
point7.isActive = false;
} else if (left > 0) {
point3.isActive = true;
point7.isActive = false;
} else if (left < 0) {
point3.isActive = false;
point7.isActive = true;
}
// 处理中间点4 和 点8
const point4 = this.movingPoints.find(p => p.id === 'point-4');
const point8 = this.movingPoints.find(p => p.id === 'point-8');
if (center === 0) {
point4.isActive = false;
point8.isActive = false;
} else if (center > 0) {
point4.isActive = true;
point8.isActive = false;
} else if (center < 0) {
point4.isActive = false;
point8.isActive = true;
}
// 处理右边点5 和 点9
const point5 = this.movingPoints.find(p => p.id === 'point-5');
const point9 = this.movingPoints.find(p => p.id === 'point-9');
if (right === 0) {
point5.isActive = false;
point9.isActive = false;
} else if (right > 0) {
point5.isActive = true;
point9.isActive = false;
} else if (right < 0) {
point5.isActive = false;
point9.isActive = true;
}
}
}
}
@ -598,4 +1056,4 @@
height: 650rpx;
position: relative;
}
</style>
</style>

View File

@ -197,6 +197,7 @@
this.stationId = val.id
this.userId = this.userData.userId
console.log(val.topologyType)
this.topologyType = val.topologyType
this.getComponents()
this.$nextTick(() => {
@ -273,10 +274,9 @@
const {
data
} = await this.$u.api.homePageData.GetHomePageComponents(this.stationId)
if(data && data.length > 0){
this.rightCenter = data[0]?.rightCenter
}
if(data && data.length > 0){
this.rightCenter = data[0]?.rightCenter
}
},
openTimer() {

View File

@ -14,9 +14,18 @@
</view>
</Section>
<view class="search-box">
<view class="content-box">
<!-- 海外 -->
<view v-if="stationValue" style="width: 100%;" class="content-box">
<view style="width: calc(100% - (50% - 300rpx));" class="content-title">
{{ $t('homePage.home.station') }}
</view>
<view style="width: calc(100% - (50% - 300rpx));" class="content-value">
{{ currentStationName }}
</view>
</view>
<view v-else class="content-box">
<view class="content-title">
{{ this.$t('homePage.price.provinceRegion') }}
{{ $t('homePage.price.provinceRegion') }}
</view>
<view class="content-value">
{{ regionName }}
@ -32,7 +41,7 @@
</view>
</view>
<view class="content-box">
<view v-if="!stationValue" class="content-box">
<view class="content-title">
{{ this.$t('homePage.price.eleType') }}
</view>
@ -51,7 +60,7 @@
</view>
</view>
<view class="content-box">
<view v-if="!stationValue" class="content-box">
<view class="content-title">
{{ this.$t('homePage.price.exeTime') }}
</view>
@ -78,31 +87,34 @@
{{ this.$t('homePage.price.exeTime') }}
</view>
<view class="time-value">
{{ detailData.executionTime }}
{{ detailData.executionTime || timeSlot }}
</view>
<view class="time-title">
<view v-if="!stationValue" class="time-title">
{{ this.$t('homePage.price.eleType') }}
</view>
<view class="time-value">
<view v-if="!stationValue" class="time-value">
{{ detailData.electricityTypeLabel }}
</view>
<view class="time-title">
{{ this.$t('homePage.price.volLevel') }}
</view>
<view class="time-value">
{{ detailData.voltageLevelLabel }}
{{ stationValue? (detailData.voltageLevelLabel || voltageLevelName): detailData.voltageLevelLabel }}
</view>
<view class="title">
{{ this.$t('homePage.price.fsdd') }}{{ this.$t('homePage.price.dietailUnit') }}
{{ stationValue? this.$t('homePage.home.useElecPrice'):this.$t('homePage.price.fsdd') }}{{ this.$t('homePage.price.dietailUnit') }}
</view>
<view class="levels-chart">
<zero-loading v-if="levelsChart_loading"></zero-loading>
<charts v-else id="levelsChart" :options="levelsChart_option" :labelFormatter="true" :dataList="dataList"></charts>
<!-- <view v-else> -->
<!-- <charts v-if="stationValue" id="levelsChart" :options="levelsChart_option" :labelFormatter="true" :dataList="dataList"></charts> -->
<charts v-else id="levelsChart" :options="levelsChart_option" :labelFormatter="true" :dataList="dataList"></charts>
<!-- </view> -->
</view>
<view class="title">
{{ this.$t('homePage.price.eleprice') }}{{ this.$t('homePage.price.dietailUnit') }}
</view>
<view class="value-box">
<view v-if="!stationValue" class="value-box">
<view class="box">
<view class="box-value">
{{ detailData.nonTimePrice ? detailData.nonTimePrice : '--' }}
@ -138,7 +150,7 @@
</view>
</view>
<view class="price-box">
<view v-if="!stationValue" class="price-box">
<Section :title="$t('homePage.price.historytrend')">
<view slot="right" style="flex: 1">
<view class="top-right-box">
@ -162,8 +174,6 @@
<uni-th width="100" align="center">{{this.$t('homePage.price.regular')}}</uni-th>
<uni-th width="100" align="center">{{this.$t('homePage.price.lowValley')}}</uni-th>
<uni-th width="100" align="center">{{this.$t('homePage.price.deepValley')}}</uni-th>
</uni-tr>
<uni-tr v-for="(item, index) in history_tableData" :key="index">
<uni-td align="center">{{ item.executionTime }}</uni-td>
@ -172,13 +182,12 @@
<uni-td align="center">{{ item.regularPrice ? item.regularPrice : '-' }}</uni-td>
<uni-td align="center">{{ item.lowValleyPrice ? item.lowValleyPrice : '-' }}</uni-td>
<uni-td align="center">{{ item.deepValleyPrice ? item.deepValleyPrice : '-' }}</uni-td>
</uni-tr>
</uni-table>
</view>
</view>
<view class="price-box">
<view v-if="!stationValue" class="price-box">
<Section :title="$t('homePage.price.peakDifference')">
<view slot="right" style="flex: 1">
<view class="top-right-box">
@ -216,9 +225,14 @@
</view>
<view class="popup-box">
<u-popup v-model="popupShow" mode="bottom" border-radius="20" height="75%" placement="top-end" @close="closePop">
<u-popup v-model="popupShow" mode="bottom" border-radius="20" :height="stationValue? '40%':'75%'" placement="top-end" @close="closePop">
<view class="title">{{this.$t('homePage.price.sift')}}</view>
<view class="s-station">
<view v-if="stationValue" class="s-station">
<u-section :title="$t('homePage.home.station')" line-color="#009458" color="#2A2A2A" class="s-title" :right="false"
style="margin-bottom: 20rpx;"></u-section>
<stationDropdow style="width: 100%;border-color: rgb(220, 223, 230);border: 1px solid #dcdfe6;" ref="dropdow" />
</view>
<view v-else class="s-station">
<u-section :title="$t('homePage.price.provinceRegion')" line-color="#009458" color="#2A2A2A" class="s-title" :right="false"
style="margin-bottom: 20rpx;"></u-section>
<view style="margin-top: 20rpx;">
@ -230,7 +244,7 @@
label-name="regionName" @confirm="confirmRegion"></u-select>
</view>
<view class="s-station">
<view v-if="!stationValue" class="s-station">
<u-section :title="$t('homePage.price.customerType')" line-color="#009458" color="#2A2A2A" class="s-title" :right="false"
style="margin-bottom: 20rpx;"></u-section>
<view style="margin-top: 20rpx;">
@ -243,7 +257,7 @@
@confirm="confirmCustomer" value-name="value" label-name="name"></u-select>
</view>
<view class="s-station">
<view v-if="!stationValue" class="s-station">
<u-section :title="$t('homePage.price.eleType')" line-color="#009458" color="#2A2A2A" class="s-title" :right="false"
style="margin-bottom: 20rpx;"></u-section>
<view style="margin-top: 20rpx;">
@ -255,7 +269,7 @@
label-name="name" @confirm="confirmElectricity"></u-select>
</view>
<view class="s-station">
<view v-if="!stationValue" class="s-station">
<u-section :title="$t('homePage.price.volLevel')" line-color="#009458" color="#2A2A2A" class="s-title" :right="false"
style="margin-bottom: 20rpx;"></u-section>
<view style="margin-top: 20rpx;">
@ -267,7 +281,7 @@
@confirm="confirmVoltage" value-name="value" label-name="name"></u-select>
</view>
<view class="s-station">
<view v-if="!stationValue" class="s-station">
<u-section :title="$t('homePage.price.exeTime')" :default-value="defaultcTimeArr" line-color="#009458" color="#2A2A2A" class="s-title"
:right="false" style="margin-bottom: 20rpx;"></u-section>
<view style="margin-top: 20rpx;"><u-input v-model="filters.executionTime" type="select" border="border"
@ -288,10 +302,18 @@
</template>
<script>
import stationDropdow from '@/components/station-dropdow/index'
import Section from '@/components/section/index.vue'
import charts from "@/components/charts/index";
import Search from "@/components/Search/index";
export default {
components: {
stationDropdow,
Section,
charts,
Search
},
data() {
return {
background: {
@ -325,6 +347,12 @@ export default {
color: '#FF3333'
}
],
overseasColorList:[
{
name: this.language !== 'en_US'? '平时段':'Normal period',
color: '#048FFF'
}
],
popupShow: false,
filters: {
regionId: undefined,
@ -333,6 +361,7 @@ export default {
voltageLevel: undefined,
executionTime: undefined
},
currentStationName:'',
regionName: '上海',
electricityName: '两部制',
customerName: '大工业用户',
@ -353,7 +382,7 @@ export default {
second: false
},
sureButtonStyle: {
backgroundColor: '#009458',
backgroundColor: '#009458',
width: '280rpx',
height: '70rpx',
fontSize: '28rpx',
@ -386,23 +415,31 @@ export default {
useCustList: [],
useVolList: [],
middleIndexList: [],
dataList: []
customElecPriceData:[],
timeSlot:''
}
},
computed: {
language(){
return this.vuex_language
},
stationValue(){
return this.vuex_stationValue === 'Overseas Station' || this.vuex_stationValue === '海外站'? true:false
},
stationList () {
return this.vuex_provinceStation
},
stationShow (){
return this.vuex_StationShow
},
stationid (){
return this.vuex_currentStation.id
}
},
components: {
Section,
charts,
Search
},
onLoad() {
},
onLoad() {},
created() {
this.getRegionList()
if (!this.stationValue) {this.getRegionList()}
var currentDate = new Date();
// 获取年份和月份
var year = currentDate.getFullYear();
@ -414,8 +451,13 @@ export default {
this.filters.customerType = 2
this.filters.voltageLevel = 4
this.filters.executionTime = formattedDate
this.getData()
this.loading = true
if (this.stationValue) {
this.currentStationName = this.stationList[0].list[0].list[0].name
this.GetCustomElecPricePageData(this.stationList[0].list[0].list[0].id)
} else{
this.getData()
this.loading = true
}
},
methods: {
@ -431,10 +473,11 @@ export default {
this.filters.customerType = 2
this.filters.voltageLevel = 4
this.filters.executionTime = formattedDate
this.regionName = '上海'
this.electricityName = '两部制'
this.customerName = '大工业用户'
this.voltageLevelName = '10千伏'
this.currentStationName = ''
this.regionName = this.stationValue? '' : '上海'
this.electricityName = this.stationValue? '' : '两部制'
this.customerName = this.stationValue? '' : '大工业用户'
this.voltageLevelName = this.stationValue? '' : '10千伏'
this.useEleList = this.electricityList.filter(item => +item.type === +this.filters.customerType)
this.useVolList = this.voltageLevelList.filter(item => +item.type === +this.filters.customerType)
@ -518,7 +561,6 @@ export default {
}
},
confirmRegion(val) {
const regionIndex = this.regionList.findIndex((item) => {
@ -597,8 +639,13 @@ export default {
search() {
this.pageNum = 1;
this.dataList = [];
this.getData();
if (this.stationValue) {
this.GetCustomElecPricePageData(this.stationid)
} else{
this.getData()
}
this.popupShow = false;
this.currentStationName = this.$refs.dropdow.stationName;
},
findMiddleIndex(arr) {
let firstIndex = -1 // 第一个不为null的
@ -627,16 +674,151 @@ export default {
return result
},
// 查询自定义电价
async GetCustomElecPricePageData(id) {
this.levelsChart_loading = true
const params = {
stationId: id,
templateName: '',
isEnable:'',
validityStartTime:'',
validityEndTime:'',
elecType:1
}
try {
const { data } = await this.$u.api.proxyPrice.GetCustomElecPricePage(params)
// this.customElecPriceData = data
let nowdata = [
{
list:[],
name:data[0].type
}
];
for (let i = 0; i < 49; i++) {
nowdata[0].list.push(data[0].price)
}
this.initLevelsChartOverses(nowdata)
this.dataList = nowdata;
this.detailList = data;
this.customerName = this.language !== 'en_US'? '大工业用户':'Large industrial users',
this.voltageLevelName = this.language !== 'en_US'? '10kv': '10kv',
this.timeSlot = data[0].validityStartTime + ' —— ' + data[0].validityEndTime;
console.log(JSON.stringify(this.dataList),JSON.stringify(this.overseasColorList));
} finally {
this.loading = false
this.levelsChart_loading = false
}
},
async getLevelsChart(id) {
this.levelsChart_loading = true
try {
const res = await this.$u.api.proxyPrice.GetTouLineById(id)
this.initLevelsChart(res.data)
this.dataList = res.data ? res.data : []
this.dataList = res.data ? res.data : [],
console.log(this.dataList);
} finally {
this.levelsChart_loading = false
}
},
// 新增:初始化海外站电价图表
initLevelsChartOverses(data) {
const series = []
if (data.length > 0) {
data.map(item => {
const colorInfo = this.colorList.find(color => color.name === item.name)
const param = {
type: 'line',
itemStyle: {
normal: {
color: colorInfo ? colorInfo.color : undefined,
lineStyle: {
color: colorInfo ? colorInfo.color : undefined
},
areaStyle: {
type: 'default',
opacity: 0.2
}
}
},
name: item.name,
data: item.list,
symbol: 'circle',
'symbolSize': 0.001,
label: {
show: true,
}
}
series.push(param)
})
}
this.levelsChart_option = {
tooltip: {
trigger: 'axis',
confine: true,
textStyle: {
textShadowBlur: 10, // 重点
textShadowColor: 'transparent', // 重点
},
},
legend: {
},
grid: {
bottom: "15%",
top: "20%",
},
calculable: true,
xAxis: [{
type: 'category',
boundaryGap: false,
data: ['0', '0.5', '1', '1.5', '2', '2.5', '3', '3.5', '4', '4.5', '5', '5.5', '6',
'6.5', '7', '7.5', '8', '8.5', '9', '9.5', '10', '10.5', '11', '11.5', '12',
12.5, 13, 13.5, 14, 14.5, 15, 15.5, 16, 16.5, 17, 17.5, 18, 18.5, 19, 19.5, 20,
20.5, 21, 21.5, 22, 22.5, 23, 23.5, 24
],
splitLine: {
show: true,
lineStyle: {
color: '#F0F0F0',
}
},
axisLine: {
lineStyle: {
color: '#F0F0F0',
}
},
axisLabel: {
show: true,
color: '#A3A3A3'
},
axisTick: {
show: false
}
}],
yAxis: [{
type: 'value',
axisLine: {
show: false
},
axisLabel: {
show: true,
color: '#A3A3A3'
},
splitLine: {
show: true,
lineStyle: {
color: '#F0F0F0',
}
}
}],
series: series
}
},
initLevelsChart(data) {
const series = []
@ -1181,7 +1363,19 @@ export default {
.s-station {
margin-bottom: 60rpx;
padding: 0 20px 0 20px;
::v-deep .uicon-arrow-down-fill {
color: rgb(192, 196, 204) !important;
}
.home-navbar-warp{
padding:0 20rpx;
}
::v-deep .search {
width:100%;
}
::v-deep .uni-input-input{
text-align:left;
color: #303133;
}
.s-title {
font-size: 35rpx;
text-align: left;