Browse Source

v1版本

master
dong 1 month ago
parent
commit
7dbf54d9ee

+ 1
- 2
api/index.js View File

@@ -37,7 +37,7 @@ function request(url, method, data, options = {}) {
37 37
       success: (res) => {
38 38
         console.log(res);
39 39
         // Token 失效或未授权
40
-        if ([320, 400, 401, 403].includes(res.statusCode)) {
40
+        if ([320, 400, 401, 403].includes(res.data.code)) {
41 41
           handleTokenInvalid(res.data.msg || '登录已过期');
42 42
           reject(res.data);
43 43
           return;
@@ -58,7 +58,6 @@ function request(url, method, data, options = {}) {
58 58
     });
59 59
   });
60 60
 }
61
-
62 61
 // 跳转到登录页
63 62
 function redirectToLogin(message = '') {
64 63
   wx.clearStorageSync();

+ 102
- 250
app.js View File

@@ -1,5 +1,5 @@
1 1
 // app.js
2
-const api = require('./api/index.js'); // 注意路径
2
+const api = require('./api/index.js');
3 3
 App({
4 4
   globalData: {
5 5
     socketTask: null,
@@ -11,15 +11,21 @@ App({
11 11
   },
12 12
 
13 13
   onLaunch() {
14
-    // wx.setStorageSync('user', { userId: 'driver_1001', operationRole: 4 }); 
15 14
     this.initWebSocketService();
16 15
     wx.onAppShow(() => this.handleAppShow());
17 16
     wx.onAppHide(() => this.handleAppHide());
17
+
18 18
     this.locationService = {
19 19
       isTracking: false,
20
-      currentWorkorderId: '', // 存储当前跟踪的工单ID
21
-      isLocationUpdateStarted: false // 标记是否已启动定位服务
20
+      currentWorkorderId: '',
21
+      isLocationUpdateStarted: false
22 22
     };
23
+
24
+    // 司机自动启动【普通实时定位上传】
25
+    const { operationRole } = this.globalData.userInfo;
26
+    if (operationRole === 4) {
27
+      this.startDriverRealTimeLocation();
28
+    }
23 29
   },
24 30
 
25 31
   initWebSocketService() {
@@ -31,15 +37,12 @@ App({
31 37
             that.wsService.close();
32 38
           }
33 39
 
34
-          console.log('正在连接WebSocket:', url);
35 40
           const socketTask = wx.connectSocket({ url, header: { 'content-type': 'application/json' } });
36 41
 
37 42
           socketTask.onOpen(() => {
38
-            console.log('WebSocket 连接成功');
39 43
             that.globalData.isConnected = true;
40 44
             that.globalData.socketTask = socketTask;
41 45
             that.clearReconnectTimer();
42
-            // that.startHeartbeat();
43 46
             if (that.globalData.currentWorkorderId) {
44 47
               that.wsService.send({ type: 'subscribe', workorderId: that.globalData.currentWorkorderId });
45 48
             }
@@ -48,53 +51,38 @@ App({
48 51
 
49 52
           socketTask.onMessage((res) => {
50 53
             try {
51
-              console.log(res);
52 54
               const message = JSON.parse(res.data);
53
-              console.log('收到消息:', message);
54 55
               wx.$emit('wsMessage', message);
55
-            } catch (err) { console.error('消息解析失败', err); }
56
+            } catch (err) { }
56 57
           });
57 58
 
58 59
           socketTask.onClose((res) => {
59
-            console.log('WebSocket 连接关闭, 状态码:', res.code);
60 60
             that.globalData.isConnected = false;
61 61
             that.globalData.socketTask = null;
62 62
             that.stopHeartbeat();
63
-            wx.$emit('socketClose');
64
-            if (res.code !== 1000) { that.startReconnect(); }
63
+            if (res.code !== 1000) that.startReconnect();
65 64
           });
66 65
 
67 66
           socketTask.onError((err) => {
68
-            console.error('WebSocket 连接错误:', err);
69 67
             that.globalData.isConnected = false;
70 68
             that.globalData.socketTask = null;
71 69
             that.stopHeartbeat();
72
-            wx.$emit('socketError', err);
73 70
           });
74 71
         },
75 72
 
76 73
         send: (data) => {
77 74
           const that = this;
78 75
           if (that.globalData.isConnected && that.globalData.socketTask) {
79
-            try {
80
-              that.globalData.socketTask.send({
81
-                data: JSON.stringify(data),
82
-                fail: (err) => {
83
-                  console.error('消息发送失败:', err);
84
-                  wx.showToast({ title: '消息发送失败', icon: 'none' });
85
-                }
86
-              });
87
-            } catch (e) { console.error('消息序列化失败:', e); }
88
-          } else {
89
-            console.warn('WebSocket 未连接');
90
-            wx.showToast({ title: '网络连接中...', icon: 'none' });
76
+            that.globalData.socketTask.send({
77
+              data: JSON.stringify(data),
78
+              fail: (err) => console.error('发送失败', err)
79
+            });
91 80
           }
92 81
         },
93 82
 
94 83
         close: (code = 1000, reason = 'normal close') => {
95 84
           const that = this;
96 85
           if (that.globalData.socketTask) {
97
-            console.log(`关闭WebSocket连接: ${code} - ${reason}`);
98 86
             that.globalData.socketTask.close({ code, reason });
99 87
           }
100 88
         }
@@ -104,25 +92,15 @@ App({
104 92
 
105 93
   handleAppShow() {
106 94
     const that = this;
107
-    console.log(!that.globalData.isConnected);
108
-    console.log(!that.globalData.reconnectTimer);
109 95
     if (!that.globalData.isConnected && !that.globalData.reconnectTimer) {
110
-      const { operationId, operationRole } = that.globalData.userInfo;
111
-      console.log(operationRole);
112
-      // 修复:startReconnect 中用了 operationId,这里统一字段
113
-      if (!operationId) {
114
-        console.error('用户operationId不存在,无法连接WebSocket');
115
-        return;
116
-      }
96
+      const { operationId } = that.globalData.userInfo;
97
+      if (!operationId) return;
117 98
       const wsUrl = `wss://esos-iot.com:9443/communication/update/${operationId}`;
118 99
       that.wsService.connect(wsUrl);
119 100
     }
120 101
   },
121 102
 
122
-  handleAppHide() {
123
-    // 可以选择在后台关闭连接
124
-    // this.wsService.close(1001, 'app enter background');
125
-  },
103
+  handleAppHide() { },
126 104
 
127 105
   startHeartbeat() {
128 106
     const that = this;
@@ -147,8 +125,7 @@ App({
147 125
     let delay = 1000;
148 126
     that.globalData.reconnectTimer = setInterval(() => {
149 127
       if (!that.globalData.isConnected) {
150
-        console.log(`尝试重连 in ${delay}ms...`);
151
-        const { operationId, operationRole } = that.globalData.userInfo; // 修复:用 operationId 而非 userId
128
+        const { operationId } = that.globalData.userInfo;
152 129
         if (operationId) {
153 130
           const wsUrl = `wss://esos-iot.com:9443/communication/update/${operationId}`;
154 131
           that.wsService.connect(wsUrl);
@@ -167,208 +144,91 @@ App({
167 144
     }
168 145
   },
169 146
 
170
-  /**
171
-   * 司机端开始后台定位并上传(单工单)
172
-   * @param {string} workorderId - 当前工单ID
173
-   */
174
-  startDriverLocationUpload(workorderId) {
175
-    const service = this.locationService;
147
+  /****************************************************************************
148
+   * 1. 司机【普通实时定位】(一直上传,不绑定工单)
149
+   ***************************************************************************/
150
+  startDriverRealTimeLocation() {
151
+    const { operationRole } = this.globalData.userInfo;
152
+    if (operationRole !== 4) return;
176 153
 
177
-    // 入参校验
178
-    if (!workorderId) {
179
-      console.error('工单ID不能为空');
180
-      wx.showToast({ title: '工单ID异常', icon: 'none' });
181
-      return;
182
-    }
183
-
184
-    // 如果已经在为当前工单上传,则忽略
185
-    if (service.isTracking && service.currentWorkorderId === workorderId) {
186
-      console.log(`已经在为工单 ${workorderId} 上传位置`);
187
-      return;
188
-    }
189
-
190
-    // 如果已经在为其他工单上传,先停止
191
-    if (service.isTracking && service.currentWorkorderId !== workorderId) {
192
-      console.log(`当前正在为工单 ${service.currentWorkorderId} 上传,切换到 ${workorderId},先停止旧定位`);
193
-      this.stopDriverLocationUpload();
194
-    }
195
-
196
-    // 权限校验
197
-    wx.getSetting({
198
-      success: (res) => {
199
-        if (!res.authSetting['scope.userLocationBackground']) {
200
-          wx.authorize({
201
-            scope: 'scope.userLocationBackground',
202
-            success: () => {
203
-              this._doStartLocationUpload(workorderId, service);
204
-            },
205
-            fail: () => {
206
-              wx.showModal({
207
-                title: '权限不足',
208
-                content: '需要开启后台定位权限才能实时上传位置,请前往设置页开启',
209
-                confirmText: '去设置',
210
-                success: (modalRes) => {
211
-                  if (modalRes.confirm) {
212
-                    wx.openSetting({
213
-                      success: (settingRes) => {
214
-                        if (settingRes.authSetting['scope.userLocationBackground']) {
215
-                          this._doStartLocationUpload(workorderId, service);
216
-                        }
217
-                      }
218
-                    });
219
-                  }
220
-                }
221
-              });
222
-            } 
223
-          });
224
-        } else {
225
-          this._doStartLocationUpload(workorderId, service);
226
-        }
227
-      }
228
-    });
229
-  },
230
-
231
-  /**
232
-   * 私有方法:执行真正的定位启动逻辑(核心修复:兼容低版本,改用 wx.onLocationChange)
233
-   */
234
- 
235
-  _doStartLocationUpload(workorderId, service) {
236
-    console.log(`开始为工单 ${workorderId} 启动后台定位上传...`);
237
-    service.currentWorkorderId = workorderId;
238
-
239
-    // 修复1:先移除旧的定位监听(防止重复监听)
154
+    const service = this.locationService;
240 155
     this._removeLocationListener();
241 156
 
242
-    // 修复2:启动后台定位(兼容低版本,用 startLocationUpdate 兜底)
243 157
     const startLocationApi = wx.startLocationUpdateBackground || wx.startLocationUpdate;
244 158
     startLocationApi({
245 159
       type: 'gcj02',
246
-      success: (res) => {
247
-        console.log('定位服务已启动', res);
160
+      success: () => {
248 161
         service.isLocationUpdateStarted = true;
249
-// 存储上一次的定位信息
250
-let lastLocation = null;
251
-// 距离阈值(单位:米,根据需求调整,5米)
252
-const DISTANCE_THRESHOLD = 5;
253
-        // 修复3:改用低版本支持的 wx.onLocationChange(替代 wx.watchPosition)
162
+        let lastLocation = null;
163
+        const DISTANCE_THRESHOLD = 5;
164
+
254 165
         wx.onLocationChange((location) => {
255
-          if (!lastLocation) {
256
-            lastLocation = location;
257
-            console.log('位置变化,准备上传:', location);
258
-            this._uploadLocation(location, workorderId);
259
-            return;
166
+          // 距离过滤
167
+          if (lastLocation) {
168
+            const distance = this.calculateDistance(
169
+              lastLocation.latitude, lastLocation.longitude,
170
+              location.latitude, location.longitude
171
+            );
172
+            if (distance < DISTANCE_THRESHOLD) return;
173
+          }
174
+          lastLocation = location;
175
+
176
+          // 统一上传:实时位置 + 有工单就工单一起传
177
+          this._uploadRealTimeLocation(location);
178
+          if (service.currentWorkorderId) {
179
+            this._uploadWorkorderLocation(location, service.currentWorkorderId);
260 180
           }
261
-        // 计算当前定位与上一次的直线距离(Haversine公式)
262
-  const distance = this.calculateDistance(
263
-    lastLocation.latitude,
264
-    lastLocation.longitude,
265
-    location.latitude,
266
-    location.longitude
267
-  );
268
-console.log(distance);
269
-  // 只有距离超过阈值,才认为是“有效变化”
270
-  if (distance >= DISTANCE_THRESHOLD) {
271
-    lastLocation = location; // 更新上一次定位
272
-    this._uploadLocation(location, workorderId);
273
-  }  
274
-      
275 181
         });
276
-        // 标记定位中状态
277
-        service.isTracking = true;
278
-        console.log('位置监听已注册,开始实时上传');
279
-      },
280
-      fail: (err) => {
281
-        let errMsg = '启动定位失败';
282
-        if (err.errMsg.includes('auth deny')) errMsg = '定位权限被拒绝';
283
-        else if (err.errMsg.includes('system')) errMsg = '系统不支持定位';
284
-        
285
-        console.error(errMsg, err);
286
-        wx.showToast({ title: errMsg, icon: 'none', duration: 2000 });
287 182
       }
288 183
     });
289 184
   },
290 185
 
291
-// Haversine公式:计算两点经纬度之间的直线距离(单位:米)
292
- calculateDistance(lat1, lng1, lat2, lng2) {
293
-  const R = 6371000; // 地球半径(米)
294
-  const radLat1 = (lat1 * Math.PI) / 180;
295
-  const radLat2 = (lat2 * Math.PI) / 180;
296
-  const deltaLat = radLat2 - radLat1;
297
-  const deltaLng = (lng2 - lng1) * Math.PI / 180;
298
-
299
-  const a = 
300
-    Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) +
301
-    Math.cos(radLat1) * Math.cos(radLat2) *
302
-    Math.sin(deltaLng / 2) * Math.sin(deltaLng / 2);
303
-  
304
-  const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
305
-  return R * c; // 距离(米)
306
-},
307
-  /**
308
-   * 司机端停止定位上传(核心修复:对应移除 wx.onLocationChange 监听)
309
-   */
310
-  stopDriverLocationUpload() {
186
+  /****************************************************************************
187
+   * 2. 司机【开始执行工单】(绑定工单,额外上传工单位置)
188
+   ***************************************************************************/
189
+  startDriverWorkorderLocation(workorderId) {
190
+    if (!workorderId) return;
311 191
     const service = this.locationService;
192
+    service.currentWorkorderId = workorderId;
193
+  },
312 194
 
313
-    if (!service.isTracking) {
314
-      return;
315
-    }
316
-
317
-    console.log(`停止为工单 ${service.currentWorkorderId} 上传位置`);
318
-
319
-    // 1. 移除位置监听(wx.onLocationChange 对应 wx.offLocationChange)
320
-    this._removeLocationListener();
321
-
322
-    // 2. 停止定位服务(兼容低版本,用 stopLocationUpdate 兜底)
323
-    this._stopLocationService();
324
-
325
-    // 3. 重置状态
326
-    service.isTracking = false;
195
+  /****************************************************************************
196
+   * 3. 停止工单定位(只停止工单,不影响实时定位上传)
197
+   ***************************************************************************/
198
+  stopDriverWorkorderLocation() {
199
+    const service = this.locationService;
327 200
     service.currentWorkorderId = '';
328
-    service.isLocationUpdateStarted = false;
329 201
   },
330 202
 
331
-  /**
332
-   * 私有方法:移除位置监听(兼容低版本)
333
-   */
334
-  _removeLocationListener() {
335
-    if (wx.offLocationChange) {
336
-      wx.offLocationChange();
337
-      console.log('位置监听已移除');
338
-    } else {
339
-      console.warn('当前基础库不支持 wx.offLocationChange,可能存在重复监听风险');
340
-    }
341
-  },
203
+  /****************************************************************************
204
+   * 上传:司机实时位置(一直传)
205
+   ***************************************************************************/
206
+  _uploadRealTimeLocation(location) {
207
+    const { operationRole } = this.globalData.userInfo;
208
+    if (operationRole !== 4) return;
342 209
 
343
-  /**
344
-   * 私有方法:统一停止定位服务(兼容低版本)
345
-   */
346
-  _stopLocationService() {
347
-    const stopLocationApi = wx.stopLocationUpdateBackground || wx.stopLocationUpdate;
348
-    if (stopLocationApi && this.locationService.isLocationUpdateStarted) {
349
-      stopLocationApi({
350
-        success: (res) => {
351
-          console.log('定位服务已停止', res);
352
-        },
353
-        fail: (err) => {
354
-          console.error('停止定位服务失败:', err);
355
-        }
356
-      });
357
-    }
210
+    const latOk = location.latitude >= 3.86 && location.latitude <= 53.55;
211
+    const lngOk = location.longitude >= 73.66 && location.longitude <= 135.05;
212
+    if (!latOk || !lngOk) return;
213
+
214
+    const data = {
215
+      userType: operationRole,
216
+      latitude: location.latitude,
217
+      longitude: location.longitude,
218
+      accuracy: location.accuracy,
219
+      createTime: Date.now()
220
+    };
221
+    api.request('/sysoperation/inseroperationlocation', 'post', data, { isPublic: false })
222
+      .catch(err => console.error('实时位置上传失败', err));
358 223
   },
359 224
 
360
-  /**
361
-   * 私有方法:上传位置到服务器(无改动)
362
-   */
363
-  _uploadLocation(location, workorderId, retryCount = 0) {
364
-    const maxRetry = 2;
365
-    const isLatValid = location.latitude >= 3.86 && location.latitude <= 53.55;
366
-    const isLngValid = location.longitude >= 73.66 && location.longitude <= 135.05;
367
-
368
-    if (!isLatValid || !isLngValid) {
369
-      console.warn(`无效位置信息(工单: ${workorderId}),跳过上传`, location);
370
-      return;
371
-    }
225
+  /****************************************************************************
226
+   * 上传:工单位置(执行工单时才传)
227
+   ***************************************************************************/
228
+  _uploadWorkorderLocation(location, workorderId) {
229
+    const latOk = location.latitude >= 3.86 && location.latitude <= 53.55;
230
+    const lngOk = location.longitude >= 73.66 && location.longitude <= 135.05;
231
+    if (!latOk || !lngOk) return;
372 232
 
373 233
     const data = {
374 234
       workorderId: workorderId,
@@ -377,25 +237,23 @@ console.log(distance);
377 237
       createTime: Date.now(),
378 238
       accuracy: location.accuracy
379 239
     };
240
+    api.request('/sysworkorder/insercoordinateredis', 'post', data, { isPublic: false })
241
+      .catch(err => console.error('工单位置上传失败', err));
242
+  },
380 243
 
381
-    api.request(`/sysworkorder/insercoordinateredis`, 'post', data, { isPublic: false })
382
-      .then((response) => {
383
-        if (response.code !== 200) {
384
-          throw new Error(`响应码异常: ${response.code}`);
385
-        }
386
-        console.log(`位置上传成功 (工单: ${workorderId})`, data);
387
-      })
388
-      .catch((err) => {
389
-        console.error(`位置上传失败(第${retryCount+1}次)(工单: ${workorderId})`, err);
390
-        if (retryCount < maxRetry) {
391
-          setTimeout(() => {
392
-            this._uploadLocation(location, workorderId, retryCount + 1);
393
-          }, 10000 * (retryCount + 1));
394
-        } else {
395
-          wx.showToast({ title: '位置上传失败,请检查网络', icon: 'none' });
396
-        }
397
-      });
244
+  calculateDistance(lat1, lng1, lat2, lng2) {
245
+    const R = 6371000;
246
+    const radLat1 = lat1 * Math.PI / 180;
247
+    const radLat2 = lat2 * Math.PI / 180;
248
+    const dLat = radLat2 - radLat1;
249
+    const dLng = (lng2 - lng1) * Math.PI / 180;
250
+    const a = Math.sin(dLat / 2) ** 2 + Math.cos(radLat1) * Math.cos(radLat2) * Math.sin(dLng / 2) ** 2;
251
+    return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
398 252
   },
253
+
254
+  _removeLocationListener() {
255
+    if (wx.offLocationChange) wx.offLocationChange();
256
+  }
399 257
 });
400 258
 
401 259
 // 全局事件总线
@@ -404,18 +262,12 @@ wx.$on = function (eventName, callback) {
404 262
   if (!this.$events[eventName]) this.$events[eventName] = [];
405 263
   this.$events[eventName].push(callback);
406 264
 };
407
-
408 265
 wx.$emit = function (eventName, data) {
409 266
   if (!this.$events || !this.$events[eventName]) return;
410
-  this.$events[eventName].forEach(callback => callback(data));
267
+  this.$events[eventName].forEach(cb => cb(data));
411 268
 };
412
-
413 269
 wx.$off = function (eventName, callback) {
414 270
   if (!this.$events || !this.$events[eventName]) return;
415
-  if (callback) {
416
-    this.$events[eventName] = this.$events[eventName].filter(cb => cb !== callback);
417
-  } else {
418
-    this.$events[eventName] = [];
419
-  }
420
-};
421
-
271
+  if (callback) this.$events[eventName] = this.$events[eventName].filter(cb => cb !== callback);
272
+  else this.$events[eventName] = [];
273
+};

+ 3
- 1
app.json View File

@@ -5,7 +5,9 @@
5 5
     "pages/tool/index",
6 6
     "pages/equipment/index",
7 7
     "pages/balance/index",
8
-    "pages/details/index"
8
+    "pages/details/index",
9
+    "pages/projectlist/index",
10
+    "pages/projectdetails/index"
9 11
   ],
10 12
   "requiredBackgroundModes": ["location"],
11 13
  

+ 3
- 14
package-map/pages/map/index.js View File

@@ -85,7 +85,7 @@ Page({
85 85
     // 创建地图上下文
86 86
     this.mapCtx = wx.createMapContext('map');
87 87
   },
88
-  
88
+// 
89 89
   onLoad(options) {
90 90
     // 监听WebSocket消息
91 91
     wx.$on('wsMessage', this.detailsWsMessage);
@@ -207,7 +207,7 @@ Page({
207 207
             if (this.data.isDriver) {
208 208
               // 如果工单状态变为进行中 (1-4),且之前未在上传,则启动上传
209 209
               if (data.data.workorderType >= 1 && data.data.workorderType <= 2) {
210
-                app.startDriverLocationUpload(this.data.optionsid);
210
+                app.startDriverWorkorderLocation(this.data.optionsid);
211 211
                 this.showInfo('已开启实时位置上传');
212 212
               } 
213 213
             }
@@ -1040,18 +1040,7 @@ success(res) {
1040 1040
     api.request(`/sysworkorder/submitworkorder`, 'post', data, { isPublic: false })
1041 1041
       .then((data) => {
1042 1042
         if (data.code == 200) {
1043
-          // if (this.data.isDriver && type == 4) {
1044
-          //   wx.stopLocationUpdateBackground({
1045
-          //     success: (res) => {
1046
-          //       console.log('后台定位已停止', res);
1047
-          //       this.showInfo(this.data.isDriver ? '已停止定位追踪' : '已停止位置追踪');
1048
-          //     },
1049
-          //     fail: (err) => {
1050
-          //       console.error('停止后台定位失败', err);
1051
-          //     },
1052
-          //   });
1053
-          //   wx.offLocationChange();
1054
-          // }
1043
+          app.stopDriverWorkorderLocation();
1055 1044
           setTimeout(() => {
1056 1045
             const slideComponent = this.selectComponent("#mySlideConfirm");
1057 1046
             if (slideComponent) {

+ 6
- 3
package-user/pages/login/index.js View File

@@ -20,7 +20,7 @@ password:'',
20 20
 passwordtype:true,
21 21
 checked:false,
22 22
 shakeClass: '', // 控制晃动动画的类名
23
-Loginswitch:true
23
+Loginswitch:true,
24 24
   },
25 25
 
26 26
   /**
@@ -48,7 +48,9 @@ Loginswitch:true
48 48
   checkboxChange(e) {
49 49
     let _this = this
50 50
     console.log('checkbox发生change事件,携带value值为:', e.currentTarget.dataset.value)
51
- 
51
+   if (e.currentTarget.dataset.value) {
52
+     return
53
+   }
52 54
    wx.requestSubscribeMessage({
53 55
     tmplIds: ['t46217wOQ7HBvw0MfP78Zo8FuwYTKBESaGYIpaXccFw','lLN0xmyLgBSnvveLAOhHiEHvHUi286idSuv-kO61TMI'],
54 56
     success(res) {
@@ -130,7 +132,8 @@ onGetPhoneNumber(e) {
130 132
       let obj = {
131 133
         // phonecode:e.detail.code,
132 134
         phonecode:this.data.account,
133
-        code:code
135
+        code:code,
136
+        password:this.data.password
134 137
       }
135 138
       api.request(`/sysoperation/login`, 'post',obj,{ isPublic: true })
136 139
       .then((data) => {

+ 8
- 3
package-user/pages/login/index.wxml View File

@@ -19,15 +19,20 @@
19 19
  </view>
20 20
 
21 21
  </view>
22
-
22
+ <view style="padding:0rpx 20rpx;">
23
+  <view class="account">登录密码</view>
24
+  <view class="password">
25
+  <image class="login_imgae1" src="https://esos-iot.com/wx_images/password.png" mode=""/>
26
+  <input class="weui-input"	value="{{password}}" placeholder="请输入登录密码"  bindinput="bindKeyInput2"/></view>
27
+ </view>
23 28
  <view class="loginbotton">
24 29
   <!-- <button wx:if="{{!Loginswitch}}" class="button_button" open-type="getPhoneNumber" bindgetphonenumber="onGetPhoneNumber">手机号一键登录</button> -->
25 30
  
26 31
  <!-- <button wx:if="{{!Loginswitch}}" bindphoneoneclicklogin="onHandleLogin" open-type="phoneOneClickLogin">一键登录按钮</button> -->
27 32
  <button wx:if="{{checked}}" class="button_button" color="#00BA6E" open-type="getPhoneNumber" bindgetphonenumber="onGetPhoneNumber">登录</button>
28
- <button wx:if="{{!checked}}" class="button_button" color="#00BA6E" bind:tap="promptcheck">登录</button>
33
+ <button wx:if="{{!checked}}" disabled="{{!checked}}" class="button_button" color="#cccccc" bind:tap="promptcheck">登录</button>
29 34
  <view class="register">
30
-<view class="register_box" bind:tap="onregister">注册</view> 
35
+<!-- <view class="register_box" bind:tap="onregister">注册</view>  -->
31 36
 </view>
32 37
  <view class="agreement">
33 38
   <t-radio t-class="t_box" value="{{checked}}" icon="dot" data-value="{{checked}}" bind:tap="checkboxChange"/>

+ 1
- 1
package-user/pages/privacy/index.js View File

@@ -17,7 +17,7 @@ URL:''
17 17
    this.setData({
18 18
     URL:'https://esos-iot.com/wx_images/service.png'
19 19
    })
20
- }else if(options.name=='隐私协议'){
20
+ }else if(options.name=='隐私政策'){
21 21
   this.setData({
22 22
     URL:'https://esos-iot.com/wx_images/privacy.png'
23 23
    })

+ 1
- 0
pages/index/index.js View File

@@ -37,6 +37,7 @@ Page({
37 37
 this.getuser()
38 38
 this.initMap()
39 39
 wx.$on('wsMessage', this.handleWsMessage);
40
+
40 41
   },
41 42
   onHide(){
42 43
     // 页面卸载时,取消订阅,这是至关重要的一步!

+ 14
- 20
pages/index/index.wxml View File

@@ -34,20 +34,19 @@
34 34
   <t-icon name="focus" size="40rpx" data-name="focus" bind:tap="onIconTap" />
35 35
 
36 36
 </view>
37
-   <view class="carousel">
37
+   <!-- <view class="carousel">
38 38
     <swiper indicator-dots="{{indicatorDots}}"
39 39
         autoplay="{{autoplay}}" interval="{{interval}}" duration="{{duration}}" circular="{{true}}">
40 40
         <block wx:for="{{background}}" wx:key="*this">
41 41
           <swiper-item>
42
-            <!-- <view class="swiper-item">{{item}}</view> -->
43 42
             <image class="swiper_img" src="{{item}}" mode="widthFix"/>
44 43
           </swiper-item>
45 44
         </block>
46 45
       </swiper>
47
-   </view>
46
+   </view> -->
48 47
    <!-- 底部面板 -->
49
-  <view class="bottom-panel" wx:if="{{workorderdata.length > 0 }}">
50
-    <!--  -->
48
+  <view class="bottom-panel">
49
+  <!--  -->
51 50
   <!-- 客户信息--(叫车后显示) -->
52 51
     <view  wx:if="{{userdata.operationRole==5||userdata.operationRole==6}}">
53 52
     <view class="driver-info" wx:for="{{workorderdata}}" wx:key="index" data-id="{{item.workorderId}}" bindtap="details">
@@ -71,12 +70,14 @@
71 70
 <view wx:if="{{item.workorderType==5&&item.workorderExaminetye==0}}">待审核</view>
72 71
 <view wx:if="{{item.workorderType==5&&item.workorderExaminetye==1}}">审核成功</view>
73 72
 <view wx:if="{{item.workorderType==5&&item.workorderExaminetye==2}}">审核失败</view>
74
-      
75 73
       </view>
76 74
       </view>
77 75
       <view class="driver-arrive1">预约时间:{{item.workorderStarttime}}</view>
78 76
     </view>
79 77
     </view>
78
+    <view class="available" wx:if="{{workorderdata.length<1}}">
79
+<image src="https://esos-iot.com/myminio/project/9efa1691f71a48b6ae20648c0a2dae56.png" mode="aspectFit"/>
80
+</view> 
80 81
     </view>
81 82
     <!-- 司机信息--(叫车后显示) --> 
82 83
     <view  wx:if="{{userdata.operationRole==4}}">
@@ -98,7 +99,6 @@
98 99
 <view wx:if="{{item.workorderType==3}}">到达地点</view>
99 100
 <view wx:if="{{item.workorderType==4}}">工作中</view>
100 101
 <view wx:if="{{item.workorderType==6}}">取消工单</view>
101
-
102 102
 <view wx:if="{{item.workorderType==5&&item.settlementType==0}}">待结算</view>
103 103
 <view wx:if="{{item.workorderType==5&&item.settlementType==1}}">结算成功</view>
104 104
 <view wx:if="{{item.workorderType==5&&item.settlementType==2}}">结算失败</view>
@@ -106,29 +106,23 @@
106 106
       </view>
107 107
       <view class="driver-arrive1">约定到达时间:{{item.workorderCreatetime}}</view>
108 108
     </view>
109
-    
110
-    </view>
111
-    
112 109
     </view>
113
-    <!-- <view class="available" wx:if="{{workorderdata.length<1}}">
110
+    <view class="available" wx:if="{{workorderdata.length<1}}">
114 111
 <image src="https://esos-iot.com/myminio/project/9efa1691f71a48b6ae20648c0a2dae56.png" mode="aspectFit"/>
115
-</view>  -->
116
-   
112
+</view> 
113
+    </view>
117 114
     <view style="height: 140rpx;" wx:if="{{userdata.operationRole==5||userdata.operationRole==6}}"></view>
118 115
      <!-- <button class="call-btn" bindtap="onelectricity">
119 116
       <text class="call-btn_left_electricity">预约</text>
120 117
     </button> -->
121 118
   </view>
122
-   
123
- 
124
-  
125 119
 </view>
126 120
 
127 121
 <button class="call-btn" bindtap="onelectricity" wx:if="{{userdata.operationRole==5||userdata.operationRole==6}}">
128 122
       <text class="call-btn_left_electricity">预约</text>
129 123
       
130 124
     </button>
131
-
132
-<!--   
133
-       
134
- -->   
125
+<!-- 
126
+  https://esos-iot.com:9443/syscar/selectoperationcar
127
+Request Method: POST
128
+ -->

+ 94
- 0
pages/projectdetails/index.js View File

@@ -0,0 +1,94 @@
1
+Page({
2
+  /**
3
+   * 页面的初始数据
4
+   */
5
+  data: {
6
+    projectList:[
7
+      {title:'测算完成'},
8
+      {title:'勘测完成'},
9
+      {title:'方案生成'},
10
+      {title:'采购完成'},
11
+      {title:'项目进行中'},
12
+  ],
13
+    // 储能车项目详情数据(模拟真实场景)
14
+    projectInfo: {
15
+      id: 1,
16
+      name: "上海市浦东新区储能车运营及充电服务项目",
17
+      status: "进行中",
18
+      statusType: "ongoing",
19
+      address: "上海市浦东新区张江高科技园区科苑路88号",
20
+      time: "2026-01-01 至 2028-12-31",
21
+      // 项目分成
22
+      splitList: [
23
+        { id: 1, role: "主导方", rate: "40%" },
24
+        { id: 4, role: "合伙人", rate: "10%" },
25
+        { id: 2, role: "供电方A", rate: "25%" },
26
+        { id: 3, role: "供电方B", rate: "20%" },
27
+        { id: 5, role: "用电方", rate: "5%" }
28
+      ],
29
+      // 项目主导方
30
+      leader: {
31
+        name: "上海电速新能源科技有限公司",
32
+        contact: "张经理",
33
+        phone: "13800138000",
34
+        scope: "项目整体运营、储能车调度、客户对接"
35
+      },
36
+      // 供电方信息
37
+
38
+      partners: [
39
+        {
40
+          id: 1,
41
+          name: "国家电网上海电力公司",
42
+          type: "工商业用电(峰谷平电价)",
43
+          capacity: "500kW/h(储能容量)",
44
+          term: "2026-01-01 至 2028-12-31"
45
+        },
46
+        {
47
+          id: 2,
48
+          name: "国家电网北京电力公司",
49
+          type: "工商业用电(峰谷平电价)",
50
+          capacity: "500kW/h(储能容量)",
51
+          term: "2026-01-01 至 2028-12-31"
52
+        }
53
+      ],
54
+      // 合伙人信息
55
+
56
+      powerSupplier: {
57
+        name: "合伙人(上海能联科技)",
58
+        phone: "13700137000",
59
+        investRate: "25%",
60
+        responsibility: "储能车运输、场地租赁、后勤保障"
61
+      },
62
+      // 用电方信息
63
+      powerConsumer: {
64
+        name: "上海张江园区多家科技企业",
65
+        scale: "日均用电约8000度",
66
+        timePeriod: "高峰时段(9:00-18:00)为主",
67
+        settlement: "月结,按峰谷电价结算"
68
+      }
69
+    }
70
+  },
71
+
72
+  /**
73
+   * 生命周期函数--监听页面加载
74
+   */
75
+  onLoad(options) {
76
+    // 实际项目中,从列表页传递projectId,这里根据ID请求接口获取详情
77
+    // const projectId = options.id;
78
+    // this.getProjectDetail(projectId);
79
+  },
80
+
81
+  /**
82
+   * 模拟请求项目详情接口
83
+   */
84
+  getProjectDetail(projectId) {
85
+    // 实际开发中替换为wx.request请求后端接口
86
+    // wx.request({
87
+    //   url: 'https://你的接口地址/project/detail',
88
+    //   data: { id: projectId },
89
+    //   success: (res) => {
90
+    //     this.setData({ projectInfo: res.data });
91
+    //   }
92
+    // });
93
+  }
94
+});

+ 9
- 0
pages/projectdetails/index.json View File

@@ -0,0 +1,9 @@
1
+{
2
+  "navigationBarTitleText": "项目详情",
3
+  "enablePullDownRefresh": false,
4
+  "backgroundColor": "#f5f7fa",
5
+  "usingComponents": {
6
+    "t-steps": "tdesign-miniprogram/steps/steps",
7
+    "t-step-item": "tdesign-miniprogram/step-item/step-item"
8
+  }
9
+}

+ 129
- 0
pages/projectdetails/index.wxml View File

@@ -0,0 +1,129 @@
1
+<!-- 页面容器 -->
2
+<scroll-view class="page-container" scroll-y>
3
+  <!-- 顶部项目基础信息区 -->
4
+  <view class="project-header">
5
+    <!-- 项目名称 -->
6
+    <view class="project-name">{{projectInfo.name}}</view>
7
+    <!-- 项目核心信息行 -->
8
+    <view class="base-info-row">
9
+      <view class="base-info-item">
10
+        <text class="info-label">项目地址:</text>
11
+        <text class="info-value">{{projectInfo.address}}</text>
12
+      </view>
13
+      <view class="base-info-item">
14
+        <text class="info-label">项目周期:</text>
15
+        <text class="info-value">{{projectInfo.time}}</text>
16
+      </view>
17
+      <view class="base-info-item">
18
+        <text class="info-label">签约电量:</text>
19
+        <text class="info-value">600kWh</text>
20
+      </view>
21
+    </view>
22
+  </view>
23
+
24
+  <!-- 项目分成模块 -->
25
+  <view class="module-card">
26
+    <view class="module-title">项目成员</view>
27
+    <view class="split-container">
28
+      <view class="split-item" wx:for="{{projectInfo.splitList}}" wx:key="id">
29
+        <view class="split-name">{{item.role}}</view>
30
+        <view class="split-value">{{item.rate}}</view>
31
+      </view>
32
+    </view>
33
+  </view>
34
+
35
+  <!-- 项目主导方 -->
36
+  <view class="module-card">
37
+    <view class="module-title">项目负责方</view>
38
+    <view class="party-info">
39
+      <view class="party-item">
40
+        <text class="info-label">企业名称:</text>
41
+        <text class="info-value">{{projectInfo.leader.name}}</text>
42
+      </view>
43
+      <view class="party-item">
44
+        <text class="info-label">联系人:</text>
45
+        <text class="info-value">{{projectInfo.leader.contact}}</text>
46
+      </view>
47
+      <view class="party-item">
48
+        <text class="info-label">联系方式:</text>
49
+        <text class="info-value">{{projectInfo.leader.phone}}</text>
50
+      </view>
51
+      <view class="party-item">
52
+        <text class="info-label">负责范围:</text>
53
+        <text class="info-value">{{projectInfo.leader.scope}}</text>
54
+      </view>
55
+    </view>
56
+  </view>
57
+<!-- 合伙人信息 -->
58
+<view class="module-card">
59
+    <view class="module-title">合伙人信息</view>
60
+    <view class="party-info">
61
+      <view class="party-item">
62
+        <text class="info-label">企业名称:</text>
63
+        <text class="info-value">{{projectInfo.powerSupplier.name}}</text>
64
+      </view>
65
+      <view class="party-item">
66
+            <text class="info-label">联系方式:</text>
67
+            <text class="info-value">{{projectInfo.powerSupplier.phone}}</text>
68
+          </view>
69
+          <view class="party-item">
70
+            <text class="info-label">出资比例:</text>
71
+            <text class="info-value">{{projectInfo.powerSupplier.investRate}}</text>
72
+          </view>
73
+          <view class="party-item">
74
+            <text class="info-label">负责内容:</text>
75
+            <text class="info-value">{{projectInfo.powerSupplier.responsibility}}</text>
76
+          </view>
77
+    </view>
78
+    
79
+  </view>
80
+  <!-- 供电方信息 -->
81
+  <view class="module-card">
82
+    <view class="module-title">供电方信息</view>
83
+    <view class="partner-list">
84
+      <view class="partner-item" wx:for="{{projectInfo.partners}}" wx:key="id">
85
+        <view class="partner-name">{{item.name}}</view>
86
+        <view class="partner-detail">
87
+        
88
+          <view class="party-item">
89
+        <text class="info-label">供电类型:</text>
90
+        <text class="info-value">{{item.type}}</text>
91
+      </view>
92
+      <view class="party-item">
93
+        <text class="info-label">供电容量:</text>
94
+        <text class="info-value">{{item.capacity}}</text>
95
+      </view>
96
+      <view class="party-item">
97
+        <text class="info-label">合作期限:</text>
98
+        <text class="info-value">{{item.term}}</text>
99
+      </view>
100
+        </view>
101
+      </view>
102
+    </view>
103
+  </view>
104
+
105
+  
106
+
107
+  <!-- 用电方信息 -->
108
+  <view class="module-card">
109
+    <view class="module-title">用电方信息</view>
110
+    <view class="party-info">
111
+      <view class="party-item">
112
+        <text class="info-label">企业名称:</text>
113
+        <text class="info-value">{{projectInfo.powerConsumer.name}}</text>
114
+      </view>
115
+      <view class="party-item">
116
+        <text class="info-label">用电规模:</text>
117
+        <text class="info-value">{{projectInfo.powerConsumer.scale}}</text>
118
+      </view>
119
+      <view class="party-item">
120
+        <text class="info-label">用电时段:</text>
121
+        <text class="info-value">{{projectInfo.powerConsumer.timePeriod}}</text>
122
+      </view>
123
+      <view class="party-item">
124
+        <text class="info-label">结算方式:</text>
125
+        <text class="info-value">{{projectInfo.powerConsumer.settlement}}</text>
126
+      </view>
127
+    </view>
128
+  </view>
129
+</scroll-view>

+ 139
- 0
pages/projectdetails/index.wxss View File

@@ -0,0 +1,139 @@
1
+/* 页面容器 */
2
+.page-container {
3
+  min-height: 100vh;
4
+  background-color: #f5f7fa;
5
+  padding-bottom: 40rpx;
6
+  box-sizing: border-box;
7
+
8
+}
9
+
10
+/* 顶部项目基础信息区 */
11
+.project-header {
12
+  width: 100%;
13
+  background: #fff;
14
+  padding: 30rpx 24rpx;
15
+  margin-bottom: 20rpx;
16
+  box-sizing: border-box;
17
+}
18
+
19
+/* 状态标签 */
20
+.status-tag {
21
+  display: inline-block;
22
+  font-size: 24rpx;
23
+  padding: 6rpx 16rpx;
24
+  border-radius: 20rpx;
25
+  color: #fff;
26
+  margin-bottom: 20rpx;
27
+}
28
+/* 状态类型样式 */
29
+.status-tag.pending { background: #909399; }
30
+.status-tag.ongoing { background: #409eff; }
31
+.status-tag.done { background: #67c23a; }
32
+.status-tag.suspended { background: #f56c6c; }
33
+
34
+/* 项目名称 */
35
+.project-name {
36
+  font-size: 36rpx;
37
+  font-weight: 600;
38
+  color: #333;
39
+  margin-bottom: 24rpx;
40
+  line-height: 1.4;
41
+  margin-top: 20rpx;
42
+  box-sizing: border-box;
43
+}
44
+
45
+/* 基础信息行 */
46
+.base-info-row {
47
+  font-size: 28rpx;
48
+  color: #666;
49
+  line-height: 1.8;
50
+}
51
+.base-info-item {
52
+  margin-bottom: 12rpx;
53
+}
54
+
55
+/* 通用模块卡片 */
56
+.module-card {
57
+  background: #fff;
58
+  border-radius: 16rpx;
59
+  padding: 24rpx;
60
+  margin: 0 20rpx 20rpx;
61
+  box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
62
+}
63
+
64
+/* 模块标题 */
65
+.module-title {
66
+  font-size: 32rpx;
67
+  font-weight: 600;
68
+  color: #333;
69
+  padding-bottom: 16rpx;
70
+  margin-bottom: 16rpx;
71
+  border-bottom: 1rpx solid #f0f0f0;
72
+}
73
+
74
+/* 项目分成容器 */
75
+.split-container {
76
+  display: flex;
77
+  flex-wrap: wrap;
78
+  gap: 16rpx;
79
+  padding: 8rpx 0;
80
+}
81
+.split-item {
82
+  background: #f5f7fa;
83
+  border-radius: 8rpx;
84
+  padding: 12rpx 20rpx;
85
+  flex: 1;
86
+  min-width: 180rpx;
87
+  text-align: center;
88
+}
89
+.split-name {
90
+  font-size: 26rpx;
91
+  color: #666;
92
+  margin-bottom: 8rpx;
93
+}
94
+.split-value {
95
+  font-size: 28rpx;
96
+  font-weight: 600;
97
+  color: #409eff;
98
+}
99
+
100
+/* 通用方信息样式 */
101
+.party-info {
102
+  font-size: 28rpx;
103
+  color: #666;
104
+  line-height: 2;
105
+}
106
+.party-item {
107
+  display: flex;
108
+  flex-wrap: wrap;
109
+  margin-bottom: 8rpx;
110
+}
111
+.info-label {
112
+  color: #999;
113
+  min-width: 120rpx;
114
+}
115
+.info-value {
116
+  flex: 1;
117
+  color: #333;
118
+}
119
+
120
+/* 合伙人列表 */
121
+.partner-list {
122
+  padding: 8rpx 0;
123
+}
124
+.partner-item {
125
+  padding: 16rpx 0;
126
+  border-bottom: 1rpx dashed #eee;
127
+}
128
+.partner-item:last-child {
129
+  border-bottom: none;
130
+}
131
+.partner-name {
132
+  font-size: 30rpx;
133
+  font-weight: 600;
134
+  color: #333;
135
+  margin-bottom: 12rpx;
136
+}
137
+.partner-detail {
138
+  padding-left: 12rpx;
139
+}

+ 97
- 0
pages/projectlist/index.js View File

@@ -0,0 +1,97 @@
1
+const api = require('../../api/index.js');
2
+
3
+Page({
4
+  /**
5
+   * 页面的初始数据
6
+   */
7
+  data: {
8
+    projectList: [], // 项目列表数据
9
+    pageNum: 1, // 当前页码
10
+    pageSize: 10, // 每页条数
11
+    hasMore: true, // 是否有更多数据
12
+    loading: false, // 是否正在加载
13
+    refreshing: false, // 是否正在下拉刷新
14
+  statedata:[{title:'未审核'},{title:'未勘探'},{title:'未签约'},{title:'已启用'}]
15
+  },
16
+
17
+  /**
18
+   * 生命周期函数--监听页面加载
19
+   */
20
+  onLoad(options) {
21
+    // 页面加载时获取第一页数据
22
+    this.getProjectList();
23
+  },
24
+
25
+  /**
26
+   * 获取项目列表数据
27
+   * @param {boolean} isRefresh 是否是下拉刷新
28
+   */
29
+  getProjectList(isRefresh = false) {
30
+    // 如果正在加载或没有更多数据,直接返回
31
+    if (this.data.loading && !isRefresh) return;
32
+
33
+    this.setData({
34
+      loading: true,
35
+      ...(isRefresh && { refreshing: true }), // 刷新时设置refreshing为true
36
+    });
37
+
38
+    let data = {
39
+     
40
+    }
41
+    api.request(`/sysproject/selectproject`, 'post', data, { isPublic: false })
42
+    .then((data) => {
43
+      console.log('实时数据:', data.data);
44
+      if (data.code === 200) {
45
+      // 处理数据:分割图片URL字符串为数组
46
+const processedList = data.data.map(item => {
47
+  // 处理逻辑:
48
+  // 1. 先判断 picture 字段是否存在且不为空
49
+  // 2. 按逗号分割成数组
50
+  // 3. 过滤掉分割后可能出现的空字符串(避免数据异常)
51
+  const pictureArray = item.picture 
52
+    ? item.picture.split(',').filter(url => url.trim() !== '') 
53
+    : [];
54
+  
55
+  return {
56
+    ...item, // 保留原有的所有字段
57
+    picture: pictureArray // 替换 picture 为数组格式
58
+  };
59
+});
60
+console.log(processedList);
61
+// 更新数据到页面
62
+this.setData({
63
+  projectList: processedList
64
+});
65
+      }
66
+    })
67
+    .catch((err) => {
68
+      console.error('实时数据请求失败:', err);
69
+    });
70
+  },
71
+
72
+  /**
73
+   * 下拉刷新
74
+   */
75
+  onPullDownRefresh() {
76
+    this.getProjectList(true);
77
+  },
78
+
79
+  /**
80
+   * 上拉加载更多
81
+   */
82
+  onReachBottom() {
83
+    if (this.data.hasMore && !this.data.loading) {
84
+      this.getProjectList();
85
+    }
86
+  },
87
+
88
+  /**
89
+   * 点击列表项进入详情页
90
+   */
91
+  goToDetail(e) {
92
+    const { id } = e.currentTarget.dataset;
93
+    wx.navigateTo({
94
+      url: `/pages/detail/detail?id=${id}`,
95
+    });
96
+  },
97
+});

+ 6
- 0
pages/projectlist/index.json View File

@@ -0,0 +1,6 @@
1
+{
2
+  "usingComponents": {
3
+    "t-steps": "tdesign-miniprogram/steps/steps",
4
+    "t-step-item": "tdesign-miniprogram/step-item/step-item"
5
+  }
6
+}

+ 44
- 0
pages/projectlist/index.wxml View File

@@ -0,0 +1,44 @@
1
+<view class="list-container">
2
+  <!-- 下拉刷新提示 -->
3
+  <scroll-view 
4
+    scroll-y 
5
+    class="list-scroll"
6
+    refresher-enabled="{{true}}"
7
+    refresher-triggered="{{refreshing}}"
8
+    bindrefresherrefresh="onPullDownRefresh"
9
+    bindscrolltolower="onReachBottom"
10
+    lower-threshold="50"
11
+  >
12
+    <!-- 列表内容 -->
13
+    <view class="list-items">
14
+      <block>
15
+      <view class="project" wx:for="{{projectList}}" wx:key="id">
16
+        <t-steps theme="dot" current="{{item.projectType}}" bind:change="onThirdChange">
17
+    <t-step-item wx:for="{{statedata}}" wx:for-item="items" wx:key="indexs" content="{{items.title}}" />
18
+  </t-steps>
19
+        <view class="list-item" bindtap="goToDetail" data-id="{{item.id}}">
20
+        
21
+          <view class="item-left">
22
+            <image class="item-img" src="{{item.picture[0] || ''}}" mode="aspectFill"></image>
23
+            <!-- <view class="item-title">{{item.projectId}}</view> -->
24
+
25
+          </view>
26
+          <view class="item-right">
27
+            <view class="item-title">项目名称:{{item.projectName}}</view>
28
+            <view class="item-desc">{{item.electricName}}</view>
29
+            <view class="item-meta">
30
+              <text class="item-time">{{item.partnershipName}}</text>
31
+              <text class="item-tag">{{item.createTime}}</text>
32
+            </view>
33
+          </view>
34
+        </view>
35
+      </view>
36
+
37
+      </block>
38
+      
39
+    </view>
40
+
41
+    
42
+  </scroll-view>
43
+</view>         
44
+  <!--  -->

+ 130
- 0
pages/projectlist/index.wxss View File

@@ -0,0 +1,130 @@
1
+.list-container {
2
+  height: 100vh;
3
+  background-color: #f5f5f5;
4
+}
5
+
6
+.list-scroll {
7
+  height: 100%;
8
+}
9
+
10
+.list-items {
11
+  padding: 20rpx;
12
+}
13
+.project{
14
+  background-color: #fff;
15
+  border-radius: 10rpx;
16
+  padding: 20rpx;
17
+  margin-top: 20rpx;
18
+}
19
+.list-item {
20
+  display: flex;
21
+  margin-top: 20rpx;
22
+}
23
+
24
+.item-left {
25
+  width: 120rpx;
26
+  height: 120rpx;
27
+  margin-right: 20rpx;
28
+}
29
+
30
+.item-img {
31
+  width: 100%;
32
+  height: 100%;
33
+  border-radius: 8rpx;
34
+}
35
+
36
+.item-right {
37
+  flex: 1;
38
+  display: flex;
39
+  flex-direction: column;
40
+  justify-content: space-between;
41
+}
42
+
43
+.item-title {
44
+  font-size: 32rpx;
45
+  font-weight: 600;
46
+  color: #333;
47
+  line-height: 1.4;
48
+  overflow: hidden;
49
+  text-overflow: ellipsis;
50
+  display: -webkit-box;
51
+  -webkit-line-clamp: 2;
52
+  -webkit-box-orient: vertical;
53
+}
54
+
55
+.item-desc {
56
+  font-size: 26rpx;
57
+  color: #666;
58
+  line-height: 1.4;
59
+  overflow: hidden;
60
+  text-overflow: ellipsis;
61
+  display: -webkit-box;
62
+  -webkit-line-clamp: 1;
63
+  -webkit-box-orient: vertical;
64
+  margin: 10rpx 0;
65
+}
66
+
67
+.item-meta {
68
+  display: flex;
69
+  justify-content: space-between;
70
+  align-items: center;
71
+  font-size: 24rpx;
72
+  color: #999;
73
+}
74
+
75
+.item-tag {
76
+  padding: 4rpx 12rpx;
77
+  background-color: #f0f8ff;
78
+  color: #007545;
79
+  border-radius: 12rpx;
80
+}
81
+
82
+/* 状态提示样式 */
83
+.list-status {
84
+  padding: 30rpx 0;
85
+  text-align: center;
86
+}
87
+
88
+.loading {
89
+  display: flex;
90
+  align-items: center;
91
+  justify-content: center;
92
+  color: #999;
93
+  font-size: 26rpx;
94
+}
95
+
96
+.loading text {
97
+  margin-left: 10rpx;
98
+}
99
+
100
+.no-more {
101
+  color: #999;
102
+  font-size: 26rpx;
103
+}
104
+
105
+.empty {
106
+  padding: 100rpx 0;
107
+}
108
+
109
+.empty-img {
110
+  width: 200rpx;
111
+  height: 200rpx;
112
+  margin-bottom: 20rpx;
113
+}
114
+
115
+.empty-text {
116
+  display: block;
117
+  color: #999;
118
+  font-size: 28rpx;
119
+  margin-bottom: 30rpx;
120
+}
121
+
122
+.empty-btn {
123
+  padding: 12rpx 30rpx;
124
+  background-color: #007545;
125
+  color: #fff;
126
+  border: none;
127
+  border-radius: 24rpx;
128
+  font-size: 26rpx;
129
+}
130
+/*  */

+ 71
- 6
pages/setup/index.js View File

@@ -22,7 +22,18 @@ station:wx.getStorageSync('station'),
22 22
 showMultiTextAndTitle:false,
23 23
 inputValue: '', // 初始值
24 24
 passwordtype:true,
25
-accountdata:''
25
+accountdata:'',
26
+projectList: [{cooperationTime: "2025-01-01——2026-01-01",
27
+createTime: "2026-03-05 16:31:00",
28
+electric: "2",
29
+electricName: "晟运能源江西",
30
+partnership: "8",
31
+partnershipName: "超级大型运营公司",
32
+picture: "https://esos-iot.com:9442/myminio/partner/6f107f0fb7bc4bf79175181a96f1b7f9.webp,https://esos-iot.com:9442/myminio/partner/19fb2a62785247a1975e73d864bba5bc.png,https://esos-iot.com:9442/myminio/partner/8a66ec2cf1c54c62810fe2a6f8242a82.jpg",
33
+projectId: "2",
34
+projectName: "北京油田项目",
35
+projectType: "3"}],
36
+statedata:[{title:'未签约'},{title:'已签约'},{title:'服务中'}]
26 37
   },
27 38
   onstation(){
28 39
     wx.navigateTo({
@@ -46,6 +57,12 @@ accountdata:''
46 57
  })
47 58
     
48 59
   },
60
+  // 跳转到项目详情页
61
+  onCardClick() {
62
+    wx.navigateTo({
63
+      url: `/pages/projectdetails/index`
64
+    });
65
+  },
49 66
   closeDialog(){
50 67
  this.setData({
51 68
   showMultiTextAndTitle:false
@@ -113,6 +130,8 @@ accountdata:''
113 130
     console.error("获取小程序版本号失败:", e);
114 131
   }
115 132
      this.account()
133
+    this.getProjectList()
134
+
116 135
   },
117 136
   account(){
118 137
     let data ={
@@ -131,6 +150,48 @@ accountdata:''
131 150
       console.error('请求失败:', err);
132 151
     });
133 152
   },
153
+  getProjectList(isRefresh = false) {
154
+    // 如果正在加载或没有更多数据,直接返回
155
+    if (this.data.loading && !isRefresh) return;
156
+  
157
+    this.setData({
158
+      loading: true,
159
+      ...(isRefresh && { refreshing: true }), // 刷新时设置refreshing为true
160
+    });
161
+  
162
+    let data = {
163
+     
164
+    }
165
+    api.request(`/sysprojectcontroller/selectproject`, 'post', data, { isPublic: false })
166
+    .then((data) => {
167
+      console.log('实时数据:', data.data);
168
+      if (data.code === 200) {
169
+      // 处理数据:分割图片URL字符串为数组
170
+  const processedList = data.data.map(item => {
171
+  // 处理逻辑:
172
+  // 1. 先判断 picture 字段是否存在且不为空
173
+  // 2. 按逗号分割成数组
174
+  // 3. 过滤掉分割后可能出现的空字符串(避免数据异常)
175
+  const pictureArray = item.picture 
176
+    ? item.picture.split(',').filter(url => url.trim() !== '') 
177
+    : [];
178
+  
179
+  return {
180
+    ...item, // 保留原有的所有字段
181
+    picture: pictureArray // 替换 picture 为数组格式
182
+  };
183
+  });
184
+  console.log(processedList);
185
+  // 更新数据到页面
186
+  this.setData({
187
+  projectList: processedList
188
+  });
189
+      }
190
+    })
191
+    .catch((err) => {
192
+      console.error('实时数据请求失败:', err);
193
+    });
194
+  },
134 195
   onpassword(){
135 196
      this.setData({
136 197
       passwordtype:!this.data.passwordtype
@@ -147,6 +208,9 @@ accountdata:''
147 208
       url: '/pages/personalInfo/index', // 登录页面的路径,注意路径前面加上 '/' 表示从根目录开始
148 209
     });
149 210
   },
211
+  formatBalance(num) {
212
+    return num ? parseInt(num) : 0;
213
+  },
150 214
   /**
151 215
    * 生命周期函数--监听页面初次渲染完成
152 216
    */
@@ -186,18 +250,19 @@ accountdata:''
186 250
   onPullDownRefresh() {
187 251
 
188 252
   },
189
-
253
+  
190 254
   /**
191 255
    * 页面上拉触底事件的处理函数
192 256
    */
193 257
   onReachBottom() {
194
-
258
+  
195 259
   },
196
-
260
+  
197 261
   /**
198
-   * 用户点击右上角分享   
262
+   * 用户点击右上角分享
199 263
    */                  
200 264
   onShareAppMessage() {
201
-
265
+  
202 266
   }
203 267
 })
268
+// 

+ 3
- 1
pages/setup/index.json View File

@@ -4,6 +4,8 @@
4 4
     "t-icon": "tdesign-miniprogram/icon/icon",
5 5
     "t-button": "tdesign-miniprogram/button/button",
6 6
     "t-dialog": "tdesign-miniprogram/dialog/dialog",
7
-    "t-input": "tdesign-miniprogram/input/input"
7
+    "t-input": "tdesign-miniprogram/input/input",
8
+    "t-steps": "tdesign-miniprogram/steps/steps",
9
+    "t-step-item": "tdesign-miniprogram/step-item/step-item"
8 10
   }
9 11
 }

+ 38
- 7
pages/setup/index.wxml View File

@@ -1,5 +1,5 @@
1 1
 <view class="setup">
2
- 
2
+
3 3
 <view style="width: 100%;height:60rpx"></view>
4 4
 <view class="user">
5 5
 <image bind:tap="onuser" class="user_to" src="{{user.operationPicture||'https://thirdwx.qlogo.cn/mmopen/vi_32/POgEwh4mIHO4nibH0KlMECNjjGxQUq24ZEaGT4poC6icRiccVGKSyXwibcPq4BWmiaIGuG1icwxaQX6grC9VemZoJ8rg/132'}}" mode=""/>
@@ -13,9 +13,6 @@
13 13
 </view>
14 14
 </view>
15 15
 <view style="width: 100%;height:40rpx"></view>
16
-<!--
17
-    
18
- -->
19 16
 <view class="allocation_box">
20 17
   <view class="allocation">
21 18
 <view class="allocation_3_password">我的账户<image class="login_imgae" src="https://esos-iot.bjdexn.cn/wx_images/password_1.png" wx:if="{{passwordtype}}" bind:tap="onpassword" mode=""/>
@@ -29,7 +26,8 @@
29 26
 <view>
30 27
 <text wx:if="{{!passwordtype}}">¥</text>
31 28
 <text style="font-size: 26px;" wx:if="{{passwordtype}}">∗∗∗∗</text>
32
-<text style="font-size: 26px;" wx:else>{{accountdata.balance}}</text>
29
+<text style="font-size: 26px;" wx:else>{{ js.toFixed2(accountdata.balance) }}</text>
30
+<!-- <text style="font-size: 26px;" wx:else>{{accountdata.balance}}</text> -->
33 31
 </view>
34 32
 </view>
35 33
 <view class="allocation_money">
@@ -56,6 +54,23 @@
56 54
 </view>
57 55
 </view>
58 56
 </view>
57
+<view class="project" bind:tap="onCardClick" wx:if="{{user.operationRole!=4}}">
58
+<!-- <view></view> -->
59
+<view class="project_box" wx:for="{{projectList}}" wx:if="{{index<1}}" wx:key="index" bind:tap="onCardClick">
60
+<view class="project_top1">
61
+  <t-steps theme="dot" current="{{item.projectType}}" bind:change="onThirdChange">
62
+    <t-step-item wx:for="{{statedata}}" wx:for-item="items" wx:key="indexs" content="{{items.title}}" />
63
+  </t-steps>
64
+<t-icon name="chevron-right-s" size="40rpx" data-name="chevron-right-s"/>
65
+</view>
66
+<view class="project_top">
67
+<view class="project_title">北方油田项目</view>
68
+</view>
69
+<view class="project_name">项目地址:{{item.electricName}}</view>
70
+<view class="project_name">项目时间:{{item.createTime}}</view>
71
+</view>
72
+</view>
73
+
59 74
 <view class="allocation_box_more">
60 75
 <view class="allocation_box_allocate" wx:if="{{user.operationRole==5||user.operationRole==6}}">
61 76
 <view class="allocation_allocate" data-name="userlist" bind:tap="toconfigure">
@@ -229,6 +244,22 @@
229 244
 </view>
230 245
 </view> -->
231 246
 </view>
232
- 
247
+<wxs module="js">
248
+// 金额省略小数点后两位(直接取整数,丢掉小数)
249
+function formatIntMoney(num) {
250
+  if (!num || isNaN(num)) return "0";
251
+  return parseInt(num); // 直接截取整数部分
252
+}
253
+
254
+// 可选:保留两位小数(标准金额)
255
+function toFixed2(num) {
256
+  if (!num || isNaN(num)) return "0.00";
257
+  return parseFloat(num).toFixed(2);
258
+}
233 259
 
234
- 
260
+module.exports = {
261
+  formatIntMoney: formatIntMoney,
262
+  toFixed2: toFixed2
263
+};
264
+</wxs>
265
+<!--  -->

+ 40
- 1
pages/setup/index.wxss View File

@@ -316,4 +316,43 @@ justify-content: center;
316 316
    display: flex;
317 317
    align-items: center;
318 318
    justify-content: center;
319
-}
319
+}
320
+
321
+.project{
322
+  width: 100%;
323
+  /* padding: 20rpx; */
324
+  margin-top: 20rpx;
325
+  /* background-color: #222222; */
326
+  box-sizing: border-box;
327
+  }
328
+  .project_top1{
329
+    display: flex;
330
+    font-size:13px;
331
+  } 
332
+
333
+  .project_box{
334
+    width: 100%;
335
+    height: 300rpx;
336
+    padding: 20rpx;
337
+    margin-top: 20rpx;
338
+    background-color: #ffffff;
339
+    border-radius: 10rpx;
340
+  box-sizing: border-box;
341
+  }
342
+  .project_title{
343
+    font-size: 32rpx;
344
+  }
345
+  .project_top{
346
+    margin-top: 20rpx;
347
+    display: flex;
348
+    align-items: center;
349
+    justify-content: space-between;
350
+  }
351
+  .project_right{
352
+    font-size: 28rpx;
353
+    color: #007545;
354
+  }
355
+  .project_name{
356
+    margin-top: 20rpx;
357
+  }
358
+  /* index.js  */

+ 2
- 2
pages/tool/index.wxml View File

@@ -6,11 +6,11 @@
6 6
 <view class="workorder">
7 7
   <view class="discharge" wx:if="{{userdata.operationRole==5}}">
8 8
     <view class="discharge_cheng {{selected==1?'selected':''}}" data-index="1" bind:tap="onselected">工单</view>
9
-<view class="discharge_fang {{selected==2?'selected':''}}" data-index="2" bind:tap="onselected">结算</view>
9
+<!-- <view class="discharge_fang {{selected==2?'selected':''}}" data-index="2" bind:tap="onselected">结算</view> -->
10 10
 </view>
11 11
 <view class="discharge" wx:if="{{userdata.operationRole==6}}">
12 12
     <view class="discharge_cheng {{selected==1?'selected':''}}" data-index="1" bind:tap="onselected">工单</view>
13
-<view class="discharge_fang {{selected==2?'selected':''}}" data-index="2" bind:tap="onselected">结算</view>
13
+<!-- <view class="discharge_fang {{selected==2?'selected':''}}" data-index="2" bind:tap="onselected">结算</view> -->
14 14
 </view>
15 15
 <view class="discharge" wx:if="{{userdata.operationRole==4}}">
16 16
 <view class="discharge_cheng {{selected==1?'selected':''}}" data-index="1" bind:tap="onselected">充电工单</view>

+ 3
- 2
pages/tool/index.wxss View File

@@ -171,8 +171,9 @@ display: flex;
171 171
  background-color: #ffffff;
172 172
  color: #EA6E38;
173 173
 
174
- border-top-left-radius: 10rpx;
175
- border-bottom-left-radius: 10rpx;
174
+ /* border-top-left-radius: 10rpx; */
175
+ /* border-bottom-left-radius: 10rpx; */
176
+ border-radius: 10rpx;
176 177
  border: 1rpx solid #EA6E38;
177 178
  border-right: 0rpx solid #EA6E38;
178 179
 }

Loading…
Cancel
Save