工单管理 分配人模块

master
张萌 3 years ago
parent b88492a199
commit ddc0dd448f

Binary file not shown.

After

Width:  |  Height:  |  Size: 794 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 531 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 769 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 841 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 836 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 754 B

@ -24,6 +24,7 @@ class SAASAPI {
static _Inspection inspection = _Inspection();
static _User user = _User();
static _Message message = _Message();
static _WorkOrder workOrder = _WorkOrder();
///
static _OtherApi other = _OtherApi();
@ -122,3 +123,51 @@ class _Message {
///app
String get messageList => '/butlerApp/user/message/list';
}
class _WorkOrder {
///
String get reminderPay => '/butlerApp/user/workOrder/reminderPay';
///
String get startService => '/butlerApp/user/workOrder/startService';
///
String get finish => '/butlerApp/user/workOrder/finish';
///
String get report => '/butlerApp/user/workOrder/report';
///
String get receiveTask => '/butlerApp/user/workOrder/receiveTask';
///
String get reminderConfirm => '/butlerApp/user/workOrder/reminderConfirm';
///
String get reminderDone => '/butlerApp/user/workOrder/reminderDone';
///
String get reminderProcessing => '/butlerApp/user/workOrder/reminderDone';
///
String get moveToAssignment => '/butlerApp/user/workOrder/moveToAssignment';
///
String get joinTicketPool => '/butlerApp/user/workOrder/joinTicketPool';
///
String get cancel => '/butlerApp/user/workOrder/cancel';
///
String get findServiceTeamList =>
'/butlerApp/user/workOrder/findServiceTeamList';
///id
String get findById => '/butlerApp/user/workOrder/findById';
///app
String get insert => '/butlerApp/user/workOrder/insert';
///app
String get list => '/butlerApp/user/workOrder/list';
}

@ -146,6 +146,86 @@ class $AssetsHomeGen {
AssetGenImage get sos => const AssetGenImage('assets/home/sos.png');
}
class $AssetsIconsGen {
const $AssetsIconsGen();
/// File path: assets/icons/alarm_clock.png
AssetGenImage get alarmClock =>
const AssetGenImage('assets/icons/alarm_clock.png');
/// File path: assets/icons/camera.png
AssetGenImage get camera => const AssetGenImage('assets/icons/camera.png');
/// File path: assets/icons/cancel_task.png
AssetGenImage get cancelTask =>
const AssetGenImage('assets/icons/cancel_task.png');
/// File path: assets/icons/clock_circle.png
AssetGenImage get clockCircle =>
const AssetGenImage('assets/icons/clock_circle.png');
/// File path: assets/icons/connect.png
AssetGenImage get connect => const AssetGenImage('assets/icons/connect.png');
/// File path: assets/icons/copy.png
AssetGenImage get copy => const AssetGenImage('assets/icons/copy.png');
/// File path: assets/icons/dissatisfied.png
AssetGenImage get dissatisfied =>
const AssetGenImage('assets/icons/dissatisfied.png');
/// File path: assets/icons/edit.png
AssetGenImage get edit => const AssetGenImage('assets/icons/edit.png');
/// File path: assets/icons/environment.png
AssetGenImage get environment =>
const AssetGenImage('assets/icons/environment.png');
/// File path: assets/icons/examining.png
AssetGenImage get examining =>
const AssetGenImage('assets/icons/examining.png');
/// File path: assets/icons/finish_order.png
AssetGenImage get finishOrder =>
const AssetGenImage('assets/icons/finish_order.png');
/// File path: assets/icons/normal.png
AssetGenImage get normal => const AssetGenImage('assets/icons/normal.png');
/// File path: assets/icons/pass.png
AssetGenImage get pass => const AssetGenImage('assets/icons/pass.png');
/// File path: assets/icons/phone.png
AssetGenImage get phone => const AssetGenImage('assets/icons/phone.png');
/// File path: assets/icons/phone_circle.png
AssetGenImage get phoneCircle =>
const AssetGenImage('assets/icons/phone_circle.png');
/// File path: assets/icons/record.png
AssetGenImage get record => const AssetGenImage('assets/icons/record.png');
/// File path: assets/icons/reject.png
AssetGenImage get reject => const AssetGenImage('assets/icons/reject.png');
/// File path: assets/icons/reward.png
AssetGenImage get reward => const AssetGenImage('assets/icons/reward.png');
/// File path: assets/icons/satisfied.png
AssetGenImage get satisfied =>
const AssetGenImage('assets/icons/satisfied.png');
/// File path: assets/icons/tag.png
AssetGenImage get tag => const AssetGenImage('assets/icons/tag.png');
/// File path: assets/icons/task_location.png
AssetGenImage get taskLocation =>
const AssetGenImage('assets/icons/task_location.png');
/// File path: assets/icons/watch.png
AssetGenImage get watch => const AssetGenImage('assets/icons/watch.png');
}
class $AssetsInspectionGen {
const $AssetsInspectionGen();
@ -456,6 +536,7 @@ class Assets {
Assets._();
static const $AssetsHomeGen home = $AssetsHomeGen();
static const $AssetsIconsGen icons = $AssetsIconsGen();
static const $AssetsInspectionGen inspection = $AssetsInspectionGen();
static const $AssetsManageGen manage = $AssetsManageGen();
static const $AssetsMessageGen message = $AssetsMessageGen();

@ -0,0 +1,35 @@
import 'package:aku_new_community_manager/ui/widgets/common/bee_long_button.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:velocity_x/velocity_x.dart';
class UrgeDialog extends StatelessWidget {
final VoidCallback onConfirm;
final String title;
final String content;
const UrgeDialog({
Key? key,
required this.onConfirm,
required this.title,
required this.content,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
padding: EdgeInsets.symmetric(horizontal: 32.w),
child: Column(
children: [
120.w.heightBox,
title.text.size(36.sp).black.bold.isIntrinsic.make(),
40.w.heightBox,
content.text.size(28.sp).isIntrinsic.make(),
150.w.heightBox,
BeeLongButton(onPressed: onConfirm, text: '确认提醒')
],
),
);
}
}

@ -0,0 +1,248 @@
import 'package:aku_new_community_manager/gen/assets.gen.dart';
import 'package:aku_new_community_manager/new_ui/work_order/distributor/distributor_detail_page.dart';
import 'package:aku_new_community_manager/saas_models/work_order/work_order_list_model.dart';
import 'package:aku_new_community_manager/style/app_style.dart';
import 'package:aku_new_community_manager/ui/widgets/common/bee_hor_image_view.dart';
import 'package:aku_new_community_manager/ui/widgets/common/car_bottom_button.dart';
import 'package:aku_new_community_manager/utils/bee_date_util.dart';
import 'package:common_utils/common_utils.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:velocity_x/src/extensions/string_ext.dart';
import 'package:velocity_x/velocity_x.dart';
import '../work_order_func.dart';
import '../work_order_map.dart';
class DistributorCard extends StatelessWidget {
final WorkOrderListModel model;
final VoidCallback refresh;
const DistributorCard({Key? key, required this.model, required this.refresh})
: super(key: key);
@override
Widget build(BuildContext context) {
return Stack(
children: [
Positioned(
top: 9.35.w,
right: 0,
child: Container(
width: 160.w,
height: 60.w,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.bottomLeft,
end: Alignment.topRight,
colors: [
Color(0xFFFAC058),
Color(0xFFFFD589),
]),
color: kPrimaryColor,
borderRadius:
BorderRadius.only(topRight: Radius.circular(12.w)),
),
alignment: Alignment.center,
child: Text(
'${WorkOrderMap.orderStatus[model.status]}',
style: TextStyle(
fontSize: 26.sp,
color: Colors.black,
),
),
)),
GestureDetector(
onTap: () {
Get.to(() => DistributorDetailPage(
id: model.id,
));
},
child: ClipPath(
clipper: WorkOrderCardClip(),
child: Container(
padding: EdgeInsets.all(24.w),
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(12.w),
bottomLeft: Radius.circular(12.w),
bottomRight: Radius.circular(12.w)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Container(
padding: EdgeInsets.symmetric(
vertical: 8.w, horizontal: 16.w),
decoration: BoxDecoration(
color: Color(0xFFFFFBE6),
borderRadius: BorderRadius.circular(8.w),
),
child: '${model.workOrderTypeName}'
.text
.size(24.sp)
.color(Color(0xFFD48806))
.make(),
),
],
),
16.w.heightBox,
Row(
children: [
Assets.icons.alarmClock.image(width: 40.w, height: 40.w),
24.w.widthBox,
'${model.updateDate}'
.text
.size(24.sp)
.color(Colors.black.withOpacity(0.45))
.make(),
],
),
16.w.heightBox,
Row(
children: [
Assets.icons.taskLocation
.image(width: 40.w, height: 40.w),
24.w.widthBox,
'${model.reserveAddress}'
.text
.size(24.sp)
.color(Colors.black.withOpacity(0.45))
.make(),
],
),
60.w.heightBox,
'${model.content}'
.text
.size(28.sp)
.color(Colors.black.withOpacity(0.65))
.make(),
24.w.heightBox,
BeeHorImageView(
maxCount: 4,
imgs: model.imgList ?? [],
imgWidth: 146.w,
imgHeight: 146.w),
24.w.heightBox,
Row(
children: [
BeeDateUtil(DateUtil.getDateTime(model.createDate))
.timeAgo
.text
.size(24.sp)
.color(Colors.black.withOpacity(0.45))
.make(),
Spacer(),
],
),
],
),
),
),
)
],
);
}
Widget getCardBottomButton() {
switch (model.status) {
case 1:
return SizedBox.shrink();
case 2:
return SizedBox.shrink();
case 3:
return CardBottomButton.yellow(
text: '提醒处理',
onPressed: () async {
var re = await WorkOrderFuc.reminderProcessing(model.id);
if (re) {
refresh();
}
});
case 4:
return CardBottomButton.yellow(
text: '提醒完成',
onPressed: () async {
var re = await WorkOrderFuc.reminderDone(model.id);
if (re) {
refresh();
}
});
case 5:
return CardBottomButton.yellow(
text: '提醒确认',
onPressed: () async {
var re = await WorkOrderFuc.reminderConfirm(model.id);
if (re) {
refresh();
}
});
case 6:
return CardBottomButton.yellow(
text: '提醒支付',
onPressed: () async {
var re = await WorkOrderFuc.reminderPay(model.id);
if (re) {
refresh();
}
});
case 7:
return CardBottomButton.yellow(text: '去评价', onPressed: () {});
case 8:
return CardBottomButton.yellow(text: '查看评价', onPressed: () {});
case 9:
case 10:
default:
return SizedBox.shrink();
}
}
}
class WorkOrderCardClip extends CustomClipper<Path> {
@override
bool shouldReclip(covariant CustomClipper oldClipper) {
return false;
}
@override
Path getClip(Size size) {
Path path = Path();
//
double asx = 531.w;
//
double aex = 542.46.w;
//
double aey = 9.34.w;
//
double acx = 540.w;
//
double bsx = 558.45.w;
//
double bsy = 58.88.w;
//
double bex = 569.91.w;
//
double bey = 67.35.w;
//
double bcx = 561.06.w;
//
double bcy = 67.35.w;
path.lineTo(asx, 0);
path.quadraticBezierTo(acx, 0, aex, aey);
path.lineTo(bsx, bsy);
path.quadraticBezierTo(bcx, bcy, bex, bey);
path.lineTo(size.width, bey);
path.lineTo(size.width, size.height);
path.lineTo(0, size.height);
path.lineTo(0, 0);
path.close();
return path;
}
}

