拆解PowerApps - 请假申请 - 7

上一节我们完成了页面 NewRequestScreen 的解析,那个页面相当于是提交请假申请的第一步,选择要请的假期的类型。

本节接下来会沿着这个申请,一步步解析相关的页面。
当点选了假期类型后,所跳转到的页面就是下面这个 SelectDatesScreen,让用户选择假期的开始日期和结束日期。

1. 页面结构
从上图能看出的是,整个页面由多种独立控件组成。从上到下,这个页面涉及到图标、标签、图片、几何形状、日期拾取器和按钮六种控件。

2. 控件解析
接下来我们就逐个看这些控件和如何结合在一起运行的。
首先,注意到SelectDatesScreen层面上设置了 OnVisible 属性:
OnVisible  = If(!_editingRequest && !_reviewRequest, Set(_leaveStart,Today());Set(_leaveEnd,Today()));    //如果当前既不是编辑之前的申请(!_editingRequest) 也不是查看之前的申请(!_reviewRequest),就把开始日期和结束日期都设置成当天(相当于是新建一个申请)。
//注意: 本节多次用到这两个布尔类型的变量 _editingRequest 和 _reviewRequest。
//这两个变量在之前的HomeScreen里有做过初始化设置,后续根据申请页面的状态不同,还有几个页面也对其进行了初始化设置。


2.1 iconBackSelectDates  - 左上角的返回按钮
OnSelect = Back();Reset(LeaveStartDatePicker);Reset(LeaveEndDatePicker)     //返回上一页,然后重置两个日期拾取器

2.2 LabelSelectDatesHeader - 页面标题
Text = If(_editingRequest, "Edit ", "Select ") & "dates"   //根据当前页面的属性是编辑之前的申请还是新建申请(通过变量 _editingRequest 进行控制),显示不同的标题

2.3 ImageLeaveType    - 假期类型图标  
Image = If(_editingRequest, LookUp(LeaveTypeCollection, Upper(type)=Upper(First(RequestEdit).LeaveType)).icon, _selectedLeaveType.icon) 
//和上面的标签控件很类似,也是根据当前页面的属性进行相应的后续处理。区别在于上面是直接固定设定好不同情况下的文字提示,这里是根据情况设置不同的图标。
//如果当前是编辑页面,就通过LookUp函数从LeaveTypeCollection里找出对应的假期类型图标; 否则就利用上一节传递过来的变量 _selectedLeaveType, 其实也是个对象,通过 . 运算符来获取所选的假期对应的图标。 
//这里还涉及到第四节设置的一个集合 RequestEdit ,其中存储的时用户要编辑的请假申请数据,后续会继续提及。

2.4 LabelLeaveType   - 假期类型名称  
Text = If(_editingRequest, First(RequestEdit).LeaveType, _selectedLeaveType.type)     //还是类似的逻辑,同时又用到了上一节传来的变量

2.5 LabelCurrentBalanceText   
Text = "Current balance: "    //文字固定的提示标签

2.6 LabelCurrentBalanceVal    - 当前可用的假期天数
Text = LookUp(RequesterBalanceCollection,     //Lookup函数的第一个参数:要去查询的数据源,这里设定的是第三节里创建的集合 RequesterBalanceCollection。顺便回忆一下,这个集合里存储的是员工当前可用的假期天数。
          Upper(type)=If(_editingRequest, Upper(First(RequestEdit).LeaveType), Upper(_selectedLeaveType.type)),     //Lookup 函数的第二个参数:查询条件
          Text(balance) &If(balance<2, " day", " days"))    //LookUp函数的结果,这里利用Text函数将依据 Type条件查询返回的结果,也就是假期天数(balance)转成了文本,然后和文字 day 或者 days组合成新的文本。

上面四个控件在有数据时,所显示出来的效果如下图所示:

2.7 Rectangle9_4  - 区域分割线

2.8 LabelSelectDates  - 提示性的文本信息
Text = "Select Dates"    //文字固定的提示标签

2.9 Label19    -- 假期起始日期的提示性文本
Text = "*From"        //文字固定的提示标签

2.10 LeaveStartDatePicker - 用来选择假期的起始日期
这个控件有四个关键的属性设置:
 - DateTimeZone = Local    //日期的时区设置
 - DefaultDate = If(_editingRequest, First(RequestEdit).StartDate, _reviewRequest, _leaveStart ,Today())   //设置页面打开后,日期选择器默认显示的日期。这里利用 IF(条件1,结果1,条件2,结果2,..., 条件n, 结果n, 默认结果 )的格式,定义了三种不同状态的显示日期: 编辑状态,查看状态,其它状态。
 - OnChange = Set(_leaveStart, LeaveStartDatePicker.SelectedDate)    //利用日期选择器选择了其它日期后,将新选的日期赋值给变量 _leaveStart
 - StartOfWeek = StartOfWeek.Sunday      //每周的起始日期设置为周日,这个设置会直接影响到诸如第四节里的假期天数计算逻辑。

2.11 Label19_1 - 假期结束日期的提示性文本
Text = "*From"        //文字固定的提示标签

