李志伟 3 年之前
父節點
當前提交
795ee60586

+ 28
- 14
android/app/build.gradle 查看文件

26
 apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
26
 apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
27
 
27
 
28
 android {
28
 android {
29
-    compileSdkVersion flutter.compileSdkVersion
29
+    compileSdkVersion 31
30
 
30
 
31
     compileOptions {
31
     compileOptions {
32
         sourceCompatibility JavaVersion.VERSION_1_8
32
         sourceCompatibility JavaVersion.VERSION_1_8
33
         targetCompatibility JavaVersion.VERSION_1_8
33
         targetCompatibility JavaVersion.VERSION_1_8
34
     }
34
     }
35
 
35
 
36
-    kotlinOptions {
37
-        jvmTarget = '1.8'
38
-    }
39
-
40
-    sourceSets {
41
-        main.java.srcDirs += 'src/main/kotlin'
42
-    }
43
-
44
     defaultConfig {
36
     defaultConfig {
45
         // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
37
         // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
46
         applicationId "com.example.worker_client"
38
         applicationId "com.example.worker_client"
47
-        minSdkVersion flutter.minSdkVersion
48
-        targetSdkVersion flutter.targetSdkVersion
39
+        minSdkVersion 21
40
+        targetSdkVersion 28
49
         versionCode flutterVersionCode.toInteger()
41
         versionCode flutterVersionCode.toInteger()
50
         versionName flutterVersionName
42
         versionName flutterVersionName
51
     }
43
     }
44
+    signingConfigs {
45
+        debug {
46
+            //keystore中key的别名
47
+            keyAlias 'mykey'
48
+            //keystore中key的密码
49
+            keyPassword 'SJPrpy7yF8XdkXHY'
50
+            //keystore的文件路径,可以是绝对路径也可以是相对路径
51
+            storeFile file('../machinery.keystore')
52
+            //keystore的密码l
53
+            storePassword 'Op4CCmT20L0c0fLP'
54
+        }
55
+    }
56
+
57
+    dependencies {
58
+        implementation('com.amap.api:3dmap:9.1.0')
59
+        implementation('com.amap.api:location:6.1.0')
60
+    }
52
 
61
 
53
     buildTypes {
62
     buildTypes {
63
+        debug {
64
+            minifyEnabled false
65
+        }
54
         release {
66
         release {
55
             // TODO: Add your own signing config for the release build.
67
             // TODO: Add your own signing config for the release build.
56
             // Signing with the debug keys for now, so `flutter run --release` works.
68
             // Signing with the debug keys for now, so `flutter run --release` works.
57
             signingConfig signingConfigs.debug
69
             signingConfig signingConfigs.debug
70
+
71
+            //关闭混淆, 否则在运行release包后可能出现运行崩溃, TODO后续进行混淆配置
72
+            minifyEnabled false //删除无用代码
73
+            shrinkResources false //删除无用资源
58
         }
74
         }
59
     }
75
     }
60
 }
76
 }
63
     source '../..'
79
     source '../..'
64
 }
80
 }
65
 
81
 
66
-dependencies {
67
-    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
68
-}
82
+

+ 29
- 0
android/app/src/main/AndroidManifest.xml 查看文件

1
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
+    xmlns:tools="http://schemas.android.com/tools"
2
     package="com.example.worker_client">
3
     package="com.example.worker_client">
4
+    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
5
+    <!--允许获取精确位置,精准定位必选-->
6
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
7
+    <!--允许获取粗略位置,粗略定位必选-->
8
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
9
+    <!--允许获取设备和运营商信息,用于问题排查和网络定位(无gps情况下的定位),若需网络定位功能则必选-->
10
+    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
11
+    <!--允许获取网络状态,用于网络定位(无gps情况下的定位),若需网络定位功能则必选-->
12
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
13
+    <!--允许获取wifi网络信息,用于网络定位(无gps情况下的定位),若需网络定位功能则必选-->
14
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
15
+    <!--允许获取wifi状态改变,用于网络定位(无gps情况下的定位),若需网络定位功能则必选-->
16
+    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
17
+    <!--后台获取位置信息,若需后台定位则必选-->
18
+    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
19
+    <!--用于申请调用A-GPS模块,卫星定位加速-->
20
+    <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
21
+    <!--允许写设备缓存,用于问题排查-->
22
+    <uses-permission android:name="android.permission.WRITE_SETTINGS" tools:ignore="ProtectedPermissions" />
23
+    <!--允许写入扩展存储,用于写入缓存定位数据-->
24
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
25
+    <!--允许读设备等信息,用于问题排查-->
26
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
3
    <application
27
    <application
4
         android:label="worker_client"
28
         android:label="worker_client"
5
         android:name="${applicationName}"
29
         android:name="${applicationName}"
30
         <meta-data
54
         <meta-data
31
             android:name="flutterEmbedding"
55
             android:name="flutterEmbedding"
32
             android:value="2" />
56
             android:value="2" />
57
+       <meta-data
58
+           android:name="com.amap.api.v2.apikey"
59
+           android:value="b481b4187e24e625fa0056fd0530e663"/>
60
+       <service android:name="com.amap.api.location.APSService"
61
+           tools:ignore="MissingClass" />
33
     </application>
62
     </application>
34
 </manifest>
63
 </manifest>

二進制
android/app/src/main/res/drawable/launch_image.png 查看文件


二進制
android/app/src/main/res/mipmap-hdpi/ic_launcher.png 查看文件


二進制
android/app/src/main/res/mipmap-mdpi/ic_launcher.png 查看文件


