feat(mobile): allow manual input for planting quantity
- Replace static text with editable TextField for quantity - Add warning when input exceeds max quantity based on balance - Sync +/- buttons with input field value 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
3dcf685715
commit
4074281088
|
|
@ -34,10 +34,58 @@ class _PlantingQuantityPageState extends ConsumerState<PlantingQuantityPage> {
|
|||
/// 加载错误信息
|
||||
String? _errorMessage;
|
||||
|
||||
/// 数量输入框控制器
|
||||
final TextEditingController _quantityController = TextEditingController();
|
||||
|
||||
/// 数量输入框焦点
|
||||
final FocusNode _quantityFocusNode = FocusNode();
|
||||
|
||||
/// 是否显示超出警告
|
||||
bool _showExceedWarning = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_loadBalance();
|
||||
_quantityController.addListener(_onQuantityChanged);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_quantityController.removeListener(_onQuantityChanged);
|
||||
_quantityController.dispose();
|
||||
_quantityFocusNode.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
/// 输入框数量变化监听
|
||||
void _onQuantityChanged() {
|
||||
final text = _quantityController.text;
|
||||
if (text.isEmpty) {
|
||||
setState(() {
|
||||
_quantity = 0;
|
||||
_showExceedWarning = false;
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
final inputQty = int.tryParse(text) ?? 0;
|
||||
setState(() {
|
||||
_quantity = inputQty;
|
||||
_showExceedWarning = inputQty > _maxQuantity;
|
||||
});
|
||||
}
|
||||
|
||||
/// 更新输入框显示的数量
|
||||
void _updateQuantityText(int qty) {
|
||||
final newText = qty > 0 ? qty.toString() : '';
|
||||
if (_quantityController.text != newText) {
|
||||
_quantityController.text = newText;
|
||||
// 将光标移到末尾
|
||||
_quantityController.selection = TextSelection.fromPosition(
|
||||
TextPosition(offset: newText.length),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 加载用户余额
|
||||
|
|
@ -69,7 +117,10 @@ class _PlantingQuantityPageState extends ConsumerState<PlantingQuantityPage> {
|
|||
// 自动填入最大可认种数量,至少为1(如果有足够余额)
|
||||
_quantity = maxQty > 0 ? maxQty : 0;
|
||||
_isLoading = false;
|
||||
_showExceedWarning = false;
|
||||
});
|
||||
// 更新输入框
|
||||
_updateQuantityText(_quantity);
|
||||
} catch (e) {
|
||||
debugPrint('加载余额失败: $e');
|
||||
setState(() {
|
||||
|
|
@ -89,14 +140,24 @@ class _PlantingQuantityPageState extends ConsumerState<PlantingQuantityPage> {
|
|||
/// 减少数量
|
||||
void _decreaseQuantity() {
|
||||
if (_quantity > 1) {
|
||||
setState(() => _quantity--);
|
||||
final newQty = _quantity - 1;
|
||||
setState(() {
|
||||
_quantity = newQty;
|
||||
_showExceedWarning = false;
|
||||
});
|
||||
_updateQuantityText(newQty);
|
||||
}
|
||||
}
|
||||
|
||||
/// 增加数量
|
||||
void _increaseQuantity() {
|
||||
if (_quantity < _maxQuantity) {
|
||||
setState(() => _quantity++);
|
||||
final newQty = _quantity + 1;
|
||||
setState(() {
|
||||
_quantity = newQty;
|
||||
_showExceedWarning = false;
|
||||
});
|
||||
_updateQuantityText(newQty);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -403,55 +464,139 @@ class _PlantingQuantityPageState extends ConsumerState<PlantingQuantityPage> {
|
|||
|
||||
/// 构建数量选择器
|
||||
Widget _buildQuantitySelector() {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(24),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0x99FFFFFF),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
boxShadow: const [
|
||||
BoxShadow(
|
||||
color: Color(0x1A000000),
|
||||
blurRadius: 6,
|
||||
offset: Offset(0, 4),
|
||||
return Column(
|
||||
children: [
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(24),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0x99FFFFFF),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
boxShadow: const [
|
||||
BoxShadow(
|
||||
color: Color(0x1A000000),
|
||||
blurRadius: 6,
|
||||
offset: Offset(0, 4),
|
||||
),
|
||||
BoxShadow(
|
||||
color: Color(0x1A000000),
|
||||
blurRadius: 4,
|
||||
offset: Offset(0, 2),
|
||||
),
|
||||
],
|
||||
),
|
||||
BoxShadow(
|
||||
color: Color(0x1A000000),
|
||||
blurRadius: 4,
|
||||
offset: Offset(0, 2),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
// 减少按钮
|
||||
_buildQuantityButton(
|
||||
icon: '-',
|
||||
onTap: _canDecrease ? _decreaseQuantity : null,
|
||||
enabled: _canDecrease,
|
||||
),
|
||||
const SizedBox(width: 24),
|
||||
// 数量输入框
|
||||
SizedBox(
|
||||
width: 80,
|
||||
child: TextField(
|
||||
controller: _quantityController,
|
||||
focusNode: _quantityFocusNode,
|
||||
keyboardType: TextInputType.number,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 36,
|
||||
fontFamily: 'Inter',
|
||||
fontWeight: FontWeight.w400,
|
||||
height: 1.5,
|
||||
color: _showExceedWarning
|
||||
? const Color(0xFFE65100)
|
||||
: const Color(0xFF5D4037),
|
||||
),
|
||||
decoration: InputDecoration(
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(
|
||||
color: _showExceedWarning
|
||||
? const Color(0xFFE65100)
|
||||
: const Color(0xFFD4AF37),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(
|
||||
color: _showExceedWarning
|
||||
? const Color(0xFFE65100)
|
||||
: const Color(0xFFD4AF37),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(
|
||||
color: _showExceedWarning
|
||||
? const Color(0xFFE65100)
|
||||
: const Color(0xFFD4AF37),
|
||||
width: 2,
|
||||
),
|
||||
),
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: 8,
|
||||
vertical: 8,
|
||||
),
|
||||
isDense: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 24),
|
||||
// 增加按钮
|
||||
_buildQuantityButton(
|
||||
icon: '+',
|
||||
onTap: _canIncrease ? _increaseQuantity : null,
|
||||
enabled: _canIncrease,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
// 减少按钮
|
||||
_buildQuantityButton(
|
||||
icon: '-',
|
||||
onTap: _canDecrease ? _decreaseQuantity : null,
|
||||
enabled: _canDecrease,
|
||||
),
|
||||
const SizedBox(width: 38),
|
||||
// 数量显示
|
||||
Text(
|
||||
'$_quantity',
|
||||
style: const TextStyle(
|
||||
fontSize: 36,
|
||||
fontFamily: 'Inter',
|
||||
fontWeight: FontWeight.w400,
|
||||
height: 1.5,
|
||||
color: Color(0xFF5D4037),
|
||||
),
|
||||
// 超出警告提示
|
||||
if (_showExceedWarning)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 12),
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFFFF3E0),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(
|
||||
color: const Color(0xFFE65100),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.warning_amber_rounded,
|
||||
color: Color(0xFFE65100),
|
||||
size: 20,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'输入数量 $_quantity 超过最大可认种数量 $_maxQuantity,请调整',
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontFamily: 'Inter',
|
||||
height: 1.5,
|
||||
color: Color(0xFFE65100),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 38),
|
||||
// 增加按钮
|
||||
_buildQuantityButton(
|
||||
icon: '+',
|
||||
onTap: _canIncrease ? _increaseQuantity : null,
|
||||
enabled: _canIncrease,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue