首页 > 其他分享 >React后台管理(十四)-- 完整示例页面构建教学

React后台管理(十四)-- 完整示例页面构建教学

时间:2024-05-31 10:31:10浏览次数:21  
标签:current const 示例 -- React useState import data

文章目录


前言

经过了前面文章的学习,终于到最后一步了,那就是一个管理页面的构建,包括处理列表请求,搜索、重置和展开/收起等功能。
结合之前封装的布局、功能相关组件,在本文只需要按需引入,统一了代码标准,减少重复代码,提高代码的可维护性和可复用性。


一、组件源码+详细注释说明+技术分析

页面技术分析:
(1)React Hooks:使用了React的Hooks,如useState、useEffect和useRef,用于管理状态和副作用
(2)React Router DOM:使用了React Router DOM,实现页面路由和导航
(3)MobX-React lite:使用了MobX-React lite,实现响应式数据管理
(4)Ant Design:使用了Ant Design,用于构建表格、按钮、输入框等用户界面元素
(5)自定义组件:使用了自定义组件,如SearchIndex、SearchItem和SearchButton,用于实现搜索和过滤功能

// @/page/chainManage/index.jsx
import { useEffect, useState, useRef } from "react";
import { useNavigate } from "react-router-dom";
import { observer } from "mobx-react-lite";
import { Table, Space, Button, Select, message, Input } from "antd";
import { DeleteOutlined } from "@ant-design/icons";
// api
import { ApiCustomersList, ApiDeleteCustomer } from "@/api";
// hook
import { useTable, useSearch } from "@/hook/index.js";
// 函数组件
import SearchIndex from "@/components/search/index.jsx";
import SearchItem from "@/components/search/item.jsx";
import SearchButton from "@/components/search/button.jsx";
import CdList from "@/layout/list/index.jsx";
import CdTabs from "@/layout/tabs/index.jsx";

