cloudcc-cli 2.3.8 → 2.4.0

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 (66) hide show
  1. package/.cursor/skills/{cloudcc-cli-dev → dev-guide}/SKILL.md +5 -1
  2. package/README.md +82 -1
  3. package/bin/cc.js +2 -1
  4. package/bin/index.js +1 -0
  5. package/cloudcc-dev-skill/SKILL.md +31 -8
  6. package/cloudcc-dev-skill/cloudcc-dev-html.md +42 -0
  7. package/cloudcc-dev-skill/config.json +2 -2
  8. package/mcp/index.js +27 -3
  9. package/mcp/tools/JSP Migrator/handler.js +51 -866
  10. package/mcp/tools/Object Creator/handler.js +14 -4
  11. package/mcp/tools/Object Fields Creator/handler.js +149 -3
  12. package/package.json +1 -1
  13. package/src/classes/docs/devguide.md +758 -364
  14. package/src/classes/docs/introduction.md +279 -143
  15. package/src/fields/buildFieldData.js +692 -0
  16. package/src/fields/create.js +10 -170
  17. package/src/fields/detail.js +37 -0
  18. package/src/fields/docs/devguide.md +168 -44
  19. package/src/fields/docs/introduction.md +2 -0
  20. package/src/fields/fields/A.js +3 -2
  21. package/src/fields/fields/AD.js +4 -2
  22. package/src/fields/fields/B.js +8 -5
  23. package/src/fields/fields/C.js +13 -5
  24. package/src/fields/fields/D.js +4 -4
  25. package/src/fields/fields/E.js +10 -5
  26. package/src/fields/fields/ENC.js +27 -8
  27. package/src/fields/fields/ENCD.js +27 -8
  28. package/src/fields/fields/F.js +4 -4
  29. package/src/fields/fields/FL.js +8 -4
  30. package/src/fields/fields/H.js +4 -4
  31. package/src/fields/fields/IMG.js +23 -5
  32. package/src/fields/fields/J.js +21 -6
  33. package/src/fields/fields/L.js +32 -8
  34. package/src/fields/fields/LT.js +23 -6
  35. package/src/fields/fields/M.js +2 -2
  36. package/src/fields/fields/MR.js +2 -2
  37. package/src/fields/fields/N.js +31 -8
  38. package/src/fields/fields/P.js +13 -5
  39. package/src/fields/fields/Q.js +42 -12
  40. package/src/fields/fields/S.js +19 -7
  41. package/src/fields/fields/SCORE.js +9 -4
  42. package/src/fields/fields/T.js +4 -4
  43. package/src/fields/fields/U.js +18 -5
  44. package/src/fields/fields/X.js +20 -6
  45. package/src/fields/fields/Y.js +17 -4
  46. package/src/fields/index.js +2 -0
  47. package/src/fields/update.js +148 -0
  48. package/src/jsp/analyze.js +17 -0
  49. package/src/jsp/doc.js +18 -0
  50. package/src/jsp/docs/devguide.md +111 -0
  51. package/src/jsp/docs/introduction.md +50 -0
  52. package/src/jsp/docs.js +21 -0
  53. package/src/jsp/index.js +14 -0
  54. package/src/jsp/migration.js +871 -0
  55. package/src/jsp/split.js +17 -0
  56. package/src/object/create.js +36 -10
  57. package/src/object/docs/devguide.md +6 -3
  58. package/src/project/docs/devguide.md +1 -1
  59. package/src/timer/docs/devguide.md +849 -400
  60. package/src/timer/docs/introduction.md +343 -231
  61. package/src/triggers/docs/devguide.md +929 -352
  62. package/src/triggers/docs/introduction.md +640 -369
  63. package/src/version/listModuleCommands.js +6 -0
  64. package/test/fields.cli.test.js +3 -1
  65. package/test/jsp.cli.test.js +70 -0
  66. package/test/object.cli.test.js +9 -1
@@ -1,554 +1,1003 @@
1
- # CloudCC 定时作业完全指南
1
+ # CloudCC 定时器类 AI 开发规范
2
2
 
3
- > 定时作业(Scheduled Jobs)是 CloudCC CRM 系统中的后台任务调度机制,用于在指定时间自动执行业务逻辑。
3
+ ## 1. 文档目的
4
4
 
5
- ---
5
+ 本文用于约束 AI 在当前 CloudCC 项目中编写定时器类时的分析方式、实现方式、SDK 选型和输出要求。
6
6
 
7
- ## CLI 与本地文件(必读)
7
+ 目标不是让 AI “能写出代码”即可,而是让 AI 写出的定时器类:
8
8
 
9
- 本仓库中的**定时类**(与定时作业绑定的 Java 类)通过 **cloudcc-cli** 与平台同步,本地目录为 **`schedule/<类名>/`**(内含 `*.java` 与 `config.json`),源码中的 `// @SOURCE_CONTENT_START` … `// @SOURCE_CONTENT_END` 与发布、拉取逻辑一致。**必须通过下列命令** 完成新建目录、发布、拉取与删除;不要手工新建 `schedule/` 子目录、不要整包复制其他项目的定时类、不要私自篡改 `config.json` 中的 `id` 或版本字段。
9
+ - 适合放在定时器而不是触发器或页面脚本中
10
+ - 符合 CloudCC 官方 SDK 用法
11
+ - 符合 `cloudcc-cli` 的目录和发布约束
12
+ - 符合当前项目的主流实现模式
13
+ - 具备幂等性、可观测性、批量处理意识和时区安全意识
10
14
 
11
- **允许的做法**:在 CLI 已生成的主类中,仅在上述 SOURCE 标记之间编写业务逻辑;与云端列表、详情、拉取、删除、发布相关的操作一律走命令。
15
+ ## 2. 依据来源
12
16
 
13
- 执行命令前请确认:已完成 `cloudcc doc project devguide` 中的环境初始化,项目根目录配置可用且包含 `accessToken`。
17
+ - 官方 SDK 文档提供 `CCObject`、`CCService`、`SendEmail`、`DevLogger`、`TimeUtil` 等核心 API 依据
18
+ - `2-timer-classes-analysis.md` 提供当前项目定时器使用场景和共性模式
19
+ - `timer devguide` 提供本地目录、CLI、发布和 SOURCE 区域约束
14
20
 
15
- ### 命令总览(以代码实现为准)
21
+ ## 3. 先判断:是不是应该写成定时器类
16
22
 
17
- ```bash
18
- cloudcc create timer <name>
19
- cloudcc publish timer <name>
20
- cloudcc pull timer <name>
21
- cloudcc get timer [listQueryJson] [projectPath]
22
- cloudcc detail timer <name>
23
- cloudcc detail timer "" <id>
24
- cloudcc pullList timer <id> <projectPath>
25
- cloudcc delete timer <nameOrId> [projectPath]
26
- cloudcc doc timer <introduction|devguide>
27
- ```
23
+ AI 在动手写代码前,必须先判断需求是否真的适合用定时器类。
28
24
 
29
- 参数约定:
25
+ ### 3.1 适合定时器类的情况
30
26
 
31
- - `name`:定时类名,与 `schedule/<name>/` 目录名一致。
32
- - `listQueryJson`:可选;列表查询 JSON 经 `encodeURI(JSON.stringify(...))` 编码后传入;不传则使用默认分页参数。
33
- - `projectPath`:项目根路径,可选。
34
- - `id`:线上定时类 ID。`detail` 仅查服务器时:`cloudcc detail timer "" <id>`。`pullList` 必填。
35
- - `nameOrId`:本地目录名或类 ID;若本地 `config.json` 含 `id`,删除时优先使用该 ID。
27
+ - 任务按时间触发,而不是按单条记录实时触发
28
+ - 需要每天、每周、每月、月初、月末执行
29
+ - 需要批量扫描一批记录并统一处理
30
+ - 需要失败补偿、周期重试或后台巡检
31
+ - 需要构建底表、看板、台账、报表支撑数据
32
+ - 需要在满足条件后自动提醒、自动推进、自动同步
36
33
 
