基于vue和elementui的课程表

        之前用的课程表基本都是基于calendar开发的,calendar功能比较丰富,能实现很多功能,但是基于学校项目来说并不完美,首先就是最左侧的时间轴,学校课程表一般都是节次,而calendar都是时间。因为学校夏季和冬季上课时间都不同,所以并不实用。而有的calendar组件封装的比较厉害,想改造是很麻烦的,正是基于此我自己写了一个基础版本的课程表,分享给有需要的朋友。

        

        上面是课程表的截图,样式是采用正方教务的课程表样式,大部分学校用的都是正方的教务系统,这种样式老师和学生都能接受。如果不想用这种样式,也可以自己修改,代码比较简单。 

        课程表最左侧是时间段:上午、下午和晚上。第二列是节次,节次上午固定为4节课,下午的节次是可扩展的,只需要传入一个值即可,因为在做项目的过程中遇到过学校下午是5节课的,4节课的都有,所以做了一个可变动的。晚上的节次是根据总节次和上午,下午的节次算出来的,所有在调用组件的时候,需要传入总节次和下午的节次。

        课程表内容展示了一周7天,可以根据实际情况进行调整 。内容比较简单,标题和内容,标题是课程名称,内容可以自由拼接,在渲染的时候用的v-html,因此在拼接内容时,可以自由拼接一些html元素,让内容更好看。并且课程表数据中还有一个class属性,可以传入不同的class自定义一些样式。(这个版本只是有,但并未使用)

        整个课程表的内容大概就是这些,比较简单,但是挺实用,而且可以自己根据项目需要进行修改,比如添加点击事件,修改样式等等。

 

 直接上代码:

<template>
  <div>
    <div class="panel">
      <el-table :data="timetable" :span-method="objectSpanMethod" border
                :header-cell-style="{background:'#d9e5fd', color:'black', fontWeight: 1000}"
                :cell-style="tableCellStyle"
      >
        <el-table-column prop="sjd" label="时间段" width="80" align="center">
        </el-table-column>
        <el-table-column prop="jc" label="节次" width="80" align="center">
        </el-table-column>
        <el-table-column prop="mon" label="星期一" align="center">
          <template slot-scope="scope">
            <h4>{{ scope.row.mon.title }}</h4>
            <div v-html="scope.row.mon.content"></div>
          </template>
        </el-table-column>
        <el-table-column prop="tue" label="星期二" align="center">
          <template slot-scope="scope">
            <h4>{{ scope.row.tue.title }}</h4>
            <div v-html="scope.row.tue.content"></div>
          </template>
        </el-table-column>
        <el-table-column prop="wed" label="星期三" align="center">
          <template slot-scope="scope">
            <h4>{{ scope.row.wed.title }}</h4>
            <div v-html="scope.row.wed.content"></div>
          </template>
        </el-table-column>
        <el-table-column prop="thu" label="星期四" align="center">
          <template slot-scope="scope">
            <h4>{{ scope.row.thu.title }}</h4>
            <div v-html="scope.row.thu.content"></div>
          </template>
        </el-table-column>
        <el-table-column prop="fri" label="星期五" align="center">
          <template slot-scope="scope">
            <h4>{{ scope.row.fri.title }}</h4>
            <div v-html="scope.row.fri.content"></div>
          </template>
        </el-table-column>
        <el-table-column prop="sat" label="星期六" align="center">
          <template slot-scope="scope">
            <h4>{{ scope.row.sat.title }}</h4>
            <div v-html="scope.row.sat.content"></div>
          </template>
        </el-table-column>
        <el-table-column prop="sun" label="星期日" align="center">
          <template slot-scope="scope">
            <h4>{{ scope.row.sun.title }}</h4>
            <div v-html="scope.row.sun.content"></div>
          </template>
        </el-table-column>
      </el-table>
    </div>
  </div>
