❤ React体系24-字典值部分(一)搭建(源码已开放)

❤ React体系24-字典值部分(一)搭建

使用场景

使用背景 在项目之中我们很多时候会用到一些公开的类型,这些类型可能是自定义的,比如说(性别男女 受教育程度:大专 本科 硕士 博士),这里我们就需要用到一个字典功能 建立一个字典值,从而可以自定义字典数据 字典数据是依靠字典值从而查询出来的,所以以字典值作为查询条件

先来看一下我们最后搭建的效果

1、接口封装

封装相关的接口,还是跟我们之前差不多,但是这次我们新建文件src\api\system\dict.js

js 复制代码
import request from '@/utils/request.js'

// 字典值列表
export function getDict (n) {
    return request({
      url: '/api/dict',
      method: 'get',
      params:n
    })
}

// 添加字典值 
export function addDict (n) {
    return request({
            url: '/api/dict',
            method: 'post',
            data:n
    })
}

// 删除字典值
export function delDict (id) {
    return request({
      url: '/api/dict/'+id,
      method: 'delete'
    })      
}

// 修改字典值
export function editDict(n) {
    return request({
            url: '/api/dict',
            method: 'put',
            data:n
    })
}

// 获取字典值详情
export function getDict(id) {
    return request({
      url: '/api/dict/'+id,
      method: 'get'
    })
}
// 修改字典值状态 
export function editDictStatus (DictId,status) {
    return request({
            url: '/api/dict/status/'+DictId,
            method: 'put',
            data:status
    })
}

2、页面路由的增加

在页面的路由之中添加相关页面的路由部分src\router\index.tsx

js 复制代码
const DictTypeValue=lazy(() => import('@/views/system/dict/dicttype'));

<Route path="dictvalue" element={<DictTypeValue />} />

3、页面搭建

整个页面的部分我们都写到这个里面 src\views\system\dict\index.tsx

先来搭建一个简单的页面列表

表格部分搭建

表单引入

js 复制代码
import React, { useState, useRef, useEffect } from 'react';
import { Button, Form, Input, Radio, Table, Space, Tag, message, Modal, Popconfirm, Flex } from 'antd';
import { getUserList, addUser, delUser, editUser, getUser, editUserStatus } from '@/api/common/user';
import { getDictTypeList,getDictType, delDictType, addDictType, editDictType} from '@/api/system/dictType';
import axios,{ AxiosResponse } from 'axios';

const { Item } = Form;

const DictTypeValueManagement = () => {
  
  const [visible, setVisible] = useState(false);
  const [form] = Form.useForm();

  useEffect(() => {
    fetchData();
  }, []);
 
  
  

  const handleQuery = () => {
    console.log('handleQuery');
    fetchData();
  }

  const fetchData = () => {
    getDictTypeList().then(res => {
      console.log(res, 'getUser');
      setData(res.data);
      console.log(res.data,'res.data');
    }).catch(error => {
      message.error('Failed to fetch data');
    }); 
  };

  const handleAdd = () => {
    setVisible(true);
  };

  const handleCancel = () => {
    setVisible(false);
  };

  const handleSave = () => {
    form.validateFields()
      .then(values => {
        // Submit data to the backend
        axios.post('http://localhost:3000/api/dict', values)
          .then(() => {
            message.success('Data added successfully');
            setVisible(false);
            form.resetFields();
            fetchData();
          })
          .catch(error => {
            message.error('Failed to add data');
          });
      })
      .catch(errorInfo => {
        console.log('Validation failed:', errorInfo);
      });
  };

  return (
    <>
    <div className="pagedict compage">

        <div className='comback'>
          {/* <Form
            {...formItemLayout}
            layout={formLayout}
            form={form}
            initialValues={{ layout: formLayout }}
            onValuesChange={onFormLayoutChange}
          >
            <Form.Item label="姓名">
              <Input placeholder="请输入姓名" style={{ width: 200 }} value={name} onChange={e => setName(e.target.value)} />
            </Form.Item>
            <Form.Item label="年龄">
              <Input style={{ width: 200 }} placeholder="请输入年龄" value={age} onChange={e => setAge(e.target.value)} />
            </Form.Item>
            <Form.Item {...handleQuery}>
              <Button onClick={() => { handleQuery() }} type="primary">查询</Button>
            </Form.Item>
            <Form.Item>
              <Button onClick={() => { handleReset() }} type="primary">重置</Button>
            </Form.Item>
          </Form> */}
          <Button onClick={() => { handleQuery() }} type="primary">查询</Button>
        </div>


        <div className='comback'>
          <Button type="primary" onClick={handleAdd}>添加</Button>
        </div>

        <div className='comback' style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
          <Table rowKey="id" dataSource={data} columns={columns}/>
        </div>

        <Modal
          title="Add Data"
          open={visible}
          onOk={handleSave}
          onCancel={handleCancel}
        >
          <Form form={form} layout="vertical">
            <Item name="dict_label" label="Label" rules={[{ required: true, message: 'Please input the label!' }]}>
              <Input />
            </Item>
          </Form>
        </Modal>
    </div>
    </>
  );
};
export default DictTypeValueManagement;