37
- ### 命令作用摘要
34
+ ### 3.2 不适合定时器类的情况
38
35
 
39
- | 命令 | 作用 |
40
- |------|------|
41
- | `create` | 在 `schedule/<name>/` 生成继承 `CCSchedule` 的 Java 模板与 `config.json` |
42
- | `publish` | 将 SOURCE 区域提交到服务器;首次成功后可写回 `config.json` 的 `id` |
43
- | `pull` | 按本地 `id` 拉取远端源码,覆盖主类中 SOURCE 区域(需已发布) |
44
- | `get` | 查询线上定时类列表(JSON 输出) |
45
- | `detail` | 按类名优先读本地;或仅按 `id` 读服务器 |
46
- | `pullList` | 按类 `id` 将线上定时类落到指定项目的 `schedule/<类名>/` |
47
- | `delete` | 删除服务器上的定时类 |
48
- | `doc` | 输出模块文档;`devguide` 含附录后端 Java SDK 速查 |
36
+ - 记录保存时必须立刻校验或立刻拦截
37
+ - 单笔数据变化后必须在同一事务里马上联动
38
+ - 高度依赖前端交互、人工确认、页面反馈
39
+ - 只是一次性临时数据处理,不需要长期调度
49
40
 
50
- ### 推荐操作顺序
41
+ ### 3.3 当前项目中定时器的六大主类型
51
42
 
52
- ```bash
53
- # 1) 查看线上已有定时类(可选)
54
- cloudcc get timer
43
+ 根据现有项目总结,AI 应优先将需求归入以下类型之一:
55
44
 
56
- # 2) 新建定时类(仅通过 create 生成目录与模板)
57
- cloudcc create timer MySchedule
45
+ - 提醒通知类
46
+ - 同步推送集成类
47
+ - 刷新更新修正类
48
+ - 报表底表支撑类
49
+ - 自动生成派生类
50
+ - 权限共享治理类
58
51
 
59
- # 3) 编辑 schedule/MySchedule/MySchedule.java 中 SOURCE 区域后发布
60
- cloudcc publish timer MySchedule
52
+ 如果需求明显不属于上述类型,AI 应重新评估是否真的应该落到定时器类。
61
53
 
62
- # 4) 与服务器对齐时拉取
63
- cloudcc pull timer MySchedule
54
+ ## 4. 文件与交付规范
64
55
 
65
- # 5) 按已知线上 ID 拉到指定项目
66
- cloudcc pullList timer <线上类ID> <projectPath>
56
+ 这是 AI 必须遵守的第一层约束。
67
57
 
68
- # 6) 删除
69
- cloudcc delete timer MySchedule
70
- ```
58
+ ### 4.1 目录与文件来源
71
59
 
72
- ### 文档子命令
60
+ - 定时器目录必须位于 `schedule/<类名>/`
61
+ - 每个定时器目录包含主类 `*.java` 和 `config.json`
62
+ - 定时器目录必须通过 `cloudcc create timer <name>` 创建
73
63
 
74
- ```bash
75
- cloudcc doc timer introduction
76
- cloudcc doc timer devguide
77
- ```
64
+ ### 4.2 AI 不得做的事情
78
65
 
79
- 仅支持 `introduction` 与 `devguide`。
66
+ - 不要手工新建 `schedule/` 子目录
67
+ - 不要整包复制其他项目的定时器目录
68
+ - 不要手工修改 `config.json` 中的 `id` 或版本字段
69
+ - 不要在 `// @SOURCE_CONTENT_START` 与 `// @SOURCE_CONTENT_END` 之外写业务逻辑
80
70
 
81
- ---
71
+ ### 4.3 AI 允许做的事情
82
72
 
83
- ## 📌 什么是定时作业?
73
+ - 只在 CLI 生成的主类 SOURCE 区域内实现业务逻辑
74
+ - 保持 `package schedule.<类名>;` 与目录名一致
75
+ - 让类继承 `CCSchedule`
76
+ - 构造方法名与类名一致
84
77
 
85
- 定时作业是一种**自动化任务调度系统**,允许你:
78
+ ## 5. AI 编写定时器类的核心原则
86
79
 
87
- - 设定任务的执行时间(如每天上午 8 点、每周一、每月 1 号)
88
- - 关联自定义的业务逻辑代码(定时类)
89
- - 系统自动在指定时间触发执行,无需人工干预
80
+ ### 5.1 先分析,再编码
90
81
 
91
- **类比理解:** 就像手机的闹钟功能,但触发的是业务代码而不是铃声。
82
+ AI 在写代码前,至少应明确以下内容:
92
83
 
93
- ---
84
+ - 主对象是什么
85
+ - 关联对象是什么
86
+ - 触发频率是什么
87
+ - 筛选条件是什么
88
+ - 执行动作是什么
89
+ - 是否存在重复执行风险
90
+ - 是否需要批量处理
91
+ - 是否需要通知
92
+ - 是否需要日志
93
+ - 是否需要失败补偿
94
94
 
95
- ## 🎯 定时作业的主要作用
95
+ ### 5.2 优先配置化,不要硬编码
96
96
 
97
- ### 1. 自动化重复性任务
97
+ 以下信息如果未来可能变化,优先配置化,不要直接写死在代码里:
98
98
 
99
- 将人工需要定期执行的操作自动化,例如:
99
+ - 提醒天数
100
+ - 阈值条件
101
+ - 模版 ID
102
+ - 收件人范围
103
+ - 开关标记
104
+ - 外部接口地址或行为参数
100
105
 
101
- - 每天发送收款提醒邮件
102
- - 每周生成销售报表
103
- - 每月清理过期数据
106
+ 如果必须读取配置,优先使用官方 SDK 的自定义设置能力。
104
107
 
105
- ### 2. 时间敏感的业务逻辑
108
+ ### 5.3 必须考虑幂等性
106
109
 
107
- 在特定时间点必须执行的操作:
110
+ 定时器会重复执行,因此 AI 生成代码时必须避免“重复跑一次就重复造数据”。
108
111
 
109
- - 合同到期前 30 天提醒续约
110
- - 客户生日当天发送祝福
111
- - 季度末自动生成业绩报告
112
+ 常见幂等策略包括:
112
113
 
113
- ### 3. 后台批处理
114
+ - 先判断是否已处理,再执行
115
+ - 通过状态位、标记位、执行日期控制重复执行
116
+ - 通过业务唯一键判断是否已存在目标记录
117
+ - 通过补偿表或日志表判断是否已成功处理
114
118
 
115
- 处理大量数据的离线任务:
119
+ ### 5.4 必须考虑批量处理
116
120
 
117
- - 夜间同步外部系统数据
118
- - 批量更新客户状态
119
- - 计算佣金和业绩
121
+ 定时器天然面向批量数据。AI 不能默认按“单笔页面逻辑”写法来写。
120
122
 
121
- ### 4. 监控与预警
123
+ 应优先考虑:
122
124
 
123
- 持续监控系统状态并触发告警:
125
+ - 分页查询
126
+ - 分批写入
127
+ - 减少循环内查询
128
+ - 减少循环内单条更新
124
129
 
125
- - 客户超过 15 天未联系 → 提醒销售跟进
126
- - 收款计划逾期 → 通知财务人员
127
- - 资产即将失效 → 自动生成业务机会
130
+ ### 5.5 必须考虑可观测性
128
131
 
129
- ---
132
+ AI 生成的定时器类至少要做到:
130
133
 
131
- ## 💡 为什么要用定时作业?
134
+ - 关键路径有日志
135
+ - 异常可定位
136
+ - 批处理数量可观察
137
+ - 失败信息可追踪
132
138
 
133
- ### 对比人工操作
139
+ ### 5.6 必须考虑时区安全
134
140
 
135
- | 维度 | 人工操作 | 定时作业 |
136
- |------|----------|----------|
137
- | **准确性** | 可能遗忘、出错 | 100% 准时执行 |
138
- | **效率** | 耗时耗力 | 自动执行,零人力成本 |
139
- | **一致性** | 不同人操作可能有差异 | 每次执行逻辑一致 |
140
- | **可扩展性** | 任务多了忙不过来 | 可同时运行多个任务 |
141
- | **可追溯** | 难以追踪谁什么时候做的 | 完整执行日志 |
141
+ 涉及日期比较、日期格式化、写库时间时,不能默认依赖本地时区。
142
142
 
143
- ### 核心价值
143
+ 应优先使用 `TimeUtil`。
144
144
 
145
- ```
146
- 定时作业 = 自动化 + 准时性 + 可追溯
147
- ```
145
+ ## 6. 官方 SDK 详细速查
148
146
 
149
- ---
147
+ - 本节优先给出方法签名、入参、返回值和使用场景
148
+ - 表中“必填”信息来源于官方文档
149
+ - 如果某个批量方法在当前项目里很常见,但官方页面没有展开签名,会单独标注“项目约定”
150
+ - 当前项目大量定时器直接调用 `this.cquery(...)`、`this.cqlQuery(...)`、`this.insert(...)` 等 inherited 方法;AI 在理解参数语义时,应以官方 `CCService` 版本为准
150
151
 
151
- ## 🔧 定时作业能解决哪些问题?
152
+ ### 6.1 `CCObject`
152
153
 
153
- ### 问题 1:遗忘和延误
154
+ 类定位:
154
155
 
155
- **场景:** 销售忘记跟进客户,导致商机流失
156
+ - CloudCC 对象封装类
157
+ - 用于承载新增、更新、删除、共享等对象数据
156
158
 
157
- **解决:** 设置定时作业检测客户最后联系时间,超过 15 天自动提醒
159
+ #### 构造方法 1
158
160
 
159
- ```
160
- ┌─────────────────┐ ┌──────────────┐ ┌─────────────────┐
161
- │ 客户最后联系时间 │ → │ 定时作业检测 │ → │ 创建跟进活动 │
162
- │ > 15 天 │ │ (每天 8:00) │ │ 并通知销售 │
163
- └─────────────────┘ └──────────────┘ └─────────────────┘
161
+ ```java
162
+ public CCObject()
164
163
  ```
165
164
 
166
- ### 问题 2:重复劳动效率低
165
+ 说明:
167
166
 
168
- **场景:** 财务人员每天手动发送收款提醒,耗时 2 小时
167
+ - 官方提供默认构造
168
+ - 在当前项目定时器中较少单独使用
169
169
 
170
- **解决:** 定时作业自动扫描逾期收款计划,批量发送邮件
170
+ #### 构造方法 2
171
171
 
172
- ```
173
- 人工方式:每天 2 小时 × 250 工作日 = 500 小时/年
174
- 定时作业:配置 1 次,自动执行,0 小时/年
175
- 节省:500 小时/年 ≈ 62 个工作日
172
+ ```java
173
+ public CCObject(String ccobj)
176
174
  ```
177
175
 
178
- ### 问题 3:跨系统数据同步
176
+ 参数说明:
179
177
 
180
- **场景:** CRM ERP 系统数据需要保持一致
178
+ | 参数 | 类型 | 必填 | 说明 |
179
+ | --- | --- | --- | --- |
180
+ | `ccobj` | `String` | 是 | 对象 API 名 |
181
181
 
182
- **解决:** 定时作业每晚同步两个系统的数据
182
+ 返回:
183
183
 
184
- ```
185
- ┌──────────┐ ┌──────────────┐ ┌──────────┐
186
- │ CRM │ ←─────→ │ 定时作业同步 │ ←─────→ │ ERP │
187
- │ 客户数据 │ 2:00 │ (每日凌晨) │ 2:30 │ 客户数据 │
188
- └──────────┘ └──────────────┘ └──────────┘
189
- ```
184
+ - `CCObject` 实例
190
185
 
191
- ### 问题 4:报表生成和分发
186
+ AI 使用要求:
192
187
 
193
- **场景:** 管理层需要定期查看各类报表
188
+ - 新增普通记录时优先用这个构造器
189
+ - `ccobj` 必须写对象 API 名,不要写对象标签名
194
190
 
195
- **解决:** 定时作业自动生成报表并邮件发送给相关人员
191
+ #### 构造方法 3
196
192
 