@ -0,0 +1,529 @@
import 'package:aku_new_community_manager/const/saas_api.dart';
import 'package:aku_new_community_manager/gen/assets.gen.dart';
import 'package:aku_new_community_manager/saas_models/work_order/work_order_detail_model.dart';
import 'package:aku_new_community_manager/ui/widgets/app_widgets/bee_grid_image_view.dart';
import 'package:aku_new_community_manager/ui/widgets/app_widgets/bee_image_network.dart';
import 'package:aku_new_community_manager/ui/widgets/common/aku_scaffold.dart';
import 'package:aku_new_community_manager/ui/widgets/common/bee_divider.dart';
import 'package:aku_new_community_manager/ui/widgets/common/bee_long_button.dart';
import 'package:aku_new_community_manager/ui/widgets/common/stack_avatar.dart';
import 'package:aku_new_community_manager/utils/network/net_util.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/services.dart';
import 'package:flutter_easyrefresh/easy_refresh.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:velocity_x/src/extensions/num_ext.dart';
import 'package:velocity_x/src/extensions/string_ext.dart';
import '../team_list_page.dart';
import '../work_order_func.dart';
import '../work_order_map.dart';
class DistributorDetailPage extends StatefulWidget {
final int id;
const DistributorDetailPage({
Key? key,
required this.id,
}) : super(key: key);
@override
_DistributorDetailPageState createState() => _DistributorDetailPageState();
}
class _DistributorDetailPageState extends State<DistributorDetailPage> {
WorkOrderDetailModel? _model;
EasyRefreshController _refreshController = EasyRefreshController();
@override
void dispose() {
_refreshController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return AkuScaffold(
title: '',
extendBody: true,
body: Stack(
children: [
_model == null
? Container()
: Container(
width: double.infinity,
height: 380.w,
decoration: BoxDecoration(
gradient: _getLiner,
),
child: Column(
children: [
150.w.heightBox,
Row(
children: [
Padding(
padding: EdgeInsets.symmetric(horizontal: 32.w),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
GestureDetector(
onTap: () async {},
child: Material(
color: Colors.transparent,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
'${WorkOrderMap.orderStatus[_model?.status] ?? ''}'
.text
.size(40.sp)
.color(Colors.black)
.bold
.make(),
16.w.widthBox,
Icon(
CupertinoIcons.chevron_right,
size: 32.w,
color: Colors.black.withOpacity(0.65),
)
],
),
),
),
'${WorkOrderMap.subStatusString[_model?.status] ?? ''}'
.text
.size(24.sp)
.color(Colors.black.withOpacity(0.45))
.make(),
],
),
),
Spacer(),
],
),
],
),
),
SafeArea(
child: EasyRefresh(
firstRefresh: true,
header: MaterialHeader(),
onRefresh: () async {
var base = await NetUtil().get(SAASAPI.workOrder.findById,
params: {'workOrderId': widget.id});
if (base.success) {
_model = WorkOrderDetailModel.fromJson(base.data);
setState(() {});
}
},
child: _model == null
? Container()
: ListView(
padding:
EdgeInsets.only(top: 120.w, left: 32.w, right: 32.w),
children: [
Offstage(
offstage: _model!.servicePersonnelImgList == null ||
_model!.servicePersonnelImgList!.isEmpty,
child: Column(
children: [
_servicePeople(),
24.w.heightBox,
],
)),
_head(),
24.w.heightBox,
_content(),
24.w.heightBox,
_taskInfo(),
],
),
)),
],
),
bottom: Padding(
padding: EdgeInsets.only(
left: 32.w,
right: 32.w,
bottom: MediaQuery.of(context).padding.bottom + 32.w),
child: _getBottomButton()),
);
}
LinearGradient get _getLiner {
switch (_model?.status) {
case 7:
case 8:
return LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [
Color(0xFFA5A5A6).withOpacity(0),
Color(0xFFE0DDDE),
]);
case 9:
return LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [
Color(0xFFFF0000).withOpacity(0),
Color(0xFFFC5757),
]);
default:
return LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [
Color(0xFFFFD589).withOpacity(0),
Color(0xFFFAC058),
]);
}
}
Widget _getBottomButton() {
switch (_model?.status) {
case 1:
return BeeLongButton(
onPressed: () async {
var re = await WorkOrderFuc.joinOrderPool(widget.id);
if (re) {
_refreshController.callRefresh();
}
},
text: '加入工单池');
case 2:
return BeeLongButton(
onPressed: () async {
var re = await WorkOrderFuc.moveToAssignment(widget.id);
if (re) {
_refreshController.callRefresh();
}
},
text: '移至待分配');
case 3:
return BeeLongButton(
onPressed: () async {
var re = await WorkOrderFuc.reminderProcessing(widget.id);
if (re) {
_refreshController.callRefresh();
}
},
text: '提醒处理');
case 4:
return BeeLongButton(
onPressed: () async {
var re = await WorkOrderFuc.reminderConfirm(widget.id);
if (re) {
_refreshController.callRefresh();
}
},
text: '提醒用户确认');
case 5:
return BeeLongButton(
onPressed: () async {
var re = await WorkOrderFuc.reminderPay(widget.id);
if (re) {
_refreshController.callRefresh();
}
},
text: '提醒支付');
case 6:
case 7:
case 8:
return SizedBox.shrink();
case 9:
return SizedBox.shrink();
default:
return SizedBox.shrink();
}
}
Widget _historyReport() {
return GestureDetector(
onTap: () {},
child: Material(
color: Colors.transparent,
child: Container(
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white, borderRadius: BorderRadius.circular(16.w)),
padding: EdgeInsets.symmetric(horizontal: 32.w, vertical: 32.w),
child: Row(
children: [
'历史报告'
.text
.size(28.sp)
.color(Colors.black.withOpacity(0.85))
.make(),
Spacer(),
'点击查看'
.text
.size(24.sp)
.color(Colors.black.withOpacity(0.45))
.make(),
24.w.widthBox,
Icon(
CupertinoIcons.chevron_right,
size: 24.w,
color: Colors.black.withOpacity(0.45),
),
],
),
),
),
);
}
Widget _servicePeople() {
return Container(
padding: EdgeInsets.all(24.w),
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12.w),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
'服务人员名单'
.text
.size(28.sp)
.color(Colors.black.withOpacity(0.85))
.make(),
24.w.heightBox,
BeeDivider.horizontal(),
24.w.heightBox,
GestureDetector(
onTap: () {
Get.to(() => TeamListPage(
workOderId: _model!.id,
));
},
child: Material(
color: Colors.transparent,
child: Row(
children: [
StackAvatar(
avatars: (_model!.servicePersonnelImgList ?? [])
.map((e) => e.url)
.toList()),
Spacer(),
'点击查看'
.text
.size(28.sp)
.color(Colors.black.withOpacity(0.65))
.make(),
Icon(
CupertinoIcons.chevron_right,
size: 24.w,
)
],
),
),
)
],
),
);
}
Widget _head() {
return Container(
padding: EdgeInsets.all(24.w),
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12.w),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Container(
padding: EdgeInsets.symmetric(vertical: 8.w, horizontal: 16.w),
decoration: BoxDecoration(
color: Color(0xFFFFFBE6),
borderRadius: BorderRadius.circular(8.w),
),
child: '${_model!.workOrderTypeName}'
.text
.size(24.sp)
.color(Color(0xFFD48806))
.make(),
),
],
),
16.w.heightBox,
Row(
children: [
Assets.icons.alarmClock.image(width: 40.w, height: 40.w),
24.w.widthBox,
'${DateUtil.formatDateStr(_model!.reserveDate)}'
.text
.size(24.sp)
.color(Colors.black.withOpacity(0.45))
.make(),
],
),
16.w.heightBox,
Row(
children: [
Assets.icons.taskLocation.image(width: 40.w, height: 40.w),
24.w.widthBox,
'${_model!.reserveAddress}'
.text
.size(24.sp)
.color(Colors.black.withOpacity(0.45))
.make(),
],
),
24.w.heightBox,
Container(
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 24.w),
child: Column(
children: [
'申请人'
.text
.size(28.sp)
.color(Colors.black.withOpacity(0.25))
.make(),
24.w.heightBox,
Row(
children: [
ClipOval(
child: BeeImageNetwork(
width: 108.w,
height: 108.w,
imgs: _model!.applicantImgList,
),
),
16.w.widthBox,
Expanded(
child: Column(
children: [
_model!.applicantName.text
.size(28.sp)
.color(Colors.black.withOpacity(0.85))
.make(),
8.w.heightBox,
'${_model!.identity == 1 ? '住户' : '物业'}${_model!.buildingName}${_model!.unitName}${_model!.estateName}'
.text
.size(28.sp)
.color(Colors.black.withOpacity(0.45))
.make(),
GestureDetector(
onTap: () {
launch('tel:${_model!.applicantTel}');
},
child: Assets.icons.phoneCircle
.image(width: 40.w, height: 40.w)),
],
)),
],
)
],
),
),
24.w.heightBox,
],
),
);
}
Widget _content() {
return Container(
padding: EdgeInsets.all(24.w),
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12.w),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
'${_model!.content}'
.text
.size(28.sp)
.color(Colors.black.withOpacity(0.65))
.make(),
24.w.heightBox,
BeeGridImageView(
urls: (_model!.imgList ?? []).map((e) => e.url).toList(),
),
24.w.heightBox,
],
),
);
}
Widget _taskInfo() {
return Container(
width: 686.w,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8.w),
),
padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 24.w),
child: Column(
children: [
Row(
children: [
'任务信息'.text.size(28.sp).color(Colors.black).bold.make(),
Spacer(),
],
),
24.w.heightBox,
BeeDivider.horizontal(),
24.w.heightBox,
Row(
children: [
'创建时间'
.text
.size(24.sp)
.color(Colors.black.withOpacity(0.45))
.make(),
Spacer(),
'${DateUtil.formatDateStr(_model!.createDate)}'
.text
.size(24.sp)
.color(Colors.black.withOpacity(0.45))
.make(),
64.w.widthBox,
],
),
24.w.heightBox,
Row(
children: [
'工单编号'
.text
.size(24.sp)
.color(Colors.black.withOpacity(0.45))
.make(),
Spacer(),
'${_model!.code}'
.text
.size(24.sp)
.color(Colors.black.withOpacity(0.45))
.make(),
24.w.widthBox,
GestureDetector(
onTap: () async {
await Clipboard.setData(ClipboardData(text: _model!.code));
BotToast.showText(text: '已复制到粘贴板');
},
child: Assets.icons.copy.image(width: 40.w, height: 40.w)),
],
)
],
),
);
}
}

