@qingflow-tech/qingflow-cli 1.1.51 → 1.1.54

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.
Files changed (106) hide show
  1. package/README.md +4 -4
  2. package/npm/lib/runtime.mjs +29 -13
  3. package/package.json +1 -1
  4. package/pyproject.toml +8 -2
  5. package/skills/qingflow-cli/SKILL.md +93 -322
  6. package/skills/qingflow-cli/manifest.yaml +1 -1
  7. package/skills/qingflow-cli/reference/00-INDEX.md +4 -4
  8. package/skills/qingflow-cli/reference/QINGFLOW_CLI_ADMIN_CHEATSHEET.md +1 -1
  9. package/skills/qingflow-cli/reference/QINGFLOW_CLI_BUILDER_VIEWS_WORKFLOW.md +3 -9
  10. package/skills/qingflow-cli/reference/QINGFLOW_CLI_DATA_RETRIEVAL_WORKFLOW.md +3 -137
  11. package/skills/qingflow-cli/reference/QINGFLOW_CLI_EXPLORATION_REPORT.md +6 -4
  12. package/skills/qingflow-cli/reference/QINGFLOW_CLI_FIELD_DATA_TYPES.md +14 -14
  13. package/skills/qingflow-cli/reference/QINGFLOW_CLI_MEMBER_CHEATSHEET.md +20 -19
  14. package/skills/qingflow-cli/reference/QINGFLOW_CLI_ONE_SHOT_CHEATSHEET.md +18 -14
  15. package/skills/qingflow-cli/reference/QINGFLOW_CLI_RECORD_CREATE_WORKFLOW.md +7 -12
  16. package/skills/qingflow-cli/reference/QINGFLOW_CLI_RECORD_UPDATE_WORKFLOW.md +2 -1
  17. package/skills/qingflow-cli/reference/builder/20-build-complete-system.md +3 -2
  18. package/skills/qingflow-cli/reference/builder/30-schema-fields.md +9 -5
  19. package/skills/qingflow-cli/reference/builder/50-views.md +192 -191
  20. package/skills/qingflow-cli/reference/builder/80-buttons-associated-resources.md +2 -0
  21. package/skills/qingflow-cli/reference/builder/README.md +1 -1
  22. package/skills/qingflow-cli/reference/builder/reference/app-delivery-sop.md +6 -6
  23. package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_ADMIN_CHEATSHEET.md +1 -1
  24. package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_DATA_RETRIEVAL_WORKFLOW.md +76 -95
  25. package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_EXPLORATION_REPORT.md +6 -4
  26. package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_FIELD_DATA_TYPES.md +13 -13
  27. package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_MEMBER_CHEATSHEET.md +20 -19
  28. package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_ONE_SHOT_CHEATSHEET.md +18 -14
  29. package/skills/qingflow-cli/reference/data/README.md +32 -0
  30. package/skills/qingflow-cli/reference/examples/README.md +1 -1
  31. package/skills/qingflow-cli/reference/examples/views/views_apply_v1alpha1.example.json +14 -0
  32. package/skills/qingflow-cli/reference/examples/views/views_upsert_table_minimal.example.json +30 -36
  33. package/skills/qingflow-cli/reference/record/QINGFLOW_CLI_RECORD_SPECIALIZED_WORKFLOW.md +50 -0
  34. package/skills/qingflow-cli/reference/record/QINGFLOW_CLI_RECORD_UPDATE_WORKFLOW.md +2 -1
  35. package/skills/qingflow-cli/reference/record/analysis/README.md +21 -113
  36. package/skills/qingflow-cli/reference/record/analysis/analysis-gotchas.md +10 -10
  37. package/skills/qingflow-cli/reference/record/analysis/analysis-patterns.md +9 -9
  38. package/skills/qingflow-cli/reference/record/analysis/business-context.md +1 -1
  39. package/skills/qingflow-cli/reference/record/analysis/confidence-reporting.md +10 -10
  40. package/skills/qingflow-cli/reference/record/analysis/data-access-playbook.md +52 -80
  41. package/skills/qingflow-cli/reference/record/analysis/pandas-recipes.md +2 -2
  42. package/skills/qingflow-common/SKILL.md +7 -4
  43. package/src/qingflow_mcp/app_form_compat.py +3 -0
  44. package/src/qingflow_mcp/app_form_validator.py +69 -17
  45. package/src/qingflow_mcp/builder_facade/app_form.py +497 -100
  46. package/src/qingflow_mcp/builder_facade/models.py +227 -17
  47. package/src/qingflow_mcp/builder_facade/schemas/app_form/manifest.json +1 -0
  48. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/complete.json +64 -30
  49. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/address.json +4 -8
  50. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/amount.json +4 -8
  51. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/attachment.json +6 -10
  52. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/code_block.json +6 -10
  53. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/data_relation.json +11 -18
  54. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/date.json +4 -8
  55. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/datetime.json +4 -8
  56. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/department.json +6 -10
  57. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/email.json +4 -8
  58. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/link.json +4 -8
  59. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/long_text.json +4 -8
  60. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/member.json +6 -10
  61. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/multi_select.json +4 -8
  62. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/number.json +4 -8
  63. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/phone.json +4 -8
  64. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/q_linker.json +6 -10
  65. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/relation.json +46 -15
  66. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/rich_text.json +146 -0
  67. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/single_choice.json +4 -8
  68. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/single_select.json +4 -8
  69. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/subtable.json +61 -27
  70. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/text.json +4 -8
  71. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/formula.json +43 -0
  72. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/summary.json +7 -12
  73. package/src/qingflow_mcp/builder_facade/schemas/views/manifest.json +42 -0
  74. package/src/qingflow_mcp/builder_facade/schemas/views/v1alpha1/complete.json +1245 -0
  75. package/src/qingflow_mcp/builder_facade/schemas/views/v1alpha1/details/button-config.json +53 -0
  76. package/src/qingflow_mcp/builder_facade/schemas/views/v1alpha1/details/data-permission.json +60 -0
  77. package/src/qingflow_mcp/builder_facade/schemas/views/v1alpha1/details/display.json +73 -0
  78. package/src/qingflow_mcp/builder_facade/schemas/views/v1alpha1/details/operation-permission.json +48 -0
  79. package/src/qingflow_mcp/builder_facade/schemas/views/v1alpha1/details/query-condition.json +47 -0
  80. package/src/qingflow_mcp/builder_facade/schemas/views/v1alpha1/summary.json +319 -0
  81. package/src/qingflow_mcp/builder_facade/service.py +1709 -518
  82. package/src/qingflow_mcp/builder_facade/views_extract.py +595 -0
  83. package/src/qingflow_mcp/builder_facade/views_schema.py +400 -0
  84. package/src/qingflow_mcp/cli/commands/__init__.py +2 -1
  85. package/src/qingflow_mcp/cli/commands/builder.py +76 -55
  86. package/src/qingflow_mcp/cli/commands/data.py +134 -0
  87. package/src/qingflow_mcp/cli/commands/record.py +1 -1
  88. package/src/qingflow_mcp/cli/context.py +3 -0
  89. package/src/qingflow_mcp/cli/formatters.py +97 -1
  90. package/src/qingflow_mcp/public_surface.py +8 -0
  91. package/src/qingflow_mcp/response_trim.py +11 -2
  92. package/src/qingflow_mcp/server.py +2 -0
  93. package/src/qingflow_mcp/server_app_builder.py +34 -10
  94. package/src/qingflow_mcp/server_app_user.py +4 -0
  95. package/src/qingflow_mcp/solution/compiler/view_compiler.py +2 -1
  96. package/src/qingflow_mcp/solution/executor.py +96 -8
  97. package/src/qingflow_mcp/solution/spec_models.py +1 -0
  98. package/src/qingflow_mcp/tools/ai_builder_tools.py +218 -398
  99. package/src/qingflow_mcp/tools/csv_export.py +168 -0
  100. package/src/qingflow_mcp/tools/data_tools.py +284 -0
  101. package/src/qingflow_mcp/tools/record_tools.py +11 -46
  102. package/src/qingflow_mcp/tools/solution_tools.py +2 -0
  103. package/src/qingflow_mcp/tools/view_tools.py +0 -6
  104. package/src/qingflow_mcp/tools/view_writer.py +44 -0
  105. package/skills/qingflow-cli/reference/examples/views/views_batch_full.example.json +0 -159
  106. package/skills/qingflow-cli/reference/views_upsert_table_minimal.example.json +0 -42
