elementUI根据自定义时间控制el-date-picker可选区域

1,218 阅读1分钟

一、需求

  1. 动态添加/删减表格

  2. 选中code,根据code找出相对应的name和日期,并且填充到input之中

  3. 选中name,根据name找出相对应的code和日期,并且填充到input之中

  4. 日期默认为一年前的今天

  5. 表头根据UI图修改

  6. 可选时间范围是后台给的时间和当前时间的前一天这个区间

  7. 获取日期后跟默认时间相比较,规则如下:

    1、 后台所给时间比默认时间大,选择默认时间

    2、后台所给时间比默认时间小,选择后台所给时间

二、完整代码

<template>
  <div class="main">
    <el-table
      :data="tableData"
      style="width: 100%"
      :header-cell-style="{
        background: '#eeeeee',
        color: '#000000',
        fontWeight: '600',
        textAlign: 'center',
      }"
    >
      <el-table-column prop="code" label="代码">
        <template slot-scope="scope">
          <el-select
            v-model="scope.row.code"
            filterable
            remote
            reserve-keyword
            placeholder="输入选择"
            :loading="loading"
            @change="queryCode($event, scope.$index)"
          >
            <el-option
              v-for="item in options"
              :key="item.code"
              :label="item.code"
              :value="item.code"
              :disabled="item.disabled"
            />
          </el-select>
        </template>
      </el-table-column>
      <el-table-column prop="name" label="名称">
        <template slot-scope="scope">
          <el-select
            v-model="scope.row.name"
            filterable
            remote
            reserve-keyword
            placeholder="请选择"
            :loading="loading"
            @change="queryName($event, scope.$index)"
          >
            <el-option
              v-for="item in options"
              :key="item.code"
              :label="item.name"
              :value="item.name"
              :disabled="item.disabled"
            />
          </el-select>
        </template>
      </el-table-column>
      <el-table-column prop="start_date" label="日期">
        <template slot-scope="scope">
          <el-date-picker
            v-model="scope.row.start_date"
            type="date"
            format="yyyy/MM/dd"
            value-format="yyyy/MM/dd"
            :picker-options="pickerOptions"
            @focus="OutputIndex(scope.$index)"
            placeholder="选择日期"
          />
        </template>
      </el-table-column>
      <el-table-column prop="address" label="操作" width="80">
        <template slot-scope="scope">
          <i
            :class="scope.row.status"
            @click="operation(scope.row, scope.$index)"
          />
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>
<script>
import { getList } from "@/api/index";
export default {
  name: "timeFrame",
  data() {
    return {
      tableData: [
        {
          code: "",
          name: "",
          start_date: "",
          status: "increase",
        },
      ],
      options: [], // 保存后端所给的数据
      loading: false,
      optionsArr: [], // 保存所有选过的code,选过之后不能再次选择,这个数组中的code相对应的对象都添加disable
      testTime: [], // 保存被选的当前行后台传回的时间,根据这个时间去控制当前行每个时间的可选范围
      tableIndex: "", // 被保存的下标,根据此下标去找testTime数组中的相对应的时间,控制可选时间的范围
      pickerOptions: {
        disabledDate: (time) => {
          return this.selectTime(time); // 调用控制当前行时间可选范围的方法
        },
      },
    };
  },
  mounted() {
    // 获取后端数据
    this.getList();
    // 给表格第一行的时间赋值默认时间(一年前的今天)
    this.tableData[0].start_date = this.OutputTime();
  },
  methods: {
    //   获取后端数据
    getList() {
      getList().then((res) => {
        console.log(res.data);
        this.options = res.data.result;
      });
    },
    // 获取当前下标,给选择时间控件使用
    OutputIndex(index) {
      // 保存一个下标,根据下标去找this.testTime数组中相对应的时间
      this.tableIndex = index;
    },

    // 时间可选范围的处理
    selectTime(time) {
      // 根据下标去获取保存在this.testTime数组中相对应的时间
      const rowTime = this.testTime[this.tableIndex];
      // 解析当前时间,把后端传回的时间转换为时间戳
      const timestamp = Date.parse(rowTime);
      //   返回一个true
      return (
        //   过去的48小时不能选择
        time.getTime() > Date.now() - 48 * 60 * 60 * 1000 ||
        //   后台传的时间的以前的时间不可以选
        time.getTime() < timestamp
      );
    },
    // 根据所选代码赋值
    queryCode(code, index) {
      //  被选过的code
      this.optionsArr[index] = code;
      // 根据选择的code找后端给的数据中的当前对象
      const optionsObj = this.options.find((obj) => {
        return obj.code === code;
      });

      // 根据选择的code找列表中的当前对象
      const tableDataObj = this.tableData.find((obj) => {
        return obj.code === code;
      });
      // 后台传给的时间
      const productTime = optionsObj.start_date;
      // 默认时间
      const defaultTime = this.OutputTime();
      // 根据下标保存被选过的时间
      this.testTime[index] = productTime;

      /*
       * 后台传的时间比默认时间大,选择默认时间
       * 后台传时间比默认时间小,选择后台传时间
       * */

      //   用后台传给的时间和默认时间作比较
      if (new Date(productTime) >= new Date(defaultTime)) {
        //   后台传的时间比默认时间大,选择默认时间
        this.$set(tableDataObj, "start_date", productTime);
      } else {
        //  后台传时间比默认时间小,选择后台传时间
        this.$set(tableDataObj, "start_date", defaultTime);
      }
      //   给当前对象相对应的name复制
      this.$set(tableDataObj, "name", optionsObj.name);
      //   遍历所保存的后台传回的数据和遍历已选的,如果code相同择给当前对象添加disabled未true;
      this.options.map((i) => {
        i.disabled = false;
        this.optionsArr.map((j) => {
          if (i.code === j) {
            i.disabled = true;
          }
        });
      });
    },
    // 根据所选名称赋值
    queryName(name, index) {
      // 根据name查找后台传输数据中相对应的对象
      const optionsObj = this.options.find((obj) => {
        return obj.name === name;
      });
      //   被选中的对象的code保存到this.optionsArr数组中指定下标的位置
      this.optionsArr[index] = optionsObj.code;
      // 根据选择的code找列表中的当前对象
      const tableDataObj = this.tableData.find((obj) => {
        return obj.name === name;
      });

      // 后台传给的时间
      const productTime = optionsObj.start_date;
      // 默认时间
      const defaultTime = this.OutputTime();
      // 根据下标保存被选过的时间
      this.testTime[index] = productTime;
      /*
       * 后台传的时间比默认时间大,选择默认时间
       * 后台传的时间比默认时间小,选择后台传的时间
       * */
      //   用后台传给的时间和默认时间作比较
      if (new Date(productTime) >= new Date(defaultTime)) {
        //   后台传的时间比默认时间大,选择默认时间
        tableDataObj.start_date = productTime;
      } else {
        //   后台传的时间比默认时间小,选择后台传的时间
        tableDataObj.start_date = defaultTime;
      }
      //   给当前对象相对应的name复制
      tableDataObj.code = optionsObj.code;
      //   遍历所保存的后台传回的数据和遍历已选的,如果code相同择给当前对象添加disabled未true;
      this.options.map((i) => {
        i.disabled = false;
        this.optionsArr.map((j) => {
          if (i.code === j) {
            i.disabled = true;
          }
        });
      });
    },
    // 增加或减少列表
    operation(row, index) {
      // 用increase字段来判断是增加列表还是删减列表,increase是曾加,reduce是删减
      if (row.status === "increase") {
        //   创建一个对象
        const obj = {
          code: "",
          name: "",
          start_date: this.OutputTime(),
          status: "reduce",
        };
        // 把创建对象push到tableData数组中
        this.tableData.push(obj);
      } else {
        //   在optionsArr数组中寻找是否有当前code
        if (this.optionsArr.includes(row.code)) {
          // 如果有就删去下标对应的当前对象
          this.tableData.splice(index, 1);
          // 同时删掉optionsArr数组中当前的code
          this.optionsArr.splice(index, 1);
          //   遍历保存的后台数据,把被删掉的code对应的对象的disabled改为false
          this.options.map((i) => {
            i.disabled = false;
            this.optionsArr.map((j) => {
              if (i.code === j) {
                i.disabled = true;
              }
            });
          });
        } else {
          // 删掉未被复制code空列表的当前行
          this.tableData.splice(index, 1);
        }
      }
    },
    // 输出一年前时间
    OutputTime() {
      const nowDate = new Date();
      const date = new Date(nowDate);
      date.setDate(date.getDate() - 365);
      const Slash = "/";
      const year = date.getFullYear();
      let month = date.getMonth() + 1;
      let strDate = date.getDate();
      if (month >= 1 && month <= 9) {
        month = "0" + month;
      }
      if (strDate >= 0 && strDate <= 9) {
        strDate = "0" + strDate;
      }
      const currentDate = year + Slash + month + Slash + strDate;
      return currentDate;
    },
  },
};
</script>

<style lang="scss" scoped>
.main {
  width: 820px;
  margin: 0 auto;
  ::v-deep .el-input__inner {
    border: none;
  }
  ::v-deep .el-table__row {
    td {
      text-align: center;
    }
  }
  .increase {
    display: inline-block;
    width: 20px;
    height: 20px;
    background-image: url("../../assets/images/increase.svg");
    background-repeat: no-repeat;
  }
  .reduce {
    display: inline-block;
    width: 20px;
    height: 20px;
    background-image: url("../../assets/images/reduce.svg");
    background-repeat: no-repeat;
  }
}
</style>

三、后台传回的数据格式

"result": [{
		"code": "10000",
		"name": "Shirley Jackson",
		"start_date": "2021/03/08"
	},
	{
		"code": "20000",
		"name": "Eric Wilson",
		"start_date": "2021/03/18"
	},
	{
		"code": "30000",
		"name": "Shirley Wilson",
		"start_date": "2020/08/27"
	},
	{
		"code": "40000",
		"name": "Ruth Gonzalez",
		"start_date": "2020/09/02"
	},
	{
		"code": "50000",
		"name": "Eric Harris",
		"start_date": "2020/09/03"
	},
]

四、图片演示

time.gif

更多请看