后臺(tái)管理系統(tǒng)項(xiàng)目使用ElementUI組件庫(kù)完成在日歷上的某一天添加日程的功能

1、效果展示

1.1、添加日程
添加日程.png
1.2、顯示已添加了的日程,并且在日歷上標(biāo)注
效果圖.png
1.3、點(diǎn)擊標(biāo)注,彈出日程內(nèi)容以及重要程度
查看.png

2、需求分析

在新項(xiàng)目中,需要在首頁(yè)做個(gè)日歷展示以及實(shí)現(xiàn)添加,查看,修改,刪除日程的功能,ElementUI組件庫(kù)中有一個(gè)calendar組件可以拿來(lái)進(jìn)行復(fù)用。

3、后臺(tái)接口查看

一開(kāi)始后臺(tái)那邊沒(méi)有返回日期,在日歷上進(jìn)行標(biāo)注的過(guò)程必須是需要后臺(tái)那邊返回添加了日程的時(shí)間過(guò)來(lái)的,前端這邊再去將帶有日程的時(shí)間存進(jìn)一個(gè)數(shù)組,然后再去單獨(dú)渲染到日歷上去。


列表返回?cái)?shù)據(jù).png

4、標(biāo)注渲染問(wèn)題的難點(diǎn)

這里可以有很多不同的方式去實(shí)現(xiàn)這個(gè)難點(diǎn),我這邊是和后臺(tái)開(kāi)發(fā)人員協(xié)商好,前端傳入年月給后臺(tái),然后后臺(tái)返回那一個(gè)月份所有添加了日程的數(shù)據(jù)給我,然后通過(guò)給上一個(gè)月以及下一個(gè)月添加點(diǎn)擊事件,通過(guò)事件的觸發(fā)來(lái)完成獲取年月的信息,從而調(diào)一次接口,拿到當(dāng)月的數(shù)據(jù)。

4、代碼實(shí)現(xiàn)過(guò)程

4.1、日歷的初步渲染

這里的calendar_nolabel類是沒(méi)有做標(biāo)注的時(shí)間部分,而calendar_label是做了標(biāo)注的部分

    <el-calendar v-model="value" v-loading="loading" class="cal">
      <template slot="dateCell" slot-scope="{ date, data }">
        <p
          v-if="handleSelected(data.day) == '1'"
          class="calendar_nolabel"
          @click="clickCalendar(data)"
        >
          {{ data.day.split("-").slice(2).join("-") }}
        </p>
        <p
          v-if="handleSelected(data.day) == '2'"
          class="calendar_label"
          @click="clickCalendar(data)"
        >
          {{ data.day.split("-").slice(2).join("-") }}
        </p>
      </template>
    </el-calendar>
4.2、添加日程按鈕
    <el-button class="add-canlendar" @click="handleAdd">+ 添加日程</el-button>
4.3、封裝日程彈窗組件

這里有一點(diǎn)需要注意,在打開(kāi)的時(shí)候我添加了重置表單的操作,這里在使用重置的時(shí)候需要使用this.$nextTick(()=>{}),因?yàn)檫@一步操作需要在DOM渲染完成時(shí)去執(zhí)行。

<template>
  <div class="canlendar">
    <el-dialog :title="title" :visible.sync="dialogFormVisible">
      <el-form :model="form" :rules="rules" ref="ruleForm">
        <el-form-item
          label="重要等級(jí)"
          prop="level"
          :label-width="formLabelWidth"
        >
          <el-select v-model="form.level" placeholder="請(qǐng)選擇">
            <el-option
              v-for="item in options"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            >
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item
          label="日程日期"
          prop="scheduleDate"
          :label-width="formLabelWidth"
        >
          <el-date-picker
            v-model="form.scheduleDate"
            type="date"
            format="yyyy-MM-dd"
            placeholder="選擇日程日期"
          >
          </el-date-picker>
        </el-form-item>
        <el-form-item
          label="日程內(nèi)容"
          prop="content"
          :label-width="formLabelWidth"
        >
          <el-input
            type="textarea"
            v-model="form.content"
            autocomplete="off"
          ></el-input>
        </el-form-item>
      </el-form>
      <div slot="footer" v-if="isAdd" class="dialog-footer">
        <el-button @click="handleCancel">取 消</el-button>
        <el-button type="primary" @click="handleDeterminer">確 定</el-button>
      </div>
      <div slot="footer" v-else-if="!isAdd" class="dialog-footer">
        <el-button class="del-btn" @click="handleRemove">刪除日程</el-button>
        <el-button type="primary" @click="handleClose">關(guān)閉</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { postAddSchedule, deleteSchedule } from "@/api/home";