@@ -0,0 +1,146 @@
1
+ {
2
+ "$defs": {
3
+ "EmptyConfig": {
4
+ "additionalProperties": false,
5
+ "description": "该字段类型没有特殊配置。",
6
+ "type": "object"
7
+ },
8
+ "FieldCommon": {
9
+ "allOf": [
10
+ {
11
+ "if": {
12
+ "properties": {
13
+ "defaultType": {
14
+ "const": 2
15
+ }
16
+ },
17
+ "required": [
18
+ "defaultType"
19
+ ]
20
+ },
21
+ "then": {
22
+ "properties": {
23
+ "defaultValue": {
24
+ "type": "null"
25
+ }
26
+ }
27
+ }
28
+ },
29
+ {
30
+ "if": {
31
+ "properties": {
32
+ "defaultType": {
33
+ "const": 3
34
+ }
35
+ },
36
+ "required": [
37
+ "defaultType"
38
+ ]
39
+ },
40
+ "then": {
41
+ "properties": {
42
+ "defaultValue": {
43
+ "minLength": 1,
44
+ "type": [
45
+ "string",
46
+ "null"
47
+ ]
48
+ }
49
+ }
50
+ }
51
+ }
52
+ ],
53
+ "anyOf": [
54
+ {
55
+ "required": [
56
+ "queId"
57
+ ]
58
+ },
59
+ {
60
+ "required": [
61
+ "name"
62
+ ]
63
+ }
64
+ ],
65
+ "description": "顶层业务字段的公共属性;字段类型由 TopField 的判别分支定义。",
66
+ "properties": {
67
+ "beingRequired": {
68
+ "description": "该字段是否必填;缺失时保留已有字段当前值。",
69
+ "type": "boolean"
70
+ },
71
+ "defaultType": {
72
+ "default": 1,
73
+ "description": "默认值类型,与 defaultValue 联动;1 表示静态值,2 表示关联/绑定值且 defaultValue 只能省略或为 null,3 表示公式值且提供 defaultValue 时必须为非空公式文本。省略 defaultType 但提供 defaultValue 时按 1 处理。",
74
+ "enum": [
75
+ 1,
76
+ 2,
77
+ 3
78
+ ],
79
+ "type": "integer"
80
+ },
81
+ "defaultValue": {
82
+ "$ref": "#/$defs/ScalarDefaultValue",
83
+ "description": "普通字段的默认值;后端 queDefaultValue 为字符串,因此数字等字面量也必须以字符串传入。defaultType 为 1 时表示静态文本,为 3 时表示公式文本,为 2 时不携带字面量默认值。表格、地址、附件、引用等结构化默认值必须放在具体字段 config.defaultValues。显式 null 表示清除默认值。"
84
+ },
85
+ "name": {
86
+ "description": "字段展示名称;新增字段必填,已有字段可在携带 queId 时省略;同父级允许同名(后端以 queId 为字段身份),配置引用建议携带 queId。",
87
+ "minLength": 1,
88
+ "type": "string"
89
+ },
90
+ "queId": {
91
+ "description": "已有字段的后端 ID;更新时用于精确定位并复用,新增字段通常省略。",
92
+ "minimum": 1,
93
+ "type": "integer"
94
+ },
95
+ "questionDescription": {
96
+ "description": "字段说明;null 或空字符串表示清空。",
97
+ "type": [
98
+ "string",
99
+ "null"
100
+ ]
101
+ },
102
+ "questionType": {
103
+ "description": "字段类型;具体可用值由当前字段详情 Schema 的判别分支约束。",
104
+ "type": "string"
105
+ },
106
+ "width": {
107
+ "description": "字段在所在行的宽度百分比(1-100 整数);后端不校验总和与取值,存量数据存在 33/34 等三等分布值。",
108
+ "maximum": 100,
109
+ "minimum": 1,
110
+ "type": "integer"
111
+ }
112
+ },
113
+ "type": "object"
114
+ },
115
+ "ScalarDefaultValue": {
116
+ "description": "后端 queDefaultValue 支持的普通字段默认值;非空值必须是字符串,显式 null 表示清除默认值。数字和布尔值应先转换为字符串,对象和数组必须使用字段专用默认值配置。defaultType 为 3 时,通过 AppForm Schema 查询能力传入当前 schema_version 并设置 schema_kind=formula 获取公式语法、字段引用、运算符和全部函数说明;CLI 使用 builder app-form schema --schema-kind formula。需要配置结构化默认值时,传入当前 schema_version,并将字段的 questionType 作为 field_type 获取字段详细 Schema。",
117
+ "type": [
118
+ "null",
119
+ "string"
120
+ ]
121
+ }
122
+ },
123
+ "$id": "https://builder.qingflow.com/schemas/app-form-apply/v1alpha1/fields/rich_text.json",
124
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
125
+ "allOf": [
126
+ {
127
+ "$ref": "#/$defs/FieldCommon"
128
+ },
129
+ {
130
+ "properties": {
131
+ "config": {
132
+ "$ref": "#/$defs/EmptyConfig"
133
+ },
134
+ "questionType": {
135
+ "const": "rich_text"
136
+ }
137
+ },
138
+ "required": [
139
+ "questionType"
140
+ ]
141
+ }
142
+ ],
143
+ "title": "Qingflow AppForm v1alpha1 rich_text field",
144
+ "type": "object",
145
+ "unevaluatedProperties": false
146
+ }
@@ -146,7 +146,7 @@
146
146
  "description": "普通字段的默认值;后端 queDefaultValue 为字符串,因此数字等字面量也必须以字符串传入。defaultType 为 1 时表示静态文本,为 3 时表示公式文本,为 2 时不携带字面量默认值。表格、地址、附件、引用等结构化默认值必须放在具体字段 config.defaultValues。显式 null 表示清除默认值。"
