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 d7564a97767eeb7b901faead8c879832678ea38c..c73cae013c851dc6ef8891efc3c55870e7ad7656 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