197
- ```
198
- 定时触发 查询数据 生成报表 → 发送邮件 → 完成
199
-
200
- 每周一 9:00
193
+ ```java
194
+ public CCObject(String ccobj, String isShared)
201
195
  ```
202
196
 
203
- ---
197
+ 参数说明:
204
198
 
205
- ## 📚 典型业务场景
199
+ | 参数 | 类型 | 必填 | 说明 |
200
+ | --- | --- | --- | --- |
201
+ | `ccobj` | `String` | 是 | 对象 API 名 |
202
+ | `isShared` | `String` | 是 | 共享标识,官方建议使用 `CCObject.IS_SHARED` |
206
203
 
207
- ### 场景 1:销售管理
204
+ 返回:
208
205
 
209
- | 场景 | 触发条件 | 执行动作 |
210
- |------|----------|----------|
211
- | 线索分配 | 新线索创建后 24 小时未分配 | 自动分配给销售主管 |
212
- | 客户跟进提醒 | 客户最后联系时间 > 15 天 | 创建跟进活动并通知销售 |
213
- | 商机推进提醒 | 商机停留当前阶段 > 30 天 | 提醒销售经理介入 |
214
- | 业绩统计 | 每日 23:00 | 计算当日业绩并更新报表 |
206
+ - `CCObject` 实例
215
207
 
216
- ### 场景 2:客户服务
208
+ AI 使用要求:
217
209
 
218
- | 场景 | 触发条件 | 执行动作 |
219
- |------|----------|----------|
220
- | 服务到期提醒 | 服务合同到期前 30 天 | 发送续约提醒邮件 |
221
- | 客户满意度调查 | 服务完成后 7 天 | 发送满意度调查问卷 |
222
- | 生日祝福 | 客户生日当天 | 发送祝福短信/邮件 |
223
- | 投诉升级 | 投诉 48 小时未处理 | 自动升级至上级主管 |
210
+ - 仅在共享表对象场景使用
211
+ - 不要自己发明共享标识字符串,优先使用 `CCObject.IS_SHARED`
224
212
 
225
- ### 场景 3:财务管理
213
+ #### 常用对象方法
226
214
 
227
- | 场景 | 触发条件 | 执行动作 |
228
- |------|----------|----------|
229
- | 收款提醒 | 收款计划日期前 7 天 | 邮件通知客户和财务 |
230
- | 逾期通知 | 收款计划逾期 1 天 | 发送逾期通知并标记 |
231
- | 发票生成 | 确认收款后 | 自动生成并发送发票 |
232
- | 佣金计算 | 每月 1 日 | 计算销售佣金并生成报表 |
215
+ 官方文档列出:
233
216
 
234
- ### 场景 4:数据维护
217
+ - `getUserId()`
218
+ - `getOrgId()`
219
+ - `getRoleId()`
235
220
 
236
- | 场景 | 触发条件 | 执行动作 |
237
- |------|----------|----------|
238
- | 数据清理 | 每周日 3:00 | 清理临时表和过期日志 |
239
- | 数据备份 | 每日 1:00 | 备份关键数据到指定位置 |
240
- | 数据同步 | 每日 2:00 | 同步 CRM 与外部系统数据 |
241
- | 索引优化 | 每月 1 日 4:00 | 重建数据库索引提升性能 |
221
+ AI 使用要求:
242
222
 
243
- ### 场景 5:营销自动化
223
+ - 如果需要读取当前对象上下文中的用户、组织、角色信息,可使用这些方法
224
+ - 定时器的主要业务数据写入仍以 `put` 为主
244
225
 
245
- | 场景 | 触发条件 | 执行动作 |
246
- |------|----------|----------|
247
- | 营销活动提醒 | 活动开始前 3 天 | 通知参与人员准备 |
248
- | 线索培育 | 线索创建后第 3/7/14 天 | 发送培育邮件 |
249
- | 活动效果分析 | 活动结束后 1 天 | 生成效果分析报告 |
250
- | 客户分群更新 | 每日 5:00 | 根据行为更新客户分群 |
226
+ ### 6.2 `CCService`
251
227
 
252
- ---
228
+ 类定位:
253
229
 
254
- ## ⚙️ 技术实现
230
+ - CloudCC 核心对象服务类
231
+ - 提供对象增删改查、自定义设置、共享删除等能力
255
232
 
256
- ### 定时作业结构
233
+ #### 构造函数
257
234
 
235
+ ```java
236
+ public CCService(UserInfo userInfo)
258
237
  ```
259
- ┌─────────────────────────────────────────────────────────┐
260
- │ 定时作业 (Schedule Job) │
261
- ├─────────────────────────────────────────────────────────┤
262
- │ 基本信息 │
263
- │ ├── 名称 (name) │
264
- │ ├── ID (id) │
265
- │ └── 描述 (description) │
266
- ├─────────────────────────────────────────────────────────┤
267
- │ 调度配置 │
268
- │ ├── 频率类型 (frequency): daily/weekly/monthly │
269
- │ ├── 执行时间 (executetime): 08:00 │
270
- │ ├── 星期 (weeks): Mon,Tues,Wed,Thur,Fri │
271
- │ ├── 开始日期 (startdate): 2024-01-01 │
272
- │ └── 结束日期 (enddate): 2024-12-31 │
273
- ├─────────────────────────────────────────────────────────┤
274
- │ 关联程序 │
275
- │ ├── 程序 ID (prgid) │
276
- │ └── 定时类 (className): com.xxx.scheduler.MyJob │
277
- └─────────────────────────────────────────────────────────┘
238
+
239
+ 参数说明:
240
+
241
+ | 参数 | 类型 | 必填 | 说明 |
242
+ | --- | --- | --- | --- |
243
+ | `userInfo` | `UserInfo` | 是 | 当前用户对象 |
244
+
245
+ 返回:
246
+
247
+ - `CCService` 实例
248
+
249
+ AI 使用要求:
250
+
251
+ - 定时器中默认先初始化 `CCService cs = new CCService(userInfo);`
252
+ - 除非使用 `CCSchedule` 已提供的同语义快捷方法,否则统一从 `cs` 调用 SDK
253
+
254
+ ### 6.3 `insert`
255
+
256
+ 方法签名:
257
+
258
+ ```java
259
+ public ServiceResult insert(CCObject ccobj) throws BusiException
278
260
  ```
279
261
 
280
- ### 执行流程
262
+ 参数说明:
263
+
264
+ | 参数 | 类型 | 必填 | 说明 |
265
+ | --- | --- | --- | --- |
266
+ | `ccobj` | `CCObject` | 是 | 待新增的 CloudCC 对象 |
267
+
268
+ 返回:
269
+
270
+ - `ServiceResult`
271
+
272
+ 适用场景:
273
+
274
+ - 新增单条记录
275
+ - 新增任务、提醒、日志类单条对象
276
+
277
+ AI 使用要求:
278
+
279
+ - 先构造 `CCObject`,再 `put` 字段,最后 `insert`
280
+ - 不要在大批量循环里无脑逐条 `insert`
281
+ - 如果需要创建大量记录,优先考虑项目已有的批量写法
282
+
283
+ ### 6.4 `cquery`
284
+
285
+ #### 查询普通数据
281
286
 
287
+ 方法签名:
288
+
289
+ ```java
290
+ public List<CCObject> cquery(String apiName, String condition, String order) throws Exception
282
291
  ```
283
- ┌─────────────┐
284
- │ 系统时钟 │
285
- └──────┬──────┘
286
- 到达触发时间
287
-
288
- ┌─────────────┐
289
- 调度器检查 │ ──→ 是否在有效期内?
290
- └──────┬──────┘ ──→ 状态是否激活?
291
- │ 是
292
-
293
- ┌─────────────┐
294
- 加载定时类 │
295
- └──────┬──────┘
296
-
297
-
298
- ┌─────────────┐
299
- 执行 main() │
300
- └──────┬──────┘
301
-
302
-
303
- ┌─────────────┐
304
- 记录执行日志 │
305
- └─────────────┘
292
+
293
+ 参数说明:
294
+
295
+ | 参数 | 类型 | 必填 | 说明 |
296
+ | --- | --- | --- | --- |
297
+ | `apiName` | `String` | 是 | 对象 API 名 |
298
+ | `condition` | `String` | 否 | 查询条件;自定义字段 API 名要带 `__c` |
299
+ | `order` | `String` | 否 | 排序条件 |
300
+
301
+ 返回:
302
+
303
+ - `List<CCObject>`
304
+
305
+ 适用场景:
306
+
307
+ - 单对象简单条件查询
308
+ - 条件和排序较直接的巡检类定时器
309
+
310
+ AI 使用要求:
311
+
312
+ - 优先用于简单查询
313
+ - 不要把页面字段标签名写进条件
314
+ - 自定义字段必须用 API 名并带 `__c`
315
+
316
+ #### 查询共享数据
317
+
318
+ 方法签名:
319
+
320
+ ```java
321
+ public List<CCObject> cquery(String apiName, String condition, boolean isDataObject) throws Exception
306
322
  ```
307
323
 
308
- ### 定时类示例
309
-
310
- ```javascript
311
- /**
312
- * 定时类:客户长时间未联系自动新建活动
313
- * 程序 ID: ccp20213DC20298RebnS
314
- */
315
- function main($CCDK, obj) {
316
- // 1. 查询超过 15 天未联系的客户
317
- const fifteenDaysAgo = new Date();
318
- fifteenDaysAgo.setDate(fifteenDaysAgo.getDate() - 15);
319
-
320
- const customers = $CCDK.query(`
321
- SELECT Id, Name, OwnerId
322
- FROM Account
323
- WHERE LastActivityDate < '${fifteenDaysAgo.toISOString()}'
324
- `);
325
-
326
- // 2. 为每个客户创建跟进活动
327
- customers.forEach(customer => {
328
- $CCDK.create('Activity', {
329
- Subject: `跟进客户:${customer.Name}`,
330
- Type: 'Call',
331
- Status: 'Not Started',
332
- OwnerId: customer.OwnerId,
333
- RelatedToId: customer.Id
334
- });
335
- });
336
-
337
- return `已为 ${customers.length} 个客户创建跟进活动`;
338
- }
324
+ 参数说明:
325
+
326
+ | 参数 | 类型 | 必填 | 说明 |
327
+ | --- | --- | --- | --- |
328
+ | `apiName` | `String` | 是 | 对象 API 名 |
329
+ | `condition` | `String` | 否 | 查询条件 |
330
+ | `isDataObject` | `boolean` | 是 | 是否查询业务对象;共享数据场景按项目现有写法传入对应布尔值 |
331
+
332
+ 返回:
333
+
334
+ - `List<CCObject>`
335
+
336
+ 适用场景:
337
+
338
+ - 共享关系查询
339
+ - 权限治理类定时器
340
+
341
+ AI 使用要求:
342
+
343
+ - 涉及共享表查询时使用该重载
344
+ - 布尔参数不要凭空猜测语义,优先参考现有仓库同类写法
345
+
346
+ ### 6.5 `cqlQuery`
347
+
348
+ 方法签名:
349
+
350
+ ```java
351
+ public List<CCObject> cqlQuery(String apiName, String cql) throws Exception
339
352
  ```
