# 低代码文档
通过配置json文件的形式去创建带crud的控制器代码
# 项目结构
├── extend
│ ├── builder
│ │ └── index.js
│ ├── helper
│ │ └── index.js
│ └── validator
│ ├── index.js
│ └── rule_parser.js
├── generator
│ ├── base
│ │ └── index.js
│ ├── controller
│ │ └── index.js
│ └── service
│ └── index.js
├── index.js
├── module
│ ├── common
│ │ ├── field.js
│ │ ├── group.js
│ │ ├── having.js
│ │ ├── join.js
│ │ ├── order.js
│ │ ├── orm.js
│ │ ├── pagination.js
│ │ ├── relation.js
│ │ ├── validator.js
│ │ └── where.js
│ └── index.js
├── package.json
└── README.md
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
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
# 如何使用
创建一个存放json配置文件的目录, 并且编写所需要的json配置文件, 然后将目录配置到 生成器 里面, 使用 node 命令运行生成器文件
# 快速创建
- 安装
npm i @kbd151/code-generator
1
- 创建空目录与执行文件
#文件夹说明
#gen/prod文件夹会提交到git仓库,里面的json会自动被框架载入并注册到路由里面
# 生成配置文件夹
mkdir -vp gen/local/controller
mkdir -vp gen/local/service
# 生成配置文件
touch gen/local/controller/xxx.json
touch gen/local/service/xxx.json
# 生成入口文件
touch gen.js
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
- 入口文件
const gen = require('@kbd151/code-generator')
function optionFile(file) {
console.log(`使用文件 ${file}`);
return true
}
function help() {
console.log('选项:');
console.log(' -cf 指定控制器配置文件');
console.log(' -sf 指定服务配置文件');
console.log(' help 显示帮助');
}
const args = process.argv.slice(2);
let cf,sf
for (let i = 0; i < args.length; i++) {
if (args[i] === '-cf') {
cf = args[i + 1];
}else if(args[i] === '-sf'){
sf = args[i + 1];
}
}
if (args.includes('help')) {
help();
} else if (!cf && !sf){
console.log('无效命令。你必须用 -cf 指定控制器配置文件 或 -sf 指定服务配置文件。');
}
cf && optionFile(cf) && gen.controllerGen.generate({
filePath: cf,
appPath: 'server/app/controller'
})
sf && optionFile(sf) && gen.serviceGen.generate({
filePath: sf,
appPath: 'server/app/service'
})
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
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
- 控制器json文件
{
"name": "推品接口",
"moduleName": "promotion",
"extend": {"name": "WwwController", "path": "base/www_controller"},
"outputPath": "promotion/goods.js",
"routes": [
{
"moduleName": "goodsPromotionDetail",
"method": "GET",
"version": "v1",
"comment": "查询推品信息",
"permission": false,
"type": "query",
"service": {
"moduleName": "promotionService.goodsService.goodsPromotionDetail",
"hasReturn": true
}
}
]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
- 执行入口文件
node gen.js -cf gen/local/controller/goods.json
#输出
#使用文件 gen/local/controller/goods.json
#文件生成成功,路径:server/app/controller/promotion/goods.js
1
2
3
4
5
2
3
4
5
- 执行得到下面的js
const _ = require('lodash')
const moment = require('moment')
const gen = require('@kbd151/code-generator')
const permission = true
const moduleName = 'promotion'
const {WwwController} = require('../base/www_controller')
/**
* 查询推品信息
*/
module.exports.goodsPromotionDetail = class extends WwwController {
permission = false
url = "/v1/" + moduleName + "/goods_promotion_detail"
async get({ query }) {
return await this.promotionService.goodsService.goodsPromotionDetail({ body: query })
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
- 服务配置文件
{
"name": "推品服务",
"moduleName": "goodsService",
"extend": {"name": "BaseService", "path": "base/base_service"},
"outputPath": "promotion/goods.js",
"routes": [
{
"moduleName": "goodsPromotionDetail",
"comment": "推品详情",
"type": "query",
"operateLists": {
"comment": "查询详情",
"model": "xpinModel.XpinGoodsPromotion",
"pagination": {
"paginate": true
},
"method": "findAndCountAll",
"params": {
"attributes": ["title", "price", "shop_id"],
"where": [
],
"relation": [
{
"method": "relateMany",
"model": "xpinModel.XpinShop",
"localField": "id",
"fromField": "shop_id",
"as": "shop",
"attributes": ["shop_name", "id"],
"where": [
{"id": {"op": ">","value": 0}}
]
}
]
}
}
}
]
}
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
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
- 执行入口文件
node gen.js -sf gen/local/service/goods.json
#输出
#使用文件 gen/local/service/goods.json
#文件生成成功,路径:server/app/service/promotion/goods.js
1
2
3
4
5
2
3
4
5
- 发起请求后得到响应
{
"success": true,
"data": {
"count": 7200,
"rows": [
{
"title": "圣诞节 中闽飘香 拍1发3 冻干柠檬片",
"price": 3480,
"shop_id": 19338,
"shop": [
{
"shop_name": "中闽飘香专卖店",
"id": 19338
}
]
},
...
]
},
"code": 0
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
- 说明
如果提示service不存在,自行去基础类实例化一下
# 如何配置
# 基本数据结构:
字段 | 类型 | 必填项 | 说明 |
---|---|---|---|
name | string | 否 | 关于这个json文件的说明 |
moduleName | string | 是 | 模块名 |
extend | array | 否 | 需要继承的类信息 |
extend.name | string | 否 | 需要继承的类的名字 |
extend.path | string | 否 | 需要继承的类引入的路径 |
outputPath | string | 否 | 文件输出地址,仅生成代码填写 |
routes | array | 是 | 控制器/服务路由配置 |
# 控制器内routes结构
字段 | 类型 | 必填项 | 说明 |
---|---|---|---|
moduleName | string | 是 | 驼峰形式的模块名, 也就是控制器类名 |
method | string | 是 | get/post 方法 |
version | string | 是 | 版本, 默认填写 v1 |
comment | string | 是 | 当前模块的注释 |
permission | bool | 否 | 是否鉴权, 默认: 是 |
type | string | 是 | 类型: query=>查询, update=>修改 |
inject | array | 否 | 需要注入的变量, 比如company,admin |
validate | object | 否 | 验证器 |
operateLists | object | 是 | 操作列表, 查询/更新的具体orm操作 |
service | object | 否 | 服务类 |
# 服务内routes结构
字段 | 类型 | 必填项 | 说明 |
---|---|---|---|
moduleName | string | 是 | 驼峰形式的模块名, 也就是服务名 |
comment | string | 是 | 当前模块的注释 |
type | string | 是 | 类型: query=>查询, update=>修改 |
inject | array | 否 | 需要注入的变量, 比如company,admin |
operateLists | object | 是 | 操作列表, 查询/更新的具体orm操作 |
# validate结构
字段 | 说明 | 例子 |
---|---|---|
required | 必填字段 | required |
alpha | 只能包含字母 | alpha |
alphaDash | 只能包含字母、数字、破折号或下划线 | alphaDash |
alphaNum | 只能包含字母和数字 | alphaNum |
between | 值必须在指定范围内 | between: 1, 10 |
date | 必须是有效的日期格式 | date |
different | 值必须与指定字段的值不同 | different: username |
必须是有效的电子邮件地址 | ||
float | 必须是浮点数 | float |
integer | 必须是整数 | integer |
number | 必须是数字 | number |
length | 值的长度必须是指定长度范围内 | length: 2, 500 |
max | 值不能大于指定数值 | max: 100 |
min | 值不能小于指定数值 | min: 5 |
regex | 值必须符合指定的正则表达式 | regex: ^[A-Z]+$ |
string | 必须是字符串 | string |
in | 必须在列表里 | in: 1, 2, 3 |
notIn | 必须不在列表里 | notIn: 1, 2, 3 |
url | url验证 | url |
gt | 必须大于指定的数值 | gt: 10 |
lt | 必须小于指定的数值 | lt: 10 |
gte | 必须大于等于指定的数值 | gte: 20 |
lte | 必须小于等于指定的数值 | lte: 20 |
# service结构
字段 | 类型 | 必填项 | 说明 |
---|---|---|---|
moduleName | string | 是 | 要调用的模块名,例如:promotionService.goodsService.goodsPromotionDetail |
hasReturn | bool | 否 | 是否有返回值,如果有返回值,那么当前的控制器就会直接返回服务类的内容给前端 |
# operateLists结构
字段 | 类型 | 必填项 | 说明 |
---|---|---|---|
comment | string | 否 | 关于这个orm操作的说明 |
model | string | 是 | 要操作的model, 需要具体到数据库名, 例如:xpinModel.XpinGoodsPromotion |
method | string | 是 | 要操作的方法, 也就是sequelize 的方法,例如:update,findOne |
pagination | object | 否 | 分页配置 |
params | object | 是 | orm操作表的配置参数 |
# pagination结构
字段 | 类型 | 必填项 | 说明 |
---|---|---|---|
paginate | bool | 否 | 是否分页 |
jsonContains | array | 否 | json搜索 |
timestamps | array | 否 | |
timestamps_origin | array | 否 | |
dates | array | 否 | 时间范围过虑 |
likes | array | 否 | 模糊搜索 |
jsonContainsNone | array | 否 |
# params结构
字段 | 类型 | 必填项 | 说明 |
---|---|---|---|
attributes | array | 否 | 要查询的字段, 如果要查询的字段包含 +-*/()符号或者包含` as `, 会直接作为原生sql拼装查询 |
order | array | 否 | 排序, 二维数组, 例如: ["XpinGoodsPromotion.id","desc"] |
group | array | 否 | 分组, 如果分组的字段包含 +-*/()符号, 会直接作为原生sql拼接 |
having | string | 否 | having查询直接传字符串,会当做原生sql解析 |
where | array | 否 | 查询条件配置 |
joins | array | 否 | 连表配置 |
relation | array | 否 | 关联查询,解决n+1问题 |
isBatchUpdate | bool | 否 | 更新的时候使用, 默认 falsetrue: 仅判断是否更新成功false: 强制判断更新行数为1 |
createOrUpdateData | object | 否 | 创建/更新的数据 |
# where基本用法
条件字段不可以是 where
或orWhere
关键词
where
用于描述数据查询条件
[
{"title": {"op": "like", "type": "js", "value": "$.title+'%'"}},
{
"shop_id": {
"op": "in",
"type": "sql",
"value": "(select id from xpin_shop where dsr_level = 1)"
}
},
{"id": {"op": "=", "type": "js", "value": "parseInt($.id)"}},
{"where": ["XpinGoodsPromotion.sale_count > 0", {"price": 990}]},
{
"orWhere": [
{"status": {"op": "in", "value": [1, 2, 3]}},
{"id": {"op": ">", "value": 1000}}
]
}
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
解析后的 SQL语句
为:
WHERE `XpinGoodsPromotion`.`title` LIKE 'a%'
AND `XpinGoodsPromotion`.`shop_id` IN ( SELECT id FROM xpin_shop WHERE dsr_level = 1 )
AND `XpinGoodsPromotion`.`id` = 43
AND ( XpinGoodsPromotion.sale_count > 0 AND `XpinGoodsPromotion`.`price` = 990 )
AND ( `XpinGoodsPromotion`.`status` IN ( 1, 2, 3 ) OR `XpinGoodsPromotion`.`id` > 1000 )
1
2
3
4
5
2
3
4
5
# where结构
# And & Or 嵌套
字段 | 类型 | 必填项 | 说明 |
---|---|---|---|
where | array | 否 | 嵌套 and 操作, 也就是此数组里的所有内容 在拼接sql时 外层会单独套一层 括号, 并且数组里的第一层查询 全都是 and 的关系, 例如 在id = 1 的sql 里, 拼接完之后是:id = 1 and (xxx and xxx and xxx) |
orWhere | array | 否 | 嵌套 or 操作, 也就是此数组里的所有内容 在拼接sql时 外层会单独套一层 括号, 并且数组里的第一层查询 全都是 or 的关系, 例如 在id = 1 的sql 里, 拼接完之后是:id = 1 and (xxx or xxx or xxx) |
# 原始sql拼接
直接放sql
到 where或者orWhere内的数组里即可
# 正常筛选
字段 | 类型 | 必填项 | 说明 |
---|---|---|---|
field | string | 否 | 要搜索的字段 |
field.op | string | 否 | 默认是等于操作, 具体支持的类型翻阅 sequelize 文档, 这里我将 =,>,<,>=,<=,<>,!= 转换成了 sequelize支持的类型 |
field.type | string | 否 | 默认:value 给的是什么类型,查询就是什么类型(value 是变量时除外)当 type 是 js 时, 会作为js代码去执行当 type 是 sql 时, 会作为原生sql解析 |
field.value | string | 否 | 当查询内容是对象的时候, value 必填, value里如果含有$. 关键词时,$. 会自动替换为 前端传来的变量, get请求就是query , post请求就是body |
field.must | string | 否 | 过滤查询内容使用,js代码,前端的参数用$. 标识出来 |
# joins结构
字段 | 类型 | 必填项 | 说明 |
---|---|---|---|
model | string | 是 | 要操作的model, 需要具体到数据库名, 例如:xpinModel.XpinShop |
localField | string | 是 | 要操作的表的关联字段shop_id |
from | string | 是 | 连表时原model, 需要具体到数据库名, 例如:xpinModel.XpinGoodsPromotion |
fromField | string | 是 | 原表的关联字段, 例如id |
left | bool | 否 | 是否是左连接, 默认是左连接 |
attributes | string | 否 | 当前表要查询的字段 |
where | array | 否 | 查询条件配置 |
as | string | 是 | 别名 v1.0.13 新增 |
# relation结构
字段 | 类型 | 必填项 | 说明 |
---|---|---|---|
method | string | 是 | relateOne 或者 relateMany |
model | string | 是 | 要操作的model, 需要具体到数据库名, 例如:xpinModel.XpinShop |
localField | string | 是 | 要操作的表的关联字段shop_id |
fromField | string | 是 | 原表的关联字段, 例如id |
as | string | 是 | 查询的数据作为一个别放放到对象里 |
attributes | string | 否 | 当前表要查询的字段,不支持原始sql填写 |
where | array | 否 | 查询条件配置 |
# createOrUpdateData结构
字段 | 类型 | 必填项 | 说明 |
---|---|---|---|
attributes | string | 是 | 要更新/新增的字段, 多个值用 逗号 分隔, 字段和参数名保持一致 |
appendData | object | 否 | 额外要更新/新增的字段数据 |
appendData.field | string | 否 | 要操作的字段场景:前端传的参数名和数据库字段不对应 或 需要额外操作的字段 |
appendData.type | string | 否 | 默认:value 给的是什么类型,查询就是什么类型(value 是变量时除外)当 type 是 js 时, 会作为js代码去执行当 type 是 sql 时, 会作为原生sql解析 |
appendData.value | string | 否 | value里如果含有$. 关键词时,$. 会自动替换为 前端传来的变量, get请求就是query , post请求就是body |
# 补充说明
凡是涉及到原始sql操作的地方,都需要使用参数绑定去操作前端传过来的参数,代码生成的时候会自动做绑定
用法:
sql里前端参数直接用**:field
**的格式就行,也就是前端的参数名加一个冒号
# 例子
# 连表查询和子查询
json配置
{
"name": "推品接口",
"moduleName": "goods",
"extend": {"name": "WwwController", "path": "base/www_controller"},
"outputPath": "compass/detail.js",
"routes": [
{
"moduleName": "goodsPromotionDetail",
"method": "GET",
"version": "v1",
"comment": "查询推品信息",
"permission": false,
"type": "query",
"validate": {"id": ["required","number"]},
"operateLists": {
"comment": "查询详情",
"model": "xpinModel.XpinGoodsPromotion",
"method": "findOne",
"params": {
"attributes": ["title", "price"],
"where": [
{"title": {"op": "like", "type": "js", "value": "$.title+'%'"}},
{
"shop_id": {
"op": "in",
"type": "sql",
"value": "(select id from xpin_shop where dsr_level = 1)"
}
},
{"id": {"op": "=", "type": "js", "value": "parseInt($.id)"}},
{"where": ["XpinGoodsPromotion.sale_count > 0", {"price": 990}]},
{
"orWhere": [
{"status": {"op": "in", "value": [1, 2, 3]}},
{"id": {"op": ">", "value": 1000}}
]
}
],
"joins": [
{
"model": "xpinModel.XpinShop",
"localField": "id",
"left": true,
"from": "xpinModel.XpinGoodsPromotion",
"fromField": "shop_id",
"attributes": ["id as shop_id", "shop_name"],
"as": "shop",
"where": [
{"id": {"op": ">", "value": 10}}
],
"pagination": {
"likes": {"shop_name": ["shop_name"]}
}
}
]
}
}
}
]
}
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
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
对应的js代码
const _ = require('lodash')
const moment = require('moment')
const gen = require('@kbd151/code-generator')
const permission = true
const moduleName = 'goods'
const {WwwController} = require('../base/www_controller')
/**
* 查询推品信息
*/
module.exports.goodsPromotionDetail = class extends WwwController {
permission = false
url = "/v1/" + moduleName + "/goods_promotion_detail"
async get({ query }) {
let [ok, error] = gen.validate(query, { id: ["required", "number"] })
if (!ok) {
return { success: false, code: 4000, msg: "参数验证失败", data: error }
}
// 查询详情
let builder = new gen.sequelizeQueryBuilder()
let queryObj = builder
.select("title", "price", builder.raw("shop.id as shop_id"), "shop.shop_name")
.where("title", "like", query.title + "%")
.where("shop_id", "in", builder.raw("(select id from xpin_shop where dsr_level = 1)"))
.where("id", "=", parseInt(query.id))
.where(function (queryBuilder) {
queryBuilder.whereRaw("XpinGoodsPromotion.sale_count > 0").where("price", 990)
})
.orWhere(function (queryBuilder) {
queryBuilder.where("status", "in", [1, 2, 3]).where("id", ">", 1000)
})
.leftJoin({
fromModel: this.xpinModel.XpinGoodsPromotion,
fromField: "shop_id",
toModel: this.xpinModel.XpinShop,
toField: "id",
as: "shop",
where: (function (application) {
let builder = new gen.sequelizeQueryBuilder()
let queryObj = builder.where("id", ">", 10).build()
application.helper.pagination({
params: query,
origin_data: queryObj,
likes: { shop_name: ["shop_name"] }
})
return queryObj.where
})(this.application)
})
.bind(query)
.build()
let result = await this.xpinModel.XpinGoodsPromotion.findOne(queryObj)
return { success: true, data: result }
}
}
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
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
对应的sql代码
SELECT `XpinGoodsPromotion`.`title`,
`XpinGoodsPromotion`.
`price`,
shop.id as shop_id,
`shop`.`shop_name`
FROM `kbd_xuanpin`.`xpin_goods_promotion` AS `XpinGoodsPromotion`
LEFT OUTER JOIN `kbd_xuanpin`.`xpin_shop` AS `shop`
ON `XpinGoodsPromotion`.`shop_id` = `shop`.`id`
AND (`shop`.`id` > 10)
AND `shop`.`shop_name` LIKE '%444555555555555555555%'
WHERE (`XpinGoodsPromotion`.`title` LIKE 'a%'
AND `XpinGoodsPromotion`.`shop_id` IN (select id from xpin_shop where dsr_level = 1)
AND `XpinGoodsPromotion`.`id` = 43
AND (XpinGoodsPromotion.sale_count > 0 AND `XpinGoodsPromotion`.`price` = 990)
AND (`XpinGoodsPromotion`.`status` IN (1, 2, 3) OR `XpinGoodsPromotion`.`id` > 1000));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 批量写操作
json配置
{
"name": "店铺接口",
"moduleName": "goods",
"extend": {"name": "WwwController", "path": "base/www_controller"},
"outputPath": "goods/update.js",
"routes": [
{
"moduleName": "updateShopInfo",
"method": "POST",
"version": "v1",
"comment": "更新店铺信息",
"type": "update",
"permission": false,
"validate": {
"id": "required",
"brand_name": "required|length:2,10",
"city_name": "required|length:2,10",
"author_id": "required|integer",
"gid": "required|integer"
},
"operateLists": [
{
"model": "xpinModel.XpinShop",
"method": "update",
"comment": "更新店铺卖家名称",
"params": {
"isBatchUpdate": false,
"where": [{"id": {"op": "=", "value": "$.id"}}],
"createOrUpdateData": {
"attributes": [],
"appendData": [
{
"field": "nick_name",
"type": "sql",
"value": "1+1"
}
]
}
}
},
{
"model": "xpinModel.XpinShop",
"method": "update",
"comment": "更新店铺品牌名称",
"params": {
"isBatchUpdate": false,
"where": [{"id": {"op": "=", "value": "$.id"}}],
"createOrUpdateData": {
"attributes": ["brand_name"],
"appendData": [
{
"field": "city",
"value": "$.city_name"
}
]
}
}
},
{
"model": "xpinModel.XpinShopcaseRecord",
"method": "create",
"comment": "新增挂车记录",
"params": {
"createOrUpdateData": {
"attributes": ["author_id"],
"appendData": [
{
"field": "goods_id",
"value": "$.gid"
}
]
}
}
}
]
}
]
}
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
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
js代码
const _ = require('lodash')
const moment = require('moment')
const gen = require('@kbd151/code-generator')
const permission = true
const moduleName = 'goods'
const {WwwController} = require('../base/www_controller')
/**
* 更新店铺信息
*/
module.exports.updateShopInfo = class Controller extends WwwController {
permission = false
url = "/v1/" + moduleName + "/update_shop_info"
async post({ request: { body } }) {
let [ok, error] = gen.validate(body, {
id: "required",
brand_name: "required|length:2,10",
city_name: "required|length:2,10",
author_id: "required|integer",
gid: "required|integer"
})
if (!ok) {
return { success: false, code: 4000, msg: "参数验证失败", data: error }
}
let transactionA = this.xpinModel.transaction()
try {
// 更新店铺卖家名称
let builder = new gen.sequelizeQueryBuilder()
let queryObjA = builder.bindTransaction(transactionA).build()
let [updateRowsA] = await this.xpinModel.XpinShop.update(
{ nick_name: builder.raw("1+1") },
queryObjA
)
if (updateRowsA !== 1) {
throw new Error("更新失败")
}
// 更新店铺品牌名称
builder = new gen.sequelizeQueryBuilder()
let queryObjB = builder.bindTransaction(transactionA).build()
let [updateRowsB] = await this.xpinModel.XpinShop.update(
{ brand_name: body.brand_name, city: body.city_name },
queryObjB
)
if (updateRowsB !== 1) {
throw new Error("更新失败")
}
// 新增挂车记录
builder = new gen.sequelizeQueryBuilder()
let queryObjC = builder.bindTransaction(transactionA).build()
await this.xpinModel.XpinShopcaseRecord.create(
{ author_id: body.author_id, goods_id: body.gid },
queryObjC
)
transactionA.commit()
return { success: true }
} catch (e) {
transactionA.rollback()
return { success: false, msg: e.message }
}
}
}
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
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
对应的sql
START TRANSACTION;
UPDATE `kbd_xuanpin`.`xpin_shop` SET `nick_name`=1+1,`updated_at`=? WHERE (`id` = 1)
UPDATE `kbd_xuanpin`.`xpin_shop` SET `brand_name`=?,`city`=?,`updated_at`=? WHERE (`id` = 1)
INSERT INTO `kbd_xuanpin`.`xpin_shopcase_record` (`id`,`author_id`,`channel`,`created_at`,`goods_id`,`goods_promotion_id`,`is_delete`,`issue_company_id`,`operate_user_id`,`position`,`reason`,`recommend_user_id`,`result`,`share_id`,`shopcase_company_id`,`site_info_id`,`source`,`sum_pay_amount`,`terminal`,`user_id`,`visited_at`) VALUES (DEFAULT,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);
COMMIT;
1
2
3
4
5
2
3
4
5
# 排序,分组,having
配置json
{
"model": "compassModel.ProductDayData",
"method": "findAll",
"pagination": {
"paginate": true
},
"params": {
"attributes": ["title", "max(id)"],
"order":[["id","desc"]],
"group": ["id"],
"having": "id > 10"
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
生成的js
builder
.select("title", builder.raw("max(id)"))
.orderBy("id", "desc")
.groupBy("id")
.havingRaw("id > 10")
.bind(query)
.build()
1
2
3
4
5
6
7
2
3
4
5
6
7
# relateOne查询
配置json
{
"method": "relateOne",
"model": "xpinModel.XpinShop",
"localField": "id",
"fromField": "shop_id",
"as": "shop",
"attributes": ["shop_name", "id"],
"where": [
{"id": {"op": ">","value": 0}}
]
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
生成的js
await this.relateOne({
data: result,
model: this.xpinModel.XpinShop,
id_name: "shop_id",
over_id: "id",
obj_name: "shop",
attributes: ["shop_name", "id"],
where: new gen.sequelizeQueryBuilder().where("id", ">", 0).bind(query).build().where
})
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
对于的sql
SELECT `shop_name`, `id` FROM `xpin_shop` AS `XpinShop` WHERE (`XpinShop`.`id` > 0) AND `XpinShop`.`id` IN (19338, 2405, 19328);
1
# relateMany查询
json配置
{
"method": "relateMany",
"model": "xpinModel.XpinShop",
"localField": "id",
"fromField": "shop_id",
"as": "shop",
"attributes": ["shop_name", "id"],
"where": [
{"id": {"op": ">","value": 0}}
]
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
生成的js
await this.relateMany({
data: result,
model: this.xpinModel.XpinShop,
id_name: "id",
over_id: "shop_id",
obj_name: "shop",
attributes: ["shop_name", "id"],
where: new gen.sequelizeQueryBuilder().where("id", ">", 0).bind(query).build().where
})
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
对应的sql
SELECT `shop_name`, `id` FROM `xpin_shop` AS `XpinShop` WHERE (`XpinShop`.`id` > 0) AND `XpinShop`.`id` IN (19338, 2405, 19328);
1