cloudcc-cli 2.3.1 → 2.3.3
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/.claude/settings.json +25 -0
- package/.cloudcc-cache.json +21 -4
- package/.cursor/skills/cloudcc-cli-dev.zip +0 -0
- package/.cursor/skills/cloudcc-cli-usage/SKILL.md +68 -0
- package/README.md +22 -0
- package/bin/cc.js +13 -8
- package/bin/index.js +9 -2
- package/bin/mcp.js +1 -1
- package/build/component-CCPlugin1774500425584.common.js +831 -0
- package/build/component-CCPlugin1774500425584.common.js.map +1 -0
- package/build/component-CCPlugin1774500425584.css +1 -0
- package/build/component-CCPlugin1774500425584.umd.js +874 -0
- package/build/component-CCPlugin1774500425584.umd.js.map +1 -0
- package/build/component-CCPlugin1774500425584.umd.min.js +8 -0
- package/build/component-CCPlugin1774500425584.umd.min.js.map +1 -0
- package/build/demo.html +1 -0
- package/{src/mcp → mcp}/tools/Class Editor Guide/handler.js +12 -4
- package/{src/mcp → mcp}/tools/Component Editor Guide/handler.js +15 -14
- package/{src/mcp → mcp}/tools/Trigger Editor Guide/handler.js +8 -2
- package/package.json +3 -2
- package/src/application/doc.js +46 -0
- package/src/application/docs/devguide.md +173 -0
- package/src/application/docs/introduction.md +81 -0
- package/src/application/index.js +1 -0
- package/src/brief/get.js +1 -1
- package/src/classes/create.js +6 -1
- package/src/classes/delete.js +7 -1
- package/src/classes/detail.js +8 -1
- package/src/classes/doc.js +49 -472
- package/src/classes/docs/devguide.md +541 -0
- package/src/classes/get.js +9 -2
- package/src/classes/index.js +2 -1
- package/src/classes/publish.js +6 -1
- package/src/classes/pull.js +6 -1
- package/src/classes/pullList.js +6 -3
- package/src/config/doc.js +31 -0
- package/src/config/docs/devguide.md +100 -0
- package/src/config/index.js +5 -0
- package/src/customPage/create.js +52 -19
- package/src/customPage/doc.js +46 -0
- package/src/customPage/docs/devguide.md +200 -0
- package/{.cursor/skills/cloudcc-cli-dev/docs//350/207/252/345/256/232/344/271/211/351/241/265/351/235/242.md → src/customPage/docs/introduction.md} +1 -5
- package/src/customPage/index.js +1 -0
- package/src/customSetting/create.js +9 -0
- package/src/customSetting/delete.js +10 -1
- package/src/customSetting/deleteCustomSettingField.js +43 -0
- package/src/customSetting/detail.js +10 -1
- package/src/customSetting/doc.js +22 -179
- package/src/customSetting/docs/devguide.md +181 -0
- package/src/customSetting/docs/introduction.md +3 -0
- package/src/customSetting/editCustomSettingField.js +34 -0
- package/src/customSetting/get.js +9 -0
- package/src/customSetting/index.js +6 -1
- package/src/customSetting/modify.js +30 -0
- package/src/customSetting/saveCustomSettingField.js +46 -0
- package/src/fields/doc.js +45 -0
- package/src/fields/docs/devguide.md +224 -0
- package/src/fields/docs/introduction.md +217 -0
- package/src/fields/index.js +1 -0
- package/src/globalSelectList/create.js +51 -0
- package/src/globalSelectList/delete.js +56 -0
- package/src/globalSelectList/detail.js +45 -0
- package/src/globalSelectList/doc.js +52 -0
- package/src/globalSelectList/docs/devguide.md +153 -0
- package/src/globalSelectList/docs/introduction.md +82 -0
- package/src/globalSelectList/get.js +31 -0
- package/src/globalSelectList/index.js +16 -0
- package/src/menu/create-page.js +43 -6
- package/src/menu/create-script.js +67 -19
- package/src/menu/doc.js +57 -0
- package/src/menu/docs/devguide.md +129 -0
- package/src/menu/docs/introduction.md +99 -0
- package/src/menu/index.js +1 -0
- package/src/menu/validator.js +80 -0
- package/src/object/doc.js +45 -0
- package/src/object/docs/devguide.md +112 -0
- package/src/object/docs/introduction.md +187 -0
- package/src/object/get.js +1 -23
- package/src/object/index.js +1 -0
- package/src/pagelayout/create.js +123 -0
- package/src/pagelayout/delete.js +57 -0
- package/src/pagelayout/doc.js +46 -0
- package/src/pagelayout/docs/devguide.md +83 -0
- package/src/pagelayout/docs/introduction.md +44 -0
- package/src/pagelayout/get.js +46 -0
- package/src/pagelayout/index.js +10 -0
- package/src/plugin/doc.js +43 -863
- package/src/plugin/docs/devguide.md +996 -0
- package/src/profile/create.js +108 -0
- package/src/profile/delete.js +59 -0
- package/src/profile/doc.js +46 -0
- package/src/profile/docs/devguide.md +77 -0
- package/src/profile/docs/introduction.md +123 -0
- package/src/profile/get.js +55 -0
- package/src/profile/index.js +14 -0
- package/src/project/doc.js +39 -372
- package/src/project/docs/devguide.md +359 -0
- package/src/project/docs/introduction.md +3 -0
- package/src/recordType/create.js +77 -0
- package/src/recordType/delete.js +52 -0
- package/src/recordType/doc.js +36 -0
- package/src/recordType/docs/devguide.md +160 -0
- package/src/recordType/docs/introduction.md +53 -0
- package/src/recordType/editInfo.js +39 -0
- package/src/recordType/editSave.js +47 -0
- package/src/recordType/getList.js +31 -0
- package/src/recordType/index.js +16 -3
- package/src/recordType/newInfo.js +39 -0
- package/src/recordType/validDelete.js +91 -0
- package/src/res.md +66 -0
- package/src/role/create.js +153 -0
- package/src/role/delete.js +59 -0
- package/src/role/doc.js +46 -0
- package/src/role/docs/devguide.md +81 -0
- package/src/role/docs/introduction.md +124 -0
- package/src/role/get.js +57 -0
- package/src/role/index.js +10 -0
- package/src/scheduleJob/doc.js +49 -0
- package/src/scheduleJob/docs/devguide.md +79 -0
- package/src/scheduleJob/docs/introduction.md +101 -0
- package/src/scheduleJob/index.js +5 -0
- package/src/script/delete.js +112 -0
- package/src/script/doc.js +31 -245
- package/src/script/docs/devguide.md +290 -0
- package/src/script/docs/introduction.md +48 -0
- package/src/script/index.js +1 -0
- package/src/staticResource/count.js +31 -10
- package/src/staticResource/create.js +97 -0
- package/src/staticResource/delete.js +30 -8
- package/src/staticResource/detail.js +32 -10
- package/src/staticResource/doc.js +21 -88
- package/src/staticResource/docs/devguide.md +157 -0
- package/src/staticResource/docs/introduction.md +3 -0
- package/src/staticResource/get.js +31 -8
- package/src/staticResource/index.js +2 -1
- package/src/timer/create.js +6 -1
- package/src/timer/delete.js +7 -1
- package/src/timer/detail.js +5 -5
- package/src/timer/doc.js +57 -0
- package/{.cursor/skills/cloudcc-cli-dev/docs/cloudcc/345/256/232/346/227/266/344/275/234/344/270/232.md → src/timer/docs/devguide.md} +83 -1
- package/src/timer/get.js +7 -1
- package/src/timer/index.js +3 -1
- package/src/timer/publish.js +6 -1
- package/src/timer/pull.js +6 -1
- package/src/timer/pullList.js +5 -3
- package/src/triggers/detail.js +5 -5
- package/src/triggers/doc.js +49 -364
- package/src/triggers/docs/devguide.md +442 -0
- package/src/triggers/get.js +7 -3
- package/src/triggers/index.js +1 -4
- package/src/triggers/pullList.js +7 -7
- package/src/user/create.js +50 -0
- package/src/user/delete.js +59 -0
- package/src/user/doc.js +46 -0
- package/src/user/docs/devguide.md +122 -0
- package/src/user/docs/introduction.md +124 -0
- package/src/user/get.js +112 -0
- package/src/user/index.js +12 -0
- package/src/user/update.js +96 -0
- package/src/user/view.js +60 -0
- package/test/classes.cli.test.js +7 -4
- package/test/customPage.cli.test.js +96 -0
- package/test/globalSelectList.cli.test.js +94 -0
- package/test/menu-script.cli.test.js +147 -0
- package/test/menu.cli.test.js +8 -1
- package/test/plugin.cli.test.js +5 -3
- package/test/timer.cli.test.js +15 -8
- package/test/trigger.cli.test.js +5 -3
- package/.cursor/skills/cloudcc-cli-dev/BACKEND_CLASS.md +0 -111
- package/.cursor/skills/cloudcc-cli-dev/BACKEND_SCHEDULE.md +0 -152
- package/.cursor/skills/cloudcc-cli-dev/BACKEND_TRIGGER.md +0 -150
- package/.cursor/skills/cloudcc-cli-dev/CLI_CHEATSHEET.md +0 -372
- package/.cursor/skills/cloudcc-cli-dev/CUSTOM-SETTING-API.md +0 -62
- package/.cursor/skills/cloudcc-cli-dev/INSTALL_AND_BOOTSTRAP.md +0 -62
- package/.cursor/skills/cloudcc-cli-dev/OBJECTS_AND_FIELDS.md +0 -214
- package/.cursor/skills/cloudcc-cli-dev/REQUIREMENTS_BREAKDOWN.md +0 -113
- package/.cursor/skills/cloudcc-cli-dev/SKILL.md +0 -66
- package/.cursor/skills/cloudcc-cli-dev/STATIC-RESOURCE-API.md +0 -60
- package/.cursor/skills/cloudcc-cli-dev/VUE_CUSTOM_COMPONENT.md +0 -151
- package/.cursor/skills/cloudcc-cli-dev/VUE_CUSTOM_PAGE.md +0 -216
- package/src/approval/approve.js +0 -105
- package/src/approval/get.js +0 -245
- package/src/approval/index.js +0 -11
- package/src/approval/reject.js +0 -105
- package/src/plugin/readme.md +0 -7
- /package/{src/mcp → mcp}/cliRunner.js +0 -0
- /package/{src/mcp → mcp}/index.js +0 -0
- /package/{src/mcp → mcp}/readme.md +0 -0
- /package/{src/mcp → mcp}/tools/Application Creator/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/Approval/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/Class Creator/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/Class Detail Retriever/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/Class List Retriever/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/Class Publisher/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/Class Puller/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/Client Script Detail Retriever/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/Client Script Editor Guide/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/Client Script List Retriever/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/Client Script Publisher/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/Client Script Puller/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/CloudCC Development Overview/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/Component Creator/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/Component Detail Retriever/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/Component List Retriever/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/Component Publisher/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/Component Puller/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/Dev Environment Creator/fetcher.js +0 -0
- /package/{src/mcp → mcp}/tools/Dev Environment Creator/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/Dev Environment Validator/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/Developer Key Setup Guide/fetcher.js +0 -0
- /package/{src/mcp → mcp}/tools/Developer Key Setup Guide/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/JSP Migrator/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/Menu Creator/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/Object Creator/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/Object Fields Creator/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/Object Fields Retriever/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/Object List Retriever/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/Scheduled Class Creator/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/Scheduled Class Detail Retriever/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/Scheduled Class List Retriever/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/Scheduled Class Publisher/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/Scheduled Class Puller/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/Trigger Creator/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/Trigger Detail Retriever/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/Trigger List Retriever/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/Trigger Publisher/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/Trigger Puller/handler.js +0 -0
- /package/{src/mcp → mcp}/tools/index.js +0 -0
- /package/{.cursor/skills/cloudcc-cli-dev/docs//350/207/252/345/256/232/344/271/211/347/261/273.md" → src/classes/docs/introduction.md} +0 -0
- /package/{.cursor/skills/cloudcc-cli-dev/docs/CloudCC/350/207/252/345/256/232/344/271/211/347/273/204/344/273/266/344/275/277/347/224/250/350/257/264/346/230/216.md" → src/plugin/docs/introduction.md} +0 -0
- /package/{.cursor/skills/cloudcc-cli-dev/docs/cloudcc/345/256/232/346/227/266/347/261/273.md" → src/timer/docs/introduction.md} +0 -0
- /package/{.cursor/skills/cloudcc-cli-dev/docs//350/247/246/345/217/221/345/231/250/347/261/273.md" → src/triggers/docs/introduction.md} +0 -0
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
# CloudCC 触发器使用总结
|
|
2
|
+
|
|
3
|
+
> 基于 25 个生产环境触发器实例分析。
|
|
4
|
+
> 文档版本:v1.0
|
|
5
|
+
> 更新时间:2026-03-24
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## CLI 与本地文件(必读)
|
|
10
|
+
|
|
11
|
+
本仓库中的触发器源码通过 **cloudcc-cli** 与平台同步,本地目录为 **`triggers/<对象 API 名小写>/<触发器名>/`**(内含 `*.java`、`config.json`),源码中的 `// @SOURCE_CONTENT_START` … `// @SOURCE_CONTENT_END` 与发布、拉取逻辑一致。**必须通过下列命令** 完成新建、发布、拉取与删除;不要手工拼目录、不要整包复制其他项目的触发器、不要私自篡改 `config.json` 中的 `id`、`apiname` 等字段。
|
|
12
|
+
|
|
13
|
+
**允许的做法**:在 CLI 已生成的主类中,仅在上述 SOURCE 标记之间编写业务逻辑;与云端列表、详情、拉取、删除、发布相关的操作一律走命令。
|
|
14
|
+
|
|
15
|
+
执行命令前请确认:已完成 `cc doc project devguide` 中的环境初始化,项目根目录配置可用且包含 `accessToken`。创建触发器前通常需要先通过 `cc get object ...` 等拿到目标对象的 `schemetableName`、`targetObjectId`(见下文物「创建」示例)。
|
|
16
|
+
|
|
17
|
+
### 命令总览(以代码实现为准)
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
cc create triggers <encodedCreateJson>
|
|
21
|
+
cc publish triggers <namePath>
|
|
22
|
+
cc pull triggers <namePath>
|
|
23
|
+
cc get triggers <listQueryJson> [projectPath]
|
|
24
|
+
cc detail triggers <namePath>
|
|
25
|
+
cc detail triggers "" <id>
|
|
26
|
+
cc pullList triggers <id> <projectPath>
|
|
27
|
+
cc delete triggers <namePathOrId> [projectPath]
|
|
28
|
+
cc doc triggers <introduction|devguide>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
参数约定:
|
|
32
|
+
|
|
33
|
+
- `encodedCreateJson`:`encodeURI(JSON.stringify({ ... }))`,其中至少包含:
|
|
34
|
+
- `schemetableName`:目标对象 API 名(如 `Account`)
|
|
35
|
+
- `targetObjectId`:目标对象 ID
|
|
36
|
+
- `triggerTime`:触发时机(如 `beforeInsert`、`beforeUpsert` 等,以平台为准)
|
|
37
|
+
- `name`:触发器类名(目录名)
|
|
38
|
+
- `apiname`:触发器 API 名(全局唯一)
|
|
39
|
+
- `namePath`:**对象目录/触发器名**,与本地路径一致,例如 `account/MyTrigger`(`schemetableName` 小写 + `/` + `name`)。`publish`、`pull`、`delete`(按路径删除时)均使用该形式。
|
|
40
|
+
- `listQueryJson`:列表查询 JSON,经 `encodeURI(JSON.stringify(...))` 编码后传入(**必填**,实现上无默认空查询)。
|
|
41
|
+
- `projectPath`:项目根路径,可选。
|
|
42
|
+
- `id`:线上触发器 ID。`detail` 仅查服务器:`cc detail triggers "" <id>`。
|
|
43
|
+
- `namePathOrId`:可为 `对象小写/触发器名` 形式的路径;若本地 `config.json` 含 `id`,删除时优先用该 ID。
|
|
44
|
+
|
|
45
|
+
### 命令作用摘要
|
|
46
|
+
|
|
47
|
+
| 命令 | 作用 |
|
|
48
|
+
|------|------|
|
|
49
|
+
| `create` | 在 `triggers/<对象小写>/<name>/` 生成继承 `CCTrigger` 的 Java 与 `config.json` |
|
|
50
|
+
| `publish` | 提交 SOURCE 区域等到服务器;首次成功后可写回 `config.json` 的 `id`、`apiname` 等 |
|
|
51
|
+
| `pull` | 按本地已发布 `id` 拉取远端源码,覆盖 SOURCE 区域 |
|
|
52
|
+
| `get` | 按条件查询线上触发器列表(JSON 输出) |
|
|
53
|
+
| `detail` | 按 `namePath` 优先读本地;或仅按 `id` 读服务器 |
|
|
54
|
+
| `pullList` | 按触发器 `id` 还原到指定项目的 `triggers/...` |
|
|
55
|
+
| `delete` | 删除服务器上的触发器 |
|
|
56
|
+
| `doc` | 输出模块文档;`devguide` 含附录后端 Java SDK 速查 |
|
|
57
|
+
|
|
58
|
+
### 创建示例(需先准备对象信息)
|
|
59
|
+
|
|
60
|
+
先构造对象(字段与平台约定一致),再整段做 `encodeURI(JSON.stringify(...))`,作为 `cc create triggers` 的**唯一参数**:
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"schemetableName": "Account",
|
|
65
|
+
"targetObjectId": "<目标对象 ID>",
|
|
66
|
+
"triggerTime": "beforeInsert",
|
|
67
|
+
"name": "MyTrigger",
|
|
68
|
+
"apiname": "NTrigger_unique_api_name"
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
在 Node 中生成编码后参数示例:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
node -p "encodeURI(JSON.stringify({schemetableName:'Account',targetObjectId:'<对象ID>',triggerTime:'beforeInsert',name:'MyTrigger',apiname:'NTrigger_xxx'}))"
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
将命令输出的**一整行**传给:`cc create triggers '<粘贴>'`。
|
|
79
|
+
|
|
80
|
+
### 推荐操作顺序
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
# 1) 查询自定义对象,取得 schemetableName、targetObjectId(示例)
|
|
84
|
+
cc get object . custom
|
|
85
|
+
|
|
86
|
+
# 2) 创建本地触发器目录与模板(encodedCreateJson 见上文)
|
|
87
|
+
cc create triggers '<encodedCreateJson>'
|
|
88
|
+
|
|
89
|
+
# 3) 编辑 triggers/<对象小写>/<name>/<name>.java 中 SOURCE 后发布
|
|
90
|
+
cc publish triggers account/MyTrigger
|
|
91
|
+
|
|
92
|
+
# 4) 与服务器对齐
|
|
93
|
+
cc pull triggers account/MyTrigger
|
|
94
|
+
|
|
95
|
+
# 5) 列表(查询 JSON 需 encodeURI)
|
|
96
|
+
cc get triggers '<listQueryJson>' .
|
|
97
|
+
|
|
98
|
+
# 6) 按线上 ID 拉到指定项目
|
|
99
|
+
cc pullList triggers <线上触发器ID> <projectPath>
|
|
100
|
+
|
|
101
|
+
# 7) 删除
|
|
102
|
+
cc delete triggers account/MyTrigger
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### 文档子命令
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
cc doc triggers introduction
|
|
109
|
+
cc doc triggers devguide
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
仅支持 `introduction` 与 `devguide`。
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## 一、什么是触发器
|
|
117
|
+
|
|
118
|
+
CloudCC 触发器是完全符合 Java 语法规范的代码,在特定业务事件发生时自动执行,实现业务逻辑自动化处理。
|
|
119
|
+
|
|
120
|
+
触发器本质:
|
|
121
|
+
- 一段 Java 代码,运行在 CloudCC 平台沙箱环境中
|
|
122
|
+
- 使用 CCService、CCObject 等平台提供的 API 类
|
|
123
|
+
- 在数据变更的特定时刻(前/后)自动触发执行
|
|
124
|
+
|
|
125
|
+
## 二、触发器能干什么
|
|
126
|
+
|
|
127
|
+
### 2.1 核心能力
|
|
128
|
+
|
|
129
|
+
| 能力 | 说明 | 示例 |
|
|
130
|
+
|------|------|------|
|
|
131
|
+
| 自动赋值 | 在记录保存前自动计算并填充字段 | 个人业绩/部门业绩自动赋值 |
|
|
132
|
+
| 数据校验 | 阻止不符合业务规则的数据保存 | 预算金额校验、审批金额验证 |
|
|
133
|
+
| 关联更新 | 修改一条记录时自动更新关联记录 | 回款明细汇总到收款计划 |
|
|
134
|
+
| 自动生成 | 根据业务规则自动创建新记录 | 审批通过后自动生成回款记录 |
|
|
135
|
+
| 权限控制 | 自动设置数据共享权限 | 按部门/人员自动共享 |
|
|
136
|
+
| 状态同步 | 审批状态变更后同步更新相关字段 | 预算审批状态回写 |
|
|
137
|
+
| 汇总计算 | 实时汇总明细数据到主记录 | 部门业绩字段汇总 |
|
|
138
|
+
|
|
139
|
+
### 2.2 技术能力(基于 CCService API)
|
|
140
|
+
|
|
141
|
+
```java
|
|
142
|
+
// 1. 新增记录
|
|
143
|
+
CCObject opp = new CCObject("Opportunity");
|
|
144
|
+
opp.put("name", "value");
|
|
145
|
+
cs.insert(opp);
|
|
146
|
+
|
|
147
|
+
// 2. 查询记录(指定字段)
|
|
148
|
+
List<CCObject> opps1 = cs.cqueryByFields(
|
|
149
|
+
"Opportunity",
|
|
150
|
+
"khmc__c='" + record_new.get("id") + "'",
|
|
151
|
+
"id,name,createdate"
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
// 3. 查询记录(全部字段)
|
|
155
|
+
List<CCObject> opps2 = cs.cquery(
|
|
156
|
+
"Opportunity",
|
|
157
|
+
"khmc__c='" + record_new.get("id") + "'"
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
// 4. 复杂查询
|
|
161
|
+
List<CCObject> ccobjs = cs.cqlQuery(
|
|
162
|
+
"Opportunity",
|
|
163
|
+
"select sum(amount) as sumAmount from Opportunity where khmc='0012001238ytwuiw'"
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
// 5. 修改/删除
|
|
167
|
+
cs.update(opp);
|
|
168
|
+
cs.delete(opp);
|
|
169
|
+
|
|
170
|
+
// 6. 发送邮件通知
|
|
171
|
+
SendEmail sendEmail = new SendEmail(userInfo);
|
|
172
|
+
sendEmail.sendMailFromSystem(toAddress, ccAddress, bccAddress, subject, content, isText);
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## 三、触发器的触发时机详解
|
|
178
|
+
|
|
179
|
+
### 3.1 beforeUpsert(创建或更新前)
|
|
180
|
+
- 执行时机:记录保存之前,数据尚未写入数据库
|
|
181
|
+
- 典型用途:自动计算字段、数据格式校验、阻止非法数据保存、自动填充默认值
|
|
182
|
+
- 生产实例:个人业绩/部门业绩赋值、计算产研成本/净业绩、生成部门/个人业绩
|
|
183
|
+
|
|
184
|
+
```java
|
|
185
|
+
// beforeUpsert 示例
|
|
186
|
+
CCObject record = (CCObject) data.get("record");
|
|
187
|
+
BigDecimal income = record.getBigDecimal("ysr");
|
|
188
|
+
BigDecimal cost = record.getBigDecimal("cycb");
|
|
189
|
+
BigDecimal net = income.subtract(cost);
|
|
190
|
+
record.put("jyj", net);
|
|
191
|
+
if (net.compareTo(BigDecimal.ZERO) < 0) {
|
|
192
|
+
throw new Exception("毛利不能为负数!");
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### 3.2 afterInsert(创建后)
|
|
197
|
+
- 执行时机:记录创建成功后(可获取 ID)
|
|
198
|
+
- 典型用途:基于新记录 ID 创建关联记录、发送创建通知、初始化关联数据
|
|
199
|
+
- 生产实例:根据净业绩拆分生成净业绩拆分回款
|
|
200
|
+
|
|
201
|
+
```java
|
|
202
|
+
// afterInsert 示例
|
|
203
|
+
CCObject newRecord = (CCObject) data.get("record");
|
|
204
|
+
String recordId = newRecord.getString("id");
|
|
205
|
+
CCObject hkRecord = new CCObject("Huikuan");
|
|
206
|
+
hkRecord.put("mingxi__c", recordId);
|
|
207
|
+
hkRecord.put("je", newRecord.get("je"));
|
|
208
|
+
cs.insert(hkRecord);
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### 3.3 afterUpsert(创建或更新后)
|
|
212
|
+
- 执行时机:记录保存成功后(新增或修改)
|
|
213
|
+
- 典型用途:汇总数据到父记录、触发下游流程、更新关联记录状态
|
|
214
|
+
- 生产实例:金额汇总到收款计划、更新部门业绩字段、更新回款明细
|
|
215
|
+
|
|
216
|
+
```java
|
|
217
|
+
// afterUpsert 示例 - 汇总金额到父记录
|
|
218
|
+
CCObject detail = (CCObject) data.get("record");
|
|
219
|
+
String planId = detail.getString("skjh__c");
|
|
220
|
+
List<CCObject> plans = cs.cqueryByFields(
|
|
221
|
+
"ShoukuanJihua",
|
|
222
|
+
"id='" + planId + "'",
|
|
223
|
+
"id,shyjje,yishouje"
|
|
224
|
+
);
|
|
225
|
+
if (!plans.isEmpty()) {
|
|
226
|
+
CCObject plan = plans.get(0);
|
|
227
|
+
BigDecimal current = plan.getBigDecimal("yishouje");
|
|
228
|
+
BigDecimal detailAmount = detail.getBigDecimal("je");
|
|
229
|
+
plan.put("yishouje", current.add(detailAmount));
|
|
230
|
+
cs.update(plan);
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### 3.4 afterDelete(删除后)
|
|
235
|
+
- 执行时机:记录删除成功后
|
|
236
|
+
- 典型用途:清理关联数据、反向汇总更新
|
|
237
|
+
- 生产实例:回款明细删除后重新计算回款金额
|
|
238
|
+
|
|
239
|
+
### 3.5 approval(审批时)
|
|
240
|
+
- 执行时机:记录提交审批或审批通过时
|
|
241
|
+
- 典型用途:审批前校验、审批通过后执行业务操作
|
|
242
|
+
- 生产实例:更新拆分审批状态、订单审批判断、审批通过计算剩余欠款
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## 四、为什么要用触发器
|
|
247
|
+
|
|
248
|
+
### 4.1 解决的核心问题
|
|
249
|
+
|
|
250
|
+
| 问题 | 传统方案 | 触发器方案 |
|
|
251
|
+
|------|----------|------------|
|
|
252
|
+
| 数据一致性 | 依赖用户手动操作,容易遗漏 | 自动执行,保证数据准确 |
|
|
253
|
+
| 业务规则执行 | 前端校验可绕过 | 统一在平台层执行,无法绕过 |
|
|
254
|
+
| 跨对象联动 | 需要多次手动操作 | 自动关联更新 |
|
|
255
|
+
| 审批复杂逻辑 | 审批流配置难以承载 | Java 代码可实现复杂逻辑 |
|
|
256
|
+
| 实时性要求 | 定时任务有延迟 | 实时触发,立即执行 |
|
|
257
|
+
|
|
258
|
+
### 4.2 与其他方案对比
|
|
259
|
+
|
|
260
|
+
| 方案 | 优点 | 缺点 | 适用场景 |
|
|
261
|
+
|------|------|------|----------|
|
|
262
|
+
| 触发器 | 实时、自动、无法绕过 | 需要 Java 开发能力 | 核心业务逻辑 |
|
|
263
|
+
| 审批流 | 配置简单、可视化 | 逻辑能力有限 | 简单审批流程 |
|
|
264
|
+
| 工作流 | 可视化编排 | 复杂逻辑实现困难 | 跨系统流程编排 |
|
|
265
|
+
| 定时任务 | 适合批量处理 | 有延迟 | 数据同步、报表生成 |
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## 五、典型业务场景
|
|
270
|
+
|
|
271
|
+
### 5.1 财务业绩管理(核心场景)
|
|
272
|
+
|
|
273
|
+
```text
|
|
274
|
+
订单 (Order)
|
|
275
|
+
└─ approval:审批判断
|
|
276
|
+
预算 (Budget)
|
|
277
|
+
├─ beforeUpsert:计算产研成本/净业绩
|
|
278
|
+
└─ afterUpsert:自动拆分/生成回款
|
|
279
|
+
净业绩拆分 (jyjcf)
|
|
280
|
+
├─ beforeUpsert:生成部门/个人业绩
|
|
281
|
+
└─ afterUpsert:校验金额累计是否超预算
|
|
282
|
+
部门业绩 (bmyj)
|
|
283
|
+
├─ afterUpsert:更新部门业绩字段
|
|
284
|
+
└─ afterUpdate:汇总部门资金池
|
|
285
|
+
回款明细 (cloudccproceeddetail)
|
|
286
|
+
├─ afterInsert:生成净业绩拆分回款
|
|
287
|
+
├─ afterUpsert:金额汇总到收款计划
|
|
288
|
+
├─ afterUpsert:更新回款明细
|
|
289
|
+
└─ afterDelete:回款明细删除
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### 5.2 费用报销管理
|
|
293
|
+
|
|
294
|
+
```text
|
|
295
|
+
费用报销提交
|
|
296
|
+
-> approval 触发器:验证审批时校验预算(报销金额 <= 预算余额)
|
|
297
|
+
审批通过
|
|
298
|
+
-> approval 触发器:计算剩余欠款(借款 - 报销)
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### 5.3 借款还款管理
|
|
302
|
+
|
|
303
|
+
| 触发器 | 对象 | 时机 | 作用 |
|
|
304
|
+
|--------|------|------|------|
|
|
305
|
+
| 借款单触发器 | 借款单 | beforeUpsert | 借款前校验、自动计算 |
|
|
306
|
+
| 还款记录审批通过更新借款单 | 还款记录 | approval | 审批后回写借款单 |
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
## 六、触发器开发最佳实践
|
|
311
|
+
|
|
312
|
+
### 6.1 代码规范
|
|
313
|
+
|
|
314
|
+
```java
|
|
315
|
+
try {
|
|
316
|
+
CCObject record = (CCObject) data.get("record");
|
|
317
|
+
cs.update(record);
|
|
318
|
+
} catch (Exception e) {
|
|
319
|
+
System.out.println("触发器执行失败:" + e.getMessage());
|
|
320
|
+
throw new Exception("业务校验失败:" + e.getMessage());
|
|
321
|
+
}
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### 6.2 性能优化
|
|
325
|
+
|
|
326
|
+
```java
|
|
327
|
+
// 推荐:字段过滤,只查询需要的字段
|
|
328
|
+
List<CCObject> records = cs.cqueryByFields(
|
|
329
|
+
"Object__c",
|
|
330
|
+
"status__c='active'",
|
|
331
|
+
"id,name,amount__c"
|
|
332
|
+
);
|
|
333
|
+
|
|
334
|
+
// 推荐:批量更新,降低递归风险
|
|
335
|
+
cs.updateLt(records);
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### 6.3 避免递归触发
|
|
339
|
+
|
|
340
|
+
```java
|
|
341
|
+
// 方法 1:使用 updateLt
|
|
342
|
+
cs.updateLt(records);
|
|
343
|
+
|
|
344
|
+
// 方法 2:增加标志位(示例)
|
|
345
|
+
if ("true".equals(System.getProperty("trigger.running"))) {
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
System.setProperty("trigger.running", "true");
|
|
349
|
+
cs.update(record);
|
|
350
|
+
System.setProperty("trigger.running", "false");
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
---
|
|
354
|
+
|
|
355
|
+
## 七、触发器调试与监控
|
|
356
|
+
|
|
357
|
+
### 7.1 日志记录
|
|
358
|
+
|
|
359
|
+
```java
|
|
360
|
+
System.out.println("=== 触发器开始执行 ===");
|
|
361
|
+
System.out.println("对象:" + record.getSObjectName());
|
|
362
|
+
System.out.println("操作:" + data.get("action"));
|
|
363
|
+
System.out.println("记录 ID:" + record.get("id"));
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### 7.2 常见问题排查
|
|
367
|
+
|
|
368
|
+
| 问题 | 可能原因 | 解决方案 |
|
|
369
|
+
|------|----------|----------|
|
|
370
|
+
| 触发器不执行 | 未激活、触发时机不对 | 检查状态与配置 |
|
|
371
|
+
| 递归触发 | 更新操作再次触发触发器 | 使用 `updateLt` 或增加条件判断 |
|
|
372
|
+
| 性能问题 | 查询数据量过大 | 增加查询条件、字段过滤 |
|
|
373
|
+
| 数据不一致 | 触发器执行失败 | 增加异常处理与关键日志 |
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
377
|
+
## 八、总结
|
|
378
|
+
|
|
379
|
+
### 8.1 触发器价值
|
|
380
|
+
1. 自动化:减少人工操作,降低出错率
|
|
381
|
+
2. 一致性:保证数据准确与规则统一执行
|
|
382
|
+
3. 实时性:业务变更立即响应
|
|
383
|
+
4. 灵活性:Java 代码可承载复杂逻辑
|
|
384
|
+
|
|
385
|
+
### 8.2 适用与不适用场景
|
|
386
|
+
|
|
387
|
+
**适合使用触发器:**
|
|
388
|
+
- 需要实时数据联动
|
|
389
|
+
- 核心业务规则校验
|
|
390
|
+
- 跨对象数据同步
|
|
391
|
+
- 审批流程复杂逻辑
|
|
392
|
+
- 自动创建或更新关联记录
|
|
393
|
+
|
|
394
|
+
**不适合使用触发器:**
|
|
395
|
+
- 简单字段默认值(优先配置化能力)
|
|
396
|
+
- 大批量离线数据处理
|
|
397
|
+
- 跨系统集成调用
|
|
398
|
+
- 强交互型前端界面逻辑
|
|
399
|
+
|
|
400
|
+
### 8.3 触发器开发 Checklist
|
|
401
|
+
|
|
402
|
+
- [ ] 本地 `triggers/` 目录仅通过 `cc create` / `cc pull` / `cc pullList` / `cc publish` / `cc delete` 等命令维护,不手造路径、不手改 `config.json` 的 `id`
|
|
403
|
+
- [ ] 明确触发时机(before/after/approval)
|
|
404
|
+
- [ ] 评估并规避递归触发风险
|
|
405
|
+
- [ ] 添加异常处理与关键日志
|
|
406
|
+
- [ ] 覆盖边界条件测试
|
|
407
|
+
- [ ] 完成大数据量场景性能测试
|
|
408
|
+
|
|
409
|
+
---
|
|
410
|
+
|
|
411
|
+
## 附录:25 个生产触发器清单
|
|
412
|
+
|
|
413
|
+
| # | 名称 | 对象 | 时机 | 状态 |
|
|
414
|
+
|---|------|------|------|------|
|
|
415
|
+
| 1 | 个人业绩/部门业绩赋值 | 对外付款 | beforeUpsert | ✅ |
|
|
416
|
+
| 2 | 个人业绩/部门业绩赋值 | 费用报销 | beforeUpsert | ❌ |
|
|
417
|
+
| 3 | 本部业绩统计 | 本部业绩统计 | beforeUpsert | ✅ |
|
|
418
|
+
| 4 | 更新拆分审批状态 | 预算 | approval | ✅ |
|
|
419
|
+
| 5 | 订单审批判断 | 订单 | approval | ✅ |
|
|
420
|
+
| 6 | 根据净业绩拆分生成净业绩拆分回款 | 回款明细 | afterInsert | ✅ |
|
|
421
|
+
| 7 | 金额汇总到收款计划 | 回款明细 | afterUpsert | ✅ |
|
|
422
|
+
| 8 | 回款明细删除 | 回款明细 | afterDelete | ❌ |
|
|
423
|
+
| 9 | 计算产研成本/净业绩 | 预算 | beforeUpsert | ✅ |
|
|
424
|
+
| 10 | 保证金回款记录 | 概算 | afterUpdate | ✅ |
|
|
425
|
+
| 11 | 校验金额累计是否超预算 | 净业绩拆分 | afterUpsert | ✅ |
|
|
426
|
+
| 12 | 更新部门业绩字段 | 部门业绩 | afterUpsert | ✅ |
|
|
427
|
+
| 13 | 汇总部门资金池 | 部门业绩 | afterUpdate | ✅ |
|
|
428
|
+
| 14 | 编辑更新部门业绩 | 净业绩拆分回款 | beforeUpsert | ✅ |
|
|
429
|
+
| 15 | 生成部门/个人业绩 | 净业绩拆分 | beforeUpsert | ✅ |
|
|
430
|
+
| 16 | 更新回款明细 | 回款明细 | afterUpsert | ✅ |
|
|
431
|
+
| 17 | 新建自动拆分/审批通过自动生成回款 | 预算 | afterUpsert | ✅ |
|
|
432
|
+
| 18 | 提交审批验证金额 | 对外付款 | approval | ❌ |
|
|
433
|
+
| 19 | 还款记录审批通过更新借款单 | 还款记录 | approval | ✅ |
|
|
434
|
+
| 20 | 审批通过计算剩余欠款 | 费用报销 | approval | ✅ |
|
|
435
|
+
| 21 | 借款单触发器 | 借款单 | beforeUpsert | ✅ |
|
|
436
|
+
| 22 | 创建编辑项目任务时判断 | 项目任务 | beforeUpsert | ✅ |
|
|
437
|
+
| 23 | 任务派工工时限制 | 项目任务 | afterUpsert | ✅ |
|
|
438
|
+
| 24 | 测试 AI 代码生成 | 客户 | beforeInsert | ❌ |
|
|
439
|
+
| 25 | 验证审批时校验预算 | 费用报销 | approval | ❌ |
|
|
440
|
+
|
|
441
|
+
文档生成时间:2026-03-24
|
|
442
|
+
基于 CloudCC 生产环境 25 个触发器实例分析
|
package/src/triggers/get.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
const { getPackageJson } = require("../../utils/config")
|
|
2
2
|
const { postClass } = require("../../utils/http")
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
/**
|
|
5
|
+
* cc get triggers <listQueryJson> [projectPath]
|
|
6
|
+
* @param {string[]} argvs
|
|
7
|
+
*/
|
|
8
|
+
async function get(argvs, isMcp = false) {
|
|
9
|
+
let body = JSON.parse(decodeURI(argvs[2]))
|
|
10
|
+
let config = await getPackageJson(argvs[3]);
|
|
7
11
|
let res = await postClass(config.setupSvc + "/api/triggerSetup/getTriggerByCondition", body, config.accessToken)
|
|
8
12
|
if (res.result) {
|
|
9
13
|
const simpleList = (res.data.list || []).map(item => ({
|
package/src/triggers/index.js
CHANGED
|
@@ -7,11 +7,8 @@ cc.pullList = require("./pullList")
|
|
|
7
7
|
cc.detail = require("./detail")
|
|
8
8
|
cc.doc = require("./doc")
|
|
9
9
|
cc.delete = require("./delete")
|
|
10
|
+
|
|
10
11
|
function Classes(action, argvs) {
|
|
11
|
-
if (action === "detail") {
|
|
12
|
-
cc[action](argvs[2], argvs[3]);
|
|
13
|
-
return;
|
|
14
|
-
}
|
|
15
12
|
cc[action](argvs)
|
|
16
13
|
}
|
|
17
14
|
|
package/src/triggers/pullList.js
CHANGED
|
@@ -7,19 +7,19 @@ const { getPackageJson } = require("../../utils/config");
|
|
|
7
7
|
const { postClass } = require("../../utils/http");
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
11
|
-
* @param
|
|
10
|
+
* cc pullList triggers <id> <projectPath>
|
|
11
|
+
* @param {string[]} argvs
|
|
12
12
|
*/
|
|
13
|
-
async function pullList(
|
|
14
|
-
const body = { id:
|
|
15
|
-
let config = await getPackageJson(
|
|
13
|
+
async function pullList(argvs, isMcp = false) {
|
|
14
|
+
const body = { id: argvs[2] };
|
|
15
|
+
let config = await getPackageJson(argvs[3]);
|
|
16
16
|
const res = await postClass(config.setupSvc + "/api/trigger/newobjtrigger", body, config.accessToken);
|
|
17
17
|
try {
|
|
18
18
|
const data = res.data;
|
|
19
19
|
const targetObj = data.targetObj;
|
|
20
20
|
const trigger = data.trigger;
|
|
21
21
|
const triggerName = trigger.name;
|
|
22
|
-
const folderPath = path.join(
|
|
22
|
+
const folderPath = path.join(argvs[3], `triggers/${targetObj.schemetableName.toLowerCase()}/${trigger.name}`);
|
|
23
23
|
if (!fs.existsSync(folderPath)) {
|
|
24
24
|
fs.mkdirSync(folderPath, { recursive: true });
|
|
25
25
|
}
|
|
@@ -41,7 +41,7 @@ async function pullList(args, isMcp = false) {
|
|
|
41
41
|
console.log("true");
|
|
42
42
|
}
|
|
43
43
|
} catch (e) {
|
|
44
|
-
console.error(`Error occurred while processing trigger id: ${
|
|
44
|
+
console.error(`Error occurred while processing trigger id: ${argvs[2]}, message: ${e.message}${JSON.stringify(res)}}`);
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 创建用户
|
|
5
|
+
* 用法:cc create user <path> <userName> <profileId> [email]
|
|
6
|
+
* @param {Array} argvs - 命令行参数数组
|
|
7
|
+
* @returns {Promise<Object>} 创建结果
|
|
8
|
+
*/
|
|
9
|
+
async function create(argvs) {
|
|
10
|
+
try {
|
|
11
|
+
// 命令行参数格式:cc create user <path> <userName> <profileId> [email]
|
|
12
|
+
const projectPath = argvs[2] || process.cwd();
|
|
13
|
+
const userName = argvs[3];
|
|
14
|
+
const profileId = argvs[4];
|
|
15
|
+
const email = argvs[5] || '';
|
|
16
|
+
|
|
17
|
+
if (!userName) {
|
|
18
|
+
console.error();
|
|
19
|
+
console.error(chalk.red('Error: 缺少用户名称'));
|
|
20
|
+
console.error('用法: cc create user <path> <userName> <profileId> [email]');
|
|
21
|
+
console.error('示例:');
|
|
22
|
+
console.error(' cc create user . "张三" a0I9D000000XXXXUAI');
|
|
23
|
+
console.error(' cc create user . "李四" a0I9D000000XXXXUAI "lisi@example.com"');
|
|
24
|
+
console.error();
|
|
25
|
+
throw new Error('缺少必需参数: userName');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (!profileId) {
|
|
29
|
+
console.error();
|
|
30
|
+
console.error(chalk.red('Error: 缺少简档 ID'));
|
|
31
|
+
console.error('用法: cc create user <path> <userName> <profileId> [email]');
|
|
32
|
+
console.error();
|
|
33
|
+
throw new Error('缺少必需参数: profileId');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
console.error();
|
|
37
|
+
console.error(chalk.green(`Creating user (${userName}), please wait...`));
|
|
38
|
+
console.error();
|
|
39
|
+
|
|
40
|
+
// TODO: 实现创建用户的 API 调用
|
|
41
|
+
console.error(chalk.yellow('创建用户功能待实现'));
|
|
42
|
+
|
|
43
|
+
} catch (error) {
|
|
44
|
+
console.error();
|
|
45
|
+
console.error(chalk.red("用户创建失败:"), error);
|
|
46
|
+
throw error;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
module.exports = create;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
const chalk = require("chalk");
|
|
2
|
+
const { postClass } = require("../../utils/http");
|
|
3
|
+
const { getPackageJson } = require("../../utils/config");
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 删除用户
|
|
7
|
+
* 用法:cc delete user <projectPath> <userId>
|
|
8
|
+
*/
|
|
9
|
+
async function remove(argvs) {
|
|
10
|
+
try {
|
|
11
|
+
const projectPath = argvs[2] || process.cwd();
|
|
12
|
+
const userId = argvs[3];
|
|
13
|
+
|
|
14
|
+
if (!userId) {
|
|
15
|
+
console.error();
|
|
16
|
+
console.error(chalk.red("Error: 缺少用户 ID"));
|
|
17
|
+
console.error(chalk.yellow("用法: cc delete user <projectPath> <userId>"));
|
|
18
|
+
console.error();
|
|
19
|
+
throw new Error("缺少必需参数: userId");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const config = await getPackageJson(projectPath);
|
|
23
|
+
if (!config || !config.accessToken) {
|
|
24
|
+
console.error();
|
|
25
|
+
console.error(chalk.red("Error: 配置未找到或 accessToken 缺失"));
|
|
26
|
+
console.error();
|
|
27
|
+
throw new Error("配置未找到或 accessToken 缺失");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
console.error();
|
|
31
|
+
console.error(chalk.green(`Deleting user (${userId}), please wait...`));
|
|
32
|
+
console.error();
|
|
33
|
+
|
|
34
|
+
const result = await postClass(
|
|
35
|
+
config.setupSvc + "/api/user/deleteUser",
|
|
36
|
+
{ id: userId },
|
|
37
|
+
config.accessToken
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
if (result && result.result) {
|
|
41
|
+
console.error();
|
|
42
|
+
console.error(chalk.green("Success! User deleted."));
|
|
43
|
+
console.error();
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const msg = result && (result.returnInfo || result.message) ? (result.returnInfo || result.message) : "Unknown error";
|
|
48
|
+
console.error();
|
|
49
|
+
console.error(chalk.red("Error: " + msg));
|
|
50
|
+
console.error();
|
|
51
|
+
throw new Error("Delete User Failed: " + msg);
|
|
52
|
+
} catch (error) {
|
|
53
|
+
console.error();
|
|
54
|
+
console.error(chalk.red("用户删除失败:"), error);
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
module.exports = remove;
|
package/src/user/doc.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* user 文档入口:正文均在 `docs/` 目录。
|
|
3
|
+
*/
|
|
4
|
+
const fs = require("fs");
|
|
5
|
+
const path = require("path");
|
|
6
|
+
|
|
7
|
+
const DOCS_DIR = path.join(__dirname, "docs");
|
|
8
|
+
|
|
9
|
+
function readDocFile(basename) {
|
|
10
|
+
return fs.readFileSync(path.join(DOCS_DIR, `${basename}.md`), "utf8");
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** 介绍文档:用户能力、类型与入口 */
|
|
14
|
+
function getIntroductionDoc() {
|
|
15
|
+
return readDocFile("introduction");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** 开发指导:CLI 创建/查询/删除等 */
|
|
19
|
+
function getDevGuideDoc() {
|
|
20
|
+
return readDocFile("devguide");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* cc doc user <introduction|devguide>
|
|
25
|
+
* @param {string[]} argvs [doc, type, introduction|devguide, ...]
|
|
26
|
+
*/
|
|
27
|
+
function doc(argvs) {
|
|
28
|
+
const subType = argvs[2];
|
|
29
|
+
const key = String(subType || "").trim().toLowerCase();
|
|
30
|
+
if (!key) {
|
|
31
|
+
throw new Error("cc doc user 需要子命令:introduction 或 devguide");
|
|
32
|
+
}
|
|
33
|
+
if (key === "introduction") {
|
|
34
|
+
const content = getIntroductionDoc();
|
|
35
|
+
console.log(content);
|
|
36
|
+
return content;
|
|
37
|
+
}
|
|
38
|
+
if (key === "devguide") {
|
|
39
|
+
const content = getDevGuideDoc();
|
|
40
|
+
console.log(content);
|
|
41
|
+
return content;
|
|
42
|
+
}
|
|
43
|
+
throw new Error(`doc 不支持的子命令: ${subType},请使用 introduction 或 devguide`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
module.exports = doc;
|