基础框架

[toc]

框架优化/升级方案

为了有更好的用户体验,我们提出以下优化和升级方案。

白屏体验

网络恢复

一、可能的初始”白屏”(可选)

1、场景

页面无任何占位视图。如页面本身就是一个列表。

页面数据来源于网络,网络请求回来前,空。

2、处理方案及实现方式

主要有以下两种方案,各自独立,分场景使用。

①界面框架预染页(美团/饿了么的灰底效果)

②数据预加载(首页)

2.1、处理方案:界面框架的预染页:美团/饿了么的灰底效果(如商品详情页)

2.1.1、方案描述

美团/饿了么的灰底效果(如商品详情页)

2.1.2、实现方式
1
2
3
4
5
6
7
8
9
// bad
return realWidgets(data: netdata); // netdata 可能为空,导致页面空白

// good
if (data == null) {
return nodataWidgets(); // 页面预览页
} else {
return withdataWidgets(data: data);
}

2.2、数据预加载(根据需要)

当realWidgets中的数据全部来自网络时候,也有白屏的可能,如列表,如需确实有界面框架显示,使用如下方式:

  • 初次冷启动:

    使用与产品约定的默认数据来加载

  • 其他:

    保存缓存数据,下次使用缓存数据来加载

3、工期预算

框架接入 2d

二、请求结束后的”白屏”(必须)

1、场景

②处理请求后的场景:文字提示+页面展示(无数据+无网络)

2、处理方案及实现方式

2、网络异常:

为页面提供网络异常页并伴有刷新恢复重试

3、工期预算

框架接入 2d

三、网络异常(提示+恢复)

2.1、文字提示

根据情况,弹出易于用户理解的错误提示

  • 接口问题:服务器开小差了,请稍后重试

2.2、界面提示(实现网络恢复后能再显示正确界面)

1
2
3
4
5
6
7
8
9
10
11
// bad
return successWidget();

// good
if (ApiResult.type == error) {
return errorWidget();
} else if (ApiResult.type == nodata) {
return nodataWidget();
} else {
return successWidget();
}

四、程序异常(上报+提示)

接入bugly服务+自定义异常页

接入第三方bugly华为AGC的崩溃服务

默认的程序异常页 VS 处理后的程序异常页

默认的程序异常页 处理后的程序异常页

程序异常上报后的后台:

程序异常上报后的后台

工期预算

异常上报 1d

五、测试问题反馈与排查优化

1、新增查看版本页面

新增查看版本页面,方便对应反馈的问题出现的版本(防止是旧包)。

2、新增抓包设置(代理)

新增代理设置,方便接口人员抓包排查

六、视觉体验优化

定义加载动画loading

愿望灯动画效果优化(底部下沉)

1、Loading自定义

UI提供 images 或 json,自定义loading动画

2、愿望灯

采用上层愿望灯不变,底部进行下沉动画来实现愿望灯上飘的效果

3、Toast自定义

图层

七、开发规范优化

1、用户操作/页面形态展示优化

1、入口的点击

内部界面

  • 开发中/已实现:

    点击后直接进入,并展示

  • 待开发:

    点击后,弹出”将进入XXX功能,其待开发中”

  • 产品未规划:

    不显示该入口

2、h5白屏

重定向

域名切换:tke

八、接口请求优化:接口拆分

通过页面分析,与产品和后台确认哪些页面需要进行接口拆分。

目前可能需要处理的有:

  • 商品详情页

框架实现拆分项

1、是否显示加载动画isLoading

1.1、loading动画(images 或 json)

使用 image 或 json 实现loading动画

1.2、含loading显示控制的页面组件

1
static void showLoading(bool show);

2、页面状态PageType

2.1、加载结束不同页面状态页面组件

编号 页面状态PageType 功能 人日
1 加载失败 errorWidget 0.25
2 加载成功,但无数据 nodataWidget(含”重新加载”操作) 0.5
3 加载成功,且有数据 successWidget 0

2.2、含页面状态控制的视图组件

通过传入不同的状态,显示不同状态下的页面

3、请求

5、含状态管理的页面基类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
int currentPageType = successWidget; // 默认的状态页面
bool showLoading = false; // 是否显示加载动画

return pageTypeWidget(pageType: currentPageType, showLoading: showLoading);


