opt vote panel

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-07-30 19:20:56 +08:00
parent 83e5095cc3
commit c4e87925cf

View File

@@ -44,14 +44,75 @@ class _VotePanelState extends State<VotePanel> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = Theme.of(context); final theme = Theme.of(context);
return Column( final usePortrait =
context.orientation == Orientation.portrait || context.isTablet;
final right = [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
_enabled
? '投票选项'
: groupValue.isEmpty
? '已结束'
: '已完成',
),
if (_enabled) Obx(() => Text('${groupValue.length} / $_maxCnt')),
],
),
Flexible(
child: ListView.builder(
key: const PageStorageKey('vote_opions'),
shrinkWrap: true,
itemCount: _voteInfo.options.length,
itemBuilder: (context, index) => _buildOptions(index),
),
),
if (_enabled) ...[
_checkBoxs,
Padding(
padding: const EdgeInsets.only(top: 8),
child: Obx(
() => OutlinedButton(
onPressed: groupValue.isNotEmpty
? () async {
final res = await widget.callback(
groupValue,
anonymity,
);
if (res.isSuccess) {
if (mounted) {
setState(() {
_enabled = false;
_showPercentage = true;
_voteInfo = res.data;
_percentage = _cnt2Percentage(_voteInfo.options);
});
}
} else {
res.toast();
}
}
: null,
child: const Center(child: Text('投票')),
),
),
),
],
];
Widget child = Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
if (_voteInfo.title != null) if (_voteInfo.title != null)
Text(_voteInfo.title!, style: theme.textTheme.titleMedium), Text(_voteInfo.title!, style: theme.textTheme.titleMedium),
if (_voteInfo.desc != null) if (_voteInfo.desc != null)
Text(_voteInfo.desc!, style: theme.textTheme.titleSmall), Text(
_voteInfo.desc!,
style: theme.textTheme.titleSmall!.copyWith(
color: theme.colorScheme.onSurfaceVariant.withValues(alpha: 0.8),
),
),
Padding( Padding(
padding: const EdgeInsets.symmetric(vertical: 8), padding: const EdgeInsets.symmetric(vertical: 8),
child: Wrap( child: Wrap(
@@ -75,71 +136,49 @@ class _VotePanelState extends State<VotePanel> {
], ],
), ),
), ),
Row( if (usePortrait) ...right,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
_enabled
? '投票选项'
: groupValue.isEmpty
? '已结束'
: '已完成',
),
if (_enabled) Obx(() => Text('${groupValue.length} / $_maxCnt')),
],
),
Flexible(fit: FlexFit.loose, child: _buildContext()),
if (_enabled)
Padding(
padding: const EdgeInsets.only(top: 16),
child: Obx(
() => OutlinedButton(
onPressed: groupValue.isNotEmpty
? () async {
final res = await widget.callback(
groupValue,
anonymity,
);
if (res.isSuccess) {
if (mounted) {
setState(() {
_enabled = false;
_showPercentage = true;
_voteInfo = res.data;
_percentage = _cnt2Percentage(_voteInfo.options);
});
}
} else {
res.toast();
}
}
: null,
child: const Center(child: Text('投票')),
),
),
),
], ],
); );
if (!usePortrait) {
child = Row(
spacing: 12,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(child: child),
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: right,
),
),
],
);
}
return child;
} }
List<Widget> get _checkBoxs => [ Widget get _checkBoxs => Row(
CheckBoxText( spacing: 16,
text: '显示比例', children: [
selected: _showPercentage, CheckBoxText(
onChanged: (value) { text: '显示比例',
setState(() { selected: _showPercentage,
_showPercentage = value; onChanged: (value) {
}); setState(() {
}, _showPercentage = value;
), });
CheckBoxText( },
text: '匿名', ),
selected: anonymity, CheckBoxText(
onChanged: (val) { text: '匿名',
anonymity = val; selected: anonymity,
}, onChanged: (val) {
), anonymity = val;
]; },
),
],
);
Widget _buildOptions(int index) { Widget _buildOptions(int index) {
return Padding( return Padding(
@@ -178,19 +217,6 @@ class _VotePanelState extends State<VotePanel> {
} }
} }
Widget _buildContext() {
return CustomScrollView(
shrinkWrap: true,
slivers: [
SliverList.builder(
itemCount: _voteInfo.options.length,
itemBuilder: (context, index) => _buildOptions(index),
),
if (_enabled) SliverList.list(children: _checkBoxs),
],
);
}
static List<double> _cnt2Percentage(List<Option> options) { static List<double> _cnt2Percentage(List<Option> options) {
final total = options.fold(0, (sum, opt) => sum + opt.cnt); final total = options.fold(0, (sum, opt) => sum + opt.cnt);
return total == 0 return total == 0
@@ -288,16 +314,19 @@ Future showVoteDialog(
if (voteInfo.isSuccess) { if (voteInfo.isSuccess) {
showDialog( showDialog(
context: context, context: context,
builder: (context) => AlertDialog( builder: (context) => Dialog(
content: SizedBox( child: ConstrainedBox(
width: 160, constraints: const BoxConstraints(maxWidth: 625),
child: VotePanel( child: Padding(
voteInfo: voteInfo.data, padding: const EdgeInsets.all(24),
callback: (votes, anonymity) => DynamicsHttp.doVote( child: VotePanel(
voteId: voteId, voteInfo: voteInfo.data,
votes: votes.toList(), callback: (votes, anonymity) => DynamicsHttp.doVote(
anonymity: anonymity, voteId: voteId,
dynamicId: dynamicId, votes: votes.toList(),
anonymity: anonymity,
dynamicId: dynamicId,
),
), ),
), ),
), ),