mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
split report dialog (#460)
This commit is contained in:
committed by
GitHub
parent
0b8e95477c
commit
7854c5e6b9
@@ -1,15 +1,24 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
Widget radioWidget<T>({
|
||||
required T value,
|
||||
T? groupValue,
|
||||
required ValueChanged onChanged,
|
||||
required String title,
|
||||
EdgeInsetsGeometry? padding,
|
||||
}) {
|
||||
Widget child() => Row(
|
||||
class RadioWidget<T> extends StatelessWidget {
|
||||
final T value;
|
||||
final T? groupValue;
|
||||
final ValueChanged<T?> onChanged;
|
||||
final String title;
|
||||
final EdgeInsetsGeometry? padding;
|
||||
|
||||
const RadioWidget({
|
||||
super.key,
|
||||
required this.value,
|
||||
this.groupValue,
|
||||
required this.onChanged,
|
||||
required this.title,
|
||||
this.padding,
|
||||
});
|
||||
|
||||
Widget _child() => Row(
|
||||
children: [
|
||||
Radio(
|
||||
Radio<T>(
|
||||
value: value,
|
||||
groupValue: groupValue,
|
||||
onChanged: onChanged,
|
||||
@@ -18,13 +27,67 @@ Widget radioWidget<T>({
|
||||
Text(title),
|
||||
],
|
||||
);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return InkWell(
|
||||
onTap: () => onChanged(value),
|
||||
child: padding != null
|
||||
? Padding(
|
||||
padding: padding,
|
||||
child: child(),
|
||||
padding: padding!,
|
||||
child: _child(),
|
||||
)
|
||||
: child(),
|
||||
: _child(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class WrapRadioOptionsGroup<T> extends StatelessWidget {
|
||||
final String groupTitle;
|
||||
final Map<T, String> options;
|
||||
final T? selectedValue;
|
||||
final ValueChanged<T?> onChanged;
|
||||
final EdgeInsetsGeometry? itemPadding;
|
||||
|
||||
const WrapRadioOptionsGroup({
|
||||
super.key,
|
||||
required this.groupTitle,
|
||||
required this.options,
|
||||
required this.selectedValue,
|
||||
required this.onChanged,
|
||||
this.itemPadding,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (groupTitle.isNotEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 22),
|
||||
child: Text(
|
||||
groupTitle,
|
||||
style: TextStyle(color: Theme.of(context).colorScheme.outline),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
child: Wrap(
|
||||
children: options.entries.map((entry) {
|
||||
return IntrinsicWidth(
|
||||
child: RadioWidget<T>(
|
||||
value: entry.key,
|
||||
groupValue: selectedValue,
|
||||
onChanged: onChanged,
|
||||
title: entry.value,
|
||||
padding: itemPadding ?? const EdgeInsets.only(right: 10),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'package:PiliPlus/common/widgets/radio_widget.dart';
|
||||
import 'package:PiliPlus/utils/extension.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
@@ -16,149 +15,56 @@ void autoWrapReportDialog(
|
||||
late final key = GlobalKey<FormState>();
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
builder: (context) => StatefulBuilder(
|
||||
builder: (context, setState) {
|
||||
return AlertDialog(
|
||||
title: const Text('举报'),
|
||||
titlePadding: const EdgeInsets.only(left: 22, top: 16, right: 22),
|
||||
contentPadding: const EdgeInsets.symmetric(vertical: 5),
|
||||
actionsPadding: const EdgeInsets.only(left: 16, right: 16, bottom: 10),
|
||||
content: Builder(
|
||||
builder: (context) {
|
||||
return Column(
|
||||
actionsPadding:
|
||||
const EdgeInsets.only(left: 16, right: 16, bottom: 10),
|
||||
content: Form(
|
||||
key: key,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Flexible(
|
||||
child: Material(
|
||||
child: SingleChildScrollView(
|
||||
child: AnimatedSize(
|
||||
duration: const Duration(milliseconds: 200),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(
|
||||
left: 22,
|
||||
right: 22,
|
||||
bottom: 5,
|
||||
),
|
||||
child: const Text('请选择举报的理由:'),
|
||||
child: Text('请选择举报的理由:'),
|
||||
),
|
||||
...options.entries.map<Widget>((title) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (title.key.isNotEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 22),
|
||||
child: Text(
|
||||
title.key,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.outline),
|
||||
...options.entries.map(
|
||||
(entry) => WrapRadioOptionsGroup<int>(
|
||||
groupTitle: entry.key,
|
||||
options: entry.value,
|
||||
selectedValue: reasonType,
|
||||
onChanged: (value) =>
|
||||
setState(() => reasonType = value),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12),
|
||||
child: Wrap(
|
||||
children: title.value.entries.map((opt) {
|
||||
return IntrinsicWidth(
|
||||
child: radioWidget<int>(
|
||||
value: opt.key,
|
||||
groupValue: reasonType,
|
||||
title: opt.value,
|
||||
padding: const EdgeInsets.only(
|
||||
right: 10),
|
||||
onChanged: (value) {
|
||||
reasonType = value;
|
||||
if (context.mounted) {
|
||||
(context as Element?)
|
||||
?.markNeedsBuild();
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
if (reasonType == 0)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 22,
|
||||
top: 5,
|
||||
right: 22,
|
||||
),
|
||||
child: Form(
|
||||
key: key,
|
||||
child: TextFormField(
|
||||
autofocus: true,
|
||||
minLines: 4,
|
||||
maxLines: 4,
|
||||
initialValue: reasonDesc,
|
||||
inputFormatters: [
|
||||
LengthLimitingTextInputFormatter(60),
|
||||
],
|
||||
decoration: const InputDecoration(
|
||||
labelText:
|
||||
'为帮助审核人员更快处理,请补充问题类型和出现位置等详细信息',
|
||||
border: OutlineInputBorder(),
|
||||
contentPadding: EdgeInsets.all(10),
|
||||
),
|
||||
onChanged: (value) => reasonDesc = value,
|
||||
validator: (value) {
|
||||
if (value.isNullOrEmpty) {
|
||||
return '理由不能为空';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
ReasonField(
|
||||
onChanged: (value) => reasonDesc = value),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
banUid = !banUid;
|
||||
(context as Element?)?.markNeedsBuild();
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 18, top: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
size: 22,
|
||||
banUid
|
||||
? Icons.check_box_outlined
|
||||
: Icons.check_box_outline_blank,
|
||||
color: banUid
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
Text(
|
||||
' 拉黑该用户',
|
||||
style: TextStyle(
|
||||
color: banUid
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: null,
|
||||
),
|
||||
),
|
||||
BanUserCheckbox(onChanged: (value) => banUid = value),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: Get.back,
|
||||
@@ -193,9 +99,97 @@ void autoWrapReportDialog(
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
class ReasonField extends StatefulWidget {
|
||||
final ValueChanged<String> onChanged;
|
||||
String? _validator(String? value) => value.isNullOrEmpty ? '理由不能为空' : null;
|
||||
|
||||
const ReasonField({super.key, required this.onChanged});
|
||||
|
||||
@override
|
||||
State<ReasonField> createState() => _ReasonFieldState();
|
||||
}
|
||||
|
||||
class _ReasonFieldState extends State<ReasonField> {
|
||||
final _controller = TextEditingController();
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(left: 22, top: 5, right: 22),
|
||||
child: TextFormField(
|
||||
controller: _controller,
|
||||
autofocus: true,
|
||||
minLines: 4,
|
||||
maxLines: 4,
|
||||
decoration: const InputDecoration(
|
||||
labelText: '为帮助审核人员更快处理,请补充问题类型和出现位置等详细信息',
|
||||
border: OutlineInputBorder(),
|
||||
contentPadding: EdgeInsets.all(10),
|
||||
),
|
||||
onChanged: (value) {
|
||||
widget.onChanged(value);
|
||||
},
|
||||
validator: widget._validator,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class BanUserCheckbox extends StatefulWidget {
|
||||
final ValueChanged<bool> onChanged;
|
||||
|
||||
const BanUserCheckbox({super.key, required this.onChanged});
|
||||
|
||||
@override
|
||||
State<BanUserCheckbox> createState() => _BanUserCheckboxState();
|
||||
}
|
||||
|
||||
class _BanUserCheckboxState extends State<BanUserCheckbox> {
|
||||
bool _banUid = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
setState(() => _banUid = !_banUid);
|
||||
widget.onChanged(_banUid);
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 18, top: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
size: 22,
|
||||
_banUid
|
||||
? Icons.check_box_outlined
|
||||
: Icons.check_box_outline_blank,
|
||||
color: _banUid
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
Text(
|
||||
' 拉黑该用户',
|
||||
style: TextStyle(
|
||||
color: _banUid ? Theme.of(context).colorScheme.primary : null,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ReportOptions {
|
||||
// from https://s1.hdslb.com/bfs/seed/jinkela/comment-h5/static/js/605.chunks.js
|
||||
static Map<String, Map<int, String>> get commentReport => {
|
||||
|
||||
@@ -582,7 +582,7 @@ class _ReportPanelState extends State<ReportPanel> {
|
||||
const Text('举报理由(单选,非必选)'),
|
||||
...List.generate(
|
||||
5,
|
||||
(index) => radioWidget<int>(
|
||||
(index) => RadioWidget<int>(
|
||||
value: index,
|
||||
groupValue: _reasonV2,
|
||||
onChanged: (value) {
|
||||
|
||||
@@ -407,7 +407,7 @@ class Utils {
|
||||
child: Builder(
|
||||
builder: (context) => Column(
|
||||
children: List.generate(list.length, (index) {
|
||||
return radioWidget(
|
||||
return RadioWidget(
|
||||
padding: const EdgeInsets.only(left: 14),
|
||||
title: list[index].title ?? '',
|
||||
groupValue: checkedId,
|
||||
|
||||
Reference in New Issue
Block a user