当前位置: 首页 > news >正文

React antd的datePicker自定义,封装成组件

一、antd的datePicker自定义
需求:用户需要为日期选择器的每个日期单元格添加一个Tooltip,当鼠标悬停时显示日期、可兑换流量余额和本公会可兑流量。这些数据需要从接口获取。我需要结合之前的代码,确保Tooltip正确显示,并且数据来自接口。

主要汉化点:

  1. 整个日期选择器面板中文化
  2. 星期显示为中文(周一 到 周日)
  3. 月份显示为中文格式
  4. 操作按钮汉化("确定"、"现在" 等)
  5. 日期格式统一使用中文年月日
  6. 加载提示中文化
  7. Tooltip内容中文化

效果包含:

  • 月份显示为 "2024年5月"
  • 星期列显示为 "一、二、三、四、五、六、日"
  • 今天按钮显示为 "今天"
  • 确定按钮显示为 "确定"
  • 十年范围显示为 "2020-2029"
  • 时间列显示为 "时","分","秒"
  • index.tsx文件
import React, { useState, useEffect } from 'react';
import { DatePicker, Tooltip, Spin, ConfigProvider } from 'antd';
import dayjs, { Dayjs } from 'dayjs';
import isSameOrAfter from 'dayjs/plugin/isSameOrAfter';
import isSameOrBefore from 'dayjs/plugin/isSameOrBefore';
import './custom-datepicker.css';
import 'dayjs/locale/zh-cn';
import zhCN from 'antd/locale/zh_CN';
dayjs.extend(isSameOrAfter);
dayjs.extend(isSameOrBefore);
dayjs.locale('zh-cn'); // 设置dayjs为中文interface TrafficData {date: string;personal: string;guild: string;
}const App: React.FC = () => {const [selectedDate, setSelectedDate] = useState<Dayjs | null>(null);const [trafficData, setTrafficData] = useState<Record<string, TrafficData>>({});const [loading, setLoading] = useState(true);const today = dayjs().startOf('day');const sevenDaysLater = today.add(6, 'day');useEffect(() => {const mockApi = async () => {const data: Record<string, TrafficData> = {};Array.from({ length: 7 }).forEach((_, i) => {const date = today.add(i, 'day').format('YYYY-MM-DD');data[date] = {date,personal: `${[0, 20, 30, 40, 80, 100, 50][i]}%`,guild: `${Math.floor(Math.random() * 100000).toLocaleString()}`,};});await new Promise(resolve => setTimeout(resolve, 500));setTrafficData(data);setLoading(false);};mockApi();}, []);const disabledDate = (current: Dayjs) => current.isBefore(today, 'day') || current.isAfter(sevenDaysLater, 'day');if (loading) return <Spin tip="数据加载中..." />;return (<ConfigProvider locale={zhCN}> {/* 设置Ant Design为中文 */}<DatePickervalue={selectedDate}disabledDate={disabledDate}onChange={setSelectedDate}dropdownClassName="custom-picker-dropdown"dateRender={current => {const dateStr = current.format('YYYY-MM-DD');const data = trafficData[dateStr];const isInRange = current.isSameOrAfter(today) && current.isSameOrBefore(sevenDaysLater);const isSelected = selectedDate?.isSame(current, 'day');return (<div className="custom-cell-wrapper"><div className="native-cell-content">{current.date()}</div><Tooltiptitle={data ?`${dayjs(dateStr).format('YYYY年M月D日')}\n可兑流量余额: ${data.personal}\n本公会可兑流量: ${data.guild}`: '无可用数据'}overlayStyle={{whiteSpace: 'pre-line',pointerEvents: 'none',}}placement="bottom"mouseEnterDelay={0}mouseLeaveDelay={0.1}trigger={['hover']}getPopupContainer={trigger => trigger.parentElement!}><div className={`custom-cell ${isInRange ? 'recent-date' : ''}`}><div className={`date-number ${isSelected ? 'selected' : ''}`}>{current.date()}</div>{data && (<div className={`availability ${data.personal === '0%' ? 'empty' : ''}`}>余{data.personal}</div>)}</div></Tooltip></div>);}}/></ConfigProvider>);
};export default App;
  • custom-datepicker.css文件
