Files
zhxg_app/pages/instructor/performance-appraisal/components/student-management.vue
Stickman ecc0d00a4f 辅导员管理-添加业绩考核个人填报详情和加分项、就业指导工作API
- 新增kpiFillingDetail函数用于获取业绩考核个人填报详情
- 新增加分项相关API:kpiFillingBonusPointsAdd、kpiFillingBonusPointsUpdate、
  kpiFillingBonusPointsDetail
- 新增就业指导工作相关API:kpiFillingGraduationGuidanceAdd、
  kpiFillingGraduationGuidanceUpdate、kpiFillingGraduationGuidanceDetail
- 添加TODO注释标记待后端API完成的功能

fix(pages): 解决部门名称存储问题

- 启用被注释掉的部门名称存储功能
- 确保deptName正确存入本地缓存

feat(performance): 支持毕业班和非毕业班不同考核标准

- 为考勤管理组件添加classType参数支持
- 为负面清单组件添加classType参数支持
- 为专业工作组件重构标签显示逻辑,支持根据classType动态显示
- 为奖励绩效加班组件添加classType参数支持
- 为学生突发事件组件添加classType参数支持
- 为学生管理组件添加毕业班/非毕业班差异化显示逻辑

refactor(performance): 优化业绩评估页面结构

- 添加班级类型选择按钮(毕业班/非毕业班)
- 在填报时间弹窗中集成班级类型选择功能
- 更新数据加载逻辑以支持classType参数
- 修正各种评分计算中的数值类型转换问题
```
2026-03-13 15:14:29 +08:00

285 lines
9.0 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="student-management">
<view class="form-item">
<label>{{label01}}</label>
<view class="bottom">
<input @blur="onLimitInput($event,'classScoring',10)" v-model="classScoring" type="number"
placeholder="请输入分值" placeholder-class="input-placeholder" />
<text @tap="uploadClassMeetingMaterial">
{{commitStatus==1?"查看材料":"上传材料"}}
</text>
</view>
</view>
<view class="form-item" v-if="!isGraduate">
<label>{{label02}}</label>
<view class="bottom">
<input @blur="onLimitInput($event,'visitDormitoryScoring',10)" v-model="visitDormitoryScoring" type="number" placeholder="请输入分值"
placeholder-class="input-placeholder" />
<text @tap="uploadSleepCheckMaterial">
{{commitStatus==1?"查看材料":"上传材料"}}
</text>
</view>
</view>
<view class="form-item">
<label>{{label03}}</label>
<view class="bottom">
<input @blur="onLimitInput($event,'stuTalkScoring',10)" v-model="stuTalkScoring" type="number" placeholder="请输入分值"
placeholder-class="input-placeholder" />
<text @tap="uploadInterviewMaterial">
{{commitStatus==1?"查看材料":"上传材料"}}
</text>
</view>
</view>
<view class="form-item" v-if="!isGraduate">
<label>{{label04}}</label>
<view class="bottom">
<input @blur="onLimitInput($event,'cadreScoring',5)" v-model="cadreScoring" type="number" placeholder="请输入分值" placeholder-class="input-placeholder" />
<text @tap="uploadLeagueMeetingMaterial">
{{commitStatus==1?"查看材料":"上传材料"}}
</text>
</view>
</view>
<view class="form-item" v-if="!isGraduate">
<label>{{label05}}</label>
<view class="bottom">
<input @blur="onLimitInput($event,'stuActivityScoring',5)" v-model="stuActivityScoring" type="number" placeholder="请输入分值"
placeholder-class="input-placeholder" />
<text @tap="uploadStuActivityMaterials">
{{commitStatus==1?"查看材料":"上传材料"}}
</text>
</view>
</view>
<view class="form-item" v-if="!isGraduate">
<label>{{label06}}</label>
<view class="bottom">
<input @blur="onLimitInput($event,'edgScoring',5)" v-model="edgScoring" type="number" placeholder="请输入分值"
placeholder-class="input-placeholder" />
</view>
</view>
<view class="form-item" v-if="!isGraduate">
<label>{{label07}}</label>
<view class="bottom">
<input @blur="onLimitInput($event,'noticeScoring',5)" v-model="noticeScoring" type="number" placeholder="请输入分值"
placeholder-class="input-placeholder" />
</view>
</view>
</view>
</template>
<script>
import {
teacherKpiFillingMgtDetail
} from "@/api/instructor/superintendent.js"
import {
limitInput
} from "@/utils/limitInput.js"
export default {
props: {
queryDetailParams: Object,
commitStatus: [String, Number],
classType: {
type: String,
default: 'ungraduate'
}
},
computed: {
isGraduate() {
return this.classType === 'graduate';
},
label01() {
return this.isGraduate
? "01 每月通过线上线下方式定期召开班会开展教育10分"
: "01 每周日及节假日收假当天组织开展班会10分";
},
label02() {
if (this.isGraduate) return "";
return "02 每周深入学生宿舍至少2次10分";
},
label03() {
return this.classType === 'graduate'
? "03 月度谈心谈话总量≥10人次覆盖重点关注学生困难救助、就业预警、心理危机、违纪待处理等10分"
: "03 月度谈心谈话总量≥10人次覆盖重点关注学生困难救助、学业指导、心理危机、违纪待处理等10分";
},
label04() {
if (this.isGraduate) return "";
return "04 每月开展班团干部培训、专题工作会议频次均不少于1次5分";
},
label05() {
if (this.isGraduate) return "";
return "05 每月组织或参与学生社区育人活动、思政教育活动及文化艺术体育活动频次不少于2次5分";
},
label06() {
if (this.isGraduate) return "";
return "06 根据学校就业育人工作部署第一学期需指导并组织所带班级学生参与职业测评整体完成率需≥90%第二学期每月需开展1次就业育人相关活动。5分";
},
label07() {
if (this.isGraduate) return "";
return "07 按时按质完成学校及相关职能部门发布的与学生相关的各项工作通知、任务5分";
}
},
data() {
return {
classScoring: "", //班会材料分数
visitDormitoryScoring: "", //每周深入学生宿舍材料分数
stuTalkScoring: "", // 学生谈话分数
cadreScoring: "", //班团干部会议材料分数
stuActivityScoring: "", //学生开展活动材料分数
edgScoring: "", //职业测评分数
noticeScoring: "", //其他任务分数
id: "", //学生开展活动材料分数
queryParams:null
}
},
created() {
console.log('===== student-management created =====');
console.log('queryDetailParams:', this.queryDetailParams);
console.log('classType:', this.classType);
},
mounted() {
// 初始化查询参数
this.initQueryParams();
// 等待 classType 准备好后再查询
if (this.classType) {
this.loadData();
}
},
methods: {
loadData() {
// 查询时带上 classType
const queryParams = {
...this.queryDetailParams,
classType: this.classType
};
console.log('最终查询参数:', queryParams);
teacherKpiFillingMgtDetail(queryParams).then(res => {
console.log('===== API 返回数据 =====');
console.log(res);
if (res.data) {
// 毕业班只填充需要的字段
if (this.isGraduate) {
this.classScoring = res.data.classScoring;
this.stuTalkScoring = res.data.stuTalkScoring;
this.id = res.data.id;
} else {
this.classScoring = res.data.classScoring;
this.visitDormitoryScoring = res.data.visitDormitoryScoring;
this.stuTalkScoring = res.data.stuTalkScoring;
this.cadreScoring = res.data.cadreScoring;
this.stuActivityScoring = res.data.stuActivityScoring;
this.edgScoring = res.data.edgScoring;
this.noticeScoring = res.data.noticeScoring;
this.id = res.data.id;
}
}
})
},
initQueryParams() {
this.queryParams = new URLSearchParams({
year: this.queryDetailParams.fillingYear,
month: this.queryDetailParams.fillingMonth,
commitStatus:this.commitStatus
});
},
onLimitInput(event,name,max) {
let result = limitInput(event.detail.value,max);
this[name] = result;
},
initQueryParams() {
this.queryParams = new URLSearchParams({
year: this.queryDetailParams.fillingYear,
month: this.queryDetailParams.fillingMonth,
commitStatus:this.commitStatus
});
},
onLimitInput(event,name,max) {
let result = limitInput(event.detail.value,max);
this[name] = result;
},
uploadClassMeetingMaterial() {
uni.navigateTo({
url: `/pages/instructor/performance-appraisal/performance-evaluation/class-meeting-evidence/list?${this.queryParams.toString()}`
})
},
uploadSleepCheckMaterial() {
uni.navigateTo({
url: `/pages/instructor/performance-appraisal/performance-evaluation/sleep-check-evidence/list?${this.queryParams.toString()}`
})
},
uploadInterviewMaterial() {
uni.navigateTo({
url: `/pages/instructor/performance-appraisal/performance-evaluation/interview/list?${this.queryParams.toString()}`
})
},
uploadLeagueMeetingMaterial() {
uni.navigateTo({
url: `/pages/instructor/performance-appraisal/performance-evaluation/league-meeting/list?${this.queryParams.toString()}`
})
},
uploadStuActivityMaterials() {
uni.navigateTo({
url: `/pages/instructor/performance-appraisal/performance-evaluation/student-activity/list?${this.queryParams.toString()}`
})
},
getFormData() {
const data = {
classScoring: this.classScoring,
stuTalkScoring: this.stuTalkScoring,
id: this.id
};
// 非毕业班才包含这些字段
if (!this.isGraduate) {
data.visitDormitoryScoring = this.visitDormitoryScoring;
data.cadreScoring = this.cadreScoring;
data.stuActivityScoring = this.stuActivityScoring;
data.edgScoring = this.edgScoring;
data.noticeScoring = this.noticeScoring;
}
return data;
}
}
}
</script>
<style scoped lang="scss">
.student-management {
.form-item {
padding: 22rpx 40rpx 40rpx 40rpx;
background-color: white;
margin-bottom: 40rpx;
border-radius: 16rpx;
label {
margin-bottom: 20rpx;
display: inline-block;
font-size: 26rpx;
}
.bottom {
display: flex;
align-items: center;
input {
flex: 1;
border: 1px solid #E1E1E1;
border-radius: 10rpx;
height: 60rpx;
padding-left: 30rpx;
.input-placeholder {
color: #b6b6b6;
}
}
text {
color: #1890FF;
border-bottom: 2px solid #1890FF;
margin-left: 40rpx;
font-weight: bold;
font-size: 26rpx;
}
}
}
}
</style>