二進制
android/app/src/main/res/mipmap-xhdpi/ic_launcher.png 查看文件


二進制
android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png 查看文件


二進制
android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png 查看文件


+ 1
- 1
android/app/src/main/res/values/styles.xml 查看文件

4
     <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
4
     <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
5
         <!-- Show a splash screen on the activity. Automatically removed when
5
         <!-- Show a splash screen on the activity. Automatically removed when
6
              Flutter draws its first frame -->
6
              Flutter draws its first frame -->
7
-        <item name="android:windowBackground">@drawable/launch_background</item>
7
+        <item name="android:windowBackground">@drawable/launch_image</item>
8
     </style>
8
     </style>
9
     <!-- Theme applied to the Android Window as soon as the process has started.
9
     <!-- Theme applied to the Android Window as soon as the process has started.
10
          This theme determines the color of the Android Window while your
10
          This theme determines the color of the Android Window while your

+ 33
- 15
lib/models/app.dart 查看文件

1
 
1
 
2
 import 'dart:io';
2
 import 'dart:io';
3
 
3
 
4
-import './entities/person.dart';
4
+import 'package:amap_flutter_location/amap_flutter_location.dart';
5
+import '/models/entities/person.dart';
6
+import '/widgets/Modal.dart';
5
 import 'package:get/get.dart';
7
 import 'package:get/get.dart';
6
-import 'package:location/location.dart';
7
-import '../services/user.dart';
8
 import '../utils/location.dart';
8
 import '../utils/location.dart';
9
 
9
 
10
 class AppController extends GetxController {
10
 class AppController extends GetxController {
12
   static AppController t = Get.find();
12
   static AppController t = Get.find();
13
 
13
 
14
   final user = Rx<Person>(Person());
14
   final user = Rx<Person>(Person());
15
-  final location = Rxn<LocationData>();
15
+  final location = Rxn<Map<String, Object>>();
16
   final testInt = 1.obs;
16
   final testInt = 1.obs;
17
 
17
 
18
+  AMapFlutterLocation? _location;
19
+
20
+  get locationStr {
21
+    if (null == location.value) return null;
22
+
23
+    double longitude = location.value!['longitude'] as double;
24
+    double latitude = location.value!['latitude'] as double;
25
+
26
+    return longitude.toString() + "," + latitude.toString();
27
+  }
28
+
29
+  void onLocationChange (Map<String, Object> result) {
30
+    location(result);
31
+  }
32
+
18
   @override
33
   @override
19
   void onInit() {
34
   void onInit() {
20
     super.onInit();
35
     super.onInit();
21
 
36
 
22
     // 尝试获取 location
37
     // 尝试获取 location
23
-    requireLocation().then((loc) async {
24
-      var _data = await loc.getLocation();
25
-      location(_data);
26
-
27
-      // 监听位置变化
28
-      loc.onLocationChanged.listen((LocationData currentLocation) {
29
-        location(currentLocation);
30
-      });
38
+    requireLocation(onLocationChange).then((loc) {
39
+      _location = loc;
31
     }).catchError((e) {
40
     }).catchError((e) {
32
       print(e);
41
       print(e);
33
-      Get.defaultDialog(
34
-        title: e.message,
42
+
43
+      showAlert(
44
+        title: '获取定位失败',
45
+        message: e.message,
35
         onConfirm: () => exit(1),
46
         onConfirm: () => exit(1),
36
       );
47
       );
37
     });
48
     });
38
 
49
 
39
-    // 尝试获取一次人员信息
50
+    // // 尝试获取一次人员信息
40
     // getCurrent().then((person) {
51
     // getCurrent().then((person) {
41
     //   user(person);
52
     //   user(person);
42
     // }).catchError((e) {
53
     // }).catchError((e) {
44
     // });
55
     // });
45
   }
56
   }
46
 
57
 
58
+  @override
59
+  void onClose() {
60
+    if (null != _location) {
61
+      _location?.destroy();
62
+    }
63
+  }
64
+
47
 }
65
 }

+ 3
- 3
lib/models/entities/Banner.dart 查看文件

