Browse Source

基础架构+散户加气3.1

chenlei 1 năm trước cách đây
mục cha
commit
7cbf7ffc91
57 tập tin đã thay đổi với 2668 bổ sung708 xóa
  1. 8 0
      manifest.config.ts
  2. 1 0
      package.json
  3. 0 6
      pages.config.ts
  4. 24 0
      pnpm-lock.yaml
  5. 196 123
      src/components/business/carNumber.vue
  6. 13 6
      src/components/business/station/index.vue
  7. 4 1
      src/components/container/index.vue
  8. 45 0
      src/components/countdown/index.vue
  9. 27 0
      src/components/fieldGroups/index.vue
  10. 3 0
      src/components/skeletons/index.vue
  11. 7 4
      src/enums/index.ts
  12. 5 0
      src/main.ts
  13. 12 2
      src/manifest.json
  14. 27 13
      src/pages.json
  15. 3 3
      src/pages/account/index.vue
  16. 214 84
      src/pages/index/index.vue
  17. 24 23
      src/pages/login/index.vue
  18. 14 5
      src/pages/createOrder/index.vue
  19. 42 28
      src/pages/orderList/index.vue
  20. 371 0
      src/pages/order/orderDetail.vue
  21. 326 0
      src/pages/order/prePay.vue
  22. 301 0
      src/pages/org/index.vue
  23. 119 14
      src/pages/personCenter/index.vue
  24. 0 222
      src/pages/prePay/index.vue
  25. 144 0
      src/pages/truckInfo/detail.vue
  26. 106 0
      src/pages/truckInfo/index.vue
  27. 17 6
      src/pagesSubExample/index.vue
  28. BIN
      src/static/images/controct_bg.png
  29. BIN
      src/static/images/driver_apply1.png
  30. BIN
      src/static/images/driver_apply3.png
  31. BIN
      src/static/images/icons/org_icon.png
  32. BIN
      src/static/images/qr@3x.png
  33. 11 1
      src/style/_variables.scss
  34. 205 58
      src/style/index.scss
  35. 26 0
      src/types/global.d.ts
  36. 1 39
      src/types/schemas/account.d.ts
  37. 2 0
      src/types/schemas/allinpay.d.ts
  38. 107 0
      src/types/schemas/custom.d.ts
  39. 12 0
      src/types/schemas/message.d.ts
  40. 30 4
      src/types/schemas/strategy.d.ts
  41. 18 0
      src/types/schemas/user.d.ts
  42. 13 0
      src/utils/aop/index.ts
  43. 31 2
      src/utils/config/index.ts
  44. 7 1
      src/utils/config/interFaces/account.ts
  45. 16 4
      src/utils/config/interFaces/allinpay.ts
  46. 15 15
      src/utils/config/interFaces/index.ts
  47. 10 4
      src/utils/config/interFaces/strategy.ts
  48. 6 0
      src/utils/config/interFaces/user.ts
  49. 47 13
      src/utils/config/pages.ts
  50. 2 1
      src/utils/container/index.ts
  51. 10 3
      src/utils/func/convert.ts
  52. 18 6
      src/utils/func/native.ts
  53. 0 11
      src/utils/platform.ts
  54. 2 0
      src/utils/store/common.ts
  55. 3 3
      src/utils/store/curPage.ts
  56. 11 2
      src/utils/store/user.ts
  57. 12 1
      src/utils/store/webapi.ts

+ 8 - 0
manifest.config.ts