表单部分我们增加一下

js 复制代码
const [data, setData] = useState([]);
const columns = [
    {
      title: '字典编号',
      dataIndex: 'dict_id',
      key: 'dict_id',
    },
    {
      title: '字典名称',
      dataIndex: 'dict_name',
      key: 'dictName',
    },
    {
      title: '字典类型',
      dataIndex: 'dict_type',
      key: 'dict_type',
      valueType: 'text',
      render: (dom, record) => {
        return (
          <a
          className='text-blue-600/75 text-sm'
            onClick={() => {
              console.log(record.dictId);
              // history.push(`/system/dict-data/index/${record.dictId}`);
            }}
          >
          {dom}
          </a>
        );
      },
    },
    
    {
      title: '状态',
      dataIndex: 'status',
      key: 'status',
      render: (_: any, row) => {
        return (
          <Tag color={row.status == 0 ? '#87d068' : "#f50"} key={row.status}>
            {row.status == 0 ? '正常' : '异常'}
          </Tag>
        )
      },
    },
    {
      title: '备注',
      dataIndex: 'remark',
      key: 'remark',
      render: (_: any, row) => {
        return (<>{row?.remark||'--'}</>);
      },
    },
    {
      title: '创建时间',
      dataIndex: 'create_time',
      key: 'create_time',
      render: (_, record) => {
        return (<span>{record.create_time.toString()} </span>);
      },
    },
    {
      title: '操作',
      dataIndex: 'option',
      key: 'option',
      valueType: 'option',
      width: '220px',
      render: (_, record) => [
        <Button
          type="link"
          size="small"
          key="edit"
          // hidden={!access.hasPerms('system:dictType:edit')}
          // onClick={() => {
          //   setModalVisible(true);
          //   setCurrentRow(record);
          // }}
        >
          编辑
        </Button>,
        <Button
          type="link"
          size="small"
          danger
          key="batchRemove"
          // hidden={!access.hasPerms('system:dictType:remove')}
          onClick={async () => {
            Modal.confirm({
              title: '删除',
              content: '确定删除该项吗?',
              okText: '确认',
              cancelText: '取消',
              onOk: async () => {
                console.log('ok');
              },
            });
          }}
        >
          删除
        </Button>,
      ],
    },
  ];
  

  
 <div className='comback' style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
   <Table rowKey="id" dataSource={data} columns={columns} />
 </div>      

表格我们自定义设置一下antd

js 复制代码
.ant-table-cell{
    text-align: center !important;
}

页面搭建部分先看看

这里我们还需要优化一下时间

那我们就搭建一个格式化时间的函数

然后我们进行引入和使用

js 复制代码
import { parseTime } from '@/utils/methods';

// 使用这个时间函数
 render: (_, record) => {
        return (<span>{parseTime(record.create_time).toString()} </span>);
 },

搭建增加弹窗部分

接下来搭建我们的弹窗部分,这里还是跟我们之前用户部分的搭建弹窗差不多!

先来看一下我们搭建的弹窗部分

底部我们自定义设置一下antd

js 复制代码
.ant-modal .ant-modal-footer{
    text-align: center !important;
}

查询部分

js 复制代码
const handleQuery = () => {
console.log('handleQuery');

getList();
}
const getList = () => {
getDictTypeList().then(res => {
  console.log(res, 'getUser');
  setData(res.data);
  console.log(res.data,'res.data');
}).catch(error => {
  message.error('Failed to fetch data');
}); 
};

增加部分

可以看到我们参数都是正确的

js 复制代码
文章类型
nexus_articletype
文章类型使用

修改部分

js 复制代码
const handleEdit = async (row) => {
    setTitle("编辑");
    try {
      setLoading(true);
      let data = await handleDetail(row); // 接口的方式查询
      form.setFieldsValue(data); // 填充数据到表单中
    } catch (error) {
      message.error('获取数据详情失败,请重试!');
    } finally {
      setLoading(false);
    }
    setVisible(true);
  };
  /**
 * 处理详情
 *
 * @param row 表格行数据
 * @returns 返回获取到的详情数据
 */
  const handleDetail = async (row) => {
    try {
      const response = await getDictType(row.dict_id);
      const data = response.data;
      return data;
    } catch (error) {
      message.error('获取数据详情失败,请重试!');
    }
  }

删除部分

js 复制代码
<Button
          type="link"
          size="small"
          danger
          key="batchRemove"
          // hidden={!access.hasPerms('system:dictType:remove')}
          onClick={async () => {
            console.log(row,'row--1');          
            Modal.confirm({
              title: '删除',
              content: '确定删除该项吗?',
              okText: '确认',
              cancelText: '取消',
              onOk:  () => {
                handleDelete(row);
              },
            });
          }}
        >
          删除
 </Button>
        
        
