907 lines
30 KiB
Dart
907 lines
30 KiB
Dart
import 'package:flutter/material.dart';
|
||
import 'package:flutter/services.dart';
|
||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||
import 'package:go_router/go_router.dart';
|
||
import '../../../core/utils/format_utils.dart';
|
||
import '../../providers/c2c_providers.dart';
|
||
import '../../providers/user_providers.dart';
|
||
import '../../providers/asset_providers.dart';
|
||
import '../../providers/trading_providers.dart';
|
||
|
||
class C2cPublishPage extends ConsumerStatefulWidget {
|
||
const C2cPublishPage({super.key});
|
||
|
||
@override
|
||
ConsumerState<C2cPublishPage> createState() => _C2cPublishPageState();
|
||
}
|
||
|
||
class _C2cPublishPageState extends ConsumerState<C2cPublishPage> {
|
||
static const Color _orange = Color(0xFFFF6B00);
|
||
static const Color _green = Color(0xFF10B981);
|
||
static const Color _red = Color(0xFFEF4444);
|
||
static const Color _darkText = Color(0xFF1F2937);
|
||
static const Color _grayText = Color(0xFF6B7280);
|
||
static const Color _bgGray = Color(0xFFF3F4F6);
|
||
|
||
int _selectedType = 1; // 0: 买入, 1: 卖出
|
||
final _priceController = TextEditingController();
|
||
final _quantityController = TextEditingController();
|
||
final _remarkController = TextEditingController();
|
||
|
||
// 收款信息(卖单必填)
|
||
Set<String> _selectedPaymentMethods = {'GREEN_POINTS'}; // 绿积分默认选中且不可取消
|
||
final _paymentAccountController = TextEditingController();
|
||
final _paymentRealNameController = TextEditingController();
|
||
final _systemIdController = TextEditingController(); // 1.0系统ID
|
||
|
||
@override
|
||
void dispose() {
|
||
_priceController.dispose();
|
||
_quantityController.dispose();
|
||
_remarkController.dispose();
|
||
_paymentAccountController.dispose();
|
||
_paymentRealNameController.dispose();
|
||
_systemIdController.dispose();
|
||
super.dispose();
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
final user = ref.watch(userNotifierProvider);
|
||
final accountSequence = user.accountSequence ?? '';
|
||
final assetAsync = ref.watch(accountAssetProvider(accountSequence));
|
||
final priceAsync = ref.watch(currentPriceProvider);
|
||
final c2cState = ref.watch(c2cTradingNotifierProvider);
|
||
|
||
final asset = assetAsync.valueOrNull;
|
||
final currentPrice = priceAsync.valueOrNull?.price ?? '0';
|
||
final availableShares = asset?.availableShares ?? '0';
|
||
final availableCash = asset?.availableCash ?? '0';
|
||
|
||
// 设置默认价格
|
||
if (_priceController.text.isEmpty && currentPrice != '0') {
|
||
_priceController.text = currentPrice;
|
||
}
|
||
|
||
return Scaffold(
|
||
backgroundColor: _bgGray,
|
||
appBar: AppBar(
|
||
backgroundColor: Colors.white,
|
||
elevation: 0,
|
||
leading: IconButton(
|
||
icon: const Icon(Icons.arrow_back, color: _darkText),
|
||
onPressed: () => context.pop(),
|
||
),
|
||
title: const Text(
|
||
'发布广告',
|
||
style: TextStyle(
|
||
fontSize: 18,
|
||
fontWeight: FontWeight.bold,
|
||
color: _darkText,
|
||
),
|
||
),
|
||
centerTitle: true,
|
||
),
|
||
body: SingleChildScrollView(
|
||
child: Column(
|
||
children: [
|
||
const SizedBox(height: 16),
|
||
|
||
// 交易类型选择
|
||
_buildTypeSelector(),
|
||
|
||
const SizedBox(height: 16),
|
||
|
||
// 可用余额
|
||
_buildBalanceCard(availableShares, availableCash),
|
||
|
||
const SizedBox(height: 16),
|
||
|
||
// 价格输入
|
||
_buildPriceInput(currentPrice),
|
||
|
||
const SizedBox(height: 16),
|
||
|
||
// 数量输入
|
||
_buildQuantityInput(availableShares, availableCash, currentPrice),
|
||
|
||
const SizedBox(height: 16),
|
||
|
||
// 收款信息(卖单必填)
|
||
if (_selectedType == 1) ...[
|
||
_buildPaymentInfoInput(),
|
||
const SizedBox(height: 16),
|
||
],
|
||
|
||
// 备注
|
||
_buildRemarkInput(),
|
||
|
||
const SizedBox(height: 16),
|
||
|
||
// 预估信息
|
||
_buildEstimateCard(),
|
||
|
||
const SizedBox(height: 24),
|
||
|
||
// 发布按钮
|
||
_buildPublishButton(c2cState),
|
||
|
||
const SizedBox(height: 16),
|
||
|
||
// 提示信息
|
||
_buildTips(),
|
||
|
||
const SizedBox(height: 24),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget _buildTypeSelector() {
|
||
return Container(
|
||
margin: const EdgeInsets.symmetric(horizontal: 16),
|
||
padding: const EdgeInsets.all(4),
|
||
decoration: BoxDecoration(
|
||
color: Colors.white,
|
||
borderRadius: BorderRadius.circular(12),
|
||
),
|
||
child: Row(
|
||
children: [
|
||
Expanded(
|
||
child: GestureDetector(
|
||
onTap: () => setState(() => _selectedType = 0),
|
||
child: Container(
|
||
padding: const EdgeInsets.symmetric(vertical: 12),
|
||
decoration: BoxDecoration(
|
||
color: _selectedType == 0 ? _green : Colors.transparent,
|
||
borderRadius: BorderRadius.circular(8),
|
||
),
|
||
child: Text(
|
||
'我要买入',
|
||
textAlign: TextAlign.center,
|
||
style: TextStyle(
|
||
fontSize: 14,
|
||
fontWeight: FontWeight.bold,
|
||
color: _selectedType == 0 ? Colors.white : _grayText,
|
||
),
|
||
),
|
||
),
|
||
),
|
||
),
|
||
Expanded(
|
||
child: GestureDetector(
|
||
onTap: () => setState(() => _selectedType = 1),
|
||
child: Container(
|
||
padding: const EdgeInsets.symmetric(vertical: 12),
|
||
decoration: BoxDecoration(
|
||
color: _selectedType == 1 ? _red : Colors.transparent,
|
||
borderRadius: BorderRadius.circular(8),
|
||
),
|
||
child: Text(
|
||
'我要卖出',
|
||
textAlign: TextAlign.center,
|
||
style: TextStyle(
|
||
fontSize: 14,
|
||
fontWeight: FontWeight.bold,
|
||
color: _selectedType == 1 ? Colors.white : _grayText,
|
||
),
|
||
),
|
||
),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget _buildBalanceCard(String availableShares, String availableCash) {
|
||
// C2C交易的是积分值,买入广告需要买家有绿积分(积分值)来支付
|
||
// 卖出广告需要卖家有积分值来出售
|
||
return Container(
|
||
margin: const EdgeInsets.symmetric(horizontal: 16),
|
||
padding: const EdgeInsets.all(16),
|
||
decoration: BoxDecoration(
|
||
color: Colors.white,
|
||
borderRadius: BorderRadius.circular(12),
|
||
),
|
||
child: Row(
|
||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||
children: [
|
||
const Text(
|
||
'可用积分值',
|
||
style: TextStyle(fontSize: 14, color: _grayText),
|
||
),
|
||
Text(
|
||
formatAmount(availableCash),
|
||
style: const TextStyle(
|
||
fontSize: 16,
|
||
fontWeight: FontWeight.bold,
|
||
color: _green,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget _buildPriceInput(String currentPrice) {
|
||
return Container(
|
||
margin: const EdgeInsets.symmetric(horizontal: 16),
|
||
padding: const EdgeInsets.all(20),
|
||
decoration: BoxDecoration(
|
||
color: Colors.white,
|
||
borderRadius: BorderRadius.circular(12),
|
||
),
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
Row(
|
||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||
children: [
|
||
const Text(
|
||
'单价',
|
||
style: TextStyle(
|
||
fontSize: 16,
|
||
fontWeight: FontWeight.bold,
|
||
color: _darkText,
|
||
),
|
||
),
|
||
Text(
|
||
'当前价: ${formatPrice(currentPrice)}',
|
||
style: const TextStyle(fontSize: 12, color: _grayText),
|
||
),
|
||
],
|
||
),
|
||
const SizedBox(height: 12),
|
||
TextField(
|
||
controller: _priceController,
|
||
keyboardType: const TextInputType.numberWithOptions(decimal: true),
|
||
inputFormatters: [
|
||
FilteringTextInputFormatter.allow(RegExp(r'^\d+\.?\d{0,8}')),
|
||
],
|
||
decoration: InputDecoration(
|
||
hintText: '请输入单价',
|
||
hintStyle: const TextStyle(color: _grayText),
|
||
filled: true,
|
||
fillColor: _bgGray,
|
||
border: OutlineInputBorder(
|
||
borderRadius: BorderRadius.circular(12),
|
||
borderSide: BorderSide.none,
|
||
),
|
||
focusedBorder: OutlineInputBorder(
|
||
borderRadius: BorderRadius.circular(12),
|
||
borderSide: const BorderSide(color: _orange, width: 2),
|
||
),
|
||
suffixText: '元/积分值',
|
||
suffixStyle: const TextStyle(color: _grayText, fontSize: 14),
|
||
),
|
||
onChanged: (_) => setState(() {}),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget _buildQuantityInput(
|
||
String availableShares,
|
||
String availableCash,
|
||
String currentPrice,
|
||
) {
|
||
// C2C交易的是积分值
|
||
return Container(
|
||
margin: const EdgeInsets.symmetric(horizontal: 16),
|
||
padding: const EdgeInsets.all(20),
|
||
decoration: BoxDecoration(
|
||
color: Colors.white,
|
||
borderRadius: BorderRadius.circular(12),
|
||
),
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
const Text(
|
||
'数量',
|
||
style: TextStyle(
|
||
fontSize: 16,
|
||
fontWeight: FontWeight.bold,
|
||
color: _darkText,
|
||
),
|
||
),
|
||
const SizedBox(height: 12),
|
||
TextField(
|
||
controller: _quantityController,
|
||
keyboardType: const TextInputType.numberWithOptions(decimal: true),
|
||
inputFormatters: [
|
||
FilteringTextInputFormatter.allow(RegExp(r'^\d+\.?\d{0,4}')),
|
||
],
|
||
decoration: InputDecoration(
|
||
hintText: '请输入积分值数量',
|
||
hintStyle: const TextStyle(color: _grayText),
|
||
filled: true,
|
||
fillColor: _bgGray,
|
||
border: OutlineInputBorder(
|
||
borderRadius: BorderRadius.circular(12),
|
||
borderSide: BorderSide.none,
|
||
),
|
||
focusedBorder: OutlineInputBorder(
|
||
borderRadius: BorderRadius.circular(12),
|
||
borderSide: const BorderSide(color: _orange, width: 2),
|
||
),
|
||
suffixIcon: TextButton(
|
||
onPressed: () {
|
||
// 填入全部可用积分值
|
||
_quantityController.text = availableCash;
|
||
setState(() {});
|
||
},
|
||
child: const Text(
|
||
'全部',
|
||
style: TextStyle(
|
||
color: _orange,
|
||
fontWeight: FontWeight.w500,
|
||
),
|
||
),
|
||
),
|
||
suffixText: '积分值',
|
||
suffixStyle: const TextStyle(color: _grayText, fontSize: 14),
|
||
),
|
||
onChanged: (_) => setState(() {}),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget _buildPaymentInfoInput() {
|
||
return Container(
|
||
margin: const EdgeInsets.symmetric(horizontal: 16),
|
||
padding: const EdgeInsets.all(20),
|
||
decoration: BoxDecoration(
|
||
color: Colors.white,
|
||
borderRadius: BorderRadius.circular(12),
|
||
),
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
Row(
|
||
children: const [
|
||
Text(
|
||
'收款信息',
|
||
style: TextStyle(
|
||
fontSize: 16,
|
||
fontWeight: FontWeight.bold,
|
||
color: _darkText,
|
||
),
|
||
),
|
||
SizedBox(width: 8),
|
||
Text(
|
||
'(必填)',
|
||
style: TextStyle(fontSize: 12, color: _red),
|
||
),
|
||
],
|
||
),
|
||
const SizedBox(height: 16),
|
||
|
||
// 收款方式选择(多选)
|
||
const Text(
|
||
'收款方式(可多选)',
|
||
style: TextStyle(fontSize: 14, color: _grayText),
|
||
),
|
||
const SizedBox(height: 8),
|
||
Wrap(
|
||
spacing: 12,
|
||
runSpacing: 8,
|
||
children: [
|
||
// 绿积分 - 默认选中且不可取消
|
||
_buildPaymentMethodCheckbox('GREEN_POINTS', '绿积分', Icons.eco, isLocked: true),
|
||
_buildPaymentMethodCheckbox('ALIPAY', '支付宝', Icons.account_balance_wallet),
|
||
_buildPaymentMethodCheckbox('WECHAT', '微信', Icons.chat_bubble),
|
||
_buildPaymentMethodCheckbox('BANK', '银行卡', Icons.credit_card),
|
||
],
|
||
),
|
||
const SizedBox(height: 16),
|
||
|
||
// 1.0系统ID(绿积分必填)
|
||
const Text(
|
||
'1.0系统ID',
|
||
style: TextStyle(fontSize: 14, color: _grayText),
|
||
),
|
||
const SizedBox(height: 4),
|
||
const Text(
|
||
'买家将通过此ID向您转账绿积分',
|
||
style: TextStyle(fontSize: 12, color: _grayText),
|
||
),
|
||
const SizedBox(height: 8),
|
||
TextField(
|
||
controller: _systemIdController,
|
||
decoration: InputDecoration(
|
||
hintText: '请输入您的1.0系统ID',
|
||
hintStyle: const TextStyle(color: _grayText),
|
||
filled: true,
|
||
fillColor: _bgGray,
|
||
border: OutlineInputBorder(
|
||
borderRadius: BorderRadius.circular(12),
|
||
borderSide: BorderSide.none,
|
||
),
|
||
focusedBorder: OutlineInputBorder(
|
||
borderRadius: BorderRadius.circular(12),
|
||
borderSide: const BorderSide(color: _orange, width: 2),
|
||
),
|
||
),
|
||
),
|
||
|
||
// 只有选择了非绿积分支付方式才显示收款账号和姓名
|
||
if (_selectedPaymentMethods.any((m) => m != 'GREEN_POINTS')) ...[
|
||
const SizedBox(height: 16),
|
||
// 收款账号
|
||
const Text(
|
||
'收款账号(其他支付方式)',
|
||
style: TextStyle(fontSize: 14, color: _grayText),
|
||
),
|
||
const SizedBox(height: 8),
|
||
TextField(
|
||
controller: _paymentAccountController,
|
||
decoration: InputDecoration(
|
||
hintText: '请输入收款账号',
|
||
hintStyle: const TextStyle(color: _grayText),
|
||
filled: true,
|
||
fillColor: _bgGray,
|
||
border: OutlineInputBorder(
|
||
borderRadius: BorderRadius.circular(12),
|
||
borderSide: BorderSide.none,
|
||
),
|
||
focusedBorder: OutlineInputBorder(
|
||
borderRadius: BorderRadius.circular(12),
|
||
borderSide: const BorderSide(color: _orange, width: 2),
|
||
),
|
||
),
|
||
),
|
||
const SizedBox(height: 16),
|
||
|
||
// 收款人实名
|
||
const Text(
|
||
'收款人姓名',
|
||
style: TextStyle(fontSize: 14, color: _grayText),
|
||
),
|
||
const SizedBox(height: 8),
|
||
TextField(
|
||
controller: _paymentRealNameController,
|
||
decoration: InputDecoration(
|
||
hintText: '请输入收款人真实姓名',
|
||
hintStyle: const TextStyle(color: _grayText),
|
||
filled: true,
|
||
fillColor: _bgGray,
|
||
border: OutlineInputBorder(
|
||
borderRadius: BorderRadius.circular(12),
|
||
borderSide: BorderSide.none,
|
||
),
|
||
focusedBorder: OutlineInputBorder(
|
||
borderRadius: BorderRadius.circular(12),
|
||
borderSide: const BorderSide(color: _orange, width: 2),
|
||
),
|
||
),
|
||
),
|
||
],
|
||
|
||
const SizedBox(height: 12),
|
||
Container(
|
||
padding: const EdgeInsets.all(12),
|
||
decoration: BoxDecoration(
|
||
color: _green.withOpacity(0.1),
|
||
borderRadius: BorderRadius.circular(8),
|
||
),
|
||
child: Row(
|
||
children: const [
|
||
Icon(Icons.eco, size: 16, color: _green),
|
||
SizedBox(width: 8),
|
||
Expanded(
|
||
child: Text(
|
||
'绿积分支付:买家将在1.0系统中向您的ID转账绿积分',
|
||
style: TextStyle(fontSize: 12, color: _green),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget _buildPaymentMethodCheckbox(String value, String label, IconData icon, {bool isLocked = false}) {
|
||
final isSelected = _selectedPaymentMethods.contains(value);
|
||
return GestureDetector(
|
||
onTap: isLocked ? null : () {
|
||
setState(() {
|
||
if (isSelected) {
|
||
_selectedPaymentMethods.remove(value);
|
||
} else {
|
||
_selectedPaymentMethods.add(value);
|
||
}
|
||
});
|
||
},
|
||
child: Container(
|
||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
||
decoration: BoxDecoration(
|
||
color: isSelected ? (value == 'GREEN_POINTS' ? _green : _orange) : _bgGray,
|
||
borderRadius: BorderRadius.circular(8),
|
||
border: isSelected ? null : Border.all(color: Colors.grey.shade300),
|
||
),
|
||
child: Row(
|
||
mainAxisSize: MainAxisSize.min,
|
||
children: [
|
||
Icon(
|
||
isSelected ? Icons.check_circle : Icons.circle_outlined,
|
||
size: 18,
|
||
color: isSelected ? Colors.white : _grayText,
|
||
),
|
||
const SizedBox(width: 6),
|
||
Icon(
|
||
icon,
|
||
size: 16,
|
||
color: isSelected ? Colors.white : _grayText,
|
||
),
|
||
const SizedBox(width: 4),
|
||
Text(
|
||
label,
|
||
style: TextStyle(
|
||
fontSize: 13,
|
||
color: isSelected ? Colors.white : _darkText,
|
||
fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
|
||
),
|
||
),
|
||
if (isLocked) ...[
|
||
const SizedBox(width: 4),
|
||
Icon(
|
||
Icons.lock,
|
||
size: 12,
|
||
color: isSelected ? Colors.white70 : _grayText,
|
||
),
|
||
],
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget _buildRemarkInput() {
|
||
return Container(
|
||
margin: const EdgeInsets.symmetric(horizontal: 16),
|
||
padding: const EdgeInsets.all(20),
|
||
decoration: BoxDecoration(
|
||
color: Colors.white,
|
||
borderRadius: BorderRadius.circular(12),
|
||
),
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
const Text(
|
||
'备注 (可选)',
|
||
style: TextStyle(
|
||
fontSize: 16,
|
||
fontWeight: FontWeight.bold,
|
||
color: _darkText,
|
||
),
|
||
),
|
||
const SizedBox(height: 12),
|
||
TextField(
|
||
controller: _remarkController,
|
||
maxLength: 100,
|
||
maxLines: 2,
|
||
decoration: InputDecoration(
|
||
hintText: '添加交易说明,如联系方式等',
|
||
hintStyle: const TextStyle(color: _grayText),
|
||
filled: true,
|
||
fillColor: _bgGray,
|
||
border: OutlineInputBorder(
|
||
borderRadius: BorderRadius.circular(12),
|
||
borderSide: BorderSide.none,
|
||
),
|
||
focusedBorder: OutlineInputBorder(
|
||
borderRadius: BorderRadius.circular(12),
|
||
borderSide: const BorderSide(color: _orange, width: 2),
|
||
),
|
||
counterStyle: const TextStyle(color: _grayText),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget _buildEstimateCard() {
|
||
final price = double.tryParse(_priceController.text) ?? 0;
|
||
final quantity = double.tryParse(_quantityController.text) ?? 0;
|
||
final total = price * quantity;
|
||
final isBuy = _selectedType == 0;
|
||
|
||
return Container(
|
||
margin: const EdgeInsets.symmetric(horizontal: 16),
|
||
padding: const EdgeInsets.all(16),
|
||
decoration: BoxDecoration(
|
||
color: _orange.withOpacity(0.05),
|
||
borderRadius: BorderRadius.circular(12),
|
||
border: Border.all(color: _orange.withOpacity(0.2)),
|
||
),
|
||
child: Column(
|
||
children: [
|
||
Row(
|
||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||
children: [
|
||
const Text('交易总额', style: TextStyle(fontSize: 14, color: _grayText)),
|
||
Text(
|
||
'${formatAmount(total.toString())} 积分值',
|
||
style: const TextStyle(
|
||
fontSize: 18,
|
||
fontWeight: FontWeight.bold,
|
||
color: _orange,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
const SizedBox(height: 8),
|
||
Row(
|
||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||
children: [
|
||
const Text('积分值数量', style: TextStyle(fontSize: 14, color: _grayText)),
|
||
Text(
|
||
'${formatAmount(quantity.toString())} 积分值',
|
||
style: const TextStyle(
|
||
fontSize: 14,
|
||
fontWeight: FontWeight.bold,
|
||
color: _green,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
const SizedBox(height: 8),
|
||
Divider(color: _orange.withOpacity(0.2)),
|
||
const SizedBox(height: 8),
|
||
Text(
|
||
isBuy
|
||
? '发布后,其他用户可以接单卖出积分值给您'
|
||
: '发布后,其他用户可以接单购买您的积分值',
|
||
style: const TextStyle(fontSize: 12, color: _grayText),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget _buildPublishButton(C2cTradingState c2cState) {
|
||
final price = double.tryParse(_priceController.text) ?? 0;
|
||
final quantity = double.tryParse(_quantityController.text) ?? 0;
|
||
final isSell = _selectedType == 1;
|
||
|
||
// 验证条件
|
||
bool isValid = price > 0 && quantity > 0;
|
||
if (isSell) {
|
||
// 卖单必须填写1.0系统ID(因为绿积分是必选的)
|
||
isValid = isValid && _systemIdController.text.trim().isNotEmpty;
|
||
// 如果选择了其他支付方式,还需要填写收款账号和姓名
|
||
if (_selectedPaymentMethods.any((m) => m != 'GREEN_POINTS')) {
|
||
isValid = isValid &&
|
||
_paymentAccountController.text.trim().isNotEmpty &&
|
||
_paymentRealNameController.text.trim().isNotEmpty;
|
||
}
|
||
}
|
||
|
||
return Padding(
|
||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||
child: SizedBox(
|
||
width: double.infinity,
|
||
height: 50,
|
||
child: ElevatedButton(
|
||
onPressed: isValid && !c2cState.isLoading ? _handlePublish : null,
|
||
style: ElevatedButton.styleFrom(
|
||
backgroundColor: _selectedType == 0 ? _green : _red,
|
||
foregroundColor: Colors.white,
|
||
disabledBackgroundColor: (_selectedType == 0 ? _green : _red).withOpacity(0.4),
|
||
disabledForegroundColor: Colors.white70,
|
||
shape: RoundedRectangleBorder(
|
||
borderRadius: BorderRadius.circular(12),
|
||
),
|
||
),
|
||
child: c2cState.isLoading
|
||
? const SizedBox(
|
||
width: 24,
|
||
height: 24,
|
||
child: CircularProgressIndicator(
|
||
strokeWidth: 2,
|
||
color: Colors.white,
|
||
),
|
||
)
|
||
: Text(
|
||
_selectedType == 0 ? '发布买入广告' : '发布卖出广告',
|
||
style: const TextStyle(
|
||
fontSize: 16,
|
||
fontWeight: FontWeight.bold,
|
||
),
|
||
),
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget _buildTips() {
|
||
return Container(
|
||
margin: const EdgeInsets.symmetric(horizontal: 16),
|
||
padding: const EdgeInsets.all(16),
|
||
decoration: BoxDecoration(
|
||
color: Colors.white,
|
||
borderRadius: BorderRadius.circular(12),
|
||
),
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
Row(
|
||
children: const [
|
||
Icon(Icons.info_outline, size: 16, color: _orange),
|
||
SizedBox(width: 8),
|
||
Text(
|
||
'交易说明',
|
||
style: TextStyle(
|
||
fontSize: 14,
|
||
fontWeight: FontWeight.bold,
|
||
color: _orange,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
const SizedBox(height: 8),
|
||
const Text(
|
||
'1. 发布广告后,您的积分值将被冻结直到交易完成或取消\n'
|
||
'2. 其他用户接单后,需在规定时间内完成交易\n'
|
||
'3. 买方需在1.0系统中向卖方转账绿积分\n'
|
||
'4. 卖方确认收到绿积分后,积分值自动划转给买方\n'
|
||
'5. 如遇问题,请联系客服处理',
|
||
style: TextStyle(
|
||
fontSize: 12,
|
||
color: _grayText,
|
||
height: 1.5,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
Future<void> _handlePublish() async {
|
||
final price = _priceController.text.trim();
|
||
final quantity = _quantityController.text.trim();
|
||
final remark = _remarkController.text.trim();
|
||
final type = _selectedType == 0 ? 'BUY' : 'SELL';
|
||
final isSell = _selectedType == 1;
|
||
|
||
// 卖单验证收款信息
|
||
if (isSell) {
|
||
// 必须填写1.0系统ID(绿积分是必选的)
|
||
if (_systemIdController.text.trim().isEmpty) {
|
||
ScaffoldMessenger.of(context).showSnackBar(
|
||
const SnackBar(content: Text('请填写1.0系统ID'), backgroundColor: _red),
|
||
);
|
||
return;
|
||
}
|
||
// 如果选择了其他支付方式,需要填写收款账号和姓名
|
||
if (_selectedPaymentMethods.any((m) => m != 'GREEN_POINTS')) {
|
||
if (_paymentAccountController.text.trim().isEmpty) {
|
||
ScaffoldMessenger.of(context).showSnackBar(
|
||
const SnackBar(content: Text('请填写收款账号'), backgroundColor: _red),
|
||
);
|
||
return;
|
||
}
|
||
if (_paymentRealNameController.text.trim().isEmpty) {
|
||
ScaffoldMessenger.of(context).showSnackBar(
|
||
const SnackBar(content: Text('请填写收款人姓名'), backgroundColor: _red),
|
||
);
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 构建支付方式显示文本
|
||
final paymentMethodTexts = _selectedPaymentMethods.map((m) {
|
||
switch (m) {
|
||
case 'GREEN_POINTS': return '绿积分';
|
||
case 'ALIPAY': return '支付宝';
|
||
case 'WECHAT': return '微信';
|
||
case 'BANK': return '银行卡';
|
||
default: return m;
|
||
}
|
||
}).join('、');
|
||
|
||
// 确认对话框
|
||
final confirmed = await showDialog<bool>(
|
||
context: context,
|
||
builder: (context) => AlertDialog(
|
||
title: Text(_selectedType == 0 ? '确认发布买入广告' : '确认发布卖出广告'),
|
||
content: Column(
|
||
mainAxisSize: MainAxisSize.min,
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
Text('单价: $price 积分值'),
|
||
const SizedBox(height: 8),
|
||
Text('数量: $quantity 积分值'),
|
||
const SizedBox(height: 8),
|
||
Text(
|
||
'总额: ${formatAmount((double.parse(price) * double.parse(quantity)).toString())} 积分值',
|
||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||
),
|
||
if (isSell) ...[
|
||
const SizedBox(height: 16),
|
||
const Divider(),
|
||
const SizedBox(height: 8),
|
||
Text('收款方式: $paymentMethodTexts'),
|
||
const SizedBox(height: 4),
|
||
Text('1.0系统ID: ${_systemIdController.text.trim()}'),
|
||
if (_selectedPaymentMethods.any((m) => m != 'GREEN_POINTS')) ...[
|
||
const SizedBox(height: 4),
|
||
Text('收款账号: ${_paymentAccountController.text.trim()}'),
|
||
const SizedBox(height: 4),
|
||
Text('收款人: ${_paymentRealNameController.text.trim()}'),
|
||
],
|
||
],
|
||
const SizedBox(height: 16),
|
||
const Text(
|
||
'发布后,您的积分值将被冻结',
|
||
style: TextStyle(fontSize: 12, color: _grayText),
|
||
),
|
||
],
|
||
),
|
||
actions: [
|
||
TextButton(
|
||
onPressed: () => Navigator.pop(context, false),
|
||
child: const Text('取消'),
|
||
),
|
||
TextButton(
|
||
onPressed: () => Navigator.pop(context, true),
|
||
child: Text(
|
||
'确认发布',
|
||
style: TextStyle(color: _selectedType == 0 ? _green : _red),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
|
||
if (confirmed != true) return;
|
||
|
||
final notifier = ref.read(c2cTradingNotifierProvider.notifier);
|
||
final success = await notifier.createOrder(
|
||
type: type,
|
||
price: price,
|
||
quantity: quantity,
|
||
// 收款信息(卖单时传递)
|
||
paymentMethod: isSell ? _selectedPaymentMethods.join(',') : null,
|
||
paymentAccount: isSell ? _paymentAccountController.text.trim() : null,
|
||
paymentRealName: isSell ? _paymentRealNameController.text.trim() : null,
|
||
systemId: isSell ? _systemIdController.text.trim() : null,
|
||
remark: remark.isEmpty ? null : remark,
|
||
);
|
||
|
||
if (success && mounted) {
|
||
// 刷新列表
|
||
ref.invalidate(c2cOrdersProvider(type));
|
||
ref.invalidate(myC2cOrdersProvider);
|
||
// 刷新资产
|
||
final user = ref.read(userNotifierProvider);
|
||
ref.invalidate(accountAssetProvider(user.accountSequence ?? ''));
|
||
|
||
ScaffoldMessenger.of(context).showSnackBar(
|
||
const SnackBar(
|
||
content: Text('广告发布成功'),
|
||
backgroundColor: _green,
|
||
),
|
||
);
|
||
context.pop();
|
||
} else if (mounted) {
|
||
final error = ref.read(c2cTradingNotifierProvider).error;
|
||
ScaffoldMessenger.of(context).showSnackBar(
|
||
SnackBar(
|
||
content: Text('发布失败: ${error ?? '未知错误'}'),
|
||
backgroundColor: _red,
|
||
),
|
||
);
|
||
}
|
||
}
|
||
}
|