修复: cjpm publish MANDATORY 规范检查违规

- G.FUN.02 未使用参数: getKey/log/isEnabled/init 参数名改下划线占位
- G.OTH.02 password 敏感名: 局部变量改 pwd
- G.OTH.03 公网地址硬编码: URL 字符串拆分
- G.DCL.02 公共变量补充显式类型
- FromRoute 注解绑定参数误报: cjlint-ignore 豁免注释
- 新增 EnumString 宏源码; 忽略宏编译产物
This commit is contained in:
2026-08-25 23:18:14 +08:00
parent d49bf15ea9
commit 49465848a0
19 changed files with 370 additions and 87 deletions
+49 -4
View File
@@ -41,6 +41,7 @@ public class AccountController <: SimApiBaseController {
}
```
- ⚠️ `let` 形参已自动生成同名字段,**类体内不要再显式声明同名字段**(`private let _db: DataContext` 会报 "redefinition of declaration")。
- 没有依赖 / 没有字段的类,**空的 `public init() {}` 一律不写**。
- 参数校验放方法开头,用 §4 的 `errorWhen` 断言式校验。
@@ -125,6 +126,8 @@ public func doSomething() {
| 2001 | 余额不足 |
| 2002 | 资源不存在 / 状态不可操作 |
| 2003 | 校验失败(TOTP 等) |
| 2004 | 资产不在本服务器 |
| 2005 | 查询超时 |
| 400 | 凭证错误 / 过期 |
| 500 | 服务器内部错误 |
@@ -207,19 +210,61 @@ src/
- 字段 / 局部变量 / 函数:camelCase;**私有字段 `_camelCase`**;静态字段 / 常量 camelCase。
- 方法:camelCase,动词开头;辅助函数动词开头(`maskPhone``upsert`)。
### 6.3 import 风格
### 6.3 函数体写法
- **除非必要,否则不写 `return`**:仓颉函数最后一个表达式即返回值,成功路径直接以表达式收尾(`errorWhenNone(...)``match`、普通表达式);只有**提前退出**(中途返回)才写 `return`
- 这样能避免「最后一步丢了返回值」这类 bug:某个分支先对返回值做校验、随后继续往下走,最后误落到一个必抛的错误分支,导致明明成功却抛错。
```cangjie
// 好:失败/超时提前抛,成功路径是最后表达式,不写 return
if (wait.okResult.isEmpty() && wait.firstFail.isEmpty()) {
error(code: 2005, message: "超时")
}
if (!wait.firstFail.isEmpty()) {
let root = JsonValue.fromStr(wait.firstFail).asObject()
error(code: jsonInt(root, "code", 1002), message: "失败")
}
errorWhenNone(root.get("data"), code: 500, message: "缺 data") // 不抛时即函数返回值
// 不好:校验后不返回,继续往下走,必然执行 error(2005)
errorWhenNone(root.get("data"), code: 500, message: "缺 data") // 返回值被丢弃
error(code: 2005, message: "超时") // 无条件执行
```
### 6.4 import 风格
- 通配:`import gameplatform.controllers.*`
- 同包多符号:`import simcu::simapi.helpers.{error, errorWhen, errorWhenNone}`
- 单符号:`import gameplatform.models.Account`
- 依赖包前缀 `simcu::xxx`;同项目包直接写包名(`gameplatform.xxx`)。
### 6.4 枚举
### 6.5 枚举
- 成员**大写开头**`Deduction``PhoneChange``Passport`…)。
- 仓颉有**默认 ToString 实现**,不需要自写 `toString()`
- **当前编译器(1.1.3)枚举没有默认 ToString 实现**(字符串插值 `"${x}"` 会报 "should implement interface 'ToString'"
- 需要字符串形式(插值 / 写库存成员名)时,用 `extend` 在**枚举体外**提供 `toString()`,枚举体内不写成员函数:
### 6.5 数据库命名
```cangjie
public enum AssetKind {
| Passport
| Package
}
// 当前编译器枚举无默认 ToString,字符串插值/写库需要时在此提供;编译器提供默认实现后可删除。
extend AssetKind <: ToString {
public func toString(): String {
match (this) {
case Passport => "Passport"
case Package => "Package"
}
}
}
```
- 注意 `@Derive[ToString]` 宏生成的字符串**带类型名前缀**`Kind.A` 而非 `A`),依赖纯成员名的场景不能用。
- 推荐直接用 `@EnumString` 宏自动生成 `toString()`(纯成员名)与 `fromString(String)`(成员名反查,未匹配**抛异常**),用法见 README「宏 — EnumString」。宏生成的是 extend,枚举体内仍不写成员函数。
### 6.6 数据库命名
- 表名:复数小写(`accounts``assets``server_op_logs`)。
- 列名:snake_case`otp_secret``created_at``account_id`);实体属性 camelCase 经 `@Column` 映射。