const handleDelete = async (record) => {
    console.log(record, '确定删除该项吗?');
    try {
     let data:any=  await delDictType(record.dict_id);
     if(data.code==200){
      message.success('删除成功');
     }else{
       message.error('删除失败,请重试!');
     }
    } catch (error) {
      message.error('删除失败,请重试!');
    }
  };

4、页面优化

页面的正常操作我们已经完成了,接下来针对我们的页面我们进行一下详细的优化

时间渲染优化

查看列表表格我们可以发现

js 复制代码
Cannot read properties of null (reading 'toString')

对于时间渲染我们做个校验

js 复制代码
return (<span>{record.create_time?parseTime(record.create_time):'--'} </span>);


优化写法
return (<span>{parseTime(record.create_time)|| '--'} </span>);

antd弹窗样式优化

现在我们的弹窗是这样子

更改Form 身上的 layout="vertical"

js 复制代码
layout="inline"

//再次优化 删除
默认布局使用

代码提示判断写法优化

之前我们很多部分写法都是:

js 复制代码
addDictType(values).then(res => {
                setVisible(false);
                handleQuery();  // 刷新数据
 })
 
 await editDictType(values).then(res => { })

考虑到失败和成功给用户的提示进行优化,并且使用async 和awaitd的方式

js 复制代码
const res: any = await editDictType(values);
  if (res.code == 200) {
  console.log(res, '修改');
  message.success('修改成功');
  setVisible(false);
  handleQuery();  // 刷新数据
} else {
  message.error('修改失败,请重试!');
}

优化表单默认值

新增的时候我们想让表单默认选择中正常状态,这个时候应该如何做呢?

这个时候我们需要设置整个表单的初始值

js 复制代码
const initialValues = { status: 'value1', 
// 设置 status 字段的初始值 // 可以设置其他表单项的初始值 };

// 给我们的表单设置成为 initialValues 
<Form form={form}  initialValues={initialValues} ></Form>

这个时候我们可以看到我们的默认值已经生效了

筛查条件部分增加

搜索条件部分我们还没有,添加一下我们的搜索条件

js 复制代码
// 将 form 参数设置为 queryForm
// 设置表单初始值
<Form
          {...formItemLayout}
          layout='inline'
          form={queryForm} 
          initialValues={{ layout: 'inline' }} 
          onValuesChange={onFormLayoutChange}
        >
          <Form.Item label="字典名称" name="dict_name">
            <Input placeholder="请输入" style={{ width: 200 }} value={dict_name} onChange={e => setDict_name(e.target.value)} />
          </Form.Item>
          <Form.Item>
            <Button onClick={getList} type="primary">查询</Button>
            <Button onClick={handleReset} type="primary">重置</Button>
          </Form.Item>
</Form>
       

搜索方法优化

搜索方法添加,保证每次我们搜索其实都是从第一页开始进行搜索的,所以我们可以找个中间方法过渡

js 复制代码
 const handleQuery = () => {
    // 处理查询逻辑
    setPageNum(0);
    console.log('handleQuery');
    getList();
  }

搜索参数查询赋值优化

现在我们可以看到我们的搜索条件有一个,如果我们有几百个的情况下如何进行扩展呢,所以这里我们可以更改一下我们搜索方式的赋值

大批量数据查询(几十个甚至上百个,我们就拿一个公共的方法对查询条件进行赋值的优化,公使用一个方法进行赋值,重置也进行简化)

js 复制代码
 const [queryForm, setQueryForm] = useState({
    dict_name: '',
    // 添加其他参数...
  });
  const handleChange = (fieldName, value) => {
    setQueryForm(prevState => ({
      ...prevState,
      [fieldName]: value,
    }));
  };
 const handleReset = () => {
    setQueryForm({
      dict_name: '',
      // 重置其他参数...
    });
 };
  

之后我们添加新的查询使用只需要使用同样的方法就可以直接赋值

js 复制代码
<Form.Item label="字典类型">
  <Input
    placeholder="请输入"
    style={{ width: 200 }}
    value={queryForm.dict_type}
    onChange={e => handleChange('dict_type', e.target.value)}
      />
 </Form.Item>
相关推荐
前端大卫1 小时前
Vue3 + Element-Plus 自定义虚拟表格滚动实现方案【附源码】
前端
却尘1 小时前
Next.js 请求最佳实践 - vercel 2026一月发布指南
前端·react.js·next.js
ccnocare1 小时前
浅浅看一下设计模式
前端
Lee川1 小时前
🎬 从标签到屏幕:揭秘现代网页构建与适配之道
前端·面试
Ticnix2 小时前
ECharts初始化、销毁、resize 适配组件封装(含完整封装代码)
前端·echarts
纯爱掌门人2 小时前
终焉轮回里,藏着 AI 与人类的答案
前端·人工智能·aigc
twl2 小时前
OpenClaw 深度技术解析
前端
崔庆才丨静觅2 小时前
比官方便宜一半以上!Grok API 申请及使用
前端
星光不问赶路人2 小时前
vue3使用jsx语法详解
前端·vue.js
天蓝色的鱼鱼2 小时前
shadcn/ui,给你一个真正可控的UI组件库
前端