// 开始请求
showLoading = true;
setState(() {});
apiRequest.then((value) {
_xxxBean = value;
showLoading = false;
if (value == null) {
currentPageType = nodata;
} else {
currentPageType = success;
}

// setState(() {
//
// });
disabledLoading();
}).catchError((onError) {
currentPageType = error;
});


// 请求结束
showLoading = false
if (ApiResult.type == error) {
currentPageType = error;
} else if (ApiResult.type == nodata) {
currentPageType = nodata;
} else {
currentPageType = success;
}
setState(() {});

待安排优化

1、网络库升级

重构及增加错误码友好提示处理 1d

2、基类新增处理

1
2
3
4
5
6
7
8
>  Visibility 隐藏/可见,能保存组件的状态;Offstate不能保存组件的状态,组件重新加载
> * 控制child是否显示
> *
> 当offstage为true,控件隐藏; 当offstage为false,显示;
> 当Offstage不可见的时候,如果child有动画等,需要手动停掉,Offstage并不会停掉动画等操作。
>
> const Offstage({ Key key, this.offstage = true, Widget child })
>
  • 网页加载库替换,新增错误码监听,统一js
  • 基础框架新增背景设置及修复有背景时候界面显示问题,error/nodata新增color设置,用于设置透明
  • 基础框架新增unkonw类型,兼容有无初始显示界面的设置
  • 基础框架优化appbar设置,及提供最简易常用的导航栏
  • Mock api 新增缓存功能
  • Bruno接入及编译修复
  • 版本升级管理
  • 数据缓存处理
  • 精选愿望单原型开发完成,待联调
  • 新增百愿清单原型开发完成,待联调

3、App快速实现置灰样式

App快速实现置灰样式

iOS整个APP实现灰色主题的示例代码

白屏:

①处理请求前的场景:数据预加载+框架预染页(美团/饿了么的灰底效果)

②处理请求后的场景:文字提示+页面展示(无数据+无网络)

2、网络异常:

为页面提供网络异常页并伴有刷新恢复重试

3、程序异常(上报+提示):

接入bugly服务+自定义异常页

4、视觉体验优化

定义加载动画loading

愿望灯动画效果优化(底部下沉)

5、测试优化

新增查看版本页面,方便对应反馈的问题

新增代理设置,方便接口人员抓包排查

6、其他

AA送礼:提测,待测试验证后,如有问题修复

开发者账号申请审核未通过,正在处理。 (因为域名问题被拒,新域名已经准备好了,在跟apple沟通中)

下周:

继续我的模块开发,联调接口。

在完成”我的”模块或等待接口情况下,评估及开发产品规划的其他功能。

目前:

框架升级(白屏、预览页灰底、网络刷新恢复页,异常上报及异常页):今天

愿望灯 ok
许个愿 ok
我的:部分在联调,部分在等接口
AA送礼:提测,待测试验证后,如有问题修复

loading
开发者账号申请审核未通过,正在处理。 (因为域名问题被拒,新域名已经准备好了,在跟apple沟通中)

基础框架

[toc]

框架的接入

为了有更好的用户体验,我们对页面框架进行如下优化。

页面框架

1、页面头appbar、页面身successWidget

1、错误页和空白页的页面,需要自定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import 'package:flutter_effect/flutter_effect.dart';

// 修改地方1.1继承: BJHBasePage
//class TSBasePage extends StatefulWidget {
class TSBasePage extends BJHBasePage {

}

