用 ElementPlus 的日历组件 Calendar 自定义渲染

news2025/2/25 14:26:02

文章目录

    • 需求
    • 分析
      • 1. 英文改为中文
      • 2. 修改样式
      • 3. 自定义头部
      • 4. 增删改功能接入

需求

使用 ElementPlus中的 Calendar 组件完成自定义渲染

分析

1. 英文改为中文

转为中文的方式:用 ElementPlus的日历组件如何改为中文

2. 修改样式

在这里插入图片描述

  • 附源码
<template>
  <el-calendar>
    <template #date-cell="{ data }">
      <el-row :class="data.isSelected ? 'is-selected' : 'sds'">
        {{ data.day.split('-').slice(1).join('-') }}
        {{ data.isSelected ? '✔️' : '' }}
      </el-row>
      <div v-for="(item, index) in textContent(data.day)" :key="index">
                <e-row>
                  <el-col class="center">
                    <el-tag type="warning" class="tag">
                      <el-row v-if="item.xianyue == 0">
                        <el-col :span="17" class="tag">
                          <span>当日限约</span>
                        </el-col>
                        <el-col :span="1"></el-col>
                        <el-col :span="6" class="tag2">
                          <span>0</span>
                        </el-col>
                      </el-row>
                      <el-row v-else>
                        <el-col :span="17" class="tag">
                          <span>当日限约</span>
                        </el-col>
                        <el-col :span="1"></el-col>
                        <el-col :span="6" class="tag2">
                          <span>{{ item.xianyue }}</span>
                        </el-col>
                      </el-row>
                    </el-tag>
                  </el-col>
                </e-row>
                <el-row
                  style="margin-top: 10px"
                  class="yuyue"
                  v-if="item.yiyue && item.sy == 0"
                >
                  <el-col :span="11" class="center">
                    <span>已约</span
                    ><span class="center2" style="">0</span></el-col
                  >
                  <el-col :span="2" class="center">|</el-col>
                  <el-col :span="11" class="center">
                    <span>剩余</span><span class="center2">0</span></el-col
                  >
                </el-row>
                <el-row style="margin-top: 10px" class="yuyue" v-else>
                  <el-col :span="11" class="center">
                    <span>已约</span
                    ><span class="center2" style="">{{
                      item.yiyue
                    }}</span></el-col
                  >
                  <el-col :span="2" class="center">|</el-col>
                  <el-col :span="11" class="center">
                    <span>剩余</span
                    ><span class="center2">{{ item.sy }}</span></el-col
                  >
                </el-row>
              </div>

    </template>
  </el-calendar>
</template>

<style>
.is-selected {
  color: #1989fa;
}
  
  
</style>

<style scoped >
 
:deep .el-calendar__body {
  padding: 4px 20px 35px;
}
:deep .el-calendar-table thead th {
  color: #ffab11;
  font-weight: bold;
  font-size: 25px;
}
.tag {
  display: flex;
  align-items: center;
  height: 2.5vh;
  justify-content: center;
}
.tag2 {
  display: flex;
  align-items: center;
  height: 2.5vh;
  justify-content: center;
  font-size: 18px;
}
.aaa .is-selected .yuyue {
  color: #ffab11;
}
.aaa .datastyle {
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 3rem;
  color: #353636;
  font-weight: 600;
}
:deep .el-calendar-table .el-calendar-day:hover {
  background-color: #faecd8;
}
:deep .el-calendar {
  --el-calendar-selected-bg-color: #faecd8;
}
.aaa .is-selected .datastyle {
  color: #ffab11;
}
.aaa .prev .datastyle {
  color: #c4c5c8;
}
.aaa .next .datastyle {
  color: #c4c5c8;
}
:deep .el-calendar {
  --el-calendar-cell-width: 130px;
}
.center {
  display: flex;
  justify-content: center;
  align-items: center;
}
.center2 {
  display: flex;
  justify-content: center;
  align-items: center;
  color: #ffab11;
  margin-left: 5px;
  font-size: 20px;
}
:deep .el-calendar__header {
  justify-content: center;
}
</style>

