f97ae8186b
对照 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>
96 lines
3.1 KiB
Bash
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 "✅ 脱敏扫描通过 — 未发现红线词。"
|