One-week landing JD E-card Spring Festival multi-end marketing gameplay

three questions

  1. Fast project delivery: CodMi-M solution application

  2. Multi-terminal interactive solution output

  3. Multiplayer seamless collaborative exploration

First, use a picture to understand the product requirements

Because the development time for this requirement is only one week, and the development and the visual draft are simultaneously output, we need to invest multiple people into the development at the same time, so it is very important to understand the requirements and split the modules well, which is very important to whether we can deliver the project on time.

Before entering the development, we tried to draw a picture (drawing on the unified language of DDD) - auxiliary division of labor and students at each node to quickly check; at the same time, the known risk points were directly displayed to the product side.

The left part is the delivery end and adaptability, the red part is the risk we foresee; the right part disassembles the interaction flow of the entire product, and provides technical solutions in node interaction.

After such disassembly, each student only needs to pay attention to their own parts and the ability to adapt during development.

Mini Program Interactive Jump Logic

Next, let's take a look at the implementation of each end, how to quickly deliver the project in one week.

Implementation of H5 main activity page

Focus on problem solving 1. Fast project delivery: CodMi-M solution application

Application of CodMi-M

CodMi-M is a set of general solutions for mobile H5 based on our mobile terminal development in the past two years.

Based on the scaffolding CodMi, it focuses on the encapsulation of the application layer, and integrates the sdk and api encapsulation commonly used in the site, so that developers can focus more on business logic.

In this project, the development of the H5 part uses CodMi-M to quickly build the activity page.

Application of CSS Modules

Sometimes the styles we write will inadvertently affect the CSS of other styles, but we don't find them in time. Or when we write the style, it does not take effect, and the phenomenon of overwriting occurs inexplicably. Questions like these, as our project grows and more developers are involved, make people more and more desperate.

Therefore, we use the CSS Modules approach to avoid these problems as much as possible.

import styles from "./style.module.scss";
const RedEnvelope = () => {
return (
 <div className={styles.envelopeCover}>xxx</div>
)
}
export default RedEnvelope;
复制代码

But writing this way, some friends will say:

  • Every time you need to use camel case for naming

  • It is too troublesome to refer to the styles object to write styles every time

  • Mixing CSS modules with global CSS classes can be difficult to manage

  • References to undefined CSS modules do not give warnings

ok, it is indeed a bit inconvenient to say so, so here I will take you to upgrade again.

使用react-css-modules来解决上面css modules的问题
import React from 'react';
import CSSModules from 'react-css-modules';
import styles from './table.css';

class Table extends React.Component {
    render () {
        return <div styleName='table'>
            <div styleName='row'>
                <div styleName='cell'>A0</div>
                <div styleName='cell'>B0</div>
            </div>
        </div>;
    }
}

export default CSSModules(Table, styles);
复制代码

这样的话,通过我们使用react-css-modules:

  • 不必再强制使用驼峰式了

  • 无需在styles每次使用CSS模块引用该对象

  • 当引用未定义的CSS模块会收到警告

  • 全局 CSS 和 CSS 模块之间有明显的区别,例如:

<div className='global-css' styleName='local-module'></div>
复制代码

组件化管理及组件实现

组件化管理虽然是老生常谈的话题了,但确是极其重要的,尤其在项目工期紧且多人协作开发的过程中。

首先把页面先拆分成了5个独立组件,5个组件基本上互不影响。这样整个红包活动,只需要在首页配置好具体的组件入口即可,负责具体某个楼层的同学便可以随时进入开发阶段。

获奖者列表组件的实现

例如获奖者列表组件便独立开发,而且完全独立自主进行设计。

为了提供活动的氛围感和互动感,在产品形态上设计了获奖者列表,每次进入页面加载获奖者前100位进行滚动。本次需求中的获奖者列表采用无缝滚动方式实现。

目前无缝滚动的算法是将原有数据复制一份,当滚动到复制数据区域时,将滚动重置为初始状态,例如:

Winner
======
Winner
======
复制代码

在上述例子中,’======’包裹的范围我们称之为可视区,超过其包裹范围则内容不可见。上例中是仅有 1条有效数据的滚动状态,由于仅有 1 条数据,我们对这一条数据进行复制,当滚动到AB的复制数据且css 滚动效果结束,我们要马上重置滚动状态为初始状态:

======
Winner
======
Winner
复制代码

本次需求获奖者列表的可视区域仅有一条数据展示,所以我们可以仅将数据列表的第一条数据追加到尾部。

[0,1,2,3,4] // 原始数据列表
[0,1,2,3,4,0] // 复制后的数据列表
复制代码

接下来是实现动效,动效的实现主要借助 setTimeout 和 css transtion:

// tsx
<div onTransitionEnd={handleTransitionEnd}>
  [0,1,2,3,4,0].map(item => <div>item</div>)
<div>

// js
const transitionTimer = () => {
  const delayTime = 2000;
  window.setTimeout(() => {
    // 计算 tranformY 的值
    const y = calculateTranformY();
    // 设置到 style 上
    setTranformYToCSS(y);
  }, delayTime);
};
const handleTransitionEnd = () => {
  if (isNeedResetTransition()) {
    resetTransition();
  }
  transitionTimer();
};
复制代码

