鸿蒙任务项设置案例实战

目录

案例效果

资源文件与初始化

string.json

color.json

CommonConstant

添加任务

首页组件

任务列表初始化

任务列表视图

任务编辑页

添加跳转

任务目标设置模型(formatParams)

编辑页面

详情页

任务编辑列表项

目标设置展示

引入目标设置

目标设置展示实现

TaskInfo 枚举模型设置

弹窗构造逻辑

定义单击事件

定义 BroadCast

定义弹窗视图

定义弹窗 builder 组件

目标设置弹窗实现

目标设置窗口逻辑

任务目标设置视图模型

频率设置视图模型

时间提醒弹窗实现

更新TaskDetail

实现编辑任务列表的开启提醒与提醒时间

实现时间提醒弹窗

频率弹窗和提交完成的实现

实现频率任务项视图

实现频率设置弹窗

定义频率设置视图模型


案例效果

资源文件与初始化

string.json

{"string": [{"name": "entry_desc","value": "description"},{"name": "entryAbility_desc","value": "description"},{"name": "entryAbility_label","value": "List_HDC"},{"name": "task_morning","value": "早起"},{"name": "task_water","value": "喝水"},{"name": "task_apple","value": "吃苹果"},{"name": "task_smile","value": "每日微笑"},{"name": "task_brush","value": "每日刷牙"},{"name": "task_night","value": "早睡"},{"name": "already_open","value": "已开启"},{"name": "complete","value": "完成"},{"name": "frequency","value": "频率"},{"name": "remind_time","value": "提醒时间"},{"name": "open_reminder","value": "开启提醒"},{"name": "target_setting","value": "目标设置"},{"name": "cancel","value": "取消"},{"name": "confirm","value": "确认"},{"name": "set_your_frequency","value": "请设置您的频率"}]
}

color.json

{"color": [{"name": "white","value": "#FFFFFF"},{"name": "primaryBgColor","value": "#F1F3F5"},{"name": "titleColor","value": "#182431"},{"name": "btnBgColor","value": "#F2F2F2"},{"name": "statusTipColor","value": "#989A9C"},{"name": "blueColor","value": "#007DFF"},{"name": "black","value": "#000000"},{"name": "primaryRed","value": "#E92F4F"},{"name": "tabTitleColor","value": "#999"},{"name": "signatureColor","value": "#66686a"},{"name": "leveColor","value": "#c99411"},{"name": "leveBgColor","value": "#d4e6f1"},{"name": "borderColor","value": "#cccccc"},{"name": "mineBgColor","value": "#edf2f5"},{"name": "launcherBlueColor","value": "#4694C2"},{"name": "disabledColor","value": "#dddadc"}]
}

CommonConstant

// ets/common/contants/CommonConstant.etsexport const THOUSANDTH_80: string = '8%'
export const THOUSANDTH_100: string = '10%'
export const THOUSANDTH_400: string = '40%'
export const THOUSANDTH_500: string = '50%'
export const THOUSANDTH_560: string = '56%'
export const THOUSANDTH_800: string = '80%'
export const THOUSANDTH_900: string = '90%'
export const THOUSANDTH_940: string = '94%'
export const THOUSANDTH_1000: string = '100%'export const DEFAULT_2: number = 2
export const DEFAULT_8: number = 8
export const DEFAULT_12: number = 12
export const DEFAULT_10: number = 10
export const DEFAULT_16: number = 16
export const DEFAULT_18: number = 18
export const DEFAULT_20: number = 20
export const DEFAULT_24: number = 24
export const DEFAULT_28: number = 28
export const DEFAULT_32: number = 32
export const DEFAULT_48: number = 48
export const DEFAULT_56: number = 56
export const DEFAULT_60: number = 60export const LIST_ITEM_SPACE: number = 2export const ADD_TASK_TITLE: string = '添加任务'
export const EDIT_TASK_TITLE: string = '编辑任务'export const SETTING_FINISHED_MESSAGE = '设置完成!!!'
export const CHOOSE_TIME_OUT_RANGE: string = '选择时间超出范围'export const TODAY: string = new Date().toDateString()export const DEFAULT_TIME: string = '08:00'
export const GET_UP_TIME_RANGE: string = '(06:00 - 09:00)'
export const SLEEP_TIME_RANGE: string = '(20:00 - 23:00)'
export const GET_UP_EARLY_TIME: string = '06:00'
export const GET_UP_LATE_TIME: string = '09:00'
export const SLEEP_EARLY_TIME: string = '20:00'
export const SLEEP_LATE_TIME: string = '23:00'
export const DEFAULT_SELECTED_TIME: Date = new Date(`${TODAY} 8:00:00`)export const EVERYDAY: string = '每天'
export const NO_LENGTH: number = 0
export const INIT_WEEK_IDS: string = '1, 2, 3, 4, 5, 6, 7'export const PER_DAY: string = '/ 天'export const ZERO: number = 0
export const MINUS_20: number = -20
export const HAS_NO_INDEX: number = -1export const DRINK_STEP: number = 25
export const DRINK_MAX_RANGE: number = 500
export const TIMES_100: number = 100
export const EAT_APPLE_RANGE: number = 100
export const DEFAULT_TEXT: string = '0.25'
export const DEFAULT_APPLE: string = '1'

添加任务

首页组件

// ets/pages/Index.etsimport TaskList from '../view/TaskList'
import { TaskListItem, TaskInitList } from '../model/TaskInitList'
import { THOUSANDTH_1000, ADD_TASK_TITLE } from '../common/constants/CommonConstant'@Entry
@Component
struct Index {@Provide taskList: TaskListItem[] = TaskInitListbuild() {Row() {Navigation() {Column() {TaskList()}.width(THOUSANDTH_1000).justifyContent(FlexAlign.Center)}.size({ width: THOUSANDTH_1000, height: THOUSANDTH_1000 }).title(ADD_TASK_TITLE).titleMode(NavigationTitleMode.Mini)}.backgroundColor($r('app.color.primaryBgColor')).height(THOUSANDTH_1000)}
}

任务列表初始化

