415 lines
17 KiB
Dart
415 lines
17 KiB
Dart
import 'package:flutter/material.dart';
|
||
import 'package:fluttertoast/fluttertoast.dart';
|
||
import 'package:intl/intl.dart';
|
||
import '../../components/appbar.dart';
|
||
import '../../components/gradientButton.dart';
|
||
import '../../components/cached_image.dart';
|
||
import '../../../apis/app.dart';
|
||
import '../mine/mine.dart';
|
||
import '../mine/work/worksDetail.dart';
|
||
|
||
class ChoiceWorksPage extends StatefulWidget {
|
||
const ChoiceWorksPage({
|
||
super.key,
|
||
required this.data,
|
||
});
|
||
|
||
final List<Map<String, dynamic>> data;
|
||
|
||
@override
|
||
State<ChoiceWorksPage> createState() => _ChoiceWorksPageState();
|
||
}
|
||
|
||
class _ChoiceWorksPageState extends State<ChoiceWorksPage> {
|
||
List<WorkItem> works = [];
|
||
bool isLoading = false;
|
||
String? error;
|
||
late List<int?> selectedImages;
|
||
|
||
late final List<Map<String, dynamic>> sourceInfo;
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
sourceInfo = widget.data;
|
||
selectedImages = List.filled(sourceInfo.length, null);
|
||
getMyCollection();
|
||
}
|
||
|
||
Future<void> getMyCollection() async {
|
||
try {
|
||
setState(() {
|
||
isLoading = true;
|
||
error = null;
|
||
});
|
||
|
||
final result = await userApi.getMyCollection();
|
||
if (result['code'] == 200) {
|
||
final List<dynamic> data = result['rows'] ?? [];
|
||
setState(() {
|
||
works = data.map((item) => WorkItem.fromJson(item)).toList();
|
||
});
|
||
} else {
|
||
setState(() {
|
||
error = result['msg'];
|
||
});
|
||
}
|
||
} catch (e) {
|
||
setState(() {
|
||
error = e.toString();
|
||
});
|
||
} finally {
|
||
setState(() {
|
||
isLoading = false;
|
||
});
|
||
}
|
||
}
|
||
|
||
void _selectImage(int index) {
|
||
setState(() {
|
||
int? emptyPosition = selectedImages.indexOf(null);
|
||
if (emptyPosition != -1) {
|
||
selectedImages[emptyPosition] = index;
|
||
} else {
|
||
Fluttertoast.showToast(msg: '已选择足够数量的作品');
|
||
}
|
||
});
|
||
}
|
||
|
||
void _removeImage(int position) {
|
||
setState(() {
|
||
selectedImages[position] = null;
|
||
for (int i = position; i < selectedImages.length - 1; i++) {
|
||
selectedImages[i] = selectedImages[i + 1];
|
||
}
|
||
selectedImages[selectedImages.length - 1] = null;
|
||
});
|
||
}
|
||
|
||
bool get isAllImagesSelected => !selectedImages.contains(null);
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return Scaffold(
|
||
appBar: const CustomAppBar(title: '选择作品'),
|
||
body: Container(
|
||
decoration: const BoxDecoration(
|
||
color: Color(0xff0C0C16),
|
||
),
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
const Padding(
|
||
padding: EdgeInsets.all(16.0),
|
||
child: Text(
|
||
'请按照顺序依次进行投放',
|
||
style: TextStyle(
|
||
color: Colors.red,
|
||
fontSize: 16,
|
||
),
|
||
),
|
||
),
|
||
Expanded(
|
||
child: isLoading
|
||
? const Center(child: CircularProgressIndicator())
|
||
: error != null
|
||
? Center(
|
||
child: Text(
|
||
error!,
|
||
style: const TextStyle(color: Colors.red),
|
||
),
|
||
)
|
||
: works.isEmpty
|
||
? _buildEmptyState()
|
||
: GridView.builder(
|
||
padding:
|
||
const EdgeInsets.symmetric(horizontal: 16),
|
||
gridDelegate:
|
||
const SliverGridDelegateWithFixedCrossAxisCount(
|
||
crossAxisCount: 2,
|
||
childAspectRatio: 166 / 219,
|
||
crossAxisSpacing: 10,
|
||
mainAxisSpacing: 10,
|
||
),
|
||
itemCount: works.length,
|
||
itemBuilder: (context, index) {
|
||
final work = works[index];
|
||
return GestureDetector(
|
||
onTap: () => _selectImage(index),
|
||
child: Container(
|
||
decoration: BoxDecoration(
|
||
borderRadius: BorderRadius.circular(8),
|
||
// border: selectedImages.contains(index)
|
||
// ? Border.all(
|
||
// color: const Color(0xFF96FBE9)
|
||
// .withOpacity(0.8),
|
||
// width: 2)
|
||
// : null,
|
||
),
|
||
child: ClipRRect(
|
||
borderRadius: BorderRadius.circular(8),
|
||
child: Stack(
|
||
fit: StackFit.expand,
|
||
children: [
|
||
CachedImage(
|
||
imageUrl: work.imageUrl,
|
||
width: double.infinity,
|
||
height: double.infinity,
|
||
fit: BoxFit.cover,
|
||
borderRadius: BorderRadius.circular(8),
|
||
),
|
||
Positioned(
|
||
bottom: 0,
|
||
left: 0,
|
||
right: 0,
|
||
child: Container(
|
||
padding: const EdgeInsets.all(8),
|
||
decoration: BoxDecoration(
|
||
gradient: LinearGradient(
|
||
begin: Alignment.topCenter,
|
||
end: Alignment.bottomCenter,
|
||
colors: [
|
||
Colors.transparent,
|
||
Colors.black.withOpacity(0.7),
|
||
],
|
||
),
|
||
),
|
||
child: Row(
|
||
mainAxisAlignment:
|
||
MainAxisAlignment.spaceBetween,
|
||
children: [
|
||
Expanded(
|
||
child: Text(
|
||
work.title,
|
||
style: const TextStyle(
|
||
color: Colors.white,
|
||
fontSize: 14,
|
||
),
|
||
overflow: TextOverflow.ellipsis,
|
||
),
|
||
),
|
||
GestureDetector(
|
||
onTap: () {
|
||
Navigator.push(
|
||
context,
|
||
MaterialPageRoute(
|
||
builder: (context) =>
|
||
WorksDetailPage(
|
||
id: work.workId,
|
||
type: 'collection',
|
||
),
|
||
),
|
||
);
|
||
},
|
||
child: Image.asset(
|
||
'images/full.png',
|
||
width: 24,
|
||
height: 24,
|
||
color: Colors.white,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
// if (selectedImages.contains(index))
|
||
// Positioned(
|
||
// top: 8,
|
||
// right: 8,
|
||
// child: Container(
|
||
// padding:
|
||
// const EdgeInsets.all(4),
|
||
// decoration: BoxDecoration(
|
||
// color: const Color(0xFF96FBE9)
|
||
// .withOpacity(0.8),
|
||
// shape: BoxShape.circle,
|
||
// ),
|
||
// child: Text(
|
||
// '${selectedImages.indexOf(index) + 1}',
|
||
// style: const TextStyle(
|
||
// color: Colors.white,
|
||
// fontSize: 12,
|
||
// ),
|
||
// ),
|
||
// ),
|
||
// ),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
);
|
||
},
|
||
),
|
||
),
|
||
Container(
|
||
width: MediaQuery.of(context).size.width,
|
||
padding: const EdgeInsets.all(16),
|
||
color: const Color(0xff1F212E),
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
SingleChildScrollView(
|
||
scrollDirection: Axis.horizontal,
|
||
child: Row(
|
||
children: List.generate(
|
||
sourceInfo.length,
|
||
(index) => _buildSelectedImageSlot(index),
|
||
),
|
||
),
|
||
),
|
||
const SizedBox(height: 16),
|
||
// 发布按钮部分
|
||
SizedBox(
|
||
width: double.infinity, // 让按钮占满宽度
|
||
child: GradientButton(
|
||
text: '发布',
|
||
onPressed: isAllImagesSelected
|
||
? () async {
|
||
final selectedWorks = selectedImages
|
||
.map((index) =>
|
||
index != null ? works[index] : null)
|
||
.toList();
|
||
|
||
final publishData = List.generate(
|
||
selectedWorks.length,
|
||
(index) => {
|
||
"workId": selectedWorks[index]?.workId,
|
||
"sourceId": sourceInfo[index]['sourceId'],
|
||
"day": sourceInfo[index]['day'],
|
||
},
|
||
);
|
||
print("-------------publishData: $publishData");
|
||
try {
|
||
final result =
|
||
await userApi.getPublish(publishData);
|
||
// print("@@@@@@@@@@@result: $result");
|
||
if (result['code'] == 200) {
|
||
final orderId = result['msg'].toString();
|
||
print("@@@@@@@@@@@orderId: $orderId");
|
||
// 查看类型 orderId
|
||
print(
|
||
"@@@@@@@@@@@orderId类型: ${orderId.runtimeType}");
|
||
Fluttertoast.showToast(msg: '请支付订单');
|
||
Navigator.pushReplacementNamed(context, '/pay',
|
||
arguments: {
|
||
'orderId': orderId,
|
||
'totalPrice': sourceInfo[0]['totalPrice'],
|
||
},);
|
||
// Navigator.pushNamedAndRemoveUntil(
|
||
// context,
|
||
// '/tabs',
|
||
// (route) => false,
|
||
// arguments: {'initialIndex': 1}, // 传递参数,设置初始选中的tab
|
||
// );
|
||
} else {
|
||
Fluttertoast.showToast(
|
||
msg: result['msg'] ?? '发布失败');
|
||
}
|
||
} catch (e) {
|
||
Fluttertoast.showToast(msg: '发布失败:$e');
|
||
}
|
||
}
|
||
: () => Fluttertoast.showToast(msg: '请将作品选择完整'),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget _buildEmptyState() {
|
||
return Center(
|
||
child: Column(
|
||
mainAxisAlignment: MainAxisAlignment.center,
|
||
children: [
|
||
Image.asset(
|
||
'images/empty_works.png',
|
||
width: 120,
|
||
height: 120,
|
||
),
|
||
const SizedBox(height: 16),
|
||
const Text(
|
||
'暂无作品',
|
||
style: TextStyle(
|
||
color: Colors.white,
|
||
fontSize: 16,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget _buildSelectedImageSlot(int index) {
|
||
final imageIndex = selectedImages[index];
|
||
final hasImage = imageIndex != null;
|
||
final work = hasImage ? works[imageIndex] : null;
|
||
|
||
return Padding(
|
||
padding: const EdgeInsets.only(right: 16),
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
Text(
|
||
sourceInfo[index]['position'] ?? '未选择',
|
||
style: const TextStyle(color: Colors.white),
|
||
),
|
||
const SizedBox(height: 8),
|
||
Stack(
|
||
clipBehavior: Clip.none,
|
||
children: [
|
||
Container(
|
||
width: 60,
|
||
height: 60,
|
||
decoration: BoxDecoration(
|
||
borderRadius: BorderRadius.circular(8),
|
||
color: const Color(0xff1F212E),
|
||
),
|
||
child: hasImage
|
||
? ClipRRect(
|
||
borderRadius: BorderRadius.circular(8),
|
||
child: CachedImage(
|
||
imageUrl: work?.imageUrl ?? '',
|
||
width: 60,
|
||
height: 60,
|
||
fit: BoxFit.cover,
|
||
),
|
||
)
|
||
: const Center(
|
||
child: Icon(
|
||
Icons.add_photo_alternate_outlined,
|
||
color: Colors.white,
|
||
),
|
||
),
|
||
),
|
||
if (hasImage)
|
||
Positioned(
|
||
top: -8,
|
||
right: -8,
|
||
child: GestureDetector(
|
||
onTap: () => _removeImage(index),
|
||
child: Container(
|
||
padding: const EdgeInsets.all(2),
|
||
decoration: BoxDecoration(
|
||
color: Colors.black.withOpacity(0.5),
|
||
shape: BoxShape.circle,
|
||
),
|
||
child: const Icon(
|
||
Icons.close,
|
||
color: Colors.white,
|
||
size: 14,
|
||
),
|
||
),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
}
|