Build a simple shopping platform from scratch (7)

Start from scratch, build a simple shopping platform (6): https://blog.csdn.net/time_____/article/details/105440818
Project source code (continuous update): https://gitee.com/DieHunter/myCode/ tree/master/shopping

Up to now, the front-end and back-end functions of the project have realized login, token acquisition and verification, upload avatars, and add users. This article mainly describes the realization of front-end and back-end user list page search, fuzzy query, and user list rendering functions.

  • The first is paging search. The back-end implementation method uses the length of the database to look up the table, with the database function skip(n) (skip the first n data), and limit(m) (search m data backward), through db.find ().skip((page-1) * pageSize).limit(pageSize) (page represents the number of pages, starting from 0, the first page does not need to be skipped. pageSize represents the number of data items per page after paging), so We create two new methods in command.js for querying the length of the table and keyword query and pagination
 /* 查询分页
   * @param {object} mod       数据库model
   * @param {number} sort      排序顺序   负数倒序 正数顺序
   * @param {number} page      当前页数
   * @param {number} pageSize  分页大小
   * @param {object} pageSize  关键字模糊查询
   */
  static async findByPage(mod, sort, page, pageSize, keyWord) {
    //分页查
    return await mod
      .find(keyWord)
      .sort(sort)
      .skip((page - 1) * pageSize)
      .limit(pageSize);
  }
 /* 查询分页
   * @param {object} mod       数据库model
   * @param {number} pageSize  分页大小
   */
 static async getTotalPage(mod, pageSize) {
    let allNum = await mod.find().estimatedDocumentCount();
    return { totalPage: parseInt(allNum / pageSize) + 1, allNum };
  }
  • Add an interface to get the user list in users.js, search by email or username, and paging
router.get(Config.ServerApi.userList, Util.checkToken, async (req, res) => {
  if (res._data.userTokenType != "admin") {
    //非管理员
    res.send({
      result: -999,
      msg: "请用管理员账号登录",
    });
    return;
  }
  let total = await getTotalPage(Mod, res._data.pageSize);
  let query = new RegExp(res._data.keyWord, "i"); //模糊查找正则条件
  res.send({
    result: 1,
    data: {
      page: res._data.page,
      pageSize: res._data.pageSize,
      totalPage: total.totalPage,
      allNum: total.allNum,
      list: await findByPage(
        Mod,
        {
          time: res._data.sort,
        },
        res._data.page,
        res._data.pageSize,
        res._data.keyWord.length
          ? {
              $or: [
                {
                  mailaddress: query,
                },
                {
                  username: query,
                },
              ],
            }
          : {}
      ),
    },
    msg: "查找成功",
  });
});

After the back-end part is implemented, start to write the front-end. The form component, the paging component and the input search component are needed. Here, the form component can be written separately and written as our own component for reuse in the later product list.

  • First configure the user form fields and encapsulate them in a class
import React from "react";
import {
  Button,
  Popconfirm,
} from "antd";
import config from "../../config/config";

const { FilePath } = config;
export default class UserTable {
  constructor(_this) {
    return [
      { align: "center", title: "用户名", dataIndex: "username", width: 200 },
      {
        align: "center",
        title: "邮箱",
        dataIndex: "mailaddress",
        width: 200,
        render: (text, data) => {
          return <div>{text + data.mailurl}</div>;
        },
      },
      {
        align: "center",
        title: "密码",
        dataIndex: "password",
        width: 300,
      },
      {
        align: "center",
        title: "头像",
        dataIndex: "headPic",
        width: 150,
        render: (imgPath) => {
          return (
            <img
              src={FilePath + imgPath}
              alt=""
              style={
   
   { width: 60, margin: "0 auto" }}
            />
          );
        },
      },
      {
        align: "center",
        title: "性别",
        dataIndex: "sex",
        width: 200,
        render: (sex) => {
          return <div>{sex == "man" ? "男" : "女"}</div>;
        },
      },
      {
        align: "center",
        title: "收货地址",
        dataIndex: "alladdress",
        width: 200,
        render: (text, data, index) => {
          return <div>{text.join("-") + data.address}</div>;
        },
      },
      {
        align: "center",
        title: "个性签名",
        dataIndex: "descript",
        width: 200,
      },
      {
        align: "center",
        title: "用户类型",
        dataIndex: "userType",
        width: 200,
        render: (type) => {
          return <div>{type == "admin" ? "管理员" : "用户"}</div>;
        },
      },
      {
        align: "center",
        title: "注册时间",
        dataIndex: "time",
        width: 200,
      },
    ];
  }
}
  • Before the table is rendered, determine the type of the table, whether to display the user or the product, to achieve the component reuse function, and bind the paging component to pageconfig to achieve the effect of switching pages