// 修改地方1.2继承: BJHBasePageState
//class _TSBasePageState extends State<TSBasePage> {
class _TSBasePageState extends BJHBasePageState<TSBasePage> {

// 修改地方2.0:删除/注释掉原来的 Widget build(BuildContext context){}
//@override
//Widget build(BuildContext context) {
// return Scaffold(
// backgroundColor: Color(0xffF0F0F0),
// appBar: appBarWidget,
// body: bodyWidgets,
// );
//}
// 修改地方2.1:将其中的导航栏 appBarWidget 通过 PreferredSizeWidget appBar() {} 返回
// 当你的导航栏是使用系统的AppBar时候,重写appBar()方法,如
@override
PreferredSizeWidget appBar() {
return AppBar(
title: Text("导航栏标题"),
);
}
// 当你的导航栏不是使用系统的AppBar,而是自己在page上添加的Widget的时候,重写 Widget appBarWidget(BuildContext context)方法,如
@override
Widget appBarWidget(BuildContext context) {
return EasyAppBar(
title: '我是成功页面的标题',
);
return CommonAppBar(
title: AppBarTitleWidget(text: '我是成功页面的标题'),
leading: AppBarBackWidget(
onPressed: () {
Navigator.pop(context);
},
),
);
}

// @override
// Color backgroundColor() {
// return Color(0xFFF0F0F0);
// }

// 修改地方2.2:将其中的 bodyWidgets 通过 Widget buildSuccessWidget(BuildContext context) {} 返回,则当前调用 updateWidgetType(WidgetType.SuccessWithData); 的时候,其会将视图更新为该方法返回的样式
@override
Widget buildSuccessWidget(BuildContext context) {
return bodyWidgets;
}

// 修改地方2.2:自定义【请求成功,但无数据】的界面
@override
Widget buildNodataWidget(BuildContext context) {
return StateNodataWidget(
image: AssetImage('assets/images/nodata.png')
mainTitle: '我是【请求成功,但无数据】的界面',
subTitle: '',
);
}

// 修改地方2.3:自定义【请求失败】的界面
@override
Widget buildErrorWidget(BuildContext context) {
return StateErrorWidget(
//color: Colors.transparent, //可设置背景色,常用语本page有设置背景图片的时候
errorRetry: getData,
);
}


// 请求网络的方法名可任意(不再需要保证为getData,因为错误页和空白页的重新加载需要在本dart文件设置)
void getData() {
...

// 修改地方4:对返回的数据进行判空及更新状态
Api.getGoodsInfoList({}).then((ResultData data) {
if (data.isSuccess) {
...

// 修改地方4.1:对请求到数据,且状态正确的数据进行判空及更新状态
if (bean == null) {
updateWidgetType(WidgetType.SuccessNoData);
} else {
updateWidgetType(WidgetType.SuccessWithData);
}

} else {
// 修改地方4.2:对请求到数据,但状态错误的处理
//updateWidgetType(WidgetType.ErrorBusiness);
}
}).catchError(onError) {
// 修改地方4.3:对请求失败,如服务器崩溃,无网络等的处理
updateWidgetType(WidgetType.ErrorNetwork);
};
}

}

2、初始界面buildInitWidget

其他,如果你还想设置初始页面,目前初始视图默认是空白视图

1
2
3
4
5
6
7
8
9
10
11
12
@override
Widget buildInitWidget(BuildContext context) {
return Container(
color: Colors.green,
height: 100,
child: Text(
'我是初始视图...',
style: TextStyle(color: Colors.blue, fontSize: 24),
textAlign: TextAlign.center,
),
);
}

3、背景色、背景图片

设置背景图片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 背景视图(常用来设置背景图片)
@override
Widget backgroundWidget(BuildContext context) {
// 设置背景色
return Container(
color: Color(0xFFF0F0F0),
);

// eg1:设置铺满的背景图片
// return Container(
// alignment: Alignment.topCenter,
// //color: Colors.yellow,
// constraints: const BoxConstraints(
// minWidth: double.infinity,
// minHeight: double.infinity,
// ),
// child: Image.asset(
// "images/wish/bg_icon.png",
// fit: BoxFit.fitWidth,
// ),
// );

// eg2:设置绝对定位的背景图片
// return Positioned(
// top: 0,
// right: 0,
// left: 0,
// height: Adapt.px(678),
// child: Image.asset(
// "images/wish/bg_icon.png",
// fit: BoxFit.fitWidth,
// ),
// );
}

End

编译优化hmap

编译优化hmap

[toc]

一、查看编译时间

Clean后,执行Command+B,查看编译时间为24.0seconds

image-20211124154515792

而如果编译后,不Clean,继续执行编译,即使用之前的编译缓存,得到的新的编译时间为0.6seconds

image-20211124154752653

二、hmap优化的结果

系统的Pods中Headers里有Public和Private目录:

image-20211124155017822

使用 plugin ‘cocoapods-hmap-prebuilt’ 后

image-20211124155617317

在Pods中Headers里会多出一个HMap目录,里面的文件为hamp,如下截图所示:

image-20211124155527016

此时,我们重新Clean,然后编译,得到的优化后的编译时间为16.8seconds

image-20211124155414548

如果编译后,不Clean,继续执行编译,得到的时间为0.5seconds,也比之前的0.6seconds短

image-20211124155945171

三、hmap优化怎么使用

我们直接使用 cocoapods-hmap-prebuilt

1、cocoapods-hmap-prebuilt的使用方法

直接在你的Podfile中,添加以下一行代码就行

1
2
3
4
5
6
# this is part of Podfile
target 'XXX' do
plugin 'cocoapods-hmap-prebuilt' # 添加此行代码就行
pod 'XXX'
...
end

之后,你和平时一样执行pod install就行。

2、安装cocoapods-hmap-prebuilt

如果你没安装cocoapods-hmap-prebuilt,则会在执行pod install的时候,发生如下错误:

image-20211124161907639

所以请先安装,安装方法如下:

1
gem install cocoapods-hmap-prebuilt

image-20211124162055386

之后,你和平时一样执行pod install就行,执行过程中,会多出如下输出:

image-20211124165627186

三、coapods-hmap-prebuilt介绍

以下内容摘自:一款可以让大型iOS工程编译速度提升50%的工具

cocoapods-hmap-prebuilt 是美团平台迭代组自研的一款 cocoapods 插件,以 Header Map 技术 为基础,进一步提升代码的编译速度,完善头文件的搜索机制。

四、Header Map 是个啥?

Header Map是二进制文件,其包含头文件和头文件路径的映射表。

其核心功能是让编译器能够找到相应的头文件的位置,相较于使用header search path提供的路径查找会快很多

1、Hmap在编译后的文件路径

我们编译后,通过Products,找到生成的app的目录,如下图:

image-20211124165159982

在其中,我们找到Intermediates.noindex目录下的Pod.build

image-20211124165909673

2、hmap查看工具

我们通过hmap查看工具来输出下hmap文件的内容。

1
hmap print Masonry-all-target-headers.hmap

输出内容如下:

image-20211124170212021

附:该hmap工具的安装方法,如其github上的How to use一样,使用如下一行命令,在终端中执行即可。

1
brew install milend/taps/hmap

五、Xcode 编译的其他相关知识

Xcode 编译相关

End

iOS功能-Transform

关于CATransform3D

参考文章:关于CATransform3D

CATransform3DMakeRotation的使用

1
2
3
4
5
6
7
/* Returns a transform that rotates by 'angle' radians about the vector
* '(x, y, z)'. If the vector has length zero the identity transform is
* returned. */

CA_EXTERN CATransform3D CATransform3DMakeRotation (CGFloat angle, CGFloat x,
CGFloat y, CGFloat z)
CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);

angle:旋转角度
后面的x,y,z三个值组合表示坐标系里面的一个点(x,y,z),由原点和该点(x,y,z)形成一条旋转轴

CATransform3DMakeRotation是按最短路径来选择的

示例:CATransform3DMakeRotation逆时针

Git Commit规范

Git Commit规范

4. Commit 规范

摘自:https://mini.ant.design/

