+ Service
This commit is contained in:
parent
0eb9e533e2
commit
20a3e89cb7
10 changed files with 1167 additions and 93 deletions
589
app/models/kind.json
Normal file
589
app/models/kind.json
Normal file
|
|
@ -0,0 +1,589 @@
|
|||
{
|
||||
"name": "服务类型",
|
||||
"table": {
|
||||
"name": "kind",
|
||||
"comment": "服务类型",
|
||||
"engine": "InnoDB"
|
||||
},
|
||||
"columns": [
|
||||
{ "name": "id", "type": "ID" },
|
||||
{
|
||||
"name": "category_id",
|
||||
"type": "integer",
|
||||
"length": 128,
|
||||
"comment": "gw_category ID(废弃)",
|
||||
"nullable": true,
|
||||
"index": true
|
||||
},
|
||||
{
|
||||
"name": "type_id",
|
||||
"type": "integer",
|
||||
"length": 128,
|
||||
"comment": "gw_type ID(废弃)",
|
||||
"nullable": true,
|
||||
"index": true
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": "string",
|
||||
"comment": "名称",
|
||||
"index": true
|
||||
},
|
||||
{
|
||||
"name": "parent",
|
||||
"type": "bigInteger",
|
||||
"length": 128,
|
||||
"comment": "父类型ID",
|
||||
"nullable": false,
|
||||
"default": 0,
|
||||
"index": true
|
||||
},
|
||||
{
|
||||
"name": "status",
|
||||
"type": "enum",
|
||||
"option": ["enabled", "disabled"],
|
||||
"comment": "状态 enabled 开启, disabled 关闭",
|
||||
"default": "enabled",
|
||||
"index": true
|
||||
},
|
||||
{
|
||||
"name": "rank",
|
||||
"type": "bigInteger",
|
||||
"length": 128,
|
||||
"comment": "排序",
|
||||
"nullable": false,
|
||||
"default": 9999,
|
||||
"index": true
|
||||
}
|
||||
],
|
||||
"relations": {
|
||||
"parent": {
|
||||
"type": "hasOne",
|
||||
"key": "parent",
|
||||
"model": "Kind",
|
||||
"foreign": "id"
|
||||
},
|
||||
"children": {
|
||||
"type": "hasMany",
|
||||
"key": "id",
|
||||
"model": "Kind",
|
||||
"foreign": "parent"
|
||||
},
|
||||
"nodes": {
|
||||
"type": "treeNodes",
|
||||
"key": "id",
|
||||
"model": "Kind",
|
||||
"parent": "parent",
|
||||
"max_level": 256
|
||||
}
|
||||
},
|
||||
"option": { "timestamps": true, "soft_deletes": true },
|
||||
"values": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "云服务",
|
||||
"category_id": null,
|
||||
"type_id": null,
|
||||
"rank": 1,
|
||||
"parent": 0
|
||||
},
|
||||
|
||||
{
|
||||
"id": 2,
|
||||
"name": "基础服务",
|
||||
"category_id": null,
|
||||
"type_id": null,
|
||||
"rank": 1,
|
||||
"parent": 1
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "云主机",
|
||||
"category_id": null,
|
||||
"type_id": 4,
|
||||
"rank": 1,
|
||||
"parent": 2
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "对象存储",
|
||||
"category_id": null,
|
||||
"type_id": 5,
|
||||
"rank": 2,
|
||||
"parent": 2
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": "云数据库",
|
||||
"category_id": null,
|
||||
"type_id": 6,
|
||||
"rank": 3,
|
||||
"parent": 2
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"name": "块存储",
|
||||
"category_id": null,
|
||||
"type_id": 7,
|
||||
"rank": 4,
|
||||
"parent": 2
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"name": "应用托管容器",
|
||||
"category_id": null,
|
||||
"type_id": 8,
|
||||
"rank": 5,
|
||||
"parent": 2
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"name": "云缓存",
|
||||
"category_id": null,
|
||||
"type_id": 9,
|
||||
"rank": 6,
|
||||
"parent": 2
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"name": "本地负载均衡",
|
||||
"category_id": null,
|
||||
"type_id": 10,
|
||||
"rank": 7,
|
||||
"parent": 2
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"name": "全局负载均衡",
|
||||
"category_id": null,
|
||||
"type_id": 13,
|
||||
"rank": 8,
|
||||
"parent": 2
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"name": "云分发",
|
||||
"category_id": null,
|
||||
"type_id": 11,
|
||||
"rank": 9,
|
||||
"parent": 2
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"name": "企业级SaaS",
|
||||
"category_id": null,
|
||||
"type_id": 12,
|
||||
"rank": 10,
|
||||
"parent": 2
|
||||
},
|
||||
{
|
||||
"id": 13,
|
||||
"name": "云桌面",
|
||||
"category_id": null,
|
||||
"type_id": 14,
|
||||
"rank": 11,
|
||||
"parent": 2
|
||||
},
|
||||
{
|
||||
"id": 14,
|
||||
"name": "云备份",
|
||||
"category_id": null,
|
||||
"type_id": 17,
|
||||
"rank": 12,
|
||||
"parent": 2
|
||||
},
|
||||
{
|
||||
"id": 15,
|
||||
"name": "GPU云主机",
|
||||
"category_id": null,
|
||||
"type_id": 18,
|
||||
"rank": 13,
|
||||
"parent": 2
|
||||
},
|
||||
{
|
||||
"id": 16,
|
||||
"name": "物理云主机",
|
||||
"category_id": null,
|
||||
"type_id": 20,
|
||||
"rank": 14,
|
||||
"parent": 2
|
||||
},
|
||||
{
|
||||
"id": 17,
|
||||
"name": "智能云",
|
||||
"category_id": 41,
|
||||
"type_id": null,
|
||||
"rank": 2,
|
||||
"parent": 2
|
||||
},
|
||||
|
||||
{
|
||||
"id": 18,
|
||||
"name": "软件和开发",
|
||||
"category_id": null,
|
||||
"type_id": null,
|
||||
"rank": 2,
|
||||
"parent": 0
|
||||
},
|
||||
{
|
||||
"id": 19,
|
||||
"name": "虚拟化及管理",
|
||||
"category_id": 59,
|
||||
"type_id": null,
|
||||
"rank": 1,
|
||||
"parent": 18
|
||||
},
|
||||
{
|
||||
"id": 20,
|
||||
"name": "容器解决方案",
|
||||
"category_id": 65,
|
||||
"type_id": null,
|
||||
"rank": 2,
|
||||
"parent": 18
|
||||
},
|
||||
{
|
||||
"id": 21,
|
||||
"name": "微服务解决方案",
|
||||
"category_id": 76,
|
||||
"type_id": null,
|
||||
"rank": 3,
|
||||
"parent": 18
|
||||
},
|
||||
{
|
||||
"id": 22,
|
||||
"name": "serverless解决方案",
|
||||
"category_id": 82,
|
||||
"type_id": null,
|
||||
"rank": 4,
|
||||
"parent": 18
|
||||
},
|
||||
{
|
||||
"id": 23,
|
||||
"name": "云管理和云运营",
|
||||
"category_id": null,
|
||||
"type_id": null,
|
||||
"rank": 3,
|
||||
"parent": 0
|
||||
},
|
||||
{
|
||||
"id": 24,
|
||||
"name": "混合云",
|
||||
"category_id": null,
|
||||
"type_id": null,
|
||||
"rank": 1,
|
||||
"parent": 23
|
||||
},
|
||||
{
|
||||
"id": 25,
|
||||
"name": "混合云解决方案",
|
||||
"category_id": 88,
|
||||
"type_id": null,
|
||||
"rank": 1,
|
||||
"parent": 24
|
||||
},
|
||||
{
|
||||
"id": 26,
|
||||
"name": "混合云安全",
|
||||
"category_id": 671,
|
||||
"type_id": null,
|
||||
"rank": 2,
|
||||
"parent": 24
|
||||
},
|
||||
{
|
||||
"id": 27,
|
||||
"name": "多云管理",
|
||||
"category_id": 94,
|
||||
"type_id": null,
|
||||
"rank": 2,
|
||||
"parent": 23
|
||||
},
|
||||
{
|
||||
"id": 28,
|
||||
"name": "金牌运维",
|
||||
"category_id": 120,
|
||||
"type_id": null,
|
||||
"rank": 3,
|
||||
"parent": 23
|
||||
},
|
||||
{
|
||||
"id": 29,
|
||||
"name": "研发运营一体化",
|
||||
"category_id": 443,
|
||||
"type_id": null,
|
||||
"rank": 4,
|
||||
"parent": 23
|
||||
},
|
||||
{
|
||||
"id": 30,
|
||||
"name": "MSP",
|
||||
"category_id": 112,
|
||||
"type_id": null,
|
||||
"rank": 5,
|
||||
"parent": 23
|
||||
},
|
||||
{
|
||||
"id": 31,
|
||||
"name": "安全与保险",
|
||||
"category_id": null,
|
||||
"type_id": null,
|
||||
"rank": 4,
|
||||
"parent": 0
|
||||
},
|
||||
{
|
||||
"id": 32,
|
||||
"name": "风险管理",
|
||||
"category_id": 141,
|
||||
"type_id": null,
|
||||
"rank": 1,
|
||||
"parent": 31
|
||||
},
|
||||
{
|
||||
"id": 33,
|
||||
"name": "云服务用户数据保护",
|
||||
"category_id": 152,
|
||||
"type_id": null,
|
||||
"rank": 2,
|
||||
"parent": 31
|
||||
},
|
||||
{
|
||||
"id": 34,
|
||||
"name": "业务风控",
|
||||
"category_id": null,
|
||||
"type_id": null,
|
||||
"rank": 3,
|
||||
"parent": 31
|
||||
},
|
||||
{
|
||||
"id": 35,
|
||||
"name": "内容安全",
|
||||
"category_id": 159,
|
||||
"type_id": null,
|
||||
"rank": 1,
|
||||
"parent": 34
|
||||
},
|
||||
{
|
||||
"id": 36,
|
||||
"name": "反交易欺诈",
|
||||
"category_id": 164,
|
||||
"type_id": null,
|
||||
"rank": 2,
|
||||
"parent": 34
|
||||
},
|
||||
{
|
||||
"id": 37,
|
||||
"name": "反信贷欺诈",
|
||||
"category_id": 165,
|
||||
"type_id": null,
|
||||
"rank": 3,
|
||||
"parent": 34
|
||||
},
|
||||
{
|
||||
"id": 38,
|
||||
"name": "反营销欺诈",
|
||||
"category_id": 166,
|
||||
"type_id": null,
|
||||
"rank": 4,
|
||||
"parent": 34
|
||||
},
|
||||
{
|
||||
"id": 39,
|
||||
"name": "反钓鱼欺诈",
|
||||
"category_id": 167,
|
||||
"type_id": null,
|
||||
"rank": 5,
|
||||
"parent": 34
|
||||
},
|
||||
{
|
||||
"id": 40,
|
||||
"name": "云主机安全",
|
||||
"category_id": 184,
|
||||
"type_id": null,
|
||||
"rank": 4,
|
||||
"parent": 31
|
||||
},
|
||||
{
|
||||
"id": 41,
|
||||
"name": "态势感知",
|
||||
"category_id": 190,
|
||||
"type_id": null,
|
||||
"rank": 5,
|
||||
"parent": 31
|
||||
},
|
||||
{
|
||||
"id": 42,
|
||||
"name": "云保险",
|
||||
"category_id": 272,
|
||||
"type_id": null,
|
||||
"rank": 6,
|
||||
"parent": 31
|
||||
},
|
||||
{
|
||||
"id": 43,
|
||||
"name": "云网&云边",
|
||||
"category_id": null,
|
||||
"type_id": null,
|
||||
"rank": 5,
|
||||
"parent": 0
|
||||
},
|
||||
{
|
||||
"id": 44,
|
||||
"name": "云平台网络能力",
|
||||
"category_id": 102,
|
||||
"type_id": null,
|
||||
"rank": 1,
|
||||
"parent": 43
|
||||
},
|
||||
{
|
||||
"id": 45,
|
||||
"name": "SD-WAN",
|
||||
"category_id": 106,
|
||||
"type_id": null,
|
||||
"rank": 2,
|
||||
"parent": 43
|
||||
},
|
||||
{
|
||||
"id": 46,
|
||||
"name": "物联网",
|
||||
"category_id": 234,
|
||||
"type_id": null,
|
||||
"rank": 3,
|
||||
"parent": 43
|
||||
},
|
||||
{
|
||||
"id": 47,
|
||||
"name": "行业云",
|
||||
"category_id": null,
|
||||
"type_id": null,
|
||||
"rank": 6,
|
||||
"parent": 0
|
||||
},
|
||||
{
|
||||
"id": 48,
|
||||
"name": "政务",
|
||||
"category_id": null,
|
||||
"type_id": null,
|
||||
"rank": 1,
|
||||
"parent": 47
|
||||
},
|
||||
{
|
||||
"id": 49,
|
||||
"name": "政务云综合水平评估",
|
||||
"category_id": 215,
|
||||
"type_id": null,
|
||||
"rank": 1,
|
||||
"parent": 48
|
||||
},
|
||||
{
|
||||
"id": 50,
|
||||
"name": "可信政务云评估",
|
||||
"category_id": 216,
|
||||
"type_id": null,
|
||||
"rank": 2,
|
||||
"parent": 48
|
||||
},
|
||||
{
|
||||
"id": 51,
|
||||
"name": "金融",
|
||||
"category_id": 225,
|
||||
"type_id": null,
|
||||
"rank": 2,
|
||||
"parent": 47
|
||||
},
|
||||
{
|
||||
"id": 52,
|
||||
"name": "开源治理",
|
||||
"category_id": null,
|
||||
"type_id": null,
|
||||
"rank": 7,
|
||||
"parent": 0
|
||||
},
|
||||
{
|
||||
"id": 53,
|
||||
"name": "面向开源用户企业",
|
||||
"category_id": 196,
|
||||
"type_id": null,
|
||||
"rank": 1,
|
||||
"parent": 52
|
||||
},
|
||||
{
|
||||
"id": 54,
|
||||
"name": "面向自发开源企业",
|
||||
"category_id": 202,
|
||||
"type_id": null,
|
||||
"rank": 2,
|
||||
"parent": 52
|
||||
},
|
||||
{
|
||||
"id": 55,
|
||||
"name": "开源项目评估",
|
||||
"category_id": 711,
|
||||
"type_id": null,
|
||||
"rank": 3,
|
||||
"parent": 52
|
||||
},
|
||||
{
|
||||
"id": 56,
|
||||
"name": "开源工具评估",
|
||||
"category_id": 720,
|
||||
"type_id": null,
|
||||
"rank": 4,
|
||||
"parent": 52
|
||||
},
|
||||
{
|
||||
"id": 57,
|
||||
"name": "检测平台",
|
||||
"category_id": null,
|
||||
"type_id": null,
|
||||
"rank": 8,
|
||||
"parent": 0
|
||||
},
|
||||
{
|
||||
"id": 58,
|
||||
"name": "云主机分级",
|
||||
"category_id": 371,
|
||||
"type_id": null,
|
||||
"rank": 1,
|
||||
"parent": 57
|
||||
},
|
||||
{
|
||||
"id": 59,
|
||||
"name": "监管支撑",
|
||||
"category_id": null,
|
||||
"type_id": null,
|
||||
"rank": 9,
|
||||
"parent": 0
|
||||
},
|
||||
{
|
||||
"id": 60,
|
||||
"name": "企业上云效果成熟度",
|
||||
"category_id": 250,
|
||||
"type_id": null,
|
||||
"rank": 1,
|
||||
"parent": 59
|
||||
},
|
||||
{
|
||||
"id": 61,
|
||||
"name": "综合信用评估",
|
||||
"category_id": null,
|
||||
"type_id": null,
|
||||
"rank": 2,
|
||||
"parent": 59
|
||||
},
|
||||
{
|
||||
"id": 62,
|
||||
"name": "云服务企业",
|
||||
"category_id": 261,
|
||||
"type_id": null,
|
||||
"rank": 1,
|
||||
"parent": 61
|
||||
},
|
||||
{
|
||||
"id": 63,
|
||||
"name": "CDN服务企业",
|
||||
"category_id": 271,
|
||||
"type_id": null,
|
||||
"rank": 2,
|
||||
"parent": 61
|
||||
}
|
||||
]
|
||||
}
|
||||
122
app/models/service.json
Normal file
122
app/models/service.json
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
{
|
||||
"name": "云服务库",
|
||||
"table": {
|
||||
"name": "service",
|
||||
"comment": "云服务表",
|
||||
"engine": "InnoDB"
|
||||
},
|
||||
"columns": [
|
||||
{ "name": "id", "type": "ID" },
|
||||
{
|
||||
"name": "short_name",
|
||||
"type": "string",
|
||||
"length": 200,
|
||||
"comment": "简称",
|
||||
"index": true
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": "string",
|
||||
"length": 200,
|
||||
"comment": "服务名称",
|
||||
"index": true
|
||||
},
|
||||
{
|
||||
"name": "kind",
|
||||
"type": "string",
|
||||
"length": 200,
|
||||
"comment": "服务类型",
|
||||
"index": true
|
||||
},
|
||||
{
|
||||
"name": "manu",
|
||||
"type": "string",
|
||||
"length": 200,
|
||||
"comment": "所属厂商",
|
||||
"index": true
|
||||
},
|
||||
{
|
||||
"name": "registed_at",
|
||||
"type": "string",
|
||||
"length": 200,
|
||||
"comment": "注册地",
|
||||
"nullable": true,
|
||||
"index": true
|
||||
},
|
||||
{
|
||||
"name": "link",
|
||||
"type": "string",
|
||||
"length": 200,
|
||||
"comment": "官网地址",
|
||||
"nullable": true
|
||||
},
|
||||
{
|
||||
"name": "contact_name",
|
||||
"type": "string",
|
||||
"length": 200,
|
||||
"comment": "联系人",
|
||||
"nullable": true,
|
||||
"index": true
|
||||
},
|
||||
{
|
||||
"name": "contact_mobile",
|
||||
"type": "string",
|
||||
"comment": "联系电话",
|
||||
"nullable": true,
|
||||
"index": true
|
||||
},
|
||||
{
|
||||
"name": "fields",
|
||||
"type": "string",
|
||||
"length": 500,
|
||||
"comment": "JSON|服务领域(多选)",
|
||||
"nullable": true,
|
||||
"index": true
|
||||
},
|
||||
{
|
||||
"name": "price_options",
|
||||
"type": "string",
|
||||
"length": 500,
|
||||
"default": "[\"按月订阅\"]",
|
||||
"comment": "JSON|订阅方式(多选)",
|
||||
"index": true
|
||||
},
|
||||
{
|
||||
"name": "industries",
|
||||
"type": "string",
|
||||
"length": 500,
|
||||
"comment": "JSON|行业覆盖(多选)",
|
||||
"nullable": true,
|
||||
"index": true
|
||||
},
|
||||
{
|
||||
"name": "rank",
|
||||
"type": "integer",
|
||||
"default": 9999999,
|
||||
"comment": "查询排序"
|
||||
},
|
||||
{
|
||||
"name": "status",
|
||||
"type": "enum",
|
||||
"default": "enabled",
|
||||
"option": ["enabled", "disabled"],
|
||||
"comment": "状态 enabled 开启, disabled 关闭",
|
||||
"index": true
|
||||
}
|
||||
],
|
||||
"relations": {
|
||||
"manu": {
|
||||
"type": "hasOne",
|
||||
"key": "manu",
|
||||
"model": "Manu",
|
||||
"foreign": "id"
|
||||
},
|
||||
"kind": {
|
||||
"type": "hasOne",
|
||||
"key": "kind",
|
||||
"model": "Kind",
|
||||
"foreign": "id"
|
||||
}
|
||||
},
|
||||
"option": { "timestamps": true, "soft_deletes": true }
|
||||
}
|
||||
|
|
@ -1,86 +1,64 @@
|
|||
{
|
||||
"name": "云服务库",
|
||||
"version": "1.0.0",
|
||||
"decription": "可信云云服务库",
|
||||
"apis": {
|
||||
"bind": {
|
||||
"model": "service",
|
||||
"withs": {
|
||||
"manu": {
|
||||
"query": {
|
||||
"select": ["id", "name", "short_name", "status"]
|
||||
}
|
||||
},
|
||||
"kind": {
|
||||
"query": {
|
||||
"select": ["id", "name"]
|
||||
}
|
||||
"bind": {
|
||||
"model": "service",
|
||||
"withs": {
|
||||
"manu": {
|
||||
"query": {
|
||||
"select": ["id", "name", "short_name", "status"]
|
||||
}
|
||||
},
|
||||
"kind": {
|
||||
"query": {
|
||||
"select": ["id", "name"]
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
"apis": {
|
||||
"search": {
|
||||
"process": "models.service.Paginate",
|
||||
"in": [":query-param", "$query.page", "$query.pagesize"],
|
||||
"default": {
|
||||
"withs": {
|
||||
"manu": {
|
||||
"query": {
|
||||
"select": ["id", "name", "short_name", "status"]
|
||||
"default": [
|
||||
{
|
||||
"withs": {
|
||||
"manu": {
|
||||
"query": {
|
||||
"select": ["id", "name", "short_name", "status"]
|
||||
}
|
||||
},
|
||||
"kind": {
|
||||
"query": {
|
||||
"select": ["id", "name"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"kind": {
|
||||
"query": {
|
||||
"select": ["id", "name"]
|
||||
}
|
||||
}
|
||||
"wheres": [{ "column": "status", "value": "enabled" }]
|
||||
},
|
||||
"wheres": [{ "column": "status", "value": "enabled" }],
|
||||
"pagesize": 15
|
||||
}
|
||||
null,
|
||||
15
|
||||
]
|
||||
},
|
||||
"find": {
|
||||
"process": "models.service.Find",
|
||||
"in": ["$param.id"],
|
||||
"default": {
|
||||
"withs": {
|
||||
"manu": {
|
||||
"query": {
|
||||
"select": ["id", "name", "short_name", "status"]
|
||||
}
|
||||
},
|
||||
"kind": {
|
||||
"query": {
|
||||
"select": ["id", "name"]
|
||||
"default": [
|
||||
null,
|
||||
{
|
||||
"withs": {
|
||||
"manu": {
|
||||
"query": {
|
||||
"select": ["id", "name", "short_name", "status"]
|
||||
}
|
||||
},
|
||||
"kind": {
|
||||
"query": {
|
||||
"select": ["id", "name"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"save": {
|
||||
"process": "models.service.Find",
|
||||
"in": [":payload"],
|
||||
"default": {
|
||||
"fields": ["视频会议"]
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"process": "models.service.Delete",
|
||||
"in": ["$param.id"]
|
||||
},
|
||||
"insert": {
|
||||
"process": "models.service.Insert",
|
||||
"in": ["$payload.columns", "$payload.data"]
|
||||
},
|
||||
"deletewhere": {
|
||||
"process": "models.service.DeleteWhere",
|
||||
"in": [":query-param"]
|
||||
},
|
||||
"updatewhere": {
|
||||
"process": "models.service.UpdateWhere",
|
||||
"in": [":query-param", ":payload"]
|
||||
},
|
||||
"import": {
|
||||
"process": "models.service.Import",
|
||||
"in": ["$file.file", "$param.kind", ":headers"]
|
||||
]
|
||||
}
|
||||
},
|
||||
"columns": {
|
||||
|
|
@ -295,24 +273,28 @@
|
|||
"关键词": {
|
||||
"label": "关键词",
|
||||
"bind": "where.name.like",
|
||||
"type": "input",
|
||||
"props": {
|
||||
"placeholder": "请输入关键词"
|
||||
"input": {
|
||||
"type": "input",
|
||||
"props": {
|
||||
"placeholder": "请输入关键词"
|
||||
}
|
||||
}
|
||||
},
|
||||
"所属厂商": {
|
||||
"label": "厂商",
|
||||
"bind": "where.manu_id.in",
|
||||
"type": "select",
|
||||
"props": {
|
||||
"searchable": true,
|
||||
"multiple": true,
|
||||
"placeholder": "请选择所属厂商",
|
||||
"remote": {
|
||||
"api": "/api/manu/get",
|
||||
"query": {
|
||||
"select": ["id", "name"],
|
||||
"keyword": "where_name_like"
|
||||
"input": {
|
||||
"type": "select",
|
||||
"props": {
|
||||
"searchable": true,
|
||||
"multiple": true,
|
||||
"placeholder": "请选择所属厂商",
|
||||
"remote": {
|
||||
"api": "/api/manu/get",
|
||||
"query": {
|
||||
"select": ["id", "name"],
|
||||
"keyword": "where_name_like"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -320,17 +302,19 @@
|
|||
"服务类型": {
|
||||
"label": "类型",
|
||||
"bind": "where.kind_id.in",
|
||||
"type": "select",
|
||||
"props": {
|
||||
"tree": true,
|
||||
"searchable": true,
|
||||
"multiple": true,
|
||||
"placeholder": "请选择所属类型",
|
||||
"remote": {
|
||||
"api": "/api/kind/tree",
|
||||
"query": {
|
||||
"select": ["id", "name"],
|
||||
"keyword": "where_name_like"
|
||||
"input": {
|
||||
"type": "select",
|
||||
"props": {
|
||||
"tree": true,
|
||||
"searchable": true,
|
||||
"multiple": true,
|
||||
"placeholder": "请选择所属类型",
|
||||
"remote": {
|
||||
"api": "/api/kind/tree",
|
||||
"query": {
|
||||
"select": ["id", "name"],
|
||||
"keyword": "where_name_like"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -373,7 +357,7 @@
|
|||
"deleteWhere": {},
|
||||
"updateSelect": {},
|
||||
"deleteSelect": {},
|
||||
"pagination": ["pages", "prev", "next"],
|
||||
"pagination": {},
|
||||
"setting": {}
|
||||
}
|
||||
},
|
||||
|
|
@ -46,7 +46,9 @@ func init() {
|
|||
Conf = NewConfig()
|
||||
|
||||
// 数据库连接
|
||||
capsule.AddConn("primary", "mysql", Conf.Database.Primary[0]).SetAsGlobal()
|
||||
if len(Conf.Database.Primary) > 0 {
|
||||
capsule.AddConn("primary", "mysql", Conf.Database.Primary[0]).SetAsGlobal()
|
||||
}
|
||||
|
||||
// 加密密钥
|
||||
gou.LoadCrypt(fmt.Sprintf(`{"key":"%s"}`, Conf.Database.AESKey), "AES")
|
||||
|
|
|
|||
5
table/api.go
Normal file
5
table/api.go
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
package table
|
||||
|
||||
// loadAPIs 加载数据管理 API
|
||||
func (tab *Table) loadAPIs() {
|
||||
}
|
||||
113
table/columns.go
Normal file
113
table/columns.go
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
package table
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/yaoapp/gou"
|
||||
)
|
||||
|
||||
var elms = map[string]Column{
|
||||
"string": {View: Render{Type: "label"}, Edit: Render{Type: "input"}},
|
||||
"char": {View: Render{Type: "label"}, Edit: Render{Type: "input"}},
|
||||
"text": {View: Render{Type: "label"}, Edit: Render{Type: "input"}},
|
||||
"mediumText": {View: Render{Type: "label"}, Edit: Render{Type: "input"}},
|
||||
"longText": {View: Render{Type: "label"}, Edit: Render{Type: "input"}},
|
||||
"binary": {View: Render{Type: "label"}, Edit: Render{Type: "input"}},
|
||||
"date": {View: Render{Type: "label"}, Edit: Render{Type: "input"}},
|
||||
"datetime": {View: Render{Type: "label"}, Edit: Render{Type: "datetime"}},
|
||||
"datetimeTz": {View: Render{Type: "label"}, Edit: Render{Type: "datetime"}},
|
||||
"time": {View: Render{Type: "label"}, Edit: Render{Type: "time"}},
|
||||
"timeTz": {View: Render{Type: "label"}, Edit: Render{Type: "time"}},
|
||||
"timestamp": {View: Render{Type: "label"}, Edit: Render{Type: "datetime"}},
|
||||
"timestampTz": {View: Render{Type: "label"}, Edit: Render{Type: "datetime"}},
|
||||
"tinyInteger": {View: Render{Type: "label"}, Edit: Render{Type: "input"}},
|
||||
"tinyIncrements": {View: Render{Type: "label"}, Edit: Render{Type: "input"}},
|
||||
"unsignedTinyInteger": {View: Render{Type: "label"}, Edit: Render{Type: "input"}},
|
||||
"smallInteger": {View: Render{Type: "label"}, Edit: Render{Type: "input"}},
|
||||
"smallIncrements": {View: Render{Type: "label"}, Edit: Render{Type: "input"}},
|
||||
"unsignedSmallInteger": {View: Render{Type: "label"}, Edit: Render{Type: "input"}},
|
||||
"integer": {View: Render{Type: "label"}, Edit: Render{Type: "input"}},
|
||||
"increments": {View: Render{Type: "label"}, Edit: Render{Type: "input"}},
|
||||
"unsignedInteger": {View: Render{Type: "label"}, Edit: Render{Type: "input"}},
|
||||
"bigInteger": {View: Render{Type: "label"}, Edit: Render{Type: "input"}},
|
||||
"bigIncrements": {View: Render{Type: "label"}, Edit: Render{Type: "input"}},
|
||||
"unsignedBigInteger": {View: Render{Type: "label"}, Edit: Render{Type: "input"}},
|
||||
"id": {View: Render{Type: "label"}, Edit: Render{Type: "input"}},
|
||||
"ID": {View: Render{Type: "label"}, Edit: Render{Type: "input"}},
|
||||
"decimal": {View: Render{Type: "label"}, Edit: Render{Type: "input"}},
|
||||
"unsignedDecimal": {View: Render{Type: "label"}, Edit: Render{Type: "input"}},
|
||||
"float": {View: Render{Type: "label"}, Edit: Render{Type: "input"}},
|
||||
"unsignedFloat": {View: Render{Type: "label"}, Edit: Render{Type: "input"}},
|
||||
"double": {View: Render{Type: "label"}, Edit: Render{Type: "input"}},
|
||||
"unsignedDouble": {View: Render{Type: "label"}, Edit: Render{Type: "input"}},
|
||||
"boolean": {View: Render{Type: "label"}, Edit: Render{Type: "checkbox"}},
|
||||
"enum": {View: Render{Type: "label"}, Edit: Render{Type: "select"}},
|
||||
"json": {View: Render{Type: "label"}, Edit: Render{Type: "input"}},
|
||||
"JSON": {View: Render{Type: "label"}, Edit: Render{Type: "input"}},
|
||||
"jsonb": {View: Render{Type: "label"}, Edit: Render{Type: "input"}},
|
||||
"JSONB": {View: Render{Type: "label"}, Edit: Render{Type: "input"}},
|
||||
"uuid": {View: Render{Type: "label"}, Edit: Render{Type: "input"}},
|
||||
"ipAddress": {View: Render{Type: "label"}, Edit: Render{Type: "input"}},
|
||||
"macAddress": {View: Render{Type: "label"}, Edit: Render{Type: "input"}},
|
||||
"year": {View: Render{Type: "label"}, Edit: Render{Type: "datetime"}},
|
||||
}
|
||||
|
||||
// loadColumns 加载字段呈现方式
|
||||
func (table *Table) loadColumns() {
|
||||
if table.Bind.Model == "" {
|
||||
return
|
||||
}
|
||||
defaults := getDefaultColumns(table.Bind.Model)
|
||||
for name, column := range table.Columns {
|
||||
defaults[name] = column
|
||||
}
|
||||
table.Columns = defaults
|
||||
}
|
||||
|
||||
// getDefaultColumns 读取数据模型字段的呈现方式
|
||||
func getDefaultColumns(name string) map[string]Column {
|
||||
mod := gou.Select(name)
|
||||
cmap := mod.Columns
|
||||
columns := map[string]Column{}
|
||||
|
||||
for name, col := range cmap {
|
||||
vcol, has := elms[col.Type]
|
||||
if !has {
|
||||
continue
|
||||
}
|
||||
|
||||
label := col.Label
|
||||
if label == "" {
|
||||
label = col.Comment
|
||||
}
|
||||
if label == "" {
|
||||
label = name
|
||||
}
|
||||
|
||||
vcol.Label = label
|
||||
if vcol.View.Props == nil {
|
||||
vcol.View.Props = map[string]interface{}{}
|
||||
}
|
||||
if vcol.Edit.Props == nil {
|
||||
vcol.Edit.Props = map[string]interface{}{}
|
||||
}
|
||||
vcol.View.Props["value"] = fmt.Sprintf(":%s", col.Name)
|
||||
vcol.Edit.Props["value"] = fmt.Sprintf(":%s", col.Name)
|
||||
|
||||
// 枚举型
|
||||
if col.Type == "enum" {
|
||||
options := []map[string]string{}
|
||||
for _, opt := range col.Option {
|
||||
options = append(options, map[string]string{
|
||||
"label": opt,
|
||||
"value": opt,
|
||||
})
|
||||
}
|
||||
vcol.Edit.Props["options"] = options
|
||||
}
|
||||
|
||||
columns[name] = vcol
|
||||
columns[label] = vcol
|
||||
}
|
||||
return columns
|
||||
}
|
||||
77
table/filters.go
Normal file
77
table/filters.go
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
package table
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/yaoapp/gou"
|
||||
)
|
||||
|
||||
// loadFilters 加载查询过滤器
|
||||
func (table *Table) loadFilters() {
|
||||
if table.Bind.Model == "" {
|
||||
return
|
||||
}
|
||||
defaults := getDefaultFilters(table.Bind.Model)
|
||||
for name, filter := range table.Filters {
|
||||
defaults[name] = filter
|
||||
}
|
||||
table.Filters = defaults
|
||||
}
|
||||
|
||||
// getDefaultFilters 读取数据模型索引字段的过滤器
|
||||
func getDefaultFilters(name string) map[string]Filter {
|
||||
|
||||
mod := gou.Select(name)
|
||||
cmap := mod.Columns
|
||||
filters := map[string]Filter{}
|
||||
for _, index := range mod.MetaData.Indexes {
|
||||
for _, col := range index.Columns {
|
||||
if _, has := cmap[col]; !has {
|
||||
continue
|
||||
}
|
||||
// primary,unique,index,match
|
||||
switch index.Type {
|
||||
case "index", "match":
|
||||
cmap[col].Index = true
|
||||
break
|
||||
case "unique":
|
||||
cmap[col].Unique = true
|
||||
break
|
||||
case "primary":
|
||||
cmap[col].Primary = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for name, col := range cmap {
|
||||
|
||||
if col.Type != "ID" && !col.Index && !col.Unique && !col.Primary {
|
||||
continue
|
||||
}
|
||||
|
||||
vcol, has := elms[col.Type]
|
||||
if !has {
|
||||
continue
|
||||
}
|
||||
|
||||
label := col.Label
|
||||
if label == "" {
|
||||
label = col.Comment
|
||||
}
|
||||
if label == "" {
|
||||
label = name
|
||||
}
|
||||
|
||||
filter := Filter{
|
||||
Label: label,
|
||||
Bind: fmt.Sprintf("where.%s.eq", name),
|
||||
Input: vcol.Edit,
|
||||
}
|
||||
filters[name] = filter
|
||||
filters[label] = filter
|
||||
}
|
||||
|
||||
return filters
|
||||
|
||||
}
|
||||
64
table/table.go
Normal file
64
table/table.go
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
package table
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/yaoapp/gou/helper"
|
||||
"github.com/yaoapp/kun/exception"
|
||||
)
|
||||
|
||||
// Tables 已载入模型
|
||||
var Tables = map[string]*Table{}
|
||||
|
||||
// Load 载入数据表格
|
||||
func Load(source string, name string) *Table {
|
||||
var input io.Reader = nil
|
||||
if strings.HasPrefix(source, "file://") || strings.HasPrefix(source, "fs://") {
|
||||
filename := strings.TrimPrefix(source, "file://")
|
||||
filename = strings.TrimPrefix(filename, "fs://")
|
||||
file, err := os.Open(filename)
|
||||
if err != nil {
|
||||
exception.Err(err, 400).Throw()
|
||||
}
|
||||
defer file.Close()
|
||||
input = file
|
||||
} else {
|
||||
input = strings.NewReader(source)
|
||||
}
|
||||
|
||||
table := Table{
|
||||
Source: source,
|
||||
Table: name,
|
||||
}
|
||||
err := helper.UnmarshalFile(input, &table)
|
||||
if err != nil {
|
||||
exception.Err(err, 400).Throw()
|
||||
}
|
||||
|
||||
table.loadColumns()
|
||||
table.loadFilters()
|
||||
table.loadAPIs()
|
||||
Tables[name] = &table
|
||||
return Tables[name]
|
||||
}
|
||||
|
||||
// Select 读取已加载表格配置
|
||||
func Select(name string) *Table {
|
||||
tab, has := Tables[name]
|
||||
if !has {
|
||||
exception.New(
|
||||
fmt.Sprintf("Table:%s; 尚未加载", name),
|
||||
400,
|
||||
).Throw()
|
||||
}
|
||||
return tab
|
||||
}
|
||||
|
||||
// Reload 更新数据表格配置
|
||||
func (tab *Table) Reload() *Table {
|
||||
tab = Load(tab.Source, tab.Name)
|
||||
return tab
|
||||
}
|
||||
38
table/table_test.go
Normal file
38
table/table_test.go
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
package table
|
||||
|
||||
import (
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/yaoapp/xiang/global"
|
||||
)
|
||||
|
||||
func TestLoad(t *testing.T) {
|
||||
global.Load(global.Conf)
|
||||
root := "fs://" + path.Join(global.Conf.Source, "/app/tables/service.json")
|
||||
Load(root, "service").Reload()
|
||||
|
||||
table, has := Tables["service"]
|
||||
assert.Equal(t, table.Table, "service")
|
||||
assert.Equal(t, table.Source, root)
|
||||
assert.True(t, has)
|
||||
|
||||
_, has = table.Columns["id"]
|
||||
assert.True(t, has)
|
||||
|
||||
price, has := table.Columns["计费方式"]
|
||||
assert.True(t, has)
|
||||
if has {
|
||||
assert.True(t, price.Edit.Props["multiple"].(bool))
|
||||
}
|
||||
|
||||
_, has = table.Filters["id"]
|
||||
assert.True(t, has)
|
||||
|
||||
keywords, has := table.Filters["关键词"]
|
||||
assert.True(t, has)
|
||||
if has {
|
||||
assert.True(t, keywords.Bind == "where.name.like")
|
||||
}
|
||||
}
|
||||
80
table/types.go
Normal file
80
table/types.go
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
package table
|
||||
|
||||
import "github.com/yaoapp/gou"
|
||||
|
||||
// Table 数据表格配置结构
|
||||
type Table struct {
|
||||
Table string `json:"-"`
|
||||
Source string `json:"-"`
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
Bind Bind `json:"bind,omitempty"`
|
||||
APIs APIs `json:"apis,omitempty"`
|
||||
Columns map[string]Column `json:"columns,omitempty"`
|
||||
Filters map[string]Filter `json:"filters,omitempty"`
|
||||
List Page `json:"list,omitempty"`
|
||||
Edit Page `json:"edit,omitempty"`
|
||||
View Page `json:"view,omitempty"`
|
||||
Insert Page `json:"insert,omitempty"`
|
||||
}
|
||||
|
||||
// Bind 绑定数据模型
|
||||
type Bind struct {
|
||||
Model string `json:"model"`
|
||||
Withs map[string]gou.With `json:"withs,omitempty"`
|
||||
}
|
||||
|
||||
// APIs API 配置数据结构
|
||||
type APIs struct {
|
||||
Search API `json:"search,omitempty"`
|
||||
Find API `json:"find,omitempty"`
|
||||
Save API `json:"save,omitempty"`
|
||||
Delete API `json:"delete,omitempty"`
|
||||
Insert API `json:"insert,omitempty"`
|
||||
DeleteWhere API `json:"delete-where,omitempty"`
|
||||
DeleteIn API `json:"delete-in,omitempty"`
|
||||
UpdateWhere API `json:"update-where,omitempty"`
|
||||
UpdateIn API `json:"update-in,omitempty"`
|
||||
ImportUpload API `json:"import-upload,omitempty"`
|
||||
ImportPreview API `json:"import-preview,omitempty"`
|
||||
ImportSync API `json:"import-sync,omitempty"`
|
||||
ImportAsync API `json:"import-async,omitempty"`
|
||||
ImportAsyncTasks API `json:"import-async-tasks,omitempty"`
|
||||
ImportAsyncTasksID API `json:"import-async-tasks-id,omitempty"`
|
||||
Setting API `json:"setting,omitempty"`
|
||||
}
|
||||
|
||||
// API API 配置数据结构
|
||||
type API struct {
|
||||
Process string `json:"process,omitempty"`
|
||||
Guard string `json:"guard,omitempty"`
|
||||
Default []interface{} `json:"default,omitempty"`
|
||||
}
|
||||
|
||||
// Column 字段呈现方式
|
||||
type Column struct {
|
||||
Label string `json:"label"`
|
||||
View Render `json:"view,omitempty"`
|
||||
Edit Render `json:"edit,omitempty"`
|
||||
Form Render `json:"form,omitempty"`
|
||||
}
|
||||
|
||||
// Filter 查询过滤器
|
||||
type Filter struct {
|
||||
Label string `json:"label"`
|
||||
Bind string `json:"bind,omitempty"`
|
||||
Input Render `json:"input,omitempty"`
|
||||
}
|
||||
|
||||
// Page 页面
|
||||
type Page struct {
|
||||
Primary string `json:"primary"`
|
||||
Layout map[string]interface{} `json:"layout"`
|
||||
Actions map[string]Render `json:"actions,omitempty"`
|
||||
}
|
||||
|
||||
// Render 组件渲染方式
|
||||
type Render struct {
|
||||
Type string `json:"type,omitempty"`
|
||||
Props map[string]interface{} `json:"props,omitempty"`
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue