调整成绩分析
This commit is contained in:
parent
5ab1697d2b
commit
63eca2a0ea
@ -80,8 +80,13 @@ export const jsFindByBzrNjIdApi = async (params: { njId: string }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 根据职务ID查询教师
|
// 根据职务ID查询教师
|
||||||
export const jsFindByZwIdApi = async (params: { zwId: string; zwType: string }) => {
|
export const jsFindByZwIdApi = async (params: {
|
||||||
return await get(`/api/js/findByZwId?zwId=${params.zwId}&zwType=${params.zwType}`);
|
zwId: string;
|
||||||
|
zwType: string;
|
||||||
|
}) => {
|
||||||
|
return await get(
|
||||||
|
`/api/js/findByZwId?zwId=${params.zwId}&zwType=${params.zwType}`
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 选课列表
|
// 选课列表
|
||||||
@ -98,6 +103,37 @@ export const jsdXkkcSaveApi = async (params: any) => {
|
|||||||
export const jsdXkXsListApi = async (params: any) => {
|
export const jsdXkXsListApi = async (params: any) => {
|
||||||
return await get("/mobile/js/xkxs/list", params);
|
return await get("/mobile/js/xkxs/list", params);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 获取班级学生考试成绩
|
||||||
|
export const jsdBjKscjApi = async (params: any) => {
|
||||||
|
return await get("/mobile/js/kscj/bj", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取班级学生考试成绩(按科目)
|
||||||
|
export const jsdBjKscjKmApi = async (params: any) => {
|
||||||
|
return await get("/mobile/js/kscj/bjKm", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取考试场次列表
|
||||||
|
export const jsdKsccListApi = async (params: any) => {
|
||||||
|
return await get("/api/kscc/findPage", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取教师授课班级列表
|
||||||
|
export const jsdJsdkbApi = async (params: any) => {
|
||||||
|
return await get("/mobile/js/jsdkb", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取班级考试场次列表
|
||||||
|
export const jsdKsccApi = async (params: any) => {
|
||||||
|
return await get("/mobile/js/kscc", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取考试场次科目列表
|
||||||
|
export const ksccKmFindByKsccIdApi = async (params: any) => {
|
||||||
|
return await get("/api/kscc/findKsccKmmcById", params);
|
||||||
|
};
|
||||||
|
|
||||||
//根据年级ID和班级ID查询学生及家长信息
|
//根据年级ID和班级ID查询学生及家长信息
|
||||||
export const mobilejlstudentListApi = async (params: any) => {
|
export const mobilejlstudentListApi = async (params: any) => {
|
||||||
return await get("/mobile/jl/studentList", params);
|
return await get("/mobile/jl/studentList", params);
|
||||||
@ -113,7 +149,6 @@ export const getByJlIdApi = async (params: any) => {
|
|||||||
return res.result;
|
return res.result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// 提交点名信息
|
// 提交点名信息
|
||||||
export const jsdXkdmListApi = async (params: any) => {
|
export const jsdXkdmListApi = async (params: any) => {
|
||||||
return await post("/mobile/js/xkdm/add", params);
|
return await post("/mobile/js/xkdm/add", params);
|
||||||
@ -182,8 +217,6 @@ export const getJsPjGzlApi = async () => {
|
|||||||
return await get("/api/comConfig/getJsPjGzl");
|
return await get("/api/comConfig/getJsPjGzl");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 接龙相关API
|
// 接龙相关API
|
||||||
// 根据ID获取接龙详情
|
// 根据ID获取接龙详情
|
||||||
export const jlFindByIdApi = async (params: { id: string }) => {
|
export const jlFindByIdApi = async (params: { id: string }) => {
|
||||||
@ -216,7 +249,7 @@ export const gzlGetDqXqAndZcApi = async () => {
|
|||||||
* 当前学期排课公共配置(排课设置、排课周次、排课时间)
|
* 当前学期排课公共配置(排课设置、排课周次、排课时间)
|
||||||
*/
|
*/
|
||||||
export const dqpkApi = async () => {
|
export const dqpkApi = async () => {
|
||||||
return await get("/mobile/jz/pkkb/dqpk" );
|
return await get("/mobile/jz/pkkb/dqpk");
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -249,7 +282,10 @@ export const qdzxFindByQdParamsApi = async (params: { qdId: string }) => {
|
|||||||
return await get("/api/qdzx/findByQdParams", params);
|
return await get("/api/qdzx/findByQdParams", params);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const qdzxFindByQdAndJsApi = async (params: { qdId: string; jsId: string }) => {
|
export const qdzxFindByQdAndJsApi = async (params: {
|
||||||
|
qdId: string;
|
||||||
|
jsId: string;
|
||||||
|
}) => {
|
||||||
return await get("/api/qdzx/findByQdAndJs", params);
|
return await get("/api/qdzx/findByQdAndJs", params);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
201
src/pages/view/homeSchool/components/CjBjNjPjf.vue
Normal file
201
src/pages/view/homeSchool/components/CjBjNjPjf.vue
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
<template>
|
||||||
|
<uni-section
|
||||||
|
title="本班与年级平均分对比分析图表"
|
||||||
|
type="line"
|
||||||
|
titleFontSize="16px"
|
||||||
|
padding
|
||||||
|
class="mt-10"
|
||||||
|
>
|
||||||
|
<!-- 图表容器 -->
|
||||||
|
<view class="tb-rq" id="line-chart-container">
|
||||||
|
<canvas
|
||||||
|
canvas-id="GradeAnalysisLineChart"
|
||||||
|
id="GradeAnalysisLineChart"
|
||||||
|
class="charts"
|
||||||
|
/>
|
||||||
|
<view v-if="isLoading" class="tb-placeholder">
|
||||||
|
图表加载中或无数据...
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</uni-section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import uCharts from "@/components/charts/u-charts.js";
|
||||||
|
import { nextTick, onMounted, ref, watch } from "vue";
|
||||||
|
import { lineOption } from "./cj.data";
|
||||||
|
|
||||||
|
interface BjPjInfo {
|
||||||
|
bjId: string;
|
||||||
|
bjmc: string;
|
||||||
|
njmc: string;
|
||||||
|
fs: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Props ---
|
||||||
|
interface Props {
|
||||||
|
bjPjList?: BjPjInfo[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
bjPjList: () => [],
|
||||||
|
});
|
||||||
|
|
||||||
|
// --- Emits ---
|
||||||
|
const emit = defineEmits(["update:selectedKmId", "change"]);
|
||||||
|
|
||||||
|
// --- State ---
|
||||||
|
const isLoading = ref(false);
|
||||||
|
|
||||||
|
// --- 图表绘制逻辑 ---
|
||||||
|
const drawLineChart = () => {
|
||||||
|
isLoading.value = true;
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
nextTick(() => {
|
||||||
|
// 使用 uni.createSelectorQuery() 获取当前页面/组件实例
|
||||||
|
uni
|
||||||
|
.createSelectorQuery()
|
||||||
|
.select("#line-chart-container")
|
||||||
|
.boundingClientRect((rect) => {
|
||||||
|
if (
|
||||||
|
rect &&
|
||||||
|
!Array.isArray(rect) &&
|
||||||
|
typeof rect.width === "number" &&
|
||||||
|
rect.width > 0 &&
|
||||||
|
typeof rect.height === "number" &&
|
||||||
|
rect.height > 0
|
||||||
|
) {
|
||||||
|
const containerWidth = rect.width;
|
||||||
|
const containerHeight = rect.height;
|
||||||
|
|
||||||
|
const ctx = uni.createCanvasContext("GradeAnalysisLineChart");
|
||||||
|
|
||||||
|
// 使用后端返回的班级平均分数据
|
||||||
|
const lineData = {
|
||||||
|
categories: props.bjPjList.map(
|
||||||
|
(bj) => bj.bjmc || bj.njmc + bj.bjmc
|
||||||
|
),
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: "班级平均分",
|
||||||
|
data: props.bjPjList.map((bj) => bj.fs),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
// 验证数据完整性
|
||||||
|
if (!lineData.categories || lineData.categories.length === 0) {
|
||||||
|
console.error("图表数据不完整:categories为空");
|
||||||
|
isLoading.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lineData.series || lineData.series.length === 0) {
|
||||||
|
console.error("图表数据不完整:series为空");
|
||||||
|
isLoading.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证每个series的数据
|
||||||
|
for (let i = 0; i < lineData.series.length; i++) {
|
||||||
|
const series = lineData.series[i];
|
||||||
|
if (!series.data || series.data.length === 0) {
|
||||||
|
console.error(`图表数据不完整:series[${i}].data为空`);
|
||||||
|
isLoading.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("图表数据:", lineData);
|
||||||
|
|
||||||
|
const newOption: any = {
|
||||||
|
...lineOption,
|
||||||
|
};
|
||||||
|
newOption.context = ctx;
|
||||||
|
newOption.width = containerWidth;
|
||||||
|
newOption.height = containerHeight;
|
||||||
|
newOption.categories = lineData.categories;
|
||||||
|
newOption.series = lineData.series;
|
||||||
|
|
||||||
|
const options = new uCharts(newOption);
|
||||||
|
|
||||||
|
try {
|
||||||
|
new uCharts(newOption);
|
||||||
|
isLoading.value = false;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("图表绘制失败:", error);
|
||||||
|
isLoading.value = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error(
|
||||||
|
`无法获取容器 #line-chart-container 的有效尺寸:`,
|
||||||
|
rect
|
||||||
|
);
|
||||||
|
isLoading.value = false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.exec();
|
||||||
|
});
|
||||||
|
}, 500);
|
||||||
|
};
|
||||||
|
|
||||||
|
// --- Watch ---
|
||||||
|
// 监听bjPjList变化,重新绘制图表
|
||||||
|
watch(
|
||||||
|
() => props.bjPjList,
|
||||||
|
() => {
|
||||||
|
if (props.bjPjList && props.bjPjList.length > 0) {
|
||||||
|
drawLineChart();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
// --- Lifecycle ---
|
||||||
|
onMounted(() => {
|
||||||
|
drawLineChart();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.km-xz-tabs {
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tb-rq {
|
||||||
|
width: 100%;
|
||||||
|
height: 350rpx;
|
||||||
|
position: relative;
|
||||||
|
margin: 8rpx 0;
|
||||||
|
border-radius: 6px;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: #ffffff;
|
||||||
|
box-shadow: 0 1rpx 4rpx rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.charts {
|
||||||
|
width: 100% !important;
|
||||||
|
height: 100% !important;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tb-placeholder {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
color: #999;
|
||||||
|
font-size: 24rpx;
|
||||||
|
background-color: #ffffff;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
141
src/pages/view/homeSchool/components/CjBjPicker.vue
Normal file
141
src/pages/view/homeSchool/components/CjBjPicker.vue
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
<template>
|
||||||
|
<view class="bj-xzq">
|
||||||
|
<picker
|
||||||
|
mode="selector"
|
||||||
|
:range="bjLb"
|
||||||
|
range-key="name"
|
||||||
|
:value="xzbjIndex"
|
||||||
|
@change="onBjChange"
|
||||||
|
:disabled="bjLb.length === 0"
|
||||||
|
>
|
||||||
|
<view class="xz-item">
|
||||||
|
<text v-if="bjLb.length > 0">{{ xzbjName || "选择班级" }}</text>
|
||||||
|
<text v-else class="no-data-text">暂无班级数据</text>
|
||||||
|
<uni-icons type="bottom" size="16" color="#666"></uni-icons>
|
||||||
|
</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { jsdJsdkbApi } from "@/api/base/server";
|
||||||
|
import { useUserStore } from "@/store/modules/user";
|
||||||
|
import { computed, onMounted, ref } from "vue";
|
||||||
|
|
||||||
|
// --- Interfaces ---
|
||||||
|
interface BjInfo {
|
||||||
|
id: string | number;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Props ---
|
||||||
|
interface Props {
|
||||||
|
modelValue?: string | number | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
modelValue: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
// --- Store ---
|
||||||
|
const userStore = useUserStore();
|
||||||
|
|
||||||
|
// --- Emits ---
|
||||||
|
const emit = defineEmits(["update:modelValue", "change"]);
|
||||||
|
|
||||||
|
// --- State ---
|
||||||
|
const xzbjIndex = ref<number>(0);
|
||||||
|
const bjLb = ref<BjInfo[]>([]);
|
||||||
|
|
||||||
|
// --- Computed ---
|
||||||
|
const xzbjName = computed(() => {
|
||||||
|
if (props.modelValue) {
|
||||||
|
const index = bjLb.value.findIndex((bj) => bj.id === props.modelValue);
|
||||||
|
return index >= 0 ? bjLb.value[index].name : "选择班级";
|
||||||
|
}
|
||||||
|
return bjLb.value[xzbjIndex.value]?.name || "选择班级";
|
||||||
|
});
|
||||||
|
|
||||||
|
// --- API Functions ---
|
||||||
|
const getBjLb = async () => {
|
||||||
|
try {
|
||||||
|
const jsData = userStore.getJs;
|
||||||
|
if (!jsData || !jsData.id) {
|
||||||
|
console.error("教师ID不存在");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await jsdJsdkbApi({ jsId: jsData.id });
|
||||||
|
if (res && res.resultCode === 1 && res.result) {
|
||||||
|
bjLb.value = res.result.map((bj: any) => ({
|
||||||
|
id: bj.id,
|
||||||
|
name: bj.njmc + bj.bjmc,
|
||||||
|
}));
|
||||||
|
console.log("获取班级列表成功:", bjLb.value);
|
||||||
|
|
||||||
|
// 自动选择第一个选项
|
||||||
|
if (bjLb.value.length > 0 && !props.modelValue) {
|
||||||
|
xzbjIndex.value = 0;
|
||||||
|
const firstBj = bjLb.value[0];
|
||||||
|
emit("update:modelValue", firstBj.id);
|
||||||
|
emit("change", firstBj.id, firstBj);
|
||||||
|
console.log(
|
||||||
|
`自动选择第一个班级: ${firstBj.id}, 班级名称: ${firstBj.name}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bjLb.value = [];
|
||||||
|
console.log("班级列表为空");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("获取班级列表失败:", error);
|
||||||
|
bjLb.value = [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// --- Event Handlers ---
|
||||||
|
const onBjChange = (event: any) => {
|
||||||
|
const index = Number(event.detail.value);
|
||||||
|
xzbjIndex.value = index;
|
||||||
|
const xzbj = bjLb.value[index];
|
||||||
|
|
||||||
|
emit("update:modelValue", xzbj?.id || null);
|
||||||
|
emit("change", xzbj?.id || null, xzbj || null);
|
||||||
|
|
||||||
|
console.log(`切换到班级: ${xzbj?.id}, 班级名称: ${xzbj?.name}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
// --- Lifecycle ---
|
||||||
|
onMounted(async () => {
|
||||||
|
await getBjLb();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.bj-xzq {
|
||||||
|
background-color: #ffffff;
|
||||||
|
padding: 10rpx 30rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
height: 80rpx;
|
||||||
|
border-bottom: 1rpx solid #f0f0f0;
|
||||||
|
|
||||||
|
.xz-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333;
|
||||||
|
font-weight: bold;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
uni-icons {
|
||||||
|
margin-left: 10rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-data-text {
|
||||||
|
color: #999;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
124
src/pages/view/homeSchool/components/CjBjTjGl.vue
Normal file
124
src/pages/view/homeSchool/components/CjBjTjGl.vue
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
<template>
|
||||||
|
<uni-section
|
||||||
|
title="统计概览"
|
||||||
|
type="line"
|
||||||
|
titleFontSize="16px"
|
||||||
|
padding
|
||||||
|
class="mt-10"
|
||||||
|
>
|
||||||
|
<view class="tjgl-kp">
|
||||||
|
<view class="tj-gd">
|
||||||
|
<view class="tj-item">
|
||||||
|
<text class="label">班级人数</text>
|
||||||
|
<text class="value">{{ tjglData.bjrs }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="tj-item">
|
||||||
|
<text class="label">年级平均总分</text>
|
||||||
|
<text class="value primary">{{ tjglData.njpjzf }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="tj-item">
|
||||||
|
<text class="label">班级平均分</text>
|
||||||
|
<text class="value primary">{{ tjglData.bjpjf }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="tj-item">
|
||||||
|
<text class="label">年级最高分</text>
|
||||||
|
<text class="value primary">{{ tjglData.njzgf }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="tj-item">
|
||||||
|
<text class="label">优生率</text>
|
||||||
|
<text class="value success">{{ tjglData.ysl }}%</text>
|
||||||
|
</view>
|
||||||
|
<view class="tj-item">
|
||||||
|
<text class="label">班级最高分</text>
|
||||||
|
<text class="value primary">{{ tjglData.bjzgf }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="tj-item">
|
||||||
|
<text class="label">优生人数</text>
|
||||||
|
<text class="value">{{ tjglData.ysrs }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="tj-item">
|
||||||
|
<text class="label">及格率</text>
|
||||||
|
<text class="value success">{{ tjglData.jgl }}%</text>
|
||||||
|
</view>
|
||||||
|
<view class="tj-item">
|
||||||
|
<text class="label">及格人数</text>
|
||||||
|
<text class="value">{{ tjglData.jgrs }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</uni-section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
// --- Interfaces ---
|
||||||
|
interface TjglData {
|
||||||
|
bjrs: number;
|
||||||
|
njpjzf: number;
|
||||||
|
bjpjf: number;
|
||||||
|
njzgf: number;
|
||||||
|
ysl: number;
|
||||||
|
bjzgf: number;
|
||||||
|
ysrs: number;
|
||||||
|
jgl: number;
|
||||||
|
jgrs: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Props ---
|
||||||
|
interface Props {
|
||||||
|
tjglData?: TjglData;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
tjglData: () => ({
|
||||||
|
bjrs: 45,
|
||||||
|
njpjzf: 82.5,
|
||||||
|
bjpjf: 85.1,
|
||||||
|
njzgf: 99,
|
||||||
|
ysl: 75.6,
|
||||||
|
bjzgf: 98,
|
||||||
|
ysrs: 34,
|
||||||
|
jgl: 95.6,
|
||||||
|
jgrs: 43,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.tjgl-kp {
|
||||||
|
background-color: #f8f9fd;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tj-gd {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
gap: 25rpx 15rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tj-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #666;
|
||||||
|
margin-bottom: 6rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
|
||||||
|
&.primary {
|
||||||
|
color: #447ade;
|
||||||
|
}
|
||||||
|
&.success {
|
||||||
|
color: #67c23a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
104
src/pages/view/homeSchool/components/CjBjXsList.vue
Normal file
104
src/pages/view/homeSchool/components/CjBjXsList.vue
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
<template>
|
||||||
|
<uni-section
|
||||||
|
title="学生成绩"
|
||||||
|
type="line"
|
||||||
|
titleFontSize="16px"
|
||||||
|
padding
|
||||||
|
class="mt-10"
|
||||||
|
>
|
||||||
|
<view class="xs-cj-bg">
|
||||||
|
<view class="bg-header">
|
||||||
|
<view class="th">姓名</view>
|
||||||
|
<view class="th">得分</view>
|
||||||
|
<view class="th">班级排名</view>
|
||||||
|
</view>
|
||||||
|
<view class="bg-body">
|
||||||
|
<view class="bg-row" v-for="xs in xsCjLb" :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>
|
||||||
|
</uni-section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
// --- Interfaces ---
|
||||||
|
interface XsCj {
|
||||||
|
id: string | number;
|
||||||
|
name: string;
|
||||||
|
score: number;
|
||||||
|
bjpm: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Props ---
|
||||||
|
interface Props {
|
||||||
|
xsCjLb?: XsCj[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
xsCjLb: () => [
|
||||||
|
{ id: "st-1", name: "张三", score: 95, bjpm: 1 },
|
||||||
|
{ id: "st-2", name: "李四", score: 88, bjpm: 5 },
|
||||||
|
{ id: "st-3", name: "王五", score: 92, bjpm: 3 },
|
||||||
|
{ id: "st-4", name: "赵六", score: 75, bjpm: 15 },
|
||||||
|
{ id: "st-5", name: "孙七", score: 85, bjpm: 8 },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.xs-cj-bg {
|
||||||
|
width: 100%;
|
||||||
|
font-size: 26rpx;
|
||||||
|
border: 1rpx solid #e0e0e0;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.bg-header {
|
||||||
|
display: flex;
|
||||||
|
background-color: #eaf2ff;
|
||||||
|
color: #333;
|
||||||
|
font-weight: bold;
|
||||||
|
border-bottom: 1rpx solid #e0e0e0;
|
||||||
|
|
||||||
|
.th {
|
||||||
|
flex: 1;
|
||||||
|
padding: 16rpx 10rpx;
|
||||||
|
text-align: center;
|
||||||
|
border-right: 1rpx solid #e0e0e0;
|
||||||
|
&:last-child {
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-body {
|
||||||
|
.bg-row {
|
||||||
|
display: flex;
|
||||||
|
border-bottom: 1rpx solid #f0f0f0;
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.td {
|
||||||
|
flex: 1;
|
||||||
|
padding: 16rpx 10rpx;
|
||||||
|
text-align: center;
|
||||||
|
color: #666;
|
||||||
|
border-right: 1rpx solid #f0f0f0;
|
||||||
|
&:last-child {
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.bg-empty {
|
||||||
|
text-align: center;
|
||||||
|
color: #999;
|
||||||
|
padding: 40rpx 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
160
src/pages/view/homeSchool/components/CjKsccPicker.vue
Normal file
160
src/pages/view/homeSchool/components/CjKsccPicker.vue
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
<template>
|
||||||
|
<view class="kscc-xzq">
|
||||||
|
<picker
|
||||||
|
mode="selector"
|
||||||
|
:range="ksccLb"
|
||||||
|
range-key="name"
|
||||||
|
:value="xzksccIndex"
|
||||||
|
@change="onKsccChange"
|
||||||
|
:disabled="ksccLb.length === 0"
|
||||||
|
>
|
||||||
|
<view class="xz-item">
|
||||||
|
<text v-if="ksccLb.length > 0">{{ xzksccName || "选择考试场次" }}</text>
|
||||||
|
<text v-else class="no-data-text">暂无考试场次数据</text>
|
||||||
|
<uni-icons type="bottom" size="16" color="#666"></uni-icons>
|
||||||
|
</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { jsdKsccApi } from "@/api/base/server";
|
||||||
|
import { computed, ref, watch } from "vue";
|
||||||
|
|
||||||
|
// --- Interfaces ---
|
||||||
|
interface KsccInfo {
|
||||||
|
id: string | number;
|
||||||
|
name: string;
|
||||||
|
ksmc: string;
|
||||||
|
kskstime: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Props ---
|
||||||
|
interface Props {
|
||||||
|
modelValue?: string | number | null;
|
||||||
|
bjId?: string | number | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
modelValue: null,
|
||||||
|
bjId: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
// --- Emits ---
|
||||||
|
const emit = defineEmits(["update:modelValue", "change"]);
|
||||||
|
|
||||||
|
// --- State ---
|
||||||
|
const xzksccIndex = ref<number>(0);
|
||||||
|
const ksccLb = ref<KsccInfo[]>([]);
|
||||||
|
|
||||||
|
// --- Computed ---
|
||||||
|
const xzksccName = computed(() => {
|
||||||
|
if (props.modelValue) {
|
||||||
|
const index = ksccLb.value.findIndex(
|
||||||
|
(kscc) => kscc.id === props.modelValue
|
||||||
|
);
|
||||||
|
return index >= 0 ? ksccLb.value[index].name : "选择考试场次";
|
||||||
|
}
|
||||||
|
return ksccLb.value[xzksccIndex.value]?.name || "选择考试场次";
|
||||||
|
});
|
||||||
|
|
||||||
|
// --- API Functions ---
|
||||||
|
const getKsccLb = async (bjId: string | number) => {
|
||||||
|
try {
|
||||||
|
const res = await jsdKsccApi({ bjId });
|
||||||
|
if (res && res.resultCode === 1 && res.result) {
|
||||||
|
ksccLb.value = res.result.map((kscc: any) => ({
|
||||||
|
id: kscc.id,
|
||||||
|
name: kscc.ksmc || kscc.name,
|
||||||
|
ksmc: kscc.ksmc,
|
||||||
|
kskstime: kscc.kskstime,
|
||||||
|
}));
|
||||||
|
console.log("获取考试场次列表成功:", ksccLb.value);
|
||||||
|
|
||||||
|
// 自动选择第一个选项
|
||||||
|
if (ksccLb.value.length > 0 && !props.modelValue) {
|
||||||
|
xzksccIndex.value = 0;
|
||||||
|
const firstKscc = ksccLb.value[0];
|
||||||
|
emit("update:modelValue", firstKscc.id);
|
||||||
|
emit("change", firstKscc.id, firstKscc);
|
||||||
|
console.log(
|
||||||
|
`自动选择第一个考试场次: ${firstKscc.id}, 考试名称: ${firstKscc.name}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ksccLb.value = [];
|
||||||
|
console.log("考试场次列表为空");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("获取考试场次列表失败:", error);
|
||||||
|
ksccLb.value = [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// --- Event Handlers ---
|
||||||
|
const onKsccChange = (event: any) => {
|
||||||
|
const index = Number(event.detail.value);
|
||||||
|
xzksccIndex.value = index;
|
||||||
|
const xzkscc = ksccLb.value[index];
|
||||||
|
|
||||||
|
emit("update:modelValue", xzkscc?.id || null);
|
||||||
|
emit("change", xzkscc?.id || null, xzkscc || null);
|
||||||
|
|
||||||
|
console.log(`切换到考试场次: ${xzkscc?.id}, 考试名称: ${xzkscc?.name}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
// --- Watchers ---
|
||||||
|
watch(
|
||||||
|
() => props.bjId,
|
||||||
|
async (newBjId) => {
|
||||||
|
if (newBjId) {
|
||||||
|
await getKsccLb(newBjId);
|
||||||
|
} else {
|
||||||
|
ksccLb.value = [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => ksccLb.value,
|
||||||
|
(newKsccLb) => {
|
||||||
|
// 当考试场次列表更新时,如果没有选中值且有数据,自动选择第一个
|
||||||
|
if (newKsccLb.length > 0 && !props.modelValue) {
|
||||||
|
xzksccIndex.value = 0;
|
||||||
|
const firstKscc = newKsccLb[0];
|
||||||
|
emit("update:modelValue", firstKscc.id);
|
||||||
|
emit("change", firstKscc.id, firstKscc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.kscc-xzq {
|
||||||
|
background-color: #ffffff;
|
||||||
|
padding: 10rpx 30rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
height: 80rpx;
|
||||||
|
border-bottom: 1rpx solid #f0f0f0;
|
||||||
|
|
||||||
|
.xz-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333;
|
||||||
|
font-weight: bold;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
uni-icons {
|
||||||
|
margin-left: 10rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-data-text {
|
||||||
|
color: #999;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
186
src/pages/view/homeSchool/components/CjZfDj.vue
Normal file
186
src/pages/view/homeSchool/components/CjZfDj.vue
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
<template>
|
||||||
|
<uni-section
|
||||||
|
title="总分等级段"
|
||||||
|
type="line"
|
||||||
|
titleFontSize="16px"
|
||||||
|
padding
|
||||||
|
class="mt-10"
|
||||||
|
>
|
||||||
|
<view class="tb-rq" id="area-chart-container">
|
||||||
|
<canvas
|
||||||
|
canvas-id="GradeAnalysisAreaChart"
|
||||||
|
id="GradeAnalysisAreaChart"
|
||||||
|
class="charts"
|
||||||
|
/>
|
||||||
|
<view v-if="isLoading" class="tb-placeholder">
|
||||||
|
图表加载中或无数据...
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</uni-section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import uCharts from "@/components/charts/u-charts.js";
|
||||||
|
import { nextTick, onMounted, ref } from "vue";
|
||||||
|
import { areaOption } from "./cj.data";
|
||||||
|
|
||||||
|
// --- Interfaces ---
|
||||||
|
interface DjDuan {
|
||||||
|
name: string;
|
||||||
|
value: number;
|
||||||
|
color: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Props ---
|
||||||
|
interface Props {
|
||||||
|
djDuanLb?: DjDuan[];
|
||||||
|
}
|
||||||
|
|
||||||
|
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" },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
// --- State ---
|
||||||
|
const isLoading = ref(false);
|
||||||
|
|
||||||
|
// --- 图表绘制逻辑 ---
|
||||||
|
const drawAreaChart = () => {
|
||||||
|
isLoading.value = true;
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
nextTick(() => {
|
||||||
|
uni
|
||||||
|
.createSelectorQuery()
|
||||||
|
.select("#area-chart-container")
|
||||||
|
.boundingClientRect((rect) => {
|
||||||
|
if (
|
||||||
|
rect &&
|
||||||
|
!Array.isArray(rect) &&
|
||||||
|
typeof rect.width === "number" &&
|
||||||
|
rect.width > 0 &&
|
||||||
|
typeof rect.height === "number" &&
|
||||||
|
rect.height > 0
|
||||||
|
) {
|
||||||
|
const containerWidth = rect.width;
|
||||||
|
const containerHeight = rect.height;
|
||||||
|
|
||||||
|
const ctx = uni.createCanvasContext("GradeAnalysisAreaChart");
|
||||||
|
|
||||||
|
const areaData = {
|
||||||
|
categories: props.djDuanLb.map((item) => item.name),
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: "人数",
|
||||||
|
data: props.djDuanLb.map((item) => item.value),
|
||||||
|
color: "#1890ff",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
// 验证数据完整性
|
||||||
|
if (!areaData.categories || areaData.categories.length === 0) {
|
||||||
|
console.error("图表数据不完整:categories为空");
|
||||||
|
isLoading.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!areaData.series || areaData.series.length === 0) {
|
||||||
|
console.error("图表数据不完整:series为空");
|
||||||
|
isLoading.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
!areaData.series[0].data ||
|
||||||
|
areaData.series[0].data.length === 0
|
||||||
|
) {
|
||||||
|
console.error("图表数据不完整:series[0].data为空");
|
||||||
|
isLoading.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newOption: any = {
|
||||||
|
...areaOption,
|
||||||
|
};
|
||||||
|
newOption.context = ctx;
|
||||||
|
newOption.width = containerWidth;
|
||||||
|
newOption.height = containerHeight;
|
||||||
|
newOption.categories = areaData.categories;
|
||||||
|
newOption.series = areaData.series;
|
||||||
|
|
||||||
|
// 确保没有可能导致问题的字段
|
||||||
|
if (newOption.yAxis && newOption.yAxis.data) {
|
||||||
|
delete newOption.yAxis.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("图表数据:", areaData);
|
||||||
|
|
||||||
|
try {
|
||||||
|
new uCharts(newOption);
|
||||||
|
isLoading.value = false;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("图表绘制失败:", error);
|
||||||
|
isLoading.value = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error(
|
||||||
|
`无法获取容器 #area-chart-container 的有效尺寸:`,
|
||||||
|
rect
|
||||||
|
);
|
||||||
|
isLoading.value = false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.exec();
|
||||||
|
});
|
||||||
|
}, 500);
|
||||||
|
};
|
||||||
|
|
||||||
|
// --- Lifecycle ---
|
||||||
|
onMounted(() => {
|
||||||
|
drawAreaChart();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.tb-rq {
|
||||||
|
width: 100%;
|
||||||
|
height: 350rpx;
|
||||||
|
position: relative;
|
||||||
|
margin: 8rpx 0;
|
||||||
|
border-radius: 6px;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: #ffffff;
|
||||||
|
box-shadow: 0 1rpx 4rpx rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.charts {
|
||||||
|
width: 100% !important;
|
||||||
|
height: 100% !important;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tb-placeholder {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
color: #999;
|
||||||
|
font-size: 24rpx;
|
||||||
|
background-color: #ffffff;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
176
src/pages/view/homeSchool/components/CjZfFs.vue
Normal file
176
src/pages/view/homeSchool/components/CjZfFs.vue
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
<template>
|
||||||
|
<uni-section
|
||||||
|
title="总分分数段"
|
||||||
|
type="line"
|
||||||
|
titleFontSize="16px"
|
||||||
|
padding
|
||||||
|
class="mt-10"
|
||||||
|
>
|
||||||
|
<view class="tb-rq" id="donut-chart-container">
|
||||||
|
<canvas
|
||||||
|
canvas-id="GradeAnalysisDonutChart"
|
||||||
|
id="GradeAnalysisDonutChart"
|
||||||
|
class="charts"
|
||||||
|
/>
|
||||||
|
<view v-if="isLoading" class="tb-placeholder">
|
||||||
|
图表加载中或无数据...
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</uni-section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import uCharts from "@/components/charts/u-charts.js";
|
||||||
|
import { nextTick, onMounted, ref } from "vue";
|
||||||
|
import { ringOption } from "./cj.data";
|
||||||
|
|
||||||
|
// --- Interfaces ---
|
||||||
|
interface FsDuan {
|
||||||
|
name: string;
|
||||||
|
value: number;
|
||||||
|
color: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Props ---
|
||||||
|
interface Props {
|
||||||
|
fsDuanLb?: FsDuan[];
|
||||||
|
}
|
||||||
|
|
||||||
|
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" },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
// --- State ---
|
||||||
|
const isLoading = ref(false);
|
||||||
|
|
||||||
|
// --- 图表绘制逻辑 ---
|
||||||
|
const drawDonutChart = () => {
|
||||||
|
isLoading.value = true;
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
nextTick(() => {
|
||||||
|
uni
|
||||||
|
.createSelectorQuery()
|
||||||
|
.select("#donut-chart-container")
|
||||||
|
.boundingClientRect((rect) => {
|
||||||
|
if (
|
||||||
|
rect &&
|
||||||
|
!Array.isArray(rect) &&
|
||||||
|
typeof rect.width === "number" &&
|
||||||
|
rect.width > 0 &&
|
||||||
|
typeof rect.height === "number" &&
|
||||||
|
rect.height > 0
|
||||||
|
) {
|
||||||
|
const containerWidth = rect.width;
|
||||||
|
const containerHeight = rect.height;
|
||||||
|
|
||||||
|
const ctx = uni.createCanvasContext("GradeAnalysisDonutChart");
|
||||||
|
|
||||||
|
const donutData = {
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: "总分分数段",
|
||||||
|
data: props.fsDuanLb,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
// 验证数据完整性
|
||||||
|
if (!donutData.series || donutData.series.length === 0) {
|
||||||
|
console.error("图表数据不完整:series为空");
|
||||||
|
isLoading.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
!donutData.series[0].data ||
|
||||||
|
donutData.series[0].data.length === 0
|
||||||
|
) {
|
||||||
|
console.error("图表数据不完整:series[0].data为空");
|
||||||
|
isLoading.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newOption: any = {
|
||||||
|
...ringOption,
|
||||||
|
};
|
||||||
|
newOption.context = ctx;
|
||||||
|
newOption.width = containerWidth;
|
||||||
|
newOption.height = containerHeight;
|
||||||
|
newOption.series = donutData.series;
|
||||||
|
|
||||||
|
// 确保没有可能导致问题的字段
|
||||||
|
if (newOption.yAxis && newOption.yAxis.data) {
|
||||||
|
delete newOption.yAxis.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("图表数据:", donutData);
|
||||||
|
|
||||||
|
try {
|
||||||
|
new uCharts(newOption);
|
||||||
|
isLoading.value = false;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("图表绘制失败:", error);
|
||||||
|
isLoading.value = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error(
|
||||||
|
`无法获取容器 #donut-chart-container 的有效尺寸:`,
|
||||||
|
rect
|
||||||
|
);
|
||||||
|
isLoading.value = false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.exec();
|
||||||
|
});
|
||||||
|
}, 500);
|
||||||
|
};
|
||||||
|
|
||||||
|
// --- Lifecycle ---
|
||||||
|
onMounted(() => {
|
||||||
|
drawDonutChart();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.tb-rq {
|
||||||
|
width: 100%;
|
||||||
|
height: 350rpx;
|
||||||
|
position: relative;
|
||||||
|
margin: 8rpx 0;
|
||||||
|
border-radius: 6px;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: #ffffff;
|
||||||
|
box-shadow: 0 1rpx 4rpx rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.charts {
|
||||||
|
width: 100% !important;
|
||||||
|
height: 100% !important;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tb-placeholder {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
color: #999;
|
||||||
|
font-size: 24rpx;
|
||||||
|
background-color: #ffffff;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
370
src/pages/view/homeSchool/components/cj.data.ts
Normal file
370
src/pages/view/homeSchool/components/cj.data.ts
Normal file
@ -0,0 +1,370 @@
|
|||||||
|
export const ringOption = {
|
||||||
|
type: "ring",
|
||||||
|
// context: ctx,
|
||||||
|
// width: containerWidth,
|
||||||
|
// height: containerHeight,
|
||||||
|
// series: donutData.series,
|
||||||
|
animation: true,
|
||||||
|
timing: "easeOut",
|
||||||
|
duration: 1000,
|
||||||
|
rotate: false,
|
||||||
|
rotateLock: false,
|
||||||
|
background: "#FFFFFF",
|
||||||
|
color: [
|
||||||
|
"#1890FF",
|
||||||
|
"#91CB74",
|
||||||
|
"#FAC858",
|
||||||
|
"#EE6666",
|
||||||
|
"#73C0DE",
|
||||||
|
"#3CA272",
|
||||||
|
"#FC8452",
|
||||||
|
"#9A60B4",
|
||||||
|
"#ea7ccc",
|
||||||
|
],
|
||||||
|
padding: [5, 5, 5, 5],
|
||||||
|
fontSize: 13,
|
||||||
|
fontColor: "#666666",
|
||||||
|
dataLabel: true,
|
||||||
|
dataPointShape: true,
|
||||||
|
dataPointShapeType: "solid",
|
||||||
|
touchMoveLimit: 60,
|
||||||
|
enableScroll: false,
|
||||||
|
enableMarkLine: false,
|
||||||
|
legend: {
|
||||||
|
show: true,
|
||||||
|
position: "right",
|
||||||
|
lineHeight: 25,
|
||||||
|
float: "center",
|
||||||
|
padding: 5,
|
||||||
|
margin: 5,
|
||||||
|
backgroundColor: "rgba(0,0,0,0)",
|
||||||
|
borderColor: "rgba(0,0,0,0)",
|
||||||
|
borderWidth: 0,
|
||||||
|
fontSize: 13,
|
||||||
|
fontColor: "#666666",
|
||||||
|
hiddenColor: "#CECECE",
|
||||||
|
itemGap: 10,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
name: "",
|
||||||
|
fontSize: 15,
|
||||||
|
color: "#666666",
|
||||||
|
offsetX: 0,
|
||||||
|
offsetY: 0,
|
||||||
|
},
|
||||||
|
subtitle: {
|
||||||
|
name: "",
|
||||||
|
fontSize: 25,
|
||||||
|
color: "#7cb5ec",
|
||||||
|
offsetX: 0,
|
||||||
|
offsetY: 0,
|
||||||
|
},
|
||||||
|
extra: {
|
||||||
|
ring: {
|
||||||
|
ringWidth: 30,
|
||||||
|
activeOpacity: 0.5,
|
||||||
|
activeRadius: 10,
|
||||||
|
offsetAngle: 0,
|
||||||
|
labelWidth: 15,
|
||||||
|
border: true,
|
||||||
|
borderWidth: 3,
|
||||||
|
borderColor: "#FFFFFF",
|
||||||
|
centerColor: "#FFFFFF",
|
||||||
|
customRadius: 0,
|
||||||
|
linearType: "none",
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
showBox: true,
|
||||||
|
showArrow: true,
|
||||||
|
showCategory: false,
|
||||||
|
borderWidth: 0,
|
||||||
|
borderRadius: 0,
|
||||||
|
borderColor: "#000000",
|
||||||
|
borderOpacity: 0.7,
|
||||||
|
bgColor: "#000000",
|
||||||
|
bgOpacity: 0.7,
|
||||||
|
gridType: "solid",
|
||||||
|
dashLength: 4,
|
||||||
|
gridColor: "#CCCCCC",
|
||||||
|
boxPadding: 3,
|
||||||
|
fontSize: 13,
|
||||||
|
lineHeight: 20,
|
||||||
|
fontColor: "#FFFFFF",
|
||||||
|
legendShow: true,
|
||||||
|
legendShape: "auto",
|
||||||
|
splitLine: true,
|
||||||
|
horizentalLine: false,
|
||||||
|
xAxisLabel: false,
|
||||||
|
yAxisLabel: false,
|
||||||
|
labelBgColor: "#FFFFFF",
|
||||||
|
labelBgOpacity: 0.7,
|
||||||
|
labelFontColor: "#666666",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const areaOption = {
|
||||||
|
type: "area",
|
||||||
|
// context: ctx,
|
||||||
|
// width: containerWidth,
|
||||||
|
// height: containerHeight,
|
||||||
|
// categories: areaData.categories,
|
||||||
|
// series: areaData.series,
|
||||||
|
animation: true,
|
||||||
|
timing: "easeOut",
|
||||||
|
duration: 1000,
|
||||||
|
rotate: false,
|
||||||
|
rotateLock: false,
|
||||||
|
background: "#FFFFFF",
|
||||||
|
color: [
|
||||||
|
"#1890FF",
|
||||||
|
"#91CB74",
|
||||||
|
"#FAC858",
|
||||||
|
"#EE6666",
|
||||||
|
"#73C0DE",
|
||||||
|
"#3CA272",
|
||||||
|
"#FC8452",
|
||||||
|
"#9A60B4",
|
||||||
|
"#ea7ccc",
|
||||||
|
],
|
||||||
|
padding: [15, 15, 0, 15],
|
||||||
|
fontSize: 13,
|
||||||
|
fontColor: "#666666",
|
||||||
|
dataLabel: true,
|
||||||
|
dataPointShape: true,
|
||||||
|
dataPointShapeType: "solid",
|
||||||
|
touchMoveLimit: 60,
|
||||||
|
enableScroll: false,
|
||||||
|
enableMarkLine: false,
|
||||||
|
legend: {
|
||||||
|
show: false,
|
||||||
|
position: "bottom",
|
||||||
|
float: "center",
|
||||||
|
padding: 5,
|
||||||
|
margin: 5,
|
||||||
|
backgroundColor: "rgba(0,0,0,0)",
|
||||||
|
borderColor: "rgba(0,0,0,0)",
|
||||||
|
borderWidth: 0,
|
||||||
|
fontSize: 13,
|
||||||
|
fontColor: "#666666",
|
||||||
|
lineHeight: 11,
|
||||||
|
hiddenColor: "#CECECE",
|
||||||
|
itemGap: 10,
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
disableGrid: true,
|
||||||
|
disabled: false,
|
||||||
|
axisLine: true,
|
||||||
|
axisLineColor: "#CCCCCC",
|
||||||
|
calibration: false,
|
||||||
|
fontColor: "#666666",
|
||||||
|
fontSize: 13,
|
||||||
|
lineHeight: 20,
|
||||||
|
marginTop: 0,
|
||||||
|
rotateLabel: false,
|
||||||
|
rotateAngle: 45,
|
||||||
|
itemCount: 5,
|
||||||
|
boundaryGap: "center",
|
||||||
|
splitNumber: 5,
|
||||||
|
gridColor: "#CCCCCC",
|
||||||
|
gridType: "solid",
|
||||||
|
dashLength: 4,
|
||||||
|
gridEval: 1,
|
||||||
|
scrollShow: false,
|
||||||
|
scrollAlign: "left",
|
||||||
|
scrollColor: "#A6A6A6",
|
||||||
|
scrollBackgroundColor: "#EFEBEF",
|
||||||
|
title: "",
|
||||||
|
titleFontSize: 13,
|
||||||
|
titleOffsetY: 0,
|
||||||
|
titleOffsetX: 0,
|
||||||
|
titleFontColor: "#666666",
|
||||||
|
formatter: "",
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
gridType: "dash",
|
||||||
|
dashLength: 2,
|
||||||
|
disabled: false,
|
||||||
|
disableGrid: false,
|
||||||
|
splitNumber: 5,
|
||||||
|
gridColor: "#CCCCCC",
|
||||||
|
padding: 10,
|
||||||
|
showTitle: false,
|
||||||
|
data: [],
|
||||||
|
},
|
||||||
|
extra: {
|
||||||
|
area: {
|
||||||
|
type: "straight",
|
||||||
|
opacity: 0.2,
|
||||||
|
addLine: true,
|
||||||
|
width: 2,
|
||||||
|
gradient: false,
|
||||||
|
activeType: "hollow",
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
showBox: true,
|
||||||
|
showArrow: true,
|
||||||
|
showCategory: false,
|
||||||
|
borderWidth: 0,
|
||||||
|
borderRadius: 0,
|
||||||
|
borderColor: "#000000",
|
||||||
|
borderOpacity: 0.7,
|
||||||
|
bgColor: "#000000",
|
||||||
|
bgOpacity: 0.7,
|
||||||
|
gridType: "solid",
|
||||||
|
dashLength: 4,
|
||||||
|
gridColor: "#CCCCCC",
|
||||||
|
boxPadding: 3,
|
||||||
|
fontSize: 13,
|
||||||
|
lineHeight: 20,
|
||||||
|
fontColor: "#FFFFFF",
|
||||||
|
legendShow: true,
|
||||||
|
legendShape: "auto",
|
||||||
|
splitLine: true,
|
||||||
|
horizentalLine: false,
|
||||||
|
xAxisLabel: false,
|
||||||
|
yAxisLabel: false,
|
||||||
|
labelBgColor: "#FFFFFF",
|
||||||
|
labelBgOpacity: 0.7,
|
||||||
|
labelFontColor: "#666666",
|
||||||
|
},
|
||||||
|
markLine: {
|
||||||
|
type: "solid",
|
||||||
|
dashLength: 4,
|
||||||
|
data: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const lineOption = {
|
||||||
|
type: "line",
|
||||||
|
// context: ctx,
|
||||||
|
// width: containerWidth,
|
||||||
|
// height: containerHeight,
|
||||||
|
// categories: lineData.categories,
|
||||||
|
// series: lineData.series,
|
||||||
|
animation: true,
|
||||||
|
timing: "easeOut",
|
||||||
|
duration: 1000,
|
||||||
|
rotate: false,
|
||||||
|
rotateLock: false,
|
||||||
|
background: "#FFFFFF",
|
||||||
|
color: [
|
||||||
|
"#1890FF",
|
||||||
|
"#91CB74",
|
||||||
|
"#FAC858",
|
||||||
|
"#EE6666",
|
||||||
|
"#73C0DE",
|
||||||
|
"#3CA272",
|
||||||
|
"#FC8452",
|
||||||
|
"#9A60B4",
|
||||||
|
"#ea7ccc",
|
||||||
|
],
|
||||||
|
padding: [15, 10, 0, 15],
|
||||||
|
fontSize: 13,
|
||||||
|
fontColor: "#666666",
|
||||||
|
dataLabel: true,
|
||||||
|
dataPointShape: true,
|
||||||
|
dataPointShapeType: "solid",
|
||||||
|
touchMoveLimit: 60,
|
||||||
|
enableScroll: false,
|
||||||
|
enableMarkLine: false,
|
||||||
|
legend: {
|
||||||
|
show: false,
|
||||||
|
position: "bottom",
|
||||||
|
float: "center",
|
||||||
|
padding: 5,
|
||||||
|
margin: 5,
|
||||||
|
backgroundColor: "rgba(0,0,0,0)",
|
||||||
|
borderColor: "rgba(0,0,0,0)",
|
||||||
|
borderWidth: 0,
|
||||||
|
fontSize: 13,
|
||||||
|
fontColor: "#666666",
|
||||||
|
lineHeight: 11,
|
||||||
|
hiddenColor: "#CECECE",
|
||||||
|
itemGap: 10,
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
disableGrid: true,
|
||||||
|
disabled: false,
|
||||||
|
axisLine: true,
|
||||||
|
axisLineColor: "#CCCCCC",
|
||||||
|
calibration: false,
|
||||||
|
fontColor: "#666666",
|
||||||
|
fontSize: 13,
|
||||||
|
lineHeight: 20,
|
||||||
|
marginTop: 0,
|
||||||
|
rotateLabel: false,
|
||||||
|
rotateAngle: 45,
|
||||||
|
itemCount: 5,
|
||||||
|
boundaryGap: "center",
|
||||||
|
splitNumber: 5,
|
||||||
|
gridColor: "#CCCCCC",
|
||||||
|
gridType: "solid",
|
||||||
|
dashLength: 4,
|
||||||
|
gridEval: 1,
|
||||||
|
scrollShow: false,
|
||||||
|
scrollAlign: "left",
|
||||||
|
scrollColor: "#A6A6A6",
|
||||||
|
scrollBackgroundColor: "#EFEBEF",
|
||||||
|
title: "",
|
||||||
|
titleFontSize: 13,
|
||||||
|
titleOffsetY: 0,
|
||||||
|
titleOffsetX: 0,
|
||||||
|
titleFontColor: "#666666",
|
||||||
|
formatter: "",
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
gridType: "dash",
|
||||||
|
dashLength: 2,
|
||||||
|
disabled: false,
|
||||||
|
disableGrid: false,
|
||||||
|
splitNumber: 5,
|
||||||
|
gridColor: "#CCCCCC",
|
||||||
|
padding: 10,
|
||||||
|
showTitle: false,
|
||||||
|
data: [],
|
||||||
|
},
|
||||||
|
extra: {
|
||||||
|
line: {
|
||||||
|
type: "straight",
|
||||||
|
width: 2,
|
||||||
|
activeType: "hollow",
|
||||||
|
linearType: "none",
|
||||||
|
onShadow: false,
|
||||||
|
animation: "vertical",
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
showBox: true,
|
||||||
|
showArrow: true,
|
||||||
|
showCategory: false,
|
||||||
|
borderWidth: 0,
|
||||||
|
borderRadius: 0,
|
||||||
|
borderColor: "#000000",
|
||||||
|
borderOpacity: 0.7,
|
||||||
|
bgColor: "#000000",
|
||||||
|
bgOpacity: 0.7,
|
||||||
|
gridType: "solid",
|
||||||
|
dashLength: 4,
|
||||||
|
gridColor: "#CCCCCC",
|
||||||
|
boxPadding: 3,
|
||||||
|
fontSize: 13,
|
||||||
|
lineHeight: 20,
|
||||||
|
fontColor: "#FFFFFF",
|
||||||
|
legendShow: true,
|
||||||
|
legendShape: "auto",
|
||||||
|
splitLine: true,
|
||||||
|
horizentalLine: false,
|
||||||
|
xAxisLabel: false,
|
||||||
|
yAxisLabel: false,
|
||||||
|
labelBgColor: "#FFFFFF",
|
||||||
|
labelBgOpacity: 0.7,
|
||||||
|
labelFontColor: "#666666",
|
||||||
|
},
|
||||||
|
markLine: {
|
||||||
|
type: "solid",
|
||||||
|
dashLength: 4,
|
||||||
|
data: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
228
src/pages/view/test/ApiTest.vue
Normal file
228
src/pages/view/test/ApiTest.vue
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
<template>
|
||||||
|
<BasicLayout :show-nav-bar="true" :nav-bar-props="{ title: 'API测试' }">
|
||||||
|
<view class="api-test-page">
|
||||||
|
<!-- 测试教师授课班级接口 -->
|
||||||
|
<view class="test-section">
|
||||||
|
<view class="section-title">测试教师授课班级接口</view>
|
||||||
|
<button @click="testJsdkb" class="test-btn">
|
||||||
|
测试获取教师授课班级
|
||||||
|
</button>
|
||||||
|
<view v-if="jsdkbResult" class="result-section">
|
||||||
|
<text class="result-title">结果:</text>
|
||||||
|
<text class="result-text">{{
|
||||||
|
JSON.stringify(jsdkbResult, null, 2)
|
||||||
|
}}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 测试考试场次接口 -->
|
||||||
|
<view class="test-section">
|
||||||
|
<view class="section-title">测试考试场次接口</view>
|
||||||
|
<input
|
||||||
|
v-model="testBjId"
|
||||||
|
placeholder="输入班级ID"
|
||||||
|
class="input-field"
|
||||||
|
/>
|
||||||
|
<button @click="testKscc" class="test-btn">测试获取考试场次</button>
|
||||||
|
<view v-if="ksccResult" class="result-section">
|
||||||
|
<text class="result-title">结果:</text>
|
||||||
|
<text class="result-text">{{
|
||||||
|
JSON.stringify(ksccResult, null, 2)
|
||||||
|
}}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 测试成绩接口 -->
|
||||||
|
<view class="test-section">
|
||||||
|
<view class="section-title">测试成绩接口</view>
|
||||||
|
<input
|
||||||
|
v-model="testBjId2"
|
||||||
|
placeholder="输入班级ID"
|
||||||
|
class="input-field"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
v-model="testKsccId"
|
||||||
|
placeholder="输入考试场次ID"
|
||||||
|
class="input-field"
|
||||||
|
/>
|
||||||
|
<button @click="testCjData" class="test-btn">测试获取成绩数据</button>
|
||||||
|
<view v-if="cjDataResult" class="result-section">
|
||||||
|
<text class="result-title">结果:</text>
|
||||||
|
<text class="result-text">{{
|
||||||
|
JSON.stringify(cjDataResult, null, 2)
|
||||||
|
}}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 测试缓存机制 -->
|
||||||
|
<view class="test-section">
|
||||||
|
<view class="section-title">测试缓存机制</view>
|
||||||
|
<button @click="testCache" class="test-btn">测试缓存机制</button>
|
||||||
|
<view v-if="cacheResult" class="result-section">
|
||||||
|
<text class="result-title">缓存测试结果:</text>
|
||||||
|
<text class="result-text">{{ cacheResult }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</BasicLayout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { jsdBjKscjApi, jsdJsdkbApi, jsdKsccApi } from "@/api/base/server";
|
||||||
|
import { useCommonStore } from "@/store/modules/common";
|
||||||
|
import { useUserStore } from "@/store/modules/user";
|
||||||
|
import { ref } from "vue";
|
||||||
|
|
||||||
|
const commonStore = useCommonStore();
|
||||||
|
const userStore = useUserStore();
|
||||||
|
|
||||||
|
const jsdkbResult = ref<any>(null);
|
||||||
|
const ksccResult = ref<any>(null);
|
||||||
|
const cjDataResult = ref<any>(null);
|
||||||
|
const cacheResult = ref<string>("");
|
||||||
|
|
||||||
|
const testBjId = ref<string>("");
|
||||||
|
const testBjId2 = ref<string>("");
|
||||||
|
const testKsccId = ref<string>("");
|
||||||
|
|
||||||
|
const testJsdkb = async () => {
|
||||||
|
try {
|
||||||
|
const jsData = userStore.getJs();
|
||||||
|
if (!jsData || !jsData.id) {
|
||||||
|
uni.showToast({ title: "教师信息不存在", icon: "none" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await jsdJsdkbApi({ jsId: jsData.id });
|
||||||
|
jsdkbResult.value = response;
|
||||||
|
console.log("教师授课班级测试结果:", response);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("测试教师授课班级接口出错:", error);
|
||||||
|
uni.showToast({ title: "测试失败", icon: "none" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const testKscc = async () => {
|
||||||
|
try {
|
||||||
|
if (!testBjId.value) {
|
||||||
|
uni.showToast({ title: "请输入班级ID", icon: "none" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await jsdKsccApi({ bjId: testBjId.value });
|
||||||
|
ksccResult.value = response;
|
||||||
|
console.log("考试场次测试结果:", response);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("测试考试场次接口出错:", error);
|
||||||
|
uni.showToast({ title: "测试失败", icon: "none" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const testCjData = async () => {
|
||||||
|
try {
|
||||||
|
if (!testBjId2.value || !testKsccId.value) {
|
||||||
|
uni.showToast({ title: "请输入班级ID和考试场次ID", icon: "none" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await jsdBjKscjApi({
|
||||||
|
bjId: testBjId2.value,
|
||||||
|
ksccId: testKsccId.value,
|
||||||
|
});
|
||||||
|
cjDataResult.value = response;
|
||||||
|
console.log("成绩数据测试结果:", response);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("测试成绩数据接口出错:", error);
|
||||||
|
uni.showToast({ title: "测试失败", icon: "none" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const testCache = async () => {
|
||||||
|
try {
|
||||||
|
const jsData = userStore.getJs();
|
||||||
|
if (!jsData || !jsData.id) {
|
||||||
|
uni.showToast({ title: "教师信息不存在", icon: "none" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 第一次调用,应该从API获取数据
|
||||||
|
const startTime1 = Date.now();
|
||||||
|
const response1 = await commonStore.getJsdkb({ jsId: jsData.id });
|
||||||
|
const time1 = Date.now() - startTime1;
|
||||||
|
|
||||||
|
// 第二次调用,应该从缓存获取数据
|
||||||
|
const startTime2 = Date.now();
|
||||||
|
const response2 = await commonStore.getJsdkb({ jsId: jsData.id });
|
||||||
|
const time2 = Date.now() - startTime2;
|
||||||
|
|
||||||
|
cacheResult.value = `第一次调用耗时: ${time1}ms, 第二次调用耗时: ${time2}ms, 缓存是否生效: ${
|
||||||
|
time2 < time1
|
||||||
|
}`;
|
||||||
|
console.log("缓存测试结果:", cacheResult.value);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("测试缓存机制出错:", error);
|
||||||
|
uni.showToast({ title: "缓存测试失败", icon: "none" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.api-test-page {
|
||||||
|
padding: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.test-section {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
padding: 20rpx;
|
||||||
|
margin-bottom: 30rpx;
|
||||||
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.test-btn {
|
||||||
|
background: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
padding: 20rpx 40rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-field {
|
||||||
|
border: 1rpx solid #ddd;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
padding: 20rpx;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-section {
|
||||||
|
background: #f8f9fa;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
padding: 20rpx;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-title {
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 10rpx;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-text {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #666;
|
||||||
|
word-break: break-all;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -1,11 +1,12 @@
|
|||||||
import { defineStore } from "pinia";
|
|
||||||
import {
|
import {
|
||||||
njFindAll,
|
|
||||||
bjFindByNjId,
|
bjFindByNjId,
|
||||||
jsFindAll,
|
jsFindAll,
|
||||||
|
njFindAll,
|
||||||
zwFindAllApi,
|
zwFindAllApi,
|
||||||
zwGetListByLxApi,
|
zwGetListByLxApi,
|
||||||
} from "@/api/base/common";
|
} from "@/api/base/common";
|
||||||
|
import { jsdJsdkbApi, jsdKsccApi } from "@/api/base/server";
|
||||||
|
import { defineStore } from "pinia";
|
||||||
|
|
||||||
interface CommonState {
|
interface CommonState {
|
||||||
data: any;
|
data: any;
|
||||||
@ -15,12 +16,12 @@ export const useCommonStore = defineStore({
|
|||||||
id: "app-common",
|
id: "app-common",
|
||||||
state: (): CommonState => ({
|
state: (): CommonState => ({
|
||||||
// 字典数据
|
// 字典数据
|
||||||
data: {}
|
data: {},
|
||||||
}),
|
}),
|
||||||
getters: {
|
getters: {
|
||||||
getData(): any {
|
getData(): any {
|
||||||
return this.data;
|
return this.data;
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
setData(data: any) {
|
setData(data: any) {
|
||||||
@ -36,6 +37,7 @@ export const useCommonStore = defineStore({
|
|||||||
// 根据年级查询班级
|
// 根据年级查询班级
|
||||||
async getBjListByNj(params: any): Promise<any> {
|
async getBjListByNj(params: any): Promise<any> {
|
||||||
if (!this.data.bj || !this.data.bj[params.njId]) {
|
if (!this.data.bj || !this.data.bj[params.njId]) {
|
||||||
|
this.data.bj = this.data.bj || {};
|
||||||
this.data.bj[params.njId] = await bjFindByNjId(params);
|
this.data.bj[params.njId] = await bjFindByNjId(params);
|
||||||
}
|
}
|
||||||
return Promise.resolve(this.data.bj[params.njId]);
|
return Promise.resolve(this.data.bj[params.njId]);
|
||||||
@ -62,10 +64,38 @@ export const useCommonStore = defineStore({
|
|||||||
}
|
}
|
||||||
return Promise.resolve(this.data.zw[params.zwlx]);
|
return Promise.resolve(this.data.zw[params.zwlx]);
|
||||||
},
|
},
|
||||||
|
// 获取教师授课班级列表
|
||||||
|
async getJsdkb(params: any): Promise<any> {
|
||||||
|
if (!this.data.jsdkb || !this.data.jsdkb[params.jsId]) {
|
||||||
|
this.data.jsdkb = this.data.jsdkb || {};
|
||||||
|
this.data.jsdkb[params.jsId] = await jsdJsdkbApi(params);
|
||||||
|
}
|
||||||
|
return Promise.resolve(this.data.jsdkb[params.jsId]);
|
||||||
|
},
|
||||||
|
// 获取班级考试场次列表(带缓存机制)
|
||||||
|
async getKscc(params: any): Promise<any> {
|
||||||
|
if (!this.data.kscc || !this.data.kscc[params.bjId]) {
|
||||||
|
this.data.kscc = this.data.kscc || {};
|
||||||
|
this.data.kscc[params.bjId] = await jsdKsccApi(params);
|
||||||
|
}
|
||||||
|
return Promise.resolve(this.data.kscc[params.bjId]);
|
||||||
|
},
|
||||||
|
// 清除班级考试场次缓存
|
||||||
|
clearKsccCache(bjId?: string) {
|
||||||
|
if (bjId) {
|
||||||
|
// 清除指定班级的缓存
|
||||||
|
if (this.data.kscc && this.data.kscc[bjId]) {
|
||||||
|
delete this.data.kscc[bjId];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 清除所有考试场次缓存
|
||||||
|
this.data.kscc = {};
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
persist: {
|
persist: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
detached: true,
|
detached: true,
|
||||||
H5Storage: localStorage
|
H5Storage: localStorage,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user