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
+19 -12
View File
@@ -1,13 +1,13 @@
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/api_service/mine_service.dart';
import 'package:hgmj/hj_utils/screen.dart';
import 'package:hgmj/tools_base/loading/loading_center_widget.dart';
import 'package:hgmj/tools_base/refresh/pull_refresh.dart';
import 'package:wydj/assets_tool/app_colors.dart';
import 'package:wydj/assets_tool/images.dart';
import 'package:wydj/hj_utils/api_service/mine_service.dart';
import 'package:wydj/hj_utils/screen.dart';
import 'package:wydj/tools_base/loading/loading_center_widget.dart';
import 'package:wydj/tools_base/refresh/pull_refresh.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'package:hgmj/tools_base/widget/sheet_handle_bar.dart';
import 'package:wydj/tools_base/widget/sheet_handle_bar.dart';
import '../../../hj_utils/widget_util.dart';
import '../../mine/mine_vip/coupon_model.dart';
@@ -42,7 +42,9 @@ class _AICouponSheetState extends State<AICouponSheet> {
dataList ??= []; //首屏失败也要退出 loading,否则永远转圈
setState(() {});
if (page == 1) refreshCtr?.refreshCompleted();
(res?.length ?? 0) < size ? refreshCtr?.loadNoData() : refreshCtr?.loadComplete();
(res?.length ?? 0) < size
? refreshCtr?.loadNoData()
: refreshCtr?.loadComplete();
}
Future<void> loadMore() => loadData(page: curPage + 1);
@@ -59,7 +61,9 @@ class _AICouponSheetState extends State<AICouponSheet> {
children: [
const SheetHandleBar(),
18.sizeBoxH,
Text('使用抵扣券', style: textStyle(18, Colors.white.withValues(alpha: .9), FontWeight.w600)),
Text('使用抵扣券',
style: textStyle(
18, Colors.white.withValues(alpha: .9), FontWeight.w600)),
18.sizeBoxH,
Expanded(child: _list()),
],
@@ -92,12 +96,14 @@ class _AICouponSheetState extends State<AICouponSheet> {
alignment: Alignment.center,
height: 68,
decoration: BoxDecoration(
image: DecorationImage(image: AssetImage('ai_coupon_bg.webp'.aiPath), fit: BoxFit.fill),
image: DecorationImage(
image: AssetImage('ai_coupon_bg.webp'.aiPath), fit: BoxFit.fill),
),
child: Row(
children: [
18.sizeBoxW,
Text('${model.goodsName}', style: textStyle(18, couponText, FontWeight.w600)),
Text('${model.goodsName}',
style: textStyle(18, couponText, FontWeight.w600)),
12.sizeBoxW,
Expanded(
child: Text(
@@ -116,7 +122,8 @@ class _AICouponSheetState extends State<AICouponSheet> {
color: const Color(0xffFFDCB3),
borderRadius: BorderRadius.circular(22),
),
child: Text('立即使用', style: textStyle(12, Color(0xFF7F0000), FontWeight.w400)),
child: Text('立即使用',
style: textStyle(12, Color(0xFF7F0000), FontWeight.w400)),
),
18.sizeBoxW,
],
+38 -16
View File
@@ -1,11 +1,11 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:hgmj/hj_utils/api_service/ai_service.dart';
import 'package:hgmj/routers/jump_router.dart';
import 'package:hgmj/tools_base/debug_log.dart';
import 'package:hgmj/tools_base/loading/loading_alert_widget.dart';
import 'package:hgmj/tools_base/toast.dart';
import 'package:hgmj/tools_base/widget/sheet_handle_bar.dart';
import 'package:wydj/hj_utils/api_service/ai_service.dart';
import 'package:wydj/routers/jump_router.dart';
import 'package:wydj/tools_base/debug_log.dart';
import 'package:wydj/tools_base/loading/loading_alert_widget.dart';
import 'package:wydj/tools_base/toast.dart';
import 'package:wydj/tools_base/widget/sheet_handle_bar.dart';
import '../../../hj_utils/widget_util.dart';
import '../models/ai_girl_resp_model.dart';
@@ -26,7 +26,8 @@ class _AIGirlSheetState extends State<AIGirlSheet> {
List<AIGirlFriendCurrency> get _items => widget.list ?? [];
//列表可能为空,取不到就没得选
AIGirlFriendCurrency? get _selected => selectIndex < _items.length ? _items[selectIndex] : null;
AIGirlFriendCurrency? get _selected =>
selectIndex < _items.length ? _items[selectIndex] : null;
@override
Widget build(BuildContext context) {
@@ -44,9 +45,12 @@ class _AIGirlSheetState extends State<AIGirlSheet> {
const SheetHandleBar(color: Color(0x1AFFFFFF)),
Padding(
padding: const EdgeInsets.only(top: 18, bottom: 12),
child: Text('AI女友', style: textStyle(20, Colors.white, FontWeight.w600)),
child: Text('AI女友',
style: textStyle(20, Colors.white, FontWeight.w600)),
),
Text('充值积分', style: textStyle(14, Colors.white.withValues(alpha: .8), FontWeight.w400)),
Text('充值积分',
style: textStyle(
14, Colors.white.withValues(alpha: .8), FontWeight.w400)),
GridView.builder(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 18),
shrinkWrap: true,
@@ -65,11 +69,13 @@ class _AIGirlSheetState extends State<AIGirlSheet> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('支付小贴士:', style: textStyle(14, Colors.white, FontWeight.w500)),
Text('支付小贴士:',
style: textStyle(14, Colors.white, FontWeight.w500)),
const SizedBox(height: 6),
Text(
'1.因超时支付无法到账,请重新发起。\n2.连续发起且未支付,账号可能被加入黑名单\n3.充值成功后会在1~5分钟内到账,可重新刷新进入当前页面',
style: textStyle(12, Colors.white.withValues(alpha: .6), FontWeight.w400),
style: textStyle(12, Colors.white.withValues(alpha: .6),
FontWeight.w400),
),
],
),
@@ -83,7 +89,12 @@ class _AIGirlSheetState extends State<AIGirlSheet> {
alignment: Alignment.center,
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [Color(0xff1E3C72), Color(0xff5F40B6), Color(0xff1E3C72), Color(0xff2A5298)],
colors: [
Color(0xff1E3C72),
Color(0xff5F40B6),
Color(0xff1E3C72),
Color(0xff2A5298)
],
begin: Alignment.centerLeft,
end: Alignment.centerRight,
),
@@ -109,10 +120,14 @@ class _AIGirlSheetState extends State<AIGirlSheet> {
onTap: () => setState(() => selectIndex = index),
child: Container(
decoration: BoxDecoration(
color: isSelected ? const Color(0xff4039A1) : Colors.white.withValues(alpha: .05),
color: isSelected
? const Color(0xff4039A1)
: Colors.white.withValues(alpha: .05),
borderRadius: BorderRadius.circular(6),
border: Border.all(
color: isSelected ? const Color(0xff30509C) : Colors.white.withValues(alpha: .1),
color: isSelected
? const Color(0xff30509C)
: Colors.white.withValues(alpha: .1),
),
),
child: Column(
@@ -120,14 +135,21 @@ class _AIGirlSheetState extends State<AIGirlSheet> {
children: [
Text(
'${item.coins ?? 0}积分',
style: textStyle(16, isSelected ? const Color(0xffAFABFF) : const Color(0xff7D95D5), FontWeight.w400),
style: textStyle(
16,
isSelected
? const Color(0xffAFABFF)
: const Color(0xff7D95D5),
FontWeight.w400),
),
const SizedBox(height: 4),
Text(
'${(item.price ?? 0).truncate()}金币',
style: textStyle(
12,
isSelected ? const Color(0x4DF3F5FF) : Colors.white.withValues(alpha: .3),
isSelected
? const Color(0x4DF3F5FF)
: Colors.white.withValues(alpha: .3),
FontWeight.w400,
),
),
+21 -12
View File
@@ -1,12 +1,12 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:hgmj/hj_model/video_model.dart';
import 'package:hgmj/hj_utils/const.dart';
import 'package:hgmj/tools_base/toast.dart';
import 'package:hgmj/tools_base/video_download/video_cache_store.dart';
import 'package:hgmj/tools_base/video_download/video_download_manager.dart';
import 'package:hgmj/tools_base/widget/image_browser_page.dart';
import 'package:wydj/hj_model/video_model.dart';
import 'package:wydj/hj_utils/const.dart';
import 'package:wydj/tools_base/toast.dart';
import 'package:wydj/tools_base/video_download/video_cache_store.dart';
import 'package:wydj/tools_base/video_download/video_download_manager.dart';
import 'package:wydj/tools_base/widget/image_browser_page.dart';
import '../../video/simple_video_player_page.dart';
import '../ai_sub_type/ai_function_logic.dart';
@@ -39,7 +39,8 @@ class AIImageRecord extends StatelessWidget {
final AiType aiType;
final VoidCallback? onDeleteCallback;
const AIImageRecord(this.model, {super.key, this.aiType = AiType.autoStrip, this.onDeleteCallback});
const AIImageRecord(this.model,
{super.key, this.aiType = AiType.autoStrip, this.onDeleteCallback});
bool get isVideoFace => aiType.isVideoFace;
@@ -110,7 +111,8 @@ class AIImageRecord extends StatelessWidget {
String get _resultCover {
if (_state == AIRecordState.success) {
//视频换脸有的成功订单后端不回 cover,退回素材封面,别让结果位空着露占位图
if (isVideoFace) return model.cover?.isNotEmpty == true ? model.cover! : _sourceCover;
if (isVideoFace)
return model.cover?.isNotEmpty == true ? model.cover! : _sourceCover;
return model.newPic?.firstOrNull ?? '';
}
if (isVideoFace) return model.picture?.firstOrNull ?? '';
@@ -124,14 +126,17 @@ class AIImageRecord extends StatelessWidget {
ImageBrowserPage.open([images.first], showSaveButton: true);
return;
}
final isCached = await VideoCacheStore.instance.isExistLoadVideoByUrl(MediaStyle.Video, model.url ?? '');
final isCached = await VideoCacheStore.instance
.isExistLoadVideoByUrl(MediaStyle.Video, model.url ?? '');
if (isCached) {
showToast('你已经添加过缓存了');
return;
}
/// VideoDownloadManager下载到了 应用的外部私有目录中,无需动态权限
/// if (!await _checkPermission()) return;
final result = await VideoDownloadManager.instance.download(url: model.url ?? '');
final result =
await VideoDownloadManager.instance.download(url: model.url ?? '');
if (result != null) return;
final viewModel = VideoModel()
..sourceURL = model.url
@@ -147,7 +152,8 @@ class AIImageRecord extends StatelessWidget {
//视频换脸的结果位单独接播放器,链接由 VideoModel 拼(和 AiRecordModel.realVideoUrl 的 query 不一样)
void _playResultVideo() {
final videoModel = VideoModel()..sourceURL = model.url;
Get.to(SimpleVideoPlayerPage(videoUrl: videoModel.realVideoUrl, title: 'AI生成视频'));
Get.to(SimpleVideoPlayerPage(
videoUrl: videoModel.realVideoUrl, title: 'AI生成视频'));
}
//三张图:模版 + 素材 = 结果
@@ -164,7 +170,10 @@ class AIImageRecord extends StatelessWidget {
),
const AIRecordJoin(gap: 3.5),
],
AIRecordThumb(imageUrl: _sourceCover, badge: const AISourceBadge(isTemplate: false), width: 90.w),
AIRecordThumb(
imageUrl: _sourceCover,
badge: const AISourceBadge(isTemplate: false),
width: 90.w),
const AIRecordJoin(isEquals: true, gap: 3.5),
AIResultThumb(
imageUrl: _resultCover,
+11 -5
View File
@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:hgmj/assets_tool/images.dart';
import 'package:hgmj/tools_base/widget/net_image_widget.dart';
import 'package:wydj/assets_tool/images.dart';
import 'package:wydj/tools_base/widget/net_image_widget.dart';
import '../models/ai_change_face_video_model.dart';
@@ -10,7 +10,8 @@ class AIModCell extends StatelessWidget {
final bool isSelected;
final VoidCallback? onTap;
const AIModCell({super.key, required this.mod, this.isSelected = false, this.onTap});
const AIModCell(
{super.key, required this.mod, this.isSelected = false, this.onTap});
@override
Widget build(BuildContext context) {
@@ -28,7 +29,9 @@ class AIModCell extends StatelessWidget {
right: 8,
top: 8,
child: Image.asset(
isSelected ? 'radio_select.png'.commonImgPath : 'ai_draw_unselected.png'.aiPath,
isSelected
? 'radio_select.png'.commonImgPath
: 'ai_draw_unselected.png'.aiPath,
width: 20,
),
),
@@ -38,7 +41,10 @@ class AIModCell extends StatelessWidget {
const Spacer(),
Text(
mod.title ?? '',
style: TextStyle(color: Colors.white.withValues(alpha: .8), fontSize: 14, fontWeight: FontWeight.w500),
style: TextStyle(
color: Colors.white.withValues(alpha: .8),
fontSize: 14,
fontWeight: FontWeight.w500),
),
],
),
+13 -6
View File
@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:hgmj/tools_base/toast.dart';
import 'package:hgmj/tools_base/widget/image_browser_page.dart';
import 'package:wydj/tools_base/toast.dart';
import 'package:wydj/tools_base/widget/image_browser_page.dart';
import '../models/ai_record_model.dart';
import 'ai_record_parts.dart';
@@ -11,7 +11,8 @@ class AIPaintRecord extends StatelessWidget {
final int status; // 1 排队 2 成功 3 失败
final VoidCallback? onDeleteCallback;
const AIPaintRecord(this.model, {super.key, required this.status, this.onDeleteCallback});
const AIPaintRecord(this.model,
{super.key, required this.status, this.onDeleteCallback});
AIRecordState get _state => switch (status) {
2 => AIRecordState.success,
@@ -22,10 +23,13 @@ class AIPaintRecord extends StatelessWidget {
/// 排队/失败没有结果图,退回模版封面占位。
/// 后端在这个接口里放模版封面的字段不固定(styleUrl 常为空),挨个兜一遍,别露占位图
String get _templateCover =>
[model.styleUrl, model.cover, model.modCover, model.modPic].firstWhere((e) => e?.isNotEmpty == true, orElse: () => '') ?? '';
[model.styleUrl, model.cover, model.modCover, model.modPic]
.firstWhere((e) => e?.isNotEmpty == true, orElse: () => '') ??
'';
//只有成功才是真结果图;未知 status 按排队处理,与 _state 的口径保持一致
String get _resultCover => status == 2 ? (model.newImgUrl ?? '') : _templateCover;
String get _resultCover =>
status == 2 ? (model.newImgUrl ?? '') : _templateCover;
@override
Widget build(BuildContext context) {
@@ -71,7 +75,10 @@ class AIPaintRecord extends StatelessWidget {
AIResultThumb(
imageUrl: _resultCover,
state: _state,
onTap: _resultCover.isEmpty ? null : () => ImageBrowserPage.open([_resultCover], showSaveButton: true),
onTap: _resultCover.isEmpty
? null
: () =>
ImageBrowserPage.open([_resultCover], showSaveButton: true),
),
],
),
+51 -19
View File
@@ -1,9 +1,9 @@
import 'package:flutter/material.dart';
import 'package:hgmj/assets_tool/images.dart';
import 'package:hgmj/hj_utils/date_time_util.dart';
import 'package:hgmj/hj_utils/screen.dart';
import 'package:hgmj/tools_base/widget/common_alert.dart';
import 'package:hgmj/tools_base/widget/net_image_widget.dart';
import 'package:wydj/assets_tool/images.dart';
import 'package:wydj/hj_utils/date_time_util.dart';
import 'package:wydj/hj_utils/screen.dart';
import 'package:wydj/tools_base/widget/common_alert.dart';
import 'package:wydj/tools_base/widget/net_image_widget.dart';
import '../../../hj_utils/widget_util.dart';
@@ -13,7 +13,8 @@ import '../../../hj_utils/widget_util.dart';
enum AIRecordState { queuing, success, failed }
/// 失败原因:接口没给就退回通用文案。底部文案和失败弹窗共用,改一处即可
String _failedText(String? remark) => remark?.isNotEmpty == true ? remark! : '生成失败';
String _failedText(String? remark) =>
remark?.isNotEmpty == true ? remark! : '生成失败';
/// 记录卡:白 5% 底 + 12 圆角,版式固定为
/// 创建时间/删除 → 内容 → 细线 → 状态胶囊/下载或失败原因。
@@ -60,7 +61,11 @@ class AIRecordCard extends StatelessWidget {
12.sizeBoxH,
0.5.line,
12.sizeBoxH,
AIRecordFooter(state: state, remark: remark, onDownload: onDownload, onStatusTap: onStatusTap),
AIRecordFooter(
state: state,
remark: remark,
onDownload: onDownload,
onStatusTap: onStatusTap),
],
),
);
@@ -68,7 +73,8 @@ class AIRecordCard extends StatelessWidget {
//失败原因底部只放得下两行,点卡片看全文。四类记录都走这里,别再各自实现
return GestureDetector(
behavior: HitTestBehavior.opaque, //卡片内的空白也要能点
onTap: () => CommonAlert.show(title: '失败原因', content: _failedText(remark), showCancel: false),
onTap: () => CommonAlert.show(
title: '失败原因', content: _failedText(remark), showCancel: false),
child: card,
);
}
@@ -108,7 +114,12 @@ class AIRecordFooter extends StatelessWidget {
final VoidCallback? onDownload;
final VoidCallback? onStatusTap;
const AIRecordFooter({super.key, required this.state, this.remark, this.onDownload, this.onStatusTap});
const AIRecordFooter(
{super.key,
required this.state,
this.remark,
this.onDownload,
this.onStatusTap});
@override
Widget build(BuildContext context) {
@@ -117,7 +128,8 @@ class AIRecordFooter extends StatelessWidget {
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
AIStatusPill(state, onTap: state == AIRecordState.success ? onStatusTap : null),
AIStatusPill(state,
onTap: state == AIRecordState.success ? onStatusTap : null),
if (state == AIRecordState.success && onDownload != null)
AIDownloadBtn(onTap: onDownload)
else if (state == AIRecordState.failed)
@@ -154,13 +166,18 @@ class AIStatusPill extends StatelessWidget {
onTap: onTap,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
decoration:
isFailed ? null : BoxDecoration(color: const Color(0x1AFFDB9E), borderRadius: BorderRadius.circular(3)),
decoration: isFailed
? null
: BoxDecoration(
color: const Color(0x1AFFDB9E),
borderRadius: BorderRadius.circular(3)),
child: Text(
text,
style: textStyle(
13,
isFailed ? Colors.white.withValues(alpha: .55) : const Color(0xffFFDB9E),
isFailed
? Colors.white.withValues(alpha: .55)
: const Color(0xffFFDB9E),
FontWeight.w400,
),
),
@@ -183,14 +200,16 @@ class AIDownloadBtn extends StatelessWidget {
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 4),
decoration: BoxDecoration(
border: Border.all(width: 0.5, color: Colors.white.withValues(alpha: .15)),
border: Border.all(
width: 0.5, color: Colors.white.withValues(alpha: .15)),
borderRadius: BorderRadius.circular(6),
),
child: Row(
children: [
Image.asset('icon_ai_download.png'.aiPath, width: 18),
2.5.sizeBoxW,
const Text('一键下载', style: TextStyle(color: Colors.white, fontSize: 12)),
const Text('一键下载',
style: TextStyle(color: Colors.white, fontSize: 12)),
],
),
),
@@ -206,7 +225,8 @@ class AIRecordThumb extends StatelessWidget {
final VoidCallback? onTap;
final double width;
const AIRecordThumb({super.key, this.imageUrl, this.badge, this.onTap, this.width = 90});
const AIRecordThumb(
{super.key, this.imageUrl, this.badge, this.onTap, this.width = 90});
@override
Widget build(BuildContext context) {
@@ -222,7 +242,11 @@ class AIRecordThumb extends StatelessWidget {
color: Color(0xff262626),
borderRadius: BorderRadius.all(Radius.circular(8)),
),
child: NetworkImageLoader(imageUrl: imageUrl, width: width, height: 90, borderRadius: 8),
child: NetworkImageLoader(
imageUrl: imageUrl,
width: width,
height: 90,
borderRadius: 8),
),
if (badge != null) badge!,
],
@@ -239,7 +263,12 @@ class AIResultThumb extends StatelessWidget {
final VoidCallback? onTap;
final double width;
const AIResultThumb({super.key, this.imageUrl, required this.state, this.onTap, this.width = 90});
const AIResultThumb(
{super.key,
this.imageUrl,
required this.state,
this.onTap,
this.width = 90});
@override
Widget build(BuildContext context) {
@@ -260,7 +289,10 @@ class AIResultThumb extends StatelessWidget {
),
),
if (state == AIRecordState.failed)
Positioned.fill(child: Center(child: Image.asset('ai_record_failed.webp'.aiPath, width: 20))),
Positioned.fill(
child: Center(
child:
Image.asset('ai_record_failed.webp'.aiPath, width: 20))),
],
);
}
+39 -20
View File
@@ -1,15 +1,15 @@
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_page/video/simple_video_player_page.dart';
import 'package:hgmj/hj_utils/date_time_util.dart';
import 'package:hgmj/hj_utils/screen.dart';
import 'package:hgmj/tools_base/widget/header_widget.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_page/video/simple_video_player_page.dart';
import 'package:wydj/hj_utils/date_time_util.dart';
import 'package:wydj/hj_utils/screen.dart';
import 'package:wydj/tools_base/widget/header_widget.dart';
import 'package:wydj/tools_base/widget/net_image_widget.dart';
import '../../../hj_utils/widget_util.dart';
import 'package:hgmj/tools_base/widget/image_browser_page.dart';
import 'package:wydj/tools_base/widget/image_browser_page.dart';
import '../ai_sub_type/ai_function_logic.dart';
import '../models/ai_square_model.dart';
@@ -39,7 +39,9 @@ class AISquareCell extends StatelessWidget {
Widget _imgView() {
return switch (AiTypeCode.fromServerCode(model.type)) {
AiType.imageChangeFace || AiType.autoStrip => _twoImgsView(model.originalImage, model.generateImage),
AiType.imageChangeFace ||
AiType.autoStrip =>
_twoImgsView(model.originalImage, model.generateImage),
AiType.videoChangeFace => _videoChangeFace(),
AiType.imageToVideo => _imgToVideo(),
AiType.aiPaint => _aiDraw(),
@@ -53,20 +55,24 @@ class AISquareCell extends StatelessWidget {
Expanded(
child: InkWell(
enableFeedback: false,
onTap: () => ImageBrowserPage.open([left ?? ''], showSaveButton: true),
onTap: () =>
ImageBrowserPage.open([left ?? ''], showSaveButton: true),
child: NetworkImageLoader(
imageUrl: left,
imgBorderRadius: const BorderRadius.horizontal(left: Radius.circular(9)),
imgBorderRadius:
const BorderRadius.horizontal(left: Radius.circular(9)),
),
),
),
Expanded(
child: InkWell(
enableFeedback: false,
onTap: () => ImageBrowserPage.open([right ?? ''], showSaveButton: true),
onTap: () =>
ImageBrowserPage.open([right ?? ''], showSaveButton: true),
child: NetworkImageLoader(
imageUrl: right,
imgBorderRadius: const BorderRadius.horizontal(right: Radius.circular(9)),
imgBorderRadius:
const BorderRadius.horizontal(right: Radius.circular(9)),
),
),
),
@@ -80,7 +86,10 @@ class AISquareCell extends StatelessWidget {
children: [
Text(
'“${model.originContent ?? ''}”',
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w400, color: Color(0xff03FCEB)),
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w400,
color: Color(0xff03FCEB)),
),
12.sizeBoxH,
Row(
@@ -88,7 +97,8 @@ class AISquareCell extends StatelessWidget {
Expanded(
child: InkWell(
enableFeedback: false,
onTap: () => ImageBrowserPage.open([model.generateImage ?? ''], showSaveButton: true),
onTap: () => ImageBrowserPage.open([model.generateImage ?? ''],
showSaveButton: true),
child: NetworkImageLoader(imageUrl: model.generateImage),
),
),
@@ -113,7 +123,9 @@ class AISquareCell extends StatelessWidget {
Widget _videoChangeFace() {
return Row(
children: [
Expanded(child: _videoItem(model.generateVideoCover, model.realGenerateVideoUrl)),
Expanded(
child: _videoItem(
model.generateVideoCover, model.realGenerateVideoUrl)),
10.sizeBoxW,
const Expanded(child: SizedBox.shrink()),
],
@@ -141,7 +153,10 @@ class AISquareCell extends StatelessWidget {
style: textStyle(10, Colors.white, FontWeight.w500),
),
)),
TextSpan(text: model.title, style: textStyle(14, Colors.white.withValues(alpha: .9), FontWeight.w500))
TextSpan(
text: model.title,
style: textStyle(
14, Colors.white.withValues(alpha: .9), FontWeight.w500))
]));
}
@@ -175,7 +190,8 @@ class AISquareCell extends StatelessWidget {
10.sizeBoxW,
Text(
DateTimeUtil.utcTurnYear(model.reviewAt),
style: textStyle(12, Colors.white.withValues(alpha: 0.55), FontWeight.w400),
style: textStyle(12, Colors.white.withValues(alpha: 0.55),
FontWeight.w400),
)
],
)
@@ -189,7 +205,9 @@ class AISquareCell extends StatelessWidget {
width: 70,
height: 24,
alignment: Alignment.center,
decoration: BoxDecoration(borderRadius: BorderRadius.circular(3), color: AppColors.actionRed),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(3),
color: AppColors.actionRed),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
@@ -218,7 +236,8 @@ class AISquareCell extends StatelessWidget {
Widget _videoItem(String? img, String url) {
return InkWell(
enableFeedback: false,
onTap: () => Get.to(() => SimpleVideoPlayerPage(videoUrl: url, title: model.title ?? '')),
onTap: () => Get.to(
() => SimpleVideoPlayerPage(videoUrl: url, title: model.title ?? '')),
child: Stack(
alignment: Alignment.center,
children: [
+13 -7
View File
@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:hgmj/assets_tool/images.dart';
import 'package:hgmj/tools_base/toast.dart';
import 'package:hgmj/tools_base/widget/image_browser_page.dart';
import 'package:wydj/assets_tool/images.dart';
import 'package:wydj/tools_base/toast.dart';
import 'package:wydj/tools_base/widget/image_browser_page.dart';
import '../models/ai_record_model.dart';
import 'ai_record_parts.dart';
@@ -12,7 +12,8 @@ class AIVideoRecord extends StatelessWidget {
final int status; // 1 排队 2 成功 3 失败
final VoidCallback? onDeleteCallback;
const AIVideoRecord(this.model, {super.key, required this.status, this.onDeleteCallback});
const AIVideoRecord(this.model,
{super.key, required this.status, this.onDeleteCallback});
AIRecordState get _state => switch (status) {
2 => AIRecordState.success,
@@ -20,7 +21,8 @@ class AIVideoRecord extends StatelessWidget {
_ => AIRecordState.queuing,
};
String get _resultCover => model.status == 3 ? (model.newImgUrl ?? '') : (model.imgUrl ?? '');
String get _resultCover =>
model.status == 3 ? (model.newImgUrl ?? '') : (model.imgUrl ?? '');
@override
Widget build(BuildContext context) {
@@ -51,13 +53,17 @@ class AIVideoRecord extends StatelessWidget {
children: [
AIRecordThumb(
imageUrl: model.imgUrl,
badge: Image.asset('ai_record_org.png'.aiPath, width: 36, height: 18),
badge:
Image.asset('ai_record_org.png'.aiPath, width: 36, height: 18),
),
const AIRecordJoin(isEquals: true),
AIResultThumb(
imageUrl: _resultCover,
state: _state,
onTap: _resultCover.isEmpty ? null : () => ImageBrowserPage.open([_resultCover], showSaveButton: true),
onTap: _resultCover.isEmpty
? null
: () =>
ImageBrowserPage.open([_resultCover], showSaveButton: true),
),
],
),
+10 -7
View File
@@ -2,10 +2,10 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_pickers/image_pickers.dart';
import 'package:hgmj/assets_tool/app_colors.dart';
import 'package:hgmj/assets_tool/images.dart';
import 'package:hgmj/tools_base/toast.dart';
import 'package:hgmj/hj_utils/screen.dart';
import 'package:wydj/assets_tool/app_colors.dart';
import 'package:wydj/assets_tool/images.dart';
import 'package:wydj/tools_base/toast.dart';
import 'package:wydj/hj_utils/screen.dart';
import 'package:mobkit_dashed_border/mobkit_dashed_border.dart';
/// AI 功能的单图选择器:未选时是虚线占位框,选后是缩略图 + 右上角删除
@@ -54,7 +54,8 @@ class _PicPickerState extends State<PicPicker> {
selectCount: 1,
showCamera: true,
);
final paths = medias.map((e) => e.path ?? "").where((e) => e.isNotEmpty).toList();
final paths =
medias.map((e) => e.path ?? "").where((e) => e.isNotEmpty).toList();
if (paths.length < medias.length) showToast("添加图片失败");
return paths;
}
@@ -92,7 +93,8 @@ class _PicPickerState extends State<PicPicker> {
onTap: _delPic,
child: Padding(
padding: const EdgeInsets.all(6),
child: Image.asset("close_grey.png".commonImgPath, width: 14, height: 14),
child: Image.asset("close_grey.png".commonImgPath,
width: 14, height: 14),
),
),
),
@@ -120,7 +122,8 @@ class _PicPickerState extends State<PicPicker> {
children: [
Image.asset('add_grey.png'.communityPath, width: 24),
10.sizeBoxH,
const Text("添加图片", style: TextStyle(fontSize: 12, color: Color(0xff999999))),
const Text("添加图片",
style: TextStyle(fontSize: 12, color: Color(0xff999999))),
],
),
),