@ -0,0 +1,112 @@
import 'package:aku_new_community_manager/const/saas_api.dart';
import 'package:aku_new_community_manager/new_ui/work_order/distributor/distributor_card.dart';
import 'package:aku_new_community_manager/saas_models/work_order/work_order_list_model.dart';
import 'package:aku_new_community_manager/ui/widgets/common/aku_scaffold.dart';
import 'package:aku_new_community_manager/ui/widgets/inner/aku_tab_bar.dart';
import 'package:aku_new_community_manager/utils/network/net_util.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyrefresh/easy_refresh.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:velocity_x/velocity_x.dart';
class WorkOrderDistributorPage extends StatefulWidget {
const WorkOrderDistributorPage({Key? key}) : super(key: key);
@override
_WorkOrderDistributorPageState createState() =>
_WorkOrderDistributorPageState();
}
class _WorkOrderDistributorPageState extends State<WorkOrderDistributorPage>
with SingleTickerProviderStateMixin {
List<String> _tabs = ['全部', '待分配', '工单池', '已接单', '处理中', '待确认', '已完成', ''];
late TabController _tabController;
EasyRefreshController _refreshController = EasyRefreshController();
int _page = 1;
int _size = 10;
List<WorkOrderListModel> _models = [];
@override
void initState() {
_tabController = TabController(length: _tabs.length, vsync: this);
super.initState();
}
@override
void dispose() {
_refreshController.dispose();
_tabController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return AkuScaffold(
title: '工单管理',
actions: [
IconButton(
onPressed: () {},
icon: Icon(
CupertinoIcons.plus_circle,
size: 40.w,
))
],
appBarBottom: PreferredSize(
preferredSize: Size.fromHeight(88.w),
child: AkuTabBar(
tabs: _tabs,
controller: _tabController,
),
),
body: TabBarView(
controller: _tabController,
children:
_tabs.mapIndexed((e, index) => _getOrderView(index)).toList()),
);
}
Widget _getOrderView(int index) {
return EasyRefresh(
firstRefresh: true,
header: MaterialHeader(),
onRefresh: () async {
_page = 1;
var base = await NetUtil().getList(SAASAPI.workOrder.list, params: {
'pageNum': _page,
'size': _size,
'status': index == 0 ? null : index,
});
_models =
base.rows.map((e) => WorkOrderListModel.fromJson(e)).toList();
setState(() {});
},
onLoad: () async {
_page++;
var base = await NetUtil().getList(SAASAPI.workOrder.list, params: {
'pageNum': _page,
'size': _size,
'status': index == 0 ? null : index,
});
if (_models.length < base.total) {
_models.addAll(
base.rows.map((e) => WorkOrderListModel.fromJson(e)).toList());
setState(() {});
} else {
_refreshController.finishLoad();
}
},
child: ListView.separated(
padding: EdgeInsets.all(24.w),
itemBuilder: (context, index) {
return DistributorCard(
model: _models[index],
refresh: _refreshController.callRefresh,
);
},
separatorBuilder: (context, index) {
return 24.w.heightBox;
},
itemCount: _models.length));
}
}

@ -0,0 +1,111 @@
import 'package:aku_new_community_manager/const/saas_api.dart';
import 'package:aku_new_community_manager/gen/assets.gen.dart';
import 'package:aku_new_community_manager/saas_models/work_order/team_list_model.dart';
import 'package:aku_new_community_manager/ui/widgets/common/aku_scaffold.dart';
import 'package:aku_new_community_manager/utils/network/net_util.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyrefresh/easy_refresh.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:velocity_x/velocity_x.dart';
class TeamListPage extends StatefulWidget {
final int workOderId;
const TeamListPage({Key? key, required this.workOderId}) : super(key: key);
@override
_TeamListPageState createState() => _TeamListPageState();
}
class _TeamListPageState extends State<TeamListPage> {
List<TeamListModel> _models = [];
TeamListModel? get _mainModel {
for (var item in _models) {
if (item.userType == 1) {
return item;
} else {
return null;
}
}
}
@override
Widget build(BuildContext context) {
return AkuScaffold(
title: '服务团队名单',
body: EasyRefresh(
onRefresh: () async {
var base = await NetUtil()
.get(SAASAPI.workOrder.findServiceTeamList, params: {
'workOrderId': widget.workOderId,
});
if (base.success) {
_models = (base.data as List)
.map((e) => TeamListModel.fromJson(e))
.toList();
setState(() {});
}
},
child: ListView(
children: [
_positionTile('主负责人'),
if (_mainModel != null) _personTile(_mainModel!),
_positionTile('协同人'),
..._models.map((e) => _personTile(e)).toList()
],
),
),
);
}
Widget _personTile(TeamListModel model) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 32.w, vertical: 16.w),
width: double.infinity,
child: Row(
children: [
CircleAvatar(
backgroundColor: Colors.red,
),
16.w.heightBox,
Column(
children: [
model.manageUserName.text
.size(28.sp)
.color(Colors.black.withOpacity(0.85))
.make(),
8.w.heightBox,
model.departmentName.text
.size(24.sp)
.color(Colors.black.withOpacity(0.45))
.make(),
],
),
Spacer(),
GestureDetector(
onTap: () async {
await launch('tel:${model.manageUserTel}');
},
child: Assets.icons.phone.image(width: 40.w, height: 40.w),
)
],
),
);
}
Widget _positionTile(String text) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 32.w, vertical: 16.w),
width: double.infinity,
child: Text(
text,
style: TextStyle(
fontSize: 26.sp,
color: Colors.black.withOpacity(0.45),
),
),
);
}
}

@ -0,0 +1,108 @@
import 'package:aku_new_community_manager/const/saas_api.dart';
import 'package:aku_new_community_manager/saas_models/net_model/base_model.dart';
import 'package:aku_new_community_manager/saas_models/work_order/work_order_submit_model.dart';
import 'package:aku_new_community_manager/utils/network/net_util.dart';
class WorkOrderFuc {
///
static Future<bool> reminderConfirm(int id) async {
BaseModel baseModel = await NetUtil().get(SAASAPI.workOrder.reminderConfirm,
params: {'workOrderId': id}, showMessage: true);
return baseModel.success;
}
///
static Future<bool> reminderDone(int id) async {
BaseModel baseModel = await NetUtil().get(SAASAPI.workOrder.reminderDone,
params: {'workOrderId': id}, showMessage: true);
return baseModel.success;
}
///
static Future<bool> reminderProcessing(int id) async {
BaseModel baseModel = await NetUtil().get(
SAASAPI.workOrder.reminderProcessing,
params: {'workOrderId': id},
showMessage: true);
return baseModel.success;
}
///
static Future<bool> reminderPay(int id) async {
BaseModel baseModel = await NetUtil().get(SAASAPI.workOrder.reminderPay,
params: {'workOrderId': id}, showMessage: true);
return baseModel.success;
}
///
static Future<bool> startService(int id) async {
BaseModel baseModel = await NetUtil().get(SAASAPI.workOrder.startService,
params: {'workOrderId': id}, showMessage: true);
return baseModel.success;
}
///
static Future<bool> joinOrderPool(int id) async {
BaseModel baseModel = await NetUtil().get(SAASAPI.workOrder.joinTicketPool,
params: {'workOrderId': id}, showMessage: true);
return baseModel.success;
}
///
static Future<bool> moveToAssignment(int id) async {
BaseModel baseModel = await NetUtil().get(
SAASAPI.workOrder.moveToAssignment,
params: {'workOrderId': id},
showMessage: true);
return baseModel.success;
}
///
static Future<bool> receiveTask(int id) async {
BaseModel baseModel = await NetUtil().get(SAASAPI.workOrder.receiveTask,
params: {'workOrderId': id}, showMessage: true);
return baseModel.success;
}
///
static Future<bool> confirmComplete(WorkOrderSubmitModel model) async {
BaseModel baseModel = await NetUtil().get(SAASAPI.workOrder.finish,
params: model.toJson(), showMessage: true);
return baseModel.success;
}
///
static Future<bool> cancel({
required int workOrderId,
}) async {
var base = await NetUtil().get(SAASAPI.workOrder.cancel,
params: {
'workOrderId': workOrderId,
},
showMessage: true);
return base.success;
}
///
static Future<bool> publish({
required int estateId,
required int workOrderTypeId,
required String reserveDate,
required String reserveAddress,
required String content,
required List<String> imgUrls,
}) async {
var base = await NetUtil().post(SAASAPI.workOrder.insert,
params: {
'estateId': estateId,
'workOrderTypeId': workOrderTypeId,
'reserveDate': reserveDate,
'reserveAddress': reserveAddress,
'content': content,
'imgUrls': imgUrls,
},
showMessage: true);
return base.success;
}
}

@ -0,0 +1,25 @@
class WorkOrderMap {
static Map<int, String> orderStatus = {
1: '待分配',
2: '工单池',
3: '已接单',
4: '处理中',
5: '待确认',
6: '待支付',
7: '已完成',
8: '已评价',
9: '已取消',
};
static Map<int, String> subStatusString = {
1: '请及时前往现场与业主进行确认、检查',
2: '请及时前往现场与业主进行确认、检查',
3: '请及时前往现场与业主进行确认、检查',
4: '进行过程中,记得提交报告哦',
5: '如果申请人长时间未确认,请让物业尝试联系对方',
6: '如果申请人长时间未支付,请让物业尝试联系对方',
7: '用户已支付工单费用',
8: '用户已对您的表现进行评价',
9: '任务已拒绝,中止工单进行'
};
}