常量的提取

整个红包项目逻辑上最复杂的也就是活动状态和用户状态的区分匹配了,用户状态分为:初始状态、助力状态、可开奖状态和已开奖状态。活动状态分为:初始状态、进行中状态、结束状态和异常状态。

而我们要做的就是根据每一个不同的用户状态和每一个不同的活动状态,匹配出不同的页面状态,那么整个项目在设计上就需要提前思考好。

由于不同的框架组件,可能都需要进行状态匹配,这里首先要做的就是对于常量先进行提取,封装在最外层,各组件可以随时调用。

// common/constants.ts
export const USER_STATUS = {
  InitialUserStatus: 1, // 初始状态
  HelpUserStatus: 2, // 助力状态
  CompleteUserStatus: 3, // 可开奖状态
  EndsUserStatus: 4 // 已开奖状态
};
export const STATUS = {
  ProgressStatus: 2, // 进行中状态
  EndsStatus: 4, // 结束状态
  ErrorStatus: 5, // 异常状态
};
复制代码

这样不仅减少了组件中一大堆令人看不懂的数字,提高了维护性和可读性。而且组件之间调用相同的常量状态,较少因为笔误,将状态匹配书写错误。

小程序的实现

本次需求有礼小程序中无新增页面,但需要在现有若干界面中进行改造,需要控制部分元素的显示与否、部分界面新增相关楼层等;同时考虑到春节活动的用户量及用户体验,需要对首页中多tab商品楼层加载缓慢导致首页卡顿问题进行修复。

  1. 梳理需求及代码的过程,也是综合考虑新增楼层标识的过程

前后端同时进入开发,在开发前的综合考虑以及接口沟通至关重要。

由于部分界面需要根据礼品卡的标识新增不同的楼层,有些楼层只需判断是否为春晚红包活动,而有些还需要区分普通主题还是活动期间的主题,此时就需要前后端在开发前一起综合考虑礼品卡的标识,之后根据标识各自进入开发。

  1. 新增功能类似,对方法进行封装而不是粘贴复制

多个新增楼层涉及到页面跳转,此时不是在页面间粘贴复制而是对方法进行了封装以兼容不同的情况。

function gotoActivity(url) {
  let jumpUrl = url;
  if (jumpUrl && jumpUrl.indexOf("http") == -1) {
    jumpUrl = `https:${jumpUrl}`;
  }
  if (jumpUrl) {
    let url = '/pages/login/wv-common/wv-common?h5_url=' + encodeURIComponent(jumpUrl)
    wx.navigateTo({
      url,
    });
  }
}
复制代码
  1. 通过微信开发者工具自带的mock功能模拟接口数据以减轻后期接口联调压力。

多端交互的实现

关注解决问题2: 多端交互方案输出

本次视觉稿时间和前端时间部分重合,正好可以利用此空档做多端交互的调研方案。整个流转里有两个主体,1是H5活动页,用来引流;2是京东有礼小程序里的拼手气页面,即主体页面。

从图中拆解为以下几步:

  1. 从JD APP的“H5活动页”直接跳转到京东有礼小程序“拼手气页面“;
  2. 从JD APP的“H5活动页”分享到微信会话框;
  3. 从微信会话框打开微信小程序,并定位到京东有礼小程序里的 H5 活动页;【在第二步中,只要设置好小程序id和路径,微信会处理这次的跳转。】
  4. 从微信京东有礼小程序里的 H5 活动页,打开有礼小程序“拼手气页面”。

同时复用老的批量绑卡的逻辑,以及实现有礼小程序里的登录态的打通。

我们这里关注多端交互的实现方法。

跳转1. 从JD APP的“H5活动页”直接跳转到京东有礼小程序“拼手气页面“

因为原生与H5之间有时需要主动交互,例如H5去使用调用原生的功能(比如拍照等),原生去唤起通知H5事件等,所以这里我们借助京东商城WebView,来为我们的红包活动的H5提供了丰富的定制化的能力。

export const gotoMP = (id: string) => {
  //跳转至小程序
  const u = navigator.userAgent;
  let jsonParams = {
    businessType: "jumpToMiniProgram", //string类型,固定字段,必须是这个
    callBackName: "cb", //string类型,h5用来接收callback的方法名称,如h5想在window.callback(jsonStr) 方法中接收回调,此项传值为"window.callback"
    params: {
      username: "gh_xxx", //填小程序原始id(有礼小程序)
      path: `pages/xx/xx?id=${id}`, //拉起小程序页面的可带参路径,不填默认拉起小程序首页
      miniProgramType: 0, //可选。打开开发版,体验版或正式版
    },
  };
  const jsonString = JSON.stringify(jsonParams);
  if (!!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)) {
    //iOS
    window.webkit.messageHandlers.JDAppUnite.postMessage({
      method: "notifyMessageToNative",
      params: jsonString,
    });
  } else {
    //Android
    window.JDAppUnite && window.JDAppUnite.notifyMessageToNative(jsonString);
  }
};
复制代码

