diff --git a/entry/src/main/ets/config/LogEnum.ets b/entry/src/main/ets/config/LogEnum.ets index 62d97e8..3718ebf 100644 --- a/entry/src/main/ets/config/LogEnum.ets +++ b/entry/src/main/ets/config/LogEnum.ets @@ -40,4 +40,7 @@ export const CenterUdpTag = '[CenterUdpBusiness]' export const TerminalInfoTag = '[TerminalInfo]'; // CommonFile -export const CommonFileTag = '[CommonFile]'; \ No newline at end of file +export const CommonFileTag = '[CommonFile]'; + +//首页 +export const HomeTag = '[Home]'; \ No newline at end of file diff --git a/entry/src/main/ets/pages/Index.ets b/entry/src/main/ets/pages/Index.ets index 105c612..f08bb11 100644 --- a/entry/src/main/ets/pages/Index.ets +++ b/entry/src/main/ets/pages/Index.ets @@ -1,7 +1,7 @@ import common from '@ohos.app.ability.common'; import router from '@ohos.router'; -import { JudgeConfig } from '../config'; +import { HomeTag, JudgeConfig } from '../config'; import VoiceAnnounce from './judgeSDK/utils/voiceAnnouncements'; import { BaseInfoType } from '../model/Common'; import { CarInfoType, InitializeTheCentralTableType, MASYSSETTableType, TimeSynchronizationRspBody } from '../model'; @@ -38,6 +38,7 @@ struct Index { @State carInfo: CarInfoType = {}; @State num: number = 0; @State isPlay: boolean = false; + @State initWork: boolean = false // 请求网络表等待弹窗 customDialogController: CustomDialogController = new CustomDialogController({ builder: LoadingComponent(), @@ -163,9 +164,16 @@ struct Index { } }, router.RouterMode.Single) } else { - router.pushUrl({ - url: 'pages/ExaminerLogin', - }, router.RouterMode.Single) + if (this.singlePlay) { + router.pushUrl({ + url: 'pages/UserInfo', + }, router.RouterMode.Single) + } else { + router.pushUrl({ + url: 'pages/ExaminerLogin', + }, router.RouterMode.Single) + } + } }) }); @@ -194,7 +202,10 @@ struct Index { // CenterUDPBusinessInstance.startHeartBeat() CreateAlbum(this.fileHelper) // 启动worker通道 - DifferentialAndSignal.init() + if (!this.initWork) { + DifferentialAndSignal.init() + this.initWork = true + } DifferentialAndSignal.onMsg(() => { console.log("外层接受") }) @@ -212,9 +223,11 @@ struct Index { CardComponent({ isSingle: this.singlePlay, singleClick: () => { + console.log(HomeTag, "单机模式点击") this.singlePlayerTraining() }, networkingClick: () => { + console.log(HomeTag, "联网考试点击") this.onlineExam() } }) @@ -225,6 +238,7 @@ struct Index { hasAuth: this.baseInfo.hasAuth, examCarNumber: this.deviceId, versionClick: () => { + console.log(HomeTag, "版本号点击事件") this.singlePlay = !this.singlePlay AppStorage.setOrCreate('singlePlay', this.singlePlay) } diff --git a/entry/src/main/ets/pages/Index/BottomMessage.ets b/entry/src/main/ets/pages/Index/BottomMessage.ets index 4ac0f0c..d7cacfb 100644 --- a/entry/src/main/ets/pages/Index/BottomMessage.ets +++ b/entry/src/main/ets/pages/Index/BottomMessage.ets @@ -19,7 +19,7 @@ export default struct BottomMessageComponent { Text('授权信息:' + (this.hasAuth ? "已授权" : "未授权")).textCommonStyle() }.gesture( GestureGroup(GestureMode.Exclusive, - TapGesture({ count: 2 }) + TapGesture({ count: 5 }) .onAction(() => { this.versionClick && this.versionClick() }) diff --git a/entry/src/main/ets/pages/Judge.ets b/entry/src/main/ets/pages/Judge.ets index a9db672..e776cf2 100644 --- a/entry/src/main/ets/pages/Judge.ets +++ b/entry/src/main/ets/pages/Judge.ets @@ -43,7 +43,7 @@ import { } from '../model'; import { GetSyncData } from '../utils/table/Operation'; import dayTs from '../utils/Date'; -import { CutArray, GetCurrentTime } from '../utils/Common'; +import { CutArray, FormatTimeFlexible, GetCurrentTime } from '../utils/Common'; import FileUtils from '../utils/FileUtils'; @@ -158,16 +158,14 @@ struct Index { } async aboutToAppear() { - const time = GetCurrentTime() this.carInfo = AppStorage.get('carInfo')! this.singlePlay = AppStorage.get('singlePlay')! - this.startTime = time.split(' ')[1] this.startFullTime = GetCurrentTime(1); // this.startHourTime = await getCurrentHourTime() - this.startTime = dayTs().format("HHmmssSSS") - this.startExamTime = time + this.startTime = dayTs().format("YYYY-MM-DD HH:mm:ss") + this.startExamTime = dayTs().format("YYYY-MM-DD HH:mm:ss") setInterval(async () => { - this.time = GetCurrentTime(); + this.time = dayTs().format("YYYY-MM-DD HH:mm:ss"); this.examTime += 1; }, 1000); //初始化数据库表 @@ -214,6 +212,7 @@ struct Index { const result = await GetSyncData("ES_CARINFO") const carInfo = result[0] || {}; this.carName = decodeURI(carInfo.carclass!) + console.log("查看carType", carInfo.cartype) this.carType = carInfo.kscx! this.carinfoArr.push({ CARID: carInfo.carid!, @@ -709,8 +708,7 @@ struct Index { Row() { Text('考试用时:').fontColor('#E5CCA1').fontSize(this.FONTSIZE) - // Text(formatTime(this.examTime)).fontColor('#FFF').fontSize(this.FONTSIZE) - Text(dayTs(this.examTime).format("YYYY-MM-DD HH:mm:ss")).fontColor('#FFF').fontSize(this.FONTSIZE) + Text(FormatTimeFlexible(this.examTime)).fontColor('#FFF').fontSize(this.FONTSIZE) }.margin({ bottom: 10 }) if (this.examSubject == "3") { diff --git a/entry/src/main/ets/pages/judgeSDK/judge.ets b/entry/src/main/ets/pages/judgeSDK/judge.ets index cc3d6f1..5b08855 100644 --- a/entry/src/main/ets/pages/judgeSDK/judge.ets +++ b/entry/src/main/ets/pages/judgeSDK/judge.ets @@ -34,7 +34,7 @@ import { uploadExamProgressData, writeObjectOut } from '../../api/judge'; import { endRecordVideo, saveStartRecordVideo } from '../../utils/Video'; import common from '@ohos.app.ability.common'; -import { ConvertDdmmToDecimalDegrees, GetCurrentTime,DeepClone } from '../../utils/Common'; +import { ConvertDdmmToDecimalDegrees, DeepClone, GetCurrentTime } from '../../utils/Common'; import UsbService from '../../utils/USB'; import FileUtils from '../../utils/FileUtils'; import { @@ -179,38 +179,6 @@ export default class Judge { private isExamEnd: boolean // 是否发送udp private isUdpEnd: boolean = false - // 处理udp plc信号 - handleUdp = async (msg: string) => { - console.info('plc信号', msg) - const stachArr = msg.split(',') - if (stachArr[0] != '#DN_GD' || this.isUdpEnd) { - return - } - const plcData = await this.getPlcData(msg); - // 4.过程数据 - await this.fileLog?.setExamJudgeData(JSON.stringify(plcData)) - //检测到有无锡所设备接入,需要发送特定的数据,供检测 - // if (this.usbService.isWXUSBDevice) { - // const str = await senorToWXDataStr(msg); - // this.usbService.sendUSB(str) - // } - const param350: number = Reflect.get(this.judgeUI.judgeConfigObj, '350') - this.judgeUI.sd = ((param350 == 0 ? plcData.gps.sd : plcData.sensor.cs) as number * 1.852).toFixed(0) + '' - this.judgeUI.dw = (Math.floor(plcData.sensor.dw as number) || 0) + '' - //TODO 暂时关闭差分检测异常 - // await this.checkDwzt(plcData.gps.dwzt,plcData.gps.jdzt); - if (!this.isExamEnd) { - await examJudgeRealExam(plcData) - } - let udpIndex = AppStorage.get('udpIndex') || 0; - if (udpIndex % 5 === 0 && !this.isUdpEnd) { - // TODO UPD缺失 - // const judgeUdp = globalThis.judgeUdp - // const bytes = await this.getMessageHeartbeat(this.isExamEnd); - // judgeUdp.send(bytes) - } - AppStorage.setOrCreate('udpIndex', udpIndex++) - } //是否手动结束考试 private isManual: boolean = false //UDP服务序列号 @@ -258,6 +226,60 @@ export default class Judge { console.info(judgeTag, '过程数据文件上传 end') } private judgeTask: JudgeTask + // 检测扣分、结束项目时该项目是否开始 + checkProjectIsStart = async (xmdm: number, currentType: 1 | 2, kf?: MarkRule) => { + if (xmdm == 20) { + return true + } + const judgeUI = this.judgeUI; + const judgeTask = this.judgeTask; + const projectsObj: object = this.judgeUI.projectsObj + const currentProject: ProjectInfo = Reflect.get(projectsObj, xmdm) + const isUpload = currentProject.isUpload + + //如果项目没有开始 + console.info('surenjun isUpload=>', isUpload) + if (!isUpload) { + console.info(judgeTag, '项目补传开始') + //项目开始补传 + judgeTask.addTask(async () => { + await this.beginProject(xmdm) + }, { + isDelay: true + }) + judgeTask.addTask(async () => { + await this.uploadProgressPhoto(xmdm) + }, { + isDelay: true + }) + currentProject.isUpload = true; + Reflect.set(this.judgeUI.projectsObj, xmdm, currentProject) + //扣分补传 + if (currentType == 2) { + judgeTask.addTask(async () => { + await this.pointsDedute(xmdm, kf!) + }, { + isDelay: true + }) + } + //扣分补传判断是否合格 不合格补传项目结束 + if (currentType == 1 || (currentType == 2 && this.totalScore < judgeUI.passingScore)) { + judgeTask.addTask(async () => { + await this.endProject(xmdm) + }, { + isDelay: true + }) + currentProject.isEnd = true; + Reflect.set(this.judgeUI.projectsObj, xmdm, currentProject) + } + judgeTask.addTask(async () => { + this.checkExamIsEnd() + }) + return false; + } else { + return true + } + } private tempData?: Plc //实时计算gps经纬度距离 handDistance = async () => { @@ -421,6 +443,38 @@ export default class Judge { AppStorage.setOrCreate('msgStr', plc) return tempData } + // 处理udp plc信号 + handleUdp = async (msg: string) => { + console.info('plc信号', msg) + const stachArr = msg.split(',') + if (stachArr[0] != '#DN_GD' || this.isUdpEnd) { + return + } + const plcData = await this.getPlcData(msg); + // 4.过程数据 + await this.fileLog?.setExamJudgeData(JSON.stringify(plcData)) + //检测到有无锡所设备接入,需要发送特定的数据,供检测 + // if (this.usbService.isWXUSBDevice) { + // const str = await senorToWXDataStr(msg); + // this.usbService.sendUSB(str) + // } + const param350: number = Reflect.get(this.judgeUI.judgeConfigObj, '350') + this.judgeUI.sd = ((param350 == 0 ? plcData.gps.sd : plcData.sensor.cs) as number * 1.852).toFixed(0) + '' + this.judgeUI.dw = (Math.floor(plcData.sensor.dw as number) || 0) + '' + //TODO 暂时关闭差分检测异常 + // await this.checkDwzt(plcData.gps.dwzt,plcData.gps.jdzt); + if (!this.isExamEnd) { + await examJudgeRealExam(plcData) + } + let udpIndex = AppStorage.get('udpIndex') || 0; + if (udpIndex % 5 === 0 && !this.isUdpEnd) { + // TODO UPD缺失 + // const judgeUdp = globalThis.judgeUdp + // const bytes = await this.getMessageHeartbeat(this.isExamEnd); + // judgeUdp.send(bytes) + } + AppStorage.setOrCreate('udpIndex', udpIndex++) + } // 处理轨迹plc信号 handleTrajectoryUdp = async (strArr: string[]) => { // const { fileLog, setJudgeItem, setJudgeMark, endExam } = this; @@ -459,9 +513,9 @@ export default class Judge { } //本地轨迹回放地址 private trajectoryPath: string + //当前科目二的考试项目 // private currentKm2ItemsObj: any private isTrajectoryOpen: boolean; - //当前科目二的考试项目 // 调代理接口是否断网了 private isJudgeDisConnect: boolean = false; // 断网数据补传 @@ -476,67 +530,6 @@ export default class Judge { const code = await writeObjectOut(JSON.parse(examDataStr), "", this.context); } } - // 考试过程照片 - uploadProgressPhoto = async (ksxm: number) => { - const time = GetCurrentTime(); - const judgeUI = this.judgeUI - const plcData = this.plcData - const photoBase64 = await this.getPhoto(); - const carInfo = AppStorage.get('carInfo'); - - const project: ProjectInfo = Reflect.get(judgeUI.projectsObj, ksxm) - const judgeConfig_305: number = Reflect.get(judgeUI.judgeConfigObj, '305') - const drvexam: DrvexamType = { - lsh: judgeUI.lsh, - kskm: carInfo?.examSubject || "2", - ksxm: project.projectCodeCenter, - sfzmhm: judgeUI.idCard, - kchp: encodeURI(carInfo?.plateNo || ""), - zpsj: time, - zp: photoBase64, - cs: Math.floor((judgeConfig_305 == 0 ? (plcData?.gps?.sd || 0) : (plcData?.sensor?.cs || 0)) * 1.852), - ksdd: encodeURI(judgeUI.ksdd) - } - const data: RegulatoryInterfaceParams = { - xtlb: '17', - jkxlh: judgeUI.serialNumber, - jkid: '17C54', - drvexam - }; - const temp: WR = await this.sendWriteObjectOut(data, this.filePath); - if (temp.code === 2300007) { - this.isJudgeDisConnect = true - } - promptWxCode('17C54', temp.code || 0) - console.info(judgeTag, '上传照片 end') - } - private artSubject3ProjectsCodesArr: number[] = [3, 9, 4, 10, 12, 11] - private lane: LANE = { - road: '', num: 0, count: 0 - } - private videoData?: RecordHandleType - private disConnectNum: number = 0; - //调用监管接口 - sendWriteObjectOut: SendWriteObjectOut = async (data, filePath) => { - const temp = await writeObjectOut(data, filePath, this.context); - console.log("wzj", JSON.stringify(temp)) - //断网&网络超时次数计算 - if (temp.code == 2300007 || temp.code == 2300028) { - this.disConnectNum += 1; - if (this.disConnectNum < 5) { - return await this.sendWriteObjectOut(data, filePath) - } - } - - if (this.disConnectNum >= 5) { - console.info('surenjun', '123') - this.judgeUI.errorMsg = '当前的考试过程信息网络传输异常,程序点击确认将重启!'; - this.judgeUI.disConnectErrorOpen = true - } - - this.disConnectNum = 0 - return temp - } // 项目开始接口同步 beginProject = async (ksxm: number) => { const carInfo = AppStorage.get('carInfo'); @@ -606,59 +599,66 @@ export default class Judge { console.info(judgeTag, '项目结束 end') promptWxCode('17C55', temp.code || 0) } - // 检测扣分、结束项目时该项目是否开始 - checkProjectIsStart = async (xmdm: number, currentType: 1 | 2, kf?: MarkRule) => { - if (xmdm == 20) { - return true + private artSubject3ProjectsCodesArr: number[] = [3, 9, 4, 10, 12, 11] + private lane: LANE = { + road: '', num: 0, count: 0 + } + private videoData?: RecordHandleType + private disConnectNum: number = 0; + //调用监管接口 + sendWriteObjectOut: SendWriteObjectOut = async (data, filePath) => { + const temp = await writeObjectOut(data, filePath, this.context); + console.log("wzj", JSON.stringify(temp)) + //断网&网络超时次数计算 + if (temp.code == 2300007 || temp.code == 2300028) { + this.disConnectNum += 1; + if (this.disConnectNum < 5) { + return await this.sendWriteObjectOut(data, filePath) + } } - const judgeUI = this.judgeUI; - const judgeTask = this.judgeTask; - const projectsObj: object = this.judgeUI.projectsObj - const currentProject: ProjectInfo = Reflect.get(projectsObj, xmdm) - const isUpload = currentProject.isUpload - //如果项目没有开始 - console.info('surenjun isUpload=>', isUpload) - if (!isUpload) { - console.info(judgeTag, '项目补传开始') - //项目开始补传 - judgeTask.addTask(async () => { - await this.beginProject(xmdm) - }, { - isDelay: true - }) - judgeTask.addTask(async () => { - await this.uploadProgressPhoto(xmdm) - }, { - isDelay: true - }) - currentProject.isUpload = true; - Reflect.set(this.judgeUI.projectsObj, xmdm, currentProject) - //扣分补传 - if (currentType == 2) { - judgeTask.addTask(async () => { - await this.pointsDedute(xmdm, kf!) - }, { - isDelay: true - }) - } - //扣分补传判断是否合格 不合格补传项目结束 - if (currentType == 1 || (currentType == 2 && this.totalScore < judgeUI.passingScore)) { - judgeTask.addTask(async () => { - await this.endProject(xmdm) - }, { - isDelay: true - }) - currentProject.isEnd = true; - Reflect.set(this.judgeUI.projectsObj, xmdm, currentProject) - } - judgeTask.addTask(async () => { - this.checkExamIsEnd() - }) - return false; - } else { - return true + if (this.disConnectNum >= 5) { + console.info('surenjun', '123') + this.judgeUI.errorMsg = '当前的考试过程信息网络传输异常,程序点击确认将重启!'; + this.judgeUI.disConnectErrorOpen = true } + + this.disConnectNum = 0 + return temp + } + // 考试过程照片 + uploadProgressPhoto = async (ksxm: number) => { + const time = GetCurrentTime(); + const judgeUI = this.judgeUI + const plcData = this.plcData + const photoBase64 = await this.getPhoto(); + const carInfo = AppStorage.get('carInfo'); + + const project: ProjectInfo = Reflect.get(judgeUI.projectsObj, ksxm) + const judgeConfig_305: number = Reflect.get(judgeUI.judgeConfigObj, '305') + const drvexam: DrvexamType = { + lsh: judgeUI.lsh, + kskm: carInfo?.examSubject || "2", + ksxm: project.projectCodeCenter, + sfzmhm: judgeUI.idCard, + kchp: encodeURI(carInfo?.plateNo || ""), + zpsj: time, + zp: photoBase64, + cs: Math.floor((judgeConfig_305 == 0 ? (plcData?.gps?.sd || 0) : (plcData?.sensor?.cs || 0)) * 1.852), + ksdd: encodeURI(judgeUI.ksdd) + } + const data: RegulatoryInterfaceParams = { + xtlb: '17', + jkxlh: judgeUI.serialNumber, + jkid: '17C54', + drvexam + }; + const temp: WR = await this.sendWriteObjectOut(data, this.filePath); + if (temp.code === 2300007) { + this.isJudgeDisConnect = true + } + promptWxCode('17C54', temp.code || 0) + console.info(judgeTag, '上传照片 end') } constructor(judgeUI: JudgeUI) { diff --git a/entry/src/main/ets/utils/Common.ets b/entry/src/main/ets/utils/Common.ets index 5e840e6..b08d480 100644 --- a/entry/src/main/ets/utils/Common.ets +++ b/entry/src/main/ets/utils/Common.ets @@ -201,4 +201,24 @@ export function CreateDir(path: string): Promise { reject(false); } }); +} + +/* + * 将秒数转换为灵活的时间格式(HH:MM:SS) + * @param seconds 要转换的秒数 + * @return 返回格式化后的时间字符串 + */ +export function FormatTimeFlexible(seconds: number): string { + if (seconds < 0) throw new Error("秒数不能为负数"); + + const hours = Math.floor(seconds / 3600); + const minutes = Math.floor((seconds % 3600) / 60); + const secs = seconds % 60; + + // 强制使用两位数格式化,确保始终是 HH:MM:SS + const formattedHours = hours.toString().padStart(2, '0'); + const formattedMinutes = minutes.toString().padStart(2, '0'); + const formattedSeconds = secs.toString().padStart(2, '0'); + + return `${formattedHours}:${formattedMinutes}:${formattedSeconds}`; } \ No newline at end of file diff --git a/entry/src/main/ets/utils/table/Operation.ets b/entry/src/main/ets/utils/table/Operation.ets index 0d3af57..9df1cca 100644 --- a/entry/src/main/ets/utils/table/Operation.ets +++ b/entry/src/main/ets/utils/table/Operation.ets @@ -103,12 +103,9 @@ export async function InitializeTheCentralTable(params: InitializeTheCentralTabl let flag = false // 单机模式 if (params.singlePlay) { - const tableList = - ['MA_SYSSET', 'MA_SYSTEMPARM', 'MA_MARKRULE', 'MA_MARKRULESET', 'ES_CARINFO', 'MA_MAP_ROAD', 'MA_MAP_ROAD_LANE', - 'MAP_SUBITEM', 'MA_T_CARPARMSET', 'MA_MAP_ITEMCLASS', 'MA_MAP_POINT', 'MA_MAP_POINT_ITEM']; + const tableList = ['MA_SYSSET', 'MA_SYSTEMPARM', 'MA_MARKRULE', 'MA_MARKRULESET', 'ES_CARINFO', 'MA_MAP_ROAD', 'MA_MAP_ROAD_LANE', 'MAP_SUBITEM', 'MA_T_CARPARMSET', 'MA_MAP_ITEMCLASS', 'MA_MAP_POINT', 'MA_MAP_POINT_ITEM'] for (let i = 0; i <= tableList.length - 1; i++) { - const data = - await fileUtil.readFile(GlobalConfig.commonFileWriteAddress + `/config/tableList/${tableList[i]}.txt`); + const data = await fileUtil.readFile(GlobalConfig.commonFileWriteAddress + `/config/tableList/${tableList[i]}.txt`); flag = await SqlInsertTable(tableList[i], JSON.parse(data) || []) } if (!flag) { diff --git a/entry/src/main/ets/workers/Log.ets b/entry/src/main/ets/workers/Log.ets index e49c830..540e3a0 100644 --- a/entry/src/main/ets/workers/Log.ets +++ b/entry/src/main/ets/workers/Log.ets @@ -18,7 +18,7 @@ workerPort.onmessage = (e: MessageEvents) => { Init() } if (result.type === WorkerMessageType.OpenProcessDataFile) { - OpenProcessDataFile(logPaths, logFileFd, result.data) + OpenProcessDataFile(logPaths, logFileFd, result.data || "") } } @@ -27,14 +27,14 @@ async function Init() { // /mnt/hmdfs/100/account/device_view/local/files/duolun/logs/2024_10_12 // 创建duolun文件夹 /mnt/hmdfs/100/account/device_view/local/files/duolun const basePath = GlobalConfig.commonFileWriteAddress; - const isExit = await IsExit(basePath); + const isExit = await IsExit(basePath!); if (!isExit) { // 创建文件夹 - await CreateDir(basePath) + await CreateDir(basePath!) } // 创建logs文件夹/mnt/hmdfs/100/account/device_view/local/files/duolun/logs let logPath = `${basePath}/logs`; - const logIsExit = await IsExit(logPath); + const logIsExit = await IsExit(logPath!); if (!logIsExit) { // 创建logs文件夹 await CreateDir(logPath); @@ -42,7 +42,7 @@ async function Init() { // 创建日期文件夹/mnt/hmdfs/100/account/device_view/local/files/duolun/logs/2024_10_12 let date = dayTs().format("YYYY_MM_DD"); const folderName = `${GlobalConfig.commonFileWriteAddress}/logs/${date}`; - const folderIsExit = await IsExit(folderName); + const folderIsExit = await IsExit(folderName!); if (!folderIsExit) { // 创建日期文件夹 await CreateDir(folderName);