@ -24,6 +24,9 @@ class UserInfoModel extends Equatable {
final String entryDate;
final String? remake;
final List<ImgModel>? imgList;
final String communityName;
final String positionName;
final int? workOrderJurisdiction;
String get sexValue {
if (sex == 1) return '';
@ -63,6 +66,9 @@ class UserInfoModel extends Equatable {
entryDate,
remake,
imgList,
communityName,
positionName,
workOrderJurisdiction
];
const UserInfoModel({
@ -83,5 +89,8 @@ class UserInfoModel extends Equatable {
required this.entryDate,
this.remake,
this.imgList,
required this.communityName,
required this.positionName,
this.workOrderJurisdiction,
});
}

@ -27,4 +27,7 @@ UserInfoModel _$UserInfoModelFromJson(Map<String, dynamic> json) =>
imgList: (json['imgList'] as List<dynamic>?)
?.map((e) => ImgModel.fromJson(e as Map<String, dynamic>))
.toList(),
communityName: json['communityName'] as String,
positionName: json['positionName'] as String,
workOrderJurisdiction: json['workOrderJurisdiction'] as int?,
);

@ -0,0 +1,45 @@
import 'package:equatable/equatable.dart';
import 'package:json_annotation/json_annotation.dart';
part 'team_list_model.g.dart';
@JsonSerializable()
class TeamListModel extends Equatable {
final int id;
final int userType;
final int manageUserId;
final String manageUserName;
final String manageUserTel;
final int departmentId;
final String departmentName;
final int positionId;
final String positionName;
factory TeamListModel.fromJson(Map<String, dynamic> json) =>
_$TeamListModelFromJson(json);
const TeamListModel({
required this.id,
required this.userType,
required this.manageUserId,
required this.manageUserName,
required this.manageUserTel,
required this.departmentId,
required this.departmentName,
required this.positionId,
required this.positionName,
});
@override
List<Object?> get props => [
id,
userType,
manageUserId,
manageUserName,
manageUserTel,
departmentId,
departmentName,
positionId,
positionName,
];
}

@ -0,0 +1,20 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'team_list_model.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
TeamListModel _$TeamListModelFromJson(Map<String, dynamic> json) =>
TeamListModel(
id: json['id'] as int,
userType: json['userType'] as int,
manageUserId: json['manageUserId'] as int,
manageUserName: json['manageUserName'] as String,
manageUserTel: json['manageUserTel'] as String,
departmentId: json['departmentId'] as int,
departmentName: json['departmentName'] as String,
positionId: json['positionId'] as int,
positionName: json['positionName'] as String,
);

@ -0,0 +1,87 @@
import 'package:aku_new_community_manager/models/common/img_model.dart';
import 'package:equatable/equatable.dart';
import 'package:json_annotation/json_annotation.dart';
part 'work_order_detail_model.g.dart';
@JsonSerializable()
class WorkOrderDetailModel extends Equatable {
final int id;
final String code;
final int status;
final String workOrderTypeName;
final String reserveAddress;
final String reserveDate;
final int identity;
final int applicantId;
final String applicantName;
final String applicantTel;
final List<ImgModel>? applicantImgList;
final String buildingName;
final String unitName;
final String estateName;
final String content;
final String createDate;
final List<ImgModel>? imgList;
final List<ImgModel>? servicePersonnelImgList;
final int newReportNum;
final int? evaluateLevel;
final String? evaluateContent;
final String? evaluateDate;
final double totalCost;
factory WorkOrderDetailModel.fromJson(Map<String, dynamic> json) =>
_$WorkOrderDetailModelFromJson(json);
@override
List<Object?> get props => [
code,
status,
workOrderTypeName,
reserveAddress,
reserveDate,
identity,
applicantId,
applicantName,
applicantTel,
buildingName,
unitName,
estateName,
content,
createDate,
imgList,
servicePersonnelImgList,
newReportNum,
evaluateLevel,
evaluateContent,
evaluateDate,
totalCost,
applicantImgList,
];
const WorkOrderDetailModel({
required this.id,
required this.code,
required this.status,
required this.workOrderTypeName,
required this.reserveAddress,
required this.reserveDate,
required this.identity,
required this.applicantId,
required this.applicantName,
required this.applicantTel,
this.applicantImgList,
required this.buildingName,
required this.unitName,
required this.estateName,
required this.content,
required this.createDate,
this.imgList,
this.servicePersonnelImgList,
required this.newReportNum,
this.evaluateLevel,
this.evaluateContent,
this.evaluateDate,
required this.totalCost,
});
}

@ -0,0 +1,42 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'work_order_detail_model.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
WorkOrderDetailModel _$WorkOrderDetailModelFromJson(
Map<String, dynamic> json) =>
WorkOrderDetailModel(
id: json['id'] as int,
code: json['code'] as String,
status: json['status'] as int,
workOrderTypeName: json['workOrderTypeName'] as String,
reserveAddress: json['reserveAddress'] as String,
reserveDate: json['reserveDate'] as String,
identity: json['identity'] as int,
applicantId: json['applicantId'] as int,
applicantName: json['applicantName'] as String,
applicantTel: json['applicantTel'] as String,
applicantImgList: (json['applicantImgList'] as List<dynamic>?)
?.map((e) => ImgModel.fromJson(e as Map<String, dynamic>))
.toList(),
buildingName: json['buildingName'] as String,
unitName: json['unitName'] as String,
estateName: json['estateName'] as String,
content: json['content'] as String,
createDate: json['createDate'] as String,
imgList: (json['imgList'] as List<dynamic>?)
?.map((e) => ImgModel.fromJson(e as Map<String, dynamic>))
.toList(),
servicePersonnelImgList:
(json['servicePersonnelImgList'] as List<dynamic>?)
?.map((e) => ImgModel.fromJson(e as Map<String, dynamic>))
.toList(),
newReportNum: json['newReportNum'] as int,
evaluateLevel: json['evaluateLevel'] as int?,
evaluateContent: json['evaluateContent'] as String?,
evaluateDate: json['evaluateDate'] as String?,
totalCost: (json['totalCost'] as num).toDouble(),
);

@ -0,0 +1,54 @@
import 'package:aku_new_community_manager/models/common/img_model.dart';
import 'package:common_utils/common_utils.dart';
import 'package:equatable/equatable.dart';
import 'package:json_annotation/json_annotation.dart';
part 'work_order_list_model.g.dart';
@JsonSerializable()
class WorkOrderListModel extends Equatable {
final int id;
final String code;
final int status;
final String workOrderTypeName;
final String reserveAddress;
final String reserveDate;
final String content;
final String updateDate;
final String createDate;
final List<ImgModel>? imgList;
factory WorkOrderListModel.fromJson(Map<String, dynamic> json) =>
_$WorkOrderListModelFromJson(json);
DateTime? get updateDateDT => DateUtil.getDateTime(updateDate);
DateTime? get createDateDT => DateUtil.getDateTime(createDate);
@override
List<Object?> get props => [
id,
code,
status,
workOrderTypeName,
reserveAddress,
reserveDate,
content,
updateDate,
createDate,
imgList
];
const WorkOrderListModel({
required this.id,
required this.code,
required this.status,
required this.workOrderTypeName,
required this.reserveAddress,
required this.reserveDate,
required this.content,
required this.updateDate,
required this.createDate,
this.imgList,
});
}

@ -0,0 +1,23 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'work_order_list_model.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
WorkOrderListModel _$WorkOrderListModelFromJson(Map<String, dynamic> json) =>
WorkOrderListModel(
id: json['id'] as int,
code: json['code'] as String,
status: json['status'] as int,
workOrderTypeName: json['workOrderTypeName'] as String,
reserveAddress: json['reserveAddress'] as String,
reserveDate: json['reserveDate'] as String,
content: json['content'] as String,
updateDate: json['updateDate'] as String,
createDate: json['createDate'] as String,
imgList: (json['imgList'] as List<dynamic>?)
?.map((e) => ImgModel.fromJson(e as Map<String, dynamic>))
.toList(),
);

@ -0,0 +1,51 @@
import 'package:equatable/equatable.dart';
import 'package:json_annotation/json_annotation.dart';
part 'work_order_submit_model.g.dart';
@JsonSerializable(createToJson: true)
class WorkOrderSubmitModel extends Equatable {
final int workOrderId;
final String content;
final List<String> imgUrls;
final WorkOrderFinishCostDTOList workOrderFinishCostDTOList;
factory WorkOrderSubmitModel.fromJson(Map<String, dynamic> json) =>
_$WorkOrderSubmitModelFromJson(json);
Map<String, dynamic> toJson() => _$WorkOrderSubmitModelToJson(this);
WorkOrderSubmitModel({
required this.workOrderId,
required this.content,
required this.imgUrls,
required this.workOrderFinishCostDTOList,
});
@override
List<Object?> get props =>
[workOrderId, content, imgUrls, workOrderFinishCostDTOList];
}
@JsonSerializable(createToJson: true)
class WorkOrderFinishCostDTOList extends Equatable {
final int costType;
final String name;
final int num;
final double price;
factory WorkOrderFinishCostDTOList.fromJson(Map<String, dynamic> json) =>
_$WorkOrderFinishCostDTOListFromJson(json);
Map<String, dynamic> toJson() => _$WorkOrderFinishCostDTOListToJson(this);
WorkOrderFinishCostDTOList({
required this.costType,
required this.name,
required this.num,
required this.price,
});
@override
List<Object?> get props => [costType, num, name, price];
}

@ -0,0 +1,45 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'work_order_submit_model.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
WorkOrderSubmitModel _$WorkOrderSubmitModelFromJson(
Map<String, dynamic> json) =>
WorkOrderSubmitModel(
workOrderId: json['workOrderId'] as int,
content: json['content'] as String,
imgUrls:
(json['imgUrls'] as List<dynamic>).map((e) => e as String).toList(),
workOrderFinishCostDTOList: WorkOrderFinishCostDTOList.fromJson(
json['workOrderFinishCostDTOList'] as Map<String, dynamic>),
);
Map<String, dynamic> _$WorkOrderSubmitModelToJson(
WorkOrderSubmitModel instance) =>
<String, dynamic>{
'workOrderId': instance.workOrderId,
'content': instance.content,
'imgUrls': instance.imgUrls,
'workOrderFinishCostDTOList': instance.workOrderFinishCostDTOList,
};
WorkOrderFinishCostDTOList _$WorkOrderFinishCostDTOListFromJson(
Map<String, dynamic> json) =>
WorkOrderFinishCostDTOList(
costType: json['costType'] as int,
name: json['name'] as String,
num: json['num'] as int,
price: (json['price'] as num).toDouble(),
);
Map<String, dynamic> _$WorkOrderFinishCostDTOListToJson(
WorkOrderFinishCostDTOList instance) =>
<String, dynamic>{
'costType': instance.costType,
'name': instance.name,
'num': instance.num,
'price': instance.price,
};

@ -1,16 +1,18 @@
import 'package:aku_new_community_manager/const/api.dart';
import 'package:aku_new_community_manager/const/resource.dart';
import 'package:aku_new_community_manager/const/saas_api.dart';
import 'package:aku_new_community_manager/gen/assets.gen.dart';
import 'package:aku_new_community_manager/ui/widgets/inner/bee_image_preview.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class BeeGridImageView extends StatelessWidget {
final List<String> urls;
final List<String?> urls;
final EdgeInsetsGeometry padding;
final int? crossCount;
const BeeGridImageView({
Key? key,
required this.urls,
this.padding = EdgeInsets.zero,
this.crossCount = 3,
}) : super(key: key);
@override
@ -19,7 +21,7 @@ class BeeGridImageView extends StatelessWidget {
return GridView.builder(
padding: padding,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisCount: crossCount!,
crossAxisSpacing: 16.w,
mainAxisSpacing: 16.w,
),
@ -29,19 +31,15 @@ class BeeGridImageView extends StatelessWidget {
BeeImagePreview.toPath(path: urls[index], tag: urls[index]);
},
child: Hero(
tag: urls[index],
tag: urls[index]!,
child: ClipRRect(
borderRadius: BorderRadius.circular(8.w),
child: FadeInImage.assetNetwork(
height: 184.w,
width: 184.w,
placeholder: R.ASSETS_PLACEHOLDER_WEBP,
image: API.image(urls[index]),
placeholder: Assets.placeholder.path,
image: SAASAPI.image(urls[index]),
fit: BoxFit.cover,
imageErrorBuilder: (context, error, stackTrace) {
return Image.asset(R.ASSETS_PLACEHOLDER_WEBP,height: 184.w,
width: 184.w,);
},
),
),
),

@ -1,9 +1,9 @@
// Flutter imports:
import 'package:flutter/material.dart';
// Project imports:
import 'package:aku_new_community_manager/tools/screen_tool.dart';
import 'package:aku_new_community_manager/ui/widgets/common/aku_back_button.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
///Scaffold
@ -50,7 +50,10 @@ class AkuScaffold extends StatefulWidget {
final List<Widget> actions;
final bool extendBody;
final PreferredSizeWidget? appBarBottom;
AkuScaffold({
Key? key,
this.appBar,
@ -64,6 +67,7 @@ class AkuScaffold extends StatefulWidget {
this.appBarColor = Colors.white,
this.appBarBottom,
this.actions = const [],
this.extendBody = false,
}) : super(key: key);
@override
@ -75,11 +79,14 @@ class _AkuScaffoldState extends State<AkuScaffold> {
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: widget.backgroundColor,
extendBody: widget.extendBody,
extendBodyBehindAppBar: widget.extendBody,
appBar: widget.appBar ??
AppBar(
backgroundColor: widget.appBarColor,
leading: widget.leading ?? AkuBackButton(),
brightness: widget.brightness,
systemOverlayStyle:
SystemUiOverlayStyle(statusBarBrightness: widget.brightness),
elevation: 0,
centerTitle: true,
title: DefaultTextStyle(

@ -0,0 +1,118 @@
import 'package:aku_new_community_manager/models/common/img_model.dart';
import 'package:aku_new_community_manager/ui/widgets/app_widgets/bee_image_network.dart';
import 'package:aku_new_community_manager/ui/widgets/inner/bee_image_preview.dart';
import 'package:aku_new_community_manager/utils/extension/list_extension.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:velocity_x/src/extensions/string_ext.dart';
import 'package:velocity_x/velocity_x.dart';
class BeeHorImageView extends StatefulWidget {
final EdgeInsets? padding;
final int maxCount;
final List<ImgModel> imgs;
final double imgWidth;
final double imgHeight;
final BorderRadiusGeometry? borderRadius;
final int? spacing;
final VoidCallback? onPressed;
const BeeHorImageView(
{Key? key,
this.padding = EdgeInsets.zero,
required this.maxCount,
required this.imgs,
required this.imgWidth,
required this.imgHeight,
this.borderRadius,
this.spacing,
this.onPressed})
: super(key: key);
@override
_BeeHorImageViewState createState() => _BeeHorImageViewState();
}
class _BeeHorImageViewState extends State<BeeHorImageView> {
bool get overFlow => widget.imgs.length > widget.maxCount;
int get overCount => overFlow ? (widget.imgs.length - widget.maxCount) : 0;
@override
Widget build(BuildContext context) {
return Container(
padding: widget.padding,
child: Row(
children: List.generate(widget.imgs.length - overCount, (index) {
if (overFlow && (index == widget.maxCount - 1)) {
return _overFlowWidget(widget.imgs[index]);
} else {
return _imageView(widget.imgs[index]);
}
}).sepWidget(separate: (widget.spacing ?? 10).w.widthBox),
),
);
}
Widget _overFlowWidget(ImgModel img) {
return Stack(
children: [
Container(
clipBehavior: Clip.antiAliasWithSaveLayer,
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: widget.borderRadius ?? BorderRadius.circular(16.w)),
child: BeeImageNetwork(
width: widget.imgWidth,
height: widget.imgHeight,
imgs: [img],
),
),
GestureDetector(
onTap: widget.onPressed,
child: Container(
width: widget.imgWidth,
height: widget.imgHeight,
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.5),
borderRadius: widget.borderRadius ?? BorderRadius.circular(16.w),
),
alignment: Alignment.center,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.image,
size: 24.w,
color: Colors.white,
),
8.w.widthBox,
'${overCount + 1}'.text.size(28.sp).color(Colors.white).make(),
],
),
),
)
],
);
}
Widget _imageView(ImgModel img) {
return GestureDetector(
onTap: () {
BeeImagePreview.toPath(path: img.url);
},
child: Container(
clipBehavior: Clip.antiAliasWithSaveLayer,
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: widget.borderRadius ?? BorderRadius.circular(16.w)),
child: BeeImageNetwork(
width: widget.imgWidth,
height: widget.imgHeight,
imgs: [img],
),
),
);
}
}

