初始化

This commit is contained in:
谢宇宁
2026-09-15 15:44:13 +07:00
commit a23ba685e9
1065 changed files with 101122 additions and 0 deletions
+353
View File
@@ -0,0 +1,353 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:hgdj/assets_tool/images.dart';
import 'package:hgdj/config/address.dart';
import 'package:hgdj/config/config.dart';
import 'package:hgdj/hj_page/main_page/provider/msg_provider.dart';
import 'package:hgdj/hj_page/pre_sale/pre_sale_provider.dart';
import 'package:hgdj/hj_utils/screen.dart';
import 'package:hgdj/routers/jump_router.dart';
import 'package:hgdj/tools_base/global_store/store.dart';
import 'package:hgdj/tools_base/refresh/pull_refresh.dart';
import 'package:hgdj/tools_base/toast.dart';
import 'package:hgdj/tools_base/widget/net_image_widget.dart';
import 'package:provider/provider.dart';
import '../../hj_utils/widget_util.dart';
import '../../tools_base/banner/ads_grid_view_widget.dart';
import 'home_mine_logic.dart';
import 'widgets/mine_info_widget.dart';
import 'widgets/vip_entry_card.dart';
//我的页面
class HomeMinePage extends StatelessWidget {
const HomeMinePage({super.key});
/// 常用功能里唯一需要展示未读红点的入口
static const _messageMenuTitle = '我的消息';
@override
Widget build(BuildContext context) {
return GetBuilder<MineMainLogic>(
init: MineMainLogic(),
builder: (logic) {
return Consumer<GlobalStore>(builder: (_, store, ___) {
return Scaffold(
body: SizedBox.expand(
child: pullYsRefresh(
onInit: (ctr) => logic.refreshCtr = ctr,
enablePullUp: false,
onRefresh: (ctr) => logic.onRefresh(),
child: SingleChildScrollView(
child: Stack(
children: [
Positioned(
left: 0,
right: 0,
top: 0,
child: _buildBg(),
),
SafeArea(child: _buildContent(logic, store)),
],
),
),
),
),
);
});
},
);
}
//顶部背景:优先后台下发,兜底默认图
Widget _buildBg() {
final bg = Config.mineBg;
if (bg != null && bg.isNotEmpty) {
return NetworkImageLoader(imageUrl: bg, borderRadius: 0);
}
return Image.asset(
'mine_bg.webp'.mineImgPath,
);
}
Widget _buildContent(MineMainLogic logic, GlobalStore store) {
return Stack(
children: [
_buildTop(logic),
Column(
children: [
48.sizeBoxH,
MineInfoWidget(logic: logic),
21.sizeBoxH,
_buildCountView(), //次数
21.sizeBoxH,
VipEntryCard(), //会员入口
12.sizeBoxH,
MineTaskMenuWidget(), //金币充值等
12.sizeBoxH,
MineFunchtionGridView(), //收藏/历史/下载/关注
12.sizeBoxH,
_buildShop(logic), //商店入口
AdsGridViewWidget(
8,
accordingAdsType: true,
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
),
Container(
margin: EdgeInsets.symmetric(horizontal: 16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(9),
color: Colors.white.withValues(alpha: .05),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
alignment: Alignment.centerLeft,
margin: EdgeInsets.symmetric(horizontal: 16, vertical: 5),
child: Text("常用功能",
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w500,
fontSize: 16,
)),
),
GridView.builder(
physics: NeverScrollableScrollPhysics(),
padding: EdgeInsets.zero,
shrinkWrap: true,
itemCount: logic.menuVerNameArr.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,
crossAxisSpacing: 0,
mainAxisSpacing: 0,
childAspectRatio: 1,
),
itemBuilder: (context, index) {
String titleDesc = logic.menuVerNameArr[index];
String imagePath =
'mine_menu_${index + 1}.png'.mineImgPath;
// 仅「我的消息」带未读红点,按名称判断避免菜单顺序变动后红点错位
final isMessageEntry = titleDesc == _messageMenuTitle;
return InkWell(
enableFeedback: false,
onTap: () => logic.menuVerTapEvent(index),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
!isMessageEntry
? Image.asset(imagePath, width: 28)
: Stack(
children: [
Image.asset(
"mine_notification.png".mineImgPath,
width: 28,
),
Consumer<MineMsgProvider>(
builder: (context, model, child) =>
Positioned(
right: 2,
top: 2,
child: model.buildTipsView(),
),
)
],
),
5.sizeBoxH,
Text(
titleDesc,
style:
TextStyle(color: Colors.white, fontSize: 12),
),
],
),
);
},
),
// iOS 换图标需弹系统弹窗且要预置图标资源,暂不支持,仅 Android 显示该入口
if (!Platform.isIOS) ...[
Padding(
padding: EdgeInsets.only(left: 12, top: 10, right: 12),
child: Row(
children: [
Text(
'设置桌面图标',
style: TextStyle(
color: Color(0xffEFEFEF),
fontSize: 14,
fontWeight: FontWeight.w500),
),
Spacer(),
InkWell(
enableFeedback: false,
onTap: () => logic.changeIcon(0),
child: Text(
'恢复默认',
style: TextStyle(
color: Color(0xff989898),
fontSize: 12,
fontWeight: FontWeight.w400),
),
),
],
),
),
11.sizeBoxH,
SizedBox(
height: 76,
child: ListView.separated(
padding: EdgeInsets.symmetric(horizontal: 16),
scrollDirection: Axis.horizontal,
separatorBuilder: (_, __) => 7.sizeBoxW,
itemCount: logic.iconList.length,
itemBuilder: (BuildContext context, int index) {
final data = logic.iconList[index];
return InkWell(
enableFeedback: false,
onTap: () => logic.changeIcon(index),
child: Column(
children: [
Image.asset(data.image, width: 54),
4.sizeBoxH,
Text(
data.name,
style: TextStyle(
color: Colors.white.withValues(alpha: 0.9),
fontSize: 12,
),
)
],
),
);
},
),
),
10.sizeBoxH,
],
],
),
),
12.sizeBoxH,
Text(
'我的邀请码: ${store.meInfo?.promotionCode ?? ''}',
style: textStyle(16, Color(0xffBDBDBD), FontWeight.w400),
),
6.sizeBoxH,
_buildGroundUrl(),
30.sizeBoxH,
],
),
],
);
}
//永久官方地址:地址未下发时不渲染,避免点击/复制空串
Widget _buildGroundUrl() {
final url = Address.groundUrl;
if (url == null || url.isEmpty) return const SizedBox.shrink();
return GestureDetector(
onTap: () => launchUrlToWeb(url),
onLongPress: () {
Clipboard.setData(ClipboardData(text: url));
showToast("复制成功");
},
child: Text(
'永久官方地址: $url',
style: textStyle(12, Color(0xff525252), FontWeight.w400),
),
);
}
//消息和设置
Widget _buildTop(MineMainLogic logic) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
child: Row(
children: [
InkWell(
enableFeedback: false,
onTap: () => logic.menuTapEvent(3),
child: Image.asset("mine_notification.png".mineImgPath, width: 24),
),
Spacer(),
InkWell(
enableFeedback: false,
onTap: () => logic.toSetting(),
child: Image.asset("setting.png".mineImgPath, width: 24),
),
],
),
);
}
//次数
Widget _buildCountView() {
return Row(
children: [
50.sizeBoxW,
Expanded(
child: Consumer2<GlobalStore, PreSaleProvider>(
builder: (context, store, provider, child) {
int count = (store.wallet?.downloadCount ?? 0) +
(provider.remain?.todayDownloadCount ?? 0);
return _buildCountItem(count.toString(), '剩余缓存次数');
},
),
),
Container(
color: Colors.white.withValues(alpha: .1),
width: 0.5,
height: 12,
),
Expanded(
child: Consumer2<GlobalStore, PreSaleProvider>(
builder: (context, store, provider, child) {
//预售权益和免费次数的和
final total = (store.wallet?.aiUndressFreeTimes ?? 0) +
(provider.remain?.todayAiUndressCount ?? 0);
return _buildCountItem(total.toString(), '剩余AI脱衣次数');
},
),
),
50.sizeBoxW,
],
);
}
Widget _buildCountItem(String count, String title) {
return Column(
children: [
Text(
count,
style: textStyle(16, Colors.white, FontWeight.w500),
),
4.sizeBoxH,
Text(
title,
style: textStyle(
12, Colors.white.withValues(alpha: .7), FontWeight.w400),
),
],
);
}
Widget _buildShop(MineMainLogic logic) {
if (Config.isStoreOpen) {
return InkWell(
enableFeedback: false,
onTap: () => logic.toShop(),
child: Padding(
padding: const EdgeInsets.only(bottom: 10.0, left: 10, right: 10),
child: AspectRatio(
aspectRatio: 355 / 82,
child: Image.asset('mine_shop_icon.webp'.mineImgPath),
),
),
);
}
return SizedBox.shrink();
}
}