Files
tuiche/lib/pages/mh_page/apply_repair_page.dart
2025-08-01 22:25:47 +08:00

1970 lines
133 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'package:ef/ef.dart';
import 'package:flutter/material.dart';
import 'package:flutterflow_ui/flutterflow_ui.dart';
import 'package:vbvs_app/common/color/ServiceConstant.dart';
import 'package:vbvs_app/common/color/appConstants.dart';
import 'package:vbvs_app/common/color/appFontsize.dart';
import 'package:vbvs_app/common/color/app_uri_status.dart';
import 'package:vbvs_app/common/util/FitTool.dart';
import 'package:vbvs_app/common/util/MyUtils.dart';
import 'package:vbvs_app/common/util/requestWithLog.dart';
import 'package:vbvs_app/component/img/img_default_widget.dart';
import 'package:vbvs_app/component/img/img_preview_widget.dart';
import 'package:vbvs_app/component/tool/CustomCard.dart';
import 'package:vbvs_app/component/tool/TopSlideNotification.dart';
import 'package:vbvs_app/controller/mh_controller/apply_repair_controller.dart';
import 'package:vbvs_app/controller/mh_controller/repair_list_controller.dart';
import 'package:vbvs_app/controller/repair/repair_controller.dart';
import 'package:vbvs_app/model/api_response.dart';
import 'package:vbvs_app/pages/mh_page/applyRepair/apply_repair_success.dart';
class ApplyRepairPage extends GetView<ApplyRepairController> {
final scaffoldKey = GlobalKey<ScaffoldState>();
BoxConstraints? bodysize;
RepairListController repairListController = Get.find();
ApplyRepairController applyRepairController = Get.find();
ApplyRepairPage() {
controller.attr.value.listenlists.clear();
controller.getDeviceList();
controller.model.device_type = null;
controller.model.select_device = "";
controller.model.device_category = "";
controller.model.device_name = "";
controller.model.device_id = "";
}
final List<GlobalKey> repairItemKeys = [];
final GlobalKey contactKey = GlobalKey();
final GlobalKey phoneKey = GlobalKey();
@override
Widget build(BuildContext context) {
var tmpcontroller =
FormFieldController<String>(controller.model.select_device);
// List<String> deviceTypeNames = ['床', '床垫'];
// List<String> deviceTypeIds = ['床', '床垫'];
return LayoutBuilder(builder: (context, cc) {
bodysize = cc;
return GestureDetector(
// onTap: () => FocusScope.of(context).unfocus(),,
child: Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/new_background.png'), // 本地图片
fit: BoxFit.fill, // 填满整个 Container
),
),
child: Scaffold(
resizeToAvoidBottomInset: true, // 自动调整页面避免被键盘遮挡
backgroundColor: Colors.transparent,
appBar: AppBar(
backgroundColor: Colors.transparent,
iconTheme: const IconThemeData(color: Colors.white),
automaticallyImplyLeading: false,
titleSpacing: 0,
title: SizedBox(
width: double.infinity,
height: 180.rpx,
child: Stack(
alignment: Alignment.center,
children: [
// 中间居中的标题
Text(
'申请报修'.tr,
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 30.rpx,
),
),
// 左侧图标
Positioned(
left: 0.rpx,
child: returnIconButtomNew(),
),
],
),
),
centerTitle: false,
),
body: Container(
width: bodysize!.maxWidth,
height: bodysize!.maxHeight * 1,
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
// TitleComponentWidget(
// titleName: '申请保修',
// ),
Flexible(
child: Padding(
padding: EdgeInsetsDirectional.fromSTEB(
30.rpx, 0, 30.rpx, 30.rpx),
child: Container(
width: bodysize!.maxWidth,
height: 1000,
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
Padding(
padding: EdgeInsetsDirectional.fromSTEB(
0, 27.rpx, 0, 0),
child: Container(
width: MediaQuery.sizeOf(context).width,
height:
MediaQuery.sizeOf(context).height * 0.247,
constraints: BoxConstraints(
minHeight: 500.rpx,
maxHeight: 500.rpx,
),
decoration: BoxDecoration(
color: const Color(0XFF003058),
borderRadius: BorderRadius.circular(16.rpx),
),
child: Padding(
padding: EdgeInsetsDirectional.fromSTEB(
25.rpx, 27.rpx, 34.rpx, 0),
child: Container(
width: 100,
height: 100,
child: Container(
width: 100,
height: 100,
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
Align(
alignment:
const AlignmentDirectional(
0, 0),
child: Container(
width: MediaQuery.sizeOf(context)
.width,
height: 44,
child: Align(
alignment:
const AlignmentDirectional(
0, -1),
child: Text(
'选择需要报修的设备'.tr,
style: TextStyle(
fontFamily: 'Readex Pro',
letterSpacing: 0,
fontSize: AppFontsize
.title_size,
color:
Colors.white // 加粗文字
),
),
),
),
),
Expanded(
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
Flexible(
child: Container(
width: MediaQuery.sizeOf(
context)
.width,
height: 10,
constraints: BoxConstraints(
minHeight: 60.rpx,
),
child: Row(
mainAxisSize:
MainAxisSize.max,
children: [
Container(
width: 105.rpx,
height:
MediaQuery.sizeOf(
context)
.height *
0.038,
constraints:
const BoxConstraints(
minWidth: 60,
),
child: Align(
alignment:
const AlignmentDirectional(
-1, 0),
child: Text(
'已绑设备'.tr,
style: TextStyle(
fontFamily:
'Readex Pro',
fontSize:
26.rpx,
letterSpacing:
0,
height: 1,
color: Colors
.white),
),
),
),
Expanded(
child: Container(
width:
300, // 可以根据需要调整宽度
height:
56, // 可以根据需要调整高度
decoration:
BoxDecoration(
borderRadius:
BorderRadius
.circular(
8),
color: Colors
.white,
),
child: Obx(() {
final isDeviceListEmpty = controller
.model
.device_list
?.isEmpty ??
true;
List<Map<String, String>>
deviceOptions =
controller
.model
.device_list!
.map((device) =>
{
'mac'.tr: device['mac'.tr].toString(),
'name': device['name'].toString(),
'type': device['device_type'].toString()
})
.toList();
List<String>
deviceNames =
controller
.model
.device_list!
.map(
(device) {
final mac =
device['mac'.tr]?.toString() ??
'';
final name =
device['name']?.toString() ??
'';
final type =
getDeviceTypeName(
int.tryParse('${device['device_type']}'));
return name
.isNotEmpty
? '$name-MAC$mac'
: '$type-MAC$mac';
}).toList();
List<String>
deviceMacs =
deviceOptions
.map((device) =>
device['mac'.tr]!)
.toList();
return AbsorbPointer(
absorbing:
isDeviceListEmpty, // 禁止点击
child: FlutterFlowDropDown<
String>(
controller:
tmpcontroller,
fillColor: isDeviceListEmpty
? Colors.grey[
300]!
: Colors
.white,
options: isDeviceListEmpty
? []
: deviceMacs,
optionLabels:
isDeviceListEmpty
? []
: deviceNames,
onChanged:
(val) {
var selectedDevice = controller
.model
.device_list!
.firstWhere((device) =>
device['mac'.tr].toString() ==
val);
final mac =
selectedDevice['mac'.tr]?.toString() ??
'未知MAC'.tr;
final name =
selectedDevice['name']?.toString();
final type =
int.tryParse('${selectedDevice['device_type']}');
final typeName =
getDeviceTypeName(type);
controller
.model
.select_device = mac;
controller
.model
.device_type = selectedDevice['device_type'];
controller
.model
.device_category = '未知型号'.tr;
controller
.model
.device_name = (name != null &&
name.isNotEmpty)
? name
: '$typeName-MAC$mac';
controller
.model
.device_id = mac;
controller
.updateAll();
},
width:
300,
height:
56,
textStyle:
TextStyle(
fontFamily:
'Readex Pro',
color: isDeviceListEmpty
? Colors.grey
: Colors.black,
fontSize:
26.rpx,
letterSpacing:
0,
),
hintText: isDeviceListEmpty
? '暂无可选设备'
.tr
: '请选择绑定设备'
.tr,
searchHintText:
'查找'.tr,
icon:
Icon(
Icons
.keyboard_arrow_down_rounded,
color: isDeviceListEmpty
? Colors.grey
: Colors.black,
size:
24,
),
elevation:
2,
borderColor:
Colors
.white,
borderWidth:
0,
borderRadius:
8,
margin: EdgeInsetsDirectional.fromSTEB(
20.rpx,
8.rpx,
20.rpx,
4.rpx),
hidesUnderline:
true,
isOverButton:
false,
isSearchable:
false,
isMultiSelect:
false,
),
);
}))),
].divide(SizedBox(
width: 26.rpx)),
),
),
),
Flexible(
child: Container(
width: MediaQuery.sizeOf(
context)
.width,
height: 10,
constraints: BoxConstraints(
minHeight: 60.rpx,
),
child: Row(
mainAxisSize:
MainAxisSize.max,
children: [
Container(
width: 105.rpx,
height:
MediaQuery.sizeOf(
context)
.height *
0.038,
constraints:
BoxConstraints(
minWidth: 60,
),
child: Align(
alignment:
const AlignmentDirectional(
-1, 0),
child: Text(
'设备系列'.tr,
maxLines: 2,
style: TextStyle(
fontFamily:
'Readex Pro',
fontSize:
26.rpx,
letterSpacing:
0,
height: 1,
color: Colors
.white),
),
),
),
Expanded(
child: Container(
decoration:
BoxDecoration(
color:
Colors.white,
borderRadius:
BorderRadius
.circular(
8),
),
width:
double.infinity,
child: Padding(
padding:
EdgeInsetsDirectional
.fromSTEB(
20.rpx,
0,
35.rpx,
0),
child: Row(
mainAxisSize:
MainAxisSize
.max,
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
Expanded(
child:
Container(
child:
Align(
alignment: AlignmentDirectional(
-1,
0),
child:
TextFormField(
onChanged:
(value) {
controller.model.device_series =
value;
},
autofocus:
false,
obscureText:
false,
decoration:
InputDecoration(
contentPadding:
EdgeInsets.all(0),
isDense:
false,
labelStyle:
TextStyle(
fontFamily: 'Inter',
fontSize: 26.rpx,
letterSpacing: 0.0,
),
hintStyle:
TextStyle(
fontFamily: 'Inter',
fontSize: 26.rpx,
letterSpacing: 0.0,
color: themeController.currentColor.sc4,
),
enabledBorder:
OutlineInputBorder(
borderSide: BorderSide(
color: Color(0x00000000),
width: 1.rpx,
),
borderRadius: BorderRadius.circular(8.rpx),
),
focusedBorder:
OutlineInputBorder(
borderSide: BorderSide(
color: Color(0x00000000),
width: 1.rpx,
),
borderRadius: BorderRadius.circular(8.rpx),
),
errorBorder:
OutlineInputBorder(
borderSide: BorderSide(
color: Colors.red,
width: 1.rpx,
),
borderRadius: BorderRadius.circular(8.rpx),
),
focusedErrorBorder:
OutlineInputBorder(
borderSide: BorderSide(
color: Colors.red,
width: 1.rpx,
),
borderRadius: BorderRadius.circular(8.rpx),
),
filled:
false,
fillColor:
Colors.white,
),
style:
TextStyle(
fontFamily:
'Readex Pro',
letterSpacing:
0,
color:
Colors.black,
fontSize:
26.rpx,
),
// cursorColor:
// Colors.black,
// validator: _model
// .textControllerValidator
// .asValidator(context),
),
),
),
),
],
),
),
),
),
].divide(SizedBox(
width: 26.rpx)),
),
),
),
Flexible(
child: Container(
width: MediaQuery.sizeOf(
context)
.width,
height: 10,
constraints: BoxConstraints(
minHeight: 60.rpx,
),
child: Row(
mainAxisSize:
MainAxisSize.max,
children: [
Container(
width: 105.rpx,
height:
MediaQuery.sizeOf(
context)
.height *
0.038,
constraints:
BoxConstraints(
minWidth: 60,
),
child: Align(
alignment:
const AlignmentDirectional(
-1, 0),
child: Text(
'产品型号'.tr,
style: TextStyle(
fontFamily:
'Readex Pro',
fontSize:
26.rpx,
letterSpacing:
0,
height: 1,
color: Colors
.white),
),
),
),
Expanded(
child: Container(
decoration:
BoxDecoration(
color:
Colors.white,
borderRadius:
BorderRadius
.circular(
8),
),
width:
double.infinity,
child: Padding(
padding:
EdgeInsetsDirectional
.fromSTEB(
20.rpx,
0,
35.rpx,
0),
child: Row(
mainAxisSize:
MainAxisSize
.max,
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
Expanded(
child:
Container(
child:
Align(
alignment: AlignmentDirectional(
-1,
0),
child:
TextFormField(
onChanged:
(value) {
controller.model.device_category =
value;
},
autofocus:
false,
obscureText:
false,
decoration:
InputDecoration(
contentPadding:
EdgeInsets.all(0),
isDense:
false,
labelStyle:
TextStyle(
fontFamily: 'Inter',
fontSize: 26.rpx,
letterSpacing: 0.0,
),
hintStyle:
TextStyle(
fontFamily: 'Inter',
fontSize: 26.rpx,
letterSpacing: 0.0,
color: themeController.currentColor.sc4,
),
enabledBorder:
OutlineInputBorder(
borderSide: BorderSide(
color: Color(0x00000000),
width: 1.rpx,
),
borderRadius: BorderRadius.circular(8.rpx),
),
focusedBorder:
OutlineInputBorder(
borderSide: BorderSide(
color: Color(0x00000000),
width: 1.rpx,
),
borderRadius: BorderRadius.circular(8.rpx),
),
errorBorder:
OutlineInputBorder(
borderSide: BorderSide(
color: Colors.red,
width: 1.rpx,
),
borderRadius: BorderRadius.circular(8.rpx),
),
focusedErrorBorder:
OutlineInputBorder(
borderSide: BorderSide(
color: Colors.red,
width: 1.rpx,
),
borderRadius: BorderRadius.circular(8.rpx),
),
filled:
false,
fillColor:
Colors.white,
),
style:
TextStyle(
fontFamily:
'Readex Pro',
letterSpacing:
0,
color:
Colors.black,
fontSize:
26.rpx,
),
// cursorColor:
// Colors.black,
// validator: _model
// .textControllerValidator
// .asValidator(context),
),
),
),
),
],
),
),
),
),
].divide(SizedBox(
width: 26.rpx)),
),
),
),
Flexible(
child: Container(
width: MediaQuery.sizeOf(
context)
.width,
height: 10,
constraints: BoxConstraints(
minHeight: 60.rpx,
),
child: Row(
mainAxisSize:
MainAxisSize.max,
children: [
Container(
width: 105.rpx,
height:
MediaQuery.sizeOf(
context)
.height *
0.038,
constraints:
BoxConstraints(
minWidth: 60,
minHeight:
60.rpx),
child: Align(
alignment:
const AlignmentDirectional(
-1, 0),
child: Text(
'序列号'.tr,
style: TextStyle(
fontFamily:
'Readex Pro',
fontSize:
26.rpx,
letterSpacing:
0,
height: 1,
color: Colors
.white),
),
),
),
Expanded(
child: Container(
decoration:
BoxDecoration(
color:
Colors.white,
borderRadius:
BorderRadius
.circular(
8),
),
width:
double.infinity,
child: Padding(
padding:
EdgeInsetsDirectional
.fromSTEB(
20.rpx,
0,
35.rpx,
0),
child: Row(
mainAxisSize:
MainAxisSize
.max,
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
Expanded(
child:
Container(
child:
Align(
alignment: AlignmentDirectional(
-1,
0),
child:
TextFormField(
onChanged:
(value) {
controller.model.device_id =
value;
},
autofocus:
false,
obscureText:
false,
decoration:
InputDecoration(
contentPadding:
EdgeInsets.all(0),
isDense:
false,
labelStyle:
TextStyle(
fontFamily: 'Inter',
fontSize: 26.rpx,
letterSpacing: 0.0,
),
hintStyle:
TextStyle(
fontFamily: 'Inter',
fontSize: 26.rpx,
letterSpacing: 0.0,
color: themeController.currentColor.sc4,
),
enabledBorder:
OutlineInputBorder(
borderSide: BorderSide(
color: Color(0x00000000),
width: 1.rpx,
),
borderRadius: BorderRadius.circular(8.rpx),
),
focusedBorder:
OutlineInputBorder(
borderSide: BorderSide(
color: Color(0x00000000),
width: 1.rpx,
),
borderRadius: BorderRadius.circular(8.rpx),
),
errorBorder:
OutlineInputBorder(
borderSide: BorderSide(
color: Colors.red,
width: 1.rpx,
),
borderRadius: BorderRadius.circular(8.rpx),
),
focusedErrorBorder:
OutlineInputBorder(
borderSide: BorderSide(
color: Colors.red,
width: 1.rpx,
),
borderRadius: BorderRadius.circular(8.rpx),
),
filled:
false,
fillColor:
Colors.white,
),
style:
TextStyle(
fontFamily:
'Readex Pro',
letterSpacing:
0,
color:
Colors.black,
fontSize:
26.rpx,
),
// cursorColor:
// Colors.black,
// validator: _model
// .textControllerValidator
// .asValidator(context),
),
),
),
),
],
),
),
),
),
].divide(SizedBox(
width: 26.rpx)),
),
),
),
].divide(
SizedBox(height: 30.rpx)),
),
)
],
),
),
),
),
),
),
Padding(
padding: EdgeInsetsDirectional.fromSTEB(
0, 26.rpx, 0, 0),
child: Container(
width: bodysize!.maxWidth,
height: bodysize!.maxHeight * 0.17,
constraints: BoxConstraints(
minHeight: 345.rpx,
),
decoration: BoxDecoration(
color: const Color(0XFF003058),
borderRadius: BorderRadius.circular(16.rpx),
),
child: Obx(() {
return Container(
width: bodysize!.maxWidth,
height: bodysize!.maxHeight * 0.17,
decoration: BoxDecoration(
color: const Color(0XFF003058),
borderRadius:
BorderRadius.circular(16.rpx),
),
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
if (controller.model.issue_img ==
null ||
controller.model.issue_img!.isEmpty)
Flexible(
child: InkWell(
onTap: () async {
ApiResponse apiResponse =
await applyRepairController
.uploadImg();
if (apiResponse.code ==
HttpStatusCodes.ok) {
} else {
if (controller
.model.issue_img ==
null ||
controller.model.issue_img!
.isEmpty) {
TopSlideNotification.show(
context,
text: apiResponse.msg!,
textColor: apiResponse
.code ==
HttpStatusCodes.ok
? themeController
.currentColor.sc2
: themeController
.currentColor.sc9,
);
}
}
},
child: Container(
width: MediaQuery.sizeOf(context)
.width,
height: MediaQuery.sizeOf(context)
.height *
0.186,
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment:
MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.center,
children: [
Flexible(
child: Align(
alignment:
const AlignmentDirectional(
0, 0),
// child: Icon(
// Icons
// .linked_camera_outlined,
// color:
// Color(0xFF9EA4B7),
// size: 40,
// ),
child: Container(
width: 50,
height: 50,
decoration:
BoxDecoration(
image:
DecorationImage(
fit: BoxFit.cover,
image: Image.asset(
'assets/images/camera.png',
).image,
),
),
),
),
),
Flexible(
child: Container(
width: 300.rpx,
height: 62.rpx,
decoration: BoxDecoration(
borderRadius:
BorderRadius
.circular(50),
border: Border.all(
color: const Color(
0xFF9EA4B7),
),
),
child: Align(
alignment:
const AlignmentDirectional(
0, 0),
child: Text(
'上传设备故障照片'.tr,
style: TextStyle(
fontFamily:
'Readex Pro',
color: const Color(
0xFF9EA4B7),
fontSize: AppFontsize
.normal_text_size,
letterSpacing: 0,
),
),
),
),
),
],
),
),
)),
if (controller.model.issue_img !=
null &&
controller
.model.issue_img!.isNotEmpty)
Flexible(
child: Container(
width: MediaQuery.sizeOf(context)
.width,
height: MediaQuery.sizeOf(context)
.height *
0.186,
constraints: const BoxConstraints(
minHeight: 250,
),
decoration: const BoxDecoration(
color: Colors.white,
),
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
Align(
alignment:
const AlignmentDirectional(
1, 0),
child: Padding(
padding:
const EdgeInsetsDirectional
.fromSTEB(
0, 7, 21, 7),
child: Container(
width:
MediaQuery.sizeOf(
context)
.width *
0.2,
height: 21,
decoration:
const BoxDecoration(
color: Colors.white,
),
child: Container(
width:
MediaQuery.sizeOf(
context)
.width *
0.2,
height: 21,
decoration:
const BoxDecoration(
color: Colors.white,
),
child: Row(
mainAxisSize:
MainAxisSize
.max,
mainAxisAlignment:
MainAxisAlignment
.end,
children: [
Text(
// '2',
controller
.model
.issue_img!
.length
.toString(),
style:
TextStyle(
fontFamily:
'Readex Pro',
fontSize:
AppFontsize
.normal_text_size,
letterSpacing:
0,
),
),
Text(
'/',
style:
TextStyle(
fontFamily:
'Readex Pro',
fontSize:
AppFontsize
.normal_text_size,
letterSpacing:
0,
),
),
Text(
'3',
style:
TextStyle(
fontFamily:
'Readex Pro',
fontSize:
AppFontsize
.normal_text_size,
letterSpacing:
0,
),
),
],
),
),
),
),
),
Flexible(
child: Padding(
padding:
const EdgeInsetsDirectional
.fromSTEB(
0, 0, 21, 0),
child: Container(
width:
MediaQuery.sizeOf(
context)
.width,
height:
MediaQuery.sizeOf(
context)
.height *
0.15,
constraints:
const BoxConstraints(
minHeight: 152,
),
decoration:
const BoxDecoration(
color: Colors.white,
),
child: Container(
width: 100,
height: 100,
decoration:
const BoxDecoration(
color:
Colors.white,
),
child: Obx(() => ListView(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
children: getImage()
.divide(const SizedBox(
width: 12,
))
.addToStart(const SizedBox(
width: 21,
))))),
),
),
),
],
),
),
),
],
),
);
}),
),
),
Padding(
padding: EdgeInsetsDirectional.fromSTEB(
0, 25.rpx, 0, 0),
child: Container(
width: bodysize!.maxWidth,
height: bodysize!.maxHeight * 0.17,
constraints: BoxConstraints(
minHeight: 345.rpx,
),
decoration: BoxDecoration(
color: const Color(0xFF003058),
borderRadius: BorderRadius.circular(16.rpx),
),
child: Container(
width: bodysize!.maxWidth,
height: bodysize!.maxHeight * 0.19,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16.rpx),
),
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
Align(
alignment:
const AlignmentDirectional(0, 0),
child: Padding(
padding: const EdgeInsetsDirectional
.fromSTEB(0, 15, 0, 16),
child: Text(
'请描述一下您的问题'.tr,
style: TextStyle(
fontFamily: 'Readex Pro',
color: Colors.white,
fontSize: 30.rpx,
letterSpacing: 0,
),
),
),
),
Expanded(
child: Padding(
padding:
EdgeInsetsDirectional.fromSTEB(
34.rpx, 0, 34.rpx, 34.rpx),
child: Container(
width: MediaQuery.sizeOf(context)
.width,
height: MediaQuery.sizeOf(context)
.height *
1,
constraints: BoxConstraints(
minHeight: 181.rpx,
),
decoration: BoxDecoration(
color: const Color(0xFFF3F5F6),
borderRadius:
BorderRadius.circular(8),
),
child: TextFormField(
// autofocus: true,
onChanged: (value) {
controller.model.desc = value;
},
initialValue:
controller.model.desc,
obscureText: false,
decoration: InputDecoration(
hintText: '问题描述100个字以内'.tr,
labelStyle: TextStyle(
fontFamily: 'Readex Pro',
fontSize: AppFontsize
.normal_text_size,
letterSpacing: 0,
color: const Color(
0XFF929699)),
hintStyle: TextStyle(
fontFamily: 'Readex Pro',
fontSize: AppFontsize
.normal_text_size,
letterSpacing: 0,
color: const Color(
0XFF929699)),
enabledBorder:
UnderlineInputBorder(
borderSide: const BorderSide(
color: Color(0x00000000),
width: 2,
),
borderRadius:
BorderRadius.circular(8),
),
focusedBorder:
UnderlineInputBorder(
borderSide: const BorderSide(
color: Color(0x00000000),
width: 2,
),
borderRadius:
BorderRadius.circular(8),
),
errorBorder:
UnderlineInputBorder(
borderSide: const BorderSide(
color: Color(0x00000000),
width: 2,
),
borderRadius:
BorderRadius.circular(8),
),
focusedErrorBorder:
UnderlineInputBorder(
borderSide: const BorderSide(
color: Color(0x00000000),
width: 2,
),
borderRadius:
BorderRadius.circular(8),
),
// contentPadding:
// EdgeInsetsDirectional
// .fromSTEB(0, 0, 0, 12),
contentPadding:
const EdgeInsetsDirectional
.fromSTEB(10, 5, 10, 5),
),
maxLines: 4,
maxLength: 100, // ✅ 限制最多输入 100 字符
style: TextStyle(
fontFamily: 'Readex Pro',
fontSize: AppFontsize
.normal_text_size,
letterSpacing: 0,
),
),
),
),
),
],
),
),
),
),
Padding(
padding: EdgeInsetsDirectional.fromSTEB(
0, 48.rpx, 0, 0),
child: Container(
width: bodysize!.maxWidth,
height: bodysize!.maxHeight * 0.17,
constraints: BoxConstraints(
minHeight: 345.rpx,
),
decoration: BoxDecoration(
color: const Color(0XFF003058),
borderRadius: BorderRadius.circular(16),
),
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
Align(
alignment:
const AlignmentDirectional(0, 0),
child: Padding(
padding: EdgeInsetsDirectional.fromSTEB(
0, 48.rpx, 0, 48.rpx),
child: Text(
'联系方式'.tr,
style: TextStyle(
fontFamily: 'Readex Pro',
color: Colors.white,
fontSize: 30.rpx,
letterSpacing: 0,
),
),
),
),
Expanded(
child: Padding(
padding: EdgeInsetsDirectional.fromSTEB(
25.rpx, 0, 34.rpx, 70.rpx),
child: Container(
width:
MediaQuery.sizeOf(context).width,
height: MediaQuery.sizeOf(context)
.height *
1,
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
Flexible(
child: Container(
width:
MediaQuery.sizeOf(context)
.width,
height:
MediaQuery.sizeOf(context)
.height *
0.038,
constraints: BoxConstraints(
minHeight: 61.rpx,
),
child: Row(
mainAxisSize:
MainAxisSize.max,
children: [
Container(
width: 105.rpx,
height:
MediaQuery.sizeOf(
context)
.height *
0.038,
constraints:
BoxConstraints(
minWidth: 60.rpx,
),
// decoration:
// BoxDecoration(
// color: FlutterFlowTheme.of(
// context)
// .secondaryBackground,
// ),
child: Row(
mainAxisSize:
MainAxisSize.max,
children: [
Text(
'联系人'.tr,
style: TextStyle(
fontFamily:
'Readex Pro',
fontSize:
26.rpx,
letterSpacing:
0,
color: Colors
.white),
),
],
),
),
Expanded(
child: Container(
width:
MediaQuery.sizeOf(
context)
.width,
height: 100,
decoration:
BoxDecoration(
color: Colors.white,
borderRadius:
BorderRadius
.circular(
8),
),
child: TextFormField(
// autofocus: true,
obscureText: false,
onChanged: (val) {
controller.model
.apply_name =
val;
},
decoration:
InputDecoration(
contentPadding:
EdgeInsets
.symmetric(
vertical:
25.rpx,
horizontal:
26.rpx,
),
labelStyle:
TextStyle(
fontFamily:
'Readex Pro',
letterSpacing:
0,
),
hintStyle:
TextStyle(
fontFamily:
'Readex Pro',
letterSpacing:
0,
),
enabledBorder:
UnderlineInputBorder(
borderSide:
const BorderSide(
color: Color(
0x00000000),
width: 2,
),
borderRadius:
BorderRadius
.circular(
8),
),
focusedBorder:
UnderlineInputBorder(
borderSide:
const BorderSide(
color: Color(
0x00000000),
width: 2,
),
borderRadius:
BorderRadius
.circular(
8),
),
errorBorder:
UnderlineInputBorder(
borderSide:
const BorderSide(
color: Color(
0x00000000),
width: 2,
),
borderRadius:
BorderRadius
.circular(
8),
),
focusedErrorBorder:
UnderlineInputBorder(
borderSide:
const BorderSide(
color: Color(
0x00000000),
width: 2,
),
borderRadius:
BorderRadius
.circular(
8),
),
),
style: TextStyle(
fontFamily:
'Readex Pro',
letterSpacing: 0,
color:
Colors.black,
fontSize: 26.rpx,
),
),
),
),
].divide(const SizedBox(
width: 13)),
),
),
),
Flexible(
child: Container(
width:
MediaQuery.sizeOf(context)
.width,
height:
MediaQuery.sizeOf(context)
.height *
0.038,
constraints:
const BoxConstraints(
minHeight: 31,
),
child: Row(
mainAxisSize:
MainAxisSize.max,
children: [
Container(
width: 105.rpx,
height:
MediaQuery.sizeOf(
context)
.height *
0.038,
constraints:
BoxConstraints(
minWidth: 60.rpx,
),
child: Row(
mainAxisSize:
MainAxisSize.max,
children: [
Text(
'手机号码'.tr,
style: TextStyle(
fontFamily:
'Readex Pro',
fontSize:
26.rpx,
letterSpacing:
0,
color: Colors
.white),
),
],
),
),
Expanded(
child: Container(
width: 100,
height: 100,
decoration:
BoxDecoration(
color: Colors.white,
borderRadius:
BorderRadius
.circular(
8),
),
child: TextFormField(
// autofocus: true,
obscureText: false,
onChanged: (val) {
controller.model
.tel = val;
},
decoration:
InputDecoration(
contentPadding:
EdgeInsets
.symmetric(
vertical:
25.rpx,
horizontal:
26.rpx,
),
labelStyle:
TextStyle(
fontFamily:
'Readex Pro',
letterSpacing:
0,
),
// hintText:
// "请输入手机号".tr,
hintStyle:
TextStyle(
fontFamily:
'Readex Pro',
letterSpacing:
0,
),
enabledBorder:
UnderlineInputBorder(
borderSide:
const BorderSide(
color: Color(
0x00000000),
width: 2,
),
borderRadius:
BorderRadius
.circular(
8),
),
focusedBorder:
UnderlineInputBorder(
borderSide:
const BorderSide(
color: Color(
0x00000000),
width: 2,
),
borderRadius:
BorderRadius
.circular(
8),
),
errorBorder:
UnderlineInputBorder(
borderSide:
const BorderSide(
color: Color(
0x00000000),
width: 2,
),
borderRadius:
BorderRadius
.circular(
8),
),
focusedErrorBorder:
UnderlineInputBorder(
borderSide:
const BorderSide(
color: Color(
0x00000000),
width: 2,
),
borderRadius:
BorderRadius
.circular(
8),
),
),
style: TextStyle(
fontFamily:
'Readex Pro',
letterSpacing: 0,
color:
Colors.black,
fontSize: 26.rpx,
),
),
),
),
].divide(const SizedBox(
width: 13)),
),
),
),
].divide(
const SizedBox(height: 15)),
),
),
),
),
],
),
),
),
],
),
),
),
),
),
Padding(
padding: EdgeInsetsDirectional.fromSTEB(30.rpx, 30.rpx,
30.rpx, AppConstants.page_button_bottom_padding),
child: Container(
width: bodysize!.maxWidth,
height: bodysize!.maxHeight * 0.056,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16.rpx),
),
child: CustomCard(
borderRadius: 16.rpx,
gradientDirection: GradientDirection.vertical,
onTap: () async {
String msg = checkRepairParam();
if (msg.isNotEmpty) {
TopSlideNotification.show(context,
text: msg,
textColor: themeController.currentColor.sc9);
} else {
String serviceAddress =
ServiceConstant.service_address;
String serviceName = ServiceConstant.server_service;
String serviceApi = ServiceConstant.submit_repair;
String queryUrl =
"$serviceAddress$serviceName$serviceApi";
var data = {
"type": controller.model.device_type,
"contacts": {
"name": controller.model.apply_name,
"phone": controller.model.tel,
},
"device": [
{
"mac".tr: controller.model.device_id,
"desc": controller.model.desc,
"img": controller.model.issue_img,
"category": controller.model.device_category,
"series": controller.model.device_series,
"name": controller.model.device_name
}
],
};
ApiResponse apiResponse = await requestWithLog(
logTitle: "提交报修信息".tr,
method: MyHttpMethod.post,
queryUrl: queryUrl,
data: data,
onSuccess: (res) {
TopSlideNotification.show(context,
text: res.msg!);
repairListController.getRepairList();
Get.toNamed("/applyRepairSuccess");
},
onFailure: (res) {
TopSlideNotification.show(context,
text: res.msg!,
textColor:
themeController.currentColor.sc9);
},
);
controller.model =
ApplyRepairModel(); // 在 submitRepair 完成后执行
controller.updateAll();
}
},
colors: const [
Color(0xFFFCFCFC),
Color(0xFFF8FAF9),
Color(0XFFECF6F3),
Color(0XFFD9F0E9),
Color(0xFFCEECE3)
],
child: Container(
width: double.infinity,
height: 90.rpx,
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6),
),
child: Text(
"提交申请".tr,
style: TextStyle(
fontFamily: 'Readex Pro',
color: stringToColor("#011D33"),
letterSpacing: 0,
fontSize: 30.rpx,
),
),
),
)),
),
],
),
),
),
));
});
}
List<Widget> getImage() {
List<Widget> images = [];
controller.model.issue_img!.forEach((element) async {
images.add(ImgPreviewWidget(
imgUrl: element,
index: controller.model.issue_img!.indexOf(element),
applyRepairController: controller,
isDel: true,
));
});
if (images.length < controller.model.imagesLImit!) {
images.add(ImgPreviewDefaultWidget(
applyRepairController: controller,
));
}
return images;
}
String checkRepairParam() {
String message = "";
if (controller.model.device_type == null ||
controller.model.device_series!.isEmpty) {
message = '请输入设备系列!'.tr;
return message;
}
if (controller.model.device_category == null ||
controller.model.device_category!.isEmpty) {
message = '请输入设备型号!'.tr;
return message;
}
if (controller.model.device_id == null ||
controller.model.device_id!.isEmpty) {
message = '请输入设备序列号id'.tr;
return message;
}
if (controller.model.apply_name == null ||
controller.model.apply_name!.isEmpty) {
message = '请输入姓名!'.tr;
return message;
}
RegExp nameRegExp = RegExp(r'^[\u4e00-\u9fa5]{2,4}$');
if (!nameRegExp.hasMatch(controller.model.apply_name!)) {
message = '姓名必须为2到4个汉字'.tr;
return message;
}
if (controller.model.tel == null || controller.model.tel!.isEmpty) {
message = '请输入手机号!'.tr;
return message;
}
if (!MyUtils.isValidPhoneNumber(controller.model.tel!)) {
message = '无效的手机号!'.tr;
return message;
}
if (controller.model.desc == null || controller.model.desc!.isEmpty) {
message = '请输入问题描述!'.tr;
return message;
}
if (controller.model.issue_img == null ||
controller.model.issue_img!.isEmpty) {
message = '请至少上传一张问题图片!'.tr;
return message;
}
return message;
}
// 新增滚动方法
void _scrollToKey(GlobalKey key) {
WidgetsBinding.instance.addPostFrameCallback((_) {
Scrollable.ensureVisible(
key.currentContext!,
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut,
);
});
}
String getDeviceTypeName(int? type) {
if (type == null) return '';
switch (type) {
case 1:
return '体征检测设备'.tr;
case 2:
return '智能床'.tr;
case 3:
return '智能床垫'.tr;
default:
return '未知设备'.tr;
}
}
}