Code Linter 不是为了让代码看起来整齐而是为了把低级问题提前挡在提交前。HarmonyOS 7 / API 26 工程如果多人协作靠人工 review 去发现空判断、异步未处理、无意义状态更新、调试日志残留效率很低也容易漏。这篇按工程落地来讲规则怎么分级误报怎么处理提交前怎么检查CI 怎么阻断最后怎么让修复结果能回归。版本和执行位置项目说明工程目标HarmonyOS 7 / API 26检查对象ArkTS、配置文件、工程脚本执行位置本地提交前、CI 构建前、合并前结果要求错误阻断警告记录误报可追踪Linter 如果只在开发者本地跑很容易有人漏跑。真正稳定的做法是本地快检加 CI 强制检查。规则先分级不要一上来把所有规则都设成阻断。否则误报多了团队会绕开它。~~~tstype RuleLevel error | warn | offtype LintRule {name: stringlevel: RuleLevelreason: string}const rules: LintRule[] [{ name: no-floating-promise, level: error, reason: 异步结果未处理会造成状态不可控 },{ name: no-debug-log-in-release, level: error, reason: release 包不能残留调试日志 },{ name: prefer-stable-key, level: warn, reason: 列表 key 不稳定容易造成状态错位 },{ name: max-function-lines, level: warn, reason: 过长函数需要拆分但不直接阻断 }]~~~我的原则是会造成线上风险的规则设 error影响可维护性的先设 warn。等团队适应后再逐步提高要求。案例一异步任务没有处理失败下面这种写法很常见~~~tsfunction onPageShow(): void {loadRemoteConfig()refreshList()}~~~看起来没问题但这两个异步任务如果失败页面不知道如果返回太晚还可能覆盖新状态。Linter 至少要把未处理 Promise 拦出来。~~~tsfunction onPageShowBetter(): void {void loadRemoteConfig().catch(error {console.error([config], String(error))})void refreshListSafely()}async function refreshListSafely(): Promisevoid {try {const rows await requestRows()applyRows(rows)} catch (error) {showListError(String(error))}}~~~这里不是要求所有异步都 await而是要求每个异步都有明确去向等待、捕获、忽略但说明原因。案例二release 包残留调试日志调试日志在开发阶段有用但 release 包里大量 console 会影响排查也可能泄露内部信息。~~~tstype LintIssue {file: stringline: numberrule: stringlevel: RuleLevelmessage: string}function checkDebugLog(file: string, content: string): LintIssue[] {return content.split().flatMap((line, index) {if (line.includes(console.log()) {return [{file,line: index 1,rule: no-debug-log-in-release,level: error,message: release 代码不要保留 console.log}]}return []})}~~~实际项目可以接成熟 linter这里写简化版本只是为了说明规则结果要结构化。结构化以后CI 才能稳定判断是否阻断。误报白名单要可追踪没有白名单误报会拖慢开发白名单太随意又会把门禁掏空。所以我会给白名单加原因和过期时间。~~~tstype LintIgnore {rule: stringfile: stringreason: stringexpireAt: string}function isIgnored(issue: LintIssue, ignores: LintIgnore[]): boolean {const today 2026-08-05return ignores.some(item {return item.rule issue.rule item.file issue.file item.expireAt today})}~~~白名单不是永久免死牌。过期后还要重新评估不然规则会慢慢失效。CI 阻断逻辑CI 只需要一个清楚的判断有没有 error 级问题。~~~tsfunction assertLintPassed(issues: LintIssue[], ignores: LintIgnore[]): void {const activeIssues issues.filter(issue !isIgnored(issue, ignores))const errors activeIssues.filter(issue issue.level error)for (const issue of activeIssues) {console.info([lint-issue], issue.level, issue.rule, issue.file : issue.line, issue.message)}if (errors.length 0) {throw new Error(lint failed with errors.length error(s))}}~~~warn 可以输出报告但不阻断error 必须失败。这个边界要固定否则每次 CI 失败都要靠人解释。本地验证脚本先用两段代码模拟检查结果。~~~tsfunction verifyLintGate(): void {const content [function test() {, console.log(debug), loadRemoteConfig(),}].join()const issues checkDebugLog(src/main/ets/pages/Index.ets, content)const ignores: LintIgnore[] []assertLintPassed(issues, ignores)}~~~预期结果是 CI 阻断因为 release 代码里出现 console.log。再加一条未过期白名单可以验证误报放行逻辑是否生效。~~~tsfunction verifyIgnore(): void {const issue: LintIssue {file: src/main/ets/pages/DebugOnly.ets,line: 10,rule: no-debug-log-in-release,level: error,message: temporary debug page}const ignores: LintIgnore[] [{rule: no-debug-log-in-release,file: src/main/ets/pages/DebugOnly.ets,reason: only used in internal debug build,expireAt: 2026-08-30}]console.info([verify-ignore], isIgnored(issue, ignores))}~~~落地清单检查项通过标准规则分级error/warn/off 有明确原因异步处理未处理 Promise 不能进主干release 日志console.log 等调试输出被阻断白名单有原因、有过期时间CI 输出能定位到文件、行号、规则名回归本地脚本能复现阻断和放行小结HarmonyOS 7 / API 26 工程接 Code Linter重点不是把规则一次开满而是把质量门禁落稳。先分级再处理误报再把 error 级问题放进 CI 阻断。这样 review 不用反复纠结低级问题团队也能把精力放到真正的架构和业务风险上。