1
-class Banners {
1
+class BannerModel {
2
   String? bannerId;
2
   String? bannerId;
3
   String? title;
3
   String? title;
4
   String? thumb;
4
   String? thumb;
6
   num? sortNo;
6
   num? sortNo;
7
   num? status;
7
   num? status;
8
   String? createDat;
8
   String? createDat;
9
-  Banners();
9
+  BannerModel();
10
 
10
 
11
-  Banners.fromJson(Map<String, dynamic> json)
11
+  BannerModel.fromJson(Map<String, dynamic> json)
12
       : bannerId = json["bannerId"],
12
       : bannerId = json["bannerId"],
13
         title = json["title"],
13
         title = json["title"],
14
         thumb = json["thumb"],
14
         thumb = json["thumb"],

+ 172
- 170
lib/pages/Login/index.dart 查看文件

104
   Widget build(BuildContext context) {
104
   Widget build(BuildContext context) {
105
     return Scaffold(
105
     return Scaffold(
106
       resizeToAvoidBottomInset: false,
106
       resizeToAvoidBottomInset: false,
107
-      body: Container(
108
-          padding: EdgeInsets.all(15.w),
109
-          decoration: const BoxDecoration(
110
-            image: DecorationImage(
111
-              image: AssetImage("images/login/loginImg.png"),
112
-              fit: BoxFit.cover,
107
+      body: SafeArea(
108
+        child: Container(
109
+            padding: EdgeInsets.all(15.w),
110
+            decoration: const BoxDecoration(
111
+              image: DecorationImage(
112
+                image: AssetImage("images/login/loginImg.png"),
113
+                fit: BoxFit.cover,
114
+              ),
113
             ),
115
             ),
114
-          ),
115
-          child: Column(
116
-            crossAxisAlignment: CrossAxisAlignment.start,
117
-            children: [
118
-              SizedBox(
119
-                height: 44.w,
120
-                child: Center(
116
+            child: Column(
117
+              crossAxisAlignment: CrossAxisAlignment.start,
118
+              children: [
119
+                SizedBox(
120
+                  height: 44.w,
121
+                  child: Center(
122
+                    child: Text(
123
+                      '登录',
124
+                      style: TextStyle(
125
+                        letterSpacing: 3,
126
+                        fontWeight: FontWeight.bold,
127
+                        color: const Color(0xFF333333),
128
+                        fontSize: 17.sp,
129
+                      ),
130
+                    ),
131
+                  ),
132
+                ),
133
+                Container(
134
+                  margin: EdgeInsets.fromLTRB(0, 49.h, 0, 22.h),
121
                   child: Text(
135
                   child: Text(
122
-                    '登录',
136
+                    '您好!',
123
                     style: TextStyle(
137
                     style: TextStyle(
124
                       letterSpacing: 3,
138
                       letterSpacing: 3,
125
                       fontWeight: FontWeight.bold,
139
                       fontWeight: FontWeight.bold,
140
+                      fontSize: 33.sp,
126
                       color: const Color(0xFF333333),
141
                       color: const Color(0xFF333333),
127
-                      fontSize: 17.sp,
128
                     ),
142
                     ),
129
                   ),
143
                   ),
130
                 ),
144
                 ),
131
-              ),
132
-              Container(
133
-                margin: EdgeInsets.fromLTRB(0, 49.h, 0, 22.h),
134
-                child: Text(
135
-                  '您好!',
145
+                Text(
146
+                  '欢迎进入农机手端小程序!',
136
                   style: TextStyle(
147
                   style: TextStyle(
137
                     letterSpacing: 3,
148
                     letterSpacing: 3,
138
                     fontWeight: FontWeight.bold,
149
                     fontWeight: FontWeight.bold,
139
-                    fontSize: 33.sp,
150
+                    fontSize: 27.sp,
140
                     color: const Color(0xFF333333),
151
                     color: const Color(0xFF333333),
141
                   ),
152
                   ),
142
                 ),
153
                 ),
143
-              ),
144
-              Text(
145
-                '欢迎进入农机手端小程序!',
146
-                style: TextStyle(
147
-                  letterSpacing: 3,
148
-                  fontWeight: FontWeight.bold,
149
-                  fontSize: 27.sp,
150
-                  color: const Color(0xFF333333),
151
-                ),
152
-              ),
153
-              Cell(
154
-                margin: EdgeInsets.fromLTRB(0, 43.h, 0, 16.h),
155
-                header: Text(
156
-                  "+86",
157
-                  style: TextStyle(
158
-                    fontWeight: FontWeight.w500,
159
-                    fontSize: 19.sp,
160
-                    color: const Color(0xFF333333),
161
-                  ),
162
-                ),
163
-                child: TextField(
164
-                  maxLength: 11,
165
-                  //数字文本框
166
-                  keyboardType: TextInputType.number,
167
-                  style: TextStyle(
168
-                    fontSize: 17.sp,
169
-                  ),
170
-                  decoration: InputDecoration(
171
-                    isCollapsed: true,
172
-                    contentPadding: EdgeInsets.symmetric(
173
-                        horizontal: 15.5.w, vertical: 19.h),
174
-                    labelText: "请输入手机号码",
175
-                    counterText: '', //去掉右下角的东西
176
-                    border: InputBorder.none,
177
-                    floatingLabelBehavior: FloatingLabelBehavior.never,
178
-                  ),
179
-                  onChanged: (val) {
180
-                    setPhone(val);
181
-                  },
182
-                ),
183
-                footer: SizedBox(
184
-                  width: 94.w,
185
-                  height: 34.h,
186
-                  child: GradientButton(
187
-                      colors: const [
188
-                        Color(0xFFA0E067),
189
-                        Color(0xFF00AE39),
190
-                      ],
191
-                      borderRadius: BorderRadius.all(Radius.circular(10.w)),
192
-                      onPressed: disableQcode ? null : handleQCode,
193
-                      child: Text(
194
-                        qCodeText,
195
-                        style: TextStyle(
196
-                          fontSize: 15.sp,
197
-                          fontWeight: FontWeight.bold,
198
-                        ),
199
-                      )),
200
-                ),
201
-              ),
202
-              Cell(
203
-                  header: Padding(
204
-                    padding: EdgeInsets.fromLTRB(9.5.w, 0, 0, 0),
205
-                    child: Stack(
206
-                      children: [
207
-                        Positioned(
208
-                          child: Image.asset(
209
-                            "images/login/VerificationCode.png",
210
-                            width: 20.w,
211
-                            height: 20.w,
212
-                          ),
213
-                        ),
214
-                      ],
154
+                Cell(
155
+                  margin: EdgeInsets.fromLTRB(0, 43.h, 0, 16.h),
156
+                  header: Text(
157
+                    "+86",
158
+                    style: TextStyle(
159
+                      fontWeight: FontWeight.w500,
160
+                      fontSize: 19.sp,
161
+                      color: const Color(0xFF333333),
215
                     ),
162
                     ),
216
                   ),
163
                   ),
217
                   child: TextField(
164
                   child: TextField(
225
                       isCollapsed: true,
172
                       isCollapsed: true,
226
                       contentPadding: EdgeInsets.symmetric(
173
                       contentPadding: EdgeInsets.symmetric(
227
                           horizontal: 15.5.w, vertical: 19.h),
174
                           horizontal: 15.5.w, vertical: 19.h),
228
-                      labelText: "请输入验证码",
175
+                      labelText: "请输入手机号码",
229
                       counterText: '', //去掉右下角的东西
176
                       counterText: '', //去掉右下角的东西
230
                       border: InputBorder.none,
177
                       border: InputBorder.none,
231
                       floatingLabelBehavior: FloatingLabelBehavior.never,
178
                       floatingLabelBehavior: FloatingLabelBehavior.never,
232
                     ),
179
                     ),
233
                     onChanged: (val) {
180
                     onChanged: (val) {
181
+                      setPhone(val);
182
+                    },
183
+                  ),
184
+                  footer: SizedBox(
185
+                    width: 94.w,
186
+                    height: 34.h,
187
+                    child: GradientButton(
188
+                        colors: const [
189
+                          Color(0xFFA0E067),
190
+                          Color(0xFF00AE39),
191
+                        ],
192
+                        borderRadius: BorderRadius.all(Radius.circular(10.w)),
193
+                        onPressed: disableQcode ? null : handleQCode,
194
+                        child: Text(
195
+                          qCodeText,
196
+                          style: TextStyle(
197
+                            fontSize: 15.sp,
198
+                            fontWeight: FontWeight.bold,
199
+                          ),
200
+                        )),
201
+                  ),
202
+                ),
203
+                Cell(
204
+                    header: Padding(
205
+                      padding: EdgeInsets.fromLTRB(9.5.w, 0, 0, 0),
206
+                      child: Stack(
207
+                        children: [
208
+                          Positioned(
209
+                            child: Image.asset(
210
+                              "images/login/VerificationCode.png",
211
+                              width: 20.w,
212
+                              height: 20.w,
213
+                            ),
214
+                          ),
215
+                        ],
216
+                      ),
217
+                    ),
218
+                    child: TextField(
219
+                      maxLength: 11,
220
+                      //数字文本框
221
+                      keyboardType: TextInputType.number,
222
+                      style: TextStyle(
223
+                        fontSize: 17.sp,
224
+                      ),
225
+                      decoration: InputDecoration(
226
+                        isCollapsed: true,
227
+                        contentPadding: EdgeInsets.symmetric(
228
+                            horizontal: 15.5.w, vertical: 19.h),
229
+                        labelText: "请输入验证码",
230
+                        counterText: '', //去掉右下角的东西
231
+                        border: InputBorder.none,
232
+                        floatingLabelBehavior: FloatingLabelBehavior.never,
233
+                      ),
234
+                      onChanged: (val) {
235
+                        setState(() {
236
+                          qCode = val;
237
+                        });
238
+                      },
239
+                    )),
240
+                //找到了 下面就是置底
241
+                const Spacer(),
242
+                Center(
243
+                  child: SizedBox(
244
+                    width: 315.w,
245
+                    height: 49.h,
246
+                    child: GradientButton(
247
+                        colors: const [
248
+                          Color(0xFFA0E067),
249
+                          Color(0xFF00AE39),
250
+                        ],
251
+                        borderRadius: BorderRadius.all(Radius.circular(24.5.w)),
252
+                        onPressed: disableLogin ? null : handleLogin,
253
+                        child: Text(
254
+                          '登录',
255
+                          style: TextStyle(
256
+                            fontSize: 17.sp,
257
+                            fontWeight: FontWeight.bold,
258
+                          ),
259
+                        )),
260
+                  ),
261
+                ),
262
+                Container(
263
+                  margin: EdgeInsets.fromLTRB(0, 30.h, 0, 0),
264
+                  child: GestureDetector(
265
+                    onTap: () {
234
                       setState(() {
266
                       setState(() {
235
-                        qCode = val;
267
+                        isCheck = !isCheck;
236
                       });
268
                       });
237
                     },
269
                     },
238
-                  )),
239
-              //找到了 下面就是置底
240
-              const Spacer(),
241
-              Center(
242
-                child: SizedBox(
243
-                  width: 315.w,
244
-                  height: 49.h,
245
-                  child: GradientButton(
246
-                      colors: const [
247
-                        Color(0xFFA0E067),
248
-                        Color(0xFF00AE39),
249
-                      ],
250
-                      borderRadius: BorderRadius.all(Radius.circular(24.5.w)),
251
-                      onPressed: disableLogin ? null : handleLogin,
252
-                      child: Text(
253
-                        '登录',
254
-                        style: TextStyle(
255
-                          fontSize: 17.sp,
256
-                          fontWeight: FontWeight.bold,
257
-                        ),
258
-                      )),
259
-                ),
260
-              ),
261
-              Container(
262
-                margin: EdgeInsets.fromLTRB(0, 30.h, 0, 0),
263
-                child: GestureDetector(
264
-                  onTap: () {
265
-                    setState(() {
266
-                      isCheck = !isCheck;
267
-                    });
268
-                  },
269
-                  child: Row(
270
-                    children: <Widget>[
271
-                      Padding(
272
-                        padding: EdgeInsets.fromLTRB(0, 0, 5.5.w, 0),
273
-                        child: GestureDetector(
274
-                          onTap: () {
275
-                            setState(() {
276
-                              isCheck = !isCheck;
277
-                            });
278
-                          },
279
-                          child: Image.asset(
280
-                            isCheck ? checkedImg : unCheckedImg,
281
-                            width: 14.h,
282
-                            height: 14.h,
270
+                    child: Row(
271
+                      children: <Widget>[
272
+                        Padding(
273
+                          padding: EdgeInsets.fromLTRB(0, 0, 5.5.w, 0),
274
+                          child: GestureDetector(
275
+                            onTap: () {
276
+                              setState(() {
277
+                                isCheck = !isCheck;
278
+                              });
279
+                            },
280
+                            child: Image.asset(
281
+                              isCheck ? checkedImg : unCheckedImg,
282
+                              width: 14.h,
283
+                              height: 14.h,
284
+                            ),
283
                           ),
285
                           ),
284
                         ),
286
                         ),
285
-                      ),
286
-                      RichText(
287
-                        text: TextSpan(
288
-                          children: <InlineSpan>[
289
-                            TextSpan(
290
-                              text: '请认真查看',
291
-                              style: TextStyle(
292
-                                color: const Color(0xFF999999),
293
-                                fontSize: 13.sp,
287
+                        RichText(
288
+                          text: TextSpan(
289
+                            children: <InlineSpan>[
290
+                              TextSpan(
291
+                                text: '请认真查看',
292
+                                style: TextStyle(
293
+                                  color: const Color(0xFF999999),
294
+                                  fontSize: 13.sp,
295
+                                ),
294
                               ),
296
                               ),
295
-                            ),
296
-                            TextSpan(
297
-                                text: '文本协议/隐私政策',
297
+                              TextSpan(
298
+                                  text: '文本协议/隐私政策',
299
+                                  style: TextStyle(
300
+                                    color: const Color(0xFF02902E),
301
+                                    fontSize: 13.sp,
302
+                                  ),
303
+                                  //给span添加点击事件厉害
304
+                                  recognizer: TapGestureRecognizer()
305
+                                    ..onTap = () {
306
+                                      print(999);
307
+                                    }),
308
+                              TextSpan(
309
+                                text: ',确认之后选择此项!',
298
                                 style: TextStyle(
310
                                 style: TextStyle(
299
-                                  color: const Color(0xFF02902E),
311
+                                  color: const Color(0xFF999999),
300
                                   fontSize: 13.sp,
312
                                   fontSize: 13.sp,
301
                                 ),
313
                                 ),
302
-                                //给span添加点击事件厉害
303
-                                recognizer: TapGestureRecognizer()
304
-                                  ..onTap = () {
305
-                                    print(999);
306
-                                  }),
307
-                            TextSpan(
308
-                              text: ',确认之后选择此项!',
309
-                              style: TextStyle(
310
-                                color: const Color(0xFF999999),
311
-                                fontSize: 13.sp,
312
                               ),
314
                               ),
313
-                            ),
314
-                          ],
315
+                            ],
316
+                          ),
315
                         ),
317
                         ),
316
-                      ),
317
-                    ],
318
+                      ],
319
+                    ),
318
                   ),
320
                   ),
319
                 ),
321
                 ),
320
-              ),
321
-            ],
322
-          )),
322
+              ],
323
+            )),
324
+      ),
323
     );
325
     );
324
   }
326
   }
