From 61c290cf64cb991847382427a67879d35b5295ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B0=A2=E5=AE=87=E5=AE=81?= Date: Thu, 5 Nov 2026 17:04:01 +0700 Subject: [PATCH] =?UTF-8?q?=E8=A7=92=E6=A0=87=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/hj_page/cartoon/acg_widget_item.dart | 5 +- .../home_cell_style/drama_cover_card.dart | 16 +-- .../home/home_cell_style/level_mark_chip.dart | 10 +- replace_and_run.sh | 128 ++++++++++++++++++ 4 files changed, 132 insertions(+), 27 deletions(-) create mode 100644 replace_and_run.sh diff --git a/lib/hj_page/cartoon/acg_widget_item.dart b/lib/hj_page/cartoon/acg_widget_item.dart index 50c883a..c0fde7b 100644 --- a/lib/hj_page/cartoon/acg_widget_item.dart +++ b/lib/hj_page/cartoon/acg_widget_item.dart @@ -99,16 +99,13 @@ class AcgItemWidget extends StatelessWidget { } Widget _buildLevelIcon() { - if (info?.permission == 1 && Config.coinMark) - return _levelTag('金币', const Color(0xFF1F2029), - bgColor: [const Color(0xFFFFE580), const Color(0xFFFACC15)]); if (info?.permission == 0 && Config.vipMark) return _levelTag('VIP', Colors.white, bgColor: [const Color(0xFFFF8000), const Color(0xFFFF7A01)]); return const SizedBox.shrink(); } - // 金币/VIP 角标:渐变底 + 文字,仅文字与文字色不同 + // VIP 角标:渐变底 + 文字,仅文字与文字色不同 Widget _levelTag(String text, Color textColor, {List? bgColor}) { return Container( padding: const EdgeInsets.symmetric(horizontal: 6), diff --git a/lib/hj_page/home/home_cell_style/drama_cover_card.dart b/lib/hj_page/home/home_cell_style/drama_cover_card.dart index 52604a4..57b5afc 100644 --- a/lib/hj_page/home/home_cell_style/drama_cover_card.dart +++ b/lib/hj_page/home/home_cell_style/drama_cover_card.dart @@ -8,7 +8,6 @@ import 'package:hjsq/config/config.dart'; import 'package:hjsq/hj_model/drama_media_info.dart'; import 'package:hjsq/hj_page/drama/drama_detail_page.dart'; import 'package:hjsq/hj_page/drama/drama_tag_detail_page.dart'; -import 'package:hjsq/hj_utils/free_play_manager.dart'; import 'package:hjsq/tools_base/widget/net_image_widget.dart'; /// AI 短剧封面卡:按 Figma「短片封面展示样式」独立绘制。 @@ -196,12 +195,9 @@ class DramaCoverCard extends StatelessWidget { Widget? get _badge { if (mediaInfo.permissionIconHide == true) return null; - /// 免费 + /// 免费:仅真正免费的内容(permission == 2)展示;不再因剩余试看次数把 VIP 显示成免费 /// Config.freeMark 后端下发是否展示免费角标 - /// mediaInfo.permission == 2视频为免费 - /// FreePlayManager().canShowFreeBadge() 免费观看次数是否可看, 相等于 需要金币或者vip观看的,只要免费观看次数有,都为免费 - if (Config.freeMark && - (mediaInfo.permission == 2 || FreePlayManager().canShowFreeBadge())) { + if (Config.freeMark && mediaInfo.permission == 2) { return _cornerBadge( '免费', const Color(0xFF1CD302), @@ -223,14 +219,6 @@ class DramaCoverCard extends StatelessWidget { ); } - /// 金币 - if (Config.coinMark && mediaInfo.permission == 1) { - return _cornerBadge( - '金币', - const Color(0xFFFFCC14), - const Color(0xFF292929), - ); - } return null; } diff --git a/lib/hj_page/home/home_cell_style/level_mark_chip.dart b/lib/hj_page/home/home_cell_style/level_mark_chip.dart index 10df0b0..0b74759 100644 --- a/lib/hj_page/home/home_cell_style/level_mark_chip.dart +++ b/lib/hj_page/home/home_cell_style/level_mark_chip.dart @@ -2,9 +2,8 @@ import 'package:flutter/material.dart'; import '../../../config/config.dart'; import '../../../hj_model/video_model.dart'; -import '../../../hj_utils/free_play_manager.dart'; -/// 封面右上角的售卖角标:免费试看 / 金币 / VIP,三者互斥,都不满足就不占位。 +/// 封面右上角的售卖角标:仅 VIP(金币角标已去掉;不再因试看次数显示「免费」)。 /// 展不展示还受 ping 下发的 freeMark / coinMark / vipMark 三个开关控制 class LevelMarkChip extends StatelessWidget { final VideoModel? videoModel; @@ -14,14 +13,7 @@ class LevelMarkChip extends StatelessWidget { @override Widget build(BuildContext context) { if (videoModel?.freeArea == true) return const SizedBox(); - // 免费试看:ping 免费类角标总开关 freeMark + 实时试看权益(次数用尽即不再展示) - if (Config.freeMark && FreePlayManager().canShowFreeTrialBadge(videoModel)) { - return _chip("免费", const Color(0xffffffff), const [Color(0xff1CD302), Color(0xff1CD302)]); - } final isCoin = videoModel?.isCoinVideo() == true; - if (isCoin && Config.coinMark) { - return _chip("金币", const Color(0xff1F2029), const [Color(0xffFFE580), Color(0xffFACC15)]); - } if (!isCoin && Config.vipMark) { return _chip("VIP", const Color(0xffFFFFFF), const [Color(0xffFF8000), Color(0xffFF7A01)]); } diff --git a/replace_and_run.sh b/replace_and_run.sh new file mode 100644 index 0000000..7a7fe31 --- /dev/null +++ b/replace_and_run.sh @@ -0,0 +1,128 @@ +#!/usr/bin/env bash +# ============================================================ +# 手动替换加固模板 APK 并立即触发加固任务(多 app 支持) +# +# 用法: +# ./replace_and_run.sh # 不换模板,只触发一次(六个 app 都跑) +# ./replace_and_run.sh huangguo /path/xxx.apk # 替换 huangguo 模板,再触发 +# ./replace_and_run.sh 91fans /path/xxx.apk # 替换 91fans 模板,再触发 +# ./replace_and_run.sh tangguo /path/xxx.apk # 替换 tangguo 模板,再触发 +# ./replace_and_run.sh hgmj /path/xxx.apk # 替换 hgmj 模板,再触发 +# ./replace_and_run.sh 51dj /path/xxx.apk # 替换 51dj 模板,再触发 +# ./replace_and_run.sh hjsq /path/xxx.apk # 替换 hjsq 模板,再触发 +# ./replace_and_run.sh -n huangguo /path/xxx.apk # 只替换 huangguo 模板,不触发 +# ./replace_and_run.sh -f # 只 follow 远端日志 +# +# App: +# huangguo -> template/hgdj_source.apk (appId=2) +# 91fans -> template/jyfans_source.apk (appId=3) +# tangguo -> template/tgdj_source.apk (appId=4) +# hgmj -> template/hgmj_source.apk (appId=5) +# 51dj -> template/51dj_source.apk (appId=6) +# hjsq -> template/hjsq_source.apk (appId=7) +# ============================================================ + +set -euo pipefail + +JIAGU_HOST=root@139.162.47.194 +JIAGU_DIR=/root/JiaguTool +LOG=$JIAGU_DIR/auto_jiagu.log + +# app -> 服务器上模板文件名 +declare_template() { + case "$1" in + huangguo) echo "hgdj_source.apk" ;; + 91fans) echo "jyfans_source.apk" ;; + tangguo) echo "tgdj_source.apk" ;; + hgmj) echo "hgmj_source.apk" ;; + 51dj) echo "51dj_source.apk" ;; + hjsq) echo "hjsq_source.apk" ;; + *) echo "" ;; + esac +} + +NO_RUN=0 +FOLLOW_ONLY=0 +APP="" +APK="" + +while [ $# -gt 0 ]; do + case "$1" in + -n) NO_RUN=1; shift ;; + -f) FOLLOW_ONLY=1; shift ;; + -h|--help) + sed -n '3,22p' "$0"; exit 0 ;; + huangguo|91fans|tangguo|hgmj|51dj|hjsq) + APP="$1"; shift ;; + *) APK="$1"; shift ;; + esac +done + +log() { echo "[$(date +'%H:%M:%S')] $*"; } + +if [ "$FOLLOW_ONLY" -eq 1 ]; then + log "→ follow 远端日志(Ctrl+C 退出)" + ssh "$JIAGU_HOST" "tail -f $LOG" + exit 0 +fi + +# ---------- 替换模板 APK ---------- +if [ -n "$APK" ]; then + [ -z "$APP" ] && { echo "❌ 提供 APK 时必须先指定 app: huangguo | 91fans | tangguo | hgmj | 51dj | hjsq"; exit 1; } + [ ! -f "$APK" ] && { echo "❌ APK 不存在: $APK"; exit 1; } + TPL=$(declare_template "$APP") + [ -z "$TPL" ] && { echo "❌ 未知 app: $APP"; exit 1; } + + TEMPLATE=$JIAGU_DIR/template/$TPL + SIZE=$(stat -f%z "$APK" 2>/dev/null || stat -c%s "$APK") + log "→ [$APP] 上传 $(basename $APK) ($SIZE bytes) → $TEMPLATE" + scp -C "$APK" "$JIAGU_HOST:$TEMPLATE" + ssh "$JIAGU_HOST" "chmod 600 $TEMPLATE && ls -l $TEMPLATE" +fi + +if [ "$NO_RUN" -eq 1 ]; then + log "✓ 只替换模板,不触发(-n)" + exit 0 +fi + +# ---------- 触发一次加固(六 app 都跑,由 auto_jiagu.sh 内部循环)---------- +log "→ 远端触发 $JIAGU_DIR/auto_jiagu.sh(六 app 依次加固,约 4-6 分钟)" + +ssh "$JIAGU_HOST" "nohup $JIAGU_DIR/auto_jiagu.sh >/dev/null 2>&1 &" /dev/null || true + break + fi +done + +log "→ 拉取最终状态" +ssh "$JIAGU_HOST" "bash -c ' + echo \"----- S3 huangguo/ 最新 -----\" + aws s3 ls s3://meirenyu/huangguo/ | grep -v channels/ | tail -3 + echo \"\" + echo \"----- S3 91fans/ 最新 -----\" + aws s3 ls s3://meirenyu/91fans/ | tail -3 + echo \"\" + echo \"----- S3 tangguo/ 最新 -----\" + aws s3 ls s3://meirenyu/tangguo/ | tail -3 + echo \"\" + echo \"----- S3 hgmj/ 最新 -----\" + aws s3 ls s3://meirenyu/hgmj/ | tail -3 + echo \"\" + echo \"----- S3 51dj/ 最新 -----\" + aws s3 ls s3://meirenyu/51dj/ | tail -3 + echo \"\" + echo \"----- S3 hjsq/ 最新 -----\" + aws s3 ls s3://meirenyu/hjsq/ | tail -3 + echo \"\" + echo \"----- MongoDB link -----\" + mongosh \"mongodb://stat_center:v5weEdNvXnJCMr9TeFFm@172.104.52.130:27017,172.104.52.26:27017,172.104.52.242:27017/stat_center?authSource=stat_center&replicaSet=fish0\" --quiet --eval \" + db.getCollection(\\\"version\\\").find({appId:{\\\$in:[2,3,4,5,6,7]}}).forEach(d => print(\\\"appId=\\\" + d.appId + \\\" \\\" + d.link[0])); + \" +'" + +log "✅ 完成"