Compare commits

...

4 Commits

Author SHA1 Message Date
wangzhongjie
f03ace7f04 fix: 优化首页获取车辆后才可以进入联网以及单机逻辑 2025-07-02 17:34:25 +08:00
wangzhongjie
b0692d358c fix: 评判代码抽离优化 2025-07-02 15:53:11 +08:00
wangzhongjie
98813fe361 fix: 评判页面结构优化 2025-07-02 10:41:49 +08:00
wangzhongjie
b2b7950d81 fix: 结束考试问题修复 2025-07-01 17:51:36 +08:00
16 changed files with 1002 additions and 894 deletions

View File

@ -1,2 +1,2 @@
gitLog:
git log --since="2025-06-27 15:02" --until="2025-06-30 17:14" --pretty=format:"<details>%n <summary>%s</summary>%n <span style=\"color: #888;\">[提交人]:</span><span style=\"color: #333;\">%an</span><br>%n <span style=\"color: #888;\">[提交时间]:</span><span style=\"color: #333;\">%ad</span><br>%n <span style=\"color: #888;\">[提交版本]:</span><span style=\"color: #333;\">%h</span>%n</details>%n" --date=format:"%Y-%m-%d %H:%M" > release_note.md
git log --since="2025-06-30 17:14" --until="2025-07-1 17:14" --pretty=format:"<details>%n <summary>%s</summary>%n <span style=\"color: #888;\">[提交人]:</span><span style=\"color: #333;\">%an</span><br>%n <span style=\"color: #888;\">[提交时间]:</span><span style=\"color: #333;\">%ad</span><br>%n <span style=\"color: #888;\">[提交版本]:</span><span style=\"color: #333;\">%h</span>%n</details>%n" --date=format:"%Y-%m-%d %H:%M" > release_note.md

View File

