任务发布-发布新任务-添加照片

pull/1/head
张萌 3 years ago
parent b5bcee3842
commit fc22339a6e

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 531 B

File diff suppressed because it is too large Load Diff

@ -7,6 +7,7 @@
import 'package:audio_session/audio_session_web.dart'; import 'package:audio_session/audio_session_web.dart';
import 'package:device_info_plus_web/device_info_plus_web.dart'; import 'package:device_info_plus_web/device_info_plus_web.dart';
import 'package:flutter_sound_web/flutter_sound_web.dart';
import 'package:image_picker_for_web/image_picker_for_web.dart'; import 'package:image_picker_for_web/image_picker_for_web.dart';
import 'package:just_audio_web/just_audio_web.dart'; import 'package:just_audio_web/just_audio_web.dart';
import 'package:package_info_plus_web/package_info_plus_web.dart'; import 'package:package_info_plus_web/package_info_plus_web.dart';
@ -18,6 +19,7 @@ import 'package:flutter_web_plugins/flutter_web_plugins.dart';
void registerPlugins(Registrar registrar) { void registerPlugins(Registrar registrar) {
AudioSessionWeb.registerWith(registrar); AudioSessionWeb.registerWith(registrar);
DeviceInfoPlusPlugin.registerWith(registrar); DeviceInfoPlusPlugin.registerWith(registrar);
FlutterSoundPlugin.registerWith(registrar);
ImagePickerPlugin.registerWith(registrar); ImagePickerPlugin.registerWith(registrar);
JustAudioPlugin.registerWith(registrar); JustAudioPlugin.registerWith(registrar);
PackageInfoPlugin.registerWith(registrar); PackageInfoPlugin.registerWith(registrar);

@ -218,7 +218,7 @@ class _HomePageState extends State<HomePage>
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
head, head,
HomeSwiper(), // // HomeSwiper(), //
// SizedBox(height: 100.w), // SizedBox(height: 100.w),
Container( Container(
padding: EdgeInsets.only(top: 24.w, bottom: 32.w), padding: EdgeInsets.only(top: 24.w, bottom: 32.w),

@ -39,6 +39,7 @@ class _HallViewState extends State<HallView> {
padding: EdgeInsets.symmetric(horizontal: 32.w, vertical: 24.w), padding: EdgeInsets.symmetric(horizontal: 32.w, vertical: 24.w),
itemBuilder: (context, index) { itemBuilder: (context, index) {
return HallCard( return HallCard(
key: ValueKey(models[index].id),
model: models[index], model: models[index],
refresh: () => _refreshController.callRefresh()); refresh: () => _refreshController.callRefresh());
}, },

@ -1,19 +1,23 @@
import 'package:flutter/cupertino.dart'; import 'dart:io';
import 'package:flutter/material.dart';
import 'package:bot_toast/bot_toast.dart';
import 'package:common_utils/common_utils.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:velocity_x/velocity_x.dart';
import 'package:aku_new_community/base/base_style.dart'; import 'package:aku_new_community/base/base_style.dart';
import 'package:aku_new_community/gen/assets.gen.dart';
import 'package:aku_new_community/ui/service/task_func.dart'; import 'package:aku_new_community/ui/service/task_func.dart';
import 'package:aku_new_community/ui/service/task_remark_page.dart';
import 'package:aku_new_community/utils/headers.dart'; import 'package:aku_new_community/utils/headers.dart';
import 'package:aku_new_community/widget/bee_divider.dart'; import 'package:aku_new_community/widget/bee_divider.dart';
import 'package:aku_new_community/widget/bee_scaffold.dart'; import 'package:aku_new_community/widget/bee_scaffold.dart';
import 'package:aku_new_community/widget/picker/bee_date_picker.dart'; import 'package:aku_new_community/widget/picker/bee_date_picker.dart';
import 'package:aku_new_community/widget/picker/bee_pick_image_widget.dart';
import 'package:aku_new_community/widget/picker/bee_picker_box.dart'; import 'package:aku_new_community/widget/picker/bee_picker_box.dart';
import 'package:aku_new_community/widget/voice_player.dart';
import 'package:bot_toast/bot_toast.dart';
import 'package:common_utils/common_utils.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:velocity_x/velocity_x.dart';
class PublishTaskPage extends StatefulWidget { class PublishTaskPage extends StatefulWidget {
const PublishTaskPage({Key? key}) : super(key: key); const PublishTaskPage({Key? key}) : super(key: key);
@ -33,14 +37,16 @@ class _PublishTaskPageState extends State<PublishTaskPage> {
int _rewardType = 0; int _rewardType = 0;
DateTime? _appointDate = DateTime.now(); DateTime? _appointDate = DateTime.now();
TextEditingController _titleController = TextEditingController(); TextEditingController _titleController = TextEditingController();
TextEditingController _contentController = TextEditingController();
TextEditingController _addressController = TextEditingController(); TextEditingController _addressController = TextEditingController();
TextEditingController _rewardController = TextEditingController(); TextEditingController _rewardController = TextEditingController();
TextEditingController _nameController = TextEditingController();
TextEditingController _telController = TextEditingController();
String? _content;
List<File> _photos = [];
@override @override
void dispose() { void dispose() {
_titleController.dispose(); _titleController.dispose();
_contentController.dispose();
_addressController.dispose(); _addressController.dispose();
_rewardController.dispose(); _rewardController.dispose();
super.dispose(); super.dispose();
@ -50,49 +56,72 @@ class _PublishTaskPageState extends State<PublishTaskPage> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BeeScaffold( return BeeScaffold(
title: '发布任务', title: '发布任务',
body: SafeArea( extendBody: true,
child: ListView( body: Stack(
padding: EdgeInsets.symmetric(horizontal: 32.w, vertical: 24.w),
children: [ children: [
Container( ClipPath(
clipper: _taskBackgroundClip(),
child: Container(
width: double.infinity, width: double.infinity,
padding: EdgeInsets.only(left: 32.w, right: 32.w, bottom: 32.w), height: 400.w,
decoration: BoxDecoration( color: kPrimaryColor,
color: Colors.white, )),
borderRadius: BorderRadius.circular(16.w), SafeArea(
), child: ListView(
child: Column( padding: EdgeInsets.symmetric(horizontal: 32.w, vertical: 24.w),
children: [
Row(
children: [ children: [
SizedBox( _baseInfo(context),
width: 170.w, 32.w.heightBox,
child: '标题' _dateAndAddress(),
.text 24.w.heightBox,
.size(28.sp) _remarkWidget(),
.color(Colors.black.withOpacity(0.45)) 24.w.heightBox,
.make(), _photoAndVoice(),
), 24.w.heightBox,
Expanded( _rewardWidget(),
child: TextField( ],
controller: _titleController,
onChanged: (text) => setState(() {}),
autofocus: false,
decoration: InputDecoration(
hintStyle: TextStyle(
fontSize: 28.sp,
color: Colors.black.withOpacity(0.25),
),
border: InputBorder.none,
hintText: '请输入',
), ),
)
],
), ),
bottomNavi: Padding(
padding: EdgeInsets.symmetric(horizontal: 32.w, vertical: 32.w),
child: MaterialButton(
elevation: 0,
height: 93.w,
disabledColor: Colors.black.withOpacity(0.06),
disabledTextColor: Colors.black.withOpacity(0.25),
textColor: Colors.black.withOpacity(0.85),
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(65.w)),
color: kPrimaryColor,
onPressed: !canTap
? null
: () async {
var cancel = BotToast.showLoading();
var re = await TaskFunc.publish(
title: _titleController.text,
taskType: _type,
taskSex: _sex,
serviceObject: _service,
taskContent: _content ?? '',
taskDate: _appointDate.toString(),
taskAddress: _addressController.text,
rewardType: _rewardType,
reward: _rewardController.text);
if (re) {
Get.back();
}
cancel();
},
child: '确认发布'.text.size(32.sp).bold.make(),
), ),
],
), ),
BeeDivider.horizontal(), );
32.w.heightBox, }
GestureDetector(
Container _baseInfo(BuildContext context) {
var type = GestureDetector(
onTap: () async { onTap: () async {
_type = 1; _type = 1;
showModalBottomSheet( showModalBottomSheet(
@ -138,8 +167,7 @@ class _PublishTaskPageState extends State<PublishTaskPage> {
'${_type == 0 ? '请选择分类' : _types[_type - 1]}' '${_type == 0 ? '请选择分类' : _types[_type - 1]}'
.text .text
.size(28.sp) .size(28.sp)
.color(Colors.black .color(Colors.black.withOpacity(_type == 0 ? 0.25 : 0.85))
.withOpacity(_type == 0 ? 0.25 : 0.85))
.make(), .make(),
Spacer(), Spacer(),
Icon( Icon(
@ -149,11 +177,8 @@ class _PublishTaskPageState extends State<PublishTaskPage> {
], ],
), ),
), ),
), );
32.w.heightBox, var sex = GestureDetector(
BeeDivider.horizontal(),
32.w.heightBox,
GestureDetector(
onTap: () async { onTap: () async {
await Get.bottomSheet(CupertinoActionSheet( await Get.bottomSheet(CupertinoActionSheet(
cancelButton: CupertinoActionSheetAction( cancelButton: CupertinoActionSheetAction(
@ -221,8 +246,7 @@ class _PublishTaskPageState extends State<PublishTaskPage> {
'${_sex == 0 ? '请选择性别' : _sexStr[_sex - 1]}' '${_sex == 0 ? '请选择性别' : _sexStr[_sex - 1]}'
.text .text
.size(28.sp) .size(28.sp)
.color(Colors.black .color(Colors.black.withOpacity(_sex == 0 ? 0.25 : 0.85))
.withOpacity(_sex == 0 ? 0.25 : 0.85))
.make(), .make(),
Spacer(), Spacer(),
Icon( Icon(
@ -232,11 +256,8 @@ class _PublishTaskPageState extends State<PublishTaskPage> {
], ],
), ),
), ),
), );
32.w.heightBox, var servicePersonnel = GestureDetector(
BeeDivider.horizontal(),
32.w.heightBox,
GestureDetector(
onTap: () async { onTap: () async {
await Get.bottomSheet(CupertinoActionSheet( await Get.bottomSheet(CupertinoActionSheet(
cancelButton: CupertinoActionSheetAction( cancelButton: CupertinoActionSheetAction(
@ -304,8 +325,7 @@ class _PublishTaskPageState extends State<PublishTaskPage> {
'${_service == 0 ? '请选择服务人员' : _serviceObject[_service - 1]}' '${_service == 0 ? '请选择服务人员' : _serviceObject[_service - 1]}'
.text .text
.size(28.sp) .size(28.sp)
.color(Colors.black .color(Colors.black.withOpacity(_service == 0 ? 0.25 : 0.85))
.withOpacity(_service == 0 ? 0.25 : 0.85))
.make(), .make(),
Spacer(), Spacer(),
Icon( Icon(
@ -315,57 +335,35 @@ class _PublishTaskPageState extends State<PublishTaskPage> {
], ],
), ),
), ),
), );
32.w.heightBox, return Container(
BeeDivider.horizontal(),
32.w.heightBox,
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
'任务内容'
.text
.size(28.sp)
.color(Colors.black.withOpacity(0.45))
.make(),
],
),
32.w.heightBox,
Container(
width: double.infinity,
padding: EdgeInsets.symmetric(horizontal: 24.w),
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.06),
borderRadius: BorderRadius.circular(16.w)),
child: TextField(
controller: _contentController,
autofocus: false,
onChanged: (text) => setState(() {}),
minLines: 5,
maxLength: 200,
maxLines: 20,
decoration: InputDecoration(
border: InputBorder.none,
),
),
),
],
),
),
32.w.heightBox,
Container(
width: double.infinity, width: double.infinity,
padding: EdgeInsets.only( padding: EdgeInsets.only(left: 32.w, right: 32.w, bottom: 32.w),
left: 32.w, right: 32.w, bottom: 32.w, top: 32.w),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(16.w), borderRadius: BorderRadius.circular(16.w),
), ),
child: Column( child: Column(
children: [ children: [
GestureDetector( 32.w.heightBox,
type,
32.w.heightBox,
BeeDivider.horizontal(),
32.w.heightBox,
sex,
32.w.heightBox,
BeeDivider.horizontal(),
32.w.heightBox,
servicePersonnel,
],
),
);
}
Container _dateAndAddress() {
var date = GestureDetector(
onTap: () async { onTap: () async {
_appointDate = _appointDate = await BeeDatePicker.timePicker(DateTime.now());
await BeeDatePicker.timePicker(DateTime.now());
}, },
child: Material( child: Material(
color: Colors.transparent, color: Colors.transparent,
@ -373,7 +371,7 @@ class _PublishTaskPageState extends State<PublishTaskPage> {
children: [ children: [
SizedBox( SizedBox(
width: 170.w, width: 170.w,
child: '预约时间' child: '预计时间'
.text .text
.size(28.sp) .size(28.sp)
.color(Colors.black.withOpacity(0.45)) .color(Colors.black.withOpacity(0.45))
@ -382,8 +380,7 @@ class _PublishTaskPageState extends State<PublishTaskPage> {
'${DateUtil.formatDate(_appointDate)}' '${DateUtil.formatDate(_appointDate)}'
.text .text
.size(28.sp) .size(28.sp)
.color(Colors.black .color(Colors.black.withOpacity(_type == 0 ? 0.25 : 0.85))
.withOpacity(_type == 0 ? 0.25 : 0.85))
.make(), .make(),
Spacer(), Spacer(),
Icon( Icon(
@ -393,40 +390,59 @@ class _PublishTaskPageState extends State<PublishTaskPage> {
], ],
), ),
), ),
), );
32.w.heightBox, var contact = Row(
BeeDivider.horizontal(),
32.w.heightBox,
Row(
children: [ children: [
SizedBox( SizedBox(
width: 170.w, width: 170.w,
child: '预约地址' child: '联系人'
.text .text
.size(28.sp) .size(28.sp)
.color(Colors.black.withOpacity(0.45)) .color(Colors.black.withOpacity(0.45))
.make(), .make(),
), ),
'${S.of(context)!.tempPlotName}' Expanded(
.text child: TextField(
.size(28.sp) textAlign: TextAlign.start,
.color(Colors.black.withOpacity(0.85)) onChanged: (text) => setState(() {}),
.make(), autofocus: false,
'' controller: _nameController,
style: TextStyle(color: Colors.red),
decoration: InputDecoration(
contentPadding: EdgeInsets.zero,
isDense: true,
border: InputBorder.none,
hintText: '请输入姓名',
hintStyle: TextStyle(
fontSize: 28.sp,
color: Colors.black.withOpacity(0.25),
)),
),
),
],
);
var tel = Row(
children: [
SizedBox(
width: 170.w,
child: '联系电话'
.text .text
.size(28.sp) .size(28.sp)
.color(Colors.black.withOpacity(0.25)) .color(Colors.black.withOpacity(0.45))
.make(), .make(),
),
Expanded( Expanded(
child: TextField( child: TextField(
autofocus: false, textAlign: TextAlign.start,
controller: _addressController,
onChanged: (text) => setState(() {}), onChanged: (text) => setState(() {}),
autofocus: false,
controller: _telController,
style: TextStyle(color: Colors.red),
decoration: InputDecoration( decoration: InputDecoration(
contentPadding: EdgeInsets.zero, contentPadding: EdgeInsets.zero,
isDense: true, isDense: true,
border: InputBorder.none, border: InputBorder.none,
hintText: '请输入', hintText: '请输入电话',
hintStyle: TextStyle( hintStyle: TextStyle(
fontSize: 28.sp, fontSize: 28.sp,
color: Colors.black.withOpacity(0.25), color: Colors.black.withOpacity(0.25),
@ -434,11 +450,217 @@ class _PublishTaskPageState extends State<PublishTaskPage> {
), ),
), ),
], ],
);
return Container(
width: double.infinity,
padding:
EdgeInsets.only(left: 32.w, right: 32.w, bottom: 32.w, top: 32.w),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16.w),
), ),
child: Column(
children: [
date,
32.w.heightBox,
BeeDivider.horizontal(),
32.w.heightBox,
contact,
32.w.heightBox,
BeeDivider.horizontal(),
32.w.heightBox,
tel,
32.w.heightBox, 32.w.heightBox,
BeeDivider.horizontal(), BeeDivider.horizontal(),
32.w.heightBox, 32.w.heightBox,
GestureDetector( GestureDetector(
onTap: () {},
child: Material(
color: Colors.transparent,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
children: [
Container(
margin: EdgeInsets.only(left: 8.w),
width: 32.w,
height: 32.w,
alignment: Alignment.center,
decoration: BoxDecoration(
color: kPrimaryColor,
borderRadius: BorderRadius.circular(20.w)),
child: ''.text.size(20.w).black.bold.make(),
),
8.w.heightBox,
_connect(5),
8.w.heightBox,
],
),
20.w.widthBox,
SizedBox(
width: 430.w,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
'鲍汁牛肉饭'.text.size(32.sp).black.bold.make(),
12.w.heightBox,
'江西省萍乡市莲花县良坊镇 19 幢 252 室daidjwoajdiowajdoiwa'
.text
.maxLines(1)
.overflow(TextOverflow.ellipsis)
.size(24.sp)
.color(Colors.black.withOpacity(0.45))
.make(),
],
),
),
Spacer(),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
20.hb,
Icon(
CupertinoIcons.chevron_right,
size: 40.w,
color: Colors.black.withOpacity(0.45),
)
],
)
],
),
),
),
Row(
children: [
Padding(
padding: EdgeInsets.only(left: 2.w),
child: Assets.icons.connect.image(width: 40.w, height: 40.w),
),
20.wb,
BeeDivider.horizontal().expand(),
],
),
GestureDetector(
onTap: () {},
child: Material(
color: Colors.transparent,
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Column(
children: [
8.w.heightBox,
_connect(5),
8.w.heightBox,
Container(
margin: EdgeInsets.only(left: 8.w),
width: 32.w,
height: 32.w,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.circular(20.w)),
child: ''.text.size(20.w).white.bold.make(),
),
],
),
20.w.widthBox,
SizedBox(
width: 430.w,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
'鲍汁牛肉饭'
.text
.size(32.sp)
.black
.lineHeight(1.1)
.bold
.make(),
12.w.heightBox,
'江西省萍乡市莲花县良坊镇 19 幢 252 室daidjwoajdiowajdoiwa'
.text
.maxLines(1)
.overflow(TextOverflow.ellipsis)
.size(24.sp)
.color(Colors.black.withOpacity(0.45))
.make(),
],
),
),
Spacer(),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
20.hb,
Icon(
CupertinoIcons.chevron_right,
size: 40.w,
color: Colors.black.withOpacity(0.45),
)
],
)
],
),
),
)
],
),
);
}
Container _remarkWidget() {
return Container(
width: double.infinity,
padding:
EdgeInsets.only(left: 32.w, right: 32.w, bottom: 32.w, top: 32.w),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16.w),
),
child: Column(
children: [
GestureDetector(
onTap: () async {
_content = await Get.to(() => TaskRemarkPage());
},
child: Material(
color: Colors.transparent,
child: Row(
children: [
SizedBox(
width: 170.w,
child: '任务备注'
.text
.size(28.sp)
.color(Colors.black.withOpacity(0.45))
.make(),
),
'${_content == null ? '请输入任务备注' : _content}'
.text
.size(28.sp)
.color(Colors.black
.withOpacity(_rewardType == 0 ? 0.25 : 0.85))
.make(),
Spacer(),
Icon(
CupertinoIcons.chevron_right,
size: 24.w,
),
],
),
),
),
],
),
);
}
Container _rewardWidget() {
var type = GestureDetector(
onTap: () async { onTap: () async {
await Get.bottomSheet(CupertinoActionSheet( await Get.bottomSheet(CupertinoActionSheet(
cancelButton: CupertinoActionSheetAction( cancelButton: CupertinoActionSheetAction(
@ -494,8 +716,7 @@ class _PublishTaskPageState extends State<PublishTaskPage> {
'${_rewardType == 0 ? '请选择报酬类型' : _rewardTypes[_rewardType - 1]}' '${_rewardType == 0 ? '请选择报酬类型' : _rewardTypes[_rewardType - 1]}'
.text .text
.size(28.sp) .size(28.sp)
.color(Colors.black .color(Colors.black.withOpacity(_rewardType == 0 ? 0.25 : 0.85))
.withOpacity(_rewardType == 0 ? 0.25 : 0.85))
.make(), .make(),
Spacer(), Spacer(),
Icon( Icon(
@ -505,11 +726,8 @@ class _PublishTaskPageState extends State<PublishTaskPage> {
], ],
), ),
), ),
), );
32.w.heightBox, var count = Row(
BeeDivider.horizontal(),
32.w.heightBox,
Row(
children: [ children: [
SizedBox( SizedBox(
width: 170.w, width: 170.w,
@ -543,45 +761,91 @@ class _PublishTaskPageState extends State<PublishTaskPage> {
.color(Colors.black.withOpacity(0.85)) .color(Colors.black.withOpacity(0.85))
.make(), .make(),
], ],
) );
return Container(
width: double.infinity,
padding:
EdgeInsets.only(left: 32.w, right: 32.w, bottom: 32.w, top: 32.w),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16.w),
),
child: Column(
children: [
type,
32.w.heightBox,
BeeDivider.horizontal(),
32.w.heightBox,
count,
], ],
), ),
);
}
Container _photoAndVoice() {
return Container(
width: double.infinity,
padding:
EdgeInsets.only(left: 32.w, right: 32.w, bottom: 32.w, top: 32.w),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16.w),
), ),
child: Column(
children: [
Row(
children: [
'上传图片'
.text
.size(28.sp)
.color(Colors.black.withOpacity(0.45))
.make(),
Spacer(),
'建议上传图片不超过6张'
.text
.size(24.sp)
.color(Colors.black.withOpacity(0.25))
.make(),
], ],
), ),
), 24.w.heightBox,
bottomNavi: Padding( BeePickImageWidget(onChanged: (value) {
padding: EdgeInsets.symmetric(horizontal: 32.w, vertical: 32.w), _photos = value;
child: MaterialButton( }),
elevation: 0, 24.w.heightBox,
height: 93.w, BeeDivider.horizontal(),
disabledColor: Colors.black.withOpacity(0.06), 24.w.heightBox,
disabledTextColor: Colors.black.withOpacity(0.25), GestureDetector(
textColor: Colors.black.withOpacity(0.85), onTap: () async {
shape: await Get.bottomSheet(Container());
RoundedRectangleBorder(borderRadius: BorderRadius.circular(65.w)),
color: kPrimaryColor,
onPressed: !canTap
? null
: () async {
var cancel = BotToast.showLoading();
var re = await TaskFunc.publish(
title: _titleController.text,
taskType: _type,
taskSex: _sex,
serviceObject: _service,
taskContent: _contentController.text,
taskDate: _appointDate.toString(),
taskAddress: _addressController.text,
rewardType: _rewardType,
reward: _rewardController.text);
if (re) {
Get.back();
}
cancel();
}, },
child: '确认发布'.text.size(32.sp).bold.make(), child: Material(
color: Colors.transparent,
child: Row(
children: [
SizedBox(
width: 170.w,
child: '上传语音'
.text
.size(28.sp)
.color(Colors.black.withOpacity(0.45))
.make(),
),
VoicePlayer(
url: '5d143e1b735b0.mp3',
showXmark: true,
onDelete: () {},
),
Spacer(),
Icon(
CupertinoIcons.chevron_right,
size: 24.w,
),
],
),
),
), ),
],
), ),
); );
} }
@ -602,7 +866,7 @@ class _PublishTaskPageState extends State<PublishTaskPage> {
if (_appointDate == null) { if (_appointDate == null) {
return false; return false;
} }
if (_contentController.text.isEmpty) { if (_content == null) {
return false; return false;
} }
if (_addressController.text.isEmpty) { if (_addressController.text.isEmpty) {
@ -613,4 +877,38 @@ class _PublishTaskPageState extends State<PublishTaskPage> {
} }
return true; return true;
} }
_connect(int num) {
return Column(
children: List.generate(
num,
(index) => Container(
width: 4.w,
height: 4.w,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(2.w),
color: Colors.black.withOpacity(0.25)),
)).sepWidget(separate: 4.w.heightBox),
);
}
}
class _taskBackgroundClip extends CustomClipper<Path> {
@override
Path getClip(Size size) {
var offset = size.height - 25.0;
var path = Path();
path.moveTo(0, offset);
path.quadraticBezierTo(size.width / 2, size.height, size.width, offset);
path.lineTo(size.width, 0);
path.lineTo(0, 0);
path.lineTo(0, offset);
path.close();
return path;
}
@override
bool shouldReclip(covariant CustomClipper oldClipper) {
return false;
}
} }

@ -32,7 +32,7 @@ class TaskFunc {
static Future<bool> cancel({ static Future<bool> cancel({
required int taskId, required int taskId,
}) async { }) async {
var base = await NetUtil().get(API.manager.task.cancel, params: { var base = await NetUtil().get(SARSAPI.task.cancel, params: {
'taskId': taskId, 'taskId': taskId,
}); });
return base.success; return base.success;
@ -43,9 +43,11 @@ class TaskFunc {
static Future<bool> take({ static Future<bool> take({
required int taskId, required int taskId,
}) async { }) async {
var base = await NetUtil().get(API.manager.task.take, params: { var base = await NetUtil().get(SARSAPI.task.receive,
params: {
'taskId': taskId, 'taskId': taskId,
}); },
showMessage: true);
return base.success; return base.success;
} }
@ -54,9 +56,40 @@ class TaskFunc {
static Future<bool> finish({ static Future<bool> finish({
required int taskId, required int taskId,
}) async { }) async {
var base = await NetUtil().get(API.manager.task.finish, params: { var base = await NetUtil().get(SARSAPI.task.finish, params: {
'taskId': taskId,
});
return base.success;
}
///
static Future<bool> confirm({
required int taskId,
}) async {
var base = await NetUtil().get(SARSAPI.task.confirm, params: {
'taskId': taskId,
});
return base.success;
}
///
static Future<bool> start({
required int taskId,
}) async {
var base = await NetUtil().get(SARSAPI.task.startService, params: {
'taskId': taskId, 'taskId': taskId,
}); });
return base.success; return base.success;
} }
///
static Future<bool> evaluate({
required int taskId,
required int star,
required String evaluation,
}) async {
var base = await NetUtil().get(SARSAPI.task.evaluation,
params: {'taskId': taskId, 'star': star, 'evaluation': evaluation});
return base.success;
}
} }

@ -0,0 +1,82 @@
import 'package:aku_new_community/base/base_style.dart';
import 'package:aku_new_community/widget/bee_scaffold.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:velocity_x/src/extensions/num_ext.dart';
import 'package:velocity_x/src/extensions/string_ext.dart';
class TaskRemarkPage extends StatefulWidget {
const TaskRemarkPage({Key? key}) : super(key: key);
@override
_TaskRemarkPageState createState() => _TaskRemarkPageState();
}
class _TaskRemarkPageState extends State<TaskRemarkPage> {
TextEditingController _contentController = TextEditingController();
@override
void dispose() {
_contentController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return BeeScaffold(
title: '添加备注',
body: ListView(
padding: EdgeInsets.all(32.w),
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
'任务内容'
.text
.size(28.sp)
.color(Colors.black.withOpacity(0.45))
.make(),
],
),
32.w.heightBox,
Container(
width: double.infinity,
padding: EdgeInsets.symmetric(horizontal: 24.w),
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.06),
borderRadius: BorderRadius.circular(16.w)),
child: TextField(
controller: _contentController,
autofocus: false,
onChanged: (text) => setState(() {}),
minLines: 5,
maxLength: 200,
maxLines: 20,
decoration: InputDecoration(
border: InputBorder.none,
),
),
)
],
),
bottomNavi: Padding(
padding: EdgeInsets.symmetric(horizontal: 32.w, vertical: 32.w),
child: MaterialButton(
elevation: 0,
height: 93.w,
disabledColor: Colors.black.withOpacity(0.06),
disabledTextColor: Colors.black.withOpacity(0.25),
textColor: Colors.black.withOpacity(0.85),
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(65.w)),
color: kPrimaryColor,
onPressed: () async {
Get.back(result: _contentController.text);
},
child: '完成'.text.size(32.sp).bold.make(),
),
),
);
}
}

@ -0,0 +1,115 @@
// Dart imports:
import 'dart:io';
import 'package:aku_new_community/extensions/widget_list_ext.dart';
import 'package:aku_new_community/gen/assets.gen.dart';
import 'package:aku_new_community/widget/picker/bee_image_picker.dart';
// Package imports:
import 'package:dotted_border/dotted_border.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:velocity_x/velocity_x.dart';
class BeePickImageWidget extends StatefulWidget {
final double? size;
final Function(List<File> files) onChanged;
final String description;
BeePickImageWidget(
{Key? key, this.size, required this.onChanged, this.description = '上传照片'})
: super(key: key);
@override
_BeePickImageWidgetState createState() => _BeePickImageWidgetState();
}
class _BeePickImageWidgetState extends State<BeePickImageWidget> {
List<File> _files = [];
@override
Widget build(BuildContext context) {
return Row(
children: [
..._files.map((e) => showImage(e)).toList(),
GestureDetector(
onTap: () async {
await BeeImagePicker.pick(title: '选择图片').then(
(value) {
if (value != null) {
_files.add(
File(value.path),
);
}
},
);
widget.onChanged(_files);
setState(() {});
},
child: DottedBorder(
color: Colors.black.withOpacity(0.25),
borderType: BorderType.RRect,
strokeWidth: 2.w,
dashPattern: [6, 3],
radius: Radius.circular(8.w),
child: Container(
width: widget.size ?? 160.w,
height: widget.size ?? 160.w,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Image.asset(
Assets.icons.camera.path,
width: 60.w,
height: 60.w,
color: Color(0xFF999999),
),
4.w.heightBox,
widget.description.text
.color(Colors.black.withOpacity(0.45))
.size(22.sp)
.make(),
],
),
),
).material(color: Colors.transparent),
)
].sepWidget(separate: 10.w.widthBox),
);
}
Widget showImage(File file) {
return Stack(children: [
Container(
width: widget.size ?? 160.w,
height: widget.size ?? 160.w,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8.w),
color: Colors.black.withOpacity(0.03)),
child: Image.file(file),
),
Positioned(
top: 8.w,
right: 8.w,
child: Container(
width: 40.w,
height: 40.w,
child: Icon(
CupertinoIcons.xmark,
size: 20.w,
color: Colors.white,
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20.w),
color: Color(0xFF000000),
),
).onTap(() {
_files.remove(file);
widget.onChanged(_files);
setState(() {});
}),
)
]);
}
}

@ -3,14 +3,19 @@ import 'dart:math';
import 'package:aku_new_community/constants/sars_api.dart'; import 'package:aku_new_community/constants/sars_api.dart';
import 'package:aku_new_community/extensions/num_ext.dart'; import 'package:aku_new_community/extensions/num_ext.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:just_audio/just_audio.dart'; import 'package:just_audio/just_audio.dart';
class VoicePlayer extends StatefulWidget { class VoicePlayer extends StatefulWidget {
final String url; final String url;
final VoidCallback? onDelete;
final bool showXmark;
const VoicePlayer({Key? key, required this.url}) : super(key: key); const VoicePlayer(
{Key? key, required this.url, this.onDelete, this.showXmark = false})
: super(key: key);
@override @override
_VoicePlayerState createState() => _VoicePlayerState(); _VoicePlayerState createState() => _VoicePlayerState();
@ -26,12 +31,13 @@ class _VoicePlayerState extends State<VoicePlayer>
bool inAnimate = false; bool inAnimate = false;
final player = AudioPlayer(); final player = AudioPlayer();
Timer? _timer; Timer? _timer;
int _voiceLength = 0; Duration? _voiceLength;
int _currentLength = 0;
void stopPlay() { void stopPlay() {
inAnimate = false; inAnimate = false;
controller.stop(); controller.stop();
player.stop(); player.pause();
_timer?.cancel(); _timer?.cancel();
_timer = null; _timer = null;
if (mounted) { if (mounted) {
@ -39,23 +45,43 @@ class _VoicePlayerState extends State<VoicePlayer>
} }
} }
void startPlay() { void startPlay() async {
inAnimate = true; inAnimate = true;
controller.forward(); controller.forward();
player.play(); player.play();
_timer = Timer.periodic(Duration(seconds: 1), (timer) async { _timer = Timer.periodic(Duration(seconds: 1), (timer) async {
_voiceLength--; _currentLength--;
if (_voiceLength <= 0) { if (_currentLength <= 0) {
_voiceLength = (player.duration?.inSeconds) ?? 0; resetPlay();
} else {
if (mounted) {
setState(() {});
}
}
});
}
Future initVoice() async {
await player.setUrl(SARSAPI.image(widget.url));
_voiceLength = await player.load();
_currentLength = _voiceLength?.inSeconds ?? 0;
await player.setClip(start: Duration(seconds: 0), end: _voiceLength);
if (mounted) {
setState(() {});
}
}
Future resetPlay() async {
_timer?.cancel(); _timer?.cancel();
_timer = null; _timer = null;
controller.stop(); controller.stop();
inAnimate = false; inAnimate = false;
} player.stop();
_currentLength = _voiceLength?.inSeconds ?? 0;
await player.setClip(start: Duration(seconds: 0), end: _voiceLength);
if (mounted) { if (mounted) {
setState(() {}); setState(() {});
} }
});
} }
@override @override
@ -80,17 +106,16 @@ class _VoicePlayerState extends State<VoicePlayer>
controller.forward(); controller.forward();
} }
}); });
Future.delayed(Duration(milliseconds: 0), () async { initVoice();
await player.setUrl(SARSAPI.image(widget.url));
var length = await player.load();
_voiceLength = length?.inSeconds ?? 0;
if (mounted) {
setState(() {});
}
});
super.initState(); super.initState();
} }
@override
void didUpdateWidget(covariant VoicePlayer oldWidget) {
resetPlay();
super.didUpdateWidget(oldWidget);
}
@override @override
void dispose() { void dispose() {
stopPlay(); stopPlay();
@ -113,7 +138,11 @@ class _VoicePlayerState extends State<VoicePlayer>
}, },
child: Material( child: Material(
color: Colors.transparent, color: Colors.transparent,
child: Container( child: Stack(
fit: StackFit.passthrough,
clipBehavior: Clip.none,
children: [
Container(
width: width, width: width,
// height: height, // height: height,
padding: EdgeInsets.symmetric(vertical: 14.w, horizontal: 20.w), padding: EdgeInsets.symmetric(vertical: 14.w, horizontal: 20.w),
@ -123,13 +152,27 @@ class _VoicePlayerState extends State<VoicePlayer>
child: Row( child: Row(
children: [ children: [
CustomPaint( CustomPaint(
painter: VoicePlayerPainter(inAnimate ? animation.value : 3), painter:
VoicePlayerPainter(inAnimate ? animation.value : 3),
), ),
40.wb, 40.wb,
Text('${_voiceLength}\"'), Text('${_currentLength}\"'),
], ],
), ),
), ),
if (widget.showXmark)
Positioned(
top: -10.w,
right: -10.w,
child: GestureDetector(
onTap: widget.onDelete,
child: Icon(
CupertinoIcons.xmark_circle_fill,
size: 30.w,
),
))
],
),
), ),
); );
} }