147
147
  },
148
148
  "name": {
149
- "description": "字段展示名称;新增字段必填,已有字段可在携带 queId 时省略;同一父级内唯一。",
149
+ "description": "字段展示名称;新增字段必填,已有字段可在携带 queId 时省略;同父级允许同名(后端以 queId 为字段身份),配置引用建议携带 queId。",
150
150
  "minLength": 1,
151
151
  "type": "string"
152
152
  },
@@ -167,13 +167,9 @@
167
167
  "type": "string"
168
168
  },
169
169
  "width": {
170
- "description": "字段在所在行的宽度百分比;只能选择 25、50、75 或 100。",
171
- "enum": [
172
- 25,
173
- 50,
174
- 75,
175
- 100
176
- ],
170
+ "description": "字段在所在行的宽度百分比(1-100 整数);后端不校验总和与取值,存量数据存在 33/34 等三等分布值。",
171
+ "maximum": 100,
172
+ "minimum": 1,
177
173
  "type": "integer"
178
174
  }
179
175
  },
@@ -146,7 +146,7 @@
146
146
  "description": "普通字段的默认值;后端 queDefaultValue 为字符串,因此数字等字面量也必须以字符串传入。defaultType 为 1 时表示静态文本,为 3 时表示公式文本,为 2 时不携带字面量默认值。表格、地址、附件、引用等结构化默认值必须放在具体字段 config.defaultValues。显式 null 表示清除默认值。"
