结合 ElementUI 的 table 和 calendar 做一个价格日历

项目中需要做一个价格日历,便于展示和修改日期价格,我们先看下最终效果,然后利用ElementUI的table 和 calendar 实现一下。

价格日历
设置价格

来看看主要代码(代码仅保留了主要代码和属性,并不完整,可以自行根据实际情况修改):

<template>
  <div class="calendar-list-container">
    <!--expand-row-keys设置了row-key也要设置,
    expand-change    当用户对某一行展开或者关闭的时候会触发该事件(展开行时,回调的第二个参数为 expandedRows;树形表格时第二参数为 expanded)    row, (expandedRows | expanded)-->
    <el-table
      ref="table"
      key="id"
      v-loading="listLoading"
      :data="list"
      element-loading-text="loading"
      row-key="id"
      :expand-row-keys="expands"
      @expand-change="expandChange"
    >
      <el-table-column 
        align="center"
        type="expand"
      >
        <template slot-scope="scope">
            <!--价格日历渲染 -->
          <el-calendar
            v-loading="calendarLoad"  
            element-loading-text="loading"
          >
            <template
              slot="dateCell"
              slot-scope="{date, data}"
            >
            <!--今日及之后的价格可设置setPrice -->
              <div
                :class="nowDay <= data.day.replace(/-/g, '')? 'calendar-div' : 'calendar-div calendar-prev'"
                @click="nowDay <= data.day.replace(/-/g, '') && setPrice(data, date)"
              >
                <div>{{ data.day.slice(-2) }}</div>
                <div
                  v-if="data.type == 'current-month' && refreshPrice(data)"
                  class="price "
                >
                  预订价:{{ priceList[data.day.slice(-2) -1] }}</div>
              </div>
            </template>
          </el-calendar>
        </template>
      </el-table-column>
      <el-table-column
        align="center"
        label="名称"
        class-name="overflow-on"
      >
        <template slot-scope="scope">
          {{ scope.row.name }}
        </template>
      </el-table-column>

      <el-table-column
        align="center"
        label="图片"
        width="210"
      >
        <template slot-scope="scope">
          <img
            :src="scope.row.imageList[0]"
            style="width:150px"
          >
        </template>
      </el-table-column>

      <el-table-column
        align="center"
        label="今日价格"
        max-width="200"
      >
        <template slot-scope="scope">
          <span>{{ scope.row.price }}</span>
        </template>
      </el-table-column>

      <el-table-column
        align="center"
        label="原价"
        max-width="200"
      >
        <template slot-scope="scope">
          <span>{{ scope.row.original_price }}</span>
        </template>
      </el-table-column>

      <el-table-column
        align="center"
        label="操作"
      >
        <template slot-scope="scope">
          <el-button
            type="primary"
            @click="handleCheck(scope.row)"
          >
            价格设置
          </el-button>
        </template>
      </el-table-column>
    </el-table>

    <el-dialog
      title="设置价格"
      :visible.sync="dialogPriceVisible"
    >
      <el-form
        class="small-space"
        :model="temp"
        label-position="left"
        label-width="100px"
        style="width: 500px; margin-left:50px;"
      >
        <el-form-item label="名称">
          <el-input
            v-model="temp.name"
            disabled
          />
        </el-form-item>
        <el-form-item label="时间段">
          <el-date-picker
            v-model="temp.date"
            type="daterange"
            range-separator="至"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            :picker-options="pickerBeginDateBefore"
          />
        </el-form-item>

        <el-form-item
          label="分时计价"
          prop="is_part"
          required
        >
          <el-radio
            v-model="temp.is_part"
            :label="0"
          >
            不分平时周末
          </el-radio>
          <el-radio
            v-model="temp.is_part"
            :label="1"
          >
            区分周末
          </el-radio>
        </el-form-item>
        <el-form-item label="平时价">
          <el-input v-model="temp.normal_price" />
        </el-form-item>

        <el-form-item
          v-if="temp.is_part == 1"
          label="周末价"
        >
          <el-input v-model="temp.week_price" />
        </el-form-item>
      </el-form>

      <div
        slot="footer"
        class="dialog-footer"
      >
        <el-button @click="dialogPriceVisible = false">
          取 消
        </el-button>
        <el-button
          type="primary"
          @click="putPrice"
        >
          确 定
        </el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { fetchList, setRoomPrice, getRoomPrice } from "@/api";
