parent
b5f1320f84
commit
598b0d117d
@ -0,0 +1,37 @@
|
||||
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/src/extensions/num_ext.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.w.heightBox,
|
||||
'确认要取消工单?'.text.size(36.sp).black.bold.isIntrinsic.make(),
|
||||
40.w.heightBox,
|
||||
'确认后,工单会马上取消,\n且服务人员的工作会立即结束'
|
||||
.text
|
||||
.align(TextAlign.center)
|
||||
.size(28.sp)
|
||||
.isIntrinsic
|
||||
.make(),
|
||||
150.w.heightBox,
|
||||
BeeLongButton(onPressed: onCancel, text: '确认提醒')
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
import 'package:aku_new_community_manager/saas_models/work_order/work_order_bill_model.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/utils/extension/list_extension.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:velocity_x/src/extensions/num_ext.dart';
|
||||
import 'package:velocity_x/src/extensions/string_ext.dart';
|
||||
|
||||
class WorkOrderBillDialog extends StatelessWidget {
|
||||
final List<WorkOrderBillModel> models;
|
||||
final VoidCallback onConfirm;
|
||||
|
||||
const WorkOrderBillDialog(
|
||||
{Key? key, required this.models, required this.onConfirm})
|
||||
: 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.w.heightBox,
|
||||
'确认账单'
|
||||
.text
|
||||
.size(32.sp)
|
||||
.isIntrinsic
|
||||
.color(Colors.black.withOpacity(0.65))
|
||||
.make(),
|
||||
80.w.heightBox,
|
||||
...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()
|
||||
.sepWidget(
|
||||
separate: 16.w.heightBox,
|
||||
),
|
||||
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.w.heightBox,
|
||||
BeeLongButton(onPressed: onConfirm, text: '提醒用户支付'),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,128 @@
|
||||
import 'package:aku_new_community_manager/saas_models/work_order/work_order_progress_model.dart';
|
||||
import 'package:aku_new_community_manager/ui/widgets/common/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<WorkOrderProgressModel> 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.w.widthBox,
|
||||
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.w.heightBox,
|
||||
Container(
|
||||
width: 4.w,
|
||||
height: 55.w,
|
||||
color: index == 0
|
||||
? Color(0xFFFAC058)
|
||||
: Colors.black.withOpacity(0.25),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
16.w.widthBox,
|
||||
DateUtil.formatDateStr(model.createDate, format: 'HH:mm')
|
||||
.text
|
||||
.size(28.sp)
|
||||
.color(Colors.black.withOpacity(0.85))
|
||||
.make(),
|
||||
32.w.widthBox,
|
||||
'${model.content}'
|
||||
.text
|
||||
.size(28.sp)
|
||||
.color(index == 0
|
||||
? Color(0xFFFAC058)
|
||||
: Colors.black.withOpacity(0.65))
|
||||
.make()
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
import 'package:aku_new_community_manager/ui/widgets/common/aku_scaffold.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class FinishReportPage extends StatefulWidget {
|
||||
const FinishReportPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_FinishReportPageState createState() => _FinishReportPageState();
|
||||
}
|
||||
|
||||
class _FinishReportPageState extends State<FinishReportPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AkuScaffold(
|
||||
title: '完成报告',
|
||||
body: ListView(
|
||||
children: [],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,282 @@
|
||||
import 'package:aku_new_community_manager/const/saas_api.dart';
|
||||
import 'package:aku_new_community_manager/saas_models/work_order/work_order_report_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/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/dotted_line.dart';
|
||||
import 'package:aku_new_community_manager/utils/extension/list_extension.dart';
|
||||
import 'package:aku_new_community_manager/utils/network/net_util.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/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<HistoryReportPage> {
|
||||
List<WorkOrderReportModel> _models = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AkuScaffold(
|
||||
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(() {});
|
||||
}
|
||||
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<LineCard> {
|
||||
double _height = 0;
|
||||
|
||||
double get total {
|
||||
double sum = 0;
|
||||
for (var item in widget.model.reportRecordVoList) {
|
||||
sum = sum + item.price;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
@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.w.widthBox,
|
||||
Expanded(
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
'${widget.model.type == 1 ? '工单报告' : '完结报告'}'
|
||||
.text
|
||||
.size(28.sp)
|
||||
.color(Colors.black.withOpacity(0.85))
|
||||
.make(),
|
||||
16.w.widthBox,
|
||||
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.w.widthBox,
|
||||
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.w.heightBox,
|
||||
BeeGridImageView(
|
||||
urls: widget.model.imgList.map((e) => e.url).toList()),
|
||||
],
|
||||
),
|
||||
),
|
||||
Offstage(
|
||||
offstage: widget.model.reportRecordVoList.isEmpty,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
24.w.heightBox,
|
||||
...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()
|
||||
.sepWidget(
|
||||
separate: 16.w.heightBox,
|
||||
),
|
||||
24.w.heightBox,
|
||||
BeeDivider.horizontal(),
|
||||
24.w.heightBox,
|
||||
Row(
|
||||
children: [
|
||||
'工单总费用'
|
||||
.text
|
||||
.size(28.sp)
|
||||
.color(Colors.black.withOpacity(0.65))
|
||||
.make(),
|
||||
Spacer(),
|
||||
'¥${total}'
|
||||
.text
|
||||
.size(28.sp)
|
||||
.color(Color(0xFFF5222D))
|
||||
.make(),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,156 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:aku_new_community_manager/const/saas_api.dart';
|
||||
import 'package:aku_new_community_manager/new_ui/work_order/work_order_func.dart';
|
||||
import 'package:aku_new_community_manager/ui/widgets/app_widgets/bee_pick_image_widget.dart';
|
||||
import 'package:aku_new_community_manager/ui/widgets/common/aku_scaffold.dart';
|
||||
import 'package:aku_new_community_manager/ui/widgets/common/bee_long_button.dart';
|
||||
import 'package:aku_new_community_manager/utils/network/net_util.dart';
|
||||
import 'package:bot_toast/bot_toast.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get_core/src/get_main.dart';
|
||||
import 'package:get/get_navigation/src/extension_navigation.dart';
|
||||
import 'package:velocity_x/src/extensions/num_ext.dart';
|
||||
import 'package:velocity_x/src/extensions/string_ext.dart';
|
||||
|
||||
class ReportProgress extends StatefulWidget {
|
||||
final int id;
|
||||
|
||||
const ReportProgress({Key? key, required this.id}) : super(key: key);
|
||||
|
||||
@override
|
||||
_ReportProgressState createState() => _ReportProgressState();
|
||||
}
|
||||
|
||||
class _ReportProgressState extends State<ReportProgress> {
|
||||
TextEditingController _textEditingController = TextEditingController();
|
||||
List<File> _photos = [];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AkuScaffold(
|
||||
title: '工单报告',
|
||||
body: ListView(
|
||||
children: [
|
||||
24.w.heightBox,
|
||||
Container(
|
||||
padding: EdgeInsets.all(32.w),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white, borderRadius: BorderRadius.circular(16.w)),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
'具体需求'
|
||||
.text
|
||||
.size(28.sp)
|
||||
.color(Colors.black.withOpacity(0.45))
|
||||
.make(),
|
||||
],
|
||||
),
|
||||
32.w.heightBox,
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.symmetric(horizontal: 24.w),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.black.withOpacity(0.06),
|
||||
borderRadius: BorderRadius.circular(16.w)),
|
||||
child: TextField(
|
||||
controller: _textEditingController,
|
||||
autofocus: false,
|
||||
onChanged: (text) => setState(() {}),
|
||||
minLines: 5,
|
||||
maxLength: 200,
|
||||
maxLines: 20,
|
||||
decoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
),
|
||||
),
|
||||
),
|
||||
32.w.heightBox,
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.symmetric(horizontal: 24.w),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.black.withOpacity(0.06),
|
||||
borderRadius: BorderRadius.circular(16.w)),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
'上传图片'
|
||||
.text
|
||||
.size(28.sp)
|
||||
.color(Colors.black.withOpacity(0.45))
|
||||
.make(),
|
||||
Spacer(),
|
||||
'建议上传图片不超过6张'
|
||||
.text
|
||||
.size(24.sp)
|
||||
.color(Colors.black.withOpacity(0.25))
|
||||
.make(),
|
||||
],
|
||||
),
|
||||
24.w.heightBox,
|
||||
BeePickImageWidget(
|
||||
maxCount: 6,
|
||||
onChanged: (value) {
|
||||
_photos = value;
|
||||
}),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
bottom: Padding(
|
||||
padding: EdgeInsets.only(
|
||||
left: 32.w,
|
||||
right: 32.w,
|
||||
bottom: MediaQuery.of(context).padding.bottom + 32.w),
|
||||
child: BeeLongButton(
|
||||
onPressed: () async {
|
||||
if (!canTap) {
|
||||
return;
|
||||
}
|
||||
var cancel = BotToast.showLoading();
|
||||
var imgUrls = <String>[];
|
||||
try {
|
||||
imgUrls = await NetUtil()
|
||||
.uploadFiles(_photos, SAASAPI.other.file.uploadImg);
|
||||
} catch (e) {
|
||||
print(e.toString());
|
||||
}
|
||||
try {
|
||||
var re = await WorkOrderFuc.reportProgress(
|
||||
content: _textEditingController.text,
|
||||
imgUrls: imgUrls,
|
||||
workOrderId: widget.id);
|
||||
if (re) {
|
||||
Get.back();
|
||||
}
|
||||
} catch (e) {
|
||||
print(e.toString());
|
||||
}
|
||||
cancel();
|
||||
},
|
||||
text: '确认发布'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
bool get canTap {
|
||||
if (_textEditingController.text.isEmpty) {
|
||||
BotToast.showText(text: '请输入具体需求');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -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<String, dynamic> json) =>
|
||||
_$WorkOrderBillModelFromJson(json);
|
||||
|
||||
const WorkOrderBillModel({
|
||||
required this.id,
|
||||
required this.costType,
|
||||
required this.name,
|
||||
required this.number,
|
||||
required this.price,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
id,
|
||||
costType,
|
||||
name,
|
||||
number,
|
||||
price,
|
||||
];
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'work_order_bill_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
WorkOrderBillModel _$WorkOrderBillModelFromJson(Map<String, dynamic> 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,
|
||||
);
|
@ -0,0 +1,19 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'work_order_progress_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
WorkOrderProgressModel _$WorkOrderProgressModelFromJson(
|
||||
Map<String, dynamic> 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,
|
||||
);
|
@ -0,0 +1,81 @@
|
||||
import 'dart:core';
|
||||
|
||||
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_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<ImgModel> imgList;
|
||||
final List<ReportRecordVoList> reportRecordVoList;
|
||||
|
||||
factory WorkOrderReportModel.fromJson(Map<String, dynamic> 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<Object?> 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<String, dynamic> json) =>
|
||||
_$ReportRecordVoListFromJson(json);
|
||||
|
||||
const ReportRecordVoList({
|
||||
required this.id,
|
||||
required this.costType,
|
||||
required this.name,
|
||||
required this.number,
|
||||
required this.price,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
id,
|
||||
costType,
|
||||
name,
|
||||
number,
|
||||
price,
|
||||
];
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'work_order_report_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
WorkOrderReportModel _$WorkOrderReportModelFromJson(
|
||||
Map<String, dynamic> 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<dynamic>)
|
||||
.map((e) => ImgModel.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
reportRecordVoList: (json['reportRecordVoList'] as List<dynamic>)
|
||||
.map((e) => ReportRecordVoList.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
);
|
||||
|
||||
ReportRecordVoList _$ReportRecordVoListFromJson(Map<String, dynamic> 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,
|
||||
);
|
@ -1,113 +0,0 @@
|
||||
// Dart imports:
|
||||
import 'dart:io';
|
||||
|
||||
// Flutter imports:
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
// Package imports:
|
||||
import 'package:dotted_border/dotted_border.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:velocity_x/velocity_x.dart';
|
||||
|
||||
// Project imports:
|
||||
import 'package:aku_new_community_manager/const/resource.dart';
|
||||
import 'package:aku_new_community_manager/style/app_style.dart';
|
||||
import 'package:aku_new_community_manager/ui/widgets/inner/pick_image.dart';
|
||||
import 'package:aku_new_community_manager/utils/extension/list_extension.dart';
|
||||
|
||||
class AkuPickImageWidget extends StatefulWidget {
|
||||
final double? size;
|
||||
final Function(List<File> files) onChanged;
|
||||
final String description;
|
||||
AkuPickImageWidget(
|
||||
{Key? key, this.size, required this.onChanged, this.description = '上传照片'})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
_AkuPickImageWidgetState createState() => _AkuPickImageWidgetState();
|
||||
}
|
||||
|
||||
class _AkuPickImageWidgetState extends State<AkuPickImageWidget> {
|
||||
List<File> _files = [];
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
children: [
|
||||
..._files.map((e) => showImage(e)).toList(),
|
||||
GestureDetector(
|
||||
onTap: () async {
|
||||
await akuPickImage().then(
|
||||
(value) => _files.add(
|
||||
File(value!.path),
|
||||
),
|
||||
);
|
||||
widget.onChanged(_files);
|
||||
setState(() {});
|
||||
},
|
||||
child: DottedBorder(
|
||||
color: Color(0xFF999999),
|
||||
borderType: BorderType.RRect,
|
||||
strokeWidth: 2.w,
|
||||
dashPattern: [6, 3],
|
||||
radius: Radius.circular(8.w),
|
||||
child: Container(
|
||||
width: widget.size ?? 160.w,
|
||||
height: widget.size ?? 160.w,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Image.asset(
|
||||
R.ASSETS_MANAGE_IC_IMAGE_PNG,
|
||||
width: 60.w,
|
||||
height: 60.w,
|
||||
color: Color(0xFF999999),
|
||||
),
|
||||
4.w.heightBox,
|
||||
widget.description.text
|
||||
.color(kTextSubColor)
|
||||
.size(22.sp)
|
||||
.bold
|
||||
.make(),
|
||||
],
|
||||
),
|
||||
),
|
||||
).material(color: Colors.transparent),
|
||||
)
|
||||
].sepWidget(separate: 10.w.widthBox),
|
||||
);
|
||||
}
|
||||
|
||||
Widget showImage(File file) {
|
||||
return Stack(children: [
|
||||
Container(
|
||||
width: widget.size ?? 160.w,
|
||||
height: widget.size ?? 160.w,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8.w), color: kBackgroundColor),
|
||||
child: Image.file(file),
|
||||
),
|
||||
Positioned(
|
||||
top: 8.w,
|
||||
right: 8.w,
|
||||
child: Container(
|
||||
width: 40.w,
|
||||
height: 40.w,
|
||||
child: Icon(
|
||||
CupertinoIcons.xmark,
|
||||
size: 20.w,
|
||||
color: Colors.white,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(20.w),
|
||||
color: Color(0xFF000000),
|
||||
),
|
||||
).onTap(() {
|
||||
_files.remove(file);
|
||||
setState(() {});
|
||||
}),
|
||||
)
|
||||
]);
|
||||
}
|
||||
}
|
@ -0,0 +1,135 @@
|
||||
// Dart imports:
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:aku_new_community_manager/gen/assets.gen.dart';
|
||||
import 'package:aku_new_community_manager/ui/widgets/inner/bee_image_pick.dart';
|
||||
import 'package:aku_new_community_manager/ui/widgets/inner/bee_image_preview.dart';
|
||||
// Package imports:
|
||||
import 'package:dotted_border/dotted_border.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:velocity_x/velocity_x.dart';
|
||||
|
||||
class BeePickImageWidget extends StatefulWidget {
|
||||
final double? size;
|
||||
final Function(List<File> files) onChanged;
|
||||
final String description;
|
||||
final int? maxCount;
|
||||
BeePickImageWidget(
|
||||
{Key? key,
|
||||
this.size,
|
||||
required this.onChanged,
|
||||
this.description = '上传照片',
|
||||
this.maxCount})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
_BeePickImageWidgetState createState() => _BeePickImageWidgetState();
|
||||
}
|
||||
|
||||
class _BeePickImageWidgetState extends State<BeePickImageWidget> {
|
||||
List<File> _files = [];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Wrap(
|
||||
crossAxisAlignment: WrapCrossAlignment.start,
|
||||
alignment: WrapAlignment.start,
|
||||
spacing: 10.w,
|
||||
runSpacing: 10.w,
|
||||
children: [
|
||||
..._files.map((e) => showImage(e)).toList(),
|
||||
Offstage(
|
||||
offstage:
|
||||
widget.maxCount != null && _files.length >= widget.maxCount!,
|
||||
child: GestureDetector(
|
||||
onTap: () async {
|
||||
await BeeImagePicker.pick(title: '选择图片').then(
|
||||
(value) {
|
||||
if (value != null) {
|
||||
_files.add(
|
||||
File(value.path),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
widget.onChanged(_files);
|
||||
setState(() {});
|
||||
},
|
||||
child: DottedBorder(
|
||||
color: Colors.black.withOpacity(0.25),
|
||||
borderType: BorderType.RRect,
|
||||
strokeWidth: 2.w,
|
||||
dashPattern: [6, 3],
|
||||
radius: Radius.circular(8.w),
|
||||
child: Container(
|
||||
width: widget.size ?? 160.w,
|
||||
height: widget.size ?? 160.w,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Image.asset(
|
||||
Assets.icons.camera.path,
|
||||
width: 60.w,
|
||||
height: 60.w,
|
||||
color: Color(0xFF999999),
|
||||
),
|
||||
4.w.heightBox,
|
||||
widget.description.text
|
||||
.color(Colors.black.withOpacity(0.45))
|
||||
.size(22.sp)
|
||||
.make(),
|
||||
],
|
||||
),
|
||||
),
|
||||
).material(color: Colors.transparent),
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget showImage(File file) {
|
||||
return Stack(children: [
|
||||
GestureDetector(
|
||||
onTap: () async {
|
||||
await BeeImagePreview.toFile(file: file);
|
||||
},
|
||||
child: Container(
|
||||
width: widget.size ?? 160.w,
|
||||
height: widget.size ?? 160.w,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8.w),
|
||||
color: Colors.black.withOpacity(0.03)),
|
||||
child: Image.file(
|
||||
file,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
top: 0.w,
|
||||
right: 0.w,
|
||||
child: Container(
|
||||
width: 40.w,
|
||||
height: 40.w,
|
||||
child: Icon(
|
||||
CupertinoIcons.xmark,
|
||||
size: 20.w,
|
||||
color: Colors.white,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(20.w),
|
||||
color: Color(0xFF000000),
|
||||
),
|
||||
).onTap(() {
|
||||
_files.remove(file);
|
||||
widget.onChanged(_files);
|
||||
setState(() {});
|
||||
}),
|
||||
)
|
||||
]);
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:velocity_x/velocity_x.dart';
|
||||
|
||||
class BeeImagePicker {
|
||||
static Future<File?> pick(
|
||||
{required String title,
|
||||
double maxWidth = 1000,
|
||||
double maxHeight = 1000}) async {
|
||||
PickedFile? file = await Get.bottomSheet(CupertinoActionSheet(
|
||||
title: title.text.isIntrinsic.make(),
|
||||
actions: [
|
||||
CupertinoDialogAction(
|
||||
onPressed: () async => Get.back(
|
||||
result: await ImagePicker().getImage(
|
||||
source: ImageSource.gallery,
|
||||
maxHeight: maxHeight,
|
||||
maxWidth: maxWidth,
|
||||
),
|
||||
),
|
||||
child: [
|
||||
Icon(CupertinoIcons.photo),
|
||||
30.w.widthBox,
|
||||
'相册'.text.isIntrinsic.make(),
|
||||
].row(),
|
||||
),
|
||||
CupertinoDialogAction(
|
||||
onPressed: () async => Get.back(
|
||||
result: await ImagePicker().getImage(
|
||||
source: ImageSource.camera,
|
||||
maxHeight: maxHeight,
|
||||
maxWidth: maxWidth,
|
||||
),
|
||||
),
|
||||
child: [
|
||||
Icon(CupertinoIcons.camera),
|
||||
30.w.widthBox,
|
||||
'相机'.text.isIntrinsic.make(),
|
||||
].row(),
|
||||
),
|
||||
],
|
||||
cancelButton: CupertinoDialogAction(
|
||||
onPressed: Get.back,
|
||||
child: '取消'.text.isIntrinsic.make(),
|
||||
),
|
||||
));
|
||||
if (file != null)
|
||||
return File(file.path);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
// Dart imports:
|
||||
import 'dart:io';
|
||||
|
||||
// Flutter imports:
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
// Package imports:
|
||||
import 'package:get/get.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
|
||||
Future<File?> akuPickImage() async {
|
||||
return await showCupertinoModalPopup(
|
||||
context: Get.context!,
|
||||
builder: (context) {
|
||||
return CupertinoActionSheet(
|
||||
title: Text('选择图片'),
|
||||
actions: [
|
||||
CupertinoActionSheetAction(
|
||||
onPressed: () {
|
||||
ImagePicker()
|
||||
.getImage(
|
||||
source: ImageSource.camera,
|
||||
maxHeight: 600,
|
||||
maxWidth: 600,
|
||||
)
|
||||
.then((file) {
|
||||
Get.back(result: File(file!.path));
|
||||
});
|
||||
},
|
||||
child: Text('拍照'),
|
||||
),
|
||||
CupertinoActionSheetAction(
|
||||
onPressed: () {
|
||||
ImagePicker()
|
||||
.getImage(
|
||||
source: ImageSource.gallery,
|
||||
maxHeight: 600,
|
||||
maxWidth: 600,
|
||||
)
|
||||
.then((file) {
|
||||
Get.back(result: File(file!.path));
|
||||
});
|
||||
},
|
||||
child: Text('相册'),
|
||||
),
|
||||
],
|
||||
cancelButton: CupertinoButton(
|
||||
child: Text('取消'),
|
||||
onPressed: () => Get.back(),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
Loading…
Reference in new issue