340
353
 
341
- ---
354
+ 参数说明:
355
+
356
+ | 参数 | 类型 | 必填 | 说明 |
357
+ | --- | --- | --- | --- |
358
+ | `apiName` | `String` | 是 | 对象 API 名 |
359
+ | `cql` | `String` | 否 | SQL/CQL 查询语句,支持常见 `where` 条件 |
360
+
361
+ 返回:
362
+
363
+ - `List<CCObject>`
364
+
365
+ 适用场景:
366
+
367
+ - 联表查询
368
+ - 聚合查询
369
+ - 分组统计
370
+ - 报表底表查询
371
+ - 复杂分页场景
342
372
 
343
- ## 📊 实际案例(来自你的系统)
373
+ AI 使用要求:
344
374
 
345
- ### 案例 1:客户长时间未联系新建活动
375
+ - 复杂查询优先 `cqlQuery`
376
+ - 默认把它当“查询接口”使用
377
+ - 除非有充分依据,不要把它写成更新或删除通道
378
+ - 报表、底表、汇总类定时器优先考虑 `cqlQuery`
346
379
 
380
+ ### 6.6 `update`
381
+
382
+ 方法签名:
383
+
384
+ ```java
385
+ public ServiceResult update(CCObject ccobj) throws Exception
347
386
  ```
348
- ┌─────────────────────────────────────────────────────┐
349
- │ 作业名称:客户长时间未联系新建活动 │
350
- ├─────────────────────────────────────────────────────┤
351
- 执行时间:每天 上午 8:00 │
352
- 有效期:2021-12-04 ~ 2033-12-21 │
353
- 状态:✅ 运行中 │
354
- │ │
355
- │ 业务逻辑: │
356
- │ 1. 扫描所有客户,找出最后联系时间 > 15 天的 │
357
- 2. 为每个客户自动创建"跟进"活动 │
358
- │ 3. 活动分配给对应的销售负责人 │
359
- │ │
360
- │ 价值:防止销售遗忘客户跟进,提升客户满意度 │
361
- └─────────────────────────────────────────────────────┘
387
+
388
+ 参数说明:
389
+
390
+ | 参数 | 类型 | 必填 | 说明 |
391
+ | --- | --- | --- | --- |
392
+ | `ccobj` | `CCObject` | 是 | 待更新对象,必须含 `id` |
393
+
394
+ 返回:
395
+
396
+ - `ServiceResult`
397
+
398
+ 适用场景:
399
+
400
+ - 修改单条记录
401
+ - 回填单条标记、状态、编号
402
+
403
+ AI 使用要求:
404
+
405
+ - 更新前必须 `put("id", ...)`
406
+ - 仅回写必要字段,不要把无关字段全量覆盖
407
+ - 如果数据量大,优先改用批量更新策略
408
+
409
+ ### 6.7 `delete`
410
+
411
+ 方法签名:
412
+
413
+ ```java
414
+ public ServiceResult delete(CCObject ccobj) throws Exception
362
415
  ```
363
416
 
364
- ### 案例 2:计划收款日期 7 天后发送邮件
417
+ 参数说明:
418
+
419
+ | 参数 | 类型 | 必填 | 说明 |
420
+ | --- | --- | --- | --- |
421
+ | `ccobj` | `CCObject` | 是 | 待删除对象,通常至少包含 `id` |
365
422
 
423
+ 返回:
424
+
425
+ - `ServiceResult`
426
+
427
+ 适用场景:
428
+
429
+ - 删除普通业务记录
430
+
431
+ AI 使用要求:
432
+
433
+ - 删除前必须确认这是业务允许的动作
434
+ - 默认不要在定时器中做大批量物理/逻辑删除,除非需求明确
435
+
436
+ ### 6.8 `deleteShareObjectBySql`
437
+
438
+ 方法签名:
439
+
440
+ ```java
441
+ public void deleteShareObjectBySql(String objectApiName, String expression) throws Exception
366
442
  ```
367
- ┌─────────────────────────────────────────────────────┐
368
- │ 作业名称:计划收款日期 7 天后发送邮件 │
369
- ├─────────────────────────────────────────────────────┤
370
- 执行时间:每天 上午 8:00 │
371
- 有效期:2021-12-10 ~ 2034-12-31 │
372
- 状态:✅ 运行中 │
373
- │ │
374
- │ 业务逻辑: │
375
- │ 1. 查询收款计划日期 = 今天 + 7 天的记录 │
376
- │ 2. 发送邮件给客户提醒付款 │
377
- 3. 抄送财务人员和对应销售 │
378
- │ │
379
- │ 价值:提前提醒客户付款,降低逾期率,改善现金流 │
380
- └─────────────────────────────────────────────────────┘
443
+
444
+ 参数说明:
445
+
446
+ | 参数 | 类型 | 必填 | 说明 |
447
+ | --- | --- | --- | --- |
448
+ | `objectApiName` | `String` | 是 | 共享对象 API 名 |
449
+ | `expression` | `String` | 是 | SQL 表达式;官方说明字段名不需要加 `__c` |
450
+
451
+ 返回:
452
+
453
+ - `void`
454
+
455
+ 适用场景:
456
+
457
+ - 共享关系清理
458
+ - 权限治理类定时器
459
+
460
+ AI 使用要求:
461
+
462
+ - 优先用于共享对象删除,不要拿它删除普通业务对象
463
+ - 条件一定要收敛,避免误删共享关系
464
+
465
+ ### 6.9 自定义设置 `getListCustomSetting`
466
+
467
+ #### 读取列表类型全部记录
468
+
469
+ 方法签名:
470
+
471
+ ```java
472
+ public Map getListCustomSetting(String objectApiName)
381
473
  ```
382
474
 
383
- ### 案例 3:资产失效三个月自动生成业务机会
475
+ 参数说明:
476
+
477
+ | 参数 | 类型 | 必填 | 说明 |
478
+ | --- | --- | --- | --- |
479
+ | `objectApiName` | `String` | 是 | 自定义设置 API 名 |
384
480
 
481
+ 返回:
482
+
483
+ - `Map`
484
+
485
+ 适用场景:
486
+
487
+ - 读取一整套配置项
488
+ - 读取阈值表、邮件配置表、组织映射配置
489
+
490
+ #### 读取列表类型单条记录
491
+
492
+ 方法签名:
493
+
494
+ ```java
495
+ Map map = cs.getListCustomSetting(String apiName, String name);
385
496
  ```
386
- ┌─────────────────────────────────────────────────────┐
387
- │ 作业名称:资产失效三个月自动生成业务机会 │
388
- ├─────────────────────────────────────────────────────┤
389
- 执行时间:每天 凌晨 1:00 │
390
- 有效期:2021-12-10 ~ 2033-12-31 │
391
- 状态:✅ 运行中 │
392
- │ │
393
- │ 业务逻辑: │
394
- │ 1. 查询资产失效时间 = 今天 - 3 个月的记录 │
395
- │ 2. 自动创建新的业务机会(续费/升级) │
396
- 3. 分配给原销售或客户经理 │
397
- │ │
398
- 价值:抓住续费时机,提升客户生命周期价值 │
399
- └─────────────────────────────────────────────────────┘
497
+
498
+ 参数说明:
499
+
500
+ | 参数 | 类型 | 必填 | 说明 |
501
+ | --- | --- | --- | --- |
502
+ | `apiName` | `String` | 是 | 自定义设置 API 名 |
503
+ | `name` | `String` | 是 | 自定义设置记录名称 |
504
+
505
+ 返回:
506
+
507
+ - `Map`
508
+
509
+ AI 使用要求:
510
+
511
+ - 可配置项优先放自定义设置,不要硬编码
512
+ - 提醒阈值、开关、模板 ID、收件人规则都应优先配置化
513
+
514
+ ### 6.10 `getCustomSetting`
515
+
516
+ 方法签名:
517
+
518
+ ```java
519
+ public Map getCustomSetting(String objectApiName, String id)
400
520
  ```