<script setup lang="ts">
import { ref, reactive, toRefs, onMounted } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
  
  const state = reactive({
      tableData: [],
        //测试数据
      calendarData: [
        {
          day: "2022-11-04",
          xianyue: 400,
          yiyue: 5,
          sy: 1,
        },
        {
          day: "2022-11-05",
          xianyue: 500,
          yiyue: 5,
          sy: 1,
        },
        {
          day: "2022-11-06",
          xianyue: 200,
          yiyue: 5,
          sy: 1,
        },
        {
          day: "2022-11-07",
          xianyue: 0,
          yiyue: 0,
          sy: 0,
        },
      ],
    });
  
  
  //处理日期获取后台数据动态渲染上去
    const textContent = (date) => {
        //当前date是拿到上面日历组件当前的日期值 根据该值去筛选测试数据找到对应各个日期下对应的数据return出去
        console.log(date, 1111);
        return state.calendarData.filter((item) => {
          return date === item.day;
        });
      };

</script>

3. 自定义头部

在这里插入图片描述

<el-calendar v-model="value" ref="calendar">
   <template #header="{ date }">
       <el-button-group>
           <el-button size="small" @click="selectDate('prev-year')">
               上一年
           </el-button>
           <el-button size="small" @click="selectDate('prev-month')">
               上个月
           </el-button>
       </el-button-group>
       <span>{{ date }}</span>
       <el-button-group>
           <el-button size="small" @click="selectDate('today')">今天</el-button>
           <el-button size="small" @click="selectDate('next-month')">
               下个月
           </el-button>
           <el-button size="small" @click="selectDate('next-year')">
               下一年
           </el-button>
       </el-button-group>
   </template>
<el-calendar/>



const value = ref(new Date());
const dateList = ref([])
const calendar = ref();
const selectDate = (val) => {
    dateList.value.length = 0
    calendar.value.selectDate(val);
};
function handleMonthChange(date) {
    dateList.value.push(date)
    // date 是切换后的日期,根据这个日期来计算开始日期和结束日期
    // const year = date.getFullYear();
    // const month = date.getMonth();
    // const startDate = new Date(year, month, 1); // 开始日期
    // const endDate = new Date(year, month + 1, 1); // 结束日期


    //根据开始日期和结束日期来查询数据,然后更新视图
    // ...
}

4. 增删改功能接入

在这里插入图片描述

<template>
    <div class="container my-container">
        <a-card :bordered="false" :style="{ width: '100%' }">
            <el-calendar v-model="value" ref="calendar">
                <template #header="{ date }">
                    <el-button-group>
                        <el-button size="small" @click="selectDate('prev-year')">
                            上一年
                        </el-button>
                        <el-button size="small" @click="selectDate('prev-month')">
                            上个月
                        </el-button>
                    </el-button-group>
                    <span>{{ date }}</span>
                    <el-button-group>
                        <el-button size="small" @click="selectDate('today')">今天</el-button>
                        <el-button size="small" @click="selectDate('next-month')">
                            下个月
                        </el-button>
                        <el-button size="small" @click="selectDate('next-year')">
                            下一年
                        </el-button>
                    </el-button-group>
                </template>
                <template #date-cell="{ data }">
                    <div class="calendar-day">
                        <div :class="data.isSelected ? 'is-selected' : ''">
                            {{ data.day.split('-').slice(1).join('-') }}
                        </div>
                        {{ handleMonthChange(data.day) }}
                        <p class="duty-text">
                            值班人员:
                            <span v-for="item in tableData" :key="item.id">
                                <span v-if="item.dutyDate == data.day">
                                    {{ item.dutyUser }}
                                </span>
                            </span>
                        <div>
                            <a-button size="mini" type="text" @click="handleEdit(data)"
                                style="color: #58a7fe;">编辑</a-button>
                            <a-popconfirm content="确定要删除" @ok="handleDelete(data)">
                                <a-button size="mini" type="text" style="color: #58a7fe;">删除</a-button>
                            </a-popconfirm>
                        </div>
                        </p>
                    </div>
                </template>
            </el-calendar>
        </a-card>
        <a-modal v-model:visible="visible" :title="title" draggable :on-before-ok="handleOk" :mask-closable="false">
            <a-form ref="formRef" :model="editForm" :label-col-props="{ span: 5 }" :wrapper-col-props="{ span: 16 }">
                <a-form-item field="deptId" label="部门:">
                    <el-cascader v-model="editForm.deptId" style="min-width: 350px;" ref="cas"
                        :options="typeList.deptList" :props="props" clearable collapse-tags @change="cascaderChange"
                        placeholder="请选择">
                    </el-cascader>
                </a-form-item>
                <a-form-item field="userId" label="值班人:" :rules="[
            {
                required: true,
                message: '请选择',
            },
        ]">
                    <el-select style="min-width: 350px;" v-model="editForm.userId" placeholder="请选择">
                        <el-option v-for="(item, index) in typeList.userList" :key="index" :label="item.userName"
                            :value="item.userId" />
                    </el-select>
                </a-form-item>

            </a-form>
        </a-modal>
    </div>
