需求复盘,也是一个对自己的警示

179 阅读4分钟

前言

上周接手了另一个项目的同事需求,简单看了下设计原型,感觉还行,就和产品简简单单的过了一遍,产品说做的和之前一样就行and这个功能另一个页面有,想想有做过就ok,也就没太深入了解,最不济cv后修改一下。

但是真的有点被这两句话伤害到。开发过程中,遇到了不少问题,整个开发过程甚为艰难,总结反思一下,所以写了这篇文章,同时在复盘一下需求。

遇到的问题(反思)

  1. 业务需求没了解清楚,算是中途接手(更应该主动去了解)
  2. 盲目相信那两句话,导致功能没有完成实现,即使我cv了之前的功能(了解需求)
  3. 技术不够,看了下tapd上测试提的Bug单,陷入怀疑,虽然有部分需求不清晰(这可能是最主要原因了,学习永不停息)
  4. 开发时间不足,虽然给的时间也没几天,测试的过程中也在开发
  5. 第一次遇到产品上线,整体氛围紧张,导致整个人逻辑精神状态不太对,到了最后改了bug还是错
  6. 没有认真检查代码及功能,很重要(看到简单的错误,有点羞愧)
  7. 将要做事情的记录下来,否则一旦被其中一件耽误,其他也就忘记了

image.png

虽然最后还是完成的功能需求开发,这可能是我职业生涯第一次遇到的困难,即使是刚开始,离不开同事的帮助,帮我提供方案滤清思路,想想如果没有,我肯定非常焦虑。

正文

主要复盘整个需求中最难的功能点,不过现在感觉开发方向对之后,逻辑理解起来就很清晰。途中遇到的苦和泪,不言而喻,先看功能,难点主要集中在提交给后端的数据上,我们需要对输入的数据进行校验及数据处理。

动画.gif

我们可以通过点击$股票搜索我们想要的股票消息,点击上方的tag获取想要的股票。那么输入框中就会出现以下几种情况:

image.png

文案:普通输入的文本,在移动端显示为正常文本

股票:通过搜索点击得到的股票$xxx$(以$开头和结尾),在移动端是下划线高亮,可点击跳转

情况:文案、股票、文案+股票、股票+文案、文案+股票+文案、文案+股票+文案+股票、股票+文案+股票

那么后端需要我们提交的格式,属于文案的type为1,text存放文案;输入股票的type为3,其他参数则是股票的其他信息,最终一起提交是一个数组类型

image.png

那么怎么样可以分别获取文案和股票呢,大致思路就是通过$xxx$来分割,获取文案,而$$里面的内容我们可以之前点击股票获取,我们前面搜索点击的股票也会被push进一个数组quoteList(下图),那么遍历获取$xxx$。一开始是这么想的,但是,产品说希望复制点击过的股票也可以高亮(下图,前一个是搜索点击获得,后一个是复制前一个),那么quoteList只保存一个元素,就无法实现识别两个(也许有其他方案)但是后期我们还要验证输入的是否与quoteList相同,以防输入后期被修改了,所以遍历quoteList这个方案不行。

image.png

image.png

正则

另一个方案大致就是通过正则表达式匹配整个输入内容,但是这个最开始我是拒绝的,麻烦要写正则表达式(主要这方面知识忘光光了),所以花了不少时间去想quoteList咋做。不过最后我妥协了,还是得正则,被迫重新捡起知识。

总结规则:$10303.HK 納指摩通二九購B$ ,后面对应正则

  1. $开头 \$[^\$] 只出现一次
  2. 5位数的数字 \d{5}
  3. . \.
  4. HK或US HK|US
  5. 空格 \s
  6. 任意文字、字母及数量 .{3,} 3个任意字符及以上
  7. $结尾 \$

最终结合为\$[^\$](\d{5}(\.HK|\.US)\s.{3,}?)\$,可以看到最后有一个?,如果不加上?,只能实现匹配最后一个字符是$,所以会出现$$结尾也会被包括(下图),?是尽可能少匹配

正则验证地址,有兴趣可以试试c.runoob.com/front-end/8…

image.png

我们有了正则,就可以直接去匹配输入框中的$xxx$

let messageContentTemp = this.content //内容
var reg = RegExp(/\$(\d{5}(\.HK|\.US)\s[\s\S]{3,}?)\$/g)
const arr = messageContentTemp.match(reg) || []  //match返回数组,数组存放匹配成功的元素
console.log(arr)

image.png

具体代码

