neo-cmp-cli 1.13.13 → 1.13.16

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 (67) hide show
  1. package/README.md +1 -1
  2. package/dist/neo/neoEnvManager.js +1 -1
  3. package/dist/neo/neoLogin.js +1 -1
  4. package/dist/neo/neoRequire.js +1 -1
  5. package/dist/package.json.js +1 -1
  6. package/docs//351/200/232/347/224/250/344/273/243/347/220/206/346/216/245/345/217/243/forward.zip +0 -0
  7. package/docs//351/200/232/347/224/250/344/273/243/347/220/206/346/216/245/345/217/243//350/207/252/345/256/232/344/271/211API:/351/200/232/347/224/250/344/273/243/347/220/206/346/216/245/345/217/243/344/275/277/347/224/250/350/257/264/346/230/216.md +13 -0
  8. package/package.json +1 -1
  9. package/template/antd-custom-cmp-template/package.json +1 -1
  10. package/template/asset-manage-template/package.json +1 -1
  11. package/template/echarts-custom-cmp-template/package.json +1 -1
  12. package/template/empty-custom-cmp-template/package.json +1 -1
  13. package/template/map-custom-cmp-template/package.json +1 -1
  14. package/template/neo-bi-cmps/package.json +1 -1
  15. package/template/neo-bi-cmps/src/components/aiCommitDrawer__c/index.tsx +17 -10
  16. package/template/neo-bi-cmps/src/components/aiCommitDrawer__c/model.ts +47 -6
  17. package/template/neo-bi-cmps/src/components/filterBar__c/index.tsx +21 -7
  18. package/template/neo-bi-cmps/src/components/forecastChart__c/index.tsx +6 -9
  19. package/template/neo-bi-cmps/src/components/forecastChart__c/model.ts +2 -1
  20. package/template/neo-bi-cmps/src/components/forecastGrid__c/model.ts +32 -4
  21. package/template/neo-bi-cmps/src/components/gapCloser__c/index.tsx +7 -2
  22. package/template/neo-bi-cmps/src/components/gapCloser__c/model.ts +6 -3
  23. package/template/neo-bi-cmps/src/components/kpiCards__c/model.ts +18 -3
  24. package/template/neo-bi-cmps/src/components/oppList__c/index.tsx +70 -13
  25. package/template/neo-bi-cmps/src/components/oppList__c/model.ts +50 -4
  26. package/template/neo-bi-cmps/src/components/pipelineFunnel__c/index.tsx +3 -1
  27. package/template/neo-bi-cmps/src/components/pipelineFunnel__c/model.ts +28 -4
  28. package/template/neo-bi-cmps/src/components/stageSwitch__c/index.tsx +21 -6
  29. package/template/neo-bi-cmps/src/components/stageSwitch__c/model.ts +60 -5
  30. package/template/neo-bi-cmps/src/components/stageTimeChart__c/model.ts +26 -4
  31. package/template/neo-custom-cmp-template/package.json +1 -1
  32. package/template/neo-h5-cmps/package.json +1 -1
  33. package/template/neo-order-cmps/package.json +1 -1
  34. package/template/neo-web-entity-grid/package.json +1 -1
  35. package/template/neo-web-form/package.json +1 -1
  36. package/template/neo-web-form/src/components/batchAddTable__c/index.tsx +17 -17
  37. package/template/react-custom-cmp-template/package.json +1 -1
  38. package/template/react-ts-custom-cmp-template/package.json +1 -1
  39. package/template/vue2-custom-cmp-template/package.json +1 -1
  40. package/template/neo-bi-cmps/docs/gartner-pipeline-apis.md +0 -279
  41. package/template/neo-bi-cmps/docs/gartner-pipeline-prd.md +0 -389
  42. package/template/neo-bi-cmps/docs/neo-backend-dev/SKILL.md +0 -188
  43. package/template/neo-bi-cmps/docs/neo-backend-dev/references/01-Trigger/345/274/200/345/217/221.md +0 -183
  44. package/template/neo-bi-cmps/docs/neo-backend-dev/references/02-/350/207/252/345/256/232/344/271/211API/345/274/200/345/217/221.md +0 -196
  45. package/template/neo-bi-cmps/docs/neo-backend-dev/references/03-SDK/345/267/245/345/205/267/347/261/273/346/216/245/345/217/243.md +0 -346
  46. package/template/neo-bi-cmps/docs/neo-backend-dev/references/04-/350/256/241/345/210/222/344/275/234/344/270/232/345/274/200/345/217/221.md +0 -188
  47. package/template/neo-bi-cmps/docs/neo-backend-dev/references/05-/351/241/265/351/235/242/345/274/200/345/217/221.md +0 -293
  48. package/template/neo-bi-cmps/docs/neo-backend-dev/references/06-/346/265/201/347/250/213/346/211/251/345/261/225/345/274/200/345/217/221.md +0 -175
  49. package/template/neo-bi-cmps/docs/neo-backend-dev/references/PaaS/345/271/263/345/217/260/345/274/200/345/217/221/346/211/213/345/206/214/350/247/243/350/257/273.md +0 -313
  50. package/template/neo-bi-cmps/docs/neo-backend-dev/references/auth-config.md +0 -77
  51. package/template/neo-bi-cmps/docs/neo-backend-dev/scripts/deploy_server_script.py +0 -118
  52. package/template/neo-bi-cmps/docs/neo-backend-dev/scripts/download_server_script.py +0 -74
  53. package/template/neo-bi-cmps/docs/neo-backend-dev/scripts/gen_entity_desc.py +0 -69
  54. package/template/neo-bi-cmps/docs/neo-backend-dev/scripts/gen_entitylist.py +0 -87
  55. package/template/neo-bi-cmps/docs/neo-backend-dev/scripts/query_crm.py +0 -65
  56. package/template/neo-bi-cmps/docs/neo-backend-dev/scripts/uninstall_server_script.py +0 -48
  57. package/template/neo-bi-cmps/docs/neo-backend-dev/scripts/update_model_jar.py +0 -49
  58. package/template/neo-bi-cmps/docs/neo-frontend-dev/SKILL.md +0 -138
  59. package/template/neo-bi-cmps/docs/neo-frontend-dev/references/auth-config.md +0 -77
  60. package/template/neo-bi-cmps/docs/neo-frontend-dev/references/component-dev.md +0 -205
  61. package/template/neo-bi-cmps/docs/neo-frontend-dev/references/entityTable-example.md +0 -167
  62. package/template/neo-bi-cmps/docs/neo-frontend-dev/references/templates.md +0 -38
  63. package/template/neo-bi-cmps/docs/neo-frontend-dev/scripts/gen_entity_desc.py +0 -69
  64. package/template/neo-bi-cmps/docs/neo-frontend-dev/scripts/gen_entitylist.py +0 -87
  65. package/template/neo-bi-cmps/docs/neo-frontend-dev/scripts/query_crm.py +0 -65
  66. package/template/neo-bi-cmps/docs/prototype-pipeline-forecasting.html +0 -2453
  67. package/template/neo-bi-cmps/docs//350/264/246/345/217/267/347/233/270/345/205/263/344/277/241/346/201/257.md +0 -10