</template>

<script lang="ts" setup>
import { onMounted, ref, watch, watchEffect, defineComponent, computed } from 'vue';
import { Message } from '@arco-design/web-vue';
import {
    getDutyPlanData as getInfo,
    getdept,
    getUser,
    getUserData,
    addDutyPlanData as addData,
    editDutyPlaneData as editData,
    deleteDutyPlanData as deleteData,
} from '@/api/common-management'
import { handleTree } from "@/utils/common-tools";

function findItemUser(data) {
    const currentObj = typeList.value.userLists.find(item => {
        return item.user_id == data
    })
    if (currentObj) {
        return currentObj.user_name
    }
}

const value = ref(new Date());
// 编辑
const resetEditForm = () => {
    return {
        deptId: null,
        userId: null
    }
}
const editForm = ref(resetEditForm())
const visible = ref(false)
const title = ref('')
// 编辑
function handleEdit(val) {
    editForm.value = resetEditForm()
    getInfo({ dutyDate: val.day }).then(res => {
        if (res.rows.length) {
            editForm.value = res.rows[0]
            title.value = '编辑'
        } else {
            editForm.value.dutyDate = val.day
            title.value = '添加'
        }
    })
    visible.value = true
}
const formRef = ref()
const handleOk = async () => {
    const res = await formRef.value?.validate();
    if (!res) {
        if (title.value == '编辑') {
            const tempData = {
                dutyDate: editForm.value.dutyDate,
                dutyUserId: editForm.value.userId,
                id: editForm.value.id,
                dutyUser: findItemUser(editForm.value.userId)
            }
            editData(tempData).then(res => {
                Message.success('编辑成功')
                visible.value = false
            })
        } else {
            const tempData = {
                dutyDate: editForm.value.dutyDate,
                dutyUserId: editForm.value.userId,
                // id: editForm.value.id,
                dutyUser: findItemUser(editForm.value.userId)
            }
            addData(tempData).then(res => {
                visible.value = false
                Message.success('添加成功')
            })
        }
        getTableData({
            pageNum: 1,
            pageSize: dateList.value.length,
            'params.beginTime': dateList.value[0],
            'params.endTime': dateList.value[dateList.value.length - 1],
        })
    } else {
        Message.error('请完整填写表单信息')
        return false
    }
};
// 删除
function handleDelete(val) {
    getInfo({ dutyDate: val.day }).then(res => {
        if (res?.rows[0]?.id) {
            deleteData(res.rows[0].id).then(res => {
                Message.success('删除成功')
                getTableData({
                    pageNum: 1,
                    pageSize: dateList.value.length,
                    'params.beginTime': dateList.value[0],
                    'params.endTime': dateList.value[dateList.value.length - 1],
                })
            })
        }
    })
}
const dateList = ref([])// 存放当前页所获取的所有日期
const calendar = ref();
const selectDate = (val) => {
    dateList.value.length = 0
    calendar.value.selectDate(val);
};
function handleMonthChange(date) {
    dateList.value.push(date)
}
const watchObj = computed(() => {
    return dateList.value[0]
})
watch(watchObj, (val) => {
    if (val) {
        const tempData = {
            pageNum: 1,
            pageSize: dateList.value.length,
            'params.beginTime': dateList.value[0],
            'params.endTime': dateList.value[dateList.value.length - 1],
        }
        getTableData(tempData)
    }
})
// 获取页面信息
const tableData = ref([])
const getTableData = (tempData) => {
    getInfo(tempData).then(res => {
        tableData.value = res.rows
    })
}
// 获取类型信息
const typeList = ref({
    deptList: [],
    userList: [],
    userLists: []
})
//  树选择器
const props = {
    expandTrigger: 'hover',
    label: "deptName",
    checkStrictly: true,
    value: "deptId",
}
function getTypeList() {
    getdept().then(res => {
        const temp = JSON.parse(JSON.stringify(res.data))
        typeList.value.deptList = handleTree(res.data, "deptId")
    })
    getUserData().then(res => {
        typeList.value.userLists = res.data
    })
}
const cas = ref()
function cascaderChange(data, id) {
    let nodes = cas.value.getCheckedNodes()
    getUser({ deptId: nodes[0].value }).then(res => {
        typeList.value.userList = res.rows
    })
}
const fetchData = () => {
    getTypeList()
}