const Customer = () => {
  // table
  const [loading, setLoading] = useState(false);
  const { getHeight, tableHeight } = useTable();
  // 请求参数初始化
  const { getReq, updateReq } = useSearch({
    name: "",
    liaisonName: "",
    liaisonMobile: "",
    brandStatus: undefined,
  });
  // table ref
  const tableRef = useRef();
  // 消息
  const [messageApi, contextHolder] = message.useMessage();
  // 路由导航
  const navigate = useNavigate();
  // 搜索ref
  const searchRef = useRef();
  // 是否展示更多搜索条件
  const [open, setOpen] = useState(false);
  // 客户参数管理
  const [params, setParams] = useState({
    page: 1,
    per_page: 10,
  });
  // 客户列表管理
  const [customerData, setCustomerData] = useState({
    list: [], // 客户列表
    count: 0, // 客户数量
  });
  // 状态select列表
  const [statusOptions] = useState([
    { value: "1", label: "及格" },
    { value: "0", label: "不及格" },
  ]);
  // 表格column项
  const columns = [
    {
      title: "客户名称",
      dataIndex: "brandName",
      key: "brandName",
      width: 220,
      render: (text) => <a>{text}</a>,
    },
    {
      title: "状态",
      dataIndex: "brandStatus",
      key: "brandStatus",
      ellipsis: true,
    },
    {
      title: "费率",
      dataIndex: "serviceChargeRateStr",
      key: "serviceChargeRateStr",
      width: 220,
      align: "right",
    },
    {
      title: "联系人",
      dataIndex: "liaisonName",
      key: "liaisonName",
      ellipsis: true,
    },
    {
      title: "联系人手机",
      dataIndex: "liaisonMobile",
      key: "liaisonMobile",
      ellipsis: true,
    },
    {
      title: "操作",
      width: 240,
      render: (data) => {
        return (
          <Space>
            <Button type="link" size="small" icon={<i className="iconfont icon-eye" />} onClick={() => handlerEdit(data)}>
              详情
            </Button>
            <Button type="link" size="small" icon={<i className="iconfont icon-edit" />} onClick={() => handlerEdit(data)}>
              编辑
            </Button>
            <Button type="link" size="small" icon={<DeleteOutlined />} onClick={() => handlerDel(data)}>
              删除
            </Button>
          </Space>
        );
      },
      fixed: "right",
    },
  ];
  // 获取客户列表数据
  const getList = async () => {
    setLoading(true); // 页面loading打开
    ApiCustomersList(getReq())
      .then((res) => {
        console.log("getReq", getReq());
        setCustomerData({
          list: res.data?.records || [],
          count: res.data?.total || 0,
        }); // 表格数据
        setLoading(false); // 页面loading关闭
        tableRef.current && tableRef.current.setTotal(res.data?.total); // 设置分页器总条数
      })
      .catch(() => {
        setLoading(false); // 页面loading关闭
      });
  };
  // 切换页码
  const changePage = () => {
    return getList();
  };
  // 设置表格区域高度以及请求列表数据
  useEffect(() => {
    getHeight().then(() => {
      getList();
    });
  }, []);
  // 展开/收起
  const handlerToggle = (value) => {
    setOpen(value);
    getHeight();
  };
  // 搜索
  const handlerSearch = () => {
    console.log("搜索", searchRef.current.getFieldValue());
    searchRef.current.getFieldValue() && updateReq(searchRef.current.getFieldValue());
    tableRef.current.reset();
    getList();
  };
  // 重置
  const handlerReset = () => {
    searchRef.current.reset();
    getList();
  };
  // 状态select下拉
  const onStatusChange = (val) => {
    searchRef.current.setFieldValue("brandStatus", val);
  };
  // 编辑
  const handlerEdit = (data) => {
    navigate(`/layout/publish?id=${data.id}`);
  };
  // 删除
  const handlerDel = async (data) => {
    ApiDeleteCustomer({ id: data.id }).then((res) => {
      // 刷新列表
      setParams({
        ...params,
        page: 1,
      });
      getList();
      messageApi.open({
        type: "success",
        content: "删除成功",
      });
    });
  };

  return (
    <>
      {contextHolder}
      <CdList tableRef={tableRef} page={changePage}>
        {{
          tabs: (
            <CdTabs title="客户管理">
              <Space size={10}>
                <Button type="primary">新增</Button>
                <Button>导 出</Button>
              </Space>
            </CdTabs>
          ),
          search: (
            <>
              {/* 筛选区域 */}
              <SearchIndex searchRef={searchRef}>
                <SearchItem label="客户名:" name="name" labelWidth="60px">
                  <Input placeholder="请输入名称/简称" maxLength={100} />
                </SearchItem>
                <SearchItem label="联系人:" name="liaisonName" labelWidth="60px">
                  <Input placeholder="请输入" maxLength={100} />
                </SearchItem>
                <SearchItem label="联系人手机:" name="liaisonMobile" labelWidth="90px">
                  <Input placeholder="请输入" maxLength={20} />
                </SearchItem>
                {open ? (
                  <SearchItem label="状态:" name="brandStatus" labelWidth="45px">
                    <Select placeholder="请选择" options={statusOptions} onChange={onStatusChange} allowClear />
                  </SearchItem>
                ) : null}
                <SearchItem span={open ? 24 : 6}>
                  <SearchButton toggle={handlerToggle} reset={handlerReset} search={handlerSearch}></SearchButton>
                </SearchItem>
              </SearchIndex>
            </>
          ),
          default: (
            <>
              {/* 客户列表区域 */}
              <Table
                rowKey="id"
                loading={loading}
                columns={columns}
                dataSource={customerData.list}
                scroll={{
                  y: tableHeight,
                }}
                pagination={false}
              />
            </>
          ),
        }}
      </CdList>
    </>
  );
};

export default observer(Customer);

二、效果展示

在这里插入图片描述


总结

关注本栏目,会实时更新。

标签:current,const,示例,--,React,useState,import,data
From: https://blog.csdn.net/weixin_43883615/article/details/138999109