325
 }
327
 }

+ 47
- 32
lib/pages/home/widgets/home/index.dart 查看文件

1
-import 'dart:math';
2
-
3
 import 'package:carousel_slider/carousel_slider.dart';
1
 import 'package:carousel_slider/carousel_slider.dart';
4
 import 'package:flutter/material.dart';
2
 import 'package:flutter/material.dart';
5
 import 'package:flutter_screenutil/flutter_screenutil.dart';
3
 import 'package:flutter_screenutil/flutter_screenutil.dart';
6
 import 'package:get/get.dart';
4
 import 'package:get/get.dart';
5
+import 'package:worker_client/models/entities/Banner.dart';
6
+import 'package:worker_client/models/entities/Job.dart';
7
 import 'package:worker_client/pages/home/widgets/home/widgets/headers.dart';
7
 import 'package:worker_client/pages/home/widgets/home/widgets/headers.dart';
8
 import 'package:worker_client/services/banner.dart';
8
 import 'package:worker_client/services/banner.dart';
9
+import 'package:worker_client/services/job.dart';
9
 import 'package:worker_client/widgets/MyCard/index.dart';
10
 import 'package:worker_client/widgets/MyCard/index.dart';
10
 
11
 
11
 class HomePage extends StatefulWidget {
12
 class HomePage extends StatefulWidget {
16
 }
17
 }
