初始化
This commit is contained in:
@@ -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),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user