147
147
  },
148
148
  "name": {
149
- "description": "字段展示名称;新增字段必填,已有字段可在携带 queId 时省略;同一父级内唯一。",
149
+ "description": "字段展示名称;新增字段必填,已有字段可在携带 queId 时省略;同父级允许同名(后端以 queId 为字段身份),配置引用建议携带 queId。",
150
150
  "minLength": 1,
151
151
  "type": "string"
152
152
  },
@@ -167,13 +167,9 @@
167
167
  "type": "string"
168
168
  },
169
169
  "width": {
170
- "description": "字段在所在行的宽度百分比;只能选择 25、50、75 或 100。",
171
- "enum": [
172
- 25,
173
- 50,
174
- 75,
175
- 100
176
- ],
170
+ "description": "字段在所在行的宽度百分比(1-100 整数);后端不校验总和与取值,存量数据存在 33/34 等三等分布值。",
171
+ "maximum": 100,
172
+ "minimum": 1,
177
173
  "type": "integer"
178
174
  }
179
175
  },
@@ -111,7 +111,7 @@
111
111
  ]
112
112
  },
113
113
  "fileSize": {
114
- "minimum": 1,
114
+ "minimum": 0,
115
115
  "type": [
116
116
  "integer",
117
117
  "null"
@@ -131,7 +131,7 @@
131
131
  ]
132
132
  },
133
133
  "maxFileLimit": {
134
- "minimum": 1,
134
+ "minimum": 0,
135
135
  "type": [
136
136
  "integer",
137
137
  "null"
@@ -229,7 +229,7 @@
229
229
  },
230
230
  "DataRelationCondition": {
231
231
  "additionalProperties": false,
232
- "description": "一条数据关联过滤条件;sourceField 必须属于数据来源,operator 必须适用于该字段类型。固定值请使用 literal operand,不要直接声明后端 matchRules。",
232
+ "description": "一条数据关联过滤条件;sourceField 必须属于数据来源,operator 必须适用于该字段类型。固定值请使用 literal operand,不要直接声明后端 matchRules。sourceField 省略为存量读回形态(历史脏公式的源字段缺失,如 #queId_0$,写回时以 queId=0 透传),新建条件应提供 sourceField。",
233
233
  "properties": {
234
234
  "operand": {
235
235
  "$ref": "#/$defs/DataRelationOperand",
@@ -265,11 +265,10 @@
265
265
  },
266
266
  "sourceField": {
267
267
  "$ref": "#/$defs/FieldSelector",
268
- "description": "被过滤的数据源字段。"
268
+ "description": "被过滤的数据源字段;存量读回形态可能缺失(后端反解析出的条件源字段 queId=0 且无名称)。"
269
269
  }
270
270
  },
271
271
  "required": [
272
- "sourceField",
273
272
  "operator",
274
273
  "operand"
275
274
  ],
@@ -277,7 +276,7 @@
277
276
  },
278
277
  "DataRelationConfig": {
279
278
  "additionalProperties": false,
280
- "description": "数据关联字段配置;从应用、Q-Linker 或代码块输出中读取数据。",
279
+ "description": "数据关联字段配置;从应用、Q-Linker 或代码块输出中读取数据。source 省略表示该字段当前无关联来源配置(存量表单读回形态:后端 GET 对 displayed 目标缺失的 relation 行不回传,FormSvcImpl#getQuestionRelationsBeans continue 分支;新建数据关联字段应提供 source)。",
281
280
  "properties": {
282
281
  "aggregation": {
283
282
  "description": "可选聚合方式;null 表示不聚合。",
@@ -312,12 +311,10 @@
312
311
  },
313
312
  "source": {
314
313
  "$ref": "#/$defs/DataRelationSource",
315
- "description": "数据来源;按 kind 选择一种来源结构。"
314
+ "description": "数据来源;按 kind 选择一种来源结构。存量读回形态可能无 source(后端读面不回传关联配置),此时写回不重建该字段的关联。"
316
315
  }
317
316
  },
318
- "required": [
319
- "source"
320
- ],
317
+ "required": [],
321
318
  "type": "object"
322
319
  },
323
320
  "DataRelationCustomButton": {
@@ -989,7 +986,7 @@
989
986
  "description": "普通字段的默认值;后端 queDefaultValue 为字符串,因此数字等字面量也必须以字符串传入。defaultType 为 1 时表示静态文本,为 3 时表示公式文本,为 2 时不携带字面量默认值。表格、地址、附件、引用等结构化默认值必须放在具体字段 config.defaultValues。显式 null 表示清除默认值。"
990
987
  },
991
988
  "name": {
992
- "description": "字段展示名称;新增字段必填,已有字段可在携带 queId 时省略;同一父级内唯一。",
989
+ "description": "字段展示名称;新增字段必填,已有字段可在携带 queId 时省略;同父级允许同名(后端以 queId 为字段身份),配置引用建议携带 queId。",
993
990
  "minLength": 1,
994
991
  "type": "string"
995
992
  },
@@ -1010,13 +1007,9 @@
1010
1007
  "type": "string"
1011
1008
  },
1012
1009
  "width": {
1013
- "description": "字段在所在行的宽度百分比;只能选择 25、50、75 或 100。",
1014
- "enum": [
1015
- 25,
1016
- 50,
1017
- 75,
1018
- 100
1019
- ],
1010
+ "description": "字段在所在行的宽度百分比(1-100 整数);后端不校验总和与取值,存量数据存在 33/34 等三等分布值。",
1011
+ "maximum": 100,
1012
+ "minimum": 1,
1020
1013
  "type": "integer"
1021
1014
  }
1022
1015
  },
@@ -1036,10 +1029,10 @@
1036
1029
  ]
1037
1030
  }
1038
1031
  ],
1039
- "description": "字段选择器;用于定位应用的数据标题、数据封面、自定义编号取值来源或其他配置引用的字段。至少提供 queId 或 name,两者同时提供时必须指向同一字段。",
1032
+ "description": "字段选择器;用于定位应用的数据标题、数据封面、自定义编号取值来源或其他配置引用的字段。至少提供 queId 或 name,两者同时提供时必须指向同一字段。后端允许同父级同名字段,queId 是稳定身份;name 仅在唯一时可解析,命中多个同名时报 AMBIGUOUS_FIELD_SELECTOR,此时必须改用 queId。",
1040
1033
  "properties": {
1041
1034
  "name": {
1042
- "description": "字段名称;仅在当前作用域内唯一时可用于解析。",
1035
+ "description": "字段名称;仅在当前作用域内唯一时可用于解析,同名命中多个字段时报 AMBIGUOUS_FIELD_SELECTOR,应改用 queId。",
1043
1036
  "minLength": 1,
1044
1037
  "type": "string"
1045
1038
  },
@@ -1401,7 +1394,7 @@
1401
1394
  },
