开发流程

1. 看原型

通过原型,来确定要开发的模块,并做一些设计与规划。

例如要开发的店铺模块,这时候需要在

  • pages 目录下建立 store 目录
  • services 目录下建立 store 目录

这种规划不知道是否合理,我见antDesignPro是将 servicedata.d 放在 page 目录下的。我单独提出来,想着以后好重用,就跟 page 文件分别放在了不同的目录中了。

2. 定义 data.d

每个模块都单独建立一个data.d.ts文件。

代码如下,这里要定义namespace,这样可以通过Store.StoreClass来快速引用这个定义。

declare namespace Store {
export type StoreClass = {
storeClassId: number; // 索引id [最大位数:11]
name: string; // 分类名称 [最大位数:50]
bail: number; // 保证金数额 [最大位数:10,2]
sort: number; // 排序 [最大位数:11]
gmtCreate?: string; // 记录创建时间
gmtModified?: string; // 记录修改时间
};
}

上面的代码可以通过后台生成,具体的方法如下:

view-source:http://192.168.31.213:8080/getTableInfo?pwd=fanaaa&prefix=ec&searchTable=ec_

①②③④⑤⑥⑦⑧⑨

3. 定义 service

这里举一些常用的例子。希望今后可以通过代码自动生成,我看到antDesignPro可以通过swagger自动生成 service 代码,今后可以尝试一下这个功能。

具体规则如下

  • 每个模块单独一个文件夹,例如店铺模块,建立 store 文件夹
  • 默认data.d.ts 是头文件

① 定义文件头

头文件主要定义数据结构,例如下面的例子:

declare namespace Store {
export type StoreClass = {
storeClassId: number; // 索引id [最大位数:11]
name: string; // 分类名称 [最大位数:50]
bail: number; // 保证金数额 [最大位数:10,2]
sort: number; // 排序 [最大位数:11]
gmtCreate?: string; // 记录创建时间
gmtModified?: string; // 记录修改时间
};
}

其中namespace 是模块名称

定义的数据结构,一半与后台数据库一一对应,那么这部分代码是自动生成的。

可以在浏览器中输入相应的表明,就能得到这部分代码:

view-source:http://192.168.31.213:8080/getTableInfo?pwd=fanaaa&prefix=ec&searchTable=ec_

② 可分页查询排序

如果代码是按照 antDesign 的标准接口来写,所有的分页查询都应该这么写。

/**
* 品牌列表
* @param data 参数 可以传入分页
*/
export async function getBrandList(data: API.SearchListParams) {
return request<API.ResponseInfo<API.ResponseListData<API.Brand>>>(
`${prifix}/getBrandList`,
{
method: 'POST',
data,
},
);
}

以下是不同点:

  • 函数名:getBrandList : 有两个地方需要修改
  • 返回的对象:API.Brand

今后这个函数,可以自动生成

后面的 Page 例子,会说明如何调用合格函数

③ 得到全部集合

针对那些记录比较少,可以一次得到全部记录。那代码可以这么来写

/**
* 得到店铺等级
* @returns 全部店铺等级
*/
export async function getStoreGradeList() {
return request<API.ResponseInfo<Store.StoreGrade[]>>(
`${prifix}/getStoreGradeList`,
{
method: 'GET',
},
);
}

如果是一个新写的代码,可以修改一下三个方面:

  • 函数名:getStoreGradeList : 有两个地方需要修改

  • 返回的对象:Store.StoreGrade

今后这个函数,可以自动生成

后面的 Page 例子,会说明如何调用合格函数

④ 得到下拉框集合

antDesign下拉框需要一定的数据格式,那么希望有一个通用的转换函数,来进行转换。

在 page 中会这么来引用,一般在一个 column 中定义。

{
title: '级别',
dataIndex: 'storeClassId',
request: () => getStoreClassListOptions([]),
params: {},
valueType: 'select',
},

getStoreClassListOptions 是得到下拉框的格式。

/**
* 得到店铺分类
* @returns 全部店铺分类
*/
export async function getStoreClassList() {
return request<API.ResponseInfo<Store.StoreClass[]>>(
`${prifix}/getStoreClassList`,
{
method: 'GET',
},
);
}
/**
* 将权限列表转换成 select table下拉框可以读取的格式。
* @param initValues 不是从数据库中读取的一些数值,例如下拉框中的全部。
*/
export async function getStoreClassListOptions(initValues: any[]) {
const result = await getStoreClassList();
return convertToOptions(initValues, result.data, 'name', 'storeClassId');
}

