فهرست منبع

合并xyb代码

liuwei 1 ماه پیش
والد
کامیت
a72797a2bf

+ 3 - 1
component/customTabbar/index.vue

@@ -62,6 +62,7 @@ export default {
         is_auth: 0,
         status: 0
       },
+	  // accountInfo: uni.getAccountInfoSync(),
 	  plate_number: '',
 	  isScanCondeRentalCar: false,
     };
@@ -75,7 +76,8 @@ export default {
   },
   methods: {
     routerPush(url) {
-      uni.switchTab({ url });
+      // uni.switchTab({ url });
+      uni.navigateTo({ url })
     },
     loadFaceToken() {
       const me = this

+ 1 - 0
js_sdk/wa-permission/permission.js

@@ -1,5 +1,6 @@
 /**
  * 本模块封装了Android、iOS的应用权限判断、打开应用权限设置界面、以及位置系统服务是否开启
+ *  https://ext.dcloud.net.cn/plugin?id=594
  */
 
 var isIos

+ 35 - 12
pages.json

@@ -14,7 +14,12 @@
 		{
 			"path": "pages/my/my",
 			"style": {
-				"titleNView": false
+				"app-plus" : {
+					"titleNView": {
+						"type": "transparent"
+					}
+				}
+				
 			}
 		},
 		{
@@ -27,48 +32,41 @@
 		{
 			"path": "pages/loginRegister/login",
 			"style": {
-				"titleNView": false,
 				"navigationBarTitleText": "登录"
 			}
 		},
 		{
 			"path": "pages/loginRegister/forgetPassword",
 			"style": {
-				"titleNView": false,
 				"navigationBarTitleText": "忘记密码"
 			}
 		},
 		{
 			"path": "pages/loginRegister/register",
 			"style": {
-				"titleNView": false,
 				"navigationBarTitleText": "账号注册"
 			}
 		},
 		{
 			"path": "pages/loginRegister/changePassword",
 			"style": {
-				"titleNView": false,
 				"navigationBarTitleText": "修改密码"
 			}
 		},
 		{
 			"path": "pages/my/set",
 			"style": {
-				"titleNView": false,
 				"navigationBarTitleText": "设置"
 			}
 		},
 		{
 			"path": "pages/message/index",
 			"style": {
-				"titleNView": false
 			}
 		},
 		{
 			"path": "pages/message/deviceInfo",
 			"style": {
-				"titleNView": false
 			}
 		},
 		{
@@ -81,29 +79,48 @@
 		{
 			"path": "pages/bluetoothUnlock/unlockSet",
 			"style": {
-				"titleNView": false,
 				"navigationBarTitleText": "开启感应解锁"
 			}
 		},
 		{
 			"path": "pages/carFunctionSet/more",
 			"style": {
-				"titleNView": false,
 				"navigationBarTitleText": "更多功能"
 			}
 		},
 		{
 			"path": "pages/carFunctionSet/unbind",
 			"style": {
-				"titleNView": false,
 				"navigationBarTitleText": "解除绑定"
 			}
 		},
-
+		{
+			"path": "pages/mileageStatistics/index",
+			"style": {
+				"navigationBarTitleText": "里程统计"
+			}
+		},
+		{
+			"path": "pages/index/homeNotRent",
+			"style": {
+				"app-plus" : {
+					"titleNView": {
+						"type": "transparent"
+					}
+				}
+				
+			}
+		},
 		{
 			"path": "pages/service/service",
 			"style": {}
 		},
+		{
+			"path": "pages/feedback/index",
+			"style": {
+				"navigationBarTitleText": "意见反馈"
+			}
+		},
 		{
 			"path": "pages/aboutMy/aboutMy",
 			"style": {
@@ -116,6 +133,12 @@
 				"navigationBarTitleText": "激活车辆"
 			}
 		},
+		{
+			"path": "pages/dashboard/dashboard",
+			"style": {
+				"navigationBarTitleText": "仪表盘"
+			}
+		},
 		{
 			"path": "pages/authIdentity/authIdentity",
 			"style": {

+ 243 - 185
pages/bluetoothUnlock/components/AndroidUnlockAuth.vue

@@ -1,69 +1,121 @@
 <template>
-    <u-popup v-model="showDialog" mode="bottom" border-radius="28" @close="close">
-        <view class="dialog-content">
-            <view class="title">{{ $t('开启感应解锁') }}</view>
-            <view class="tips">为保证 感应解锁 的正常使用,请依次开以下权限,开启后可以显著提高解锁成功率,且不会明显增加手机电量消耗</view>
-            <view class="authorization-wrap">
-                <view class="corner-mark">{{ $t('授权引导') }}</view>
-                <view class="step-item-container">
-                    <view class="step-item" v-for="(auth, idx) in authStepList" :key="idx">
-                        <view :class="['icon', `icon_${auth.type}`]"></view>
-                        <view class="desc-wrap">
-                            <view class="title-row">
-                                <view class="title">{{ auth.title }}</view>
-                                <view class="turn-on-switch is-open">{{ $t('已开启') }}</view>
-                            </view>
-                            <view class="desc">{{ auth.desc }}</view>
-                        </view>
-                    </view>
+  <u-popup v-model="showDialog" mode="bottom" border-radius="28" @close="close">
+    <view class="dialog-content">
+      <view class="title">{{ $t('开启感应解锁') }}</view>
+      <view class="tips">
+        为保证 感应解锁 的正常使用,请依次开以下权限,开启后可以显著提高解锁成功率,且不会明显增加手机电量消耗
+      </view>
+      <view class="authorization-wrap">
+        <view class="corner-mark">{{ $t('授权引导') }}</view>
+        <view class="step-item-container">
+          <view v-for="(item, idx) in authStepList" :key="idx" @tap="enablePermissions(item)" class="step-item">
+            <view :class="['icon', `icon_${item.type}`]" />
+            <view class="desc-wrap">
+              <view class="title-row">
+                <view class="title">{{ item.title }}</view>
+                <view :class="['turn-on-switch', permisionCheckObj[item.type] && 'is-open']">
+                  {{ permisionCheckObj[item.type] ? $t('已开启') : $t('未开启') }}
                 </view>
+              </view>
+              <view class="desc">{{ item.desc }}</view>
             </view>
-            <view class="btn" @tap="linkTo">{{ $t('我已开启') }}</view>
+          </view>
         </view>
-    </u-popup>
+      </view>
+      <view class="btn" @tap="linkTo">{{ $t('我已开启') }}</view>
+    </view>
+  </u-popup>
 </template>
 
 <script>
 	var bluetooth = require('@/common/bluetooth.js');
+import permision from "@/js_sdk/wa-permission/permission.js"
 export default {
-    props: {
-        value: {
-            type: Boolean,
-            default: false
-        }
-    },
+  props: {
+    value: {
+      type: Boolean,
+      default: false
+    }
+  },
 	created(){
 		bluetooth.initBluetooth()
 		this.bluetoothClose()
 	},
-    data() {
-        return {
-            showDialog: this.value,
-        }
+  data() {
+    return {
+      showDialog: this.value,
+      permisionCheckObj: {}
+    }
+  },
+  computed: {
+    authStepList() {
+      const lang = v => this.$t(v)
+      return [
+        { title: lang('位置权限'), type: 'location', desc: '打开手机定位,并运行APP始终使用' },
+        { title: lang('电池优化'), type: 'battery', desc: '打开电池优化设置, 将弗兰克APP加入保护名单' },
+        { title: lang('后台运行'), type: 'backstage', desc: '打开后台运行权限 清选择手动控制' },
+        { title: lang('打开应用锁'), type: 'appLock', desc: '打开应用权限锁' }
+      ]
+    }
+  },
+  watch: {
+    value(newValue) {
+      this.showDialog = newValue
+      if (newValue) {
+        this._initCheckdPermission()
+      }
+    }
+  },
+  methods: {
+    async _initCheckdPermission() {
+      
+      const permissionsToCheck = [
+        { key: 'location', permission: 'android.permission.ACCESS_FINE_LOCATION' },
+        { key: 'backstage', permission: 'android.permission.SET_PROCESS_FOREGROUND' }
+      ]
+
+      for (const { key, permission } of permissionsToCheck) {
+        const result = await this.requestAndroidPermission(permission)
+        this.$set(this.permisionCheckObj, key, result)
+      }
     },
-    computed: {
-        authStepList() {
-            const lang = v => this.$t(v)
-            return  [
-                { title: lang('位置权限'), type: 'location', desc: '打开手机定位,并运行APP始终使用' },
-                { title: lang('电池优化'), type: 'battery', desc: '打开电池优化设置, 将弗兰克APP加入保护名单' },
-                { title: lang('后台运行'), type: 'backstage', desc: '打开后台运行权限 清选择手动控制' },
-                { title: lang('打开应用锁'), type: 'appLock', desc: '打开应用权限锁' },
-            ]
-        }
+    // vue的method里编写如下代码
+    async requestAndroidPermission(permisionID) {
+      const AUTHORIZ = 1 // 已授权
+      const result = await permision.requestAndroidPermission(permisionID)
+      console.log(123456, result)
+      return result == AUTHORIZ
+      // var strStatus
+      // if (result == 1) {
+      //   strStatus = "已获得授权"
+      // } else if (result == 0) {
+      //   strStatus = "未获得授权"
+      // } else {
+      //   strStatus = "被永久拒绝权限"
+      // }
+      // permision.gotoAppPermissionSetting()
+      // uni.showModal({
+      //   content: permisionID + strStatus,
+      //   showCancel: false
+      // });
     },
-    watch: {
-        value(newValue) {
-            this.showDialog = newValue;
-        }
+    enablePermissions({ type }) {
+      if (!this.permisionCheckObj[type]) {
+        permision.gotoAppPermissionSetting()
+      }
+    },
+    linkTo() {
+      const allPermissionsGranted = Object.values(this.permisionCheckObj).every(value => value === true);
+      if (allPermissionsGranted) {
+        this.close()
+        uni.navigateTo({ url: '/pages/bluetoothUnlock/bluetoothPair' })
+      } else {
+        permision.gotoAppPermissionSetting()
+      }
+    },
+    close() {
+      this.$emit('input', false)
     },
-    methods: {
-        linkTo() {
-            uni.navigateTo({ url: '/pages/bluetoothUnlock/bluetoothPair' })
-        },
-        close() {
-            this.$emit('input', false);
-        },
 		bluetoothClose: function() {
 			bluetooth.closeBluetoothAdapter();
 			bluetooth.closeDevice(
@@ -77,157 +129,163 @@ export default {
 			);
 			bluetooth.offCharacteristicStateChange("095A5832", 'home');
 			bluetooth.offConnectionStateChange("095A5832", 'home');	 
-		},
-    }
+		},,
+  }
 }
 </script>
 
 <style lang="scss" scoped>
 .dialog-content {
+  width: 100%;
+  height: 100%;
+  background: #F1F3F4;
+  padding: 40rpx 32rpx;
+
+  .title {
+    font-family: PingFangSC, PingFang SC;
+    font-weight: 600;
+    font-size: 40rpx;
+    color: #060809;
+  }
+
+  .tips {
+    font-family: PingFangSC, PingFang SC;
+    font-weight: 400;
+    font-size: 24rpx;
+    color: #828DA2;
+    line-height: 40rpx;
+    margin: 32rpx 0 40rpx;
+  }
+
+  .authorization-wrap {
+    background: #fff;
     width: 100%;
-    height: 100%;
-    background: #F1F3F4;
-    padding: 40rpx 32rpx;
-
-    .title {
-        font-family: PingFangSC, PingFang SC;
-        font-weight: 600;
-        font-size: 40rpx;
-        color: #060809;
+    border-radius: 40rpx;
+    position: relative;
+
+    .corner-mark {
+      width: 224rpx;
+      height: 100rpx;
+      background: #0A59F7;
+      border-radius: 40rpx 0 0 0;
+      display: flex;
+      color: #fff;
+      line-height: 86rpx;
+      text-align: center;
+      justify-content: flex-end;
+
+      &::after {
+        content: "";
+        width: 86rpx;
+        height: 80rpx;
+        background: url('https://qiniu.bms16.com/FibAaPERzqi6m95EP2jREUKixjUi');
+        background-size: 100%;
+      }
     }
 
-    .tips {
-        font-family: PingFangSC, PingFang SC;
-        font-weight: 400;
-        font-size: 24rpx;
-        color: #828DA2;
-        line-height: 40rpx;
-        margin: 32rpx 0 40rpx;
+    .step-item-container {
+      background: #fff;
+      border-top-left-radius: 40rpx;
+      padding: 30rpx 24rpx;
+      margin-top: -24rpx;
     }
 
-    .authorization-wrap {
-        background: #fff;
-        width: 100%;
-        border-radius: 40rpx;
-        position: relative;
-
-        .corner-mark {
-            width: 224rpx;
-            height: 100rpx;
-            background: #0A59F7;
-            border-radius: 40rpx 0 0 0;
-            display: flex;
-            color: #fff;
-            line-height: 86rpx;
-            text-align: center;
-            justify-content: flex-end;
-
-            &::after {
-                content: "";
-                width: 86rpx;
-                height: 80rpx;
-                background: url('https://qiniu.bms16.com/FibAaPERzqi6m95EP2jREUKixjUi');
-                background-size: 100%;
-            }
-        }
+    .step-item {
+      width: 100%;
+      background: #F4F5F6;
+      border-radius: 24rpx;
+      padding: 32rpx 28rpx;
+      margin-bottom: 24rpx;
+      display: flex;
+      align-items: center;
+
+      &:last-child {
+        margin-bottom: 0;
+      }
+
+      .desc-wrap {
+        flex: 1;
+        margin-left: 24rpx;
+      }
+
+      .title-row {
+        display: flex;
+        justify-content: space-between;
+        margin-bottom: 24rpx;
 
-        .step-item-container {
-            background: #fff;
-            border-top-left-radius: 40rpx;
-            padding: 30rpx 24rpx;
-            margin-top: -24rpx;
+        .title {
+          font-family: PingFangSC, PingFang SC;
+          font-weight: 500;
+          font-size: 32rpx;
+          color: #060809;
+          font-weight: bold;
         }
 
-        .step-item {
-            width: 100%;
-            background: #F4F5F6;
-            border-radius: 24rpx;
-            padding: 32rpx 28rpx;
-            margin-bottom: 24rpx;
-            display: flex;
-            align-items: center;
-
-            &:last-child {
-                margin-bottom: 0;
-            }
-
-            .desc-wrap {
-                flex: 1;
-                margin-left: 24rpx;
-            }
-
-            .title-row {
-                display: flex;
-                justify-content: space-between;
-                margin-bottom: 24rpx;
-
-                .title {
-                    font-family: PingFangSC, PingFang SC;
-                    font-weight: 500;
-                    font-size: 32rpx;
-                    color: #060809;
-                    font-weight: bold;
-                }
-
-                .turn-on-switch {
-                    background: #2ADA62;
-                    border-radius: 20rpx;
-                    font-size: 22rpx;
-                    color: #FFFFFF;
-                    display: flex;
-                    align-items: center;
-                    justify-content: center;
-                    padding: 8rpx 20rpx;
-                }
-            }
-
-            .desc {
-                font-size: 24rpx;
-                color: #060809;
-            }
-            .icon {
-                width: 66rpx;
-                height: 70rpx;
-            }
-            .icon_location {
-                background: url('https://qiniu.bms16.com/FpNU0wp-E5Iin60nT8_NwT1_h_xm');
-                background-size: 100% 100%;
-            }
-
-            .icon_battery {
-                background: url('https://qiniu.bms16.com/FjD4CXHuNUL85_JYI7w2MDucjeI-');
-                background-size: 100% 100%;
-            }
-
-            .icon_backstage {
-                background: url('https://qiniu.bms16.com/Fo7RGbv1gokn1iUQpF8tca5aUWkD');
-                background-size: 100% 100%;
-            }
-
-            .icon_appLock {
-                background: url('https://qiniu.bms16.com/FoWg_FjfV5_v9fxvFQ2dHzXOCDPD');
-                background-size: 100% 100%;
-            }
+        .turn-on-switch {
+          background: #FF791A;
+          border-radius: 20rpx;
+          font-size: 22rpx;
+          color: #FFFFFF;
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          padding: 8rpx 20rpx;
+
+          &.is-open {
+            background: #2ADA62;
+          }
         }
+      }
+
+      .desc {
+        font-size: 24rpx;
+        color: #060809;
+      }
+
+      .icon {
+        width: 66rpx;
+        height: 70rpx;
+      }
+
+      .icon_location {
+        background: url('https://qiniu.bms16.com/FpNU0wp-E5Iin60nT8_NwT1_h_xm');
+        background-size: 100% 100%;
+      }
+
+      .icon_battery {
+        background: url('https://qiniu.bms16.com/FjD4CXHuNUL85_JYI7w2MDucjeI-');
+        background-size: 100% 100%;
+      }
+
+      .icon_backstage {
+        background: url('https://qiniu.bms16.com/Fo7RGbv1gokn1iUQpF8tca5aUWkD');
+        background-size: 100% 100%;
+      }
+
+      .icon_appLock {
+        background: url('https://qiniu.bms16.com/FoWg_FjfV5_v9fxvFQ2dHzXOCDPD');
+        background-size: 100% 100%;
+      }
     }
+  }
 
-    .btn {
-        margin-top: 40rpx;
-        width: 100%;
-        height: 80rpx;
-        background: #060809;
-        border-radius: 40rpx;
-        color: #fff;
-        display: flex;
-        align-items: center;
-        justify-content: center;
-        font-family: PingFangSC, PingFang SC;
-        font-weight: 500;
-        font-size: 32rpx;
-
-        &:active {
-            opacity: 0.8;
-        }
+  .btn {
+    margin-top: 40rpx;
+    width: 100%;
+    height: 80rpx;
+    background: #060809;
+    border-radius: 40rpx;
+    color: #fff;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    font-family: PingFangSC, PingFang SC;
+    font-weight: 500;
+    font-size: 32rpx;
+
+    &:active {
+      opacity: 0.8;
     }
+  }
 }
 </style>

+ 1 - 1
pages/carFunctionSet/more.vue

@@ -44,7 +44,7 @@ const ICONS = {
 
 export default {
   components: {
-    // draggable
+    draggable
   },
   data() {
     const MAX_TAB_LEN = 4

+ 3 - 1
pages/carFunctionSet/unbind.vue

@@ -27,8 +27,9 @@
         </view>
       </view>
       <view
+        style="margin-top: 40rpx;"
         :class="[
-          'zx-form-btn', 'fix-bottom-btn',
+          'zx-form-btn',
           passwd && 'is-submit'
         ]"
         @tap="unbindTap"
@@ -85,6 +86,7 @@
   @import "@/libs/css/layout.scss";
   .unbind-page {
     .car-info-wrap {
+        padding: 0 32rpx 40rpx;
         .car-img {
             width: 100%;
             height: 492rpx;

+ 191 - 0
pages/dashboard/dashboard.vue

@@ -0,0 +1,191 @@
+<template>
+    <view class="dashboard-page zx-page-linear">
+        <view class="dashboard">
+            <view class="shadow" :style="{ '--progress': progress + '%' }"></view>
+            <view class="spe—wrap">
+                <view class="spe-num">
+                    {{ speed }}
+                </view>
+                <view class="unit">km/h</view>
+            </view>
+            <view class="power-wrap">
+                <u-count-to :startVal="0" bold :endVal="progress" fontSize="48rpx" />
+            </view>
+        </view>
+
+        <view class="battery_life_progress">
+            <view class="is_progress">
+                <text>续航</text>
+                <text>46.5km</text>
+            </view>
+        </view>
+
+        <view class="info-container">
+            <view class="info-wrap" v-for="(item, index) in infoList" :key="index">
+                <view class="label">{{ item.label }}</view>
+                <view class="value">{{ 10 + index }} <text class="unit">{{ item.unit }}</text></view>
+            </view>
+        </view>
+    </view>
+</template>
+
+
+<script>
+export default {
+    data() {
+        return {
+            speed: 50,
+            infoList: []
+        }
+    },
+    computed: {
+        progress() {
+            const MAX_SPEED = 120;
+            return this.speed / MAX_SPEED * 100
+        }
+    },
+    created() {
+        this._initInfoList()
+    },
+    methods: {
+        _initInfoList() {
+            this.infoList = [
+                { label: '骑行里程', prop: 'km', unit: 'km' },
+                { label: '骑行时长', prop: 'km', unit: 'h' },
+                { label: '最大速度', prop: 'km', unit: 'km/h' },
+                { label: '平均速度', prop: 'km', unit: 'km/h' },
+            ]
+        }
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+@import "@/libs/css/layout.scss";
+
+.dashboard-page {
+    padding: 24rpx 32rpx 0;
+    min-height: calc(100vh - 100rpx);
+
+    .dashboard {
+        width: 554rpx;
+        height: 554rpx;
+        margin: 0 auto 58rpx;
+        background: url('https://qiniu.bms16.com/Ftwa7u9tJYw3XSLaXYvrDyGNRuD5');
+        background-size: 100%;
+        position: relative;
+        .shadow {
+            box-shadow: inset 0rpx 2rpx 6rpx 0rpx #fff;
+            width: 490rpx;
+            height: 502rpx;
+            position: relative;
+            top: 20rpx;
+            left: 50%;
+            transform: translateX(-50%);
+            border-radius: 50%;
+            background: conic-gradient(from -122deg, #0A59F7 0%, #20FFCA var(--progress), #F3F8FF 0% 245deg, transparent 245deg 360deg);
+            mask: radial-gradient(transparent 200rpx, #000 200rpx);
+            -webkit-mask: radial-gradient(transparent 210rpx, #000 213rpx);
+        }
+
+        .spe—wrap {
+            width: 218rpx;
+            height: 218rpx;
+            background: #0A59F7;
+            border-radius: 50%;
+            position: absolute;
+            left: 50%;
+            top: 50%;
+            transform: translate(-50%, -50%);
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            flex-direction: column;
+            color: #fff;
+            .spe-num {
+                font-family: Futura, Futura;
+                font-weight: bold;
+                font-size: 80rpx;
+                color: #FFFFFF;
+                line-height: 64rpx;
+                text-align: center;
+                font-style: normal;
+                margin-bottom: 16rpx;
+            }
+            .unit {
+                line-height: 28rpx;
+                font-style: italic;
+            }
+        }
+
+        .power-wrap {
+            width: 230rpx;
+            height: 104rpx;
+            background: #D6E7FF;
+            border-radius: 64rpx;
+            position: absolute;
+            bottom: 22rpx;
+            left: 50%;
+            transform: translateX(-50%);
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            font-family: Futura, Futura;
+            font-weight: bold;
+            font-size: 48rpx;
+            color: #060809;
+        }
+    }
+
+    .battery_life_progress {
+        width: 100%;
+        margin-bottom: 40rpx;
+        background: #FFFFFF;
+        border-radius: 40rpx;
+        padding: 6rpx;
+        overflow: hidden;
+
+        .is_progress {
+            width: 50%;
+            height: 100%;
+            padding: 16rpx 32rpx;
+            background: #0A59F7;
+            border-radius: 36rpx;
+            display: flex;
+            align-items: center;
+            justify-content: space-between;
+            color: #fff;
+            font-size: 36rpx;
+        }
+    }
+
+    .info-container {
+        display: flex;
+        flex-wrap: wrap;
+        justify-content: space-between;
+
+        .info-wrap {
+            width: 336rpx;
+            margin-bottom: 14rpx;
+            background: #FFFFFF;
+            border-radius: 40rpx;
+            padding: 32rpx 24rpx;
+
+            .label {
+                font-size: 28rpx;
+                color: #060809;
+                margin-bottom: 24rpx;
+            }
+
+            .value {
+                font-size: 48rpx;
+
+                .unit {
+                    margin-left: 8rpx;
+                    font-size: 28rpx;
+                }
+            }
+        }
+    }
+}
+</style>

+ 267 - 0
pages/feedback/index.vue

@@ -0,0 +1,267 @@
+<template>
+    <view class="container">
+        <text class="title">问题类型</text>
+        <view class="title-wrapper">
+            <view v-for="(item, index) in typeList" @tap="tapType(item)" :key="index"
+                :class="item.type_id == typeId ? 'text-wrapper text-wrapper-i' : 'text-wrapper text-wrapper-s'"
+               >{{ item.type_name }}</view>
+        </view>
+        <view style="margin: 64rpx 0;">            
+            <view class="title">问题描述</view>
+            <view class="text-description-input">
+                <textarea :enableNative="false" @input="inputContent" :value="content"
+                    placeholder-class="description-placeholder" placeholder="请详细说明,以便我们解决问题,最多可填写300字。"
+                    maxlength="300"></textarea>
+            </view>
+        </view>
+        <view>
+            <view class="title-img">
+                <view class="title-img-text">问题图片</view>
+                <view class="img-text">{{ imgList.length }} / 3</view>
+            </view>
+
+            <view class="upload-img-row">
+                <view class="upload-img-view" v-for="(item, index) in imgList" :key="index">
+                    <img @tap="bindChangeImg" :data-index="index" class="upload-img" :src="item" alt="">
+                </view>
+                <view class="upload-img-view" v-if="imgList.length < 3">
+                    <img @tap="bindUpImg" class="upload-img" src="https://qiniu.bms16.com/Fv3KFmim5gle_kWR9g1Mym56lJpC"
+                        alt="">
+                </view>
+            </view>
+
+        </view>
+        <view class="submit-btn-view">
+            <view v-if="typeId != '' && imgList.length != 0 && content != ''" class="submit" @tap="submitFeedback">提交
+            </view>
+            <view v-else class="submit-btn">提交</view>
+        </view>
+    </view>
+</template>
+
+<script>
+const http = require('../../common/http.js');
+const config = require('../../common/config.js');
+const common = require('../../common/common.js');
+export default {
+    data() {
+        return {
+            typeList: [
+                { type_id: 1, type_name: '车辆' },
+                { type_id: 2, type_name: '电池' },
+                { type_id: 3, type_name: '电柜' },
+                { type_id: 4, type_name: '应用操作' },
+                { type_id: 5, type_name: '其他' },
+            ],
+            typeId: '',
+            content: '',
+            imgList: [],
+            isDiabled: false,
+        };
+    },
+    /**
+     * 生命周期函数--监听页面加载
+     */
+    onLoad: function (options) {
+        // this.loadTypeList()
+    },
+    /**
+     * 生命周期函数--监听页面显示
+     */
+    onShow: function () {
+
+    },
+    methods: {
+        loadTypeList() {
+            http.postApi(config.API_DAYHIRE_REPORT_REPORT_TYPE, {}, (resp) => {
+                if (resp.data.code === 200) {
+                    this.setData({
+                        typeList: resp.data.data.list
+                    });
+                } else {
+                    common.simpleToast(resp.data.msg)
+                }
+            })
+        },
+
+        tapType({ type_id }) {
+            this.setData({
+                typeId: type_id
+            })
+        },
+
+        inputContent(e) {
+            const content_text = e.detail.value
+            if (content_text.length >= 300) {
+                common.simpleToast('最多输入300字');
+            } else {
+                this.setData({
+                    content: content_text
+                })
+            }
+        },
+
+        bindUpImg: function () {
+            const that = this;
+            let _imgList = this.imgList
+            common.upLoadImgQiNiu(function (imgUrl) {
+                _imgList.push(imgUrl)
+                that.setData({
+                    imgList: _imgList
+                });
+            });
+        },
+
+        bindChangeImg(e) {
+            const that = this;
+            const index = e.currentTarget.dataset.index
+            let _imgList1 = this.imgList
+            common.upLoadImgQiNiu(function (imgUrl) {
+                _imgList1.splice(index, 1, imgUrl)
+                that.setData({
+                    imgList: _imgList1
+                });
+            });
+        },
+
+        submitFeedback() {
+            const imgs = this.imgList.join(',')
+            const pData = {
+                content: this.content,
+                imgs: imgs,
+                type_id: this.typeId
+            }
+            const that = this
+            http.postApi(config.API_DAYHIRE_REPORT_REPORT, pData, (resp) => {
+                if (resp.data.code === 200) {
+                    // that.setData({
+                    // 	isDiabled:true
+                    // })
+                    common.simpleToast('上传成功')
+                    setTimeout(() => {
+                        wx.navigateBack({
+                            delta: 1 // 返回上一级页面
+                        })
+                    }, 1000)
+                } else {
+                    common.simpleToast(resp.data.msg)
+                }
+            })
+        }
+    }
+};
+</script>
+
+<style scoped lang="scss">
+.container {
+    padding: 48rpx 32rpx 0;
+    background-color: white;
+    height: 100vh;
+}
+
+.title {
+    font-size: 40rpx;
+    color: #2A3A5A;
+    font-weight: 600;
+    margin-bottom: 40rpx;
+}
+
+.title-wrapper {
+    display: flex;
+    flex-wrap: wrap;
+    margin-right: -32rpx;
+}
+
+.text-wrapper {
+    padding: 24rpx 0;
+    text-align: center;
+    width: 218rpx;
+    background: #F3F8FF;
+    border-radius: 16rpx;
+    margin: 0 16rpx 16rpx 0;
+    font-size: 32rpx;
+    border: 4rpx solid transparent
+}
+
+.text-wrapper-s {
+    background-color: #F3F8FF;
+    color: #2A3A5A;
+}
+
+.text-wrapper-i {
+    color: #0A59F7;
+    background: #FFFFFF;
+    border-color: #0A59F7;
+}
+
+.text-description-input {
+    background: #F3F8FF;
+    padding-left: 32rpx;
+    padding-top: 24rpx;
+}
+
+.description-placeholder {
+    color: #828DA2;
+    font-size: 28rpx;
+}
+
+.title-img {
+    font-size: 40rpx;
+    color: #2A3A5A;
+    font-weight: 600;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 40rpx;
+}
+
+.img-text {
+    font-size: 32rpx;
+    color: #9FA7B7;
+    font-weight: 400;
+}
+
+.upload-img-row {
+    display: flex;
+    justify-content: flex-start;
+    flex-wrap: wrap;
+}
+
+.upload-img-view {
+    margin-right: 20rpx;
+}
+
+.upload-img {
+    width: 218rpx;
+    height: 218rpx;
+}
+
+.submit-btn-view {
+    border-top: 2rpx solid #F4F5F6;
+    padding-top: 24rpx;
+    position: fixed;
+    bottom: 0;
+    width: 93%
+}
+
+.submit-btn {
+    background: #0074FF;
+    opacity: 0.2;
+    border-radius: 70rpx;
+    color: #FFF;
+    font-size: 32rpx;
+    text-align: center;
+    padding: 24rpx 0;
+    margin: 0 0 24rpx 0;
+}
+
+.submit {
+    background: #0074FF;
+    border-radius: 40rpx;
+    color: #FFF;
+    font-size: 32rpx;
+    text-align: center;
+    padding: 24rpx 0;
+    margin: 0 32rpx 24rpx 32rpx;
+}
+</style>

+ 148 - 0
pages/index/homeNotRent.vue

@@ -0,0 +1,148 @@
+<template>
+    <view class="home-not-rent-page">
+      <view class="top-area">
+        <image :src="IMGS.baseTitle" class="base-title" />
+      </view>
+      <image :src="IMGS.carImg" class="car-img" />
+      <view :style="{ backgroundImage: `url(${IMGS.boxOmg})` }" class="desc-wrap">
+        <swiper
+          :interval="3000"
+          :circular="true"
+          indicator-color="#CED1D8"
+          indicator-active-color="#ffffff"
+          autoplay
+          indicator-dots
+          class="swiper-box"
+        >
+          <swiper-item v-for="(item, index) in descArr" :key="index">
+            <view class="swiper-item">
+                {{ item.speed }}
+                <view class="more-btn">了解更多</view>
+            </view>
+          </swiper-item>
+        </swiper>
+      </view>
+      <view class="options">
+        <view class="btn btn-left">{{ $t('租赁设备') }}</view>
+        <view class="btn btn-right">{{ $t('绑定设备') }}</view>
+      </view>
+    </view>
+  </template>
+  
+  <script>
+  import { QINIU_URL } from '@/common/constant'
+  
+  const IMGS = {
+    baseTitle: `${QINIU_URL}Fix835oiq463VWd1QdxwhIWNDLp6`,
+    carImg: `${QINIU_URL}FksY_ZCse57K6QrcBy52vep2WPHd`,
+    boxOmg: `${QINIU_URL}Fi9K2vXFEO5AGoUenf8nRDtyvMiW`
+  }
+  export default {
+    data() {
+      return {
+        IMGS,
+        descArr: [
+          { speed: 100 },
+          { speed: 200 },
+          { speed: 300 }
+        ]
+      }
+    }
+  }
+  </script>
+  
+  <style lang="scss" scoped>
+  .home-not-rent-page {
+    width: 750rpx;
+    min-height: 100vh;
+    background: linear-gradient(180deg, #EFF7FC 0%, #BAC0CC 100%);
+  
+    .top-area {
+        width: 100%;
+        height: 440rpx;
+        display: flex;
+        justify-content: center;
+        background: linear-gradient(180deg, #4A5567 0%, rgba(74, 85, 103, 0) 100%);
+  
+        .base-title {
+            width: 362rpx;
+            height: 182rpx;
+            margin: 66rpx auto 0;
+        }
+    }
+  
+    .car-img {
+        width: 100%;
+        height: 420rpx;
+        margin-top: -180rpx;
+  
+    }
+  
+    .desc-wrap {
+        width: 550rpx;
+        height: 538rpx;
+        background-size: 100%;
+        margin: 0 auto;
+        padding-bottom: 140rpx;
+        .swiper-box {
+            width: 100%;
+            height: 100%;
+        }
+        .swiper-item {
+            padding: 80rpx 100rpx;
+            font-weight: bold;
+            font-size: 64rpx;
+            color: #FFFFFF;
+            height: 100%;
+            .more-btn {
+                width: 268rpx;
+                height: 76rpx;
+                margin: 48rpx auto 0;
+                background: linear-gradient( 180deg, #6E798C 0%, #7F8C9B 100%);
+                border-radius: 40rpx;
+                font-size: 28rpx;
+                color: #FFFFFF;
+                display: flex;
+                align-items: center;
+                justify-content: center;
+                &::after {
+                    content: "";
+                    width: 28rpx;
+                    height: 28rpx;
+                    background: url('https://qiniu.bms16.com/Fi2Lg800Mc1MhCnvHT1DkvOEdJB1');
+                    background-size: 100%;
+                }
+            }
+        }
+    }
+  
+    .options {
+        padding: 0 28rpx;
+        display: flex;
+        justify-content: space-between;
+        margin-top: -100rpx;
+  
+        .btn {
+            width: 336rpx;
+            height: 98rpx;
+            border-radius: 50rpx;
+            border: 4rpx solid #060809;
+            font-size: 36rpx;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+        }
+  
+        .btn-left {
+            color: #060809;
+            background: rgba(255, 255, 255, 0.6);
+        }
+  
+        .btn-right {
+            color: #fff;
+            background: #060809;
+        }
+    }
+  }
+  </style>
+  

+ 220 - 0
pages/mileageStatistics/index.vue

@@ -0,0 +1,220 @@
+<template>
+  <view class="mileage-statistics-page">
+    <view class="search-type-wrap">
+      <view
+        v-for="item in queryTypes"
+        :class="['item', curType == item.type && 'isActive']"
+        :key="item.type"
+        @tap="changeType(item.type)"
+      >
+        {{ item.label }}
+      </view>
+    </view>
+    <view class="statistics-wrap">
+      <view class="kilometers-row">
+        <view class="kilometers">
+          <u-count-to
+            :start-val="0"
+            :end-val="1361.8"
+            :decimals="1"
+            class="count"
+            font-size="80rpx"
+            bold
+          />
+          <text class="unit">km</text>
+        </view>
+        <view class="date">2023-2024</view>
+      </view>
+      <view class="statistics-row">
+        <view
+          v-for="(item, idx) in statisticsEnum"
+          :key="idx"
+          class="item"
+        >
+          <view class="label">{{ item.label }}</view>
+          <view class="value">
+            <u-count-to
+              :start-val="0"
+              :end-val="statisticsInfo[item.prop]"
+              bold
+            />
+            {{ item.unit }}
+          </view>
+        </view>
+      </view>
+    </view>
+    <view ref="chartContainer" class="charts-container"></view>
+    <view class="list-wrap">
+      <view
+        v-for="(item, idx) in cyclingRecord"
+        :key="idx"
+        class="list-item"
+      >
+        <view class="row top-row">
+          <view>行驶里程
+            <u-count-to
+              :start-val="0"
+              :end-val="54"
+              :decimals="2"
+              class="num"
+              bold
+            /> km
+          </view>
+          <view>2024-12-04 16:15</view>
+        </view>
+        <view class="row bottom-row">
+          <text>功率: 30wh</text>
+          <text>减少碳排放: 40g</text>
+          <text>骑行时长: 00:20:31</text>
+        </view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+import * as echarts from 'echarts';
+export default {
+  data() {
+    return {
+      chart: null,
+      queryTypes: [],
+      curType: '0',
+      cyclingRecord: [
+        {}, {}, {}
+      ],
+      statisticsInfo: {
+        num: 9,
+        power: '475',
+        reduceEmissions: '996',
+        cyclingDuration: 432
+      }
+    }
+  },
+  computed: {
+    statisticsEnum() {
+      const t = v => this.$t(v)
+      return [
+        { label: t('骑行次数'), unit: t('次'), prop: 'num' },
+        { label: t('累计功率'), unit: 'wh', prop: 'power' },
+        { label: t('减少排放量'), unit: 'g', prop: 'reduceEmissions' },
+        { label: t('骑行时长'), unit: '天', prop: 'cyclingDuration' }
+      ]
+    }
+  },
+  created() {
+    this._initQueryTypes()
+  },
+  mounted() {
+    this.initChart()
+  },
+  methods: {
+    _initQueryTypes() {
+      this.queryTypes = [
+        { label: '总', type: '0' },
+        { label: '年', type: '1' },
+        { label: '月', type: '2' },
+        { label: '周', type: '3' },
+        { label: '日', type: '4' }
+      ]
+    },
+    changeType(type) {
+      this.setData({
+        curType: type
+      })
+    },
+    initChart() {
+        // this.chart = echarts.init(this.$refs.chartContainer);
+        console.log(111, this.$refs.chartContainer)
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+@import "@/libs/css/layout.scss";
+
+.mileage-statistics-page {
+  padding: 24rpx 32rpx;
+  background: #fff;
+  min-height: 100vh;
+  .search-type-wrap {
+      background: #F4F5F6;
+      border-radius: 16rpx;
+      display: flex;
+      padding: 4rpx;
+      .item {
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          width: 134rpx;
+          height: 52rpx;
+          border-radius: 12rpx;
+          font-size: 28rpx;
+          color: #060809;
+          &.isActive {
+              background: #FFFFFF;
+          }
+      }
+  }
+  .statistics-wrap {
+      margin: 64rpx 0 0 0;
+      .kilometers-row {
+          display: flex;
+          align-items: center;
+          justify-content: space-between;
+          .kilometers {
+              .count {
+                  font-family: DIN, DIN;
+                  font-size: 80rpx;
+                  color: #060809;
+              }
+              .unit {
+                  font-weight: bold;
+                  font-size: 40rpx;
+                  margin-left: 16rpx;
+              }
+          }
+          .date {
+              font-family: Roboto, Roboto;
+              font-weight: 400;
+              font-size: 32rpx;
+              color: #060809;
+          }
+      }
+      .statistics-row {
+          display: flex;
+          justify-content: space-between;
+          margin: 64rpx 0 102rpx;
+          .item {}
+      }
+  }
+  .charts-container {
+    width: 100%;
+    height: 250rpx;
+  }
+  .list-wrap {
+      .list-item {
+          margin-bottom: 70rpx;
+      }
+      .row {
+          display: flex;
+          align-items: center;
+          justify-content: space-between;
+      }
+      .top-row {
+          margin-bottom: 22rpx;
+          font-size: 28rpx;
+          color: #060809;
+          .num {
+              margin: 0 4rpx 0 8rpx;
+              font-size: 44rpx;
+          }
+      }
+      .bottom-row {
+          font-size: 28rpx;
+          color: #9D9E9F;
+      }
+  }
+}
+</style>

+ 2 - 1
pages/my/my.vue

@@ -76,7 +76,7 @@
     computed: {
       commonTabs() {
         return [
-          { name: `${this.$t('我的车辆')}`, url: '', icon: 'Fp6G-Kzb-YUGkP2WR-kjTlIbbTj1' },
+          { name: `${this.$t('我的车辆')}`, url: '/pages/mileageStatistics/index', icon: 'Fp6G-Kzb-YUGkP2WR-kjTlIbbTj1' },
           { name: `${this.$t('用车人')}`, url: '', icon: 'FnxGW52BCkTkK9HxsTdVrghU7B4D' },
           { name: `${this.$t('换电套餐')}`, jumpCheck: 'combo', url: '', icon: 'FsOsd1SxYDHDm00aiwrTib_k0Mbr' }
         ]
@@ -86,6 +86,7 @@
         return [
           { name: `${lang('我的订单')}`, url: '/pages/order/order', icon: 'FkLJGLo1faYtJWhW4Q0gt5dphI7g' },
           { name: `${lang('换电记录')}`, url: '', icon: 'FnSjwcN7Mcpa-WA7Cqx2cGTvX2V1' },
+          { name: `${lang('意见反馈')}`, url: '/pages/feedback/index', icon: 'FnSjwcN7Mcpa-WA7Cqx2cGTvX2V1' },
         //   { name: `${lang('关于我们')}`, url: '/pages/bluetoothUnlock/unlockSet', icon: 'Fmin1_DG6ZkENCdsI1qJZJpDNkhQ' },
           { name: `${lang('客服中心')}`, url: '/pages/bluetoothUnlock/bluetoothPair', icon: 'FhA9TUbTMF0e7ma6NZXqPrkscN6l' },
           { name: `${lang('设置')}`, url: '/pages/my/set', icon: 'Fu3f2iRi5BspRfbVLPcw8ryWc4lu' }