diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 06f64d98..59948331 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -382,7 +382,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 8; - DEVELOPMENT_TEAM = R45ZDS6S92; + DEVELOPMENT_TEAM = 89Z9B4EZ45; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -526,7 +526,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 8; - DEVELOPMENT_TEAM = R45ZDS6S92; + DEVELOPMENT_TEAM = 89Z9B4EZ45; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -564,7 +564,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 8; - DEVELOPMENT_TEAM = R45ZDS6S92; + DEVELOPMENT_TEAM = 89Z9B4EZ45; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", diff --git a/lib/constants/saas_api.dart b/lib/constants/saas_api.dart index 7cac0182..24cdba51 100644 --- a/lib/constants/saas_api.dart +++ b/lib/constants/saas_api.dart @@ -32,6 +32,7 @@ class SAASAPI { static _Activity activity = _Activity(); static _Announce announce = _Announce(); static _Information information = _Information(); + static _WorkOrder workOrder = _WorkOrder(); ///二级分类 static _ProfileApi profile = _ProfileApi(); @@ -208,3 +209,41 @@ class _Information { ///查询app所有的资讯分类信息 String get categoryList => '/app/user/information/categoryList'; } + +class _WorkOrder { + ///根据工单主键id查询工单账单 + String get workOrderBill => '/app/user/workOrder/workOrderBill'; + + ///根据工单主键id查询工单报告列表 + String get findRRById => '/app/user/workOrder/findRRById'; + + ///根据工单主键id查询工单信息 + String get findById => '/app/user/workOrder/findById'; + + ///根据工单主键id查询工单进度列表 + String get findScheduleById => '/app/user/workOrder/findScheduleById'; + + ///评价 + String get evaluate => '/app/user/workOrder/evaluate'; + + ///确认完成 + String get confirmCompletion => '/app/user/workOrder/confirmCompletion'; + + ///催促进度 + String get promotionRate => '/app/user/workOrder/promotionRate'; + + ///取消工单 + String get cancel => '/app/user/workOrder/cancel'; + + ///查询服务团队名单 + String get findServiceTeamList => '/app/user/workOrder/findServiceTeamList'; + + ///发布工单 + String get insert => '/app/user/workOrder/insert'; + + ///查询所有的工单类型信息 + String get typeList => '/app/user/workOrder/typeList'; + + ///查询所有的工单信息 + String get list => '/app/user/workOrder/list'; +} diff --git a/lib/models/work_order/team_list_model.dart b/lib/models/work_order/team_list_model.dart index a03b3252..565b8c42 100644 --- a/lib/models/work_order/team_list_model.dart +++ b/lib/models/work_order/team_list_model.dart @@ -1,24 +1,45 @@ -import 'package:aku_new_community/model/common/img_model.dart'; +import 'package:equatable/equatable.dart'; import 'package:json_annotation/json_annotation.dart'; part 'team_list_model.g.dart'; @JsonSerializable() -class TeamListModel { +class TeamListModel extends Equatable { final int id; - final String name; - final List imgs; - final String tel; - final String position; + 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 json) => _$TeamListModelFromJson(json); const TeamListModel({ required this.id, - required this.name, - required this.imgs, - required this.tel, - required this.position, + 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 get props => [ + id, + userType, + manageUserId, + manageUserName, + manageUserTel, + departmentId, + departmentName, + positionId, + positionName, + ]; } diff --git a/lib/models/work_order/team_list_model.g.dart b/lib/models/work_order/team_list_model.g.dart index d526c0b8..27c44de3 100644 --- a/lib/models/work_order/team_list_model.g.dart +++ b/lib/models/work_order/team_list_model.g.dart @@ -9,10 +9,12 @@ part of 'team_list_model.dart'; TeamListModel _$TeamListModelFromJson(Map json) => TeamListModel( id: json['id'] as int, - name: json['name'] as String, - imgs: (json['imgs'] as List) - .map((e) => ImgModel.fromJson(e as Map)) - .toList(), - tel: json['tel'] as String, - position: json['position'] as String, + 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, ); diff --git a/lib/models/work_order/work_order_bill_model.dart b/lib/models/work_order/work_order_bill_model.dart new file mode 100644 index 00000000..b1f3a80e --- /dev/null +++ b/lib/models/work_order/work_order_bill_model.dart @@ -0,0 +1,34 @@ +import 'package:equatable/equatable.dart'; +import 'package:json_annotation/json_annotation.dart'; + +part 'work_order_bill_model.g.dart'; + +@JsonSerializable() +class WorkOrderBillModel extends Equatable { + final int id; + final int costType; + final String name; + @JsonKey(name: 'num') + final int number; + final num price; + + factory WorkOrderBillModel.fromJson(Map json) => + _$WorkOrderBillModelFromJson(json); + + const WorkOrderBillModel({ + required this.id, + required this.costType, + required this.name, + required this.number, + required this.price, + }); + + @override + List get props => [ + id, + costType, + name, + number, + price, + ]; +} diff --git a/lib/models/work_order/work_order_bill_model.g.dart b/lib/models/work_order/work_order_bill_model.g.dart new file mode 100644 index 00000000..79ea7939 --- /dev/null +++ b/lib/models/work_order/work_order_bill_model.g.dart @@ -0,0 +1,16 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'work_order_bill_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +WorkOrderBillModel _$WorkOrderBillModelFromJson(Map json) => + WorkOrderBillModel( + id: json['id'] as int, + costType: json['costType'] as int, + name: json['name'] as String, + number: json['num'] as int, + price: json['price'] as num, + ); diff --git a/lib/models/work_order/work_order_detail_model.dart b/lib/models/work_order/work_order_detail_model.dart new file mode 100644 index 00000000..92eca55f --- /dev/null +++ b/lib/models/work_order/work_order_detail_model.dart @@ -0,0 +1,58 @@ +import 'package:aku_new_community/model/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 String content; + final String createDate; + final List? servicePersonnelImgList; + final int newReportNum; + final int? evaluateLevel; + final String? evaluateContent; + final String? evaluateDate; + + factory WorkOrderDetailModel.fromJson(Map json) => + _$WorkOrderDetailModelFromJson(json); + + const WorkOrderDetailModel({ + required this.id, + required this.code, + required this.status, + required this.workOrderTypeName, + required this.reserveAddress, + required this.reserveDate, + required this.content, + required this.createDate, + this.servicePersonnelImgList, + required this.newReportNum, + this.evaluateLevel, + this.evaluateContent, + this.evaluateDate, + }); + + @override + List get props => [ + id, + code, + status, + workOrderTypeName, + reserveAddress, + reserveDate, + content, + createDate, + servicePersonnelImgList, + newReportNum, + evaluateLevel, + evaluateContent, + evaluateDate, + ]; +} diff --git a/lib/models/work_order/work_order_detail_model.g.dart b/lib/models/work_order/work_order_detail_model.g.dart new file mode 100644 index 00000000..6ba23bb3 --- /dev/null +++ b/lib/models/work_order/work_order_detail_model.g.dart @@ -0,0 +1,28 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'work_order_detail_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +WorkOrderDetailModel _$WorkOrderDetailModelFromJson( + Map 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, + content: json['content'] as String, + createDate: json['createDate'] as String, + servicePersonnelImgList: + (json['servicePersonnelImgList'] as List?) + ?.map((e) => ImgModel.fromJson(e as Map)) + .toList(), + newReportNum: json['newReportNum'] as int, + evaluateLevel: json['evaluateLevel'] as int?, + evaluateContent: json['evaluateContent'] as String?, + evaluateDate: json['evaluateDate'] as String?, + ); diff --git a/lib/models/work_order/work_order_list_model.dart b/lib/models/work_order/work_order_list_model.dart new file mode 100644 index 00000000..11fe8496 --- /dev/null +++ b/lib/models/work_order/work_order_list_model.dart @@ -0,0 +1,48 @@ +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; + + factory WorkOrderListModel.fromJson(Map json) => + _$WorkOrderListModelFromJson(json); + DateTime? get updateDateDT => DateUtil.getDateTime(updateDate); + DateTime? get createDateDT => DateUtil.getDateTime(createDate); + + @override + List get props => [ + id, + code, + status, + workOrderTypeName, + reserveAddress, + reserveDate, + content, + updateDate, + createDate, + ]; + + 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, + }); +} diff --git a/lib/models/work_order/work_order_list_model.g.dart b/lib/models/work_order/work_order_list_model.g.dart new file mode 100644 index 00000000..13336c14 --- /dev/null +++ b/lib/models/work_order/work_order_list_model.g.dart @@ -0,0 +1,20 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'work_order_list_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +WorkOrderListModel _$WorkOrderListModelFromJson(Map 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, + ); diff --git a/lib/models/work_order/work_order_progress_model.dart b/lib/models/work_order/work_order_progress_model.dart new file mode 100644 index 00000000..7ec91924 --- /dev/null +++ b/lib/models/work_order/work_order_progress_model.dart @@ -0,0 +1,42 @@ +import 'package:equatable/equatable.dart'; +import 'package:json_annotation/json_annotation.dart'; + +part 'work_order_progress_model.g.dart'; + +@JsonSerializable() +class WorkOrderProgressModel extends Equatable { + final int id; + + /// 工单进度状态:1.待分配,2.工单池,3.已接单,4.处理中,5.待确认,6.待支付,7.已完成,8.已评价,9.已拒绝,10.已取消 + final int status; + final String content; + + ///创建人类型:1.申请人,2.分配人,3.负责人,4.管理员,5.协同人 + final int userType; + final int createId; + final String createName; + final String createDate; + + factory WorkOrderProgressModel.fromJson(Map json) => + _$WorkOrderProgressModelFromJson(json); + + const WorkOrderProgressModel({ + required this.id, + required this.status, + required this.content, + required this.userType, + required this.createId, + required this.createName, + required this.createDate, + }); + @override + List get props => [ + id, + status, + content, + userType, + createId, + createName, + createDate, + ]; +} diff --git a/lib/models/work_order/work_order_progress_model.g.dart b/lib/models/work_order/work_order_progress_model.g.dart new file mode 100644 index 00000000..7326fc01 --- /dev/null +++ b/lib/models/work_order/work_order_progress_model.g.dart @@ -0,0 +1,19 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'work_order_progress_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +WorkOrderProgressModel _$WorkOrderProgressModelFromJson( + Map json) => + WorkOrderProgressModel( + id: json['id'] as int, + status: json['status'] as int, + content: json['content'] as String, + userType: json['userType'] as int, + createId: json['createId'] as int, + createName: json['createName'] as String, + createDate: json['createDate'] as String, + ); diff --git a/lib/models/work_order/work_order_report_model.dart b/lib/models/work_order/work_order_report_model.dart new file mode 100644 index 00000000..0bfb3c4a --- /dev/null +++ b/lib/models/work_order/work_order_report_model.dart @@ -0,0 +1,81 @@ +import 'dart:core'; + +import 'package:aku_new_community/model/common/img_model.dart'; +import 'package:equatable/equatable.dart'; +import 'package:json_annotation/json_annotation.dart'; + +part 'work_order_report_model.g.dart'; + +@JsonSerializable() +class WorkOrderReportModel extends Equatable { + final int id; + final int type; + final String content; + final int userType; + final int createId; + final String createName; + final String createDate; + final String totalCost; + final List imgList; + final List reportRecordVoList; + + factory WorkOrderReportModel.fromJson(Map json) => + _$WorkOrderReportModelFromJson(json); + + const WorkOrderReportModel({ + required this.id, + required this.type, + required this.content, + required this.userType, + required this.createId, + required this.createName, + required this.createDate, + required this.totalCost, + required this.imgList, + required this.reportRecordVoList, + }); + + @override + List get props => [ + id, + type, + content, + userType, + createId, + createName, + createDate, + totalCost, + imgList, + reportRecordVoList, + ]; +} + +@JsonSerializable() +class ReportRecordVoList extends Equatable { + final int id; + final int costType; + final String name; + @JsonKey(name: 'num') + final int number; + final num price; + + factory ReportRecordVoList.fromJson(Map json) => + _$ReportRecordVoListFromJson(json); + + const ReportRecordVoList({ + required this.id, + required this.costType, + required this.name, + required this.number, + required this.price, + }); + + @override + List get props => [ + id, + costType, + name, + number, + price, + ]; +} diff --git a/lib/models/work_order/work_order_report_model.g.dart b/lib/models/work_order/work_order_report_model.g.dart new file mode 100644 index 00000000..0cbbd41a --- /dev/null +++ b/lib/models/work_order/work_order_report_model.g.dart @@ -0,0 +1,35 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'work_order_report_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +WorkOrderReportModel _$WorkOrderReportModelFromJson( + Map json) => + WorkOrderReportModel( + id: json['id'] as int, + type: json['type'] as int, + content: json['content'] as String, + userType: json['userType'] as int, + createId: json['createId'] as int, + createName: json['createName'] as String, + createDate: json['createDate'] as String, + totalCost: json['totalCost'] as String, + imgList: (json['imgList'] as List) + .map((e) => ImgModel.fromJson(e as Map)) + .toList(), + reportRecordVoList: (json['reportRecordVoList'] as List) + .map((e) => ReportRecordVoList.fromJson(e as Map)) + .toList(), + ); + +ReportRecordVoList _$ReportRecordVoListFromJson(Map json) => + ReportRecordVoList( + id: json['id'] as int, + costType: json['costType'] as int, + name: json['name'] as String, + number: json['num'] as int, + price: json['price'] as num, + ); diff --git a/lib/pages/sign/login/other_login_page.dart b/lib/pages/sign/login/other_login_page.dart index 0d173534..bb9c3e32 100644 --- a/lib/pages/sign/login/other_login_page.dart +++ b/lib/pages/sign/login/other_login_page.dart @@ -13,6 +13,7 @@ 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:power_logger/power_logger.dart'; import 'package:provider/provider.dart'; import 'package:velocity_x/velocity_x.dart'; @@ -98,17 +99,24 @@ class _OtherLoginPageState extends State { return; } var cancel = BotToast.showLoading(); - var response = await SignFunc.login( - _tel.text, - _psd.text, - UserTool - .appProvider.pickedCityAndCommunity!.communityModel!.id); - if (response.data['success']) { - await UserTool.userProvider.setLogin(response.data['data']); - await UserTool.dataProvider.addHistories(); - } else { - BotToast.showText(text: response.data['message']); + + try { + var response = await SignFunc.login( + _tel.text, + _psd.text, + UserTool.appProvider.pickedCityAndCommunity!.communityModel! + .id); + if (response.data['success']) { + await UserTool.userProvider.setLogin(response.data['data']); + await UserTool.dataProvider.addHistories(); + } else { + BotToast.showText(text: response.data['message']); + } + } catch (e) { + print(e.toString()); + LoggerData.addData(e.toString()); } + cancel(); }, text: '登录'), diff --git a/lib/ui/community/community_views/community_page.dart b/lib/ui/community/community_views/community_page.dart index 57c4a416..a006ddc4 100644 --- a/lib/ui/community/community_views/community_page.dart +++ b/lib/ui/community/community_views/community_page.dart @@ -44,7 +44,12 @@ class _CommunityPageState extends State with TickerProviderStateMixin, AutomaticKeepAliveClientMixin { TabController? _tabController; late EasyRefreshController _easyRefreshController; - List _tabs = []; + + List get _tabs { + if (UserTool.userProvider.isLogin) return ['附近社区', '我的动态']; + return ['附近社区']; + } + GlobalKey topicKey = GlobalKey(); GlobalKey myKey = GlobalKey(); @@ -62,9 +67,6 @@ class _CommunityPageState extends State void initState() { super.initState(); _easyRefreshController = EasyRefreshController(); - final userProvider = Provider.of(context, listen: false); - if (userProvider.isLogin) _tabs = ['附近社区', '我的动态']; - if (userProvider.isNotLogin) _tabs = ['附近社区']; _tabController = TabController( vsync: this, length: _tabs.length, @@ -103,7 +105,7 @@ class _CommunityPageState extends State indicator: const BoxDecoration(), tabs: _tabs.map((e) => Tab(text: e)).toList(), labelStyle: - TextStyle(fontSize: 32.sp, fontWeight: FontWeight.bold), + TextStyle(fontSize: 36.sp, fontWeight: FontWeight.bold), labelColor: Color(0xD9000000), unselectedLabelStyle: TextStyle(fontSize: 32.sp), unselectedLabelColor: Color(0x73000000), diff --git a/lib/ui/function_and_service/task/dialogs/task_evaluation_dialog.dart b/lib/ui/function_and_service/task/dialogs/task_evaluation_dialog.dart index 98c9216d..d8883788 100644 --- a/lib/ui/function_and_service/task/dialogs/task_evaluation_dialog.dart +++ b/lib/ui/function_and_service/task/dialogs/task_evaluation_dialog.dart @@ -8,12 +8,10 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:velocity_x/src/extensions/string_ext.dart'; -import '../task_func.dart'; - class TaskEvaluationDialog extends StatefulWidget { - final int taskId; + final Future Function(int star, String content) evaluate; - const TaskEvaluationDialog({Key? key, required this.taskId}) + const TaskEvaluationDialog({Key? key, required this.evaluate}) : super(key: key); @override @@ -107,10 +105,8 @@ class _TaskEvaluationDialogState extends State { BotToast.showText(text: '请选择评价满意度'); return; } - var re = await TaskFunc.evaluate( - taskId: widget.taskId, - star: _currentIndex!, - evaluation: _controller.text); + var re = + await widget.evaluate(_currentIndex!, _controller.text); if (re) { Get.back(); } diff --git a/lib/ui/function_and_service/task/my_task/my_task_detail_page.dart b/lib/ui/function_and_service/task/my_task/my_task_detail_page.dart index 9fa6e3f0..ac8a8097 100644 --- a/lib/ui/function_and_service/task/my_task/my_task_detail_page.dart +++ b/lib/ui/function_and_service/task/my_task/my_task_detail_page.dart @@ -239,7 +239,10 @@ class _MyTaskDetailPageState extends State { return BeeLongButton( onPressed: () async { var re = await Get.bottomSheet(TaskEvaluationDialog( - taskId: widget.model.id, + evaluate: (star, content) async { + return await TaskFunc.evaluate( + taskId: widget.model.id, star: star, evaluation: content); + }, )); }, text: '点击评价', diff --git a/lib/ui/function_and_service/work_order/dialogs/cancel_dialog.dart b/lib/ui/function_and_service/work_order/dialogs/cancel_dialog.dart new file mode 100644 index 00000000..2cc03ad3 --- /dev/null +++ b/lib/ui/function_and_service/work_order/dialogs/cancel_dialog.dart @@ -0,0 +1,37 @@ +import 'package:aku_new_community/extensions/num_ext.dart'; +import 'package:aku_new_community/widget/buttons/bee_long_button.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:velocity_x/src/extensions/string_ext.dart'; + +class CancelDialog extends StatelessWidget { + final VoidCallback onCancel; + + const CancelDialog({ + Key? key, + required this.onCancel, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + width: double.infinity, + padding: EdgeInsets.symmetric(horizontal: 32.w), + child: Column( + children: [ + 120.hb, + '确认要取消工单?'.text.size(36.sp).black.bold.isIntrinsic.make(), + 40.hb, + '确认后,工单会马上取消,\n且服务人员的工作会立即结束' + .text + .align(TextAlign.center) + .size(28.sp) + .isIntrinsic + .make(), + 150.hb, + BeeLongButton(onPressed: onCancel, text: '确认提醒') + ], + ), + ); + } +} diff --git a/lib/ui/function_and_service/work_order/dialogs/urge_dialog.dart b/lib/ui/function_and_service/work_order/dialogs/urge_dialog.dart new file mode 100644 index 00000000..57d7d312 --- /dev/null +++ b/lib/ui/function_and_service/work_order/dialogs/urge_dialog.dart @@ -0,0 +1,32 @@ +import 'package:aku_new_community/extensions/num_ext.dart'; +import 'package:aku_new_community/widget/buttons/bee_long_button.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:velocity_x/src/extensions/string_ext.dart'; + +class UrgeDialog extends StatelessWidget { + final VoidCallback onConfirm; + + const UrgeDialog({ + Key? key, + required this.onConfirm, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + width: double.infinity, + padding: EdgeInsets.symmetric(horizontal: 32.w), + child: Column( + children: [ + 120.hb, + '确认发送提醒?'.text.size(36.sp).black.bold.isIntrinsic.make(), + 40.hb, + '确认后,会对服务人员发送尽快完成任务的通知'.text.size(28.sp).isIntrinsic.make(), + 150.hb, + BeeLongButton(onPressed: onConfirm, text: '确认提醒') + ], + ), + ); + } +} diff --git a/lib/ui/function_and_service/work_order/dialogs/work_order_bill_dialog.dart b/lib/ui/function_and_service/work_order/dialogs/work_order_bill_dialog.dart new file mode 100644 index 00000000..9518e801 --- /dev/null +++ b/lib/ui/function_and_service/work_order/dialogs/work_order_bill_dialog.dart @@ -0,0 +1,80 @@ +import 'package:aku_new_community/extensions/num_ext.dart'; +import 'package:aku_new_community/models/work_order/work_order_bill_model.dart'; +import 'package:aku_new_community/widget/bee_divider.dart'; +import 'package:aku_new_community/widget/buttons/bee_long_button.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:velocity_x/src/extensions/string_ext.dart'; + +class WorkOrderBillDialog extends StatelessWidget { + final List models; + + const WorkOrderBillDialog({Key? key, required this.models}) : super(key: key); + + double get total { + double sum = 0; + for (var item in models) { + sum = sum + item.price; + } + return sum; + } + + @override + Widget build(BuildContext context) { + return Container( + width: double.infinity, + color: Colors.white, + child: Column( + children: [ + 40.hb, + '确认账单' + .text + .size(32.sp) + .isIntrinsic + .color(Colors.black.withOpacity(0.65)) + .make(), + 80.hb, + ...models + .map((e) => Row( + children: [ + '${e.costType == 1 ? '人工费' : '耗材费'}${e.name}${e.costType == 1 ? '' : '*${e.number}'}' + .text + .size(28.sp) + .color(Colors.black.withOpacity(0.65)) + .isIntrinsic + .make(), + Spacer(), + '¥${e.price}' + .text + .size(28.sp) + .color(Colors.black.withOpacity(0.65)) + .isIntrinsic + .make(), + ], + )) + .toList(), + BeeDivider.horizontal(), + Row( + children: [ + '工单总费用' + .text + .size(28.sp) + .color(Colors.black.withOpacity(0.65)) + .isIntrinsic + .make(), + Spacer(), + '¥${total}' + .text + .size(28.sp) + .color(Color(0xFFF5222D)) + .isIntrinsic + .make(), + ], + ), + 80.hb, + BeeLongButton(onPressed: () {}, text: '确认支付'), + ], + ), + ); + } +} diff --git a/lib/ui/function_and_service/work_order/work_order_finish_dialog.dart b/lib/ui/function_and_service/work_order/dialogs/work_order_finish_dialog.dart similarity index 100% rename from lib/ui/function_and_service/work_order/work_order_finish_dialog.dart rename to lib/ui/function_and_service/work_order/dialogs/work_order_finish_dialog.dart diff --git a/lib/ui/function_and_service/work_order/dialogs/work_order_progress_dialog.dart b/lib/ui/function_and_service/work_order/dialogs/work_order_progress_dialog.dart new file mode 100644 index 00000000..486345e8 --- /dev/null +++ b/lib/ui/function_and_service/work_order/dialogs/work_order_progress_dialog.dart @@ -0,0 +1,129 @@ +import 'package:aku_new_community/extensions/num_ext.dart'; +import 'package:aku_new_community/models/work_order/work_order_progress_model.dart'; +import 'package:aku_new_community/widget/bee_divider.dart'; +import 'package:common_utils/common_utils.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 WorkOrderProgressDialog extends StatelessWidget { + final List models; + + const WorkOrderProgressDialog({Key? key, required this.models}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + width: double.infinity, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16.w), color: Colors.white), + child: Column( + children: [ + Padding( + padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 36.w), + child: Row( + children: [ + '工单进度' + .text + .size(28.sp) + .isIntrinsic + .color(Colors.black.withOpacity(0.85)) + .make(), + ], + ), + ), + BeeDivider.horizontal(), + Padding( + padding: EdgeInsets.symmetric(horizontal: 40.w, vertical: 36.w), + child: Column( + children: [ + ...models + .mapIndexed((currentValue, index) => _buildLine( + currentValue, + index, + )) + .toList() + ], + )) + ], + ), + ); + } + + Widget _buildLine(WorkOrderProgressModel model, int index) { + return Container( + width: double.infinity, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + DateUtil.formatDateStr(model.createDate, format: 'MM/dd') + .text + .size(28.sp) + .color(Colors.black.withOpacity(0.45)) + .make(), + 16.wb, + Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + Container( + width: 32.w, + height: 32.w, + alignment: Alignment.center, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16.w), + border: index == 0 + ? Border.all(color: Color(0xFFFAC058), width: 4.w) + : null, + color: index == 0 + ? Colors.white + : Colors.black.withOpacity(0.25)), + child: Container( + width: 16.w, + height: 16.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8.w), + color: index == 0 + ? Color(0xFFFAC058) + : Colors.black.withOpacity(0.25)), + ), + ), + Offstage( + offstage: index == models.length - 1, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + 16.hb, + Container( + width: 4.w, + height: 55.w, + color: index == 0 + ? Color(0xFFFAC058) + : Colors.black.withOpacity(0.25), + ), + ], + ), + ), + ], + ), + 16.wb, + DateUtil.formatDateStr(model.createDate, format: 'HH:mm') + .text + .size(28.sp) + .color(Colors.black.withOpacity(0.85)) + .make(), + 32.wb, + '${model.content}' + .text + .size(28.sp) + .color(index == 0 + ? Color(0xFFFAC058) + : Colors.black.withOpacity(0.65)) + .make() + ], + ), + ); + } +} diff --git a/lib/ui/function_and_service/work_order/history_report_page.dart b/lib/ui/function_and_service/work_order/history_report_page.dart new file mode 100644 index 00000000..b68719b4 --- /dev/null +++ b/lib/ui/function_and_service/work_order/history_report_page.dart @@ -0,0 +1,263 @@ +import 'dart:math'; + +import 'package:aku_new_community/extensions/num_ext.dart'; +import 'package:aku_new_community/models/work_order/work_order_report_model.dart'; +import 'package:aku_new_community/widget/bee_scaffold.dart'; +import 'package:aku_new_community/widget/dotted_line.dart'; +import 'package:aku_new_community/widget/views/bee_grid_image_view.dart'; +import 'package:common_utils/common_utils.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/src/extensions/string_ext.dart'; +import 'package:velocity_x/velocity_x.dart'; + +class HistoryReportPage extends StatefulWidget { + final int id; + + const HistoryReportPage({Key? key, required this.id}) : super(key: key); + + @override + _HistoryReportPageState createState() => _HistoryReportPageState(); +} + +class _HistoryReportPageState extends State { + List _models = []; + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return BeeScaffold( + title: '历史报告', + body: EasyRefresh( + firstRefresh: true, + header: MaterialHeader(), + onRefresh: () async { + // var base = + // await NetUtil().get(SAASAPI.workOrder.findRRById, params: { + // 'workOrderId': widget.id, + // }); + // if (base.success) { + // _models = (base.data as List) + // .map((e) => WorkOrderReportModel.fromJson(e)) + // .toList(); + // setState(() {}); + // } + _models.add(WorkOrderReportModel( + id: Random().nextInt(100), + type: Random().nextInt(100), + content: '${List.filled(Random().nextInt(50), 'aabb')}', + userType: Random().nextInt(2), + createId: Random().nextInt(100), + createName: 'xxx', + createDate: DateTime.now().toString(), + totalCost: '300', + imgList: [], + reportRecordVoList: [])); + setState(() {}); + }, + child: _models.isEmpty + ? Container() + : ListView(children: [ + Container( + width: double.infinity, + padding: EdgeInsets.all(32.w), + margin: EdgeInsets.only(top: 10.w), + color: Colors.white, + child: Column( + children: _models + .mapIndexed((e, index) => LineCard( + key: ValueKey(e.id), + model: e, + index: index, + length: _models.length, + )) + .toList(), + ), + ) + ])), + ); + } +} + +class LineCard extends StatefulWidget { + final WorkOrderReportModel model; + final int index; + final int length; + + const LineCard( + {Key? key, + required this.model, + required this.index, + required this.length}) + : super(key: key); + + @override + _LineCardState createState() => _LineCardState(); +} + +class _LineCardState extends State { + double _height = 0; + + @override + void didChangeDependencies() { + WidgetsBinding.instance?.addPostFrameCallback((timeStamp) { + _height = context.size?.height ?? 0; + print(context.size?.height); + setState(() {}); + }); + super.didChangeDependencies(); + } + + @override + void didUpdateWidget(covariant LineCard oldWidget) { + // WidgetsBinding.instance?.addPostFrameCallback((timeStamp) { + // _height = context.size?.height ?? 0; + // print(context.size?.height); + // }); + super.didUpdateWidget(oldWidget); + } + + @override + Widget build(BuildContext context) { + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + mainAxisSize: MainAxisSize.min, + children: [ + widget.index == 0 + ? Container( + alignment: Alignment.center, + width: 40.w, + height: 40.w, + decoration: BoxDecoration( + color: Color(0xFFFAC058), + borderRadius: BorderRadius.circular(20.w)), + child: Icon( + CupertinoIcons.checkmark_alt, + color: Colors.white, + size: 24.w, + ), + ) + : Container( + margin: EdgeInsets.all(4.w), + width: 32.w, + height: 32.w, + alignment: Alignment.center, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(16.w), + border: Border.all( + color: Colors.black.withOpacity(0.25), width: 4.w), + ), + child: Container( + width: 16.w, + height: 16.w, + decoration: BoxDecoration( + color: Colors.black.withOpacity(0.25), + borderRadius: BorderRadius.circular(8.w), + ), + ), + ), + if (widget.index != widget.length - 1) + SizedBox( + height: _height, + child: DottedLine( + width: 10.w, + color: Colors.black.withOpacity(0.25), + proportion: 0.5, + direction: Axis.vertical, + ), + ), + ], + ), + 40.wb, + Expanded( + child: Column( + children: [ + Row( + children: [ + '${widget.model.type == 1 ? '工单报告' : '完结报告'}' + .text + .size(28.sp) + .color(Colors.black.withOpacity(0.85)) + .make(), + 16.wb, + DateUtil.formatDateStr(widget.model.createDate, + format: 'MM-dd HH:ss') + .text + .size(26.sp) + .color(Colors.black.withOpacity(0.45)) + .make(), + Spacer(), + '${widget.model.userType == 1 ? '负责人' : '协同人'}' + .text + .size(26.sp) + .color(Colors.black.withOpacity(0.45)) + .make(), + 16.wb, + widget.model.createName.text + .size(26.sp) + .color(Colors.black.withOpacity(0.45)) + .make(), + ], + ), + SizedBox( + width: 606.w, + child: Text( + widget.model.content, + style: TextStyle( + color: Colors.black.withOpacity(0.45), fontSize: 26.sp), + ), + ), + Offstage( + offstage: widget.model.imgList.isEmpty, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + 24.hb, + BeeGridImageView( + urls: widget.model.imgList.map((e) => e.url).toList()), + ], + ), + ), + Offstage( + offstage: widget.model.reportRecordVoList.isEmpty, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ...widget.model.reportRecordVoList + .map((e) => Row( + children: [ + '${e.costType == 1 ? '人工费' : '耗材费'}${e.name}${e.costType == 1 ? '' : '*${e.number}'}' + .text + .size(28.sp) + .color(Colors.black.withOpacity(0.65)) + .isIntrinsic + .make(), + Spacer(), + '¥${e.price}' + .text + .size(28.sp) + .color(Colors.black.withOpacity(0.65)) + .isIntrinsic + .make(), + ], + )) + .toList(), + ], + ), + ) + ], + ), + ) + ], + ); + } +} diff --git a/lib/ui/function_and_service/work_order/team_list_page.dart b/lib/ui/function_and_service/work_order/team_list_page.dart index 7ba31fff..e88f95dc 100644 --- a/lib/ui/function_and_service/work_order/team_list_page.dart +++ b/lib/ui/function_and_service/work_order/team_list_page.dart @@ -1,29 +1,62 @@ +import 'package:aku_new_community/constants/saas_api.dart'; import 'package:aku_new_community/extensions/num_ext.dart'; import 'package:aku_new_community/gen/assets.gen.dart'; import 'package:aku_new_community/models/work_order/team_list_model.dart'; +import 'package:aku_new_community/utils/network/net_util.dart'; import 'package:aku_new_community/widget/bee_scaffold.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/src/extensions/string_ext.dart'; class TeamListPage extends StatefulWidget { - const TeamListPage({Key? key}) : super(key: key); + final int workOderId; + + const TeamListPage({Key? key, required this.workOderId}) : super(key: key); @override _TeamListPageState createState() => _TeamListPageState(); } class _TeamListPageState extends State { + List _models = []; + + TeamListModel? get _mainModel { + for (var item in _models) { + if (item.userType == 1) { + return item; + } else { + return null; + } + } + } + @override Widget build(BuildContext context) { return BeeScaffold( title: '服务团队名单', - body: ListView( - children: [ - _PositionTile('主负责人'), - ...[].map((e) => _personTile(e)).toList() - ], + 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() + ], + ), ), ); } @@ -40,12 +73,12 @@ class _TeamListPageState extends State { 16.wb, Column( children: [ - model.name.text + model.manageUserName.text .size(28.sp) .color(Colors.black.withOpacity(0.85)) .make(), 8.hb, - model.position.text + model.departmentName.text .size(24.sp) .color(Colors.black.withOpacity(0.45)) .make(), @@ -54,7 +87,7 @@ class _TeamListPageState extends State { Spacer(), GestureDetector( onTap: () async { - await launch('tel:${model.tel}'); + await launch('tel:${model.manageUserTel}'); }, child: Assets.icons.phone.image(width: 40.w, height: 40.w), ) @@ -63,7 +96,7 @@ class _TeamListPageState extends State { ); } - Widget _PositionTile(String text) { + Widget _positionTile(String text) { return Container( padding: EdgeInsets.symmetric(horizontal: 32.w, vertical: 16.w), width: double.infinity, diff --git a/lib/ui/function_and_service/work_order/work_order_card.dart b/lib/ui/function_and_service/work_order/work_order_card.dart index 396d1ed8..a823803b 100644 --- a/lib/ui/function_and_service/work_order/work_order_card.dart +++ b/lib/ui/function_and_service/work_order/work_order_card.dart @@ -1,16 +1,26 @@ import 'package:aku_new_community/base/base_style.dart'; import 'package:aku_new_community/extensions/num_ext.dart'; import 'package:aku_new_community/gen/assets.gen.dart'; +import 'package:aku_new_community/models/work_order/work_order_list_model.dart'; +import 'package:aku_new_community/ui/function_and_service/work_order/work_order_detail_page.dart'; +import 'package:aku_new_community/ui/function_and_service/work_order/work_order_func.dart'; +import 'package:aku_new_community/ui/function_and_service/work_order/work_order_map.dart'; import 'package:aku_new_community/utils/bee_date_util.dart'; import 'package:aku_new_community/widget/buttons/card_bottom_button.dart'; import 'package:aku_new_community/widget/views/bee_hor_image_view.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/src/extensions/string_ext.dart'; class WorkOrderCard extends StatelessWidget { - const WorkOrderCard({Key? key}) : super(key: key); + final WorkOrderListModel model; + final VoidCallback refresh; + + const WorkOrderCard({Key? key, required this.model, required this.refresh}) + : super(key: key); @override Widget build(BuildContext context) { @@ -36,106 +46,151 @@ class WorkOrderCard extends StatelessWidget { ), alignment: Alignment.center, child: Text( - '已接单', + '${WorkOrderMap.orderStatus[model.status]}', style: TextStyle( fontSize: 26.sp, color: Colors.black, ), ), )), - 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), + GestureDetector( + onTap: () { + Get.to(() => WorkOrderDetailPage( + model: model, + )); + }, + 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(), ), - child: '家政服务' + ], + ), + 16.hb, + Row( + children: [ + Assets.icons.alarmClock.image(width: 40.w, height: 40.w), + 24.wb, + '${model.updateDate}' .text .size(24.sp) - .color(Color(0xFFD48806)) + .color(Colors.black.withOpacity(0.45)) .make(), - ), - ], - ), - 16.hb, - Row( - children: [ - Assets.icons.alarmClock.image(width: 40.w, height: 40.w), - 24.wb, - '2022.02.21 15:30' - .text - .size(24.sp) - .color(Colors.black.withOpacity(0.45)) - .make(), - ], - ), - 16.hb, - Row( - children: [ - Assets.icons.taskLocation.image(width: 40.w, height: 40.w), - 24.wb, - '绿城·碧桂园3好楼门外' - .text - .size(24.sp) - .color(Colors.black.withOpacity(0.45)) - .make(), - ], - ), - 60.hb, - 'xxxxxxxxxxxxxxxxxxxxxxxx' - .text - .size(28.sp) - .color(Colors.black.withOpacity(0.65)) - .make(), - 24.hb, - BeeHorImageView( - maxCount: 4, imgs: [], imgWidth: 146.w, imgHeight: 146.w), - 24.hb, - Row( - children: [ - BeeDateUtil(DateTime.now()) - .timeAgo - .text - .size(24.sp) - .color(Colors.black.withOpacity(0.45)) - .make(), - Spacer(), - CardBottomButton.yellow(text: '催促进度', onPressed: () {}), - 24.wb, - GestureDetector( - onTap: () {}, - child: Icon( - CupertinoIcons.ellipsis_vertical, - size: 40.w, - ), - ) - ], - ), - ], + ], + ), + 16.hb, + Row( + children: [ + Assets.icons.taskLocation + .image(width: 40.w, height: 40.w), + 24.wb, + '${model.reserveAddress}' + .text + .size(24.sp) + .color(Colors.black.withOpacity(0.45)) + .make(), + ], + ), + 60.hb, + '${model.content}' + .text + .size(28.sp) + .color(Colors.black.withOpacity(0.65)) + .make(), + 24.hb, + BeeHorImageView( + maxCount: 4, imgs: [], imgWidth: 146.w, imgHeight: 146.w), + 24.hb, + Row( + children: [ + BeeDateUtil(DateUtil.getDateTime(model.createDate)) + .timeAgo + .text + .size(24.sp) + .color(Colors.black.withOpacity(0.45)) + .make(), + Spacer(), + 24.wb, + GestureDetector( + onTap: () {}, + child: Icon( + CupertinoIcons.ellipsis_vertical, + size: 40.w, + ), + ) + ], + ), + ], + ), ), ), ) ], ); } + + Widget getCardBottomButton() { + switch (model.status) { + case 1: + return SizedBox.shrink(); + case 2: + return SizedBox.shrink(); + case 3: + case 4: + return CardBottomButton.yellow( + text: '催促进度', + onPressed: () async { + var re = await WorkOrderFuc.promotionRate(model.id); + if (re) { + refresh(); + } + }); + case 5: + return CardBottomButton.yellow( + text: '确认完成', + onPressed: () async { + var re = await WorkOrderFuc.confirmComplete(model.id); + if (re) { + refresh(); + } + }); + case 6: + return CardBottomButton.yellow(text: '去支付', onPressed: () {}); + 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 { diff --git a/lib/ui/function_and_service/work_order/work_order_detail_page.dart b/lib/ui/function_and_service/work_order/work_order_detail_page.dart index d28b44b7..6c275ae7 100644 --- a/lib/ui/function_and_service/work_order/work_order_detail_page.dart +++ b/lib/ui/function_and_service/work_order/work_order_detail_page.dart @@ -1,7 +1,19 @@ +import 'package:aku_new_community/constants/saas_api.dart'; import 'package:aku_new_community/extensions/num_ext.dart'; import 'package:aku_new_community/gen/assets.gen.dart'; +import 'package:aku_new_community/models/work_order/work_order_detail_model.dart'; +import 'package:aku_new_community/models/work_order/work_order_list_model.dart'; +import 'package:aku_new_community/ui/function_and_service/task/dialogs/task_evaluation_dialog.dart'; +import 'package:aku_new_community/ui/function_and_service/work_order/dialogs/urge_dialog.dart'; +import 'package:aku_new_community/ui/function_and_service/work_order/dialogs/work_order_bill_dialog.dart'; +import 'package:aku_new_community/ui/function_and_service/work_order/dialogs/work_order_finish_dialog.dart'; +import 'package:aku_new_community/ui/function_and_service/work_order/team_list_page.dart'; +import 'package:aku_new_community/ui/function_and_service/work_order/work_order_func.dart'; +import 'package:aku_new_community/ui/function_and_service/work_order/work_order_map.dart'; +import 'package:aku_new_community/utils/network/net_util.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/buttons/bee_long_button.dart'; import 'package:aku_new_community/widget/others/stack_avatar.dart'; import 'package:aku_new_community/widget/views/bee_grid_image_view.dart'; import 'package:bot_toast/bot_toast.dart'; @@ -9,18 +21,32 @@ 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'; class WorkOrderDetailPage extends StatefulWidget { - const WorkOrderDetailPage({Key? key}) : super(key: key); + final WorkOrderListModel model; + + const WorkOrderDetailPage({Key? key, required this.model}) : super(key: key); @override _WorkOrderDetailPageState createState() => _WorkOrderDetailPageState(); } class _WorkOrderDetailPageState extends State { + WorkOrderDetailModel? _model; + EasyRefreshController _refreshController = EasyRefreshController(); + + @override + void dispose() { + _refreshController.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { return BeeScaffold( @@ -31,18 +57,7 @@ class _WorkOrderDetailPageState extends State { width: double.infinity, height: 380.w, decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.centerLeft, - end: Alignment.centerRight, - colors: false - ? [ - Colors.white, - Color(0xFFADACAC), - ] - : [ - Color(0xFFFFB737), - Color(0xFFFFD361), - ]), + gradient: _getLiner, ), child: Column( children: [ @@ -54,13 +69,24 @@ class _WorkOrderDetailPageState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - 'detailStatusToString' - .text - .size(40.sp) - .color(Colors.black) - .bold - .make(), - 'subStatusString' + 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(), + ], + ), + ), + ), + '${WorkOrderMap.subStatusString[_model?.status] ?? ''}' .text .size(24.sp) .color(Colors.black.withOpacity(0.45)) @@ -75,18 +101,170 @@ class _WorkOrderDetailPageState extends State { ), ), SafeArea( - child: ListView( - padding: EdgeInsets.only(top: 120.w, left: 32.w, right: 32.w), - children: [ - _head(), - 24.hb, - _content(), - 24.w.heightBox, - _taskInfo(), - ], + child: EasyRefresh( + firstRefresh: true, + header: MaterialHeader(), + onRefresh: () async { + var base = await NetUtil().get(SAASAPI.workOrder.findById); + 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, + child: Column( + children: [ + _servicePeople(), + 24.hb, + ], + )), + _head(), + 24.hb, + _content(), + 24.w.heightBox, + _taskInfo(), + ], + ), )), ], ), + bottomNavi: _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: () { + launch('tel:'); + }, + text: '联系物业'); + case 2: + case 3: + case 4: + return BeeLongButton( + onPressed: () async { + await Get.bottomSheet(UrgeDialog(onConfirm: () async { + var re = await WorkOrderFuc.promotionRate(_model!.id); + if (re) { + _refreshController.callRefresh(); + } + })); + }, + text: '催促进度', + ); + case 5: + return BeeLongButton( + onPressed: () async { + await Get.bottomSheet(WorkOrderFinishDialog(onConfirm: () async { + var re = await WorkOrderFuc.confirmComplete(_model!.id); + if (re) { + Get.back(); + _refreshController.callRefresh(); + } + })); + }, + text: '确认完成'); + case 6: + return BeeLongButton( + onPressed: () async { + var bills = await WorkOrderFuc.getBill(workOrderId: _model!.id); + await Get.bottomSheet(WorkOrderBillDialog(models: bills)); + }, + text: '确认支付'); + case 7: + return BeeLongButton( + onPressed: () async { + await Get.bottomSheet(TaskEvaluationDialog( + evaluate: (star, content) async { + return await WorkOrderFuc.evaluate( + workOrderId: widget.model.id, + star: star, + evaluation: content); + }, + )); + }, + text: '点击评价'); + 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.wb, + Icon( + CupertinoIcons.chevron_right, + size: 24.w, + color: Colors.black.withOpacity(0.45), + ), + ], + ), + ), + ), ); } @@ -109,12 +287,19 @@ class _WorkOrderDetailPageState extends State { BeeDivider.horizontal(), 24.hb, GestureDetector( - onTap: () {}, + onTap: () { + Get.to(() => TeamListPage( + workOderId: _model!.id, + )); + }, child: Material( color: Colors.transparent, child: Row( children: [ - StackAvatar(avatars: []), + StackAvatar( + avatars: (_model!.servicePersonnelImgList ?? []) + .map((e) => e.url) + .toList()), Spacer(), '点击查看' .text @@ -153,7 +338,11 @@ class _WorkOrderDetailPageState extends State { color: Color(0xFFFFFBE6), borderRadius: BorderRadius.circular(8.w), ), - child: '家政服务'.text.size(24.sp).color(Color(0xFFD48806)).make(), + child: '${_model!.workOrderTypeName}' + .text + .size(24.sp) + .color(Color(0xFFD48806)) + .make(), ), ], ), @@ -162,7 +351,7 @@ class _WorkOrderDetailPageState extends State { children: [ Assets.icons.alarmClock.image(width: 40.w, height: 40.w), 24.wb, - '2022.02.21 15:30' + '${DateUtil.formatDateStr(_model!.reserveDate)}' .text .size(24.sp) .color(Colors.black.withOpacity(0.45)) @@ -174,7 +363,7 @@ class _WorkOrderDetailPageState extends State { children: [ Assets.icons.taskLocation.image(width: 40.w, height: 40.w), 24.wb, - '绿城·碧桂园3好楼门外' + '${_model!.reserveAddress}' .text .size(24.sp) .color(Colors.black.withOpacity(0.45)) @@ -198,7 +387,7 @@ class _WorkOrderDetailPageState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - 'xxxxxxxxxxxxxxxxxxxxxxxx' + '${_model!.content}' .text .size(28.sp) .color(Colors.black.withOpacity(0.65)) @@ -240,7 +429,7 @@ class _WorkOrderDetailPageState extends State { .color(Colors.black.withOpacity(0.45)) .make(), Spacer(), - '${DateUtil.formatDateStr('')}' + '${DateUtil.formatDateStr(_model!.createDate)}' .text .size(24.sp) .color(Colors.black.withOpacity(0.45)) @@ -251,13 +440,13 @@ class _WorkOrderDetailPageState extends State { 24.w.heightBox, Row( children: [ - '任务单号' + '工单编号' .text .size(24.sp) .color(Colors.black.withOpacity(0.45)) .make(), Spacer(), - 'widget.model.code}' + '${_model!.code}' .text .size(24.sp) .color(Colors.black.withOpacity(0.45)) @@ -265,8 +454,7 @@ class _WorkOrderDetailPageState extends State { 24.w.widthBox, GestureDetector( onTap: () async { - await Clipboard.setData( - ClipboardData(text: 'widget.model.code')); + await Clipboard.setData(ClipboardData(text: _model!.code)); BotToast.showText(text: '已复制到粘贴板'); }, child: Assets.icons.copy.image(width: 40.w, height: 40.w)), diff --git a/lib/ui/function_and_service/work_order/work_order_func.dart b/lib/ui/function_and_service/work_order/work_order_func.dart new file mode 100644 index 00000000..cd27c174 --- /dev/null +++ b/lib/ui/function_and_service/work_order/work_order_func.dart @@ -0,0 +1,66 @@ +import 'package:aku_new_community/constants/saas_api.dart'; +import 'package:aku_new_community/models/work_order/work_order_bill_model.dart'; +import 'package:aku_new_community/utils/network/base_model.dart'; +import 'package:aku_new_community/utils/network/net_util.dart'; + +class WorkOrderFuc { + ///催促 + static Future promotionRate(int id) async { + BaseModel baseModel = await NetUtil().get(SAASAPI.workOrder.promotionRate, + params: {'workOrderId': id}, showMessage: true); + return baseModel.success; + } + + ///确认完成 + static Future confirmComplete(int id) async { + BaseModel baseModel = await NetUtil().get( + SAASAPI.workOrder.confirmCompletion, + params: {'workOrderId': id}, + showMessage: true); + return baseModel.success; + } + + ///评价 + static Future evaluate({ + required int workOrderId, + required int star, + required String evaluation, + }) async { + var base = await NetUtil().get(SAASAPI.workOrder.evaluate, + params: { + 'workOrderId': workOrderId, + 'evaluateLevel': star, + 'evaluateContent': evaluation + }, + showMessage: true); + return base.success; + } + + ///取消 + static Future cancel({ + required int workOrderId, + }) async { + var base = await NetUtil().get(SAASAPI.workOrder.cancel, + params: { + 'workOrderId': workOrderId, + }, + showMessage: true); + return base.success; + } + + ///账单 + static Future> getBill({ + required int workOrderId, + }) async { + var models = []; + var base = await NetUtil().get(SAASAPI.workOrder.cancel, params: { + 'workOrderId': workOrderId, + }); + if (base.success) { + models = (base.data as List) + .map((e) => WorkOrderBillModel.fromJson(e)) + .toList(); + } + return models; + } +} diff --git a/lib/ui/function_and_service/work_order/work_order_map.dart b/lib/ui/function_and_service/work_order/work_order_map.dart index 082e04d9..fdbc4cb8 100644 --- a/lib/ui/function_and_service/work_order/work_order_map.dart +++ b/lib/ui/function_and_service/work_order/work_order_map.dart @@ -2,4 +2,27 @@ class WorkOrderMap { static Map orderType = { 1: '报事报修', }; + static Map orderStatus = { + 1: '待分配', + 2: '工单池', + 3: '已接单', + 4: '处理中', + 5: '待确认', + 6: '待支付', + 7: '已完成', + 8: '已评价', + 9: '已取消', + }; + + static Map subStatusString = { + 1: '请及时前往现场与业主进行确认、检查', + 2: '请及时前往现场与业主进行确认、检查', + 3: '请及时前往现场与业主进行确认、检查', + 4: '进行过程中,记得提交报告哦', + 5: '如果申请人长时间未确认,请让物业尝试联系对方', + 6: '如果申请人长时间未支付,请让物业尝试联系对方', + 7: '用户已支付工单费用', + 8: '用户已对您的表现进行评价', + 9: '任务已拒绝,中止工单进行' + }; } diff --git a/lib/ui/function_and_service/work_order/work_order_page.dart b/lib/ui/function_and_service/work_order/work_order_page.dart index fb277199..7787ea5a 100644 --- a/lib/ui/function_and_service/work_order/work_order_page.dart +++ b/lib/ui/function_and_service/work_order/work_order_page.dart @@ -1,5 +1,8 @@ -import 'package:aku_new_community/ui/function_and_service/work_order/publish_work_order_page.dart'; +import 'package:aku_new_community/constants/saas_api.dart'; +import 'package:aku_new_community/models/work_order/work_order_list_model.dart'; +import 'package:aku_new_community/ui/function_and_service/work_order/history_report_page.dart'; import 'package:aku_new_community/ui/function_and_service/work_order/work_order_card.dart'; +import 'package:aku_new_community/utils/network/net_util.dart'; import 'package:aku_new_community/widget/bee_scaffold.dart'; import 'package:aku_new_community/widget/tab_bar/bee_tab_bar.dart'; import 'package:flutter/cupertino.dart'; @@ -20,6 +23,10 @@ class _WorkOrderPageState extends State with SingleTickerProviderStateMixin { List _tabs = ['全部', '待分配', '已接单', '处理中', '待确认']; late TabController _tabController; + EasyRefreshController _refreshController = EasyRefreshController(); + int _page = 1; + int _size = 10; + List _models = []; @override void initState() { @@ -27,6 +34,13 @@ class _WorkOrderPageState extends State super.initState(); } + @override + void dispose() { + _refreshController.dispose(); + _tabController.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { return BeeScaffold( @@ -34,7 +48,10 @@ class _WorkOrderPageState extends State actions: [ IconButton( onPressed: () { - Get.to(() => PublishWorkOrderPage()); + // Get.to(() => PublishWorkOrderPage()); + Get.to(() => HistoryReportPage( + id: 1, + )); }, icon: Icon( CupertinoIcons.plus_circle, @@ -54,14 +71,43 @@ class _WorkOrderPageState extends State Widget _getOrderView(int index) { return EasyRefresh( + onRefresh: () async { + _page = 1; + var base = await NetUtil().getList(SAASAPI.workOrder.list, params: { + 'pageNum': _page, + 'size': _size, + 'status': 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 + 1, + }); + 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 WorkOrderCard(); + return WorkOrderCard( + model: _models[index], + refresh: _refreshController.callRefresh, + ); }, separatorBuilder: (context, index) { return 24.w.heightBox; }, - itemCount: 1)); + itemCount: _models.length)); } } diff --git a/lib/widget/dotted_line.dart b/lib/widget/dotted_line.dart index fa963456..d2da227d 100644 --- a/lib/widget/dotted_line.dart +++ b/lib/widget/dotted_line.dart @@ -2,14 +2,23 @@ import 'package:flutter/material.dart'; /// 虚线 class DottedLine extends StatelessWidget { + ///虚线高度(横向为高度,纵向为宽度 final double height; final Color color; final Axis direction; + ///虚线宽度 + final double? width; + + ///空白与虚线比例 + final double? proportion; + const DottedLine({ this.height = 1, this.color = Colors.black, this.direction = Axis.horizontal, + this.width, + this.proportion, }); @override @@ -19,9 +28,10 @@ class DottedLine extends StatelessWidget { final boxWidth = direction == Axis.horizontal ? constraints.constrainWidth() : constraints.constrainHeight(); - final dashWidth = 10.0; + final dashWidth = width ?? 10.0; final dashHeight = height; - final dashCount = (boxWidth / (2 * dashWidth)).floor(); + final spaceProportion = proportion == null ? 2.0 : (1 + proportion!); + final dashCount = (boxWidth / (spaceProportion * dashWidth)).floor(); return Flex( children: List.generate(dashCount, (_) { return SizedBox( diff --git a/lib/widget/views/bee_grid_image_view.dart b/lib/widget/views/bee_grid_image_view.dart index a3fb8a77..78b4557f 100644 --- a/lib/widget/views/bee_grid_image_view.dart +++ b/lib/widget/views/bee_grid_image_view.dart @@ -6,11 +6,12 @@ import 'package:flutter/material.dart'; class BeeGridImageView extends StatelessWidget { final List 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 +20,7 @@ class BeeGridImageView extends StatelessWidget { return GridView.builder( padding: padding, gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 3, + crossAxisCount: crossCount!, crossAxisSpacing: 16.w, mainAxisSpacing: 16.w, ),