1402
1395
  "RelationConfig": {
1403
1396
  "additionalProperties": false,
1404
- "description": "引用字段配置;引用其他应用中的数据。",
1397
+ "description": "引用字段配置;引用其他应用中的数据。展示字段与权限以 displayFields 为准(后端 referQuestions 全量有序回写,queAuth 1=可编辑/2=隐藏/3=仅可见);displayField/visibleFields 为已废弃旧形态,apply 兼容接收一个版本窗口(displayField 同时视为双向绑定目标)。",
1405
1398
  "properties": {
1406
1399
  "beingDefaultFormulaAutoFillEnabled": {
1407
1400
  "description": "是否启用引用字段的默认值公式自动填充。",
@@ -1439,7 +1432,32 @@
1439
1432
  },
1440
1433
  "displayField": {
1441
1434
  "$ref": "#/$defs/FieldSelector",
1442
- "description": "引用值的主展示字段。"
1435
+ "description": "已废弃:主展示字段;apply 兼容翻译为 twoWayBoundField + displayFields 首项,后续版本移除。"
1436
+ },
1437
+ "displayFields": {
1438
+ "description": "有序展示字段全量列表(含隐藏字段),按 ordinal 保序回写为后端 referQuestions。可为空列表:空 = 双向绑定未配展示字段的合法存量形态(后端写链路对空 referQuestions 跳过插入、读面容忍空),round-trip 空↔空稳定;与已废弃 displayField/visibleFields 不可混用,条目 queId 不可重复。",
1439
+ "items": {
1440
+ "additionalProperties": false,
1441
+ "properties": {
1442
+ "auth": {
1443
+ "default": "visible",
1444
+ "description": "展示字段权限;editable=可编辑(1), hidden=隐藏(2), visible=仅可见(3);缺失按 visible。",
1445
+ "enum": [
1446
+ "editable",
1447
+ "hidden",
1448
+ "visible"
1449
+ ]
1450
+ },
1451
+ "field": {
1452
+ "$ref": "#/$defs/FieldSelector"
1453
+ }
1454
+ },
1455
+ "required": [
1456
+ "field"
1457
+ ],
1458
+ "type": "object"
1459
+ },
1460
+ "type": "array"
1443
1461
  },
1444
1462
  "relationMode": {
1445
1463
  "default": "single",
@@ -1454,8 +1472,19 @@
1454
1472
  "minLength": 1,
1455
1473
  "type": "string"
1456
1474
  },
1475
+ "twoWayBoundField": {
1476
+ "description": "双向引用绑定的目标字段(后端 referQueId);null/省略 = 单向引用。get 读面在 referQueId 非空时必产出。",
1477
+ "oneOf": [
1478
+ {
1479
+ "type": "null"
1480
+ },
1481
+ {
1482
+ "$ref": "#/$defs/FieldSelector"
1483
+ }
1484
+ ]
1485
+ },
1457
1486
  "visibleFields": {
1458
- "description": "引用选择界面额外展示的字段。",
1487
+ "description": "已废弃:额外展示字段;apply 兼容翻译为 displayFields 后续项,后续版本移除。",
1459
1488
  "items": {
1460
1489
  "$ref": "#/$defs/FieldSelector"
1461
1490
  },
@@ -1464,8 +1493,7 @@
1464
1493
  }
1465
1494
  },
1466
1495
  "required": [
1467
- "targetAppKey",
1468
- "displayField"
1496
+ "targetAppKey"
1469
1497
  ],
1470
1498
  "type": "object"
1471
1499
  },
@@ -1584,7 +1612,10 @@
1584
1612
  "$ref": "#/$defs/NumberConfig"
1585
1613
  },
1586
1614
  "questionType": {
1587
- "const": "number"
1615
+ "enum": [
1616
+ "number",
1617
+ "amount"
1618
+ ]
1588
1619
  }
1589
1620
  },
1590
1621
  "required": [
@@ -1597,7 +1628,10 @@
1597
1628
  "$ref": "#/$defs/EmptyConfig"
1598
1629
  },
1599
1630
  "questionType": {
1600
- "const": "date"
1631
+ "enum": [
1632
+ "date",
1633
+ "datetime"
1634
+ ]
1601
1635
  }
1602
1636
  },
