584 lines
16 KiB
Vue
Raw Normal View History

2025-06-06 15:31:45 +08:00
<script setup>
import { ref, onMounted, watch } from 'vue'
import { Table, Tag, Divider, ConfigProvider, Input, Button, Modal, Select, Pagination, message } from 'ant-design-vue';
import { PlusOutlined, CloseOutlined } from '@ant-design/icons-vue';
import { VueDraggableNext } from 'vue-draggable-next'
import zhCN from 'ant-design-vue/es/locale/zh_CN';
import { useRoute } from 'vue-router';
import { GetClassPageList, GetTeacherNames, StudentGetClassAll, AddHallClass, updateHallClass, TeacherGetClassPageList, GetGradeName } from '@/api/grade';
const route = useRoute();
onMounted(async() => {
console.log('detailReport', route.query)
await getGradeId()
await getClassList()
getTeacherList()
getStundList(0)
})
//获取年级id
const gradeId = ref(0); // 默认年级ID为90
const getGradeId = async() =>{
const res = await GetGradeName()
gradeId.value = res.data[0].id
}
//获取班级列表
const getClassList = async (name = '') => {
const res = await GetClassPageList(gradeId.value, name, 1, 100);
if (res.code === 200) {
classList.value = res.data.datas;
if (name == '') {
allStudentClass.value = res.data.datas[0] || {}
}
} else {
console.error('获取班级列表失败:', res.message);
}
}
//通过教师姓名获取班级列表
const getTeacherClassList = async (name = '') => {
//获取全部班级列表
const classAll = await GetClassPageList(90, searchClassName.value, 1, 100);
const res = await TeacherGetClassPageList(name, '', '', '', 1, 100);
if (res.code === 200) {
let list = []
res.data.datas.forEach(item => {
if (item.gradeAndClassIds['90'].length > 0) {
// list.push(item);
item.gradeAndClassIds['90'].map(c => {
if (c.id != allStudentClass.value.id) {
let nnn = classAll.data.datas.find(e => c == e.id)
if (nnn) {
list.push(nnn);
}
}
});
}
// item.teacherName = classAll.data.datas.find(c => c.id === item.classId && c.id != allStudentClass.value.id)?.teacherName || '';
});
classList.value = list;
} else {
console.error('获取班级列表失败:', res.message);
}
}
//获取所有教练名称
const getTeacherList = async () => {
try {
const res = await GetTeacherNames();
if (res.code == 200) {
teacherList.value = res.data;
} else {
ElMessage.error(res.message)
}
} catch (error) {
console.error('Error occurred while calling API:', error);
}
}
const getStundList = async (id = 0) => {
try {
const res = await StudentGetClassAll(id);
if (res.code == 200) {
if (id == 0) {
if (nowStudentShow.value) {
nowStudentList.value = res.data;
}
studentslist.value = res.data;
} else {
if (classId.value != 0) {
classFrom.value.studentIds = res.data.sort((a, b) => a.orderNo <= b.orderNo ? -1 : 1);
studentslist.value.forEach(item => {
item.isSelect = classFrom.value.studentIds.some(selected => selected.studentNo === item.studentNo);
});
console.log('classFrom.value.studentIds', classFrom.value.studentIds);
} else {
nowStudentList.value = res.data.sort((a, b) => a.orderNo <= b.orderNo ? -1 : 1);
}
// nowStudentList.value = res.data.datas;
}
} else {
ElMessage.error(res.message)
}
} catch (error) {
console.error('Error occurred while calling API:', error);
}
}
const allStudentClass = ref({});
const classList = ref([])
const columns = [
{
title: '序号',
key: 'index',
// width: 80,
customRender: ({ index }) => index + 1
},
{
title: '班级名称',
dataIndex: 'className',
key: 'className',
},
{
title: '所属教练',
dataIndex: 'teacherName',
key: 'teacherName',
},
{
title: '班级人数',
dataIndex: 'studentCount',
key: 'studentCount',
sorter: (a, b) => a - b,
},
{
title: '操作',
dataIndex: 'set',
key: 'set',
},
]
//展示弹窗
const open = ref(false);
const classId = ref(0);
const setCilck = (id, className, teacherName) => {
if (id == 0) {
classFrom.value = {
className: '',
teacherDetail: '',
studentIds: [],
}
} else {
classFrom.value = {
className: className,
teacherDetail: teacherName,
studentIds: [],
}
classId.value = id;
getStundList(id);
}
open.value = !open.value;
}
//创建班级
const handleOk = () => {
// open.value = false;
console.log('提交表单', classFrom.value);
if (!classFrom.value.className) {
message.error('班级名称不能为空');
return;
}
// if (!classFrom.value.teacherDetail) {
// message.error('所属教练不能为空');
// return;
// }
// if (classFrom.value.studentIds.length == 0) {
// message.error('学生列表不能为空');
// return;
// }
let teacherDetail = {}
if(classFrom.value.teacherDetail) {
teacherDetail = teacherList.value.find(item => item.teacherName === classFrom.value.teacherDetail);
}
// if (!teacherDetail) {
// message.error('请选择有效的教练');
// return;
// }
2025-06-06 15:31:45 +08:00
let studentIds = [];
classFrom.value.studentIds.map(item => {
studentIds.push(item.studentNo);
})
let params = {
className: classFrom.value.className,
teacherIds: teacherDetail.id ? [teacherDetail.id] : [],
2025-06-06 15:31:45 +08:00
studentNoList: studentIds // 只传学生ID
};
console.log('params', params);
const key = 'updatable';
if (classId.value != 0) {
params.classId = classId.value; // 如果是编辑传入班级ID
console.log('params222', params);
message.loading({ content: '班级信息修改中...', key });
updateHallClass(params).then(res => {
if (res.code == 200) {
message.success({content:'班级信息修改成功', key});
open.value = false;
getClassList();
} else {
message.error(res.message, key)
}
})
} else {
message.loading({ content: '创建班级中...', key });
AddHallClass(params).then(res => {
if (res.code == 200) {
message.success({content:'创建班级成功', key});
open.value = false;
getClassList();
} else {
message.error(res.message, key)
}
})
}
};
//是否展示学生列表
const studentShow = ref(false);
const studentslist = ref([]);
const teacherList = ref([]);
//展示学生列表
const classFrom = ref({
className: '',
teacherDetail: '',
studentIds: [],
})
const showStudent = () => {
studentShow.value = true;
}
const selectStudent = () => {
console.log('选择学生', classFrom.value.studentIds);
let studentIds = [];
studentslist.value.forEach(item => {
if (item.isSelect) {
studentIds.push(item);
}
});
classFrom.value.studentIds = studentIds;
console.log('选择的学生', classFrom.value.studentIds);
studentShow.value = false;
}
const log = (evt) => {
console.log(evt)
console.log(classFrom.value.studentIds)
}
const nowStudentList = ref([]);
const nowStudentShow = ref(false);
const lookStudent = (id) => {
console.log('查看学员详情', id);
nowStudentShow.value = true;
getStundList(id == allStudentClass.value.id ? 0 : id);
}
watch(open, (newVal) => {
console.log('studentShow', newVal);
if (!newVal) {
classId.value = 0;
studentslist.value.forEach(item => {
item.isSelect = false;
});
}
});
const searchClassName = ref('')
const searchTeacherName = ref('')
//重置
const handleReset = () => {
searchClassName.value = '';
searchTeacherName.value = '';
}
//查询
const handleSearch = () => {
if (searchTeacherName.value) {
getTeacherClassList(searchTeacherName.value);
return;
}
getClassList(searchClassName.value);
}
</script>
<template>
<div class="class-manage">
<div class="select-box">
班级
<Input type="text" placeholder="请输入班级名称" v-model:value="searchClassName" class="inputt" />
<!-- 所属教练
<Input type="text" placeholder="请输入教练姓名" v-model:value="searchTeacherName" class="inputt" /> -->
<Button class="btn" @click="handleReset"> 重置</Button>
<Button type="primary" class="btn" @click="handleSearch">查询</Button>
</div>
<div class="new-class-btn">
<Button type="primary" class="mb10" @click="setCilck(0)">新增班级</Button>
</div>
<ConfigProvider :locale="zhCN">
<Table :columns="columns" :data-source="classList" :locale="zhCN" :pagination="{ pageSize: 20 }">
<template #bodyCell="{ column, record, index }">
<template v-if="column.key === 'index'">
{{ index + 1 }}
</template>
<template v-if="column.key === 'studentCount' && record.id == allStudentClass.id">
{{ studentslist.length }}
</template>
<template v-if="column.key == 'set'">
<a @click="lookStudent(record.id)" class="settingg">学员详情</a>
<a @click="setCilck(record.id, record.className, record.teacherName)"
v-if="record.id != allStudentClass.id" class="settingg">编辑</a>
<!-- <a @click="setCilck" class="settingg">删除</a> -->
</template>
</template>
</Table>
</ConfigProvider>
</div>
<ConfigProvider :locale="zhCN">
<Modal v-model:visible="open" title="新增班级" @ok="handleOk" width="60%">
<div class="ever"><text style="color: red;">*&nbsp;</text>班级名称&nbsp;&nbsp;
<Input type="text" placeholder="请输入班级名称" v-model:value="classFrom.className" class="inputtt" show-count
:maxlength="32" />
</div>
<div class="ever">学生列表&nbsp;&nbsp;
2025-06-06 15:31:45 +08:00
<Button @click="showStudent" type="primary">分配学生</Button>
</div>
<div class="action">
拖动可以对学员进行排序
</div>
<vue-draggable-next v-if="classFrom.studentIds.length > 0" v-model="classFrom.studentIds" @change="log"
group="warngroup" ghost-class="ghost" class="student-box click-box" animation="300">
<!-- <div class="posi"><text style="color: red;">*&nbsp;</text>拖动可以对学员进行排序</div> -->
<transition-group>
<!-- <div class="student-box"> -->
<div v-for="(itemm, index) in classFrom.studentIds" :key="index" class="student-item">
<div class="index">{{ index + 1 }}</div>
&nbsp;&nbsp;&nbsp;&nbsp;{{ itemm.studentName }}
<img :src="`https://yuedong-wechatapplet.oss-cn-shanghai.aliyuncs.com/static/report-icon/sex_${itemm.sex}.png`"
class="sex">
<div>{{ itemm.age }} </div>
</div>
<!-- </div> -->
</transition-group>
</vue-draggable-next>
<!-- <text style="color: red;">*&nbsp;</text> -->
<div class="ever">所属教练&nbsp;&nbsp;
2025-06-06 15:31:45 +08:00
<Select v-model:value="classFrom.teacherDetail" style="width: 200px"
:options="teacherList.map(item => ({ value: item.teacherName }))"></Select>
</div>
</Modal>
<Modal v-model:visible="studentShow" title="分配学员" @ok="selectStudent" width="60%">
<div class="student-box">
<view v-for="(ite, index) in studentslist" @click="ite.isSelect = !ite.isSelect" :key="index"
class="student-item" :class="{ click: ite.isSelect, noClick: !ite.isSelect }">
{{ ite.studentName }}
<img :src="`https://yuedong-wechatapplet.oss-cn-shanghai.aliyuncs.com/static/report-icon/sex_${ite.sex}.png`"
class="sex">
<div>{{ ite.age }} &nbsp;&nbsp;</div>
<PlusOutlined v-if="!ite.isSelect" class="ml10" />
<CloseOutlined v-else class="ml10" />
</view>
</div>
</Modal>
<Modal v-model:visible="nowStudentShow" title="学员详情" @ok="nowStudentShow = false" width="60%">
<div class="student-box">
<view v-for="(ite, index) in nowStudentList" :key="index" class="student-item">
{{ ite.studentName }}
<img :src="`https://yuedong-wechatapplet.oss-cn-shanghai.aliyuncs.com/static/report-icon/sex_${ite.sex}.png`"
class="sex">
<div>{{ ite.age }} &nbsp;&nbsp;</div>
</view>
</div>
</Modal>
</ConfigProvider>
</template>
<style scoped lang="scss">
.ever {
display: flex;
align-items: center;
margin-top: 30px;
}
.inputtt {
width: 600px;
}
.posi {
position: absolute;
top: 4px;
left: 20px;
color: #999;
}
.student-box {
display: flex;
flex-wrap: wrap;
margin-top: 16px;
justify-content: flex-start;
padding: 0 30px 30px;
}
.action {
margin-left: 94px;
margin-top: 20px;
margin-bottom: -10px;
color: #999;
}
.student-item {
display: flex;
align-items: center;
justify-content: space-around;
min-width: 100px;
height: 40px;
border-radius: 10px;
background-color: #fff;
margin-right: 20px;
margin-bottom: 10px;
box-sizing: border-box;
padding: 0 16px;
font-size: 14px;
position: relative;
border: 1px solid #1890ff;
.sex {
width: 20px;
height: 20px;
background-color: #fff;
border-radius: 50%;
margin-left: 4px;
margin-right: 4px;
}
.index {
position: absolute;
top: 0;
left: 0;
background-color: #1890ff;
color: #fff;
min-width: 20px;
border-radius: 5px 0 5px 0;
display: flex;
align-items: center;
justify-content: center;
}
}
.click {
background-color: #1890ff;
color: #fff;
animation: selectAnimation 0.3s ease;
}
.noClick {
// animation: noSelectAnimation 0.3s ease;
}
@keyframes noSelectAnimation {
0% {
background-color: #1890ff;
transform: scale(1);
}
50% {
transform: scale(1.05);
}
100% {
background-color: #f0f0f0;
transform: scale(1);
}
}
@keyframes selectAnimation {
0% {
background-color: #f0f0f0;
transform: scale(1);
}
50% {
transform: scale(1.05);
}
100% {
background-color: #1890ff;
transform: scale(1);
}
}
.click-box {
margin-left: 86px;
margin-right: 66px;
box-sizing: border-box;
border: 1px solid #d9d9d9;
border-radius: 10px;
padding: 10px;
padding-top: 20px;
}
.class-manage {
padding: 24px;
background: #fff;
margin: 12px;
border-radius: 10px;
min-height: 90vh;
.select-box {
display: flex;
align-items: center;
/* justify-content: space-between; */
margin-bottom: 16px;
font-size: 14px;
}
.select-name {
font-size: 14px;
font-weight: 500;
color: #333;
margin-right: 16px;
}
.btn {
margin-right: 16px;
}
.new-class-btn {
margin-bottom: 16px;
display: flex;
justify-content: flex-end;
}
.inputt {
width: 250px;
height: 36px;
border-radius: 5px;
padding-left: 5px;
margin-right: 16px;
}
.settingg {
margin-right: 12px;
}
}
</style>