def make_page(user, logo, container: inc.Component = None, parser: Type[UserParser] = DefaultUserParser): username, user_number, profile = parser(user).get_user_info() if container is None: container = inc.Container( Slider(height=550) .plus(img=PATHS[0], big_text='贪玩蓝月', tiny_text='你没有玩过的全新版本', align='right') .plus(img=PATHS[1], big_text='点一下', tiny_text='玩一年', align='left') .plus(img=PATHS[2], big_text='装备不花一分钱', tiny_text='原来装备,真能赚钱', align='left') .plus(img=PATHS[3], big_text='今晚八点', tiny_text='不见不散', align='right') .inc(), inc.Blockquote('常用功能'), inc.Row( inc.C( inc.C(inc.Grid(s=12, m=4), inc.Align.center) << inc.IconTextBlock('red', "今晚八点", "贪玩蓝月,找回年秀时贪玩的你", inc.Icon('edit')), inc.C(inc.Grid(s=12, m=4), inc.Align.center) << inc.IconTextBlock('orange', '贪玩气球', '玩玩一年,原来装备真能赚钱', inc.Icon('edit')), inc.C(inc.Grid(s=12, m=4), inc.Align.center) << inc.IconTextBlock('green', title='一人我渣渣辉', text='刚好遇见渣渣辉', icon=inc.Icon('edit')) )), inc.Blockquote('其他功能')) return str(inc.Page( make_nav_bar(logo, username), *make_side_nav('id', username, user_number, profile, BACKGROUND), container ))
def make_index_preview(activities: List[Tuple[GroupId, db.Activity]], courses: Dict[SectionId, List[db.Course]]): return inc.Collapsible( inc.Li << inc.CollapsibleHeader(inc.Icon("edit_location"), "活动") << inc.CollapsibleBody( inc.Collection( inc.Attr("id", "index_activity"), *(inc.CollectionItemA( inc.Href( f'group/room%3Fgroup%3D{group_id}%3Fchannel%3Dpublic'), activity.name) for group_id, activity in activities))), inc.Li << inc.CollapsibleHeader(inc.Icon("all_inclusive"), "课程") << inc.CollapsibleBody( inc.Collection( inc.Attr("id", "index_course"), *(inc.CollectionItemA('|'.join( map(lambda _: _.name, courses[Section(i).name]))) for i in sorted( sections_to_select.intersection( range(1, 15)[SyncCurrent.to_section().value - 1:])) if courses.get(Section(i).name)))))
def make_side_nav( side_nav_id: str, username: str, user_number: str, profile: str, background: str ) -> 'Tuple[inc.Component, inc.Component, inc.Component]': """ """ ret = inc.SideNav.new( id=side_nav_id, profile_background_img=background, user_info=[ # 头像 inc.SideNavItem( inc.Href('profile'), inc.Img(inc.Attr('class', 'circle'), src=profile, alt='')), # 昵称 inc.SideNavItem( inc.Href('profile'), inc.Span(inc.Attr('class', 'name'), inc.TextColor('white'), username)).append(inc.Align.center), # 编号 inc.SideNavItem( inc.Href('change_info'), inc.Span(inc.Attr('class', 'name'), inc.TextColor('white'), user_number)).append(inc.Align.center) ], items=[ inc.Li(inc.SideNavItem("平台相关", inc.Attr('class', 'subheader'))), inc.Li( inc.SideNavItem(inc.Href('#!'), inc.Attr('class', 'waves-effect'), "问题反馈")), inc.Li(inc.SideNavItem(inc.Href('#!'), inc.Attr('#!'), '关于')) ]) return ret, ret.link(inc.Icon('menu', inc.Attr('class', 'medium'))), ret.active()
def sign_stats(inst_id: int): user: db.User = g.user if user.permission != db.Permission.teacher: return inc.Page( '<link rel="shortcut icon" href="/static/favicon.ico">', inc.Container( inc.IconTextBlock( "red", "提示", "您没有管理课程的权限。", inc.Icon("edit"))).append( inc.Align.force_center).set_indent(1)).__str__() res = render_course_sign_stats( RxList(user.ref_courses).where(course_id=inst_id, user_cls=db.Role.leader).first()) return inc.Html( inc.Head( inc.Tag("style", TableStyle), '<link rel="shortcut icon" href="/static/favicon.ico">', ), inc.Container(*res).append( inc.Align.center).set_indent(1)).__str__() if isinstance( res, tuple) else inc.Page( inc.Container(res).set_indent(1)).__str__()
def render_course_sign_stats( user_course: db.UserCourse ) -> Union[Tuple[inc.Table, ...], inc.IconTextBlock]: course = user_course.course inst_id = course.id teacher = user_course.user.ref_teachers.first().teacher # 当前周数 week_index = cache_storage.get( name_pattern('c', str(inst_id), None, "week")) if not week_index: return inc.IconTextBlock("blue", f"{course.name}", "暂无记录", inc.Icon("edit")) count = int(week_index) src_rows = defaultdict(dict) course = RxTable(db.Course).where(id=inst_id).first() 上课周 = [ i + 1 for i, test in enumerate(map(lambda _: _ is '1', course.week[2:count])) if test ] total_count = len(course.week) - 2 上课周 = tuple(map(lambda _: "-".join(map(str, _)), to_interval(上课周))) if not week_index: return inc.IconTextBlock("blue", f"{course.name}", "无签到记录", inc.Icon("edit")) 上课时间 = f'第{",".join(上课周)}周' 上课地点 = course.location 学期 = course.term stats = [] for week_index in range(1, count + 1): src = cache_storage.hget( name_pattern('c', str(inst_id), None, "values"), week_index) if src: src = json.loads(src) 应到 = src['应到'] 实到 = src['实到'] 到勤率 = 实到 / 应到 stats.append((应到, 实到, 到勤率)) for each in src['人员']: src_rows[each['name'], each['number']][week_index] = each['is_sign'] 上课周数 = len(stats) stats = tuple(zip(*stats)) 应到平均 = round(sum(stats[0]) / 上课周数, 2) 实到平均 = round(sum(stats[1]) / 上课周数, 2) 到勤率平均 = f"{round(100 * sum(stats[2]) / 上课周数, 2)}%" src_rows = dict(src_rows) 签到总览 = [[ 姓名, 学号, *('+' if _2.get(i, 0) else ' ' for i in range(1, total_count + 1)), f"{round(100 * sum(_2.values()) / 上课周数, 2)}%" ] for (姓名, 学号), _2 in sorted((_1 for _1 in src_rows.items()), key=lambda _: _[0][1])] table1 = inc.Table( data_source=[[ course.name, teacher.name, 上课时间, 上课地点, 学期, 应到平均, 实到平均, 到勤率平均 ]], columns=['课程名', '任课老师', "上课时间", "上课地点", "学期", "平均应到", "平均实到", "平均到勤率"]) table2 = inc.Table(data_source=签到总览, columns=['姓名', '学号', *range(1, total_count + 1), '平时分']) return table1 << inc.Attr("id", "stats"), table2 << inc.Attr( "id", "details")