// ets/model/TaskInitList.etsexport interface TaskListItem {taskID: numbertaskName: ResourceisOpen: booleanunit: stringicon: ResourcetargetValue: stringisAlarm: booleanstartTime: stringfrequency: string
}export interface FrequencyContentType {id: number,label: string,isChecked: boolean
}export const TaskInitList: TaskListItem[] = [{ // Get up early.taskID: 1,taskName: $r('app.string.task_morning'),icon: $r('app.media.morning'),targetValue: '08: 00',isOpen: true,unit: '',isAlarm: false,startTime: '08: 00',frequency: '1, 2, 3, 4, 5, 6, 7'},{ // Drink water.taskID: 2,taskName: $r('app.string.task_water'),icon: $r('app.media.water'),targetValue: '0.25',isOpen: true,unit: 'L',isAlarm: false,startTime: '08: 00',frequency: '1, 2, 3, 4, 5, 6, 7'},{ // Eat apples.taskID: 3,taskName: $r('app.string.task_apple'),icon: $r('app.media.apple'),targetValue: '1',isOpen: true,unit: '个',isAlarm: false,startTime: '08: 00',frequency: '1, 2, 3, 4, 5, 6, 7'},{ // Smile every day.taskID: 4,taskName: $r('app.string.task_smile'),icon: $r('app.media.smile'),targetValue: '1',isOpen: false,unit: '次',isAlarm: false,startTime: '08: 00',frequency: '1, 2, 3, 4, 5, 6, 7'},{ // Clean one’s teeth.taskID: 5,taskName: $r('app.string.task_brush'),icon: $r('app.media.brush'),targetValue: '1',isOpen: false,unit: '次',isAlarm: false,startTime: '08: 00',frequency: '1, 2, 3, 4, 5, 6, 7'},{ // Go to bed early.taskID: 6,taskName: $r('app.string.task_night'),icon: $r('app.media.night'),targetValue: '20: 00',isOpen: false,unit: '',isAlarm: false,startTime: '08: 00',frequency: '1, 2, 3, 4, 5, 6, 7'}
]

任务列表视图

// ets/view/TaskList.etsimport * as commonConst from '../common/constants/CommonConstant'
import { TaskListItem } from '../model/TaskInitList'@Component
export default struct TaskList {@Consume taskList: TaskListItem[]build() {List({ space: commonConst.LIST_ITEM_SPACE }) {ForEach(this.taskList, (item: TaskListItem) => {ListItem() {Row() {Row() {Image(item?.icon).width(commonConst.DEFAULT_24).height(commonConst.DEFAULT_24).margin({ right: commonConst.DEFAULT_8 })Text(item?.taskName).fontSize(commonConst.DEFAULT_20).fontColor($r('app.color.titleColor'))}.width(commonConst.THOUSANDTH_500)Blank().layoutWeight(1)if (item?.isOpen) {Text($r('app.string.already_open')).fontSize(commonConst.DEFAULT_16).flexGrow(1).align(Alignment.End).margin({ right: commonConst.DEFAULT_8 }).fontColor($r('app.color.titleColor'))}Image($r('app.media.right_grey')).width(commonConst.DEFAULT_8).height(commonConst.DEFAULT_16)}.width(commonConst.THOUSANDTH_1000).justifyContent(FlexAlign.SpaceBetween).padding({ left: commonConst.DEFAULT_12, right: commonConst.DEFAULT_12 })}.height(commonConst.THOUSANDTH_80).borderRadius(commonConst.DEFAULT_12).backgroundColor($r('app.color.white'))})}.height(commonConst.THOUSANDTH_1000).width(commonConst.THOUSANDTH_940)}
}

任务编辑页

添加跳转

// ets/view/TaskList.etsimport * as commonConst from '../common/constants/CommonConstant'
import { TaskListItem } from '../model/TaskInitList'
import { router } from '@kit.ArkUI'
import { formatParams } from '../viewModel/TaskTargetSetting'@Component
export default struct TaskList {@Consume taskList: TaskListItem[]build() {List({ space: commonConst.LIST_ITEM_SPACE }) {ForEach(this.taskList, (item: TaskListItem) => {ListItem() {Row() {Row() {Image(item?.icon).width(commonConst.DEFAULT_24).height(commonConst.DEFAULT_24).margin({ right: commonConst.DEFAULT_8 })Text(item?.taskName).fontSize(commonConst.DEFAULT_20).fontColor($r('app.color.titleColor'))}.width(commonConst.THOUSANDTH_500)Blank().layoutWeight(1)if (item?.isOpen) {Text($r('app.string.already_open')).fontSize(commonConst.DEFAULT_16).flexGrow(1).align(Alignment.End).margin({ right: commonConst.DEFAULT_8 }).fontColor($r('app.color.titleColor'))}Image($r('app.media.right_grey')).width(commonConst.DEFAULT_8).height(commonConst.DEFAULT_16)}.width(commonConst.THOUSANDTH_1000).justifyContent(FlexAlign.SpaceBetween).padding({ left: commonConst.DEFAULT_12, right: commonConst.DEFAULT_12 })}.height(commonConst.THOUSANDTH_80).borderRadius(commonConst.DEFAULT_12).backgroundColor($r('app.color.white'))// 1. 添加链接.onClick(() => {router.pushUrl({url: 'pages/TaskEditPage',params: {params: formatParams(item)}})})})}.height(commonConst.THOUSANDTH_1000).width(commonConst.THOUSANDTH_940)}
}

任务目标设置模型(formatParams)

// ets/viewModel/TaskTargetSettingimport { TaskListItem } from '../model/TaskInitList'
export const formatParams = (params: TaskListItem) => {return JSON.stringify(params)
}

编辑页面

// ets/pages/TaskEditPage.etsimport { THOUSANDTH_1000, EDIT_TASK_TITLE } from '../common/constants/CommonConstant'
import TaskDetail from '../view/TaskDetail'@Entry
@Component
struct TaskEdit {build() {Row() {Navigation() {Column() {TaskDetail()}.width(THOUSANDTH_1000).height(THOUSANDTH_1000)}.size({ width: THOUSANDTH_1000, height: THOUSANDTH_1000 }).title(EDIT_TASK_TITLE).titleMode(NavigationTitleMode.Mini)}.height(THOUSANDTH_1000).backgroundColor($r('app.color.primaryBgColor'))}
}

详情页

// ets/view/TaskDetail.etsimport * as commonConst from '../common/constants/CommonConstant'
import { TaskListItem } from '../model/TaskInitList'
import {TaskChooseItem
} from './TaskEditListItem'
import { router } from '@kit.ArkUI'@Styles
function listItemStyle() {.backgroundColor($r('app.color.white')).height(commonConst.DEFAULT_56).borderRadius(commonConst.DEFAULT_10).padding({ left: commonConst.DEFAULT_12, right: commonConst.DEFAULT_12 })
}@Component
export default struct TaskDetail {@Provide settingParams: TaskListItem = this.parseRouterParams()parseRouterParams() {let params = router.getParams() as Record<string, Object>const routerParams: TaskListItem = JSON.parse(params.params as string)return routerParams}build() {Column() {List({ space: commonConst.LIST_ITEM_SPACE }) {ListItem() {TaskChooseItem()}.listItemStyle()}}.width(commonConst.THOUSANDTH_1000)}
}

任务编辑列表项

// ets/view/TaskEditListItem.etsimport { TaskListItem } from '../model/TaskInitList'
import {DEFAULT_20,DEFAULT_32,DEFAULT_56,THOUSANDTH_1000,
} from '../common/constants/CommonConstant'@Component
export struct TaskChooseItem {@Consume settingParams: TaskListItembuild() {Row() {Text(this.settingParams.taskName).fontSize(DEFAULT_20).fontWeight(FontWeight.Medium)Toggle({ type: ToggleType.Switch, isOn: this.settingParams.isOpen }).width(DEFAULT_56).height(DEFAULT_32).selectedColor($r('app.color.blueColor')).onChange((isOn: boolean) => {this.settingParams.isOpen = isOn;})}.width(THOUSANDTH_1000).justifyContent(FlexAlign.SpaceBetween)}
}

目标设置展示

引入目标设置

// ets/view/TaskDetail.etsimport * as commonConst from '../common/constants/CommonConstant'
import { TaskListItem } from '../model/TaskInitList'
import {TaskChooseItem,// 2. 引入TargetSetItemTargetSetItem
} from './TaskEditListItem'
import { router } from '@kit.ArkUI'
import { taskType } from '../model/TaskInfo'@Styles
function listItemStyle() {.backgroundColor($r('app.color.white')).height(commonConst.DEFAULT_56).borderRadius(commonConst.DEFAULT_10).padding({ left: commonConst.DEFAULT_12, right: commonConst.DEFAULT_12 })
}@Component
export default struct TaskDetail {@Provide settingParams: TaskListItem = this.parseRouterParams()parseRouterParams() {let params = router.getParams() as Record<string, Object>const routerParams: TaskListItem = JSON.parse(params.params as string)return routerParams}build() {Column() {List({ space: commonConst.LIST_ITEM_SPACE }) {ListItem() {TaskChooseItem()}.listItemStyle()// 1. 目标设置入口ListItem() {TargetSetItem()}.listItemStyle().enabled(this.settingParams?.isOpen &&(this.settingParams?.taskID !== taskType.smile) &&(this.settingParams?.taskID !== taskType.brushTeeth))}.width(commonConst.THOUSANDTH_940)}.width(commonConst.THOUSANDTH_1000)}
}

目标设置展示实现

// ets/view/TaskEditListItem.etsimport { TaskListItem } from '../model/TaskInitList'
import {DEFAULT_16,DEFAULT_20,DEFAULT_32,DEFAULT_56,DEFAULT_8,PER_DAY,THOUSANDTH_1000,
} from '../common/constants/CommonConstant'
import { taskType } from '../model/TaskInfo'// 2.定义公共样式targetSetCommon
@Extend(Text)
function targetSetCommon() {.fontSize(DEFAULT_16).flexGrow(1).margin({ right: DEFAULT_8 }).align(Alignment.End)
}// 2.定义公共样式targetSettingStyle
@Extend(Text)
function targetSettingStyle(isOpen: boolean, taskID: number) {.fontColor(isOpen && taskID !== taskType.smile && taskID !== taskType.brushTeeth ?$r('app.color.titleColor') :$r('app.color.disabledColor'))
}@Component
export struct TaskChooseItem {@Consume settingParams: TaskListItembuild() {Row() {Text(this.settingParams.taskName).fontSize(DEFAULT_20).fontWeight(FontWeight.Medium)Toggle({ type: ToggleType.Switch, isOn: this.settingParams.isOpen }).width(DEFAULT_56).height(DEFAULT_32).selectedColor($r('app.color.blueColor')).onChange((isOn: boolean) => {this.settingParams.isOpen = isOn;})}.width(THOUSANDTH_1000).justifyContent(FlexAlign.SpaceBetween)}
}// 1. 定义TargetSetItem组件
@Component
export struct TargetSetItem {@Consume settingParams: TaskListItem;build() {Row() {Text($r('app.string.target_setting')).fontSize(DEFAULT_20).fontWeight(FontWeight.Medium)Blank().layoutWeight(1)if (this.settingParams?.unit === '') {Text(`${this.settingParams?.targetValue}`).targetSetCommon().targetSettingStyle(this.settingParams?.isOpen, this.settingParams?.taskID)} else {Text(`${this.settingParams?.targetValue} ${this.settingParams?.unit} ${PER_DAY}`).targetSetCommon().targetSettingStyle(this.settingParams?.isOpen, this.settingParams?.taskID)}Image($r('app.media.right_grey')).width(DEFAULT_8).height(DEFAULT_16);}.width(THOUSANDTH_1000).justifyContent(FlexAlign.SpaceBetween)}
}

TaskInfo 枚举模型设置

// ets/model/TaskInfo.etsexport enum taskType {'getup' = 1,'drinkWater','eatApple','smile','brushTeeth','sleepEarly'
}

弹窗构造逻辑

定义单击事件

import * as commonConst from '../common/constants/CommonConstant'
import { TaskListItem } from '../model/TaskInitList'
import {TaskChooseItem,TargetSetItem
} from './TaskEditListItem'
import { router } from '@kit.ArkUI'
import { taskType } from '../model/TaskInfo'// 4. 引入BroadCast(先去创建)
import { BroadCast, BroadCastType } from '../common/utils/BroadCast'import { CustomDialogView } from './CustomDialogView'@Styles
function listItemStyle() {.backgroundColor($r('app.color.white')).height(commonConst.DEFAULT_56).borderRadius(commonConst.DEFAULT_10).padding({ left: commonConst.DEFAULT_12, right: commonConst.DEFAULT_12 })
}@Component
export default struct TaskDetail {@Provide settingParams: TaskListItem = this.parseRouterParams()// 5. 提供 broadCast@Provide broadCast: BroadCast = new BroadCast()parseRouterParams() {let params = router.getParams() as Record<string, Object>const routerParams: TaskListItem = JSON.parse(params.params as string)return routerParams}// 7. 先去定义弹窗和builder,注册(on)完,这里解绑aboutToAppear() {this.broadCast.off()}build() {Column() {List({ space: commonConst.LIST_ITEM_SPACE }) {ListItem() {TaskChooseItem()}.listItemStyle()ListItem() {TargetSetItem()}.listItemStyle()// 3. 设置 smile & brushTeeth 不可单击.enabled(this.settingParams?.isOpen &&(this.settingParams?.taskID !== taskType.smile) &&(this.settingParams?.taskID !== taskType.brushTeeth))// 1. 定义单击事件.onClick(() => {// 2. 测试单击,目的是引出第 3 步// console.log('test')// 8. 最后再触发this.broadCast.emit(BroadCastType.SHOW_TARGET_SETTING_DIALOG)})// 9. 测试提醒时间设置ListItem() {Text('提醒时间')}.listItemStyle().enabled(this.settingParams?.isOpen && this.settingParams?.isAlarm).onClick(() => {this.broadCast.emit(BroadCastType.SHOW_REMIND_TIME_DIALOG)})// 9. 测试频率设置ListItem() {Text('频率')}.listItemStyle().enabled(this.settingParams?.isOpen).onClick(() => {this.broadCast.emit(BroadCastType.SHOW_FREQUENCY_DIALOG)})}// 6.定义弹框视图(先去创建)CustomDialogView()}.width(commonConst.THOUSANDTH_1000)}
}

定义 BroadCast

// ets/common/util/BroadCast.etsexport class BroadCast {private callBackArray = []public on(event: string, callback: Function) {(this.callBackArray[event] || (this.callBackArray[event] = [])).push(callback)}public off() {this.callBackArray = []}public emit(event: string) {let _self = thisif (!this.callBackArray[event]) {return}let cbs: Function[] = this.callBackArray[event]if (cbs) {let len = cbs.length;for (let i = 0; i < len; i++) {try {cbs[i](_self)} catch (e) {new Error(e)}}}}
}export enum BroadCastType {SHOW_TARGET_SETTING_DIALOG = 'showTargetSettingDialog',SHOW_REMIND_TIME_DIALOG = 'showRemindTimeDialog',SHOW_FREQUENCY_DIALOG = 'showFrequencyDialog'
}

定义弹窗视图

// ets/view/CustomDialogView.etsimport { TargetSettingDialog, RemindTimeDialog, FrequencyDialog } from './TaskSettingDialog'
import { BroadCast, BroadCastType } from '../common/utils/BroadCast'
import { ZERO, MINUS_20 } from '../common/constants/CommonConstant'@Component
export struct CustomDialogView {@State isShow: boolean = false@Provide achievementLevel: number = 3@Consume broadCast: BroadCasttargetSettingDialogController: CustomDialogController = new CustomDialogController({builder: TargetSettingDialog(),autoCancel: true,alignment: DialogAlignment.Bottom,offset: { dx: ZERO, dy: MINUS_20 }})RemindTimeDialogController: CustomDialogController = new CustomDialogController({builder: RemindTimeDialog(),autoCancel: true,alignment: DialogAlignment.Bottom,offset: { dx: ZERO, dy: MINUS_20 }});FrequencyDialogController: CustomDialogController = new CustomDialogController({builder: FrequencyDialog(),autoCancel: true,alignment: DialogAlignment.Bottom,offset: { dx: ZERO, dy: MINUS_20 }})aboutToAppear() {let self = thisthis.broadCast.on(BroadCastType.SHOW_TARGET_SETTING_DIALOG,() => {self.targetSettingDialogController.open()})this.broadCast.on(BroadCastType.SHOW_REMIND_TIME_DIALOG,() => {self.RemindTimeDialogController.open()})this.broadCast.on(BroadCastType.SHOW_FREQUENCY_DIALOG,() => {self.FrequencyDialogController.open()})}build() {}
}

定义弹窗 builder 组件

// ets/view/TaskSettingDialog.etsimport * as commonConst from '../common/constants/CommonConstant'@CustomDialog
export struct TargetSettingDialog {controller: CustomDialogController = new CustomDialogController({builder: TargetSettingDialog()})build() {Column() {Text('target setting dialog')}.justifyContent(FlexAlign.Center).height(commonConst.THOUSANDTH_560).padding(commonConst.DEFAULT_12)}
}@CustomDialog
export struct RemindTimeDialog {controller: CustomDialogController = new CustomDialogController({builder: RemindTimeDialog()})build() {Column() {Text('remind time dialog')}.justifyContent(FlexAlign.Center).height(commonConst.THOUSANDTH_560).padding(commonConst.DEFAULT_12)}
}@CustomDialog
export struct FrequencyDialog {controller: CustomDialogController = new CustomDialogController({builder: FrequencyDialog()})build() {Column() {Text('frequency dialog')}.justifyContent(FlexAlign.Center).height(commonConst.THOUSANDTH_560).padding(commonConst.DEFAULT_12)}
}

目标设置弹窗实现

目标设置窗口逻辑

// ets/view/TaskSettingDialog.etsimport * as commonConst from '../common/constants/CommonConstant'
import { taskType } from '../model/TaskInfo'
import { TaskListItem } from '../model/TaskInitList'
import { createAppleRange, createDrinkRange, formatTime, returnTimeStamp } from '../viewModel/TaskTargetSetting'
import { promptAction } from '@kit.ArkUI'@CustomDialog
export struct TargetSettingDialog {controller: CustomDialogController = new CustomDialogController({builder: TargetSettingDialog()})@Consume settingParams: TaskListItemcurrentTime: string = commonConst.DEFAULT_TIMEcurrentValue: string = this.settingParams.taskID === taskType.drinkWater ? commonConst.DEFAULT_TEXT :commonConst.DEFAULT_APPLEdrinkRange: string[] = createDrinkRange()appleRange: string[] = createAppleRange()createSubTitle() {if (this.settingParams.taskID === taskType.getup) {return commonConst.GET_UP_TIME_RANGE}if (this.settingParams.taskID === taskType.sleepEarly) {return commonConst.SLEEP_TIME_RANGE}return ''}setTargetValue() {if (this.settingParams.taskID === taskType.getup) {if (!this.compareTime(commonConst.GET_UP_EARLY_TIME, commonConst.GET_UP_LATE_TIME)) {return}this.settingParams.targetValue = this.currentTimereturn}if (this.settingParams.taskID === taskType.sleepEarly) {if (!this.compareTime(commonConst.SLEEP_EARLY_TIME, commonConst.SLEEP_LATE_TIME)) {return}this.settingParams.targetValue = this.currentTimereturn}this.settingParams.targetValue = this.currentValue}compareTime(startTime: string, endTime: string) {if (returnTimeStamp(this.currentTime) < returnTimeStamp(startTime) ||returnTimeStamp(this.currentTime) > returnTimeStamp(endTime)) {promptAction.showToast({message: commonConst.CHOOSE_TIME_OUT_RANGE})return false}return true}build() {Column() {Row() {Text($r('app.string.target_setting')).fontSize(commonConst.DEFAULT_20).margin({ right: commonConst.DEFAULT_12 })Text(this.createSubTitle()).fontSize(commonConst.DEFAULT_16)}.width(commonConst.THOUSANDTH_1000).justifyContent(FlexAlign.Start)if ([taskType.getup, taskType.sleepEarly].indexOf(this.settingParams.taskID) > commonConst.HAS_NO_INDEX) {TimePicker({selected: commonConst.DEFAULT_SELECTED_TIME}).height(commonConst.THOUSANDTH_800).useMilitaryTime(true).onChange((value: TimePickerResult) => {this.currentTime = formatTime(value)})} else {TextPicker({ range: this.settingParams.taskID === taskType.drinkWater ? this.drinkRange : this.appleRange,value: this.settingParams.targetValue }).width(commonConst.THOUSANDTH_900).height(commonConst.THOUSANDTH_800).onChange((value: string | string[]) => {this.currentValue = (value as string)?.split(' ')[0]})}Row() {Text($r('app.string.cancel')).fontSize(commonConst.DEFAULT_20).fontColor($r('app.color.blueColor')).onClick(() => {this.currentTime = commonConst.DEFAULT_TIMEthis.currentValue = commonConst.DEFAULT_TEXTthis.controller.close()})Text($r('app.string.confirm')).fontSize(commonConst.DEFAULT_20).fontColor($r('app.color.blueColor')).onClick(() => {this.setTargetValue()this.controller.close()})}.justifyContent(FlexAlign.SpaceAround).width(commonConst.THOUSANDTH_1000).height(commonConst.DEFAULT_28).margin({ bottom: commonConst.DEFAULT_20 })}.justifyContent(FlexAlign.Center).height(commonConst.THOUSANDTH_560).padding(commonConst.DEFAULT_12)}
}@CustomDialog
export struct RemindTimeDialog {controller: CustomDialogController = new CustomDialogController({builder: RemindTimeDialog()})build() {Column() {Text('remind time dialog')}.justifyContent(FlexAlign.Center).height(commonConst.THOUSANDTH_560).padding(commonConst.DEFAULT_12)}
}@CustomDialog
export struct FrequencyDialog {controller: CustomDialogController = new CustomDialogController({builder: FrequencyDialog()})build() {Column() {Text('frequency dialog')}.justifyContent(FlexAlign.Center).height(commonConst.THOUSANDTH_560).padding(commonConst.DEFAULT_12)}
}

任务目标设置视图模型

// ets/TaskTargetSetting.etsimport { DRINK_MAX_RANGE, DRINK_STEP, EAT_APPLE_RANGE, TIMES_100, TODAY } from '../common/constants/CommonConstant'
import { TaskListItem } from '../model/TaskInitList'
import { padTo2Digits } from './FrequencySetting'export const formatParams = (params: TaskListItem) => {return JSON.stringify(params)
}export const formatTime = (value: TimePickerResult) => {let hour: number = 0let minute: number = 0if (value.hour !== undefined && value.minute !== undefined) {hour = value.hourminute = value.minute}return `${padTo2Digits(hour)}:${padTo2Digits(minute)}`
}export const createDrinkRange = () => {const drinkRangeArr: string[] = []for (let i = DRINK_STEP; i <= DRINK_MAX_RANGE; i += DRINK_STEP) {drinkRangeArr.push(`${i / TIMES_100} L`)}return drinkRangeArr
}export const createAppleRange = () => {const appleRangeArr: string[] = []for (let i = 1; i <= EAT_APPLE_RANGE; i++) {appleRangeArr.push(`${i} 个`)}return appleRangeArr
}export const returnTimeStamp = (currentTime: string) => {const timeString = `${TODAY} ${currentTime}`return new Date(timeString).getTime()
}

频率设置视图模型

// ets/viewModel/FrequencySetting.etsexport function padTo2Digits(num: number) {return num.toString().padStart(2, '0')
}

时间提醒弹窗实现

更新TaskDetail

// ets/view/TaskDetail.etsimport * as commonConst from '../common/constants/CommonConstant'
import { TaskListItem } from '../model/TaskInitList'
import {TaskChooseItem,TargetSetItem,// 3. 导入模块OpenRemindItem, RemindTimeItem
} from './TaskEditListItem'
import { router } from '@kit.ArkUI'
import { taskType } from '../model/TaskInfo'
import { BroadCast, BroadCastType } from '../common/utils/BroadCast'
import { CustomDialogView } from './CustomDialogView'@Styles
function listItemStyle() {.backgroundColor($r('app.color.white')).height(commonConst.DEFAULT_56).borderRadius(commonConst.DEFAULT_10).padding({ left: commonConst.DEFAULT_12, right: commonConst.DEFAULT_12 })
}@Component
export default struct TaskDetail {@Provide settingParams: TaskListItem = this.parseRouterParams()@Provide broadCast: BroadCast = new BroadCast()parseRouterParams() {let params = router.getParams() as Record<string, Object>const routerParams: TaskListItem = JSON.parse(params.params as string)return routerParams}aboutToAppear() {this.broadCast.off()}build() {Column() {List({ space: commonConst.LIST_ITEM_SPACE }) {ListItem() {TaskChooseItem()}.listItemStyle()ListItem() {TargetSetItem()}.listItemStyle().enabled(this.settingParams?.isOpen &&(this.settingParams?.taskID !== taskType.smile) &&(this.settingParams?.taskID !== taskType.brushTeeth)).onClick(() => {this.broadCast.emit(BroadCastType.SHOW_TARGET_SETTING_DIALOG)})// 1.构造编辑列表相应内容ListItem() {OpenRemindItem()}.listItemStyle().enabled(this.settingParams.isOpen)ListItem() {// 2.构造编辑列表相应内容RemindTimeItem()}.listItemStyle().onClick(() => {this.broadCast.emit(BroadCastType.SHOW_REMIND_TIME_DIALOG)})ListItem() {Text('频率')}.listItemStyle().onClick(() => {this.broadCast.emit(BroadCastType.SHOW_FREQUENCY_DIALOG)})}CustomDialogView()}.width(commonConst.THOUSANDTH_1000)}
}

实现编辑任务列表的开启提醒与提醒时间

import { TaskListItem } from '../model/TaskInitList'
import {DEFAULT_16,DEFAULT_20,DEFAULT_32,DEFAULT_56,DEFAULT_8,PER_DAY,THOUSANDTH_1000,
} from '../common/constants/CommonConstant'
import { taskType } from '../model/TaskInfo'@Extend(Text)
function targetSetCommon() {.fontSize(DEFAULT_16).flexGrow(1).margin({ right: DEFAULT_8 }).align(Alignment.End)
}@Extend(Text)
function targetSettingStyle(isOpen: boolean, taskID: number) {.fontColor(isOpen && taskID !== taskType.smile && taskID !== taskType.brushTeeth ?$r('app.color.titleColor') :$r('app.color.disabledColor'))
}@Extend(Text)
function remindTimeStyle(isOpen: boolean, isAlarm: boolean) {.fontColor(isOpen && isAlarm ? $r('app.color.titleColor') : $r('app.color.disabledColor'))
}@Component
export struct TaskChooseItem {@Consume settingParams: TaskListItembuild() {Row() {Text(this.settingParams.taskName).fontSize(DEFAULT_20).fontWeight(FontWeight.Medium)Toggle({ type: ToggleType.Switch, isOn: this.settingParams.isOpen }).width(DEFAULT_56).height(DEFAULT_32).selectedColor($r('app.color.blueColor')).onChange((isOn: boolean) => {this.settingParams.isOpen = isOn;})}.width(THOUSANDTH_1000).justifyContent(FlexAlign.SpaceBetween)}
}@Component
export struct TargetSetItem {@Consume settingParams: TaskListItembuild() {Row() {Text($r('app.string.target_setting')).fontSize(DEFAULT_20).fontWeight(FontWeight.Medium)Blank().layoutWeight(1)if (this.settingParams?.unit === '') {Text(`${this.settingParams?.targetValue}`).targetSetCommon().targetSettingStyle(this.settingParams?.isOpen, this.settingParams?.taskID)} else {Text(`${this.settingParams?.targetValue} ${this.settingParams?.unit} ${PER_DAY}`).targetSetCommon().targetSettingStyle(this.settingParams?.isOpen, this.settingParams?.taskID)}Image($r('app.media.right_grey')).width(DEFAULT_8).height(DEFAULT_16);}.width(THOUSANDTH_1000).justifyContent(FlexAlign.SpaceBetween)}
}// 1.实现开启提醒
@Component
export struct OpenRemindItem {@Consume settingParams: TaskListItembuild() {Row() {Text($r('app.string.open_reminder')).fontSize(DEFAULT_20).fontWeight(FontWeight.Medium)Blank().layoutWeight(1)Toggle({ type: ToggleType.Switch, isOn: this.settingParams?.isAlarm }).width(DEFAULT_56).height(DEFAULT_32).selectedColor($r('app.color.blueColor')).onChange((isOn: boolean) => {this.settingParams.isAlarm = isOn})}.width(THOUSANDTH_1000).justifyContent(FlexAlign.SpaceBetween)}
}// 2.实现提醒时间
@Component
export struct RemindTimeItem {@Consume settingParams: TaskListItembuild() {Row() {Text($r('app.string.remind_time')).fontSize(DEFAULT_20).fontWeight(FontWeight.Medium)Blank().layoutWeight(1)Text(this.settingParams?.startTime).targetSetCommon().remindTimeStyle(this.settingParams.isOpen, this.settingParams.isAlarm)Image($r('app.media.right_grey')).width(DEFAULT_8).height(DEFAULT_16)}.width(THOUSANDTH_1000).justifyContent(FlexAlign.SpaceBetween)}
}

实现时间提醒弹窗

import * as commonConst from '../common/constants/CommonConstant'
import { taskType } from '../model/TaskInfo'
import { TaskListItem } from '../model/TaskInitList'
import { createAppleRange, createDrinkRange, formatTime, returnTimeStamp } from '../viewModel/TaskTargetSetting'
import { promptAction } from '@kit.ArkUI'@CustomDialog
export struct TargetSettingDialog {controller: CustomDialogController = new CustomDialogController({builder: TargetSettingDialog()})@Consume settingParams: TaskListItemcurrentTime: string = commonConst.DEFAULT_TIMEcurrentValue: string = this.settingParams.taskID === taskType.drinkWater ? commonConst.DEFAULT_TEXT :commonConst.DEFAULT_APPLEdrinkRange: string[] = createDrinkRange()appleRange: string[] = createAppleRange()createSubTitle() {if (this.settingParams.taskID === taskType.getup) {return commonConst.GET_UP_TIME_RANGE}if (this.settingParams.taskID === taskType.sleepEarly) {return commonConst.SLEEP_TIME_RANGE}return ''}setTargetValue() {if (this.settingParams.taskID === taskType.getup) {if (!this.compareTime(commonConst.GET_UP_EARLY_TIME, commonConst.GET_UP_LATE_TIME)) {return}this.settingParams.targetValue = this.currentTimereturn}if (this.settingParams?.taskID === taskType.sleepEarly) {if (!this.compareTime(commonConst.SLEEP_EARLY_TIME, commonConst.SLEEP_LATE_TIME)) {return}this.settingParams.targetValue = this.currentTimereturn}this.settingParams.targetValue = this.currentValue}compareTime(startTime: string, endTime: string) {if (returnTimeStamp(this.currentTime) < returnTimeStamp(startTime) ||returnTimeStamp(this.currentTime) > returnTimeStamp(endTime)) {promptAction.showToast({message: commonConst.CHOOSE_TIME_OUT_RANGE})return false}return true}build() {Column() {Row() {Text($r('app.string.target_setting')).fontSize(commonConst.DEFAULT_20).margin({ right: commonConst.DEFAULT_12 })Text(this.createSubTitle()).fontSize(commonConst.DEFAULT_16)}.width(commonConst.THOUSANDTH_1000).justifyContent(FlexAlign.Start)if ([taskType.getup, taskType.sleepEarly].indexOf(this.settingParams.taskID) > commonConst.HAS_NO_INDEX) {TimePicker({selected: commonConst.DEFAULT_SELECTED_TIME}).height(commonConst.THOUSANDTH_800).useMilitaryTime(true).onChange((value: TimePickerResult) => {this.currentTime = formatTime(value)})} else {TextPicker({ range: this.settingParams?.taskID === taskType.drinkWater ? this.drinkRange : this.appleRange,value: this.settingParams.targetValue }).width(commonConst.THOUSANDTH_900).height(commonConst.THOUSANDTH_800).onChange((value: string | string[]) => {this.currentValue = (value as string)?.split(' ')[0]})}Row() {Text($r('app.string.cancel')).fontSize(commonConst.DEFAULT_20).fontColor($r('app.color.blueColor')).onClick(() => {this.currentTime = commonConst.DEFAULT_TIME;this.currentValue = commonConst.DEFAULT_TEXT;this.controller.close()})Text($r('app.string.confirm')).fontSize(commonConst.DEFAULT_20).fontColor($r('app.color.blueColor')).onClick(() => {this.setTargetValue()this.controller.close()})}.justifyContent(FlexAlign.SpaceAround).width(commonConst.THOUSANDTH_1000).height(commonConst.DEFAULT_28).margin({ bottom: commonConst.DEFAULT_20 })}.justifyContent(FlexAlign.Center).height(commonConst.THOUSANDTH_560).padding(commonConst.DEFAULT_12)}
}// 实现时间提醒弹窗
@CustomDialog
export struct RemindTimeDialog {controller: CustomDialogController = new CustomDialogController({builder: RemindTimeDialog()})currentTime: string = commonConst.DEFAULT_TIME@Consume settingParams: TaskListItembuild() {Column() {Column() {Text($r('app.string.remind_time')).fontSize(commonConst.DEFAULT_20).margin({ top: commonConst.DEFAULT_10 }).width(commonConst.THOUSANDTH_1000).textAlign(TextAlign.Start)}.width(commonConst.THOUSANDTH_900)TimePicker({selected: commonConst.DEFAULT_SELECTED_TIME}).height(commonConst.THOUSANDTH_800).useMilitaryTime(true).onChange((value: TimePickerResult) => {this.currentTime = formatTime(value)})Row() {Text($r('app.string.cancel')).fontSize(commonConst.DEFAULT_20).fontColor($r('app.color.blueColor')).onClick(() => {this.currentTime = commonConst.DEFAULT_TIMEthis.controller.close()})Text($r('app.string.confirm')).fontSize(commonConst.DEFAULT_20).fontColor($r('app.color.blueColor')).onClick(() => {this.settingParams.startTime = this.currentTimethis.controller.close()})}.justifyContent(FlexAlign.SpaceAround).width(commonConst.THOUSANDTH_1000).height(commonConst.DEFAULT_28).margin({ bottom: commonConst.DEFAULT_20 })}.justifyContent(FlexAlign.Center).height(commonConst.THOUSANDTH_560).padding(commonConst.DEFAULT_12)}
}@CustomDialog
export struct FrequencyDialog {controller: CustomDialogController = new CustomDialogController({builder: FrequencyDialog()})build() {Column() {Text('frequency dialog')}.justifyContent(FlexAlign.Center).height(commonConst.THOUSANDTH_560).padding(commonConst.DEFAULT_12)}
}

频率弹窗和提交完成的实现

// ets/view/TaskDetail.etsimport * as commonConst from '../common/constants/CommonConstant'
import { TaskListItem } from '../model/TaskInitList'
import {TaskChooseItem,TargetSetItem,OpenRemindItem,RemindTimeItem,FrequencyItem
} from './TaskEditListItem'
import { promptAction, router } from '@kit.ArkUI'
import { taskType } from '../model/TaskInfo'
import { BroadCast, BroadCastType } from '../common/utils/BroadCast'
import { CustomDialogView } from './CustomDialogView'@Styles
function listItemStyle() {.backgroundColor($r('app.color.white')).height(commonConst.DEFAULT_56).borderRadius(commonConst.DEFAULT_10).padding({ left: commonConst.DEFAULT_12, right: commonConst.DEFAULT_12 })
}@Component
export default struct TaskDetail {@Provide settingParams: TaskListItem = this.parseRouterParams()@Provide broadCast: BroadCast = new BroadCast()@Provide frequency: string = commonConst.EVERYDAYparseRouterParams() {let params = router.getParams() as Record<string, Object>const routerParams: TaskListItem = JSON.parse(params.params as string)return routerParams}aboutToAppear() {this.broadCast.off()}finishTaskEdit() {promptAction.showToast({message: commonConst.SETTING_FINISHED_MESSAGE})}build() {Column() {List({ space: commonConst.LIST_ITEM_SPACE }) {ListItem() {TaskChooseItem()}.listItemStyle()ListItem() {TargetSetItem()}.listItemStyle().enabled(this.settingParams?.isOpen &&(this.settingParams?.taskID !== taskType.smile) &&(this.settingParams?.taskID !== taskType.brushTeeth)).onClick(() => {this.broadCast.emit(BroadCastType.SHOW_TARGET_SETTING_DIALOG)})ListItem() {OpenRemindItem()}.listItemStyle().enabled(this.settingParams?.isOpen)ListItem() {RemindTimeItem()}.listItemStyle().onClick(() => {this.broadCast.emit(BroadCastType.SHOW_REMIND_TIME_DIALOG)})// 1. 引入FrequencyItemListItem() {FrequencyItem()}.listItemStyle().onClick(() => {this.broadCast.emit(BroadCastType.SHOW_FREQUENCY_DIALOG)})}.width(commonConst.THOUSANDTH_940)// x. 最后实现完成按钮提交Button() {Text($r('app.string.complete')).fontSize(commonConst.DEFAULT_20).fontColor($r('app.color.blueColor'))}.width(commonConst.THOUSANDTH_800).height(commonConst.DEFAULT_48).backgroundColor($r('app.color.borderColor')).onClick(() => {this.finishTaskEdit()}).position({x: commonConst.THOUSANDTH_100,y: commonConst.THOUSANDTH_800})CustomDialogView()}.width(commonConst.THOUSANDTH_1000)}
}

实现频率任务项视图

// ets/view/TaskEditListItem.etsimport { TaskListItem } from '../model/TaskInitList'
import {DEFAULT_12,DEFAULT_16,DEFAULT_20,DEFAULT_32,DEFAULT_56,DEFAULT_8,PER_DAY,THOUSANDTH_1000,
} from '../common/constants/CommonConstant'
import { taskType } from '../model/TaskInfo'@Extend(Text)
function targetSetCommon() {.fontSize(DEFAULT_16).flexGrow(1).margin({ right: DEFAULT_8 }).align(Alignment.End)
}@Extend(Text)
function targetSettingStyle(isOpen: boolean, taskID: number) {.fontColor(isOpen && taskID !== taskType.smile && taskID !== taskType.brushTeeth ?$r('app.color.titleColor') :$r('app.color.disabledColor'))
}@Extend(Text)
function remindTimeStyle(isOpen: boolean, isAlarm: boolean) {.fontColor(isOpen && isAlarm ? $r('app.color.titleColor') : $r('app.color.disabledColor'))
}@Extend(Text)
function frequencyStyle(isOpen: boolean) {.fontSize(DEFAULT_12).flexGrow(1).margin({ right: DEFAULT_8 }).textAlign(TextAlign.End).fontColor(isOpen ? $r('app.color.titleColor') : $r('app.color.disabledColor'))
}@Component
export struct TaskChooseItem {@Consume settingParams: TaskListItembuild() {Row() {Text(this.settingParams.taskName).fontSize(DEFAULT_20).fontWeight(FontWeight.Medium)Toggle({ type: ToggleType.Switch, isOn: this.settingParams.isOpen }).width(DEFAULT_56).height(DEFAULT_32).selectedColor($r('app.color.blueColor')).onChange((isOn: boolean) => {this.settingParams.isOpen = isOn;})}.width(THOUSANDTH_1000).justifyContent(FlexAlign.SpaceBetween)}
}@Component
export struct TargetSetItem {@Consume settingParams: TaskListItembuild() {Row() {Text($r('app.string.target_setting')).fontSize(DEFAULT_20).fontWeight(FontWeight.Medium)Blank().layoutWeight(1)if (this.settingParams?.unit === '') {Text(`${this.settingParams?.targetValue}`).targetSetCommon().targetSettingStyle(this.settingParams?.isOpen, this.settingParams?.taskID)} else {Text(`${this.settingParams?.targetValue} ${this.settingParams?.unit} ${PER_DAY}`).targetSetCommon().targetSettingStyle(this.settingParams?.isOpen, this.settingParams?.taskID)}Image($r('app.media.right_grey')).width(DEFAULT_8).height(DEFAULT_16);}.width(THOUSANDTH_1000).justifyContent(FlexAlign.SpaceBetween)}
}@Component
export struct OpenRemindItem {@Consume settingParams: TaskListItembuild() {Row() {Text($r('app.string.open_reminder')).fontSize(DEFAULT_20).fontWeight(FontWeight.Medium)Blank().layoutWeight(1)Toggle({ type: ToggleType.Switch, isOn: this.settingParams?.isAlarm }).width(DEFAULT_56).height(DEFAULT_32).selectedColor($r('app.color.blueColor')).onChange((isOn: boolean) => {this.settingParams.isAlarm = isOn})}.width(THOUSANDTH_1000).justifyContent(FlexAlign.SpaceBetween)}
}@Component
export struct RemindTimeItem {@Consume settingParams: TaskListItembuild() {Row() {Text($r('app.string.remind_time')).fontSize(DEFAULT_20).fontWeight(FontWeight.Medium)Blank().layoutWeight(1)Text(this.settingParams?.startTime).targetSetCommon().remindTimeStyle(this.settingParams.isOpen, this.settingParams.isAlarm)Image($r('app.media.right_grey')).width(DEFAULT_8).height(DEFAULT_16)}.width(THOUSANDTH_1000).justifyContent(FlexAlign.SpaceBetween)}
}// 1. 实现频率任务项视图
@Component
export struct FrequencyItem {@Consume settingParams: TaskListItem@Consume frequency: stringbuild() {Row() {Text($r('app.string.frequency')).fontSize(DEFAULT_20).fontWeight(FontWeight.Medium)Text(this.frequency).targetSetCommon().frequencyStyle(this.settingParams.isOpen)Image($r('app.media.right_grey')).width(DEFAULT_8).height(DEFAULT_16)}.width(THOUSANDTH_1000).justifyContent(FlexAlign.SpaceBetween)}
}

实现频率设置弹窗

// ets/view/TaskSettingDialog.etsimport * as commonConst from '../common/constants/CommonConstant'
import { taskType } from '../model/TaskInfo'
import { FrequencyContentType, TaskListItem } from '../model/TaskInitList'
import { createAppleRange, createDrinkRange, formatTime, returnTimeStamp } from '../viewModel/TaskTargetSetting'
import { promptAction } from '@kit.ArkUI'
import { frequencyRange } from '../viewModel/FrequencySetting'@CustomDialog
export struct TargetSettingDialog {controller: CustomDialogController = new CustomDialogController({builder: TargetSettingDialog()})@Consume settingParams: TaskListItemcurrentTime: string = commonConst.DEFAULT_TIMEcurrentValue: string = this.settingParams.taskID === taskType.drinkWater ? commonConst.DEFAULT_TEXT :commonConst.DEFAULT_APPLEdrinkRange: string[] = createDrinkRange()appleRange: string[] = createAppleRange()createSubTitle() {if (this.settingParams.taskID === taskType.getup) {return commonConst.GET_UP_TIME_RANGE}if (this.settingParams.taskID === taskType.sleepEarly) {return commonConst.SLEEP_TIME_RANGE}return ''}setTargetValue() {if (this.settingParams.taskID === taskType.getup) {if (!this.compareTime(commonConst.GET_UP_EARLY_TIME, commonConst.GET_UP_LATE_TIME)) {return}this.settingParams.targetValue = this.currentTimereturn}if (this.settingParams?.taskID === taskType.sleepEarly) {if (!this.compareTime(commonConst.SLEEP_EARLY_TIME, commonConst.SLEEP_LATE_TIME)) {return}this.settingParams.targetValue = this.currentTimereturn}this.settingParams.targetValue = this.currentValue}compareTime(startTime: string, endTime: string) {if (returnTimeStamp(this.currentTime) < returnTimeStamp(startTime) ||returnTimeStamp(this.currentTime) > returnTimeStamp(endTime)) {promptAction.showToast({message: commonConst.CHOOSE_TIME_OUT_RANGE})return false}return true}build() {Column() {Row() {Text($r('app.string.target_setting')).fontSize(commonConst.DEFAULT_20).margin({ right: commonConst.DEFAULT_12 })Text(this.createSubTitle()).fontSize(commonConst.DEFAULT_16)}.width(commonConst.THOUSANDTH_1000).justifyContent(FlexAlign.Start)if ([taskType.getup, taskType.sleepEarly].indexOf(this.settingParams.taskID) > commonConst.HAS_NO_INDEX) {TimePicker({selected: commonConst.DEFAULT_SELECTED_TIME}).height(commonConst.THOUSANDTH_800).useMilitaryTime(true).onChange((value: TimePickerResult) => {this.currentTime = formatTime(value)})} else {TextPicker({ range: this.settingParams?.taskID === taskType.drinkWater ? this.drinkRange : this.appleRange,value: this.settingParams.targetValue }).width(commonConst.THOUSANDTH_900).height(commonConst.THOUSANDTH_800).onChange((value: string | string[]) => {this.currentValue = (value as string)?.split(' ')[0]})}Row() {Text($r('app.string.cancel')).fontSize(commonConst.DEFAULT_20).fontColor($r('app.color.blueColor')).onClick(() => {this.currentTime = commonConst.DEFAULT_TIME;this.currentValue = commonConst.DEFAULT_TEXT;this.controller.close()})Text($r('app.string.confirm')).fontSize(commonConst.DEFAULT_20).fontColor($r('app.color.blueColor')).onClick(() => {this.setTargetValue()this.controller.close()})}.justifyContent(FlexAlign.SpaceAround).width(commonConst.THOUSANDTH_1000).height(commonConst.DEFAULT_28).margin({ bottom: commonConst.DEFAULT_20 })}.justifyContent(FlexAlign.Center).height(commonConst.THOUSANDTH_560).padding(commonConst.DEFAULT_12)}
}@CustomDialog
export struct RemindTimeDialog {controller: CustomDialogController = new CustomDialogController({builder: RemindTimeDialog()})currentTime: string = commonConst.DEFAULT_TIME@Consume settingParams: TaskListItembuild() {Column() {Column() {Text($r('app.string.remind_time')).fontSize(commonConst.DEFAULT_20).margin({ top: commonConst.DEFAULT_10 }).width(commonConst.THOUSANDTH_1000).textAlign(TextAlign.Start)}.width(commonConst.THOUSANDTH_900)TimePicker({selected: commonConst.DEFAULT_SELECTED_TIME}).height(commonConst.THOUSANDTH_800).useMilitaryTime(true).onChange((value: TimePickerResult) => {this.currentTime = formatTime(value);})Row() {Text($r('app.string.cancel')).fontSize(commonConst.DEFAULT_20).fontColor($r('app.color.blueColor')).onClick(() => {this.currentTime = commonConst.DEFAULT_TIMEthis.controller.close()})Text($r('app.string.confirm')).fontSize(commonConst.DEFAULT_20).fontColor($r('app.color.blueColor')).onClick(() => {this.settingParams.startTime = this.currentTimethis.controller.close()})}.justifyContent(FlexAlign.SpaceAround).width(commonConst.THOUSANDTH_1000).height(commonConst.DEFAULT_28).margin({ bottom: commonConst.DEFAULT_20 })}.justifyContent(FlexAlign.Center).height(commonConst.THOUSANDTH_560).padding(commonConst.DEFAULT_12)}
}// 1.实现频率设置弹窗
@CustomDialog
export struct FrequencyDialog {controller: CustomDialogController = new CustomDialogController({builder: FrequencyDialog()})private frequencyChooseRange: FrequencyContentType[] = frequencyRange()private currentFrequency: string = commonConst.EVERYDAY@Consume settingParams: TaskListItem@Consume frequency: stringsetFrequency() {const checkedArr = this.frequencyChooseRange.filter((item: FrequencyContentType) => item.isChecked)if (checkedArr.length === this.frequencyChooseRange.length || checkedArr.length === commonConst.NO_LENGTH) {this.currentFrequency = commonConst.EVERYDAYthis.settingParams.frequency = commonConst.INIT_WEEK_IDSreturn}this.currentFrequency = checkedArr.reduce((sum: string, current: FrequencyContentType) => {return sum + ' ' + current.label}, '')this.settingParams.frequency = checkedArr.reduce((sum: string, current: FrequencyContentType) => {return sum === '' ? sum + current.id : sum + ',' + current.id}, '')}build() {Column() {Column() {Text($r('app.string.set_your_frequency')).fontSize(commonConst.DEFAULT_20).margin({ top: commonConst.DEFAULT_10 }).width(commonConst.THOUSANDTH_1000).textAlign(TextAlign.Start)}.width(commonConst.THOUSANDTH_900)List() {ForEach(this.frequencyChooseRange, (item: FrequencyContentType) => {ListItem() {Row() {Text(item?.label).fontSize(commonConst.DEFAULT_20)Toggle({ type: ToggleType.Checkbox }).onChange((isOn: boolean) => {item.isChecked = isOn})}.width(commonConst.THOUSANDTH_1000).justifyContent(FlexAlign.SpaceBetween).height(commonConst.DEFAULT_60)}})}.divider({strokeWidth: commonConst.DEFAULT_2,color: $r('app.color.btnBgColor')}).flexGrow(1).padding(commonConst.DEFAULT_12).width(commonConst.THOUSANDTH_1000)Row() {Text($r('app.string.cancel')).fontSize(commonConst.DEFAULT_20).fontColor($r('app.color.blueColor')).onClick(() => {this.controller.close()})Text($r('app.string.confirm')).fontSize(commonConst.DEFAULT_20).fontColor($r('app.color.blueColor')).onClick(() => {this.setFrequency()this.frequency = this.currentFrequencythis.controller.close()})}.justifyContent(FlexAlign.SpaceAround).width(commonConst.THOUSANDTH_900).height(commonConst.DEFAULT_28).margin({ bottom: commonConst.DEFAULT_16 })}.justifyContent(FlexAlign.Center).height(commonConst.THOUSANDTH_940).padding(commonConst.DEFAULT_12)}
}

定义频率设置视图模型

// ets/viewModel/FrequencySetting.etsimport { FrequencyContentType } from "../model/TaskInitList"export function padTo2Digits(num: number) {return num.toString().padStart(2, '0')
}const chineseNumOfWeek: string[] = ['一', '二', '三', '四', '五', '六', '日']
const WEEK: string = '星期'export const frequencyRange = () => {const frequencyRangeArr: FrequencyContentType[] = []chineseNumOfWeek.forEach((item: string, index: number) => {frequencyRangeArr.push({id: (index + 1),label: `${WEEK}${item}`,isChecked: false})})return frequencyRangeArr
}

 基础知识:切换按钮 (Toggle)

Toggle组件提供状态按钮样式、勾选框样式和开关样式,一般用于两种状态之间的切换。

创建切换按钮

Toggle通过调用接口来创建,接口调用形式如下:

Toggle(options: { type: ToggleType, isOn?: boolean })

其中,ToggleType为开关类型,包括Button、Checkbox和Switch,isOn为切换按钮的状态。

API version 11开始,Checkbox默认样式由圆角方形变为圆形。

接口调用有以下两种形式:

  • 创建不包含子组件的Toggle。

当ToggleType为Checkbox或者Switch时,用于创建不包含子组件的Toggle:

Toggle({ type: ToggleType.Checkbox, isOn: false })
Toggle({ type: ToggleType.Checkbox, isOn: true })

Toggle({ type: ToggleType.Switch, isOn: false })
Toggle({ type: ToggleType.Switch, isOn: true })

  • 创建包含子组件的Toggle。

当ToggleType为Button时,只能包含一个子组件,如果子组件有文本设置,则相应的文本内容会显示在按钮上。

Toggle({ type: ToggleType.Button, isOn: false }) {Text('status button').fontColor('#182431').fontSize(12)
}.width(100)
Toggle({ type: ToggleType.Button, isOn: true }) {Text('status button').fontColor('#182431').fontSize(12)
}.width(100)

自定义样式

  • 通过selectedColor属性设置Toggle打开选中后的背景颜色。
Toggle({ type: ToggleType.Button, isOn: true }) {Text('status button').fontColor('#182431').fontSize(12)
}.width(100).selectedColor(Color.Pink)
Toggle({ type: ToggleType.Checkbox, isOn: true }).selectedColor(Color.Pink)
Toggle({ type: ToggleType.Switch, isOn: true }).selectedColor(Color.Pink)

  • 通过switchPointColor属性设置Switch类型的圆形滑块颜色,仅对type为ToggleType.Switch生效。
Toggle({ type: ToggleType.Switch, isOn: false }).switchPointColor(Color.Pink)
Toggle({ type: ToggleType.Switch, isOn: true }).switchPointColor(Color.Pink)

添加事件

除支持通用事件外,Toggle还用于选中和取消选中后触发某些操作,可以绑定onChange事件来响应操作后的自定义行为。

Toggle({ type: ToggleType.Switch, isOn: false }).onChange((isOn: boolean) => {if(isOn) {// 需要执行的操作}})

案例整理

// ets/pages/toggle/usagePage.ets@Entry
@Component
struct usagePage {@State isOn: boolean = truebuild() {Column({ space: 20 }) {Row() {Toggle({ type: ToggleType.Checkbox, isOn: false })Toggle({ type: ToggleType.Checkbox, isOn: true })}Row() {Toggle({ type: ToggleType.Switch, isOn: false })Toggle({ type: ToggleType.Switch, isOn: true })}Row() {Toggle({ type: ToggleType.Button, isOn: false }) {Text('status button').fontColor('#182431').fontSize(12)}.width(100)Toggle({ type: ToggleType.Button, isOn: true }) {Text('status button').fontColor('#182431').fontSize(12)}.width(100)}Row() {Toggle({ type: ToggleType.Button, isOn: true }) {Text('status button').fontColor('#182431').fontSize(12)}.width(100).selectedColor(Color.Orange)Toggle({ type: ToggleType.Checkbox, isOn: true }).selectedColor(Color.Orange)Toggle({ type: ToggleType.Switch, isOn: true }).selectedColor(Color.Orange)}Row() {Toggle({ type: ToggleType.Switch, isOn: false }).switchPointColor(Color.Orange)Toggle({ type: ToggleType.Switch, isOn: true }).switchPointColor(Color.Orange)}Row() {Toggle({ type: ToggleType.Switch, isOn: this.isOn }).onChange((isOn: boolean) => {this.isOn = !this.isOn})Text(`${this.isOn}`)}}.width('100%')}
}

场景示例

Toggle用于切换蓝牙开关状态。

// ets/pages/toggle/CasePage.etsimport { promptAction } from '@kit.ArkUI';@Entry
@Component
struct CasePage {@State BOnSt: promptAction.ShowToastOptions = { 'message': 'Bluetooth is on.' }@State BOffSt: promptAction.ShowToastOptions = { 'message': 'Bluetooth is off.' }build() {Column() {Row() {Text("Bluetooth Mode").height(50).fontSize(16)}Row() {Text("Bluetooth").height(50).padding({ left: 10 }).fontSize(16).textAlign(TextAlign.Start).backgroundColor(0xFFFFFF)Toggle({ type: ToggleType.Switch }).margin({ left: 200, right: 10 }).onChange((isOn: boolean) => {if (isOn) {promptAction.showToast(this.BOnSt)} else {promptAction.showToast(this.BOffSt)}})}.backgroundColor(0xFFFFFF)}.padding(10).backgroundColor(0xDCDCDC).width('100%').height('100%')}
}

基础知识:学习Picker选择器

CalendarPicker

示例

// ets/pages/picker/CalendarPickerPage.ets@Entry
@Component
struct CalendarPickerPage {private selectedDate: Date = new Date('2025-03-05')build() {Column() {Text('月历日期选择器').fontSize(30)Column() {CalendarPicker({ hintRadius: 10, selected: this.selectedDate }).edgeAlign(CalendarAlign.END).textStyle({ color: "#182431", font: { size: 20, weight: FontWeight.Normal } }).margin(10).onChange((value) => {console.info("CalendarPicker onChange:" + JSON.stringify(value))})}.alignItems(HorizontalAlign.End).width("100%")}.width('100%')}
}

DatePicker

示例

// ets/pages/picker/DatePickerPage.ets@Entry
@Component
struct DatePickerPage {@State isLunar: boolean = falseprivate selectedDate: Date = new Date('2025-08-08')build() {Column() {Button('切换公历农历').margin({ top: 30, bottom: 30 }).onClick(() => {this.isLunar = !this.isLunar})DatePicker({start: new Date('1970-1-1'),end: new Date('2100-1-1'),selected: this.selectedDate}).disappearTextStyle({ color: Color.Gray, font: { size: '16fp', weight: FontWeight.Bold } }).textStyle({ color: '#182431', font: { size: '18fp', weight: FontWeight.Normal } }).selectedTextStyle({ color: '#0000FF', font: { size: '26fp', weight: FontWeight.Regular } }).lunar(this.isLunar).onDateChange((value: Date) => {this.selectedDate = valueconsole.info('select current date is: ' + value.toString())})}.width('100%')}
}

TextPicker

示例1(设置选择器列数)

该示例通过配置range实现单列或多列文本选择器。

// ets/pages/picker/TextPicker01Page.etsclass bottom {bottom: number = 50
}let bott: bottom = new bottom()@Entry
@Component
struct TextPicker01Page {private select: number = 1private apFruits: string[] = ['apple1', 'apple2', 'apple3', 'apple4']private orFruits: string[] = ['orange1', 'orange2', 'orange3', 'orange4']private peFruits: string[] = ['peach1', 'peach2', 'peach3', 'peach4']private multi: string[][] = [this.apFruits, this.orFruits, this.peFruits]private cascade: TextCascadePickerRangeContent[] = [{text: '辽宁省',children: [{ text: '沈阳市', children: [{ text: '沈河区' }, { text: '和平区' }, { text: '浑南区' }] },{ text: '大连市', children: [{ text: '中山区' }, { text: '金州区' }, { text: '长海县' }] }]},{text: '吉林省',children: [{ text: '长春市', children: [{ text: '南关区' }, { text: '宽城区' }, { text: '朝阳区' }] },{ text: '四平市', children: [{ text: '铁西区' }, { text: '铁东区' }, { text: '梨树县' }] }]},{text: '黑龙江省',children: [{ text: '哈尔滨市', children: [{ text: '道里区' }, { text: '道外区' }, { text: '南岗区' }] },{ text: '牡丹江市', children: [{ text: '东安区' }, { text: '西安区' }, { text: '爱民区' }] }]}]build() {Column() {TextPicker({ range: this.apFruits, selected: this.select }).onChange((value: string | string[], index: number | number[]) => {console.info('Picker item changed, value: ' + value + ', index: ' + index)}).margin(bott)TextPicker({ range: this.multi }).onChange((value: string | string[], index: number | number[]) => {console.info('TextPicker 多列:onChange ' + JSON.stringify(value) + ', ' + 'index: ' + JSON.stringify(index))}).margin(bott)TextPicker({ range: this.cascade }).onChange((value: string | string[], index: number | number[]) => {console.info('TextPicker 多列联动:onChange ' + JSON.stringify(value) + ', ' + 'index: ' +JSON.stringify(index))})}}
}

示例2(设置文本样式)

该示例通过配置disappearTextStyle、textStyle、selectedTextStyle实现文本选择器中的文本样式。

// ets/pages/picker/TextPicker02Page.ets@Entry
@Component
struct TextPicker02Page {private select: number = 1private fruits: string[] = ['apple1', 'orange2', 'peach3', 'grape4']build() {Column() {TextPicker({ range: this.fruits, selected: this.select }).onChange((value: string | string[], index: number | number[]) => {console.info('Picker item changed, value: ' + value + ', index: ' + index)}).disappearTextStyle({ color: Color.Red, font: { size: 15, weight: FontWeight.Lighter } }).textStyle({ color: Color.Black, font: { size: 20, weight: FontWeight.Normal } }).selectedTextStyle({ color: Color.Blue, font: { size: 30, weight: FontWeight.Bolder } })}.width('100%').height('100%')}
}

示例3(设置无分割线样式)

该示例通过配置divider为null实现无分割线样式的文本选择器。

// ets/pages/picker/TextPicker03Page.ets@Entry
@Component
struct TextPicker03Page {private select: number = 1private fruits: string[] = ['apple1', 'orange2', 'peach3', 'grape4']build() {Column() {TextPicker({ range: this.fruits, selected: this.select }).onChange((value: string | string[], index: number | number[]) => {console.info('Picker item changed, value: ' + value + ', index: ' + index)}).disappearTextStyle({color: Color.Red, font: {size: 15, weight: FontWeight.Lighter}}).textStyle({color: Color.Black, font: {size: 20, weight: FontWeight.Normal}}).selectedTextStyle({color: Color.Blue, font: {size: 30, weight: FontWeight.Bolder}}).divider(null)}.width('100%').height('100%')}
}

示例4(设置分割线样式)

该示例通过配置divider的DividerOptions类型实现分割线样式的文本选择器。

// ets/pages/picker/TextPicker04Page.ets@Entry
@Component
struct TextPicker04Page {private select: number = 1private fruits: string[] = ['apple1', 'orange2', 'peach3', 'grape4']build() {Column() {TextPicker({ range: this.fruits, selected: this.select }).onChange((value: string | string[], index: number | number[]) => {console.info('Picker item changed, value: ' + value + ', index: ' + index)}).disappearTextStyle({ color: Color.Red, font: { size: 15, weight: FontWeight.Lighter } }).textStyle({ color: Color.Black, font: { size: 20, weight: FontWeight.Normal } }).selectedTextStyle({ color: Color.Blue, font: { size: 30, weight: FontWeight.Bolder } }).divider({strokeWidth: 10,color: Color.Red,startMargin: 10,endMargin: 20} as DividerOptions)}.width('100%').height('100%')}
}

示例5(设置渐隐效果)

该示例通过gradientHeight自定义TextPicker的渐隐效果高度。

// ets/pages/picker/TextPicker05Page.ets@Entry
@Component
struct TextPicker05Page {private select: number = 1private fruits: string[] = ['apple1', 'orange2', 'peach3', 'grape4']build() {Column() {TextPicker({ range: this.fruits, selected: this.select }).onChange((value: string | string[], index: number | number[]) => {console.info('Picker item changed, value: ' + value + ', index: ' + index)}).disappearTextStyle({ color: Color.Red, font: { size: 15, weight: FontWeight.Lighter } }).textStyle({ color: Color.Black, font: { size: 20, weight: FontWeight.Normal } }).selectedTextStyle({ color: Color.Blue, font: { size: 30, weight: FontWeight.Bolder } }).gradientHeight(100)}.width('100%').height('100%')}
}

TimePicker

示例

// ets/pages/picker/TimePicker.ets@Entry
@Component
struct TimePickerExample {@State isMilitaryTime: boolean = falseprivate selectedTime: Date = new Date('2025-07-22T08:00:00')build() {Column() {Button('切换12小时制/24小时制').margin(30).onClick(() => {this.isMilitaryTime = !this.isMilitaryTime})TimePicker({selected: this.selectedTime,format: TimePickerFormat.HOUR_MINUTE_SECOND}).useMilitaryTime(this.isMilitaryTime).onChange((value: TimePickerResult) => {if(value.hour >= 0) {this.selectedTime.setHours(value.hour, value.minute)console.info(`${value}`)}}).disappearTextStyle({color: Color.Red, font: {size: 15, weight: FontWeight.Lighter}}).textStyle({color: Color.Black, font: {size: 20, weight: FontWeight.Normal}}).selectedTextStyle({color: Color.Blue, font: {size: 30, weight: FontWeight.Bolder}})}.width('100%')}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/news/908287.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DeepSeek-R1-0528重磅升级:三大突破重新定义AI生产力

2025年5月28日&#xff0c;中国AI领军企业深度求索&#xff08;DeepSeek&#xff09;正式发布DeepSeek-R1-0528版本&#xff0c;这是继2025年1月R1模型登顶中美App Store后&#xff0c;DeepSeek在通用大模型领域的又一次战略级突破。此次升级虽为小版本迭代&#xff0c;却在推理…

【算法训练营Day07】字符串part1

文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接&#xff1a;344. 反转字符串 双指针法&#xff0c;两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …

中国西部逐日1 km全天候地表温度数据集(TRIMS LST-TP;2000-2024)

时间分辨率&#xff1a;日空间分辨率&#xff1a;100m - 1km共享方式&#xff1a;开放获取数据大小&#xff1a;474.31 GB数据时间范围&#xff1a;2000-01-01 — 2024-12-31元数据更新时间&#xff1a;2025-05-31 数据集摘要 青藏高原是全球气候变化的敏感区域。地表温度&…

PPT转图片拼贴工具 v1.0

软件介绍 这个软件的作用就是将单个PPT的每一页转换为单独的图片&#xff0c;然后将图片进行拼接起来。 但是我没有还没有解决一次性处理多个文件。 效果展示如下&#xff1a; 软件安装 软件源码 import os import re import win32com.client from PIL import Imagedef con…

嵌入式学习笔记DAY33(网络编程——TCP)

一、网络架构 C/S &#xff08;client/server 客户端/服务器&#xff09;&#xff1a;由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序&#xff0c;负责提供用户界面和交互逻辑 &#xff0c;接收用户输入&#xff0c;向服务器发送请求&#xff0c;并展示服务…

抛砖引玉:RadarDet4D,NuScenes数据集Radar模态目标检测第二名(即将开源)

这几年一直在关注自动驾驶3D目标检测相关的研究。在NuScenes数据集上有很多经典的模型被提出并得到了验证&#xff0c;纯视觉3D目标检测经典的方法有BEVFormer、BEVDet系列、DETR3D、Sparse4D等工作&#xff0c;基于LiDAR的有CenterPoint、多模态有BEVFusion、DAL、UniTR等。 …

更新Java的环境变量后VScode/cursor里面还是之前的环境变量

最近我就遇到这个问题&#xff0c;这个一般是安装了多个版本的Java&#xff0c;并设置好环境变量&#xff0c;但VScode/cursor内部环境变量却没有改变 解决办法 打开设置&#xff0c;或者直接快捷键CTRL&#xff0c;搜索Java:Home编辑settings.json文件 把以下部分改为正确的…

线程的基础知识

进程和线程的区别&#xff1f; 从实例去引入我们的进程和线程的概念&#xff0c;说出进程和线程的关系&#xff0c;引出线程&#xff0c;说出两者的内存分配占用&#xff0c;上下文切换的区别 当操作系统把我们磁盘中的程序加载到我们的内存当中&#xff0c;为其分配内存空间&a…

x86 汇编中的【条件跳转指令】:从基础到扩展的全面解析(查表版)

为了彻底覆盖 x86 架构中所有条件跳转指令&#xff0c;包括 8086 到现代 x86-64 的全部变体&#xff0c;我重新整理了分类体系&#xff0c;并补充了鲜为人知的指令变体、操作数大小前缀和历史演进。 本文需要运用的知识(需要详细了解可点击对应的点)&#xff1a; flags寄存器…

FPGA点亮ILI9488驱动的SPI+RGB接口LCD显示屏(一)

FPGA点亮ILI9488驱动的SPIRGB接口LCD显示屏 ILI9488 RGB接口初始化 目录 前言 一、ILI9488简介 二、3线SPI接口简介 三、配置寄存器介绍 四、手册和初始化verilog FPGA代码 总结 前言 ILI9488是一款广泛应用于嵌入式系统和电子设备的彩色TFT LCD显示控制器芯片。本文将介…

Git忽略规则.gitignore不生效解决

我在gitlab中新建了一个项目仓库&#xff0c;先把项目文件目录绑定到仓库&#xff0c;并全部文件都上传到了仓库中。 然后又从别的项目复制了忽略文件配置过来&#xff0c;怎么搞他都不能生效忽略我不要提交仓库的文件。 从网上查到说在本地仓库目录中&#xff0c;打开命…

记一个判决书查询API接口的开发文档

一、引言 在企业风控、背景调查、尽职调查等场景中&#xff0c;判决书查询是一个非常重要的环节。通过判决书查询&#xff0c;可以了解个人或企业的司法涉诉情况&#xff0c;为风险评估提供数据支持。本文将详细介绍如何开发和使用一个司法涉诉查询API接口&#xff0c;包括客户…

mac版excel如何制作时长版环形图

设置辅助列 创建簇状柱形图 将辅助列绘制在次坐标轴 工作时长在主坐标轴&#xff0c;右键分别更改图表类型为圆环。 辅助列圆环全部为灰色&#xff0c;边框为白色 辅助列设置透明度100% 设置辅助列和工作时长列同样的圆环大小 可得 核心&#xff1a;只要辅助列边框不透明…

贪心算法应用:埃及分数问题详解

贪心算法与埃及分数问题详解 埃及分数&#xff08;Egyptian Fractions&#xff09;问题是数论中的经典问题&#xff0c;要求将一个真分数表示为互不相同的单位分数之和。本文将用2万字全面解析贪心算法在埃及分数问题中的应用&#xff0c;涵盖数学原理、算法设计、Java实现、优…

量化面试绿皮书:1. 海盗分金博弈

文中内容仅限技术学习与代码实践参考&#xff0c;市场存在不确定性&#xff0c;技术分析需谨慎验证&#xff0c;不构成任何投资建议。 1. 海盗分金博弈 五个海盗抢走了一个装满 100 枚金币的箱子。作为一群民主的海盗&#xff0c;他们同意以下分配战利品的方法:最资深的海盗将…

购物商城网站 Java+Vue.js+SpringBoot,包括商家管理、商品分类管理、商品管理、在线客服管理、购物订单模块

购物商城网站 JavaVue.jsSpringBoot&#xff0c;包括商家管理、商品分类管理、商品管理、在线客服管理、购物订单模块 百度云盘链接&#xff1a;https://pan.baidu.com/s/10W0kpwswDSmtbqYFsQmm5w 密码&#xff1a;68jy 摘 要 随着科学技术的飞速发展&#xff0c;各行各业都在…

用mediamtx搭建简易rtmp,rtsp视频服务器

简述&#xff1a; 平常测试的时候搭建rtmp服务器很麻烦&#xff0c;这个mediamtx服务器&#xff0c;只要下载就能运行&#xff0c;不用安装、编译、配置等&#xff0c;简单易用、ffmpeg推流、vlc拉流 基础环境&#xff1a; vmware17&#xff0c;centos10 64位&#xff0c;wi…

Java 高频面试题场景(二):老年健康手环数据管理系统

系列文章 序号文章名称1Java 高频面试题场景(一):社区智能充电桩管理系统2Java 高频面试题场景(二):老年健康手环数据管理系统文章目录 系列文章一、项目信息项目介绍技术栈主要工作二、面试题及回答1. **面试官问**:在这个老年健康手环数据管理系统项目中,为什么要用R…

Python爬虫爬取天猫商品数据,详细教程【Python经典实战项目】

Python爬取天猫商品数据详细教程 一、前期准备 1. 环境配置 Python环境&#xff1a;确保已安装Python 3.x版本&#xff0c;建议使用Anaconda或直接从Python官网下载安装。第三方库&#xff1a; requests&#xff1a;用于发送HTTP请求。BeautifulSoup&#xff1a;用于解析HTM…

Symbol as Points: Panoptic Symbol Spotting via Point-based Representation

文章目录 AbstractIntroductionRelated WorkVector Graphics RecognitionPanoptic Symbol SpottingPoint Cloud Segmentation MethodFrom Symbol to PointsPrimitive positionPrimitive feature Panoptic Symbol Spotting via Point-based RepresentationBackboneSymbol Spotti…