import React from "react";
import {
  Table,
  Button,
  Card,
  Pagination,
  Input,
  Col,
  Row,
} from "antd";
import userTab from "./userTab";
import { PlusOutlined } from "@ant-design/icons";
const { Search } = Input;
export default class ListTable extends React.Component {
  state = {
    tableType: this.props.tableType,
    pageConfig: {
      totalPage: 0,
      page: 0,
      pageSize: 0,
      allNum: 0,
    },
    columns: [],
    list: [],
  };
  componentDidMount() {
    if (this.state.tableType == "user") {
      this.setState({
        columns: new userTab(this)
      });
    } else {
      
    }
    this.props.onTableRef(this);
  }
  render() {
    return (
      <Card title="用户列表">
        <Row gutter={16}>
          <Col span={12}>
            <Button onClick={this.props.showDrawer} type="primary">
              <PlusOutlined />
              新增用户
            </Button>
          </Col>
          <Col span={12}>
            <Search
              style={
   
   { float: "right" }}
              placeholder="输入用户名/邮箱"
              enterButton="查找"
              size="large"
              allowClear
              onSearch={(val) => {
                let { pageConfig } = this.state;
                pageConfig.keyWord = val;
                this.setState({
                  pageConfig,
                });
                this.props.changePage(pageConfig);
              }}
            />
          </Col>
        </Row>
        <Table
          scroll={
   
   { x: 2000 }}
          rowKey={(record) => record._id}
          columns={this.state.columns}
          dataSource={this.state.list}
          pagination={false}
        ></Table>
        <Pagination
          style={
   
   { marginTop: 50 }}
          hideOnSinglePage
          total={this.state.pageConfig.allNum}
          current={this.state.pageConfig.page}
          pageSize={this.state.pageConfig.pageSize}
          showSizeChanger
          showQuickJumper
          showTotal={(total) => `共 ${total} 条`}
          onChange={this.changePage}
          onShowSizeChange={this.changePage}
        />
      </Card>
    );
  }
  changePage = (page, pageSize) => {
    let pageConfig = this.state.pageConfig;
    pageConfig.page = page;
    pageConfig.pageSize = pageSize;
    this.setState({
      pageConfig,
    });
    this.props.changePage(pageConfig);
  };
}
  • Finally, it is called in the userlist to achieve a data two-way binding effect with the page in the table
import React from "react";
import ListTable from "../../../components/table/table";
import {
  message,
} from "antd";
import config from "../../../config/config";
const { ServerApi, StorageName } = config;

export default class UserList extends React.Component {
  state = {
    userType: "adduser",
    pageConfig: {
      token: this.$utils.getStorage(StorageName.token),
      keyWord: "",
      page: 1,
      pageSize: 2,
      totalPage: 1,
      sort: 1,
    },
  };
  componentDidMount() {
    this.getUserList();
  }
  render() {
    return (
      <div>
        <ListTable
          tableType="user"
          onTableRef={(child) => {
            this.tableChild = child;
          }}
          showDrawer={this.showDrawer}
          changePage={this.changePage}
        ></ListTable>
        <ListDrower
          getUserList={this.getUserList}
          userType={this.state.userType}
          onDrowerRef={(child) => {
            this.drawerChild = child;
          }}
        ></ListDrower>
      </div>
    );
  }
  showDrawer = () => {
    this.drawerChild.showDrawer();
  };
  changePage = (pageConfig) => {
    this.setState({ pageConfig });
    this.getUserList();
  };

  getUserList = () => {
    let data = { ...this.state.pageConfig };
    this.$axios
      .get(ServerApi.user.userList, {
        params: { crypto: this.$crypto.setCrypto(data) },
      })
      .then((res) => {
        let { list, totalPage, allNum } = res.data;
        let { pageConfig } = this.state;
        pageConfig.allNum = allNum;
        pageConfig.totalPage = totalPage;
        this.tableChild.setState({ pageConfig, list });
      })
      .catch((err) => {});
  };
}
  • After all is done, test it

to sum up

In the component-based development of front-end code, component reuse can improve the maintainability of the code. By modifying the state or initial state value to use the corresponding component, the code efficiency is greatly improved

Guess you like

Origin blog.csdn.net/time_____/article/details/105448383