vite4+vue3:从0到1搭建vben后台管理系统(四)-封装dayjs的日历组件

前言

在后台管理系统中,封装vue的日历组件是很常见的一个功能,有时候antdvue里面的组件跟我们业务需求差异比较大时,去改antdui的官方组件比较麻烦,这个时候,我们就得自己去封装这样一个日历组件,效果如下图所示:

请添加图片描述

两种实现方式之vue2.x的实现

<template>
  <div>
    <a-month-picker
      placeholder="选择年月"
      allowClear
      @change="changeMonth"
      :defaultValue="defaultValue"
    />
    <div class="date_box">
      <!-- 星期 -->
      <div class="week">
        <span class="w-item" v-for="(item, index) in week" :key="index">{{
          item
        }}</span>
      </div>
      <!-- 日期 -->
      <div class="day">
        <div class="day_time" v-for="(item, index) in calendar" :key="index">
          <div v-for="(subItem, idx) in item" :key="idx" class="num">
            <p class="c-date" :class="{ 'is-current-month': !subItem.isShow }">
              {{ subItem.date }}
            </p>
            <p class="c-text" v-if="subItem.isShow">{{ subItem.content }}</p>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

js代码逻辑

<script>
import { Component, Vue } from 'vue-property-decorator';
import dayjs from 'dayjs';
import { chunk } from 'lodash';

@Component({})
export default class WorkTimeCalendar extends Vue {
  created() {
    this.init();
  }
  calendar = [];
  week = ['日', '一', '二', '三', '四', '五', '六'];
  init() {
    //处理日期
    this.calendar = chunk(this.getMonth(this.defaultValue), 7);
  }
  getMonth(e) {
    const startDay = dayjs(e).startOf('month');
    const endDay = dayjs(e).endOf('month');
    let currentDay = startDay;
    let list = [];
    while (currentDay.isBefore(endDay)) {
      list.push({ day: currentDay, isShow: true });
      currentDay = currentDay.add(1, 'day');
    }
    // console.log(list,'list')
    let week = list[0].day.day();
    if (week === 0) {
      week = 7;
    }

    for (let i = 1; i < week; i++) {
      // ishow:区分是否是本月日期
      list.unshift({ day: startDay.add(-i, 'day'), isShow: false });
    }
    //下个月补充   42:日历中的六周 * 一周七天
    const nextWeek = 42 - (dayjs(e).daysInMonth() + week - 1);
    for (let i = 1; i <= nextWeek; i++) {
      // ishow:区分是否是本月日期
      list.push({ day: endDay.add(i, 'day'), isMonth: false });
    }
    list = list.map((item, index) => {
      const str = item.day.$d.toLocaleDateString().replaceAll('/', '-');
      item.time = dayjs(str).format('YYYY-MM-DD');
      item.date = dayjs(str).date();
      item.content = `出勤了${index}小时`;
      return item;
    });
    // console.log("本月天数",list)
    return list;
  }
  get defaultValue() {
    return this.dayjs().format('YYYY-MM-DD');
  }
  curentValue = '';
  changeMonth(value) {
    // window.console.log('month', this.dayjs(value).month());
    // window.console.log('year', this.dayjs(value).year());
    const year = this.dayjs(value).year();
    const month = this.dayjs(value).month();
    this.calendar = chunk(this.getMonth(`${year}-${month + 1}`), 7);
  }
}
</script>

样式美化

<style lang="less" scoped>
.date_box {
  padding: 0.32rem 0;
  .week {
    display: flex;
    align-items: center;
    text-align: center;
    width: 90%;
    margin: 0 auto;
    span {
      flex: 1;
      // border: 1px solid #ccc;
      // border-bottom: none;
      height: 0.6rem;
    }
  }
  .day {
    width: 90%;
    margin: 0 auto 24px;
    // background: green;
    .day_time {
      display: flex;
      align-items: center;
      justify-content: space-around;
      text-align: center;
      box-sizing: border-box;
      .num {
        // border: 1px solid #ccc;
        // width: 0.98rem;
        flex: 1;
        height: 0.8rem;
        .is-current-month {
          color: #4a4a4a;
        }
        .c-date,
        .c-text {
          padding: 0;
          margin: 0;
        }
        .c-text {
          font-size: 0.14rem;
          font-family: Microsoft YaHei UI-Regular;
          font-weight: 400;
          color: #37d7db;
        }
      }
    }
  }
}
</style>

这样就实现了我们的日历组件,里面可以根据自己的需求定制props,日历里面的content,非常方便了

两种实现方式之vue3.x的实现

在这里插入图片描述

<template>
  <div>
    <!-- {{ data.calendar }} -->
     <div class="date_box">
      <!-- 星期 -->
      <div class="week">
          <span class="w-item" v-for="(item, index) in week" :key="index">{{ item }}</span>
      </div>
      <!-- 日期 -->
      <div class="day">
         <div class="day_time" v-for="(item, index) in data.calendar"
            :key="index">
            <div v-for="(subItem, idx) in item" :key="idx" class="num">
                <p :class="{'is-current-month':!subItem.isShow}">{{subItem.date}}</p> 
                <p v-if="subItem.isShow">{{ subItem.content}}</p>
            </div>
      </div>
     </div>
     </div>
  </div>
</template>

js逻辑

