Commit 29123da1 authored by 罗超's avatar 罗超

完善上课消耗表

parent 3790833d
...@@ -277,6 +277,13 @@ export function queryChapterTree(data) { ...@@ -277,6 +277,13 @@ export function queryChapterTree(data) {
}) })
} }
export function queryScheduleCourseStu(data) {
return request({
url: "/ScheduleCourse/GetScheduleCourseStu ",
method: 'post',
data
})
}
/** /**
* 保存课程章节 * 保存课程章节
* @param {JSON参数} data * @param {JSON参数} data
......
<template> <template>
<div class="col"></div> <div class="col scroll-box" id="scrollBox" @scroll="(e)=>scrollHandle(e)">
<div :style="{width: innerW}" id="scrollInnerTemplate"></div>
</div>
</template> </template>
<script> <script>
...@@ -15,26 +17,45 @@ export default { ...@@ -15,26 +17,45 @@ export default {
} }
}, },
data() { data() {
return {}; return {
innerW:'0px',
ratio:0,
boxRatio:0
};
}, },
methods: { methods: {
createResizeObserver() { createResizeObserver() {
this.resizeObserver = new ResizeObserver(entries => { this.resizeObserver = new ResizeObserver(entries => {
for (let entry of entries) { this.calcHandle()
console.log("Element size changed:", entry.contentRect);
// 你可以在这里处理大小变化的逻辑
}
}); });
this.resizeObserver.observe(this.$refs.resizeElement); this.resizeObserver.observe(document.querySelector(`#${this.targetBox}`));
this.resizeObserver.observe(document.querySelector(`#${this.targetWrap}`));
}, },
destroyResizeObserver() { destroyResizeObserver() {
if (this.resizeObserver) { if (this.resizeObserver) {
this.resizeObserver.disconnect(); this.resizeObserver.disconnect();
} }
},
calcHandle(){
const box = document.querySelector('#scrollBox')
const tb = document.querySelector(`#${this.targetBox}`)
const tw = document.querySelector(`#${this.targetWrap}`)
if(box && tb && tw){
this.ratio = tw.offsetWidth/tb.offsetWidth
this.innerW = `${this.ratio * box.offsetWidth}px`
this.boxRatio = tb.offsetWidth/box.offsetWidth
}
},
scrollHandle(e){
const box = document.querySelector('#scrollBox')
const sl = box.scrollLeft*this.boxRatio
this.$emit("scrollChange", sl);
} }
}, },
mounted() { mounted() {
this.createResizeObserver(); this.createResizeObserver();
}, },
beforeDestroy() { beforeDestroy() {
this.destroyResizeObserver(); this.destroyResizeObserver();
...@@ -43,6 +64,11 @@ export default { ...@@ -43,6 +64,11 @@ export default {
</script> </script>
<style> <style>
.scroll-box{
overflow-x: auto;
overflow-y: hidden;
height: 15px;
}
.scroll-box::-webkit-scrollbar { .scroll-box::-webkit-scrollbar {
width: 6px; width: 6px;
height: 6px; height: 6px;
......
<template> <template>
<!-- <div class="page-body" style="height:calc(100% - 30px);"> --> <!-- <div class="page-body" style="height:calc(100% - 30px);"> -->
<div class="sptable-box"> <div class="sptable-box" id="sptable">
<div class="sptable-wrap"> <div class="sptable-wrap" id="sptableWrap" v-loading="loading" :style="{'zoom':zoom}">
<table class="sptable"> <table class="sptable">
<thead> <thead>
<tr class="sticky-header"> <tr class="sticky-header">
<th class="sticky-column">Header 1</th> <th class="sticky-column stubg">学员</th>
<th>Header 2</th> <th class="stubg" v-for="(x,i) in students" :key="i">{{ x.GuestName }}</th>
<th>Header 3</th>
<th>Header 4</th>
<th>Header 1</th>
<th>Header 2</th>
<th>Header 3</th>
<th>Header 4</th>
<th>Header 1</th>
<th>Header 2</th>
<th>Header 3</th>
<th>Header 4</th>
<th>Header 1</th>
<th>Header 2</th>
<th>Header 3</th>
<th>Header 4</th>
<th>Header 1</th>
<th>Header 2</th>
<th>Header 3</th>
<th>Header 4</th>
<!-- 更多表头列... -->
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<!-- 表格内容 --> <tr>
<tr v-for="i in 50" :key="i"> <td class="sticky-column coursebg">课程</td>
<td class="sticky-column">1</td> <td class="coursebg" v-for="(x,i) in students" :key="i">
<td>1</td> {{ currentCourse.CourseName }}
<td>1</td> </td>
<td>1</td> </tr>
<td>1</td> <tr>
<td>1</td> <td class="sticky-column teacherbg">班主任</td>
<td>1</td> <td class="teacherbg" v-for="(x,i) in students" :key="i">{{ x.HeadMasterName }}</td>
<td>1</td> </tr>
<td>1</td> <tr>
<td>1</td> <td class="sticky-column studybg">方式</td>
<td>1</td> <td
<td>1</td> :class="{ 'study-online-bg': x.TeachingMethod== 2, studybg: x.TeachingMethod!= 2 }"
<td>1</td> v-for="(x,i) in students" :key="i"
<td>1</td> >
<td>1</td> {{ x.TeachingMethod== 2 ? "线上" : "面授" }}
<td>1</td> </td>
<td>1</td> </tr>
<td>1</td> <tr>
<td>1</td> <td class="sticky-column defaultBg">
<td>1</td> 进度<br />({{ currentCourse.ClassHours }}课时)
</td>
<td v-for="(x,i) in students" :key="i" :class="{ 'stop': currentCourse.ClassHours-x.ClassProgress<0 || x.ScheduleStatus==1 }">
<span>剩余{{ currentCourse.ClassHours-x.ClassProgress }}课时</span>
<div v-if="currentCourse.ClassHours-x.ClassProgress<0 || x.ScheduleStatus==1">暂停排课</div>
<div v-else class="text-primary">周一,五排课</div>
</td>
</tr>
<tr>
<td class="sticky-column studybg">备注</td>
<td
v-for="(x,i) in students" :key="i"
style="word-wrap: break-word;white-space: wrap; max-width: 150px; vertical-align: middle;"
@dblclick="changeRemark(i)"
:contenteditable="i==currentRemark"
></td>
</tr>
<tr>
<td :colspan="students.length+1">&nbsp;</td>
</tr>
<!-- 表格内容 study-online-bg -->
<tr v-for="(x,i) in chapters" :key="i">
<td class="sticky-column defaultBg" style="text-align: left;">{{ x.ChapterName }}</td>
<td v-for="(y,yi) in x.assemble" :key="yi" :class="{'study-normal':y}">
&nbsp;
<q-tooltip :offset="[0, 0]" v-if="y">
{{ y.Date }}
</q-tooltip>
</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</div> </div>
<div class="cusor-tools row"> <div class="cusor-tools row">
<div class="item active">N5</div> <div class="col row">
<div class="item">N4</div> <div
<div class="item">N3</div> class="item"
<div class="item">N2</div> @click="changeCourseHandle(x)"
<div class="item">N1</div> :class="{ active: x.CourseId == currentCourse.CourseId }"
<div class="item">一对一中教</div> v-for="(x,i) in list"
:key="i"
>
{{ x.CourseName }}
</div>
</div>
<scroll-bar
targetBox="sptable"
targetWrap="sptableWrap"
@scrollChange="scrollHandle"
></scroll-bar>
</div> </div>
</div> </div>
<!-- </div> --> <!-- </div> -->
</template> </template>
<script> <script>
import scrollBar from 'src/components/common/scrollBar.vue'; import scrollBar from "src/components/common/scrollBar.vue";
import { queryCoursePage,queryChapterTree,queryScheduleCourseStu } from "../../api/course/index";
export default { export default {
components: { scrollBar },
meta: { meta: {
title: "学员学习进度表" title: "学员学习进度表"
}, },
data() { data() {
return {}; return {
list: [],
loading: true,
msg: {
pageIndex: 1,
pageSize: 120,
rowsPerPage: 120,
CourseName: "",
QCateIds: "",
IsQPrice: 1,
Status: "0",
Saleplat: 0,
CourseSubject: 1,
SaleState: 1
},
currentCourse: {},
chapters: [],
currentRemark: 0,
students:[],
assemble:[],
zoom:1
};
},
methods: {
scrollHandle(e) {
console.log(e);
const box = document.querySelector("#sptable");
box.scrollLeft = e;
},
getCourse() {
this.loading = true;
queryCoursePage(this.msg)
.then(res => {
this.loading = false;
this.list = res.Data.PageData.reverse();
this.currentCourse = this.list[0];
this.getChapters()
})
.catch(() => {
this.loading = false;
});
},
getChapters() {
if(!this.currentCourse || !this.currentCourse.CourseId) return
this.loading = true;
queryChapterTree({CourseId:this.currentCourse.CourseId})
.then(res => {
this.loading = false;
this.chapters = res.Data
this.getStudents()
})
.catch(() => {
this.loading = false;
});
},
changeCourseHandle(item) {
this.currentCourse = item;
this.getChapters()
},
changeRemark(i){
this.currentRemark=i
},
getStudents(){
if(!this.currentCourse || !this.currentCourse.CourseId) return
this.loading = true;
queryScheduleCourseStu({CourseRate:this.currentCourse.CourseRate}).then(r=>{
console.log(r.Data)
this.students = r.Data
this.loading = false;
this.assembleHandler()
}).catch(()=>{
this.loading = false;
})
},
assembleHandler(){
this.assemble = []
this.chapters.forEach(x=>{
x.assemble=[]
this.students.forEach(stu=>{
const r = stu.CourseItems.find(item=>item.ChapterId==x.ChapterGradeNo)
x.assemble.push(r)
})
})
},
handleWheel(event) {
if(event.ctrlKey === true || event.metaKey === true){
if (event.deltaY > 0) {
this.zoomOut();
} else {
this.zoomIn();
}
event.preventDefault();
return false
}
},
zoomIn() {
// 放大逻辑
if(this.zoom<4) this.zoom+=0.05
},
zoomOut() {
// 缩小逻辑
if(this.zoom>0.1) this.zoom-=0.05
}
}, },
methods: {} created() {
this.getCourse();
},
mounted(){
document.addEventListener('wheel', this.handleWheel,{ passive: false });
},
beforeDestroy(){
document.removeEventListener('wheel', this.handleWheel,{ passive: false });
}
}; };
</script> </script>
...@@ -84,11 +216,12 @@ export default { ...@@ -84,11 +216,12 @@ export default {
.sptable-box { .sptable-box {
width: 100%; width: 100%;
height: 100%; height: 100%;
overflow: auto; overflow-y: auto;
overflow: overlay;
padding-bottom: 20px; padding-bottom: 20px;
user-select: none;
background: #fff;
} }
.sptable-box .sptable-wrap{ .sptable-box .sptable-wrap {
position: relative; position: relative;
} }
...@@ -117,8 +250,28 @@ export default { ...@@ -117,8 +250,28 @@ export default {
.sptable th { .sptable th {
border-right: 1px solid #000; border-right: 1px solid #000;
border-bottom: 1px solid #000; border-bottom: 1px solid #000;
padding: 3px 6px; padding: 6px 15px;
min-width: 200px; /* min-width: 200px; */
white-space: nowrap;
text-align: center;
color: #000;
outline: none;
position: relative;
}
.sptable td:focus::before{
}
.sptable td:focus::before{
position: absolute;
content: " ";
display: block;
top: -1px;
left: -1px;
right: -1px;
bottom: -1px;
z-index: 15;
border: 3px solid #418F1F;
pointer-events: none;
} }
.sptable tr td:last-child { .sptable tr td:last-child {
border-right: none; border-right: none;
...@@ -126,93 +279,120 @@ export default { ...@@ -126,93 +279,120 @@ export default {
.sptable tr:last-child td:last-child { .sptable tr:last-child td:last-child {
border: none; border: none;
} }
.sptable .sticky-header th{ .sptable .sticky-header th {
position: sticky; position: sticky;
top: 0px; top: 0px;
background: #FFF; background: #fff;
z-index: 2; z-index: 2;
border-bottom: none; border-bottom: none;
} }
.sptable .sticky-column { .sptable .sticky-column {
position: sticky; position: sticky;
left: 0px; left: 0px;
background: #FFF; background: #fff;
box-shadow: inset -4px -2px 0px -3px #1FBB7D; box-shadow: inset -4px -2px 0px -3px #1fbb7d;
border-right:0; border-right: 0;
z-index: 1; z-index: 1;
} }
.sptable .sticky-header th::before, .sptable .sticky-header th::before,
.sptable .sticky-header th::after, .sptable .sticky-header th::after,
.sptable .sticky-column::before{ .sptable-box::before,
.sptable .sticky-column::before {
position: absolute; position: absolute;
content: ''; content: "";
display: block; display: block;
width: 1px; width: 1px;
background: #000; background: #000;
top: 0; top: 0;
left: -1px; left: -1px;
bottom: 0; bottom: 0;
z-index: 5; z-index: 15;
height: 100%; height: 100%;
} }
.sptable .sticky-header th::before{ .sptable-box::before {
left: 0;
}
.sptable .sticky-header th::before {
top: 0; top: 0;
left: 0; left: 0;
width: 100%; width: 100%;
height: 1px; height: 1px;
} }
.sptable .sticky-header th::after{ .sptable .sticky-header th::after {
top: unset; top: unset;
bottom: 0; bottom: 0;
left: 0; left: 0;
width: 100%; width: 100%;
height: 1px; height: 1px;
background: #1FBB7D; background: #1fbb7d;
} }
.sptable .sticky-header .sticky-column { .sptable .sticky-header .sticky-column {
z-index: 3; z-index: 3;
border-right:0; border-right: 0;
} }
.sptable-box .cusor-tools{ .sptable-box .cusor-tools {
position: absolute; position: absolute;
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
height: 27px; height: 27px;
background: #E3E6ED; background: #e3e6ed;
border-top: 1px solid #C9CCD2; border-top: 1px solid #c9ccd2;
border-bottom: 1px solid #C9CCD2; border-bottom: 1px solid #c9ccd2;
border-left: 1px solid #000; border-left: 1px solid #000;
border-right: 1px solid #000; border-right: 1px solid #000;
z-index: 9; z-index: 9;
padding: 0 30px; padding: 0 30px;
} }
.sptable-box .cusor-tools .item{ .sptable-box .cusor-tools .item {
height: 22px; height: 22px;
line-height: 22px; line-height: 22px;
border:1px solid transparent; border: 1px solid transparent;
border-radius: 5px; border-radius: 5px;
border-top-left-radius: 0; border-top-left-radius: 0;
border-top-right-radius: 0; border-top-right-radius: 0;
font-size: 12px; font-size: 12px;
color:#000; color: #000;
padding: 0 15px; padding: 0 15px;
cursor: pointer; cursor: pointer;
position: relative; position: relative;
} }
.sptable-box .cusor-tools .item:hover{ .sptable-box .cusor-tools .item:hover {
background: #CFCFCF; background: #cfcfcf;
} }
.sptable-box .cusor-tools .item.active{ .sptable-box .cusor-tools .item.active {
background: #FFF !important; background: #fff !important;
cursor: default !important; cursor: default !important;
border-color: #C9CCD2; border-color: #c9ccd2;
border-top: transparent; border-top: transparent;
margin-top: -1px; margin-top: -1px;
font-weight: bold; font-weight: bold;
color: #007A6B; color: #007a6b;
height: 23px; height: 23px;
line-height: 23px; line-height: 23px;
} }
.sptable .coursebg {
background: #ffd964;
}
.sptable .stubg {
background: #92d050;
}
.sptable .teacherbg {
background: #9999ff;
}
.sptable .studybg {
background: #f08784;
}
.sptable .study-online-bg {
background: #ed7b30;
}
.sptable .stop {
background: #ea3680;
}
.sptable .defaultBg{
background: #cfcfcf;
}
.sptable .study-normal{
background: #548235;
}
</style> </style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment