cloudcc-cli 2.4.1 → 2.4.2
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/README.md +42 -0
- package/bin/index.js +5 -0
- package/cloudcc-dev-skill/SKILL.md +6 -12
- package/cloudcc-dev-skill/config.json +2 -2
- package/package.json +2 -2
- package/src/classes/create.js +1 -1
- package/src/config/use.js +20 -5
- package/src/dupeCatcher/create.js +76 -0
- package/src/dupeCatcher/delete.js +69 -0
- package/src/dupeCatcher/detail.js +57 -0
- package/src/dupeCatcher/doc.js +11 -0
- package/src/dupeCatcher/docs/devguide.md +125 -0
- package/src/dupeCatcher/docs/introduction.md +21 -0
- package/src/dupeCatcher/get.js +88 -0
- package/src/dupeCatcher/index.js +14 -0
- package/src/html/doc.js +35 -0
- package/src/html/docs/devguide.md +67 -0
- package/src/html/docs/introduction.md +4 -0
- package/src/html/index.js +11 -0
- package/src/openapi/cloudcc-openapi-sdk.js +1085 -0
- package/src/openapi/doc.js +30 -0
- package/src/openapi/docs/devguide.md +65 -0
- package/src/openapi/docs/introduction.md +43 -0
- package/src/openapi/get.js +45 -0
- package/src/openapi/index.js +12 -0
- package/src/plugin/publish1.js +1 -1
- package/src/plugin/pull.js +2 -2
- package/src/sharingRule/doc.js +46 -0
- package/src/sharingRule/docs/devguide.md +28 -0
- package/src/sharingRule/docs/introduction.md +7 -0
- package/src/sharingRule/get.js +48 -0
- package/src/sharingRule/index.js +9 -0
- package/src/site/doc.js +35 -0
- package/src/site/docs/devguide.md +209 -0
- package/src/site/docs/introduction.md +4 -0
- package/src/site/index.js +11 -0
- package/src/triggers/docs/devguide.md +1 -2
- package/src/triggers/get.js +1 -2
- package/src/version/doctor.js +11 -4
- package/src/version/listModuleCommands.js +20 -0
- package/template/index.js +2 -2
- package/utils/config.js +129 -21
- package/cloudcc-dev-skill/cloudcc-dev-html.md +0 -42
- package/template/cloudcc-cli.configjs +0 -7
package/README.md
CHANGED
|
@@ -71,6 +71,48 @@ Resolve the script path on macOS/Linux with:
|
|
|
71
71
|
echo "$(npm root -g)/cloudcc-cli/bin/mcp.js"
|
|
72
72
|
```
|
|
73
73
|
|
|
74
|
+
# ReleaseV2.4.2
|
|
75
|
+
|
|
76
|
+
#### Release Date: 2026-4-9
|
|
77
|
+
|
|
78
|
+
#### Release Scope: Full
|
|
79
|
+
|
|
80
|
+
#### Release Content
|
|
81
|
+
|
|
82
|
+
- Config resilience
|
|
83
|
+
- Fixed `utils/config.js` fallback flow so commands no longer throw `ENOENT` when `package.json` is missing in the current working directory
|
|
84
|
+
- Added safe existence check and parse guard for legacy `devConsoleConfig` loading to continue with cache/v3/v2 config sources
|
|
85
|
+
- Release maintenance
|
|
86
|
+
- Bumped package version to `2.4.2` and synchronized lockfile root version metadata
|
|
87
|
+
- Dupe Catcher module
|
|
88
|
+
- Added a new `dupeCatcher` resource with `get`, `detail`, `create`, `delete`, and `doc` actions for filter/rule management
|
|
89
|
+
- Added `src/dupeCatcher/docs/devguide.md` with command contracts and payload guidance
|
|
90
|
+
- Sharing Rule module
|
|
91
|
+
- Added a new `sharingRule` resource focused on object-based rule query via `cloudcc get sharingRule <objid> [projectPath]`
|
|
92
|
+
- Integrated sharing rule docs (`introduction` and `devguide`) aligned to the query-only workflow
|
|
93
|
+
- CLI discovery and routing
|
|
94
|
+
- Registered `dupeCatcher` and `sharingRule` in `bin/index.js` and help metadata (`src/version/listModuleCommands.js`) so `cloudcc --help` and `cloudcc get -h` can discover both modules
|
|
95
|
+
- HTML docs module
|
|
96
|
+
- Added a new `html` resource with `cloudcc doc html <introduction|devguide>` for single-file HTML component guidance
|
|
97
|
+
- Added `src/html/docs/introduction.md` and `src/html/docs/devguide.md`, including static-resource referencing guidance for JS/CSS/image assets
|
|
98
|
+
- Skill alignment
|
|
99
|
+
- Updated `cloudcc-dev-skill/SKILL.md` to route HTML component guidance through `cloudcc doc html introduction|devguide`
|
|
100
|
+
- Site docs module
|
|
101
|
+
- Added a new `site` resource with `cloudcc doc site <introduction|devguide>` to provide standalone site development guidance
|
|
102
|
+
- Added `src/site/docs/introduction.md`, `src/site/docs/devguide.md`, and frontend aesthetics references under `src/site/docs/frontend_aesthetics/`
|
|
103
|
+
- OpenAPI browser SDK module
|
|
104
|
+
- Added a new `openapi` resource with `cloudcc get openapi [targetDir] [outputFileName]` to copy browser SDK files into standalone site projects
|
|
105
|
+
- Added `cloudcc doc openapi <introduction|devguide>` and module docs for account/password login and object API access from independent sites
|
|
106
|
+
- CLI help and routing updates
|
|
107
|
+
- Registered `site` and `openapi` in routing/help metadata so `cloudcc --help` and `cloudcc get -h` can discover the new resources
|
|
108
|
+
- Skill package cleanup
|
|
109
|
+
- Removed deprecated `cloudcc-dev-html` skill file and aligned `cloudcc-dev-skill` version metadata for consolidated site guidance
|
|
110
|
+
- Project configuration (JSON)
|
|
111
|
+
- Added `cloudcc-cli.config.json` support via `getPackageJson4` in `utils/config.js` so projects with `package.json` `"type":"module"` are not blocked by CommonJS `require` on `.js` config
|
|
112
|
+
- `getPackageJson` now resolves JSON after cache and before legacy JS loaders (`getPackageJson3` / `getPackageJson2`); `loadCloudccConfigRootSync` and `resolveCloudccConfigFile` prefer JSON when both `.json` and `.js` exist
|
|
113
|
+
- `cloudcc create project` scaffolds `cloudcc-cli.config.json` (replaces the former `template/cloudcc-cli.configjs` template)
|
|
114
|
+
- Updated `config use`, `doctor`, plugin pull/publish ignore lists, `.npmignore`, and `classes` error text to recognize the new config filename
|
|
115
|
+
|
|
74
116
|
# ReleaseV2.4.1
|
|
75
117
|
|
|
76
118
|
#### Release Date: 2026-4-9
|
package/bin/index.js
CHANGED
|
@@ -11,6 +11,8 @@ const modules = {
|
|
|
11
11
|
triggers: require("../src/triggers/index"),
|
|
12
12
|
timer: require("../src/timer/index"),
|
|
13
13
|
script: require("../src/script/index"),
|
|
14
|
+
html: require("../src/html/index"),
|
|
15
|
+
site: require("../src/site/index"),
|
|
14
16
|
jsp: require("../src/jsp/index"),
|
|
15
17
|
token: require("../src/token/index"),
|
|
16
18
|
object: require("../src/object/index"),
|
|
@@ -29,7 +31,10 @@ const modules = {
|
|
|
29
31
|
singleSignOn: require("../src/singleSignOn/index"),
|
|
30
32
|
pagelayout: require("../src/pagelayout/index"),
|
|
31
33
|
validationRule: require("../src/validationRule/index"),
|
|
34
|
+
dupeCatcher: require("../src/dupeCatcher/index"),
|
|
35
|
+
sharingRule: require("../src/sharingRule/index"),
|
|
32
36
|
permission: require("../src/permission/index"),
|
|
37
|
+
openapi: require("../src/openapi/index"),
|
|
33
38
|
};
|
|
34
39
|
|
|
35
40
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: cloudcc-dev-skill
|
|
3
|
-
description: 用于 CloudCC CRM 二次开发设计与实施。优先通过 `cloudcc doc <module> introduction|devguide` 获取官方模块文档,再给出方案与代码。用户提到 CloudCC、cloudcc-cli、模块文档、对象/字段、权限、触发器、类、组件、页面、脚本、JSP
|
|
3
|
+
description: 用于 CloudCC CRM 二次开发设计与实施。优先通过 `cloudcc doc <module> introduction|devguide` 获取官方模块文档,再给出方案与代码。用户提到 CloudCC、cloudcc-cli、模块文档、对象/字段、权限、触发器、类、组件、页面、脚本、JSP 迁移、静态资源、菜单、应用、单点登录、身份提供方、校验规则、查重过滤器(Dupe Catcher)、重复/去重、共享规则时应优先使用。
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# CloudCC CRM 二开技能
|
|
@@ -34,7 +34,9 @@ description: 用于 CloudCC CRM 二次开发设计与实施。优先通过 `clou
|
|
|
34
34
|
- 全局选项:`cloudcc doc globalSelectList introduction`、`cloudcc doc globalSelectList devguide`
|
|
35
35
|
- 按钮:`cloudcc doc button introduction`、`cloudcc doc button devguide`
|
|
36
36
|
- 页面布局:`cloudcc doc pagelayout introduction`、`cloudcc doc pagelayout devguide`
|
|
37
|
-
-
|
|
37
|
+
- 验证规则:`cloudcc doc validationRule introduction`、`cloudcc doc validationRule devguide`
|
|
38
|
+
- 查重过滤器(dupeCatcher):`cloudcc doc dupeCatcher introduction`、`cloudcc doc dupeCatcher devguide`
|
|
39
|
+
- 共享规则(sharingRule):`cloudcc doc sharingRule introduction`、`cloudcc doc sharingRule devguide`
|
|
38
40
|
|
|
39
41
|
### 组织与权限
|
|
40
42
|
|
|
@@ -53,7 +55,8 @@ description: 用于 CloudCC CRM 二次开发设计与实施。优先通过 `clou
|
|
|
53
55
|
### 前端扩展
|
|
54
56
|
|
|
55
57
|
- 自定义Vue组件:`cloudcc doc plugin introduction`、`cloudcc doc plugin devguide`
|
|
56
|
-
- 自定义
|
|
58
|
+
- 自定义 HTML 组件:`cloudcc doc html introduction`、`cloudcc doc html devguide`
|
|
59
|
+
- Site 开发规范:`cloudcc doc site introduction`、`cloudcc doc site devguide`
|
|
57
60
|
- 自定义页面:`cloudcc doc customPage introduction`、`cloudcc doc customPage devguide`
|
|
58
61
|
- 客户端脚本:`cloudcc doc script introduction`、`cloudcc doc script devguide`
|
|
59
62
|
- 静态资源:`cloudcc doc staticResource introduction`、`cloudcc doc staticResource devguide`
|
|
@@ -90,12 +93,3 @@ description: 用于 CloudCC CRM 二次开发设计与实施。优先通过 `clou
|
|
|
90
93
|
- **发布日志/Release Notes 规则(强制)**:凡是更新发布记录、版本日志、README 中
|
|
91
94
|
`Release`/`Release Notes`
|
|
92
95
|
区块,内容必须使用英文(标题、日期标签、条目描述均不得使用中文)。
|
|
93
|
-
|
|
94
|
-
## 快速规则
|
|
95
|
-
|
|
96
|
-
- 先确认 CLI 可用:优先检查 `cloudcc --version`。
|
|
97
|
-
- 若未安装,执行:`npm i -g cloudcc-cli@latest`。
|
|
98
|
-
- 当进行 CloudCC 方案设计时,必须读取所有模块的`introduction`文档后,再设计
|
|
99
|
-
- 当进行 CloudCC 方案开发时,需要读取,对应模块的`devguide`信息后,再开发
|
|
100
|
-
- 命令统一格式:`cloudcc doc <module> <introduction|devguide>`。
|
|
101
|
-
- 特例:`config` 仅支持 `devguide`,不支持 `introduction`。
|
package/package.json
CHANGED
package/src/classes/create.js
CHANGED
|
@@ -17,7 +17,7 @@ async function create(argvs) {
|
|
|
17
17
|
console.error()
|
|
18
18
|
console.error(
|
|
19
19
|
chalk.yellow(
|
|
20
|
-
"No valid cloudcc-cli config for this project. Create or fix cloudcc-cli.config.js (see cloudcc doc project devguide)."
|
|
20
|
+
"No valid cloudcc-cli config for this project. Create or fix cloudcc-cli.config.json (or .js) (see cloudcc doc project devguide)."
|
|
21
21
|
)
|
|
22
22
|
)
|
|
23
23
|
console.error()
|
package/src/config/use.js
CHANGED
|
@@ -1,14 +1,29 @@
|
|
|
1
1
|
const path = require("path")
|
|
2
2
|
const fs = require("fs")
|
|
3
|
+
const { resolveCloudccConfigFile } = require("../../utils/config.js")
|
|
3
4
|
|
|
4
5
|
function use(env, projectPath = process.cwd()) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
const resolved = resolveCloudccConfigFile(projectPath)
|
|
7
|
+
if (!resolved) {
|
|
8
|
+
throw new Error("No cloudcc-cli.config.json or cloudcc-cli.config.js found")
|
|
9
|
+
}
|
|
10
|
+
if (resolved.kind === "json") {
|
|
11
|
+
const config = JSON.parse(fs.readFileSync(resolved.filePath, "utf8"))
|
|
12
|
+
config.use = env
|
|
13
|
+
fs.writeFileSync(resolved.filePath, JSON.stringify(config, null, 4) + "\n", "utf8")
|
|
14
|
+
return
|
|
15
|
+
}
|
|
16
|
+
const jsPath = resolved.filePath
|
|
17
|
+
delete require.cache[require.resolve(jsPath)]
|
|
18
|
+
const config = require(jsPath)
|
|
19
|
+
config.use = env
|
|
20
|
+
fs.writeFileSync(
|
|
21
|
+
jsPath,
|
|
8
22
|
`module.exports =
|
|
9
23
|
${JSON.stringify(config)}
|
|
10
|
-
|
|
11
|
-
|
|
24
|
+
`,
|
|
25
|
+
"utf8"
|
|
26
|
+
)
|
|
12
27
|
}
|
|
13
28
|
|
|
14
29
|
module.exports = use;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
const chalk = require("chalk")
|
|
2
|
+
const { getPackageJson } = require("../../utils/config")
|
|
3
|
+
const { postClass } = require("../../utils/http")
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Supported:
|
|
7
|
+
* - cloudcc create dupeCatcher filter <encodedBodyJson> [projectPath]
|
|
8
|
+
* -> /api/duplication/saveFilter
|
|
9
|
+
*
|
|
10
|
+
* - cloudcc create dupeCatcher rule <encodedBodyJson> [projectPath]
|
|
11
|
+
* -> /api/duplication/nsaverule
|
|
12
|
+
*/
|
|
13
|
+
function isPathLikeToken(v) {
|
|
14
|
+
if (typeof v !== "string" || !v) return false
|
|
15
|
+
return v === "." || v === ".." || /[\\/]/.test(v) || /:/.test(v)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async function request(projectPath, apiPath, body) {
|
|
19
|
+
const config = await getPackageJson(projectPath)
|
|
20
|
+
return await postClass(config.setupSvc + apiPath, body || {}, config.accessToken)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async function create(projectPath = process.cwd(), kind, encoded, isMcp = false) {
|
|
24
|
+
// compatibility: cloudcc create dupeCatcher filter <encoded> [projectPath]
|
|
25
|
+
if (!isPathLikeToken(projectPath)) {
|
|
26
|
+
encoded = kind
|
|
27
|
+
kind = projectPath
|
|
28
|
+
projectPath = process.cwd()
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (!kind || !encoded) {
|
|
32
|
+
throw new Error(
|
|
33
|
+
"Usage:\n" +
|
|
34
|
+
"- cloudcc create dupeCatcher filter <encodedBodyJson> [projectPath]\n" +
|
|
35
|
+
"- cloudcc create dupeCatcher rule <encodedBodyJson> [projectPath]"
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let body
|
|
40
|
+
try {
|
|
41
|
+
body = JSON.parse(decodeURI(encoded))
|
|
42
|
+
} catch (e) {
|
|
43
|
+
throw new Error("Invalid encodedBodyJson (must be encodeURI(JSON.stringify(obj))). " + e.message)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (kind === "filter") {
|
|
47
|
+
console.error()
|
|
48
|
+
console.error(chalk.green("Saving dupe catcher filter, please wait..."))
|
|
49
|
+
console.error()
|
|
50
|
+
const res = await request(projectPath, "/api/duplication/saveFilter", body)
|
|
51
|
+
if (res && res.result) {
|
|
52
|
+
const data = res.data || res
|
|
53
|
+
if (!isMcp) console.log(JSON.stringify(data))
|
|
54
|
+
return data
|
|
55
|
+
}
|
|
56
|
+
throw new Error("Create/Update DupeCatcher filter failed: " + (res?.returnInfo || res?.message || "Unknown error"))
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (kind === "rule") {
|
|
60
|
+
console.error()
|
|
61
|
+
console.error(chalk.green("Saving dupe catcher rule, please wait..."))
|
|
62
|
+
console.error()
|
|
63
|
+
const res = await request(projectPath, "/api/duplication/nsaverule", body)
|
|
64
|
+
if (res && res.result) {
|
|
65
|
+
const data = res.data || res
|
|
66
|
+
if (!isMcp) console.log(JSON.stringify(data))
|
|
67
|
+
return data
|
|
68
|
+
}
|
|
69
|
+
throw new Error("Create/Update DupeCatcher rule failed: " + (res?.returnInfo || res?.message || "Unknown error"))
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
throw new Error(`Unknown kind for create dupeCatcher: ${kind}. Expected 'filter' or 'rule'.`)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
module.exports = create
|
|
76
|
+
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
const chalk = require("chalk")
|
|
2
|
+
const { getPackageJson } = require("../../utils/config")
|
|
3
|
+
const { postClass } = require("../../utils/http")
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Supported:
|
|
7
|
+
* - cloudcc delete dupeCatcher filter <filterid> [projectPath]
|
|
8
|
+
* -> /api/duplication/deletefilter
|
|
9
|
+
*
|
|
10
|
+
* - cloudcc delete dupeCatcher rule <ruleid> [projectPath]
|
|
11
|
+
* -> /api/duplication/deleterule
|
|
12
|
+
*/
|
|
13
|
+
function isPathLikeToken(v) {
|
|
14
|
+
if (typeof v !== "string" || !v) return false
|
|
15
|
+
return v === "." || v === ".." || /[\\/]/.test(v) || /:/.test(v)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async function request(projectPath, apiPath, body) {
|
|
19
|
+
const config = await getPackageJson(projectPath)
|
|
20
|
+
return await postClass(config.setupSvc + apiPath, body || {}, config.accessToken)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async function del(projectPath = process.cwd(), kind, id, isMcp = false) {
|
|
24
|
+
// compatibility: cloudcc delete dupeCatcher filter <id> [projectPath]
|
|
25
|
+
if (!isPathLikeToken(projectPath)) {
|
|
26
|
+
id = kind
|
|
27
|
+
kind = projectPath
|
|
28
|
+
projectPath = process.cwd()
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (!kind || !id) {
|
|
32
|
+
throw new Error(
|
|
33
|
+
"Usage:\n" +
|
|
34
|
+
"- cloudcc delete dupeCatcher filter <filterid> [projectPath]\n" +
|
|
35
|
+
"- cloudcc delete dupeCatcher rule <ruleid> [projectPath]"
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (kind === "filter") {
|
|
40
|
+
console.error()
|
|
41
|
+
console.error(chalk.green(`Deleting dupe catcher filter (${id}), please wait...`))
|
|
42
|
+
console.error()
|
|
43
|
+
const res = await request(projectPath, "/api/duplication/deletefilter", { filterid: id })
|
|
44
|
+
if (res && res.result) {
|
|
45
|
+
const data = res.data || res
|
|
46
|
+
if (!isMcp) console.log(JSON.stringify(data))
|
|
47
|
+
return data
|
|
48
|
+
}
|
|
49
|
+
throw new Error("Delete DupeCatcher filter failed: " + (res?.returnInfo || res?.message || "Unknown error"))
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (kind === "rule") {
|
|
53
|
+
console.error()
|
|
54
|
+
console.error(chalk.green(`Deleting dupe catcher rule (${id}), please wait...`))
|
|
55
|
+
console.error()
|
|
56
|
+
const res = await request(projectPath, "/api/duplication/deleterule", { ruleid: id })
|
|
57
|
+
if (res && res.result) {
|
|
58
|
+
const data = res.data || res
|
|
59
|
+
if (!isMcp) console.log(JSON.stringify(data))
|
|
60
|
+
return data
|
|
61
|
+
}
|
|
62
|
+
throw new Error("Delete DupeCatcher rule failed: " + (res?.returnInfo || res?.message || "Unknown error"))
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
throw new Error(`Unknown kind for delete dupeCatcher: ${kind}. Expected 'filter' or 'rule'.`)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
module.exports = del
|
|
69
|
+
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
const { getPackageJson } = require("../../utils/config")
|
|
2
|
+
const { postClass } = require("../../utils/http")
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Supported:
|
|
6
|
+
* - cloudcc detail dupeCatcher <filterid> [projectPath]
|
|
7
|
+
* -> /api/duplication/detailfilter
|
|
8
|
+
*
|
|
9
|
+
* - cloudcc detail dupeCatcher rule <ruleid> [projectPath]
|
|
10
|
+
* -> /api/duplication/updateNewrule
|
|
11
|
+
*/
|
|
12
|
+
function isPathLikeToken(v) {
|
|
13
|
+
if (typeof v !== "string" || !v) return false
|
|
14
|
+
return v === "." || v === ".." || /[\\/]/.test(v) || /:/.test(v)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async function request(projectPath, apiPath, body) {
|
|
18
|
+
const config = await getPackageJson(projectPath)
|
|
19
|
+
return await postClass(config.setupSvc + apiPath, body || {}, config.accessToken)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async function detail(projectPath = process.cwd(), kindOrId, maybeId, isMcp = false) {
|
|
23
|
+
// compatibility: cloudcc detail dupeCatcher <filterid> [projectPath]
|
|
24
|
+
if (!isPathLikeToken(projectPath)) {
|
|
25
|
+
maybeId = kindOrId
|
|
26
|
+
kindOrId = projectPath
|
|
27
|
+
projectPath = process.cwd()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (!kindOrId) {
|
|
31
|
+
throw new Error("Missing id. Usage: cloudcc detail dupeCatcher <filterid> [projectPath]")
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (kindOrId === "rule") {
|
|
35
|
+
const ruleid = maybeId
|
|
36
|
+
if (!ruleid) throw new Error("Missing ruleid. Usage: cloudcc detail dupeCatcher rule <ruleid> [projectPath]")
|
|
37
|
+
const res = await request(projectPath, "/api/duplication/updateNewrule", { ruleid })
|
|
38
|
+
if (res && res.result) {
|
|
39
|
+
const data = res.data || res
|
|
40
|
+
if (!isMcp) console.log(JSON.stringify(data))
|
|
41
|
+
return data
|
|
42
|
+
}
|
|
43
|
+
throw new Error("Detail DupeCatcher rule failed: " + (res?.returnInfo || res?.message || "Unknown error"))
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const filterid = kindOrId
|
|
47
|
+
const res = await request(projectPath, "/api/duplication/detailfilter", { filterid })
|
|
48
|
+
if (res && res.result) {
|
|
49
|
+
const data = res.data || res
|
|
50
|
+
if (!isMcp) console.log(JSON.stringify(data))
|
|
51
|
+
return data
|
|
52
|
+
}
|
|
53
|
+
throw new Error("Detail DupeCatcher filter failed: " + (res?.returnInfo || res?.message || "Unknown error"))
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
module.exports = detail
|
|
57
|
+
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# CloudCC 查重过滤器(Dupe Catcher)CLI 命令说明
|
|
2
|
+
|
|
3
|
+
> 对应 one-setup-web 的接口前缀:`{setupSvc}/api/duplication/*`
|
|
4
|
+
|
|
5
|
+
## 1. 功能范围
|
|
6
|
+
|
|
7
|
+
- 过滤器(Filter):列表、详情、保存(新建/编辑)、删除
|
|
8
|
+
- 规则(Rule):回显详情、保存(新建/编辑)、删除
|
|
9
|
+
- 辅助查询:可选对象、可选字段、条件面板字段列表
|
|
10
|
+
|
|
11
|
+
## 2. 命令总览
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# 过滤器列表
|
|
15
|
+
cloudcc get dupeCatcher [projectPath]
|
|
16
|
+
|
|
17
|
+
# 过滤器详情(含规则列表)
|
|
18
|
+
cloudcc detail dupeCatcher <projectPath> <filterid>
|
|
19
|
+
|
|
20
|
+
# 保存过滤器(新建/编辑)
|
|
21
|
+
cloudcc create dupeCatcher <projectPath> filter <encodedBodyJson>
|
|
22
|
+
|
|
23
|
+
# 删除过滤器
|
|
24
|
+
cloudcc delete dupeCatcher <projectPath> filter <filterid>
|
|
25
|
+
|
|
26
|
+
# 规则详情(回显)
|
|
27
|
+
cloudcc detail dupeCatcher <projectPath> rule <ruleid>
|
|
28
|
+
|
|
29
|
+
# 保存规则(新建/编辑)
|
|
30
|
+
cloudcc create dupeCatcher <projectPath> rule <encodedBodyJson>
|
|
31
|
+
|
|
32
|
+
# 删除规则
|
|
33
|
+
cloudcc delete dupeCatcher <projectPath> rule <ruleid>
|
|
34
|
+
|
|
35
|
+
# 新建过滤器前:查询可选对象
|
|
36
|
+
cloudcc get dupeCatcher objects [projectPath]
|
|
37
|
+
|
|
38
|
+
# 新建规则前:查询可选字段
|
|
39
|
+
cloudcc get dupeCatcher <projectPath> fields <filterid>
|
|
40
|
+
|
|
41
|
+
# 条件面板字段列表(复用工作流接口)
|
|
42
|
+
cloudcc get dupeCatcher <projectPath> workflowFields <targetobjectid>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## 3. 参数说明
|
|
46
|
+
|
|
47
|
+
### 3.1 projectPath
|
|
48
|
+
|
|
49
|
+
- **可选**,项目根目录(默认当前目录)。
|
|
50
|
+
|
|
51
|
+
### 3.2 encodedBodyJson
|
|
52
|
+
|
|
53
|
+
- **必须**:`encodeURI(JSON.stringify(body))`
|
|
54
|
+
|
|
55
|
+
### 3.3 命令参数一览
|
|
56
|
+
|
|
57
|
+
| 命令 | 参数 |
|
|
58
|
+
| :--- | :--- |
|
|
59
|
+
| `cloudcc get dupeCatcher [projectPath]` | `projectPath` 可选 |
|
|
60
|
+
| `cloudcc detail dupeCatcher <projectPath> <filterid>` | `projectPath` 可选(默认当前目录),`filterid` 必填 |
|
|
61
|
+
| `cloudcc create dupeCatcher <projectPath> filter <encodedBodyJson>` | `projectPath` 可选(默认当前目录),`encodedBodyJson` 必填 |
|
|
62
|
+
| `cloudcc delete dupeCatcher <projectPath> filter <filterid>` | `projectPath` 可选(默认当前目录),`filterid` 必填 |
|
|
63
|
+
| `cloudcc detail dupeCatcher <projectPath> rule <ruleid>` | `projectPath` 可选(默认当前目录),`ruleid` 必填 |
|
|
64
|
+
| `cloudcc create dupeCatcher <projectPath> rule <encodedBodyJson>` | `projectPath` 可选(默认当前目录),`encodedBodyJson` 必填 |
|
|
65
|
+
| `cloudcc delete dupeCatcher <projectPath> rule <ruleid>` | `projectPath` 可选(默认当前目录),`ruleid` 必填 |
|
|
66
|
+
| `cloudcc get dupeCatcher objects [projectPath]` | `projectPath` 可选 |
|
|
67
|
+
| `cloudcc get dupeCatcher <projectPath> fields <filterid>` | `projectPath` 可选(默认当前目录),`filterid` 必填 |
|
|
68
|
+
| `cloudcc get dupeCatcher <projectPath> workflowFields <targetobjectid>` | `projectPath` 可选(默认当前目录),`targetobjectid` 必填 |
|
|
69
|
+
|
|
70
|
+
### 3.4 `create dupeCatcher filter` 的 body 字段
|
|
71
|
+
|
|
72
|
+
| 字段 | 类型 | 是否必须 | 说明 |
|
|
73
|
+
| :--- | :--- | :--- | :--- |
|
|
74
|
+
| `id` | string | 否 | 编辑时传;新建可不传 |
|
|
75
|
+
| `name` | string | 是 | 过滤器名称 |
|
|
76
|
+
| `objid` | string | 是 | 目标对象 id |
|
|
77
|
+
| `errormessage` | string | 否 | 错误提示文案 |
|
|
78
|
+
| `insertoperation` | string | 是 | 新增策略:`check` / `nothing` |
|
|
79
|
+
| `insertIsSave` | string/null | 条件必填 | `insertoperation=check` 时建议传 `"1"`/`"0"`,否则传 `null` |
|
|
80
|
+
| `insertIsTips` | string/null | 条件必填 | `insertoperation=check` 时建议传 `"1"`/`"0"`,否则传 `null` |
|
|
81
|
+
| `updateoperation` | string | 是 | 更新策略:`check` / `nothing` |
|
|
82
|
+
| `updateIsSave` | string/null | 条件必填 | `updateoperation=check` 时建议传 `"1"`/`"0"`,否则传 `null` |
|
|
83
|
+
| `updateIsTips` | string/null | 条件必填 | `updateoperation=check` 时建议传 `"1"`/`"0"`,否则传 `null` |
|
|
84
|
+
| `isprofile` | boolean | 否 | 是否简档 |
|
|
85
|
+
| `isactive` | boolean | 否 | 是否启用 |
|
|
86
|
+
| `conditionVals` | string | 是 | 条件面板产出的 JSON 字符串 |
|
|
87
|
+
|
|
88
|
+
### 3.5 `create dupeCatcher rule` 的 body 字段
|
|
89
|
+
|
|
90
|
+
| 字段 | 类型 | 是否必须 | 说明 |
|
|
91
|
+
| :--- | :--- | :--- | :--- |
|
|
92
|
+
| `id` | string | 否 | 编辑时传;新建可不传 |
|
|
93
|
+
| `filterid` | string | 是 | 所属过滤器 id |
|
|
94
|
+
| `fieldid` | string | 是 | 匹配字段 id |
|
|
95
|
+
| `matchoption` | string | 是 | `exact` / `contains` / `firstNletters` / `lastNletters` |
|
|
96
|
+
| `firstletters` | string | 条件必填 | `matchoption` 为 `firstNletters/lastNletters` 时传字母数 |
|
|
97
|
+
| `isblank` | number | 否 | 空值是否参与匹配,常用 `1/0` |
|
|
98
|
+
|
|
99
|
+
## 4. 示例
|
|
100
|
+
|
|
101
|
+
### 4.1 查询过滤器列表
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
cloudcc get dupeCatcher .
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### 4.2 保存过滤器(新建)
|
|
108
|
+
|
|
109
|
+
> 关键字段(与页面一致):`name`、`objid`、`insertoperation`、`updateoperation`、`conditionVals` 等。
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
cloudcc create dupeCatcher . filter "$(node -e "console.log(encodeURI(JSON.stringify({name:'测试过滤器',objid:'<objid>',errormessage:'',insertoperation:'check',insertIsSave:'1',insertIsTips:'1',updateoperation:'check',updateIsSave:'1',updateIsTips:'1',isprofile:false,isactive:true,conditionVals:'{}'})))")"
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### 4.3 保存规则(新建)
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
cloudcc create dupeCatcher . rule "$(node -e "console.log(encodeURI(JSON.stringify({filterid:'<filterid>',fieldid:'<fieldid>',matchoption:'exact',firstletters:'',isblank:0})))")"
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## 5. 注意事项
|
|
122
|
+
|
|
123
|
+
- `filterid` / `ruleid` / `objid` / `fieldid` 都来自平台返回数据,请先通过列表/详情接口获取。
|
|
124
|
+
- `conditionVals` 是页面条件面板产出的 **json 字符串**(不是对象),请按接口要求传入字符串。
|
|
125
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# CloudCC 查重过滤器(Dupe Catcher)介绍
|
|
2
|
+
|
|
3
|
+
查重过滤器用于在**新建或编辑业务数据**时,按配置的**对象、字段与条件**检测是否与已有记录重复,从而提示或阻断保存。平台侧通过 **过滤器(Filter)** 与 **规则(Rule)** 两层建模:过滤器绑定目标对象与启用范围,规则描述具体匹配字段与逻辑。
|
|
4
|
+
|
|
5
|
+
## 适用场景
|
|
6
|
+
|
|
7
|
+
- 客户、联系人、线索等主数据**去重**(姓名 + 手机、邮箱等组合)。
|
|
8
|
+
- 同一业务对象下**多套查重策略**(不同过滤器、不同规则集)。
|
|
9
|
+
- 与 **one-setup-web** 中查重配置能力一致,CLI 面向**导出配置、脚本化维护、与本地工程联调**。
|
|
10
|
+
|
|
11
|
+
## 能力边界(与开发指南的关系)
|
|
12
|
+
|
|
13
|
+
- **介绍(本文)**:说明是什么、何时用、与平台概念对应关系。
|
|
14
|
+
- **开发指南**:`cloudcc doc dupeCatcher devguide` — 列出 `get` / `detail` / `create` / `delete` 等 CLI 命令、参数与接口前缀 `{setupSvc}/api/duplication/*`。
|
|
15
|
+
|
|
16
|
+
## 相关命令入口
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
cloudcc doc dupeCatcher introduction # 本文
|
|
20
|
+
cloudcc doc dupeCatcher devguide # CLI 与接口说明
|
|
21
|
+
```
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
const { getPackageJson } = require("../../utils/config")
|
|
2
|
+
const { postClass } = require("../../utils/http")
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Dupe Catcher (Duplication) queries.
|
|
6
|
+
*
|
|
7
|
+
* Supported:
|
|
8
|
+
* - cloudcc get dupeCatcher [projectPath]
|
|
9
|
+
* -> /api/duplication/getList
|
|
10
|
+
*
|
|
11
|
+
* - cloudcc get dupeCatcher objects [projectPath]
|
|
12
|
+
* -> /api/duplication/insetNewfilter
|
|
13
|
+
*
|
|
14
|
+
* - cloudcc get dupeCatcher fields <filterid> [projectPath]
|
|
15
|
+
* -> /api/duplication/insetNewrule
|
|
16
|
+
*
|
|
17
|
+
* - cloudcc get dupeCatcher workflowFields <targetobjectid> [projectPath]
|
|
18
|
+
* -> /api/workFlowSetup/newWorkflow
|
|
19
|
+
*/
|
|
20
|
+
function isPathLikeToken(v) {
|
|
21
|
+
if (typeof v !== "string" || !v) return false
|
|
22
|
+
return v === "." || v === ".." || /[\\/]/.test(v) || /:/.test(v)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async function request(projectPath, apiPath, body) {
|
|
26
|
+
const config = await getPackageJson(projectPath)
|
|
27
|
+
return await postClass(config.setupSvc + apiPath, body || {}, config.accessToken)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function get(projectPath = process.cwd(), sub, subArg, isMcp = false) {
|
|
31
|
+
// compatibility: cloudcc get dupeCatcher objects [projectPath]
|
|
32
|
+
if (!isPathLikeToken(projectPath) && (projectPath === "objects" || projectPath === "fields" || projectPath === "workflowFields")) {
|
|
33
|
+
subArg = sub
|
|
34
|
+
sub = projectPath
|
|
35
|
+
projectPath = process.cwd()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (!sub) {
|
|
39
|
+
const res = await request(projectPath, "/api/duplication/getList", {})
|
|
40
|
+
if (res && res.result) {
|
|
41
|
+
const list = res.data || res.list || []
|
|
42
|
+
if (!isMcp) console.log(JSON.stringify(list))
|
|
43
|
+
return list
|
|
44
|
+
}
|
|
45
|
+
throw new Error("Get DupeCatcher filter list failed: " + (res?.returnInfo || res?.message || "Unknown error"))
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (sub === "objects") {
|
|
49
|
+
const res = await request(projectPath, "/api/duplication/insetNewfilter", {})
|
|
50
|
+
if (res && res.result) {
|
|
51
|
+
const data = res.data || res
|
|
52
|
+
if (!isMcp) console.log(JSON.stringify(data))
|
|
53
|
+
return data
|
|
54
|
+
}
|
|
55
|
+
throw new Error("Get DupeCatcher objects failed: " + (res?.returnInfo || res?.message || "Unknown error"))
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (sub === "fields") {
|
|
59
|
+
const filterid = subArg
|
|
60
|
+
if (!filterid) throw new Error("Missing filterid. Usage: cloudcc get dupeCatcher fields <filterid> [projectPath]")
|
|
61
|
+
const res = await request(projectPath, "/api/duplication/insetNewrule", { filterid })
|
|
62
|
+
if (res && res.result) {
|
|
63
|
+
const data = res.data || res
|
|
64
|
+
if (!isMcp) console.log(JSON.stringify(data))
|
|
65
|
+
return data
|
|
66
|
+
}
|
|
67
|
+
throw new Error("Get DupeCatcher fields failed: " + (res?.returnInfo || res?.message || "Unknown error"))
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (sub === "workflowFields") {
|
|
71
|
+
const targetobjectid = subArg
|
|
72
|
+
if (!targetobjectid) {
|
|
73
|
+
throw new Error("Missing targetobjectid. Usage: cloudcc get dupeCatcher workflowFields <targetobjectid> [projectPath]")
|
|
74
|
+
}
|
|
75
|
+
const res = await request(projectPath, "/api/workFlowSetup/newWorkflow", { targetobjectid })
|
|
76
|
+
if (res && res.result) {
|
|
77
|
+
const data = res.data || res
|
|
78
|
+
if (!isMcp) console.log(JSON.stringify(data))
|
|
79
|
+
return data
|
|
80
|
+
}
|
|
81
|
+
throw new Error("Get DupeCatcher workflowFields failed: " + (res?.returnInfo || res?.message || "Unknown error"))
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
throw new Error(`Unknown subcommand for get dupeCatcher: ${sub}`)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
module.exports = get
|
|
88
|
+
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const cc = {}
|
|
2
|
+
|
|
3
|
+
cc.get = require("./get")
|
|
4
|
+
cc.detail = require("./detail")
|
|
5
|
+
cc.create = require("./create")
|
|
6
|
+
cc.delete = require("./delete")
|
|
7
|
+
cc.doc = require("./doc")
|
|
8
|
+
|
|
9
|
+
function main(action, argvs) {
|
|
10
|
+
cc[action](argvs[2], argvs[3], argvs[4], argvs[5])
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
module.exports = main
|
|
14
|
+
|