调整成绩分析

This commit is contained in:
ywyonui 2025-07-30 12:53:33 +08:00
parent 63eca2a0ea
commit 67ab505da5
4 changed files with 222 additions and 59 deletions

View File

@ -37,26 +37,13 @@
<CjBjTjGl :tjgl-data="tjglData" />
<!-- 6. 本班与年级平均分对比分析图表 -->
<CjBjNjPjf
:km-lb="
ksccKmLb.map((km) => ({
id: km.id,
name: km.kmmc,
kmmc: km.kmmc,
}))
"
v-model:selected-km-id="xzkmId"
:bj-pj-list="bjPjList"
:bj-pjf="tjglData.bjpjf"
:nj-pjf="tjglData.njpjzf"
@change="onKmChange"
/>
<CjBjNjPjf v-model:selected-km-id="xzkmId" :bj-pj-list="bjPjList" />
<!-- 7. 总分分数段图表 -->
<CjZfFs :fs-duan-lb="fsDuanLb" />
<CjZfFs :dj-rs-list="djRsList" />
<!-- 8. 总分等级段图表 -->
<CjZfDj :dj-duan-lb="djDuanLb" />
<CjZfDj :dj-rs-list="djRsList" />
</view>
</view>
</view>
@ -116,22 +103,15 @@ interface BjPjInfo {
njmc: string;
fs: number;
}
interface DjRsInfo {
dj: string;
rs: number;
zgf: string;
zdf: string;
}
// --- Static Mock Data ---
const staticFsDuanLb: FsDuan[] = [
{ name: "240-269", value: 5, color: "#1890ff" },
{ name: "210-239", value: 12, color: "#2fc25b" },
{ name: "180-210", value: 18, color: "#facc14" },
{ name: "180以下", value: 10, color: "#f04864" },
];
const staticDjDuanLb: DjDuan[] = [
{ name: "A", value: 5, color: "#1890ff" },
{ name: "B", value: 15, color: "#2fc25b" },
{ name: "C", value: 18, color: "#facc14" },
{ name: "D", value: 10, color: "#f04864" },
{ name: "E", value: 2, color: "#999999" },
];
// 使 djRsList
// --- State ---
const xzbjId = ref<string | number | null>(null);
@ -150,9 +130,8 @@ const tjglData = ref<TjglData>({
jgl: 0,
jgrs: 0,
});
const fsDuanLb = ref<FsDuan[]>([...staticFsDuanLb]);
const djDuanLb = ref<DjDuan[]>([...staticDjDuanLb]);
const bjPjList = ref<BjPjInfo[]>([]);
const djRsList = ref<DjRsInfo[]>([]);
// --- API Functions ---
const getKsccKmLb = async (ksccId: string | number) => {
@ -197,6 +176,7 @@ const getBjKscjKmData = async (
score: cj.ksfs || 0,
bjpm: cj.bjpm || 0, // 使
}));
console.log("学生成绩列表:", xsCjLb.value);
//
tjglData.value.bjrs = res.result.bjRs || 0;
@ -211,7 +191,12 @@ const getBjKscjKmData = async (
// CjBjNjPjf
bjPjList.value = res.result.bjPjList || [];
// CjZfFsCjZfDj
djRsList.value = res.result.djRsList || [];
console.log("获取班级科目成绩数据成功:", res.result);
console.log("等级人数列表:", djRsList.value);
}
} catch (error) {
console.error("获取班级科目成绩数据失败:", error);
@ -316,4 +301,24 @@ onMounted(async () => {
}
}
}
.debug-info {
background-color: #f0f0f0;
padding: 20rpx;
margin-top: 20rpx;
border-radius: 10rpx;
.debug-title {
font-size: 32rpx;
font-weight: bold;
margin-bottom: 10rpx;
text-align: center;
}
.debug-item {
font-size: 28rpx;
color: #333;
margin-bottom: 5rpx;
}
}
</style>

View File