import moment from 'moment';

export default {
  name: "room",
  data() {
    return {
      pickerBeginDateBefore:{
        disabledDate(time) {
          return time.getTime() < Date.now() - 86400*1000;
        }
      },
      schedule: [],
      list: [],
      dialogPriceVisible: false,
      dialogFormVisible: false,
      priceDate: '2020-01-01',
      nowDate: 1,
      nowMonth: 1,
      nowDay: 0,
      nowYear: 2020,
      calendarMonth: 1,
      priceList: [],
      expands: [],//只展开一行放入当前行id
      room: {},
      listLoading:false,
      calendarLoad: false,
    };
  },
  created() {
    this.priceDate = new Date();
    this.nowDate = this.priceDate.getDate();
    this.nowMonth = this.priceDate.getMonth();
    this.calendarMonth = this.nowMonth;
    this.nowYear = this.priceDate.getFullYear();
    this.nowDay = this.priceDate.getFullYear()*10000+ (1+this.priceDate.getMonth())*100+ this.priceDate.getDate();
  },
  methods: {
    refreshPrice (data) {
      // console.log(data);
      if (!data.isSelected) {
        return true;
      }
      if (data.day.slice(5, 7) == this.calendarMonth + 1) {
        return true;
      }
      this.calendarMonth = data.day.slice(5, 7) - 1;
      var that = this;
      getRoomPrice(that.room.id, {'date': data.day}).then(response => {
        var arr = [];
        response.data.priceList.forEach((item,index,array)=>{
            arr[index] = item? item : that.room.price;
        })
        that.priceList = arr
      });
      that.$forceUpdate()
    },
    getRowKeys(row) {
        // console.log(row.id)
        return row.id   //这里看这一行中需要根据哪个属性值是id
    },
    selectDate(type) {
      // consoloe.log(type)
    },
    expandChange(row, expandedRows) {
      // console.log(this.expands)
      var that = this;
      that.room = row;
      // 每次只展开一行
      if (expandedRows.length) { 
        that.calendarLoad = true;
        getRoomPrice(row.id, {'date': this.priceDate}).then(response => {
          that.calendarLoad = false;
          var arr = [];
          response.data.priceList.forEach((item,index,array)=>{
              arr[index] = item? item : row.price;
          })
          that.priceList = arr
          that.expands = [row.id]
        });
      } else { 
          // 收起价格日历
        that.expands = []
      }
    },
    setPrice(data, date) {
      if (this.nowDay > data.day.replace(/-/g, '')) {
          return false;
      }
      var that = this;
      this.temp = {
        name: that.room.name,
        date: [date, date],
        is_part: 0,
      };
      this.dialogPriceVisible = true;
    },
    putPrice() {
      this.dialogPriceVisible = true;
        setRoomPrice(this.room.id, this.temp).then(res => {
          if (res.code == 0) {
            this.$message.success("编辑成功");
            this.dialogPriceVisible = !this.dialogPriceVisible;
            var that = this;
            getRoomPrice(that.room.id, {'date': this.temp.date[0]}).then(response => {
              var arr = [];
              response.data.priceList.forEach((item,index,array)=>{
                  arr[index] = item? item : that.room.price;
              })
              that.priceList = arr
            });
            fetchList(that.params).then(response => {
              that.list = response.data;
            });
            that.resetTemp();
            that.$forceUpdate()
          } else {
            this.$message.error(res.msg);
          }
        });
    },
    // 用于可展开表格与树形表格,切换某一行的展开状态,如果使用了第二个参数,则是设置这一行展开与否(expanded 为 true 则展开)
    handleCheck(row) {
        const $table = this.$refs.table
        $table.toggleRowExpansion(row)
    }
  }
};
</script>

价格日历返回数据格式:

{
    "status": "success",
    "code": 0,
    "msg": "操作成功",
    "data": {
        "room": {
            "name": "大床房",
            "price": 299,
            "original_price": 289
        },
        "priceList": [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, 209, 219, false, false, false, false, false],
    }
}

priceList是本月价格,false表示未设置。


table的功能比较强大,部分属性函数并不常用,可以自行打印出来看看,研究一下即可。
calendar是2.8版本新增的组件,如果版本过低,可以尝试升级到新版本。

本作品采用《CC 协议》,转载必须注明作者和本文链接
分享开发知识,欢迎交流。公众号:开源到
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!