@ -0,0 +1,36 @@
import 'package:aku_new_community_manager/style/app_style.dart';
import 'package:flutter/material.dart';
import 'package:velocity_x/src/extensions/string_ext.dart';
class BeeLongButton extends StatelessWidget {
final VoidCallback? onPressed;
final String text;
final Color backColor;
final BorderSide border;
const BeeLongButton({Key? key, required this.onPressed, required this.text})
: backColor = kPrimaryColor,
border = BorderSide.none,
super(key: key);
BeeLongButton.white({Key? key, required this.onPressed, required this.text})
: backColor = Colors.white,
border = BorderSide(color: Colors.black.withOpacity(0.45)),
super(key: key);
@override
Widget build(BuildContext context) {
return 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), side: border),
color: backColor,
onPressed: onPressed,
child: text.text.size(32.sp).bold.make(),
);
}
}

@ -0,0 +1,43 @@
import 'package:aku_new_community_manager/ui/widgets/app_widgets/bee_image_network.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class StackAvatar extends StatelessWidget {
final List<String?> avatars;
const StackAvatar({Key? key, required this.avatars}) : super(key: key);
double get offset => 35.w;
int get length => avatars.length;
@override
Widget build(BuildContext context) {
return Stack(
children: [
SizedBox(
width: 44.w * 2 + 26.w,
height: 44.w + 6.w,
),
...List.generate(length, (index) {
return Positioned(
left: index * offset,
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(22.w + 2.w),
// border: Border.all(color: Color(0xFF999999)),
),
clipBehavior: Clip.antiAlias,
child: BeeImageNetwork(
width: 44.w,
height: 44.w,
urls: [avatars[index] ?? ''],
),
),
);
}),
],
);
}
}

