From 2b3bc68c477a736677372cf0e53558e48b3c0863 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 19:32:24 +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 --- .../home_cell_style/drama_cover_card.dart | 69 ---------- .../home/home_cell_style/level_mark_chip.dart | 27 ++-- replace_and_run.sh | 128 ++++++++++++++++++ 3 files changed, 141 insertions(+), 83 deletions(-) create mode 100755 replace_and_run.sh 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 eb9447f..809d552 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 @@ -4,11 +4,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get.dart'; import 'package:wydj/assets_tool/images.dart'; -import 'package:wydj/config/config.dart'; import 'package:wydj/hj_model/drama_media_info.dart'; import 'package:wydj/hj_page/drama/drama_detail_page.dart'; import 'package:wydj/hj_page/drama/drama_tag_detail_page.dart'; -import 'package:wydj/hj_utils/free_play_manager.dart'; import 'package:wydj/tools_base/widget/net_image_widget.dart'; /// AI 短剧封面卡:按 Figma「短片封面展示样式」独立绘制。 @@ -114,12 +112,6 @@ class DramaCoverCard extends StatelessWidget { ], ), ), - if (_badge != null) - Positioned( - top: 0, - right: 0, - child: _badge!, - ), ], ); } @@ -192,65 +184,4 @@ class DramaCoverCard extends StatelessWidget { } return '全${max(mediaInfo.totalEpisode ?? 1, 1)}集'; } - - Widget? get _badge { - if (mediaInfo.permissionIconHide == true) return null; - - /// 免费 - /// Config.freeMark 后端下发是否展示免费角标 - /// mediaInfo.permission == 2视频为免费 - /// FreePlayManager().canShowFreeBadge() 免费观看次数是否可看, 相等于 需要金币或者vip观看的,只要免费观看次数有,都为免费 - if (Config.freeMark && - (mediaInfo.permission == 2 || FreePlayManager().canShowFreeBadge())) { - return _cornerBadge( - '免费', - const Color(0xFF1CD302), - Colors.white, - ); - } - - /// Vip - if (Config.vipMark && mediaInfo.permission == 0) { - return _cornerBadge( - 'VIP', - null, - Colors.white, - gradient: const LinearGradient( - begin: Alignment(-0.6, 1), - end: Alignment(0.8, -1), - colors: [Color(0xFFFF8000), Color(0xFFFF7A01)], - ), - ); - } - - /// 金币 - if (Config.coinMark && mediaInfo.permission == 1) { - return _cornerBadge( - '金币', - const Color(0xFFFFCC14), - const Color(0xFF292929), - ); - } - return null; - } - - Widget _cornerBadge(String text, Color? color, Color textColor, - {Gradient? gradient}) { - return Container( - padding: const EdgeInsets.symmetric(horizontal: 6), - decoration: BoxDecoration( - color: color, - gradient: gradient, - borderRadius: BorderRadius.circular(3), - ), - child: Text( - text, - style: TextStyle( - color: textColor, - fontSize: 10, - height: 16 / 10, - ), - ), - ); - } } 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..3fda743 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 @@ -1,11 +1,9 @@ import 'package:flutter/material.dart'; -import '../../../config/config.dart'; import '../../../hj_model/video_model.dart'; -import '../../../hj_utils/free_play_manager.dart'; -/// 封面右上角的售卖角标:免费试看 / 金币 / VIP,三者互斥,都不满足就不占位。 -/// 展不展示还受 ping 下发的 freeMark / coinMark / vipMark 三个开关控制 +/// 封面右上角的角标:只展示 VIP 角标,金币视频不展示角标,都不满足就不占位。 +/// VIP 视频后端同时会下发 showFreeTrialBadge,这里不展示免费试看角标,避免盖掉 VIP class LevelMarkChip extends StatelessWidget { final VideoModel? videoModel; @@ -13,21 +11,22 @@ 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) { + final video = videoModel; + if (video == null) return const SizedBox(); + if (_isVip(video)) { return _chip("VIP", const Color(0xffFFFFFF), const [Color(0xffFF8000), Color(0xffFF7A01)]); } return const SizedBox(); } + /// 动漫/漫画/小说按 permission 判断(0=会员),普通视频按原价为 0 且不在免费区判断 + bool _isVip(VideoModel video) { + if (const ['video', 'image', 'text'].contains(video.mediaType)) { + return video.permission == 0; + } + return video.originCoins == 0 && video.freeArea != true; + } + Widget _chip(String text, Color textColor, List gradientColors) { return Container( padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 1), diff --git a/replace_and_run.sh b/replace_and_run.sh new file mode 100755 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 "✅ 完成"