YTDiaLogBuild.ets 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548
  1. import { BasicType, YTAvoid } from 'basic'
  2. import { DiaLogPageEnum, DiaLogParam } from 'basic/src/main/ets/models/YTDiaLogModel'
  3. import { HistoryApis } from '../../Apis/HistoryApis'
  4. import { HistoryEventDetail } from '../../model/Index'
  5. import { BubbleStorage, StabilityStorage } from '../../model/Storage'
  6. import { NumberKeyBoard, NumberKeyBoardStyle } from './NumberKeyboard'
  7. import { YtDatePicker } from './YtDatePicker'
  8. import { _YtHeader } from './_YtHeader'
  9. import { AppStorageV2 } from '@kit.ArkUI'
  10. @Builder
  11. export function getBuilder(param: DiaLogParam, onBack: (ans?: ESObject) => void){
  12. if(param.pageEnum == DiaLogPageEnum.BottomMenu) BottomMenu(onBack, param.params)
  13. else if (param.pageEnum == DiaLogPageEnum.DatePicker) DatePickerBuilder(onBack, param.param)
  14. else if (param.pageEnum == DiaLogPageEnum.NumBerInput) NumberInputBuilder({onBack: onBack, param: param.param})
  15. else if (param.pageEnum == DiaLogPageEnum.Confirm) DoubleConfirm(onBack, param.param)
  16. else if (param.pageEnum == DiaLogPageEnum.TextInput) InputComp({onBack: onBack, param: param.param})
  17. else if (param.pageEnum == DiaLogPageEnum.HistoryToday) HistoryToday({onBack: onBack, param: param.param})
  18. else if (param.pageEnum == DiaLogPageEnum.BubbleSetting) BubbleSetting({onBack: onBack, param: param.param})
  19. else if (param.pageEnum == DiaLogPageEnum.GameOver) GameOver({onBack: onBack, param: param.param})
  20. }
  21. // 底部菜单
  22. @Builder
  23. function BottomMenu(onBack: (ans:ESObject) => void, params?: Array<BasicType>) {
  24. Column(){
  25. ForEach(params, (item: BasicType, index) => {
  26. Row(){
  27. Text(item.text)
  28. .fontSize(16)
  29. .textAlign(TextAlign.Center)
  30. }
  31. .width("100%")
  32. .alignItems(VerticalAlign.Center)
  33. .justifyContent(FlexAlign.Center)
  34. .padding({ top: 24, bottom: 24 })
  35. .onClick(() => {
  36. let ans = item.message ?? item.text ?? `${index}`
  37. onBack(ans)
  38. })
  39. Divider().width("80%").height(1).backgroundColor('#000000F2')
  40. })
  41. }
  42. .width("100%")
  43. .padding({ bottom: 30 })
  44. .backgroundColor(Color.White)
  45. .justifyContent(FlexAlign.Center)
  46. .alignItems(HorizontalAlign.Center)
  47. .borderRadius({ topLeft: 8, topRight: 8 })
  48. }
  49. // 时间选择器
  50. @Builder
  51. function DatePickerBuilder(onBack: (ans?:ESObject) => void, param?: BasicType){
  52. YtDatePicker({
  53. selectDateBack: (date?: Date) => {
  54. if(!date) return onBack()
  55. // 转换为 YY-MM-DD HH:mm:ss 格式
  56. const year = date.getFullYear().toString();
  57. const month = (date.getMonth() + 1).toString().padStart(2, '0');
  58. const day = date.getDate().toString().padStart(2, '0');
  59. const result = `${year}-${month}-${day}`;
  60. onBack(result)
  61. },
  62. selectedDate: param?.date ? new Date(param.date) : new Date(),
  63. linearInfo: { colors: [[param?.color ?? '#95C50A', 1]] },
  64. needCancel: true
  65. })
  66. }
  67. // 对话框
  68. @Builder
  69. function DoubleConfirm(onBack: (ans?:ESObject) => void, param?: BasicType) {
  70. Column() {
  71. if(param?.text)
  72. Text(param.text)
  73. .fontColor(Color.Black)
  74. .lineHeight(18)
  75. .fontSize(18)
  76. .textAlign(TextAlign.Center)
  77. .margin({ bottom: 18 })
  78. Row() {
  79. Text('取消')
  80. .fontSize(16)
  81. .fontWeight(400)
  82. .borderRadius(param?.number ?? 36)
  83. .fontColor(Color.Black)
  84. .backgroundColor('#F5F5F7')
  85. .padding({ left: 36, top: 9, right: 36, bottom: 9})
  86. .onClick(() => {
  87. onBack('false')
  88. })
  89. Text('确定')
  90. .fontSize(16)
  91. .fontWeight(400)
  92. .borderRadius(param?.number ?? 36)
  93. .fontColor(Color.Black)
  94. .padding({ left: 36, top: 9, right: 36, bottom: 9})
  95. .linearGradient({
  96. colors: [ param?.color ? [param.color, 1 ] : ['#30E3CE', 0.4], ['#91F1FF', 0.8] ],
  97. angle: 200
  98. })
  99. .onClick(() => {
  100. onBack('true')
  101. })
  102. }
  103. .justifyContent(FlexAlign.SpaceBetween)
  104. .width('100%')
  105. }
  106. // .height(160)
  107. .width(280)
  108. .padding({ top: 28, left: 32, right: 32, bottom: 20 })
  109. .backgroundColor(Color.White)
  110. .borderRadius(8)
  111. }
  112. // 数字输入框
  113. @ComponentV2
  114. struct NumberInputBuilder{
  115. @Event onBack: (ans:ESObject) => void
  116. @Param @Require param: BasicType
  117. @Local ans: string = ''
  118. aboutToAppear(): void {
  119. this.ans = this.param.text ?? ''
  120. }
  121. build() {
  122. Column(){
  123. // 标题
  124. RelativeContainer(){
  125. _YtHeader({ title: this.param?.text ?? '', isShowBackComp: false, })
  126. .height(44)
  127. .id('_title')
  128. .width("100%")
  129. .alignRules({
  130. top: { anchor: "__container__", align: VerticalAlign.Top},
  131. left: { anchor: "__container__", align: HorizontalAlign.Start}
  132. })
  133. Text(this.ans)
  134. .fontSize(32)
  135. .fontWeight(500)
  136. .fontColor('#30E3CE')
  137. .id('weight')
  138. .padding({left: 58, right: 58, bottom: 10, top: 60})
  139. .alignRules({
  140. top: { anchor: "_title", align: VerticalAlign.Bottom},
  141. middle: { anchor: "__container__", align: HorizontalAlign.Center}
  142. })
  143. Row()
  144. .width(151)
  145. .height(3)
  146. .backgroundColor('#30E3CE')
  147. .borderRadius(8)
  148. .alignRules({
  149. top: { anchor: "weight", align: VerticalAlign.Bottom},
  150. middle: { anchor: "__container__", align: HorizontalAlign.Center}
  151. })
  152. Text(this.param?.message ?? '')
  153. .fontSize(20)
  154. .fontWeight(500)
  155. .padding({ bottom: 10 })
  156. .fontColor('rgba(0, 0, 0, 0.5)')
  157. .alignRules({
  158. bottom: { anchor: "weight", align: VerticalAlign.Bottom},
  159. right: { anchor: "weight", align: HorizontalAlign.End}
  160. })
  161. }
  162. .height(210)
  163. .backgroundColor(Color.White)
  164. // 数字键盘
  165. Column(){
  166. NumberKeyBoard({
  167. textInputValue: this.ans,
  168. maxInputNum: 3,
  169. keyBoardStyle: new NumberKeyBoardStyle()
  170. .setFinishBackGround('#30E3CE')
  171. .setZeroBackGround(Color.White)
  172. .setBorder({ width: 0 })
  173. .setDeleteIcon($r('app.media.icon_delback')),
  174. onTextInputValueChange: (textInputValue: string) => {
  175. this.ans = textInputValue
  176. },
  177. onFinishClick: (text: string) => {
  178. if(!text || text == '0' || text == '0.') return
  179. if(text.charAt(text.length-1) === '.') this.ans += '0'
  180. this.onBack(this.ans!)
  181. }
  182. })
  183. }
  184. .height(260)
  185. .width("100%")
  186. .backgroundColor('#F5F6FA')
  187. .padding({ top: 10, bottom: 35, left: 10, right: 10})
  188. }
  189. // .height(470)
  190. .width("100%")
  191. .backgroundColor(Color.White)
  192. .padding({
  193. top: 24,
  194. })
  195. }
  196. }
  197. // 输入框
  198. @ComponentV2
  199. struct InputComp{
  200. @Event onBack: (ans?:ESObject) => void
  201. @Param @Require param: BasicType
  202. @Local ans: string = ''
  203. aboutToAppear(): void {
  204. this.ans = this.param.text ?? ''
  205. }
  206. build() {
  207. Column({space: 10}){
  208. Row(){
  209. Text("取消")
  210. .fontSize(12)
  211. .fontWeight(400)
  212. .borderRadius(45)
  213. .fontColor(Color.Black)
  214. // .backgroundColor('#C1EDE9')
  215. .padding({ left: 20,top: 8, right: 20, bottom: 8})
  216. .onClick(() => {
  217. this.onBack()
  218. })
  219. // Text(this.param.text ?? '')
  220. // .fontSize(18)
  221. // .fontWeight(500)
  222. Text("确定")
  223. .fontSize(12)
  224. .fontWeight(400)
  225. .borderRadius(45)
  226. .fontColor(Color.Black)
  227. // .backgroundColor('#30E3CE')
  228. .padding({ left: 20,top: 8, right: 20, bottom: 8})
  229. .onClick(() => {
  230. this.onBack(this.ans)
  231. })
  232. }
  233. .width("100%")
  234. .alignItems(VerticalAlign.Center)
  235. .justifyContent(FlexAlign.SpaceBetween)
  236. TextInput({text: $$this.ans, placeholder: this.param.message})
  237. .height('48')
  238. .borderRadius(8)
  239. .defaultFocus(true)
  240. .maxLength(13)
  241. .fontColor(Color.Black)
  242. .placeholderColor('#f1f1f1')
  243. .backgroundColor('#F6F6F6')
  244. .onSubmit(() => {
  245. this.onBack(this.ans)
  246. })
  247. }
  248. .width("100%")
  249. .borderRadius({ topLeft: 10, topRight: 10 })
  250. .backgroundColor(this.param.color ?? '#ffff')
  251. .padding({ bottom: 42, left: 16, right: 16, top: 24 })
  252. }
  253. }
  254. @ComponentV2
  255. struct HistoryToday{
  256. @Event onBack: (ans?:ESObject) => void
  257. @Param @Require param: BasicType
  258. @Local dataSource: Array<HistoryEventDetail> = []
  259. @Local safeBottom: number = AppStorage.get(YTAvoid.SAFE_BOTTOM_KEY) as number
  260. // 获取今日历史事件
  261. async getHistoryToday(): Promise<void> {
  262. this.dataSource = await HistoryApis.getTodayInHistory()
  263. }
  264. aboutToAppear(): void {
  265. this.getHistoryToday()
  266. }
  267. build() {
  268. Column({space: 18}){
  269. Row(){
  270. Text()
  271. Text('历史今日')
  272. .fontSize(18)
  273. .fontWeight(500)
  274. .fontColor('#FF415C06')
  275. Image($r('app.media.icon_close'))
  276. .width(24)
  277. .aspectRatio(1)
  278. .onClick(() => { this.onBack('false') })
  279. }
  280. .width("100%")
  281. .justifyContent(FlexAlign.SpaceBetween)
  282. Column(){
  283. List({space: 18}){
  284. Repeat(this.dataSource)
  285. .each(i => {
  286. ListItem(){
  287. Column({space: 10}){
  288. Text(i.item.historyTime)
  289. .fontSize(18)
  290. .width("100%")
  291. .fontWeight(500)
  292. .fontColor('#FF333333')
  293. Text(i.item.title)
  294. .width("100%")
  295. .fontSize(14)
  296. .fontWeight(400)
  297. .fontColor('#FF333333')
  298. Text(i.item.content)
  299. .width("100%")
  300. .fontSize(14)
  301. .fontWeight(300)
  302. .fontColor('#FF333333')
  303. }
  304. .width("100%")
  305. .borderRadius(5)
  306. .backgroundColor('#FFE6EBDA')
  307. .alignItems(HorizontalAlign.Start)
  308. .border({ width: {left: 8.5}, color: '#FF7A9E2B'})
  309. .padding({ top: 14, left: 18, right: 18, bottom: 14 })
  310. }
  311. })
  312. }
  313. .width("100%")
  314. .height("100%")
  315. .scrollBar(BarState.Off)
  316. .padding({bottom: this.safeBottom})
  317. }
  318. .layoutWeight(1)
  319. .width("100%")
  320. }
  321. .width("100%")
  322. .height('auto')
  323. .backgroundColor(Color.White)
  324. .borderRadius({ topLeft: 20, topRight: 20 })
  325. .padding({left: 16, right: 16, top: 14 })
  326. .constraintSize({minHeight: 380, maxHeight: '50%'})
  327. }
  328. }
  329. @ComponentV2
  330. struct BubbleSetting{
  331. @Event onBack: (ans?:ESObject) => void
  332. @Param @Require param: BasicType
  333. @Local bubbleConnect: BubbleStorage = AppStorageV2.connect(BubbleStorage, () => new BubbleStorage())!
  334. @Local stabilityStorage: StabilityStorage = AppStorageV2.connect(StabilityStorage, () => new StabilityStorage())!
  335. @Local forEach: Array<string> = []
  336. @Local isBubble: boolean = true
  337. aboutToAppear(): void {
  338. this.isBubble = this.param.isShowClose ?? true
  339. if(this.isBubble) {
  340. this.forEach = ['气泡出现频率', '气泡消失时间']
  341. } else {
  342. this.forEach = ['水平最大偏移', '竖直最大偏移', '训练时间']
  343. }
  344. }
  345. build() {
  346. Column({space: 9}){
  347. Row(){
  348. Image($r('app.media.icon_close'))
  349. .width(24)
  350. .aspectRatio(1)
  351. .onClick(() => { this.onBack() })
  352. }
  353. .width("100%")
  354. .justifyContent(FlexAlign.End)
  355. .padding({right: 14, top: 10, bottom: 10})
  356. Column({space: 25}){
  357. ForEach(this.forEach, (item: string, index) => {
  358. Row(){
  359. Text(`${item}:`)
  360. .fontSize(16)
  361. .fontWeight(500)
  362. .fontColor('#FF333333')
  363. Row({space: 12}){
  364. if(this.isBubble) {
  365. TextInput({text: `${index == 0 ? this.bubbleConnect.bubbleFrequency : this.bubbleConnect.bubbleDisappearTime}`})
  366. .width(45)
  367. .height(30)
  368. .padding(0)
  369. .maxLength(2)
  370. .borderRadius(5)
  371. .type(InputType.Number)
  372. .textAlign(TextAlign.Center)
  373. .border({width: 1, color: '#FFFFA001'})
  374. .onChange((text: string) => {
  375. if(text){
  376. let num = parseInt(text) || 1
  377. if(index == 0){
  378. this.bubbleConnect.bubbleFrequency = num
  379. }else{
  380. this.bubbleConnect.bubbleDisappearTime = num
  381. }
  382. }
  383. })
  384. Text('s')
  385. .fontSize(16)
  386. .fontWeight(500)
  387. .fontColor('#FF333333')
  388. } else {
  389. TextInput({text: `${index == 0 ? this.stabilityStorage.horizontalMaxOffset : index == 1 ? this.stabilityStorage.verticalMaxOffset : this.stabilityStorage.trainingTime}`})
  390. .width(45)
  391. .height(30)
  392. .padding(0)
  393. .maxLength(2)
  394. .borderRadius(5)
  395. .type(InputType.Number)
  396. .textAlign(TextAlign.Center)
  397. .border({width: 1, color: '#FFFFA001'})
  398. .onChange((text: string) => {
  399. if(text){
  400. let num = parseInt(text) || 1
  401. if(index == 0){
  402. this.stabilityStorage.horizontalMaxOffset = Math.min(num, 40)
  403. }else if(index == 1){
  404. this.stabilityStorage.verticalMaxOffset = Math.min(num, 100)
  405. } else {
  406. this.stabilityStorage.trainingTime = num
  407. }
  408. }
  409. })
  410. Text(index == 2 ? 's' : '°')
  411. .fontSize(16)
  412. .fontWeight(500)
  413. .fontColor('#FF333333')
  414. }
  415. }
  416. }
  417. .width("100%")
  418. .padding({left: 51, right: 51})
  419. .justifyContent(FlexAlign.SpaceBetween)
  420. })
  421. if(this.isBubble) {
  422. Text('气泡最多存在 10 个')
  423. .fontSize(12)
  424. }
  425. }
  426. .width("100%")
  427. .alignItems(HorizontalAlign.Center)
  428. }
  429. .width(294)
  430. .borderRadius(20)
  431. .padding({bottom: 26})
  432. .backgroundColor(Color.White)
  433. .justifyContent(FlexAlign.Start)
  434. }
  435. }
  436. @ComponentV2
  437. struct GameOver{
  438. @Event onBack: (ans?:ESObject) => void
  439. @Param @Require param: BasicType
  440. @Local isWin: boolean = true
  441. aboutToAppear(): void {
  442. this.isWin = this.param.isShowClose ?? true
  443. }
  444. build() {
  445. Column({space: 9}){
  446. Row(){
  447. Image(this.isWin ? $r("app.media.icon_win") : $r("app.media.icon_fail"))
  448. .width(175)
  449. .height(105)
  450. }
  451. .width("100%")
  452. .position({y: -53})
  453. .justifyContent(FlexAlign.Center)
  454. Text(this.isWin ? '稳定性训练成功' : '稳定性训练失败')
  455. .fontSize(16)
  456. .fontWeight(500)
  457. .fontColor(Color.Black)
  458. .padding({top: 67, bottom: 46})
  459. Row(){
  460. Text(this.isWin ? '太棒了' : '继续努力')
  461. .fontSize(16)
  462. .fontWeight(500)
  463. }
  464. .borderRadius(8)
  465. .padding({left: 41, top: 16, right: 41, bottom: 16})
  466. .linearGradient({colors: [['#FFCC00', 0], ['#FF9F02', 1]], angle: 90})
  467. .onClick(() => { this.onBack() })
  468. }
  469. .width(294)
  470. .borderRadius(20)
  471. .padding({bottom: 30})
  472. .backgroundColor(Color.White)
  473. .justifyContent(FlexAlign.Start)
  474. .alignItems(HorizontalAlign.Center)
  475. }
  476. }