首次提交
This commit is contained in:
@@ -0,0 +1,320 @@
|
||||
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]]
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user