onMounted(() => {
    fetchData()
});
</script>




<style scoped lang="less">
.wrapper {
    padding-top: 10px;
}

.duty-text {
    text-align: center;
    color: #939fb6;
    font-size: large;
}

.is-selected {
    color: #1989fa;
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1585705.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【YOLOv8】Yolov5和Yolov8网络结构的分析与对比

目录 一 YOLOv5 二 YOLOv8 yolo通常采用backbone-neck-head的网络结构。 Backbone 主要负责从输入图像中提取高层次的语义特征,常包含多个卷积层和池化层&#xff0c;构建了一个深层次的特征提取器。Neck通常用来进一步整合与调整backbone提取的特征&#xff0c;有利于将不同…

内容创作策略:打造影响力强大的技术博客

CSDN的朋友你们好&#xff0c;我是未来&#xff0c;今天给大家带来专栏【程序员博主教程&#xff08;完全指南&#xff09;】的第6篇文章——“博客内容创作策略”。本文为技术博主提供了一个精简的内容创作策略指南&#xff0c;涵盖了设定目标、分析竞争、关键词研究、内容规划…

PMP与软考的区别看不懂?看懂这五点,小白都知道怎么选!

如果你心怀抱负&#xff0c;不甘心做项目“小透明” 如果你遇到年龄危机&#xff0c;进阶管理无门道&#xff1f; 如果你是技术&#xff0c;管理项目有如盲人摸象&#xff1f;可以考PMP! 如果你准备想攒积分&#xff0c;轻松落户 如果你想评职称&#xff0c;获得专业技术职务 如…

【环境搭建】(五)Ubuntu22.04安装cuda_11.8.0+cudnn_8.6.0

一个愿意伫立在巨人肩膀上的农民...... 设备配置&#xff1a; 一、安装GCC 安装cuda之前&#xff0c;首先应该安装GCC&#xff0c;安装cuda需要用到GCC&#xff0c;否则报错。可以先使用下方指令在终端查看是否已经安装GCC。 gcc --version 如果终端打印如下则说明已经安装…

【浏览器】Google Chrome浏览器打开自动访问网址 gw1.dhwz333.top

目录 [TOC](目录) 问题描述1、查看谷歌浏览器信息2、查看快捷方式属性2、查找注册表3、重装浏览器 解决方案一、使用360系统急救箱进行杀毒步骤1、下载360系统急救箱方式1、直接下载方式2、从360杀毒中打开&#xff0c;需要联网2.1、打开“功能大全”2.2、打开系统急救箱 步骤2…

Fitzgerald:Renin antibody抗体

货号&#xff1a;10-2421 名称&#xff1a;Renin antibody 规格&#xff1a;250ug 产品描述&#xff1a; 别名&#xff1a;Monoclonal Renin antibody, Anti-Renin antibody, FLJ10761 antibody, HNFJ2 antibody, REN antibody, RENI antibody, Renin antibody, renin precu…

第十四篇【传奇开心果系列】Python自动化办公库技术点案例示例:深度解读Python自动化处理图像

传奇开心果博文系列 系列博文目录Python自动化办公库技术点案例示例系列 博文目录前言一、Python自动化图像处理的优点介绍二、Python常用图像处理库和功能介绍三、强大且易于上手示例代码四、丰富的算法资源示例代码五、批量处理图片示例代码六、支持多种图像格式示例代码七、…

【C#】版本号

&#x1f4bb; 代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace ConsoleApp16 {internal class Program{static void Main(string[] args){Version version01 new Version("4.0.0…

SSM整合----第一个SSM项目

文章目录 前言一、使用步骤1.引入库2.建表3 项目结构4 web.xml的配置5 配置数据源6 SpringMVC配置7 配置MyBatis Mapper8 书写控制类 总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; SSM整合是指Spring、SpringMVC和MyBatis这三个框架的整合使用。…

数据结构OJ题——栈和队列

1. 用栈实现队列&#xff08;OJ链接&#xff09; 题目描述&#xff1a;请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作&#xff08;push、pop、peek、empty&#xff09; void push(int x) 将元素 x 推到队列的末尾 int pop() 从队列的开头移除并返回…

Mysql安装和初始化密码

一、下载地址&#xff1a; MySQL :: Download MySQL Community Server (Archived Versions) 1、解压到本地目录下&#xff0c;然后配置环境变量&#xff08;也可以不配置&#xff0c;不影响使用&#xff0c;不过为了区分多版本的MySQL最好配置一下系统变量&#xff09; 复制…

分享:temu跨境电商项目是真的能赚钱吗?有哪些技巧?

近年来&#xff0c;跨境电商成为了一个备受瞩目的领域&#xff0c;temu跨境电商项目也吸引了众多创业者和投资者的目光。那么&#xff0c;temu跨境电商项目真的能够赚钱吗?又有哪些技巧可以帮助我们在这个领域取得成功呢? 首先&#xff0c;可以肯定的是&#xff0c;temu跨境电…

谷歌查问题

1&#xff0c;打开 it工具箱-里面啥都有 2&#xff0c;找到谷歌 3&#xff0c;访问gpt

使用LNMP部署动态网站环境

目录 实验环境 一、配置LNMP架构环境 二、验证部署的LNMP 动态网站环境是否可用 三、配置过程中遇到的问题及解决思路 实验环境 centos7 192.168.81.131/24 一、配置LNMP架构环境 概念及配置手册参考第20章 使用LNMP架构部署动态网站环境。 | 《Linux就该这么学》 安装g…

开源项目ChatGPT-Next-Web的容器化部署(四)-- k8s容器部署使用configmap配置

一、接着上文 本文的内容是在k8s容器中&#xff0c;如何使用configmap对.env文件进行挂载&#xff0c;实现环境的差异化配置。 二、源码结构 项目ChatGPT-Next-Web使用了.env文件来配置不同环境下的值&#xff1a; 所以&#xff0c;我们同理新增两个配置文件&#xff0c;见下…

PixArt-β:Fast and controllable image generation with latent consistency models

PixArt α to Σ: All about Efficient Diffusion Models - 知乎前言自年初Sora和Stable Diffusion 3推出以来&#xff0c;笔者就开始关注基于Diffusion Transformer的工作。在我的往期文章《 Diffusion Transformer Family&#xff1a;关于Sora和Stable Diffusion 3你需要知道…

跟TED演讲学英文:A new way to build AI, openly by Percy Liang

A new way to build AI, openly Link: https://www.ted.com/talks/percy_liang_a_new_way_to_build_ai_openly? Speaker: Percy Liang Date: October 2023 文章目录 A new way to build AI, openlyIntroductionVocabularyTranscriptSummary后记 Introduction Today’s AI …

HiSilicon352 android9.0 系统显示方向旋转与截屏问题分析

一&#xff0c;系统显示方向 1. 概述 Android的旋转显示&#xff0c;主要运用于广告机。Android的旋转&#xff0c;包括图形UI的旋转、鼠标和遥控器的旋转及媒体旋转。 下图为竖屏UI的绘制坐标系和显示坐标系。 2. 功能说明 方案依据Android原生的旋转原理设计&#xff0c…

“安全边际大师”卡拉曼2023年珍贵访谈:如果视市场为狂躁的交易对手,那你就能利用反复无常来获利

“对于那些被广泛跟踪的股票&#xff0c;如果你不比其他人更聪明&#xff0c;且你的观点与别人无异&#xff0c;你是赚不到钱的。” “足够大的折价也许可以抵消你对它缺乏最深刻的认识。” “拓宽投资视野不仅诱人&#xff0c;也可能价值连城。” “如果向市场寻求答案&…

JAVA面试八股文之数据库

MySQL面试题 MySQL 存储引擎架构了解吗&#xff1f;CHAR 和 VARCHAR 的区别是什么&#xff1f;索引是越多越好嘛&#xff1f;MySQL数据库中空值&#xff08;null&#xff09;和空字符串&#xff08;&#xff09;的区别&#xff1f;SQL 中 on 条件与 where 条件的区别&#xff1…