Files
tuiche/lib/pages/mh_page/apply_repair_page.dart
2025-07-23 13:55:46 +08:00

2111 lines
144 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(
'申请报修',
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(
'选择需要报修的设备',
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(
'已绑设备',
style: TextStyle(
fontFamily:
'Readex Pro',
fontSize:
26.rpx,
letterSpacing:
0,
color: Colors
.white),
),
),
),
Expanded(
child: Container(
width:
300, // 可以根据需要调整宽度
height:
56, // 可以根据需要调整高度
decoration:
BoxDecoration(
borderRadius:
BorderRadius
.circular(
8),
color: Colors
.white,
),
// child: Obx(
// () {
// List<Map<String, String>> deviceOptions = controller
// .model
// .device_list!
// .map((device) => {
// 'mac': device['mac'].toString(), // 提取设备 Mac
// 'name': device['name'].toString(), // 提取设备名称
// 'type': device['device_type'].toString()
// })
// .toList();
// // 提取 optionsLabel 和 optionsValue
// // List<String> deviceNames = deviceOptions
// // .map((device) => device['name']!) // 用于显示的名称列表
// // .toList();
// List<String>
// deviceNames =
// controller.model.device_list!.map((device) {
// final mac =
// device['mac']?.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']!) // 用于匹配的 ID 列表
// .toList();
// return FlutterFlowDropDown<
// String>(
// controller:
// tmpcontroller,
// fillColor:
// Colors.white, // 控件区域背景色
// options:
// deviceMacs, // 下拉菜单选项为设备的 ID
// optionLabels:
// deviceNames, // 下拉菜单显示的内容为设备名称
// onChanged:
// (val) {
// // var selectedDevice = controller.model.device_list!.firstWhere((device) => device['mac'].toString() == val);
// // controller.model.select_device = val;
// // controller.model.device_type = selectedDevice['device_type'];
// // // controller.model.device_category = selectedDevice['deviceSeries']['name'] ?? '未知型号'; // 获取设备型号
// // controller.model.device_category = '未知型号';
// // controller.model.device_id = selectedDevice['mac'] ?? '未知设备mac'; // 获取设备ID
// // controller.model.device_name = selectedDevice['name'] ?? '未知设备'; // 获取设备名称
// // controller.updateAll();
// var selectedDevice = controller.model.device_list!.firstWhere((device) => device['mac'].toString() == val);
// final mac = selectedDevice['mac']?.toString() ?? '未知MAC';
// 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 = '未知型号'; // 后续可替换成设备系列
// // 如果 name 不为空则用 name否则用 typeName-mac
// controller.model.device_name = (name != null && name.isNotEmpty) ? name : '$typeName-MAC$mac';
// controller.model.device_id = mac;
// controller.updateAll();
// },
// width:
// 300,
// height:
// 56,
// searchHintTextStyle:
// const TextStyle(
// fontFamily: 'Readex Pro',
// letterSpacing: 0,
// ),
// searchTextStyle:
// const TextStyle(
// fontFamily: 'Readex Pro',
// letterSpacing: 0,
// ),
// textStyle:
// TextStyle(
// fontFamily: 'Readex Pro',
// color: Colors.black,
// fontSize: 26.rpx,
// letterSpacing: 0,
// ),
// hintText:
// '请选择绑定设备',
// searchHintText:
// '查找',
// icon:
// const Icon(
// Icons.keyboard_arrow_down_rounded,
// color: Colors.black,
// size: 24,
// ),
// // fillColor:
// // FlutterFlowTheme.of(context).secondaryBackground,
// elevation:
// 2,
// borderColor:
// Colors.white,
// borderWidth:
// 0,
// borderRadius:
// 8,
// margin: const EdgeInsetsDirectional.fromSTEB(
// 10,
// 4,
// 10,
// 4),
// hidesUnderline:
// true,
// isOverButton:
// false,
// isSearchable:
// false,
// isMultiSelect:
// false,
// );
// })
child: Obx(() {
final isDeviceListEmpty = controller
.model
.device_list
?.isEmpty ??
true;
List<Map<String, String>>
deviceOptions =
controller
.model
.device_list!
.map((device) =>
{
'mac': device['mac'].toString(),
'name': device['name'].toString(),
'type': device['device_type'].toString()
})
.toList();
List<String>
deviceNames =
controller
.model
.device_list!
.map(
(device) {
final mac =
device['mac']?.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']!)
.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'].toString() ==
val);
final mac =
selectedDevice['mac']?.toString() ??
'未知MAC';
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 = '未知型号';
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
? '暂无可选设备'
: '请选择绑定设备',
searchHintText:
'查找',
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: const EdgeInsetsDirectional
.fromSTEB(
10,
4,
10,
4),
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:
const BoxConstraints(
minWidth: 60,
),
child: Align(
alignment:
const AlignmentDirectional(
-1, 0),
child: Text(
'设备系列',
style: TextStyle(
fontFamily:
'Readex Pro',
fontSize:
26.rpx,
letterSpacing:
0,
color: Colors
.white),
),
),
),
Expanded(
child: Container(
decoration:
BoxDecoration(
color:
Colors.white,
borderRadius:
BorderRadius
.circular(
8),
),
width:
double.infinity,
child: Padding(
padding:
EdgeInsetsDirectional
.fromSTEB(
35.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:
true,
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:
const BoxConstraints(
minWidth: 60,
),
child: Align(
alignment:
const AlignmentDirectional(
-1, 0),
child: Text(
'产品型号',
style: TextStyle(
fontFamily:
'Readex Pro',
fontSize:
26.rpx,
letterSpacing:
0,
color: Colors
.white),
),
),
),
Expanded(
child: Container(
decoration:
BoxDecoration(
color:
Colors.white,
borderRadius:
BorderRadius
.circular(
8),
),
width:
double.infinity,
child: Padding(
padding:
EdgeInsetsDirectional
.fromSTEB(
35.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:
true,
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:
const BoxConstraints(
minWidth: 60,
),
child: Align(
alignment:
const AlignmentDirectional(
-1, 0),
child: Text(
'序列号',
style: TextStyle(
fontFamily:
'Readex Pro',
fontSize:
26.rpx,
letterSpacing:
0,
color: Colors
.white),
),
),
),
Expanded(
child: Container(
decoration:
BoxDecoration(
color:
Colors.white,
borderRadius:
BorderRadius
.circular(
8),
),
width:
double.infinity,
child: Padding(
padding:
EdgeInsetsDirectional
.fromSTEB(
35.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:
true,
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: 138,
height: 31,
decoration: BoxDecoration(
borderRadius:
BorderRadius
.circular(50),
border: Border.all(
color: const Color(
0xFF9EA4B7),
),
),
child: Align(
alignment:
const AlignmentDirectional(
0, 0),
child: Text(
'上传设备故障照片',
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(
'请描述一下您的问题',
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个字以内',
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(
'联系方式',
style: TextStyle(
fontFamily: 'Readex Pro',
color: Colors.white,
fontSize: 30.rpx,
letterSpacing: 0,
fontWeight: FontWeight.w600,
),
),
),
),
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(
'联系人',
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(
'手机号码',
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,
),
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": 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: "提交报修信息",
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(
"提交申请",
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;
}
List<DropdownMenuItem<String>> _getDropdownItems() {
List<String> options = [
'智能床垫AH-2型',
'智能床垫BY-H型',
'智能床垫BY-C型',
// 可以在这里添加更多选项
];
return options.map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList();
}
String checkRepairParam() {
String message = "";
if (controller.model.device_type == null ||
controller.model.device_series!.isEmpty) {
message = '请输入设备系列!';
return message;
}
if (controller.model.device_category == null ||
controller.model.device_category!.isEmpty) {
message = '请输入设备型号!';
return message;
}
if (controller.model.device_id == null ||
controller.model.device_id!.isEmpty) {
message = '请输入设备序列号id';
return message;
}
if (controller.model.apply_name == null ||
controller.model.apply_name!.isEmpty) {
message = '请输入姓名!';
return message;
}
RegExp nameRegExp = RegExp(r'^[\u4e00-\u9fa5]{2,4}$');
if (!nameRegExp.hasMatch(controller.model.apply_name!)) {
message = '姓名必须为2到4个汉字';
return message;
}
if (controller.model.tel == null || controller.model.tel!.isEmpty) {
message = '请输入手机号!';
return message;
}
if (!MyUtils.isValidPhoneNumber(controller.model.tel!)) {
message = '无效的手机号!';
return message;
}
if (controller.model.desc == null || controller.model.desc!.isEmpty) {
message = '请输入问题描述!';
return message;
}
if (controller.model.issue_img == null ||
controller.model.issue_img!.isEmpty) {
message = '请至少上传一张问题图片!';
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 '体征检测设备';
case 2:
return '智能床';
case 3:
return '智能床垫';
default:
return '未知设备';
}
}
}