export default {
  data() {
    return {
      dialogFormVisible: false,
      form: {},
      formLabelWidth: "80px",
      title: "",
      scheId: "",
      isAdd: true,
      options: [
        {
          value: 1,
          label: "一般",
        },
        {
          value: 2,
          label: "重要",
        },
        {
          value: 3,
          label: "很重要",
        },
      ],
      // 表單校驗(yàn)
      rules: {
        level: [{ required: true, message: "請(qǐng)輸入等級(jí)", trigger: "blur" }],
        content: [{ required: true, message: "請(qǐng)輸入內(nèi)容", trigger: "change" }],
        scheduleDate: [
          {
            type: "date",
            required: true,
            message: "請(qǐng)選擇日期",
            trigger: "change",
          },
        ],
      },
    };
  },
  methods: {
    // 打開(kāi)彈窗
    handleOpen(row) {
      if (row) {
        this.title = "查看日程";
        //彈出日程信息
        this.form = JSON.parse(JSON.stringify(row));
        this.scheId = JSON.parse(JSON.stringify(row)).id;
        this.isAdd = false;
      } else {
        this.title = "添加日程";
        this.isAdd = true;
        this.$nextTick(() => {
          this.form = {};
          this.$refs.ruleForm.resetFields();
        });
      }
      this.dialogFormVisible = true;
    },
    // 刪除日程
    handleRemove() {
      // 寫(xiě)上你的刪除接口
      });
    },
    handleClose() {
      this.dialogFormVisible = false;
    },
    // 點(diǎn)擊取消
    handleCancel() {
      this.form = {};
      this.$refs.ruleForm.resetFields();
      this.dialogFormVisible = false;
    },
    // 點(diǎn)擊確定
    handleDeterminer() {
      this.$refs.ruleForm.validate((val) => {
        if (val) {
          // 寫(xiě)上你的添加日程的接口
          this.dialogFormVisible = false;
        } else {
          this.dialogFormVisible = true;
        }
      });
    },
  },
};
</script>
4.4、添加子組件彈窗

將彈窗加入到日歷組件代碼中去,在日歷組件中通過(guò)獲取子組件的handleOpen()方法,彈出日程框。

  • 引入組件
import AddCanlendar from "./canlendarDialog";
  • 彈窗組件
    <!-- 日程彈窗 -->
    <AddCanlendar
      ref="canlendarDialog"
      @handleSuccess="handleSuccess"
    ></AddCanlendar>
4.5、開(kāi)始渲染當(dāng)月日程并做標(biāo)注

通過(guò)map遍歷,取每個(gè)元素節(jié)點(diǎn)下的日期,然后返回到一個(gè)新數(shù)組中去。

// 獲取當(dāng)月的日程信息
    handleSchedule() {
      // 將日期傳入接口,判斷當(dāng)前時(shí)間是否有日程
      getScheduleList(this.moment(this.value).format("YYYY-MM"))
        .then((res) => {
          if (res.code == 0) {
            // this.label.push(res.data);
            this.label = res.data.map((item) => {
              return item.scheduleDate;
            });
            this.notLabel = res.data;
            this.loading = false;
          }
        })
        .catch();
    },

通過(guò)遍歷數(shù)組,判斷日期,有標(biāo)注的日程數(shù)組中有數(shù)據(jù)的話返回flag為2,否則就是默認(rèn)的1。這里可以繼續(xù)多重判斷,比如可以根據(jù)重要的等級(jí)程度去返回不同的值去做渲染。

    handleSelected(day) {
      let flag = "1"; 
      this.label.forEach((item) => {
        if (item == day) {
          flag = "2";
          return;
        }
      });
      return flag;
    },
4.6、給上一月,下一月按鈕添加點(diǎn)擊事件
 created() {
    this.$nextTick(() => {
      // 點(diǎn)擊上個(gè)月
      let prevBtn = document.querySelector(
        ".el-calendar__button-group .el-button-group>button:nth-child(1)"
      );
      prevBtn.addEventListener("click", () => {
        this.value = this.moment(this.value).format("YYYY-MM");
        console.info(this.value);
        this.handleSchedule();
      });
      // 點(diǎn)擊今天
      let currBtn = document.querySelector(
        ".el-calendar__button-group .el-button-group>button:nth-child(2)"
      );
      currBtn.addEventListener("click", () => {
        this.value = this.moment(this.value).format("YYYY-MM");
        console.info(this.value);
        this.handleSchedule();
      });
      // 點(diǎn)擊下個(gè)月
      let nextBtn = document.querySelector(
        ".el-calendar__button-group .el-button-group>button:nth-child(3)"
      );
      nextBtn.addEventListener("click", () => {
        this.value = this.moment(this.value).format("YYYY-MM");
        console.info(this.value);
        this.handleSchedule();
      });
    });
  },