17
 
18
 
18
 class _HomePageState extends State<HomePage> {
19
 class _HomePageState extends State<HomePage> {
19
-
20
+  final bannerList = Rx<List<BannerModel>>([]);
21
+  final jobList = Rx<List<Job>>([]);
22
+  final job = Rx<Job>(Job());
20
   @override
23
   @override
21
   void initState() {
24
   void initState() {
22
     super.initState();
25
     super.initState();
23
-    getBannerList('bannerWorker').then((value) {}
24
-    );
26
+    getBannerList('bannerWorker').then((res) {
27
+      List<BannerModel> list=[];
28
+      for (var item in res) {
29
+        list.add(BannerModel.fromJson(item));
30
+      }
31
+      bannerList.value=list;
32
+    });
33
+    getJobList().then((res) {
34
+      List<Job> list=[];
35
+      for (var item in res['records']) {
36
+        list.add(Job.fromJson(item));
37
+      }
38
+      jobList.value=list;
39
+    });
25
   }
40
   }
26
 
41
 
27
-  final List<String> imgList = [
28
-    'https://images.unsplash.com/photo-1520342868574-5fa3804e551c?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=6ff92caffcdd63681a35134a6770ed3b&auto=format&fit=crop&w=1951&q=80',
29
-    'https://images.unsplash.com/photo-1522205408450-add114ad53fe?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=368f45b0888aeb0b7b08e3a1084d3ede&auto=format&fit=crop&w=1950&q=80',
30
-    'https://images.unsplash.com/photo-1519125323398-675f0ddb6308?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=94a1e718d89ca60a6337a6008341ca50&auto=format&fit=crop&w=1950&q=80',
31
-    'https://images.unsplash.com/photo-1523205771623-e0faa4d2813d?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=89719a0d55dd05e2deae4120227e6efc&auto=format&fit=crop&w=1953&q=80',
32
-    'https://images.unsplash.com/photo-1508704019882-f9cf40e475b4?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=8c6e5e3aba713b17aa1fe71ab4f0ae5b&auto=format&fit=crop&w=1352&q=80',
33
-    'https://images.unsplash.com/photo-1519985176271-adb1088fa94c?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=a0c8d632e977f94e5d312d9893258f59&auto=format&fit=crop&w=1355&q=80'
34
-  ];
35
-
36
   @override
42
   @override
37
   Widget build(BuildContext context) {
43
   Widget build(BuildContext context) {
38
     return Container(
44
     return Container(
44
           //banner
50
           //banner
45
           Container(
51
           Container(
46
             margin: EdgeInsets.fromLTRB(0, 15.h, 0, 15.h),
52
             margin: EdgeInsets.fromLTRB(0, 15.h, 0, 15.h),
47
-            child: CarouselSlider(
48
-              items: imgList
49
-                  .map((item) => Container(
50
-                        child: Center(
51
-                            child: Image.network(item,
52
-                                fit: BoxFit.cover, width: 345.w)),
53
-                      ))
54
-                  .toList(),
55
-              options: CarouselOptions(
56
-                autoPlay: true,
57
-                enlargeCenterPage: false, //图片中心放大
58
-                viewportFraction: 1, //每个页面应占据的视口部分。默认为 0.8,这意味着每个页面填充 80% 的轮播。
59
-                // aspectRatio: 1.6,//纵横比
60
-                height: 214.w,
61
-                initialPage: 1, //初始页
62
-              ),
63
-            ),
53
+            child: Obx(() => CarouselSlider(
54
+                  items: bannerList.value
55
+                      .map((item) => Container(
56
+                            child: Center(
57
+                                child: Image.network(item.thumb.toString(),
58
+                                    fit: BoxFit.cover, width: 345.w)),
59
+                          ))
60
+                      .toList(),
61
+                  options: CarouselOptions(
62
+                    autoPlay: true,
63
+                    enlargeCenterPage: false, //图片中心放大
64
+                    viewportFraction:
65
+                        1, //每个页面应占据的视口部分。默认为 0.8,这意味着每个页面填充 80% 的轮播。
66
+                    // aspectRatio: 1.6,//纵横比
67
+                    height: 214.w,
68
+                    initialPage: 1, //初始页
69
+                  ),
70
+                )),
64
           ),
71
           ),
65
           Container(
72
           Container(
66
             margin: EdgeInsets.fromLTRB(0, 15.h, 0, 20.h),
73
             margin: EdgeInsets.fromLTRB(0, 15.h, 0, 20.h),
83
               ],
90
               ],
84
             ),
91
             ),
85
           ),
92
           ),
86
-          MyCard(),
93
+          Obx(
94
+            () => Column(
95
+              children: jobList.value
96
+                  .map(
97
+                    (item) => const MyCard(),
98
+                  )
99
+                  .toList(),
100
+            ),
101
+          ),
87
         ],
102
         ],