@ -1,10 +1,11 @@
import 'dart:io';
import 'package:aku_new_community_manager/const/api.dart';
import 'package:aku_new_community_manager/const/resource.dart';
import 'package:aku_new_community_manager/const/saas_api.dart';
import 'package:aku_new_community_manager/gen/assets.gen.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
///
class BeeImagePreview extends StatefulWidget {
static Future<T?> toFile<T>({required File file, String? tag}) async {
return await navigator!.push(
@ -45,6 +46,7 @@ class BeeImagePreview extends StatefulWidget {
final File? file;
final String? path;
final String? tag;
BeeImagePreview.file({Key? key, required this.file, this.tag})
: path = null,
super(key: key);
@ -63,8 +65,14 @@ class _BeeImagePreviewState extends State<BeeImagePreview> {
return Hero(
tag: widget.tag ?? widget.path!,
child: FadeInImage.assetNetwork(
placeholder: R.ASSETS_PLACEHOLDER_WEBP,
image: API.image(widget.path!),
placeholder: Assets.placeholder.path,
image: SAASAPI.image(widget.path),
imageErrorBuilder: (context, obj, stackTrace) {
return Image.asset(
Assets.placeholder.path,
fit: BoxFit.fill,
);
},
),
);
else

@ -102,6 +102,7 @@ flutter:
- assets/manage/
- assets/inspection/
- assets/outdoor/
- assets/icons/
- assets/static_temp/
- assets/static_fix/

Loading…
Cancel
Save