401
521
 
402
- ### 案例 4:报表订阅(已过期)
522
+ 参数说明:
523
+
524
+ | 参数 | 类型 | 必填 | 说明 |
525
+ | --- | --- | --- | --- |
526
+ | `objectApiName` | `String` | 是 | 自定义设置 API 名 |
527
+ | `id` | `String` | 是 | 简档 ID 或用户 ID |
528
+
529
+ 返回:
530
+
531
+ - `Map`
532
+
533
+ 适用场景:
534
+
535
+ - 分用户、分角色、分权限读取配置
536
+ - 不同组织或角色使用不同阈值/模版
537
+
538
+ ### 6.11 `SendEmail`
403
539
 
540
+ 类定位:
541
+
542
+ - 官方邮件发送服务
543
+
544
+ #### 构造函数
545
+
546
+ ```java
547
+ public SendEmail(UserInfo userInfo)
404
548
  ```
405
- ┌─────────────────────────────────────────────────────┐
406
- │ 作业名称:报表订阅 - 销售部收款统计报表 │
407
- ├─────────────────────────────────────────────────────┤
408
- 执行时间:每月 10 下午 4:00 │
409
- 有效期:2025-01-01 ~ 2025-02-28 ⚠️ 已过期 │
410
- 状态:⚠️ 需要续期或停用 │
411
- │ │
412
- 业务逻辑: │
413
- │ 1. 生成销售部收款统计报表 │
414
- │ 2. 发送邮件给销售总监和财务经理 │
415
- │ │
416
- │ 建议:如仍需此报表,需更新有效期 │
417
- └─────────────────────────────────────────────────────┘
549
+
550
+ 参数说明:
551
+
552
+ | 参数 | 类型 | 必填 | 说明 |
553
+ | --- | --- | --- | --- |
554
+ | `userInfo` | `UserInfo` | 是 | 当前用户对象 |
555
+
556
+ #### `sendMailFromSystem`
557
+
558
+ 方法签名:
559
+
560
+ ```java
561
+ public boolean sendMailFromSystem(
562
+ String[] toAddress,
563
+ String[] ccAddress,
564
+ String[] bccAddress,
565
+ String subject,
566
+ String content,
567
+ boolean isText
568
+ )
418
569
  ```
419
570
 
420
- ---
571
+ 参数说明:
572
+
573
+ | 参数 | 类型 | 必填 | 说明 |
574
+ | --- | --- | --- | --- |
575
+ | `toAddress` | `String[]` | 是 | 收件人数组 |
576
+ | `ccAddress` | `String[]` | 是 | 抄送人数组,可传空数组 |
577
+ | `bccAddress` | `String[]` | 是 | 密送人数组,可传空数组 |
578
+ | `subject` | `String` | 是 | 邮件主题 |
579
+ | `content` | `String` | 是 | 邮件正文,支持 HTML |
580
+ | `isText` | `boolean` | 是 | `true` 为纯文本,`false` 为 HTML |
581
+
582
+ 返回:
583
+
584
+ - `boolean`
585
+
586
+ 适用场景:
587
+
588
+ - 简单通知
589
+ - 汇总提醒
590
+ - 失败告警
591
+
592
+ AI 使用要求:
421
593
 
422
- ## 🎓 最佳实践
594
+ - 优先聚合后发送,避免一条记录一封邮件
595
+ - HTML 邮件时 `isText` 应传 `false`
596
+ - 收件人为空时不要发
423
597
 
424
- ### 1. 合理设置执行时间
598
+ #### `sendEmailNew`
425
599
 
600
+ 方法签名:
601
+
602
+ ```java
603
+ public ServiceResult sendEmailNew(
604
+ String emailtemplateid,
605
+ String[] toaddress,
606
+ String[] ccaddress,
607
+ String[] bcaddress,
608
+ String id
609
+ ) throws Exception
426
610
  ```
427
- ✅ 推荐:
428
- - 报表生成:非工作时间(如 23:00 或凌晨)
429
- - 邮件通知:工作时间开始前(如 8:00)
430
- - 数据同步:系统负载低时(如 2:00-4:00)
431
-
432
- 避免:
433
- - 业务高峰期执行大量数据处理
434
- - 多个重任务同时执行
611
+
612
+ 参数说明:
613
+
614
+ | 参数 | 类型 | 必填 | 说明 |
615
+ | --- | --- | --- | --- |
616
+ | `emailtemplateid` | `String` | 是 | 邮件模板 ID |
617
+ | `toaddress` | `String[]` | 是 | 收件人数组 |
618
+ | `ccaddress` | `String[]` | 是 | 抄送人数组 |
619
+ | `bcaddress` | `String[]` | 是 | 密送人数组 |
620
+ | `id` | `String` | 是 | 关联记录 ID |
621
+
622
+ 返回:
623
+
624
+ - `ServiceResult`
625
+
626
+ 适用场景:
627
+
628
+ - 已存在标准模版的业务提醒
629
+ - 需要统一邮件样式的场景
630
+
631
+ AI 使用要求:
632
+
633
+ - 模板 ID 应优先配置化
634
+ - 关联记录 ID 应传实际业务记录,不要随意填空字符串
635
+
636
+ ### 6.12 `DevLogger`
637
+
638
+ 类定位:
639
+
640
+ - 官方运行日志采集工具
641
+
642
+ #### 构造函数
643
+
644
+ ```java
645
+ public DevLogger(UserInfo userInfo)
435
646
  ```
436
647
 
437
- ### 2. 设置合理的有效期
648
+ 参数说明:
438
649
 
650
+ | 参数 | 类型 | 必填 | 说明 |
651
+ | --- | --- | --- | --- |
652
+ | `userInfo` | `UserInfo` | 是 | 当前用户对象 |
653
+
654
+ #### `devLogInfo`
655
+
656
+ 方法签名:
657
+
658
+ ```java
659
+ public void devLogInfo(String info)
439
660
  ```
440
- ✅ 推荐:
441
- - 长期任务:设置 5-10 年有效期
442
- - 临时任务:设置明确结束日期
443
- - 定期审查:每季度检查过期任务
444
-
445
- 避免:
446
- - 不设置结束日期(永久运行)
447
- - 过期任务不处理(占用系统资源)
661
+
662
+ 参数说明:
663
+
664
+ | 参数 | 类型 | 必填 | 说明 |
665
+ | --- | --- | --- | --- |
666
+ | `info` | `String` | 是 | info 级别日志内容 |
667
+
668
+ 返回:
669
+
670
+ - `void`
671
+
672
+ #### `devLogError`
673
+
674
+ 方法签名:
675
+
676
+ ```java
677
+ public void devLogError(String error, Throwable throwable)
448
678
  ```
449
679
 