@ -13,18 +13,26 @@
<view class="th">班级排名</view>
</view>
<view class="bg-body">
<view class="bg-row" v-for="xs in xsCjLb" :key="xs.id">
<view class="bg-row" v-for="xs in displayList" :key="xs.id">
<view class="td">{{ xs.name }}</view>
<view class="td">{{ xs.score }}</view>
<view class="td">{{ xs.bjpm }}</view>
</view>
<view v-if="!xsCjLb.length" class="bg-empty"> 暂无数据 </view>
</view>
<view
v-if="xsCjLb.length > 5"
class="expand-btn-wrap"
@click="toggleExpand"
>
{{ expanded ? "收拢" : "展开全部" }}
</view>
</view>
</uni-section>
</template>
<script lang="ts" setup>
import { computed, ref } from "vue";
// --- Interfaces ---
interface XsCj {
id: string | number;
@ -47,6 +55,22 @@ const props = withDefaults(defineProps<Props>(), {
{ id: "st-5", name: "孙七", score: 85, bjpm: 8 },
],
});
// /
const expanded = ref(false);
//
const displayList = computed(() => {
if (expanded.value) {
return props.xsCjLb;
}
return props.xsCjLb.slice(0, 5);
});
// /
function toggleExpand() {
expanded.value = !expanded.value;
}
</script>
<style scoped lang="scss">
@ -100,5 +124,15 @@ const props = withDefaults(defineProps<Props>(), {
padding: 40rpx 0;
}
}
.expand-btn-wrap {
display: flex;
justify-content: center;
padding: 16rpx 10rpx;
text-align: center;
background: #fff;
color: #1890ff;
border-top: 1rpx solid #f0f0f0;
}
}
</style>

View File

