|
|
@@ -2899,11 +2899,10 @@ function addBusinessDays(dateKey,days) { return businessDate(new Date(new Date(d
|
|
|
function scheduleTrendRange(period,today=businessDate()) { if(!['week','month','year'].includes(period))fail(400,'排课趋势时间维度无效');if(period==='week')return{dateFrom:addBusinessDays(today,-6),dateTo:today,periodLabel:'近 7 天'};if(period==='month')return{dateFrom:today.slice(0,8)+'01',dateTo:today,periodLabel:'本月'};return{dateFrom:today.slice(0,4)+'-01-01',dateTo:today,periodLabel:'本年'}; }
|
|
|
function scheduleTrendFromSnapshot(snapshot,period,today=businessDate()) {
|
|
|
const range=scheduleTrendRange(period,today),buckets=[],weekdays=['周日','周一','周二','周三','周四','周五','周六'];
|
|
|
- if(period==='year'){const year=today.slice(0,4),monthCount=number(today.slice(5,7));for(let month=1;month<=monthCount;month++){const key=year+'-'+String(month).padStart(2,'0');buckets.push({key,label:year+'年'+month+'月',shortLabel:month+'月'});}}
|
|
|
- else{for(let key=range.dateFrom;key<=range.dateTo;key=addBusinessDays(key,1)){const month=number(key.slice(5,7)),day=number(key.slice(8,10)),weekday=new Date(key+'T12:00:00+08:00').getDay();buckets.push({key,label:month+'月'+day+'日',shortLabel:period==='week'?weekdays[weekday]:day+'日'});}}
|
|
|
+ for(let key=range.dateFrom;key<=range.dateTo;key=addBusinessDays(key,1)){const month=number(key.slice(5,7)),day=number(key.slice(8,10)),weekday=new Date(key+'T12:00:00+08:00').getDay();buckets.push({key,label:month+'月'+day+'日',shortLabel:period==='week'?weekdays[weekday]:period==='year'?month+'/'+day:day+'日'});}
|
|
|
const byKey=new Map(buckets.map((bucket)=>[bucket.key,{courseCount:0,completedCount:0,students:new Set()}])),allStudents=new Set(),todayStudents=new Set();let todayCourseCount=0;
|
|
|
- for(const row of snapshot.appointments){if(row.cancelled||!row.startsAt)continue;const date=businessDate(row.startsAt);if(date<range.dateFrom||date>range.dateTo)continue;const key=period==='year'?date.slice(0,7):date,bucket=byKey.get(key);if(!bucket)continue;bucket.courseCount++;if(row.statusCode>=30)bucket.completedCount++;if(row.studentId){bucket.students.add(row.studentId);allStudents.add(row.studentId);}if(date===today){todayCourseCount++;if(row.studentId)todayStudents.add(row.studentId);}}
|
|
|
- const points=buckets.map((bucket)=>{const value=byKey.get(bucket.key);return{...bucket,courseCount:value.courseCount,studentCount:value.students.size,completedCount:value.completedCount,isToday:period==='year'?bucket.key===today.slice(0,7):bucket.key===today};}),totalCourseCount=points.reduce((sum,point)=>sum+point.courseCount,0),maxValue=Math.max(1,...points.flatMap((point)=>[point.courseCount,point.studentCount]));
|
|
|
+ for(const row of snapshot.appointments){if(row.cancelled||!row.startsAt)continue;const date=businessDate(row.startsAt);if(date<range.dateFrom||date>range.dateTo)continue;const bucket=byKey.get(date);if(!bucket)continue;bucket.courseCount++;if(row.statusCode>=30)bucket.completedCount++;if(row.studentId){bucket.students.add(row.studentId);allStudents.add(row.studentId);}if(date===today){todayCourseCount++;if(row.studentId)todayStudents.add(row.studentId);}}
|
|
|
+ const points=buckets.map((bucket)=>{const value=byKey.get(bucket.key);return{...bucket,courseCount:value.courseCount,studentCount:value.students.size,completedCount:value.completedCount,isToday:bucket.key===today};}),totalCourseCount=points.reduce((sum,point)=>sum+point.courseCount,0),maxValue=Math.max(1,...points.flatMap((point)=>[point.courseCount,point.studentCount]));
|
|
|
return{period,periodLabel:range.periodLabel,dateFrom:range.dateFrom,dateTo:range.dateTo,points,todayCourseCount,todayStudentCount:todayStudents.size,totalCourseCount,totalStudentCount:allStudents.size,maxValue,refreshedAt:new Date().toISOString(),liveSourceAvailable:snapshot.live.available,liveSourceMessage:snapshot.live.message};
|
|
|
}
|
|
|
async function scheduleTrendData(context,input) { const period=text(input.period||'week'),today=businessDate(),range=scheduleTrendRange(period,today),snapshot=await appointmentSnapshot(context,input,range.dateFrom);return scheduleTrendFromSnapshot(snapshot,period,today); }
|