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