logo和名称替换

This commit is contained in:
谢宇宁
2026-10-14 11:23:36 +07:00
parent 1cb514cd02
commit c5c04a7967
478 changed files with 8990 additions and 4948 deletions
@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:hgmj/assets_tool/images.dart';
import 'package:hgmj/hj_utils/screen.dart';
import 'package:wydj/assets_tool/images.dart';
import 'package:wydj/hj_utils/screen.dart';
import 'package:mobkit_dashed_border/mobkit_dashed_border.dart';
class AddMediaSourceButton extends StatelessWidget {
@@ -43,11 +43,13 @@ class AddMediaSourceButton extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.center,
children: [
((111 - 24) / 2).sizeBoxH,
Image.asset('add_grey.png'.communityPath, width: 24, color: const Color(0xffDCDCDC)),
Image.asset('add_grey.png'.communityPath,
width: 24, color: const Color(0xffDCDCDC)),
9.sizeBoxH,
Text(
title ?? (isVideo ? '添加视频' : '添加图片'),
style: TextStyle(color: const Color(0xff999999), fontSize: 14.sp),
style:
TextStyle(color: const Color(0xff999999), fontSize: 14.sp),
),
],
),
@@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
import 'package:hgmj/tools_base/widget/card_swiper/src/swiper_plugin.dart';
import 'package:wydj/tools_base/widget/card_swiper/src/swiper_plugin.dart';
class SwiperControl extends SwiperPlugin {
const SwiperControl({
+21 -8
View File
@@ -1,8 +1,8 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:hgmj/assets_tool/app_colors.dart';
import 'package:hgmj/hj_utils/screen.dart';
import 'package:hgmj/tools_base/widget/common_dialog.dart';
import 'package:wydj/assets_tool/app_colors.dart';
import 'package:wydj/hj_utils/screen.dart';
import 'package:wydj/tools_base/widget/common_dialog.dart';
/// 全站统一的提示/确认弹窗:标题 + 分割线 + 正文 + 副文案 + 灰「取消」红「确定」双按钮。
/// 壳走 [CommonDialog],业务结果一律用返回值传(点确定=true),别在弹窗里塞跳转逻辑。
@@ -68,7 +68,10 @@ class CommonAlert extends StatelessWidget {
children: [
Text(
title,
style: TextStyle(color: Colors.white.withValues(alpha: .9), fontSize: 20, fontWeight: FontWeight.w600),
style: TextStyle(
color: Colors.white.withValues(alpha: .9),
fontSize: 20,
fontWeight: FontWeight.w600),
),
if (showDivider) ...[
12.sizeBoxH,
@@ -79,7 +82,10 @@ class CommonAlert extends StatelessWidget {
Text(
content!,
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white.withValues(alpha: .5), fontSize: 16, fontWeight: FontWeight.w500),
style: TextStyle(
color: Colors.white.withValues(alpha: .5),
fontSize: 16,
fontWeight: FontWeight.w500),
),
],
if (subContent?.isNotEmpty == true) ...[
@@ -89,7 +95,8 @@ class CommonAlert extends StatelessWidget {
child: Text(
subContent!,
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white.withValues(alpha: .5), fontSize: 16),
style: TextStyle(
color: Colors.white.withValues(alpha: .5), fontSize: 16),
),
),
],
@@ -111,7 +118,10 @@ class CommonAlert extends StatelessWidget {
),
child: Text(
cancelText,
style: const TextStyle(color: Color(0xff989898), fontSize: 16, fontWeight: FontWeight.w500),
style: const TextStyle(
color: Color(0xff989898),
fontSize: 16,
fontWeight: FontWeight.w500),
),
),
),
@@ -129,7 +139,10 @@ class CommonAlert extends StatelessWidget {
),
child: Text(
confirmText,
style: const TextStyle(color: Colors.black, fontSize: 16, fontWeight: FontWeight.w500),
style: const TextStyle(
color: Colors.black,
fontSize: 16,
fontWeight: FontWeight.w500),
),
),
),
+35 -14
View File
@@ -1,12 +1,12 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:hgmj/assets_tool/images.dart';
import 'package:hgmj/hj_utils/screen.dart';
import 'package:wydj/assets_tool/images.dart';
import 'package:wydj/hj_utils/screen.dart';
import '../../assets_tool/app_colors.dart';
import '../../hj_utils/api_service/acg_service.dart';
import '../../hj_utils/api_service/mine_service.dart';
import 'package:hgmj/tools_base/toast.dart';
import 'package:wydj/tools_base/toast.dart';
import '../../hj_utils/widget_util.dart';
enum FollowEnum {
@@ -64,7 +64,9 @@ class _FollowButtonState extends State<FollowButton> {
child: isLoading
? _loading()
: Image.asset(
isFollow ? 'collect_red.png'.commonImgPath : 'collect_path.png'.commonImgPath,
isFollow
? 'collect_red.png'.commonImgPath
: 'collect_path.png'.commonImgPath,
width: 24,
),
);
@@ -86,11 +88,17 @@ class _FollowButtonState extends State<FollowButton> {
),
child: Row(
children: [
isLoading ? _loading() : const Icon(Icons.check, size: 14, color: Color(0xff989898)),
isLoading
? _loading()
: const Icon(Icons.check,
size: 14, color: Color(0xff989898)),
4.sizeBoxW,
const Text(
'关注',
style: TextStyle(fontSize: 10, fontWeight: FontWeight.w500, color: Color(0xff989898)),
style: TextStyle(
fontSize: 10,
fontWeight: FontWeight.w500,
color: Color(0xff989898)),
),
],
),
@@ -104,11 +112,17 @@ class _FollowButtonState extends State<FollowButton> {
),
child: Row(
children: [
isLoading ? _loading() : const Icon(Icons.add, size: 14, color: AppColors.actionRed),
isLoading
? _loading()
: const Icon(Icons.add,
size: 14, color: AppColors.actionRed),
4.sizeBoxW,
const Text(
'关注',
style: TextStyle(fontSize: 10, fontWeight: FontWeight.w500, color: AppColors.actionRed),
style: TextStyle(
fontSize: 10,
fontWeight: FontWeight.w500,
color: AppColors.actionRed),
),
],
),
@@ -132,20 +146,25 @@ class _FollowButtonState extends State<FollowButton> {
borderRadius: BorderRadius.circular(3),
),
child: isFollow
? Text('已收藏', style: textStyle(10, Colors.white, FontWeight.w400))
? Text('已收藏',
style: textStyle(10, Colors.white, FontWeight.w400))
: Row(
mainAxisSize: MainAxisSize.min,
children: [
Image.asset('add_red.png'.commonImgPath, width: 16, color: Colors.black),
Image.asset('add_red.png'.commonImgPath,
width: 16, color: Colors.black),
2.sizeBoxW,
Text('收藏', style: textStyle(10, Colors.black, FontWeight.w400)),
Text('收藏',
style:
textStyle(10, Colors.black, FontWeight.w400)),
],
),
),
);
}
Widget _loading() => const CupertinoActivityIndicator(color: Colors.white, radius: 8);
Widget _loading() =>
const CupertinoActivityIndicator(color: Colors.white, radius: 8);
//加入书架 / 取消收藏
void _onCollectTap() => isFollow ? _unCollect() : _collect();
@@ -153,7 +172,8 @@ class _FollowButtonState extends State<FollowButton> {
void _unCollect() async {
if (isLoading) return;
setState(() => isLoading = true);
if (await ACGService.deleteBookshelf(mediaId ?? '')) widget.onSuccess?.call(false);
if (await ACGService.deleteBookshelf(mediaId ?? ''))
widget.onSuccess?.call(false);
isLoading = false;
if (mounted) setState(() {});
}
@@ -161,7 +181,8 @@ class _FollowButtonState extends State<FollowButton> {
void _collect() async {
if (isLoading) return;
setState(() => isLoading = true);
if (await ACGService.addBookshelf(mediaId ?? '')) widget.onSuccess?.call(true);
if (await ACGService.addBookshelf(mediaId ?? ''))
widget.onSuccess?.call(true);
isLoading = false;
if (mounted) setState(() {});
}
+3 -2
View File
@@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
import 'package:hgmj/tools_base/widget/net_image_widget.dart';
import 'package:wydj/tools_base/widget/net_image_widget.dart';
///用户头像
class HeaderWidget extends StatelessWidget {
@@ -27,7 +27,8 @@ class HeaderWidget extends StatelessWidget {
height: headHeight,
decoration: isCircle
? const BoxDecoration(
border: Border.fromBorderSide(BorderSide(width: 4, color: Color.fromRGBO(253, 45, 85, 1))),
border: Border.fromBorderSide(
BorderSide(width: 4, color: Color.fromRGBO(253, 45, 85, 1))),
shape: BoxShape.circle,
)
: null,
+61 -31
View File
@@ -1,12 +1,12 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:hgmj/assets_tool/app_colors.dart';
import 'package:hgmj/assets_tool/images.dart';
import 'package:hgmj/hj_utils/image_util.dart';
import 'package:hgmj/tools_base/cache/image_cache_manager.dart';
import 'package:hgmj/tools_base/loading/loading_alert_widget.dart';
import 'package:hgmj/tools_base/toast.dart';
import 'package:hgmj/tools_base/widget/net_image_widget.dart';
import 'package:wydj/assets_tool/app_colors.dart';
import 'package:wydj/assets_tool/images.dart';
import 'package:wydj/hj_utils/image_util.dart';
import 'package:wydj/tools_base/cache/image_cache_manager.dart';
import 'package:wydj/tools_base/loading/loading_alert_widget.dart';
import 'package:wydj/tools_base/toast.dart';
import 'package:wydj/tools_base/widget/net_image_widget.dart';
/// 微信风格图片浏览器
/// 横滑切图 + 双指/双击缩放 + 上下滑拖拽退出(图片跟手、背景随拖动渐隐露出下层页面) + 长按保存
@@ -20,18 +20,26 @@ class ImageBrowserPage extends StatefulWidget {
final int initialIndex;
final bool showSaveButton; // 右上角显式"保存到相册"按钮(AI 生成图等场景);默认只支持长按保存
const ImageBrowserPage({super.key, required this.images, this.initialIndex = 0, this.showSaveButton = false});
const ImageBrowserPage(
{super.key,
required this.images,
this.initialIndex = 0,
this.showSaveButton = false});
/// 打开浏览器(透明路由 + 淡入)
/// [showSaveButton] 显示右上角"保存到相册"按钮
static void open(List<String> images, {int index = 0, bool showSaveButton = false}) {
static void open(List<String> images,
{int index = 0, bool showSaveButton = false}) {
final valid = images.where((e) => e.isNotEmpty).toList();
if (valid.isEmpty) return;
// fullscreenDialog:true → GetX canTransitionTo 返回 false,下层页面不做外出转场,
// 保持完整渲染 → 拖拽偷看时看到的是整页而非"pop 一半"。
// 瞬时 fadeIn:打开无残影。仍是 Get.to → Get.back 能正常 pop,下滑退出正常
Get.to(
() => ImageBrowserPage(images: valid, initialIndex: index.clamp(0, valid.length - 1), showSaveButton: showSaveButton),
() => ImageBrowserPage(
images: valid,
initialIndex: index.clamp(0, valid.length - 1),
showSaveButton: showSaveButton),
opaque: false,
transition: Transition.fadeIn,
duration: Duration.zero,
@@ -43,7 +51,8 @@ class ImageBrowserPage extends StatefulWidget {
State<ImageBrowserPage> createState() => _ImageBrowserPageState();
}
class _ImageBrowserPageState extends State<ImageBrowserPage> with TickerProviderStateMixin {
class _ImageBrowserPageState extends State<ImageBrowserPage>
with TickerProviderStateMixin {
// ========== 分页 ==========
late final PageController _pageCtr;
late int _curIndex;
@@ -72,11 +81,17 @@ class _ImageBrowserPageState extends State<ImageBrowserPage> with TickerProvider
super.initState();
_curIndex = widget.initialIndex;
_pageCtr = PageController(initialPage: _curIndex);
_transCtrs = List.generate(widget.images.length, (_) => TransformationController());
_resetCtr = AnimationController(vsync: this, duration: const Duration(milliseconds: 200));
_zoomCtr = AnimationController(vsync: this, duration: const Duration(milliseconds: 200));
_enterCtr = AnimationController(vsync: this, duration: const Duration(milliseconds: 220))..forward();
_exitCtr = AnimationController(vsync: this, duration: const Duration(milliseconds: 200));
_transCtrs =
List.generate(widget.images.length, (_) => TransformationController());
_resetCtr = AnimationController(
vsync: this, duration: const Duration(milliseconds: 200));
_zoomCtr = AnimationController(
vsync: this, duration: const Duration(milliseconds: 200));
_enterCtr = AnimationController(
vsync: this, duration: const Duration(milliseconds: 220))
..forward();
_exitCtr = AnimationController(
vsync: this, duration: const Duration(milliseconds: 200));
}
@override
@@ -97,10 +112,12 @@ class _ImageBrowserPageState extends State<ImageBrowserPage> with TickerProvider
bool get _isZoomed => _transCtrs[_curIndex].value.getMaxScaleOnAxis() > 1.05;
// 背景不透明度:随竖直拖动距离渐隐(下拉偷看下层)
double get _bgOpacity => (1 - _dragY.abs() / (Get.height * 0.6)).clamp(0.0, 1.0);
double get _bgOpacity =>
(1 - _dragY.abs() / (Get.height * 0.6)).clamp(0.0, 1.0);
// 拖动时图片轻微缩小
double get _dragScale => (1 - _dragY.abs() / (Get.height * 2)).clamp(0.85, 1.0);
double get _dragScale =>
(1 - _dragY.abs() / (Get.height * 2)).clamp(0.85, 1.0);
// 退出淡出系数:1→0
double get _exitFactor => 1 - _exitCtr.value;
@@ -119,8 +136,8 @@ class _ImageBrowserPageState extends State<ImageBrowserPage> with TickerProvider
_exit();
return;
}
final anim =
Tween<double>(begin: _dragY, end: 0).animate(CurvedAnimation(parent: _resetCtr, curve: Curves.easeOut));
final anim = Tween<double>(begin: _dragY, end: 0)
.animate(CurvedAnimation(parent: _resetCtr, curve: Curves.easeOut));
void listener() => setState(() => _dragY = anim.value);
anim.addListener(listener);
// whenComplete 在 dispose 取消 ticker 时也会触发,一律先判 mounted
@@ -156,8 +173,8 @@ class _ImageBrowserPageState extends State<ImageBrowserPage> with TickerProvider
-pos.dx * (scale - 1), -pos.dy * (scale - 1), 0, 1, //
);
}
final anim =
Matrix4Tween(begin: ctr.value, end: target).animate(CurvedAnimation(parent: _zoomCtr, curve: Curves.easeOut));
final anim = Matrix4Tween(begin: ctr.value, end: target)
.animate(CurvedAnimation(parent: _zoomCtr, curve: Curves.easeOut));
void listener() => ctr.value = anim.value;
anim.addListener(listener);
_zoomCtr.forward(from: 0).whenComplete(() {
@@ -195,7 +212,10 @@ class _ImageBrowserPageState extends State<ImageBrowserPage> with TickerProvider
builder: (_, __) => Stack(
children: [
// 黑色背景,随拖动/退出渐隐
Positioned.fill(child: ColoredBox(color: Colors.black.withValues(alpha: _bgOpacity * _exitFactor))),
Positioned.fill(
child: ColoredBox(
color: Colors.black
.withValues(alpha: _bgOpacity * _exitFactor))),
GestureDetector(
onLongPress: _saveCurrent, // 长按保存
onDoubleTapDown: (d) => _tapPos = d.localPosition,
@@ -209,7 +229,8 @@ class _ImageBrowserPageState extends State<ImageBrowserPage> with TickerProvider
opacity: _enterCtr,
child: Transform.translate(
offset: Offset(0, _dragY),
child: Transform.scale(scale: _dragScale, child: _pageView()),
child:
Transform.scale(scale: _dragScale, child: _pageView()),
),
),
),
@@ -226,7 +247,9 @@ class _ImageBrowserPageState extends State<ImageBrowserPage> with TickerProvider
if (_isSaving)
const Positioned.fill(
child: AbsorbPointer(
child: ColoredBox(color: Color(0x80000000), child: LoadingAlertWidget(title: '保存中...')),
child: ColoredBox(
color: Color(0x80000000),
child: LoadingAlertWidget(title: '保存中...')),
),
),
],
@@ -272,7 +295,8 @@ class _ImageBrowserPageState extends State<ImageBrowserPage> with TickerProvider
right: 20,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 11, vertical: 2),
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(20)),
decoration: BoxDecoration(
color: Colors.white, borderRadius: BorderRadius.circular(20)),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
@@ -287,7 +311,8 @@ class _ImageBrowserPageState extends State<ImageBrowserPage> with TickerProvider
: (isIncoming ? const Offset(0, -1) : const Offset(0, 1));
return ClipRect(
child: SlideTransition(
position: Tween<Offset>(begin: begin, end: Offset.zero).animate(anim),
position: Tween<Offset>(begin: begin, end: Offset.zero)
.animate(anim),
child: child,
),
);
@@ -295,10 +320,12 @@ class _ImageBrowserPageState extends State<ImageBrowserPage> with TickerProvider
child: Text(
'${_curIndex + 1}',
key: ValueKey(_curIndex),
style: const TextStyle(color: AppColors.actionRed, fontSize: 12),
style:
const TextStyle(color: AppColors.actionRed, fontSize: 12),
),
),
Text('/${widget.images.length}', style: const TextStyle(color: Color(0xff3D3D3D), fontSize: 12)),
Text('/${widget.images.length}',
style: const TextStyle(color: Color(0xff3D3D3D), fontSize: 12)),
],
),
),
@@ -331,8 +358,11 @@ class _ImageBrowserPageState extends State<ImageBrowserPage> with TickerProvider
onTap: _saveCurrent,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(4), color: const Color(0xFFE57310)),
child: const Text('保存到相册', style: TextStyle(color: Colors.white, fontSize: 14)),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4),
color: const Color(0xFFE57310)),
child: const Text('保存到相册',
style: TextStyle(color: Colors.white, fontSize: 14)),
),
),
),
+11 -6
View File
@@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
import 'package:hgmj/assets_tool/images.dart';
import 'package:wydj/assets_tool/images.dart';
/// 双击点赞爱心动效的触发器。onDoubleTapDown 里 [markAt] 记落点,onDoubleTap 里 [burst] 放动画
class LikeBurstController extends ChangeNotifier {
@@ -31,16 +31,19 @@ class LikeBurstView extends StatefulWidget {
State<LikeBurstView> createState() => _LikeBurstViewState();
}
class _LikeBurstViewState extends State<LikeBurstView> with SingleTickerProviderStateMixin {
class _LikeBurstViewState extends State<LikeBurstView>
with SingleTickerProviderStateMixin {
late final AnimationController _ctr;
Offset? _at;
@override
void initState() {
super.initState();
_ctr = AnimationController(vsync: this, duration: const Duration(milliseconds: 600))
_ctr = AnimationController(
vsync: this, duration: const Duration(milliseconds: 600))
..addStatusListener((status) {
if (status == AnimationStatus.completed && mounted) setState(() => _at = null);
if (status == AnimationStatus.completed && mounted)
setState(() => _at = null);
});
widget.controller.addListener(_onBurst);
}
@@ -81,8 +84,10 @@ class _LikeBurstViewState extends State<LikeBurstView> with SingleTickerProvider
TweenSequenceItem(tween: Tween(begin: 1.0, end: 0.0), weight: 40),
]).animate(_ctr),
child: ScaleTransition(
scale: Tween(begin: 0.5, end: 1.3).animate(CurvedAnimation(parent: _ctr, curve: Curves.easeOutBack)),
child: Image.asset(widget.icon.commonImgPath, width: widget.size, height: widget.size),
scale: Tween(begin: 0.5, end: 1.3).animate(
CurvedAnimation(parent: _ctr, curve: Curves.easeOutBack)),
child: Image.asset(widget.icon.commonImgPath,
width: widget.size, height: widget.size),
),
),
),
+13 -7
View File
@@ -2,9 +2,9 @@ import 'dart:ui';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:hgmj/assets_tool/images.dart';
import 'package:hgmj/hj_utils/screen.dart';
import 'package:hgmj/tools_base/cache/image_cache_manager.dart';
import 'package:wydj/assets_tool/images.dart';
import 'package:wydj/hj_utils/screen.dart';
import 'package:wydj/tools_base/cache/image_cache_manager.dart';
class NetworkImageLoader extends StatelessWidget {
final String? imageUrl;
@@ -55,12 +55,15 @@ class NetworkImageLoader extends StatelessWidget {
fadeOutCurve: Curves.linear,
);
final radius = imgBorderRadius ?? BorderRadius.circular(borderRadius);
if (borderRadius != 0) image = ClipRRect(borderRadius: radius, child: image);
if (borderRadius != 0)
image = ClipRRect(borderRadius: radius, child: image);
//模糊会溢出边界,外面再裁一层
if (blur) {
image = ClipRRect(
borderRadius: radius,
child: ImageFiltered(imageFilter: ImageFilter.blur(sigmaX: 5, sigmaY: 5), child: image),
child: ImageFiltered(
imageFilter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
child: image),
);
}
return image;
@@ -72,7 +75,9 @@ class NetworkImageLoader extends StatelessWidget {
final dpr = screen.devicePixelRatio;
if (!isResizeImage) return (screen.screenWidth * dpr).toInt();
//约束无限时用屏幕宽兜底,避免退化成按原图解码(图片过载)
final w = (cons.maxWidth == double.infinity || cons.maxWidth.isNaN) ? screen.screenWidth : cons.maxWidth;
final w = (cons.maxWidth == double.infinity || cons.maxWidth.isNaN)
? screen.screenWidth
: cons.maxWidth;
return (w * dpr).toInt();
}
@@ -82,7 +87,8 @@ class NetworkImageLoader extends StatelessWidget {
padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 2),
decoration: const BoxDecoration(color: Color(0xff151E2D)),
alignment: Alignment.center,
child: Image.asset('place_holder_logo.webp'.commonImgPath, width: 100, height: 35),
child: Image.asset('place_holder_logo.webp'.commonImgPath,
width: 100, height: 35),
);
}
}
@@ -8,15 +8,14 @@ import 'dart:math';
import 'package:collection/collection.dart' show IterableExtension;
import 'package:flutter/scheduler.dart';
import 'package:flutter/widgets.dart';
import 'package:hgmj/tools_base/widget/scroll_positioned_list/src/item_positions_listener.dart';
import 'package:hgmj/tools_base/widget/scroll_positioned_list/src/item_positions_notifier.dart';
import 'package:hgmj/tools_base/widget/scroll_positioned_list/src/scroll_offset_listener.dart';
import 'package:wydj/tools_base/widget/scroll_positioned_list/src/item_positions_listener.dart';
import 'package:wydj/tools_base/widget/scroll_positioned_list/src/item_positions_notifier.dart';
import 'package:wydj/tools_base/widget/scroll_positioned_list/src/scroll_offset_listener.dart';
import 'positioned_list.dart';
import 'post_mount_callback.dart';
import 'scroll_offset_notifier.dart';
/// Number of screens to scroll when scrolling a long distance.
const int _screenScrollCount = 2;