/* custom-datepicker.css */
.custom-picker-dropdown {z-index: 1001;
}.custom-cell-wrapper {position: relative;height: 100%;width: 100%;
}.native-cell-content {visibility: hidden;
}.custom-cell {position: absolute;top: 0;left: 0;width: 100%;height: 100%;display: flex;flex-direction: column;align-items: center;justify-content: center;cursor: pointer;z-index: 2;padding: 3px 0;
}.date-number {width: 24px;height: 24px;line-height: 24px;text-align: center;color: #000;transition: all 0.2s;border-radius: 50%;
}.date-number.selected {background: #1890ff;color: white !important;
}.recent-date:hover .date-number:not(.selected) {color: #1890ff;
}.availability {font-size: 10px;line-height: 14px;color: #1890ff;margin-top: 2px;
}.availability.empty {color: #ff4d4f !important;
}.ant-picker-cell-inner {padding: 0 !important;height: 100% !important;
}.ant-picker-cell:hover .ant-picker-cell-inner {background: transparent !important;
}/* 添加中文面板样式调整 */
.ant-picker-date-panel {font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
}.ant-picker-header-view button {font-weight: 500;
}.ant-picker-cell-inner::before {border-radius: 50% !important;
}

二、封装成组件

  • DateSelector.tsx文件
// DateSelector.tsx
import React from 'react';
import {DatePicker, Tooltip, Spin, ConfigProvider} from 'antd';
import dayjs, { Dayjs } from 'dayjs';
import isSameOrAfter from 'dayjs/plugin/isSameOrAfter';
import isSameOrBefore from 'dayjs/plugin/isSameOrBefore';
import 'dayjs/locale/zh-cn';
import './custom-datepicker.css';
import zhCN from 'antd/locale/zh_CN';dayjs.extend(isSameOrAfter);
dayjs.extend(isSameOrBefore);export interface TrafficData {personal: string;guild: string;
}interface DateSelectorProps {value?: Dayjs | null;trafficData: Record<string, TrafficData>;onChange?: (date: Dayjs | null) => void;loading?: boolean;
}const DateSelector: React.FC<DateSelectorProps> = ({value,trafficData,onChange,loading = false,
}) => {const today = dayjs().startOf('day');const sevenDaysLater = today.add(6, 'day');const disabledDate = (current: Dayjs) => current.isBefore(today, 'day') || current.isAfter(sevenDaysLater, 'day');const handleChange = (date: Dayjs | null) => {onChange?.(date);};if (loading) {return <Spin tip="数据加载中..." style={{ padding: '8px 0' }} />;}return (<ConfigProvider locale={zhCN}> {/* 设置Ant Design为中文 */}<DatePickervalue={value}disabledDate={disabledDate}onChange={handleChange}dropdownClassName="custom-picker-dropdown"dateRender={current => {const dateStr = current.format('YYYY-MM-DD');const data = trafficData[dateStr];const isInRange = current.isSameOrAfter(today) && current.isSameOrBefore(sevenDaysLater);const isSelected = value?.isSame(current, 'day');return (<div className="custom-cell-wrapper"><div className="native-cell-content">{current.date()}</div><Tooltiptitle={data ?`${dayjs(dateStr).format('YYYY年M月D日')}\n可兑流量余额: ${data.personal}\n本公会可兑流量: ${data.guild}`: '无可用数据'}overlayStyle={{whiteSpace: 'pre-line',pointerEvents: 'none',}}placement="bottom"mouseEnterDelay={0}mouseLeaveDelay={0.1}><div className={`custom-cell ${isInRange ? 'recent-date' : ''}`}><div className={`date-number ${isSelected ? 'selected' : ''}`}>{current.date()}</div>{data && (<div className={`availability ${data.personal === '0%' ? 'empty' : ''}`}>余{data.personal}</div>)}</div></Tooltip></div>);}}/></ConfigProvider>);
};export default DateSelector;
  • custom-datepicker.css