如果我们没有通过$股票来进行获取股票,那么即使手动输入正确的股票也只能默认为文本,因为前端无法校验他是否输入正确,需要后端配合,目前不支持。如果他只输入了文案,那type就为1

if (quoteList?.length) {
...xxx
} else {
  richTextList.push({
   type: 1,
   text: this.content
  })
}

我们遍历match来的数组,对其进行以下一系列的处理

for (const i of arr) {
    const stockStr = i.slice(1, i.length - 1)
    const splitArr = stockStr.split('.')
    // const code = splitArr[0] 
    // const market = splitArr[1] 
    // const exchange = marketInfo[market] 
    // 以上当type=3时,需要提交的字段
    
    const idx = messageContentTemp.indexOf(i)
    const strOne = messageContentTemp.slice(0, idx) // 前一段
    messageContentTemp = idx + i.length !== messageContentTemp.length 
    && messageContentTemp.slice(idx + i.length) || '' // 后一段
}

indexOf(i)可以获取第一个股票的位置下标idx,那么从字符串(0,idx)就是文案,如果idx也是0,那证明股票前面没有文案。而剩下的后半段会在复制给messageContentTemp,下次循环找到新的股票,前提是i的长度不等于messageContentTemp的长度,如果相同,那也就证明messageContentTemp只有股票,就没有后半段,messageContentTemp为空

if (strOne.length !== '') {
  richTextList.push({
    type: 1,
    text: strOne
  })
}

文案在前,先将其push进数组,不仅要实现匹配识别,也要保证整体的文案顺序正确。

const trueArr = this.quoteList.filter(item => item.code === code) || []
// 验证输入的股票是否与接口返回的相同,不相同则变成文案
if (trueArr.length && trueArr[0]?.stockSymbol === stockStr) {
  //richTextList.push({
  //   type: 3,
  //   stockSymbol: stockStr,
  //   stockCode: code,
  //   market: market,
  //   exchange: exchange,
  // })
  // 本来是使用上面获取的参数的,但是有个问题就是我是通过符号点(.)去做分割的,如果用户把点给删除了
  // 那还怎么拿数据,所有上面声明的就没用了。好在,可以获取到quoteList里的股票数据且一定不会错。
  richTextList.push({
    type: 3,
    stockSymbol: trueArr[0].stockSymbol,
    stockCode: trueArr[0].code,
    market: trueArr[0].market,
    exchange: trueArr[0].exchange,
    categoryType: trueArr[0].categoryType,
  })
} else {
  richTextList.push({
    type: 1,
    text: stockStr,
  })
}
// 当messageContentTemp后一段匹配不到股票$xxx$,证明剩下都是文案
const msgReg = messageContentTemp.match(reg) || []
!msgReg.length && richTextList.push({
  type: 1,
  text: messageContentTemp
})

这里还有一种情况,就是原本有一个股票,arr里面也存放后,但是后来我把股票删除了,arr就没有股票了,只剩下文案的情况,所以需要加上一个判断arr.length是否为0

if (arr.length) {
  for (const i of arr) {
    ...xxxx
    // 当只有一个股票,且股票在前,文案在后的情况
    const msgReg = messageContentTemp.match(reg) || []
    !msgReg.length && richTextList.push({
      type: 1,
      text: messageContentTemp
    })
  }
} else {
  // 原本有股票,后面删除了只剩文本
  richTextList.push({
    type: 1,
    text: this.content
  })
}

到此,我们基本就把所有的情况处理完毕,当输入以下,查看处理结果,达到预期

image.png

image.png

还有就是当我们打开已经存在过的数据,我们需要再处理数据,将其转会我们能用的,例如我们得把type=3的股票保存到quoteList、把股票和文案按我们输入的顺序展示。

最后

昨天说股票要兼容美股,自己忘记了,那么正则表达式又需要再修改

如果在开发的紧张时刻,一定要保持(强迫)自己冷静,滤清代码和业务逻辑思路,可以写在本子上,可以有一个更好的逻辑方向。

这一块前前后后出了不少错误,这几天还在修复存在的bug,到今天可能算是结束了,看着自己写的代码和情况,说实话有些沮丧,很多很基本的检查都没有做,存在简单的错误,没有最开始的谨慎仔细了。

有一个事情挺可笑,看了许多想学的技术,想想自己掌握的样子,很兴奋,可是到现在也只是在收藏夹吃灰罢了,没啥行动,即使有也断断续续。

如果可以,告诉自己请按时离开自己的舒适区。