1603
1637
  "required": [
@@ -78,7 +78,7 @@
78
78
  "description": "普通字段的默认值;后端 queDefaultValue 为字符串,因此数字等字面量也必须以字符串传入。defaultType 为 1 时表示静态文本,为 3 时表示公式文本,为 2 时不携带字面量默认值。表格、地址、附件、引用等结构化默认值必须放在具体字段 config.defaultValues。显式 null 表示清除默认值。"
79
79
  },
80
80
  "name": {
81
- "description": "字段展示名称;新增字段必填,已有字段可在携带 queId 时省略;同一父级内唯一。",
81
+ "description": "字段展示名称;新增字段必填,已有字段可在携带 queId 时省略;同父级允许同名(后端以 queId 为字段身份),配置引用建议携带 queId。",
82
82
  "minLength": 1,
83
83
  "type": "string"
84
84
  },
@@ -99,13 +99,9 @@
99
99
  "type": "string"
100
100
  },
101
101
  "width": {
102
- "description": "字段在所在行的宽度百分比;只能选择 25、50、75 或 100。",
103
- "enum": [
104
- 25,
105
- 50,
106
- 75,
107
- 100
108
- ],
102
+ "description": "字段在所在行的宽度百分比(1-100 整数);后端不校验总和与取值,存量数据存在 33/34 等三等分布值。",
103
+ "maximum": 100,
104
+ "minimum": 1,
109
105
  "type": "integer"
110
106
  }
111
107
  },
@@ -236,6 +236,28 @@
236
236
  "DATEDELTA(date, number, unit)"
237
237
  ]
238
238
  },
239
+ "DATEDIF": {
240
+ "category": "date",
241
+ "example": "DATEDIF(#queId_102$, #queId_101$)",
242
+ "meaning": "历史日期差函数名,仅存在于存量公式中(当前公式引擎未注册,日期差请使用 DAYS(end, start))。为使存量声明的 validate/round-trip 通过而保留声明,不建议新公式使用。",
243
+ "parameters": [
244
+ {
245
+ "description": "结束日期或列表",
246
+ "name": "end"
247
+ },
248
+ {
249
+ "description": "开始日期或列表",
250
+ "name": "start"
251
+ }
252
+ ],
253
+ "returns": {
254
+ "description": "天数差文本列表",
255
+ "type": "list"
256
+ },
257
+ "signatures": [
258
+ "DATEDIF(end, start)"
259
+ ]
260
+ },
239
261
  "DATETOTIMESTAMP": {
240
262
  "category": "date",
241
263
  "example": "DATETOTIMESTAMP(#queId_101$)",
@@ -363,6 +385,19 @@
363
385
  "GETUSEREMAIL()"
364
386
  ]
365
387
  },
388
+ "GETUSERENAME": {
389
+ "category": "context",
390
+ "example": "GETUSERENAME()",
391
+ "meaning": "历史拼写(GETUSERNAME 的讹写),仅存在于存量公式中(当前公式引擎未注册,请使用 GETUSERNAME())。为使存量声明的 validate/round-trip 通过而保留声明,不建议新公式使用。",
392
+ "parameters": [],
393
+ "returns": {
394
+ "description": "当前用户显示名称;无法取得时为空字符串",
395
+ "type": "string"
396
+ },
397
+ "signatures": [
398
+ "GETUSERENAME()"
399
+ ]
400
+ },
366
401
  "GETUSERNAME": {
367
402
  "category": "context",
368
403
  "example": "GETUSERNAME()",
@@ -1590,5 +1625,13 @@
1590
1625
  "需要拼接字段当前值时,将该字段的实际 queId 写成未加引号的 #queId_<字段ID>$;字段 name、字段标题和字段默认值都不能替代字段引用。",
1591
1626
  "新建应用的同一次 create 声明中尚未获得 queId 时,不得虚构 queId 或以字段 name 代替:先创建字段,app_form_get 回读实际 queId 后,再提交公式默认值更新。"
1592
1627
  ]
1628
+ },
1629
+ "x-qingflow-validation": {
1630
+ "functionCallPolicy": "validate 会识别公式文本中引号外的 函数名( 调用;函数名必须在 x-qingflow-functions 中声明。未知函数会被拒绝,字符串字面量中的 NAME() 不视为函数调用。",
1631
+ "scope": [
1632
+ "defaultType=3 的 defaultValue",
1633
+ "config.defaultValueFormula",
1634
+ "data_relation config.filters.mode=advanced 的 config.filters.formula"
1635
+ ]
1593
1636
  }
1594
1637
  }
@@ -136,10 +136,10 @@
136
136
  ]
137
137
  }
138
138
  ],