@@ -1,167 +0,0 @@
1
- # entityTable__c 参考实现
2
-
3
- 这是一个完整的实体数据表格组件示例,支持增删改查操作。开发新组件前参考此实现了解最佳实践。
4
-
5
- ## 目录
6
-
7
- - [关键设计模式](#关键设计模式)
8
- - [组件代码](#组件代码)
9
- - [模型代码](#模型代码)
10
- - [样式代码](#样式代码)
11
-
12
- ## 关键设计模式
13
-
14
- ### 1. 使用 xObjectDataApi 配置项对接实体数据源
15
-
16
- 模型中使用 `type: 'xObjectDataApi'` 配置项,让设计器提供实体选择和字段选择的 UI:
17
-
18
- ```typescript
19
- propsSchema = [
20
- {
21
- type: 'xObjectDataApi',
22
- name: 'xObjectDataApi',
23
- label: '实体数据源',
24
- value: {
25
- xObjectApiKey: 'customContact__c',
26
- fields: ['name', 'phone__c'],
27
- },
28
- custom: true, // true 表示自定义实体
29
- },
30
- ];
31
- ```
32
-
33
- 组件通过 `this.props.xObjectDataApi` 获取配置,包含:
34
- - `xObjectApiKey`:实体 API Key
35
- - `fields`:选中的字段列表
36
- - `fieldDescList`:字段描述信息(平台自动注入)
37
- - `pageSize` / `page`:分页参数
38
-
39
- ### 2. 动态获取字段描述
40
-
41
- 通过 `xObject.getDesc()` 获取实体的字段元数据,用于动态生成表格列和表单:
42
-
43
- ```typescript
44
- const resultData = await xObject.getDesc(xObjectApiKey);
45
- const fieldList = resultData.data.fields; // 包含 apiKey, label, type, required 等
46
- ```
47
-
48
- ### 3. 根据字段类型渲染表单控件
49
-
50
- 根据 `field.type` 动态选择输入组件:
51
- - `picklist` → Select 单选
52
- - `multipicklist` → Select 多选
53
- - `textarea` → Input.TextArea
54
- - `datetime` / `date` / `time` → DatePicker
55
- - `int` / `float` → InputNumber
56
- - `entityType` → Select(业务类型列表)
57
- - 默认 → Input
58
-
59
- ### 4. 声明组件函数(可执行动作)
60
-
61
- 使用 `@NeoEvent.function` 装饰器声明可被其他组件调用的动作:
62
-
63
- ```typescript
64
- @NeoEvent.function
65
- async loadData(page = 1, pageSize = 10) { ... }
66
- ```
67
-
68
- 模型中声明函数列表:
69
-
70
- ```typescript
71
- functions = [
72
- { apiKey: 'loadData', label: '刷新表格', helpTextKey: '刷新当前表格数据' },
73
- {
74
- apiKey: 'handleDelete', label: '删除记录', helpTextKey: '删除指定记录',
75
- funcInParams: [
76
- { apiKey: 'id', label: '记录ID', type: 'String', required: true },
77
- ],
78
- },
79
- ];
80
- ```
81
-
82
- ### 5. 使用 panelSwitch 配置开关
83
-
84
- ```typescript
85
- { type: 'panelSwitch', name: 'showAddButton', label: '显示新增按钮' },
86
- ```
87
-
88
- ### 6. componentDidUpdate 响应配置变化
89
-
90
- 当设计器中修改了 xObjectDataApi 配置时,组件需要重新加载数据:
91
-
92
- ```typescript
93
- async componentDidUpdate(prevProps) {
94
- if (xObjectApiKey !== prevXObjectApiKey || !isEqual(fields, prevFields)) {
95
- await this.loadFieldList();
96
- this.loadData(page, pageSize);
97
- }
98
- }
99
- ```
100
-
101
- ## 组件代码
102
-
103
- ```typescript
104
- // index.tsx 关键结构
105
- import { Table, Button, Space, Modal, Form, Input, Select, message, Popconfirm, Spin, Empty, Card } from 'antd';
106
- import { PlusOutlined, EditOutlined, DeleteOutlined, ReloadOutlined } from '@ant-design/icons';
107
- import { xObject } from 'neo-open-api';
108
- import { BaseCmp, NeoEvent } from 'neo-ui-common';
109
-
110
- interface EntityTableProps {
111
- xObjectDataApi: {
112
- xObjectApiKey: string;
113
- fields: string[];
114
- fieldDescList?: any[];
115
- pageSize?: number;
116
- page?: number;
117
- };
118
- showAddButton?: boolean;
119
- showEditButton?: boolean;
120
- showDeleteButton?: boolean;
121
- className?: string;
122
- }
123
-
124
- // 组件继承 BaseCmp,实现 CRUD 操作
125
- // 使用 xObject.query / create / update / delete 对接平台数据
126
- // 使用 xObject.getDesc 获取字段元数据
127
- // 使用 xObject.getEntityTypeList 获取业务类型列表
128
- ```
129
-
130
- ## 模型代码
131
-
132
- ```typescript
133
- // model.ts 关键配置
134
- export class EntityTableModel {
135
- label = '实体数据表格';
136
- description = '基于 XObject 的数据表格组件,支持增删改查操作';
137
- targetPage = ['all'];
138
- targetDevice = 'web';
139
-
140
- defaultComProps = {
141
- showAddButton: true,
142
- showEditButton: true,
143
- showDeleteButton: true,
144
- xObjectDataApi: {
145
- xObjectApiKey: 'customContact__c',
146
- fields: ['name', 'phone__c'],
147
- },
148
- };
149
-
150
- // 组件函数声明
151
- functions = [
152
- { apiKey: 'loadData', label: '刷新表格' },
153
- { apiKey: 'handleDelete', label: '删除记录', funcInParams: [...] },
154
- ];
155
-
156
- propsSchema = [
157
- { type: 'xObjectDataApi', name: 'xObjectDataApi', label: '实体数据源', custom: true },
158
- { type: 'panelSwitch', name: 'showAddButton', label: '显示新增按钮' },
159
- { type: 'panelSwitch', name: 'showEditButton', label: '显示编辑按钮' },
160
- { type: 'panelSwitch', name: 'showDeleteButton', label: '显示删除按钮' },
161
- ];
162
- }
163
- ```
164
-
165
- ## 样式代码
166
-
167
- 组件根节点 class 为 `entityTable__c`(与目录名一致),使用 Card 包裹,包含响应式设计(768px / 576px 断点)。
@@ -1,38 +0,0 @@
1
- # 内置模板
2
-
3
- 执行 `neo init` 时可选择以下模板,也可通过 `-t <类型> -n <名称>` 非交互创建。
4
-
5
- | 模板类型 | 说明 | 适用场景 |
6
- |----------|------|----------|
7
- | `neo-web-cmps` | Web 端列表组件模板 | 基础大列表、Picker 列表等 |
8
- | `neo-h5-cmps` | H5 端业务组件模板 | 全局搜索、数据列表、数据 Tabs、AI 对话页等 |
9
- | `neo` | 自定义业务组件模板 | 实体表单、实体详情、实体表格等 |
10
- | `neo-bi-cmps` | 数值指标组件模板 | 展示实体数据源中关键数值指标 |
11
- | `echarts` | ECharts 图表组件模板 | 基于 ECharts 的图表(地图场景用 `amap`) |
12
- | `antd` | Ant Design 组件模板 | 数据仪表板、搜索组件等 |
13
- | `amap` | 高德地图组件模板 | 基于高德地图 API 的地图组件 |
14
- | `vue2` | Vue2 组件模板 | 基于 Vue2 的组件 |
15
-
16
- ## 选择建议
17
-
18
- - 需要实体数据 CRUD → `neo`
19
- - 需要图表可视化 → `echarts`
20
- - 需要地图展示 → `amap`
21
- - 需要丰富 UI 组件库 → `antd`
22
- - H5 移动端场景 → `neo-h5-cmps`
23
- - Web 端列表场景 → `neo-web-cmps`
24
- - BI 数值指标展示 → `neo-bi-cmps`
25
- - Vue 技术栈 → `vue2`
26
-
27
- ## 非交互创建示例
28
-
29
- ```bash
30
- neo init -t neo -n myBizCmp
31
- neo init -t echarts -n myChartCmp
32
- neo init -t antd -n myAntdCmp
33
- neo init -t amap -n myMapCmp
34
- neo init -t vue2 -n myVue2Cmp
35
- neo init -t neo-web-cmps -n myWebListCmp
36
- neo init -t neo-h5-cmps -n myH5Cmp
37
- neo init -t neo-bi-cmps -n myBiCmp
38
- ```
@@ -1,69 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- 生成实体字段描述:通过 API 获取指定实体的字段信息,输出 <apiKey>.md
4
- 用法: python3 gen_entity_desc.py <项目目录> <实体apiKey>
5
- 示例: python3 gen_entity_desc.py NEOTrail investment__c
6
- """
7
- import sys, os, json, urllib.request
8
-
9
- if len(sys.argv) < 3:
10
- print("用法: python3 gen_entity_desc.py <项目目录> <实体apiKey>")
11
- sys.exit(1)
12
-
13
- project_dir = sys.argv[1]
14
- api_key = sys.argv[2]
15
- token_path = os.path.join(project_dir, '.neo-cli/token.json')
16
- output_dir = os.path.join(project_dir, 'src/entity-model')
17
-
18
- if not os.path.exists(token_path):
19
- print("错误: 未找到 %s,请先执行 neo login" % token_path)
20
- sys.exit(1)
21
-
22
- token = json.load(open(token_path))
23
- access_token = token['access_token']
24
- base_url = token['instance_uri'].rstrip('/')
25
- headers = {'Authorization': 'Bearer ' + access_token, 'Content-Type': 'application/json'}
26
-
27
- def api_get(path):
28
- req = urllib.request.Request(base_url + path, method='GET')
29
- for k, v in headers.items():
30
- req.add_header(k, v)
31
- return json.loads(urllib.request.urlopen(req).read().decode('utf-8'))
32
-
33
- # 1. 获取实体信息
34
- print("获取实体信息: %s ..." % api_key)
35
- try:
36
- entity_data = api_get('/rest/metadata/v2.0/xobjects/' + api_key)
37
- entity = entity_data.get('data', {}).get('records', {})
38
- entity_label = entity.get('label', api_key)
39
- except Exception as e:
40
- print("错误: 获取实体信息失败: %s" % e)
41
- entity_label = api_key
42
-
43
- # 2. 获取字段列表
44
- print("获取字段列表 ...")
45
- try:
46
- fields_data = api_get('/rest/metadata/v2.0/xobjects/' + api_key + '/items')
47
- fields = fields_data.get('data', {}).get('records', [])
48
- except Exception as e:
49
- print("错误: 获取字段列表失败: %s" % e)
50
- sys.exit(1)
51
-
52
- # 3. 生成 <apiKey>.md
53
- os.makedirs(output_dir, exist_ok=True)
54
-
55
- lines = ['# %s (%s)' % (entity_label, api_key), '',
56
- '| 字段名称 | API Key | 字段类型 | 是否标准字段 |',
57
- '|----------|---------|----------|------------|']
58
- for f in fields:
59
- fk = f.get('apiKey', '')
60
- label = f.get('label', '')
61
- ftype = f.get('type', '')
62
- is_std = '是' if not fk.endswith('__c') else '否'
63
- lines.append('| %s | %s | %s | %s |' % (label, fk, ftype, is_std))
64
-
65
- output_path = os.path.join(output_dir, api_key + '.md')
66
- with open(output_path, 'w', encoding='utf-8') as f:
67
- f.write('\n'.join(lines))
68
-
69
- print("完成: %s (%s, %d 个字段)" % (output_path, entity_label, len(fields)))
@@ -1,87 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- 生成实体字典:下载 model.jar,解析实体列表,通过 API 获取 label,输出 entitylist.md
4
- 用法: python3 gen_entitylist.py <项目目录>
5
- 示例: python3 gen_entitylist.py NEOTrail
6
- """
7
- import sys, os, json, zipfile, urllib.request
8
-
9
- if len(sys.argv) < 2:
10
- print("用法: python3 gen_entitylist.py <项目目录>")
11
- sys.exit(1)
12
-
13
- project_dir = sys.argv[1]
14
- token_path = os.path.join(project_dir, '.neo-cli/token.json')
15
- output_dir = os.path.join(project_dir, 'src/entity-model')
16
- jar_path = os.path.join(project_dir, 'model.jar')
17
-
18
- if not os.path.exists(token_path):
19
- print("错误: 未找到 %s,请先执行 neo login" % token_path)
20
- sys.exit(1)
21
-
22
- token = json.load(open(token_path))
23
- access_token = token['access_token']
24
- base_url = token['instance_uri'].rstrip('/')
25
- headers = {'Authorization': 'Bearer ' + access_token, 'Content-Type': 'application/json'}
26
-
27
- def api_get(path):
28
- req = urllib.request.Request(base_url + path, method='GET')
29
- for k, v in headers.items():
30
- req.add_header(k, v)
31
- return json.loads(urllib.request.urlopen(req).read().decode('utf-8'))
32
-
33
- # 1. 下载 model.jar
34
- print("下载 model.jar ...")
35
- jar_url_data = api_get('/rest/metadata/v2.0/scripts/packages/model/jar/url')
36
- jar_url = jar_url_data.get('data', {}).get('records', '')
37
- urllib.request.urlretrieve(jar_url, jar_path)
38
- print("已下载: %s" % jar_path)
39
-
40
- # 2. 解析 jar 获取实体列表
41
- with zipfile.ZipFile(jar_path, 'r') as z:
42
- classes = [n for n in z.namelist() if n.endswith('.class') and '/model/' in n]
43
-
44
- jar_entities = {}
45
- for c in classes:
46
- name = c.split('/')[-1].replace('.class', '')
47
- apiKey = name[0].lower() + name[1:]
48
- is_standard = not (name.endswith('__c') or name.endswith('__a'))
49
- jar_entities[apiKey] = {'className': name, 'apiKey': apiKey, 'isStandard': is_standard, 'label': ''}
50
-
51
- # 3. 批量获取 label
52
- print("获取实体 label ...")
53
- label_map = {}
54
- for custom_flag in ['true', 'false']:
55
- try:
56
- data = api_get('/rest/metadata/v2.0/xobjects/filter?custom=%s&active=true' % custom_flag)
57
- for r in data.get('data', {}).get('records', []):
58
- label_map[r.get('apiKey', '')] = r.get('label', '')
59
- except Exception as e:
60
- print("警告: 获取实体列表失败 (custom=%s): %s" % (custom_flag, e))
61
-
62
- for ak, label in label_map.items():
63
- if ak in jar_entities:
64
- jar_entities[ak]['label'] = label
65
-
66
- # 4. 生成 entitylist.md
67
- entities = sorted(jar_entities.values(), key=lambda x: x['className'])
68
- standard = [e for e in entities if e['isStandard']]
69
- custom = [e for e in entities if not e['isStandard']]
70
-
71
- os.makedirs(output_dir, exist_ok=True)
72
-
73
- lines = ['# 实体字典', '',
74
- '租户 ID: %s | 环境: %s' % (token.get('tenant_id', ''), base_url), '',
75
- '共 %d 个实体(%d 个标准实体 + %d 个自定义实体)' % (len(entities), len(standard), len(custom)), '',
76
- '| 实体名称 | API Key | 类型 |',
77
- '|----------|---------|------|']
78
- for e in entities:
79
- label = e['label'] if e['label'] else e['className']
80
- etype = '标准' if e['isStandard'] else '自定义'
81
- lines.append('| %s | %s | %s |' % (label, e['apiKey'], etype))
82
-
83
- output_path = os.path.join(output_dir, 'entitylist.md')
84
- with open(output_path, 'w', encoding='utf-8') as f:
85
- f.write('\n'.join(lines))
86
-
87
- print("完成: %s (%d 个实体, %d 个 label)" % (output_path, len(entities), len(label_map)))
@@ -1,65 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- 查询 CRM 系统数据工具。借助当前项目的登录状态执行 SQL 查询。
4
- 用法: python3 query_crm.py <项目目录> "<SQL查询语句>"
5
- 示例: python3 query_crm.py 临时验证 "SELECT id, opportunityName, amount FROM opportunity LIMIT 10"
6
- """
7
- import os, json, urllib.request, urllib.error, sys
8
-
9
- if len(sys.argv) < 3:
10
- print("用法: python3 query_crm.py <项目目录> \"<SQL查询语句>\"")
11
- sys.exit(1)
12
-
13
- project_dir = sys.argv[1]
14
- sql = sys.argv[2]
15
- token_path = os.path.join(project_dir, '.neo-cli/token.json')
16
-
17
- if not os.path.exists(token_path):
18
- print("错误: 未找到 %s,请先执行 neo login" % token_path)
19
- sys.exit(1)
20
-
21
- token = json.load(open(token_path))
22
- access_token = token['access_token']
23
- base_url = token['instance_uri'].rstrip('/')
24
-
25
- print("执行查询: %s\n" % sql)
26
-
27
- url = base_url + '/rest/data/v2/query'
28
- encoded_sql = urllib.request.quote(sql)
29
- full_url = url + '?q=' + encoded_sql
30
-
31
- req = urllib.request.Request(full_url, method='GET')
32
- req.add_header('Authorization', 'Bearer ' + access_token)
33
- req.add_header('Content-Type', 'application/json')
34
-
35
- try:
36
- resp = urllib.request.urlopen(req)
37
- data = json.loads(resp.read().decode('utf-8'))
38
-
39
- records = data.get('result', data.get('data', {})).get('records', [])
40
- total = data.get('result', data.get('data', {})).get('totalSize', len(records) if isinstance(records, list) else 0)
41
-
42
- if isinstance(records, list) and len(records) > 0:
43
- # 提取字段名
44
- fields = list(records[0].keys()) if isinstance(records[0], dict) else []
45
-
46
- # 打印表头
47
- header = ' | '.join(str(f) for f in fields)
48
- print(header)
49
- print('-' * len(header))
50
-
51
- # 打印数据
52
- for r in records:
53
- if isinstance(r, dict):
54
- row = ' | '.join(str(r.get(f, '')) for f in fields)
55
- print(row)
56
-
57
- print("\n共 %s 条记录" % total)
58
- else:
59
- print("无数据")
60
- print("原始响应: %s" % json.dumps(data, ensure_ascii=False)[:1000])
61
-
62
- except urllib.error.HTTPError as e:
63
- print("请求失败 HTTP %d: %s" % (e.code, e.read().decode('utf-8')[:500]))
64
- except Exception as e:
65
- print("异常: %s" % e)