@ -512,6 +512,27 @@ packages:
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "0.6.0" version: "0.6.0"
flutter_sound:
dependency: "direct main"
description:
name: flutter_sound
url: "https://pub.flutter-io.cn"
source: hosted
version: "9.1.3"
flutter_sound_platform_interface:
dependency: transitive
description:
name: flutter_sound_platform_interface
url: "https://pub.flutter-io.cn"
source: hosted
version: "9.1.3"
flutter_sound_web:
dependency: transitive
description:
name: flutter_sound_web
url: "https://pub.flutter-io.cn"
source: hosted
version: "9.1.3"
flutter_test: flutter_test:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter
@ -990,7 +1011,7 @@ packages:
name: provider name: provider
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "5.0.0" version: "6.0.2"
pub_semver: pub_semver:
dependency: "direct dev" dependency: "direct dev"
description: description:
@ -1042,6 +1063,13 @@ packages:
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.1.0" version: "2.1.0"
recase:
dependency: transitive
description:
name: recase
url: "https://pub.flutter-io.cn"
source: hosted
version: "4.0.0"
rxdart: rxdart:
dependency: transitive dependency: transitive
description: description:

@ -18,7 +18,7 @@ dependencies:
#包信息 #包信息
package_info: ^2.0.0 package_info: ^2.0.0
#状态管理 #状态管理
provider: ^5.0.0 provider: ^6.0.0
#屏幕适配 #屏幕适配
flutter_screenutil: ^5.0.0+2 flutter_screenutil: ^5.0.0+2
#图标集合 #图标集合
@ -117,6 +117,8 @@ dependencies:
palette_generator: ^0.3.2 palette_generator: ^0.3.2
#音频播放 #音频播放
just_audio: ^0.9.20 just_audio: ^0.9.20
#录音
flutter_sound: ^9.1.3
dev_dependencies: dev_dependencies:

Loading…
Cancel
Save