Files
pangolin/ci/scan-redline.sh
wangjia f97ae8186b feat(client): Flutter 逐屏还原 + iPad ≥900 断点 (tsk_gpPXi-icyeOE)
对照 design/ui_kits mobile+tablet 原型逐屏补齐 Flutter 客户端:

- l10n 资源层(strings_zh/en,单显)+ Riverpod 状态层(连接状态机/免费额度/
  节点选择/语言/主题),UI 与数据解耦,mock 数据接 API 不动 UI。
- 连接键严格三态(off 虚线轨道环 / connecting 旋转弧 / on 满环+计时+光晕),
  状态来自 connectionProvider,点击只派发事件——禁止乐观显示。
- 节点页置顶「智能选择」推荐卡(clay 渐变 zap + 推荐胶囊,默认选中);
  免费额度卡(剩余分钟+进度条 ≤3 分钟切 warning + 看广告解锁变绿)。
- Tab 左右滑动切换(手势竞技场仲裁,子页滚动不误触发,200ms 方向感知滑入)。
- iPad/宽屏 ≥900 LayoutBuilder 切侧栏分栏(导航行高 ≥48,连接页双栏/节点双列网格),
  复用同一批原子组件,不 fork 页面。
- 语义 token 零硬编码;文案全部走 l10n;套餐数字对齐 §7;无支付表单/emoji 国旗。
- CI 红线词扫描扩展到 client/lib;新增 Flutter analyze+test CI 任务。
- 测试:连接状态机/额度/节点单测、连接键三态与卡片组件测试、
  golden(连接键三态/推荐卡/额度卡 × 明暗)。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 14:32:36 +08:00

96 lines
3.1 KiB
Bash

#!/usr/bin/env bash
# scan-redline.sh — 脱敏红线词扫描(UI 文案资源)。
#
# 扫描范围: design/ui_kits/**/*.{jsx,js,html}
# design/flutter/**/*.{dart,html}
# client/lib/**/*.dart ← 生产 Flutter 客户端(界面文案全部走 l10n 资源)
# 不扫描: README.md、CLAUDE.md 等纯文档文件
#
# 红线词(来源: design/CLAUDE.md §1 铁律 13):
# VPN 翻墙 科学上网 突破封锁 自由穿越 Go anywhere
#
# 允许例外:
# - 纯注释行 (// ... 或 /* ... 或 * ... 开头)
# - 外部渠道 handle (@PangolinVPN_bot / @pangolinvpn 等)
#
# 发现违规 → 非零退出码 (CI fail)。
set -euo pipefail
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
cd "$REPO_ROOT"
VIOLATIONS=0
SCANNED=0
# 逐文件扫描函数
# 用法: scan_file <文件路径>
scan_file() {
local file="$1"
local file_violations=0
# 逐个红线词扫描
for word in 'VPN' '翻墙' '科学上网' '突破封锁' '自由穿越' '[Gg]o anywhere'; do
# 1. 找出含有红线词的行
# 2. 排除纯注释行 (行首可选空白 + // 或 /* 或 *)
# 3. 排除外部渠道 handle 行 (@PangolinVPN_bot / @pangolinvpn)
local hits
hits="$(grep -nE "$word" "$file" 2>/dev/null \
| grep -vE '^[0-9]+:[[:space:]]*(//|/\*|\*)' \
| grep -vE '@[Pp]angolin[Vv][Pp][Nn]_?[Bb]ot' \
| grep -vE '@pangolinvpn' \
|| true)"
if [ -n "$hits" ]; then
if [ "$file_violations" -eq 0 ]; then
echo "$file" >&2
fi
echo "$hits" | while IFS= read -r line; do
printf ' 红线词 [%s] %s\n' "$word" "$line" >&2
done
file_violations=1
fi
done
return "$file_violations"
}
echo "→ 开始脱敏扫描 ..."
# 扫描 design/ui_kits 下的 jsx / js / html 文件
while IFS= read -r -d '' f; do
SCANNED=$((SCANNED + 1))
if ! scan_file "$f"; then
VIOLATIONS=$((VIOLATIONS + 1))
fi
done < <(find design/ui_kits -type f \( -name "*.jsx" -o -name "*.js" -o -name "*.html" \) -not -name "README.md" -print0)
# 扫描 design/flutter 下的 dart / html 文件
while IFS= read -r -d '' f; do
SCANNED=$((SCANNED + 1))
if ! scan_file "$f"; then
VIOLATIONS=$((VIOLATIONS + 1))
fi
done < <(find design/flutter -type f \( -name "*.dart" -o -name "*.html" \) -not -name "README.md" -print0)
# 扫描生产 Flutter 客户端 client/lib 下的 dart 文件(排除构建产物)
if [ -d client/lib ]; then
while IFS= read -r -d '' f; do
SCANNED=$((SCANNED + 1))
if ! scan_file "$f"; then
VIOLATIONS=$((VIOLATIONS + 1))
fi
done < <(find client/lib -type f -name "*.dart" -not -path '*/.dart_tool/*' -not -path '*/build/*' -print0)
fi
echo "→ 扫描完成:共 ${SCANNED} 个文件,${VIOLATIONS} 个违规。"
echo ""
if [ "$VIOLATIONS" -ne 0 ]; then
echo "脱敏检查失败!请根据 design/CLAUDE.md §1 铁律 13 修改以上文案:" >&2
echo " - 禁用词:VPN、翻墙、科学上网、突破封锁、自由穿越、Go anywhere" >&2
echo " - 代用词:网络加速、极速畅连、稳定、加速线路、隐私保护、无日志" >&2
exit 1
fi
echo "✅ 脱敏扫描通过 — 未发现红线词。"