dwf-platform-cli 0.2.0__py3-none-any.whl

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 (47) hide show
  1. dwf_cli/__init__.py +3 -0
  2. dwf_cli/__main__.py +4 -0
  3. dwf_cli/api/__init__.py +3 -0
  4. dwf_cli/api/auth.py +46 -0
  5. dwf_cli/api/client.py +113 -0
  6. dwf_cli/api/datamodel.py +458 -0
  7. dwf_cli/api/formmodel.py +197 -0
  8. dwf_cli/api/funcmodel.py +436 -0
  9. dwf_cli/cli/__init__.py +69 -0
  10. dwf_cli/cli/_common.py +152 -0
  11. dwf_cli/cli/auth.py +197 -0
  12. dwf_cli/cli/config.py +200 -0
  13. dwf_cli/cli/datamodel.py +2270 -0
  14. dwf_cli/cli/formmodel.py +1007 -0
  15. dwf_cli/cli/funcmodel.py +2055 -0
  16. dwf_cli/cli/schema.py +210 -0
  17. dwf_cli/core/__init__.py +0 -0
  18. dwf_cli/core/config.py +177 -0
  19. dwf_cli/core/crypto.py +22 -0
  20. dwf_cli/core/errors.py +63 -0
  21. dwf_cli/core/output.py +6 -0
  22. dwf_cli/core/validator.py +129 -0
  23. dwf_cli/mcp/__init__.py +3 -0
  24. dwf_cli/mcp/server.py +411 -0
  25. dwf_cli/schemas/__init__.py +37 -0
  26. dwf_cli/schemas/datamodel/attribute_bind.schema.json +21 -0
  27. dwf_cli/schemas/datamodel/attribute_create.schema.json +24 -0
  28. dwf_cli/schemas/datamodel/attribute_update.schema.json +21 -0
  29. dwf_cli/schemas/datamodel/create.schema.json +27 -0
  30. dwf_cli/schemas/datamodel/excel_confirm.schema.json +65 -0
  31. dwf_cli/schemas/datamodel/external_create.schema.json +47 -0
  32. dwf_cli/schemas/datamodel/external_update.schema.json +47 -0
  33. dwf_cli/schemas/datamodel/object_create.schema.json +24 -0
  34. dwf_cli/schemas/datamodel/object_update.schema.json +17 -0
  35. dwf_cli/schemas/datamodel/relation_create.schema.json +34 -0
  36. dwf_cli/schemas/datamodel/relation_update.schema.json +34 -0
  37. dwf_cli/schemas/datamodel/update.schema.json +26 -0
  38. dwf_cli/schemas/funcmodel/app_create.schema.json +150 -0
  39. dwf_cli/schemas/funcmodel/app_update.schema.json +153 -0
  40. dwf_cli/schemas/funcmodel/language-package_create.schema.json +15 -0
  41. dwf_cli/schemas/funcmodel/operations_create.schema.json +77 -0
  42. dwf_cli/schemas/funcmodel/operations_update.schema.json +76 -0
  43. dwf_platform_cli-0.2.0.dist-info/METADATA +347 -0
  44. dwf_platform_cli-0.2.0.dist-info/RECORD +47 -0
  45. dwf_platform_cli-0.2.0.dist-info/WHEEL +4 -0
  46. dwf_platform_cli-0.2.0.dist-info/entry_points.txt +3 -0
  47. dwf_platform_cli-0.2.0.dist-info/licenses/LICENSE +190 -0
