一、成果展现
二、性能实现的思路
本我的项目基于 APICloud 的 AVM 多端框架编写,因而须要想方法去结构特定数据、而后再扭转数据,本我的项目外围业务就是课程数据的解决,难点就是课表的增加。
我的项目次要针对大学课表进行设计,课程很多中央存在不确定性,如课程周次数可能间断也可能不间断、上课工夫可能 1 - 2 节也可能一整天、上课教室也可能不一样,因而课程的数据结构如下图。
后端须要提供以后周、以后周课程数据、增加课程等接口,当然课程数据查问是比较复杂的,这里就不讲。前端次要是将课表信息显示在指定地位,数据比较简单。
1、课程列表页面
(1)以后周课程原始数据构造
这个数据须要再重组,因为须要将课程摆放到指定地位,必须晓得间隔顶部间隔以及本身高度。能够通过上课工夫 jie 这个参数获取 height,top。
let data = [{
'name': '大数据可视化技术',
'room': '机房 C414',
'weekday': '3',
'bg': '2',
'jie': '3-4',
'top': '140px',
'height': '140px'
}]
横向分为 8 份, 每份宽度 12.5%,高度 70px,默认能够显示 13 节课。课程背景默认有 7 种款式,星期对应的是 left 参数也有 7 种款式,上课节次对应 top 参数有 12 种款式具体 css 如下:
.bg-1 {background: linear-gradient(#facea8, #fe8979)}
.bg-2 {background: linear-gradient(#dfc3fe, #90c5fb)}
.bg-3 {background: linear-gradient(#9deef5, #68e1b5)}
.bg-4 {background: linear-gradient(#eeba93, #dd65c7)}
.bg-5 {background: linear-gradient(#e6f6c9, #68e1b5)}
.bg-6 {background: linear-gradient(#dfc3fe, #dd65c7)}
.bg-7 {background: linear-gradient(#c8e65f, #7abafb)}
.week-1 {left: 12.5%;}
.week-2 {left: 25%;}
.week-3 {left: 37.5%;}
.week-4 {left: 50%;}
.week-5 {left: 62.5%;}
.week-6 {left: 75%;}
.week-0 {left: 87.5%;}
每一门课程都是用相对定位, 宽度雷同,依据上课工夫决定高度、地位代码示意如下
<view class="course_list">
<view v-for="(rs,key) in course_data" :key="key" :class="'course week-'+rs.weekday+'bg-'+rs.bg":style="'height:'+rs.height+';top:'+rs.top">
<text class="course-name">{{rs.name}}</text>
<text class="course-room">{{rs.room}}</text>
</view>
</view>
(2)以后周星期数据结构
获取以后周的工夫代码如下
this.setDate(new Date());
setDate(date) {let arr = [];
let week = date.getDay() - 1;
date = this.addDate(date, week * -1);
this.currentFirstDate = new Date(date);
for (var i = 0; i < 7; i++) {arr[i] = this.formatDate(i == 0 ? date : this.addDate(date, 1))
}
this.week_data = arr
this.currentWeek()},
addDate(date, n) {date.setDate(date.getDate() + n);
return date;
},
formatDate(date) {let year = date.getFullYear();
let month = (date.getMonth() + 1);
let day = date.getDate();
let week = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'][date.getDay()];
this.currentMonth = month;
if (month < 10) {month = '0' + month;}
if (day < 10) {day = '0' + day;}
return {"week": week, "date": month + '/' + day, "active": false};
},
// 以后星期
currentWeek() {let date = new Date();
let weekday = date.getDay();
if (weekday == 1) {this.week_data[0].active = true
} else if (weekday == 2) {this.week_data[1].active = true
} else if (weekday == 3) {this.week_data[2].active = true
} else if (weekday == 4) {this.week_data[3].active = true
} else if (weekday == 5) {this.week_data[4].active = true
} else if (weekday == 6) {this.week_data[5].active = true
} else if (weekday == 0) {this.week_data[6].active = true
}
}
上一周以及下一周相应代码
last() {if (this.week > 1) {
this.week = this.week - 1
this.setDate(this.addDate(this.currentFirstDate, -7));
}
},
next() {if (this.week < 20) {
this.week = this.week + 1
this.setDate(this.addDate(this.currentFirstDate, 7));
}
},
2、课程增加页面
本我的项目次要针对大学课程进行设计,因为上课工夫地点可能不法则,因而须要思考周次、节次、星期、上课地点几个因素。为了不便用户疾速增加课程,同一门课程可反对增加多个上课工夫。页面业务逻辑只有周次抉择、工夫抉择两个中央有点简单因而将其拆分为两个组件 <class-week></class-week> <class-time></class-time>
课程的次要字段如下
name: '大学计算机', // 课程名称
room: '机房 C411', // 上课教室
teacher: '李国海', // 任课教师
weekday: '0', // 星期
weeks: '1-9,11-20', // 上课周数
jie: '5-9', // 上课节次
bg:'1', // 课程色彩, 零碎提供 7 种颜色
大学的课程上课工夫可能不法则上课周数也不肯定是 20 周,周数大抵分为单双周以及其余,周数的格局如下:
不法则的周次格局:1-9,11,13,15-20
1-20 周单周的格局:1,3,5,7,9,11,13,15,17,19
1-20 周双周的格局:2,4,6,8,10,12,14,16,18,20
1-20 周的格局:1-20
然而这种数据格式对后端数据查问很不敌对。
页面初始数据,默认 1 -24 周全副选中。
(1)单周 choose(1),双周 choose(2),全选 choose(0) 具体业务解决源代码如下:
choose(n) {for (let i in this.weeks) {this.weeks[i].on = false
}
if (n == 1) {if (this.choose == 1) {this.choose = 3} else {
this.choose = 1
for (let i = 0; i < this.weeks.length; i++) {if (this.weeks[i].week % 2 != 0) {this.weeks[i].on = true
}
}
}
} else if (n == 2) {if (this.choose == 2) {this.choose = 3} else {
this.choose = 2
for (let i = 0; i < this.weeks.length; i++) {if (this.weeks[i].week % 2 == 0) {this.weeks[i].on = true
}
}
}
} else if (n == 0) {if (this.choose == 0) {this.choose = 3} else {
this.choose = 0
for (let i in this.weeks) {this.weeks[i].on = true
}
}
}
}
(2)抉择某一周的函数 set_week(i) 源代码如下
set_week(i) {if (this.weeks[i].on == true) {this.weeks[i].on = false
} else {this.weeks[i].on = true
}
}
(3)确定按钮 get_weeks() 源代码如下
get_weeks() {
this.mask = false // 影藏组件
let arr = [];
for (let i = 0; i < this.weeks.length; i++) {let on = this.weeks[i].on;
if (on == true) {arr.push(this.weeks[i].week);
}
}
let result = [];
let tmp;
while (tmp = arr.shift()) {if (result.length == 0) {result.push([tmp]);
continue;
}
let e = result[result.length - 1];
if (tmp == e[e.length - 1] + 1) {e.push(tmp);
} else {result.push([tmp]);
}
}
for (let i = 0; i < result.length; i++) {let res = result[i];
if (res.length > 1) {result[i] = res[0] + '-' + res[res.length - 1];
} else {result[i] = res[0] + ''
}
}
for (let i = 0; i < result.length; i++) {if (result[i].indexOf("-") != -1) {result[i] = result[i]
}
}
this.fire('GetWeek', { weeks: result.join(',') });// 格局为 1 -9,11,13,15-20
}
上课工夫组件 <class-time></class-time> 外面蕴含星期、上课节次数(留神上课节次数必须是间断的否则须要独自增加另一个上课工夫),次要难点在于判断上课节次数是否间断。
页面初始数据,默认最大上课节次 13 节。
weekdays: [{ name: '星期一', on: false},
{name: '星期二', on: false},
{name: '星期三', on: false},
{name: '星期四', on: false},
{name: '星期五', on: false},
{name: '星期六', on: false},
{name: '星期日', on: false}
],
times: base.class_time(),
num_arr: [],
mask: false,
jie: '',
weekday: 0
class_time() {
let data = [{ 'jie': '1 节', 'time': '08:30-09:15'},
{'jie': '2 节', 'time': '09:25-10:10'},
{'jie': '3 节', 'time': '10:25-11:10'},
{'jie': '4 节', 'time': '11:20-12:05'},
{'jie': '5 节', 'time': '14:00-14:45'},
{'jie': '6 节', 'time': '14:55-15:40'},
{'jie': '7 节', 'time': '15:55-16:40'},
{'jie': '8 节', 'time': '16:50-17:35'},
{'jie': '9 节', 'time': '17:45-18:30'},
{'jie': '10 节', 'time': '18:30-19:00'},
{'jie': '11 节', 'time': '19:00-19:45'},
{'jie': '12 节', 'time': '19:50-20:35'},
{'jie': '13 节', 'time': '20:45-21:30'}
]
return data;
}
抉择上课节次数(如 5 -9 这里须要判断单击后选中的数据是否为间断的数字)函数 set_time(index) 源代码如下
set_time(index) {let jie = (index + 1);
// 判断是否已增加
if (this.isInArray(this.num_arr, jie)) {this.delArrItem(this.num_arr, jie);
this.num_arr.sort(function (x, y) {return x - y;});
//console.log('删除' + jie)
if (this.isContinuityNum(this.num_arr)) {this.times[index].td1 = false
} else {//console.log('删除后不间断')
this.times[index].td1 = true
this.num_arr.push(jie);
this.num_arr.sort(function (x, y) {return x - y;});
api.toast({msg: '上课工夫必须间断'});
}
} else {this.num_arr.push(jie);
this.num_arr.sort(function (x, y) {return x - y;});
if (this.isContinuityNum(this.num_arr)) {this.times[index].td1 = true
} else {//console.log('减少后不间断')
this.delArrItem(this.num_arr, jie);
this.num_arr.sort(function (x, y) {return x - y;});
this.times[index].td1 = false
api.toast({msg: '上课工夫必须间断'});
}
}
this.jie =this.num_arr[0]+ '-'+this.num_arr[(this.num_arr.length -1)];// 格局 1 -2
}
// 删除数组元素
delArrItem(arr, item) {for (var i = 0; i < arr.length; i++) {if (arr[i] === item) {if (arr[i + 1] === item) {arr.splice(i, 1);
i--;
continue;
}
arr.splice(i, 1);
}
}
return arr;
},
// 判断是否是间断的数字
isContinuityNum(array) {if (!array) {
// 数组为 null
return false;
}
if (array.length == 0) {// 数组为 []
return true;
}
var len = array.length;
var n0 = array[0];
var sortDirection = 1;// 默认升序
if (array[0] > array[len - 1]) {
// 降序
sortDirection = -1;
}
if ((n0 * 1 + (len - 1) * sortDirection) !== array[len - 1]) {// 筛除 ['3',4,5,6,7,8]
return false;
}
var isContinuation = true;
for (var i = 0; i < len; i++) {if (array[i] !== (i + n0 * sortDirection)) {
isContinuation = false;
break;
}
}
return isContinuation;
},
// 判断元素是否在数组外面
isInArray(arr, value) {for (var i = 0; i < arr.length; i++) {if (value == arr[i]) {return true;}
}
return false;
}
最终前端须要提交给后端的数据格式如下:
yearId: '200', // 学年 id, 这里是指那一学期的课程
name: '大学计算机', // 课程名称
teacher: '李国海', // 任课教师
bg: '1', // 课程色彩, 零碎提供 7 种颜色
class_time: [{ weeks: '1-20', room: '一教 A307', weekday: '1', jie: '1-2'},
{weeks: '1-20', room: '机房 C405', weekday: '3', jie: '3-4'}
]