最近遇到了项目中写日历的形式
看了看react 和 antd ,用的时候发现了好大的坑。建议看看antd 的 API 。一定要看看,不然你就崩溃了。

好了先看看布局后的样式图展

数据怎么返回你要和后端协定好。
不然数据有问题,前端就要麻烦处理了。
上图可见,这是详情数据,通过id 拿回的。接口的话自己写吧,我这里就不展示了。
协定的是: 数据创建的时候肯定是要传一个时间和具体的事项。但是你要想在日历中展示成一条条的形式,那可定是数组最好处理。
我们模拟一下情景
创建数据的时候:给后端传的数据(前端怎么传,后端怎么存,需要的时候就怎么返回来就行)
我们模拟一下后端返回的数据:

parasm = [ {fitTime: '2022-09-01 00:00:00' // 这个时间最好是带着 时分秒,但是不用实时获取当前时间的时分秒,你可以去看 days 或者  moment  当然也可以只到年月日就行,看你们需求。data : [{工序:1.....}{工序:2.....}{工序:3.....}{工序:4.....}]},{fitTime: '2022-09-02 00:00:00' // 这个时间最好是带着 时分秒,但是不用实时获取当前时间的时分秒,你可以去看 days 或者 moment  当然也可以只到年月日就行,看你们需求。data : [{工序:1.....}{工序:2.....}]},{fitTime: '2022-09-03 00:00:00' // 这个时间最好是带着 时分秒,但是不用实时获取当前时间的时分秒,你可以去看 days 或者 moment  当然也可以只到年月日就行,看你们需求。data : [{工序:1.....}{工序:2.....}{工序:3.....} ]}
]

好了。这是我们约定的数据样式
,剩下的交给我吧。
看一下antd


注意:
dateFullCellRender 自定义渲染日期单元格,返回内容覆盖单元格 function(date: Moment): ReactNode。
headerRender 自定义头部内容 function(object:{value: Moment, type: string, onChange: f(), onTypeChange: f()})

当你在代码中布局后,在页面上展示,通过log 发现打印了好多的时间,就是因为antd 组件本身已经封装过了。不能在时间上去改变什么。
唯一不同的是,你获取后端返回的时间和antd 的时间做比较然后渲染页面就行了。。
看代码操作。解析放在代码里了

除了做个日历后边加了个echart 图
如果你不需要可以不用看 this.complete(); // echart 展示图方法

import React from 'react';
import { ElNotification, ElCard } from '@/components/el';
import { Spin, Button } from 'antd';
import dayjs from 'dayjs';
import { ElRowContainer } from '@/components/el';
import * as service from './service';  // 接口封装的文件 ,这里不做展示,一般项目里都会有自己的接口封装方法,直接用你们的接口替换就行
import MultiTabMobx from '@/store/multiTab';
import { Badge, Calendar, Select, Row, Col } from 'antd'; // antd 里面的 图标和组件引用
import type { Moment } from 'moment'; // 这个是要用的,可以直接用,一般项目里面都会有
import 'moment/locale/zh-cn'; // 这个也是必须的,不然你会发现引用了之后转义的都是英文时间
import './index.less'; // 样式
import moment from 'moment'; // 也必须的,直接用
import EditModal from './EditModal/index';
import * as echarts from 'echarts'; // echarts 的引用
import { statusMap } from '@/utils'; // 这个是展示出日历后,对每一条 li 做的颜色展示,不同的需求展示不同的颜色interface Props {match: any;push?: any;location: any; // 这个是其他页面传回的数据 这里用了 react 中state 的路由传参方式
}
interface State {loading: boolean;RenderData: any;modalVisible: Boolean;mark: String;data: any;formRef: any; //表单的reflocationState: any; // 定义的接收传参的处理
}class PurcBuyerLook extends React.Component<Props, State> {modalRef: any;multiTabStore: any;constructor(props) {super(props);this.multiTabStore = MultiTabMobx;this.state = {loading: false,RenderData: [], // 前端定义的接收后端数据做展示的modalVisible: false,formRef: null, //表单的refmark: 'create',data: null, // 这个是弹框要用的,需要就用locationState: this.props.location  // 接收传参};}async componentDidMount() {let params = this.state?.locationState?.state.params; // 接收state传参 的处理。if (params) {this.getCalendDetail(params); // 日历接口方法this.complete(); // echart 展示图方法}}// 获取详情 日历看板数据getCalendDetail = async (params) => {this.setState({loading: true});const res = await service.QueryCalendar(params); // 接口调取处理结果this.setState({loading: false});if (res.success) {// 请求成功的返回的数据;let details = res.data.map((item) => {return item;});this.setState({RenderData: details // 直接赋值,});}};// 这个是改变年 月 的事件操作。(需要当前接收的id,因为我们看的是特定某条的明细,所以主单的id是唯一的,直接用就行。
这里的时间是你实时变化的,不管是点击年的时候还是月的时候,这里展示的是选中年或月的当前月的第一天,因为要展示一月,所以不用管哪天。)getData = async (data) => {const capaBoardId = this.state?.locationState?.state?.params?.capaBoardId;const calendarDate = dayjs(data).startOf('month').format('YYYY-MM-DD 00:00:00');let params = {capaBoardId,calendarDate // // 选中时间的当前月第一天};this.getCalendDetail(params);};// 返回到主单,直接放路由就行了onBack = () => {const { push } = this.props;push('/Capacity/manage/Capacitykan/list', () => false);};// antd 自定义渲染日期单元格,返回内容会被追加到单元格 dateCellRenderdateFullCellRender = (value: Moment) => { // 这里的 value 就是好多的时间,antd 返的const listData = this.getListData(value); // 这里就是数据的处理展示  ,因为是数组,展示的话用 li 做合适。return (<ul className='events'>{listData.map((item) => (<likey={item.itemId}onClick={() => this.handleClick(item)} // 每一个 li 的点击事件style={{  // 么个数据的样式肯定要加的 ,不然放不下怎么办,所以 溢出隐藏width: '100px',marginLeft: '-30px',whiteSpace: 'nowrap',overflow: 'hidden',textOverflow: 'ellipsis',// 报工时间 reportTime 大于排产时间 scheduleTime 已逾期-红色, 已报工数量 reportQty 为0  未开始-黄色 ,已报工数量小于任务数量 scheduleQty 已开始-蓝色 ,已报工数量大于等于任务数量已完成-绿色,color: statusMap.get(`QTY_${item.reportTime > item.scheduleTime? 3: item.reportQty == 0? 0: item.reportQty < item.scheduleQty? 1: item.reportQty > item.scheduleQty? 2: 0 || item.reportQty == item.scheduleQty? 2: 0}`)}}>{item.itemName}&nbsp;{item.itemCode}&nbsp;{item.equiProcName}&nbsp;{item.techName}</li>))}</ul>);};// 数据的展示处理,主要的就是这里了//  解析 这里的value 还是 antd 的时间 ,我们要做的就是拿接口返回的数据时间和这个时间做对比。只要有时间数据一样的就把数据展示到对应的那一天getListData = (value: Moment) => {let listData;this.state.RenderData.map((item) => { // 拿到处理后的后端数据,前边已经state了// 判断一下  后端返回的数据时间 == 通过moment处理的value 时间 (我们是到年月日时分秒了。如果你们不用时分秒就不用处理 直接 [value] 或者 [value.data()] 或者 value )if (item.scheduleTime == moment(value).format('YYYY-MM-DD 00:00:00')) {listData = [...item.details];}});// 这里把对应的时间数据返回后return 出去。上边有接收处理的 ul --li return listData || [];};// 这是点击每一个li 的事件弹框处理,你们怎么用就怎么改handleClick = async (item) => {const dataForm = {...item};this.setState({modalVisible: true,mark: 'edit',data: dataForm});};// 关闭弹窗closeModal = () => {this.setState({ modalVisible: false });this.state.formRef.resetFields(); // 清空数据};// form表单refformRef = (ref) => {this.setState({formRef: ref});};// 弹框保存 有新增有编辑 if判断save = async () => {const { formRef } = this.state;// 表单验证await formRef.validateFields().catch(() => {ElNotification({type: 'warning',message: '请检查基础信息'});return Promise.reject();});const fieldsValue = formRef.getFieldsValue();let reportId = this.state.data.id;let reportQty = fieldsValue.EditReportQty;const res = await service.saveEdit(reportId, reportQty);if (res.success) {ElNotification({ type: 'success', message: res.msg });this.setState({modalVisible: false});formRef.resetFields(); // 清空数据let params = this.state?.locationState?.state.params;this.getCalendDetail(params); // 日历接口方法} else {ElNotification({type: 'error',message: res.msg || res.data || '操作失败!'});}};// 完成情况 echartcomplete = async () => {var chartDom = document.getElementById('mainStatus');var myChart = echarts.init(chartDom);var option;let id = this.state?.locationState?.state.params?.capaBoardId;const echartData = await service.echartDetail(id);if (echartData.success) {let data1 = []; // 完成工序占比let data2 = []; // 未完成工序占比// 展示n个工序名称let equiProcName = echartData.data.map((item) => {return item.equiProcName; // 工序名称});let itemEquiProc = echartData.data.map((item) => {return {totalQty: item.totalQty, // 总数finishQty: item.finishQty, // 完成数量Quantity: item.totalQty - item.finishQty // 未完成数量};});for (let i = 0; i < echartData.data.length; i++) {itemEquiProc.forEach((item) => {data1.push(item.finishQty); // 完成工序占比data2.push(item.Quantity); // 未完成工序占比});}var emphasisStyle = {itemStyle: {shadowBlur: 10,shadowColor: 'rgba(0,0,0,0.3)'}};option = {legend: {data: ['完成', '未完成'], // 头长度left: '10%'},tooltip: {},xAxis: {data: equiProcName,name: '工序',axisLine: { onZero: true },splitLine: { show: false },splitArea: { show: false }},yAxis: {},grid: {bottom: 100},series: [{name: '完成',type: 'bar',stack: 'one',emphasis: emphasisStyle,data: data1},{name: '未完成',type: 'bar',stack: 'one',emphasis: emphasisStyle,data: data2}]};myChart.on('brushSelected', function (params) {var brushed = [];myChart.setOption({title: {backgroundColor: '#333',text: 'SELECTED DATA INDICES: \n' + brushed.join('\n'),bottom: 0,right: '10%',width: 100,textStyle: {fontSize: 12,color: '#fff'}}});});option && myChart.setOption(option);} else {ElNotification({type: 'error',message: echartData.msg || '操作失败'});}};// 页面的渲染render() {const { modalVisible, loading, data, mark } = this.state;return (<div><Spin spinning={loading}><ElRowContainer blocks={[]} position='top' onBack={this.onBack} /><ElCard title='产能看板详情'><CalendardateCellRender={this.dateFullCellRender}headerRender={({ value, type, onChange, onTypeChange }) => {const start = 0;const end = 12;const monthOptions = [];const current = value.clone();const localeData = value.localeData();const months = [];for (let i = 0; i < 12; i++) {current.month(i);months.push(localeData.monthsShort(current));}for (let i = start; i < end; i++) {monthOptions.push(<Select.Option key={i} value={i} className='month-item'>{months[i]}</Select.Option>);}const year = value.year();const month = value.month();const options = [];for (let i = year - 10; i < year + 10; i += 1) {options.push(<Select.Option key={i} value={i} className='year-item'>{i}</Select.Option>);}return (<div style={{ padding: 8 }}><Row gutter={8}><Col><Selectsize='small'dropdownMatchSelectWidth={false}className='my-year-select'value={year}onChange={(newYear) => {const now = value.clone().year(newYear);onChange(now);// 可以在这里打印一下 now  看你需要什么样的时间格式就处理什么格式,然后传到方法里面this.getData(now.format('YYYY-MM-DD'));}}>{options}</Select></Col><Col><Selectsize='small'dropdownMatchSelectWidth={false}value={month}onChange={(newMonth) => {const now = value.clone().month(newMonth);onChange(now);this.getData(now.format('YYYY-MM-DD'));}}>{monthOptions}</Select></Col></Row></div>);}}/></ElCard>// echarts 展示图<ElCard title='完成情况'><divid='mainStatus'style={{ height: '300px', marginTop: '30px' }}></div></ElCard></Spin><EditModaltitle={mark === 'create' ? '新增报工' : '编辑报工'}modalVisible={modalVisible}closeModal={this.closeModal}save={this.save}onRef={this.formRef}data={data}mark={mark}></EditModal></div>);}
}export default PurcBuyerLook;

到此就结束了。 是不是可简单

react 自定义日历 手把手教你相关推荐

  1. react商城项目(手把手教)

    最近刚学完react 直接来开搞个小项目 创建项目 技术栈 跨域 扩展跨域 路由 Antd 页面 首页 音乐组件 首页内容 注册 登录 一级分类和二级分类 详情页 制造商 有些代码很丑陋,望评论区的大 ...

  2. android 自定义心电图,手把手教你打造一个心电图效果View Android自定义View

    大家好,看我像不像蘑菇-因为我在学校呆的发霉了. 思而不学则殆 丽丽说得对,我有奇怪的疑问,大都是思而不学造成的,在我书读不够的情况下想太多,大多等于白想 ,所以革命没成功,同志仍需努力. 好了废话不 ...

  3. android 自定义心电图,手把手教你打造一个心电图效果View Android自定义View(示例代码)...

    大家好,看我像不像蘑菇-因为我在学校呆的发霉了. 思而不学则殆 丽丽说得对,我有奇怪的疑问,大都是思而不学造成的,在我书读不够的情况下想太多,大多等于白想 ,所以革命没成功,同志仍需努力. 好了废话不 ...

  4. ajax无刷新kesion,手把手教你使用KesionCMS自定义SQL,轻松打造人才招聘系统

    科汛系统有着强大的自定义SQL标签,利用SQL标签,我们可以做出很多一般系统函数标签没办法实现的特殊效果. 今天我们接着"解密 V4.0自定义模型(手把手教你建企业招聘模块)"这篇 ...

  5. 自定义view学习-手把手教你制作一个可扩展日历控件

    来看看效果图先,手把手教你实现一个简易,但高扩展度的日历控件,可自由扩展成签到,单选,多选日期. 首先我们来分析实现思路.对于上图的效果,很明显是一个6x7的表格. 我们可以两个for循环控制绘制每个 ...

  6. 手把手教你在Hexo中使用Github贡献日历(以Next主题为例)

    手把手教你在Hexo中使用Github贡献日历(以Next主题为例) 起因 现在开始! 最简单的方法 自定义贡献日历的配色方案 放进首页和归档页(以Next主题为例) :warning: 注意 最终效 ...

  7. C# SuperSocket 手把手教你入门 傻瓜教程---5(探索自定义AppServer、AppSession,Conmmand,用配置文件App.comfig启动服务器)

    C# SuperSocket 手把手教你入门 傻瓜教程系列教程 C# SuperSocket 手把手教你入门 傻瓜教程---1(服务器单向接收客户端发送数据) C# SuperSocket 手把手教你 ...

  8. 解放前端工程师——手把手教你开发自己的自定义列表和自定义表单系列之二接口

    前言 阅读前请按照顺序参看系列文章,效果更佳! Vue中路由到一个公共组件,然后根据路径中是否存在文件动态加载组件 解放前端工程师--手把手教你开发自己的自定义列表和自定义表单系列之一缘起 据说系列文 ...

  9. 手把手教你写web全栈入门项目—React+Koa+MongoDB(3w字教程,真的很详细,有代码)

    手把手教你写web全栈入门项目-React+Koa+MongoDB

最新文章

  1. 如何读取超大文本文件
  2. Office Web Apps安装部署(二)
  3. 复旦博士用130行代码搞定核酸统计,2分钟解决人工一小时工作量
  4. 问题:anaconda: command not found 解决方案
  5. 关闭tomcat报错Cannot allocate memory
  6. Updater Application Block for .net 2.0 发布了
  7. Spring @AutoWired实现原理
  8. 特性Attibute定义和使用
  9. ajax 详解(GET,POST方式传输以其封装)
  10. 去水印原理_图片去水印|视频去水印
  11. 挣脱“数据沼泽”,重获用云自由
  12. Google GMS包中的applist
  13. 每周小节-2 d3-zoom,pan,brush阅读心得 d3.js on angular读书笔记
  14. 竣达技术丨多台精密空调微信云监控方案
  15. RPC TAF(TARS) 框架 初学
  16. UVA 662 Fast Food(dp)
  17. 无人机设备+AI识别算法,为城市管理打造“智慧之眼”
  18. Python+Django+Mysql开发在线购物推荐网 协同过滤推荐算法在购物网站中的运用 个性化推荐算法开发 基于用户、物品的协同过滤推荐算法 机器学习、分布式大数据、人工智能开发
  19. 大数据系统架构包含内容涉及哪些?
  20. 计算机研究生博士课程设置,计算机科学与技术学科博士研究生培养方案.doc

热门文章

  1. 用SVGDeveloper制作svg地图
  2. JDK API 版本6、7、8、9汉化文档及部分英文文档CHM一起分享
  3. 浏览器协商缓存与强制缓存经典版
  4. LCR表和万用表有什么区别?
  5. 12306订票候补是个坑_抢票神器成GitHub热榜第一,支持候补抢票,Python跑起来 | 标星8400...
  6. 【笔记】移动端自动化:adb调试工具+appium+UIAutomatorViewer
  7. C语言 栈的基本操作 栈的实现
  8. 黑帽python第二版(Black Hat Python 2nd Edition)读书笔记 之 第一章 配置python环境
  9. autocad命令、快捷键
  10. 大众汽车:芯片供应仍是主要挑战,但计划提高汽车产量