chore(hmos): 导入生产环境鸿蒙工程

- 以 D:\SmartSenior 生产工程为源,纳入 AppScope、entry、cjagent、hvigor 及根配置
- 移除 build-profile.json5 的 signingConfigs(p12/p7b/cer 路径与加密口令)及 products.signingConfig 引用
- 不纳入本地与开发产物:local.properties、.idea、.hvigor、.codegenie、demo、backup_a2a_native、SESSION_LOG.md、build_err.txt、build/、oh_modules
- .gitignore 追加 .codegenie 与密钥文件通配(*.p12/*.p7b/*.cer/*.jks/*.keystore/*.pem)
This commit is contained in:
CAPTAIN1275
2026-09-29 18:44:37 +08:00
parent d7f0e2f8a8
commit baf307e9d5
184 changed files with 31334 additions and 0 deletions
+875
View File
@@ -0,0 +1,875 @@
// entry/src/main/ets/utils/LiveViewUtil.ets
import { liveViewManager } from '@kit.LiveViewKit';
import { Want, wantAgent, WantAgent } from '@kit.AbilityKit';
import { FlightData, LiveDataService, PilotData, ApiResponse } from './LiveDataService';
import { hilog } from '@kit.PerformanceAnalysisKit';
import deviceInfo from '@ohos.deviceInfo';
import { http } from '@kit.NetworkKit';
// Push Kit相关类型定义
interface ClickAction {
actionType: number;
action: string;
}
interface RichProgress {
type: number;
nodeIcons: string[];
indicatorIcon: string;
progress: number;
indicatorType: number;
color: string;
bgColor: string;
}
interface CapsuleData {
type: number;
status: number;
icon: string;
bgColor: string; // Push Kit格式
backgroundColor: string; // 本地API格式
title: string;
content: string; // 显式声明必填
}
// Push Kit专用的胶囊数据接口
interface PushKitCapsuleData {
type: number;
status: number;
icon: string;
bgColor: string; // Push Kit要求的字段名
title: string;
content?: string; // 可选字段
}
// JWT令牌响应接口
interface JwtTokenResponse {
token?: string;
}
interface ContentTextItem {
text: string;
foregroundColor?: string;
}
interface NotificationData {
type: number;
contentTitle: string;
contentText: Array<ContentTextItem>;
clickAction: ClickAction;
richProgress: RichProgress;
largeIcon: string; // 添加largeIcon字段
keywords?: Record<string, string>; // 修改为可选的对象类型
}
interface ActivityData {
notificationData: NotificationData;
capsuleData: PushKitCapsuleData; // 使用Push Kit专用接口
}
// PHP接口响应接口
interface PhpApiResponse {
success?: boolean;
error?: string;
code?: string | number;
msg?: string;
}
// PHP接口请求数据接口
interface StartLiveViewRequestData {
token: string;
flight_data: FlightData;
activity_id: number;
authorization: string;
}
interface UpdateLiveViewRequestData {
token: string;
flight_data: FlightData;
activity_id: number;
authorization: string;
}
interface EndLiveViewRequestData {
token: string;
activity_id: number;
authorization: string;
}
const DOMAIN = 0x0000;
/**
* 实况窗控制器类,负责管理实况窗的整个生命周期
*/
export class LiveViewController {
private static selectedPilot: PilotData | null = null;
private static deviceId: string = '';
private static wantAgentInstance: WantAgent | null = null;
private static readonly TEMPLATE_ID = 'flight_live_view_template'; // 模板ID
private static activityId: number = 0; // 实况活动ID
// 添加PHP接口URL
private static readonly START_LIVE_VIEW_PUSH_API = 'https://system.ldpfly.cn/hmos/startLiveViewPush.php';
private static readonly UPDATE_LIVE_VIEW_PUSH_API = 'https://system.ldpfly.cn/hmos/updateLiveViewPush.php';
private static readonly END_LIVE_VIEW_PUSH_API = 'https://system.ldpfly.cn/hmos/endLiveViewPush.php';
private static readonly ONLINE_PILOTS_API = 'https://system.ldpfly.cn/hmos/OnlinePilots.php'; // 使用OnlinePilots.php
/**
* 设置选中的飞行员
* @param pilot 选中的飞行员数据
*/
public static setSelectedPilot(pilot: PilotData): void {
LiveViewController.selectedPilot = pilot;
// 获取设备ID
LiveViewController.deviceId = deviceInfo.productModel || 'unknown_device';
hilog.info(DOMAIN, 'LiveViewController',
`Selected pilot: ${pilot.callsign}, Device ID: ${LiveViewController.deviceId}`);
}
/**
* 设置实况活动ID
* @param id 实况活动ID
*/
public static setActivityId(id: number): void {
LiveViewController.activityId = id;
}
/**
* 获取设备ID
* @returns string 设备ID
*/
public static getDeviceId(): string {
hilog.info(DOMAIN, 'LiveViewController', `Getting device ID: ${LiveViewController.deviceId}`);
return LiveViewController.deviceId;
}
/**
* 启动实况窗
* @returns Promise<ApiResponse> - 启动结果
*/
public static async startLiveView(): Promise<ApiResponse> {
hilog.info(DOMAIN, 'LiveViewController', 'Starting live view');
if (!LiveViewController.selectedPilot) {
const errorMsg = "请先选择一个飞行员";
hilog.error(DOMAIN, 'LiveViewController', errorMsg);
throw new Error(errorMsg);
}
// 校验实况窗开关是否打开
if (!await LiveViewController.isLiveViewEnabled()) {
const errorMsg = "Live view is disabled.";
hilog.error(DOMAIN, 'LiveViewController', errorMsg);
throw new Error(errorMsg);
}
// 构建WantAgent
await LiveViewController.buildWantAgent();
// 转换选中的飞行员数据为航班数据格式
const flightData = LiveViewController.convertPilotToFlightData(LiveViewController.selectedPilot);
hilog.info(DOMAIN, 'LiveViewController', `Converted flight data: ${JSON.stringify(flightData)}`);
// 获取设备ID
const deviceId = LiveViewController.getDeviceId();
if (!deviceId) {
throw new Error("设备ID获取失败");
}
// 获取Push Token
let pushToken: string;
try {
pushToken = await LiveDataService.fetchPushToken(deviceId);
if (!pushToken) {
throw new Error("未能获取到推送令牌");
}
} catch (tokenError) {
hilog.error(DOMAIN, 'LiveViewController', `获取Push Token失败: ${tokenError.message}`);
throw new Error("获取推送令牌失败: " + tokenError.message);
}
// 获取JWT令牌
let authorization: string;
try {
authorization = await LiveViewController.getAuthorizationToken();
if (!authorization) {
throw new Error("未能获取到授权令牌");
}
} catch (authError) {
hilog.error(DOMAIN, 'LiveViewController', `获取JWT令牌失败: ${authError.message}`);
throw new Error("获取授权令牌失败: " + authError.message);
}
// 生成activityId
LiveViewController.activityId = parseInt(Date.now().toString().slice(-9));
// 通过Push Kit启动实况窗
await LiveViewController.startRemoteLiveViewViaPushKit(
pushToken,
flightData,
LiveViewController.activityId,
authorization
);
// 创建本地实况窗
hilog.info(DOMAIN, 'LiveViewController', 'Creating local live view');
return await LiveDataService.createRemoteLiveView(LiveViewController.deviceId, flightData);
}
/**
* 更新实况窗
* @returns Promise<ApiResponse> - 更新结果
*/
public static async updateLiveView(): Promise<ApiResponse> {
hilog.info(DOMAIN, 'LiveViewController', 'Updating live view');
if (!LiveViewController.selectedPilot) {
const errorMsg = "没有选中的飞行员";
hilog.error(DOMAIN, 'LiveViewController', errorMsg);
throw new Error(errorMsg);
}
// 从OnlinePilots.php重新获取最新的航班数据
hilog.info(DOMAIN, 'LiveViewController', 'Fetching latest flight data from OnlinePilots.php');
const flightData = await LiveViewController.fetchFlightDataFromOnlinePilots();
hilog.info(DOMAIN, 'LiveViewController', `Fetched flight data: ${JSON.stringify(flightData)}`);
// 获取设备ID
const deviceId = LiveViewController.getDeviceId();
if (!deviceId) {
throw new Error("设备ID获取失败");
}
// 获取Push Token
let pushToken: string;
try {
pushToken = await LiveDataService.fetchPushToken(deviceId);
if (!pushToken) {
throw new Error("未能获取到推送令牌");
}
} catch (tokenError) {
hilog.error(DOMAIN, 'LiveViewController', `获取Push Token失败: ${tokenError.message}`);
throw new Error("获取推送令牌失败: " + tokenError.message);
}
// 获取JWT令牌
let authorization: string;
try {
authorization = await LiveViewController.getAuthorizationToken();
if (!authorization) {
throw new Error("未能获取到授权令牌");
}
} catch (authError) {
hilog.error(DOMAIN, 'LiveViewController', `获取JWT令牌失败: ${authError.message}`);
throw new Error("获取授权令牌失败: " + authError.message);
}
// 通过Push Kit更新实况窗
await LiveViewController.updateRemoteLiveViewViaPushKit(
pushToken,
flightData,
LiveViewController.activityId,
authorization
);
return await LiveDataService.updateRemoteLiveView(LiveViewController.deviceId, flightData);
}
/**
* 结束实况窗
* @returns Promise<ApiResponse> - 结束结果
*/
public static async endLiveView(): Promise<ApiResponse> {
hilog.info(DOMAIN, 'LiveViewController', 'Ending live view');
if (!LiveViewController.deviceId) {
const errorMsg = "设备ID未获取";
hilog.error(DOMAIN, 'LiveViewController', errorMsg);
throw new Error(errorMsg);
}
// 获取设备ID
const deviceId = LiveViewController.getDeviceId();
if (!deviceId) {
throw new Error("设备ID获取失败");
}
// 获取Push Token
let pushToken: string;
try {
pushToken = await LiveDataService.fetchPushToken(deviceId);
if (!pushToken) {
throw new Error("未能获取到推送令牌");
}
} catch (tokenError) {
hilog.error(DOMAIN, 'LiveViewController', `获取Push Token失败: ${tokenError.message}`);
throw new Error("获取推送令牌失败: " + tokenError.message);
}
// 获取JWT令牌
let authorization: string;
try {
authorization = await LiveViewController.getAuthorizationToken();
if (!authorization) {
throw new Error("未能获取到授权令牌");
}
} catch (authError) {
hilog.error(DOMAIN, 'LiveViewController', `获取JWT令牌失败: ${authError.message}`);
throw new Error("获取授权令牌失败: " + authError.message);
}
// 通过Push Kit结束实况窗
await LiveViewController.endRemoteLiveViewViaPushKit(
pushToken,
LiveViewController.activityId,
authorization
);
// 清理WantAgent
if (LiveViewController.wantAgentInstance) {
try {
hilog.info(DOMAIN, 'LiveViewController', 'Cancelling wantAgent');
await wantAgent.cancel(LiveViewController.wantAgentInstance);
LiveViewController.wantAgentInstance = null;
hilog.info(DOMAIN, 'LiveViewController', 'WantAgent cancelled successfully');
} catch (error) {
hilog.error(DOMAIN, 'LiveViewController', `Failed to cancel wantAgent: ${error.message}`);
}
}
// 结束本地实况窗
try {
await LiveViewController.stopLiveView();
hilog.info(DOMAIN, 'LiveViewController', 'Local live view stopped successfully');
} catch (error) {
hilog.error(DOMAIN, 'LiveViewController', `Failed to stop local live view: ${error.message}`);
}
hilog.info(DOMAIN, 'LiveViewController', 'Ending remote live view');
return await LiveDataService.endRemoteLiveView(LiveViewController.deviceId);
}
/**
* 将飞行员数据转换为航班数据格式
* @param pilot 飞行员数据
* @returns FlightData 航班数据
*/
public static convertPilotToFlightData(pilot: PilotData): FlightData {
hilog.info(DOMAIN, 'LiveViewController', `Converting pilot to flight data: ${pilot.callsign}`);
const flightData: FlightData = {
flightNumber: pilot.callsign,
altitude: pilot.altitude,
speed: pilot.groundSpeed,
origin: pilot.departureAirport || "未知", // 防止空字符串
destination: pilot.destinationAirport || "未知", // 防止空字符串
originName: "出发机场", // 固定显示
destinationName: "到达机场", // 固定显示
statusCode: 1,
statusText: "飞行中"
};
hilog.info(DOMAIN, 'LiveViewController', `Converted flight data: ${JSON.stringify(flightData)}`);
return flightData;
}
/**
* 校验实况窗功能是否启用
* @returns boolean - 是否启用
*/
private static async isLiveViewEnabled(): Promise<boolean> {
try {
hilog.info(DOMAIN, 'LiveViewController', 'Checking if live view is enabled');
const enabled = await liveViewManager.isLiveViewEnabled();
hilog.info(DOMAIN, 'LiveViewController', `Live view enabled status: ${enabled}`);
return enabled;
} catch (error) {
hilog.error(DOMAIN, 'LiveViewController', `Failed to check live view status: ${error.message}`);
return false;
}
}
/**
* 构建点击动作WantAgent
* @returns Want - 点击后的跳转意图
*/
public static async buildWantAgent(): Promise<void> {
try {
hilog.info(DOMAIN, 'LiveViewController', 'Building WantAgent');
const wantAgentInfo: wantAgent.WantAgentInfo = {
wants: [
{
bundleName: 'com.example.ldpflyefb', // 应用实际bundleName
abilityName: 'EntryAbility',
moduleName: 'entry',
parameters: {
targetPage: 'map',
flightNo: LiveViewController.selectedPilot?.callsign || '',
departure: LiveViewController.selectedPilot?.departureAirport || '',
destination: LiveViewController.selectedPilot?.destinationAirport || ''
}
} as Want
],
operationType: wantAgent.OperationType.START_ABILITY,
requestCode: 0,
wantAgentFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]
};
hilog.info(DOMAIN, 'LiveViewController', `WantAgent info: ${JSON.stringify(wantAgentInfo)}`);
LiveViewController.wantAgentInstance = await wantAgent.getWantAgent(wantAgentInfo);
hilog.info(DOMAIN, 'LiveViewController', 'WantAgent created successfully');
} catch (error) {
hilog.error(DOMAIN, 'LiveViewController', `Failed to create WantAgent: ${error.message}`);
throw new Error(`WantAgent创建失败: ${error.message}`);
}
}
/**
* 获取WantAgent实例
* @returns WantAgent实例
*/
public static getWantAgent(): WantAgent | null {
hilog.info(DOMAIN, 'LiveViewController',
`Getting WantAgent instance: ${LiveViewController.wantAgentInstance !== null}`);
return LiveViewController.wantAgentInstance;
}
/**
* 构建实况胶囊数据(本地API格式)
* @param flightData 航班数据
* @returns capsuleData 实况胶囊数据
*/
public static buildCapsuleData(flightData: FlightData): CapsuleData {
hilog.info(DOMAIN, 'LiveViewController', `Building capsule data for flight: ${flightData.flightNumber}`);
// 提供默认值而不是抛出错误
const speed = flightData.speed || 0;
const altitude = flightData.altitude || 0;
const capsuleData: CapsuleData = {
//实况胶囊数据显示
type: 1,
status: 1,
icon: "icon.png", //实况胶囊左侧图标定义,你爹地默认使用LDP FLY的图标
bgColor: "#FF0A59F7", // Push Kit格式
backgroundColor: "#FF0A59F7", // 本地API格式
title: "飞行中", // 固定显示"飞行中"
content: flightData.flightNumber // 显示航班号
};
hilog.info(DOMAIN, 'LiveViewController', `Built capsule data: ${JSON.stringify(capsuleData)}`);
return capsuleData;
}
/**
* 转换胶囊数据为Push Kit格式
* @param capsule 本地胶囊数据
* @returns PushKitCapsuleData Push Kit格式的胶囊数据
*/
private static convertCapsuleForPushKit(capsule: CapsuleData): PushKitCapsuleData {
hilog.info(DOMAIN, 'LiveViewController', 'Converting capsule data for Push Kit');
// 验证数据完整性
if (!capsule || !capsule.type || !capsule.status || capsule.icon === undefined || !capsule.bgColor ||
!capsule.title) {
const errorMsg = "胶囊数据不完整";
hilog.error(DOMAIN, 'LiveViewController', `${errorMsg}. Capsule data: ${JSON.stringify(capsule)}`);
throw new Error(errorMsg);
}
// 验证胶囊类型
if (capsule.type !== 1 && capsule.type !== 2) {
const errorMsg = "胶囊类型必须为1或2";
hilog.error(DOMAIN, 'LiveViewController', `${errorMsg}. Type: ${capsule.type}`);
throw new Error(errorMsg);
}
// 验证背景颜色格式
if (!/^#([0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/.test(capsule.bgColor)) {
const errorMsg = "背景颜色格式必须为#RRGGBB或#AARRGGBB";
hilog.error(DOMAIN, 'LiveViewController', `${errorMsg}. Color: ${capsule.bgColor}`);
throw new Error(errorMsg);
}
const pushKitCapsuleData: PushKitCapsuleData = {
type: capsule.type,
status: capsule.status,
icon: capsule.icon || "flight_icon.png", // 提供默认图标
bgColor: capsule.bgColor, // 字段名转换
title: capsule.title,
content: capsule.content // 可选字段
};
hilog.info(DOMAIN, 'LiveViewController', `Converted PushKit capsule data: ${JSON.stringify(pushKitCapsuleData)}`);
return pushKitCapsuleData;
}
/**
* 通过PHP接口启动实况窗
* @param token Push Token
* @param flightData 航班数据
* @param activityId 实况活动ID
* @param authorization JWT授权令牌
*/
public static async startRemoteLiveViewViaPushKit(token: string, flightData: FlightData, activityId: number,
authorization: string): Promise<void> {
try {
hilog.info(DOMAIN, 'LiveViewController', `Starting remote live view via PHP API. Activity ID: ${activityId}`);
const httpRequest = http.createHttp();
const requestData: StartLiveViewRequestData = {
token: token,
flight_data: flightData,
activity_id: activityId,
authorization: authorization
};
hilog.info(DOMAIN, 'LiveViewController', `Request data: ${JSON.stringify(requestData)}`);
const response = await httpRequest.request(
LiveViewController.START_LIVE_VIEW_PUSH_API,
{
method: http.RequestMethod.POST,
header: {
'Content-Type': 'application/json'
},
extraData: JSON.stringify(requestData)
}
);
hilog.info(DOMAIN, 'LiveViewController',
`Start remote live view via PHP API response code: ${response.responseCode}`);
hilog.info(DOMAIN, 'LiveViewController', `Start remote live view via PHP API response: ${response.result}`);
const responseText = response.result as string;
const responseJson = JSON.parse(responseText) as PhpApiResponse;
hilog.info(DOMAIN, 'LiveViewController', `Parsed response: ${JSON.stringify(responseJson)}`);
// 修复错误判断逻辑:将"80000000"视为成功响应
if ((responseJson.success === false) ||
(responseJson.code && responseJson.code !== "80000000" && responseJson.code !== "200" &&
responseJson.code !== 200)) {
const errorMsg = `PHP API Error: ${responseJson.msg || responseJson.error || responseJson.code}`;
hilog.error(DOMAIN, 'LiveViewController', errorMsg);
throw new Error(errorMsg);
}
hilog.info(DOMAIN, 'LiveViewController', 'Remote live view started successfully via PHP API');
} catch (error) {
const err = error as Error;
hilog.error(DOMAIN, 'LiveViewController', `Failed to start remote live view via PHP API: ${err.message}`);
hilog.error(DOMAIN, 'LiveViewController', `Stack trace: ${err.stack}`);
throw new Error(`通过PHP接口启动实况窗失败: ${err.message}`);
}
}
/**
* 通过PHP接口更新实况窗
* @param token Push Token
* @param flightData 航班数据
* @param activityId 实况活动ID
* @param authorization JWT授权令牌
*/
public static async updateRemoteLiveViewViaPushKit(token: string, flightData: FlightData, activityId: number,
authorization: string): Promise<void> {
try {
hilog.info(DOMAIN, 'LiveViewController', `Updating remote live view via PHP API. Activity ID: ${activityId}`);
const httpRequest = http.createHttp();
const requestData: UpdateLiveViewRequestData = {
token: token,
flight_data: flightData,
activity_id: activityId,
authorization: authorization
};
hilog.info(DOMAIN, 'LiveViewController', `Request data: ${JSON.stringify(requestData)}`);
const response = await httpRequest.request(
LiveViewController.UPDATE_LIVE_VIEW_PUSH_API,
{
method: http.RequestMethod.POST,
header: {
'Content-Type': 'application/json'
},
extraData: JSON.stringify(requestData)
}
);
hilog.info(DOMAIN, 'LiveViewController',
`Update remote live view via PHP API response code: ${response.responseCode}`);
hilog.info(DOMAIN, 'LiveViewController', `Update remote live view via PHP API response: ${response.result}`);
const responseText = response.result as string;
const responseJson = JSON.parse(responseText) as PhpApiResponse;
hilog.info(DOMAIN, 'LiveViewController', `Parsed response: ${JSON.stringify(responseJson)}`);
// 修复错误判断逻辑:将"80000000"视为成功响应
if ((responseJson.success === false) ||
(responseJson.code && responseJson.code !== "80000000" && responseJson.code !== "200" &&
responseJson.code !== 200)) {
const errorMsg = `PHP API Error: ${responseJson.msg || responseJson.error || responseJson.code}`;
hilog.error(DOMAIN, 'LiveViewController', errorMsg);
throw new Error(errorMsg);
}
hilog.info(DOMAIN, 'LiveViewController', 'Remote live view updated successfully via PHP API');
} catch (error) {
const err = error as Error;
hilog.error(DOMAIN, 'LiveViewController', `Failed to update remote live view via PHP API: ${err.message}`);
hilog.error(DOMAIN, 'LiveViewController', `Stack trace: ${err.stack}`);
throw new Error(`通过PHP接口更新实况窗失败: ${err.message}`);
}
}
/**
* 通过PHP接口结束实况窗
* @param token Push Token
* @param activityId 实况活动ID
* @param authorization JWT授权令牌
*/
public static async endRemoteLiveViewViaPushKit(token: string, activityId: number,
authorization: string): Promise<void> {
try {
hilog.info(DOMAIN, 'LiveViewController', `Ending remote live view via PHP API. Activity ID: ${activityId}`);
const httpRequest = http.createHttp();
const requestData: EndLiveViewRequestData = {
token: token,
activity_id: activityId,
authorization: authorization
};
hilog.info(DOMAIN, 'LiveViewController', `Request data: ${JSON.stringify(requestData)}`);
const response = await httpRequest.request(
LiveViewController.END_LIVE_VIEW_PUSH_API,
{
method: http.RequestMethod.POST,
header: {
'Content-Type': 'application/json'
},
extraData: JSON.stringify(requestData)
}
);
hilog.info(DOMAIN, 'LiveViewController',
`End remote live view via PHP API response code: ${response.responseCode}`);
hilog.info(DOMAIN, 'LiveViewController', `End remote live view via PHP API response: ${response.result}`);
const responseText = response.result as string;
const responseJson = JSON.parse(responseText) as PhpApiResponse;
hilog.info(DOMAIN, 'LiveViewController', `Parsed response: ${JSON.stringify(responseJson)}`);
// 修复错误判断逻辑:将"80000000"视为成功响应
if ((responseJson.success === false) ||
(responseJson.code && responseJson.code !== "80000000" && responseJson.code !== "200" &&
responseJson.code !== 200)) {
const errorMsg = `PHP API Error: ${responseJson.msg || responseJson.error || responseJson.code}`;
hilog.error(DOMAIN, 'LiveViewController', errorMsg);
throw new Error(errorMsg);
}
hilog.info(DOMAIN, 'LiveViewController', 'Remote live view ended successfully via PHP API');
} catch (error) {
const err = error as Error;
hilog.error(DOMAIN, 'LiveViewController', `Failed to end remote live view via PHP API: ${err.message}`);
hilog.error(DOMAIN, 'LiveViewController', `Stack trace: ${err.stack}`);
throw new Error(`通过PHP接口结束实况窗失败: ${err.message}`);
}
}
/**
* 构建本地实况窗视图
* @returns Promise<liveViewManager.LiveView> 实况窗对象
*/
private static async buildLocalLiveView(flightData: FlightData): Promise<liveViewManager.LiveView> {
// 获取WantAgent实例
const wantAgent: WantAgent | null = LiveViewController.getWantAgent();
if (!wantAgent) {
throw new Error("WantAgent未初始化");
}
return {
id: 0,
event: "FLIGHT",
liveViewData: {
primary: {
title: flightData.flightNumber, // 只显示航班号
content: [
{ text: "高度 " },
{ text: `${flightData.altitude}`, textColor: "#FF0A59F7" },
{ text: " ft" },
{ text: " | " },
{ text: "速度 " },
{ text: `${flightData.speed}`, textColor: "#FF0A59F7" },
{ text: " kts" },
],
keepTime: 15,
backgroundType: liveViewManager.BackgroundType.SYS_BACKGROUND_FLIGHT_SUNSET,
clickAction: wantAgent,
layoutData: {
layoutType: liveViewManager.LayoutType.LAYOUT_TYPE_FLIGHT,
spaceIcon: "flight_icon1.png",
firstTitle: flightData.origin || "未知", // 防止空字符串导致参数错误
firstContent: flightData.originName || "出发机场",
lastTitle: flightData.destination || "未知", // 防止空字符串导致参数错误
lastContent: flightData.destinationName || "到达机场",
additionalText: "数据来源于FSD服务器,仅供参考 | LDP FLY空天模拟飞行平台",
}
},
// 添加实况胶囊数据 - 修改为新的显示格式
capsule: {
type: 1,
status: 1,
icon: "icon.png",
backgroundColor: "#FF0A59F7",
title: "飞行中", // 固定显示"飞行中"
content: flightData.flightNumber // 显示航班号
}
}
};
}
/**
* 更新本地实况窗
* @returns Promise<liveViewManager.LiveViewResult> 更新结果
*/
public static async updateLocalLiveView(): Promise<liveViewManager.LiveViewResult> {
// 校验实况窗开关是否打开
if (!await LiveViewController.isLiveViewEnabled()) {
throw new Error("Live view is disabled.");
}
if (!LiveViewController.selectedPilot) {
throw new Error("没有选中的飞行员");
}
// 转换选中的飞行员数据为航班数据格式
const flightData = LiveViewController.convertPilotToFlightData(LiveViewController.selectedPilot);
// 构建实况窗视图
const liveView = await LiveViewController.buildLocalLiveView(flightData);
// 更新实况窗
return await liveViewManager.updateLiveView(liveView);
}
/**
* 结束本地实况窗
* @returns Promise<liveViewManager.LiveViewResult> 结束结果
*/
public static async stopLiveView(): Promise<liveViewManager.LiveViewResult> {
// 校验实况窗开关是否打开
if (!await LiveViewController.isLiveViewEnabled()) {
throw new Error("Live view is disabled.");
}
if (!LiveViewController.selectedPilot) {
throw new Error("没有选中的飞行员");
}
// 转换选中的飞行员数据为航班数据格式
const flightData = LiveViewController.convertPilotToFlightData(LiveViewController.selectedPilot);
// 修改实况窗内容为结束状态
const liveView = await LiveViewController.buildLocalLiveView(flightData);
liveView.liveViewData.primary.title = `${flightData.flightNumber} 已到达`;
liveView.liveViewData.primary.content = [
{ text: '航班已安全降落,' },
{ text: '感谢您的飞行' }
];
liveView.liveViewData.primary.layoutData = {
layoutType: liveViewManager.LayoutType.LAYOUT_TYPE_FLIGHT,
spaceIcon: "flight_icon1.png",
firstTitle: flightData.origin || "未知", // 防止空字符串导致参数错误
firstContent: flightData.originName || "出发机场",
lastTitle: flightData.destination || "未知", // 防止空字符串导致参数错误
lastContent: flightData.destinationName || "到达机场",
additionalText: "数据来源于FSD服务器,仅供参考 | LDP FLY空天模拟飞行平台",
};
liveView.liveViewData.capsule = {
type: 1,
status: 1,
icon: "icon.png",
backgroundColor: "#FF0A59F7",
title: `${flightData.flightNumber} 已到达`
};
// 结束实况窗
return await liveViewManager.stopLiveView(liveView);
}
/**
* 获取JWT授权令牌
* @returns Promise<string> JWT令牌
*/
private static async getAuthorizationToken(): Promise<string> {
try {
const httpRequest = http.createHttp();
const response = await httpRequest.request(
'https://system.ldpfly.cn/hmos/getJwtToken.php',
{
method: http.RequestMethod.GET,
header: {
'Content-Type': 'application/json'
}
}
);
// 检查HTTP状态码
if (response.responseCode !== 200) {
throw new Error(`HTTP Error: ${response.responseCode}`);
}
const resultText = response.result as string;
// 检查返回内容是否为HTML(错误页面)
if (resultText.trim().startsWith('<html') || resultText.trim().startsWith('<!DOCTYPE')) {
throw new Error('Server returned HTML error page instead of JSON');
}
const result: JwtTokenResponse = JSON.parse(resultText);
if (result.token) {
return result.token;
} else {
throw new Error('服务器返回的JWT令牌无效');
}
} catch (error) {
const err = error as Error;
hilog.error(DOMAIN, 'LiveViewController', `获取JWT令牌失败: ${err.message}`);
throw new Error('获取授权令牌失败: ' + err.message);
}
}
/**
* 从OnlinePilots.php获取最新的航班数据
* @returns Promise<FlightData> 航班数据
*/
private static async fetchFlightDataFromOnlinePilots(): Promise<FlightData> {
try {
// 获取所有在线飞行员数据
const onlinePilots = await LiveDataService.fetchOnlinePilots();
// 查找与当前选中飞行员匹配的数据
const selectedPilotCallsign = LiveViewController.selectedPilot?.callsign;
const matchingPilot = onlinePilots.find(pilot => pilot.callsign === selectedPilotCallsign);
if (matchingPilot) {
// 将PilotData转换为FlightData
return LiveViewController.convertPilotToFlightData(matchingPilot);
} else {
// 如果未找到匹配的飞行员,抛出错误
throw new Error(`未找到呼号为 ${selectedPilotCallsign} 的飞行员数据`);
}
} catch (error) {
const err = error as Error;
hilog.error(DOMAIN, 'LiveViewController', `获取航班数据失败: ${err.message}`);
throw new Error('获取航班数据失败: ' + err.message);
}
}
}