<script setup>
import { onMounted,reactive } from 'vue';
import dayjs from 'dayjs'
import {chunk} from 'lodash'
onMounted(() => {
  init()
})
const data =reactive({
  calendar:[]
})
function init(){
  //处理日期
  data.calendar = chunk(getMonth('2023-6'),7)
}
function getMonth(e) {
  const startDay = dayjs(e).startOf('month');
  const endDay = dayjs(e).endOf('month');
  let currentDay = startDay;
  let list = [];
  while(currentDay.isBefore(endDay)){
    list.push({day:currentDay,isShow:true})
    currentDay = currentDay.add(1,'day')
  }
  // console.log(list,'list')

  let week = list[0].day.day();
    if (week == 0) {
      week = 7;
    }

    for (let i = 1; i < week; i++) {
       // ishow:区分是否是本月日期
      list.unshift({ day: startDay.add(-i, 'day'),isShow:false });
    }
    //下个月补充   42:日历中的六周 * 一周七天
    let nextWeek = 42 - (dayjs(e).daysInMonth() + week - 1);
    for (let i = 1; i <= nextWeek; i++) {
       // ishow:区分是否是本月日期
      list.push({ day: endDay.add(i, 'day'), isMonth: false })
    }
    list = list.map((item,index) => {
      let str = item.day.$d.toLocaleDateString().replaceAll('/', '-');
      item.time = dayjs(str).format("YYYY-MM-DD")
      item.date = dayjs(str).date()
      item.content=`出勤了${index}`
        return item
    });
    // console.log("本月天数",list)
    return list
}
const week = ["日", "一", "二", "三", "四", "五", "六"];


</script>

css美化

<style lang="less" scoped>
.date_box {
      padding: 32px 0;
      .week {
        display: flex;
        align-items: center;
        text-align: center;
        width: 90%;
        margin:0 auto 6px;
        border: 1px solid #ccc;
        span {
          width: 98px;
          border: 1px solid #ccc;

        }
        
      }
      .day{
        width: 90%;
        margin:0 auto 24px;
        // background: green;
          .day_time{
            display: flex;
            align-items: center;
            justify-content: space-around;
            text-align: center;
            
           box-sizing: border-box;
            .num{
              border: 1px solid #ccc;
              width: 98px;
              height: 49px;
              .is-current-month{
                color: #4a4a4a;
              }
            }
          }
         
        }
}
</style>

也可以像vue2那样实现切换年月,展示不同的月份的日期,自己动手试试拓展这个功能吧~~~

关注我的个人公众号,获取更多前后端开发经验知识
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是搭建后台管理系统的简单步骤: 1. 创建项目 使用 Vue CLI 创建项目,选择 vue3 preset,安装完成后进入项目目录。 ``` vue create my-project cd my-project ``` 2. 安装依赖包 安装 vite、vue-router 和 element-plus。 ``` npm install vite vue-router@4 element-plus --save ``` 安装 pinia 和 echarts。 ``` npm install pinia echarts@5 --save ``` 3. 配置 vite 在根目录下创建 `vite.config.js` 文件,配置 alias 和 server。 ```js import path from 'path' import { defineConfig } from 'vite' export default defineConfig({ resolve: { alias: { '@': path.resolve(__dirname, 'src'), }, }, server: { port: 3000, open: true, }, }) ``` 4. 配置路由 在 `src` 目录下创建 `router` 文件夹,并创建 `index.js` 文件,配置路由。 ```js import { createRouter, createWebHistory } from 'vue-router' import Home from '@/views/Home.vue' const routes = [ { path: '/', name: 'Home', component: Home, }, ] const router = createRouter({ history: createWebHistory(), routes, }) export default router ``` 在 `src` 目录下的 `main.js` 中引入路由。 ```js import { createApp } from 'vue' import App from './App.vue' import router from './router' const app = createApp(App) app.use(router) app.mount('#app') ``` 5. 配置状态管理 在 `src` 目录下创建 `store` 文件夹,并创建 `index.js` 文件,配置状态管理。 ```js import { createPinia } from 'pinia' const store = createPinia() export default store ``` 在 `src` 目录下的 `main.js` 中引入状态管理。 ```js import { createApp } from 'vue' import App from './App.vue' import router from './router' import store from './store' const app = createApp(App) app.use(router) app.use(store) app.mount('#app') ``` 6. 配置 UI 框架 在 `src` 目录下的 `main.js` 中引入 element-plus。 ```js import { createApp } from 'vue' import App from './App.vue' import router from './router' import store from './store' import ElementPlus from 'element-plus' import 'element-plus/lib/theme-chalk/index.css' const app = createApp(App) app.use(router) app.use(store) app.use(ElementPlus) app.mount('#app') ``` 7. 配置 echarts 在 `src` 目录下的 `main.js` 中引入 echarts。 ```js import { createApp } from 'vue' import App from './App.vue' import router from './router' import store from './store' import ElementPlus from 'element-plus' import 'element-plus/lib/theme-chalk/index.css' import * as echarts from 'echarts' const app = createApp(App) app.use(router) app.use(store) app.use(ElementPlus) app.config.globalProperties.$echarts = echarts app.mount('#app') ``` 8. 创建页面 在 `src` 目录下创建 `views` 文件夹,并创建页面组件。 9. 创建布局 在 `src` 目录下创建 `layouts` 文件夹,并创建布局组件。 10. 配置路由和布局 在 `router/index.js` 中配置路由和布局。 ```js import { createRouter, createWebHistory } from 'vue-router' import Layout from '@/layouts/Layout.vue' import Home from '@/views/Home.vue' const routes = [ { path: '/', component: Layout, children: [ { path: '', name: 'Home', component: Home, }, ], }, ] const router = createRouter({ history: createWebHistory(), routes, }) export default router ``` 11. 运行项目 在项目根目录下运行 `npm run dev`,打开浏览器访问 `http://localhost:3000` 查看效果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值