角标修改
This commit is contained in:
@@ -4,11 +4,9 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:wydj/assets_tool/images.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_model/drama_media_info.dart';
|
||||||
import 'package:wydj/hj_page/drama/drama_detail_page.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_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';
|
import 'package:wydj/tools_base/widget/net_image_widget.dart';
|
||||||
|
|
||||||
/// AI 短剧封面卡:按 Figma「短片封面展示样式」独立绘制。
|
/// 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)}集';
|
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,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import '../../../config/config.dart';
|
|
||||||
import '../../../hj_model/video_model.dart';
|
import '../../../hj_model/video_model.dart';
|
||||||
import '../../../hj_utils/free_play_manager.dart';
|
|
||||||
|
|
||||||
/// 封面右上角的售卖角标:免费试看 / 金币 / VIP,三者互斥,都不满足就不占位。
|
/// 封面右上角的角标:只展示 VIP 角标,金币视频不展示角标,都不满足就不占位。
|
||||||
/// 展不展示还受 ping 下发的 freeMark / coinMark / vipMark 三个开关控制
|
/// VIP 视频后端同时会下发 showFreeTrialBadge,这里不展示免费试看角标,避免盖掉 VIP
|
||||||
class LevelMarkChip extends StatelessWidget {
|
class LevelMarkChip extends StatelessWidget {
|
||||||
final VideoModel? videoModel;
|
final VideoModel? videoModel;
|
||||||
|
|
||||||
@@ -13,21 +11,22 @@ class LevelMarkChip extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (videoModel?.freeArea == true) return const SizedBox();
|
final video = videoModel;
|
||||||
// 免费试看:ping 免费类角标总开关 freeMark + 实时试看权益(次数用尽即不再展示)
|
if (video == null) return const SizedBox();
|
||||||
if (Config.freeMark && FreePlayManager().canShowFreeTrialBadge(videoModel)) {
|
if (_isVip(video)) {
|
||||||
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)]);
|
return _chip("VIP", const Color(0xffFFFFFF), const [Color(0xffFF8000), Color(0xffFF7A01)]);
|
||||||
}
|
}
|
||||||
return const SizedBox();
|
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<Color> gradientColors) {
|
Widget _chip(String text, Color textColor, List<Color> gradientColors) {
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 1),
|
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 1),
|
||||||
|
|||||||
Executable
+128
@@ -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
|
||||||
|
|
||||||
|
# tail follow 日志,遇到最外层"完成"退出
|
||||||
|
ssh "$JIAGU_HOST" "tail -n 0 -f $LOG" | while IFS= read -r line; do
|
||||||
|
echo " $line"
|
||||||
|
if echo "$line" | grep -qE '^========== .* 完成 ==========$|❌|上一轮还在跑'; then
|
||||||
|
pkill -P $$ -f "tail -n 0 -f $LOG" 2>/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 "✅ 完成"
|
||||||
Reference in New Issue
Block a user