/* custom-datepicker.css */
.custom-picker-dropdown {z-index: 1001;
}.custom-cell-wrapper {position: relative;height: 100%;width: 100%;
}.native-cell-content {visibility: hidden;
}.custom-cell {position: absolute;top: 0;left: 0;width: 100%;height: 100%;display: flex;flex-direction: column;align-items: center;justify-content: center;cursor: pointer;z-index: 2;padding: 3px 0;
}.date-number {width: 24px;height: 24px;line-height: 24px;text-align: center;color: #000;transition: all 0.2s;border-radius: 50%;
}.date-number.selected {background: #1890ff;color: white !important;
}.recent-date:hover .date-number:not(.selected) {color: #1890ff;
}.availability {font-size: 10px;line-height: 14px;color: #1890ff;margin-top: 2px;
}.availability.empty {color: #ff4d4f !important;
}.ant-picker-cell-inner {padding: 0 !important;height: 100% !important;
}.ant-picker-cell:hover .ant-picker-cell-inner {background: transparent !important;
}/* 添加中文面板样式调整 */
.ant-picker-date-panel {font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
}.ant-picker-header-view button {font-weight: 500;
}.ant-picker-cell-inner::before {border-radius: 50% !important;
}
  • index.tsx文件
// 使用示例 ParentComponent.tsx
import React, { useState, useEffect } from 'react';
import DateSelector, { TrafficData } from './DateSelector';
import dayjs from 'dayjs';const ParentComponent: React.FC = () => {const [selectedDate, setSelectedDate] = useState<dayjs.Dayjs | null>(null);const [trafficData, setTrafficData] = useState<Record<string, TrafficData>>({});const [loading, setLoading] = useState(true);const today = dayjs().startOf('day');// useEffect(() => {//   // 模拟API调用//   const mockFetchData = async () => {//     const mockData = {//       [dayjs().format('YYYY-MM-DD')]: {//         personal: '80%',//         guild: '100,000',//       },//       [dayjs().add(1, 'day')//         .format('YYYY-MM-DD')]: {//         personal: '50%',//         guild: '75,000',//       },//     };////     await new Promise(resolve => setTimeout(resolve, 800));//     setTrafficData(mockData);//     setLoading(false);//   };////   mockFetchData();// }, []);useEffect(() => {const mockApi = async () => {const data: Record<string, TrafficData> = {};Array.from({ length: 7 }).forEach((_, i) => {const date = today.add(i, 'day').format('YYYY-MM-DD');data[date] = {personal: `${[0, 20, 30, 40, 80, 100, 50][i]}%`,guild: `${Math.floor(Math.random() * 100000).toLocaleString()}`,};});await new Promise(resolve => setTimeout(resolve, 500));setTrafficData(data);setLoading(false);};mockApi();}, []);return (<div style={{ padding: 24 }}><h2>日期选择器示例</h2><div style={{ marginBottom: 16 }}>当前选择:{selectedDate?.format('YYYY年M月D日') || '未选择'}</div><DateSelectorvalue={selectedDate}trafficData={trafficData}onChange={setSelectedDate}loading={loading}/></div>);
};export default ParentComponent;

三、生效时间选择完日期后,还需填入具体时间(或提供一个时间选择器),精确到分,默认为00:00;如选择的日期为今天,则填写的时间不能早于当前时间

// index.tsx
import React, { useState, useEffect } from 'react';
import { Row, Col, TimePicker, Spin, ConfigProvider } from 'antd';
import DateSelector, { TrafficData } from './DateSelector';
import dayjs, { Dayjs } from 'dayjs';
import zhCN from 'antd/locale/zh_CN';declare module 'dayjs' {interface Dayjs {isToday(): boolean;}
}dayjs.extend((o, c) => {c.prototype.isToday = function () {return this.isSame(dayjs(), 'day');}
});const DateTimePicker: React.FC = () => {const [selectedDate, setSelectedDate] = useState<Dayjs | null>(null);const [selectedTime, setSelectedTime] = useState<Dayjs>(dayjs().startOf('minute'));const [trafficData, setTrafficData] = useState<Record<string, TrafficData>>({});const [loading, setLoading] = useState(true);const today = dayjs().startOf('day');const disabledTime = (current: Dayjs | null) => {if (!current || !selectedDate?.isToday()) {return { disabledHours: () => [], disabledMinutes: () => [] };}const now = dayjs();return {disabledHours: () => {const currentHour = now.hour();return Array.from({ length: currentHour }, (_, i) => i);},disabledMinutes: (selectedHour: number) => {if (selectedHour < now.hour()) return [];return Array.from({ length: now.minute() }, (_, i) => i);},};};const handleDateChange = (date: Dayjs | null) => {setSelectedDate(date);setSelectedTime(date?.isToday() ? dayjs().startOf('minute') : dayjs().startOf('day'));};// useEffect(() => {//   // 模拟API请求//   const mockData = {//     [dayjs().format('YYYY-MM-DD')]: { personal: '80%', guild: '100,000' },//     [dayjs().add(1, 'day')//       .format('YYYY-MM-DD')]: { personal: '50%', guild: '75,000' },//   };////   setTimeout(() => {//     setTrafficData(mockData);//     setLoading(false);//   }, 800);// }, []);useEffect(() => {const mockApi = async () => {const data: Record<string, TrafficData> = {};Array.from({ length: 7 }).forEach((_, i) => {const date = today.add(i, 'day').format('YYYY-MM-DD');data[date] = {personal: `${[0, 20, 30, 40, 80, 100, 50][i]}%`,guild: `${Math.floor(Math.random() * 100000).toLocaleString()}`,};});await new Promise(resolve => setTimeout(resolve, 500));setTrafficData(data);setLoading(false);};mockApi();}, []);return (<ConfigProvider locale={zhCN}> {/* 设置Ant Design为中文 */}<div style={{ padding: 24, maxWidth: 380, margin: '0 auto' }}><h2 style={{ marginBottom: 24 }}>预约时间选择</h2><Row gutter={24} align="middle"><Col span={12}>{/*<div style={{ marginBottom: 8 }}>选择日期</div>*/}<DateSelectorvalue={selectedDate}trafficData={trafficData}onChange={handleDateChange}loading={loading}/></Col><Col span={12}>{/*<div style={{ marginBottom: 8 }}>选择时间</div>*/}<TimePickervalue={selectedTime}format="HH:mm"minuteStep={1}disabledTime={disabledTime}onChange={time => setSelectedTime(time || dayjs().startOf('minute'))}placeholder="请选择时间"disabled={!selectedDate}allowClear={false}showNow={false}style={{ width: '100%' }}/></Col></Row><div style={{ marginTop: 24, padding: 16, background: '#f5f5f5', borderRadius: 4 }}>已选择时间: {selectedDate ?`${selectedDate.format('YYYY年MM月DD日')} ${selectedTime.format('HH:mm')}`: '请先选择日期'}</div></div></ConfigProvider>);
};export default DateTimePicker;

相关文章:

React antd的datePicker自定义,封装成组件

一、antd的datePicker自定义 需求&#xff1a;用户需要为日期选择器的每个日期单元格添加一个Tooltip&#xff0c;当鼠标悬停时显示日期、可兑换流量余额和本公会可兑流量。这些数据需要从接口获取。我需要结合之前的代码&#xff0c;确保Tooltip正确显示&#xff0c;并且数据…...

学生管理前端

文章目录 首页student.html查询功能 首页 SpringBoot前端html页面放在static文件夹下&#xff1a;/src/main/resources/static 默认首页为index.html&#xff0c;我们可以用两个超链接或者两个button跳转到对应的页面。这里只是单纯的跳转页面&#xff0c;不需要提交表单等其…...

深入理解并实现自定义 unordered_map 和 unordered_set

亲爱的读者朋友们&#x1f603;&#xff0c;此文开启知识盛宴与思想碰撞&#x1f389;。 快来参与讨论&#x1f4ac;&#xff0c;点赞&#x1f44d;、收藏⭐、分享&#x1f4e4;&#xff0c;共创活力社区。 在 C 的标准模板库&#xff08;STL&#xff09;中&#xff0c;unorder…...

顶顶通呼叫中心中间件(mod_cti基于FreeSWITCH)-大模型电话机器人

语音流直接对接Realtime API 多模态大模型 直接把音频流输出给大模型&#xff0c;大模型返回音频流。 顶顶通CTI对Realtime API 的支持 提供了以下2个APP可对接任意 •cti_audio_stream 通过TCP推流和播放流&#xff0c;适合用于人机对话场景。 •cti_unicast_start 通过旁…...

kinova机械臂绿色灯一闪一闪及刷机方法