88
       ),
103
       ),
89
     );
104
     );

+ 0
- 1
lib/utils/Request.dart 查看文件

1
 import 'dart:convert';
1
 import 'dart:convert';
2
 
2
 
3
 import 'package:dio/dio.dart';
3
 import 'package:dio/dio.dart';
4
-import 'package:flutter/foundation.dart';
5
 import 'package:get/get.dart';
4
 import 'package:get/get.dart';
6
 import 'package:get_storage/get_storage.dart';
5
 import 'package:get_storage/get_storage.dart';
7
 
6
 

+ 22
- 0
lib/utils/amap/const_config.dart 查看文件

1
+import 'package:amap_flutter_base/amap_flutter_base.dart';
2
+import 'package:amap_flutter_map/amap_flutter_map.dart';
3
+
4
+class ConstConfig {
5
+  ///配置您申请的apikey,在此处配置之后,可以在初始化[AMapWidget]时,通过`apiKey`属性设置
6
+  ///
7
+  ///注意:使用[AMapWidget]的`apiKey`属性设置的key的优先级高于通过Native配置key的优先级,
8
+  ///使用[AMapWidget]的`apiKey`属性配置后Native配置的key将失效,请根据实际情况选择使用
9
+  static const AMapApiKey amapApiKeys = AMapApiKey(
10
+      androidKey: 'b481b4187e24e625fa0056fd0530e663',
11
+      iosKey: '您申请的iOS平台的key');
12
+
13
+  ///高德隐私合规声明,这里只是示例,实际使用中请按照实际参数设置[AMapPrivacyStatement]的'hasContains''hasShow''hasAgree'这三个参数
14
+  ///
15
+  /// 注意:[AMapPrivacyStatement]的'hasContains''hasShow''hasAgree'这三个参数中有一个为false,高德SDK均不会工作,会造成地图白屏等现象
16
+  ///
17
+  /// 高德开发者合规指南请参考:https://lbs.amap.com/agreement/compliance
18
+  ///
19
+  /// 高德SDK合规使用方案请参考:https://lbs.amap.com/news/sdkhgsy
20
+  static const AMapPrivacyStatement amapPrivacyStatement =
21
+  AMapPrivacyStatement(hasContains: true, hasShow: true, hasAgree: true);
22
+}

