fix: 一些问题
continuous-integration/drone/push Build is passing Details

This commit is contained in:
张哲铜 2025-10-12 22:16:49 +08:00
parent 967d14efa2
commit 7089fe521f
6 changed files with 141 additions and 182 deletions

View File

@ -214,7 +214,7 @@ function cancelTopN() {
<view class="mb-6 flex justify-center p-4"> <view class="mb-6 flex justify-center p-4">
<wd-input-number v-model="tempTopN" :min="1" :max="200" :step="1" /> <wd-input-number v-model="tempTopN" :min="1" :max="200" :step="1" />
</view> </view>
<view class="flex gap-3"> <view class="flex justify-center gap-3">
<wd-button block type="default" @click="cancelTopN"> <wd-button block type="default" @click="cancelTopN">
取消 取消
</wd-button> </wd-button>

View File

@ -134,7 +134,7 @@ const scoreRangeInfo = computed(() => {
const allScore = props.data.all_score const allScore = props.data.all_score
const item = props.data.data.find((d) => { const item = props.data.data.find((d) => {
const [min, max] = (d.score_scope || '').split('~').map(Number) const [min, max] = (d.score_scope || '').split('-').map(Number)
return allScore >= min && allScore <= max return allScore >= min && allScore <= max
}) })
@ -142,7 +142,7 @@ const scoreRangeInfo = computed(() => {
return null return null
return { return {
range: item.score_scope, range: item.score_scope.split('-').join('~'),
gradeCount: item.student_num || 0, gradeCount: item.student_num || 0,
classCount: 0, // TODO: classCount: 0, // TODO:
} }
@ -170,13 +170,13 @@ const scoreRangeInfo = computed(() => {
<view class="flex items-center gap-2"> <view class="flex items-center gap-2">
<view class="h-1 w-1 rounded-full bg-blue-500" /> <view class="h-1 w-1 rounded-full bg-blue-500" />
<text class="text-sm text-slate-700"> <text class="text-sm text-slate-700">
本人所在分数段<text class="text-blue-600 font-semibold">{{ scoreRangeInfo.range }}</text> 本人所在分数段: <text class="text-blue-600 font-semibold">{{ scoreRangeInfo.range }}</text>
</text> </text>
</view> </view>
<view class="mt-2 flex items-center gap-2"> <view class="mt-2 flex items-center gap-2">
<view class="h-1 w-1 rounded-full bg-blue-500" /> <view class="h-1 w-1 rounded-full bg-blue-500" />
<text class="text-sm text-slate-700"> <text class="text-sm text-slate-700">
本分数段年级学生数<text class="text-blue-600 font-semibold">{{ scoreRangeInfo.gradeCount }}</text>其中本班占<text class="text-blue-600 font-semibold">{{ scoreRangeInfo.classCount }}</text> 本分数段年级学生数: <text class="text-blue-600 font-semibold">{{ scoreRangeInfo.gradeCount }}</text>其中本班占<text class="text-blue-600 font-semibold">{{ scoreRangeInfo.classCount }}</text>
</text> </text>
</view> </view>
</view> </view>

View File

@ -8,11 +8,8 @@
</route> </route>
<script lang="ts" setup> <script lang="ts" setup>
import type { import type { ScoreSheetInfo } from '@/service/types'
GetScoreSheetResponse, import { computed, ref } from 'vue'
ScoreSheetInfo,
} from '@/service/types'
import { computed, onMounted, ref } from 'vue'
import { teacherAnalysisScoreSheetUsingPost } from '@/service/laoshichengjifenxi' import { teacherAnalysisScoreSheetUsingPost } from '@/service/laoshichengjifenxi'
import { useHomeStore } from '@/store/home' import { useHomeStore } from '@/store/home'
@ -20,22 +17,14 @@ defineOptions({
name: 'ScoreListPage', name: 'ScoreListPage',
}) })
//
interface ScoreSheetItemExtended extends ScoreSheetInfo {
subjectScores: Record<number, number> //
}
// 使store // 使store
const homeStore = useHomeStore() const homeStore = useHomeStore()
// // z-paging
const currentPage = ref(1) const pagingRef = ref<ZPagingRef>()
const pageSize = ref(20)
const total = ref(0)
const loading = ref(false)
// //
const scoreList = ref<ScoreSheetItemExtended[]>([]) const scoreList = ref<ScoreSheetInfo[]>([])
// //
const classOptions = computed(() => homeStore.classOptions) const classOptions = computed(() => homeStore.classOptions)
@ -55,94 +44,72 @@ function goBack() {
function handleClassChange(event: { value: string | number, selectedItem: Record<string, any> }) { function handleClassChange(event: { value: string | number, selectedItem: Record<string, any> }) {
selectedClassId.value = Number(event.value) selectedClassId.value = Number(event.value)
homeStore.selectedClassId = selectedClassId.value homeStore.selectedClassId = selectedClassId.value
// //
currentPage.value = 1 pagingRef.value?.reload()
fetchScoreList()
} }
// //
function handlePageChange(page: number) { async function queryScoreList(pageNo: number, pageSize: number) {
currentPage.value = page if (!homeStore.selectedClassId || !homeStore.selectedExamId || !homeStore.selectedGradeKey) {
fetchScoreList() pagingRef.value?.complete([])
}
//
async function fetchScoreList() {
if (!selectedClassId.value || !homeStore.selectedExamId || !homeStore.selectedGradeKey) {
return return
} }
try { try {
loading.value = true
const response = await teacherAnalysisScoreSheetUsingPost({ const response = await teacherAnalysisScoreSheetUsingPost({
body: { body: {
class_key: selectedClassId.value, class_key: homeStore.selectedClassId,
exam_id: homeStore.selectedExamId, exam_id: homeStore.selectedExamId,
grade_key: homeStore.selectedGradeKey, grade_key: homeStore.selectedGradeKey,
page: currentPage.value, page: pageNo,
page_size: pageSize.value, page_size: pageSize,
}, },
}) })
if (response) { pagingRef.value?.complete(response?.list || [])
const responseData = response as GetScoreSheetResponse
total.value = responseData.total || 0
//
scoreList.value = (responseData.list || []).map(item => ({
...item,
subjectScores: {}, // TODO: API
}))
}
} }
catch (error) { catch (error) {
console.error('获取成绩单数据失败:', error) console.error('获取成绩单数据失败:', error)
uni.showToast({ pagingRef.value?.complete(false)
title: '获取数据失败',
icon: 'none',
})
}
finally {
loading.value = false
} }
} }
//
function getSubjectScore(student: ScoreSheetInfo, subjectId: number) {
const subjectScore = student.single_subject_score_list?.find(
item => item.subject_id === subjectId,
)
return subjectScore?.subject_score ?? '--'
}
// //
function viewStudentReport(student: ScoreSheetItemExtended) { function viewStudentReport(student: ScoreSheetInfo) {
uni.navigateTo({ uni.navigateTo({
url: `/pages/student/detail?student_number=${student.student_exam_number}&student_name=${student.student_name}`, url: `/pages/student/detail?student_number=${student.student_exam_number}&student_name=${student.student_name}`,
}) })
} }
// //
function viewSubjectAnswerSheet(student: ScoreSheetItemExtended, subjectId: number = 0) { function viewSubjectAnswerSheet(student: ScoreSheetInfo, subjectId: number) {
uni.showToast({ uni.showToast({
title: '功能开发中', title: '功能开发中',
icon: 'none', icon: 'none',
}) })
} }
//
onMounted(async () => {
try {
// store
if (homeStore.classOptions.length === 0) {
await homeStore.fetchOptions()
}
//
if (homeStore.selectedClassId && homeStore.selectedExamId) {
selectedClassId.value = homeStore.selectedClassId
await fetchScoreList()
}
}
catch (error) {
console.error('初始化数据失败:', error)
}
})
</script> </script>
<template> <template>
<view class="score-list-page min-h-screen bg-slate-50"> <view class="score-list-page min-h-screen bg-slate-50">
<!-- 主要内容区域 - z-paging 包裹 -->
<z-paging
ref="pagingRef"
v-model="scoreList"
:refresher-enabled="true"
:auto="true"
:default-page-size="20"
@query="queryScoreList"
>
<template #top>
<!-- 导航栏 --> <!-- 导航栏 -->
<wd-navbar placeholder fixed right-text="成绩单"> <wd-navbar placeholder fixed right-text="成绩单">
<template #left> <template #left>
@ -160,11 +127,11 @@ onMounted(async () => {
</wd-drop-menu> </wd-drop-menu>
</template> </template>
</wd-navbar> </wd-navbar>
</template>
<!-- 主要内容区域 -->
<view class="p-4">
<!-- 成绩单表格 --> <!-- 成绩单表格 -->
<wd-table :data="scoreList" :height="600" :loading="loading"> <view class="p-4">
<wd-table :data="scoreList" :height="600">
<!-- 学生姓名列 --> <!-- 学生姓名列 -->
<wd-table-col prop="student_name" label="考生姓名" :width="`${20}%`" fixed> <wd-table-col prop="student_name" label="考生姓名" :width="`${20}%`" fixed>
<template #value="{ row }"> <template #value="{ row }">
@ -209,28 +176,12 @@ onMounted(async () => {
class="cursor-pointer text-blue-500" class="cursor-pointer text-blue-500"
@tap="viewSubjectAnswerSheet(row, subject.value)" @tap="viewSubjectAnswerSheet(row, subject.value)"
> >
{{ row.subjectScores[subject.value] || '--' }} {{ getSubjectScore(row, subject.subjectId) }}
</text> </text>
</template> </template>
</wd-table-col> </wd-table-col>
</wd-table> </wd-table>
<!-- 分页组件 -->
<view v-if="total > 0" class="mt-4 flex justify-center">
<wd-pagination
v-model="currentPage"
:total="total"
:page-size="pageSize"
show-icon
show-message
@change="handlePageChange"
/>
</view>
<!-- 空状态 -->
<view v-if="!loading && scoreList.length === 0" class="py-8 text-center text-gray-500">
暂无成绩数据
</view>
</view> </view>
</z-paging>
</view> </view>
</template> </template>

View File

@ -377,7 +377,7 @@ whenever(() => [selectedSubjectId.value, homeStore.selectedExamId, keyStudentTyp
<z-paging <z-paging
ref="keyStudentsPaging" ref="keyStudentsPaging"
v-model="keyStudentsList" v-model="keyStudentsList"
:default-page-size="keyStudentCount" :default-page-size="keyStudentCount || 5"
:refresher-enabled="true" :refresher-enabled="true"
:auto="true" :auto="true"
@query="fetchKeyStudentsPaging" @query="fetchKeyStudentsPaging"

View File

@ -144,13 +144,6 @@ onMounted(async () => {
</template> </template>
</wd-navbar> </wd-navbar>
<!-- 加载状态 -->
<view v-if="isLoading" class="h-screen flex items-center justify-center">
<wd-loading size="32" />
</view>
<!-- 内容区域 -->
<view v-else-if="studentInfo" class="pb-4">
<!-- 科目选择标签栏 --> <!-- 科目选择标签栏 -->
<wd-tabs <wd-tabs
v-model="activeTab" v-model="activeTab"
@ -166,23 +159,27 @@ onMounted(async () => {
/> />
</wd-tabs> </wd-tabs>
<!-- 加载状态 -->
<view v-if="isLoading" class="h-screen flex items-center justify-center">
<wd-loading size="32" />
</view>
<!-- 内容区域 -->
<view v-else-if="studentInfo" class="pb-4">
<!-- 主要内容区域 --> <!-- 主要内容区域 -->
<view class="p-4 space-y-4"> <view class="p-4 space-y-4">
<!-- 个人成绩卡片 --> <!-- 个人成绩卡片 -->
<view class="rounded-2xl from-blue-500 to-blue-600 bg-gradient-to-br p-5 shadow-lg"> <view class="relative rounded-2xl from-blue-500 to-blue-600 bg-gradient-to-br p-5 shadow-lg">
<view class="absolute left-0 top-4 rounded-r-full bg-white/40 px-4 backdrop-blur">
<text class="text-lg text-white">{{ studentName }}</text>
</view>
<!-- 总分展示 --> <!-- 总分展示 -->
<view class="mb-4 flex items-end justify-between"> <view class="mb-4 flex items-center justify-end gap-4">
<view>
<text class="text-sm text-blue-100">总分</text>
<view class="mt-1 flex items-baseline gap-1"> <view class="mt-1 flex items-baseline gap-1">
<text class="text-4xl text-white font-bold">{{ studentInfo.totalScore }}</text> <text class="text-4xl text-white font-bold">{{ studentInfo.totalScore }}</text>
<text class="text-lg text-blue-100">/{{ studentInfo.fullScore }}</text> <text class="text-lg text-blue-100">/{{ studentInfo.fullScore }}</text>
</view> </view>
</view> </view>
<view class="rounded-full bg-white/20 px-4 py-2 backdrop-blur">
<text class="text-sm text-white">学号: {{ studentNumber }}</text>
</view>
</view>
<!-- 成绩统计网格 --> <!-- 成绩统计网格 -->
<view class="grid grid-cols-2 gap-3"> <view class="grid grid-cols-2 gap-3">

View File

@ -2610,6 +2610,8 @@ export type ScoreSheetInfo = {
student_name?: string; student_name?: string;
/** 学生学号 */ /** 学生学号 */
student_number?: string; student_number?: string;
/** 单科成绩 */
single_subject_score_list?: SingleSubjectScore[];
}; };
export type ScoreTrendItem = { export type ScoreTrendItem = {
@ -2655,6 +2657,15 @@ export type SetProblemRecordResponse = {
record_id?: number; record_id?: number;
}; };
export type SingleSubjectScore = {
/** 科目ID */
subject_id?: number;
/** 科目名称 */
subject_name?: string;
/** 单科成绩 */
subject_score?: number;
};
export enum Statistics_modeEnum { export enum Statistics_modeEnum {
'segmented' = 'segmented', 'segmented' = 'segmented',
'cumulative' = 'cumulative', 'cumulative' = 'cumulative',