@@ -114,8 +114,16 @@ export default defineManifestConfig({
     appid: VITE_WX_APPID,
     setting: {
       urlCheck: false,
+      minified: true,
     },
     usingComponents: true,
+    requiredPrivateInfos: ['getLocation'],
+    permission: {
+      'scope.userLocation': {
+        desc: '当前位置信息将用于附近加气站搜索',
+      },
+    },
+    lazyCodeLoading: 'requiredComponents',
     // __usePrivacyCheck__: true,
   },
   'mp-alipay': {

+ 1 - 0
package.json

@@ -91,6 +91,7 @@
     "z-paging": "^2.7.10"
   },
   "devDependencies": {
+    "vconsole": "^3.15.1",
     "@commitlint/cli": "^18.6.1",
     "@commitlint/config-conventional": "^18.6.3",
     "@dcloudio/types": "^3.4.8",

+ 0 - 6
pages.config.ts

@@ -54,10 +54,4 @@ export default defineUniPages({
   //   ],
   // },
   pages: [],
-  requiredPrivateInfos: ['getLocation'],
-  permission: {
-    'scope.userLocation': {
-      desc: '当前位置信息将用于附近加气站搜索',
-    },
-  },
 })

+ 24 - 0
pnpm-lock.yaml

@@ -53,6 +53,9 @@ importers:
       vant:
         specifier: 3.6.12
         version: 3.6.12(vue@3.4.21(typescript@4.9.5))
+      vconsole:
+        specifier: ^3.15.1
+        version: 3.15.1
       vue:
         specifier: 3.4.21
         version: 3.4.21(typescript@4.9.5)
@@ -2468,6 +2471,10 @@ packages:
     resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==}
     engines: {node: '>= 0.6'}
 
+  copy-text-to-clipboard@3.2.0:
+    resolution: {integrity: sha512-RnJFp1XR/LOBDckxTib5Qjr/PMfkatD0MUCQgdpqS8MdKiNUzBjAQBEN6oUy+jW7LI93BBG3DtMB2KOOKpGs2Q==}
+    engines: {node: '>=12'}
+
   core-js-compat@3.37.1:
     resolution: {integrity: sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==}
 
@@ -4073,6 +4080,9 @@ packages:
   muggle-string@0.3.1:
     resolution: {integrity: sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==}
 
+  mutation-observer@1.0.3:
+    resolution: {integrity: sha512-M/O/4rF2h776hV7qGMZUH3utZLO/jK7p8rnNgGkjKUw8zCGjRQPxB8z6+5l8+VjRUQ3dNYu4vjqXYLr+U8ZVNA==}
+
   nanoid@3.3.7:
     resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
     engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
@@ -5239,6 +5249,9 @@ packages:
     resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
     engines: {node: '>= 0.8'}
 
+  vconsole@3.15.1:
+    resolution: {integrity: sha512-KH8XLdrq9T5YHJO/ixrjivHfmF2PC2CdVoK6RWZB4yftMykYIaXY1mxZYAic70vADM54kpMQF+dYmvl5NRNy1g==}
+
   vite-plugin-restart@0.4.0:
     resolution: {integrity: sha512-SXeyKQAzRFmEmEyGP2DjaTbx22D1K5MapyNiAP7Xa14UyFgNSDjZ86bfjWksA0pqn+bZyxnVLJpCiqDuG+tOcg==}
     peerDependencies:
@@ -8667,6 +8680,8 @@ snapshots:
 
   cookie@0.6.0: {}
 
+  copy-text-to-clipboard@3.2.0: {}
+
   core-js-compat@3.37.1:
     dependencies:
       browserslist: 4.23.1
@@ -10589,6 +10604,8 @@ snapshots:
 
   muggle-string@0.3.1: {}
 
+  mutation-observer@1.0.3: {}
+
   nanoid@3.3.7: {}
 
   natural-compare@1.4.0: {}
@@ -11838,6 +11855,13 @@ snapshots:
 
   vary@1.1.2: {}
 
+  vconsole@3.15.1:
+    dependencies:
+      '@babel/runtime': 7.24.7
+      copy-text-to-clipboard: 3.2.0
+      core-js: 3.37.1
+      mutation-observer: 1.0.3
+
   vite-plugin-restart@0.4.0(vite@5.2.8(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.1)):
     dependencies:
       micromatch: 4.0.7

+ 196 - 123
src/components/business/carNumber.vue

@@ -1,54 +1,61 @@
 <template>
-  <div class="keyboards">
-    <div class="keyboards_title">
-      输入车牌
-      <span>(绿色背景为新能源车牌)</span>
-    </div>
-    <div>
-      <ul class="input_box" @click="methods.clickShowKeyboard">
-        <li>{{ data.first }}</li>
-        <li>{{ data.numArr[0] }}</li>
-        <span style="font-size: 50rpx; line-height: 100rpx; color: #ced0d2">•</span>
-        <li>{{ data.numArr[1] }}</li>
-        <li>{{ data.numArr[2] }}</li>
-        <li>{{ data.numArr[3] }}</li>
-        <li>{{ data.numArr[4] }}</li>
-        <li>{{ data.numArr[5] }}</li>
-        <li>{{ data.numArr[6] }}</li>
-      </ul>
-    </div>
-    <div class="keySure" @click="methods.submitNumber">确定</div>
-    <!-- 键盘-中英文 -->
+  <div>
     <uni-popup ref="popup" background-color="#fff">
-      <div class="keyboards_keys">
-        <div class="finish_key"><span @click="methods.hidekeyboards">完成</span></div>
-        <div class="finish_line"></div>
-        <div class="key_box">
-          <!-- 中文 -->
-          <div v-if="data.checkLangages" class="chinese">
-            <ul v-for="(item, index) in data.chineseList" :key="index">
-              <li
-                v-for="val in item"
-                :key="val.id"
-                :class="{ del: val.id === 99 || val.id === 98 }"
-                @click="methods.chooseChinese(val)"
-              >
-                {{ val.name }}
-              </li>
-            </ul>
-          </div>
-          <!-- 数字英文 -->
-          <div v-else class="english">
-            <ul v-for="(item, index) in data.englishList" :key="index">
-              <li
-                v-for="val in item"
-                :key="val.id"
-                :class="{ del: val.id === 99 || val.id === 97 }"
-                @click="methods.chooseEnglish(val)"
-              >
-                {{ val.name }}
+      <div class="keyboards">
+        <div class="keyboards_title">
+          输入车牌
+          <span>(绿色背景为新能源车牌)</span>
+        </div>
+        <div class="cn-center">
+          <ul class="input_box">
+            <template v-for="(n, i) in cnumbers" :key="i">
+              <li :class="{ active: n.active }">
+                {{ n.value }}
               </li>
-            </ul>
+              <span class="center point" v-if="n.afterPoint">•</span>
+            </template>
+            <!-- <li>{{ data.first }}</li>
+            <li class="active">{{ data.numArr[0] }}</li>
+            <span class="center point">•</span>
+            <li>{{ data.numArr[1] }}</li>
+            <li>{{ data.numArr[2] }}</li>
+            <li>{{ data.numArr[3] }}</li>
+            <li>{{ data.numArr[4] }}</li>
+            <li>{{ data.numArr[5] }}</li>
+            <li>{{ data.numArr[6] }}</li> -->
+          </ul>
+          <button type="green" @click="methods.submitNumber">确定</button>
+        </div>
+        <!-- 键盘-中英文 -->
+
+        <div class="keyboards_keys">
+          <div class="key_box">
+            <!-- 中文 -->
+            <div v-show="showChineseList" class="chinese">
+              <ul v-for="(item, index) in data.chineseList" :key="index">
+                <li
+                  v-for="val in item"
+                  :key="val.id"
+                  :class="{ del: val.id === 99 || val.id === 98 }"
+                  @click="methods.choose(val)"
+                >
+                  {{ val.name }}
+                </li>
+              </ul>
+            </div>
+            <!-- 数字英文 -->
+            <div v-show="!showChineseList" class="english">
+              <ul v-for="(item, index) in data.englishList" :key="index">
+                <li
+                  v-for="val in item"
+                  :key="val.id"
+                  :class="{ del: val.id === 99 || val.id === 97 }"
+                  @click="methods.choose(val)"
+                >
+                  {{ val.name }}
+                </li>
+              </ul>
+            </div>
           </div>
         </div>
       </div>
@@ -57,11 +64,28 @@
 </template>
 
 <script lang="ts" setup>
+const staticData = {
+  releaser: func.releaser(),
+  get numbers() {
+    const rv = Array(8)
+      .fill(null)
+      .map((m) => {
+        return {
+          afterPoint: false,
+          value: '',
+          active: false,
+        }
+      })
+    rv[1].afterPoint = true
+    return rv
+  },
+}
 const popup = ref()
 const data = reactive({
   first: '',
   numArr: [],
-  checkLangages: true,
+  numbers: staticData.numbers,
+  editChinese: false,
   chineseList: [
     [
       { name: '京', id: 1 },
@@ -159,56 +183,81 @@ const data = reactive({
       { name: '删除', id: 99 },
     ],
   ],
-  carNUmber: '',
 })
 
-onMounted(() => {
-  popup.value.open('bottom')
+const cnumbers = computed(() => {
+  const rv = data.numbers
+  rv.forEach((f, i) => {
+    f.active = false
+    if (i === 0) {
+      f.value = data.first
+      return
+    }
+    const curnum = data.numArr[i - 1]
+    if (curnum) {
+      f.value = curnum
+    } else {
+      f.value = ''
+    }
+  })
+  if (showChineseList.value) {
+    rv[0].active = true
+  } else {
+    if (rv[carNumber.value.length]) {
+      rv[carNumber.value.length].active = true
+    } else {
+      rv[rv.length - 1].active = true
+    }
+  }
+  return rv
+})
+/** 显示中文键盘 */
+const showChineseList = computed(() => {
+  return data.first === '' || data.editChinese
 })
+/** 车牌号 */
+const carNumber = computed(() => {
+  return data.first + data.numArr.join('')
+})
+const emits = defineEmits(['submit'])
 const methods = {
-  // 唤醒键盘
-  clickShowKeyboard() {
-    popup.value.open('bottom')
-    if (!data.first) {
-      data.checkLangages = true
+  open(oc) {
+    if (oc) {
+      data.first = oc[0]
+      data.numArr = oc.split('').slice(1)
     } else {
-      data.checkLangages = false
+      data.first = ''
+      data.numArr = []
     }
+    data.editChinese = false
+    popup.value.open('bottom')
+    return staticData.releaser.p
   },
-  // 选择车牌号前面的汉字
-  chooseChinese(val) {
-    if (val.id === 97 || val.id === 98) {
-      data.checkLangages = !data.checkLangages
-    } else if (val.id === 99) {
-      if (data.numArr.length === 0) {
-        data.first = ''
-      }
-    } else {
-      // 把选中的字赋值给第一个格,并且切换键盘
-      data.first = val.name
-      data.checkLangages = false
+
+  // 软键盘点击
+  choose(val) {
+    if (val.id === 99) {
+      methods.del()
+      return
     }
-  },
-  // 选择车牌后面的数字和字母
-  chooseEnglish(val) {
+    // 切换到中文键盘
     if (val.id === 97 || val.id === 98) {
-      data.checkLangages = !data.checkLangages
-    } else if (val.id === 99) {
-      data.numArr.pop()
-
-      // 如果数字,字母被删光了,则切换到中文键盘
-      if (data.numArr.length === 0) {
-        data.checkLangages = true
-      }
+      data.editChinese = !data.editChinese
     } else {
-      // 把选中的值push到data.numArr里面
-      data.numArr.push(val.name)
-      if (data.numArr.length > 7) {
-        data.numArr.pop()
+      // 未设置中文 || 切换到中文键盘
+      if (showChineseList.value) {
+        data.first = val.name
+        if (data.editChinese) {
+          data.editChinese = false
+        }
+      } else {
+        if (data.numArr.length < 7) {
+          data.numArr.push(val.name)
+        } else {
+          data.numArr[6] = val.name
+        }
       }
     }
-    data.carNUmber = data.first + data.numArr.join('')
-    // console.log(data.carNUmber)
   },
   // 完成,隐藏键盘
   hidekeyboards() {
@@ -218,22 +267,30 @@ const methods = {
   submitNumber() {
     const carNumberReg =
       /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-HJ-NP-Z][A-HJ-NP-Z0-9]{4,5}[A-HJ-NP-Z0-9挂学警港澳]$/
-    if (carNumberReg.test(data.carNUmber)) {
-      // console.log(data.carNUmber, '确定按钮')
-      // data.show_chinese = false;
+    if (carNumberReg.test(carNumber.value)) {
+      staticData.releaser.s(carNumber.value)
+      staticData.releaser = func.releaser()
       popup.value.close()
-      // data.$emit('sendCarNumber', data.carNUmber)
       // 清空上一次输入的车牌
       data.first = ''
       data.numArr = []
     } else {
       func.native.showToast('请输入正确的车牌号')
     }
-    data.first = ''
-    data.numArr = []
-    data.checkLangages = true
+  },
+  del() {
+    if (showChineseList.value) {
+      data.first = ''
+      return
+    }
+    if (data.numArr.length) {
+      data.numArr.pop()
+    } else {
+      data.first = ''
+    }
   },
 }
+defineExpose(methods)
 </script>
 
 <style lang="scss" scoped>
@@ -242,32 +299,49 @@ const methods = {
   width: 100%;
 
   .keyboards_title {
-    margin: 15rpx 25rpx;
-    font-size: 20rpx;
+    margin: $p-spac;
     text-align: left;
+
     span {
-      margin-left: 5rpx;
-      font-size: 16rpx;
       color: #45b94d;
     }
   }
-
+  .cn-center {
+    margin: $p-spac $p-spac * 3;
+  }
   .input_box {
     box-sizing: border-box;
     display: flex;
     justify-content: center;
-    margin: 0 auto 25rpx;
-
+    margin: $p-spac 0;
+    font-size: $b-fz;
     li {
+      position: relative;
+
       flex: 1;
+      height: $b-fz * 2;
       margin: 2rpx;
-      font-size: 48rpx;
-      line-height: 100rpx;
+      line-height: $b-fz * 2;
       text-align: center;
       border: 1rpx solid #ced0d2;
-      border-radius: 4rpx;
+      border-radius: $p-spacd2;
+      &.active::after {
+        position: absolute;
+        right: 0;
+        bottom: 8rpx;
+        left: 0;
+        width: 80%;
+        height: 4rpx;
+        margin: auto;
+        content: '';
+        background: $green-color;
+        animation: cursor 1s infinite;
+      }
+    }
+    .point {
+      width: $p-spac;
+      color: $gray-color;
     }
-
     li:last-child {
       background-color: #9eefa4;
     }
@@ -292,31 +366,13 @@ const methods = {
     margin: 10rpx auto 0;
     background-color: rgb(211, 214, 221);
 
-    .finish_key {
-      font-size: 16rpx;
-      line-height: 30rpx;
-      color: rgb(104, 105, 105);
-
-      span {
-        position: absolute;
-        right: 20rpx;
-      }
-    }
-
-    .finish_line {
-      width: 375rpx;
-      border-bottom: 1rpx solid rgb(178, 179, 180);
-    }
-
     .key_box {
       ul {
         box-sizing: border-box;
         display: flex;
         justify-content: center;
-        margin: 10rpx auto 10rpx;
 
         li {
-          // flex: 1;
           width: 62rpx;
           padding: 4rpx;
           margin: 4rpx;
@@ -341,4 +397,21 @@ const methods = {
     }
   }
 }
+@keyframes cursor {
+  0% {
+    opacity: 0.8;
+  }
+  25% {
+    opacity: 0.6;
+  }
+  50% {
+    opacity: 0.4;
+  }
+  75% {
+    opacity: 0.2;
+  }
+  100% {
+    opacity: 0.8;
+  }
+}
 </style>

+ 13 - 6
src/components/business/station/index.vue

@@ -5,17 +5,21 @@
     </div>
     <div class="flex-1 mr-spac">
       <div class="mb-spacd2 center justify-between">
-        <div class="ellipsis mr-spacd2">{{ props.stationInfo.nickName }}</div>
-        <div class="whitespace-nowrap s-fz">{{ props.stationInfo.distance }} km</div>
+        <div class="ellipsis mr-spacd2">
+          {{ func.convert.nullView(props.stationInfo.nickName) }}
+        </div>
+        <div class="whitespace-nowrap s-fz">
+          {{ func.convert.nullView(props.stationInfo.distance) }} km
+        </div>
       </div>
       <div class="mb-spacd2 s-fz ellipsis gray-color sta-addr">
-        {{ props.stationInfo.address }}
+        {{ func.convert.nullView(props.stationInfo.address) }}
       </div>
-      <div class="flex items-baseline">
-        <span class="font-bold mr-spacd2 price-color">
+      <div class="flex items-end">
+        <span class="font-bold mr-spacd2 price-color price">
           {{ props.stationInfo.actualPrice }}
         </span>
-        <span class="s-fz">元/公斤</span>
+        <span class="s-fz price">元/公斤</span>
       </div>
     </div>
     <div>
@@ -60,6 +64,9 @@ const methods = {
 }
 </script>
 <style lang="scss" scoped>
+.price {
+  line-height: $p-fz;
+}
 .station {
   position: relative;
   padding: 0;

+ 4 - 1
src/components/container/index.vue

@@ -1,5 +1,6 @@
 <template>
-  <div class="container">
+  <!-- 小程序环境 会把$attrs 解析到最外层标签(虚拟标签,导致无效),只能使用自定义参数 -->
+  <div class="container" :style="props.cusStyle">
     <!-- 小程序内只能用v-if移除组件,如果用v-show条件false时,整个页面不显示。。 -->
     <ay-pull v-if="store.curPage.pageConfig?.isPager">
       <slot />
@@ -11,9 +12,11 @@
 defineOptions({
   name: 'container',
 })
+const props = defineProps<{ cusStyle?: AnyObject }>()
 </script>
 <style lang="scss" scoped>
 .container {
+  position: relative;
   box-sizing: border-box;
   height: 100vh;
   padding: $p-spac;

+ 45 - 0
src/components/countdown/index.vue

@@ -0,0 +1,45 @@
+<template>
+  <div>{{ data.countdown }}</div>
+</template>
+<script lang="ts" setup>
+defineOptions({
+  name: 'countdown',
+})
+const data = reactive({
+  countdown: '',
+})
+const props = defineProps<{ seconds: number }>()
+const emits = defineEmits(['ticker', 'ender'])
+onMounted(() => {
+  methods.start()
+})
+const methods = {
+  start(seconds = props.seconds) {
+    func.timer({
+      seconds,
+      ticker(tick) {
+        data.countdown = methods.duration(tick)
+      },
+      ender(time) {
+        emits('ender', time)
+      },
+    })
+  },
+  /** 时长处理 */
+  duration(times) {
+    if (times) {
+      let m: number | string = Math.floor(Number(times) / 60)
+      let s: number | string = Math.floor(Number(times) % 60)
+      if (s < 10) {
+        s = `0${s}`
+      }
+      if (m < 10) {
+        m = `0${m}`
+      }
+      return `${m}:${s}`
+    }
+  },
+}
+defineExpose(methods)
+</script>
+<style lang="scss" scoped></style>

+ 27 - 0
src/components/fieldGroups/index.vue

@@ -0,0 +1,27 @@
+<template>
+  <template v-for="(fg, fgi) in props.fieldGroups" :key="fgi">
+    <div v-if="fg.title" :class="fg.class">{{ fg.title }}</div>
+    <div class="chunk2" v-else>
+      <template v-for="(f, i) in fg.fields" :key="i">
+        <div v-if="!f.show || f.show(props.targetData)">
+          <span>{{ f.title }}</span>
+          <div class="center justify-end" :class="f.keyClass">
+            <span class="mr-spacd4" v-if="f.preInfo">{{ f.preInfo }}</span>
+            <span v-if="f.view">
+              {{ func.convert.nullView(f.view(props.targetData[f.key])) }}
+            </span>
+            <span v-else>{{ func.convert.nullView(props.targetData[f.key]) }}</span>
+            <span class="ml-spacd4" v-if="f.unit">{{ f.unit }}</span>
+          </div>
+        </div>
+      </template>
+    </div>
+  </template>
+</template>
+<script lang="ts" setup>
+defineOptions({
+  name: 'fieldGroups',
+})
+const props = defineProps<{ fieldGroups: IFieldGroup; targetData: AnyObject }>()
+</script>
+<style lang="scss" scoped></style>

+ 3 - 0
src/components/skeletons/index.vue

@@ -121,6 +121,9 @@ export default {
   --tw-space-x-reverse: 0;
   margin-right: calc($p-spacd2 * var(--tw-space-x-reverse));
   margin-left: calc($p-spacd2 * calc(1 - var(--tw-space-x-reverse)));
+  &:first-child {
+    margin: 0;
+  }
 }
 
 .space-y > div,

+ 7 - 4
src/enums/index.ts

@@ -2,6 +2,7 @@ enum FormatType {
   YMD = 'YYYY-MM-DD',
   YMDHMS = 'YYYY-MM-DD HH:mm:ss',
   YMD000 = 'YYYY-MM-DD 00:00:00',
+  YMDEnd = 'YYYY-MM-DD 23:59:59',
 }
 /** 页面跳转类型 */
 enum GoPageType {
@@ -39,22 +40,24 @@ enum LoadType {
   backReload,
 }
 enum ReqState {
+  /** 未请求 */
+  unasked = undefined,
   /**
    * 请求中
    */
-  ing,
+  ing = 0,
   /**
    * 请求成功
    */
-  success,
+  success = 1,
   /**
    * 请求失败
    */
-  fail,
+  fail = 2,
   /**
    * 请求取消
    */
-  cancel,
+  cancel = 3,
 }
 enum ErrorType {
   /** 业务逻辑错误 */

+ 5 - 0
src/main.ts

@@ -7,6 +7,11 @@ import { initStore } from './utils/store'
 // #ifdef H5
 import { List } from 'vant'
 import 'vant/lib/index.css'
+// import Vconsole from 'vconsole'
+// if (import.meta.env.DEV) {
+//   const vc = new Vconsole()
+// }
+
 // 小程序环境不支持自定义指令
 // const directives = import.meta.glob('./directives/**/*.ts', { eager: true })
 // console.log(directives)

+ 12 - 2
src/manifest.json

@@ -85,9 +85,19 @@
   "mp-weixin": {
     "appid": "wxf69daeba7aec5be4",
     "setting": {
-      "urlCheck": false
+      "urlCheck": false,
+      "minified": true
     },
-    "usingComponents": true
+    "usingComponents": true,
+    "requiredPrivateInfos": [
+      "getLocation"
+    ],
+    "permission": {
+      "scope.userLocation": {
+        "desc": "当前位置信息将用于附近加气站搜索"
+      }
+    },
+    "lazyCodeLoading": "requiredComponents"
   },
   "mp-alipay": {
     "usingComponents": true,

+ 27 - 13
src/pages.json

@@ -30,19 +30,37 @@
       "type": "page"
     },
     {
-      "path": "pages/createOrder/index",
+      "path": "pages/list/index",
       "type": "page"
     },
     {
-      "path": "pages/list/index",
+      "path": "pages/login/index",
+      "type": "page",
+      "style": {
+        "navigationStyle": "custom"
+      }
+    },
+    {
+      "path": "pages/order/createOrder",
       "type": "page"
     },
     {
-      "path": "pages/login/index",
+      "path": "pages/order/index",
+      "type": "page",
+      "style": {
+        "enablePullDownRefresh": true
+      }
+    },
+    {
+      "path": "pages/order/orderDetail",
+      "type": "page"
+    },
+    {
+      "path": "pages/order/prePay",
       "type": "page"
     },
     {
-      "path": "pages/orderList/index",
+      "path": "pages/org/index",
       "type": "page"
     },
     {
@@ -50,7 +68,11 @@
       "type": "page"
     },
     {
-      "path": "pages/prePay/index",
+      "path": "pages/truckInfo/detail",
+      "type": "page"
+    },
+    {
+      "path": "pages/truckInfo/index",
       "type": "page"
     },
     {
@@ -62,14 +84,6 @@
       "type": "page"
     }
   ],
-  "requiredPrivateInfos": [
-    "getLocation"
-  ],
-  "permission": {
-    "scope.userLocation": {
-      "desc": "当前位置信息将用于附近加气站搜索"
-    }
-  },
   "subPackages": [
     {
       "root": "pagesSubExample",

+ 3 - 3
src/pages/account/index.vue

@@ -2,7 +2,7 @@
   <ay-container>
     <!-- <uni-title type="h2" :title="userTitle"></uni-title> -->
     <span class="font-bold">{{ userTitle }}</span>
-    <uni-section title="所属物流 · 可用余额" type="line"></uni-section>
+    <div class="section s-fz">所属物流 · 可用余额</div>
     <div class="chunk relative s-fz">
       <div class="yebz absolute" v-if="data.accountInfo.flag === 0">[余额不足]</div>
       <div class="flex items-baseline mb-spacd2">
@@ -15,8 +15,8 @@
           }})
         </span>
       </div>
-      <div class="mb-spacd4">所属物流:{{ data.accountInfo.orgName }}</div>
-      <div>车牌号{{ data.accountInfo.carNumber }}</div>
+      <div class="mb-spacd4">所属物流:{{ func.convert.nullView(data.accountInfo.orgName) }}</div>
+      <div>车牌号{{ func.convert.nullView(data.accountInfo.carNumber) }}</div>
     </div>
   </ay-container>
 </template>

+ 214 - 84
src/pages/index/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <ay-container>
+  <ay-container v-show="store.user.isLogined">
     <div class="chunk">
       <div class="center justify-between top">
         <div class="center" @click="methods.goPerson">
@@ -46,16 +46,19 @@
       <div class="center">
         <template v-if="data.qrcode.expire">
           二维码已失效
-          <div class="center p-color" @click="methods.getQrcode">
+          <div class="center p-color" @click="methods.getQrcode(true)">
             <uni-icons type="refresh" color="" size="24"></uni-icons>
             刷新
           </div>
         </template>
-        <template v-else>有效时间:{{ data.qrcode.countdown }}</template>
+        <template v-else>
+          有效时间:
+          <ay-countdown :seconds="300" @ender="data.qrcode.expire = true" />
+        </template>
       </div>
     </div>
     <div class="flex">
-      <div class="chunk flex-1 s-fz mr-spac account" @click="methods.goAccount">
+      <div class="chunk flex-1 s-fz mr-spac money-bg" @click="methods.goAccount">
         <div class="mb-spacd4">可用余额</div>
         <div class="">
           <span class="font-bold b-fz">{{ data.accountInfo.showBalance.balance }}</span>
@@ -64,12 +67,12 @@
         </div>
       </div>
 
-      <div class="chunk flex-1 center justify-start s-fz cars" @click="">
-        <div class="p-color" v-if="false">添加车辆</div>
+      <div class="chunk flex-1 center justify-start s-fz cars" @click="methods.truckManage">
+        <div class="p-color" v-if="data.truckInfo.length === 0">添加车辆</div>
         <div v-else>
           <div class="mb-spacd4">车辆管理</div>
           <div>
-            <span class="font-bold b-fz">1</span>
+            <span class="font-bold b-fz">{{ data.truckInfo.length }}</span>
           </div>
         </div>
@@ -87,33 +90,49 @@
       </div>
     </div>
     <div class="chuck list-app">
-      <div class="center justify-between mb-spac">
+      <div
+        class="center justify-between sticky"
+        id="stationTop"
+        :class="{ stickyed: data.station.stickyed }"
+      >
         <div class="title">附近加气站</div>
         <div v-if="data.userLocation" @click="methods.drawerOpen">
           {{ data.station.curCity }}
           <uni-icons type="down" size="12" />
         </div>
       </div>
-      <template v-if="data.userLocation">
+      <div v-show="data.userLocation" id="stations">
         <ayb-station
           v-for="(la, i) in data.station.listApp"
           :key="i"
           :stationInfo="la"
         ></ayb-station>
-      </template>
-      <div class="center p-color" v-else @click="methods.getListApp({ first: true })">
+      </div>
+      <div
+        class="center p-color"
+        v-show="!data.userLocation"
+        @click="methods.getListApp({ first: true })"
+      >
         查看附近加气站
       </div>
     </div>
 
-    <uni-drawer ref="drawer" mode="right" :maskClick="true" :width="320">
+    <uni-drawer
+      ref="drawer"
+      mode="right"
+      :maskClick="true"
+      :width="320"
+      @change="methods.drawerChange"
+    >
       <uni-indexed-list
         :options="data.station.cityList"
         :show-select="false"
-        @click="methods.bindClick"
-        v-if="data.station.showIndexedList"
+        @click="methods.changeCity"
+        ref="indexedList"
+        v-if="data.station.indexedListShow"
       />
     </uni-drawer>
+    <ayb-carNumber ref="carNumber" />
   </ay-container>
 </template>
 
@@ -124,23 +143,36 @@ import payhistory from '@img/icons/payhistory.png'
 import firm from '@img/icons/firm.png'
 import card from '@img/icons/card.png'
 const drawer = ref()
+const indexedList = ref()
+const carNumber = ref()
+
 const staticData = {
+  /** 选择的城市 缓存key名 */
+  cctkn: 'chooseCity',
+  /** 默认选择城市 */
+  defCity: '全部',
+  /** websocket 实例 */
   client: null,
-  entranceArgs: null as AyContainerEntryArgs,
+  // entranceArgs: null as AyContainerEntryArgs,
+  /** 临时记录位置信息 */
   location: { longitude: '', latitude: '' } as any,
+  indexedListShowed: false,
+  /** 索引组件数据监听器 */
+  indexedListWatcher: null,
+  /** 页面滚动距离 */
+  scrollTop: 0,
 }
 const data = reactive({
+  truckInfo: [] as PersonDriver对象[],
   accountInfo: { showBalance: { balance: '', suffix: '' } } as IAccountInfo,
   /** 用户已授权定位 */
   userLocation: false,
   /** 二维码相关 */
   qrcode: {
-    /** 二维码过期倒计时 */
-    countdown: '',
     /** 二维码 */
     img: null,
     /** 已过期 */
-    expire: false,
+    expire: true,
   },
   /** 菜单列表 */
   menus: [
@@ -166,15 +198,41 @@ const data = reactive({
     },
   ],
   station: {
-    /** 首次呈现,解决索引滑动失效问题 */
-    showIndexedList: false,
+    /** 头部已吸顶 */
+    stickyed: false,
     cityList: [] /** 附近加气站列表 */,
-    curCity: '全部',
+    curCity: staticData.defCity,
     listApp: [],
+    indexedListShow: false,
   },
 })
-const methods = ay.initMethods(
+const methods =
+  // ay.initMethods(
   {
+    getTruckInfo() {
+      webapi.strategy.get_truck_info().then((res) => {
+        data.truckInfo = aop.request.AR.truckInfo(res)
+      })
+    },
+    truckManage() {
+      if (data.truckInfo.length) {
+        ay.goPage(config.pages.truckInfo_index)
+      } else {
+        carNumber.value.open().then((cn) => {
+          webapi.strategy
+            .bind_person_truck<{ userId: string }>({
+              userId: store.user.userInfo.user_id,
+              newCarNumber: cn,
+            })
+            .then((res) => {
+              if (res) {
+                func.native.showToast('添加成功')
+                methods.getTruckInfo()
+              }
+            })
+        })
+      }
+    },
     goPerson() {
       ay.goPage(config.pages.personCenter_index)
     },
@@ -184,18 +242,54 @@ const methods = ay.initMethods(
           methods.goPrePay()
         },
         1() {
-          ay.goPage(config.pages.orderList_index)
+          ay.goPage(config.pages.order_index)
+        },
+        2() {
+          ay.goPage(config.pages.org_index)
         },
       }
       maps[menu.id]()
     },
     drawerOpen() {
       drawer.value.open()
-      data.station.showIndexedList = true
+      data.station.indexedListShow = true
+      // 解决uni-indexed-list 组件滑动失效问题
+      // 问题原因: 因为嵌套于uni-drawer内,造成uni-indexed-list的winOffsetY值获取有误
+      // 解决方法:通过阅读组件源码发现uni-indexed-list在初始化时会设置winOffsetY,再给他设置正确的值。
+      // 小程序于h5环境设置时机不同;
+      // 组件内部:小程序仅首次渲染完毕会设置winOffsetY,h5环境每次打开组件都会重新设置winOffsetY
+      // 通过监听$data.loaded的变化,重新设置winOffsetY为页面滚动距离,以及小程序环境-每次呈现组件后重新设置winOffsetY
+
+      nextTick(() => {
+        // 小程序环境-每次呈现组件后重新设置winOffsetY
+        // #ifdef MP
+        if (indexedList.value) {
+          indexedList.value.$data.winOffsetY = staticData.scrollTop
+        }
+        // #endif
+        if (!staticData.indexedListWatcher) {
+          staticData.indexedListWatcher = watch(
+            () => indexedList.value?.$data.loaded,
+            (nv) => {
+              // 小程序环境仅首次呈现监听到, h5环境每次呈现都会监听到
+              if (indexedList.value) {
+                indexedList.value.$data.winOffsetY = staticData.scrollTop
+              }
+            },
+            {
+              // deep: true,
+            },
+          )
+          // 调用可释放监听
+          // staticData.indexedListWatcher()
+        }
+      })
     },
-    bindClick(args) {
+    drawerChange(isopen) {},
+    changeCity(args) {
       drawer.value.close()
       data.station.curCity = args.item.name
+      uni.setStorageSync(staticData.cctkn, args.item.name)
       methods.getListApp()
     },
     goAccount() {
@@ -226,7 +320,7 @@ const methods = ay.initMethods(
             (res) => {
               const body = JSON.parse(res.body)
               if (body.type === 1) {
-                ay.goPage(config.pages.prePay_index, { params: JSON.parse(body.content) })
+                ay.goPage(config.pages.order_prePay, { params: JSON.parse(body.content) })
               } else if (body.type === 0) {
                 const content = JSON.parse(body.content)
                 uni
@@ -250,19 +344,21 @@ const methods = ay.initMethods(
         JSON.stringify({ content: '1212' }),
       )
     },
-    async goPrePay() {
+    async goPrePay(type: 0 | 1 = 0) {
       const nopayfordriver = await webapi.pay.find_unpayfordriver()
       if (nopayfordriver) {
         // 跳未支付
-        ay.goPage(config.pages.prePay_index, { params: { orderId: nopayfordriver.orderId } })
+        ay.goPage(config.pages.order_prePay, { params: { orderId: nopayfordriver.orderId } })
         return true
       } else {
-        func.native.showToast('暂无待支付订单!')
+        if (type === 0) {
+          func.native.showToast('暂无待支付订单!')
+        }
         return false
       }
     },
     async scanCode() {
-      if (await methods.goPrePay()) {
+      if (await methods.goPrePay(1)) {
         return
       }
       const reqStr = await uni
@@ -270,13 +366,21 @@ const methods = ay.initMethods(
           scanType: ['qrcode'],
         })
         .catch((err) => {
-          func.native.showToast('二维码无效')
+          // 二维码解析失败
+          if (err.errMsg !== 'scanCode:fail cancel') {
+            func.native.showToast('二维码无效')
+          }
           return Promise.reject(err)
         })
       let ret = { gasstationId: '', cashierId: '' }
       try {
         ret = JSON.parse(reqStr.result)
+        // 没有包含必要信息
+        if (!(ret.gasstationId && ret.cashierId)) {
+          func.native.showToast('二维码无效')
+        }
       } catch {
+        // 反序列化失败
         func.native.showToast('二维码无效')
         return
       }
@@ -305,7 +409,7 @@ const methods = ay.initMethods(
           })
           if (gasJudge === 1) {
             // 创建订单
-            ay.goPage(config.pages.createOrder_index, { params: ret })
+            ay.goPage(config.pages.order_createOrder, { params: ret })
           } else if (gasJudge === 2) {
             func.native.showModal({
               title: '错误提示',
@@ -326,7 +430,7 @@ const methods = ay.initMethods(
     },
     getCityList() {
       webapi.strategy.city_list().then((res) => {
-        res.unshift({ text: '全部', children: [{ text: '全部' }] })
+        res.unshift({ text: staticData.defCity, children: [{ text: staticData.defCity }] })
         data.station.cityList = res.map((m) => {
           return {
             letter: m.text,
@@ -347,7 +451,7 @@ const methods = ay.initMethods(
       let location = staticData.location
       // 上拉不重新获取位置
       if (!cras.isAdd) {
-        location = await uni.getLocation()
+        location = await func.native.getLocation()
         staticData.location = location
       }
       data.userLocation = true
@@ -357,12 +461,12 @@ const methods = ay.initMethods(
             page: cras.page,
             size: cras.size,
             param: {
-              city: data.station.curCity === '全部' ? '' : data.station.curCity,
+              city: data.station.curCity === staticData.defCity ? '' : data.station.curCity,
               longitude: location.longitude.toString(),
               latitude: location.latitude.toString(),
             },
           },
-          { showLoading: first || !cras.isAdd },
+          { showLoading: first }, // || !cras.isAdd },
         )
         .then((res) => {
           if (cras.isAdd) {
@@ -373,51 +477,31 @@ const methods = ay.initMethods(
         })
     },
 
-    /** 时长处理 */
-    duration(times) {
-      if (times) {
-        let m: number | string = Math.floor(Number(times) / 60)
-        let s: number | string = Math.floor(Number(times) % 60)
-        if (s < 10) {
-          s = `0${s}`
-        }
-        if (m < 10) {
-          m = `0${m}`
-        }
-        return `${m}:${s}`
-      }
-    },
-    getQrcode() {
+    getQrcode(refresh = false) {
       return webapi.strategy.get_user_qrcode().then(async (res) => {
         // await func.awaiter()
         data.qrcode.img = res
         data.qrcode.expire = false
-        func.timer({
-          seconds: 300,
-          ticker(tick) {
-            data.qrcode.countdown = methods.duration(tick)
-          },
-          ender() {
-            data.qrcode.expire = true
-          },
-        })
       })
     },
-  },
-  {
-    scanCode: { showLoading: true },
-  },
-)
+  }
+//   {
+//     scanCode: { showLoading: true },
+//   },
+// )
 ay.entrance(
   (args) => {
-    staticData.entranceArgs = args
-    // webapi.strategy.getCarNumber<null, { truckId: string }>().then((res) => {
-    //   webapi.strategy.getQrcode({}, { appendUrl: '/' + res.truckId }).then((resq) => {
-    //     data.qrcode = resq
-    //   })
-    // })
+    // staticData.entranceArgs = args
     const init = async () => {
+      webapi.strategy.get_driver_balance().then((res) => {
+        data.accountInfo = {
+          ...res,
+          ...aop.request.AR.getAccountInfo(res),
+        }
+      })
+
       // #ifdef MP
+      // 用户是否授权了获取地理位置
       await uni
         .getSetting()
         .then((res) => {
@@ -428,17 +512,13 @@ ay.entrance(
         .catch()
       // #endif
       methods.getListApp({ cras: args.cras })
-      webapi.strategy.get_driver_balance().then((res) => {
-        data.accountInfo = {
-          ...res,
-          ...aop.request.AR.getAccountInfo(res),
-        }
-      })
+      methods.getTruckInfo()
     }
     if (args.loadType === enums.LoadType.onLoad) {
       methods.initWS()
       methods.getQrcode()
       methods.getCityList()
+      data.station.curCity = uni.getStorageSync(staticData.cctkn) || staticData.defCity
       init()
     }
 
@@ -451,12 +531,41 @@ ay.entrance(
     }
   },
   {
-    // addLoadTypes: [enums.LoadType.onLoad],
+    // addLoadTypes: [enums.LoadType.onShow],
   },
 )
+
+onMounted(() => {
+  // #ifdef MP
+  const iob = uni.createIntersectionObserver(getCurrentInstance())
+
+  iob.relativeTo('#stations').observe('#stationTop', (res) => {
+    data.station.stickyed = res.intersectionRatio > 0
+  })
+  // #endif
+  // uni
+  // .createSelectorQuery()
+  // .select('#stationTop')
+  // // .boundingClientRect()
+  // .fields(
+  //   {
+  //     scrollOffset: true,
+  //     rect:true,
+  //   },
+  //   (res) => {
+  //     console.log(res)
+  //   },
+  // )
+  // .exec((res) => {
+  //   console.log(res)
+  // })
+})
+onPageScroll((res) => {
+  staticData.scrollTop = res.scrollTop
+})
 </script>
 
-<style lang="scss">
+<style lang="scss" scoped>
 .top {
   padding-bottom: $p-spac;
   border-bottom: 1px dashed;
@@ -486,14 +595,35 @@ ay.entrance(
   width: 152rpx;
   height: 116rpx;
 }
-
+#stationTop {
+  top: -1px;
+  z-index: 1;
+  padding: $p-spac 0;
+  background: #fff;
+  &.stickyed {
+    border-bottom: 1rpx solid $border-color;
+    @extend %box-shadow;
+    &::before,
+    &::after {
+      position: absolute;
+      width: $p-spac;
+      height: 100%;
+      content: '';
+      background-color: #fff;
+      border-bottom: 1rpx solid $border-color;
+    }
+    &::before {
+      left: -$p-spac;
+    }
+    &::after {
+      right: -$p-spac;
+    }
+  }
+}
 .unit {
   margin: 0 $p-spacd2;
 }
 $bgc: rgba($p-color, 0.4);
-.account {
-  background-color: rgba($p-price-color, 0.1);
-}
 .cars {
   position: relative;
   overflow: hidden;
@@ -521,7 +651,7 @@ $bgc: rgba($p-color, 0.4);
   }
 }
 .list-app {
-  margin-top: $p-spac * 2;
+  margin-top: $p-spac;
   .title {
     font-size: $p-fz * 1.2;
     font-weight: bold;

+ 24 - 23
src/pages/login/index.vue

@@ -1,13 +1,14 @@
 <template>
-  <ay-container>
-    <div class="flex-col center justify-around login-con">
-      <div class="center">
+  <ay-container :cusStyle="{ 'padding-top': config.common.SystemInfo.safeArea.top + 'px' }">
+    <div class="absolute center font-bold $bs-fz title">登录</div>
+    <div class="flex-col center justify-between login-con">
+      <div class="center info">
         <image class="logo" src="/static/logo.png" mode="scaleToFill" />
-        <span class="title">优质加气 大象帮你</span>
+        <span class="desc">优质加气 大象帮你</span>
       </div>
       <div class="p-spac login-phone">
         <button
-          class="login-btn"
+          type="green"
           :loading="store.webapi.user.token.ing"
           :disabled="store.webapi.user.token.ing"
           :open-type="data.check ? 'getPhoneNumber' : ''"
@@ -84,7 +85,7 @@ const methods = {
 }
 ay.entrance(({ exts }) => {
   // #ifdef MP
-  uni.hideHomeButton()
+  // uni.hideHomeButton()
   // #endif
   if (exts) {
     // store.user.initUserInfo(exts.detail.data[0])
@@ -95,8 +96,10 @@ ay.entrance(({ exts }) => {
 })
 </script>
 <style lang="scss" scoped>
-.sss11 {
-  color: red;
+.title {
+  right: 0;
+  left: 0;
+  height: 44px;
 }
 .login-con {
   height: 100%;
@@ -105,27 +108,25 @@ ay.entrance(({ exts }) => {
   box-sizing: border-box;
   width: 100%;
   font-size: 26rpx;
-  .login-btn {
-    margin-bottom: 20rpx;
-    color: #fff;
-    background: #00ad65;
-    border-radius: 50rpx;
-  }
   .checkbox {
     transform: scale(0.6);
   }
 }
-.logo {
-  width: 100rpx;
-  height: 100rpx;
-}
-.title {
-  margin-left: 30rpx;
-  font-size: 40rpx;
-  font-weight: bold;
+.info {
+  margin-top: 200rpx;
+  .logo {
+    width: 100rpx;
+    height: 100rpx;
+  }
+  .desc {
+    margin-left: 30rpx;
+    font-size: 40rpx;
+    font-weight: bold;
+  }
 }
 .login-H5 {
-  margin-top: 300rpx;
+  margin-top: 400rpx;
+  margin-bottom: $p-spac;
 }
 .accet-button-shake {
   animation: shake 0.4s infinite;

+ 14 - 5
src/pages/createOrder/index.vue

@@ -1,12 +1,12 @@
 <template>
   <ay-container>
-    <div class="station">站信息</div>
+    <ayb-station type="2" :stationInfo="data.stationInfo" />
     <div class="station">驾驶员信息</div>
     <div class="station">
       本次加气量(公斤):
       <uni-easyinput
         v-model="data.gasQty"
-        type="number"
+        type="digit"
         placeholder="请输入"
         @confirm="methods.confirm"
       />
@@ -17,6 +17,7 @@
 
 <script lang="ts" setup>
 const data = reactive({
+  stationInfo: {},
   gasQty: 0,
 })
 const user = computed(() => store.user.userInfo)
@@ -43,13 +44,21 @@ const methods = {
         createrName: user.value.user_name,
       })
       .then((res) => {
-        ay.goPage(config.pages.prePay_index, { params: { orderId: res.orderId } })
+        ay.goPage(config.pages.order_prePay, {
+          goPageType: enums.GoPageType.redirectTo,
+          params: { orderId: res.orderId },
+        })
       })
   },
 }
 
-ay.entrance((args) => {
-  console.log('oncload66', args)
+ay.entrance(async (args) => {
+  const location = await func.native.getLocation()
+  data.stationInfo = await webapi.strategy.find_for_mini({
+    gasstationId: pageConfig.value.params.gasstationId,
+    longitude: location.longitude.toString(),
+    latitude: location.latitude.toString(),
+  })
 })
 </script>
 

+ 42 - 28
src/pages/orderList/index.vue

@@ -18,10 +18,15 @@
           />
         </uni-badge>
       </div>
-      <div class="chunk child-c-jb" v-for="(o, i) in data.orderList" :key="i">
+      <div
+        class="chunk childs-fcjb-mbd2"
+        v-for="(o, i) in data.orderList"
+        :key="i"
+        @click="methods.goDetail(o)"
+      >
         <div>
           <div class="font-bold p-fz">{{ o.nickName }}</div>
-          <div>{{ func.convert.getOrderStatusStr(o.orderStatus) }}</div>
+          <div>{{ func.convert.getOrderStatusStr(o.settleStatus) }}</div>
         </div>
         <div>
           <div>加气量(公斤)</div>
@@ -44,10 +49,7 @@
       @change="methods.drawerChange"
     >
       <div class="m-spac">
-        <div class="center justify-between b-fz mb-spac">
-          <span></span>
-          <!-- <uni-icons class="hidden" type="closeempty" color="" size="24" /> -->
-
+        <div class="center b-fz mb-spac">
           <div class="font-bold">
             <span>筛选</span>
             <span v-if="checkCount">
@@ -56,23 +58,35 @@
             </span>
           </div>
 
-          <uni-icons type="closeempty" color="" size="24" @click="methods.closeFilters" />
+          <uni-icons
+            type="closeempty"
+            color=""
+            size="24"
+            class="abs-right"
+            @click="methods.closeFilters"
+          />
         </div>
         <div>
           <div>
-            <div v-for="(f, i) in filtersView" :key="i">
-              <uni-section
-                :class="'section' + f.type"
-                :title="f.label"
-                titleFontSize="18px"
-                type="line"
-              ></uni-section>
-              <!-- type="circle" -->
-              <!-- <div class="font-bold mb-spac" v-else>{{ f.label }}</div> -->
-              <div class="center justify-between flex-wrap">
+            <div v-for="(f, i) in filtersView" :key="i" :class="{ 'nmt-spac': f.type === 1 }">
+              <div
+                class="section"
+                :class="{
+                  'font-bold': !f.type,
+                  'ml-spacd2': f.type === 1,
+                  's-fz': f.type === 1,
+                }"
+              >
+                {{ f.label }}
+              </div>
+
+              <div class="center justify-between flex-wrap s-fz">
                 <div
                   class="center whitespace-nowrap p-spacd2 chunk f-item"
-                  :class="{ checked: item.checked, isall: item.value === staticData.nullValue }"
+                  :class="{
+                    'checked-full': item.checked,
+                    isall: item.value === staticData.nullValue,
+                  }"
                   v-for="(item, ii) in f.items"
                   :key="ii"
                   @click="methods.filterCheck(f, item)"
@@ -114,7 +128,7 @@ const data = reactive({
     {
       label: '结算状态',
       value: 'settleStatus',
-      items: func.convert.getCheckItem(config.common.orderStatus),
+      items: func.convert.getCheckItem(config.common.settleStatus),
     },
     {
       label: '支付方式',
@@ -166,6 +180,9 @@ const checkCount = computed(() =>
     .reduce((a, b) => a + b, 0),
 )
 const methods = {
+  goDetail(od) {
+    ay.goPage(config.pages.order_orderDetail, { params: od })
+  },
   /** 从缓存 初始化查询条件选中状态 */
   getStoreFilterCheckeds() {
     return uni.getStorageSync(staticData.fcn) || {}
@@ -173,7 +190,7 @@ const methods = {
   /** 从缓存 初始化查询条件选中状态 */
   initFiltersCheck() {
     const filterCheckeds: any = methods.getStoreFilterCheckeds()
-    if (filterCheckeds) {
+    if (Object.keys(filterCheckeds).length) {
       data.filters.forEach((f) => {
         f.items.forEach((ff) => {
           ff.checked = filterCheckeds[f.value]?.includes(ff.value)
@@ -245,7 +262,7 @@ const methods = {
           size: cras.size,
           param: {
             startTime: func.getDate(data.range[0]).format(enums.FormatType.YMD000),
-            endTime: func.getDate(data.range[1]).format(enums.FormatType.YMD000),
+            endTime: func.getDate(data.range[1]).format(enums.FormatType.YMDEnd),
             ...paramFilters,
           },
         },
@@ -283,6 +300,10 @@ ay.entrance((args) => {
 </script>
 
 <style lang="scss">
+.abs-right {
+  position: absolute;
+  right: $p-spac;
+}
 .f-item {
   box-sizing: border-box;
   width: 31%;
@@ -293,11 +314,4 @@ ay.entrance((args) => {
     color: $p-color;
   }
 }
-::v-deep .section1.uni-section {
-  margin-top: -$p-spac;
-  margin-bottom: -$p-spacd2;
-}
-::v-deep .section0.uni-section {
-  @apply font-bold;
-}
 </style>

+ 371 - 0
src/pages/order/orderDetail.vue

@@ -0,0 +1,371 @@
+<template>
+  <ay-container>
+    <ay-skeletons :rowList="data.rowList" :loading="store.webapi.strategy.get_order_detail.ing">
+      <div class="chunk2 p-color font-bold">
+        <div>
+          <div>
+            {{ data.orderDetail.nickName }}
+            <uni-icons type="right" color="" size="12" />
+          </div>
+        </div>
+      </div>
+      <div class="chunk2">
+        <div>
+          <div>加气量{{ data.orderDetail.gasQty }}公斤</div>
+          <div>
+            <div>结算金额¥{{ data.orderDetail.amount }}元</div>
+          </div>
+        </div>
+        <div v-if="data.orderDetail.carrierRebateHand">
+          <div></div>
+          <div @click="data.switchPriceDet = !data.switchPriceDet">
+            优惠金额¥{{ data.orderDetail.carrierRebateHand }}元
+            <uni-icons :type="data.switchPriceDet ? 'up' : 'down'" color="" class="p-color p-fz" />
+          </div>
+        </div>
+        <div v-if="data.switchPriceDet">
+          <div></div>
+          <div class="chunk childs-fcjb-mbd2 rebate-detail money-bg">
+            <div v-for="(rd, i) in data.orderDetail.rebateDetailHand" :key="i">
+              <div>{{ config.common.interestType[rd.interestType] }}</div>
+              <div>¥{{ rd.rebateAmount }}元</div>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <div>
+        <ay-fieldGroups :fieldGroups="curFieldGroups" :targetData="data.orderDetail" />
+      </div>
+    </ay-skeletons>
+  </ay-container>
+</template>
+
+<script lang="ts" setup>
+const staticData = {}
+const data = reactive({
+  rowList: [
+    {
+      align: 'left',
+      verticalAlign: 'top',
+      colItems: [
+        {
+          style: {
+            width: '100%',
+          },
+        },
+      ],
+    },
+    ...Array(20).fill({
+      align: 'left',
+      colItems: 1,
+    }),
+    {
+      align: 'left',
+      colItems: [
+        {
+          style: {
+            width: '60%',
+          },
+        },
+      ],
+    },
+  ],
+  switchPriceDet: false,
+  orderDetail: {} as 订单详情,
+  fieldGroups: [
+    {
+      roles: ['cashier', 'filler'],
+      fields: [
+        {
+          title: '订单编号',
+          key: 'orderId',
+          status: 'settleStatus',
+        },
+      ],
+    },
+    {
+      roles: ['carrier', 'driver'],
+      fields: [
+        {
+          title: '结算状态',
+          key: 'settleStatus',
+          view(data) {
+            return config.common.settleStatus[data]
+          },
+        },
+        {
+          title: '平台价',
+          key: 'platformPriceHand',
+          unit: '元/公斤',
+          preInfo: '¥',
+        },
+        {
+          title: '结算价',
+          key: 'actualPrice',
+          unit: '元/公斤',
+          preInfo: '¥',
+        },
+        {
+          title: '创建时间',
+          key: 'createDate',
+          view(data) {
+            return func.getDate(data).format()
+          },
+        },
+        {
+          show(data) {
+            //  已支付||已退款 才显示
+            return [2, 6].includes(data.settleStatus)
+          },
+          title: '支付时间',
+          key: 'updateDate',
+          view(data) {
+            return func.getDate(data).format()
+          },
+        },
+        {
+          show(data) {
+            //  已取消 才显示
+            return data.settleStatus === 3
+          },
+          title: '取消时间',
+          key: 'updateDate',
+          view(data) {
+            return func.getDate(data).format()
+          },
+        },
+        {
+          show(data) {
+            //  已退款 才显示
+            return data.settleStatus === 6
+          },
+          title: '退款时间',
+          key: 'refundDate',
+          view(data) {
+            return func.getDate(data).format()
+          },
+        },
+        {
+          show(data) {
+            //  已支付||已退款 才显示
+            return [2, 6].includes(data.settleStatus)
+          },
+          title: '支付方式',
+          key: 'payType',
+          view(data) {
+            return config.common.payType[data]
+          },
+        },
+        {
+          title: '订单编号',
+          key: 'orderId',
+          status: 'settleStatus',
+        },
+      ],
+    },
+    {
+      roles: ['cashier', 'filler'],
+      fields: [
+        {
+          title: '结算金额',
+          key: 'amount',
+          unit: '元',
+          preInfo: '¥',
+        },
+      ],
+    },
+    {
+      roles: ['cashier', 'filler'],
+      fields: [
+        {
+          title: '加气量',
+          key: 'gasQty',
+          unit: '公斤',
+        },
+        {
+          title: '订单总金额',
+          key: 'allAmountHand',
+          unit: '元',
+          preInfo: '¥',
+        },
+        {
+          title: '优惠金额',
+          cls: 'red',
+          key: 'carrierRebateHand',
+          // view: 'currency',
+          unit: '元',
+        },
+        {
+          title: '平台价',
+          key: 'platformPriceHand',
+          unit: '元/公斤',
+          preInfo: '¥',
+        },
+        {
+          title: '结算价',
+          key: 'actualPrice',
+          unit: '元/公斤',
+          preInfo: '¥',
+        },
+      ],
+    },
+    {
+      roles: ['cashier', 'filler'],
+      fields: [
+        {
+          title: '销售方式',
+          key: 'orderType',
+          view(data) {
+            return config.common.orderType[data]
+          },
+        },
+        {
+          title: '支付方式',
+          key: 'payType',
+          view(data) {
+            return config.common.payType[data]
+          },
+        },
+        {
+          title: '交易模式',
+          key: 'tradeType',
+          view(data) {
+            return config.common.tradeType[data]
+          },
+        },
+      ],
+    },
+    {
+      fields: [
+        {
+          title: '物流公司',
+          key: 'carrierOrgName',
+        },
+        {
+          roles: ['cashier', 'filler'],
+          title: '物流联系电话',
+          key: 'carrierMobile',
+          // view: 'mobile',
+        },
+        {
+          title: '车牌号',
+          key: 'carNumber',
+        },
+        {
+          title: '驾驶员',
+          key: 'driverName',
+        },
+      ],
+    },
+    {
+      fields: [
+        {
+          title: '加气站',
+          key: 'nickName',
+        },
+        {
+          title: '站联系电话',
+          key: 'stationMobile',
+          view(data) {
+            return func.convert.mobileDes(data)
+          },
+        },
+        {
+          title: '收银员',
+          key: 'cashierName',
+        },
+        {
+          roles: ['cashier', 'filler'],
+          title: '站清分方式',
+          key: 'splitType',
+          view(data) {
+            return config.common.splitType[data]
+          },
+        },
+        {
+          roles: ['cashier', 'filler'],
+          title: '站清分额',
+          key: 'serviceFee',
+          unit: '元',
+          preInfo: '¥',
+        },
+        {
+          roles: ['cashier', 'filler'],
+          title: '站清分单价',
+          key: 'gasstationFee',
+          unit: '元/公斤',
+          preInfo: '¥',
+        },
+      ],
+    },
+    {
+      roles: ['cashier', 'filler'],
+      fields: [
+        {
+          title: '创建时间',
+          key: 'createDate',
+          view(data) {
+            return func.getDate(data).format()
+          },
+        },
+        {
+          show(data) {
+            //  已支付||已退款 才显示
+            return [2, 6].includes(data.settleStatus)
+          },
+          title: '支付时间',
+          key: 'updateDate',
+          view(data) {
+            return func.getDate(data).format()
+          },
+        },
+        {
+          show(data) {
+            //  已取消 才显示
+            return data.settleStatus === 3
+          },
+          title: '取消时间',
+          key: 'updateDate',
+          view(data) {
+            return func.getDate(data).format()
+          },
+        },
+        {
+          show(data) {
+            //  已退款 才显示
+            return data.settleStatus === 6
+          },
+          title: '退款时间',
+          key: 'refundDate',
+          view(data) {
+            return func.getDate(data).format()
+          },
+        },
+      ],
+    },
+  ] as IFieldGroup[],
+})
+const curFieldGroups = computed(() =>
+  data.fieldGroups.filter((f) => !f.roles || f?.roles?.includes('driver')),
+)
+const methods = {}
+ay.entrance((args) => {
+  webapi.strategy
+    .get_order_detail({ orderId: store.curPage.pageConfig.params.orderId, orderType: 1 })
+    .then((res) => {
+      uni.setNavigationBarTitle({
+        title: '加气订单 · ' + config.common.settleStatus[res.settleStatus],
+      })
+      data.orderDetail = res
+    })
+})
+</script>
+
+<style lang="scss">
+.rebate-detail {
+  width: 50%;
+  padding: $p-spacd2;
+  margin-bottom: 0;
+}
+</style>

+ 326 - 0
src/pages/order/prePay.vue

@@ -0,0 +1,326 @@
+<template>
+  <ay-container>
+    <ay-skeletons :rowList="data.rowList" :loading="data.firstLoad">
+      <div class="station">
+        <ayb-station type="2" :stationInfo="data.stationInfo" />
+      </div>
+      <div class="chunk1">
+        <div>
+          <span class="mr-spacd4">加气量</span>
+          <span class="font-bold b-fz mr-spacd4">{{ data.orderDetail.gasQty }}</span>
+          <span>公斤</span>
+        </div>
+      </div>
+      <div class="section s-fz">选择支付方式</div>
+      <div class="flex chunk s-fz" :class="{ checked: data.fpayType === 0 }">
+        <span
+          class="mr-spacd2 radio"
+          :class="{ checked: data.fpayType === 0 }"
+          @click="methods.choose(0)"
+        ></span>
+        <div>
+          <span class="font-bold" @click="methods.choose(0)">个人支付</span>
+          <div class="ml-spacd2 mt-spacd2">
+            结算金额 ¥ {{ personPay?.amount }} 元 (结算价 ¥ {{ personPay?.actualPrice }} 元/公斤)
+          </div>
+        </div>
+      </div>
+      <div class="flex chunk s-fz" v-if="carrierPay" :class="{ checked: data.fpayType === 1 }">
+        <span
+          class="mr-spacd2 radio"
+          :class="{ checked: data.fpayType === 1 }"
+          @click="methods.choose(1)"
+        ></span>
+        <div class="flex-1">
+          <span class="font-bold" @click="methods.choose(1)">所属物流支付</span>
+          <div class="childs-fc-mbd2 ml-spacd2 mt-spacd2">
+            <div @click="methods.switchRebateDetail">
+              结算金额 ¥ {{ carrierPay.amount }} 元 (结算价 ¥
+              {{ carrierPay.actualPrice }} 元/公斤)
+            </div>
+            <span v-if="carrierPay.carrierRebate">
+              优惠金额{{ carrierPay.carrierRebate }}元
+              <uni-icons
+                :type="data.showRebateDetail ? 'up' : 'down'"
+                color=""
+                class="p-color p-fz"
+                v-if="carrierPay.rebateNum"
+                @click="methods.switchRebateDetail"
+              />
+            </span>
+            <span
+              v-if="carrierPay.rebateNum"
+              v-show="data.showRebateDetail"
+              class="chunk childs-fcjb-mbd2 rebate-detail money-bg"
+            >
+              <div v-for="(rd, i) in carrierPay.rebateDetail" :key="i">
+                <div>{{ config.common.interestType[rd.interestType] }}</div>
+                <div>¥{{ rd.rebateAmount }}元</div>
+              </div>
+            </span>
+            <div class="pt-spacd2 top-line">{{ carrierPay.carrierOrgName }}</div>
+            <div>[{{ carrierPay.carNumber }}]</div>
+            <div class="justify-start">
+              <div>可用余额¥{{ carrierPay.balance }}元</div>
+              <div class="center p-color ml-spacd2" @click="methods.paysel">
+                <uni-icons
+                  type="refresh"
+                  color=""
+                  size="20"
+                  :class="{ rotater: store.webapi.strategy.paysel.ing }"
+                ></uni-icons>
+                刷新
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="chunk2">
+        <div>
+          <span>创建订单</span>
+          <div>{{ data.orderDetail.createDate }}</div>
+        </div>
+        <div>
+          <span>订单编号</span>
+          <div>{{ data.orderDetail.orderId }}</div>
+        </div>
+        <div>
+          <span>驾驶员</span>
+          <div>{{ data.orderDetail.driverName }}</div>
+        </div>
+      </div>
+      <div class="btns">
+        <button
+          type="primary"
+          :disabled="!canPay"
+          :loading="store.webapi.pay.order_pay.ing"
+          @click="methods.pay()"
+        >
+          {{ curPay?.buttonMsg }}
+        </button>
+      </div>
+    </ay-skeletons>
+  </ay-container>
+</template>
+
+<script lang="ts" setup>
+const data = reactive({
+  firstLoad: true,
+  /** 页面选择支付类型: -1:未选择 0:个人:1:物流 */
+  fpayType: -1,
+  orderDetail: {} as 订单详情,
+  stationInfo: {} as GasstationVO对象,
+  paysel: {} as 待支付订单_可选支付方式获取实体类,
+  showRebateDetail: false,
+  rowList: [
+    {
+      align: 'left',
+      verticalAlign: 'top',
+      colItems: [
+        {
+          style: {
+            width: '168rpx',
+            height: '168rpx',
+            'flex-shrink': 0,
+          },
+        },
+        {
+          style: {
+            width: '100%',
+          },
+          childRowItems: [
+            {
+              style: {
+                width: '80%',
+              },
+            },
+            {
+              style: {
+                width: '100%',
+              },
+            },
+            {
+              style: {
+                width: '100%',
+              },
+            },
+          ],
+        },
+      ],
+    },
+    ...Array(20).fill({
+      align: 'left',
+      colItems: 1,
+    }),
+    {
+      align: 'left',
+      colItems: [
+        {
+          style: {
+            width: '60%',
+          },
+        },
+      ],
+    },
+  ],
+})
+
+const canPay = computed(() => curPay.value?.buttonEnable && !store.webapi.pay.order_pay.ing)
+const pageParams = computed(() => store.curPage.pageConfig.params)
+const personPay = computed(() => data.paysel?.personPay)
+const carrierPay = computed(() => data.paysel?.carrierPay)
+/** 当前支付方式 */
+const curPay = computed<待支付订单_可选支付方式物流支付实体类>(() => {
+  let rv: 待支付订单_可选支付方式物流支付实体类 = {
+    buttonMsg: '请选择支付方式',
+    buttonEnable: false,
+  }
+  if (data.fpayType === 0) {
+    rv = {
+      ...data.paysel?.personPay,
+      wxAmount: data.paysel.personPay.amount,
+    }
+  }
+  if (data.fpayType === 1) {
+    rv = data.paysel?.carrierPay
+  }
+  return rv
+})
+
+const methods = {
+  switchRebateDetail() {
+    data.showRebateDetail = !data.showRebateDetail
+  },
+  choose(fpayType) {
+    data.fpayType = fpayType
+  },
+  async pay() {
+    if (data.fpayType === -1) {
+      func.native.showToast('请选择支付方式')
+      return
+    }
+    const params: OrderPayParam = {
+      orderId: pageParams.value.orderId,
+      payType: curPay.value.payType,
+    }
+    // 需要微信支付
+    if ([1, 2, 3].includes(curPay.value.payType)) {
+      const li = await uni.login()
+      params.jsCode = li.code
+      params.wxAmount = curPay.value.wxAmount
+    }
+    // 物流支付
+    if (data.fpayType === 1) {
+      params.carNumber = carrierPay.value.carNumber
+      params.carrierOrgId = carrierPay.value.carrierOrgId
+      params.carrierOrgName = carrierPay.value.carrierOrgName
+      params.linked = carrierPay.value.linked
+      params.tradeType = carrierPay.value.tradeType
+      params.truckId = carrierPay.value.truckId
+    }
+    webapi.pay.order_pay(params).then((res) => {
+      if ([1, 2, 3].includes(curPay.value.payType)) {
+        uni.requestPayment({
+          ...JSON.parse(res.payInfo),
+          success() {
+            methods.paySuccess()
+          },
+          fail() {
+            func.native.showToast({
+              icon: 'error',
+              title: '支付失败',
+            })
+          },
+        })
+      } else {
+        methods.paySuccess()
+      }
+    })
+  },
+  paySuccess() {
+    func.native
+      .showToast({
+        icon: 'success',
+        title: '支付成功',
+      })
+      .then(() => {
+        ay.goPage(config.pages.order_orderDetail, {
+          params: data.orderDetail,
+          goPageType: enums.GoPageType.redirectTo,
+        })
+      })
+  },
+  getOrderDetail() {
+    return webapi.strategy
+      .get_order_detail({ orderId: pageParams.value.orderId, orderType: 1 })
+      .then(async (res) => {
+        data.orderDetail = res
+        const location = await func.native.getLocation()
+        data.stationInfo = await webapi.strategy.find_for_mini({
+          gasstationId: res.gasstationId,
+          longitude: location.longitude.toString(),
+          latitude: location.latitude.toString(),
+        })
+      })
+  },
+  async paysel(first) {
+    if (store.webapi.strategy.paysel.ing) return
+    await webapi.strategy
+      .paysel({ orderId: pageParams.value.orderId })
+      .then((res) => {
+        data.paysel = res
+        // 仅“(散户)个人支付”选项 时,保持 其 选中
+        if (!res.carrierPay) {
+          data.fpayType = 0
+        }
+      })
+      .catch(() => {})
+    if (first) {
+      data.firstLoad = false
+    }
+  },
+}
+
+ay.entrance(async (args) => {
+  methods.getOrderDetail()
+  methods.paysel(true)
+})
+
+onUnload(() => {
+  store.webapi.strategy.get_order_detail.set()
+  store.webapi.strategy.paysel.set()
+  store.webapi.strategy.find_for_mini.set()
+})
+</script>
+
+<style lang="scss">
+.rebate-detail {
+  width: 50%;
+  padding: $p-spacd2;
+}
+.carrier-rebate {
+  position: relative;
+  z-index: 1;
+  display: inline;
+  padding: $p-spacd2;
+  margin-bottom: 0;
+  background: #fff;
+  border: 1px solid #ccc;
+  border-bottom: 0;
+  border-top-left-radius: 10px;
+  border-top-right-radius: 10px;
+  transform: translateY(1px);
+}
+.rotater {
+  animation: rotate 0.5s linear infinite;
+}
+
+@keyframes rotate {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+</style>

+ 301 - 0
src/pages/org/index.vue

@@ -0,0 +1,301 @@
+<template>
+  <ay-container>
+    <ay-skeletons :rowList="data.rowList" :loading="data.firstLoad">
+      <div class="center items-start top">
+        <div v-if="data.orgDetail.driverApply">
+          <div>加入申请{{ config.common.auditStatus[data.orgDetail.driverApply.auditStatus] }}</div>
+          <div v-if="data.orgDetail.driverApply.auditStatus === 3" class="b-fz mt-spac">
+            {{ data.orgDetail.driverApply.resMsg }}
+          </div>
+        </div>
+        <uni-easyinput
+          suffixIcon="scan"
+          v-model="data.orgId"
+          placeholder="请输入物流公司企业识别码"
+          @iconClick="methods.scan"
+          class="getorg flex-1"
+          v-if="showFindOrg"
+        ></uni-easyinput>
+        <img :src="topbgimg" class="bgimg" />
+      </div>
+      <div v-if="orgIdVerified" class="chunk1 bs-fz">
+        <div>
+          <image src="@img/icons/org_icon.png" class="mr-spac org-icon" />
+          <div>{{ data.orgInfo.orgName }}</div>
+        </div>
+        <div @click="methods.phone(data.orgInfo.bindPhone)" class="mt-spac p-color">
+          <uni-icons type="phone" color="" class="mr-spac" size="36"></uni-icons>
+          <div class="b-fz">{{ data.orgInfo.bindPhone }}</div>
+        </div>
+      </div>
+      <div class="center m-spac">
+        <template v-if="data.orgDetail.driverApply?.auditStatus === 1">
+          若想更快审核通过,可以联系企业联系人
+        </template>
+        <div v-if="data.orgDetail.driverApply?.auditStatus === 3" class="text-center">
+          如对处理有异议,请联系物流公司处理或拨打平台客服电话:
+          <span class="p-color" @click="methods.phone(store.common.data.phone)">
+            <uni-icons type="phone" color="" class="mr-spacd4" size="none"></uni-icons>
+            <span>{{ store.common.data.phone }}</span>
+          </span>
+        </div>
+      </div>
+      <div class="btns">
+        <button
+          type="primary"
+          :disabled="!orgIdVerified"
+          v-if="showApply"
+          @click="methods.enterMsg"
+        >
+          {{ btnText }}
+        </button>
+      </div>
+      <uni-popup ref="inputDialog" type="dialog">
+        <uni-popup-dialog
+          mode="input"
+          title="请谨慎操作"
+          :beforeClose="true"
+          @confirm="methods.apply"
+          @close="methods.closePopup"
+        >
+          <div class="text-center w-100%">
+            <div class="mb-spacd2">您将申请{{ hasOrg ? '退出' : '加入' }}该物流公司</div>
+            <uni-easyinput
+              type="textarea"
+              v-model="data.reqMsg"
+              placeholder="请填写申请理由"
+            ></uni-easyinput>
+          </div>
+        </uni-popup-dialog>
+      </uni-popup>
+    </ay-skeletons>
+  </ay-container>
+</template>
+
+<script lang="ts" setup>
+import defbg from '@img/controct_bg.png'
+import topbg1 from '@img/driver_apply1.png'
+import topbg3 from '@img/driver_apply3.png'
+const inputDialog = ref()
+
+const data = reactive({
+  firstLoad: true,
+  rowList: [
+    {
+      align: 'left',
+      verticalAlign: 'top',
+      colItems: [
+        {
+          style: {
+            width: '100%',
+            height: '200px',
+          },
+        },
+      ],
+    },
+    ...Array(10).fill({
+      align: 'left',
+      colItems: 1,
+    }),
+    {
+      align: 'left',
+      colItems: [
+        {
+          style: {
+            width: '60%',
+          },
+        },
+      ],
+    },
+  ],
+  orgId: '',
+  reqMsg: '',
+  orgInfo: {} as Org对象,
+  orgDetail: {} as 司机的企业团队信息,
+})
+
+/** 头部背景图 */
+const topbgimg = computed(() => {
+  let rv = defbg
+  if (data.orgDetail.driverApply) {
+    if (data.orgDetail.driverApply?.auditStatus === 1) {
+      rv = topbg1
+    }
+    if (data.orgDetail.driverApply?.auditStatus === 3) {
+      rv = topbg3
+    }
+  }
+  return rv
+})
+/** 有所属物流 */
+const hasOrg = computed(() => {
+  return !!data.orgDetail.org
+})
+/** 显示申请界面 */
+const showApply = computed(() => {
+  return data.orgDetail.driverApply?.auditStatus === 3 || !data.orgDetail.driverApply
+})
+/** 显示企业识别码 */
+const showFindOrg = computed(() => {
+  return !data.orgDetail.driverApply && !data.orgDetail.org
+})
+/** 按钮文案 */
+const btnText = computed(() => {
+  let rv = '申请加入'
+  if (hasOrg.value) {
+    rv = '申请退出'
+  }
+  if (data.orgDetail.driverApply?.auditStatus === 3) {
+    rv = '再次申请'
+  }
+  return rv
+})
+/** 物流id验证成功 */
+const orgIdVerified = computed(() => data.orgId.length === 18)
+
+watch(
+  () => data.orgId,
+  (nv) => {
+    if (orgIdVerified.value) {
+      methods.getOrgInfo()
+    } else {
+      data.orgInfo = {}
+    }
+  },
+)
+
+const methods = {
+  phone(num) {
+    uni.makePhoneCall({
+      phoneNumber: num,
+    })
+  },
+  async scan() {
+    uni
+      .scanCode({
+        scanType: ['qrcode'],
+      })
+      .then((res) => {
+        // res.result
+      })
+      .catch((err) => {
+        // 二维码解析失败
+        if (err.errMsg !== 'scanCode:fail cancel') {
+          func.native.showToast('二维码无效')
+        }
+      })
+  },
+  closePopup() {
+    inputDialog.value.close()
+  },
+  getOrgInfo() {
+    return webapi.user.find_4({ orgId: data.orgId }).then((res) => {
+      data.orgInfo = res
+    })
+  },
+  enterMsg() {
+    inputDialog.value.open()
+  },
+  apply() {
+    if (!data.reqMsg) {
+      func.native.showToast('请输入申请原因')
+      return
+    }
+
+    if (store.webapi.user.driver_entry.ing) {
+      return
+    }
+    methods.closePopup()
+    if (hasOrg.value) {
+      webapi.user.driver_quit({ type: 4, reqMsg: data.reqMsg }).then((res) => {
+        if (res) {
+          // 退出成功 服务端身份失效
+          func.native.showToast('退出成功').then(() => {
+            store.user.clearUserInfo()
+          })
+        } else {
+          func.native.showToast('退出失败')
+        }
+      })
+    } else {
+      webapi.user
+        .driver_entry<{ orgId: string }>({ orgId: data.orgId, reqMsg: data.reqMsg })
+        .then((res) => {
+          if (res) {
+            func.native.showToast('申请成功')
+            methods.findOrgDetail()
+          } else {
+            func.native.showToast('申请失败')
+          }
+        })
+    }
+  },
+  async findOrgDetail() {
+    return webapi.user.find_org_detail({ id: store.user.userInfo.user_id }).then(async (res) => {
+      data.orgDetail = res
+
+      // 已申请 自动查询物流公司信息
+      if (res.driverApply) {
+        data.orgId = res.driverApply.orgId
+        await methods.getOrgInfo()
+      }
+      // 司机有所属物流公司
+      if (hasOrg.value) {
+        data.orgId = res.org.orgId
+        await methods.getOrgInfo()
+      }
+      if (!res.driverApply || !hasOrg.value) {
+        store.webapi.user.find_4.set(enums.ReqState.success)
+      }
+    })
+  },
+}
+
+ay.entrance(async (args) => {
+  await methods.findOrgDetail()
+  data.firstLoad = false
+})
+</script>
+
+<style lang="scss" scoped>
+::v-deep .uni-popup__info {
+  @apply: font-bold;
+  font-size: $bs-fz;
+  color: unset;
+}
+::v-deep .uni-textarea-textarea,
+.uni-easyinput__placeholder-class {
+  font-size: $p-fz;
+}
+.getorg ::v-deep .uni-easyinput__content {
+  .uni-easyinput__content-input {
+    height: $p-spac * 3;
+    font-size: $bs-fz;
+  }
+  .uni-easyinput__placeholder-class {
+    font-size: $bs-fz;
+  }
+  .uniui-scan {
+    font-size: $p-fz * 2 !important;
+  }
+}
+
+.top {
+  position: relative;
+  height: 300rpx;
+  padding: $p-spac;
+  color: $p-recolor;
+  & .bgimg {
+    position: absolute;
+    top: 0;
+    left: 0;
+    z-index: -1;
+    width: 100%;
+  }
+}
+
+.org-icon {
+  width: 32px;
+  height: 32px;
+}
+</style>

+ 119 - 14
src/pages/personCenter/index.vue

@@ -1,27 +1,132 @@
 <template>
   <ay-container>
-    <button @click="methods.logout">退出</button>
+    <div class="chunk">
+      <button
+        class="bline chooseAvatar"
+        open-type="chooseAvatar"
+        @chooseavatar="methods.chooseavatar"
+      >
+        <image class="img" :src="data.userInfo.headUrl" mode="aspectFill" />
+      </button>
+      <uni-list>
+        <uni-list-item note="">
+          <template v-slot:body>
+            <div class="flex-1 center justify-between p-fz">
+              <span>姓名</span>
+              <input
+                type="nickname"
+                :maxlength="16"
+                :value="data.userInfo.userName"
+                class="input"
+                @change="methods.nicknameChange"
+              />
+            </div>
+          </template>
+          <!-- <template v-slot:footer>
+            <uni-icons type="compose" color="" size="24" class="absolute r-spac" />
+          </template> -->
+        </uni-list-item>
+        <uni-list-item
+          title="手机号"
+          note=""
+          showArrow
+          :rightText="func.convert.mobileDes(data.userInfo.mobile)"
+        ></uni-list-item>
+        <uni-list-item title="实名认证" note="" showArrow>
+          <input type="nickname" v-model="data.userInfo.userName" />
+        </uni-list-item>
+      </uni-list>
+    </div>
+    <div class="btns">
+      <button type="warn" @click="methods.logout">退出</button>
+    </div>
   </ay-container>
 </template>
 
 <script lang="ts" setup>
-const data = reactive({})
-const methods = {
-  logout() {
-    webapi.user
-      .logout({ client_id: store.user.service, user_id: store.user.userInfo.user_id })
-      .then((res) => {
-        store.user.clearUserInfo()
-        ay.goLogin()
+import defHead from '@img/icons/turnk_number_head.png'
+const data = reactive({
+  userInfo: {} as DerIUserInfo,
+})
+const methods = ay.initMethods(
+  {
+    nicknameChange(e) {
+      if (data.userInfo.userName !== e.detail.value) {
+        return methods.saveUserInfo({ userName: e.detail.value }).then(() => {
+          store.user.setUserInfo({ userName: e.detail.value })
+          data.userInfo.userName = e.detail.value
+        })
+      }
+    },
+    chooseavatar(e) {
+      data.userInfo.headUrl = e.target.avatarUrl
+      methods.saveUserInfo({ headUrl: data.userInfo.headUrl }).then(() => {
+        store.user.setUserInfo({ headUrl: e.target.avatarUrl })
       })
+    },
+    saveUserInfo(ui: User对象) {
+      return webapi.user
+        .edit_driver_info({
+          userId: store.user.userInfo.user_id,
+          ...ui,
+        })
+        .then(() => {
+          func.native.showToast('修改成功')
+        })
+    },
+    logout() {
+      func.native
+        .showModal({
+          title: '温馨提示',
+          content: '请确认是否继续退出',
+          showCancel: true,
+        })
+        .then((res) => {
+          if (res.confirm) {
+            webapi.user
+              .logout({ client_id: store.user.service, user_id: store.user.userInfo.user_id })
+              .then((res) => {
+                store.user.clearUserInfo()
+              })
+          }
+        })
+    },
   },
-}
+  {},
+)
 
 ay.entrance((args) => {
-  webapi.user.find_6({ userId: store.user.userInfo.user_id }).then((res) => {
-    console.log(res)
-  })
+  webapi.user
+    .find_6<null, { user: DerIUserInfo }>({ userId: store.user.userInfo.user_id })
+    .then((res) => {
+      if (!res.user.headUrl) {
+        res.user.headUrl = defHead
+      }
+      data.userInfo = res.user
+    })
 })
 </script>
 
-<style lang="scss"></style>
+<style lang="scss" scoped>
+.chooseAvatar {
+  width: 160rpx;
+  height: 160rpx;
+  padding: 0;
+  margin-bottom: $p-spac * 2;
+  border-radius: 50%;
+  @extend %box-shadow;
+  .img {
+    width: 100%;
+    height: 100%;
+    border-radius: 50%;
+  }
+}
+::v-deep .uni-list-item__content-title,
+::v-deep .uni-list-item__extra-text {
+  font-size: $p-fz;
+}
+.input {
+  flex: 1;
+  text-align: right;
+}
+</style>

+ 0 - 222
src/pages/prePay/index.vue

@@ -1,222 +0,0 @@
-<template>
-  <ay-container>
-    <ay-skeletons :rowList="data.rowList" :loading="loading">
-      <div class="station">
-        <ayb-station type="2" :stationInfo="data.stationInfo" />
-      </div>
-      <div class="chunk2">
-        <span class="mr-spacd4">加气量</span>
-        <span class="font-bold b-fz mr-spacd4">{{ data.orderDetail.gasQty }}</span>
-        <span>公斤</span>
-      </div>
-      <uni-section title="选择支付方式" type="line"></uni-section>
-      <div class="flex chunk s-fz" @click="methods.choose(0)">
-        <span class="mr-spacd2 radio" :class="{ checked: data.fpayType === 0 }"></span>
-        <div class="chunk2">
-          <div>个人支付</div>
-          <div>
-            结算金额 ¥ {{ personPay?.amount }} 元 (结算价 ¥ {{ personPay?.actualPrice }} 元/公斤)
-          </div>
-        </div>
-      </div>
-      <div class="flex chunk s-fz" @click="methods.choose(1)" v-if="carrierPay">
-        <span class="mr-spacd2 radio" :class="{ checked: data.fpayType === 1 }"></span>
-        <div class="chunk2">
-          <div>所属物流支付</div>
-          <div>
-            结算金额 ¥ {{ carrierPay?.amount }} 元 (结算价 ¥
-            {{ carrierPay?.actualPrice }} 元/公斤)
-          </div>
-        </div>
-      </div>
-      <div class="chunk2">
-        <div>
-          <div>创建订单</div>
-          <div>{{ data.orderDetail.createDate }}</div>
-        </div>
-        <div>
-          <div>订单编号</div>
-          <div>{{ data.orderDetail.orderId }}</div>
-        </div>
-        <div>
-          <div>驾驶员</div>
-          <div>{{ data.orderDetail.driverName }}</div>
-        </div>
-      </div>
-      <div class="btns">
-        <button
-          type="primary"
-          :disabled="canPay"
-          :loading="store.webapi.pay.order_pay.ing"
-          @click="methods.pay()"
-        >
-          {{ curPay?.buttonMsg }}
-        </button>
-      </div>
-    </ay-skeletons>
-  </ay-container>
-</template>
-
-<script lang="ts" setup>
-const data = reactive({
-  /** 页面选择支付类型: -1:未选择 0:个人:1:物流 */
-  fpayType: -1,
-  orderDetail: {} as 订单详情,
-  stationInfo: {} as GasstationVO对象,
-  paysel: {} as 待支付订单_可选支付方式获取实体类,
-  loading: true,
-  rowList: [
-    {
-      align: 'left',
-      verticalAlign: 'top',
-      colItems: [
-        {
-          style: {
-            width: '168rpx',
-            height: '168rpx',
-            'flex-shrink': 0,
-          },
-        },
-        {
-          style: {
-            width: '100%',
-          },
-          childRowItems: [
-            {
-              style: {
-                width: '80%',
-              },
-            },
-            {
-              style: {
-                width: '100%',
-              },
-            },
-            {
-              style: {
-                width: '100%',
-              },
-            },
-          ],
-        },
-      ],
-    },
-    ...Array(20).fill({
-      align: 'left',
-      colItems: 1,
-    }),
-    {
-      align: 'left',
-      colItems: [
-        {
-          style: {
-            width: '60%',
-          },
-        },
-      ],
-    },
-  ],
-})
-
-const loading = computed(
-  () =>
-    !(
-      store.webapi.strategy.get_order_detail.success &&
-      store.webapi.strategy.paysel.success &&
-      store.webapi.strategy.find_for_mini.success
-    ),
-)
-
-const canPay = computed(() => !curPay.value?.buttonEnable && store.webapi.pay.order_pay.ing)
-const pageParams = computed(() => store.curPage.pageConfig.params)
-const personPay = computed(() => data.paysel?.personPay)
-const carrierPay = computed(() => data.paysel?.carrierPay)
-/** 当前支付方式 */
-const curPay = computed<待支付订单_可选支付方式物流支付实体类>(() =>
-  data.fpayType === 0
-    ? {
-        ...data.paysel?.personPay,
-        wxAmount: data.paysel.personPay.amount,
-      }
-    : data.paysel?.carrierPay,
-)
-
-const methods = {
-  choose(fpayType) {
-    data.fpayType = fpayType
-  },
-  async pay() {
-    if (data.fpayType === -1) {
-      func.native.showToast('请选择支付方式')
-      return
-    }
-    const params: OrderPayParam = {
-      orderId: pageParams.value.orderId,
-      payType: personPay.value.payType,
-    }
-    // 需要微信支付
-    if ([1, 2, 3].includes(curPay.value.payType)) {
-      const li = await uni.login()
-      params.jsCode = li.code
-      params.wxAmount = curPay.value.wxAmount
-    }
-    // 物流支付
-    if (data.fpayType === 1) {
-      params.carNumber = carrierPay.value.carNumber
-      params.carrierOrgId = carrierPay.value.carrierOrgId
-      params.carrierOrgName = carrierPay.value.carrierOrgName
-      params.linked = carrierPay.value.linked
-      params.tradeType = carrierPay.value.tradeType
-      params.truckId = carrierPay.value.truckId
-    }
-    webapi.pay.order_pay(params).then((res) => {
-      console.log(res)
-      uni.requestPayment({
-        ...JSON.parse(res.payInfo),
-        success() {
-          func.native.showToast({
-            icon: 'success',
-            title: '支付成功',
-          })
-        },
-        fail() {
-          func.native.showToast({
-            icon: 'fail',
-            title: '支付失败',
-          })
-          // 上报异常
-        },
-      })
-    })
-  },
-  getOrderDetail() {
-    return webapi.strategy
-      .get_order_detail({ orderId: pageParams.value.orderId, orderType: 1 })
-      .then(async (res) => {
-        data.orderDetail = res
-        const location = await uni.getLocation()
-        data.stationInfo = await webapi.strategy.find_for_mini({
-          gasstationId: res.gasstationId,
-          longitude: location.longitude.toString(),
-          latitude: location.latitude.toString(),
-        })
-      })
-  },
-  paysel() {
-    webapi.strategy.paysel({ orderId: pageParams.value.orderId }).then((res) => {
-      data.paysel = res
-      // 仅“(散户)个人支付”选项 时,保持 其 选中
-      if (!res.carrierPay) {
-        data.fpayType = 0
-      }
-    })
-  },
-}
-
-ay.entrance(async (args) => {
-  methods.getOrderDetail()
-  methods.paysel()
-})
-</script>
-
-<style lang="scss"></style>

+ 144 - 0
src/pages/truckInfo/detail.vue

@@ -0,0 +1,144 @@
+<template>
+  <ay-container>
+    <ay-fieldGroups :fieldGroups="data.fieldGroups" :targetData="data.truckInfo" />
+  </ay-container>
+</template>
+
+<script lang="ts" setup>
+const data = reactive({
+  fieldGroups: [
+    {
+      fields: [
+        {
+          title: '车牌号',
+          key: 'carNumber',
+          keyClass: ['font-bold'],
+        },
+      ],
+    },
+    {
+      fields: [
+        {
+          title: '绑车类型',
+          view() {
+            return '所属物流车'
+          },
+        },
+        {
+          title: '物流公司',
+          key: 'orgName',
+        },
+        {
+          title: '车辆经营类型',
+          key: 'linked',
+          view(value) {
+            return config.common.linked[value]
+          },
+        },
+        {
+          title: '加气交易模式',
+          key: 'tradeType',
+          view(value) {
+            return config.common.tradeType[value]
+          },
+        },
+      ],
+    },
+    {
+      class: ['section', 's-fz'],
+      title: '行驶证资料',
+    },
+    {
+      fields: [
+        {
+          title: '号牌号码',
+          key: 'carNumber',
+        },
+        {
+          title: '车辆类型',
+          key: 'typeName',
+        },
+        {
+          title: '所有人',
+          key: 'owner',
+        },
+        {
+          title: '住址',
+          key: 'address',
+        },
+        {
+          title: '使用性质',
+          key: 'useNature',
+        },
+        {
+          title: '品牌型号',
+          key: 'truckName',
+        },
+        {
+          title: '车辆识别代号',
+          key: 'vehicleIdCode',
+        },
+        {
+          title: '发动机号码',
+          key: 'engineNumber',
+        },
+        {
+          title: '注册日期',
+          key: 'registerDate',
+        },
+        {
+          title: '发证日期',
+          key: 'issueDate',
+        },
+        {
+          title: '档案编号',
+          key: 'fileNo',
+        },
+        {
+          title: '核定载人数',
+          key: '',
+          unit: '人',
+        },
+        {
+          title: '总质量',
+          key: 'grossMass',
+        },
+        {
+          title: '整备质量',
+          key: 'unladenMass',
+          unit: 'kg',
+        },
+        {
+          title: '核定载质量',
+          key: 'approvedLoad',
+          unit: 'kg',
+        },
+        {
+          title: '外廓尺寸',
+          key: 'overallDimension',
+        },
+        {
+          title: '准牵引总质量',
+          key: 'tractionMass',
+          unit: 'kg',
+        },
+        {
+          title: '检验记录(能源类型)',
+          key: 'energyType',
+        },
+      ],
+    },
+  ] as IFieldGroup[],
+  truckInfo: {} as Truck对象,
+})
+const methods = {}
+
+ay.entrance((args) => {
+  webapi.strategy.find_by_id({ id: '800136756804452353' }).then((res) => {
+    // webapi.strategy.find_by_id({ id: store.curPage.pageConfig.params.truckId }).then((res) => {
+    data.truckInfo = res
+  })
+})
+</script>
+
+<style lang="scss"></style>

+ 106 - 0
src/pages/truckInfo/index.vue

@@ -0,0 +1,106 @@
+<template>
+  <ay-container>
+    <div class="s-fz">
+      <div class="section">所属物流车</div>
+      <div class="chunk center justify-between">
+        <div>
+          <div class="font-bold mb-spac">{{ func.convert.nullView(data.truckInfo.carNumber) }}</div>
+          <div>所属物流:{{ func.convert.nullView(data.truckInfo.orgName) }}</div>
+        </div>
+        <div class="p-color" v-if="data.truckInfo.truckId" @click="methods.detail">车辆详情</div>
+      </div>
+      <div class="center justify-between">
+        <div class="section">承运协作车</div>
+        <div class="p-color" @click="methods.save">添加爱车</div>
+      </div>
+      <div>
+        <div
+          class="chunk center justify-between items-end"
+          v-for="(t, i) in data.truckInfo.personTruckList"
+          :key="i"
+        >
+          <div>
+            <div class="font-bold mb-spac">{{ func.convert.nullView(t.carNumber) }}</div>
+            <div>协作物流:{{ func.convert.nullView(t.orgName) }}</div>
+          </div>
+          <div class="p-color bs-fz">
+            <uni-icons
+              type="compose"
+              color=""
+              size="none"
+              class="mr-spacd4"
+              @click="methods.save(t)"
+            />
+            <uni-icons type="trash-filled" color="" size="none" @click="methods.del(t)" />
+          </div>
+        </div>
+      </div>
+    </div>
+    <ayb-carNumber ref="carNumber" />
+  </ay-container>
+</template>
+
+<script lang="ts" setup>
+const carNumber = ref()
+const data = reactive({
+  truckInfo: {} as 司机车辆管理信息,
+})
+const methods = {
+  getTruckInfo() {
+    webapi.strategy.get_truck_info().then((res) => {
+      data.truckInfo = res
+    })
+  },
+  detail() {
+    ay.goPage(config.pages.truckInfo_detail, { params: { truckId: data.truckInfo.truckId } })
+  },
+  del(ti: PersonDriver对象 = {}) {
+    func.native
+      .showModal({
+        title: '确认删除',
+        content: `确定要删除【${ti.carNumber}】车辆信息吗?`,
+        showCancel: true,
+      })
+      .then((res) => {
+        if (res.confirm) {
+          webapi.strategy.unbind_person_truck({ id: ti.id }).then((res) => {
+            if (res) {
+              func.native.showToast('删除成功')
+              methods.getTruckInfo()
+            }
+          })
+        }
+      })
+  },
+  save(ti: PersonDriver对象 = {}) {
+    if (!ti.id && data.truckInfo.personTruckList.length >= 3) {
+      func.native.showToast('承运协作车最多添加3辆')
+      return
+    }
+    carNumber.value.open(ti.carNumber).then((cn) => {
+      webapi.strategy
+        .bind_person_truck<{ userId: string }>({
+          userId: store.user.userInfo.user_id,
+          newCarNumber: cn,
+          id: ti.id,
+        })
+        .then((res) => {
+          if (res) {
+            if (ti.id) {
+              func.native.showToast('修改成功')
+            } else {
+              func.native.showToast('添加成功')
+            }
+            methods.getTruckInfo()
+          }
+        })
+    })
+  },
+}
+
+ay.entrance((args) => {
+  methods.getTruckInfo()
+})
+</script>
+
+<style lang="scss"></style>

+ 17 - 6
src/pagesSubExample/index.vue

@@ -1,5 +1,17 @@
 <template>
   <ay-container>
+    <uni-popup ref="addCar" type="dialog">
+      <uni-popup-dialog
+        ref="inputClose"
+        mode="input"
+        title="输入内容"
+        value="对话框预置提示内容!"
+        placeholder="请输入内容"
+      >
+        666
+      </uni-popup-dialog>
+    </uni-popup>
+    <button @click="methods.addCar">添加</button>
     <view class="mt-12">
       <image src="/static/logo.png" alt="" class="w-28 h-28 block mx-auto" />
     </view>
@@ -7,10 +19,7 @@
     <view class="text-center text-2xl mt-2 mb-8">最好用的 uniapp 开发模板</view>
 
     <view class="text-justify max-w-100 m-auto text-4 indent mb-2">{{ description }}</view>
-    <view class="text-center mt-8">
-      当前平台是:
-      <text class="text-green-500">{{ PLATFORM.platform }}</text>
-    </view>
+
     <button @click="methods.show">弹出日期组件</button>
     <button @click="methods.gopage">跳转webview</button>
     <uni-calendar ref="calendar" :insert="false" @confirm="methods.confirm" />
@@ -19,9 +28,8 @@
 </template>
 
 <script lang="ts" setup>
-import PLATFORM from '@/utils/platform'
 import dayjs from 'dayjs'
-
+const addCar = ref()
 defineOptions({
   name: 'Home',
 })
@@ -41,6 +49,9 @@ ay.entrance((args) => {
 const calendar = ref(null)
 
 const methods = {
+  addCar() {
+    addCar.value.open()
+  },
   gopage() {
     ay.goPage(config.subPages.pagesSubExample.webview_index)
   },

BIN
src/static/images/controct_bg.png


BIN
src/static/images/driver_apply1.png


BIN
src/static/images/driver_apply3.png


BIN
src/static/images/icons/org_icon.png


BIN
src/static/images/qr@3x.png


+ 11 - 1
src/style/_variables.scss

@@ -1,6 +1,8 @@
 // 主题色
 // $p-color: #f40018;
 $p-color: #0084f4;
+// 文字反色颜色
+$p-recolor: #fff;
 // 大字体大小
 $b-fz: 40rpx;
 // 大二字体大小
@@ -20,11 +22,19 @@ $p-spacd4: calc($p-spac / 4);
 // 价格颜色
 $p-price-color: #ec808d; //#f46d00;
 $gray-color: #868b9a;
-
+// 边框颜色
+$border-color: #ccc;
+// 绿色
+$green-color: #00ad65;
+$bg-color: #fff;
 $uni-primary: $p-color;
 $uni-spacing-sm: 10rpx;
 $uni-spacing-base: 10rpx;
 
+%box-shadow {
+    box-shadow: 0 0 1rpx 0 hsla(210, 34%, 80%, 0.4);
+}
+
 /* 携带参数 */
 @mixin spacing($multiple) {
     width: $width;

+ 205 - 58
src/style/index.scss

@@ -10,53 +10,44 @@
   color: red;
 }
 
-// 大字体大小
-.b-fz {
-  font-size: $b-fz;
-}
-
-.bs-fz {
-  font-size: $bs-fz;
-}
-
-// 次要字体大小
-.s-fz {
-  font-size: $s-fz;
-}
-
-.flex-1 {
-  width: 0;
-}
-
 
-
-// 主题色
-.p-color {
-  color: $p-color;
-}
-
-.price-color {
-  color: $p-price-color;
-}
-
-.gray-color {
-  color: $gray-color;
+.s-fz,
+.ss-fz {
+  & .section {
+    padding-left: calc($p-spac / 1.5);
+    margin-top: calc($p-spac / 1.5);
+    margin-bottom: calc($p-spac / 1.5);
+  }
 }
 
-.radio {
-  display: inline-block;
-  width: $p-fz;
-  height: $p-fz;
-  border: solid $p-color 2rpx;
-  border-radius: $p-fz;
-  @apply center;
+.section {
+  position: relative;
+  padding-left: $p-spac;
+  margin: $p-spac 0;
+
+  &.s-fz,
+  &.ss-fz {
+    padding-left: calc($p-spac / 1.5);
+    margin-top: calc($p-spac / 1.5);
+    margin-bottom: calc($p-spac / 1.5);
+  }
 
-  &.checked::after {
-    width: calc($p-fz / 1.5);
-    height: calc($p-fz / 1.5);
+  // &.b-fz {
+  //   padding-left: $p-spac;
+  // }
+
+  &::before {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    display: block;
+    width: 8rpx;
+    height: 80%;
+    margin: auto;
     content: '';
     background-color: $p-color;
-    border-radius: calc($p-fz / 1.5);
+    border-radius: 4rpx;
   }
 }
 
@@ -65,45 +56,101 @@
   padding: $p-spac;
   margin-bottom: $p-spac;
   overflow: hidden;
+
 }
 
 .chunk {
   @extend %chunk-base;
-  border: 1rpx solid #ccc;
+  @extend %box-shadow;
+  border: 1rpx solid $border-color;
   border-radius: $p-spacd2;
-  box-shadow: 0rem 0rem 0.5rem 0rem hsla(210, 34%, 80%, 0.4);
 
   &.checked {
+    border-color: $p-color;
+  }
+
+  &.checked-full {
+    color: $p-color;
     background-color: rgba($p-color, .2);
     border-color: $p-color;
   }
 }
 
-.child-c-jb {
+// 第一层子元素 左对齐
+%childs-fc-mbd2 {
   font-size: $s-fz;
 
   >div,
   >view {
-    @apply center justify-between;
+    @apply flex;
+    align-items: center;
+    justify-content: start;
+
+    >div:first-child,
+    >view:first-child,
+    >span:first-child,
+    >label:first-child {
+      margin-right: $p-spac;
+      white-space: nowrap;
+    }
+
+    // >div:nth-child(2),
+    // >view:nth-child(2),
+    // >span:nth-child(2),
+    // >label:nth-child(2) {
+    //   flex: 1;
+    // }
+  }
+
+  >div,
+  >view,
+  >span,
+  >label {
     margin-bottom: $p-spacd2;
 
     &:last-child {
       margin-bottom: 0;
     }
   }
+
+  >span,
+  >label {
+    display: block;
+  }
+}
+
+.childs-fc-mbd2 {
+  @extend %childs-fc-mbd2
+}
+
+// 第一层子元素 两端对齐
+.childs-fcjb-mbd2 {
+  @extend .childs-fc-mbd2;
+
+  >div,
+  >view {
+    @apply center justify-between;
+  }
+}
+
+.chunk1 {
+  @extend %chunk-base;
+  @extend %childs-fc-mbd2;
+  border-bottom: solid $border-color 1rpx;
+
 }
 
 .chunk2 {
   @extend %chunk-base;
-  @extend .child-c-jb;
+  @extend .childs-fcjb-mbd2;
   padding-top: 0;
-  border-bottom: solid #ccc 1rpx;
+  border-bottom: solid $border-color 1rpx;
 
   >div,
   >view {
 
-    >div:first-child,
-    >view:first-child {
+    >span:first-child,
+    >label:first-child {
       color: $gray-color;
     }
   }
@@ -142,10 +189,18 @@ $spac-map: (
   @for $i from 0 to 4 {
     $t: map-get($spac-map, $i);
 
+    .#{map-get($t,0)}-spac#{ $suffix} {
+      #{map-get($t,1)}: calc($p-spac / #{$j});
+    }
+
     .m#{map-get($t,0)}-spac#{ $suffix} {
       margin-#{map-get($t,1)}: calc($p-spac / #{$j});
     }
 
+    .nm#{map-get($t,0)}-spac#{ $suffix} {
+      margin-#{map-get($t,1)}: calc($p-spac / -#{$j});
+    }
+
     .p#{map-get($t,0)}-spac#{ $suffix} {
       padding-#{map-get($t,1)}: calc($p-spac / #{$j});
     }
@@ -157,7 +212,7 @@ $spac-map: (
   right: 0;
   bottom: 0;
   font-size: $ss-fz;
-  color: #fff;
+  color: $bg-color;
   background-color: $p-color;
   border-top-left-radius: $p-spacd2;
 }
@@ -173,16 +228,39 @@ $spac-map: (
 
   button {
     margin-right: $p-spac;
+    // background-color: $bg-color;
 
     &:last-child {
       margin-right: 0;
     }
   }
 
-  button[type=primary] {
+  // 指定type的按钮
+  button[type] {
     flex: 1;
-    background-color: $p-color;
   }
+
+}
+
+
+
+// 主按钮
+button[type=primary],
+button[type=primary]:active,
+button[type=primary]:hover,
+button[type=primary]:focus {
+  background-color: $p-color !important;
+}
+
+button[disabled][type=primary] {
+  background-color: rgba($p-color, .6);
+}
+
+button[type=green] {
+  margin-bottom: 20rpx;
+  color: $bg-color;
+  background: $green-color;
+  border-radius: 50rpx;
 }
 
 button::after {
@@ -227,6 +305,81 @@ image {
   -webkit-box-orient: vertical;
 }
 
+// 大字体大小
+.b-fz {
+  font-size: $b-fz;
+}
+
+.p-fz {
+  font-size: $p-fz;
+}
+
+.bs-fz {
+  font-size: $bs-fz;
+}
+
+// 次要字体大小
+.s-fz {
+  font-size: $s-fz;
+}
+
+// 次次要字体大小
+.ss-fz {
+  font-size: $ss-fz;
+}
+
+.flex-1 {
+  width: 0;
+}
+
+
+
+// 主题色
+.p-color {
+  color: $p-color;
+}
+
+.price-color {
+  color: $p-price-color;
+}
+
+.gray-color {
+  color: $gray-color;
+}
+
+.bline {
+  border: solid $border-color 1rpx;
+}
+
+.top-line {
+  border-top: solid $border-color 1rpx;
+}
+
+.bottom-line {
+  border-bottom: solid $border-color 1rpx;
+}
+
+.money-bg {
+  background-color: rgba($p-price-color, 0.1);
+}
+
+.radio {
+  display: inline-block;
+  width: $p-fz;
+  height: $p-fz;
+  border: solid $p-color 2rpx;
+  border-radius: $p-fz;
+  @apply center;
+
+  &.checked::after {
+    width: calc($p-fz / 1.5);
+    height: calc($p-fz / 1.5);
+    content: '';
+    background-color: $p-color;
+    border-radius: calc($p-fz / 1.5);
+  }
+}
+
 :root,
 page {
   font-size: $p-fz;
@@ -237,10 +390,4 @@ page {
 
   // 修改按钮背景色
   // --wot-button-primary-bg-color: green;
-}
-
-
-.uni-section {
-  margin-right: -10px;
-  margin-left: -10px;
 }

+ 26 - 0
src/types/global.d.ts

@@ -14,3 +14,29 @@ declare const __UNI_PLATFORM__:
   | 'quickapp-webview-union'
 
 declare const __VITE_APP_PROXY__: 'true' | 'false'
+/** 字段分组映射 */
+type IFieldGroup = {
+  /** 分组标题 */
+  title?: stirng
+  /** 分组样式表 */
+  class?: stirng[]
+  /** 所需角色,未设置则都可见 */
+  roles?: string[]
+  /** 组内包含的 字段信息 */
+  fields: {
+    /** 字段显示标题 */
+    title: string
+    /** 字段对应的key */
+    key: string
+    /** 字段 样式 */
+    keyClass
+    /** 前缀内容 */
+    preInfo: string
+    /** 单位 */
+    unit: string
+    /** 显示条件 */
+    show: (args) => boolean
+    /** 呈现内容 */
+    view: (args) => boolean
+  }[]
+}

+ 1 - 39
src/types/schemas/account.d.ts

@@ -630,7 +630,7 @@ interface UserAccountLog对象 {
   orgId?: string
   /** 组织名称(user.org.org_name) */
   orgName?: string
-  /** 类别(1:微信充值 2:加气消费(付款给站) ) */
+  /** 类别(1:微信充值 2:加气消费(付款给站) ) 3:退款 */
   type?: number
   /** 用户id */
   userId?: string
@@ -719,44 +719,6 @@ interface WxRefundOrder {
   /** undefined */
   wxRefundOrderId?: number
 }
-interface WxpayLog对象 {
-  /** 用户标识-微信openid */
-  acct?: string
-  /** 订单金额 */
-  amount?: string
-  /** 返回业务参数集合 */
-  bizContent?: string
-  /** 商户订单号 */
-  bizOrderNo?: string
-  /** 用户类型:0-非个人车主充值 1-个人车主充值 */
-  carOwner?: number
-  /** 订单消费状态(0:消费成功,n:错误编码) */
-  consume?: number
-  /** 创建日期时间 */
-  createDate?: string
-  /** 加气订单 */
-  gasOrder?: GasOrder
-  /** 加气订单号(gasOrderId) */
-  gasOrderId?: string
-  /** 付款方姓名 */
-  name?: string
-  /** 通知校验ID */
-  notifyId?: string
-  /** 通知时间 */
-  notifyTime?: string
-  /** 通知类型 */
-  notifyType?: string
-  /** 通商云交易订单号 */
-  orderNo?: string
-  /** 支付渠道 */
-  payChannelId?: string
-  /** 通商返回微信支付信息 */
-  payInfo?: string
-  /** 付款方商户系统用户标识(bizUserId) */
-  payerId?: string
-  /** 收款方商户系统用户标识(bizUserId) */
-  recieverId?: string
-}
 interface findTruckBalancesParam {
   /** 卡车ids */
   truckIds?: array

+ 2 - 0
src/types/schemas/allinpay.d.ts

@@ -719,6 +719,8 @@ interface WxpayParam {
   /** undefined */
   gasstationName?: string
   /** undefined */
+  jsCode?: string
+  /** undefined */
   orgId?: number
   /** undefined */
   orgName?: string

+ 107 - 0
src/types/schemas/custom.d.ts

@@ -1,3 +1,110 @@
+const truckInfo = {
+  truckId: '800136756804452353',
+  tradeType: 1,
+  orgId: '720613316032479232',
+  orgName: '东风物流二',
+  truckName: '凯迪',
+  carNumber: '宁BB0005',
+  purchaseDate: '2021-01-14 00:00:00',
+  color: '红',
+  deadWeight: 3,
+  capacity: 13,
+  manufacturer: '红梅',
+  status: 0,
+  creater: '600127803374714880',
+  createDate: '2021-01-12T09:02:43',
+  updater: '600172040824832000',
+  updateDate: '2024-08-19T11:09:35',
+  driverList: [
+    {
+      orgId: '720613316032479232',
+      userId: '600136758884843522',
+      userCode: null,
+      userName: '徐司机五 / 13300000005',
+      password: 'eee4f7d036e7655076a0607b3ea18d20',
+      mobile: '13300000005',
+      idCardNo: '370213198709114017',
+      openId: 'oR7EpvxchMcA-gXHyLWGlLpX6GdM',
+      status: 0,
+      userType: 2,
+      baseRole: 'driver',
+      creater: '600127803374714880',
+      createDate: '2021-01-12T09:10:59',
+      updater: '600172040824832000',
+      updateDate: '2024-08-19T11:09:35',
+      orgName: '东风物流二',
+      createrName: '徐红梅长',
+      updaterName: '王伟宇',
+      flag: 0,
+      carNumber: null,
+      truckId: null,
+      keyWord: null,
+      lastLoginDate: '2024-09-24 16:29:06',
+    },
+  ],
+  escortList: null,
+  driversList: null,
+  balance: 20,
+  orgBalance: 0,
+  frameNumber: null,
+  trailerNumber: '宁BB0005',
+  createrName: '徐红梅长',
+  updaterName: '王伟宇',
+  linked: 1,
+  autoAccount: 1,
+  typeName: null,
+  owner: null,
+  address: null,
+  useNature: null,
+  vehicleIdCode: 'WOSHICHEJIA000512',
+  registerDate: null,
+  issueDate: null,
+  fileNo: null,
+  energyType: null,
+  faceUrl: null,
+  backUrl: null,
+  authStatus: null,
+  authDate: null,
+  level: 1,
+  comStatus: 1,
+  comContractStatus: 0,
+  tmsStatus: 0,
+  deptId: null,
+  deptName: '',
+}
+/** 卡车信息 -- 推导 /strategy/truck/find 返回值 */
+type DerITruckInfo = typeof truckInfo
+const userinfo = {
+  orgId: '720613316032479232',
+  userId: '600136758884843522',
+  userCode: null,
+  userName: '徐司机五 / 13300000005',
+  password: null,
+  mobile: '13300000005',
+  idCardNo: '370213198709114017',
+  openId: 'oR7EpvxchMcA-gXHyLWGlLpX6GdM',
+  headUrl:
+    'http://thirdwx.qlogo.cn/mmopen/S215micoQ1V3n8IMthF0f6gIdiblq4pFeOciaM6eRMfBbhDw0GuoFqBYESRgeQiayqlfYUtArtk9kibvaZDQnI44UWg3U0Vh7D7V2/132',
+  status: 0,
+  userType: 2,
+  baseRole: 'driver',
+  creater: '600127803374714880',
+  createDate: '2021-01-12T09:10:59',
+  updater: '600172040824832000',
+  updateDate: '2024-08-19T11:09:35',
+  orgName: '东风物流二',
+  orgShortName: '东风物流东风物流东风物流有限公司',
+  createrName: '徐红梅长',
+  updaterName: '王伟宇',
+  lastLoginDate: '2024-09-23 14:40:13',
+  authStatus: null,
+  ids: null,
+  keyWord: null,
+  loginType: 0,
+}
+/** 用户信息 -- 推导 /user/user/find 返回值.user */
+type DerIUserInfo = typeof userinfo
+
 type IAccountInfo = {
   /** 显示余额 */
   showBalance: { balance?: string; suffix?: string }

+ 12 - 0
src/types/schemas/message.d.ts

@@ -505,6 +505,10 @@ interface 营业执照信息 {
 interface 行驶证识别信息 {
   /** 住址 */
   address?: string
+  /** 核定载人数 */
+  approvedCapacity?: string
+  /** 核定载质量 */
+  approvedLoad?: string
   /** 车牌号 */
   carNumber?: string
   /** 能源类型 */
@@ -513,18 +517,26 @@ interface 行驶证识别信息 {
   engineNumber?: string
   /** 档案编号 */
   fileNo?: string
+  /** 总质量 */
+  grossMass?: string
   /** 发证日期 */
   issueDate?: string
+  /** 外廓尺寸 */
+  overallDimension?: string
   /** 所有人 */
   owner?: string
   /** 注册日期 */
   registerDate?: string
   /** 识别是否成功 */
   success?: boolean
+  /** 准牵引总质量 */
+  tractionMass?: string
   /** 车辆名称,默认开车品牌名 */
   truckName?: string
   /** 车辆类型(行驶证上的车辆类型) */
   typeName?: string
+  /** 整备质量 */
+  unladenMass?: string
   /** 使用性质 */
   useNature?: string
   /** 车辆识别码 */

+ 30 - 4
src/types/schemas/strategy.d.ts

@@ -2330,7 +2330,7 @@ interface PersonDriver对象 {
   /** 司机id */
   driverId?: string
   /** id主键 */
-  id?: string
+  id?: number
   /** 物流公司id */
   orgId?: string
   /** 物流公司名称 */
@@ -3400,6 +3400,10 @@ interface TruckLog对象 {
 interface Truck对象 {
   /** 住址 */
   address?: string
+  /** 核定载人数 */
+  approvedCapacity?: string
+  /** 核定载质量 */
+  approvedLoad?: string
   /** 认证时间 */
   authDate?: string
   /** 行驶证认证状态:1 待证中 2 已认证 3认证失败 */
@@ -3470,6 +3474,8 @@ interface Truck对象 {
   fileNo?: string
   /** 车架号 */
   frameNumber?: string
+  /** 总质量 */
+  grossMass?: string
   /** 发证日期:yyyy-MM-dd */
   issueDate?: string
   /** undefined */
@@ -3488,6 +3494,8 @@ interface Truck对象 {
   orgName?: string
   /** 组织简称 */
   orgShortName?: string
+  /** 外廓尺寸 */
+  overallDimension?: string
   /** 车辆所有人 */
   owner?: string
   /** undefined */
@@ -3498,6 +3506,8 @@ interface Truck对象 {
   status?: number
   /** 运力系统车辆状态,状态:1出车检查;2.作业中;3.收车中;4.收车后检查;5.已收车 */
   tmsStatus?: number
+  /** 准牵引总质量 */
+  tractionMass?: string
   /** 交易模式(1经销模式;2直销模式,默认经销模式1) */
   tradeType?: number
   /** 挂车牌号 */
@@ -3510,6 +3520,8 @@ interface Truck对象 {
   truckName?: string
   /** 车辆类型[行驶证上的车辆类型] */
   typeName?: string
+  /** 整备质量 */
+  unladenMass?: string
   /** 修改日期时间 */
   updateDate?: string
   /** 修改人id */
@@ -4045,7 +4057,21 @@ interface 司机车辆管理信息 {
   /** 承运协作车集合 */
   personTruckList?: PersonDriver对象[]
   /** 卡车id(调用API生成) */
-  truckId?: number
+  truckId?: string
+}
+interface 司机通过车牌号创建车辆绑定自己 {
+  /** 自营车辆的圈存方式:0=账户消费 1=自动圈存,只有企业司机绑定车辆才需要传此字段 */
+  autoAccount?: number
+  /** 主键id */
+  id?: string
+  /** 新车辆的经营类型:0=自有车辆 1=挂靠车辆,只有企业司机绑定车辆才需要传此字段 */
+  linked?: number
+  /** 新车辆的车牌号 */
+  newCarNumber?: string
+  /** 原绑定的车辆id */
+  originalTruckId?: number
+  /** 司机的id */
+  userId?: string
 }
 interface 司机通过车牌号直接创建车辆绑定自己 {
   /** 自营车辆的圈存方式:0=账户消费 1=自动圈存,只有企业司机绑定车辆才需要传此字段 */
@@ -4203,7 +4229,7 @@ interface 待支付订单_可选支付方式物流支付实体类 {
   /** 车牌号 */
   carNumber?: string
   /** 所属物流公司id */
-  carrierOrgId?: number
+  carrierOrgId?: string
   /** 所属物流公司名称 */
   carrierOrgName?: string
   /** 总优惠额(目前只有物流专享优惠)(优惠差额) */
@@ -4219,7 +4245,7 @@ interface 待支付订单_可选支付方式物流支付实体类 {
   /** 交易模式(1经销模式;2直销模式,默认经销模式1) */
   tradeType?: number
   /** 卡车id */
-  truckId?: number
+  truckId?: string
   /** 所属物流支付微信支付金额 */
   wxAmount?: number
 }

+ 18 - 0
src/types/schemas/user.d.ts

@@ -2367,3 +2367,21 @@ interface 预添加司机详情 {
   /** 司机账号信息 */
   org?: Org对象
 }
+interface 驾驶员管理信息VO {
+  /** 所属物流车 */
+  carNumber?: string
+  /** 最后登录时间 */
+  lastLoginDate?: string
+  /** 手机号 */
+  mobile?: string
+  /** 所属物流id */
+  orgId?: string
+  /** 所属物流name */
+  orgName?: string
+  /** 状态(0:启用 1:停用) */
+  status?: number
+  /** 用户id */
+  userId?: string
+  /** 用户名 */
+  userName?: string
+}

+ 13 - 0
src/utils/aop/index.ts

@@ -5,6 +5,19 @@ export default {
     BA: {},
     /** 后置通知 */
     AR: {
+      truckInfo(res: 司机车辆管理信息) {
+        const rv = [...res.personTruckList]
+        if (res.truckId) {
+          rv.push({
+            carNumber: res.carNumber,
+            /** 物流公司id */
+            orgId: res.orgId,
+            /** 物流公司名称 */
+            orgName: res.orgName,
+          })
+        }
+        return rv as PersonDriver对象[]
+      },
       getAccountInfo(res: 司机账户余额信息): IAccountInfo {
         const accountInfo: IAccountInfo = {
           showBalance: { balance: '', suffix: '' },

+ 31 - 2
src/utils/config/index.ts

@@ -2,8 +2,37 @@ import pages from './pages'
 import subPages from './subPages'
 import webapi from './webapi'
 const common = {
-  /** 订单状态 */
-  get orderStatus() {
+  /** 驾驶员申请加入物流公司 审核状态 */
+  get auditStatus() {
+    return { 1: '待审核', 2: '已审核', 3: '已驳回' }
+  },
+  /** 车辆经营类型 */
+  get linked() {
+    return { 0: '自营', 1: '其他' }
+  },
+  /** 圈存方式 */
+  get autoAccount() {
+    return { 0: '手动圈存', 1: '自动圈存' }
+  },
+  /** 站清分方式 */
+  get splitType() {
+    return { 1: '线上实时', 2: '线下月度' }
+  },
+  /** 销售方式 */
+  get orderType() {
+    return { 1: '大象线上', 2: '线下-优惠', 3: '线下-标准', 4: '团液线上' }
+  },
+  /** 让利方类型 */
+  get interestType() {
+    return {
+      1: '长城奥扬优惠',
+      2: '加气站优惠',
+      3: '大象服务费优惠',
+      4: '大象优惠',
+    }
+  },
+  /** 结算状态 */
+  get settleStatus() {
     return {
       1: '待支付',
       7: '支付异常',

+ 7 - 1
src/utils/config/interFaces/account.ts

@@ -842,7 +842,13 @@ export default {
   /** 个人充值消费记账(个人-》站) */
   pay_to_gasstation: {
     realUrl: '/account/user_account/pay_to_gasstation' as const,
-    reqType: {} as WxpayLog对象,
+    reqType: {} as GasOrder,
+    resType: {} as any,
+  },
+  /** 个人充值消费退款 */
+  refund_to_person: {
+    realUrl: '/account/user_account/refund_to_person' as const,
+    reqType: {} as GasOrder,
     resType: {} as any,
   },
   /** 修改user_account */

+ 16 - 4
src/utils/config/interFaces/allinpay.ts

@@ -341,11 +341,11 @@ export default {
 
     resType: {} as ResponseEntity,
   },
-  /** 微信充值通联单边账处理 */
+  /**  B2B充值回调 */
   recharge: {
     realUrl: '/allinpay/pay/callback/recharge' as const,
 
-    resType: {} as boolean,
+
   },
   /** 分账退款申请回调 */
   splitRefund_1: {
@@ -432,8 +432,8 @@ export default {
     resType: {} as any,
   },
   /** 所属物流挂靠车微信支付(小程序支付) */
-  minapay_Carrier: {
-    realUrl: '/allinpay/pay/minapay_Carrier' as const,
+  minapay_carrier: {
+    realUrl: '/allinpay/pay/minapay_carrier' as const,
     reqType: {} as WxpayParam,
     resType: {} as any,
   },
@@ -503,12 +503,24 @@ export default {
     reqType: {} as WxpayParam,
     resType: {} as any,
   },
+  /** 个人微信支付退款分账退款回调 */
+  split_person_refund: {
+    realUrl: '/allinpay/refund/callback/split_person_refund' as const,
+
+    resType: {} as ResponseEntity,
+  },
   /** 微信退款回调 */
   wxRefund: {
     realUrl: '/allinpay/refund/callback/wxRefund' as const,
 
     resType: {} as ResponseEntity,
   },
+  /** 个人微信支付退款回调 */
+  wx_person_refund: {
+    realUrl: '/allinpay/refund/callback/wx_person_refund' as const,
+
+    resType: {} as ResponseEntity,
+  },
   /** 加气退款 */
   execute: {
     realUrl: '/allinpay/refund/execute' as const,

+ 15 - 15
src/utils/config/interFaces/index.ts

@@ -1,33 +1,33 @@
 import websocket from './websocket'
-import message from './message'
-import pay from './pay'
 import gasdata from './gasdata'
-import tms from './tms'
 import account from './account'
-import settle from './settle'
-import strategy from './strategy'
 import allinpay from './allinpay'
+import tms from './tms'
+import message from './message'
+import pay from './pay'
+import settle from './settle'
 import user from './user'
+import strategy from './strategy'
 
 export default {
   /** websocket打印中心 */
   websocket,
-  /** 消息中心 */
-  message,
-  /** 支付中心 */
-  pay,
   /** 加气站数据采集 */
   gasdata,
-  /** 运力中心 */
-  tms,
   /** 账户中心 */
   account,
-  /** 结算中心 */
-  settle,
-  /** 运营策略中心 */
-  strategy,
   /** 通联支付 */
   allinpay,
+  /** 运力中心 */
+  tms,
+  /** 消息中心 */
+  message,
+  /** 支付中心 */
+  pay,
+  /** 结算中心 */
+  settle,
   /** 用户中心 */
   user,
+  /** 运营策略中心 */
+  strategy,
 }

+ 10 - 4
src/utils/config/interFaces/strategy.ts

@@ -2387,7 +2387,7 @@ export default {
   /** 散户新增绑定协作车辆 */
   bind_person_truck: {
     realUrl: '/strategy/truck/bind_person_truck' as const,
-    reqType: {} as 司机通过车牌号直接创建车辆绑定自己,
+    reqType: {} as 司机通过车牌号创建车辆绑定自己,
     resType: {} as boolean,
   },
   /** 物流公司管理端-绑定管理 */
@@ -2399,13 +2399,13 @@ export default {
   /** 企业司机通过车牌号添加车辆绑定自己 */
   binding_truck_by_org_driver: {
     realUrl: '/strategy/truck/binding_truck_by_org_driver' as const,
-    reqType: {} as 司机通过车牌号直接创建车辆绑定自己,
+    reqType: {} as 司机通过车牌号创建车辆绑定自己,
     resType: {} as string,
   },
   /** 散户司机(非首次登录)通过车牌号添加车辆绑定自己 */
   binding_truck_by_platform_driver: {
     realUrl: '/strategy/truck/binding_truck_by_platform_driver' as const,
-    reqType: {} as 司机通过车牌号直接创建车辆绑定自己,
+    reqType: {} as 司机通过车牌号创建车辆绑定自己,
     resType: {} as string,
   },
   /** 根据orgId获取卡车列表 */
@@ -2417,7 +2417,7 @@ export default {
   /** 散户司机更换绑定的车辆 */
   change_truck_by_platform_driver: {
     realUrl: '/strategy/truck/change_truck_by_platform_driver' as const,
-    reqType: {} as 司机通过车牌号直接创建车辆绑定自己,
+    reqType: {} as 司机通过车牌号创建车辆绑定自己,
     resType: {} as string,
   },
   /** 车辆待支付订单和余额检测 */
@@ -2687,6 +2687,12 @@ export default {
     reqType: {} as Truck对象,
     resType: {} as boolean,
   },
+  /** 散户移除绑定协作车辆 */
+  unbind_person_truck: {
+    realUrl: '/strategy/truck/unbind_person_truck' as const,
+    reqType: {} as 司机通过车牌号创建车辆绑定自己,
+    resType: {} as boolean,
+  },
   /** 物流公司上传行驶证更新车辆信息 */
   update_by_carrier: {
     realUrl: '/strategy/truck/update_by_carrier' as const,

+ 6 - 0
src/utils/config/interFaces/user.ts

@@ -1597,6 +1597,12 @@ export default {
     reqType: {} as IPageParams<用户分页查询参数>,
     resType: {} as IPage<User对象>,
   },
+  /** 分页查询司机用户 */
+  page_list_driver: {
+    realUrl: '/user/user/page_list_driver' as const,
+    reqType: {} as IPageParams<注册信息>,
+    resType: {} as 驾驶员管理信息VO,
+  },
   /** 查询所有加气站的账号 */
   page_list_filler_1: {
     realUrl: '/user/user/page_list_filler' as const,

+ 47 - 13
src/utils/config/pages.ts

@@ -18,7 +18,10 @@ export default {
     _type: 'page',
     title: '登录',
     identity: false,
-    isPager: false
+    isPager: false,
+    style: {
+      navigationStyle: 'custom'
+    }
   } as ayPage,
   index_index: {
     _url: '/pages/index/index',
@@ -44,31 +47,62 @@ export default {
     identity: true,
     isPager: false
   } as ayPage,
-  prePay_index: {
-    _url: '/pages/prePay/index',
+  personCenter_index: {
+    _url: '/pages/personCenter/index',
     _type: 'page',
-    title: '加气订单 · 待支付',
+    title: '个人中心',
     identity: true,
     isPager: false
   } as ayPage,
-  createOrder_index: {
-    _url: '/pages/createOrder/index',
+  truckInfo_index: {
+    _url: '/pages/truckInfo/index',
     _type: 'page',
-    title: '创建订单',
+    title: '车辆管理',
     identity: true,
     isPager: false
   } as ayPage,
-  orderList_index: {
-    _url: '/pages/orderList/index',
+  order_index: {
+    _url: '/pages/order/index',
+    _type: 'page',
+    title: '订单列表',
+    identity: true,
+    isPager: true,
+    style: {
+      enablePullDownRefresh: true
+    }
+  } as ayPage,
+  order_orderDetail: {
+    _url: '/pages/order/orderDetail',
     _type: 'page',
     title: '加气订单',
     identity: true,
-    isPager: true
+    isPager: false
   } as ayPage,
-  personCenter_index: {
-    _url: '/pages/personCenter/index',
+  order_createOrder: {
+    _url: '/pages/order/createOrder',
+    _type: 'page',
+    title: '创建订单',
+    identity: true,
+    isPager: false
+  } as ayPage,
+  order_prePay: {
+    _url: '/pages/order/prePay',
+    _type: 'page',
+    title: '待支付',
+    identity: true,
+    isPager: false
+  } as ayPage,
+  truckInfo_detail: {
+    _url: '/pages/truckInfo/detail',
+    _type: 'page',
+    title: '车辆详情',
+    identity: true,
+    isPager: false
+  } as ayPage,
+  org_index: {
+    _url: '/pages/org/index',
     _type: 'page',
-    title: 'personCenter_index',
+    title: '所属物流',
     identity: true,
     isPager: false
   } as ayPage

+ 2 - 1
src/utils/container/index.ts

@@ -130,7 +130,8 @@ export default {
     }
 
     onUnload(() => {
-      store.curPage.removeCurPagerInfo()
+      // redirectTo跳转时会清理跳转的页面
+      // store.curPage.removeCurPagerInfo()
     })
     onLoad((options) => {
       if (!func.antiShake({ func: init, immediately: true, mark: tempid })) {

+ 10 - 3
src/utils/func/convert.ts

@@ -1,7 +1,14 @@
 export default {
-  getOrderStatusStr(orderStatus) {
-    const map = config.common.orderStatus
-    return map[orderStatus]
+  /** 手机号脱敏 */
+  mobileDes(mobile) {
+    return mobile && mobile.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
+  },
+  nullView(data) {
+    return !data && data !== 0 ? '--' : data
+  },
+  getOrderStatusStr(settleStatus) {
+    const map = config.common.settleStatus
+    return map[settleStatus]
   },
   // groupRule={个人支付:[3],所属物流:[0,1,2]}
   getCheckItem(obj, filterFunc = (f?) => true) {

+ 18 - 6
src/utils/func/native.ts

@@ -1,14 +1,21 @@
 export default {
-  showModal(args) {
-    const def = {
+  /** 获取当前的地理位置、速度, 获取失败不阻塞,返回默认经纬度 */
+  getLocation() {
+    return uni.getLocation().catch(() => {
+      return { longitude: '', latitude: '' }
+    })
+  },
+  /** 显示模态弹窗,默认不显示取消按钮 */
+  showModal(args: UniApp.ShowModalOptions) {
+    const def: UniApp.ShowModalOptions = {
       showCancel: false,
     }
-    uni.showModal({
+    return uni.showModal({
       ...def,
       ...args,
     })
   },
-  /** 显示消息提示框 */
+  /** 显示消息提示框,默认无图标 */
   showToast(args: string | UniApp.ShowToastOptions) {
     let _args: UniApp.ShowToastOptions = {
       icon: 'none',
@@ -16,9 +23,14 @@ export default {
     if (typeof args === 'string') {
       _args.title = args
     } else {
-      _args = args
+      _args = {
+        ..._args,
+        ...args,
+      }
     }
-    uni.showToast(_args)
+    return uni.showToast(_args).then(async () => {
+      await func.awaiter(1000)
+    })
   },
   /** 选择文件 */
   choose(args: UniApp.ChooseMediaOption): Promise<string[]> {

+ 0 - 11
src/utils/platform.ts

@@ -1,11 +0,0 @@
-export const platform = __UNI_PLATFORM__
-export const isH5 = __UNI_PLATFORM__ === 'h5'
-export const isApp = __UNI_PLATFORM__ === 'app'
-export const isMp = __UNI_PLATFORM__.startsWith('mp-')
-const PLATFORM = {
-  platform,
-  isH5,
-  isApp,
-  isMp,
-}
-export default PLATFORM

+ 2 - 0
src/utils/store/common.ts

@@ -5,6 +5,8 @@ export default defineStore('common', () => {
     debug: false,
     // 加气量上限
     preferWeight: 800,
+    // 客服电话
+    phone: '400-016-5388',
   })
   return {
     data,

+ 3 - 3
src/utils/store/curPage.ts

@@ -1,4 +1,5 @@
 import { defineStore } from 'pinia'
+const debug = () => import.meta.env.DEV && true
 /** 当前页面地址 */
 const curPage = ref<string>()
 const pageConfigs = reactive<Record<string, ayPage>>({})
@@ -98,7 +99,6 @@ const pagerMethods = {
     pageConfig.value.curCallBack(args)
   },
 } as AyContainerPullMethods
-const debug = false
 export default defineStore(
   'curPage',
   () => {
@@ -169,13 +169,13 @@ export default defineStore(
       /** uni-load-more 文案 */
       loadMoreContentText,
     }
-    if (debug) {
+    if (debug()) {
       rv.pageConfigs = pageConfigs
     }
     return rv
   },
   {
-    persist: debug,
+    persist: debug(),
     // persist: import.meta.env.VITE_SHOW_SOURCEMAP,
   },
 )

+ 11 - 2
src/utils/store/user.ts

@@ -27,7 +27,7 @@ const useUserStore = defineStore(
       const data = { ...val.user }
       delete data.authorities
 
-      data.mobile = data.mobile.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
+      data.mobile = func.convert.mobileDes(data.mobile)
       userInfo.value = data
       userInfo.value.token = val.access_token
       userInfo.value.orgId = val.user.authorities[0].orgId
@@ -37,9 +37,17 @@ const useUserStore = defineStore(
         `${service}:${userInfo.value.orgId}:${userInfo.value.user_id}:${userInfo.value.roleId}`,
       )
     }
-    const setUserInfo = () => {}
+    const setUserInfo = (ui: User对象) => {
+      if (ui.userName) {
+        userInfo.value.user_name = ui.userName
+      }
+      if (ui.headUrl) {
+        userInfo.value.head_url = ui.headUrl
+      }
+    }
     const clearUserInfo = () => {
       userInfo.value = { ...initState }
+      ay.goLogin()
     }
 
     const Authorization = computed(() => {
@@ -52,6 +60,7 @@ const useUserStore = defineStore(
     return {
       userInfo,
       initUserInfo,
+      setUserInfo,
       clearUserInfo,
       /** 已登录 */
       isLogined,

+ 12 - 1
src/utils/store/webapi.ts

@@ -3,13 +3,17 @@ import webapiImp from '@/utils/config/webapi'
 
 interface webapistate {
   /** 设置接口请求状态 */
-  set(rs: number): void
+  set(rs?: number): void
+  /** 未请求 */
+  unasked: boolean
   /** 请求中 */
   ing: boolean
   /** 请求成功 */
   success: boolean
   /** 请求失败 */
   fail: boolean
+  /** 请求结束 */
+  finally: boolean
 }
 type ISAPI<T> = {
   [P in keyof T]: {
@@ -25,15 +29,22 @@ for (const [gk, gv] of Object.entries(webapiImp)) {
       set(rs) {
         this._state = rs
       },
+      get unasked() {
+        return this._state === enums.ReqState.unasked
+      },
       get ing() {
         return this._state === enums.ReqState.ing
       },
       get success() {
         return this._state === enums.ReqState.success
       },
+
       get fail() {
         return this._state === enums.ReqState.fail
       },
+      get finally() {
+        return this.success || this.fail
+      },
     }
   }
 }