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

CR后的反思、编辑表格实现

最近一直在开发需求很久没有写博客了,正好组里的大佬们帮忙CR了,对自己进行了一些反思

首先很严肃的一点是我之前一直靠着Vibe Coding提高生产效率,但是通过CR发现了不少问题,虽然前期开发可能很速,但是可能一直会埋坑,会导致后面重构的过程花费时间更多,原因是因为我目前有些方面理解不到位导致了对于AI的CR没有很成功,所以目前我在尝试完全手写,虽然效率低了但是还是学到了不少东西

其次是对于数据管理的理解,之前经常还想着开一些状态变量去管理,但是这样的风险高,所以能合理对表单等数据进行封装,实现数据的点对点更新和管理是很重要的

还有就是一些细节,例如用dayjs和抽象组件进行格式化、用tailwind而不写很多css、通过阻塞渲染实现卸载防止数据遗留

也学习了很多调试网络、组件、元素等等的细节,后面整理一下分享

就贴一段关于编辑表格的代码,大家一起交流指正

这段代码实现了单行数据的单独POST或者是一键POST所有新增行,可以通过按新增按钮增加新增行

通过让form托管数据实现校验后提交

import {BeArray,BeForm,BeFormItem,BeInput,BeMButton,BeSpace,BeSubmit,BeTable,bv,createColumnHelper,PaginationState,useArrayWatch,useFieldArray,useForm,
} from '@finfe/beetle-ui';
import { Modal } from '@ss/mtd-react3';
import {DocConfigRecord,deleteDocConfig,getDocConfigList,saveDocConfig,useField,
} from '@tmc/business';
import { useAsyncEffect, useSetState } from 'ahooks';
import React, { useEffect, useState } from 'react';interface DocConfigModalProps {visible: boolean;onClose: () => void;onSuccess?: () => void;
}interface FormItemValues {id?: number;country: string;city: string;workPlace: string;
}const columnHelper = createColumnHelper<FormItemValues>();const DocConfigModal = ({visible,onClose,onSuccess,
}: DocConfigModalProps) => {// 总数据量const [totalCount, setTotalCount] = React.useState(0);// 用于区分是否为新增数据,核心是以序号这个绝对索引为主const [isNew, setIsNew] = useState<Set<number>>(new Set());const form = useForm<{ items: FormItemValues[] }>({onSubmit: (values) => handleAllSubmit(values),// 一键提交表单所有数据});const formValues = form.watch();const arrayControl = useFieldArray({name: 'items',control: form.control,});const [pagination, setPagination] = React.useState<PaginationState>({pageIndex: 0, // 注意:react-table 默认从0开始pageSize: 5,});const handlePaginationChange = (updater: PaginationState | ((old: PaginationState) => PaginationState)) => {if (isNew.size) {Modal.warning({title: '注意',message: '还有未保存的数据,是否继续切页',onOk: () => {setIsNew(new Set());setPagination(updater);// 更新分页器后观察者会自动更新表单},});} else {setPagination(updater);}};useEffect(() => {if (visible) {// 关闭页面再次打开重置分页,并且下面会监听其刷新数据setPagination({pageIndex: 0,pageSize: 5,});}}, [visible]);const initList = async () => {// 进入时的初始化数据const res = await getDocConfigList({pageNo: pagination.pageIndex + 1, // 后端从1开始,前端从0开始pageSize: pagination.pageSize,});if ((res as any)?.status === 0) {const data = (res as any)?.data || {};// 保存总数据量setTotalCount(data.totalCount || 0);console.log(data.result);// 使用 reset 完全重置表单,而不是 setValues,否则 new 不会被删除form.reset({ items: data.result || [] });}};// 当分页器配置改变时重新拿数据useAsyncEffect(async () => {if (visible) {await initList();}}, [pagination, visible]);const handleClose = () => {if (isNew.size) {Modal.warning({title: '注意',message: '还有未确认数据,是否继续退出?',onOk: onClose,});} else {onClose();// 关闭时清空新增记录setIsNew(new Set());}};const freshFormAfterDelete = (index: number) => {arrayControl.remove(index);// 更新 isNew Set,移除被删除的索引,并更新后面的索引const newIsNewSet = new Set<number>();isNew.forEach((idx) => {if (idx < index) {newIsNewSet.add(idx);} else if (idx > index) {newIsNewSet.add(idx - 1);}});setIsNew(newIsNewSet);return;};const handleDelete = async (index: number) => {const items = form.getValues('items');const currentItem = items[index];// 如果是新增的数据(没有 id),只需要更新表单if (!currentItem?.id || isNew.has(index)) {freshFormAfterDelete(index);}// 如果是服务器端已存在的数据,需要调用删除接口Modal.confirm({title: '请确认',message:'提示:删除后会影响员工交单流程,请务必核实后再进行删除,点击"确定"可进行删除。',onOk: async () => {try {const res = await deleteDocConfig({ id: currentItem.id! });if ((res as any)?.status === 0) {Modal.success({title: '成功',message: '删除成功',});freshFormAfterDelete(index);} else {Modal.error({title: '失败',message: (res as any)?.msg || '删除失败',});}} catch (error: any) {Modal.error({title: '失败',message: error?.message || '删除失败',});}},});};const handleSingleSubmit = async (index: number) => {// 校验当前行的所有字段const isValid = await form.trigger(`items.${index}` as any);if (!isValid) {// 校验失败,不执行提交return;}try {const res = await saveDocConfig([formValues.items[index]]);// 后端接收的是一个数组if ((res as any)?.status === 0) {Modal.success({title: '成功',message: '保存成功',});isNew.delete(index);onSuccess?.();} else {Modal.error({title: '失败',message: (res as any)?.msg || '保存失败',});}// 这里的catch可以在例如重复错误的时候进行提示} catch (error: any) {Modal.error({title: '失败',message: error?.message || '保存失败',});}};const handleAllSubmit = async (values: { items: FormItemValues[] }) => {// 只提交新增的数据(没有 id 的数据)const newItems = values.items.filter((item, index) => !item.id || isNew.has(index));// 如果没有新增数据,直接关闭if (newItems.length === 0) {Modal.success({title: '成功',message: '没有需要保存的新增数据',});onSuccess?.();return;}try {const res = await saveDocConfig(newItems);if ((res as any)?.status === 0) {Modal.success({title: '成功',message: '保存成功',});onSuccess?.();setIsNew(new Set());} else {Modal.error({title: '失败',message: (res as any)?.msg || '保存失败',});}// 这里的catch可以在重复的时候进行提示} catch (error: any) {Modal.error({title: '失败',message: error?.message || '保存失败',});}};const column = [columnHelper.display({id: 'index',header: '序号',cell: ({ row }) => {return row.index + 1;},}),columnHelper.accessor('country', {id: 'country',header: '交单国家',size: 150,cell(row) {return (<BeFormItembrules={bv.required('请输入二字国家代码,如CN').custom((value: string) => {if (!value) return undefined;const upperValue = value.toUpperCase();if (!/^[A-Z]{2}$/.test(upperValue)) {return '请输入二字国家代码,如CN、US等';}return undefined;})}fieldName="country"pattern={!isNew.has(row.row.index) ? 'readPretty' : undefined}required><BeInputmaxLength={2}onInput={(e: any) => {e.target.value = e.target.value.toUpperCase();}}// readOnly/></BeFormItem>);},}),columnHelper.accessor('city', {id: 'city',header: '交单城市',size: 150,cell(row) {return (<BeFormItembrules={bv.required('请输入交单城市')}fieldName="city"pattern={!isNew.has(row.row.index) ? 'readPretty' : undefined}required><BeInput /></BeFormItem>);},}),columnHelper.accessor('workPlace', {id: 'workPlace',header: '交单职场',size: 150,cell(row) {return (<BeFormItembrules={bv.required('请输入交单职场')}fieldName="workPlace"pattern={!isNew.has(row.row.index) ? 'readPretty' : undefined}required><BeInput /></BeFormItem>);},}),columnHelper.display({id: 'actions',header: '操作',cell({ row }) {const rowValues = useArrayWatch({ name: '.' });return (<BeSpace>{isNew.has(row.index) ? (<spanonClick={() => handleSingleSubmit(row.index)} // () => form.submit()}style={{color: '#795CFF',cursor: 'pointer',}}>确认</span>) : (<spanonClick={() => handleDelete(row.index)}style={{color: '#ff4d4f',cursor: 'pointer',}}>删除</span>)}</BeSpace>);},}),];return (<ModalonClose={handleClose}open={visible}style={{ width: 800 }}title="配置交单城市&职场"><Modal.Body><BeForm form={form}><BeForm.Grid><BeSpace direction="vertical" style={{ width: '100%' }}><BeArray.Root control={arrayControl}><BeArray.Tablecolumns={column}enablePagination="manual"onPaginationChange={handlePaginationChange}rowCount={totalCount}state={{pagination,}}/></BeArray.Root><divstyle={{display: 'flex',justifyContent: 'space-between',alignItems: 'center',width: '100%',}}><BeMButtononClick={() => {const items = form.getValues('items');const newIndex = items.length;arrayControl.append({country: '',city: '',workPlace: '',});// 标记新增的行setIsNew((prev) => new Set(prev).add(newIndex));}}type="primary">新增</BeMButton><BeMButton onClick={() => form.submit()} type="primary">一键确认新增</BeMButton></div></BeSpace></BeForm.Grid></BeForm></Modal.Body></Modal>);
};export default DocConfigModal;

