eggjs 怎么实现获取账单列表接口并且实现列表数据分页查询功能?

Posted 凯小默

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了eggjs 怎么实现获取账单列表接口并且实现列表数据分页查询功能?相关的知识,希望对你有一定的参考价值。

说明

该分页列表查询接口我自己分成三步写的,跟小册上的实现方式不太样,我是通过 mysql 的 limit 分页去实现的。

主要分成三个大的部分逻辑:

  1. 通过查询一个月里的账单所处的是哪一天,全都查出来,形成一个天数列表
  2. 通过天数列表,去查里面每一天的账单数据
  3. 最后统计这个月的所有账单

列表原型要求

可以查看原型,看前端账单需要怎样展示:账单是以时间天数作为一条数据,需要显示每天的账单信息,还有当月总支出,当月总收入,全部类型,月份选择。

分析接口需要字段

入参字段有:查询时需要

curPage, // 当前页数 (默认为1)
pageSize, // 一页多少条(默认为5)
typeId, // 类型 'all'就是全部类型
billDate, // 账单日期

需要返回的字段有

data: 
  totalExpense, // 当月支出
  totalIncome, // 当月收入
  dataList: [
  	day, // 日期
	bills:  // bill 数据表中的每一项账单
  , ...] // 列表数据
  pageObj: 
    curPage, // 当前页数
	pageSize, // 一页多少条
	totalPage, // 总分页数
	totalRow, // 总条数
  

实现获取账单列表接口

1、在控制层添加一个 list 方法

打开 /controller/bill.js,新增一个 list 方法,里面的大体逻辑

  1. 获取查询参数
  2. 拿到 token 获取用户信息 user_id
  3. 通过 user_id 获取列表分页数据
  4. 组装数据:需要通过日获取一天的账单列表数据
  5. 获取当月总支出、当月总收入、总条数
const moment = require('moment'); // javascript 日期处理类库
class BillController extends Controller 
	async list() 
	  const  ctx, app  = this;
	  try 
	    /**
	     *  curPage, // 当前页数 (默认为1)
	     *  pageSize, // 一页多少条(默认为5)
	     *  typeId, // 类型 'all'就是全部类型
	     *  billDate, // YYYY-MM 账单日期
	     * */ 
	    // 1、获取查询参数
	    const  curPage = 1, pageSize = 5, typeId = 'all', billDate  = ctx.query;
	    console.log('1、获取查询参数',curPage,pageSize,typeId,billDate);
	    // 2、拿到 token 获取用户信息 user_id
	    const token = ctx.request.header.authorization;
	    const decode = await app.jwt.verify(token, app.config.jwt.secret);
	    if (!decode) return;
	    let user_id = decode.id;
	    console.log('2、拿到 token 获取用户信息 user_id',user_id);
	    // 3、通过 user_id 获取列表分页数据
	    const dayResult = await ctx.service.bill.list(user_id, typeId, billDate, curPage, pageSize);
	    const dayList = JSON.parse(JSON.stringify(dayResult));
	    console.log('3、通过 user_id 获取当前用户的账单列表',dayResult,dayList);
	    // 4、组装数据:需要通过日获取一天的账单列表数据
	    let dataList = [];
	    for(var i = 0; i < dayList.length; i++) 
	      const day = moment(dayList[i].day).format("YYYY-MM-DD");
	      const month = moment(dayList[i].day).format("YYYY-MM");
	      if(month === billDate) 
	        const listResult = await ctx.service.bill.listByDay(user_id, typeId, billDate, day);
	        const billsList = JSON.parse(JSON.stringify(listResult));
	        console.log(day,listResult,billsList);
	        dataList.push(
	          day: day,
	          bills: billsList
	        );
	      
	    
	    console.log('4、然后将 list 过滤出月份和类型所对应的账单列表',dataList);
	    // 5、获取当月总支出、当月总收入、总条数
	    // 获取一个月的有账单的所有天数列表 typeId 写死为all
	    const allDayResult = await ctx.service.bill.allList(user_id, 'all', billDate);
	    const allDayList = JSON.parse(JSON.stringify(allDayResult));
	    // 当月总支出:支付类型:1:支出,2:收入
	    let totalExpense = allDayList.reduce((curr, next) => 
	      if (next.pay_type === 1) 
	        curr += Number(next.amount);
	        return curr;
	      
	      return curr;
	    , 0).toFixed(2); 
	    // 当月总收入:支付类型:1:支出,2:收入
	    let totalIncome = allDayList.reduce((curr, next) => 
	      if (next.pay_type === 2) 
	        curr += Number(next.amount);
	        return curr;
	      
	      return curr;
	    , 0).toFixed(2);
	    // 总条数 需要根据 typeId 去过滤
	    const allDayTypeIdResult = await ctx.service.bill.allList(user_id, typeId, billDate);
	    const allDayTypeIdList = JSON.parse(JSON.stringify(allDayTypeIdResult));
	    let obj = ; // 用年月日作为 key(YYYY-MM-DD)
	    // 天数去重
	    let newAllDayTypeIdList = allDayTypeIdList.reduce((item, next) => 
	      let nextDate = moment(next.date).format("YYYY-MM-DD");
	      obj[nextDate] ? '' : obj[nextDate] = true && item.push(next);
	      return item;
	    , []);
	    let totalRow = newAllDayTypeIdList.length;
	    console.log('5、获取一个月的有账单的天数列表', obj, newAllDayTypeIdList);
	    console.log('总条数', totalRow, '当月总支出:',totalExpense, '当月总收入:',totalIncome);
	    ctx.body = 
	      status: 200,
	      desc: '请求成功',
	      data: 
	        totalExpense, // 当月总支出
	        totalIncome, // 当月总收入
	        dataList: dataList, // 列表数据
	        pageObj: 
	          curPage, // 当前页数
	          pageSize, // 一页多少条
	          totalPage: Math.ceil(totalRow / pageSize), // 总分页数
	          totalRow, // 总条数
	        
	      
	    
	   catch (error) 
	    console.log(error);
	    ctx.body = 
	      status: 500,
	      desc: '系统错误',
	      data: null
	    
	  
	