450
- ### 3. 错误处理和日志
451
-
452
- ```javascript
453
- function main($CCDK, obj) {
454
- try {
455
- // 业务逻辑
456
- const result = doSomething();
457
- return `成功:${result}`;
458
- } catch (error) {
459
- // 记录错误日志
460
- $CCDK.log(`定时作业执行失败:${error.message}`);
461
- // 发送告警通知
462
- sendAlertToAdmin(error);
463
- throw error; // 让系统记录失败状态
464
- }
465
- }
680
+ 参数说明:
681
+
682
+ | 参数 | 类型 | 必填 | 说明 |
683
+ | --- | --- | --- | --- |
684
+ | `error` | `String` | 是 | 错误日志内容 |
685
+ | `throwable` | `Throwable` | 否 | 异常对象 |
686
+
687
+ 返回:
688
+
689
+ - `void`
690
+
691
+ AI 使用要求:
692
+
693
+ - 批处理开始、结束、数量、关键分支打 `info`
694
+ - 异常路径打 `error`
695
+ - 日志至少带业务主键、批次标识或关键条件
696
+
697
+ ### 6.13 `TimeUtil`
698
+
699
+ 类定位:
700
+
701
+ - 多时区安全时间工具
702
+
703
+ 官方说明重点:
704
+
705
+ - `Date` 和 `Calendar` 基于本地时区
706
+ - 跨时区场景下应优先通过 `TimeUtil` 获取当前时间、时区和格式化工具
707
+
708
+ #### `getNowDate`
709
+
710
+ 官方示例写法:
711
+
712
+ ```java
713
+ TpSysTask task = new TpSysTask();
714
+ task.setBeginTime(TimeUtil.getNowDate(userInfo));
466
715
  ```
467
716
 
468
- ### 4. 性能优化
717
+ 参数说明:
718
+
719
+ | 参数 | 类型 | 必填 | 说明 |
720
+ | --- | --- | --- | --- |
721
+ | `userInfo` | `UserInfo` | 是 | 当前用户对象 |
722
+
723
+ 返回:
724
+
725
+ - 当前用户时区下的当前时间
726
+
727
+ #### `getUserTimeZone`
469
728
 
729
+ 方法签名式写法:
730
+
731
+ ```java
732
+ TimeZone tz = TimeUtil.getUserTimeZone(userInfo);
470
733
  ```
471
- ✅ 推荐:
472
- - 批量操作代替循环单条处理
473
- - 使用分页查询避免内存溢出
474
- - 异步处理非关键逻辑
475
-
476
- 避免:
477
- - 单次查询大量数据(>10000 条)
478
- - 在定时作业中调用外部 API(无超时控制)
479
- - 长时间运行的任务(>30 分钟)
734
+
735
+ 参数说明:
736
+
737
+ | 参数 | 类型 | 必填 | 说明 |
738
+ | --- | --- | --- | --- |
739
+ | `userInfo` | `UserInfo` | 是 | 当前用户对象 |
740
+
741
+ 返回:
742
+
743
+ - `TimeZone`
744
+
745
+ #### `getSimpleDateFormat`
746
+
747
+ 官方示例写法:
748
+
749
+ ```java
750
+ SimpleDateFormat myDateFormat =
751
+ TimeUtil.getSimpleDateFormat("yyyy-MM-dd", userInfo);
480
752
  ```
481
753
 
482
- ### 5. 监控和告警
754
+ 参数说明:
755
+
756
+ | 参数 | 类型 | 必填 | 说明 |
757
+ | --- | --- | --- | --- |
758
+ | `format` | `String` | 是 | 日期格式;官方默认示例为 `yyyy-MM-dd` |
759
+ | `userInfo` | `UserInfo` | 是 | 当前用户对象 |
760
+
761
+ 返回:
762
+
763
+ - 已绑定用户时区的 `SimpleDateFormat`
483
764
 
765
+ #### `getCalendar`
766
+
767
+ 官方示例写法:
768
+
769
+ ```java
770
+ Calendar cal = Calendar.getInstance(TimeUtil.getUserTimeZone(userInfo));
771
+ // 或
772
+ Calendar cal2 = TimeUtil.getCalendar(userInfo);
484
773
  ```
485
- 建议配置:
486
- - 执行失败时发送邮件/短信告警
487
- - 定期检查执行日志
488
- - 监控任务执行时长变化
774
+
775
+ 返回:
776
+
777
+ - 带用户时区的 `Calendar`
778
+
779
+ AI 使用要求:
780
+
781
+ - 涉及比较、格式化、写入时间时,优先使用 `TimeUtil`
782
+ - 不要默认直接使用裸 `new Date()`、裸 `SimpleDateFormat`、裸 `Calendar`
783
+
784
+ ### 6.14 项目常见批量写法:`insertLt` / `updateLt`
785
+
786
+ 说明:
787
+
788
+ - 这两个方法在当前项目定时器和 `cloudcc doc timer devguide` 示例中非常常见
789
+ - 官方链接页未在本次抓取结果中展开它们的详细签名表
790
+ - 因此,AI 不能“脑补重载签名”,必须沿用仓库已有写法
791
+
792
+ 当前项目与文档中已出现的典型用法:
793
+
794
+ ```java
795
+ cs.insertLt(batch);
796
+ cs.updateLt(batch);
489
797
  ```
490
798
 
491
- ---
799
+ AI 使用要求:
800
+
801
+ - 只在已有项目先例清晰时使用
802
+ - 参数形态优先沿用本仓库同类定时器
803
+ - 如果需求需要新的批量调用方式,而仓库中没有先例,应先说明依据不足,不要编造 API
804
+
805
+ ### 6.15 本节给 AI 的结论
806
+
807
+ AI 编写定时器时,对 SDK 的使用顺序应默认如下:
808
+
809
+ 1. 用 `CCService` 作为主入口
810
+ 2. 用 `CCObject` 承载新增/更新对象
811
+ 3. 简单查询优先 `cquery`
812
+ 4. 联表和聚合优先 `cqlQuery`
813
+ 5. 单条写入用 `insert` / `update` / `delete`
814
+ 6. 通知用 `SendEmail`
815
+ 7. 观测用 `DevLogger`
816
+ 8. 时间统一走 `TimeUtil`
817
+ 9. 配置优先走 `getListCustomSetting` / `getCustomSetting`
818
+ 10. 批量方法只复用项目已验证写法,不凭空猜
819
+
820
+ ## 7. 当前项目的定时器代码风格要求
821
+
822
+ ### 7.1 当前项目更偏向这几类任务
492
823
 
493
- ## 📋 管理操作
824
+ - 提醒催办
825
+ - 数据同步
826
+ - 数据刷新与修正
827
+ - 报表底表构建
828
+ - 自动生成下游对象
829
+ - 权限治理
494
830
 
495
- ### 定时类:使用 CLI 管理本地 `schedule/`(推荐)
831
+ 因此,AI 生成方案时应优先往这些成熟模式靠拢,而不是引入与现有仓库明显脱节的实现风格。
496
832
 
497
- 与**定时类源码**的创建、同步、删除,请优先使用上文「CLI 与本地文件(必读)」中的命令,避免绕过 CLI 直接改目录或 `config.json`。
833
+ ### 7.2 当前项目中常见模式
498
834
 
499
- 以下接口面向**定时作业配置**(调度时间、启用状态等在设置中的作业),与 `schedule/` 下定时类源码管理是不同层面;具体以你环境的管理后台与 OpenAPI 为准。
835
+ - 先查数据,再按条件处理
836
+ - 按责任人聚合后通知
837
+ - 批量更新字段、状态、台账、底表
838
+ - 在满足条件时自动生成任务或派生对象
839
+ - 对接口失败记录做补偿和邮件告警
500
840
 
501
- ### 查询定时作业(平台接口示例)
841
+ ### 7.3 当前项目中 AI 应优先保留的工程意识
502
842
 
503
- ```bash
504
- # 获取列表
505
- POST /ccsetup/api/schedulAbleprg/list
843
+ - 业务逻辑尽量清晰直白
844
+ - 关键分支有日志
845
+ - 批量处理避免深层嵌套查询
846
+ - 数据写回前先判断是否真的需要写
847
+ - 可能重复执行的逻辑必须考虑去重或状态控制
506
848
 