5、完整代碼:

<template>
  <div>
    <el-calendar v-model="value" v-loading="loading" class="cal">
      <template slot="dateCell" slot-scope="{ date, data }">
        <p
          v-if="handleSelected(data.day) == '1'"
          class="calendar_nolabel"
          @click="clickCalendar(data)"
        >
          {{ data.day.split("-").slice(2).join("-") }}
        </p>
        <p
          v-if="handleSelected(data.day) == '2'"
          class="calendar_label"
          @click="clickCalendar(data)"
        >
          {{ data.day.split("-").slice(2).join("-") }}
        </p>
      </template>
    </el-calendar>
    <el-button class="add-canlendar" @click="handleAdd">+ 添加日程</el-button>
    <!-- 日程彈窗 -->
    <AddCanlendar
      ref="canlendarDialog"
      @handleSuccess="handleSuccess"
    ></AddCanlendar>
  </div>
</template>
<script>
import AddCanlendar from "./canlendarDialog";
import { getScheduleList, deleteSchedule } from "@/api/home";
export default {
  components: {
    AddCanlendar,
  },
  data() {
    return {
      value: new Date(),
      notLabel: [],
      label: [],
      loading: true,
    };
  },
  computed: {},
  created() {
    this.$nextTick(() => {
      // 點(diǎn)擊上個(gè)月
      let prevBtn = document.querySelector(
        ".el-calendar__button-group .el-button-group>button:nth-child(1)"
      );
      prevBtn.addEventListener("click", () => {
        this.value = this.moment(this.value).format("YYYY-MM");
        console.info(this.value);
        this.handleSchedule();
      });
      // 點(diǎn)擊今天
      let currBtn = document.querySelector(
        ".el-calendar__button-group .el-button-group>button:nth-child(2)"
      );
      currBtn.addEventListener("click", () => {
        this.value = this.moment(this.value).format("YYYY-MM");
        console.info(this.value);
        this.handleSchedule();
      });
      // 點(diǎn)擊下個(gè)月
      let nextBtn = document.querySelector(
        ".el-calendar__button-group .el-button-group>button:nth-child(3)"
      );
      nextBtn.addEventListener("click", () => {
        this.value = this.moment(this.value).format("YYYY-MM");
        console.info(this.value);
        this.handleSchedule();
      });
    });
  },
  mounted() {
    this.handleSchedule();
    console.log(this.label);
  },
  methods: {
    // 添加日程
    handleAdd() {
      this.$refs.canlendarDialog.handleOpen();
    },
    // 添加成功
    handleSuccess() {
      // 添加日程成功后去刷新列表
      this.handleSchedule();
    },
    handleSelected(day) {
      let flag = "1";
      this.label.forEach((item) => {
        if (item == day) {
          flag = "2";
          return;
        }
      });
      return flag;
    },
    // 獲取當(dāng)月的日程信息
    handleSchedule() {
      // 將日期傳入接口,判斷當(dāng)前時(shí)間是否有日程
      getScheduleList(this.moment(this.value).format("YYYY-MM"))
        .then((res) => {
          if (res.code == 0) {
            // this.label.push(res.data);
            this.label = res.data.map((item) => {
              return item.scheduleDate;
            });
            this.notLabel = res.data;
            this.loading = false;
          }
        })
        .catch();
    },
    // 點(diǎn)擊
    clickCalendar(day) {
      this.notLabel.forEach((item) => {
        if (item.scheduleDate == day.day) {
          // 展示日程
          this.$refs.canlendarDialog.handleOpen(item);
        }
      });
    },
  },
};
</script>
<style scoped>
.cal ::v-deep.el-calendar-day .calendar_nolabel {
  margin: 0 auto;
  padding: 2px;
  text-align: center;
}
.cal ::v-deep.el-calendar-day .calendar_label {
  border: 1px solid #F93937;
  border-radius: 50%;
  width: 23px;
  margin: 0 auto;
  padding: 2px;
  text-align: center;
}

.add-canlendar {
  width: 90%;
  height: 35px;
  line-height: 13px;
  background: #409eff;
  color: #fff;
  margin-top: 5px;
}
</style>
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容