说明:

  • getStoreClassList 得到全部数据,后台提供的接口是与前端无关的。
  • convertToOptions 是将后台的数据,转换成antDesign可以识别的格式。
    • initValues 是手工设定的数据,例如好多下拉框都有全部这个选项。
    • 'name' : 是数据库的字段名,要根据这个名称来转换
    • 'storeClassId':是数据库的字段名,要根据这个名称转换成 antDesign 识别的 ID

⑤ 根据 ID 得到记录

/**
* 根据ID店铺信息
* @returns 店铺信息
*/
export async function getStoreById(storeId: number) {
return request<API.ResponseInfo<Store.Store>>(`${prifix}/getStoreById`, {
method: 'GET',
params: {
storeId,
},
});
}

如果新添加函数,有几个地方需要修改一下:

  • getStoreById: 函数名 : 有两个地方需要修改

  • storeId: 主键 : 有两个地方需要修改

  • Store.Store:要返回的数据结构

⑥ 根据 ID 删除记录

/**
* 根据ID删除店铺等级
*/
export async function delStoreGradeById(storeGradeId: number) {
return request<API.ResponseInfo<number>>(`${prifix}/delStoreGradeById`, {
method: 'GET',
params: {
storeGradeId,
},
});
}

如果新添加函数,有几个地方需要修改一下:

  • delStoreGradeById: 函数名 : 有两个地方需要修改
  • storeGradeId: 主键 : 有两个地方需要修改

⑦ 添加或更新记录

/**
* 新增或更新店铺等级,根据Id来进行添加或更新
*/
export async function saveStoreGrade(data: Store.StoreGrade) {
return request<API.ResponseInfo<number>>(`${prifix}/saveStoreGrade`, {
method: 'POST',
data,
});
}

如果新添加函数,要修改内容如下:

  • Store.StoreGrade 传入的参数
  • saveStoreGrade 函数名: 有两个地方需要修改

⑧ 用户名是否重复

并不是每个模块都需要这个函数,这个函数在保存的时候,会判断某个字段不能重复。

/**
* 店铺等级是否存在
*/
export async function existStoreGradeName(name: string, storeGradeId: number) {
return request<API.ResponseInfo<boolean>>(`${prifix}/existStoreGradeName`, {
method: 'GET',
params: {
name,
storeGradeId,
},
});
}

如果新添加函数,要修改内容如下:

  • existStoreGradeName 函数名 : 有两个地方需要修改
  • name: string, storeGradeId: number:两个参数。 : 有两个地方需要修改

3. 定义 page

一个完整的模块,包含内容如下:

  • 一个列表页
  • 一个编辑页

代码生成

如果做一个新模块,可以生成一个简单的代码框架。

  • index.tsx
    • 模块的入口页面,一般是列表的表现形式,一般会把 Tab 逻辑放在这里
    • 如果不是多 Tab 模式,那么就直接引用 List
  • xxxxList.tsx
    • 列表页
  • xxxxEdit.tsx
    • 编辑页

① 列表页

② 列表页-Tab

带 Tab 标签的页面

③ 抽屉式编辑页

点击新增或者编辑 , 弹出一个抽屉页面,可以进行编辑。

④ 弹出式编辑页

如果要编辑的内容不多,可以使用弹出页面。 默认大部分都是抽梯型标签

⑤ 标签式编辑页

如果要编辑的内容较多,或者这个页面中还要弹出新的层,那么建议放在一个新的 Tab 中进行编辑。

⑥ 文件上传

单一文件上传,有一个预览图表

另外一种表现形式是例如头像上传的样式。

4. 修改 Route

修改routes.ts,来显示文件。

5. 测试

可以进行一些手工的测试。然后进行自动化测试。

5.1 语法测试

$ npm run lint

在提交 git 时,会自动触发这个命令。

有一个章节专门写了常见的语法错误,以及处理方式。

5.2 自动化测试脚本

还不知道如何写自动化测试脚本呢。自动化测试包含如下内容:

  • 测试函数
  • 测试界面

6. 提交代码

将代码提交到 git 服务器。