|
@@ -1,360 +1,366 @@
|
1
|
|
-<template>
|
2
|
|
- <view class="page">
|
3
|
|
- <cu-custom :isBack="false"></cu-custom>
|
4
|
|
- <view class="header" :style="[{top:topHeader + 'px'}]">
|
5
|
|
- <view class="header-title header-switch">
|
6
|
|
- <view class="header-title-main" @tap="changeTab('schedule')" :class="{'cur':type==='schedule'}">
|
7
|
|
- <view class="margin-bottom-xs">日程表</view>
|
8
|
|
- <view class="point"></view>
|
9
|
|
- </view>
|
10
|
|
- <view class="header-title-main margin-left-lg" @tap="changeTab('mine')" :class="{'cur':type==='mine'}">
|
11
|
|
- <view class="margin-bottom-xs">我的</view>
|
12
|
|
- <view class="point"></view>
|
13
|
|
- </view>
|
14
|
|
- </view>
|
15
|
|
- <view style="width:120px;" v-if="type==='mine'">
|
16
|
|
- <swiper-tab :menuList="menuList" @changeTab="swipe" :activeTab="currentIndex"></swiper-tab>
|
17
|
|
- </view>
|
18
|
|
- </view>
|
19
|
|
- <!-- 日程表 -->
|
20
|
|
- <view v-if="type==='schedule'">
|
21
|
|
- <scroll-view scroll-y="true"
|
22
|
|
- :style="[{marginTop:'56px',height:'calc(100vh - 114px - '+ topHeader+'px)'}]">
|
23
|
|
- <uni-calendar class="uni-calendar--hook" :selected="info.selected"
|
24
|
|
- style="padding-top:100px;"
|
25
|
|
- :showMonth="false" @change="changeDay" @monthSwitch="monthSwitch" />
|
26
|
|
- <view class="cu-card margin-top-xs padding-xs">
|
27
|
|
- <view class="cu-item day-info">
|
28
|
|
- <view class="day-title flex justify-between solid-bottom padding text-lg">
|
29
|
|
- <view>应到上课节数:{{present.be_section_num}}节</view>
|
30
|
|
- <view>实际上课节数: {{present.actual_section_num}}节</view>
|
31
|
|
- </view>
|
32
|
|
- <view class="day-chart flex justify-between padding">
|
33
|
|
- <view v-for="(chart,key) in attendance" :key="key" class="flex-sub">
|
34
|
|
- <canvas :canvas-id="key" style="margin:0 auto;width:100%;height:80px;"></canvas>
|
35
|
|
- <view style="margin-left:18px;">{{chart.title}}</view>
|
36
|
|
- </view>
|
37
|
|
- </view>
|
38
|
|
- </view>
|
39
|
|
- </view>
|
40
|
|
- <view class="list margin-top-xs">
|
41
|
|
- <view class="cu-card margin-top margin-bottom shadow" v-for="(item,index) in classList" :key="index">
|
42
|
|
- <view class="cu-item" v-for="(mark,i) in item.mark" :key="i">
|
43
|
|
- <view class="card-header flex justify-end solid-bottom">
|
44
|
|
- <view class="text-student course-status">
|
45
|
|
- {{mark.status_desc}}
|
46
|
|
- </view>
|
47
|
|
- </view>
|
48
|
|
- <view class="card flex">
|
49
|
|
- <view class="card-left">
|
50
|
|
- <img mode="scaleToFill" :src="mark.avatar" alt="" class="card-image">
|
51
|
|
- </view>
|
52
|
|
- <view class="card-right margin-left-sm">
|
53
|
|
- <view class="card-title">{{mark.course_name}}</view>
|
54
|
|
- <view class="card-item margin-top-xs" >
|
55
|
|
- <text class="card-text">{{mark.start_at}}</text>
|
56
|
|
- </view>
|
57
|
|
- <view class="card-item margin-top-xs" >
|
58
|
|
- <text class="card-text">{{mark.end_at}}</text>
|
59
|
|
- </view>
|
60
|
|
- <view class="card-item margin-top-xs">
|
61
|
|
- <button class="cu-btn round line-cyan button-hover" @tap="classOperation(mark.class_plan_id)">
|
62
|
|
- {{mark.status==-1?'查看':'去上课'}}
|
63
|
|
- </button>
|
64
|
|
- <button class="cu-btn round line-red button-hover margin-left" @tap="askLeave(mark.class_plan_id)">去请假</button>
|
65
|
|
- </view>
|
66
|
|
- </view>
|
67
|
|
- </view>
|
68
|
|
- </view>
|
69
|
|
- </view>
|
70
|
|
- </view>
|
71
|
|
- </scroll-view>
|
72
|
|
- </view>
|
73
|
|
- <!-- 我的 -->
|
74
|
|
- <view v-if="type==='mine'">
|
75
|
|
- <scroll-view scroll-y="true" @scrolltolower="loadMore" class="scroll-main"
|
76
|
|
- :style="[{height:'calc(100vh - 114px - '+ topHeader+'px)'}]">
|
77
|
|
- <view class="list">
|
78
|
|
- <view class="cu-card margin-top margin-bottom shadow" v-for="(item,index) in list" :key="index">
|
79
|
|
- <view class="cu-item">
|
80
|
|
- <view class="card-header flex justify-between solid-bottom">
|
81
|
|
- <view v-if="item.day">{{item.day}}</view>
|
82
|
|
- <view class="text-student course-status" v-if="item.status">
|
83
|
|
- {{item.status}}
|
84
|
|
- </view>
|
85
|
|
- <view class="text-student course-status" v-if="currentIndex===1">
|
86
|
|
- 已完结
|
87
|
|
- </view>
|
88
|
|
- </view>
|
89
|
|
- <view class="card flex">
|
90
|
|
- <view class="card-left">
|
91
|
|
- <img mode="scaleToFill" :src="item.image" alt="" class="card-image">
|
92
|
|
- </view>
|
93
|
|
- <view class="card-right margin-left-sm">
|
94
|
|
- <view class="card-title">{{item.attend_name}}</view>
|
95
|
|
- <view class="card-item margin-top-xs" >
|
96
|
|
- <text class="card-label">机构:</text>
|
97
|
|
- <text class="card-text">{{item.agency_name||'-'}}</text>
|
98
|
|
- </view>
|
99
|
|
- <view class="card-item margin-top-xs" >
|
100
|
|
- <text class="card-label">老师:</text>
|
101
|
|
- <text class="card-text">{{item.teacher||'-'}}</text>
|
102
|
|
- </view>
|
103
|
|
- </view>
|
104
|
|
- </view>
|
105
|
|
- </view>
|
106
|
|
- </view>
|
107
|
|
- </view>
|
108
|
|
- </scroll-view>
|
109
|
|
- </view>
|
110
|
|
- <mp-tabbar :outerSelected="1" />
|
111
|
|
- </view>
|
112
|
|
-</template>
|
113
|
|
-
|
114
|
|
-<script>
|
115
|
|
-import NP from 'number-precision'
|
116
|
|
-import { uniCalendar } from '@dcloudio/uni-ui'
|
117
|
|
-import { _nowCourse, _courseHistory, _attendance, _dateCourse } from '@/api/course'
|
118
|
|
-import { getDate } from '@/common/utils'
|
119
|
|
-import swiperTab from '@/components/swiper-tab.vue'
|
120
|
|
-export default {
|
121
|
|
- components: {
|
122
|
|
- uniCalendar, swiperTab
|
123
|
|
- },
|
124
|
|
- data () {
|
125
|
|
- return {
|
126
|
|
- topHeader: this.globalCustomBarHeight,
|
127
|
|
- type: 'schedule',
|
128
|
|
- menuList: ['我的', '历史'],
|
129
|
|
- currentIndex: 0,
|
130
|
|
- page_num: 1,
|
131
|
|
- noMore: false, // 加载判断
|
132
|
|
- list: [],
|
133
|
|
- classList: [], // 日程表
|
134
|
|
- info: { // 日历数据
|
135
|
|
- year: '',
|
136
|
|
- month: '',
|
137
|
|
- day: '',
|
138
|
|
- selected: []
|
139
|
|
- },
|
140
|
|
- present: {
|
141
|
|
- absenteeism_num: 0,
|
142
|
|
- actual_section_num: 5,
|
143
|
|
- be_section_num: 5,
|
144
|
|
- late_num: 0,
|
145
|
|
- leave_num: 0,
|
146
|
|
- normal_num: 0
|
147
|
|
- }, // 实际出席情况
|
148
|
|
- attendance: { // 出席统计数据
|
149
|
|
- leave_num: {
|
150
|
|
- title: '请假', times: 2, color: '#9bde78'
|
151
|
|
- },
|
152
|
|
- late_num: {
|
153
|
|
- title: '正常', times: 3, color: '#e0be60'
|
154
|
|
- },
|
155
|
|
- normal_num: {
|
156
|
|
- title: '迟到', times: 1, color: '#61d4e2'
|
157
|
|
- },
|
158
|
|
- absenteeism_num: {
|
159
|
|
- title: '旷课', times: 0, color: '#d697eb'
|
160
|
|
- }
|
161
|
|
- }
|
162
|
|
- }
|
163
|
|
- },
|
164
|
|
- onShow() {
|
165
|
|
- const today = getDate(new Date(), 0)
|
166
|
|
- this.info.year = today.year
|
167
|
|
- this.info.month = today.month
|
168
|
|
- this.info.day = today.date
|
169
|
|
- this.init()
|
170
|
|
- },
|
171
|
|
- methods: {
|
172
|
|
- init() {
|
173
|
|
- if (this.type === 'mine') {
|
174
|
|
- this.get_list()
|
175
|
|
- } else {
|
176
|
|
- this.get_attend().then(res => {
|
177
|
|
- this.present = res.data
|
178
|
|
- this.fix_attend(res.data)
|
179
|
|
- this.drawChart()
|
180
|
|
- this.get_dateCourse()
|
181
|
|
- })
|
182
|
|
- }
|
183
|
|
- },
|
184
|
|
- classOperation(id) { // 上课
|
185
|
|
- this.globalNavigateTo('studentOperation', { id })
|
186
|
|
- },
|
187
|
|
- askLeave(id) { // 请假
|
188
|
|
- this.globalNavigateTo('studentAbsent', { id })
|
189
|
|
- },
|
190
|
|
- loadMore() {
|
191
|
|
- if (this.noMore) {
|
192
|
|
- uni.showToast({ title: '没有更多了', icon: 'none' })
|
193
|
|
- return false
|
194
|
|
- }
|
195
|
|
- this.page_num++
|
196
|
|
- this.get_list()
|
197
|
|
- },
|
198
|
|
- get_list() {
|
199
|
|
- if (this.currentIndex === 0) {
|
200
|
|
- this.get_course()
|
201
|
|
- } else {
|
202
|
|
- this.get_history()
|
203
|
|
- }
|
204
|
|
- },
|
205
|
|
- get_course() {
|
206
|
|
- _nowCourse({ page_num: this.page_num }).then(res => {
|
207
|
|
- if (this.page_num > 1) {
|
208
|
|
- if (res.data.length < this.page_size) this.noMore = true
|
209
|
|
- this.list = this.list.concat(res.data)
|
210
|
|
- } else {
|
211
|
|
- this.noMore = false
|
212
|
|
- this.list = res.data
|
213
|
|
- }
|
214
|
|
- })
|
215
|
|
- },
|
216
|
|
- get_history() {
|
217
|
|
- _courseHistory({ page_num: this.page_num }).then(res => {
|
218
|
|
- if (this.page_num > 1) {
|
219
|
|
- if (res.data.length < this.page_size) this.noMore = true
|
220
|
|
- this.list = Object.assign({}, this.list, res.data)
|
221
|
|
- } else {
|
222
|
|
- this.noMore = false
|
223
|
|
- this.list = res.data
|
224
|
|
- }
|
225
|
|
- })
|
226
|
|
- },
|
227
|
|
- drawChart() {
|
228
|
|
- for (var key in this.attendance) {
|
229
|
|
- this.draw(this.attendance[key], key)
|
230
|
|
- }
|
231
|
|
- },
|
232
|
|
- changeTab(type) {
|
233
|
|
- this.type = type
|
234
|
|
- this.$nextTick(() => {
|
235
|
|
- this.init()
|
236
|
|
- })
|
237
|
|
- },
|
238
|
|
- swipe(index) {
|
239
|
|
- this.currentIndex = index
|
240
|
|
- this.page_num = 1
|
241
|
|
- this.get_list()
|
242
|
|
- },
|
243
|
|
- changeDay(e) {
|
244
|
|
- // 模拟动态打卡
|
245
|
|
- // if (this.info.selected.length > 5) return
|
246
|
|
- // this.info.selected.push({
|
247
|
|
- // date: e.fulldate,
|
248
|
|
- // info: '打卡'
|
249
|
|
- // })
|
250
|
|
- },
|
251
|
|
- monthSwitch(e) {
|
252
|
|
- console.log(e)
|
253
|
|
- },
|
254
|
|
- get_attend() { // 获取出席情况
|
255
|
|
- const date = this.info.year + '-' + this.info.month
|
256
|
|
- return new Promise((resolve, reject) => {
|
257
|
|
- const info = _attendance({ date })
|
258
|
|
- resolve(info)
|
259
|
|
- })
|
260
|
|
- },
|
261
|
|
- fix_attend(info) { // 补充出席实际数据
|
262
|
|
- Object.keys(this.attendance).forEach(key => {
|
263
|
|
- this.attendance[key].times = info[key]
|
264
|
|
- })
|
265
|
|
- },
|
266
|
|
- get_dateCourse() { // 获取对应日期数据
|
267
|
|
- _dateCourse({ year: this.info.year, month: this.info.month }).then(res => {
|
268
|
|
- this.classList = res.data
|
269
|
|
- })
|
270
|
|
- },
|
271
|
|
- draw (ele, key) {
|
272
|
|
- const ctx = uni.createCanvasContext(key)
|
273
|
|
- const value = NP.divide(ele.times, this.present.be_section_num) * 100// 次数转化对应百分比值
|
274
|
|
- const startAngle = 1.5
|
275
|
|
- const endAngle = 1.5 + value * 2 / 100
|
276
|
|
- // 画圆环
|
277
|
|
- ctx.beginPath()
|
278
|
|
- ctx.arc(34, 40, 28, 0, 2 * Math.PI)
|
279
|
|
- ctx.setStrokeStyle('#EDEDED') // 弧线的颜色
|
280
|
|
- ctx.setLineWidth('8') // 弧的宽度
|
281
|
|
- ctx.setLineCap('round') // 线条结束端点样式 butt 平直 round 圆形 square 正方形
|
282
|
|
- ctx.stroke()
|
283
|
|
- // 画进度条
|
284
|
|
- ctx.beginPath()
|
285
|
|
- ctx.arc(34, 40, 28, startAngle * Math.PI, endAngle * Math.PI)
|
286
|
|
- ctx.setStrokeStyle(ele.color)
|
287
|
|
- ctx.setLineWidth('8')
|
288
|
|
- ctx.setLineCap('round')
|
289
|
|
- ctx.stroke()
|
290
|
|
- ctx.setFontSize(14)
|
291
|
|
- ctx.setFillStyle('#000') // 文字的颜色
|
292
|
|
- ctx.fillText(ele.times + '次', 20, 44)
|
293
|
|
- ctx.draw()
|
294
|
|
- }
|
295
|
|
- }
|
296
|
|
-}
|
297
|
|
-</script>
|
298
|
|
-
|
299
|
|
-<style lang="scss">
|
300
|
|
-@import '~@/common/css/mixin.scss';
|
301
|
|
-.page{
|
302
|
|
- height:100vh;
|
303
|
|
-}
|
304
|
|
-.header-switch{
|
305
|
|
- justify-content:start;
|
306
|
|
- .header-title-main{
|
307
|
|
- font-size:18px;
|
308
|
|
- color:#999;
|
309
|
|
- .point{
|
310
|
|
- opacity: 0;
|
311
|
|
- }
|
312
|
|
- &.cur{
|
313
|
|
- transition: font-size .3s;
|
314
|
|
- font-size:24px;
|
315
|
|
- color:#000;
|
316
|
|
- .point{
|
317
|
|
- opacity: 1;
|
318
|
|
- }
|
319
|
|
- }
|
320
|
|
- }
|
321
|
|
-}
|
322
|
|
-.day-info{
|
323
|
|
-
|
324
|
|
-}
|
325
|
|
-.scroll-main{
|
326
|
|
- margin-top:78px;
|
327
|
|
- padding:20rpx;
|
328
|
|
-}
|
329
|
|
-.cu-card{
|
330
|
|
- .cu-item{
|
331
|
|
- margin-top:10rpx;
|
332
|
|
- padding:20rpx;
|
333
|
|
- margin:0;
|
334
|
|
- }
|
335
|
|
-}
|
336
|
|
-.card-header{
|
337
|
|
- padding-bottom:10px;
|
338
|
|
- @include title(10px,18px);
|
339
|
|
-}
|
340
|
|
-.card{
|
341
|
|
- &-title{
|
342
|
|
- font-size:16px;
|
343
|
|
- }
|
344
|
|
- &-image{
|
345
|
|
- width:35vw;
|
346
|
|
- height:25vw;
|
347
|
|
- border-radius:2vw;
|
348
|
|
- }
|
349
|
|
- &-label{
|
350
|
|
- color:#999;
|
351
|
|
- }
|
352
|
|
- &-text{
|
353
|
|
- color:#333;
|
354
|
|
- }
|
355
|
|
-}
|
356
|
|
-.course-status{
|
357
|
|
- font-size:14px;
|
358
|
|
- font-weight:normal;
|
359
|
|
-}
|
360
|
|
-</style>
|
|
1
|
+<template>
|
|
2
|
+ <view class="page">
|
|
3
|
+ <cu-custom :isBack="false"></cu-custom>
|
|
4
|
+ <view class="header" :style="[{top:topHeader + 'px'}]">
|
|
5
|
+ <view class="header-title header-switch">
|
|
6
|
+ <view class="header-title-main" @tap="changeTab('schedule')" :class="{'cur':type==='schedule'}">
|
|
7
|
+ <view class="margin-bottom-xs">日程表</view>
|
|
8
|
+ <view class="point"></view>
|
|
9
|
+ </view>
|
|
10
|
+ <view class="header-title-main margin-left-lg" @tap="changeTab('mine')" :class="{'cur':type==='mine'}">
|
|
11
|
+ <view class="margin-bottom-xs">我的</view>
|
|
12
|
+ <view class="point"></view>
|
|
13
|
+ </view>
|
|
14
|
+ </view>
|
|
15
|
+ <view style="width:120px;" v-if="type==='mine'">
|
|
16
|
+ <swiper-tab :menuList="menuList" @changeTab="swipe" :activeTab="currentIndex"></swiper-tab>
|
|
17
|
+ </view>
|
|
18
|
+ </view>
|
|
19
|
+ <!-- 日程表 -->
|
|
20
|
+ <view v-if="type==='schedule'">
|
|
21
|
+ <scroll-view scroll-y="true"
|
|
22
|
+ :style="[{marginTop:'56px',height:'calc(100vh - 114px - '+ topHeader+'px)'}]">
|
|
23
|
+ <uni-calendar class="uni-calendar--hook" :selected="info.selected"
|
|
24
|
+ style="padding-top:100px;"
|
|
25
|
+ :showMonth="false" @change="changeDay" @monthSwitch="monthSwitch" />
|
|
26
|
+ <view class="cu-card margin-top-xs padding-xs">
|
|
27
|
+ <view class="cu-item day-info">
|
|
28
|
+ <view class="day-title flex justify-between solid-bottom padding text-lg">
|
|
29
|
+ <view>应到上课节数:{{present.be_section_num}}节</view>
|
|
30
|
+ <view>实际上课节数: {{present.actual_section_num}}节</view>
|
|
31
|
+ </view>
|
|
32
|
+ <view class="day-chart flex justify-between padding">
|
|
33
|
+ <view v-for="(chart,key) in attendance" :key="key" class="flex-sub">
|
|
34
|
+ <canvas :canvas-id="key" style="margin:0 auto;width:100%;height:80px;"></canvas>
|
|
35
|
+ <view style="margin-left:18px;">{{chart.title}}</view>
|
|
36
|
+ </view>
|
|
37
|
+ </view>
|
|
38
|
+ </view>
|
|
39
|
+ </view>
|
|
40
|
+ <view class="list margin-top-xs">
|
|
41
|
+ <view class="cu-card margin-top margin-bottom shadow" v-for="(item,index) in classList" :key="index">
|
|
42
|
+ <view class="cu-item" v-for="(mark,i) in item.mark" :key="i">
|
|
43
|
+ <view class="card-header flex justify-end solid-bottom">
|
|
44
|
+ <view class="text-student course-status">
|
|
45
|
+ {{mark.status_desc}}
|
|
46
|
+ </view>
|
|
47
|
+ </view>
|
|
48
|
+ <view class="card flex">
|
|
49
|
+ <view class="card-left">
|
|
50
|
+ <img mode="scaleToFill" :src="mark.avatar" alt="" class="card-image">
|
|
51
|
+ </view>
|
|
52
|
+ <view class="card-right margin-left-sm">
|
|
53
|
+ <view class="card-title">{{mark.course_name}}</view>
|
|
54
|
+ <view class="card-item margin-top-xs" >
|
|
55
|
+ <text class="card-text">{{mark.start_at}}</text>
|
|
56
|
+ </view>
|
|
57
|
+ <view class="card-item margin-top-xs" >
|
|
58
|
+ <text class="card-text">{{mark.end_at}}</text>
|
|
59
|
+ </view>
|
|
60
|
+ <view class="card-item margin-top-xs">
|
|
61
|
+ <button class="cu-btn round line-cyan button-hover" @tap="classOperation(mark.class_plan_id)">
|
|
62
|
+ {{mark.status==-1?'查看':'去上课'}}
|
|
63
|
+ </button>
|
|
64
|
+ <button class="cu-btn round line-red button-hover margin-left" @tap="askLeave(mark.class_plan_id)">去请假</button>
|
|
65
|
+ </view>
|
|
66
|
+ </view>
|
|
67
|
+ </view>
|
|
68
|
+ </view>
|
|
69
|
+ </view>
|
|
70
|
+ </view>
|
|
71
|
+ </scroll-view>
|
|
72
|
+ </view>
|
|
73
|
+ <!-- 我的 -->
|
|
74
|
+ <view v-if="type==='mine'">
|
|
75
|
+ <scroll-view scroll-y="true" @scrolltolower="loadMore" class="scroll-main"
|
|
76
|
+ :style="[{height:'calc(100vh - 114px - '+ topHeader+'px)'}]">
|
|
77
|
+ <view class="list">
|
|
78
|
+ <view class="cu-card margin-top margin-bottom shadow" v-for="(item,index) in list" :key="index">
|
|
79
|
+ <view class="cu-item">
|
|
80
|
+ <view class="card-header flex justify-between solid-bottom">
|
|
81
|
+ <view v-if="item.day">{{item.day}}</view>
|
|
82
|
+ <view class="text-student course-status" v-if="item.status">
|
|
83
|
+ {{item.status}}
|
|
84
|
+ </view>
|
|
85
|
+ <view class="text-student course-status" v-if="currentIndex===1">
|
|
86
|
+ 已完结
|
|
87
|
+ </view>
|
|
88
|
+ </view>
|
|
89
|
+ <view class="card flex">
|
|
90
|
+ <view class="card-left">
|
|
91
|
+ <img mode="scaleToFill" :src="item.image" alt="" class="card-image">
|
|
92
|
+ </view>
|
|
93
|
+ <view class="card-right margin-left-sm">
|
|
94
|
+ <view class="card-title">{{item.attend_name}}</view>
|
|
95
|
+ <view class="card-item margin-top-xs" >
|
|
96
|
+ <text class="card-label">机构:</text>
|
|
97
|
+ <text class="card-text">{{item.agency_name||'-'}}</text>
|
|
98
|
+ </view>
|
|
99
|
+ <view class="card-item margin-top-xs" >
|
|
100
|
+ <text class="card-label">老师:</text>
|
|
101
|
+ <text class="card-text">{{item.teacher||'-'}}</text>
|
|
102
|
+ </view>
|
|
103
|
+ </view>
|
|
104
|
+ </view>
|
|
105
|
+ </view>
|
|
106
|
+ </view>
|
|
107
|
+ </view>
|
|
108
|
+ </scroll-view>
|
|
109
|
+ </view>
|
|
110
|
+ <mp-tabbar :outerSelected="1" />
|
|
111
|
+ </view>
|
|
112
|
+</template>
|
|
113
|
+
|
|
114
|
+<script>
|
|
115
|
+import NP from 'number-precision'
|
|
116
|
+import { uniCalendar } from '@dcloudio/uni-ui'
|
|
117
|
+import { _nowCourse, _courseHistory, _attendance, _dateCourse } from '@/api/course'
|
|
118
|
+import { getDate } from '@/common/utils'
|
|
119
|
+import swiperTab from '@/components/swiper-tab.vue'
|
|
120
|
+export default {
|
|
121
|
+ components: {
|
|
122
|
+ uniCalendar, swiperTab
|
|
123
|
+ },
|
|
124
|
+ data () {
|
|
125
|
+ return {
|
|
126
|
+ topHeader: this.globalCustomBarHeight,
|
|
127
|
+ type: 'schedule',
|
|
128
|
+ menuList: ['我的', '历史'],
|
|
129
|
+ currentIndex: 0,
|
|
130
|
+ page_num: 1,
|
|
131
|
+ noMore: false, // 加载判断
|
|
132
|
+ list: [],
|
|
133
|
+ classList: [], // 日程表
|
|
134
|
+ info: { // 日历数据
|
|
135
|
+ year: '',
|
|
136
|
+ month: '',
|
|
137
|
+ day: '',
|
|
138
|
+ selected: []
|
|
139
|
+ },
|
|
140
|
+ present: {
|
|
141
|
+ absenteeism_num: 0,
|
|
142
|
+ actual_section_num: 5,
|
|
143
|
+ be_section_num: 5,
|
|
144
|
+ late_num: 0,
|
|
145
|
+ leave_num: 0,
|
|
146
|
+ normal_num: 0
|
|
147
|
+ }, // 实际出席情况
|
|
148
|
+ attendance: { // 出席统计数据
|
|
149
|
+ leave_num: {
|
|
150
|
+ title: '请假', times: 2, color: '#9bde78'
|
|
151
|
+ },
|
|
152
|
+ late_num: {
|
|
153
|
+ title: '正常', times: 3, color: '#e0be60'
|
|
154
|
+ },
|
|
155
|
+ normal_num: {
|
|
156
|
+ title: '迟到', times: 1, color: '#61d4e2'
|
|
157
|
+ },
|
|
158
|
+ absenteeism_num: {
|
|
159
|
+ title: '旷课', times: 0, color: '#d697eb'
|
|
160
|
+ }
|
|
161
|
+ }
|
|
162
|
+ }
|
|
163
|
+ },
|
|
164
|
+ onReady() {
|
|
165
|
+ const today = getDate(new Date(), 0)
|
|
166
|
+ this.info.year = today.year
|
|
167
|
+ this.info.month = today.month
|
|
168
|
+ this.info.day = today.date
|
|
169
|
+ this.init()
|
|
170
|
+ },
|
|
171
|
+ methods: {
|
|
172
|
+ init() {
|
|
173
|
+ if (this.type === 'mine') {
|
|
174
|
+ this.get_list()
|
|
175
|
+ } else {
|
|
176
|
+ this.getSehedule()
|
|
177
|
+ }
|
|
178
|
+ },
|
|
179
|
+ getSehedule() {
|
|
180
|
+ this.get_attend().then(res => {
|
|
181
|
+ this.present = res.data
|
|
182
|
+ this.fix_attend(res.data)
|
|
183
|
+ this.drawChart()
|
|
184
|
+ this.get_dateCourse()
|
|
185
|
+ })
|
|
186
|
+ },
|
|
187
|
+ classOperation(id) { // 上课
|
|
188
|
+ this.globalNavigateTo('studentOperation', { id })
|
|
189
|
+ },
|
|
190
|
+ askLeave(id) { // 请假
|
|
191
|
+ this.globalNavigateTo('studentAbsent', { id })
|
|
192
|
+ },
|
|
193
|
+ loadMore() {
|
|
194
|
+ if (this.noMore) {
|
|
195
|
+ uni.showToast({ title: '没有更多了', icon: 'none' })
|
|
196
|
+ return false
|
|
197
|
+ }
|
|
198
|
+ this.page_num++
|
|
199
|
+ this.get_list()
|
|
200
|
+ },
|
|
201
|
+ get_list() {
|
|
202
|
+ if (this.currentIndex === 0) {
|
|
203
|
+ this.get_course()
|
|
204
|
+ } else {
|
|
205
|
+ this.get_history()
|
|
206
|
+ }
|
|
207
|
+ },
|
|
208
|
+ get_course() {
|
|
209
|
+ _nowCourse({ page_num: this.page_num }).then(res => {
|
|
210
|
+ if (this.page_num > 1) {
|
|
211
|
+ if (res.data.length < this.page_size) this.noMore = true
|
|
212
|
+ this.list = this.list.concat(res.data)
|
|
213
|
+ } else {
|
|
214
|
+ this.noMore = false
|
|
215
|
+ this.list = res.data
|
|
216
|
+ }
|
|
217
|
+ })
|
|
218
|
+ },
|
|
219
|
+ get_history() {
|
|
220
|
+ _courseHistory({ page_num: this.page_num }).then(res => {
|
|
221
|
+ if (this.page_num > 1) {
|
|
222
|
+ if (res.data.length < this.page_size) this.noMore = true
|
|
223
|
+ this.list = Object.assign({}, this.list, res.data)
|
|
224
|
+ } else {
|
|
225
|
+ this.noMore = false
|
|
226
|
+ this.list = res.data
|
|
227
|
+ }
|
|
228
|
+ })
|
|
229
|
+ },
|
|
230
|
+ drawChart() {
|
|
231
|
+ for (var key in this.attendance) {
|
|
232
|
+ this.draw(this.attendance[key], key)
|
|
233
|
+ }
|
|
234
|
+ },
|
|
235
|
+ changeTab(type) {
|
|
236
|
+ this.type = type
|
|
237
|
+ this.$nextTick(() => {
|
|
238
|
+ this.init()
|
|
239
|
+ })
|
|
240
|
+ },
|
|
241
|
+ swipe(index) {
|
|
242
|
+ this.currentIndex = index
|
|
243
|
+ this.page_num = 1
|
|
244
|
+ this.get_list()
|
|
245
|
+ },
|
|
246
|
+ changeDay(e) {
|
|
247
|
+ this.info.day = e.date
|
|
248
|
+ // 模拟动态打卡
|
|
249
|
+ // if (this.info.selected.length > 5) return
|
|
250
|
+ // this.info.selected.push({
|
|
251
|
+ // date: e.fulldate,
|
|
252
|
+ // info: '打卡'
|
|
253
|
+ // })
|
|
254
|
+ },
|
|
255
|
+ monthSwitch(e) {
|
|
256
|
+ this.info.year = e.year
|
|
257
|
+ this.info.month = e.month < 10 ? '0' + e.month : e.month
|
|
258
|
+ this.getSehedule()
|
|
259
|
+ },
|
|
260
|
+ get_attend() { // 获取出席情况
|
|
261
|
+ const date = this.info.year + '-' + this.info.month
|
|
262
|
+ return new Promise((resolve, reject) => {
|
|
263
|
+ const info = _attendance({ date })
|
|
264
|
+ resolve(info)
|
|
265
|
+ })
|
|
266
|
+ },
|
|
267
|
+ fix_attend(info) { // 补充出席实际数据
|
|
268
|
+ Object.keys(this.attendance).forEach(key => {
|
|
269
|
+ this.attendance[key].times = info[key]
|
|
270
|
+ })
|
|
271
|
+ },
|
|
272
|
+ get_dateCourse() { // 获取对应日期数据
|
|
273
|
+ _dateCourse({ year: this.info.year, month: this.info.month }).then(res => {
|
|
274
|
+ this.classList = res.data
|
|
275
|
+ })
|
|
276
|
+ },
|
|
277
|
+ draw (ele, key) {
|
|
278
|
+ const ctx = uni.createCanvasContext(key)
|
|
279
|
+ const value = NP.divide(ele.times, this.present.be_section_num) * 100// 次数转化对应百分比值
|
|
280
|
+ const startAngle = 1.5
|
|
281
|
+ const endAngle = 1.5 + value * 2 / 100
|
|
282
|
+ // 画圆环
|
|
283
|
+ ctx.beginPath()
|
|
284
|
+ ctx.arc(34, 40, 28, 0, 2 * Math.PI)
|
|
285
|
+ ctx.setStrokeStyle('#EDEDED') // 弧线的颜色
|
|
286
|
+ ctx.setLineWidth('8') // 弧的宽度
|
|
287
|
+ ctx.setLineCap('round') // 线条结束端点样式 butt 平直 round 圆形 square 正方形
|
|
288
|
+ ctx.stroke()
|
|
289
|
+ // 画进度条
|
|
290
|
+ ctx.beginPath()
|
|
291
|
+ ctx.arc(34, 40, 28, startAngle * Math.PI, endAngle * Math.PI)
|
|
292
|
+ ctx.setStrokeStyle(ele.color)
|
|
293
|
+ ctx.setLineWidth('8')
|
|
294
|
+ ctx.setLineCap('round')
|
|
295
|
+ ctx.stroke()
|
|
296
|
+ ctx.setFontSize(14)
|
|
297
|
+ ctx.setFillStyle('#000') // 文字的颜色
|
|
298
|
+ ctx.fillText(ele.times + '次', 20, 44)
|
|
299
|
+ ctx.draw()
|
|
300
|
+ }
|
|
301
|
+ }
|
|
302
|
+}
|
|
303
|
+</script>
|
|
304
|
+
|
|
305
|
+<style lang="scss">
|
|
306
|
+@import '~@/common/css/mixin.scss';
|
|
307
|
+.page{
|
|
308
|
+ height:100vh;
|
|
309
|
+}
|
|
310
|
+.header-switch{
|
|
311
|
+ justify-content:start;
|
|
312
|
+ .header-title-main{
|
|
313
|
+ font-size:18px;
|
|
314
|
+ color:#999;
|
|
315
|
+ .point{
|
|
316
|
+ opacity: 0;
|
|
317
|
+ }
|
|
318
|
+ &.cur{
|
|
319
|
+ transition: font-size .3s;
|
|
320
|
+ font-size:24px;
|
|
321
|
+ color:#000;
|
|
322
|
+ .point{
|
|
323
|
+ opacity: 1;
|
|
324
|
+ }
|
|
325
|
+ }
|
|
326
|
+ }
|
|
327
|
+}
|
|
328
|
+.day-info{
|
|
329
|
+
|
|
330
|
+}
|
|
331
|
+.scroll-main{
|
|
332
|
+ margin-top:78px;
|
|
333
|
+ padding:20rpx;
|
|
334
|
+}
|
|
335
|
+.cu-card{
|
|
336
|
+ .cu-item{
|
|
337
|
+ margin-top:10rpx;
|
|
338
|
+ padding:20rpx;
|
|
339
|
+ margin:0;
|
|
340
|
+ }
|
|
341
|
+}
|
|
342
|
+.card-header{
|
|
343
|
+ padding-bottom:10px;
|
|
344
|
+ @include title(10px,18px);
|
|
345
|
+}
|
|
346
|
+.card{
|
|
347
|
+ &-title{
|
|
348
|
+ font-size:16px;
|
|
349
|
+ }
|
|
350
|
+ &-image{
|
|
351
|
+ width:35vw;
|
|
352
|
+ height:25vw;
|
|
353
|
+ border-radius:2vw;
|
|
354
|
+ }
|
|
355
|
+ &-label{
|
|
356
|
+ color:#999;
|
|
357
|
+ }
|
|
358
|
+ &-text{
|
|
359
|
+ color:#333;
|
|
360
|
+ }
|
|
361
|
+}
|
|
362
|
+.course-status{
|
|
363
|
+ font-size:14px;
|
|
364
|
+ font-weight:normal;
|
|
365
|
+}
|
|
366
|
+</style>
|