</template>
<script>
export default {
  props: {
    // 下午节次数
    afternoonLength: {
      type: [String, Number],
      default: 4
    },
    // 总节次
    length: {
      type: [String, Number],
      default: 12
    },
    // 课表数据
    events: {
      type: Array,
      default: null
    }
  },
  data () {
    return {
      // 课程表数据
      timetable: [],
      events1: [
        {
          xq: 1,
          title: '形势与政治',
          class: 'sport',
          content: '1-4节' + '/' + '社会学1班' + '/' + '5教-402室',
          start: 1,
          end: 4
        },
        {
          xq: 1,
          title: '形势与政治',
          class: 'leisure',
          content: '9-12节' + '<br>' + '社会学2班' + '<br>' + '5教-401室',
          start: 9,
          end: 12
        },
        {
          xq: 3,
          title: '形势与政治',
          class: 'sport',
          content: '5-6节' + '/' + '社会学2班' + '/' + '1教-401室',
          start: 5,
          end: 6
        },
        {
          xq: 4,
          title: '形势与政治',
          class: 'sport',
          content: '1-2节' + '/' + '社会学1班' + '/' + '5教-402室',
          start: 1,
          end: 2
        },
        {
          xq: 4,
          title: '形势与政治',
          class: 'sport',
          content: '7-8节' + '/' + '社会学1班' + '/' + '5教-402室',
          start: 7,
          end: 8
        },
        {
          xq: 5,
          title: '形势与政治',
          class: 'sport',
          content: '社会学1班' + '/' + '5教-402室',
          start: 3,
          end: 4
        },
        {
          xq: 5,
          title: '形势与政治',
          class: 'sport',
          content: '5-6节' + '/' + '社会学1班' + '/' + '5教-402室',
          start: 5,
          end: 6
        }
      ],
      hoverOrderArr: [],
      weeks: ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']
    }
  },
  mounted () {
    this.mergeData()
  },
  watch: {
    events: {
      handler (newVal, oldVal) {
        this.mergeData()
      },
      deep: true
    }
  },
  created () {
    this.makeTimetable()
  },
  methods: {
    // 单元格添加背景色
    tableCellStyle (row) {
      if (row.row[row.column.property].title !== undefined) {
        return 'background-color:rgb(24 144 255 / 80%);color: #fff; border-radius:10px'
      }
    },
    // 构造课程表完整数据
    makeTimetable () {
      this.timetable = []
      for (let i = 0; i < this.length; i++) {
        let one = {
          sjd: '',
          jc: i + 1,
          mon: {},
          tue: {},
          wed: {},
          thu: {},
          fri: {},
          sat: {},
          sun: {}
        }
        if (i < 4) {
          one.sjd = '上午'
        } else if (i > 3 && i < (this.afternoonLength + 4)) {
          one.sjd = '下午'
        } else {
          one.sjd = '晚上'
        }
        this.timetable.push(one)
      }
    },
    mergeData () {
      // 合并数据
      if (this.events.length > 0) {
        for (let i = 0; i < this.events.length; i++) {
          // 获取星期几
          let week = this.weeks[this.events[i].xq - 1]
          this.timetable[this.events[i].start - 1][week] = this.events[i]
        }
      }
    },
    objectSpanMethod ({ row, column, rowIndex, columnIndex }) {
      if (columnIndex === 0) {
        if (rowIndex < 4) {
          if (rowIndex === 0) {
            return {
              rowspan: 4,
              colspan: 1
            }
          } else {
            return {
              rowspan: 0,
              colspan: 0
            }
          }
        } else if (rowIndex > 3 && rowIndex < (4 + this.afternoonLength)) {
          if (rowIndex === 4) {
            return {
              rowspan: this.afternoonLength,
              colspan: 1
            }
          } else {
            return {
              rowspan: 0,
              colspan: 0
            }
          }
        } else {
          if (rowIndex === (4 + this.afternoonLength)) {
            return {
              rowspan: this.length - 4 - this.afternoonLength,
              colspan: 1
            }
          } else {
            return {
              rowspan: 0,
              colspan: 0
            }
          }
        }
      }
      if (columnIndex === 2) {
        if (row.mon.title !== undefined) {
          return {
            rowspan: row.mon.end - row.mon.start + 1,
            colspan: 1
          }
        } else {
          return {
            rowspan: 1,
            colspan: 1
          }
        }
      }
      if (columnIndex === 3) {
        if (row.tue.title !== undefined) {
          return {
            rowspan: row.tue.end - row.tue.start + 1,
            colspan: 1
          }
        } else {
          return {
            rowspan: 1,
            colspan: 1
          }
        }
      }
      if (columnIndex === 4) {
        if (row.wed.title !== undefined) {
          return {
            rowspan: row.wed.end - row.wed.start + 1,
            colspan: 1
          }
        } else {
          return {
            rowspan: 1,
            colspan: 1
          }
        }
      }
      if (columnIndex === 5) {
        if (row.thu.title !== undefined) {
          return {
            rowspan: row.thu.end - row.thu.start + 1,
            colspan: 1
          }
        } else {
          return {
            rowspan: 1,
            colspan: 1
          }
        }
      }
      if (columnIndex === 6) {
        if (row.fri.title !== undefined) {
          return {
            rowspan: row.fri.end - row.fri.start + 1,
            colspan: 1
          }
        } else {
          return {
            rowspan: 1,
            colspan: 1
          }
        }
      }
      if (columnIndex === 7) {
        if (row.sat.title !== undefined) {
          return {
            rowspan: row.sat.end - row.sat.start + 1,
            colspan: 1
          }
        } else {
          return {
            rowspan: 1,
            colspan: 1
          }
        }
      }
      if (columnIndex === 8) {
        if (row.sun.title !== undefined) {
          return {
            rowspan: row.sun.end - row.sun.start + 1,
            colspan: 1
          }
        } else {
          return {
            rowspan: 1,
            colspan: 1
          }
        }
      }
    }
  }
}
</script>

调用的时候的代码:

 

  • 7
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 15
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值