一、背景 实验室有两个kinova mico机械臂&#xff0c;但经常出现操纵杆上的绿色灯一闪一闪的&#xff0c;导致无法使用操纵杆或ROS进行控制&#xff0c;下面给出官方的教程以及所需要的FS 0CPP 0008_6.2.5_mico_6dof.hex文件。 重要的东西写在前面&#xff1a; a、如果出现操…...

第16天:C++多线程完全指南 - 从基础到现代并发编程

第16天&#xff1a;C多线程完全指南 - 从基础到现代并发编程 一、多线程基础概念 1. 线程创建与管理&#xff08;C11&#xff09; #include <iostream> #include <thread>void hello() {std::cout << "Hello from thread " << std::this_…...

中科大计算机网络原理 1.5 Internt结构和ISP

一、互联网的层次化架构 ‌覆盖范围分层‌ ‌主干网&#xff08;Tier-1级&#xff09;‌ 国家级或行业级核心网络&#xff0c;承担跨区域数据传输和全球互联功能。例如中国的四大主干网&#xff08;ChinaNET、CERNET等&#xff09;以及跨国运营商&#xff08;如AT&T、Deuts…...

Windows安装sql server2017

看了下官网的文档&#xff0c;似乎只有ubuntu18.04可以安装&#xff0c;其他debian系的都不行&#xff0c;还有通过docker的方式安装的。 双击进入下载的ISO&#xff0c;点击执行可执行文件&#xff0c;并选择“是” 不要勾选 警告而已&#xff0c;不必理会 至少勾选这两…...

计算机网络之传输层(tcp协议)

一、TCP协议的特点 面向连接&#xff1a;TCP使用面向连接的通信模式&#xff0c;通信双方需要先建立连接&#xff0c;然后才能进行数据的传输。连接建立过程采用三次握手的方式。 可靠性&#xff1a;TCP提供可靠的数据传输服务&#xff0c;确保数据的完整性、有序性和正确性。…...

从零到一:如何用阿里云百炼和火山引擎搭建专属 AI 助手(DeepSeek)?

本文首发&#xff1a;从零到一&#xff1a;如何用阿里云百炼和火山引擎搭建专属 AI 助手&#xff08;DeepSeek&#xff09;&#xff1f; 阿里云百炼和火山引擎都推出了免费的 DeepSeek 模型体验额度&#xff0c;今天我和大家一起搭建一个本地的专属 AI 助手。  阿里云百炼为 …...

Open3D解决SceneWidget加入布局中消失的问题

Open3D解决SceneWidget加入布局中消失的问题 Open3D解决SceneWidget加入布局中消失的问题1. 问题2. 问题代码3. 解决 Open3D解决SceneWidget加入布局中消失的问题 1. 问题 把SceneWidget加到布局管理其中图形可以展示出来&#xff0c;但是鼠标点击就消失了。 stackoverflow上已…...