2.12 LeaveEndDatePicker  - 用来选择假期的结束日期
运行逻辑和上面那个选择起始日期的控件一样,只是从开始日期变成了结束日期。
 - DateTimeZone = Local   
 - DefaultDate = If(_editingRequest, First(RequestEdit).EndDate, _reviewRequest, _leaveEnd, Today())
 - OnChange = Set(_leaveEnd, LeaveEndDatePicker.SelectedDate)
 - StartOfWeek = StartOfWeek.Sunday   

2.13 Label1 - 当日期选择不规范时(比如结束日期比开始日期还早),用来显示警告信息,提示用户重新选择正确的日期。
Text  = If(LeaveStartDatePicker.SelectedDate > LeaveEndDatePicker.SelectedDate || And(!_editingRequest, LeaveStartDatePicker.SelectedDate < Today()), "Start date must occur on or " & If(LeaveStartDatePicker.SelectedDate > LeaveEndDatePicker.SelectedDate,"before end date", "after today"))
如下图,出错时的警告提示效果:


2.14 Rectangle9_5  - 区域分割线

2.15 ButtonNextSelectDates - 页面最下面的下一步按钮
OnSelect = 
//**** 计算假期申请天数的预备代码段 - 开始位置 ****和第四节里计算假期申请天数的代码段相同的逻辑
If(LeaveStartDatePicker.SelectedDate <= LeaveEndDatePicker.SelectedDate,    //只是这里开头是通过一个 IF语句来处理条件判断,第四节里是直接开始
    Set(_inclusiveTotalDaysRequested, DateDiff(LeaveStartDatePicker.SelectedDate, LeaveEndDatePicker.SelectedDate, Days) + 1);   //这里也有点不同,但也只是变量名称的差别,逻辑上完全一样。
    Set(_numFullWeeks, RoundDown(_inclusiveTotalDaysRequested / 7, 0));
    Set(_numFullDaysPartialWeek, _inclusiveTotalDaysRequested - _numFullWeeks * 7);
    Concurrent(Set(_startWeekday, Weekday(LeaveStartDatePicker.SelectedDate)), Set(_endWeekday, Weekday(LeaveEndDatePicker.SelectedDate)));
   //下面的IF 代码段计算从所申请的总天数减去整周用掉的天数后,剩下的工作日天数
    If(_numFullDaysPartialWeek = 6,       If(_startWeekday <= 2, Set(_numPartialWeekdays, 5), Set(_numPartialWeekdays, 4)        ),
      _numFullDaysPartialWeek = 5,        If(_startWeekday = 2, Set(_numPartialWeekdays, 5), _startWeekday = 1 || _startWeekday = 3 || _startWeekday = 4, Set(_numPartialWeekdays, 4), Set(_numPartialWeekdays, 3)        ),
      _numFullDaysPartialWeek = 4,        If(_startWeekday = 2 || _startWeekday = 3, Set(_numPartialWeekdays, 4), _startWeekday = 1 || _startWeekday = 4, Set(_numPartialWeekdays, 3), Set(_numPartialWeekdays, 2)        ),
      _numFullDaysPartialWeek = 3,        If(_startWeekday = 6 || _startWeekday = 7, Set(_numPartialWeekdays, 1), _startWeekday = 1 || _startWeekday = 5, Set(_numPartialWeekdays, 2), Set(_numPartialWeekdays, 3)        ),
      _numFullDaysPartialWeek = 2,        If(_startWeekday = 7, Set(_numPartialWeekdays, 0), _startWeekday = 1 || _startWeekday = 6, Set(_numPartialWeekdays, 1), Set(_numPartialWeekdays, 2)),     
      _numFullDaysPartialWeek = 1,        If(_startWeekday = 1 || _startWeekday = 7, Set(_numPartialWeekdays, 0), Set(_numPartialWeekdays, 1)        ),
      _numFullDaysPartialWeek = 0, Set(_numPartialWeekdays, 0)
    );
      Set(_workDaysInRequest, _numFullWeeks * 5 + _numPartialWeekdays);  
      Set(_holidaysInRequest, CountIf(Holidays, StartDate >= LeaveStartDatePicker.SelectedDate, StartDate <= LeaveEndDatePicker.SelectedDate));
      Set(_requestedDays, _workDaysInRequest - _holidaysInRequest)
);
//**** 计算假期申请天数的代码段 - 结束位置 - 最终请假的天数存储在上面最后一个变量 _requestedDays 里****   

If(_editingRequest,  Patch(RequestEdit, First(RequestEdit), { StartDate: LeaveStartDatePicker.SelectedDate, EndDate: LeaveEndDatePicker.SelectedDate, DaysCount:_requestedDays }) ;  Navigate(EditRequestScreen, None),
   _reviewRequest, Back(), 
   Navigate(SelectApproverScreen, None)
)
//最后这个 IF 是在上面计算完假期天数后,再根据不同的页面状态执行不同的动作。
//如果当前是编辑页面,就把新选的日期通过 Patch 命令暂存到 RequestEdit 集合里,然后跳转到EditRequestScreen页面;
//如果当前是查看页面,就直接返回上一个页面;
//其它状态,就跳转到SelectApproverScreen页面。


附注:本节用到的函数:
Set, Concurrent, IF, Navigate, Reset, LookUp, First, Upper, Text, Patch
----------- 本节完成了对SelectDatesScreen页面的解析,我们下一节再见------------

 

猜你喜欢

转载自blog.csdn.net/aladinggao/article/details/113603920
今日推荐