李志伟 3 lat temu
rodzic
commit
795ee60586

+ 28
- 14
android/app/build.gradle Wyświetl plik

@@ -26,35 +26,51 @@ apply plugin: 'kotlin-android'
26 26
 apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
27 27
 
28 28
 android {
29
-    compileSdkVersion flutter.compileSdkVersion
29
+    compileSdkVersion 31
30 30
 
31 31
     compileOptions {
32 32
         sourceCompatibility JavaVersion.VERSION_1_8
33 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 36
     defaultConfig {
45 37
         // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
46 38
         applicationId "com.example.worker_client"
47
-        minSdkVersion flutter.minSdkVersion
48
-        targetSdkVersion flutter.targetSdkVersion
39
+        minSdkVersion 21
40
+        targetSdkVersion 28
49 41
         versionCode flutterVersionCode.toInteger()
50 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 62
     buildTypes {
63
+        debug {
64
+            minifyEnabled false
65
+        }
54 66
         release {
55 67
             // TODO: Add your own signing config for the release build.
56 68
             // Signing with the debug keys for now, so `flutter run --release` works.
57 69
             signingConfig signingConfigs.debug
70
+
71
+            //关闭混淆, 否则在运行release包后可能出现运行崩溃, TODO后续进行混淆配置
72
+            minifyEnabled false //删除无用代码
73
+            shrinkResources false //删除无用资源
58 74
         }
59 75
     }
60 76
 }
@@ -63,6 +79,4 @@ flutter {
63 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 Wyświetl plik

@@ -1,5 +1,29 @@
1 1
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
+    xmlns:tools="http://schemas.android.com/tools"
2 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 27
    <application
4 28
         android:label="worker_client"
5 29
         android:name="${applicationName}"
@@ -30,5 +54,10 @@
30 54
         <meta-data
31 55
             android:name="flutterEmbedding"
32 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 62
     </application>
34 63
 </manifest>

BIN
android/app/src/main/res/drawable/launch_image.png Wyświetl plik


BIN
android/app/src/main/res/mipmap-hdpi/ic_launcher.png Wyświetl plik


BIN
android/app/src/main/res/mipmap-mdpi/ic_launcher.png Wyświetl plik


BIN
android/app/src/main/res/mipmap-xhdpi/ic_launcher.png Wyświetl plik


BIN
android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png Wyświetl plik


BIN
android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png Wyświetl plik


+ 1
- 1
android/app/src/main/res/values/styles.xml Wyświetl plik

@@ -4,7 +4,7 @@
4 4
     <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
5 5
         <!-- Show a splash screen on the activity. Automatically removed when
6 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 8
     </style>
9 9
     <!-- Theme applied to the Android Window as soon as the process has started.
10 10
          This theme determines the color of the Android Window while your

+ 33
- 15
lib/models/app.dart Wyświetl plik

@@ -1,10 +1,10 @@
1 1
 
2 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 7
 import 'package:get/get.dart';
6
-import 'package:location/location.dart';
7
-import '../services/user.dart';
8 8
 import '../utils/location.dart';
9 9
 
10 10
 class AppController extends GetxController {
@@ -12,31 +12,42 @@ class AppController extends GetxController {
12 12
   static AppController t = Get.find();
13 13
 
14 14
   final user = Rx<Person>(Person());
15
-  final location = Rxn<LocationData>();
15
+  final location = Rxn<Map<String, Object>>();
16 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 33
   @override
19 34
   void onInit() {
20 35
     super.onInit();
21 36
 
22 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 40
     }).catchError((e) {
32 41
       print(e);
33
-      Get.defaultDialog(
34
-        title: e.message,
42
+
43
+      showAlert(
44
+        title: '获取定位失败',
45
+        message: e.message,
35 46
         onConfirm: () => exit(1),
36 47
       );
37 48
     });
38 49
 
39
-    // 尝试获取一次人员信息
50
+    // // 尝试获取一次人员信息
40 51
     // getCurrent().then((person) {
41 52
     //   user(person);
42 53
     // }).catchError((e) {
@@ -44,4 +55,11 @@ class AppController extends GetxController {
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 Wyświetl plik

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

+ 172
- 170
lib/pages/Login/index.dart Wyświetl plik

@@ -104,114 +104,61 @@ class _Login extends State<Login> {
104 104
   Widget build(BuildContext context) {
105 105
     return Scaffold(
106 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 135
                   child: Text(
122
-                    '登录',
136
+                    '您好!',
123 137
                     style: TextStyle(
124 138
                       letterSpacing: 3,
125 139
                       fontWeight: FontWeight.bold,
140
+                      fontSize: 33.sp,
126 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 147
                   style: TextStyle(
137 148
                     letterSpacing: 3,
138 149
                     fontWeight: FontWeight.bold,
139
-                    fontSize: 33.sp,
150
+                    fontSize: 27.sp,
140 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 164
                   child: TextField(
@@ -225,101 +172,156 @@ class _Login extends State<Login> {
225 172
                       isCollapsed: true,
226 173
                       contentPadding: EdgeInsets.symmetric(
227 174
                           horizontal: 15.5.w, vertical: 19.h),
228
-                      labelText: "请输入验证码",
175
+                      labelText: "请输入手机号码",
229 176
                       counterText: '', //去掉右下角的东西
230 177
                       border: InputBorder.none,
231 178
                       floatingLabelBehavior: FloatingLabelBehavior.never,
232 179
                     ),
233 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 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 310
                                 style: TextStyle(
299
-                                  color: const Color(0xFF02902E),
311
+                                  color: const Color(0xFF999999),
300 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 Wyświetl plik

@@ -1,11 +1,12 @@
1
-import 'dart:math';
2
-
3 1
 import 'package:carousel_slider/carousel_slider.dart';
4 2
 import 'package:flutter/material.dart';
5 3
 import 'package:flutter_screenutil/flutter_screenutil.dart';
6 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 7
 import 'package:worker_client/pages/home/widgets/home/widgets/headers.dart';
8 8
 import 'package:worker_client/services/banner.dart';
9
+import 'package:worker_client/services/job.dart';
9 10
 import 'package:worker_client/widgets/MyCard/index.dart';
10 11
 
11 12
 class HomePage extends StatefulWidget {
@@ -16,23 +17,28 @@ class HomePage extends StatefulWidget {
16 17
 }
17 18
 
18 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 23
   @override
21 24
   void initState() {
22 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 42
   @override
37 43
   Widget build(BuildContext context) {
38 44
     return Container(
@@ -44,23 +50,24 @@ class _HomePageState extends State<HomePage> {
44 50
           //banner
45 51
           Container(
46 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 72
           Container(
66 73
             margin: EdgeInsets.fromLTRB(0, 15.h, 0, 20.h),
@@ -83,7 +90,15 @@ class _HomePageState extends State<HomePage> {
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 Wyświetl plik

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

+ 22
- 0
lib/utils/amap/const_config.dart Wyświetl plik

@@ -0,0 +1,22 @@
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 Wyświetl plik

@@ -1,25 +1,101 @@
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 37
   if (_permissionGranted == PermissionStatus.denied) {
18
-    _permissionGranted = await location.requestPermission();
38
+    // 如果未允许, 尝试申请一次
39
+    _permissionGranted = await Permission.location.request();
19 40
     if (_permissionGranted != PermissionStatus.granted) {
20 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 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 Wyświetl plik

@@ -8,6 +8,27 @@ packages:
8 8
       url: "https://pub.flutter-io.cn"
9 9
     source: hosted
10 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 32
   analyzer:
12 33
     dependency: transitive
13 34
     description:
@@ -56,7 +77,7 @@ packages:
56 77
       name: carousel_slider
57 78
       url: "https://pub.flutter-io.cn"
58 79
     source: hosted
59
-    version: "4.0.0"
80
+    version: "4.1.1"
60 81
   characters:
61 82
     dependency: transitive
62 83
     description:
@@ -160,6 +181,13 @@ packages:
160 181
       url: "https://pub.flutter-io.cn"
161 182
     source: hosted
162 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 191
   flutter_screenutil:
164 192
     dependency: "direct main"
165 193
     description:
@@ -352,6 +380,41 @@ packages:
352 380
       url: "https://pub.flutter-io.cn"
353 381
     source: hosted
354 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 418
   platform:
356 419
     dependency: transitive
357 420
     description:
@@ -427,6 +490,13 @@ packages:
427 490
       url: "https://pub.flutter-io.cn"
428 491
     source: hosted
429 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 500
   string_scanner:
431 501
     dependency: transitive
432 502
     description:

+ 6
- 0
pubspec.yaml Wyświetl plik

@@ -42,6 +42,12 @@ dependencies:
42 42
   fluttertoast: ^8.0.9
43 43
   get_storage: ^2.0.3
44 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 51
 dev_dependencies:
46 52
   flutter_test:
47 53
     sdk: flutter