这段代码基本可以拿去直接使用,完成从JD APP 跳转到 小程序的实现。几点注意:

  1. 这里要区分好iOS的环境和Android环境,两者调用方式存在差异。

  2. 跳转到微信小程序的jsonParams对象下的params中,有个miniProgramType属性。这里0是跳转到线上开发版,2是跳转到体验版

  3. 对于ts的警告Property 'webkit & JDAppUnite' does not exist on type 'Window & typeof globalThis',我们需要在xxx.d.ts中进行全局interface Window的声明。

跳转2. 从JD APP的“H5活动页”分享到微信会话框

这里我们借助京东App的分享组件@jmfe/jm-jdshare,来为我们的H5 页面提供简洁的客户端分享接口。

此jnpm不仅支持分享,也支持京口令的功能,感兴趣的童靴可以去查看下:npm.m.jd.com/package/@jm…

import jdShare from "@jmfe/jm-jdshare";
jdShare.setShareInfo({
  title: "快来!你即将错过1888元京东E卡!",
  content: "好友心意专递 速来领取",
  url: window.location.href,
  img: "https://img10.360buyimg.com/imagetools/jfs/t1/175484/6/25230/10720/61d3e626Eac21a76e/de6be01ec69895cd.jpg",
  /**
    * 以下非必填
    */
  channel: "Wxfriends",
  callback: null,
  clickcallback: null,
  qrparam: null,
  keyparam: null,
  timeline_title: "",
  showFriendList: "",
  /**
    * 以下是小程序参数与上面的参数没有关联
    */
  mpId: "gh_xxx",
  mpIconUrl:
    "https://img12.360buyimg.com/imagetools/jfs/t1/101710/27/20890/155471/61e52ebdE1e249fe6/e70a71969319eaa7.jpg",
  mpPath: `pages/login/wv-xx/wv-xx?h5_url=${encodeURIComponent(
    window.location.href.replace("#/", "&source=YLWX"),
  )}`,
  mpType: "0",
  /**
    * 以下是分享有礼参数
    */
  // incentiveBizType: "1",
  // incentiveBizId: "INCENTIVEBIZID_DEMO",
});
复制代码

同样,这段代码也是可以直接拿去使用的一段代码片段。需要注意的是:分享到微信小程序的卡片中,有个mpType属性。为0,点击卡片进入到线上开发版,为2进入到体验版。

跳转3. 从微信京东有礼小程序里的 H5 活动页,打开有礼小程序“拼手气页面”

这里我们借助微信官方的web-view,来作为承载网页的容器。其作为开放能力,官方也是给我们提供了相关的方法(wx.miniProgram.navigateTo)。

这里要注意:跳转的路径最前面要有/,亲测如果没有/的话,根本就跳转不过去。

// <script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.3.2.js"></script>

// javascript
export const toGiftMiniProgram = (id:string)=>{
  wx.miniProgram.navigateTo({url:`/pages/xx/xx?id=${id}`})
}
复制代码

半路杀进项目,如何快速了解并响应需求?

Focus on solving problem 3: how to add people quickly, and the effect of +1>2 after adding people.

The first must be "good design + componentized module management", which has laid a solid foundation and will not be repeated.

This part focuses on the work and experience of the new students who entered the project halfway.

Project understanding

The schedule of this project is relatively tight, and there are few initial participants. In order to ensure the normal progress, the intervention of developers was increased halfway. The first thing to do is to quickly understand the basic information such as project background, visual design progress, key nodes (development, testing, and launch).

Possible problems and solutions

This development is responsible for the rendering of the two banner lists at the bottom of the activity page, and the data comes from the ace interface. To get the task, first grasp a few points:

  1. The tasks involve a range of tasks. For front-end developers, they need to understand the connected product requirements, visual design, data interfaces and test cases. For example, this development task is rendered by two independent banners, and the data only depends on the ace interface, and does not involve handover with the back-end personnel. For this requirement of independent logic and low data dependence, we can immediately start development.

  2. Corresponding to the development progress of prd and visual draft. If the process is unclear, the visuals change frequently or may be revised later. Then you must actively communicate with the product visually, and confirm the logic and visual draft. And do a good job.

  3. Pages are also components. For projects, the mapping of the overall architecture can be reflected in the routing design. Developers need to confirm whether the current logic is stored on the page alone or referenced by other pages as a component. For example, two banner lists only need to be written as components.

  4. personnel communication. The efficiency of the docking personnel and the reliability of the information determine the development progress. If necessary, communication efficiency can be improved through the joint development of offline conference rooms.

Summarize

The unified language is borrowed from DDD and displayed in the form of a diagram, and the general solution of CodMi-M plays a key role in this time; when the function is realized, a slot is reserved to facilitate the integration of multi-component access, and it is also convenient for multiple people. Support projects with less stress.

At the same time, in the project, the realization of various components and the scheme of interactive jump are precipitated.

The most important thing is that the project can be delivered within 1 week, and some technical precipitation and thinking about the delivery of such projects in the future have also been done.

I would like to thank the small partners in the group for their cooperation on this article~

Guess you like

Origin juejin.im/post/7085310702428094477