271 lines
8.7 KiB
Vue
271 lines
8.7 KiB
Vue
<template>
|
|
<el-dialog :title="`${indicatorName} - 学生数据详情`" v-model="dialogVisible" width="1000px" append-to-body destroy-on-close>
|
|
<div v-loading="loading" element-loading-text="正在加载数据...">
|
|
<!-- 违纪处分记录区域 - 只有数据时才显示 -->
|
|
<el-card class="mb-4" shadow="never" v-if="disciplineRecords.length > 0">
|
|
<template #header>
|
|
<div class="card-header">
|
|
<span>违纪处分记录</span>
|
|
<el-tag type="danger" size="small">{{ disciplineRecords.length }} 条记录</el-tag>
|
|
</div>
|
|
</template>
|
|
<el-table :data="disciplineRecords" border style="width: 100%">
|
|
<el-table-column label="违纪日期" prop="disciplineDate" width="120">
|
|
<template #default="scope">
|
|
{{ formatDate(scope.row.disciplineDate) }}
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column label="违纪类型" prop="disciplineTypeName" width="120" />
|
|
<el-table-column label="违纪原因" prop="disciplineReason" min-width="200" show-overflow-tooltip />
|
|
<el-table-column label="违纪内容" prop="disciplineContent" min-width="200" show-overflow-tooltip />
|
|
<el-table-column label="扣分分值" prop="scoreDeduction" width="100">
|
|
<template #default="scope">
|
|
<el-tag type="danger" size="small">-{{ scope.row.scoreDeduction || 0 }}</el-tag>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
</el-card>
|
|
|
|
<!-- 奖励记录区域 - 只有数据时才显示 -->
|
|
<el-card shadow="never" v-if="rewardRecords.length > 0">
|
|
<template #header>
|
|
<div class="card-header">
|
|
<span>奖励记录</span>
|
|
<el-tag type="success" size="small">{{ rewardRecords.length }} 条记录</el-tag>
|
|
</div>
|
|
</template>
|
|
<el-table :data="rewardRecords" border style="width: 100%">
|
|
<el-table-column label="奖励日期" prop="rewardDate" width="120">
|
|
<template #default="scope">
|
|
{{ formatDate(scope.row.rewardDate) }}
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column label="奖励类型" prop="rewardTypeName" width="120" />
|
|
<el-table-column label="奖励内容" prop="rewardContent" min-width="200" show-overflow-tooltip />
|
|
<el-table-column label="加分分值" prop="scoreAddition" width="100">
|
|
<template #default="scope">
|
|
<el-tag type="success" size="small">+{{ scope.row.scoreAddition || 0 }}</el-tag>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
</el-card>
|
|
|
|
<!-- 当没有任何数据时显示 -->
|
|
<el-empty v-if="disciplineRecords.length === 0 && rewardRecords.length === 0 && !loading" description="暂无相关数据记录" />
|
|
</div>
|
|
</el-dialog>
|
|
</template>
|
|
|
|
<script setup name="IndicatorDataDialog" lang="ts">
|
|
import { ref, reactive, toRefs, watch } from 'vue';
|
|
import ElMessage from 'element-plus/es/components/message/index';
|
|
import request from '@/utils/request';
|
|
|
|
// 类型定义
|
|
interface DisciplineRecord {
|
|
id: string | number;
|
|
disciplineDate: string;
|
|
disciplineTypeName: string;
|
|
disciplineReason: string;
|
|
disciplineContent: string;
|
|
scoreDeduction: number;
|
|
}
|
|
|
|
interface RewardRecord {
|
|
id: string | number;
|
|
rewardDate: string;
|
|
rewardTypeName: string;
|
|
rewardContent: string;
|
|
scoreAddition: number;
|
|
}
|
|
|
|
interface IndicatorDataDialogProps {
|
|
indicatorId: string | number;
|
|
indicatorName: string;
|
|
studentId: string | number;
|
|
scheduleId: string | number;
|
|
dataStartTime: string; // 数据统计开始时间
|
|
dataEndTime: string; // 数据统计结束时间
|
|
}
|
|
|
|
const props = defineProps<IndicatorDataDialogProps>();
|
|
|
|
const dialogVisible = ref(false);
|
|
const loading = ref(false);
|
|
|
|
const data = reactive({
|
|
disciplineRecords: [] as DisciplineRecord[],
|
|
rewardRecords: [] as RewardRecord[]
|
|
});
|
|
|
|
const { disciplineRecords, rewardRecords } = toRefs(data);
|
|
|
|
// 监听props变化,当indicatorId变化时重新加载数据
|
|
watch(
|
|
() => props.indicatorId,
|
|
(newIndicatorId, oldIndicatorId) => {
|
|
// 只有当弹窗可见且indicatorId真正发生变化时才重新加载
|
|
if (dialogVisible.value && newIndicatorId !== oldIndicatorId && newIndicatorId) {
|
|
console.log('indicatorId变化,重新加载数据:', { old: oldIndicatorId, new: newIndicatorId });
|
|
loadData();
|
|
}
|
|
},
|
|
{ immediate: false }
|
|
);
|
|
|
|
// 格式化日期
|
|
const formatDate = (dateStr: string) => {
|
|
if (!dateStr) return '-';
|
|
return new Date(dateStr).toLocaleDateString('zh-CN');
|
|
};
|
|
|
|
// 打开弹窗
|
|
const openDialog = async () => {
|
|
dialogVisible.value = true;
|
|
// 强制刷新数据,确保使用最新的props值
|
|
await forceRefreshData();
|
|
};
|
|
|
|
// 强制刷新数据
|
|
const forceRefreshData = async () => {
|
|
// 清空之前的数据
|
|
data.disciplineRecords = [];
|
|
data.rewardRecords = [];
|
|
|
|
// 确保使用最新的props值
|
|
await loadData();
|
|
};
|
|
|
|
// 加载数据
|
|
const loadData = async () => {
|
|
// 如果弹窗未显示或没有indicatorId,则不加载数据
|
|
if (!dialogVisible.value || !props.indicatorId) {
|
|
console.log('弹窗未显示或无indicatorId,跳过数据加载');
|
|
return;
|
|
}
|
|
|
|
loading.value = true;
|
|
try {
|
|
console.log('开始加载指标数据,indicatorId:', props.indicatorId);
|
|
|
|
// 获取指标关联的违纪处分类型和奖励类型
|
|
const indicatorTypesResponse = await request({
|
|
url: `/disciplineRecord/disciplineRecord/getIndicatorTypes/${props.indicatorId}`,
|
|
method: 'get'
|
|
});
|
|
|
|
if (indicatorTypesResponse.code === 200 && indicatorTypesResponse.data) {
|
|
// 修复字段名映射:后端返回下划线格式,前端使用驼峰格式
|
|
const disciplineTypeIds = indicatorTypesResponse.data.discipline_type_ids || indicatorTypesResponse.data.disciplineTypeIds;
|
|
const rewardTypeIds = indicatorTypesResponse.data.reward_type_ids || indicatorTypesResponse.data.rewardTypeIds;
|
|
|
|
// 并行加载违纪处分记录和奖励记录
|
|
await Promise.all([loadDisciplineRecords(disciplineTypeIds), loadRewardRecords(rewardTypeIds)]);
|
|
} else {
|
|
ElMessage.warning('获取指标类型信息失败');
|
|
}
|
|
} catch (error) {
|
|
console.error('加载数据失败:', error);
|
|
ElMessage.error('加载数据失败,请稍后重试');
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
};
|
|
|
|
// 加载违纪处分记录
|
|
const loadDisciplineRecords = async (disciplineTypeIds: string) => {
|
|
if (!disciplineTypeIds) {
|
|
data.disciplineRecords = [];
|
|
return;
|
|
}
|
|
|
|
console.log('加载违纪处分记录,props:', props);
|
|
console.log('加载违纪处分记录,disciplineTypeIds:', disciplineTypeIds);
|
|
console.log('加载违纪处分记录,dataStartTime:', props.dataStartTime);
|
|
console.log('加载违纪处分记录,dataEndTime:', props.dataEndTime);
|
|
console.log('加载违纪处分记录,studentId:', props.studentId);
|
|
|
|
try {
|
|
const response = await request({
|
|
url: '/disciplineRecord/disciplineRecord/getStudentDisciplineRecords',
|
|
method: 'get',
|
|
params: {
|
|
studentId: props.studentId,
|
|
disciplineTypeIds: disciplineTypeIds,
|
|
startTime: props.dataStartTime,
|
|
endTime: props.dataEndTime,
|
|
status: 1 // 只查询状态为1的记录
|
|
}
|
|
});
|
|
|
|
if (response.code === 200) {
|
|
data.disciplineRecords = response.data || [];
|
|
} else {
|
|
ElMessage.warning('获取违纪处分记录失败');
|
|
data.disciplineRecords = [];
|
|
}
|
|
} catch (error) {
|
|
console.error('获取违纪处分记录失败:', error);
|
|
data.disciplineRecords = [];
|
|
}
|
|
};
|
|
|
|
// 加载奖励记录
|
|
const loadRewardRecords = async (rewardTypeIds: string) => {
|
|
if (!rewardTypeIds) {
|
|
data.rewardRecords = [];
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const response = await request({
|
|
url: '/rewardRecord/rewardRecord/getStudentRewardRecords',
|
|
method: 'get',
|
|
params: {
|
|
studentId: props.studentId,
|
|
rewardTypeIds: rewardTypeIds,
|
|
startTime: props.dataStartTime,
|
|
endTime: props.dataEndTime,
|
|
status: 1 // 只查询状态为1的记录
|
|
}
|
|
});
|
|
|
|
if (response.code === 200) {
|
|
data.rewardRecords = response.data || [];
|
|
} else {
|
|
ElMessage.warning('获取奖励记录失败');
|
|
data.rewardRecords = [];
|
|
}
|
|
} catch (error) {
|
|
console.error('获取奖励记录失败:', error);
|
|
data.rewardRecords = [];
|
|
}
|
|
};
|
|
|
|
// 关闭弹窗
|
|
const closeDialog = () => {
|
|
dialogVisible.value = false;
|
|
// 清空数据
|
|
data.disciplineRecords = [];
|
|
data.rewardRecords = [];
|
|
};
|
|
|
|
defineExpose({
|
|
openDialog,
|
|
closeDialog,
|
|
forceRefreshData
|
|
});
|
|
</script>
|
|
|
|
<style scoped>
|
|
.card-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
|
|
.mb-4 {
|
|
margin-bottom: 16px;
|
|
}
|
|
</style>
|