计算机毕业设计Python+DeepSeek-R1大模型游戏推荐系统 Steam游戏推荐系统 游戏可视化 游戏数据分析(源码+文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…...

Linux笔记---缓冲区

1. 什么是缓冲区 在计算机系统中&#xff0c;缓冲区&#xff08;Buffer&#xff09; 是一种临时存储数据的区域&#xff0c;主要用于协调不同速度或不同时序的组件之间的数据传输&#xff0c;以提高效率并减少资源冲突。它是系统设计中的重要概念&#xff0c;尤其在I/O操作、网…...

如何流畅访问github

1.传输数据原理 本地计算机通过本地网接入运营骨干网&#xff0c;经过DNS域名解析&#xff0c;将输入的字符解析为要连接的真实IP地址&#xff0c;服务器返还一个数据包(github)给计算机 2.原因 DNS域名污染-DNS解析出现问题&#xff0c;导致访问一个不存在的服务器 3.解决…...

java基础+面向对象

Java基础语法 CMD命令 cls 清屏 cd 目录进入文件 cd… 退回 dir 查看当前目录所有文件 E&#xff1a;进入E盘 exit 退出 环境变量就是不用去专门的盘符去找&#xff0c;直接去环境变量里找到文件 语言优势 编译型语言c&#xff1a; 整体翻译 解释型语言python&#x…...

Linux 检测内存泄漏方法总结

文章目录 strace检测asan内存检测linux下gperf工具&#xff08;tcmalloc&#xff09;检查C/C代码内存泄露问题参考 strace检测 &#xff08;1&#xff09;启动程序 &#xff08;2&#xff09; strace -f -p <PID> -tt -e brk,mmap,mmap2,munmapbrk 变大 → 说明堆增长…...

本地部署deepseek大模型后使用c# winform调用(可离线)

介于最近deepseek的大火&#xff0c;我就在想能不能用winform也玩一玩本地部署&#xff0c;于是经过查阅资料&#xff0c;然后了解到ollama部署deepseek,最后用ollama sharp NUGet包来实现winform调用ollama 部署的deepseek。 本项目使用Vs2022和.net 8.0开发&#xff0c;ollam…...

Python----数据分析(Numpy:安装,数组创建,切片和索引,数组的属性,数据类型,数组形状,数组的运算,基本函数)

一、 Numpy库简介 1.1、概念 NumPy(Numerical Python)是一个开源的Python科学计算库&#xff0c;旨在为Python提供 高性能的多维数组对象和一系列工具。NumPy数组是Python数据分析的基础&#xff0c;许多 其他的数据处理库&#xff08;如Pandas、SciPy&#xff09;都依赖于Num…...

Leetcode-最大矩形(单调栈)

一、题目描述 给定一个仅包含 0 和 1 、大小为 rows x cols 的二维二进制矩阵&#xff0c;找出只包含 1 的最大矩形&#xff0c;并返回其面积。 输入&#xff1a;matrix [["1","0","1","0","0"],["1","0&…...

域内委派维权

为某个服务账户配置 krbtgt 用户的非约束性委派或基于资源的约束性委派。这里我的 krbtgt 的基于资源约束性委派我利用不了&#xff0c;所以使用的是域控的机器账户 dc01$ 进行维权。 抓取所有 hash。 mimikatz.exe "privilege::debug" "lsadump::dcsync /doma…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

大模型多显卡多服务器并行计算方法与实践指南

一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

C++.OpenGL (14/64)多光源(Multiple Lights)

多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...

保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek

文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama&#xff08;有网络的电脑&#xff09;2.2.3 安装Ollama&#xff08;无网络的电脑&#xff09;2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...

基于 TAPD 进行项目管理

起因 自己写了个小工具&#xff0c;仓库用的Github。之前在用markdown进行需求管理&#xff0c;现在随着功能的增加&#xff0c;感觉有点难以管理了&#xff0c;所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD&#xff0c;需要提供一个企业名新建一个项目&#…...

GruntJS-前端自动化任务运行器从入门到实战

Grunt 完全指南&#xff1a;从入门到实战 一、Grunt 是什么&#xff1f; Grunt是一个基于 Node.js 的前端自动化任务运行器&#xff0c;主要用于自动化执行项目开发中重复性高的任务&#xff0c;例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...

elementUI点击浏览table所选行数据查看文档

项目场景&#xff1a; table按照要求特定的数据变成按钮可以点击 解决方案&#xff1a; <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...

永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器

一、原理介绍 传统滑模观测器采用如下结构&#xff1a; 传统SMO中LPF会带来相位延迟和幅值衰减&#xff0c;并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF)&#xff0c;可以去除高次谐波&#xff0c;并且不用相位补偿就可以获得一个误差较小的转子位…...

Modbus RTU与Modbus TCP详解指南

目录 1. Modbus协议基础 1.1 什么是Modbus? 1.2 Modbus协议历史 1.3 Modbus协议族 1.4 Modbus通信模型 🎭 主从架构 🔄 请求响应模式 2. Modbus RTU详解 2.1 RTU是什么? 2.2 RTU物理层 🔌 连接方式 ⚡ 通信参数 2.3 RTU数据帧格式 📦 帧结构详解 🔍…...

Linux 下 DMA 内存映射浅析

序 系统 I/O 设备驱动程序通常调用其特定子系统的接口为 DMA 分配内存&#xff0c;但最终会调到 DMA 子系统的dma_alloc_coherent()/dma_alloc_attrs() 等接口。 关于 dma_alloc_coherent 接口详细的代码讲解、调用流程&#xff0c;可以参考这篇文章&#xff0c;我觉得写的非常…...