@ -12,8 +12,9 @@
id="GradeAnalysisAreaChart"
class="charts"
/>
<view v-if="isLoading" class="tb-placeholder">
图表加载中或无数据...
<view v-if="isLoading" class="tb-placeholder"> 图表加载中... </view>
<view v-else-if="!hasValidData" class="tb-placeholder">
暂无等级段数据
</view>
</view>
</uni-section>
@ -21,7 +22,7 @@
<script lang="ts" setup>
import uCharts from "@/components/charts/u-charts.js";
import { nextTick, onMounted, ref } from "vue";
import { computed, nextTick, onMounted, ref, watch } from "vue";
import { areaOption } from "./cj.data";
// --- Interfaces ---
@ -31,26 +32,72 @@ interface DjDuan {
color: string;
}
interface DjRsInfo {
dj: string;
rs: number;
zgf: string;
zdf: string;
}
// --- Props ---
interface Props {
djDuanLb?: DjDuan[];
djRsList?: DjRsInfo[];
}
const props = withDefaults(defineProps<Props>(), {
djDuanLb: () => [
{ name: "A", value: 5, color: "#1890ff" },
{ name: "B", value: 15, color: "#2fc25b" },
{ name: "C", value: 18, color: "#facc14" },
{ name: "D", value: 10, color: "#f04864" },
{ name: "E", value: 2, color: "#999999" },
],
djRsList: () => [],
});
// --- State ---
const isLoading = ref(false);
// --- Computed ---
const hasValidData = computed(() => {
return (
props.djRsList &&
props.djRsList.length > 0 &&
props.djRsList.some((item) => item.rs > 0)
);
});
const processedData = computed(() => {
if (!props.djRsList || props.djRsList.length === 0) {
return [];
}
//
const djColorMap: { [key: string]: string } = {
A: "#1890ff",
B: "#2fc25b",
C: "#facc14",
D: "#f04864",
E: "#999999",
};
// 0
return props.djRsList
.filter((item) => item.rs > 0)
.map((item) => ({
name: item.dj, // 使 dj
value: item.rs,
color: djColorMap[item.dj] || "#666666", //
}))
.sort((a, b) => {
// A > B > C > D > E
const levelOrder = { A: 5, B: 4, C: 3, D: 2, E: 1 };
const aLevel = levelOrder[a.name as keyof typeof levelOrder] || 0;
const bLevel = levelOrder[b.name as keyof typeof levelOrder] || 0;
return bLevel - aLevel; //
});
});
// --- ---
const drawAreaChart = () => {
if (!hasValidData.value) {
console.log("没有有效的等级段数据");
return;
}
isLoading.value = true;
setTimeout(() => {
@ -73,11 +120,11 @@ const drawAreaChart = () => {
const ctx = uni.createCanvasContext("GradeAnalysisAreaChart");
const areaData = {
categories: props.djDuanLb.map((item) => item.name),
categories: processedData.value.map((item) => item.name),
series: [
{
name: "人数",
data: props.djDuanLb.map((item) => item.value),
data: processedData.value.map((item) => item.value),
color: "#1890ff",
},
],
@ -120,6 +167,7 @@ const drawAreaChart = () => {
}
console.log("图表数据:", areaData);
console.log("处理后的等级段数据:", processedData.value);
try {
new uCharts(newOption);
@ -141,9 +189,23 @@ const drawAreaChart = () => {
}, 500);
};
// --- Watchers ---
watch(
() => props.djRsList,
() => {
console.log("等级段数据变化:", props.djRsList);
if (hasValidData.value) {
drawAreaChart();
}
},
{ deep: true }
);
// --- Lifecycle ---
onMounted(() => {
if (hasValidData.value) {
drawAreaChart();
}
});
</script>

View File

@ -12,8 +12,9 @@
id="GradeAnalysisDonutChart"
class="charts"
/>
<view v-if="isLoading" class="tb-placeholder">
图表加载中或无数据...
<view v-if="isLoading" class="tb-placeholder"> 图表加载中... </view>
<view v-else-if="!hasValidData" class="tb-placeholder">
暂无分数段数据
</view>
</view>
</uni-section>
@ -21,7 +22,7 @@
<script lang="ts" setup>
import uCharts from "@/components/charts/u-charts.js";
import { nextTick, onMounted, ref } from "vue";
import { computed, nextTick, onMounted, ref, watch } from "vue";
import { ringOption } from "./cj.data";
// --- Interfaces ---
@ -31,25 +32,71 @@ interface FsDuan {
color: string;
}
interface DjRsInfo {
dj: string;
rs: number;
zgf: string;
zdf: string;
}
// --- Props ---
interface Props {
fsDuanLb?: FsDuan[];
djRsList?: DjRsInfo[];
}
const props = withDefaults(defineProps<Props>(), {
fsDuanLb: () => [
{ name: "240-269", value: 5, color: "#1890ff" },
{ name: "210-239", value: 12, color: "#2fc25b" },
{ name: "180-210", value: 18, color: "#facc14" },
{ name: "180以下", value: 10, color: "#f04864" },
],
djRsList: () => [],
});
// --- State ---
const isLoading = ref(false);
// --- Computed ---
const hasValidData = computed(() => {
return (
props.djRsList &&
props.djRsList.length > 0 &&
props.djRsList.some((item) => item.rs > 0)
);
});
const processedData = computed(() => {
if (!props.djRsList || props.djRsList.length === 0) {
return [];
}
//
const djColorMap: { [key: string]: string } = {
A: "#1890ff",
B: "#2fc25b",
C: "#facc14",
D: "#f04864",
E: "#999999",
};
// 0
return props.djRsList
.filter((item) => item.rs > 0)
.map((item) => ({
name: `${item.zdf}-${item.zgf}`, // 使 zdf-zgf
value: item.rs,
color: djColorMap[item.dj] || "#666666", //
}))
.sort((a, b) => {
// "-"
const aNum = parseFloat(a.name.split("-")[0] || "0");
const bNum = parseFloat(b.name.split("-")[0] || "0");
return bNum - aNum; //
});
});
// --- ---
const drawDonutChart = () => {
if (!hasValidData.value) {
console.log("没有有效的分数段数据");
return;
}
isLoading.value = true;
setTimeout(() => {
@ -75,7 +122,7 @@ const drawDonutChart = () => {
series: [
{
name: "总分分数段",
data: props.fsDuanLb,
data: processedData.value,
},
],
};
@ -110,6 +157,7 @@ const drawDonutChart = () => {
}
console.log("图表数据:", donutData);
console.log("处理后的分数段数据:", processedData.value);
try {
new uCharts(newOption);
@ -131,9 +179,23 @@ const drawDonutChart = () => {
}, 500);
};
// --- Watchers ---
watch(
() => props.djRsList,
() => {
console.log("分数段数据变化:", props.djRsList);
if (hasValidData.value) {
drawDonutChart();
}
},
{ deep: true }
);
// --- Lifecycle ---
onMounted(() => {
if (hasValidData.value) {
drawDonutChart();
}
});
</script>