Files
tuiche/lib/pages/mh_page/apply_repair_page.dart
2025-07-15 17:48:05 +08:00

2486 lines
180 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(
// // width: 100,
// // height: 100,
// // decoration:
// // BoxDecoration(
// // color: Colors
// // .white,
// // borderRadius:
// // BorderRadius
// // .circular(8),
// // ),
// // child: Padding(
// // padding: EdgeInsets.only(left: 26.rpx),
// // child: Align(
// // alignment: Alignment.centerLeft,
// // child: Obx(() => Text(
// // controller.model.device_category ?? '',
// // style: TextStyle(fontSize: 26.rpx, color: Colors.black),
// // ))))),
// // ),
// 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(
// // width: 100,
// // height: 100,
// // decoration:
// // BoxDecoration(
// // color: Colors
// // .white,
// // borderRadius:
// // BorderRadius
// // .circular(8),
// // ),
// // child: Padding(
// // padding: EdgeInsets.only(left: 26.rpx),
// // child: Align(
// // alignment: Alignment.centerLeft,
// // child: Obx(() => Text(
// // controller.model.device_id ?? '',
// // style: TextStyle(fontSize: 26.rpx, color: Colors.black),
// // ))))),
// // ),
// 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)),
// ),
// ),
// ),
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,
fontWeight: FontWeight.w600,
),
),
),
),
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 '未知设备';
}
}
}