2025-07-13 18:33:09 +08:00

303 lines
7.5 KiB
Vue

<template>
<BasicLayout :show-nav-bar="true" :nav-bar-props="{ title: '工作量统计' }">
<view class="grade-analysis-page">
<uni-section title="排课工作量" type="line" titleFontSize="16px" padding>
<view v-if="pkList.length">
<view class="section-sub-card r-md" v-for="(pk, index) in pkList" :key="index">
<view class="card-title">{{ pk.kmMc }}</view>
<view class="card-body">
<view class="summary-stats-card">
<view class="stats-grid">
<view class="stat-item">
<text class="label">课时</text>
<text class="value primary">{{ pk.ks }}</text>
</view>
<view class="stat-item">
<text class="label">系数</text>
<text class="value success">{{ pk.xs }}</text>
</view>
<view class="stat-item">
<text class="label">周工作量</text>
<text class="value">{{ (pk.xs || 1.0) * (pk.ks || 0.0) }}</text>
</view>
</view>
</view>
</view>
</view>
</view>
<view class="section-empty" v-else>
<text>无工作量</text>
</view>
</uni-section>
<uni-section title="职务工作量" type="line" titleFontSize="16px" padding>
<view class="section-sub-card r-md" v-if="zwList.length">
<view class="card-body">
<view class="score-table">
<view class="table-header">
<view class="th">职务名称</view>
<view class="th flex-80">周工作量</view>
</view>
<view class="table-body">
<view class="table-row" v-for="(zw, index) in zwList" :key="index">
<view class="td">{{ zw.zwMc }}</view>
<view class="td flex-80">{{ zw.ks }}</view>
</view>
</view>
</view>
</view>
</view>
<view class="section-empty" v-else>
<text>无工作量</text>
</view>
</uni-section>
<uni-section title="班主任工作量" type="line" titleFontSize="16px" padding>
<view v-if="bzrList.length">
<view class="section-sub-card r-md" v-for="(bzr, index) in bzrList" :key="index">
<view class="card-title">{{ bzr.njmc }}-{{ bzr.bjmc }}</view>
<view class="card-body">
<view class="summary-stats-card">
<view class="stats-grid-2">
<view class="stat-item">
<text class="label">工作量占比</text>
<text class="value success">{{ bzr.zb * 100 }}%</text>
</view>
<view class="stat-item">
<text class="label">周工作量</text>
<text class="value">{{ bzr.ks }}</text>
</view>
</view>
</view>
</view>
</view>
</view>
<view class="section-empty" v-else>
<text>无工作量</text>
</view>
</uni-section>
</view>
<template #bottom>
<view class="bottom-container">
<view class="stats-grid">
<view class="stat-item">
<text class="label">总工作量</text>
<text class="value primary">{{ gzl.zks }}</text>
</view>
<view class="stat-item">
<text class="label">校平均工作量</text>
<text class="value success">{{ pjGzl }}</text>
</view>
<view class="stat-item">
<text class="label">达标率</text>
<text class="value">{{ dbl }}%</text>
</view>
</view>
</view>
</template>
</BasicLayout>
</template>
<script lang="ts" setup>
import { gzlFindPageApi, getJsPjGzlApi } from "@/api/base/server";
import BasicLayout from "@/components/BasicLayout/Layout.vue";
import { useUserStore } from "@/store/modules/user";
const { getJs } = useUserStore();
const pjGzl = ref(1.0);
const dbl = ref(100.0);
const gzl = ref<any>({
zks: 20.0
});
const pkList = ref<any[]>([
{ id: 1, kmMc: "语文", xs: 1.0, ks: 5.0 },
{ id: 2, kmMc: "数学", xs: 1.0, ks: 4.0 },
{ id: 3, kmMc: "英语", xs: 1.0, ks: 3.0 },
]);
const zwList = ref<any[]>([
{ id: 1, zwMc: "书记", ks: 5.0 },
{ id: 2, zwMc: "校长", ks: 4.0 },
]);
const bzrList = ref<any[]>([
{ id: 1, njmc: "一年级", bjmc: "1班", zb: 0.33, ks: 2.0 },
{ id: 2, njmc: "二年级", bjmc: "1班", zb: 0.5, ks: 3.0 },
{ id: 3, njmc: "二年级", bjmc: "2班", zb: 1.0, ks: 6.0 },
]);
onMounted(async () => {
{
const res = await getJsPjGzlApi();
pjGzl.value = parseFloat((res.result || '1.0'));
}
{
const res = await gzlFindPageApi({ jsId: getJs.id });
if (!res.rows || !res.rows.length) {
return;
}
gzl.value = res.rows[0] || {};
pkList.value = gzl.value.gzlPkList || [];
zwList.value = gzl.value.gzlZwList || [];
bzrList.value = gzl.value.gzlBzrList || [];
dbl.value = gzl.value.zks * 100.0 / pjGzl.value;
}
});
</script>
<style scoped lang="scss">
.grade-analysis-page {
background-color: #f4f5f7;
padding-bottom: 20rpx;
}
// --- Section Styling ---
.uni-section {
background-color: #fff;
margin: 20rpx;
border-radius: 8px;
overflow: hidden;
.section-sub-card {
background-color: #fff;
display: flex;
flex-direction: column;
.card-title {
padding: 8px 10px;
border-bottom: 1px solid #eee;
}
.card-body {
padding: 8px 10px;
}
}
.section-empty {
text-align: center;
padding: 20px;
color: #999;
}
}
// --- Score Table ---
.score-table {
width: 100%;
font-size: 26rpx;
border: 1rpx solid #e0e0e0;
border-radius: 4px;
overflow: hidden;
.table-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;
}
&.flex-80 {
flex: 0 0 80px;
}
}
}
.table-body {
.table-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;
}
&.flex-80 {
flex: 0 0 80px;
}
}
}
.table-empty {
text-align: center;
color: #999;
padding: 40rpx 0;
}
}
}
// --- Summary Stats ---
.summary-stats-card {
background-color: #f8f9fd;
border-radius: 6px;
padding: 20rpx;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 25rpx 15rpx;
}
.stats-grid-2 {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 25rpx 15rpx;
}
.stat-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;
}
}
}
.bottom-container {
background-color: white;
padding: 15px;
margin-top: 8px;
}
</style>