2、在服务层添加几个方法获取sql数据

这里需要会一点 sql 语句,分页的参考资料在文章后面。

获取一个月的列表分页数据:主要就是通过日期去去重找到哪些天有账单的日期列表数据,然后通过降序分页处理。

async list(user_id, type_id, month, curPage, pageSize) 
    const  app  = this;
    try 
      // 去重找到日的数据列表降序分页
      let type_id_str = type_id === "all" || type_id === "" ? "" : " and type_id = " + type_id;
      let date_str = " and DATE_FORMAT(b.date,'%Y-%m') = '" + month + "'";
      let sql = "select distinct STR_TO_DATE(b.date,'%Y-%m-%d') day from `kaimo-cost`.bill b where user_id = "+ user_id+ type_id_str + date_str + " order by day desc limit "+(curPage-1)*pageSize+", "+pageSize;
      const result = await app.mysql.query(sql);
      return result;
     catch (error) 
      console.log(error);
      return null;
    
  

获取某一天的账单列表数据:主要加入一些查询条件

async listByDay(user_id, type_id, month, day) 
  const  app  = this;
  try 
    const QUERY_STR = 'id, pay_type, amount, date, type_id, type_name, remark';
    let type_id_str = type_id === "all" || type_id === "" ? "" : " and type_id = " + type_id;
    let date_str = " and STR_TO_DATE(b.date,'%Y-%m-%d') = '" + day + "'" + " and DATE_FORMAT(b.date,'%Y-%m') = '" + month + "'";
    let sql = "select " + QUERY_STR + " from `kaimo-cost`.bill b where user_id = " + user_id + date_str + type_id_str;
    console.log('通过日获取列表数据', sql);
    const result = await app.mysql.query(sql);
    return result;
   catch (error) 
    console.log(error);
    return null;
  

获取某个月的所有账单数据

async allList(user_id, type_id, month) 
  const  app  = this;
  try 
    let type_id_str = type_id === "all" || type_id === "" ? "" : " and type_id = " + type_id;
    let sql = "select * from `kaimo-cost`.bill b where user_id = "+ user_id + " and DATE_FORMAT(b.date,'%Y-%m') = '" + month + "'" + type_id_str;
    console.log('获取月的所有账单数据', sql);
    const result = await app.mysql.query(sql);
    return result;
   catch (error) 
    console.log(error);
    return null;
  

3、配置路由

// 获取账单列表
router.get('/api/bill/list', verify_token, controller.bill.list);

