From 9da9f3c783de2fd0a7eacf8906bada53b0349c52 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=95=8A=E4=B9=90-js?= <125586657@qq.com>
Date: Sat, 22 Mar 2025 09:53:32 +0000
Subject: [PATCH] =?UTF-8?q?update=2027.=20=E9=A1=B9=E7=9B=AE=E6=89=93?=
=?UTF-8?q?=E5=8C=85=E6=9E=84=E5=BB=BA/=E4=BB=A3=E7=A0=81/src/components/E?=
=?UTF-8?q?ditable/index.js.=20//=20=E5=AF=BC=E5=85=A5=20React=20=E5=92=8C?=
=?UTF-8?q?=E7=9B=B8=E5=85=B3=20hooks=EF=BC=8C=E4=BB=A5=E5=8F=8A=20Ant=20D?=
=?UTF-8?q?esign=20=E7=BB=84=E4=BB=B6=20import=20React,=20{=20useState,=20?=
=?UTF-8?q?useRef,=20useContext,=20useEffect=20}=20from=20'react';=20impor?=
=?UTF-8?q?t=20{=20Form,=20Input,=20Select,=20DatePicker=20}=20from=20'ant?=
=?UTF-8?q?d';=20const=20{=20Option=20}=20=3D=20Select;=20=20//=20?=
=?UTF-8?q?=E8=A7=A3=E6=9E=84=20Select=20=E7=9A=84=E5=AD=90=E7=BB=84?=
=?UTF-8?q?=E4=BB=B6=20Option=20import=20{=20mapData=20}=20from=20'utils/m?=
=?UTF-8?q?apData';=20=20//=20=E5=AF=BC=E5=85=A5=E9=A2=84=E8=AE=BE?=
=?UTF-8?q?=E7=9A=84=E6=98=A0=E5=B0=84=E6=95=B0=E6=8D=AE=EF=BC=88=E5=A6=82?=
=?UTF-8?q?=E9=80=89=E9=A1=B9=E5=88=97=E8=A1=A8=EF=BC=89=20import=20moment?=
=?UTF-8?q?=20from=20'moment';=20=20//=20=E6=97=B6=E9=97=B4=E5=A4=84?=
=?UTF-8?q?=E7=90=86=E5=BA=93?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
// 创建一个 React 上下文,用于在行和单元格之间传递表单实例
const EditableContext = React.createContext(null);
//- 可编辑表格行组件(包裹每一行)
export const EditableRow = ({ index, ...props }) => {
const [form] = Form.useForm(); // 创建表单实例
return (
// 包裹整个行的表单(不渲染实际
);
};
//- 可编辑单元格组件(包裹每个单元格)
export const EditableCell = ({
title, // 列标题(未直接使用)
editable, // 是否可编辑
children, // 默认内容(非编辑状态显示)
dataIndex, // 数据字段名(如 "name")
record, // 当前行数据对象
handleSave, // 保存回调函数
rules, // 表单验证规则
type, // 输入类型(inputNode/selectNode/dateNode)
...restProps // 其他透传给 的属性
}) => {
const [editing, setEditing] = useState(false); // 控制编辑状态
const inputRef = useRef(null); // 引用输入控件(用于聚焦)
const form = useContext(EditableContext); // 从行组件获取表单实例
// 当进入编辑状态时自动聚焦输入控件
useEffect(() => {
if (editing) {
inputRef.current && inputRef.current.focus();
}
}, [editing]);
//- 切换编辑状态并初始化表单值
const toggleEdit = () => {
setEditing(!editing);
// 设置表单初始值(处理时间字段为 moment 对象)
form.setFieldsValue({
[dataIndex]: record[dataIndex],
onboardingTime: moment(record.onboardingTime), // 转换时间字段
date: moment(record.date),
createTime: moment(record.createTime),
});
};
//- 保存前的验证和提交逻辑
const _sendBeforeCheck = async () => {
try {
// 验证当前字段
const editData = await form.validateFields([dataIndex]);
setEditing(!editing); // 退出编辑状态
// 值未变化时不触发保存
if (record[dataIndex] === editData[dataIndex]) return;
// 调用外部保存逻辑
handleSave({
_id: record._id, // 行唯一标识
updateVal: editData[dataIndex], // 新值
type: dataIndex // 字段名
});
} catch (error) {
setEditing(!editing); // 验证失败时退出编辑状态
}
};
//- 定义不同类型的编辑控件
const editNodeData = {
inputNode: ( // 文本输入框
),
selectNode: ( // 下拉选择器
),
dateNode: ( // 日期选择器
),
};
// 根据编辑状态渲染内容
let childNode = children; // 默认显示原始内容
if (editable) {
childNode = editing ? (
// 编辑状态:渲染表单控件
{editNodeData[type]} {/* 根据 type 选择控件类型 */}
) : (
// 非编辑状态:点击区域触发编辑
{children} {/* 显示原始值 */}
);
}
// 返回表格单元格,透传所有属性(如 className/style 等)
return | {childNode} | ;
};
Signed-off-by: 啊乐-js <125586657@qq.com>
---
.../src/components/Editable/index.js" | 250 +++++++++---------
1 file changed, 129 insertions(+), 121 deletions(-)
diff --git "a/27. \351\241\271\347\233\256\346\211\223\345\214\205\346\236\204\345\273\272/\344\273\243\347\240\201/src/components/Editable/index.js" "b/27. \351\241\271\347\233\256\346\211\223\345\214\205\346\236\204\345\273\272/\344\273\243\347\240\201/src/components/Editable/index.js"
index d7564a9..c73cae0 100644
--- "a/27. \351\241\271\347\233\256\346\211\223\345\214\205\346\236\204\345\273\272/\344\273\243\347\240\201/src/components/Editable/index.js"
+++ "b/27. \351\241\271\347\233\256\346\211\223\345\214\205\346\236\204\345\273\272/\344\273\243\347\240\201/src/components/Editable/index.js"
@@ -1,122 +1,130 @@
-import React, { useState, useRef, useContext, useEffect } from 'react';
-import { Form, Input, Select, DatePicker } from 'antd';
-const { Option } = Select;
-import { mapData } from 'utils/mapData';
-import moment from 'moment';
-
-const EditableContext = React.createContext(null);
-
-//- 可编辑的行
-export const EditableRow = ({ index, ...props }) => {
- const [form] = Form.useForm();
- return (
-
- );
-};
-
-//- 可编辑的单元格
-export const EditableCell = ({
- title,
- editable,
- children,
- dataIndex,
- record,
- handleSave,
- rules,
- type,
- ...restProps
-}) => {
- const [editing, setEditing] = useState(false);
- const inputRef = useRef(null);
- const form = useContext(EditableContext);
-
- useEffect(() => {
- if (editing) {
- inputRef.current && inputRef.current.focus();
- }
- }, [editing]);
-
- //- 单元格点击的时候进行内容的渲染
- const toggleEdit = () => {
- setEditing(!editing);
- form.setFieldsValue({
- [dataIndex]: record[dataIndex],
- onboardingTime: moment(record.onboardingTime), //- 指定的时间字段的渲染操作
- date: moment(record.date), //- 指定的时间字段的渲染操作
- createTime: moment(record.createTime), //- 指定的时间字段的渲染操作
- });
- };
-
- //- 修改之前的检测
- const _sendBeforeCheck = async () => {
- try {
- const editData = await form.validateFields([dataIndex]);
- setEditing(!editing);
- //- 当前修改后的值是否与之前的值相等
- if (record[dataIndex] === editData[dataIndex]) return;
- handleSave({
- _id: record._id,
- updateVal: editData[dataIndex],
- type: dataIndex,
- });
- } catch (error) {
- setEditing(!editing);
- }
- };
-
- const editNodeData = {
- inputNode: (
-
- ),
- selectNode: (
-
- ),
- dateNode: (
-
- ),
- };
-
- let childNode = children;
-
- if (editable) {
- childNode = editing ? (
-
- {editNodeData[type]}
-
- ) : (
-
- {children}
-
- );
- }
-
- return {childNode} | ;
-};
+// 导入 React 和相关 hooks,以及 Ant Design 组件
+import React, { useState, useRef, useContext, useEffect } from 'react';
+import { Form, Input, Select, DatePicker } from 'antd';
+const { Option } = Select; // 解构 Select 的子组件 Option
+import { mapData } from 'utils/mapData'; // 导入预设的映射数据(如选项列表)
+import moment from 'moment'; // 时间处理库
+// 创建一个 React 上下文,用于在行和单元格之间传递表单实例
+const EditableContext = React.createContext(null);
+
+//- 可编辑表格行组件(包裹每一行)
+export const EditableRow = ({ index, ...props }) => {
+ const [form] = Form.useForm(); // 创建表单实例
+ return (
+ // 包裹整个行的表单(不渲染实际
+ );
+};
+
+//- 可编辑单元格组件(包裹每个单元格)
+export const EditableCell = ({
+ title, // 列标题(未直接使用)
+ editable, // 是否可编辑
+ children, // 默认内容(非编辑状态显示)
+ dataIndex, // 数据字段名(如 "name")
+ record, // 当前行数据对象
+ handleSave, // 保存回调函数
+ rules, // 表单验证规则
+ type, // 输入类型(inputNode/selectNode/dateNode)
+ ...restProps // 其他透传给 的属性
+}) => {
+ const [editing, setEditing] = useState(false); // 控制编辑状态
+ const inputRef = useRef(null); // 引用输入控件(用于聚焦)
+ const form = useContext(EditableContext); // 从行组件获取表单实例
+
+ // 当进入编辑状态时自动聚焦输入控件
+ useEffect(() => {
+ if (editing) {
+ inputRef.current && inputRef.current.focus();
+ }
+ }, [editing]);
+
+ //- 切换编辑状态并初始化表单值
+ const toggleEdit = () => {
+ setEditing(!editing);
+ // 设置表单初始值(处理时间字段为 moment 对象)
+ form.setFieldsValue({
+ [dataIndex]: record[dataIndex],
+ onboardingTime: moment(record.onboardingTime), // 转换时间字段
+ date: moment(record.date),
+ createTime: moment(record.createTime),
+ });
+ };
+
+ //- 保存前的验证和提交逻辑
+ const _sendBeforeCheck = async () => {
+ try {
+ // 验证当前字段
+ const editData = await form.validateFields([dataIndex]);
+ setEditing(!editing); // 退出编辑状态
+ // 值未变化时不触发保存
+ if (record[dataIndex] === editData[dataIndex]) return;
+ // 调用外部保存逻辑
+ handleSave({
+ _id: record._id, // 行唯一标识
+ updateVal: editData[dataIndex], // 新值
+ type: dataIndex // 字段名
+ });
+ } catch (error) {
+ setEditing(!editing); // 验证失败时退出编辑状态
+ }
+ };
+
+ //- 定义不同类型的编辑控件
+ const editNodeData = {
+ inputNode: ( // 文本输入框
+
+ ),
+ selectNode: ( // 下拉选择器
+
+ ),
+ dateNode: ( // 日期选择器
+
+ ),
+ };
+
+ // 根据编辑状态渲染内容
+ let childNode = children; // 默认显示原始内容
+
+ if (editable) {
+ childNode = editing ? (
+ // 编辑状态:渲染表单控件
+
+ {editNodeData[type]} {/* 根据 type 选择控件类型 */}
+
+ ) : (
+ // 非编辑状态:点击区域触发编辑
+
+ {children} {/* 显示原始值 */}
+
+ );
+ }
+
+ // 返回表格单元格,透传所有属性(如 className/style 等)
+ return | {childNode} | ;
+};
\ No newline at end of file
--
Gitee