+ 92
- 16
lib/utils/location.dart 查看文件

1
-import 'package:location/location.dart';
2
-
3
-Future requireLocation() async {
4
-  Location location = Location();
5
-  bool _serviceEnabled;
6
-  PermissionStatus _permissionGranted;
7
-
8
-  _serviceEnabled = await location.serviceEnabled();
9
-  if (!_serviceEnabled) {
10
-    _serviceEnabled = await location.requestService();
11
-    if (!_serviceEnabled) {
12
-      throw Exception("请开启系统定位功能");
13
-    }
14
-  }
1
+import 'dart:async';
2
+
3
+import 'package:amap_flutter_location/amap_flutter_location.dart';
4
+import 'package:amap_flutter_location/amap_location_option.dart';
5
+import 'package:permission_handler/permission_handler.dart';
6
+
7
+import 'amap/const_config.dart';
8
+
9
+typedef AMAPListener = void Function (Map<String, Object>);
15
 
10
 
16
-  _permissionGranted = await location.hasPermission();
11
+void showPrivacy() {
12
+  /// 设置是否已经包含高德隐私政策并弹窗展示显示用户查看,如果未包含或者没有弹窗展示,高德定位SDK将不会工作
13
+  ///
14
+  /// 高德SDK合规使用方案请参考官网地址:https://lbs.amap.com/news/sdkhgsy
15
+  /// <b>必须保证在调用定位功能之前调用, 建议首次启动App时弹出《隐私政策》并取得用户同意</b>
16
+  ///
17
+  /// 高德SDK合规使用方案请参考官网地址:https://lbs.amap.com/news/sdkhgsy
18
+  ///
19
+  /// [hasContains] 隐私声明中是否包含高德隐私政策说明
20
+  ///
21
+  /// [hasShow] 隐私权政策是否弹窗展示告知用户
22
+  AMapFlutterLocation.updatePrivacyShow(true, true);
23
+
24
+  /// 设置是否已经取得用户同意,如果未取得用户同意,高德定位SDK将不会工作
25
+  ///
26
+  /// 高德SDK合规使用方案请参考官网地址:https://lbs.amap.com/news/sdkhgsy
27
+  ///
28
+  /// <b>必须保证在调用定位功能之前调用, 建议首次启动App时弹出《隐私政策》并取得用户同意</b>
29
+  ///
30
+  /// [hasAgree] 隐私权政策是否已经取得用户同意
31
+  AMapFlutterLocation.updatePrivacyAgree(true);
32
+}
33
+
34
+// 判断定位权限
35
+Future _requirePermission() async {
36
+  PermissionStatus _permissionGranted = await Permission.location.status;
17
   if (_permissionGranted == PermissionStatus.denied) {
37
   if (_permissionGranted == PermissionStatus.denied) {
18
-    _permissionGranted = await location.requestPermission();
38
+    // 如果未允许, 尝试申请一次
39
+    _permissionGranted = await Permission.location.request();
19
     if (_permissionGranted != PermissionStatus.granted) {
40
     if (_permissionGranted != PermissionStatus.granted) {
20
       throw Exception("请设置允许当前程序定位功能");
41
       throw Exception("请设置允许当前程序定位功能");
21
     }
42
     }
22
   }
43
   }
44
+}
45
+
46
+Future requireLocation(AMAPListener listener) async {
47
+  AMapFlutterLocation.setApiKey(ConstConfig.amapApiKeys.androidKey!, ConstConfig.amapApiKeys.iosKey!);
48
+  showPrivacy();
49
+  await _requirePermission();
50
+  final AMapFlutterLocation location = AMapFlutterLocation();
51
+  location.onLocationChanged().listen(listener);
52
+  location.setLocationOption(_getAMapLocationOption());
53
+  location.startLocation();
23
 
54
 
24
   return location;
55
   return location;
56
+}
57
+
58
+_getAMapLocationOption() {
59
+  AMapLocationOption locationOption = new AMapLocationOption();
60
+
61
+  ///是否单次定位
62
+  locationOption.onceLocation = false;
63
+
64
+  ///是否需要返回逆地理信息
65
+  locationOption.needAddress = true;
66
+
67
+  ///逆地理信息的语言类型
68
+  locationOption.geoLanguage = GeoLanguage.DEFAULT;
69
+
70
+  locationOption.desiredLocationAccuracyAuthorizationMode =
71
+      AMapLocationAccuracyAuthorizationMode.ReduceAccuracy;
72
+
73
+  locationOption.fullAccuracyPurposeKey = "AMapLocationScene";
74
+
75
+  ///设置Android端连续定位的定位间隔
76
+  locationOption.locationInterval = 2000;
77
+
78
+  ///设置Android端的定位模式<br>
79
+  ///可选值:<br>
80
+  ///<li>[AMapLocationMode.Battery_Saving]</li>
81
+  ///<li>[AMapLocationMode.Device_Sensors]</li>
82
+  ///<li>[AMapLocationMode.Hight_Accuracy]</li>
83
+  locationOption.locationMode = AMapLocationMode.Hight_Accuracy;
84
+
85
+  ///设置iOS端的定位最小更新距离<br>
86
+  locationOption.distanceFilter = -1;
87
+
88
+  ///设置iOS端期望的定位精度
89
+  /// 可选值:<br>
90
+  /// <li>[DesiredAccuracy.Best] 最高精度</li>
91
+  /// <li>[DesiredAccuracy.BestForNavigation] 适用于导航场景的高精度 </li>
92
+  /// <li>[DesiredAccuracy.NearestTenMeters] 10米 </li>
93
+  /// <li>[DesiredAccuracy.Kilometer] 1000米</li>
94
+  /// <li>[DesiredAccuracy.ThreeKilometers] 3000米</li>
95
+  locationOption.desiredAccuracy = DesiredAccuracy.Best;
96
+
97
+  ///设置iOS端是否允许系统暂停定位
98
+  locationOption.pausesLocationUpdatesAutomatically = false;
99
+
100
+  return locationOption;
25
 }
101
 }

