1 功能图

【Ant】PC大题个人总结 - 图1

2 工作回顾

2.1 欢迎页

这个界面可以看出我的css基础有点差,一个简单的静态界面,还是出了很多莫名其妙的bug,在忙完这阵之后考虑看一下阮一峰的flex布局,感觉flex布局可以用的很强。没啥技术含量,不多说了。

2.2 审批页

这部分主要分成两部分,一打开首先说审批列表,点击列表中的草稿项可以进行草稿详情。

2.2.1 审批列表

这部分的主要内容是一个表格,渲染所有待审批的草稿,表格中还要实现通过/不通过以及批量操作。
首先是组件框架的搭建,实现在表格中渲染需要的数据,还有批量的基础框架搭建。框架搭建完就开始获取数据填入,这里就要使用mock进行模拟请求,并将得到的数据放进表中。其中,商品可以选择是否根据状态筛选。
之后,渲染两个按钮,分别为通过/不通过,操作需要加上二次确认弹窗,在弹窗中对数据进行操作,这部分可以将对草稿的审批操作进行封装,只需修改操作入参即可。

  1. async function confirm(record: any, targetStatus: number) {
  2. const gmtIds = [];
  3. gmtIds.push(Number(record.gmtId));
  4. try {
  5. const res = await setDraftStatus(targetStatus, gmtIds);
  6. if (res.success) {
  7. actionRef.current!.reload();
  8. }
  9. setSelectedRows([]);
  10. actionRef.current?.reloadAndRest?.();
  11. } catch (err) {
  12. console.log(err);
  13. }
  14. }

2.2.2 审批详情

这个界面分为上下两部分,上部分为数据介绍,下部分为审批操作。
首先是数据的获取,首先要得到审批列表页传入的gmtId,有两种方法,一种是通过history.push传入的参数解析,另一种是解析url中的gmtId。

// 处理history.state得到gmtId
const history: any = useHistory();
const gmtId = history.location.state.gmtId;
// 处理url得到gmtId
const url: string = window.location.pathname;
console.log(url);

上部分用表格的形式展示草稿数据,同时进行判定,如果与原数据不一致,则用特殊的css进行渲染,并通过悬浮窗在鼠标悬停时进行原数据的渲染。

const getDifference = (a: any, b: any) => {
  const changes = (object: any, base: any) => {
    return _.transform(object, (result: any, value, key) => {
      if (!_.isEqual(value, base[key])) {
        result[key] =
          _.isObject(value) && _.isObject(base[key]) ? changes(value, base[key]) : value;
      }
    });
  };
  return changes(a, b);
}; const diff = (type: string): boolean => {
  return gmtData.goods[type] !== goodData[type];
};

剩下要做的事情就是,把所有数据渲染一遍,对时间进行格式处理,对列表数据转换成对应文本。
最后的sku列表渲染十分复杂,于是我找了@升正(huangshengpu.hsp)封装好的组件,感谢大佬。

2.3 其他

零零散散做了点别的,比如给侧边栏加了点好看的图标(工作量不超过50个字母😂)。
回归正题,第一次接触mock,也学习到了很多,从一开始只会模拟最简单的接口,到后面逐渐研究如何进行传参,用mock模拟后端还挺有趣的。

async function confirm(record: any, targetStatus: number) {
  const gmtIds = [];
  gmtIds.push(Number(record.gmtId));
  try {
    const res = await setDraftStatus(targetStatus, gmtIds);
    if (res.success) {
      actionRef.current!.reload();
    }
    setSelectedRows([]);
    actionRef.current?.reloadAndRest?.();
  } catch (err) {
    console.log(err);
  }
}
export async function setDraftStatus(targetStatus: number, gmtIds: number[]) {
  return request<API.DraftList>('/api/setDraftStatus', {
    method: 'POST',
    data: {
      targetStatus: targetStatus,
      gmtIds: gmtIds,
    },
  });
}
function setDraftStatus(req: Request, res: Response) {
  const { targetStatus, gmtIds } = req.body;

  copyList.data.forEach((i) => {
    if (gmtIds.indexOf(i.gmtId) !== -1) {
      // 替代
      i.gmtStatus = targetStatus;
    }
  });

  res.json(copyList);
}

然后对git熟悉了好多,特别是团队操作应该咋pull/merge之类的,还会搞分支,相比之前个人开发无脑commit push进步了好多。

2.4 不足

基本功能算是完成了,但是没有亮点,列表渲染了,也就只是渲染了,连查询功能都没做;详情页写了,也只是渲染了数据,和简单的展示了diff,没有新颖的功能。
还有就是数据结构以及系分做的太拉了,下次一定要多花点时间好好分,好好确定,这样真的会省很多时间。

3 结果

内容 完成情况 备注
欢迎页 100%
审批列表页 90% 查询功能未完成
批量审批组件封装 100%
审批详情页 90% sku组件没有自己实现,而是使用了别人封装的
diff组件封装 100%

4 CR

4.1 封装审批异步操作

async function confirm(record: any, targetStatus: number) {
  const gmtIds = [];
  gmtIds.push(Number(record.gmtId));
  try {
    const res = await setDraftStatus(targetStatus, gmtIds);
    if (res.success) {
      actionRef.current!.reload();
    }
    setSelectedRows([]);
    actionRef.current?.reloadAndRest?.();
  } catch (err) {
    console.log(err);
  }
}

4.2 状态必须搞枚举

enum gmtStatusType {
  PendingApproval = 0,
  HaveCoverd = 1,
  PendingCover = 2,
  Abandon = 3,
  Editable = 4,
}

setDraftStatus(gmtStatusType.Editable, gmtIds)

4.3 .map抽离欢迎页

memberData.map((item, index) => {
  return (
    <Card className="card-box" key={index}>
      <div className={item.avatar} />
      <h4 className="name">{item.name}</h4>
      <div dangerouslySetInnerHTML={{ __html: item.intro }} />
    </Card>
  );
})

4.4 封装diff函数

const getDifference = (a: any, b: any) => {
  const changes = (object: any, base: any) => {
    return _.transform(object, (result: any, value, key) => {
      if (!_.isEqual(value, base[key])) {
        result[key] =
          _.isObject(value) && _.isObject(base[key]) ? changes(value, base[key]) : value;
      }
    });
  };
  return changes(a, b);
};

4.5 抽离商品详情

goodDataShow.map((i) => {
  return (
    <Descriptions.Item label={i.label} key={i.label} span={i.span}>
      <Popover
        trigger="hover"
        title={i.diff ? '原数据' : ''}
        content={i.diff ? i.oldContent : ''}
      >
        <span className={i.diff ? 'diff' : ''}>{i.content}</span>
      </Popover>
    </Descriptions.Item>
  );
})

5 学习笔记

5.1 实现两种方法的路由传参

法1: 处理history.state得到gmtId

// 传参
history.push({
  pathname: './detail/' + record.gmtId,
  state: { gmtId: record.gmtId },
});

// 获取:处理history.state得到gmtId
const history: any = useHistory();
const gmtId = history.location.state.gmtId;


// 路由,:gmtId是关键
{ path: '/approval/detail/:gmtId', access: 'canAdmin', component: './approval/ApprovalDetail' },

法2: 处理url得到gmtId

// 处理url得到gmtId
const url: string = window.location.pathname;
console.log(url);
// 这里拿到还是很长一串带/的字符串,要splice处理