@ -477,7 +477,7 @@ export interface JudgeUI {
ksdd: string
errorMsg: string
name: string
kfArrScroller: Scroller
// kfArrScroller: Scroller
disConnectErrorOpen: boolean
currentXmdm?: number
isRequiredProjectsEnd: boolean
@ -582,10 +582,6 @@ export interface ItemInfos {
'1'?: ItemInfo
}
// export const defaultCdsbInfoObj:DefaultJudgeConfigObj = {
//
// }
/****** 评判初始化数据*****/
export interface JudgeInitObj extends Km3JudgeInitConfig {

View File

@ -15,10 +15,10 @@ import { JudgeEmitterInstance } from '../utils/business/UdpEvent';
import HeaderComponent from './compontents/Header';
import CardComponent from './Index/Card';
import BottomMessageComponent from './Index/BottomMessage';
import LoadingComponent from './Index/Loading';
import Prompt from '@system.prompt';
import { DifferentialAndSignal } from '../utils/business/DifferentialAndSignalWorker';
import { dConsole } from '../utils/LogWorker';
import CarLoadingComponent from './Index/Loading';
@Entry
@Component
@ -41,7 +41,7 @@ struct Index {
@State initWork: boolean = false
// 请求网络表等待弹窗
customDialogController: CustomDialogController = new CustomDialogController({
builder: LoadingComponent(),
builder: CarLoadingComponent(),
customStyle: true,
alignment: DialogAlignment.Center,
autoCancel: true
@ -222,10 +222,24 @@ struct Index {
CardComponent({
isSingle: this.singlePlay,
singleClick: () => {
if (this.deviceId === "") {
Prompt.showToast({
message: `未获取到车辆信息,请检查网络!`,
duration: 3000
});
return
}
dConsole.log(HomeTag, "单机模式点击")
this.singlePlayerTraining()
},
networkingClick: () => {
if (this.deviceId === "") {
Prompt.showToast({
message: `未获取到车辆信息,请检查网络!`,
duration: 3000
});
return
}
dConsole.log(HomeTag, "联网考试点击")
this.onlineExam()
}

View File

@ -1,5 +1,5 @@
@CustomDialog
export default struct LoadingComponent {
export default struct CarLoadingComponent {
@State angle: number = 0
private controller?: CustomDialogController;

View File

@ -24,8 +24,6 @@ import {
LANE,
MA_CDSBINFOType,
MA_ITEMINFOType,
MA_MAP_POINT_ITEMType,
MA_MAP_POINTType,
MA_SYSTEMPARMType,
MAPITEMPOINTITEM,
MAPPOINT,
@ -35,7 +33,6 @@ import {
Project,
ProjectInfo,
ProjectInfos,
ProjectRoads,
RouteParamsType,
SYSSET,
SyssetConfig,
@ -44,13 +41,19 @@ import {
} from '../model';
import { GetSyncData } from '../utils/table/Operation';
import dayTs from '../utils/Date';
import { CutArray, FormatTimeFlexible, GetCurrentTime } from '../utils/Common';
import { GetCurrentTime } from '../utils/Common';
import FileUtils from '../utils/FileUtils';
import SignalTrajectoryDialog from './Judge/SignalTrajectoryDialog';
import { DefaultJudgeConfigData } from '../mock';
import { dConsole } from '../utils/LogWorker';
import ConfirmDialog from './compontents/ConfirmDialog';
import CarLoadingDialog from './compontents/CarLoading';
import HeaderComponent from './compontents/Header';
import MessageComponent from './Judge/Message';
import OperatingAreaComponent from './Judge/OperatingArea';
import JudgeAndProjectComponent from './Judge/JudgeAndProject';
import { GetIsExitManualProject } from './Judge/utils';
import { InitMapPoint, InitMapPointItem } from './Judge/TableUtils';
@Entry
@ -59,12 +62,7 @@ struct JudgePage {
scroller: Scroller = new Scroller()
//页面通用字体大小
@State wayno: number = 0
@State FONTSIZE: number = 30
@State BIGFONTSIZE: number = 32
@State isDdxk: boolean = false;
@State time: string = ''
//考试用时
@State examTime: number = 0
//开始时间
@State startTime: string = '00:00:00'
@State startFullTime: string = ''
@ -136,7 +134,6 @@ struct JudgePage {
//定位差分状态时候正常
@State isDwztRight: boolean = true;
@State defaultTabIndex: number = 0;
public kfArrScroller: Scroller = new Scroller()
//档位
@State dw: string = ''
//速度
@ -207,13 +204,9 @@ struct JudgePage {
this.carInfo = AppStorage.get<CarInfoType>('carInfo')!
this.singlePlay = AppStorage.get<boolean>('singlePlay')!
this.startFullTime = GetCurrentTime(1);
// this.startHourTime = await getCurrentHourTime()
this.startTime = dayTs().format("YYYY-MM-DD HH:mm:ss")
this.startExamTime = dayTs().format("YYYY-MM-DD HH:mm:ss")
setInterval(async () => {
this.time = dayTs().format("YYYY-MM-DD HH:mm:ss");
this.examTime += 1;
}, 1000);
//初始化数据库表
await this.initDb()
//断点续考
@ -242,8 +235,8 @@ struct JudgePage {
// 科目三新增读取表数据
if (this.examSubject == '3') {
await this.initMapPoint()
await this.initMapPointItem()
this.mapPointArr = await InitMapPoint()
this.mapPointItemArr = await InitMapPointItem()
//定时上传考试里程
// let mileageTimer = setInterval(()=>{
// this.uploadMileage()
@ -254,7 +247,6 @@ struct JudgePage {
// 查询考车信息
async initCar() {
// const result = await getSyncData('ES_CARINFO')
const result = await GetSyncData<ES_CARINFOType>("ES_CARINFO")
const carInfo = result[0] || {};
this.carName = decodeURI(carInfo.carclass!)
@ -414,7 +406,6 @@ struct JudgePage {
systemParm.txt2 = systemParm.TXT2!;
systemParm.txt3 = systemParm.TXT3!;
}
// const { no1, no2, no3, } = systemParm;
const txt1 = decodeURI(systemParm.txt1 || "")
const txt2 = decodeURI(systemParm.txt2 || "")
@ -622,40 +613,6 @@ struct JudgePage {
}
// 初始化mapPoint表
async initMapPoint() {
const pointParams: MA_MAP_POINTType[] = await GetSyncData<MA_MAP_POINTType>('MA_MAP_POINT')
pointParams.forEach(item => {
this.mapPointArr.push({
point_no: Number(item.point_no),
gps_e: Number(item.gps_e),
gps_n: Number(item.gps_n),
point_no_f: Number(item.point_no_f),
point_type: Number(item.point_type),
road_code: item.road_code!,
gps_e_Location: Number(item.gps_e_location),
gps_n_Location: Number(item.gps_n_location),
f_gps_e: Number(item.f_gps_e),
f_gps_n: Number(item.f_gps_n),
passed: Number(item.passed)
})
})
}
// 初始化mapPointItem表
async initMapPointItem() {
const pointItemPoints: MA_MAP_POINT_ITEMType[] = await GetSyncData<MA_MAP_POINT_ITEMType>('MA_MAP_POINT_ITEM');
pointItemPoints.forEach(item => {
this.mapPointItemArr.push({
point_no: Number(item.point_no),
itemno: Number(item.itemno),
itemno1: Number(item.itemno1),
subname: item.subname!
})
})
}
// 初始化本地systemparam表、markrule表
async initTrajectoryParam(trajectoryPath: string) {
const isTrajectoryOpen = JudgeConfig.isTrajectoryOpen
@ -695,375 +652,84 @@ struct JudgePage {
}
}
// 信号区域
@Builder
logoExpansionBuilder() {
Image($rawfile(this.isDwztRight ? 'judge/xh_green.png' : 'judge/xh_red.png')).width(50).margin({
left: 10
})
}
// 当前项目
@Builder
backAreaBuilder() {
Text(`当前项目:${this.xmmcStr || '无'} `).fontColor('#E5CCA1').fontSize(34)
}
build() {
Column() {
// 顶部
Row() {
Row() {
Image($rawfile('judge/signal_logoS.png')).width(120)
Text(this.time).fontColor('#CCB48F').fontSize(34).padding({ left: 10, right: 5 })
Image($rawfile(this.isDwztRight ? 'judge/xh_green.png' : 'judge/xh_red.png')).width(50)
}.padding({ left: 20 })
Row() {
Text(`当前项目:${this.xmmcStr || '无'} `).fontColor('#E5CCA1').fontSize(34)
}
}
.width('100%')
.height('96')
.backgroundColor('#001A33')
.padding({ left: 15, right: 15 })
.justifyContent(FlexAlign.SpaceBetween)
.alignItems(VerticalAlign.Center)
HeaderComponent({
logoExpansionBuilder: this.logoExpansionBuilder,
customizeReturnArea: true,
backAreaBuilder: this.backAreaBuilder
})
Row() {
Row() {
Column() {
Row() {
Column() {
Row() {
Text('考生姓名:').fontColor('#E5CCA1').fontSize(this.FONTSIZE)
Text(this.name).fontColor('#FFF').fontSize(this.FONTSIZE)
}.margin({ bottom: 10 })
Row() {
Text('开始时间:').fontColor('#E5CCA1').fontSize(this.FONTSIZE)
Text(this.startTime).fontColor('#FFF').fontSize(this.FONTSIZE)
}.margin({ bottom: 10 })
if (this.examSubject == "3") {
Row() {
Text('考试路线:').fontColor('#E5CCA1').fontSize(this.FONTSIZE)
Text(`线路${this.wayno || 3}`).fontColor('#FFAD33').fontSize(this.FONTSIZE)
}
}
}.width('45%').alignItems(HorizontalAlign.Start)
Column() {
Row() {
Text('身份证号:').fontColor('#E5CCA1').fontSize(this.FONTSIZE)
Text(this.idCard).fontColor('#FFF').fontSize(this.FONTSIZE)
}.margin({ bottom: 10 })
Row() {
Text('考试用时:').fontColor('#E5CCA1').fontSize(this.FONTSIZE)
Text(FormatTimeFlexible(this.examTime)).fontColor('#FFF').fontSize(this.FONTSIZE)
}.margin({ bottom: 10 })
if (this.examSubject == "3") {
Row() {
if (Reflect.get(this.judgeConfigObj, '375') == '0') {
Text(`应行驶:${this.examMileage}m`)
.fontColor('#E5CCA1')
.fontSize(this.FONTSIZE)
.padding({ right: 20 })
}
Text(`已行驶:${this.jl}m`).fontColor('#FFAD33').fontSize(this.FONTSIZE)
}
}
}.alignItems(HorizontalAlign.Start)
}.width('100%')
Column() {
Row() {
Text(this.carztStr).fontColor('#FFA500').fontSize(this.FONTSIZE)
if (Reflect.get(this.judgeConfigObj, '342') == '0') {
Text(`${this.dw}挡`).fontColor('#FFA500').fontSize(this.FONTSIZE).padding({ left: 15, right: 15 })
Text(`${this.sd}km/h`).fontColor('#FFA500').fontSize(this.FONTSIZE)
}
}.height(40)
Row() {
Flex({ direction: FlexDirection.Column }) {
if (this.kfArr.length) {
List({ scroller: this.kfArrScroller }) {
ForEach(this.kfArr, (item: MarkRule) => {
ListItem() {
Column() {
Row() {
Text(item.xmmcStr).fontSize(this.BIGFONTSIZE).fontColor('#FFF')
Text(`${item.score}分`).fontSize(this.BIGFONTSIZE).fontColor('#FFF')
}
.width('100%')
.backgroundColor('#38260B')
.justifyContent(FlexAlign.SpaceBetween)
.padding({
top: 12,
bottom: 12,
left: 8,
right: 5
})
Text(item.desc + `(${item.markcatalog})`)
.fontSize(this.BIGFONTSIZE)
.fontColor('#E5CBA1')
.margin({
top: 10,
bottom: 8,
left: 5,
right: 5
})
}.margin({ top: 15 }).alignItems(HorizontalAlign.Start)
}.margin({ bottom: 25 })
})
}
.padding({
left: 15,
right: 15,
top: 30,
bottom: 5
})
} else {
Column() {
Row() {
Text('暂无扣分项').fontSize(this.BIGFONTSIZE).fontColor('#FFF')
}
.width('100%')
.backgroundColor('#38260B')
.justifyContent(FlexAlign.SpaceBetween)
.padding({
top: 12,
bottom: 12,
left: 8,
right: 3
})
}.margin({ top: 35 }).padding({ left: 20, right: 20 }).alignItems(HorizontalAlign.Start)
}
}
.backgroundImage($rawfile('judge/score_bg.png'), ImageRepeat.NoRepeat)
.backgroundImageSize({ width: '100%', height: '100%' })
.width(514)
.height(618)
.padding({
top: 18,
bottom: 15,
left: 13,
right: 14
})
//科目二
if (this.examSubject == "2") {
Flex({ wrap: FlexWrap.Wrap, direction: FlexDirection.Row, justifyContent: FlexAlign.SpaceBetween }) {
List({}) {
ForEach(CutArray(this.projects, 2), (item: [ProjectInfo, ProjectInfo]) => {
ListItem() {
Row() {
Row() {
//#FF7566 #00FFD5 #E6DECF
// Text(this.projectsObj[item[0].projectCode])
Text(item[0].abbreviation)
.fontSize(item[0].abbreviation!.length > 5 ? 28 : 32)
.fontColor(this.getProjectColor(item[0]))
}
.backgroundImage($rawfile('judge/project_item.png'), ImageRepeat.NoRepeat)
.backgroundImageSize({ width: '100%', height: '100%' })
.width('48.5%')
.height(115)
.margin({ bottom: 5 })
.justifyContent(FlexAlign.Center)
if (item[1]) {
Row() {
//#FF7566 #00FFD5 #E6DECF
Text(item[1].abbreviation)
.fontSize(item[1].abbreviation.length > 5 ? 28 : 32)
.fontColor(this.getProjectColor(item[1]))
}
.backgroundImage($rawfile('judge/project_item.png'), ImageRepeat.NoRepeat)
.backgroundImageSize({ width: '100%', height: '100%' })
.width('48.5%')
.height(115)
.margin({ left: 5, bottom: 5 })
.justifyContent(FlexAlign.Center)
}
}
}
});
}
}
.backgroundImage($rawfile('judge/project_bg.png'), ImageRepeat.NoRepeat)
.backgroundImageSize({ width: '100%', height: '100%' })
.width('57%')
.height('100%')
.padding(30)
.margin({ right: 10 })
}
//科目三
if (this.examSubject == '3') {
Column() {
Flex({
wrap: FlexWrap.Wrap,
direction: FlexDirection.Row,
justifyContent: FlexAlign.SpaceBetween
}) {
List({}) {
ForEach(this.projects, (project: ProjectInfo) => {
ListItem() {
Text(project.name) {
}
.fontColor(this.getProjectColor(project))
.margin({ bottom: 2 })
.fontSize(24)
}.margin({ bottom: 2 })
})
}.lanes(2).margin({ left: 25 })
}
.width('100%')
.height('57%')
.backgroundImage($rawfile('judge/project_km3_bg.png'), ImageRepeat.NoRepeat)
.backgroundImageSize({ width: '100%', height: '100%' })
.padding(30)
.margin({ right: 5 })
if (this.projects.length) {
Flex({
wrap: FlexWrap.Wrap,
direction: FlexDirection.Row,
justifyContent: FlexAlign.SpaceAround
}) {
List() {
ForEach(this.artSubject3Projects, (item: string, index) => {
ListItem() {
}
.backgroundImage(
$rawfile(
`judge/km3/${this.getIsExitManualProject(index) ? (this.getIsEndManualProject(index)) :
(item + '_gray')}.png`
), ImageRepeat.NoRepeat)
.backgroundImageSize({ width: '100%', height: '100%' })
.width(174)
.height(118 * 0.95)
.margin({ bottom: 8 })
.onClick(() => {
// this.vocObj.playAudio({
// type: 1,
// name: 'button_media.wav'
// })
this.setManualProjectFn(index)
})
})
}.lanes(3).margin({ left: 5, top: 12 })
}
}
}
.backgroundImage($rawfile('judge/project_bg.png'), ImageRepeat.NoRepeat)
.backgroundImageSize({ width: '100%', height: '100%' })
.width(660)
.height(640)
.padding(44)
.margin({ right: 10 })
}
}.margin({ top: 15 }).height('80%').justifyContent(FlexAlign.SpaceBetween)
}.width('100%').height('100%').alignItems(HorizontalAlign.Start).margin({ top: 10 })
// 考生信息展示区域
MessageComponent({
name: this.name,
idCard: this.idCard,
startTime: this.startTime,
examSubject: this.examSubject,
examMileage: this.examMileage,
jl: this.jl,
wayno: this.wayno,
judgeConfigObj: this.judgeConfigObj,
})
// 扣分列表和评判列表
JudgeAndProjectComponent({
carztStr: this.carztStr,
judgeConfigObj: this.judgeConfigObj,
dw: this.dw,
sd: this.sd,
kfArr: this.kfArr,
examSubject: this.examSubject,
projects: this.projects,
artSubject3Projects: this.artSubject3Projects,
artSubject3ProjectsCodesArr: this.artSubject3ProjectsCodesArr,
projectsObj: this.projectsObj,
isManualProjectIn: this.isManualProjectIn,
isProjectIn: this.isProjectIn,
jl: this.jl,
examMileage: this.examMileage,
isRequiredProjectsEnd: this.isRequiredProjectsEnd,
lane: this.lane,
examClick: (index: number) => {
this.setManualProjectFn(index)
}
})
}.height('100%').alignItems(HorizontalAlign.Start)
}.width('75%').height('100%')
Column() {
Column() {
Row() {
Text(this.totalScore <= 0 ? '0' : this.totalScore + '').fontColor('#FFEECC').fontSize(55)
Text('分').fontColor('#FFEECC').fontSize(30).padding({ top: 5 })
}
.width(334)
.height(120)
.justifyContent(FlexAlign.Center)
.alignItems(VerticalAlign.Center)
.border({ width: 5, color: '#4D4136', radius: 30 })
.onClick(() => {
// this.vocObj.playAudio({
// type: 1,
// name: 'button_media.wav'
// })
this.signalTrajectoryDialogController.open()
})
Row() {
Image(this.kszp).width('85%').height('85%')
}
.width(226)
.height(312)
.backgroundImage($rawfile('judge/photo_bg.png'), ImageRepeat.NoRepeat)
.backgroundImageSize({ width: '100%', height: '100%' })
.justifyContent(FlexAlign.Center)
.alignItems(VerticalAlign.Center)
.margin({ top: 30, bottom: 15 })
// 操作区域,分数显示区域
OperatingAreaComponent({
totalScore: this.totalScore,
kszp: this.kszp,
examSubject: this.examSubject,
singlePlay: this.singlePlay,
judgeConfigObj: this.judgeConfigObj,
signalViewingClick: () => {
this.signalTrajectoryDialogController.open()
},
artificialEvaluationClick: () => {
this.isDeductedPopShow = true
},
endTheExamClick: () => {
this.endExamDialogController.open()
}
Column() {
if (this.getIsManualKf()) {
Row() {
Row() {
}
.width(60)
.height(60)
.backgroundImage($rawfile('judge/manual_judge.png'), ImageRepeat.NoRepeat)
.backgroundImageSize({ width: '100%', height: '100%' })
Text('人工评判').fontColor('#FFF').fontSize(32).padding({ right: 12 })
}
.width(334)
.height(110)
.justifyContent(FlexAlign.Center)
.alignItems(VerticalAlign.Center)
.backgroundImage($rawfile('judge/button_nor.png'), ImageRepeat.NoRepeat)
.backgroundImageSize({ width: '100%', height: '100%' })
.margin({ bottom: 10 })
.onClick(() => {
// this.vocObj.playAudio({
// type: 1,
// name: 'button_media.wav'
// })
this.isDeductedPopShow = true
})
}
Row() {
Row() {
}
.width(60)
.height(60)
.backgroundImage($rawfile('judge/phone.png'), ImageRepeat.NoRepeat)
.backgroundImageSize({ width: '100%', height: '100%' })
Text('呼叫请求').fontColor('#FFF').fontSize(32).padding({ right: 12 })
}
.width(334)
.height(110)
.justifyContent(FlexAlign.Center)
.alignItems(VerticalAlign.Center)
.backgroundImage($rawfile('judge/button_nor.png'), ImageRepeat.NoRepeat)
.backgroundImageSize({ width: '100%', height: '100%' })
.margin({ bottom: 10 })
Row() {
}
.width(334)
.height(100)
.backgroundImage($rawfile('judge/anniu_nor.png'), ImageRepeat.NoRepeat)
.backgroundImageSize({ width: '100%', height: '100%' })
.onClick(() => {
if (Reflect.get(this.judgeConfigObj, '353') == '0') {
this.endExamDialogController.open()
} else {
Prompt.showToast({
message: '车上不允许手动结束考试!',
duration: 4000
});
}
})
}.margin({ bottom: 30 })
}
.width('25%')
.height('100%')
.justifyContent(FlexAlign.SpaceBetween)
.alignItems(HorizontalAlign.Center)
.margin({ bottom: 20 })
})
}
.height('90%')
.justifyContent(FlexAlign.Start)
@ -1152,43 +818,23 @@ struct JudgePage {
},
})
}
if (this.disConnectErrorOpen) {
}
}
.height('100%').backgroundColor('#000').justifyContent(FlexAlign.Start)
}
getProjectColor(project: ProjectInfo) {
const type = project.type;
switch (type) {
case '1':
return '#E6DECF';
case '2':
return '#FFAD33';
case '3':
return '#ff109d0a';
case '4':
return '#FF7566';
default:
return '#E6DECF';
}
}
//人工项目操作
async setManualProjectFn(index: number) {
const isManualProjectIn = this.isManualProjectIn;
const getIsExitManualProject = this.getIsExitManualProject;
const artSubject3ProjectsCodesArr = this.artSubject3ProjectsCodesArr;
const projectsObj = this.projectsObj;
const projectCode = artSubject3ProjectsCodesArr[index]
let sideParkingStatus = GetIsExitManualProject(index, this.judgeConfigObj, this.artSubject3ProjectsCodesArr, this.projectsObj, this.carztStr, this.isManualProjectIn, this.isProjectIn, this.jl, this.examMileage, this.isRequiredProjectsEnd, this.lane)
if (index === 5) {
dConsole.info(JudgeTag, 'surenjun 靠边停车状态=> ', getIsExitManualProject(index))
dConsole.info(JudgeTag, 'surenjun 靠边停车状态=> ', sideParkingStatus)
}
const currentProject: ProjectInfo = Reflect.get(projectsObj, projectCode)
if (getIsExitManualProject(index)) {
if (sideParkingStatus) {
// 正在进行的项目 取消项目
if (isManualProjectIn && currentProject.type == '2') {
//判断人工是否能取消项目 && 当前项目有扣分的不能取消
@ -1230,184 +876,5 @@ struct JudgePage {
}
}
}
// 获取是否能人工进项目
getIsExitManualProject = (index: number) => {
const judgeConfigObj = this.judgeConfigObj;
const artSubject3ProjectsCodesArr = this.artSubject3ProjectsCodesArr;
const projectsObj = this.projectsObj;
const carztStr = this.carztStr;
const isManualProjectIn = this.isManualProjectIn;
const isProjectIn = this.isProjectIn;
const getProjectIsInRoad = this.getProjectIsInRoad;
const projectCode = artSubject3ProjectsCodesArr[index];
const currentProject: ProjectInfo = Reflect.get(projectsObj, projectCode)
if (currentProject === undefined) {
return false
}
const projectType = currentProject.type;
//不允许人工触发的项目列表,以","分隔
const unExitManualProjects: string[] = Reflect.get(this.judgeConfigObj, '332').split(',') || [];
//直线行驶中不进其他考试项目(0-否 1-是)
const param348: string = Reflect.get(this.judgeConfigObj, '348') || '0',
//里程不够允许手工点靠边停车0-否 1-是)
param387: string = Reflect.get(this.judgeConfigObj, '387') || '0',
//里程不够不报靠边停车0-否+1-是+2-必考项目未完成且里程不够不报项目)
param319: string = Reflect.get(this.judgeConfigObj, '319') || '0',
//人工项目是否能取消 1:可取消;
param340: string = Reflect.get(this.judgeConfigObj, '340') || '0',
//307参数里设置的项目项目已经做过后续不能人工触发
param307: string[] = (Reflect.get(this.judgeConfigObj, '307') || '').split(',');
//非行驶状态(没有速度),人工项目不能触发(按钮灰色)
if (carztStr === '停车') {
return false
}
//车上是否能进行人工操作(0-能1-不能人工评判2-不能人工进项目3-都不能)
if (Reflect.get(this.judgeConfigObj, '342') === '3' || Reflect.get(this.judgeConfigObj, '342') === '2') {
return false
}
//不允许人工触发的项目列表
if (unExitManualProjects.includes(artSubject3ProjectsCodesArr[index])) {
return false
}
//项目进行中不能人工触发
if (isProjectIn) {
if (param340 == '1') {
if (isManualProjectIn && (currentProject.type == '2')) {
return true
} else {
return false
}
}
return false
}
//项目路段信息判断
if (!getProjectIsInRoad(projectCode + '')) {
return false
}
const project_9: ProjectInfo = Reflect.get(projectsObj, '9')
// 直线行驶中不进其他考试项目(0-否 1-是)
if (param348 == '0' && project_9.type == '2') {
return index === 0 ? true : false
}
//项目已经做过,后续不能人工触发
if (param307.includes(projectCode) && (projectType == '3' || projectType == '4')) {
return false
}
//319不为0或者387不为1里程不够时靠边停车项目不能触发
if ((param387 != '1' || param319 != '0') && index === 5) {
const examMileage = this.examMileage
const isRequiredProjectsEnd = this.isRequiredProjectsEnd
const jl = this.jl
//里程是否达标 && 必考项目是否全完成
return jl >= Number(examMileage) && isRequiredProjectsEnd
}
return true
}
// 判断项目是否在当前路段号
getProjectIsInRoad = (projectCode: string,) => {
const judgeConfigObj = this.judgeConfigObj;
const lane = this.lane;
const road = lane.road;
const num = lane.num;
const count = lane.count;
const param_3: string[] = (Reflect.get(this.judgeConfigObj, '514')?.split(',') || []);
const param_4: string[] = (Reflect.get(this.judgeConfigObj, '515')?.split(',') || []);
const param_10: string[] = (Reflect.get(this.judgeConfigObj, '516')?.split(',') || []);
const param_11: string[] = (Reflect.get(this.judgeConfigObj, '517')?.split(',') || []);
const param_9: string[] = (Reflect.get(this.judgeConfigObj, '518')?.split(',') || []);
const param_12: string[] = (Reflect.get(this.judgeConfigObj, '519')?.split(',') || []);
const projectRoads: ProjectRoads = {
//直线行驶
param_3,
//变更车道
param_4,
//超车
param_10,
//靠边停车
param_11,
//会车
param_9,
//掉头
param_12,
};
//未测绘得道路上或者不在差分状态
if (road === '') {
return false
}
const currentProjectRoad: string[] = Reflect.get(projectRoads, `param_${projectCode}`)
if (currentProjectRoad.length == 0) {
return true
}
//设置了514-519参数只能在设置的路段触发对应项目
if (currentProjectRoad.includes(road)) {
//如果525为1则514-519设置的路段不能触发对应项目
if (Reflect.get(this.judgeConfigObj, '525') == '1') {
return false
}
} else {
return false
}
//405参数为2是如果在最左侧车道超车项目不能触发;
if (projectCode == '10' &&
Reflect.get(this.judgeConfigObj, '405') == '2' &&
(num === count) &&
num > 0
) {
return false
}
// 车道总数少于2条超车和变道不能触发
if (projectCode == '10' || projectCode == '4') {
if (count < 2) {
return false
}
}
return true
}
// 获取人工项目是否已做
getIsEndManualProject = (index: number) => {
const projectName = this.artSubject3Projects[index];
const projectCode = this.artSubject3ProjectsCodesArr[index];
const currentProject: ProjectInfo = Reflect.get(this.projectsObj, projectCode)
const type = currentProject.type
if (type == '2') {
return projectName
}
return (type == '3' || type == '4') ? `${projectName}_red` : `${projectName}_green`;
}
// 获取是否能进行人工评判
getIsManualKf = () => {
if (this.examSubject == '3') {
//杭州训练模式不允许人工评判
if (this.singlePlay && Reflect.get(this.judgeConfigObj, '211') == 'zjhz') {
return false
}
if (Reflect.get(this.judgeConfigObj, '342') == '0') {
return true
}
return false
} else {
return false
}
}
}

View File

@ -0,0 +1,254 @@
import { JudgeTag } from '../../config';
import { DefaultJudgeConfigObj, LANE, MarkRule, ProjectInfo, ProjectInfos } from '../../model';
import { CutArray } from '../../utils/Common';
import { dConsole } from '../../utils/LogWorker';
import { GetIsEndManualProject, GetIsExitManualProject } from './utils';
@Component
export default struct JudgeAndProjectComponent {
public kfArrScroller: Scroller = new Scroller()
@Prop carztStr: string
@Prop judgeConfigObj: DefaultJudgeConfigObj
@Prop dw: string
@Prop sd: string
@Prop @Watch("scrollLengthChange") kfArr: MarkRule[]
@Prop examSubject: string
@Prop projects: ProjectInfo[]
@Prop artSubject3Projects: string[]
@Prop artSubject3ProjectsCodesArr: string[]
@Prop projectsObj: ProjectInfos
@Prop isManualProjectIn: boolean
@Prop isProjectIn: boolean
@Prop jl: number
@Prop examMileage: string
@Prop isRequiredProjectsEnd: boolean
@Prop lane: LANE
examClick: (index: number) => void = (index: number) => {
}
scrollLengthChange(data: MarkRule[]) {
dConsole.log(JudgeTag, "容器滚动", data.length)
if (data.length > 4) {
this.kfArrScroller.scrollTo({
yOffset: 999999, xOffset: 0
})
}
}
getProjectColor(project: ProjectInfo) {
const type = project.type;
switch (type) {
case '1':
return '#E6DECF';
case '2':
return '#FFAD33';
case '3':
return '#ff109d0a';
case '4':
return '#FF7566';
default:
return '#E6DECF';
}
}
build() {
Column() {
Row() {
Text(this.carztStr).fontColor('#FFA500').fontSize(30)
if (Reflect.get(this.judgeConfigObj, '342') == '0') {
Text(`${this.dw}挡`).fontColor('#FFA500').fontSize(30).padding({ left: 15, right: 15 })
Text(`${this.sd}km/h`).fontColor('#FFA500').fontSize(30)
}
}.height(40)
Row() {
Flex({ direction: FlexDirection.Column }) {
if (this.kfArr.length) {
List({ scroller: this.kfArrScroller }) {
ForEach(this.kfArr, (item: MarkRule) => {
ListItem() {
Column() {
Row() {
Text(item.xmmcStr).fontSize(32).fontColor('#FFF')
Text(`${item.score}分`).fontSize(32).fontColor('#FFF')
}
.width('100%')
.backgroundColor('#38260B')
.justifyContent(FlexAlign.SpaceBetween)
.padding({
top: 12,
bottom: 12,
left: 8,
right: 5
})
Text(item.desc + `(${item.markcatalog})`)
.fontSize(32)
.fontColor('#E5CBA1')
.margin({
top: 10,
bottom: 8,
left: 5,
right: 5
})
}.margin({ top: 15 }).alignItems(HorizontalAlign.Start)
}.margin({ bottom: 25 })
})
}
.padding({
left: 15,
right: 15,
top: 30,
bottom: 5
})
} else {
Column() {
Row() {
Text('暂无扣分项').fontSize(32).fontColor('#FFF')
}
.width('100%')
.backgroundColor('#38260B')
.justifyContent(FlexAlign.SpaceBetween)
.padding({
top: 12,
bottom: 12,
left: 8,
right: 3
})
}.margin({ top: 35 }).padding({ left: 20, right: 20 }).alignItems(HorizontalAlign.Start)
}
}
.backgroundImage($rawfile('judge/score_bg.png'), ImageRepeat.NoRepeat)
.backgroundImageSize({ width: '100%', height: '100%' })
.width(514)
.height(618)
.padding({
top: 18,
bottom: 15,
left: 13,
right: 14
})
//科目二
if (this.examSubject == "2") {
Flex({ wrap: FlexWrap.Wrap, direction: FlexDirection.Row, justifyContent: FlexAlign.SpaceBetween }) {
List({}) {
ForEach(CutArray(this.projects, 2), (item: [ProjectInfo, ProjectInfo]) => {
ListItem() {
Row() {
Row() {
//#FF7566 #00FFD5 #E6DECF
// Text(this.projectsObj[item[0].projectCode])
Text(item[0].abbreviation)
.fontSize(item[0].abbreviation!.length > 5 ? 28 : 32)
.fontColor(this.getProjectColor(item[0]))
}
.backgroundImage($rawfile('judge/project_item.png'), ImageRepeat.NoRepeat)
.backgroundImageSize({ width: '100%', height: '100%' })
.width('48.5%')
.height(115)
.margin({ bottom: 5 })
.justifyContent(FlexAlign.Center)
if (item[1]) {
Row() {
//#FF7566 #00FFD5 #E6DECF
Text(item[1].abbreviation)
.fontSize(item[1].abbreviation.length > 5 ? 28 : 32)
.fontColor(this.getProjectColor(item[1]))
}
.backgroundImage($rawfile('judge/project_item.png'), ImageRepeat.NoRepeat)
.backgroundImageSize({ width: '100%', height: '100%' })
.width('48.5%')
.height(115)
.margin({ left: 5, bottom: 5 })
.justifyContent(FlexAlign.Center)
}
}
}
});
}
}
.backgroundImage($rawfile('judge/project_bg.png'), ImageRepeat.NoRepeat)
.backgroundImageSize({ width: '100%', height: '100%' })
.width('57%')
.height('100%')
.padding(30)
.margin({ right: 10 })
}
//科目三
if (this.examSubject == '3') {
Column() {
Flex({
wrap: FlexWrap.Wrap,
direction: FlexDirection.Row,
justifyContent: FlexAlign.SpaceBetween
}) {
List({}) {
ForEach(this.projects, (project: ProjectInfo) => {
ListItem() {
Text(project.name) {
}
.fontColor(this.getProjectColor(project))
.margin({ bottom: 2 })
.fontSize(24)
}.margin({ bottom: 2 })
})
}.lanes(2).margin({ left: 25 })
}
.width('100%')
.height('57%')
.backgroundImage($rawfile('judge/project_km3_bg.png'), ImageRepeat.NoRepeat)
.backgroundImageSize({ width: '100%', height: '100%' })
.padding(30)
.margin({ right: 5 })
if (this.projects.length) {
Flex({
wrap: FlexWrap.Wrap,
direction: FlexDirection.Row,
justifyContent: FlexAlign.SpaceAround
}) {
List() {
ForEach(this.artSubject3Projects, (item: string, index) => {
ListItem() {
}
// $rawfile(
// `judge/km3/${this.getIsExitManualProject(index) ? (this.getIsEndManualProject(index)) :
// (item + '_gray')}.png`
// )
.backgroundImage(
$rawfile(
`judge/km3/${GetIsExitManualProject(index, this.judgeConfigObj, this.artSubject3ProjectsCodesArr, this.projectsObj, this.carztStr, this.isManualProjectIn, this.isProjectIn, this.jl, this.examMileage, this.isRequiredProjectsEnd, this.lane) ? (GetIsEndManualProject(index, this.artSubject3Projects, this.artSubject3ProjectsCodesArr, this.projectsObj)) :
(item + '_gray')}.png`
), ImageRepeat.NoRepeat)
.backgroundImageSize({ width: '100%', height: '100%' })
.width(174)
.height(118 * 0.95)
.margin({ bottom: 8 })
.onClick(() => {
// this.vocObj.playAudio({
// type: 1,
// name: 'button_media.wav'
// })
this.examClick(index)
// this.setManualProjectFn(index)
})
})
}.lanes(3).margin({ left: 5, top: 12 })
}
}
}
.backgroundImage($rawfile('judge/project_bg.png'), ImageRepeat.NoRepeat)
.backgroundImageSize({ width: '100%', height: '100%' })
.width(660)
.height(640)
.padding(44)
.margin({ right: 10 })
}
}.margin({ top: 15 }).height('80%').justifyContent(FlexAlign.SpaceBetween)
}.width('100%').height('100%').alignItems(HorizontalAlign.Start).margin({ top: 10 })
}
}

View File

@ -0,0 +1,8 @@
@CustomDialog
export default struct ManualConfirmationOfSubjectThreeProjectsDialog {
private controller?: CustomDialogController
build() {
}
}

View File

@ -0,0 +1,71 @@
import { DefaultJudgeConfigObj } from '../../model'
import { FormatTimeFlexible } from '../../utils/Common'
@Component
export default struct MessageComponent {
@Prop name: string
@Prop startTime: string
@Prop idCard: string
@State examTime: number = 0
@Prop examSubject: string
@Prop examMileage: string
@Prop jl: number
@Prop wayno: number
@Prop judgeConfigObj: DefaultJudgeConfigObj
aboutToAppear(): void {
setInterval(async () => {
this.examTime += 1;
}, 1000);
}
build() {
Row() {
Column() {
Row() {
Text('考生姓名:').fontColor('#E5CCA1').fontSize(30)
Text(this.name).fontColor('#FFF').fontSize(30)
}.margin({ bottom: 10 })
Row() {
Text('开始时间:').fontColor('#E5CCA1').fontSize(30)
Text(this.startTime).fontColor('#FFF').fontSize(30)
}.margin({ bottom: 10 })
if (this.examSubject == "3") {
Row() {
Text('考试路线:').fontColor('#E5CCA1').fontSize(30)
Text(`线路${this.wayno || 3}`).fontColor('#FFAD33').fontSize(30)
}
}
}.width('45%').alignItems(HorizontalAlign.Start)
Column() {
Row() {
Text('身份证号:').fontColor('#E5CCA1').fontSize(30)
Text(this.idCard).fontColor('#FFF').fontSize(30)
}.margin({ bottom: 10 })
Row() {
Text('考试用时:').fontColor('#E5CCA1').fontSize(30)
Text(FormatTimeFlexible(this.examTime)).fontColor('#FFF').fontSize(30)
}.margin({ bottom: 10 })
if (this.examSubject == "3") {
Row() {
if (Reflect.get(this.judgeConfigObj, '375') == '0') {
Text(`应行驶:${this.examMileage}m`)
.fontColor('#E5CCA1')
.fontSize(30)
.padding({ right: 20 })
}
Text(`已行驶:${this.jl}m`).fontColor('#FFAD33').fontSize(30)
}
}
}.alignItems(HorizontalAlign.Start)
}.width('100%')
}
}

View File

@ -0,0 +1,134 @@
import { DefaultJudgeConfigObj } from '../../model'
import Prompt from '@system.prompt'
@Component
export default struct OperatingAreaComponent {
@Prop totalScore: number
@Prop kszp: string
@Prop examSubject: string
@Prop singlePlay: boolean
@Prop judgeConfigObj: DefaultJudgeConfigObj
// 信号查看
signalViewingClick: () => void = () => {
}
// 人工评判
artificialEvaluationClick: () => void = () => {
}
// 结束考试
endTheExamClick: () => void = () => {
}
// 获取是否能进行人工评判
getIsManualKf = () => {
if (this.examSubject == '3') {
//杭州训练模式不允许人工评判
if (this.singlePlay && Reflect.get(this.judgeConfigObj, '211') == 'zjhz') {
return false
}
if (Reflect.get(this.judgeConfigObj, '342') == '0') {
return true
}
return false
} else {
return false
}
}
build() {
Column() {
Column() {
Row() {
Text(this.totalScore <= 0 ? '0' : this.totalScore + '').fontColor('#FFEECC').fontSize(55)
Text('分').fontColor('#FFEECC').fontSize(30).padding({ top: 5 })
}
.width(334)
.height(120)
.justifyContent(FlexAlign.Center)
.alignItems(VerticalAlign.Center)
.border({ width: 5, color: '#4D4136', radius: 30 })
.onClick(() => {
// this.signalTrajectoryDialogController.open()
this.signalViewingClick()
})
Row() {
Image(this.kszp).width('85%').height('85%')
}
.width(226)
.height(312)
.backgroundImage($rawfile('judge/photo_bg.png'), ImageRepeat.NoRepeat)
.backgroundImageSize({ width: '100%', height: '100%' })
.justifyContent(FlexAlign.Center)
.alignItems(VerticalAlign.Center)
.margin({ top: 30, bottom: 15 })
}
Column() {
if (this.getIsManualKf()) {
Row() {
Row() {
}
.width(60)
.height(60)
.backgroundImage($rawfile('judge/manual_judge.png'), ImageRepeat.NoRepeat)
.backgroundImageSize({ width: '100%', height: '100%' })
Text('人工评判').fontColor('#FFF').fontSize(32).padding({ right: 12 })
}
.width(334)
.height(110)
.justifyContent(FlexAlign.Center)
.alignItems(VerticalAlign.Center)
.backgroundImage($rawfile('judge/button_nor.png'), ImageRepeat.NoRepeat)
.backgroundImageSize({ width: '100%', height: '100%' })
.margin({ bottom: 10 })
.onClick(() => {
// this.isDeductedPopShow = true
this.artificialEvaluationClick()
})
}
Row() {
Row() {
}
.width(60)
.height(60)
.backgroundImage($rawfile('judge/phone.png'), ImageRepeat.NoRepeat)
.backgroundImageSize({ width: '100%', height: '100%' })
Text('呼叫请求').fontColor('#FFF').fontSize(32).padding({ right: 12 })
}
.width(334)
.height(110)
.justifyContent(FlexAlign.Center)
.alignItems(VerticalAlign.Center)
.backgroundImage($rawfile('judge/button_nor.png'), ImageRepeat.NoRepeat)
.backgroundImageSize({ width: '100%', height: '100%' })
.margin({ bottom: 10 })
Row() {
}
.width(334)
.height(100)
.backgroundImage($rawfile('judge/anniu_nor.png'), ImageRepeat.NoRepeat)
.backgroundImageSize({ width: '100%', height: '100%' })
.onClick(() => {
if (Reflect.get(this.judgeConfigObj, '353') == '0') {
// this.endExamDialogController.open()
this.endTheExamClick()
} else {
Prompt.showToast({
message: '车上不允许手动结束考试!',
duration: 4000
});
}
})
}.margin({ bottom: 30 })
}
.width('25%')
.height('100%')
.justifyContent(FlexAlign.SpaceBetween)
.alignItems(HorizontalAlign.Center)
.margin({ bottom: 20 })
}
}

View File

@ -0,0 +1,8 @@
@CustomDialog
export default struct SubjectThreeManualDeductionOfPointsDialog {
private controller?: CustomDialogController
build() {
}
}

View File

@ -0,0 +1,40 @@
import { MA_MAP_POINT_ITEMType, MA_MAP_POINTType, MAPITEMPOINTITEM, MAPPOINT } from '../../model';
import { GetSyncData } from '../../utils/table/Operation';
/**
* 初始化mapPoint表
* @returns {Promise<MAPPOINT[]>} 返回mapPoint表数据
*/
export const InitMapPoint = async (): Promise<MAPPOINT[]> => {
const pointParams = await GetSyncData<MA_MAP_POINTType>('MA_MAP_POINT');
if (pointParams.length === 0) return [];
return pointParams.map(item => ({
point_no: Number(item.point_no),
gps_e: Number(item.gps_e),
gps_n: Number(item.gps_n),
point_no_f: Number(item.point_no_f),
point_type: Number(item.point_type),
road_code: item.road_code || "",
gps_e_Location: Number(item.gps_e_location),
gps_n_Location: Number(item.gps_n_location),
f_gps_e: Number(item.f_gps_e),
f_gps_n: Number(item.f_gps_n),
passed: Number(item.passed),
} as MAPPOINT));
};
/**
* 初始化mapPointItem表
* @returns {Promise<MAPITEMPOINTITEM[]>} 返回mapPointItem表数据
*/
export const InitMapPointItem = async (): Promise<MAPITEMPOINTITEM[]> => {
const pointItemPoints: MA_MAP_POINT_ITEMType[] = await GetSyncData<MA_MAP_POINT_ITEMType>('MA_MAP_POINT_ITEM');
if (pointItemPoints.length === 0) return [];
return pointItemPoints.map(item => ({
point_no: Number(item.point_no),
itemno: Number(item.itemno),
itemno1: Number(item.itemno1),
subname: item.subname ?? ""
} as MAPITEMPOINTITEM))
}

View File

@ -1,6 +1,18 @@
import systemTime from '@ohos.systemDateTime';
import { TestRealExam } from '../../mock';
import { CarInfoType, ExtendType, Gps, LANE, PLCType, Radar, Vision } from '../../model';
import {
CarInfoType,
DefaultJudgeConfigObj,
ExtendType,
Gps,
LANE,
PLCType,
ProjectInfo,
ProjectInfos,
ProjectRoads,
Radar,
Vision
} from '../../model';
import { ArrayToByteArray, NumberToByteArray } from '../../utils/Common';
import dayTs from '../../utils/Date';
import { dConsole } from '../../utils/LogWorker';
@ -445,7 +457,9 @@ export function UploadRegulatoryCodeConversion(
// });
}
// 获取plc数据
/**
* 将PLC字符串转换为JSON对象
*/
export const PlcStrToJson = async (plc: string) => {
const plcArr = plc.split(',')
const p = plcArr.map((val, key) => {
@ -456,54 +470,6 @@ export const PlcStrToJson = async (plc: string) => {
}
});
const time = await systemTime.getCurrentTime()
// const sensor: Sensor = {
// //安全带 车门门开关 手刹 脚刹 副刹 离合器 喇叭 示宽灯 近光灯 远光灯
// aqd: p[19],
// mkg: p[14],
// ssc: p[13],
// jsc: p[12],
// fsc: p[18],
// lhq: p[17],
// lb: p[4],
// skd: p[9],
// jgd: p[7],
// ygd: p[8],
// //左方向灯 右方向灯 双跳灯 雾灯 雨刮器 点火1 点火2 发动机转速 档位 车速
// zfxd: p[2],
// yfxd: p[3],
// shtd: p[20],
// wd: p[10],
// ygq: p[11],
// dh1: p[5],
// dh2: p[6],
// fdjzs: p[25],
// dw: p[28],
// cs: p[23],
// // 方向盘
// fxp: Number(plcArr[27].split('_')[0]),
// //累计脉冲 溜车脉冲 超声波左后 超声波右后 超声波右前 超声波左前 座椅 仪表盘 后视镜 倒车镜 光照 雨量
// ljmc: p[24],
// lcmc: 0,
// csbzh: p[32],
// csbyh: p[30],
// csbyq: p[31],
// csbzq: p[29],
// zy: 0,
// tbp: 0,
// hsj: 0,
// dcj: 0,
// gx: 0,
// yl: 0,
// //TODO 数据待替换 油压 闪灯 信号灯
// yy: 0,
// sde: 0,
// xhd: '',
// rmndg: 0,
// wav: 0,
// mndg: ''
// }
const gps2: Gps = TestRealExam.gps2
const radar: Radar = TestRealExam.radar
const vision: Vision = TestRealExam.vision
@ -704,3 +670,165 @@ export function sendRed() {
const arrRedBuffer = ArrayToByteArray(arrRed).buffer
// globalThis.lightLineUdp.send(arrRedBuffer);
}
// 获取是否能人工进项目
export const GetIsExitManualProject = (index: number, judgeConfigObj: DefaultJudgeConfigObj, artSubject3ProjectsCodesArr: string[], projectsObj: ProjectInfos, carztStr: string, isManualProjectIn: boolean, isProjectIn: boolean, jl: number, examMileage: string, isRequiredProjectsEnd: boolean, lane: LANE): boolean => {
// const judgeConfigObj = this.judgeConfigObj;
// const artSubject3ProjectsCodesArr = this.artSubject3ProjectsCodesArr;
// const projectsObj = this.projectsObj;
// const carztStr = this.carztStr;
// const isManualProjectIn = this.isManualProjectIn;
// const isProjectIn = this.isProjectIn;
// const getProjectIsInRoad = this.getProjectIsInRoad;
const projectCode = artSubject3ProjectsCodesArr[index];
const currentProject: ProjectInfo = Reflect.get(projectsObj, projectCode)
if (currentProject === undefined) {
return false
}
const projectType = currentProject.type;
//不允许人工触发的项目列表,以","分隔
// TODO 可能会出错
const unExitManualProjects: string[] = (Reflect.get(judgeConfigObj, '332') || '').split(',');
//直线行驶中不进其他考试项目(0-否 1-是)
const param348: string = Reflect.get(judgeConfigObj, '348') || '0',
//里程不够允许手工点靠边停车0-否 1-是)
param387: string = Reflect.get(judgeConfigObj, '387') || '0',
//里程不够不报靠边停车0-否+1-是+2-必考项目未完成且里程不够不报项目)
param319: string = Reflect.get(judgeConfigObj, '319') || '0',
//人工项目是否能取消 1:可取消;
param340: string = Reflect.get(judgeConfigObj, '340') || '0',
//307参数里设置的项目项目已经做过后续不能人工触发
param307: string[] = (Reflect.get(judgeConfigObj, '307') || '').split(',');
//非行驶状态(没有速度),人工项目不能触发(按钮灰色)
if (carztStr === '停车') {
return false
}
//车上是否能进行人工操作(0-能1-不能人工评判2-不能人工进项目3-都不能)
if (Reflect.get(judgeConfigObj, '342') === '3' || Reflect.get(judgeConfigObj, '342') === '2') {
return false
}
//不允许人工触发的项目列表
if (unExitManualProjects.includes(artSubject3ProjectsCodesArr[index])) {
return false
}
//项目进行中不能人工触发
if (isProjectIn) {
if (param340 == '1') {
if (isManualProjectIn && (currentProject.type == '2')) {
return true
} else {
return false
}
}
return false
}
//项目路段信息判断
if (!GetProjectIsInRoad(projectCode + '', lane, judgeConfigObj)) {
return false
}
const project_9: ProjectInfo = Reflect.get(projectsObj, '9')
// 直线行驶中不进其他考试项目(0-否 1-是)
if (param348 == '0' && project_9.type == '2') {
return index === 0 ? true : false
}
//项目已经做过,后续不能人工触发
if (param307.includes(projectCode) && (projectType == '3' || projectType == '4')) {
return false
}
//319不为0或者387不为1里程不够时靠边停车项目不能触发
if ((param387 != '1' || param319 != '0') && index === 5) {
//里程是否达标 && 必考项目是否全完成
return jl >= Number(examMileage) && isRequiredProjectsEnd
}
return true
}
// 判断项目是否在当前路段号
export const GetProjectIsInRoad = (projectCode: string, lane: LANE, judgeConfigObj: DefaultJudgeConfigObj): boolean => {
// const lane = this.lane;
const road = lane.road;
const num = lane.num;
const count = lane.count;
const param_3: string[] = (Reflect.get(judgeConfigObj, '514')?.split(',') || []);
const param_4: string[] = (Reflect.get(judgeConfigObj, '515')?.split(',') || []);
const param_10: string[] = (Reflect.get(judgeConfigObj, '516')?.split(',') || []);
const param_11: string[] = (Reflect.get(judgeConfigObj, '517')?.split(',') || []);
const param_9: string[] = (Reflect.get(judgeConfigObj, '518')?.split(',') || []);
const param_12: string[] = (Reflect.get(judgeConfigObj, '519')?.split(',') || []);
const projectRoads: ProjectRoads = {
//直线行驶
param_3,
//变更车道
param_4,
//超车
param_10,
//靠边停车
param_11,
//会车
param_9,
//掉头
param_12,
};
//未测绘得道路上或者不在差分状态
if (road === '') {
return false
}
const currentProjectRoad: string[] = Reflect.get(projectRoads, `param_${projectCode}`)
if (currentProjectRoad.length == 0) {
return true
}
//设置了514-519参数只能在设置的路段触发对应项目
if (currentProjectRoad.includes(road)) {
//如果525为1则514-519设置的路段不能触发对应项目
if (Reflect.get(judgeConfigObj, '525') == '1') {
return false
}
} else {
return false
}
//405参数为2是如果在最左侧车道超车项目不能触发;
if (projectCode == '10' &&
Reflect.get(judgeConfigObj, '405') == '2' &&
(num === count) &&
num > 0
) {
return false
}
// 车道总数少于2条超车和变道不能触发
if (projectCode == '10' || projectCode == '4') {
if (count < 2) {
return false
}
}
return true
}
// 获取人工项目是否已做
export const GetIsEndManualProject = (index: number, artSubject3Projects: string[], artSubject3ProjectsCodesArr: string[], projectsObj: ProjectInfos): string => {
const projectName = artSubject3Projects[index];
const projectCode = artSubject3ProjectsCodesArr[index];
const currentProject: ProjectInfo = Reflect.get(projectsObj, projectCode)
const type = currentProject.type
if (type == '2') {
return projectName
}
return (type == '3' || type == '4') ? `${projectName}_red` : `${projectName}_green`;
}

View File

@ -67,7 +67,7 @@ export default struct HeaderComponent {
.fontColor("#fff")
.margin({
left: 10
}).fontSize(16)
}).fontSize(20)
if (this.logoExpansionBuilder) {
this.logoExpansionBuilder()
}

View File

@ -184,37 +184,6 @@ export default class Judge {
private isExamEnd: boolean
// 是否发送udp
private isUdpEnd: boolean = false
// 处理udp plc信号
handleUdp = async (msg: string) => {
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<number>('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服务序列号
@ -261,6 +230,31 @@ export default class Judge {
dConsole.info(JudgeTag, '过程数据文件上传 end')
}
private judgeTask: JudgeTask
private tempData?: PLCType
//实时计算gps经纬度距离
handDistance = async () => {
const dwzt = this.tempData?.gps?.dwzt || "";
const jdzt = this.tempData?.gps?.jdzt || "";
const tJD = ConvertDdmmToDecimalDegrees(this.tempData?.gps?.jd || 0)
const tWD = ConvertDdmmToDecimalDegrees(this.tempData?.gps?.wd || 0)
if (this.prevJd && dwzt == 4 && jdzt == 3) {
const distance = await examCalcGpsDistance({
jd1: this.prevJd,
wd1: this.prevWd,
jd2: tJD,
wd2: tWD,
h: this.tempData?.gps?.hxj || 1,
})
// const distanceClass = AppStorage.get<DistanceClass>('distanceClass')
// distanceClass?.setTimeData(Number(((distance / 100).toFixed(2))))
DrivingDataStorage.setDrivingProcessData(Number(((distance / 100).toFixed(2))))
}
this.prevJd = tJD;
this.prevWd = tWD;
}
private performInfo?: JudgePerformInfo
private isEndTip: boolean = false;
private deductedPopShowTimer: number = 0;
// 校验考试是否结束
checkExamIsEnd =
async (isManual?: boolean) => {
@ -374,85 +368,6 @@ export default class Judge {
}
}
}
private tempData?: PLCType
//实时计算gps经纬度距离
handDistance = async () => {
const dwzt = this.tempData?.gps?.dwzt || "";
const jdzt = this.tempData?.gps?.jdzt || "";
const tJD = ConvertDdmmToDecimalDegrees(this.tempData?.gps?.jd || 0)
const tWD = ConvertDdmmToDecimalDegrees(this.tempData?.gps?.wd || 0)
if (this.prevJd && dwzt == 4 && jdzt == 3) {
const distance = await examCalcGpsDistance({
jd1: this.prevJd,
wd1: this.prevWd,
jd2: tJD,
wd2: tWD,
h: this.tempData?.gps?.hxj || 1,
})
// const distanceClass = AppStorage.get<DistanceClass>('distanceClass')
// distanceClass?.setTimeData(Number(((distance / 100).toFixed(2))))
DrivingDataStorage.setDrivingProcessData(Number(((distance / 100).toFixed(2))))
}
this.prevJd = tJD;
this.prevWd = tWD;
}
private performInfo?: JudgePerformInfo
private isEndTip: boolean = false;
private deductedPopShowTimer: number = 0;
// 检测扣分、结束项目时该项目是否开始
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
//如果项目没有开始
dConsole.info(JudgeTag, 'surenjun isUpload=>', isUpload)
if (!isUpload) {
dConsole.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 ksjs?: JudgeKSJS
private kfArr?: MarkRule[]
//所有的科目考试项目(大车&小车)
@ -478,6 +393,37 @@ export default class Judge {
AppStorage.setOrCreate('msgStr', plc)
return tempData
}
// 处理udp plc信号
handleUdp = async (msg: string) => {
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<number>('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[]) => {
let num = 2;
@ -515,9 +461,9 @@ export default class Judge {
}
//本地轨迹回放地址
private trajectoryPath: string
//当前科目二的考试项目
// private currentKm2ItemsObj: any
private isTrajectoryOpen: boolean;
//当前科目二的考试项目
// 调代理接口是否断网了
private isJudgeDisConnect: boolean = false;
// 断网数据补传
@ -532,33 +478,6 @@ export default class Judge {
const code = await writeObjectOut(JSON.parse(examDataStr), "", this.context);
}
}
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);
dConsole.log(JudgeTag, "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) {
dConsole.info('surenjun', '123')
this.judgeUI.errorMsg = '当前的考试过程信息网络传输异常,程序点击确认将重启!';
this.judgeUI.disConnectErrorOpen = true
}
this.disConnectNum = 0
return temp
}
// 项目开始接口同步
beginProject = async (ksxm: number) => {
const carInfo = AppStorage.get<CarInfoType>('carInfo');
@ -662,6 +581,87 @@ export default class Judge {
UploadRegulatoryCodeConversion('17C54', temp.code || 0)
dConsole.info(JudgeTag, '上传照片 end')
}
// 检测扣分、结束项目时该项目是否开始
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
//如果项目没有开始
dConsole.info(JudgeTag, 'surenjun isUpload=>', isUpload)
if (!isUpload) {
dConsole.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 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);
dConsole.log(JudgeTag, "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) {
dConsole.info('surenjun', '123')
this.judgeUI.errorMsg = '当前的考试过程信息网络传输异常,程序点击确认将重启!';
this.judgeUI.disConnectErrorOpen = true
}
this.disConnectNum = 0
return temp
}
constructor(judgeUI: JudgeUI) {
this.serialIndex = 1;
@ -1205,11 +1205,11 @@ export default class Judge {
break
}
if (event == 2 || event == 3) {
setTimeout(() => {
this.judgeUI.kfArrScroller.scrollTo({
yOffset: 999999, xOffset: 0
})
}, 500)
// setTimeout(() => {
// this.judgeUI.kfArrScroller.scrollTo({
// yOffset: 999999, xOffset: 0
// })
// }, 500)
//统计必考项目完成数量
await this.setCountItems();
await checkExamIsEnd()
@ -1325,6 +1325,7 @@ export default class Judge {
public handEndExam = async () => {
dConsole.info(JudgeTag, '处理考试结束 handEndExam')
// this.judgeUI.loadingPopupVisible = true;
dConsole.log(JudgeTag, ' 打开车辆loading1')
this.judgeUI.generateExamRecordsDialogController.open()
// this.judgeUI.endPopupVisible = false;
this.judgeUI.endExamDialogController.close()
@ -1456,13 +1457,15 @@ export default class Judge {
this.isUdpEnd = true;
closeAllFiles()
// this.judgeUI.loadingPopupVisible = false;
dConsole.log(JudgeTag, ' 关闭车辆loading1')
this.judgeUI.generateExamRecordsDialogController.close()
return
}
dConsole.info(JudgeTag, '考试结束 end')
const param302: string = Reflect.get(judgeConfigObj, '302')
// judgeUI.loadingPopupVisible = true;
judgeUI.generateExamRecordsDialogController.open()
dConsole.log(JudgeTag, ' 打开车辆loading2')
// judgeUI.generateExamRecordsDialogController.open()
let currentKssycs = '0';
let voiceURL = ''
if (examSubject == '2') {
@ -1563,6 +1566,8 @@ export default class Judge {
setTimeout(() => {
this.isUdpEnd = true
closeAllFiles()
dConsole.log(JudgeTag, ' 关闭车辆loading2')
this.judgeUI.generateExamRecordsDialogController.close()
router.back();
}, param302 == '8' ? 3000 : 0)
})

View File

@ -13,43 +13,68 @@ interface QUEUE {
type GoTask = (currentTask: QUEUE) => Promise<boolean>
export default class JudgeTask {
//执行任务
goTask: GoTask = async (currentTask: QUEUE) => {
const fn = currentTask.fn;
const delayConfig = currentTask.delayConfig || {
isDelay: false, delayTime: 1000
}
const isDelay = delayConfig.isDelay
const delayTime = delayConfig.delayTime
return false
}
private queue?: QUEUE[] = []
private status: string
private queue: QUEUE[] = [];
private status: string = 'end';
private isExecuting: boolean = false;
// 改为迭代方式执行队列
executeQueue = async () => {
const queue = this.queue;
const executeQueue = this.executeQueue
if (queue?.length) {
for (const currentTask of queue) {
await this.goTask(currentTask)
this.queue?.shift()
await executeQueue()
if (this.isExecuting) return;
this.isExecuting = true;
this.status = 'running';
while (this.queue.length > 0) {
const currentTask = this.queue[0];
try {
await this.goTask(currentTask);
} finally {
this.queue.shift();
}
} else {
this.status = 'end'
}
this.status = 'end';
this.isExecuting = false;
}
addTask = async (fn: Function, delayConfig?: DelayConfig) => {
this.queue?.push({
fn, delayConfig
this.queue.push({
fn,
delayConfig
});
if (this.status == 'end' && this.queue?.length === 1) {
// 如果当前没有在执行,就启动执行
if (!this.isExecuting) {
await this.executeQueue();
}
}
constructor() {
this.queue = []
this.status = 'end'
this.queue = [];
this.status = 'end';
this.isExecuting = false;
}
}
// 执行任务
goTask: GoTask = async (currentTask: QUEUE) => {
try {
const fn = currentTask.fn;
const delayConfig = currentTask.delayConfig || {
isDelay: false, delayTime: 1000
}
// 实际执行任务函数
await fn();
// 处理延迟逻辑
if (delayConfig.isDelay && delayConfig.delayTime) {
await new Promise<void>(resolve => {
setTimeout(resolve, delayConfig.delayTime);
});
}
return true;
} catch (error) {
console.error(TAG, '任务执行失败:', error);
return false;
}
}
}

View File

@ -1,55 +1,13 @@
<details>
<summary>fix: 档位信号处理,信号显示界面无法进入问题解决</summary>
<summary>fix: 评判日志</summary>
<span style="color: #888;">[提交人]:</span><span style="color: #333;">wangzhongjie</span><br>
<span style="color: #888;">[提交时间]:</span><span style="color: #333;">2025-06-30 16:50</span><br>
<span style="color: #888;">[提交版本]:</span><span style="color: #333;">b92d31b</span>
<span style="color: #888;">[提交时间]:</span><span style="color: #333;">2025-07-01 11:08</span><br>
<span style="color: #888;">[提交版本]:</span><span style="color: #333;">756ced2</span>
</details>
<details>
<summary>fix: 档位信号处理</summary>
<summary>fix: 补全完善类型系统</summary>
<span style="color: #888;">[提交人]:</span><span style="color: #333;">wangzhongjie</span><br>
<span style="color: #888;">[提交时间]:</span><span style="color: #333;">2025-06-30 16:41</span><br>
<span style="color: #888;">[提交版本]:</span><span style="color: #333;">c717b16</span>
</details>
<details>
<summary>fix: 完善worker关闭性能优化,完善读取串口代码</summary>
<span style="color: #888;">[提交人]:</span><span style="color: #333;">wangzhongjie</span><br>
<span style="color: #888;">[提交时间]:</span><span style="color: #333;">2025-06-30 09:55</span><br>
<span style="color: #888;">[提交版本]:</span><span style="color: #333;">078ec1a</span>
</details>
<details>
<summary>fix: 修改版本参数</summary>
<span style="color: #888;">[提交人]:</span><span style="color: #333;">wangzhongjie</span><br>
<span style="color: #888;">[提交时间]:</span><span style="color: #333;">2025-06-30 09:10</span><br>
<span style="color: #888;">[提交版本]:</span><span style="color: #333;">fd2f75d</span>
</details>
<details>
<summary>fix: 解决页面有输入法会自动弹出自动聚焦影响体验问题</summary>
<span style="color: #888;">[提交人]:</span><span style="color: #333;">wangzhongjie</span><br>
<span style="color: #888;">[提交时间]:</span><span style="color: #333;">2025-06-27 17:29</span><br>
<span style="color: #888;">[提交版本]:</span><span style="color: #333;">f1fc2f9</span>
</details>
<details>
<summary>fix: 完善版本发布</summary>
<span style="color: #888;">[提交人]:</span><span style="color: #333;">wangzhongjie</span><br>
<span style="color: #888;">[提交时间]:</span><span style="color: #333;">2025-06-27 16:01</span><br>
<span style="color: #888;">[提交版本]:</span><span style="color: #333;">e34297a</span>
</details>
<details>
<summary>fix: 完善版本发布</summary>
<span style="color: #888;">[提交人]:</span><span style="color: #333;">wangzhongjie</span><br>
<span style="color: #888;">[提交时间]:</span><span style="color: #333;">2025-06-27 15:02</span><br>
<span style="color: #888;">[提交版本]:</span><span style="color: #333;">4705de0</span>
</details>
<details>
<summary>fix: 增加调试模式设置</summary>
<span style="color: #888;">[提交人]:</span><span style="color: #333;">wangzhongjie</span><br>
<span style="color: #888;">[提交时间]:</span><span style="color: #333;">2025-06-27 15:02</span><br>
<span style="color: #888;">[提交版本]:</span><span style="color: #333;">0809571</span>
<span style="color: #888;">[提交时间]:</span><span style="color: #333;">2025-06-30 17:15</span><br>
<span style="color: #888;">[提交版本]:</span><span style="color: #333;">03d3f09</span>
</details>