初始化

This commit is contained in:
谢宇宁
2026-09-15 15:44:13 +07:00
commit a23ba685e9
1065 changed files with 101122 additions and 0 deletions
@@ -0,0 +1,250 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:hgdj/assets_tool/app_colors.dart';
import 'package:hgdj/assets_tool/images.dart';
import 'package:hgdj/config/address.dart';
import 'package:hgdj/config/config.dart';
import 'package:hgdj/hj_utils/screen.dart';
import 'package:hgdj/tools_base/global_store/store.dart';
import 'package:hgdj/tools_base/toast.dart';
import 'package:provider/provider.dart';
import 'package:qr_flutter/qr_flutter.dart';
import '../../../hj_utils/image_util.dart';
import '../../../tools_base/widget/net_image_widget.dart';
import 'mine_share_record_page.dart';
//分享邀请
class MineSharePage extends StatelessWidget {
// 该页只通过 Get.to 作为路由根打开,实例稳定不会被父级 rebuild,
// boundaryKey 字段只创建一次,RepaintBoundary 截图正常
final GlobalKey boundaryKey = GlobalKey();
MineSharePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("邀请分享"),
actions: [
InkWell(
enableFeedback: false,
onTap: () {
Get.to(() => MineShareRecordPage());
},
child: Text(
"记录",
style: TextStyle(
color: Colors.white.withValues(alpha: .45),
fontSize: 12,
),
),
),
16.sizeBoxW,
],
),
body: Container(
padding: EdgeInsets.symmetric(horizontal: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
// 用 FittedBox 完整渲染卡片,不放进 SingleChildScrollView
// RepaintBoundary 在可滚动容器内时,toImage 受 Viewport 裁剪影响会截图残缺/失败
child: Center(
child: FittedBox(
fit: BoxFit.contain,
child: RepaintBoundary(
key: boundaryKey,
child: Container(
margin: EdgeInsets.only(top: 30),
padding: EdgeInsets.symmetric(horizontal: 16),
child: SizedBox(
width: 300,
height: 550,
child: Stack(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(9),
child: Image.asset('share_bg.webp'.mineImgPath),
),
// 整张卡片统一响应 meInfo 变化:头像/邀请码/二维码同源刷新
Consumer<GlobalStore>(
builder: (_, provider, __) {
final me = provider.meInfo;
return Column(
crossAxisAlignment:
CrossAxisAlignment.center,
children: [
30.sizeBoxH,
Container(
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(45),
border: Border.all(
color: Color(0x4DF68804),
width: 3),
),
child: NetworkImageLoader(
imageUrl: me?.portrait ?? '',
width: 82,
height: 82,
borderRadius: 45),
),
10.sizeBoxH,
Text(
'我的邀请码',
style: TextStyle(
color: Colors.white
.withValues(alpha: .9),
fontSize: 20,
fontWeight: FontWeight.w500,
),
),
10.sizeBoxH,
Text(
me?.promotionCode ?? "",
style: TextStyle(
color: Colors.white
.withValues(alpha: .55),
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
30.sizeBoxH,
Text("每邀请3人,送3天VIP",
style: TextStyle(
fontSize: 14,
color: Color(0xFFF68804))),
10.sizeBoxH,
Row(
children: [
Spacer(),
Center(
child: Container(
padding: EdgeInsets.all(11.w),
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
"code_bg.webp"
.mineImgPath),
fit: BoxFit.fill,
),
),
child: Container(
padding: EdgeInsets.all(6.w),
color: Colors.white,
child: QrImageView(
data: me?.promoteURL ?? "",
version: QrVersions.auto,
size: 100,
backgroundColor: Colors.white,
),
),
),
),
Spacer(),
],
),
4.sizeBoxH,
Text(
'提示*苹果手机请用相机扫码/安卓手机\n推荐UC浏览器扫码',
style: TextStyle(
color: Colors.white
.withValues(alpha: .55),
fontSize: 12,
fontWeight: FontWeight.w400,
),
textAlign: TextAlign.center,
),
6.sizeBoxH,
Container(
height: 30,
padding: EdgeInsets.symmetric(
horizontal: 18, vertical: 3),
child: Text(
'${Config.appName} 官网地址 ${Address.groundUrl ?? ""}',
style: TextStyle(
color: Colors.white
.withValues(alpha: .55),
fontSize: 12,
fontWeight: FontWeight.w400,
),
),
),
],
);
},
)
],
),
),
),
),
),
),
),
Container(
margin: EdgeInsets.symmetric(horizontal: 20),
padding: EdgeInsets.symmetric(vertical: 12),
child: Column(
children: [
GestureDetector(
onTap: () async {
final ok =
await ImageUtil.saveWidgetToAlbum(boundaryKey);
showToast(ok ? "保存成功" : "保存失败,请重试");
},
child: Container(
height: 44,
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(3),
color: AppColors.actionRed,
),
child: Text(
"保存图片",
style: TextStyle(
fontSize: 16,
color: Colors.white,
fontWeight: FontWeight.w500,
),
),
),
),
16.sizeBoxH,
GestureDetector(
onTap: () {
Clipboard.setData(ClipboardData(
text: globalStore.meInfo?.promoteURL ?? ""));
showToast('复制成功');
},
child: Container(
width: 112,
height: 44,
alignment: Alignment.center,
child: Text(
"复制链接",
style: TextStyle(
fontSize: 12,
color: Color(0x8CFFFFFF),
decoration: TextDecoration.underline, // 添加下划线
decorationColor: Color(0xFF11887C), // 下划线颜色
decorationThickness: 1.0, // 下划线粗细
decorationStyle: TextDecorationStyle.solid, // 下划线样式
),
),
),
),
],
),
),
],
)),
);
}
}
@@ -0,0 +1,31 @@
import 'package:hgdj/hj_model/user/user_income_info_model.dart';
import 'package:hgdj/hj_utils/api_service/mine_service.dart';
import 'package:hgdj/tools_base/base_list_controller.dart';
import '../../../hj_model/mine/promotion_record.dart';
class MineShareRecordLogic extends ListBaseLogic<Promotion> {
UserIncomeModel? model; // 邀请收益头部信息(独立接口,与列表分页无关)
@override
void onReady() {
super.onReady();
loadInfo();
loadData();
}
// 头部邀请收益信息
void loadInfo() async {
model = await MineService.fetchIncomeInfo();
update();
}
// 邀请记录列表:下拉刷新 / 上拉加载更多(分页、防重入、异常兜底交给基类)
void loadData({bool isRefresh = true}) =>
fetchData(isRefresh: isRefresh, fetch: _fetch);
Future<(List<Promotion>?, bool)> _fetch(int page) async {
final resp = await MineService.getBindRecord(10, page);
return (resp?.list, resp?.hasNext == true); // hasNext==true 才有更多(保持原语义)
}
}
@@ -0,0 +1,92 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:hgdj/extension/extensions.dart';
import 'package:hgdj/hj_model/mine/promotion_record.dart';
import 'package:hgdj/hj_utils/screen.dart';
import 'package:hgdj/tools_base/loading/loading_center_widget.dart';
import 'package:hgdj/tools_base/refresh/pull_refresh.dart';
import 'package:hgdj/tools_base/widget/net_image_widget.dart';
import '../../../hj_utils/widget_util.dart';
import 'mine_share_record_logic.dart';
class MineShareRecordPage extends StatelessWidget {
const MineShareRecordPage({super.key});
@override
Widget build(BuildContext context) {
return GetBuilder<MineShareRecordLogic>(
init: MineShareRecordLogic(),
builder: (logic) {
return Scaffold(
appBar: AppBar(title: Text("邀请记录")),
body: Column(
children: [
12.sizeBoxH,
Text('已邀请:${logic.model?.totalInviteUserCount ?? 0}',
style: textStyle(12, Color(0xff525252), FontWeight.w400)),
Expanded(
child: pullYsRefresh(
onInit: (ctr) => logic.refreshCtr = ctr,
onLoading: (_) => logic.loadData(isRefresh: false),
onRefresh: (_) => logic.loadData(),
child: _buildBody(logic),
),
),
],
),
);
},
);
}
// loading / 空数据 / 列表 三态
Widget _buildBody(MineShareRecordLogic logic) {
if (logic.isLoading) return LoadingCenterWidget();
if (logic.isEmptyData) return CErrorWidget();
final list = logic.dataList ?? [];
return ListView.separated(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
shrinkWrap: true,
itemCount: list.length,
separatorBuilder: (_, __) =>
Divider(height: 0.5, color: Colors.white.withValues(alpha: .1)),
itemBuilder: (_, index) => _buildItemView(list[index]),
);
}
// 单条邀请记录:头像 + 昵称 + 注册时间
Widget _buildItemView(Promotion item) {
return Container(
height: 30,
width: double.infinity,
margin: const EdgeInsets.symmetric(vertical: 12),
child: Row(
children: [
NetworkImageLoader(
imageUrl: item.portrait ?? '',
width: 30,
height: 30,
borderRadius: 30,
),
11.sizeBoxW,
Text(
item.name ?? '',
style: TextStyle(
color: Color(0xffffffff),
fontWeight: FontWeight.w500,
fontSize: 14.0),
),
Spacer(),
Text(
'注册时间: ${item.createAt.utcToYMD(gap: '/')}',
style: TextStyle(
color: Color(0xff989898),
fontWeight: FontWeight.w400,
fontSize: 12.0),
)
],
),
);
}
}