1. Effect display

Second, the idea of function realization

This project is written based on APICloud's AVM multi-terminal framework, so it is necessary to find a way to construct specific data and then change the data. The core business of this project is the processing of course data, and the difficulty is the addition of course schedules.

The project is mainly designed for the university timetable. There are many uncertainties in the course, such as the number of courses per week may or may not be continuous, the class time may be 1-2 sessions or a whole day, and the classrooms may be different. The data structure is as shown below.

The backend needs to provide interfaces such as current week, current week course data, and adding courses. Of course, course data query is more complicated, so I won't talk about it here. The front-end mainly displays the class schedule information in the specified location, and the data is relatively simple.

1. Course list page

(1) The original data structure of the current week's courses

This data needs to be reorganized, because the course needs to be placed in a designated position, and the distance from the top and its own height must be known. You can get height and top through the parameter jie of class time.

 let data = [{
            'name': '大数据可视化技术',
            'room': '机房C414',
            'weekday': '3',
            'bg': '2',
            'jie': '3-4',
            'top': '140px',
            'height': '140px'
 }]

It is divided into 8 horizontal sections, each with a width of 12.5% and a height of 70px. By default, 13 lessons can be displayed. There are 7 styles for the course background by default. There are 7 styles for the left parameter corresponding to the week, and 12 styles for the top parameter corresponding to the class session. The specific CSS is as follows:

 .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%;}

Each course uses absolute positioning with the same width. The height and location code are determined according to the class time as follows

 <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) The data structure of the current week

Get the time code of the current week as follows

 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
            }
        }

Corresponding codes for the previous week and the next week

 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. Course add page

This project is mainly designed for university courses. Since the time and place of classes may be irregular, several factors need to be considered: week, section, week, and class location. In order to facilitate users to quickly add courses, the same course can support adding multiple class times. The page business logic only has week selection and time selection a bit complicated, so it is split into two components <class-week></class-week> <class-time></class-time>

The main fields of the course are as follows

 name: '大学计算机',       //课程名称
room: '机房C411',        //上课教室
teacher: '李国海',       //任课教师
weekday: '0',            //星期
weeks: '1-9,11-20',      //上课周数
jie: '5-9',              //上课节次
bg:'1',                  //课程颜色,系统提供7种颜色

The class time of the university's courses may be irregular. The number of weeks is not necessarily 20 weeks. The number of weeks is roughly divided into single and bi-weekly and others. The format of the number of weeks is as follows:
Irregular week format: 1-9, 11, 13, 15-20
1-20 weeks Single week format: 1, 3, 5, 7, 9, 11, 13, 15, 17, 19
1-20 Weeks Bi-Weekly Format: 2,4,6,8,10,12,14,16,18,20
1-20 Week Format: 1-20
But this data format is very unfriendly to back-end data query.

The initial data of the page, the default week 1-24 are all selected.

(1) One-week choose(1), bi-weekly choose(2), all choose(0) The specific business processing source code is as follows:

 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) The source code of the function set_week(i) to select a certain week is as follows

 set_week(i) {
            if (this.weeks[i].on == true) {
                this.weeks[i].on = false
            } else {
                this.weeks[i].on = true
            }
        }

(3) The source code of the OK button get_weeks() is as follows

 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
        }

The class time component <class-time></class-time> contains the week and the number of class periods (note that the number of class periods must be consecutive or another class time needs to be added separately). The main difficulty lies in judging whether the number of class periods is continuous.
The initial data of the page, the default maximum class time is 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;
    }

Select the number of classes (such as 5-9 here, you need to judge whether the data selected after clicking is a continuous number) The source code of the function set_time(index) is as follows

 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;
        }

The final data format that the front-end needs to submit to the back-end is as follows:

 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' }
]

海的尽头
18 声望340 粉丝