开发过程中,提交 commit 时,需要遵循以下原则:

  • 最小化代码变更:保证每个 commit 的逻辑独立、原子化。一个 commit 只做一件事,哪怕这件事只改了 1 行代码,你也应该独立 commit 这次变更;
  • 遵循 Conventional Commits 原则:避免没有意义、看不懂的 Commit Message 引入,并且在代码提交的时候会有 Commit Message 格式校验。一般情况下,你会大量的使用到:
    1. 使用 feat(scope): xxx 来描述一个 feature 的 commit;
    2. 使用 fix(scope): xxx 来描述一个 bug fixes 的 commit;
    3. 使用 chore(scope): xxx 来来描述一个无关 feature 和 bug fixes 的小调整;
  • issue:如果改动与 issue 相关,请在 Commit Message 中带上 issue 参数,如:fix(scope): [#1] xxxxxx;

Commitizen, Husky, Commitlint

 先简要地介绍这三个工具的作用,让大家对整个校验过程如何实现有一个大体的了解。

  • Commitizen:是一个命令行提示工具,它主要用于帮助我们更快地写出规范的commit message
  • Commitlint:用于校验填写的commit message是否符合设定的规范
  • Husky:是一个git hook工具,用于在提交过程中的某个特定时刻触发commitlint

iconFont

一、Iconfont

阿里巴巴矢量图库:https://www.iconfont.cn/

设计师将图标上传到Iconfont平台,用户可以自定义下载多种格式的icon,平台也可将图标转换为字体,便于前端工程师自由调整与调用。

1、iconfont VS 图片 优势

iconfont和图片相比有如下优势:

  • 1.体积小:可以减小安装包大小。
  • 2.矢量的:iconfont都是矢量图标,放大不会影响其清晰度。
  • 3.可以应用文本样式:可以像文本一样改变字体图标的颜色、大小对齐等。
  • 4.可以通过TextSpan和文本混用。

iconfont即“字体图标”,它是将图标做成字体文件,然后通过指定不同的字符而显示不同的图片。

效果如下图:控制不同颜色和大小的icon。

image-20220318235832369

2、iconfont 资源下载方式

Iconfont 图标需要使用SVG资源,获取资源的几种方式

下载选择图片

img

二、iconfont在Flutter中的使用

Flutter中,可以像Web开发一样使用iconfont。

1、下载iconfont

2、将文件中的 .json .ttf 添加到项目中

实际建议将整个iconfont解压出来的文件都添加到项目中。主要原因有:

①更新时候,直接整个覆盖,避免内部子文件不对等

②设置icon时候,除了打开json看到图标名,还可以打开html,看到所有图片的整体。

img

3.配置(配置时候注意格式)

这里 family后面的IconFont是自定义的名字,可以自行改成想要的,后续需要用到这个family。

img

4.生成dart文件

1、手动方式:

1
2
3
4
5
6
7
8
9
import 'package:flutter/material.dart';

class AppIcon {
static const __FONT_NAME__ = 'iconfont';
static const IconData icon_dianzan = IconData(0xe612, fontFamily: __FONT_NAME__); // 点赞
static const IconData icon_zhuanfa = IconData(0xe60c, fontFamily: __FONT_NAME__); // 转发
}

// 其中 IconData(0x 后的 e612 的这个值可以从json或html文件中或取

2、自动方式(脚本):

①、脚本内容

iconfont_dart.py(其中变量IconDart,IconCss 根据实际情况可做更改)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# coding: u8
import re
from pathlib import Path
import time
ROOT = Path(__file__).resolve().parent
MAIN = ROOT
# 生成的IconFont.dart 文件路径
IconDart = 'lib/common/style/IconFont.dart'
# iconfont css 文件存放路径
#IconCss = 'assets/iconfont/iconfont.css'
IconDart = 'IconFont.dart'
IconCss = 'iconfont.css'
# 将 iconfont 的 css 自动转换为 dart 代码
def translate():
print('Begin translate...')

code = """
import 'package:flutter/widgets.dart';

/// @author: hsc
/// @date: {date}
/// @description 代码由程序自动生成。请不要对此文件做任何修改。

class IconFont {

static const String FONT_FAMILY = 'IconFont';

{icon_codes}

}
""".strip()
strings = []
content = open(MAIN / IconCss).read().replace('\n content', 'content')
matchObj = re.finditer( r'.icon-(.*?):(.|\n)*?"\\(.*?)";', content)
for match in matchObj:
name = match.group(1)
name = name.replace("-","_")
string = f' static const IconData {name} = const IconData(0x{match.group(3)}, fontFamily: IconFont.FONT_FAMILY);'
strings.append(string)
strings = '\n'.join(strings)
code = code.replace('{icon_codes}', strings)
code = code.replace('{date}', time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
open(MAIN / IconDart, 'w').write(code)
print('Finish translate...')

if __name__ == "__main__":
translate()
②、脚本执行python3 iconfont_dart.py

image-20220319012403867

执行结果如下,生成了IconFont.dart文件:

image-20220319012857584

其他脚本参考:

二、png转svg格式并上传至iconfont

实现方案:

  1. 下载转换工具inkscape
  2. 登录阿里图标上传svg

一、inkscape

https://inkscape.org

image-20220318192601125

image-20220318192634755

image-20220318192650833

image-20220318204002050

image-20220318205057886

image-20220318205202062

image-20220318205304361

image-20220318205348852

Mock基础知识

[toc]

Mock基础知识

一、常用整理

常用整理

类型 占位符 输出值
生日 @date 1990-01-01
性别 @integer(0,2) 0-2之间的随机值
身高 @float(140,220,1,1) 小数位数为1个的140-220之间的随机值
学校 @pick([‘清华大学’, ‘北京大学’, ‘哈尔滨工业大学’, ‘国防科技大学’])
家乡 @city(true) 省+市

二、常用占位符功能详述

@integer(min?, max?)

返回一个随机的整数。

  • min:可选参数,整数最小值。
  • max:可选参数,整数最大值。

例:

1
2
3
4
5
@integer
//--> 1686805249110932
@integer(10,100)
//--> 26
1234

@float( min?, max?, dmin?, dmax? )

返回一个随机浮点数。

  • min:可选,整数部分最小值。
  • max:可选,整数部分最大值。
  • dmin:可选,小数部分最小长度。
  • dmax:可选,小数部分最大长度。

例:

1
2
3
4
5
@float
//--> 1924364975802932.5
@float(60, 100, 2, 6)
//--> 68.1258
1234

@string

返回随机字串,有如下几种使用方式:

1
2
3
4
5
6
@string
@string(length)
@string(pool, length)
@string(min, max)
@string(pool, min, max)
12345
  • length: 字串长度
  • min: 字串最短长度
  • max: 字串最大长度
  • pool:表示字符池。如果传入 ‘lower’、‘upper’、‘number’或’symbol’,表示从内置的字符池从选取。对应关系如下:
1
2
3
4
5
lower: "abcdefghijklmnopqrstuvwxyz",
upper: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
number: "0123456789",
symbol: "!@#$%^&*()[]"
1234

例:

1
2
3
4
5
6
7
@string(6)
//--> kV(qj4
@string('upper',2,6)
//--> NJKU
@string('123abc!@#', 2,6)
//--> #ab!21
123456

@url(protocol?, host?)

随机生成一个 URL。

  • protocol:指定 URL 协议。例如 http。
  • host:指定URL域名和端口号。

例:

1
2
3
@url('https', '123.sogou.com')
//--> https://123.sogou.com/ccdkttr
12

@ip

随机生成一个IP地址。

@timestamp

返回当前unix时间戳

@datetime(format?)

返回一个随机的日期和时间字符串。

  • format:生成的日期和时间字符串的格式。默认值为yyyy-MM-dd HH:mm:ss。

例:

1
2
3
4
5
@datetime()
//--> 1977-11-17 03:50:15
@datetime('y-M-d H:m:s')
//--> 02-4-23 2:49:40
1234

@pick(arr)

从数组中随机选取一个元素,并返回。

例:

1
2
@pick(['this', 'is', 'picker', 'test'])
//--> picker

yapi的使用之入门篇

[toc]

yapi的使用之入门篇

一、模拟接口

如果你已在http://121.41.91.92:3000/上创建了对应接口,直接在接口path后,添加.toSimulateApi()实现,你重新请求的时候调用的是你模拟的api。

1
2
3
4
static String getVirtualList = "/account/wallet/virtualAsset/page"

//模拟时候,在字符串尾部加上`.toSimulateApi()`即可
static String getVirtualList = "/account/wallet/virtualAsset/page".toSimulateApi();

如果你未创建过接口,请查看如下接口的创建方法

二、新建接口

  • 点击左侧接口分组右侧的菜单按钮,选择 添加接口,或者点击接口列表右上角的 添加接口

img

  • 选择接口分类,输入接口名称和接口路径,点击 提交

img

  • 恭喜你!创建了第一个YApi的接口,你可以看到在左侧看到接口名称,右侧有该接口的信息预览。

三、注册

登录http://121.41.91.92:3000/进行注册,注册成功,管理员添加项目权限后,即可查看对应接口列表。如:

image-20211222151919051

End

yapi的使用之Mock篇

[toc]

yapi的使用之Mock篇2-类型修改

一、时间

编号 接口 变量 变量含义 原来为 修改为 备注
1 order/orderList
订单列表
orderTime 下单时间 string integer @timestamp
2 order/orderDetail
订单详情
deliveryTime
gmtCreate 2处
sendTime
orderTime
overTime
payTime
送达时间
创建时间
送出时间
下单时间
超时时间
付款时间
3 product/getGoodsDetailInfo
获取商品详情(包含爆品、精品)
homeRecoTime 首页推荐时间 string integer @timestamp
4 member/getMemberInfo
获取会员信息
startTime
endTime
会员有效期 - 开始时间
会员有效期 - 开始时间
5 wish/listByBuyId
用户心愿单列表查询
gmtCreate 创建时间
6 wish/listWatchWish
查询好友的心愿单列表
gmtCreate 创建时间
7 wish/getDetail
心愿单详情页
gmtCreate 2处
gmtModify 2处
statusUpdateTime
topTime 2处
创建时间
记录更新时间
状态更新时间
置顶时间
8 /user/queryUserWishCollect
查询愿望单收藏
gmtCreate 创建时间
9 product/getGoodsInfoList
获取商品列表(包含推荐,收藏,愿望,搜索推荐,分类)
categoryRecoTime
homeRecoTime
分类推荐时间
首页推荐时间

二、数字字符串

编号 接口 变量 变量含义 原来为 修改为 备注
1 wish/getDetail
心愿单详情页
progress.rate 愿望达成率 string string 40只能数字字符串
2 wish/listByBuyId
用户心愿单列表查询
progress.rate 愿望达成率 string string 40只能数字字符串
3 wish/listWatchWish
查询好友的心愿单列表
progress.rate 愿望达成率 string string 40只能数字字符串
4 /wish/listRecommendWish
查询推荐的心愿单列表
wishProgress.rate 愿望达成率 string string 40只能数字字符串

若非数字字符串,则会报以下错误:

yapi_mockjson_error1

三、Raw

用户心愿单列表查询

编号 接口 Raw旧值 Raw新值
1 user/saveUserLookTrack
保存用户足迹接口
OK {“type”:”object”,”title”:”empty object”,”properties”:{}}
2 social/operateFriend
关注/取消关注好友操作接口

四、Type Mock

用户心愿单列表查询

编号 接口 变量 变量含义 Mock值 备注
1 order/orderList
订单列表
orderInfoAndPayInfoDetailResps.orderInfoDetails.status 订单状态 @cjtsOrderType
2 order/orderDetail
订单详情
orderInfoDetails.status 订单状态 @cjtsOrderType
3 /social/pageWatched
分页查询已关注列表
watchStatus 关注方向 @cjtsFriendshipeType
4 product/getGoodsInfoList
获取商品列表(包含推荐,收藏,愿望,搜索推荐,分类)
businessType 商品类型 @goodBusinessType

End

yapi的使用之Mock篇

[toc]

yapi的使用之Mock篇

参考文章:

前言

Mock基础知识请查看本网站中的Mock知识篇

更多mock语法:请查看官网mock.js中的示例

一、Mock数据个数

指定数组返回的最小和最大个数:

yapi_mock_arraycount1

yapi_mock_arraycount2

二、Mock值

1、名字

定义如下:

1
2
3
4
5
6
7
8
// 中文名
Random.extend({
cjtsName: function(params) {
return Random.cname();
},
})

或者直接 @cname

2、Type Mock

定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 重要日子的信息内容
var allFestival =
'1.1元旦、1.23春节、2.14情人节、3.8 妇女节、5.1 劳动节、5.4青年节、6.1儿童节、7.1建党节、8.1建军节、9.10教师节、10.1国庆节、12.25圣诞节';
var festivals = allFestival.split('、');

Random.extend({
// 重要日子的信息内容
cjtsFestivaDateMessage: function(params) {
return this.pick(festivals)
},
})


var allImportantDay =
'1.1元旦、7天后生日、1.23春节、2.14情人节、3.8 妇女节、5.1 劳动节、5.4青年节、6.1儿童节、7.1建党节、8.1建军节、9.10教师节、10.1国庆节、12.25圣诞节';

常规:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
// 性别类型
var sexTypes = [
0, // 未知/未设置
1, // 男
2, // 女
];

// 订单状态
var orderTypes = [
10, // 待付款(取消订单+付款)
11, // 待送达(取消订单)
12, // 待送出(取消订单+催一下)
13, // 好礼在途(好礼进度)
14, // 好礼在途(好礼进度)
15, // 好礼送达(申请售后+晒单)
16, // 交易关闭(删除订单)
17, // 好礼送达(申请售后+晒单)
18, // 交易关闭(删除订单)
];

// 关注方向
var friendshipeTypes = [
0, // 未关注
1, // 已关注
2, // 互相关注
3, // 悄悄关注
];
// 重要日子类型
var importantDateTypes = [
'marry', // 结婚
'birthday', //生日
'festival', //节日
'anniversaryDay', //纪念日
];

// 商品类型
var goodBusinessTypes = [
'goods', // 正常的商品
'wish', // 许愿商品
];




Random.extend({
// 性别类型
cjtsSexType: function(params) {
return this.pick(sexTypes)
},

// 订单状态
cjtsOrderType: function(params) {
return this.pick(orderTypes)
},
// 商品类型
goodBusinessType: function(params) {
return this.pick(goodBusinessTypes)
},

// 好友关系
cjtsFriendshipeType: function(params) {
return this.pick(friendshipeTypes)
},
// 重要日子类型关系
cjtsImportantDateType: function(params) {
return this.pick(importantDateTypes)
},

// 价格(string或float):60.111/88.12345
cjtsIPrice: function(params) {
// Random.float( min, max, dmin, dmax )
return Random.float(60, 100, 3, 5);
},

// 数量(string或float):0-100000
cjtsICount: function(params) {
// Random.integer( min, max )
return Random.integer(0, 100000);
},
})

3、图片Mock

定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
var imageUrls = [
"https://cdn3-banquan.ituchong.com/weili/l/903088213443084399.jpeg",
"https://cdn3-banquan.ituchong.com/weili/l/902924454934609986.jpeg",
"https://cdn9-banquan.ituchong.com/weili/l/914495302984269898.jpeg",
"https://cdn6-banquan.ituchong.com/weili/l/1113166746308968471.jpeg",
"https://cdn9-banquan.ituchong.com/weili/l/1113170740519632955.jpeg",
"https://cdn3-banquan.ituchong.com/weili/l/1068890057315319833.jpeg",
"https://cdn9-banquan.ituchong.com/weili/l/1016768155267367042.jpeg",
"https://cdn9-banquan.ituchong.com/weili/l/1026741765014028478.jpeg",
"https://cdn9-banquan.ituchong.com/weili/l/967833239214751792.jpeg",
"https://cdn6-banquan.ituchong.com/weili/l/966827220441759777.jpeg",

"https://cdn6-banquan.ituchong.com/weili/l/919795258271596547.jpeg",
"https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=355970603,3245667099&fm=26&gp=0.jpg",
"https://cdn3-banquan.ituchong.com/weili/l/1073188615191658529.jpeg",
"https://cdn6-banquan.ituchong.com/weili/l/57461353849430061.jpeg",
"https://cdn6-banquan.ituchong.com/weili/l/1017308169985458197.jpeg",
"https://img1.droitstock.com/middleW/0a/3c/373880000.jpg",
"https://img1.droitstock.com/middleW/76/d4/324995286.jpg",
"https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=1892357736,3979425284&fm=26&gp=0.jpg",
"https://img1.droitstock.com/middleW/bd/f0/241894345.jpg",
"https://img1.droitstock.com/middleW/41/4f/134317211.jpg",

"https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3155622504,3922873140&fm=26&gp=0.jpg",
"https://img1.droitstock.com/middleW/5b/9c/824812856.jpg",
"https://img1.droitstock.com/middleW/5a/8d/381503287.jpg",
"https://img1.droitstock.com/middleW/b6/22/164126642.jpg",
"https://img1.droitstock.com/middleW/df/26/271782228.jpg",
"https://alifei04.cfp.cn/creative/vcg/veer/800water/veer-163722653.jpg",
"https://alifei01.cfp.cn/creative/vcg/veer/800water/veer-132426620.jpg"
]

Random.extend({
cjtsImageUrl: function(params) {
// return "http://1.jpg"
return this.pick(imageUrls)
},
})

特别注意,不能有下划线等特殊符号,如定义为cjts_imageUrl,使用@cjts_imageUrl,则不能够正确使用到。应该为定义为cjtsImageUrl,使用@cjtsImageUrl。

image-20201121190315325

End