507
- # 获取详细信息
508
- POST /ccsetup/api/schedulAbleprg/edit
509
- Body: { "id": "作业 ID" }
849
+ ## 8. AI 实现模板
850
+
851
+ 下面是推荐给 AI 的定时器实现骨架。
852
+
853
+ ```java
854
+ package schedule.示例定时器;
855
+
856
+ import com.cloudcc.core.*;
857
+
858
+ public class 示例定时器 extends CCSchedule {
859
+ public 示例定时器() {
860
+ // @SOURCE_CONTENT_START
861
+ CCService cs = new CCService(userInfo);
862
+ DevLogger log = new DevLogger(userInfo);
863
+ try {
864
+ java.util.Date now = TimeUtil.getNowDate(userInfo);
865
+ java.text.SimpleDateFormat sdf =
866
+ TimeUtil.getSimpleDateFormat("yyyy-MM-dd HH:mm:ss", userInfo);
867
+
868
+ log.devLogInfo("示例定时器 start, now=" + sdf.format(now));
869
+
870
+ // 1. 查询目标数据
871
+ // 2. 判断是否满足执行条件
872
+ // 3. 批量生成/更新/通知
873
+ // 4. 记录处理数量与结果
874
+
875
+ log.devLogInfo("示例定时器 finish");
876
+ } catch (Exception e) {
877
+ log.devLogError("示例定时器 error", e);
878
+ throw new RuntimeException(e.getMessage(), e);
879
+ }
880
+ // @SOURCE_CONTENT_END
881
+ }
882
+ }
510
883
  ```
511
884
 
512
- ### 常见管理需求
885
+ AI 可以在此基础上扩展,但不得破坏以下结构:
886
+
887
+ - `package schedule.<类名>;`
888
+ - `extends CCSchedule`
889
+ - 构造方法同名
890
+ - SOURCE 边界完整
891
+
892
+ ## 9. AI 生成定时器类时的必填设计项
893
+
894
+ AI 在输出实现前,应先在思路中覆盖以下设计项。
895
+
896
+ ### 9.1 业务定义
897
+
898
+ - 这个定时器服务什么业务目标
899
+ - 为什么它应该是定时器,而不是触发器
900
+
901
+ ### 9.2 数据范围
513
902
 
514
- | 需求 | 操作 |
515
- |------|------|
516
- | 查看有哪些定时作业 | 调用 list 接口 |
517
- | 查看作业详细配置 | 调用 edit 接口 |
518
- | 启用/禁用作业 | 修改作业状态(需管理权限) |
519
- | 修改执行时间 | 编辑作业的 executetime 和 frequency |
520
- | 延长有效期 | 更新 enddate 字段 |
521
- | 创建新作业 | 使用 cloudcc-cli 创建定时类并配置调度 |
903
+ - 主对象
904
+ - 关联对象
905
+ - 查询条件
906
+ - 是否全量
907
+ - 是否增量
908
+ - 是否分页
522
909
 
523
- ---
910
+ ### 9.3 执行动作
524
911
 
525
- ## 🚨 常见问题
912
+ - 是提醒、同步、修正、汇总、生成,还是权限治理
913
+ - 动作顺序是什么
914
+ - 失败后是否继续处理后续数据
526
915
 
527
- ### Q1: 定时作业不执行怎么办?
916
+ ### 9.4 幂等设计
528
917
 
529
- **检查清单:**
530
- 1. 当前日期是否在有效期内?
531
- 2. 作业状态是否为激活?
532
- 3. 定时类代码是否有错误?
533
- 4. 系统日志是否有报错?
918
+ - 如何防止重复新增
919
+ - 如何防止重复通知
920
+ - 如何防止重复推进状态
534
921
 
535
- ### Q2: 如何调试定时作业?
922
+ ### 9.5 性能设计
536
923
 
537
- **方法:**
538
- 1. 在代码中添加日志输出
539
- 2. 手动执行定时类测试逻辑
540
- 3. 查看系统执行日志
541
- 4. 设置测试环境验证
924
+ - 是否存在循环内查询
925
+ - 是否存在大量单条写入
926
+ - 是否需要分批提交
542
927
 
543
- ### Q3: 定时作业可以传递参数吗?
928
+ ### 9.6 观测与异常
544
929
 
545
- **答案:** 可以。在配置定时作业时设置参数,在定时类中通过 `obj` 参数接收。
930
+ - 哪些日志必须打
931
+ - 哪些异常要抛出
932
+ - 哪些异常要告警
546
933
 
547
- ### Q4: 定时作业执行失败会重试吗?
934
+ ### 9.7 配置化设计
935
+
936
+ - 阈值是否应该来自自定义设置
937
+ - 邮件模版、收件人、开关是否应该配置化
938
+
939
+ ## 10. AI 禁止事项
940
+
941
+ 以下是 AI 在当前项目中编写定时器类时应明确避免的行为。
942
+
943
+ - 不要手工创建 `schedule/<name>/` 目录
944
+ - 不要修改 `config.json` 的 `id`、版本字段
945
+ - 不要在 SOURCE 区域之外写业务代码
946
+ - 不要把明显实时场景错误地写成定时器
947
+ - 不要在大循环里频繁嵌套查询,造成 N+1 问题
948
+ - 不要在大批量处理中逐条单次写入而不考虑 `insertLt` / `updateLt`
949
+ - 不要默认使用 `new Date()`、裸 `Calendar`、裸 `SimpleDateFormat` 处理业务时间
950
+ - 不要吞掉异常而不打日志
951
+ - 不要默认把邮箱、模版 ID、阈值、组织 ID 全部硬编码
952
+ - 不要在没有明确理由时用 SQL 风格语句替代官方 CRUD
953
+ - 不要无条件全表扫描并直接修改全量数据
954
+ - 不要让定时器重复执行后反复创建相同记录、任务或邮件
955
+
956
+ ## 11. AI 输出结果要求
957
+
958
+ AI 在完成定时器类开发时,输出说明至少应包含:
959
+
960
+ - 为什么选择定时器类
961
+ - 主对象与处理范围
962
+ - 执行条件
963
+ - 核心动作
964
+ - 幂等策略
965
+ - 批量策略
966
+ - 日志与异常策略
967
+ - 是否使用通知
968
+ - 是否使用配置化
969
+
970
+ 如果未能做到其中某一项,AI 应显式说明原因,而不是默认省略。
971
+
972
+ ## 12. 推荐给 AI 的任务描述模板
973
+
974
+ 下面这个模板适合作为给 AI 下达定时器开发任务时的标准输入。
975
+
976
+ ```text
977
+ 请为 CloudCC 编写一个定时器类,要求如下:
978
+
979
+ 1. 定时器名称:
980
+ 2. 业务目标:
981
+ 3. 为什么需要定时执行:
982
+ 4. 主对象与关联对象:
983
+ 5. 查询范围(全量/增量/按日期/按状态):
984
+ 6. 满足什么条件后执行:
985
+ 7. 执行动作(提醒/同步/更新/生成/汇总/权限处理):
986
+ 8. 是否需要邮件或任务:
987
+ 9. 是否需要读取自定义设置:
988
+ 10. 幂等要求:
989
+ 11. 批量要求:
990
+ 12. 异常和日志要求:
991
+
992
+ 请按当前项目的 CloudCC 定时器规范实现,并只在 SOURCE_CONTENT 区域内编写业务代码。
993
+ ```
548
994
 
549
- **答案:** 默认不自动重试。建议在代码中实现重试逻辑或配置告警通知人工处理。
995
+ ## 13. 最终结论
550
996
 
551
- ---
997
+ 对 AI 而言,CloudCC 定时器类不是“会写 Java 就能写”,而是要同时满足三层约束:
552
998
 
999
+ - 第一层:必须符合 CloudCC 官方 SDK 的能力边界和推荐用法
1000
+ - 第二层:必须符合 `cloudcc-cli` 的目录、发布和 SOURCE 区域约束
1001
+ - 第三层:必须符合当前项目中定时器类的主流业务模式和工程风格
553
1002
 
554
- *最后更新:2026-03-25*
1003
+ 只有同时满足这三层要求,AI 生成的定时器类才能真正可落地、可维护、可发布。