|
@@ -55,6 +55,13 @@ export function scheduleCourseAvailable(
|
|
|
return course.availableToAll === true || (course.memberIds || []).includes(studentId);
|
|
return course.availableToAll === true || (course.memberIds || []).includes(studentId);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+export function scheduleCoursesForStudent(
|
|
|
|
|
+ courses: ScheduleCalendarData['courses'],
|
|
|
|
|
+ studentId: number,
|
|
|
|
|
+): ScheduleCalendarData['courses'] {
|
|
|
|
|
+ return courses.filter((course) => scheduleCourseAvailable(course, studentId));
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
export function scheduleCoachesWithAppointments(
|
|
export function scheduleCoachesWithAppointments(
|
|
|
coaches: ScheduleCalendarData['coaches'],
|
|
coaches: ScheduleCalendarData['coaches'],
|
|
|
appointments: ScheduleAppointment[],
|
|
appointments: ScheduleAppointment[],
|
|
@@ -129,7 +136,8 @@ export class OperationsScheduleComponent implements OnInit {
|
|
|
readonly unassignedCount=computed(()=>this.visibleAppointments().filter(item=>!item.coachId||item.coachAccountMissing).length);
|
|
readonly unassignedCount=computed(()=>this.visibleAppointments().filter(item=>!item.coachId||item.coachAccountMissing).length);
|
|
|
readonly hasScheduleFilters=computed(()=>Boolean(this.scheduleSearch().trim())||this.statusFilter()!=='all');
|
|
readonly hasScheduleFilters=computed(()=>Boolean(this.scheduleSearch().trim())||this.statusFilter()!=='all');
|
|
|
readonly filteredMembers=computed(()=>(this.data()?.members||[]).filter(member=>matchesScheduleSearch(this.memberSearch(),[member.displayName,member.mobileMasked,member.userId])).slice(0,12));
|
|
readonly filteredMembers=computed(()=>(this.data()?.members||[]).filter(member=>matchesScheduleSearch(this.memberSearch(),[member.displayName,member.mobileMasked,member.userId])).slice(0,12));
|
|
|
- readonly filteredCourses=computed(()=>(this.data()?.courses||[]).filter(course=>scheduleCourseAvailable(course,this.studentId())&&matchesScheduleSearch(this.courseSearch(),[course.courseName,course.categoryName,course.courseId])).slice(0,12));
|
|
|
|
|
|
|
+ readonly studentCourses=computed(()=>scheduleCoursesForStudent(this.data()?.courses||[],this.studentId()));
|
|
|
|
|
+ readonly filteredCourses=computed(()=>this.studentCourses().filter(course=>matchesScheduleSearch(this.courseSearch(),[course.courseName,course.categoryName,course.courseId])).slice(0,12));
|
|
|
readonly selectedCourse=computed(()=>this.data()?.courses.find((course)=>course.courseId===this.courseId()&&(!this.bindingId()||course.bindingId===this.bindingId())&&scheduleCourseAvailable(course,this.studentId()))||null);
|
|
readonly selectedCourse=computed(()=>this.data()?.courses.find((course)=>course.courseId===this.courseId()&&(!this.bindingId()||course.bindingId===this.bindingId())&&scheduleCourseAvailable(course,this.studentId()))||null);
|
|
|
readonly filteredCoaches=computed(()=>(this.data()?.coaches||[]).filter(coach=>matchesScheduleSearch(this.coachSearch(),[coach.displayName,coach.mobile,coach.mobileMasked,coach.userId])).sort((a,b)=>this.mode()==='time'?(Number(this.coachBusyAtSelectedTime(a.userId))-Number(this.coachBusyAtSelectedTime(b.userId)))||(Number(b.availabilityConfigured)-Number(a.availabilityConfigured))||a.displayName.localeCompare(b.displayName,'zh-CN'):a.displayName.localeCompare(b.displayName,'zh-CN')).slice(0,12));
|
|
readonly filteredCoaches=computed(()=>(this.data()?.coaches||[]).filter(coach=>matchesScheduleSearch(this.coachSearch(),[coach.displayName,coach.mobile,coach.mobileMasked,coach.userId])).sort((a,b)=>this.mode()==='time'?(Number(this.coachBusyAtSelectedTime(a.userId))-Number(this.coachBusyAtSelectedTime(b.userId)))||(Number(b.availabilityConfigured)-Number(a.availabilityConfigured))||a.displayName.localeCompare(b.displayName,'zh-CN'):a.displayName.localeCompare(b.displayName,'zh-CN')).slice(0,12));
|
|
|
readonly previewCandidates=computed(()=>schedulePreflightCandidates(this.preview()));
|
|
readonly previewCandidates=computed(()=>schedulePreflightCandidates(this.preview()));
|
|
@@ -159,7 +167,7 @@ export class OperationsScheduleComponent implements OnInit {
|
|
|
updateMemberSearch(value:string):void{this.memberSearch.set(value);this.studentId.set(0);this.selectedMemberObjectId.set('');this.courseId.set(0);this.bindingId.set('');this.courseSearch.set('');this.preview.set(null);this.openSearch('member');}
|
|
updateMemberSearch(value:string):void{this.memberSearch.set(value);this.studentId.set(0);this.selectedMemberObjectId.set('');this.courseId.set(0);this.bindingId.set('');this.courseSearch.set('');this.preview.set(null);this.openSearch('member');}
|
|
|
updateCourseSearch(value:string):void{this.courseSearch.set(value);this.courseId.set(0);this.bindingId.set('');this.openSearch('course');}
|
|
updateCourseSearch(value:string):void{this.courseSearch.set(value);this.courseId.set(0);this.bindingId.set('');this.openSearch('course');}
|
|
|
updateCoachSearch(value:string):void{this.coachSearch.set(value);this.coachId.set(0);this.openSearch('coach');}
|
|
updateCoachSearch(value:string):void{this.coachSearch.set(value);this.coachId.set(0);this.openSearch('coach');}
|
|
|
- chooseMember(member:ScheduleCalendarData['members'][number]):void{if(member.readOnly){this.error.set(member.readOnlyReason||'该会员尚未完成持续同步,当前只能查看实时资料,暂不能从新后台排课。');return;}const selectedCourse=this.data()?.courses.find(course=>course.courseId===this.courseId()&&course.bindingId===this.bindingId());this.studentId.set(member.userId);this.selectedMemberObjectId.set(member.objectId);this.memberSearch.set(`${member.displayName} · ${member.mobileMasked}`);if(selectedCourse&&!scheduleCourseAvailable(selectedCourse,member.userId)){this.courseId.set(0);this.bindingId.set('');this.courseSearch.set('');}this.activeSearch.set(null);this.preview.set(null);}
|
|
|
|
|
|
|
+ chooseMember(member:ScheduleCalendarData['members'][number]):void{if(member.readOnly){this.error.set(member.readOnlyReason||'该会员尚未完成持续同步,当前只能查看实时资料,暂不能从新后台排课。');return;}this.studentId.set(member.userId);this.selectedMemberObjectId.set(member.objectId);this.memberSearch.set(`${member.displayName} · ${member.mobileMasked}`);this.courseId.set(0);this.bindingId.set('');this.courseSearch.set('');const courses=scheduleCoursesForStudent(this.data()?.courses||[],member.userId);if(courses.length===1){this.chooseCourse(courses[0]);if(courses[0].mappingConfirmed)this.message.set(`已自动选择该学员唯一的已开课程:${courses[0].courseName}`);}else{this.activeSearch.set(courses.length?'course':null);}this.preview.set(null);}
|
|
|
chooseCourse(course:ScheduleCalendarData['courses'][number]):void{this.courseId.set(course.courseId);this.bindingId.set(course.bindingId||'');this.courseSearch.set(course.courseName);const first=course.supportedDurations?.[0];if(first)this.durationMinutes.set(first);this.activeSearch.set(null);this.preview.set(null);if(!course.mappingConfirmed)this.message.set('该开课分类缺少有效课时规则,请在排课与工资标准中配置。');}
|
|
chooseCourse(course:ScheduleCalendarData['courses'][number]):void{this.courseId.set(course.courseId);this.bindingId.set(course.bindingId||'');this.courseSearch.set(course.courseName);const first=course.supportedDurations?.[0];if(first)this.durationMinutes.set(first);this.activeSearch.set(null);this.preview.set(null);if(!course.mappingConfirmed)this.message.set('该开课分类缺少有效课时规则,请在排课与工资标准中配置。');}
|
|
|
chooseCoach(coach:ScheduleCalendarData['coaches'][number]):void{this.coachId.set(coach.userId);this.coachSearch.set(`${coach.displayName}${coach.mobileMasked?` · ${coach.mobileMasked}`:''}`);this.activeSearch.set(null);this.preview.set(null);}
|
|
chooseCoach(coach:ScheduleCalendarData['coaches'][number]):void{this.coachId.set(coach.userId);this.coachSearch.set(`${coach.displayName}${coach.mobileMasked?` · ${coach.mobileMasked}`:''}`);this.activeSearch.set(null);this.preview.set(null);}
|
|
|
clearCoach():void{this.coachId.set(0);this.coachSearch.set('');this.activeSearch.set(null);this.preview.set(null);}
|
|
clearCoach():void{this.coachId.set(0);this.coachSearch.set('');this.activeSearch.set(null);this.preview.set(null);}
|