Compare commits
2 Commits
658fbed783
...
ee4d54e8d7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee4d54e8d7 | ||
|
|
d6a5c9fdba |
@ -70,4 +70,6 @@ export const SignDisplayTag = '[SignDisplay]';
|
||||
export const StartExamTag = '[StartExam]'
|
||||
|
||||
//人脸对比
|
||||
export const FaceCompareTag = '[FaceCompare]';
|
||||
export const FaceCompareTag = '[FaceCompare]';
|
||||
//过程数据处理
|
||||
export const ProcessDataTag = '[ProcessData]';
|
||||
@ -63,7 +63,7 @@ export enum ProcessDataEnumType {
|
||||
JudgeExamData = "2",
|
||||
//judge_log_data
|
||||
JudgeLogData = "3",
|
||||
// judge_progress_callback_data
|
||||
//judge_progress_callback_data
|
||||
JudgeProgressCallbackData = "4",
|
||||
//plc_data
|
||||
PlcData = "5",
|
||||
|
||||
@ -189,7 +189,7 @@ struct Index {
|
||||
dConsole.log("test1111")
|
||||
await GetDeviceInfo(this.context)
|
||||
this.carInfo = await GetCarInfo()
|
||||
this.carInfo = AppStorage.get<CarInfoType>('carInfo')!
|
||||
AppStorage.setOrCreate<CarInfoType>("carInfo", this.carInfo)
|
||||
this.deviceId = this.carInfo.carNo || ""
|
||||
await SetCurrentTime()
|
||||
this.timeInfo = AppStorage.get<TimeSynchronizationRspBody>('timeInfo')!
|
||||
|
||||
@ -48,7 +48,7 @@ export async function GetCarInfo(): Promise<CarInfoType> {
|
||||
deviceNo: AppStorage.get<string>('deviceNo') || ""
|
||||
};
|
||||
let res: ApiResponseType = await obtainCarExamInfo(params)
|
||||
dConsole.log("获取到的车辆信息", res)
|
||||
dConsole.log("90", res)
|
||||
if (res.obtainCarExamInfoRsp && res.obtainCarExamInfoRsp.body) {
|
||||
const carInfo: ObtainCarExamInfoRspBody = res?.obtainCarExamInfoRsp?.body!
|
||||
carInfo.plateNo = decodeURIComponent(carInfo.plateNo)
|
||||
|
||||
@ -396,7 +396,6 @@ struct JudgePage {
|
||||
Reflect.set(this.projectsObj, 1, project_1)
|
||||
}
|
||||
Reflect.set(this.judgeConfigObj, sys.v_no!, value)
|
||||
dConsole.log("寻找", this.judgeConfigObj)
|
||||
});
|
||||
this.judgeConfig = syssetJudgeConfigArr;
|
||||
}
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import {
|
||||
JudgeConfigObjKmItems,
|
||||
JudgeKSJS,
|
||||
JudgePerformInfo,
|
||||
JudgeUI,
|
||||
LANE,
|
||||
MarkRule,
|
||||
PLCType,
|
||||
ProcessDataEnumType,
|
||||
@ -22,6 +24,10 @@ import { PlcStrToJson, PlcStrToWXJson } from './utils'
|
||||
import { JudgeEndFn } from './JudgeEnd'
|
||||
|
||||
export default class JudgeBusiness {
|
||||
public mndgStr: string | undefined
|
||||
public lane: LANE = {
|
||||
road: '', num: 0, count: 0
|
||||
}
|
||||
public fileUtil: FileUtils
|
||||
public avPlayer?: VoiceAnnounce
|
||||
public performInfo?: JudgePerformInfo
|
||||
@ -31,7 +37,7 @@ export default class JudgeBusiness {
|
||||
public isEndTip: boolean = false;
|
||||
//是否手动结束考试
|
||||
public isManual: boolean = false
|
||||
public deductedPopShowTimer: number = 0;
|
||||
public deductedPopShowTimer: number = -1;
|
||||
public videoData?: RecordHandleType
|
||||
//是否是考试模式
|
||||
public isExam: boolean
|
||||
@ -48,12 +54,12 @@ export default class JudgeBusiness {
|
||||
public xmxh: string = ""
|
||||
public kfArr?: MarkRule[]
|
||||
public carztStr: string
|
||||
public ksjs?: JudgeKSJS
|
||||
public plcData?: PLCType
|
||||
private judgeUI: JudgeUI
|
||||
private tempData?: PLCType
|
||||
private plcData?: PLCType
|
||||
// 是否发送udp
|
||||
private isUdpEnd: boolean = false
|
||||
private mndgStr: string | undefined
|
||||
|
||||
constructor(judgeUI: JudgeUI) {
|
||||
this.judgeUI = judgeUI
|
||||
|
||||
@ -1,9 +1,20 @@
|
||||
import { JudgeTag } from '../../config';
|
||||
import { JudgeCallBackData, JudgeUI, KmItem, MarkRule, ProcessDataEnumType, ProjectInfo } from '../../model';
|
||||
import {
|
||||
JudgeCallBackData,
|
||||
JudgeConfigObj,
|
||||
JudgeSound,
|
||||
JudgeUI,
|
||||
KmItem,
|
||||
MarkRule,
|
||||
ProcessDataEnumType,
|
||||
ProjectInfo
|
||||
} from '../../model';
|
||||
import { dConsole } from '../../utils/LogWorker';
|
||||
import VoiceAnnounce from '../judgeSDK/utils/voiceAnnouncements';
|
||||
import JudgeBusiness from './JudgeBusiness';
|
||||
import { examJudgeArtificialItem } from './JudgeSDKUtils';
|
||||
import { CurrentProjectConversion, DeductionProjectConversion } from './utils';
|
||||
import { examJudgeArtificialItem, examJudgeSoundEnd } from './JudgeSDKUtils';
|
||||
import { ProjectStart, UploadProgressPhoto } from './ProcessDataProcessing';
|
||||
import { CurrentProjectConversion, DeductionProjectConversion, DetectingDifferences, GetCarStatus } from './utils';
|
||||
|
||||
export const JudgingFn = async (strData: string, callBack: Function, judgeUI: JudgeUI, that: JudgeBusiness) => {
|
||||
let examData: JudgeCallBackData = JSON.parse(strData);
|
||||
@ -26,13 +37,10 @@ export const JudgingFn = async (strData: string, callBack: Function, judgeUI: Ju
|
||||
const isManualProjectIn = artSubject3ProjectsCodesArr.includes(xmdm);
|
||||
const examSubject = judgeUI.examSubject
|
||||
const judgeConfigObj = judgeUI.judgeConfigObj
|
||||
let project: ProjectInfo = Reflect.get(judgeUI.projectsObj, xmdm)
|
||||
const xmmcCode = project.projectCodeCenter || "";
|
||||
const kmItem: KmItem = Reflect.get(that.kmItems, xmmcCode)
|
||||
|
||||
switch (event) {
|
||||
// 项目开始
|
||||
case 1:
|
||||
case 1: {
|
||||
const project: ProjectInfo = Reflect.get(judgeUI.projectsObj, xmdm)
|
||||
project.type = '2';
|
||||
if (isManualProjectIn) {
|
||||
//手动项目是否在进行中
|
||||
@ -44,6 +52,8 @@ export const JudgingFn = async (strData: string, callBack: Function, judgeUI: Ju
|
||||
judgeUI.currentXmdm = xmdm;
|
||||
const xmmcStr = project.name || "";
|
||||
const xmmcSingleCode = project.projectCode || "";
|
||||
const xmmcCode = project.projectCodeCenter || "";
|
||||
const kmItem: KmItem = Reflect.get(that.kmItems, xmmcCode)
|
||||
kmItem.status = 2;
|
||||
that.xmmcStr = xmmcStr;
|
||||
that.xmmcCode = xmmcCode;
|
||||
@ -55,10 +65,13 @@ export const JudgingFn = async (strData: string, callBack: Function, judgeUI: Ju
|
||||
Reflect.set(judgeUI.projectsObj, xmdm, project)
|
||||
Reflect.set(that.kmItems, xmmcCode || 0, kmItem)
|
||||
break;
|
||||
}
|
||||
// 项目结束
|
||||
case 2:
|
||||
case 2: {
|
||||
const project: ProjectInfo = Reflect.get(judgeUI.projectsObj, xmdm)
|
||||
const xmmcCode = project.projectCodeCenter || "";
|
||||
project.type = (xmjs.xmhg === 0 ? '4' : '3')
|
||||
//计算项目是否全部结束
|
||||
//计算项目是否全部结束
|
||||
judgeUI.isProjectIn = (Reflect.ownKeys(judgeUI.projectsObj).filter((projectKey) => {
|
||||
const fillProject: ProjectInfo = Reflect.get(judgeUI.projectsObj, projectKey)
|
||||
return fillProject.type == '2'
|
||||
@ -66,8 +79,9 @@ export const JudgingFn = async (strData: string, callBack: Function, judgeUI: Ju
|
||||
if (isManualProjectIn) {
|
||||
judgeUI.isManualProjectIn = false
|
||||
}
|
||||
const kmItem: KmItem = Reflect.get(that.kmItems, xmmcCode)
|
||||
kmItem.status = 3;
|
||||
//统计必考项目数量
|
||||
//统计必考项目数量
|
||||
that.xmmcStr = '无';
|
||||
that.xmmcCode = '';
|
||||
that.xmdm = '';
|
||||
@ -75,8 +89,9 @@ export const JudgingFn = async (strData: string, callBack: Function, judgeUI: Ju
|
||||
Reflect.set(judgeUI.projectsObj, xmdm, project)
|
||||
Reflect.set(that.kmItems, xmmcCode, kmItem)
|
||||
break;
|
||||
}
|
||||
// 扣分
|
||||
case 3:
|
||||
case 3: {
|
||||
const thisKf = DeductionProjectConversion(`${kf.xmdm}_${kf.kfdm}`, judgeUI.markRuleListObj)
|
||||
const kfObj: MarkRule = {
|
||||
//扣分项目名称
|
||||
@ -104,32 +119,77 @@ export const JudgingFn = async (strData: string, callBack: Function, judgeUI: Ju
|
||||
Reflect.set(judgeUI.projectsObj, kf.xmdm, project)
|
||||
}
|
||||
break;
|
||||
}
|
||||
// 考试状态
|
||||
case 4:
|
||||
case 4: {
|
||||
that.carztStr = GetCarStatus(carzt);
|
||||
break;
|
||||
}
|
||||
// 考试结束
|
||||
case 5:
|
||||
case 5: {
|
||||
that.ksjs = ksjs;
|
||||
// await fileLog?.setExamJudgeData(JSON.stringify({
|
||||
// method: 'examJudgeEndExam'
|
||||
// }))
|
||||
dConsole.writeProcessData(ProcessDataEnumType.JudgeExamData, JSON.stringify({
|
||||
method: 'examJudgeEndExam'
|
||||
}))
|
||||
break;
|
||||
}
|
||||
// 项目取消
|
||||
case 6:
|
||||
case 6: {
|
||||
dConsole.info(JudgeTag, '项目取消');
|
||||
const xmdm = xmqx.xmdm;
|
||||
const project: ProjectInfo = Reflect.get(judgeUI.projectsObj, xmdm)
|
||||
const xmmcCode = project.projectCodeCenter || "";
|
||||
project.type = '1'
|
||||
const kmItem: KmItem = Reflect.get(that.kmItems, xmmcCode)
|
||||
Reflect.set(judgeUI.projectsObj, xmdm, project)
|
||||
kmItem.status = 1
|
||||
Reflect.set(that.kmItems, xmmcCode, kmItem)
|
||||
break;
|
||||
}
|
||||
// 语音播报和提示
|
||||
case 7:
|
||||
case 7: {
|
||||
goJudgeVoice(sound, that.avPlayer)
|
||||
break;
|
||||
}
|
||||
// 模拟灯光事件
|
||||
case 8:
|
||||
case 8: {
|
||||
that.mndgStr = mndg
|
||||
break;
|
||||
}
|
||||
// 车道和路段变化
|
||||
case 9:
|
||||
case 9: {
|
||||
judgeUI.lane = lane
|
||||
that.lane = lane;
|
||||
break;
|
||||
}
|
||||
// 预进项目事件
|
||||
case 10:
|
||||
break;
|
||||
case 10: {
|
||||
const xmdm = precast.xmdm
|
||||
const xmxh = precast.xmxh
|
||||
const project: ProjectInfo = Reflect.get(judgeUI.projectsObj, xmdm)
|
||||
const xmmcCode: string = judgeUI.projectsObj[xmdm].projectCodeCenter;
|
||||
const xmmcSingleCode: string = judgeUI.projectsObj[xmdm].projectCode;
|
||||
const kmItem: KmItem = Reflect.get(that.kmItems, xmmcCode)
|
||||
const xmmcStr = project?.name || "";
|
||||
kmItem.status = 2;
|
||||
Reflect.set(that.kmItems, xmmcCode, project)
|
||||
that.xmmcStr = xmmcStr || "";
|
||||
that.xmmcCode = xmmcCode || "";
|
||||
that.xmdm = xmdm;
|
||||
that.xmxh = xmxh;
|
||||
that.xmmcSingleCode = xmmcSingleCode || "";
|
||||
project.type = '2';
|
||||
Reflect.set(judgeUI.projectsObj, xmdm, project)
|
||||
}
|
||||
// 差分事件
|
||||
case 11:
|
||||
case 11: {
|
||||
DetectingDifferences(nongps.type, that.avPlayer)
|
||||
break;
|
||||
}
|
||||
default:
|
||||
83
|
||||
break;
|
||||
}
|
||||
await callBack({
|
||||
@ -139,7 +199,25 @@ export const JudgingFn = async (strData: string, callBack: Function, judgeUI: Ju
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
const goJudgeVoice = async (sound: JudgeSound, avPlayer: VoiceAnnounce) => {
|
||||
dConsole.info('surenjun code=>', JSON.stringify(sound.code))
|
||||
//判断是不是模拟灯光语音
|
||||
if (sound.type == 1) {
|
||||
avPlayer?.playAudio([`voice/${sound.code[0]}.mp3`], false, () => {
|
||||
examJudgeSoundEnd({
|
||||
xmdm: sound.xmdm, code: sound.code[0], type: sound.type
|
||||
})
|
||||
dConsole.writeProcessData(ProcessDataEnumType.JudgeExamData, JSON.stringify({
|
||||
method: 'examJudgeSoundEnd',
|
||||
itemno: sound.xmdm,
|
||||
code: sound.code[0],
|
||||
type: sound.type,
|
||||
}))
|
||||
})
|
||||
} else {
|
||||
avPlayer?.playAudio([`voice/${sound.code[0]}.mp3`])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export const SetJudgeItem = async (itemno: string, type: 1 | 2) => {
|
||||
@ -151,4 +229,48 @@ export const SetJudgeItem = async (itemno: string, type: 1 | 2) => {
|
||||
})
|
||||
dConsole.writeProcessData(ProcessDataEnumType.JudgeExamData, str)
|
||||
dConsole.info(JudgeTag, `人工评判${type == 1 ? '进入' : '取消'}项目-${itemno}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 改变考试状态
|
||||
* old goVoiceAnnounce
|
||||
* @param event
|
||||
* @param xmdm
|
||||
* @param kf
|
||||
* @param judgeUI
|
||||
* @param that
|
||||
*/
|
||||
const changeExamStatus = async (event: number, xmdm: number, kf: MarkRule[], judgeUI: JudgeUI, that: JudgeBusiness) => {
|
||||
switch (event) {
|
||||
case 1: {
|
||||
const param512: JudgeConfigObj = (Reflect.get(judgeUI.judgeConfigObj, '512') || '').split(',');
|
||||
const project: ProjectInfo = Reflect.get(judgeUI.projectsObj, xmdm)
|
||||
setTimeout(() => {
|
||||
if (Reflect.get(param512, 7) != 0) {
|
||||
clearTimeout(that.deductedPopShowTimer)
|
||||
judgeUI.isDeductedPopShow = true
|
||||
}
|
||||
}, 200)
|
||||
if (!project.isEnd) {
|
||||
// that.judgeTask.addTask(async () => {
|
||||
// dConsole.info(JudgeTag, `项目开始-${xmdm}-${project.name}`)
|
||||
// await beginProject(xmdm)
|
||||
// }, {
|
||||
// isDelay: true
|
||||
// })
|
||||
ProjectStart(xmdm, that.xmxh, judgeUI)
|
||||
// that.judgeTask.addTask(async () => {
|
||||
// dConsole.info(JudgeTag, `项目-${xmdm}-上传照片 start`)
|
||||
// await uploadProgressPhoto(xmdm)
|
||||
// }, {
|
||||
// isDelay: true
|
||||
// })
|
||||
UploadProgressPhoto(xmdm, that.plcData, judgeUI)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
import { testKm2Items, testKm3Items } from '../../mock';
|
||||
import { JudgeConfigObjKmItems, ProjectInfo, ProjectInfos } from '../../model';
|
||||
|
||||
class judgeVariable {
|
||||
public rmndg: 0 | 1 = 0
|
||||
public kmItems: JudgeConfigObjKmItems = {}
|
||||
public xmmcStr: string = ""
|
||||
public xmmcEndCode?: string = ""
|
||||
public xmxh: string = ""
|
||||
public status: string = "开始"
|
||||
|
||||
constructor() {
|
||||
|
||||
}
|
||||
|
||||
public initKmItems(examSubject: string, projectsCenterObj: ProjectInfos) {
|
||||
(examSubject == '2' ? testKm2Items : testKm3Items).forEach(item => {
|
||||
const projectCenterObj: ProjectInfo = Reflect.get(projectsCenterObj, item.code)
|
||||
Reflect.set(this.kmItems, item.code, {
|
||||
code: item.code,
|
||||
status: projectCenterObj === undefined ? 0 : (projectCenterObj.isEnd ? 3 : 1)
|
||||
})
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export const JudgeVariable = new judgeVariable();
|
||||
187
entry/src/main/ets/pages/Judge/ProcessDataProcessing.ets
Normal file
187
entry/src/main/ets/pages/Judge/ProcessDataProcessing.ets
Normal file
@ -0,0 +1,187 @@
|
||||
/**
|
||||
* 过程数据处理
|
||||
*/
|
||||
import { ProcessDataTag } from '../../config';
|
||||
import {
|
||||
CarInfoType,
|
||||
CDSBInfo,
|
||||
CDSBInfos,
|
||||
DrvexamType,
|
||||
JudgeUI,
|
||||
MarkRule,
|
||||
PLCType,
|
||||
ProjectInfo,
|
||||
RegulatoryInterfaceParams
|
||||
} from '../../model';
|
||||
import { GetPhotoBase64 } from '../../utils/Common';
|
||||
import dayTs from '../../utils/Date';
|
||||
import { dConsole } from '../../utils/LogWorker';
|
||||
import { ProcessDataTaskPoolInstance } from './ProcessDataTaskPool';
|
||||
|
||||
/**
|
||||
* beginProject 项目开始
|
||||
*/
|
||||
export const ProjectStart = (ksxm: number, xmxh: string, judgeUI: JudgeUI) => {
|
||||
const carInfo = AppStorage.get<CarInfoType>('carInfo');
|
||||
const project: ProjectInfo = Reflect.get(judgeUI.projectsObj, ksxm)
|
||||
const sbxh = getSBXH(ksxm, xmxh, judgeUI.cdsbInfoObj, judgeUI.projectsObj, carInfo.examSubject);
|
||||
const drvexam: DrvexamType = {
|
||||
lsh: judgeUI.lsh,
|
||||
kskm: carInfo?.examSubject || "2",
|
||||
sfzmhm: judgeUI.idCard,
|
||||
ksxm: project.projectCodeCenter,
|
||||
sbxh,
|
||||
ksxl: judgeUI.xldm,
|
||||
kchp: encodeURI(carInfo?.plateNo || ""),
|
||||
ksdd: encodeURI(judgeUI.ksdd),
|
||||
kslx: encodeURI(judgeUI.kslx) || '',
|
||||
kssj: dayTs().format("YYYY-MM-DD HH:mm:ss")
|
||||
}
|
||||
const data: RegulatoryInterfaceParams = {
|
||||
//系统类别 接口序列号 接口标识
|
||||
xtlb: '17',
|
||||
jkxlh: judgeUI.serialNumber,
|
||||
jkid: '17C52',
|
||||
drvexam
|
||||
}
|
||||
dConsole.log(ProcessDataTag, "项目开始数据处理", data)
|
||||
ProcessDataTaskPoolInstance.addTask(data)
|
||||
}
|
||||
|
||||
/**
|
||||
* uploadProgressPhoto 上传过程照片
|
||||
*/
|
||||
export const UploadProgressPhoto = async (ksxm: number, plcData: PLCType, judgeUI: JudgeUI) => {
|
||||
const photoBase64 = await GetPhotoBase64(judgeUI.context);
|
||||
const carInfo = AppStorage.get<CarInfoType>('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: dayTs().format("YYYY-MM-DD HH:mm:ss"),
|
||||
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
|
||||
};
|
||||
dConsole.log(ProcessDataTag, "上传过程照片数据处理", data);
|
||||
ProcessDataTaskPoolInstance.addTask(data)
|
||||
}
|
||||
|
||||
/**
|
||||
* pointsDedute 扣分补传
|
||||
*/
|
||||
export const DeductPoints = (ksxm: number, kf: MarkRule, xmmcEndCode: string, judgeUI: JudgeUI) => {
|
||||
const carInfo = AppStorage.get<CarInfoType>('carInfo')!;
|
||||
const examSubject = carInfo.examSubject
|
||||
const lsh = judgeUI.lsh
|
||||
const idCard = judgeUI.idCard
|
||||
const serialNumber = judgeUI.serialNumber
|
||||
const ksdd = judgeUI.ksdd
|
||||
const projectsObj: object = judgeUI.projectsObj
|
||||
const project: ProjectInfo = Reflect.get(judgeUI.projectsObj, ksxm)
|
||||
//科目三夜间行驶.模拟灯光、上车准备出现通用评判,ksxm为当前进行的项目
|
||||
const checkProjects = ['17', '41', '1'];
|
||||
//获取正在进行的项目
|
||||
const inProjects = Reflect.ownKeys(projectsObj).filter(projectKey => {
|
||||
const project: ProjectInfo = Reflect.get(projectsObj, projectKey)
|
||||
return project.type == '2'
|
||||
});
|
||||
let commonKsxm = '';
|
||||
checkProjects.forEach(projectCode => {
|
||||
if (inProjects.includes(projectCode)) {
|
||||
commonKsxm = projectCode
|
||||
}
|
||||
})
|
||||
let ksxmD: string;
|
||||
if (!project) {
|
||||
if (commonKsxm) {
|
||||
ksxmD = Reflect.get(projectsObj, commonKsxm).projectCodeCenter;
|
||||
} else {
|
||||
if (examSubject == '3') {
|
||||
ksxmD = '30000';
|
||||
} else {
|
||||
ksxmD = (xmmcEndCode == undefined ? '10000' : xmmcEndCode);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ksxmD = project?.projectCodeCenter || "";
|
||||
}
|
||||
const drvexam: DrvexamType = {
|
||||
lsh,
|
||||
kskm: examSubject,
|
||||
ksxm: ksxmD,
|
||||
kfxm: kf.markcatalog,
|
||||
kfxmmx: `${ksxm},${kf.markserial}`,
|
||||
sfzmhm: idCard,
|
||||
kchp: encodeURI(carInfo?.plateNo || ""),
|
||||
//扣分方式
|
||||
kffs: kf.type == 0 ? 1 : 2,
|
||||
ksdd: encodeURI(ksdd),
|
||||
kfsj: dayTs().format("YYYY-MM-DD HH:mm:ss"),
|
||||
}
|
||||
const data: RegulatoryInterfaceParams = {
|
||||
xtlb: '17',
|
||||
jkxlh: serialNumber,
|
||||
jkid: '17C53',
|
||||
drvexam
|
||||
}
|
||||
dConsole.log(ProcessDataTag, "扣分上传数据", data)
|
||||
ProcessDataTaskPoolInstance.addTask(data)
|
||||
}
|
||||
|
||||
/**
|
||||
* endProject 结束项目
|
||||
*/
|
||||
export const ProjectEnd = (ksxm: number, xmxh: string, judgeUI: JudgeUI) => {
|
||||
const carInfo = AppStorage.get<CarInfoType>('carInfo');
|
||||
const project: ProjectInfo = Reflect.get(judgeUI.projectsObj, ksxm)
|
||||
const sbxh = carInfo.examSubject == '3' ? undefined : getSBXH(ksxm, xmxh, judgeUI.cdsbInfoObj, judgeUI.projectsObj, carInfo.examSubject);
|
||||
const drvexam: DrvexamType = {
|
||||
lsh: judgeUI.lsh,
|
||||
kskm: carInfo?.examSubject || "2",
|
||||
sfzmhm: judgeUI.idCard,
|
||||
ksxm: project.projectCodeCenter,
|
||||
sbxh,
|
||||
//TODO 操作类型 1:正常 0:撤销该考试记录
|
||||
czlx: '1',
|
||||
ksxl: judgeUI.xldm,
|
||||
kchp: encodeURI(carInfo?.plateNo || ""),
|
||||
ksdd: encodeURI(judgeUI.ksdd),
|
||||
kslx: encodeURI(judgeUI.kslx) || '',
|
||||
jssj: dayTs().format("YYYY-MM-DD HH:mm:ss")
|
||||
}
|
||||
const data: RegulatoryInterfaceParams = {
|
||||
xtlb: '17',
|
||||
jkxlh: judgeUI.serialNumber,
|
||||
jkid: '17C55',
|
||||
drvexam
|
||||
}
|
||||
dConsole.log(ProcessDataTag, "结束项目数据", data)
|
||||
ProcessDataTaskPoolInstance.addTask(data)
|
||||
}
|
||||
|
||||
|
||||
const getSBXH = (ksxm: number, xmxh: string, cdsbInfoObj: CDSBInfos, projectsObj: object, examSubject: string): string => {
|
||||
const project: ProjectInfo = Reflect.get(projectsObj, ksxm);
|
||||
//科目三不需要
|
||||
if (examSubject == '3') {
|
||||
return ""
|
||||
}
|
||||
if (project === undefined) {
|
||||
return '00000000'
|
||||
}
|
||||
const projectKey = `${ksxm}_${xmxh}`;
|
||||
const currentCdsb: CDSBInfo = Reflect.get(cdsbInfoObj!, projectKey) || {}
|
||||
const sbxh: string = currentCdsb.sbbm || '00000000'
|
||||
return sbxh
|
||||
}
|
||||
@ -5,10 +5,14 @@ import http from '@ohos.net.http';
|
||||
import Request from '../../utils/Request';
|
||||
|
||||
export class ProcessDataTaskPool {
|
||||
private queue: RegulatoryInterfaceParams[] = []
|
||||
private queue: RegulatoryInterfaceParams[] = [];
|
||||
private isProcessing: boolean = false;
|
||||
/** 最大重试次数。1次初次尝试 + 5次重试 = 总共6次尝试。 */
|
||||
private readonly maxRetries = 5;
|
||||
/** 最小处理时间(毫秒) */
|
||||
private readonly minProcessingTime = 2000;
|
||||
/** 记录每个任务的开始处理时间 */
|
||||
private taskStartTime: number = 0;
|
||||
|
||||
public addTask(dataItem: RegulatoryInterfaceParams): void {
|
||||
console.info(`[Queue] 新任务已添加: ${JSON.stringify(dataItem)},当前队列长度: ${this.queue.length + 1}`);
|
||||
@ -23,11 +27,10 @@ export class ProcessDataTaskPool {
|
||||
private triggerProcessing(): void {
|
||||
if (this.isProcessing) {
|
||||
console.log('[Queue] 处理器正在运行中,新任务将在稍后被处理。');
|
||||
return; // 如果已经在处理,则直接返回,新任务会被正在运行的循环消费掉
|
||||
return;
|
||||
}
|
||||
// 使用 Promise.resolve().then() 来确保 processQueue 在下一个事件循环中异步执行
|
||||
// 这可以防止阻塞当前的 addTask 调用
|
||||
Promise.resolve().then(() => this.processQueue());
|
||||
// [优化] 直接调用 async 函数,它会立即返回一个 Promise,不会阻塞当前执行流,效果与 Promise.resolve().then() 相同但更简洁。
|
||||
this.processQueue();
|
||||
}
|
||||
|
||||
private async processQueue(): Promise<void> {
|
||||
@ -36,33 +39,52 @@ export class ProcessDataTaskPool {
|
||||
|
||||
while (this.queue.length > 0) {
|
||||
const taskData = this.queue[0]; // 查看队首任务
|
||||
this.taskStartTime = Date.now(); // 记录任务开始时间
|
||||
|
||||
try {
|
||||
console.log(`[Queue] 开始处理任务: ${JSON.stringify(taskData)}`);
|
||||
// 此方法若成功则正常返回,若永久失败则会抛出错误
|
||||
let obj: WuxiExamType = {
|
||||
|
||||
// 预先记录将要处理的数据
|
||||
const obj: WuxiExamType = {
|
||||
xtlb: taskData.xtlb,
|
||||
jkxlh: taskData.jkxlh,
|
||||
jkid: taskData.jkid,
|
||||
drvexam: {
|
||||
zp: "",
|
||||
},
|
||||
}
|
||||
dConsole.writeProcessData(ProcessDataEnumType.WuxiExam, JSON.stringify(obj))
|
||||
};
|
||||
dConsole.writeProcessData(ProcessDataEnumType.WuxiExam, JSON.stringify(obj));
|
||||
|
||||
// 此方法若成功则正常返回,若永久失败则会抛出错误
|
||||
await this.processSingleTaskWithRetries(taskData);
|
||||
|
||||
// 任务成功,将其从队列中移除
|
||||
this.queue.shift();
|
||||
console.log(`[Queue] ✅ 任务处理成功,已从队列移除。剩余任务: ${this.queue.length}`);
|
||||
|
||||
// 计算任务实际耗时
|
||||
const elapsedTime = Date.now() - this.taskStartTime;
|
||||
// 如果处理时间小于最小要求时间,则延迟剩余时间
|
||||
if (elapsedTime < this.minProcessingTime) {
|
||||
const delayTime = this.minProcessingTime - elapsedTime;
|
||||
console.log(`[Queue] 任务处理耗时 ${elapsedTime}ms,需要延迟 ${delayTime}ms 以满足最小处理时间要求`);
|
||||
await this.delay(delayTime);
|
||||
}
|
||||
} catch (error) {
|
||||
// 捕获到永久失败的错误
|
||||
console.error(`[Queue] 🔥 致命错误: ${(error as Error).message}`);
|
||||
console.error('[Queue] 队列已停止,后续任务将不会被处理。');
|
||||
// **[健壮性改进]** 捕获到永久失败的错误。
|
||||
// 原有逻辑会清空整个队列,导致后续任务丢失。
|
||||
// 优化后的逻辑是:仅移除当前失败的任务,并记录错误,然后继续处理队列中的下一个任务。
|
||||
console.error(`[Queue] 🔥 任务永久失败: ${(error as Error).message}`);
|
||||
const failedTask = this.queue.shift(); // 移除失败的任务
|
||||
console.error(`[Queue] 失败的任务已被移除: ${JSON.stringify(failedTask)},将继续处理下一个任务。`);
|
||||
|
||||
// (可选)可以在此处清空队列,防止下次意外启动时处理旧任务
|
||||
this.queue = [];
|
||||
|
||||
// 终止循环
|
||||
break;
|
||||
// 即使任务失败,也需要满足最小处理时间要求
|
||||
const elapsedTime = Date.now() - this.taskStartTime;
|
||||
if (elapsedTime < this.minProcessingTime) {
|
||||
const delayTime = this.minProcessingTime - elapsedTime;
|
||||
console.log(`[Queue] 失败任务处理耗时 ${elapsedTime}ms,需要延迟 ${delayTime}ms 以满足最小处理时间要求`);
|
||||
await this.delay(delayTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,27 +92,40 @@ export class ProcessDataTaskPool {
|
||||
console.log('[Queue] 处理器已停止。');
|
||||
}
|
||||
|
||||
/**
|
||||
* 延迟指定时间
|
||||
* @param ms 延迟的毫秒数
|
||||
*/
|
||||
private delay(ms: number): Promise<void> {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
private async processSingleTaskWithRetries(taskData: RegulatoryInterfaceParams): Promise<void> {
|
||||
// 1 次初次尝试 + 5 次重试
|
||||
for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
|
||||
const attemptNum = attempt + 1;
|
||||
try {
|
||||
const attemptType = attempt === 0 ? '初次尝试' : `重试 ${attempt}`;
|
||||
console.log(`[Queue] 开始上传 (${attemptType}, 总共第 ${attemptNum} 次): ${JSON.stringify(taskData)}`);
|
||||
console.log(`[Queue] 开始上传 (${attemptType}, 总共第 ${attemptNum} 次)`);
|
||||
|
||||
// **注意**: 这里传递的是 taskData 的引用,为了防止 worker 中意外修改原始数据,
|
||||
// 最佳实践是在 worker 内部或传递前进行深拷贝。
|
||||
// 但根据我们下面的修复,worker 不再修改原始数据,所以这里是安全的。
|
||||
const result: WR = await taskpool.execute(uploadWorkerTask, taskData);
|
||||
dConsole.writeProcessData(ProcessDataEnumType.WuxiExam, JSON.stringify(result))
|
||||
|
||||
dConsole.writeProcessData(ProcessDataEnumType.WuxiExam, JSON.stringify(result));
|
||||
if (result.code === 1) {
|
||||
console.log(`[Queue] ✔️ 上传成功 (在第 ${attemptNum} 次尝试)`);
|
||||
return; // 成功,立即返回
|
||||
}
|
||||
console.warn(`[Queue] ❌ 上传失败 (第 ${attemptNum} 次)。响应: ${result.message}`);
|
||||
} catch (e) {
|
||||
console.error(`[Queue] ❌ TaskPool 执行错误 (第 ${attemptNum} 次): ${e}`);
|
||||
// **[健壮性改进]** 现在可以捕获从 Worker 抛出的更详细的异常信息
|
||||
console.error(`[Queue] ❌ TaskPool 执行或网络错误 (第 ${attemptNum} 次): ${e}`);
|
||||
}
|
||||
|
||||
// 如果这是最后一次尝试且依然失败,则不再等待,直接跳出循环去抛出错误
|
||||
if (attempt === this.maxRetries) {
|
||||
break;
|
||||
break; // 最后一次尝试失败后,跳出循环去抛出错误
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,26 +134,28 @@ export class ProcessDataTaskPool {
|
||||
}
|
||||
}
|
||||
|
||||
export const ProcessDataTaskPoolInstance = new ProcessDataTaskPool();
|
||||
|
||||
/**
|
||||
* 这是将在 Worker 线程中执行的任务函数。
|
||||
* 它负责执行单次的上传尝试。
|
||||
*
|
||||
* @param data 需要上传的单条数据项
|
||||
* @returns 一个包含本次上传尝试结果的对象
|
||||
*/
|
||||
export async function uploadWorkerTask(data: RegulatoryInterfaceParams): Promise<WR> {
|
||||
let singlePlay: boolean = false
|
||||
let isJGNew = false
|
||||
// 这两个变量似乎未在逻辑中使用,暂时保持原样
|
||||
let singlePlay: boolean = false;
|
||||
let isJGNew = false;
|
||||
try {
|
||||
const response = await sendProcessData(data, singlePlay, isJGNew);
|
||||
// 根据返回的 code 判断是否成功
|
||||
return response
|
||||
return response;
|
||||
} catch (err) {
|
||||
// 捕获请求过程中可能出现的异常
|
||||
// [健壮性改进] 捕获请求过程中的异常,并重新抛出。
|
||||
// 这能让主线程的 taskpool.execute() promise 变为 rejected 状态,
|
||||
// 从而被 processSingleTaskWithRetries 中的 try-catch 捕获,保留了详细的错误信息。
|
||||
const error = err as Error;
|
||||
console.error(`[Worker] 上传时发生异常: ${error.message}`);
|
||||
return { code: 20038 };
|
||||
throw error; // 重新抛出异常
|
||||
}
|
||||
}
|
||||
|
||||
@ -139,32 +176,8 @@ async function sendProcessData(data: RegulatoryInterfaceParams, singlePlay: bool
|
||||
return await Request<object>({
|
||||
host: JGHOST,
|
||||
url: '/dems_ws/services/TmriOutAccess?wsdl',
|
||||
data: `<?xml version="1.0"?>
|
||||
<SOAP-ENV:Envelope
|
||||
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
|
||||
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
|
||||
>
|
||||
<SOAP-ENV:Body>
|
||||
<writeObjectOut xmlns="http://service.es.doron">
|
||||
<xtlb>${data.xtlb}</xtlb>
|
||||
<jkxlh>${data.jkxlh}</jkxlh>
|
||||
<jkid>${data.jkid}</jkid>
|
||||
<UTF8XmlDoc>
|
||||
<![CDATA[
|
||||
<?xm lversion="1.0 "encoding="GBK"?>
|
||||
<root>
|
||||
<drvexam>
|
||||
${drvexamArr}
|
||||
</drvexam>
|
||||
</root>
|
||||
]]>
|
||||
</UTF8XmlDoc>
|
||||
</writeObjectOut>
|
||||
</SOAP-ENV:Body>
|
||||
</SOAP-ENV:Envelope>`,
|
||||
data: `<?xml version="1.0"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" > <SOAP-ENV:Body> <writeObjectOut xmlns="http://service.es.doron"> <xtlb>${data.xtlb}</xtlb> <jkxlh>${data.jkxlh}</jkxlh> <jkid>${data.jkid}</jkid> <UTF8XmlDoc> <![CDATA[ <?xm lversion="1.0 "encoding="GBK"?> <root> <drvexam> ${drvexamArr} </drvexam> </root> ]]> </UTF8XmlDoc> </writeObjectOut> </SOAP-ENV:Body> </SOAP-ENV:Envelope>`,
|
||||
method: http.RequestMethod.POST,
|
||||
xml: true
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
@ -6,9 +6,11 @@ import {
|
||||
DefaultJudgeConfigObj,
|
||||
ExtendType,
|
||||
Gps,
|
||||
JudgeSound,
|
||||
LANE,
|
||||
MarkRule,
|
||||
PLCType,
|
||||
ProcessDataEnumType,
|
||||
ProjectInfo,
|
||||
ProjectInfos,
|
||||
ProjectRoads,
|
||||
@ -18,6 +20,8 @@ import {
|
||||
import { ArrayToByteArray, NumberToByteArray } from '../../utils/Common';
|
||||
import dayTs from '../../utils/Date';
|
||||
import { dConsole } from '../../utils/LogWorker';
|
||||
import VoiceAnnounce from '../judgeSDK/utils/voiceAnnouncements';
|
||||
import { examJudgeSoundEnd } from './JudgeSDKUtils';
|
||||
|
||||
|
||||
// 中心信号转换
|
||||
@ -852,4 +856,54 @@ export const DeductionProjectConversion = (code: string, markRuleListObj: object
|
||||
export const CurrentProjectConversion = (code: number, projectsObj: object): string => {
|
||||
const project: ProjectInfo = Reflect.get(projectsObj, code)
|
||||
return project?.abbreviation || '通用评判'
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取评判语音
|
||||
* @param sound - 评判音频对象
|
||||
* @param avPlayer - 语音播放器实例
|
||||
*/
|
||||
export function PlayJudgeVoice(sound: JudgeSound, avPlayer: VoiceAnnounce) {
|
||||
if (sound.type == 1) {
|
||||
avPlayer?.playAudio([`voice/${sound.code[0]}.mp3`], false, () => {
|
||||
examJudgeSoundEnd({
|
||||
xmdm: sound.xmdm, code: sound.code[0], type: sound.type
|
||||
});
|
||||
dConsole.writeProcessData(ProcessDataEnumType.JudgeExamData, JSON.stringify({
|
||||
method: 'examJudgeSoundEnd',
|
||||
itemno: sound.xmdm,
|
||||
code: sound.code[0],
|
||||
type: sound.type,
|
||||
}));
|
||||
});
|
||||
} else {
|
||||
avPlayer?.playAudio([`voice/${sound.code[0]}.mp3`]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查差分
|
||||
*/
|
||||
export const DetectingDifferences = async (type: number, avPlayer: VoiceAnnounce): Promise<boolean> => {
|
||||
switch (type) {
|
||||
case 0:
|
||||
return true;
|
||||
case 1:
|
||||
avPlayer?.playAudio([`voice/差分状态异常.mp3`], true)
|
||||
// setTimeout(() => {
|
||||
// router.back()
|
||||
// }, 3000)
|
||||
return true
|
||||
case 2:
|
||||
avPlayer?.playAudio([`voice/差分状态异常.mp3`], true);
|
||||
return false
|
||||
case 3:
|
||||
avPlayer?.playAudio([`voice/差分状态异常.mp3`], true);
|
||||
return true
|
||||
case 4:
|
||||
//差分异常上报
|
||||
return false
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -16,19 +16,12 @@ class differentialSignal {
|
||||
console.error(TCPTag, "TCP发生错误")
|
||||
this.differentialSignalTcp.reBind()
|
||||
})
|
||||
// let config: EnvironmentConfigurationType =
|
||||
// AppStorage.get<EnvironmentConfigurationType>("EnvironmentConfiguration") || {
|
||||
// tcplocalIp: "",
|
||||
// tcplocalIpPort: "",
|
||||
// tcpOppositeIp: "",
|
||||
// tcpOppositePort: ""
|
||||
// }
|
||||
console.log(TCPTag, "初始化", JSON.stringify(config))
|
||||
if (config.tcplocalIp || config.tcplocalIpPort || config.tcpOppositeIp || config.tcpOppositePort) {
|
||||
this.differentialSignalTcp.init(config.tcplocalIp || "", config.tcplocalIpPort || "", config.tcpOppositeIp || "",
|
||||
config.tcpOppositePort || "");
|
||||
} else {
|
||||
console.log(TCPTag, "未配置差分信号TCP信息,请在环境配置中设置")
|
||||
console.error(TCPTag, "未配置差分信号TCP信息,请在环境配置中设置")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user