相关文章

  • window对象的常见属性、延迟函数、时间循环eventloop
    一、window对象JavaScript中的全局对象,代表浏览器窗口或者浏览器标签页。它具有许多属性和方法,以下是其中一些常见的属性:window.document:表示当前窗口或标签页的文档对象,可以用来操作和访问文档的内容。window.navigator:包含有关浏览器的信息,如浏览器的名称、版本、......
  • 团队月度汇报:向上汇报的关键策略
    *在解决问题时,最重要的是找到问题的本质。 *图1.文章的思路    月底了,有几个月度会需要开,大多数都是要总结本月团队的工作产出,并需要对上汇报。    由于之前有工作规划和拆解,因此我这边的汇报总结,非常快速就可以输出,仅需要把之前规划内容的进展给领导同步下......
  • Java构造方法的作业题
    基于面向对象的构造方法的调用,产生有参和无参的构造方法,使用private去保护类内访问packagecom.imooc.day01;/***@authorwangChen*@date2024/5/30*@Description*/publicclassHomeWork01{privateStringname;privateintdata;privatedou......
  • 第二十五章新增H5基础(以及视频~兼容)
    1.HTML5中新增布局标签HTML5新增了页眉,页脚,内容块等文档结构相关标签,可以使文档结构更加清晰明了。1.新增的结构标签1、<header>标签定义文档或者文档中内容块的页眉。通常可以包含整个页面或一个内容区域的标题,搜索表单,相关的logo图片等。2、<footer>标签通常用来定义......
  • 四、zabbix7.0推送告警至钉钉webhook机器人
    一、前提条件1、zabbix服务器能够访问钉钉的服务器,具体说是能访问https://oapi.dingtalk.com/robot/send 2、钉钉的webhook是有安全要求的,我采用的是ip的方式,我的zabbix服务器在内网,我的网络出口有多个固定公网ip,所以这样做省事,其他方式也可以你自己考虑。下图是webhook机器......
  • 2024年第七届信息通信与信号处理国际会议(ICICSP 2024)即将召开!
    2024年第七届信息通信与信号处理国际会议(ICICSP2024)将于2024年9月21-23日在中国舟山举行。ICICSP2024是一个汇聚全球顶尖科研人才、探讨信息通信与信号处理领域最新科研成果和发展趋势的国际盛会。本次会议的主题涵盖了信号处理、多媒体信号处理、互联网技术等多个领域的前......
  • 2024年第六届电力与能源技术国际会议(ICPET 2024)即将召开!
    2024年第六届电力与能源技术国际会议(ICPET2024)将于2024年7月12-15日在中国北京举行。ICPET2024将以电力系统自动化、电力市场、电力电子技术、高电压技术、电磁场理论、能源技术与应用、储能技术等主题讨论为桥梁,建立跨学科,跨实践,跨区域的面对面交流纽带,分享最新研究经验,探......
  • flutter - [03] 运算符&条件表达式
    题记部分 一、算术运算符运算符说明示例(a=13,b=5)+加print(a+b);-减print(a-b);*乘print(a*b);/除print(a/b);~/取整print(a~/b);%取余print(a%b);   二、关系运算符  三、逻辑运算符  四、赋值运算符 五、条件......
  • 合合信息启信数据洞察:长三角新能源汽车产业协同,打造“4小时产业圈”
    新能源汽车作为战略性新兴产业的重要组成部分,已被《“十四五”规划和2035年远景目标纲要》明确聚焦,旨在推动我国经济增长新动能、构建国际竞争新优势、实现从工业大国向工业强国的转变,并作为打造中国制造“升级版”的关键领域。近日,合合信息旗下启信数据发布《2024新质生产力......
  • Flutter将视频或图文分享到抖音
    如何在Flutter中分享视频到抖音话不多说,先上效果:原理发布内容至抖音H5场景_移动/网站应用_抖音开放平台(open-douyin.com)本教程没有接入抖音原生SDK以及任何第三方插件,使用抖音的h5分享接口配合url_launcher插件实现跳转至抖音分享页面需要分享的资源需要被部......