584 lines
16 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.

<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;
// }
let studentIds = [];
classFrom.value.studentIds.map(item => {
studentIds.push(item.studentNo);
})
let params = {
className: classFrom.value.className,
teacherIds: teacherDetail.id ? [teacherDetail.id] : [],
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;
<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;
<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>