新增e2e测试脚本,修复部分问题

This commit was merged in pull request #51.
This commit is contained in:
2026-07-22 20:00:13 +08:00
parent 53d1ce6fb2
commit 4c07ec5455
105 changed files with 21700 additions and 318 deletions
@@ -30,8 +30,45 @@
</view>
</view>
<!-- 业绩数据 -->
<view class="performance-card">
<view class="section-header">
<text class="section-title">本月业绩</text>
<text class="period-text">{{ performance.periodLabel }}</text>
</view>
<view class="perf-grid">
<view class="perf-item">
<text class="perf-number">{{ performance.totalLessons }}</text>
<text class="perf-label">授课量</text>
</view>
<view class="perf-item">
<text class="perf-number">{{ performance.totalAttendees }}</text>
<text class="perf-label">学员人次</text>
</view>
<view class="perf-item" @click="showFormula('attendance')">
<text class="perf-number">{{ performance.attendanceRate != null ? performance.attendanceRate + '%' : 'N/A' }}</text>
<text class="perf-label">出勤率 </text>
<view v-if="performance.attendanceRate != null" class="perf-bar-wrap">
<view class="perf-bar" :style="{ width: performance.attendanceRate + '%', background: getRateColor(performance.attendanceRate) }"></view>
</view>
</view>
<view class="perf-item" @click="showFormula('fullness')">
<text class="perf-number">{{ performance.fullnessRate != null ? performance.fullnessRate + '%' : 'N/A' }}</text>
<text class="perf-label">满员率 </text>
<view v-if="performance.fullnessRate != null" class="perf-bar-wrap">
<view class="perf-bar" :style="{ width: performance.fullnessRate + '%', background: getRateColor(performance.fullnessRate) }"></view>
</view>
</view>
</view>
<view class="score-row" @click="showFormula('composite')">
<text class="score-label">综合评分 </text>
<text class="score-badge" :class="scoreClass">{{ scoreText }}</text>
<text v-if="scoreText !== '--'" class="score-icon"></text>
</view>
</view>
<!-- 违规统计 -->
<view class="stats-card">
<view v-if="violations.length > 0" class="stats-card">
<view class="stat-item">
<text class="stat-number">{{ violations.length }}</text>
<text class="stat-label">违规次数</text>
@@ -39,15 +76,11 @@
</view>
<!-- 违规记录列表 -->
<view class="section-header">
<view v-if="violations.length > 0" class="section-header">
<text class="section-title">违规记录</text>
</view>
<view v-if="violations.length === 0 && !loadingViolations" class="empty-wrap">
<text class="empty-text">暂无违规记录</text>
</view>
<view v-else class="violation-list">
<view v-if="violations.length > 0" class="violation-list">
<view v-for="(v, idx) in violations" :key="idx" class="violation-card">
<view class="violation-header">
<text class="violation-course">{{ v.course_name || '未知课程' }}</text>
@@ -59,6 +92,24 @@
</view>
</view>
<!-- 计算方式弹窗 -->
<view v-if="formulaVisible" class="formula-overlay" @click="closeFormula">
<view class="formula-dialog" @click.stop>
<view class="formula-header">
<text class="formula-title">{{ formulaTitle }}</text>
<text class="formula-close" @click="closeFormula"></text>
</view>
<view class="formula-body">
<text class="formula-text">{{ formulaContent }}</text>
<view class="formula-divider"></view>
<text class="formula-example">{{ formulaExample }}</text>
</view>
<view class="formula-footer">
<button class="formula-btn" @click="closeFormula">知道了</button>
</view>
</view>
</view>
<!-- 退出登录 -->
<view class="logout-area">
<button class="logout-btn" @click="handleLogout">退出登录</button>
@@ -85,7 +136,21 @@
coachId: ''
},
violations: [],
loadingViolations: true
loadingViolations: true,
performance: {
totalLessons: 0,
totalAttendees: 0,
attendanceRate: null,
fullnessRate: null,
periodLabel: ''
},
compositeScore: null,
scoreText: '--',
scoreClass: '',
formulaVisible: false,
formulaTitle: '',
formulaContent: '',
formulaExample: ''
}
},
onLoad() {
@@ -109,10 +174,61 @@
}
this.coachInfo = store.getCoachInfo() || { username: '教练', coachId: '' }
this.loadViolations()
this.loadPerformance()
},
methods: {
goBack() { uni.navigateBack() },
async loadPerformance() {
try {
const coachId = store.getCoachId()
if (!coachId) return
const data = await coachApi.getCoachPerformance(coachId, 'MONTH')
if (data) {
this.$set(this.performance, 'totalLessons', data.completedCourses != null ? data.completedCourses : 0)
this.$set(this.performance, 'totalAttendees', data.attendedStudents != null ? data.attendedStudents : 0)
this.$set(this.performance, 'attendanceRate', data.attendanceRate != null ? Math.round(data.attendanceRate) : null)
this.$set(this.performance, 'fullnessRate', data.fillRate != null ? Math.round(data.fillRate) : null)
const score = data.compositeScore != null ? Math.round(data.compositeScore * 10) / 10 : null
this.compositeScore = score
this.scoreText = score != null ? score.toFixed(1) : '--'
if (score == null) {
this.scoreClass = ''
} else if (score >= 80) {
this.scoreClass = 'score-great'
} else if (score >= 60) {
this.scoreClass = 'score-good'
} else {
this.scoreClass = 'score-low'
}
this.$set(this.performance, 'periodLabel', '本月')
}
} catch (e) {
console.error('加载业绩数据失败:', e)
}
},
showFormula(type) {
if (type === 'attendance') {
this.formulaTitle = '出勤率计算方式'
this.formulaContent = '出勤率 = 出席人次 ÷ 非取消预约总数 × 100%'
this.formulaExample = '示例:本月有 10 人预约了你的课程,其中 2 人取消预约,8 人中实际出席 7 人\n\n出勤率 = 7 ÷ (10 - 2) × 100% = 87.5%'
} else if (type === 'fullness') {
this.formulaTitle = '满员率计算方式'
this.formulaContent = '满员率 = 各课程(出席人数 ÷ 课程最大容量)的平均值 × 100%'
this.formulaExample = '示例:本月你完成了 2 节课\n- 课程 A:容量 20 人,实际出席 12 人 → 60%\n- 课程 B:容量 15 人,实际出席 9 人 → 60%\n\n满员率 = (60% + 60%) ÷ 2 = 60%'
} else if (type === 'composite') {
this.formulaTitle = '综合评分计算方式'
this.formulaContent = '综合评分 = 授课量评分 × 40% + 出勤率评分 × 30% + 满员率评分 × 30%'
this.formulaExample = '计算步骤:\n1. 授课量归一化:你的授课量 ÷ 全部教练最高授课量 × 100\n2. 出勤率与满员率各取实际百分值\n3. 加权求和\n\n示例:\n授课量评分 80 × 0.4 = 32\n出勤率 85 × 0.3 = 25.5\n满员率 60 × 0.3 = 18\n\n综合评分 = 32 + 25.5 + 18 = 75.5'
}
this.formulaVisible = true
},
closeFormula() {
this.formulaVisible = false
},
async loadViolations() {
this.loadingViolations = true
try {
@@ -245,6 +361,91 @@
color: #1E1E1E;
}
/* 业绩卡片 */
.performance-card {
background: #FFFFFF;
border-radius: 20px;
padding: 20px;
margin-bottom: 16px;
box-shadow: 0 4px 12px rgba(0,0,0,0.06);
}
.period-text {
font-size: 12px;
color: #7A7E84;
}
.perf-grid {
display: flex;
justify-content: space-between;
margin-top: 14px;
margin-bottom: 16px;
}
.perf-item {
display: flex;
flex-direction: column;
align-items: center;
flex: 1;
}
.perf-number {
font-size: 22px;
font-weight: 700;
color: #1E1E1E;
}
.perf-label {
font-size: 11px;
color: #7A7E84;
margin-top: 2px;
margin-bottom: 6px;
}
.perf-bar-wrap {
width: 40px;
height: 3px;
background: #EEEEEE;
border-radius: 2px;
overflow: hidden;
}
.perf-bar {
height: 100%;
border-radius: 2px;
}
.score-row {
display: flex;
justify-content: space-between;
align-items: center;
background: #F5F7FA;
border-radius: 16px;
padding: 16px 20px;
margin-top: 12px;
border-top: none;
}
.score-label {
font-size: 15px;
color: #7A7E84;
font-weight: 500;
}
.score-badge {
font-size: 38px;
font-weight: 800;
background: #FFFFFF;
border-radius: 12px;
padding: 4px 18px;
box-shadow: 0 2px 8px rgba(0,0,0,0.06);
}
.score-badge.score-great {
color: #00C853;
background: #E8F5E9;
}
.score-badge.score-good {
color: #FF9800;
background: #FFF3E0;
}
.score-badge.score-low {
color: #F44336;
background: #FFEBEE;
}
.score-icon {
font-size: 34px;
}
/* 违规统计 */
.stats-card {
background: #1A1A1A;
@@ -323,6 +524,81 @@
color: #7A7E84;
}
/* 计算方式弹窗 */
.formula-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 999;
}
.formula-dialog {
width: 85%;
background: #FFFFFF;
border-radius: 20px;
padding: 24px 20px 20px;
box-shadow: 0 8px 24px rgba(0,0,0,0.15);
}
.formula-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 18px;
}
.formula-title {
font-size: 18px;
font-weight: 700;
color: #1E1E1E;
}
.formula-close {
font-size: 20px;
color: #7A7E84;
padding: 4px;
}
.formula-body {
margin-bottom: 20px;
}
.formula-text {
font-size: 15px;
font-weight: 600;
color: #1E1E1E;
line-height: 1.6;
}
.formula-divider {
height: 1px;
background: #EEEEEE;
margin: 14px 0;
}
.formula-example {
font-size: 13px;
color: #7A7E84;
line-height: 1.7;
white-space: pre-line;
}
.formula-footer {
display: flex;
justify-content: center;
}
.formula-btn {
width: 100%;
height: 44px;
background: #00C853;
color: #FFFFFF;
border-radius: 40px;
font-size: 15px;
font-weight: 600;
display: flex;
align-items: center;
justify-content: center;
border: none;
}
.formula-btn::after { border: none; }
/* 退出登录 */
.logout-area {
padding: 20px 0;