http://www.dtcms.com/a/512093.html

相关文章:

  • MyBatis-Plus黑马
  • 网站建设需要几个部门网站首页布局设计
  • C语言基础入门--指针
  • 計組-中斷與子程序調用的區別
  • 做牛津布面料在哪个网站找客户八大员继续教育入口
  • SD-WAN是什么?与MPLS,MSTP,IPSEC,SSL 有什么区别?
  • 【操作系统】408操作系统核心考点精讲:宏内核、微内核与外核架构全解析​
  • EXCEL文本数字如何批量转换为数字
  • Linux 文件权限深度解析:从原理到实战管理
  • SpringMVC 数据校验和BindingResult以及自定义校验注解
  • [明道云专栏·里程碑] 从第一篇到第一百篇:这是一场属于“低代码实战者”的长跑
  • Ubuntu 安装 Harbor
  • 网站屏蔽ip地址河南网站备案系统短信
  • 中科院网站做的好的院所双鸭山网站建设公司
  • Linux配置Samba文件共享并访问Windows文件
  • Cursor配置markdown转Word的MCP工具教程
  • 常见springboot相关注解
  • ◆comfyUI教程◆第2章13节 XL模型专用工作流与refiner精炼
  • PostIn V1.3.1版本发布,新增在线更新程序命令,新增请求体json支持引用变量
  • asp网站作业下载二级建造师报名时间2022年官网
  • 信息平台网站建设微信商城网站方案
  • OpenCV计算机视觉库
  • 区块链的效率引擎:梅克尔树原理解析与应用
  • TF-A CMake构建系统
  • PowerShell下载和安装图解(附安装包,适合新手)
  • 分析网易严选网站开发wordpress类别图标
  • 元服务上架自检
  • 8款企业微信SCRM工具功能对比分析
  • 个人网站建设小江网站建设做网站需要多少钱
  • 蚂蚁集团开源的万亿参数模型Ling-1T和Ring-1T-preview