+ 71
- 1
pubspec.lock 查看文件

8
       url: "https://pub.flutter-io.cn"
8
       url: "https://pub.flutter-io.cn"
9
     source: hosted
9
     source: hosted
10
     version: "39.0.0"
10
     version: "39.0.0"
11
+  amap_flutter_base:
12
+    dependency: transitive
13
+    description:
14
+      name: amap_flutter_base
15
+      url: "https://pub.flutter-io.cn"
16
+    source: hosted
17
+    version: "3.0.0"
18
+  amap_flutter_location:
19
+    dependency: "direct main"
20
+    description:
21
+      name: amap_flutter_location
22
+      url: "https://pub.flutter-io.cn"
23
+    source: hosted
24
+    version: "3.0.0"
25
+  amap_flutter_map:
26
+    dependency: "direct main"
27
+    description:
28
+      name: amap_flutter_map
29
+      url: "https://pub.flutter-io.cn"
30
+    source: hosted
31
+    version: "3.0.0"
11
   analyzer:
32
   analyzer:
12
     dependency: transitive
33
     dependency: transitive
13
     description:
34
     description:
56
       name: carousel_slider
77
       name: carousel_slider
57
       url: "https://pub.flutter-io.cn"
78
       url: "https://pub.flutter-io.cn"
58
     source: hosted
79
     source: hosted
59
-    version: "4.0.0"
80
+    version: "4.1.1"
60
   characters:
81
   characters:
61
     dependency: transitive
82
     dependency: transitive
62
     description:
83
     description:
160
       url: "https://pub.flutter-io.cn"
181
       url: "https://pub.flutter-io.cn"
161
     source: hosted
182
     source: hosted
162
     version: "1.0.4"
183
     version: "1.0.4"
184
+  flutter_plugin_android_lifecycle:
185
+    dependency: transitive
186
+    description:
187
+      name: flutter_plugin_android_lifecycle
188
+      url: "https://pub.flutter-io.cn"
189
+    source: hosted
190
+    version: "2.0.5"
163
   flutter_screenutil:
191
   flutter_screenutil:
164
     dependency: "direct main"
192
     dependency: "direct main"
165
     description:
193
     description:
352
       url: "https://pub.flutter-io.cn"
380
       url: "https://pub.flutter-io.cn"
353
     source: hosted
381
     source: hosted
354
     version: "2.0.5"
382
     version: "2.0.5"
383
+  permission_handler:
384
+    dependency: "direct main"
385
+    description:
386
+      name: permission_handler
387
+      url: "https://pub.flutter-io.cn"
388
+    source: hosted
389
+    version: "9.2.0"
390
+  permission_handler_android:
391
+    dependency: transitive
392
+    description:
393
+      name: permission_handler_android
394
+      url: "https://pub.flutter-io.cn"
395
+    source: hosted
396
+    version: "9.0.2+1"
397
+  permission_handler_apple:
398
+    dependency: transitive
399
+    description:
400
+      name: permission_handler_apple
401
+      url: "https://pub.flutter-io.cn"
402
+    source: hosted
403
+    version: "9.0.4"
404
+  permission_handler_platform_interface:
405
+    dependency: transitive
406
+    description:
407
+      name: permission_handler_platform_interface
408
+      url: "https://pub.flutter-io.cn"
409
+    source: hosted
410
+    version: "3.7.0"
411
+  permission_handler_windows:
412
+    dependency: transitive
413
+    description:
414
+      name: permission_handler_windows
415
+      url: "https://pub.flutter-io.cn"
416
+    source: hosted
417
+    version: "0.1.0"
355
   platform:
418
   platform:
356
     dependency: transitive
419
     dependency: transitive
357
     description:
420
     description:
427
       url: "https://pub.flutter-io.cn"
490
       url: "https://pub.flutter-io.cn"
428
     source: hosted
491
     source: hosted
429
     version: "2.1.0"
492
     version: "2.1.0"
493
+  stream_transform:
494
+    dependency: transitive
495
+    description:
496
+      name: stream_transform
497
+      url: "https://pub.flutter-io.cn"
498
+    source: hosted
499
+    version: "2.0.0"
430
   string_scanner:
500
   string_scanner:
431
     dependency: transitive
501
     dependency: transitive
432
     description:
502
     description:

+ 6
- 0
pubspec.yaml 查看文件

42
   fluttertoast: ^8.0.9
42
   fluttertoast: ^8.0.9
43
   get_storage: ^2.0.3
43
   get_storage: ^2.0.3
44
   carousel_slider: ^4.0.0
44
   carousel_slider: ^4.0.0
45
+#  location: ^4.3.0
46
+  amap_flutter_map: ^3.0.0
47
+  amap_flutter_location: ^3.0.0
48
+  permission_handler: ^9.2.0
49
+
50
+
45
 dev_dependencies:
51
 dev_dependencies:
46
   flutter_test:
52
   flutter_test:
47
     sdk: flutter
53
     sdk: flutter