@josephyan/qingflow-cli 1.0.11 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/npm/bin/qingflow.mjs +40 -2
- package/npm/lib/runtime.mjs +386 -15
- package/npm/scripts/postinstall.mjs +7 -2
- package/package.json +1 -1
- package/pyproject.toml +1 -1
- package/skills/qingflow-cli/SKILL.md +440 -0
- package/skills/qingflow-cli/manifest.yaml +10 -0
- package/skills/qingflow-cli/reference/QINGFLOW_CLI_ADMIN_CHEATSHEET.md +94 -0
- package/skills/qingflow-cli/reference/QINGFLOW_CLI_BUILDER_APP_DELIVERY_WORKFLOW.md +485 -0
- package/skills/qingflow-cli/reference/QINGFLOW_CLI_BUILDER_CHARTS_WORKFLOW.md +237 -0
- package/skills/qingflow-cli/reference/QINGFLOW_CLI_BUILDER_MATCH_RULES.md +137 -0
- package/skills/qingflow-cli/reference/QINGFLOW_CLI_BUILDER_PORTAL_WORKFLOW.md +263 -0
- package/skills/qingflow-cli/reference/QINGFLOW_CLI_BUILDER_VIEWS_WORKFLOW.md +304 -0
- package/skills/qingflow-cli/reference/QINGFLOW_CLI_BUILDER_WORKSPACE_ICONS.md +41 -0
- package/skills/qingflow-cli/reference/QINGFLOW_CLI_DATA_RETRIEVAL_WORKFLOW.md +139 -0
- package/skills/qingflow-cli/reference/QINGFLOW_CLI_EXPLORATION_REPORT.md +84 -0
- package/skills/qingflow-cli/reference/QINGFLOW_CLI_FIELD_DATA_TYPES.md +129 -0
- package/skills/qingflow-cli/reference/QINGFLOW_CLI_MEMBER_CHEATSHEET.md +195 -0
- package/skills/qingflow-cli/reference/QINGFLOW_CLI_ONE_SHOT_CHEATSHEET.md +159 -0
- package/skills/qingflow-cli/reference/QINGFLOW_CLI_RECORD_CREATE_WORKFLOW.md +20 -0
- package/skills/qingflow-cli/reference/QINGFLOW_CLI_RECORD_IMPORT_WORKFLOW.md +176 -0
- package/skills/qingflow-cli/reference/QINGFLOW_CLI_RECORD_UPDATE_WORKFLOW.md +163 -0
- package/skills/qingflow-cli/reference/QINGFLOW_CLI_SCHEMA_APPLY_FIELD_TYPES_AND_SCENARIOS.md +107 -0
- package/skills/qingflow-cli/reference/QINGFLOW_CLI_TASK_CONTEXT_WORKFLOW.md +151 -0
- package/skills/qingflow-cli/reference/_batch_schema_complex.json +18 -0
- package/skills/qingflow-cli/reference/_batch_schema_scalar.json +17 -0
- package/skills/qingflow-cli/reference/charts_remove.example.json +1 -0
- package/skills/qingflow-cli/reference/charts_reorder.example.json +1 -0
- package/skills/qingflow-cli/reference/charts_upsert_bar.example.json +8 -0
- package/skills/qingflow-cli/reference/charts_upsert_dashboard_starter.example.json +37 -0
- package/skills/qingflow-cli/reference/charts_upsert_minimal.example.json +13 -0
- package/skills/qingflow-cli/reference/portal_sections_all_types.example.json +131 -0
- package/skills/qingflow-cli/reference/portal_sections_five_types.example.json +126 -0
- package/skills/qingflow-cli/reference/portal_sections_standard_workbench.example.json +128 -0
- package/skills/qingflow-cli/reference/schema_add_fields_minimal.example.json +7 -0
- package/skills/qingflow-cli/reference/schema_apply_add_fields_all_types.json +78 -0
- package/skills/qingflow-cli/reference/views_upsert_table_minimal.example.json +7 -0
- package/skills/qingflow-cli/scripts/builder-package-from-app-list.py +140 -0
- package/skills/qingflow-cli/scripts/find-app-by-keyword.py +132 -0
- package/skills/qingflow-cli/scripts/validate_qingflow_output_files.py +87 -0
- package/src/qingflow_mcp/__init__.py +1 -1
- package/src/qingflow_mcp/builder_facade/models.py +532 -48
- package/src/qingflow_mcp/builder_facade/service.py +9194 -2384
- package/src/qingflow_mcp/builder_facade/workflow_spec.py +111 -0
- package/src/qingflow_mcp/cli/commands/app.py +3 -16
- package/src/qingflow_mcp/cli/commands/builder.py +354 -56
- package/src/qingflow_mcp/cli/commands/record.py +89 -2
- package/src/qingflow_mcp/cli/formatters.py +32 -1
- package/src/qingflow_mcp/cli/main.py +245 -3
- package/src/qingflow_mcp/public_surface.py +11 -8
- package/src/qingflow_mcp/response_trim.py +143 -14
- package/src/qingflow_mcp/server.py +15 -12
- package/src/qingflow_mcp/server_app_builder.py +108 -30
- package/src/qingflow_mcp/server_app_user.py +17 -18
- package/src/qingflow_mcp/solution/compiler/__init__.py +1 -3
- package/src/qingflow_mcp/solution/compiler/icon_utils.py +294 -0
- package/src/qingflow_mcp/solution/executor.py +3 -133
- package/src/qingflow_mcp/tools/ai_builder_tools.py +2617 -440
- package/src/qingflow_mcp/tools/app_tools.py +53 -8
- package/src/qingflow_mcp/tools/package_tools.py +16 -2
- package/src/qingflow_mcp/tools/record_tools.py +2095 -176
- package/src/qingflow_mcp/tools/resource_read_tools.py +3 -0
- package/src/qingflow_mcp/tools/solution_tools.py +30 -2
- package/src/qingflow_mcp/tools/workflow_tools.py +3 -31
- package/src/qingflow_mcp/version.py +110 -0
- package/src/qingflow_mcp/solution/compiler/workflow_compiler.py +0 -173
|
@@ -0,0 +1 @@
|
|
|
1
|
+
["CHART_ID_FIRST", "CHART_ID_SECOND"]
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"name": "数据总量",
|
|
4
|
+
"chart_type": "target",
|
|
5
|
+
"metric": "count(*)",
|
|
6
|
+
"visibility": {
|
|
7
|
+
"mode": "workspace",
|
|
8
|
+
"selectors": {},
|
|
9
|
+
"external_mode": "not",
|
|
10
|
+
"external_selectors": {}
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"name": "按状态分布",
|
|
15
|
+
"chart_type": "bar",
|
|
16
|
+
"group_by": ["REPLACE_WITH_STATUS_FIELD_NAME"],
|
|
17
|
+
"metric": "count(*)",
|
|
18
|
+
"visibility": {
|
|
19
|
+
"mode": "workspace",
|
|
20
|
+
"selectors": {},
|
|
21
|
+
"external_mode": "not",
|
|
22
|
+
"external_selectors": {}
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"name": "按时间趋势",
|
|
27
|
+
"chart_type": "line",
|
|
28
|
+
"group_by": ["REPLACE_WITH_DATE_FIELD_NAME"],
|
|
29
|
+
"metric": "count(*)",
|
|
30
|
+
"visibility": {
|
|
31
|
+
"mode": "workspace",
|
|
32
|
+
"selectors": {},
|
|
33
|
+
"external_mode": "not",
|
|
34
|
+
"external_selectors": {}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
]
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"title": "筛选条_实验项_勿默认交付",
|
|
4
|
+
"source_type": "filter",
|
|
5
|
+
"position": {
|
|
6
|
+
"pc": {
|
|
7
|
+
"x": 0,
|
|
8
|
+
"y": 0,
|
|
9
|
+
"cols": 24,
|
|
10
|
+
"rows": 2
|
|
11
|
+
},
|
|
12
|
+
"mobile": {
|
|
13
|
+
"x": 0,
|
|
14
|
+
"y": 0,
|
|
15
|
+
"cols": 6,
|
|
16
|
+
"rows": 2
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"config": {
|
|
20
|
+
"filterConfig": [],
|
|
21
|
+
"graphList": [
|
|
22
|
+
{
|
|
23
|
+
"graphType": "CHART",
|
|
24
|
+
"graphKey": "REPLACE_WITH_QINGBI_CHART_ID",
|
|
25
|
+
"graphName": "可选_图表显示名"
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"title": "九宫格",
|
|
32
|
+
"source_type": "grid",
|
|
33
|
+
"position": {
|
|
34
|
+
"pc": {
|
|
35
|
+
"x": 0,
|
|
36
|
+
"y": 2,
|
|
37
|
+
"cols": 24,
|
|
38
|
+
"rows": 4
|
|
39
|
+
},
|
|
40
|
+
"mobile": {
|
|
41
|
+
"x": 0,
|
|
42
|
+
"y": 2,
|
|
43
|
+
"cols": 6,
|
|
44
|
+
"rows": 4
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"config": {}
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"title": "说明文字块",
|
|
51
|
+
"source_type": "text",
|
|
52
|
+
"position": {
|
|
53
|
+
"pc": {
|
|
54
|
+
"x": 0,
|
|
55
|
+
"y": 6,
|
|
56
|
+
"cols": 24,
|
|
57
|
+
"rows": 2
|
|
58
|
+
},
|
|
59
|
+
"mobile": {
|
|
60
|
+
"x": 0,
|
|
61
|
+
"y": 6,
|
|
62
|
+
"cols": 6,
|
|
63
|
+
"rows": 2
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"text": "本文件仅用于排障/实验:filter 在当前 CLI 直写中可能不落库;稳定自动化模板请使用 portal_sections_five_types.example.json。"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"title": "外部链接",
|
|
70
|
+
"source_type": "link",
|
|
71
|
+
"position": {
|
|
72
|
+
"pc": {
|
|
73
|
+
"x": 0,
|
|
74
|
+
"y": 8,
|
|
75
|
+
"cols": 12,
|
|
76
|
+
"rows": 2
|
|
77
|
+
},
|
|
78
|
+
"mobile": {
|
|
79
|
+
"x": 0,
|
|
80
|
+
"y": 8,
|
|
81
|
+
"cols": 6,
|
|
82
|
+
"rows": 2
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
"url": "https://example.com"
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"title": "应用视图块",
|
|
89
|
+
"source_type": "view",
|
|
90
|
+
"position": {
|
|
91
|
+
"pc": {
|
|
92
|
+
"x": 0,
|
|
93
|
+
"y": 10,
|
|
94
|
+
"cols": 24,
|
|
95
|
+
"rows": 8
|
|
96
|
+
},
|
|
97
|
+
"mobile": {
|
|
98
|
+
"x": 0,
|
|
99
|
+
"y": 10,
|
|
100
|
+
"cols": 6,
|
|
101
|
+
"rows": 8
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
"view_ref": {
|
|
105
|
+
"app_key": "YOUR_APP_KEY",
|
|
106
|
+
"view_key": "YOUR_VIEW_KEY"
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"title": "指标图",
|
|
111
|
+
"source_type": "chart",
|
|
112
|
+
"position": {
|
|
113
|
+
"pc": {
|
|
114
|
+
"x": 0,
|
|
115
|
+
"y": 18,
|
|
116
|
+
"cols": 12,
|
|
117
|
+
"rows": 6
|
|
118
|
+
},
|
|
119
|
+
"mobile": {
|
|
120
|
+
"x": 0,
|
|
121
|
+
"y": 18,
|
|
122
|
+
"cols": 6,
|
|
123
|
+
"rows": 6
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
"chart_ref": {
|
|
127
|
+
"app_key": "YOUR_APP_KEY",
|
|
128
|
+
"chart_id": "YOUR_CHART_ID"
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
]
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"title": "门户说明",
|
|
4
|
+
"source_type": "text",
|
|
5
|
+
"position": {
|
|
6
|
+
"pc": {
|
|
7
|
+
"x": 0,
|
|
8
|
+
"y": 0,
|
|
9
|
+
"cols": 24,
|
|
10
|
+
"rows": 2
|
|
11
|
+
},
|
|
12
|
+
"mobile": {
|
|
13
|
+
"x": 0,
|
|
14
|
+
"y": 0,
|
|
15
|
+
"cols": 6,
|
|
16
|
+
"rows": 2
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"text": "建议将门户设计成工作台:上方放入口,中部放指标,下方放待处理和异常列表。此文件仅演示 grid / text / link / view / chart 的稳定写法。"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"title": "业务入口",
|
|
23
|
+
"source_type": "grid",
|
|
24
|
+
"position": {
|
|
25
|
+
"pc": {
|
|
26
|
+
"x": 0,
|
|
27
|
+
"y": 2,
|
|
28
|
+
"cols": 24,
|
|
29
|
+
"rows": 4
|
|
30
|
+
},
|
|
31
|
+
"mobile": {
|
|
32
|
+
"x": 0,
|
|
33
|
+
"y": 2,
|
|
34
|
+
"cols": 6,
|
|
35
|
+
"rows": 4
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"config": {
|
|
39
|
+
"gridTitle": "业务入口",
|
|
40
|
+
"beingShowTitle": true,
|
|
41
|
+
"items": [
|
|
42
|
+
{
|
|
43
|
+
"type": 1,
|
|
44
|
+
"jumpMode": 1,
|
|
45
|
+
"linkAppKey": "APP_KEY_MAIN",
|
|
46
|
+
"linkFormType": 1,
|
|
47
|
+
"title": "核心业务",
|
|
48
|
+
"customTitle": "核心业务",
|
|
49
|
+
"beingCustomTitle": false
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"type": 1,
|
|
53
|
+
"jumpMode": 1,
|
|
54
|
+
"linkAppKey": "APP_KEY_TASK",
|
|
55
|
+
"linkFormType": 1,
|
|
56
|
+
"title": "待处理业务",
|
|
57
|
+
"customTitle": "待处理业务",
|
|
58
|
+
"beingCustomTitle": false
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"title": "核心指标",
|
|
65
|
+
"source_type": "chart",
|
|
66
|
+
"position": {
|
|
67
|
+
"pc": {
|
|
68
|
+
"x": 0,
|
|
69
|
+
"y": 6,
|
|
70
|
+
"cols": 8,
|
|
71
|
+
"rows": 6
|
|
72
|
+
},
|
|
73
|
+
"mobile": {
|
|
74
|
+
"x": 0,
|
|
75
|
+
"y": 6,
|
|
76
|
+
"cols": 6,
|
|
77
|
+
"rows": 6
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
"chart_ref": {
|
|
81
|
+
"app_key": "ead8ims5i401",
|
|
82
|
+
"chart_id": "mcp_fb104267c5c249ca"
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"title": "待处理列表",
|
|
87
|
+
"source_type": "view",
|
|
88
|
+
"position": {
|
|
89
|
+
"pc": {
|
|
90
|
+
"x": 0,
|
|
91
|
+
"y": 12,
|
|
92
|
+
"cols": 12,
|
|
93
|
+
"rows": 8
|
|
94
|
+
},
|
|
95
|
+
"mobile": {
|
|
96
|
+
"x": 0,
|
|
97
|
+
"y": 12,
|
|
98
|
+
"cols": 6,
|
|
99
|
+
"rows": 8
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
"view_ref": {
|
|
103
|
+
"app_key": "ead8ims5i401",
|
|
104
|
+
"view_key": "ead8kbf1i402"
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"title": "帮助文档",
|
|
109
|
+
"source_type": "link",
|
|
110
|
+
"position": {
|
|
111
|
+
"pc": {
|
|
112
|
+
"x": 12,
|
|
113
|
+
"y": 12,
|
|
114
|
+
"cols": 12,
|
|
115
|
+
"rows": 2
|
|
116
|
+
},
|
|
117
|
+
"mobile": {
|
|
118
|
+
"x": 0,
|
|
119
|
+
"y": 20,
|
|
120
|
+
"cols": 6,
|
|
121
|
+
"rows": 2
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
"url": "https://example.com"
|
|
125
|
+
}
|
|
126
|
+
]
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"title": "业务入口",
|
|
4
|
+
"source_type": "grid",
|
|
5
|
+
"position": {
|
|
6
|
+
"pc": {"x": 0, "y": 0, "cols": 24, "rows": 4},
|
|
7
|
+
"mobile": {"x": 0, "y": 0, "cols": 6, "rows": 4}
|
|
8
|
+
},
|
|
9
|
+
"config": {
|
|
10
|
+
"gridTitle": "业务入口",
|
|
11
|
+
"beingShowTitle": true,
|
|
12
|
+
"items": [
|
|
13
|
+
{
|
|
14
|
+
"type": 1,
|
|
15
|
+
"jumpMode": 1,
|
|
16
|
+
"linkAppKey": "APP_KEY_DEVICE",
|
|
17
|
+
"linkFormType": 1,
|
|
18
|
+
"title": "设备台账",
|
|
19
|
+
"customTitle": "设备台账",
|
|
20
|
+
"beingCustomTitle": false
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"type": 1,
|
|
24
|
+
"jumpMode": 1,
|
|
25
|
+
"linkAppKey": "APP_KEY_REPAIR",
|
|
26
|
+
"linkFormType": 1,
|
|
27
|
+
"title": "故障报修",
|
|
28
|
+
"customTitle": "故障报修",
|
|
29
|
+
"beingCustomTitle": false
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"type": 1,
|
|
33
|
+
"jumpMode": 1,
|
|
34
|
+
"linkAppKey": "APP_KEY_MAINTENANCE",
|
|
35
|
+
"linkFormType": 1,
|
|
36
|
+
"title": "保养管理",
|
|
37
|
+
"customTitle": "保养管理",
|
|
38
|
+
"beingCustomTitle": false
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"title": "设备总数",
|
|
45
|
+
"source_type": "chart",
|
|
46
|
+
"role": "metric",
|
|
47
|
+
"position": {
|
|
48
|
+
"pc": {"x": 0, "y": 4, "cols": 6, "rows": 5},
|
|
49
|
+
"mobile": {"x": 0, "y": 4, "cols": 6, "rows": 5}
|
|
50
|
+
},
|
|
51
|
+
"chart_ref": {"app_key": "APP_KEY_DEVICE", "chart_id": "CHART_ID_TOTAL"}
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"title": "正常设备",
|
|
55
|
+
"source_type": "chart",
|
|
56
|
+
"role": "metric",
|
|
57
|
+
"position": {
|
|
58
|
+
"pc": {"x": 6, "y": 4, "cols": 6, "rows": 5},
|
|
59
|
+
"mobile": {"x": 0, "y": 9, "cols": 6, "rows": 5}
|
|
60
|
+
},
|
|
61
|
+
"chart_ref": {"app_key": "APP_KEY_DEVICE", "chart_id": "CHART_ID_NORMAL"}
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"title": "维修中设备",
|
|
65
|
+
"source_type": "chart",
|
|
66
|
+
"role": "metric",
|
|
67
|
+
"position": {
|
|
68
|
+
"pc": {"x": 12, "y": 4, "cols": 6, "rows": 5},
|
|
69
|
+
"mobile": {"x": 0, "y": 14, "cols": 6, "rows": 5}
|
|
70
|
+
},
|
|
71
|
+
"chart_ref": {"app_key": "APP_KEY_DEVICE", "chart_id": "CHART_ID_REPAIRING"}
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"title": "本月报修",
|
|
75
|
+
"source_type": "chart",
|
|
76
|
+
"role": "metric",
|
|
77
|
+
"position": {
|
|
78
|
+
"pc": {"x": 18, "y": 4, "cols": 6, "rows": 5},
|
|
79
|
+
"mobile": {"x": 0, "y": 19, "cols": 6, "rows": 5}
|
|
80
|
+
},
|
|
81
|
+
"chart_ref": {"app_key": "APP_KEY_REPAIR", "chart_id": "CHART_ID_REPAIR_MONTH"}
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"title": "设备状态分布",
|
|
85
|
+
"source_type": "chart",
|
|
86
|
+
"position": {
|
|
87
|
+
"pc": {"x": 0, "y": 9, "cols": 8, "rows": 7},
|
|
88
|
+
"mobile": {"x": 0, "y": 24, "cols": 6, "rows": 7}
|
|
89
|
+
},
|
|
90
|
+
"chart_ref": {"app_key": "APP_KEY_DEVICE", "chart_id": "CHART_ID_STATUS_DIST"}
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"title": "故障类型分布",
|
|
94
|
+
"source_type": "chart",
|
|
95
|
+
"position": {
|
|
96
|
+
"pc": {"x": 8, "y": 9, "cols": 8, "rows": 7},
|
|
97
|
+
"mobile": {"x": 0, "y": 31, "cols": 6, "rows": 7}
|
|
98
|
+
},
|
|
99
|
+
"chart_ref": {"app_key": "APP_KEY_REPAIR", "chart_id": "CHART_ID_FAULT_DIST"}
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"title": "维修完成趋势",
|
|
103
|
+
"source_type": "chart",
|
|
104
|
+
"position": {
|
|
105
|
+
"pc": {"x": 16, "y": 9, "cols": 8, "rows": 7},
|
|
106
|
+
"mobile": {"x": 0, "y": 38, "cols": 6, "rows": 7}
|
|
107
|
+
},
|
|
108
|
+
"chart_ref": {"app_key": "APP_KEY_REPAIR", "chart_id": "CHART_ID_REPAIR_TREND"}
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"title": "异常设备",
|
|
112
|
+
"source_type": "view",
|
|
113
|
+
"position": {
|
|
114
|
+
"pc": {"x": 0, "y": 16, "cols": 12, "rows": 11},
|
|
115
|
+
"mobile": {"x": 0, "y": 45, "cols": 6, "rows": 11}
|
|
116
|
+
},
|
|
117
|
+
"view_ref": {"app_key": "APP_KEY_DEVICE", "view_key": "VIEW_KEY_ABNORMAL_DEVICES"}
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"title": "待处理工单",
|
|
121
|
+
"source_type": "view",
|
|
122
|
+
"position": {
|
|
123
|
+
"pc": {"x": 12, "y": 16, "cols": 12, "rows": 11},
|
|
124
|
+
"mobile": {"x": 0, "y": 56, "cols": 6, "rows": 11}
|
|
125
|
+
},
|
|
126
|
+
"view_ref": {"app_key": "APP_KEY_REPAIR", "view_key": "VIEW_KEY_PENDING_WORK_ORDERS"}
|
|
127
|
+
}
|
|
128
|
+
]
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"name": "QFCLI_AT_text",
|
|
4
|
+
"type": "text",
|
|
5
|
+
"as_data_title": true,
|
|
6
|
+
"description": "【本文件用法】推荐一次成功:npx @qingflow-tech/qingflow-cli --profile default builder schema apply --package-id <你的包tag_id> --app-name \"新应用名\" --create-if-missing --no-publish --add-fields-file schema_apply_add_fields_all_types.json。内含19种搭建 type(另含远程查询/代码块所需辅助 text),且已在本字段标记 as_data_title。关联字段 target_app_key 默认为本仓库实测用的模板应用 ead8ims5i401(须含「单行文字」「多行文字」);其它租户请改成你方可读的目标应用 app_key。若用 --app-key 向已有应用追加:须无「关联」字段且字段名不重复;每应用仅允许一个 relation。"
|
|
7
|
+
},
|
|
8
|
+
{"name": "QFCLI_AT_long_text", "type": "long_text"},
|
|
9
|
+
{"name": "QFCLI_AT_number", "type": "number"},
|
|
10
|
+
{"name": "QFCLI_AT_amount", "type": "amount"},
|
|
11
|
+
{"name": "QFCLI_AT_date", "type": "date"},
|
|
12
|
+
{"name": "QFCLI_AT_datetime", "type": "datetime"},
|
|
13
|
+
{"name": "QFCLI_AT_member", "type": "member"},
|
|
14
|
+
{"name": "QFCLI_AT_department", "type": "department", "department_scope": {"mode": "all"}},
|
|
15
|
+
{"name": "QFCLI_AT_single_select", "type": "single_select", "options": ["A", "B"]},
|
|
16
|
+
{"name": "QFCLI_AT_multi_select", "type": "multi_select", "options": ["X", "Y"]},
|
|
17
|
+
{"name": "QFCLI_AT_phone", "type": "phone"},
|
|
18
|
+
{"name": "QFCLI_AT_email", "type": "email"},
|
|
19
|
+
{"name": "QFCLI_AT_address", "type": "address"},
|
|
20
|
+
{"name": "QFCLI_AT_attachment", "type": "attachment", "as_data_cover": true},
|
|
21
|
+
{"name": "QFCLI_AT_boolean", "type": "boolean"},
|
|
22
|
+
{"name": "QFCLI_AT_ql_kw", "type": "text"},
|
|
23
|
+
{"name": "QFCLI_AT_ql_v1", "type": "text"},
|
|
24
|
+
{"name": "QFCLI_AT_ql_v2", "type": "text"},
|
|
25
|
+
{"name": "QFCLI_AT_cb_in", "type": "text"},
|
|
26
|
+
{"name": "QFCLI_AT_cb_out", "type": "text"},
|
|
27
|
+
{
|
|
28
|
+
"name": "QFCLI_AT_sub",
|
|
29
|
+
"type": "subtable",
|
|
30
|
+
"subfields": [
|
|
31
|
+
{"name": "QFCLI_AT_sub_c1", "type": "text"},
|
|
32
|
+
{"name": "QFCLI_AT_sub_c2", "type": "number"}
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"name": "QFCLI_AT_q_linker",
|
|
37
|
+
"type": "q_linker",
|
|
38
|
+
"q_linker_binding": {
|
|
39
|
+
"inputs": [{"field": {"name": "QFCLI_AT_ql_kw"}, "key": "k", "source": "query_param"}],
|
|
40
|
+
"request": {
|
|
41
|
+
"url": "https://httpbin.org/get",
|
|
42
|
+
"method": "GET",
|
|
43
|
+
"headers": [],
|
|
44
|
+
"query_params": [],
|
|
45
|
+
"body_type": 1,
|
|
46
|
+
"url_encoded_value": [],
|
|
47
|
+
"result_type": 1,
|
|
48
|
+
"auto_trigger": false,
|
|
49
|
+
"custom_button_text_enabled": true,
|
|
50
|
+
"custom_button_text": "查"
|
|
51
|
+
},
|
|
52
|
+
"outputs": [
|
|
53
|
+
{"alias": "a", "path": "$.headers.Host", "target_field": {"name": "QFCLI_AT_ql_v1"}},
|
|
54
|
+
{"alias": "b", "path": "$.url", "target_field": {"name": "QFCLI_AT_ql_v2"}}
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"name": "QFCLI_AT_code_block",
|
|
60
|
+
"type": "code_block",
|
|
61
|
+
"code_block_binding": {
|
|
62
|
+
"inputs": [{"field": {"name": "QFCLI_AT_cb_in"}, "var": "x"}],
|
|
63
|
+
"code": "qf_output = {}; qf_output.r = x ? '1' : '0';",
|
|
64
|
+
"auto_trigger": false,
|
|
65
|
+
"custom_button_text_enabled": true,
|
|
66
|
+
"custom_button_text": "运行",
|
|
67
|
+
"outputs": [{"alias": "r", "path": "$.r", "target_field": {"name": "QFCLI_AT_cb_out"}}]
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"name": "QFCLI_AT_relation",
|
|
72
|
+
"type": "relation",
|
|
73
|
+
"target_app_key": "ead8ims5i401",
|
|
74
|
+
"relation_mode": "single",
|
|
75
|
+
"display_field": {"name": "单行文字"},
|
|
76
|
+
"visible_fields": [{"name": "多行文字"}]
|
|
77
|
+
}
|
|
78
|
+
]
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""纯 CLI 曲线:在 **无** `package_list` / `package_resolve` 子命令时,用 `app list` + `builder app resolve` 解析包。
|
|
3
|
+
|
|
4
|
+
- `app list`(`GET /tag/apps` 扁平结果)常见含 **`package_name`**(分组显示名),**不一定**含数值 **`tag_id`**。
|
|
5
|
+
- `builder app resolve --app-key` 的 JSON 里常有 **`package_ids`**(与 MCP `package_get` 所用的 `tag_id` 同源)。
|
|
6
|
+
|
|
7
|
+
子命令:
|
|
8
|
+
list-names 打印去重后的 `package_name` 列表(JSON 数组)
|
|
9
|
+
resolve-id <显示名> **精确匹配** `package_name`,取该组下第一个 `app_key`,再 `builder app resolve`,打印含 `package_ids` 的 JSON object
|
|
10
|
+
|
|
11
|
+
环境(可选): `QINGFLOW_PROFILE` → 等价于 `qingflow --profile <名称>`
|
|
12
|
+
|
|
13
|
+
注意:
|
|
14
|
+
- 若工作区内存在 **同名分组**(多个 `tag_id` 共用显示名),本脚本 **无法**区分,请用管理端或 MCP `package_list`。
|
|
15
|
+
- 某包下 **尚未有任何可见应用** 时,无法从 `app list` 曲线解析。
|
|
16
|
+
|
|
17
|
+
用法:
|
|
18
|
+
./scripts/builder-package-from-app-list.py list-names
|
|
19
|
+
./scripts/builder-package-from-app-list.py resolve-id 'test'
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
import json
|
|
25
|
+
import os
|
|
26
|
+
import shutil
|
|
27
|
+
import subprocess
|
|
28
|
+
import sys
|
|
29
|
+
from typing import Any
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _qf_base() -> list[str]:
|
|
33
|
+
cmd = ["qingflow"]
|
|
34
|
+
pf = os.environ.get("QINGFLOW_PROFILE") or os.environ.get("QING_FLOW_PROFILE")
|
|
35
|
+
if pf:
|
|
36
|
+
cmd.extend(["--profile", pf])
|
|
37
|
+
return cmd
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _run_json(cmd: list[str]) -> dict[str, Any]:
|
|
41
|
+
proc = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=None)
|
|
42
|
+
if proc.returncode != 0:
|
|
43
|
+
sys.stdout.buffer.write(proc.stdout)
|
|
44
|
+
sys.stdout.flush()
|
|
45
|
+
raise SystemExit(proc.returncode)
|
|
46
|
+
try:
|
|
47
|
+
text = proc.stdout.decode("utf-8")
|
|
48
|
+
payload = json.loads(text)
|
|
49
|
+
except (UnicodeDecodeError, json.JSONDecodeError) as e:
|
|
50
|
+
print(f"qingflow JSON 解析失败: {e}", file=sys.stderr)
|
|
51
|
+
sys.stdout.buffer.write(proc.stdout)
|
|
52
|
+
sys.stdout.flush()
|
|
53
|
+
raise SystemExit(1) from e
|
|
54
|
+
if not isinstance(payload, dict):
|
|
55
|
+
print("qingflow JSON 根不是 object", file=sys.stderr)
|
|
56
|
+
raise SystemExit(1)
|
|
57
|
+
return payload
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _app_list_items(payload: dict[str, Any]) -> list[dict[str, Any]]:
|
|
61
|
+
it = payload.get("items")
|
|
62
|
+
if isinstance(it, list):
|
|
63
|
+
return [x for x in it if isinstance(x, dict)]
|
|
64
|
+
nested = payload.get("data")
|
|
65
|
+
if isinstance(nested, dict):
|
|
66
|
+
it2 = nested.get("items")
|
|
67
|
+
if isinstance(it2, list):
|
|
68
|
+
return [x for x in it2 if isinstance(x, dict)]
|
|
69
|
+
return []
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def cmd_list_names() -> None:
|
|
73
|
+
if not shutil.which("qingflow"):
|
|
74
|
+
print("qingflow: command not found", file=sys.stderr)
|
|
75
|
+
sys.exit(127)
|
|
76
|
+
payload = _run_json(_qf_base() + ["--json", "app", "list"])
|
|
77
|
+
rows = _app_list_items(payload)
|
|
78
|
+
names: set[str] = set()
|
|
79
|
+
for o in rows:
|
|
80
|
+
pn = o.get("package_name")
|
|
81
|
+
if isinstance(pn, str) and pn.strip():
|
|
82
|
+
names.add(pn.strip())
|
|
83
|
+
json.dump(sorted(names), sys.stdout, ensure_ascii=False, indent=2)
|
|
84
|
+
sys.stdout.write("\n")
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def cmd_resolve_id(display_name: str) -> None:
|
|
88
|
+
if not shutil.which("qingflow"):
|
|
89
|
+
print("qingflow: command not found", file=sys.stderr)
|
|
90
|
+
sys.exit(127)
|
|
91
|
+
want = display_name.strip()
|
|
92
|
+
if not want:
|
|
93
|
+
print("显示名不能为空", file=sys.stderr)
|
|
94
|
+
sys.exit(2)
|
|
95
|
+
|
|
96
|
+
payload = _run_json(_qf_base() + ["--json", "app", "list"])
|
|
97
|
+
rows = _app_list_items(payload)
|
|
98
|
+
app_key: str | None = None
|
|
99
|
+
for o in rows:
|
|
100
|
+
pn = o.get("package_name")
|
|
101
|
+
if isinstance(pn, str) and pn.strip() == want:
|
|
102
|
+
ak = o.get("app_key")
|
|
103
|
+
if isinstance(ak, str) and ak.strip():
|
|
104
|
+
app_key = ak.strip()
|
|
105
|
+
break
|
|
106
|
+
if not app_key:
|
|
107
|
+
print(json.dumps({"error": "no_app_under_package_name", "package_name": want}, ensure_ascii=False, indent=2))
|
|
108
|
+
sys.exit(3)
|
|
109
|
+
|
|
110
|
+
resolved = _run_json(_qf_base() + ["--json", "builder", "app", "resolve", "--app-key", app_key])
|
|
111
|
+
out = {
|
|
112
|
+
"package_name": want,
|
|
113
|
+
"sample_app_key": app_key,
|
|
114
|
+
"package_ids": resolved.get("package_ids"),
|
|
115
|
+
"resolve": resolved,
|
|
116
|
+
}
|
|
117
|
+
json.dump(out, sys.stdout, ensure_ascii=False, indent=2)
|
|
118
|
+
sys.stdout.write("\n")
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def main() -> None:
|
|
122
|
+
if len(sys.argv) < 2:
|
|
123
|
+
print(__doc__.strip(), file=sys.stderr)
|
|
124
|
+
sys.exit(2)
|
|
125
|
+
sub = sys.argv[1].strip().lower()
|
|
126
|
+
if sub in {"list-names", "list_names", "names"}:
|
|
127
|
+
cmd_list_names()
|
|
128
|
+
return
|
|
129
|
+
if sub in {"resolve-id", "resolve_id", "resolve"}:
|
|
130
|
+
if len(sys.argv) != 3:
|
|
131
|
+
print("用法: … resolve-id '<package显示名>'", file=sys.stderr)
|
|
132
|
+
sys.exit(2)
|
|
133
|
+
cmd_resolve_id(sys.argv[2])
|
|
134
|
+
return
|
|
135
|
+
print(__doc__.strip(), file=sys.stderr)
|
|
136
|
+
sys.exit(2)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
if __name__ == "__main__":
|
|
140
|
+
main()
|