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;
|
String? _errorMessage;
|
||||||
|
|
||||||
|
/// 数量输入框控制器
|
||||||
|
final TextEditingController _quantityController = TextEditingController();
|
||||||
|
|
||||||
|
/// 数量输入框焦点
|
||||||
|
final FocusNode _quantityFocusNode = FocusNode();
|
||||||
|
|
||||||
|
/// 是否显示超出警告
|
||||||
|
bool _showExceedWarning = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_loadBalance();
|
_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(如果有足够余额)
|
// 自动填入最大可认种数量,至少为1(如果有足够余额)
|
||||||
_quantity = maxQty > 0 ? maxQty : 0;
|
_quantity = maxQty > 0 ? maxQty : 0;
|
||||||
_isLoading = false;
|
_isLoading = false;
|
||||||
|
_showExceedWarning = false;
|
||||||
});
|
});
|
||||||
|
// 更新输入框
|
||||||
|
_updateQuantityText(_quantity);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
debugPrint('加载余额失败: $e');
|
debugPrint('加载余额失败: $e');
|
||||||
setState(() {
|
setState(() {
|
||||||
|
|
@ -89,14 +140,24 @@ class _PlantingQuantityPageState extends ConsumerState<PlantingQuantityPage> {
|
||||||
/// 减少数量
|
/// 减少数量
|
||||||
void _decreaseQuantity() {
|
void _decreaseQuantity() {
|
||||||
if (_quantity > 1) {
|
if (_quantity > 1) {
|
||||||
setState(() => _quantity--);
|
final newQty = _quantity - 1;
|
||||||
|
setState(() {
|
||||||
|
_quantity = newQty;
|
||||||
|
_showExceedWarning = false;
|
||||||
|
});
|
||||||
|
_updateQuantityText(newQty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 增加数量
|
/// 增加数量
|
||||||
void _increaseQuantity() {
|
void _increaseQuantity() {
|
||||||
if (_quantity < _maxQuantity) {
|
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() {
|
Widget _buildQuantitySelector() {
|
||||||
return Container(
|
return Column(
|
||||||
width: double.infinity,
|
children: [
|
||||||
padding: const EdgeInsets.all(24),
|
Container(
|
||||||
decoration: BoxDecoration(
|
width: double.infinity,
|
||||||
color: const Color(0x99FFFFFF),
|
padding: const EdgeInsets.all(24),
|
||||||
borderRadius: BorderRadius.circular(12),
|
decoration: BoxDecoration(
|
||||||
boxShadow: const [
|
color: const Color(0x99FFFFFF),
|
||||||
BoxShadow(
|
borderRadius: BorderRadius.circular(12),
|
||||||
color: Color(0x1A000000),
|
boxShadow: const [
|
||||||
blurRadius: 6,
|
BoxShadow(
|
||||||
offset: Offset(0, 4),
|
color: Color(0x1A000000),
|
||||||
|
blurRadius: 6,
|
||||||
|
offset: Offset(0, 4),
|
||||||
|
),
|
||||||
|
BoxShadow(
|
||||||
|
color: Color(0x1A000000),
|
||||||
|
blurRadius: 4,
|
||||||
|
offset: Offset(0, 2),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
BoxShadow(
|
child: Row(
|
||||||
color: Color(0x1A000000),
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
blurRadius: 4,
|
children: [
|
||||||
offset: Offset(0, 2),
|
// 减少按钮
|
||||||
|
_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(
|
if (_showExceedWarning)
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
Padding(
|
||||||
children: [
|
padding: const EdgeInsets.only(top: 12),
|
||||||
// 减少按钮
|
child: Container(
|
||||||
_buildQuantityButton(
|
width: double.infinity,
|
||||||
icon: '-',
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||||
onTap: _canDecrease ? _decreaseQuantity : null,
|
decoration: BoxDecoration(
|
||||||
enabled: _canDecrease,
|
color: const Color(0xFFFFF3E0),
|
||||||
),
|
borderRadius: BorderRadius.circular(8),
|
||||||
const SizedBox(width: 38),
|
border: Border.all(
|
||||||
// 数量显示
|
color: const Color(0xFFE65100),
|
||||||
Text(
|
width: 1,
|
||||||
'$_quantity',
|
),
|
||||||
style: const TextStyle(
|
),
|
||||||
fontSize: 36,
|
child: Row(
|
||||||
fontFamily: 'Inter',
|
children: [
|
||||||
fontWeight: FontWeight.w400,
|
const Icon(
|
||||||
height: 1.5,
|
Icons.warning_amber_rounded,
|
||||||
color: Color(0xFF5D4037),
|
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