React-字典数据部分搭建

举报
林太白 发表于 2025/01/31 23:54:22 2025/01/31
209 0 0
【摘要】 React-字典数据部分搭建

❤ React-字典数据部分搭建

使用场景

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

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

1、接口封装

封装相关的接口,还是跟我们之前差不多,但是这次我们新建文件src\api\system\dict.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

const DictTypeValue=lazy(() => import('@/views/system/dict/dicttype'));

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

3、页面搭建

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

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

表格部分搭建

表单引入


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;

表单部分我们增加一下

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

.ant-table-cell{
    text-align: center !important;
}

页面搭建部分先看看

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

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

然后我们进行引入和使用

import { parseTime } from '@/utils/methods';

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

搭建增加弹窗部分

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

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

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

.ant-modal .ant-modal-footer{
    text-align: center !important;
}

查询部分

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');
}); 
};

增加部分

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

文章类型
nexus_articletype
文章类型使用

修改部分

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('获取数据详情失败,请重试!');
    }
  }

删除部分

<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、页面优化

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

时间渲染优化

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

Cannot read properties of null (reading 'toString')

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

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

antd弹窗样式优化

现在我们的弹窗是这样子

更改Form 身上的 layout=“vertical”

layout="inline"

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

代码提示判断写法优化

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

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

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

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

优化表单默认值

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

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

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

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

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

筛查条件部分增加

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

// 将 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>

搜索方法优化

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

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

搜索参数查询赋值优化

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

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

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

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

<Form.Item label="字典类型">
  <Input
    placeholder="请输入"
    style={{ width: 200 }}
    value={queryForm.dict_type}
    onChange={e => handleChange('dict_type', e.target.value)}
      />
 </Form.Item>
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

作者其他文章

评论(0

抱歉,系统识别当前为高风险访问,暂不支持该操作

    全部回复

    上滑加载中

    设置昵称

    在此一键设置昵称,即可参与社区互动!

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。