139
- "description": "字段选择器;用于定位应用的数据标题、数据封面、自定义编号取值来源或其他配置引用的字段。至少提供 queId 或 name,两者同时提供时必须指向同一字段。",
139
+ "description": "字段选择器;用于定位应用的数据标题、数据封面、自定义编号取值来源或其他配置引用的字段。至少提供 queId 或 name,两者同时提供时必须指向同一字段。后端允许同父级同名字段,queId 是稳定身份;name 仅在唯一时可解析,命中多个同名时报 AMBIGUOUS_FIELD_SELECTOR,此时必须改用 queId。",
140
140
  "properties": {
141
141
  "name": {
142
- "description": "字段名称;仅在当前作用域内唯一时可用于解析。",
142
+ "description": "字段名称;仅在当前作用域内唯一时可用于解析,同名命中多个字段时报 AMBIGUOUS_FIELD_SELECTOR,应改用 queId。",
143
143
  "minLength": 1,
144
144
  "type": "string"
145
145
  },
@@ -258,13 +258,9 @@
258
258
  "type": "array"
259
259
  },
260
260
  "width": {
261
- "description": "字段在所在行的宽度百分比;只能选择 25、50、75 或 100。",
262
- "enum": [
263
- 25,
264
- 50,
265
- 75,
266
- 100
267
- ],
261
+ "description": "字段在所在行的宽度百分比(1-100 整数);后端不校验总和与取值,存量数据存在 33/34 等三等分布值。",
262
+ "maximum": 100,
263
+ "minimum": 1,
268
264
  "type": "integer"
269
265
  }
270
266
  },
@@ -334,11 +330,10 @@
334
330
  "description": "段落判别值。"
335
331
  },
336
332
  "rows": {
337
- "description": "段落内的非空有序字段行。",
333
+ "description": "段落内的有序字段行;可为空数组(空 = 存量空段落形态,后端容忍,round-trip 空↔空稳定)。",
338
334
  "items": {
339
335
  "$ref": "#/$defs/FieldRow"
340
336
  },
341
- "minItems": 1,
342
337
  "type": "array"
343
338
  },
344
339
  "sectionId": {
@@ -383,7 +378,6 @@
383
378
  ],
384
379
  "type": "object"
385
380
  },
386
- "minItems": 1,
387
381
  "type": "array"
388
382
  },
389
383
  "sectionId": {
@@ -695,6 +689,7 @@
695
689
  "x-qingflow-supported-field-types": [
696
690
  "text",
697
691
  "long_text",
692
+ "rich_text",
698
693
  "number",
699
694
  "amount",
700
695
  "link",
@@ -0,0 +1,42 @@
1
+ {
2
+ "manifestDescription": "面向 app_views_apply 的版本化公开视图契约。summary 提供最小声明,complete 覆盖当前可写能力,details 提供按配置域读取的自包含专项 Schema。后端已知但尚不可写的能力以说明性元数据列出,不会被误报为公开能力。",
3
+ "latestVersion": "v1alpha1",
4
+ "versions": {
5
+ "v1alpha1": {
6
+ "versionDescription": "AI 和 CLI/MCP 使用的 canonical views DSL。字段名、更新语义和约束与 app_views_apply 对齐;schema 返回会内联专项 Schema 的依赖定义。",
7
+ "apiVersion": "builder.qingflow.com/v1alpha1",
8
+ "applyDto": "v1alpha1",
9
+ "contractSource": "app_views_apply",
10
+ "contractVersion": "v1alpha1",
11
+ "enabledByDefault": true,
12
+ "schemaKinds": [
13
+ "summary",
14
+ "complete",
15
+ "display",
16
+ "data-permission",
17
+ "operation-permission",
18
+ "query-condition",
19
+ "button-config"
20
+ ],
21
+ "schemaFiles": {
22
+ "summary": "v1alpha1/summary.json",
23
+ "complete": "v1alpha1/complete.json",
24
+ "display": "v1alpha1/details/display.json",
25
+ "data-permission": "v1alpha1/details/data-permission.json",
26
+ "operation-permission": "v1alpha1/details/operation-permission.json",
27
+ "query-condition": "v1alpha1/details/query-condition.json",
28
+ "button-config": "v1alpha1/details/button-config.json"
29
+ },
30
+ "viewTypes": [
31
+ "table",
32
+ "card",
33
+ "board",
34
+ "gantt",
35
+ "hierarchy",
36
+ "calendar"
37
+ ],
38
+ "backendKnownUnsupportedViewTypes": [],
39
+ "status": "active"
40
+ }
41
+ }
42
+ }