dwf_cli/mcp/server.py ADDED
@@ -0,0 +1,411 @@
1
+ """DWF MCP Server — exposes DWF platform operations as MCP tools."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ from typing import Any
7
+
8
+ from mcp.server.fastmcp import FastMCP
9
+
10
+ from dwf_cli.api.client import APIClient
11
+ from dwf_cli.core.config import Config
12
+ from dwf_cli.core.errors import DWFError
13
+
14
+ mcp = FastMCP(
15
+ "dwf",
16
+ instructions=(
17
+ "DWF platform tools for managing data models, objects, "
18
+ "function models, and form models. "
19
+ "Run dwf_auth_status first to check connection."
20
+ ),
21
+ )
22
+
23
+
24
+ def _get_client() -> APIClient:
25
+ """Build an APIClient from saved config."""
26
+ cfg = Config()
27
+ if not cfg.server:
28
+ raise ValueError(
29
+ "DWF server not configured. Run: dwf-cli config set server <url>"
30
+ )
31
+ if not cfg.token:
32
+ raise ValueError("Not authenticated. Run: dwf-cli auth login --username <user>")
33
+ return APIClient(cfg.server, cfg.token)
34
+
35
+
36
+ def _get_app_client() -> APIClient | None:
37
+ """Build an app-server APIClient if configured differently."""
38
+ cfg = Config()
39
+ app_url = cfg.app_server
40
+ if app_url and app_url != cfg.server and cfg.token:
41
+ return APIClient(app_url, cfg.token)
42
+ return None
43
+
44
+
45
+ def _fmt(result: Any) -> str:
46
+ """Format API result as JSON string."""
47
+ if result is None:
48
+ return json.dumps({"success": True})
49
+ if isinstance(result, (dict, list)):
50
+ return json.dumps(result, ensure_ascii=False, default=str)
51
+ return str(result)
52
+
53
+
54
+ def _safe_call(fn, *args, **kwargs) -> str:
55
+ """Call an API function and return formatted result or error."""
56
+ try:
57
+ result = fn(*args, **kwargs)
58
+ return _fmt(result)
59
+ except DWFError as e:
60
+ return json.dumps({"error": str(e), "suggestion": e.suggestion})
61
+ except ValueError as e:
62
+ return json.dumps({"error": str(e)})
63
+
64
+
65
+ # ── Auth & Config ─────────────────────────────────────────────────────
66
+
67
+
68
+ @mcp.tool()
69
+ def dwf_auth_status() -> str:
70
+ """Check current DWF authentication status and server configuration."""
71
+ try:
72
+ cfg = Config()
73
+ except DWFError as e:
74
+ return json.dumps({"error": str(e)})
75
+ return json.dumps(
76
+ {
77
+ "server": cfg.server,
78
+ "app_server": cfg.app_server,
79
+ "authenticated": cfg.token is not None,
80
+ }
81
+ )
82
+
83
+
84
+ @mcp.tool()
85
+ def dwf_config_list() -> str:
86
+ """List all DWF CLI configuration values."""
87
+ try:
88
+ cfg = Config()
89
+ return json.dumps(cfg.list_all(), ensure_ascii=False)
90
+ except DWFError as e:
91
+ return json.dumps({"error": str(e)})
92
+
93
+
94
+ # ── Data Model ────────────────────────────────────────────────────────
95
+
96
+
97
+ @mcp.tool()
98
+ def dwf_datamodel_list(
99
+ model_type: str = "entity",
100
+ page: int = 0,
101
+ page_size: int = 25,
102
+ search: str | None = None,
103
+ ) -> str:
104
+ """List data models (entity/relation/external).
105
+
106
+ Args:
107
+ model_type: One of 'entity', 'relation', 'external'
108
+ page: Page index (0-based)
109
+ page_size: Items per page
110
+ search: Fuzzy search keyword
111
+ """
112
+ from dwf_cli.api.datamodel import ModelType, list_models
113
+
114
+ client = _get_client()
115
+ mt = ModelType(model_type)
116
+ return _safe_call(
117
+ list_models, client, mt, page=page, page_size=page_size, search=search
118
+ )
119
+
120
+
121
+ @mcp.tool()
122
+ def dwf_datamodel_show(class_name: str) -> str:
123
+ """Show details of a data model including its attributes.
124
+
125
+ Args:
126
+ class_name: The class name of the data model
127
+ """
128
+ from dwf_cli.api.datamodel import get_attributes, get_class
129
+
130
+ client = _get_client()
131
+ try:
132
+ cls_info = get_class(client, class_name)
133
+ attrs = get_attributes(client, class_name)
134
+ return json.dumps(
135
+ {"class": cls_info, "attributes": attrs}, ensure_ascii=False, default=str
136
+ )
137
+ except DWFError as e:
138
+ return json.dumps({"error": str(e), "suggestion": e.suggestion})
139
+
140
+
141
+ @mcp.tool()
142
+ def dwf_datamodel_create(
143
+ class_name: str,
144
+ display_name: str = "",
145
+ zone_name: str = "",
146
+ ) -> str:
147
+ """Create a new entity data model.
148
+
149
+ Args:
150
+ class_name: Unique class name (English, no spaces)
151
+ display_name: Human-readable display name
152
+ zone_name: Zone/category name
153
+ """
154
+ from dwf_cli.api.datamodel import create_entity
155
+
156
+ client = _get_client()
157
+ data = [{"className": class_name, "displayName": display_name or class_name}]
158
+ if zone_name:
159
+ data[0]["zoneName"] = zone_name
160
+ return _safe_call(create_entity, client, data)
161
+
162
+
163
+ @mcp.tool()
164
+ def dwf_datamodel_delete(class_name: str, cascade: bool = False) -> str:
165
+ """Delete a data model.
166
+
167
+ Args:
168
+ class_name: The class name to delete
169
+ cascade: Whether to cascade delete related data
170
+ """
171
+ from dwf_cli.api.datamodel import delete_class
172
+
173
+ client = _get_client()
174
+ return _safe_call(delete_class, client, class_name, cascade=cascade)
175
+
176
+
177
+ # ── Attributes ────────────────────────────────────────────────────────
178
+
179
+
180
+ @mcp.tool()
181
+ def dwf_attribute_list(keyword: str | None = None) -> str:
182
+ """List global attributes, optionally filtered by keyword.
183
+
184
+ Args:
185
+ keyword: Filter keyword
186
+ """
187
+ from dwf_cli.api.datamodel import list_attributes
188
+
189
+ client = _get_client()
190
+ return _safe_call(list_attributes, client, keyword=keyword)
191
+
192
+
193
+ @mcp.tool()
194
+ def dwf_attribute_create(
195
+ name: str,
196
+ display_name: str = "",
197
+ value_type: str = "String",
198
+ ) -> str:
199
+ """Create a new attribute.
200
+
201
+ Args:
202
+ name: Attribute name (English)
203
+ display_name: Human-readable name
204
+ value_type: Data type (String, Integer, Float, Boolean, DateTime, etc.)
205
+ """
206
+ from dwf_cli.api.datamodel import create_attributes
207
+
208
+ client = _get_client()
209
+ data = [
210
+ {"name": name, "displayName": display_name or name, "valueType": value_type}
211
+ ]
212
+ return _safe_call(create_attributes, client, data)
213
+
214
+
215
+ @mcp.tool()
216
+ def dwf_attribute_bind(
217
+ class_name: str,
218
+ attribute_name: str,
219
+ is_relation: bool = False,
220
+ ) -> str:
221
+ """Bind an existing attribute to a data model.
222
+
223
+ Args:
224
+ class_name: Target class name
225
+ attribute_name: Attribute name to bind
226
+ is_relation: Whether the target is a relation model
227
+ """
228
+ from dwf_cli.api.datamodel import bind_attributes
229
+
230
+ client = _get_client()
231
+ data = [{"name": attribute_name}]
232
+ return _safe_call(
233
+ bind_attributes, client, class_name, data, is_relation=is_relation
234
+ )
235
+
236
+
237
+ # ── Objects ───────────────────────────────────────────────────────────
238
+
239
+
240
+ @mcp.tool()
241
+ def dwf_object_list(
242
+ class_name: str,
243
+ page: int = 0,
244
+ page_size: int = 25,
245
+ condition: str | None = None,
246
+ ) -> str:
247
+ """List objects of a data model.
248
+
249
+ Args:
250
+ class_name: The class name
251
+ page: Page index (0-based)
252
+ page_size: Items per page
253
+ condition: DWF query condition string
254
+ """
255
+ from dwf_cli.api.datamodel import list_objects
256
+
257
+ client = _get_client()
258
+ return _safe_call(
259
+ list_objects,
260
+ client,
261
+ class_name,
262
+ page=page,
263
+ page_size=page_size,
264
+ condition=condition,
265
+ )
266
+
267
+
268
+ @mcp.tool()
269
+ def dwf_object_get(class_name: str, oid: str) -> str:
270
+ """Get a single object by OID.
271
+
272
+ Args:
273
+ class_name: The class name
274
+ oid: Object ID
275
+ """
276
+ from dwf_cli.api.datamodel import get_object
277
+
278
+ client = _get_client()
279
+ return _safe_call(get_object, client, class_name, oid)
280
+
281
+
282
+ @mcp.tool()
283
+ def dwf_object_create(class_name: str, data_json: str) -> str:
284
+ """Create one or more objects.
285
+
286
+ Args:
287
+ class_name: The class name
288
+ data_json: JSON string of object(s) to create. Single dict or list of dicts.
289
+ """
290
+ from dwf_cli.api.datamodel import create_objects
291
+
292
+ client = _get_client()
293
+ parsed = json.loads(data_json)
294
+ if isinstance(parsed, dict):
295
+ parsed = [parsed]
296
+ return _safe_call(create_objects, client, class_name, parsed)
297
+
298
+
299
+ @mcp.tool()
300
+ def dwf_object_update(class_name: str, data_json: str) -> str:
301
+ """Update one or more objects.
302
+
303
+ Args:
304
+ class_name: The class name
305
+ data_json: JSON string of object(s) with oid field. Single dict or list of dicts.
306
+ """
307
+ from dwf_cli.api.datamodel import update_objects
308
+
309
+ client = _get_client()
310
+ parsed = json.loads(data_json)
311
+ if isinstance(parsed, dict):
312
+ parsed = [parsed]
313
+ return _safe_call(update_objects, client, class_name, parsed)
314
+
315
+
316
+ @mcp.tool()
317
+ def dwf_object_delete(class_name: str, oids_json: str) -> str:
318
+ """Delete objects by OID list.
319
+
320
+ Args:
321
+ class_name: The class name
322
+ oids_json: JSON array of OID strings, e.g. '["oid1","oid2"]'
323
+ """
324
+ from dwf_cli.api.datamodel import delete_objects
325
+
326
+ client = _get_client()
327
+ oids = json.loads(oids_json)
328
+ return _safe_call(delete_objects, client, class_name, oids)
329
+
330
+
331
+ @mcp.tool()
332
+ def dwf_object_count(class_name: str, condition: str | None = None) -> str:
333
+ """Count objects in a data model.
334
+
335
+ Args:
336
+ class_name: The class name
337
+ condition: Optional DWF query condition
338
+ """
339
+ from dwf_cli.api.datamodel import count_objects
340
+
341
+ client = _get_client()
342
+ return _safe_call(count_objects, client, class_name, condition=condition)
343
+
344
+
345
+ # ── Function Model ────────────────────────────────────────────────────
346
+
347
+
348
+ @mcp.tool()
349
+ def dwf_funcmodel_app_list() -> str:
350
+ """List all applications in the function model."""
351
+ from dwf_cli.api.funcmodel import list_apps
352
+
353
+ client = _get_client()
354
+ app_client = _get_app_client()
355
+ return _safe_call(list_apps, app_client or client)
356
+
357
+
358
+ @mcp.tool()
359
+ def dwf_funcmodel_operation_list(
360
+ operation_type: str = "global",
361
+ page: int = 0,
362
+ page_size: int = 25,
363
+ search: str | None = None,
364
+ ) -> str:
365
+ """List function operations.
366
+
367
+ Args:
368
+ operation_type: One of 'global', 'entity', 'relation'
369
+ page: Page index (0-based)
370
+ page_size: Items per page
371
+ search: Fuzzy search keyword
372
+ """
373
+ from dwf_cli.api.funcmodel import list_operations
374
+
375
+ client = _get_client()
376
+ return _safe_call(
377
+ list_operations,
378
+ client,
379
+ operation_type,
380
+ page=page,
381
+ page_size=page_size,
382
+ fuzzy_search=search,
383
+ )
384
+
385
+
386
+ # ── Form Model ────────────────────────────────────────────────────────
387
+
388
+
389
+ @mcp.tool()
390
+ def dwf_formmodel_view_list(class_name: str) -> str:
391
+ """List form views for a data model.
392
+
393
+ Args:
394
+ class_name: The class name
395
+ """
396
+ from dwf_cli.api.formmodel import list_views
397
+
398
+ client = _get_client()
399
+ return _safe_call(list_views, client, class_name)
400
+
401
+
402
+ # ── Entry point ───────────────────────────────────────────────────────
403
+
404
+
405
+ def main() -> None:
406
+ """Run the MCP server (stdio transport)."""
407
+ mcp.run()
408
+
409
+
410
+ if __name__ == "__main__":
411
+ main()
@@ -0,0 +1,37 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ from pathlib import Path
5
+
6
+ _SCHEMAS_DIR = Path(__file__).parent
7
+ _REGISTRY: dict[str, dict] = {}
8
+
9
+
10
+ def _load_all() -> None:
11
+ if _REGISTRY:
12
+ return
13
+ for group_dir in sorted(_SCHEMAS_DIR.iterdir()):
14
+ if not group_dir.is_dir() or group_dir.name.startswith("_"):
15
+ continue
16
+ for schema_file in sorted(group_dir.glob("*.schema.json")):
17
+ name = schema_file.name.removesuffix(".schema.json")
18
+ cmd_parts = [group_dir.name]
19
+ cmd_parts.extend(name.split("_"))
20
+ key = " ".join(cmd_parts)
21
+ with open(schema_file, encoding="utf-8") as f:
22
+ _REGISTRY[key] = json.load(f)
23
+
24
+
25
+ def lookup(command_path: str) -> dict | None:
26
+ _load_all()
27
+ return _REGISTRY.get(command_path)
28
+
29
+
30
+ def all_schemas() -> dict[str, dict]:
31
+ _load_all()
32
+ return dict(_REGISTRY)
33
+
34
+
35
+ def all_commands() -> list[str]:
36
+ _load_all()
37
+ return sorted(_REGISTRY.keys())
@@ -0,0 +1,21 @@
1
+ {
2
+ "description": "批量绑定属性库的属性到类(实体类/关联类)。只允许修改 displayName、defaultValue、note",
3
+ "api": "POST /dwf/v1/meta/entities/{name}/attributes-bind 或 /dwf/v1/meta/relations/{name}/attributes-bind",
4
+ "type": "array",
5
+ "fields": [
6
+ {"name": "id", "type": "string", "required": false, "description": "属性ID"},
7
+ {"name": "attributeName", "type": "string", "required": true, "description": "属性英文名(指定要绑定的属性)", "example": "actorId"},
8
+ {"name": "displayName", "type": "string", "required": false, "description": "属性显示名(绑定时可修改)", "example": "任务执行人"},
9
+ {"name": "attributeCategory", "type": "string", "required": false, "description": "属性类别", "enum": ["Constant", "Variable"]},
10
+ {"name": "valueType", "type": "string", "required": false, "description": "字段取值类型", "example": "String"},
11
+ {"name": "valueLength", "type": "integer", "required": false, "description": "字段取值最大字节长度"},
12
+ {"name": "nullable", "type": "boolean", "required": false, "description": "字段是否可空"},
13
+ {"name": "defaultValue", "type": "string", "required": false, "description": "字段默认值(绑定时可修改)"},
14
+ {"name": "isPrimaryKey", "type": "boolean", "required": false, "description": "字段是否为主键"},
15
+ {"name": "isIdentity", "type": "boolean", "required": false, "description": "字段是否自增"},
16
+ {"name": "note", "type": "string", "required": false, "description": "备注(绑定时可修改)"}
17
+ ],
18
+ "examples": [
19
+ [{"attributeName": "age", "displayName": "年龄", "note": "绑定到User类"}]
20
+ ]
21
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "description": "批量创建属性。id 必须留空(后台自动生成)",
3
+ "api": "POST /dwf/v1/meta/attributes-create",
4
+ "type": "array",
5
+ "fields": [
6
+ {"name": "id", "type": "string", "required": false, "description": "属性ID(创建时留空,后台自动生成)"},
7
+ {"name": "attributeName", "type": "string", "required": true, "description": "属性英文名", "example": "actorId"},
8
+ {"name": "displayName", "type": "string", "required": false, "description": "属性显示名(一般为中文)", "example": "任务执行人"},
9
+ {"name": "attributeCategory", "type": "string", "required": false, "description": "属性类别:常量或变量", "enum": ["Constant", "Variable"], "example": "Variable"},
10
+ {"name": "valueType", "type": "string", "required": true, "description": "字段取值类型(如 String, Integer, Boolean, Long, UUID, Date, Double, Clob, TimeStamp, Time, Json, Timeseries, LocalFile)", "example": "String"},
11
+ {"name": "valueLength", "type": "integer", "required": false, "description": "字段取值最大字节长度", "example": 50},
12
+ {"name": "nullable", "type": "boolean", "required": false, "description": "字段是否可空", "example": true},
13
+ {"name": "defaultValue", "type": "string", "required": false, "description": "字段默认值", "example": "0"},
14
+ {"name": "isPrimaryKey", "type": "boolean", "required": false, "description": "字段是否为主键", "example": false},
15
+ {"name": "isIdentity", "type": "boolean", "required": false, "description": "字段是否自增", "example": false},
16
+ {"name": "note", "type": "string", "required": false, "description": "备注", "example": "备注"}
17
+ ],
18
+ "examples": [
19
+ [
20
+ {"attributeName": "age", "displayName": "年龄", "valueType": "Integer", "nullable": true},
21
+ {"attributeName": "name", "displayName": "姓名", "valueType": "String", "valueLength": 100}
22
+ ]
23
+ ]
24
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "description": "更新属性。id 和 attributeName 标识要更新的属性",
3
+ "api": "POST /dwf/v1/meta/attributes-update",
4
+ "type": "object",
5
+ "fields": [
6
+ {"name": "id", "type": "string", "required": false, "description": "属性ID(更新时用于标识属性)"},
7
+ {"name": "attributeName", "type": "string", "required": true, "description": "属性英文名", "example": "actorId"},
8
+ {"name": "displayName", "type": "string", "required": false, "description": "属性显示名(一般为中文)", "example": "任务执行人"},
9
+ {"name": "attributeCategory", "type": "string", "required": false, "description": "属性类别:常量或变量", "enum": ["Constant", "Variable"], "example": "Variable"},
10
+ {"name": "valueType", "type": "string", "required": false, "description": "字段取值类型", "example": "String"},
11
+ {"name": "valueLength", "type": "integer", "required": false, "description": "字段取值最大字节长度", "example": 50},
12
+ {"name": "nullable", "type": "boolean", "required": false, "description": "字段是否可空", "example": true},
13
+ {"name": "defaultValue", "type": "string", "required": false, "description": "字段默认值", "example": "0"},
14
+ {"name": "isPrimaryKey", "type": "boolean", "required": false, "description": "字段是否为主键", "example": false},
15
+ {"name": "isIdentity", "type": "boolean", "required": false, "description": "字段是否自增", "example": false},
16
+ {"name": "note", "type": "string", "required": false, "description": "备注"}
17
+ ],
18
+ "examples": [
19
+ {"attributeName": "age", "displayName": "年龄(更新)", "valueType": "Integer", "nullable": false}
20
+ ]
21
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "description": "批量新增类(实体类/关联类/模块类)。className 必填且唯一,id 可留空(后台自动生成),isSystem 默认 false",
3
+ "api": "POST /dwf/v1/meta/entities-create?withParentOid=false",
4
+ "type": "array",
5
+ "fields": [
6
+ {"name": "id", "type": "string", "required": false, "description": "类的ID(创建时留空,后台自动生成)"},
7
+ {"name": "className", "type": "string", "required": true, "description": "类的英文名(必填,唯一)", "example": "UserTest"},
8
+ {"name": "displayName", "type": "string", "required": false, "description": "类的显示名", "example": "测试用户类"},
9
+ {"name": "classType", "type": "string", "required": false, "description": "持久类或动态类", "enum": ["DynamicClass", "PersistentClass"], "example": "PersistentClass"},
10
+ {"name": "classCategory", "type": "string", "required": false, "description": "类类别:实体类、关联类、外部实体类、模块类、操作、根", "enum": ["OperationClass", "ItemClass", "ExternalItemClass", "RelationClass", "ModuleClass", "Root"], "example": "ItemClass"},
11
+ {"name": "parentClass", "type": "string", "required": false, "description": "父类名", "example": "ItemClass"},
12
+ {"name": "isSystem", "type": "boolean", "required": false, "description": "是否系统类(默认 false)", "example": false},
13
+ {"name": "state", "type": "integer", "required": false, "description": "状态(保留字段)"},
14
+ {"name": "packagePath", "type": "string", "required": false, "description": "扩展字段:模块类存图标名,外部实体类存属性映射信息"},
15
+ {"name": "zoneName", "type": "string", "required": false, "description": "自定义域名", "example": "CUS"},
16
+ {"name": "appId", "type": "string", "required": false, "description": "应用ID(仅模块类有意义)"},
17
+ {"name": "dataSourceOid", "type": "string", "required": false, "description": "数据源oid(仅外部实体类有意义)"},
18
+ {"name": "primaryKey", "type": "string", "required": false, "description": "自定义主键"},
19
+ {"name": "isDeletable", "type": "boolean", "required": false, "description": "是否可删改", "example": true},
20
+ {"name": "note", "type": "string", "required": false, "description": "备注", "example": "备注"},
21
+ {"name": "isExternalClassView", "type": "boolean", "required": false, "description": "是否为外部实体类创建view"}
22
+ ],
23
+ "examples": [
24
+ [{"className": "Asset", "displayName": "设备资产", "classCategory": "ItemClass", "zoneName": "CUS"}],
25
+ [{"className": "User", "displayName": "用户", "classCategory": "ItemClass", "zoneName": "CUS", "isDeletable": true, "note": "用户信息表"}]
26
+ ]
27
+ }
@@ -0,0 +1,65 @@
1
+ {
2
+ "description": "Excel 快速建表确认信息。由 excel-upload 返回的数据经校验、补全 attributeName/displayName 后提交",
3
+ "api": "POST /dwf/v1/quickStartFromExcel/confirmClassInfo",
4
+ "type": "object",
5
+ "fields": [
6
+ {"name": "uuid", "type": "string", "required": true, "description": "上传 Excel 后获得的唯一标识", "example": "E395B9103325E64AB25698B4E933CEC2"},
7
+ {"name": "useFirstRowAsClassName", "type": "boolean", "required": false, "description": "是否使用第一行作为类名", "example": true},
8
+ {"name": "useSecondRowAsDisplayName", "type": "boolean", "required": false, "description": "是否使用第二行作为显示名", "example": true},
9
+ {
10
+ "name": "allSheetInfo",
11
+ "type": "array",
12
+ "required": true,
13
+ "description": "所有 Sheet 信息列表",
14
+ "item_schema": {
15
+ "fields": [
16
+ {"name": "sheetName", "type": "string", "required": false, "description": "Sheet 名称", "example": "Asset"},
17
+ {"name": "className", "type": "string", "required": false, "description": "类英文名", "example": "Asset"},
18
+ {"name": "displayName", "type": "string", "required": false, "description": "类显示名", "example": "Asset"},
19
+ {"name": "zoneName", "type": "string", "required": false, "description": "自定义域名", "example": "CUS"},
20
+ {"name": "isTree", "type": "boolean", "required": false, "description": "是否为树形结构", "example": false},
21
+ {"name": "useThisSheet", "type": "boolean", "required": false, "description": "是否使用此 Sheet", "example": true},
22
+ {
23
+ "name": "infoFromColumnList",
24
+ "type": "array",
25
+ "required": false,
26
+ "description": "列信息列表",
27
+ "item_schema": {
28
+ "fields": [
29
+ {"name": "useThisColumn", "type": "boolean", "required": false, "description": "是否使用此列", "example": true},
30
+ {"name": "firstRowData", "type": "string", "required": false, "description": "第一行数据(原始值,作为属性英文名参考)", "example": "assetName"},
31
+ {"name": "firstRowDataPinyin", "type": "string", "required": false, "description": "第一行数据的拼音", "example": "assetName"},
32
+ {"name": "secondRowData", "type": "string", "required": false, "description": "第二行数据(中文显示名参考)", "example": "设备名称"},
33
+ {"name": "dataType", "type": "string", "required": false, "description": "数据类型", "example": "String"},
34
+ {"name": "index", "type": "integer", "required": false, "description": "列索引(从0开始)", "example": 1},
35
+ {"name": "attributeName", "type": "string", "required": false, "description": "属性英文名(确认时补全,通常取 firstRowData)", "example": "assetName"},
36
+ {"name": "displayName", "type": "string", "required": false, "description": "属性显示名(确认时补全,通常取 secondRowData)", "example": "设备名称"}
37
+ ]
38
+ }
39
+ }
40
+ ]
41
+ }
42
+ }
43
+ ],
44
+ "examples": [
45
+ {
46
+ "uuid": "E395B9103325E64AB25698B4E933CEC2",
47
+ "useFirstRowAsClassName": true,
48
+ "useSecondRowAsDisplayName": true,
49
+ "allSheetInfo": [
50
+ {
51
+ "sheetName": "Asset",
52
+ "className": "Asset",
53
+ "displayName": "Asset",
54
+ "zoneName": "CUS",
55
+ "isTree": false,
56
+ "useThisSheet": true,
57
+ "infoFromColumnList": [
58
+ {"useThisColumn": true, "firstRowData": "id", "secondRowData": "代号", "dataType": "String", "index": 0, "attributeName": "id", "displayName": "代号"},
59
+ {"useThisColumn": true, "firstRowData": "assetName", "secondRowData": "设备名称", "dataType": "String", "index": 1, "attributeName": "assetName", "displayName": "设备名称"}
60
+ ]
61
+ }
62
+ ]
63
+ }
64
+ ]
65
+ }
@@ -0,0 +1,47 @@
1
+ {
2
+ "description": "批量新增外部实体类",
3
+ "api": "POST /dwf/v1/meta/external-entities-create",
4
+ "type": "object",
5
+ "fields": [
6
+ {
7
+ "name": "classList",
8
+ "type": "array",
9
+ "required": true,
10
+ "description": "模型类元信息列表(MetaClassDO),classCategory 应为 ExternalItemClass",
11
+ "item_schema": {
12
+ "fields": [
13
+ {"name": "id", "type": "string", "required": false, "description": "类的ID(创建时留空)"},
14
+ {"name": "className", "type": "string", "required": true, "description": "类的英文名(必填,唯一)", "example": "ExtUser"},
15
+ {"name": "displayName", "type": "string", "required": false, "description": "类的显示名", "example": "外部用户"},
16
+ {"name": "classType", "type": "string", "required": false, "description": "持久类或动态类", "enum": ["DynamicClass", "PersistentClass"]},
17
+ {"name": "classCategory", "type": "string", "required": false, "description": "类类别(外部实体类应为 ExternalItemClass)", "enum": ["OperationClass", "ItemClass", "ExternalItemClass", "RelationClass", "ModuleClass", "Root"]},
18
+ {"name": "parentClass", "type": "string", "required": false, "description": "父类名"},
19
+ {"name": "isSystem", "type": "boolean", "required": false, "description": "是否系统类"},
20
+ {"name": "state", "type": "integer", "required": false, "description": "状态(保留字段)"},
21
+ {"name": "packagePath", "type": "string", "required": false, "description": "扩展字段:外部实体类存属性映射信息"},
22
+ {"name": "zoneName", "type": "string", "required": false, "description": "自定义域名", "example": "CUS"},
23
+ {"name": "appId", "type": "string", "required": false, "description": "应用ID"},
24
+ {"name": "dataSourceOid", "type": "string", "required": false, "description": "数据源oid"},
25
+ {"name": "primaryKey", "type": "string", "required": false, "description": "自定义主键"},
26
+ {"name": "isDeletable", "type": "boolean", "required": false, "description": "是否可删改"},
27
+ {"name": "note", "type": "string", "required": false, "description": "备注"},
28
+ {"name": "isExternalClassView", "type": "boolean", "required": false, "description": "是否为外部实体类创建view"}
29
+ ]
30
+ }
31
+ },
32
+ {
33
+ "name": "customSqlMap",
34
+ "type": "object",
35
+ "required": false,
36
+ "description": "外部实体类与其视图自定义SQL对应关系(key=className, value=SQL)"
37
+ }
38
+ ],
39
+ "examples": [
40
+ {
41
+ "classList": [
42
+ {"className": "ExtUser", "displayName": "外部用户", "classCategory": "ExternalItemClass", "zoneName": "CUS"}
43
+ ],
44
+ "customSqlMap": {"ExtUser": "SELECT * FROM ext_users"}
45
+ }
46
+ ]
47
+ }