Files
wechat-clock-mini/pages/checkin/checkin.wxml
王宏豪 ee3abed69f feat(app): 添加课程页面并优化打卡和计划功能
- 新增 pages/course/course 页面,集成 web-view 显示线上课程列表
- 在 app.json 中注册课程页面并添加底部 tabbar 导航
- 优化打卡页面,添加学号显示和改进成员列表布局
- 重构计划页面,添加内容详情弹层和优化加载逻辑
- 添加阿里云 OSS 上传工具模块用于文件上传功能
- 统一姓名和学号在同一行显示,改善 UI 体验
- 修复多个页面中的绑定事件和样式问题
2026-09-20 16:53:36 +08:00

213 lines
9.7 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- 顶部打卡卡模板 -->
<template name="top-card">
<view class="card top-card {{checked ? 'done-card' : ''}}">
<view class="status-row">
<view class="date-chip" bindtap="openWeekPicker" hover-class="{{weekList.length > 0 ? 'date-chip-hover' : 'none'}}">
<view class="date-week">{{weekday}}</view>
<view class="date-num">{{dayNum}}<text class="date-arrow" wx:if="{{weekList.length > 0}}"> ▾</text></view>
</view>
<view class="status-main">
<view class="status-title {{checked ? 'done' : 'undone'}}">{{checked ? '已打卡' : '未打卡'}}</view>
<view class="status-sub">{{checked ? '已完成今日打卡' : '请选择状态完成打卡'}}</view>
<view class="hero-status" wx:if="{{checked}}">
<view class="hero-status-dot" style="background-color:{{statusColor}}"></view>
<text class="hero-status-label" style="color:{{statusColor}}">{{record.status}}</text>
</view>
</view>
</view>
<view class="pills-grid {{submitting ? 'disabled' : ''}}">
<view
wx:for="{{statusItems}}"
wx:key="label"
class="pill {{statusIndex === index ? 'active' : ''}}"
style="background-color:{{statusIndex === index ? item.color : '#ffffff'}};border-color:{{statusIndex === index ? item.color : '#D8C7B4'}};color:{{statusIndex === index ? '#ffffff' : '#5A4A3A'}}"
data-index="{{index}}"
hover-class="pill-hover"
bindtap="onStatusTap"
>
<view class="dot" style="background-color:{{statusIndex === index ? '#ffffff' : item.color}}"></view>
<text>{{item.label}}</text>
</view>
<view class="submitting" wx:if="{{submitting}}">提交中…</view>
</view>
</view>
</template>
<!-- 成员列表项模板 -->
<template name="member-item">
<view class="member {{item.checked ? 'ok' : 'idle'}}">
<view class="member-avatar {{item.checked ? 'ok' : ''}}">{{item.shortName}}</view>
<view class="member-info">
<view class="member-line">
<text class="member-name">{{item.name}}</text>
<text class="member-sid" wx:if="{{item.student_id}}">学号 {{item.student_id}}</text>
</view>
<view class="member-meta">{{item.checked ? ('打卡 ' + item.timeText) : ''}}</view>
</view>
<view class="member-badge {{item.checked ? 'ok' : 'idle'}}">{{item.checked ? item.record.status : '未打卡'}}</view>
</view>
</template>
<!-- 加载失败 -->
<block wx:if="{{loadError}}">
<view class="page">
<view class="error-card">
<view class="error-icon">!</view>
<view class="error-title">{{loadError}}</view>
<button class="btn-retry" hover-class="btn-hover" bindtap="onRetry">重新加载</button>
</view>
</view>
</block>
<!-- 首次加载骨架屏 -->
<block wx:if="{{loading && view === 'overview'}}">
<view class="page">
<view class="skeleton-card">
<view class="sk sk-title"></view>
<view class="sk sk-line w60"></view>
<view class="sk sk-line w90"></view>
</view>
<view class="skeleton-list">
<view class="sk sk-row" wx:for="{{[1, 2, 3, 4, 5]}}" wx:key="*this"></view>
</view>
</view>
</block>
<block wx:elif="{{!loading}}">
<view class="page fade-in">
<!-- 老师总览视图 -->
<block wx:if="{{isTeacher && view === 'overview'}}">
<!-- 顶部打卡卡 -->
<template is="top-card" data="{{checked,weekList,weekday,dayNum,statusColor,record,statusItems,statusIndex,submitting}}"></template>
<!-- 小组统计列表 -->
<view class="record-panel">
<view class="section-title">小组统计</view>
<scroll-view class="record-scroll" scroll-y refresher-enabled refresher-triggered="{{refreshing}}" bindrefresherrefresh="onRefresh">
<view class="groups-list">
<view class="group-card" hover-class="group-card-hover" wx:for="{{groups}}" wx:key="group_name" wx:for-item="group">
<view class="group-main" data-group="{{group.group_name}}" bindtap="openGroup">
<view class="group-row">
<view class="group-avatar">{{index + 1}}</view>
<view class="group-name">{{group.group_name}}</view>
<view class="group-counts">
<text class="count done">已打卡 {{group.checked_count}}</text>
<text class="count total">{{group.total}}人</text>
</view>
<view class="chevron">›</view>
</view>
<view class="progress-track">
<view class="progress-bar" style="width: {{group.percent}}%"></view>
</view>
</view>
</view>
<view class="unassigned" wx:if="{{unassignedCount > 0}}">另有未分组 {{unassignedCount}} 人</view>
<view class="empty" wx:if="{{groups.length === 0}}">
<view class="empty-icon">👥</view>
<view class="empty-text">暂无小组</view>
</view>
</view>
<view class="bottom-space"></view>
</scroll-view>
</view>
</block>
<!-- 老师详情视图 -->
<block wx:elif="{{isTeacher && view === 'detail'}}">
<view class="detail-head">
<view class="back" hover-class="back-hover" bindtap="backToOverview">‹ 返回</view>
<view class="detail-title-wrap">
<view class="detail-title">{{selectedGroupName}}</view>
<view class="detail-sub" bindtap="openWeekPicker" hover-class="{{weekList.length > 0 ? 'head-hover' : 'none'}}">
{{classDate}} <text class="head-arrow" wx:if="{{weekList.length > 0}}"> ▾</text>
</view>
</view>
<view class="detail-progress">{{checkedCount}}/{{total}}</view>
</view>
<scroll-view class="detail-scroll" scroll-y refresher-enabled refresher-triggered="{{refreshing}}" bindrefresherrefresh="onRefresh">
<view class="state-block" wx:if="{{loading}}">
<view class="state-icon">◌</view>
<view>加载中...</view>
</view>
<view class="member-list" wx:else>
<block wx:for="{{members}}" wx:key="user_id" wx:for-item="item">
<template is="member-item" data="{{item: item}}"></template>
</block>
</view>
<view class="empty" wx:if="{{!loading && members.length === 0}}">暂无成员</view>
<view class="bottom-space"></view>
</scroll-view>
</block>
<!-- 学员视图 -->
<block wx:else>
<!-- 顶部打卡卡 -->
<template is="top-card" data="{{checked,weekList,weekday,dayNum,statusColor,record,statusItems,statusIndex,submitting}}"></template>
<!-- 记录区:小组/个人 tab -->
<view class="record-panel">
<view class="tabs">
<view class="tab {{tab === 'group' ? 'active' : ''}}" data-tab="group" hover-class="tab-hover" bindtap="switchTab">小组</view>
<view class="tab {{tab === 'personal' ? 'active' : ''}}" data-tab="personal" hover-class="tab-hover" bindtap="switchTab">个人</view>
</view>
<scroll-view class="record-scroll" scroll-y refresher-enabled refresher-triggered="{{refreshing}}" bindrefresherrefresh="onRefresh">
<view class="record-inner" wx:if="{{tab === 'group'}}">
<view class="group-head" wx:if="{{groupName}}">
<view class="group-title">{{groupName}} · {{classDate}}</view>
<view class="group-progress">{{checkedCount}}/{{total}} 已打卡</view>
</view>
<view class="empty" wx:if="{{!groupName}}">
<view class="empty-icon">👥</view>
<view class="empty-text">暂无小组,请联系管理员分配</view>
</view>
<view class="empty" wx:elif="{{members.length === 0}}">
<view class="empty-icon">📭</view>
<view class="empty-text">本周暂无打卡记录</view>
</view>
<view class="member-list" wx:else>
<block wx:for="{{members}}" wx:key="user_id" wx:for-item="item">
<template is="member-item" data="{{item: item}}"></template>
</block>
</view>
</view>
<view wx:else class="record-inner">
<view class="empty" wx:if="{{history.length === 0}}">
<view class="empty-icon">📒</view>
<view class="empty-text">暂无个人打卡记录</view>
</view>
<view class="history-item" wx:for="{{history}}" wx:key="id">
<view class="history-head">
<view class="history-date">{{item.class_date}}</view>
<view class="history-badge" style="color:{{item.color}};background:{{item.bg}}">{{item.status}}</view>
</view>
<view class="history-time">{{item.timeText}}</view>
</view>
<view class="history-footer" wx:if="{{history.length > 0}}">
<text wx:if="{{historyLoading}}">加载中…</text>
<text wx:elif="{{historyFinished}}">— 已加载全部 —</text>
</view>
</view>
</scroll-view>
</view>
</block>
<!-- 周选择弹层 -->
<view class="picker-mask" wx:if="{{showWeekPicker}}" bindtap="closeWeekPicker"></view>
<view class="picker-panel {{showWeekPicker ? 'show' : ''}}" wx:if="{{showWeekPicker}}">
<view class="picker-title">选择上课周</view>
<scroll-view class="picker-list" scroll-y>
<view
class="picker-item {{item === classDate ? 'active' : ''}}"
wx:for="{{weekList}}"
wx:key="*this"
data-date="{{item}}"
bindtap="onWeekSelect"
>
<text>{{item}}</text>
<text class="picker-check" wx:if="{{item === classDate}}">✓</text>
</view>
</scroll-view>
</view>
</view>
</block>