Files
teaching-feedback-assistant/pages/students/index.wxml

209 lines
10 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.

<view class="page-shell">
<text class="eyebrow">个人档案</text>
<view class="page-heading">
<text class="page-title">学生档案</text>
</view>
<text class="page-subtitle">管理学生默认信息,用于快速生成课堂反馈</text>
<view wx:if="{{errorMessage}}" class="status-banner">
<text>{{errorMessage}}</text>
<text class="status-action" bindtap="retryLoad">重试</text>
</view>
<view class="search-row">
<view class="search-box">
<icon class="search-icon" type="search" size="18" color="#6E6E73" />
<input
class="search-input"
placeholder="搜索学生姓名、年级、学科或称呼"
placeholder-class="search-placeholder"
value="{{query}}"
bindinput="onSearch"
confirm-type="search"
/>
</view>
<button class="filter-button {{filterVisible || filterCount ? 'filter-button-active' : ''}}" bindtap="toggleFilter" aria-label="筛选学生档案,已启用 {{filterCount}} 项">
<view class="filter-icon" aria-hidden="true">
<view class="filter-icon-line filter-icon-line-first"></view>
<view class="filter-icon-line filter-icon-line-second"></view>
<view class="filter-icon-line filter-icon-line-third"></view>
</view>
<text wx:if="{{filterCount}}" class="filter-count">{{filterCount}}</text>
</button>
</view>
<view wx:if="{{filterVisible}}" class="filter-panel surface">
<view class="filter-header">
<text class="filter-title">筛选学生档案</text>
<text class="filter-clear" bindtap="clearFilters">清除</text>
</view>
<text class="filter-label">年级</text>
<view class="filter-options">
<text class="filter-chip {{!filterGrade ? 'filter-chip-active' : ''}}" data-type="grade" data-value="all" bindtap="selectFilter">全部</text>
<text wx:for="{{grades}}" wx:key="*this" class="filter-chip {{filterGrade === item ? 'filter-chip-active' : ''}}" data-type="grade" data-value="{{item}}" bindtap="selectFilter">{{item}}</text>
</view>
<text class="filter-label">学科</text>
<view class="filter-options">
<text class="filter-chip {{!filterSubject ? 'filter-chip-active' : ''}}" data-type="subject" data-value="all" bindtap="selectFilter">全部</text>
<text wx:for="{{subjects}}" wx:key="*this" class="filter-chip {{filterSubject === item ? 'filter-chip-active' : ''}}" data-type="subject" data-value="{{item}}" bindtap="selectFilter">{{item}}</text>
</view>
</view>
<view class="archive-toolbar">
<view class="toolbar-copy">
<text class="toolbar-title">学生列表</text>
<text class="toolbar-updated">上次更新:{{lastUpdatedText}}</text>
</view>
<view class="toolbar-actions">
<button class="refresh-button" loading="{{loading}}" disabled="{{loading}}" bindtap="onRefresh" aria-label="刷新学生档案">↻</button>
<button class="new-student-button" bindtap="openCreate"><text class="new-student-icon"></text>新增学生</button>
</view>
</view>
<view wx:if="{{loading && profiles.length === 0}}" class="loading-state">正在从服务端读取学生档案...</view>
<view wx:elif="{{profiles.length === 0}}" class="empty-state">
<text class="empty-icon">◎</text>
<text class="empty-title">暂无学生档案</text>
<text class="empty-description">请先创建学生档案</text>
<button class="create-empty-button primary-button" bindtap="openCreate"><text class="button-icon"></text>创建学生档案</button>
</view>
<view wx:elif="{{filteredProfiles.length === 0}}" class="empty-state compact-empty">
<text class="empty-icon">⌕</text>
<text class="empty-title">没有匹配的档案</text>
<text class="empty-description">试试清除关键词或筛选条件</text>
<button class="clear-search-button secondary-button" bindtap="clearFilters">清除搜索与筛选</button>
</view>
<view wx:else class="profile-list">
<view wx:for="{{filteredProfiles}}" wx:key="id" class="profile-card surface">
<view
class="profile-summary"
data-id="{{item.id}}"
bindtap="toggleProfile"
aria-role="button"
aria-label="{{expandedProfileId === item.id ? '收起' : '展开'}}{{item.name}}的最近反馈"
aria-expanded="{{expandedProfileId === item.id}}"
>
<view class="profile-card-top">
<view>
<text class="profile-name">{{item.name}}</text>
<text class="profile-guardian">{{item.guardianTitle}}</text>
</view>
<view class="profile-card-actions">
<button
class="profile-menu-button"
disabled="{{deletingId === item.id}}"
data-id="{{item.id}}"
catchtap="openProfileActions"
aria-label="{{item.name}}的更多操作"
>
<text>{{deletingId === item.id ? '…' : '•••'}}</text>
</button>
<text class="profile-chevron {{expandedProfileId === item.id ? 'profile-chevron-expanded' : ''}}" aria-hidden="true"></text>
</view>
</view>
<view class="profile-tags">
<text class="profile-tag">{{item.grade}}</text>
<text class="profile-tag">{{item.subject}}</text>
<text class="profile-tag">{{item.academicTermLabel}}</text>
</view>
<view class="profile-time-row">
<text class="profile-time-label">上课时间</text>
<text class="profile-time-value">{{item.startTime}} - {{item.endTime}}</text>
</view>
</view>
<view wx:if="{{expandedProfileId === item.id}}" class="profile-feedback-panel">
<view class="profile-feedback-heading">
<text class="profile-feedback-title">最近反馈</text>
<text wx:if="{{recentFeedbackByProfile[item.id] && recentFeedbackByProfile[item.id].length}}" class="profile-feedback-count">{{recentFeedbackByProfile[item.id].length}} 条</text>
</view>
<view wx:if="{{feedbackLoadingByProfile[item.id]}}" class="profile-feedback-status">正在读取反馈...</view>
<view wx:elif="{{feedbackErrorsByProfile[item.id]}}" class="profile-feedback-status profile-feedback-error">
<text>{{feedbackErrorsByProfile[item.id]}}</text>
<text class="profile-feedback-retry" data-id="{{item.id}}" catchtap="retryRecentFeedback">重试</text>
</view>
<view wx:elif="{{!recentFeedbackByProfile[item.id] || recentFeedbackByProfile[item.id].length === 0}}" class="profile-feedback-status">暂无反馈记录</view>
<view wx:else class="recent-feedback-list">
<view wx:for="{{recentFeedbackByProfile[item.id]}}" wx:for-item="feedback" wx:key="id" class="recent-feedback-item">
<text class="recent-feedback-date">{{feedback.feedbackDate}}</text>
<text class="recent-feedback-content">{{feedback.content}}</text>
</view>
</view>
</view>
</view>
</view>
</view>
<view wx:if="{{sheetVisible}}" class="sheet-mask" bindtap="closeCreate">
<view class="create-sheet" catchtap="noop">
<view class="sheet-top">
<view>
<view class="sheet-title-row">
<text class="sheet-title">新增学生档案</text>
</view>
<text class="sheet-subtitle">保存后会同步到学生档案列表</text>
</view>
<view class="sheet-actions">
<text class="defaults-link" bindtap="goDefaults">设置预设项 </text>
<button class="sheet-close" bindtap="closeCreate" aria-label="关闭新增学生弹窗">×</button>
</view>
</view>
<scroll-view class="sheet-scroll" scroll-y="true">
<view class="sheet-form">
<view class="form-field full-field">
<text class="form-label">学生姓名</text>
<input class="form-input" placeholder="请输入学生姓名" value="{{draft.name}}" bindinput="onNameInput" maxlength="20" />
</view>
<view class="form-grid">
<picker class="form-field" mode="selector" range="{{grades}}" bindchange="onGradeChange">
<text class="form-label">年级</text>
<text class="form-value">{{draft.grade}}</text>
</picker>
<picker class="form-field" mode="selector" range="{{subjects}}" bindchange="onSubjectChange">
<text class="form-label">学科</text>
<text class="form-value">{{draft.subject}}</text>
</picker>
</view>
<view class="form-grid">
<picker class="form-field" mode="selector" range="{{years}}" bindchange="onYearChange">
<text class="form-label">日期年份</text>
<text class="form-value">{{draft.academicYear}}</text>
</picker>
<picker class="form-field" mode="selector" range="{{terms}}" bindchange="onTermChange">
<text class="form-label">日期</text>
<text class="form-value">{{draft.term}}</text>
</picker>
</view>
<view class="form-field full-field guardian-field">
<text class="form-label">默认家长称呼</text>
<input class="form-input" placeholder="默认:学生姓名 + 妈妈" value="{{draft.guardianTitle}}" bindinput="onGuardianInput" maxlength="24" />
</view>
<view class="form-grid bottom-grid">
<picker class="form-field" mode="time" value="{{draft.startTime}}" bindchange="onStartTimeChange">
<text class="form-label">开始时间</text>
<text class="form-value">{{draft.startTime}}</text>
</picker>
<picker class="form-field" mode="time" value="{{draft.endTime}}" bindchange="onEndTimeChange">
<text class="form-label">结束时间</text>
<text class="form-value">{{draft.endTime}}</text>
</picker>
</view>
</view>
</scroll-view>
<view class="sheet-footer">
<button class="sheet-cancel secondary-button" bindtap="closeCreate">取消</button>
<button class="sheet-save primary-button" loading="{{saving}}" disabled="{{saving}}" bindtap="saveStudent">保存</button>
</view>
</view>
</view>