import { BasicType, YTAvoid } from 'basic' import { DiaLogPageEnum, DiaLogParam } from 'basic/src/main/ets/models/YTDiaLogModel' import { HistoryApis } from '../../Apis/HistoryApis' import { HistoryEventDetail } from '../../model/Index' import { BubbleStorage, StabilityStorage } from '../../model/Storage' import { NumberKeyBoard, NumberKeyBoardStyle } from './NumberKeyboard' import { YtDatePicker } from './YtDatePicker' import { _YtHeader } from './_YtHeader' import { AppStorageV2 } from '@kit.ArkUI' @Builder export function getBuilder(param: DiaLogParam, onBack: (ans?: ESObject) => void){ if(param.pageEnum == DiaLogPageEnum.BottomMenu) BottomMenu(onBack, param.params) else if (param.pageEnum == DiaLogPageEnum.DatePicker) DatePickerBuilder(onBack, param.param) else if (param.pageEnum == DiaLogPageEnum.NumBerInput) NumberInputBuilder({onBack: onBack, param: param.param}) else if (param.pageEnum == DiaLogPageEnum.Confirm) DoubleConfirm(onBack, param.param) else if (param.pageEnum == DiaLogPageEnum.TextInput) InputComp({onBack: onBack, param: param.param}) else if (param.pageEnum == DiaLogPageEnum.HistoryToday) HistoryToday({onBack: onBack, param: param.param}) else if (param.pageEnum == DiaLogPageEnum.BubbleSetting) BubbleSetting({onBack: onBack, param: param.param}) else if (param.pageEnum == DiaLogPageEnum.GameOver) GameOver({onBack: onBack, param: param.param}) } // 底部菜单 @Builder function BottomMenu(onBack: (ans:ESObject) => void, params?: Array) { Column(){ ForEach(params, (item: BasicType, index) => { Row(){ Text(item.text) .fontSize(16) .textAlign(TextAlign.Center) } .width("100%") .alignItems(VerticalAlign.Center) .justifyContent(FlexAlign.Center) .padding({ top: 24, bottom: 24 }) .onClick(() => { let ans = item.message ?? item.text ?? `${index}` onBack(ans) }) Divider().width("80%").height(1).backgroundColor('#000000F2') }) } .width("100%") .padding({ bottom: 30 }) .backgroundColor(Color.White) .justifyContent(FlexAlign.Center) .alignItems(HorizontalAlign.Center) .borderRadius({ topLeft: 8, topRight: 8 }) } // 时间选择器 @Builder function DatePickerBuilder(onBack: (ans?:ESObject) => void, param?: BasicType){ YtDatePicker({ selectDateBack: (date?: Date) => { if(!date) return onBack() // 转换为 YY-MM-DD HH:mm:ss 格式 const year = date.getFullYear().toString(); const month = (date.getMonth() + 1).toString().padStart(2, '0'); const day = date.getDate().toString().padStart(2, '0'); const result = `${year}-${month}-${day}`; onBack(result) }, selectedDate: param?.date ? new Date(param.date) : new Date(), linearInfo: { colors: [[param?.color ?? '#95C50A', 1]] }, needCancel: true }) } // 对话框 @Builder function DoubleConfirm(onBack: (ans?:ESObject) => void, param?: BasicType) { Column() { if(param?.text) Text(param.text) .fontColor(Color.Black) .lineHeight(18) .fontSize(18) .textAlign(TextAlign.Center) .margin({ bottom: 18 }) Row() { Text('取消') .fontSize(16) .fontWeight(400) .borderRadius(param?.number ?? 36) .fontColor(Color.Black) .backgroundColor('#F5F5F7') .padding({ left: 36, top: 9, right: 36, bottom: 9}) .onClick(() => { onBack('false') }) Text('确定') .fontSize(16) .fontWeight(400) .borderRadius(param?.number ?? 36) .fontColor(Color.Black) .padding({ left: 36, top: 9, right: 36, bottom: 9}) .linearGradient({ colors: [ param?.color ? [param.color, 1 ] : ['#30E3CE', 0.4], ['#91F1FF', 0.8] ], angle: 200 }) .onClick(() => { onBack('true') }) } .justifyContent(FlexAlign.SpaceBetween) .width('100%') } // .height(160) .width(280) .padding({ top: 28, left: 32, right: 32, bottom: 20 }) .backgroundColor(Color.White) .borderRadius(8) } // 数字输入框 @ComponentV2 struct NumberInputBuilder{ @Event onBack: (ans:ESObject) => void @Param @Require param: BasicType @Local ans: string = '' aboutToAppear(): void { this.ans = this.param.text ?? '' } build() { Column(){ // 标题 RelativeContainer(){ _YtHeader({ title: this.param?.text ?? '', isShowBackComp: false, }) .height(44) .id('_title') .width("100%") .alignRules({ top: { anchor: "__container__", align: VerticalAlign.Top}, left: { anchor: "__container__", align: HorizontalAlign.Start} }) Text(this.ans) .fontSize(32) .fontWeight(500) .fontColor('#30E3CE') .id('weight') .padding({left: 58, right: 58, bottom: 10, top: 60}) .alignRules({ top: { anchor: "_title", align: VerticalAlign.Bottom}, middle: { anchor: "__container__", align: HorizontalAlign.Center} }) Row() .width(151) .height(3) .backgroundColor('#30E3CE') .borderRadius(8) .alignRules({ top: { anchor: "weight", align: VerticalAlign.Bottom}, middle: { anchor: "__container__", align: HorizontalAlign.Center} }) Text(this.param?.message ?? '') .fontSize(20) .fontWeight(500) .padding({ bottom: 10 }) .fontColor('rgba(0, 0, 0, 0.5)') .alignRules({ bottom: { anchor: "weight", align: VerticalAlign.Bottom}, right: { anchor: "weight", align: HorizontalAlign.End} }) } .height(210) .backgroundColor(Color.White) // 数字键盘 Column(){ NumberKeyBoard({ textInputValue: this.ans, maxInputNum: 3, keyBoardStyle: new NumberKeyBoardStyle() .setFinishBackGround('#30E3CE') .setZeroBackGround(Color.White) .setBorder({ width: 0 }) .setDeleteIcon($r('app.media.icon_delback')), onTextInputValueChange: (textInputValue: string) => { this.ans = textInputValue }, onFinishClick: (text: string) => { if(!text || text == '0' || text == '0.') return if(text.charAt(text.length-1) === '.') this.ans += '0' this.onBack(this.ans!) } }) } .height(260) .width("100%") .backgroundColor('#F5F6FA') .padding({ top: 10, bottom: 35, left: 10, right: 10}) } // .height(470) .width("100%") .backgroundColor(Color.White) .padding({ top: 24, }) } } // 输入框 @ComponentV2 struct InputComp{ @Event onBack: (ans?:ESObject) => void @Param @Require param: BasicType @Local ans: string = '' aboutToAppear(): void { this.ans = this.param.text ?? '' } build() { Column({space: 10}){ Row(){ Text("取消") .fontSize(12) .fontWeight(400) .borderRadius(45) .fontColor(Color.Black) // .backgroundColor('#C1EDE9') .padding({ left: 20,top: 8, right: 20, bottom: 8}) .onClick(() => { this.onBack() }) // Text(this.param.text ?? '') // .fontSize(18) // .fontWeight(500) Text("确定") .fontSize(12) .fontWeight(400) .borderRadius(45) .fontColor(Color.Black) // .backgroundColor('#30E3CE') .padding({ left: 20,top: 8, right: 20, bottom: 8}) .onClick(() => { this.onBack(this.ans) }) } .width("100%") .alignItems(VerticalAlign.Center) .justifyContent(FlexAlign.SpaceBetween) TextInput({text: $$this.ans, placeholder: this.param.message}) .height('48') .borderRadius(8) .defaultFocus(true) .maxLength(13) .fontColor(Color.Black) .placeholderColor('#f1f1f1') .backgroundColor('#F6F6F6') .onSubmit(() => { this.onBack(this.ans) }) } .width("100%") .borderRadius({ topLeft: 10, topRight: 10 }) .backgroundColor(this.param.color ?? '#ffff') .padding({ bottom: 42, left: 16, right: 16, top: 24 }) } } @ComponentV2 struct HistoryToday{ @Event onBack: (ans?:ESObject) => void @Param @Require param: BasicType @Local dataSource: Array = [] @Local safeBottom: number = AppStorage.get(YTAvoid.SAFE_BOTTOM_KEY) as number // 获取今日历史事件 async getHistoryToday(): Promise { this.dataSource = await HistoryApis.getTodayInHistory() } aboutToAppear(): void { this.getHistoryToday() } build() { Column({space: 18}){ Row(){ Text() Text('历史今日') .fontSize(18) .fontWeight(500) .fontColor('#FF415C06') Image($r('app.media.icon_close')) .width(24) .aspectRatio(1) .onClick(() => { this.onBack('false') }) } .width("100%") .justifyContent(FlexAlign.SpaceBetween) Column(){ List({space: 18}){ Repeat(this.dataSource) .each(i => { ListItem(){ Column({space: 10}){ Text(i.item.historyTime) .fontSize(18) .width("100%") .fontWeight(500) .fontColor('#FF333333') Text(i.item.title) .width("100%") .fontSize(14) .fontWeight(400) .fontColor('#FF333333') Text(i.item.content) .width("100%") .fontSize(14) .fontWeight(300) .fontColor('#FF333333') } .width("100%") .borderRadius(5) .backgroundColor('#FFE6EBDA') .alignItems(HorizontalAlign.Start) .border({ width: {left: 8.5}, color: '#FF7A9E2B'}) .padding({ top: 14, left: 18, right: 18, bottom: 14 }) } }) } .width("100%") .height("100%") .scrollBar(BarState.Off) .padding({bottom: this.safeBottom}) } .layoutWeight(1) .width("100%") } .width("100%") .height('auto') .backgroundColor(Color.White) .borderRadius({ topLeft: 20, topRight: 20 }) .padding({left: 16, right: 16, top: 14 }) .constraintSize({minHeight: 380, maxHeight: '50%'}) } } @ComponentV2 struct BubbleSetting{ @Event onBack: (ans?:ESObject) => void @Param @Require param: BasicType @Local bubbleConnect: BubbleStorage = AppStorageV2.connect(BubbleStorage, () => new BubbleStorage())! @Local stabilityStorage: StabilityStorage = AppStorageV2.connect(StabilityStorage, () => new StabilityStorage())! @Local forEach: Array = [] @Local isBubble: boolean = true aboutToAppear(): void { this.isBubble = this.param.isShowClose ?? true if(this.isBubble) { this.forEach = ['气泡出现频率', '气泡消失时间'] } else { this.forEach = ['水平最大偏移', '竖直最大偏移', '训练时间'] } } build() { Column({space: 9}){ Row(){ Image($r('app.media.icon_close')) .width(24) .aspectRatio(1) .onClick(() => { this.onBack() }) } .width("100%") .justifyContent(FlexAlign.End) .padding({right: 14, top: 10, bottom: 10}) Column({space: 25}){ ForEach(this.forEach, (item: string, index) => { Row(){ Text(`${item}:`) .fontSize(16) .fontWeight(500) .fontColor('#FF333333') Row({space: 12}){ if(this.isBubble) { TextInput({text: `${index == 0 ? this.bubbleConnect.bubbleFrequency : this.bubbleConnect.bubbleDisappearTime}`}) .width(45) .height(30) .padding(0) .maxLength(2) .borderRadius(5) .type(InputType.Number) .textAlign(TextAlign.Center) .border({width: 1, color: '#FFFFA001'}) .onChange((text: string) => { if(text){ let num = parseInt(text) || 1 if(index == 0){ this.bubbleConnect.bubbleFrequency = num }else{ this.bubbleConnect.bubbleDisappearTime = num } } }) Text('s') .fontSize(16) .fontWeight(500) .fontColor('#FF333333') } else { TextInput({text: `${index == 0 ? this.stabilityStorage.horizontalMaxOffset : index == 1 ? this.stabilityStorage.verticalMaxOffset : this.stabilityStorage.trainingTime}`}) .width(45) .height(30) .padding(0) .maxLength(2) .borderRadius(5) .type(InputType.Number) .textAlign(TextAlign.Center) .border({width: 1, color: '#FFFFA001'}) .onChange((text: string) => { if(text){ let num = parseInt(text) || 1 if(index == 0){ this.stabilityStorage.horizontalMaxOffset = Math.min(num, 40) }else if(index == 1){ this.stabilityStorage.verticalMaxOffset = Math.min(num, 100) } else { this.stabilityStorage.trainingTime = num } } }) Text(index == 2 ? 's' : '°') .fontSize(16) .fontWeight(500) .fontColor('#FF333333') } } } .width("100%") .padding({left: 51, right: 51}) .justifyContent(FlexAlign.SpaceBetween) }) if(this.isBubble) { Text('气泡最多存在 10 个') .fontSize(12) } } .width("100%") .alignItems(HorizontalAlign.Center) } .width(294) .borderRadius(20) .padding({bottom: 26}) .backgroundColor(Color.White) .justifyContent(FlexAlign.Start) } } @ComponentV2 struct GameOver{ @Event onBack: (ans?:ESObject) => void @Param @Require param: BasicType @Local isWin: boolean = true aboutToAppear(): void { this.isWin = this.param.isShowClose ?? true } build() { Column({space: 9}){ Row(){ Image(this.isWin ? $r("app.media.icon_win") : $r("app.media.icon_fail")) .width(175) .height(105) } .width("100%") .position({y: -53}) .justifyContent(FlexAlign.Center) Text(this.isWin ? '稳定性训练成功' : '稳定性训练失败') .fontSize(16) .fontWeight(500) .fontColor(Color.Black) .padding({top: 67, bottom: 46}) Row(){ Text(this.isWin ? '太棒了' : '继续努力') .fontSize(16) .fontWeight(500) } .borderRadius(8) .padding({left: 41, top: 16, right: 41, bottom: 16}) .linearGradient({colors: [['#FFCC00', 0], ['#FF9F02', 1]], angle: 90}) .onClick(() => { this.onBack() }) } .width(294) .borderRadius(20) .padding({bottom: 30}) .backgroundColor(Color.White) .justifyContent(FlexAlign.Start) .alignItems(HorizontalAlign.Center) } }