320 lines
9.3 KiB
Plaintext
320 lines
9.3 KiB
Plaintext
import { webview } from '@kit.ArkWeb';
|
|
import { http } from '@kit.NetworkKit';
|
|
import CarbonInfoInterface from '../model/CarbonInfoInterface';
|
|
import StatisticalInterface from '../model/StatisticalInterface';
|
|
import DeviceListInterface from '../model/DeviceListInterface';
|
|
import { getCarbonInfo, getCarbonList, getDeviceList } from '../utils/ApiService';
|
|
|
|
// 监测点数据接口
|
|
interface MonitorPoint {
|
|
name: string;
|
|
lat: number;
|
|
lng: number;
|
|
status: number;
|
|
color: string;
|
|
}
|
|
|
|
/**
|
|
* 碳汇计算组件
|
|
*/
|
|
@Component
|
|
export struct CarbonCalc {
|
|
// 图表控制器
|
|
controller: webview.WebviewController = new webview.WebviewController();
|
|
// 状态数据
|
|
@State carbonInfo: CarbonInfoInterface | null = null;
|
|
@State carbonTrend: StatisticalInterface[] = [];
|
|
@State monitorPoints: MonitorPoint[] = [];
|
|
@State isLoading: boolean = true;
|
|
@State isWebViewReady: boolean = false;
|
|
@State avgTemp: number = 25.0;
|
|
|
|
// 模拟数据
|
|
private mockCarbonInfo: CarbonInfoInterface = {
|
|
carbonSequestration: 125.6,
|
|
ph: 7.4,
|
|
waterTemperature: 25.2
|
|
};
|
|
|
|
private mockTrend: number[] = [98, 105, 112, 118, 122, 126];
|
|
|
|
private mockPoints: MonitorPoint[] = [
|
|
{ name: '长江监测点A', lat: 30.5, lng: 114.3, status: 1, color: '#00FF88' },
|
|
{ name: '长江监测点B', lat: 31.2, lng: 115.1, status: 0, color: '#FF6B6B' },
|
|
{ name: '长江监测点C', lat: 29.8, lng: 113.5, status: 1, color: '#00FF88' },
|
|
{ name: '长江监测点D', lat: 32.0, lng: 118.7, status: 1, color: '#00FF88' }
|
|
];
|
|
|
|
aboutToAppear(): void {
|
|
this.loadData();
|
|
setTimeout(() => {
|
|
this.isWebViewReady = true;
|
|
this.updateChart();
|
|
}, 1000);
|
|
}
|
|
|
|
loadData(): void {
|
|
this.carbonInfo = this.mockCarbonInfo;
|
|
this.monitorPoints = this.mockPoints;
|
|
this.avgTemp = this.mockCarbonInfo.waterTemperature;
|
|
this.isLoading = false;
|
|
|
|
// 尝试获取真实数据
|
|
getCarbonInfo().then((result) => {
|
|
if (result && result.data) {
|
|
this.carbonInfo = result.data;
|
|
this.avgTemp = result.data.waterTemperature;
|
|
}
|
|
}).catch(() => {
|
|
// 使用模拟数据
|
|
});
|
|
|
|
getCarbonList().then((result) => {
|
|
if (result && result.data && result.data.length > 0) {
|
|
this.carbonTrend = result.data;
|
|
}
|
|
}).catch(() => {
|
|
// 使用模拟数据
|
|
});
|
|
|
|
getDeviceList().then((result) => {
|
|
if (result && result.data && result.data.length > 0) {
|
|
this.parseDeviceData(result.data);
|
|
}
|
|
}).catch(() => {
|
|
// 使用模拟数据
|
|
});
|
|
}
|
|
|
|
parseDeviceData(devices: DeviceListInterface[]): void {
|
|
const points: MonitorPoint[] = [];
|
|
for (let i: number = 0; i < devices.length; i++) {
|
|
const device: DeviceListInterface = devices[i];
|
|
const coords: string[] = device.latitudeLongitude.split(',');
|
|
if (coords.length >= 2) {
|
|
const lat: number = parseFloat(coords[0]);
|
|
const lng: number = parseFloat(coords[1]);
|
|
points.push({
|
|
name: device.name,
|
|
lat: lat,
|
|
lng: lng,
|
|
status: device.status,
|
|
color: device.status === 1 ? '#00FF88' : '#FF6B6B'
|
|
});
|
|
}
|
|
}
|
|
if (points.length > 0) {
|
|
this.monitorPoints = points;
|
|
}
|
|
}
|
|
|
|
updateChart(): void {
|
|
if (!this.isWebViewReady) return;
|
|
try {
|
|
const jsCode: string = `updateData([${this.mockTrend.join(',')}])`;
|
|
this.controller.runJavaScript(jsCode);
|
|
} catch (e) {
|
|
console.error('图表更新失败');
|
|
}
|
|
}
|
|
|
|
build() {
|
|
Column() {
|
|
// 标题
|
|
Row() {
|
|
Text('碳汇计算')
|
|
.fontSize(18)
|
|
.fontWeight(FontWeight.Bold)
|
|
.fontColor('#FFFFFF')
|
|
Blank()
|
|
Text('水体固碳能力')
|
|
.fontSize(11)
|
|
.fontColor('rgba(255,255,255,0.5)')
|
|
}
|
|
.width('92%')
|
|
.padding({ top: 12, bottom: 8 })
|
|
|
|
// ===== 上部分:统计卡片 =====
|
|
Row({ space: 8 }) {
|
|
// 上月平均温度
|
|
Column({ space: 4 }) {
|
|
Text('上月平均温度')
|
|
.fontSize(11)
|
|
.fontColor('rgba(255,255,255,0.6)')
|
|
Text(this.avgTemp.toFixed(1) + '°C')
|
|
.fontSize(18)
|
|
.fontWeight(600)
|
|
.fontColor('#FFE66D')
|
|
Row() {
|
|
Circle().width(4).height(4).fill('#FFE66D')
|
|
Text('正常')
|
|
.fontSize(9)
|
|
.fontColor('rgba(255,255,255,0.5)')
|
|
.margin({ left: 3 })
|
|
}
|
|
}
|
|
.width('31%')
|
|
.height(70)
|
|
.padding(8)
|
|
.borderRadius(12)
|
|
.border({ width: 1, color: 'rgba(255,230,109,0.3)' })
|
|
.backgroundColor('rgba(255,230,109,0.08)')
|
|
|
|
// 上月碳汇能力
|
|
Column({ space: 4 }) {
|
|
Text('上月碳汇能力')
|
|
.fontSize(11)
|
|
.fontColor('rgba(255,255,255,0.6)')
|
|
Text((this.carbonInfo?.carbonSequestration ?? 0).toFixed(1) + 'kg')
|
|
.fontSize(18)
|
|
.fontWeight(600)
|
|
.fontColor('#00FF88')
|
|
Row() {
|
|
Circle().width(4).height(4).fill('#00FF88')
|
|
Text('良好')
|
|
.fontSize(9)
|
|
.fontColor('rgba(255,255,255,0.5)')
|
|
.margin({ left: 3 })
|
|
}
|
|
}
|
|
.width('31%')
|
|
.height(70)
|
|
.padding(8)
|
|
.borderRadius(12)
|
|
.border({ width: 1, color: 'rgba(0,255,136,0.3)' })
|
|
.backgroundColor('rgba(0,255,136,0.08)')
|
|
|
|
// 上月平均pH
|
|
Column({ space: 4 }) {
|
|
Text('上月平均pH')
|
|
.fontSize(11)
|
|
.fontColor('rgba(255,255,255,0.6)')
|
|
Text((this.carbonInfo?.ph ?? 0).toFixed(1))
|
|
.fontSize(18)
|
|
.fontWeight(600)
|
|
.fontColor('#4ECDC4')
|
|
Row() {
|
|
Circle().width(4).height(4).fill('#4ECDC4')
|
|
Text('达标')
|
|
.fontSize(9)
|
|
.fontColor('rgba(255,255,255,0.5)')
|
|
.margin({ left: 3 })
|
|
}
|
|
}
|
|
.width('31%')
|
|
.height(70)
|
|
.padding(8)
|
|
.borderRadius(12)
|
|
.border({ width: 1, color: 'rgba(78,205,196,0.3)' })
|
|
.backgroundColor('rgba(78,205,196,0.08)')
|
|
}
|
|
.width('92%')
|
|
.justifyContent(FlexAlign.SpaceBetween)
|
|
|
|
// ===== 中间部分:碳汇趋势折线图 =====
|
|
Column({ space: 6 }) {
|
|
Row() {
|
|
Text('碳汇趋势')
|
|
.fontSize(13)
|
|
.fontWeight(500)
|
|
.fontColor('#FFFFFF')
|
|
Blank()
|
|
Text('近6个月')
|
|
.fontSize(10)
|
|
.fontColor('rgba(255,255,255,0.5)')
|
|
}
|
|
.width('100%')
|
|
|
|
Web({ src: $rawfile('chart/carbon_chart.html'), controller: this.controller })
|
|
.width('100%')
|
|
.height(160)
|
|
.backgroundColor('transparent')
|
|
.javaScriptAccess(true)
|
|
}
|
|
.width('92%')
|
|
.padding(10)
|
|
.margin({ top: 8 })
|
|
.borderRadius(12)
|
|
.border({ width: 1, color: 'rgba(22,119,255,0.25)' })
|
|
.backgroundColor('rgba(13,40,71,0.5)')
|
|
|
|
// ===== 下部分:监测点分布地图 =====
|
|
Column({ space: 8 }) {
|
|
// 地图标题
|
|
Row() {
|
|
Text('监测点分布')
|
|
.fontSize(13)
|
|
.fontWeight(500)
|
|
.fontColor('#FFFFFF')
|
|
Blank()
|
|
Row({ space: 6 }) {
|
|
Row({ space: 3 }) {
|
|
Circle().width(5).height(5).fill('#00FF88')
|
|
Text('正常')
|
|
.fontSize(9)
|
|
.fontColor('rgba(255,255,255,0.6)')
|
|
}
|
|
Row({ space: 3 }) {
|
|
Circle().width(5).height(5).fill('#FF6B6B')
|
|
Text('异常')
|
|
.fontSize(9)
|
|
.fontColor('rgba(255,255,255,0.6)')
|
|
}
|
|
}
|
|
}
|
|
.width('100%')
|
|
|
|
// 监测点地图区域(图片占位符,后期添加图片后取消注释)
|
|
Image($rawfile('ces/all_point.png'))
|
|
.width('100%')
|
|
.height(180)
|
|
.borderRadius(12)
|
|
.border({ width: 1, color: 'rgba(22,119,255,0.3)' })
|
|
|
|
// 临时占位区域(待添加图片)
|
|
// Column()
|
|
// .width('100%')
|
|
// .height(180)
|
|
// .linearGradient({
|
|
// angle: 135,
|
|
// colors: [['#1a3a5c', 0], ['#0d2847', 1]]
|
|
// })
|
|
// .borderRadius(12)
|
|
// .border({ width: 1, color: 'rgba(22,119,255,0.3)' })
|
|
|
|
// 监测点列表
|
|
Row({ space: 10 }) {
|
|
ForEach(this.monitorPoints, (point: MonitorPoint) => {
|
|
Row({ space: 4 }) {
|
|
Circle()
|
|
.width(6)
|
|
.height(6)
|
|
.fill(point.color)
|
|
Text(point.name)
|
|
.fontSize(10)
|
|
.fontColor('rgba(255,255,255,0.8)')
|
|
}
|
|
.padding({ left: 6, right: 6, top: 4, bottom: 4 })
|
|
.borderRadius(8)
|
|
.backgroundColor('rgba(22,119,255,0.1)')
|
|
})
|
|
}
|
|
.width('100%')
|
|
.justifyContent(FlexAlign.Center)
|
|
}
|
|
.width('92%')
|
|
.layoutWeight(1)
|
|
.margin({ top: 8 })
|
|
.padding(10)
|
|
.borderRadius(12)
|
|
.border({ width: 1, color: 'rgba(22,119,255,0.25)' })
|
|
.backgroundColor('rgba(13,40,71,0.4)')
|
|
}
|
|
.width('100%')
|
|
.height('100%')
|
|
.linearGradient({
|
|
angle: 180,
|
|
colors: [['#0a1628', 0], ['#0d2847', 0.5], ['#1677FF', 1]]
|
|
})
|
|
}
|
|
} |