测试获取账单列表接口

1、在 apifox 里新建接口

如下图所示:

2、伪造列表数据

我们可以将下面的 sql 在 DBeaver 执行,插入这些数据。

INSERT INTO `kaimo-cost`.bill
(id, pay_type, amount, `date`, type_id, type_name, user_id, remark)
VALUES(1, 1, '33.00', '2022-01-01 22:00:00', 2, '1', 5, '测试');
INSERT INTO `kaimo-cost`.bill
(id, pay_type, amount, `date`, type_id, type_name, user_id, remark)
VALUES(2, 1, '3', '2022-01-01 19:00:00', 2, '1', 5, '测试');
INSERT INTO `kaimo-cost`.bill
(id, pay_type, amount, `date`, type_id, type_name, user_id, remark)
VALUES(3, 1, '13', '2022-01-02 22:00:00', 2, '1', 5, '测试');
INSERT INTO `kaimo-cost`.bill
(id, pay_type, amount, `date`, type_id, type_name, user_id, remark)
VALUES(4, 2, '56', '2022-01-03 18:00:00', 2, '1', 5, '测试');
INSERT INTO `kaimo-cost`.bill
(id, pay_type, amount, `date`, type_id, type_name, user_id, remark)
VALUES(5, 2, '42', '2022-01-05 12:07:00', 1, '1', 5, '测试');
INSERT INTO `kaimo-cost`.bill
(id, pay_type, amount, `date`, type_id, type_name, user_id, remark)
VALUES(6, 2, '11', '2022-01-06 22:00:00', 2, '1', 5, '测试');
INSERT INTO `kaimo-cost`.bill
(id, pay_type, amount, `date`, type_id, type_name, user_id, remark)
VALUES(7, 1, '3', '2022-01-07 22:00:00', 5, '1', 5, '测试');
INSERT INTO `kaimo-cost`.bill
(id, pay_type, amount, `date`, type_id, type_name, user_id, remark)
VALUES(8, 1, '33', '2022-02-01 22:00:00', 14, '1', 5, '测试');
INSERT INTO `kaimo-cost`.bill
(id, pay_type, amount, `date`, type_id, type_name, user_id, remark)
VALUES(9, 1, '3', '2022-02-02 22:00:00', 14, '1', 5, '测试');
INSERT INTO `kaimo-cost`.bill
(id, pay_type, amount, `date`, type_id, type_name, user_id, remark)
VALUES(10, 2, '2', '2022-02-03 22:00:00', 2, '1', 5, '测试');
INSERT INTO `kaimo-cost`.bill
(id, pay_type, amount, `date`, type_id, type_name, user_id, remark)
VALUES(11, 2, '46.9', '2022-02-04 22:00:00', 2, '1', 5, '测试');
INSERT INTO `kaimo-cost`.bill
(id, pay_type, amount, `date`, type_id, type_name, user_id, remark)
VALUES(12, 2, '27', '2022-02-05 20:00:00', 1, '1', 5, '测试');
INSERT INTO `kaimo-cost`.bill
(id, pay_type, amount, `date`, type_id, type_name, user_id, remark)
VALUES(13, 2, '4', '2022-02-05 22:00:00', 1, '1', 5, '测试');
INSERT INTO `kaimo-cost`.bill
(id, pay_type, amount, `date`, type_id, type_name, user_id, remark)
VALUES(14, 2, '7', '2022-02-07 22:00:00', 4, '1', 5, '测试');
INSERT INTO `kaimo-cost`.bill
(id, pay_type, amount, `date`, type_id, type_name, user_id, remark)
VALUES(15, 1, '11', '2022-02-08 22:00:00', 4, '1', 5, '测试');
INSERT INTO `kaimo-cost`.bill
(id, pay_type, amount, `date以上是关于eggjs 怎么实现获取账单列表接口并且实现列表数据分页查询功能?的主要内容,如果未能解决你的问题,请参考以下文章

eggjs 怎么实现账单详情页的获取详情接口?

eggjs 怎么实现账单详情页的编辑接口?

eggjs 怎么实现新增账单接口?

eggjs 怎么实现账单详情页的删除接口?

eggjs 怎么实现月度账单统计接口?

eggjs 里链接 mysql 返回数据有 RowDataPacket 应该怎么处理?