John-Hong 2 år sedan
förälder
incheckning
94f6472856

+ 1 - 1
package.json

@@ -43,7 +43,7 @@
     "mini-types": "*",
     "miniprogram-api-typings": "*",
     "node-sass": "^4.14.1",
-    "postcss": "^8.4.16",
+    "postcss": "^8.4.18",
     "postcss-comment": "^2.0.0",
     "postcss-import": "^15.0.0",
     "postcss-loader": "^4.3.0",

+ 1 - 1
postcss.config.js

@@ -6,7 +6,7 @@ module.exports = {
             viewportHeight: 1334,    // (Number) The height of the viewport.
             unitPrecision: 3,       // (Number) The decimal numbers to allow the REM units to grow to.
             viewportUnit: 'vw',     // (String) Expected units.
-            selectorBlackList: ['.ignore', '.hairlines', 'wrap'],  // (Array) The selectors to ignore and leave as px.
+            selectorBlackList: ['.ignore', '.hairlines'],  // (Array) The selectors to ignore and leave as px.
             minPixelValue: 1,       // (Number) Set the minimum pixel value to replace.
             mediaQuery: false,       // (Boolean) Allow px to be converted in media queries.
             exclude: [/node_modules/], // 设置忽略文件,用正则做目录名匹配

+ 93 - 0
prettier.config.js

@@ -2,4 +2,97 @@
 
 module.exports = {
   singleQuote: true,
+  //   tabWidth: 2,
 };
+
+// module.exports = {
+//   // 1.一行代码的最大字符数,默认是80(printWidth: <int>)
+//   printWidth: 80,
+//   // 2.tab宽度为2空格(tabWidth: <int>)
+//   tabWidth: 2,
+//   // 3.是否使用tab来缩进,我们使用空格(useTabs: <bool>)
+//   useTabs: false,
+//   // 4.结尾是否添加分号,false的情况下只会在一些导致ASI错误的其工况下在开头加分号,我选择无分号结尾的风格(semi: <bool>)
+//   semi: false,
+//   // 5.使用单引号(singleQuote: <bool>)
+//   singleQuote: true,
+//   // 6.object对象中key值是否加引号(quoteProps: "<as-needed|consistent|preserve>")as-needed只有在需求要的情况下加引号,consistent是有一个需要引号就统一加,preserve是保留用户输入的引号
+//   quoteProps: 'as-needed',
+//   // 7.在jsx文件中的引号需要单独设置(jsxSingleQuote: <bool>)
+//   jsxSingleQuote: false,
+//   // 8.尾部逗号设置,es5是尾部逗号兼容es5,none就是没有尾部逗号,all是指所有可能的情况,需要node8和es2017以上的环境。(trailingComma: "<es5|none|all>")
+//   trailingComma: 'es5',
+//   // 9.object对象里面的key和value值和括号间的空格(bracketSpacing: <bool>)
+//   bracketSpacing: true,
+//   // 10.jsx标签多行属性写法时,尖括号是否另起一行(jsxBracketSameLine: <bool>)
+//   jsxBracketSameLine: false,
+//   // 11.箭头函数单个参数的情况是否省略括号,默认always是总是带括号(arrowParens: "<always|avoid>")
+//   arrowParens: 'always',
+//   // 12.range是format执行的范围,可以选执行一个文件的一部分,默认的设置是整个文件(rangeStart: <int>  rangeEnd: <int>)
+//   rangeStart: 0,
+//   rangeEnd: Infinity,
+//   // 18. vue script和style标签中是否缩进,开启可能会破坏编辑器的代码折叠
+//   vueIndentScriptAndStyle: false,
+//   // 19.    endOfLine: "<lf|crlf|cr|auto>" 行尾换行符,默认是lf,
+//   endOfLine: 'lf',
+//   // 20.embeddedLanguageFormatting: "off",默认是auto,控制被引号包裹的代码是否进行格式化
+//   embeddedLanguageFormatting: 'off',
+// }
+
+// // 14. requirePragma: <bool>,格式化有特定开头编译指示的文件 比如下面两种
+// /**
+//  * @prettier
+//  */
+// // or
+// /**
+//  * @format
+//  */
+
+// // 15.insertPragma: <bool> 自当插入pragma到已经完成的format的文件开头
+
+// // 16. proseWrap: "<always|never|preserve>" 文章换行,默认情况下会对你的markdown文件换行进行format会控制在printwidth以内
+
+// // 13. 指定parser,因为pretter会自动选择,所以一般不用指定(parser: "<string>"  parser: require("./my-parser"))
+// // "babel" (via @babel/parser) Named "babylon" until v1.16.0
+// // "babel-flow" (same as "babel" but enables Flow parsing explicitly to avoid ambiguity) First available in v1.16.0
+// // "babel-ts" (similar to "typescript" but uses Babel and its TypeScript plugin) First available in v2.0.0
+// // "flow" (via flow-parser)
+// // "typescript" (via @typescript-eslint/typescript-estree) First available in v1.4.0
+// // "espree" (via espree) First available in v2.2.0
+// // "meriyah" (via meriyah) First available in v2.2.0
+// // "css" (via postcss-scss and postcss-less, autodetects which to use) First available in v1.7.1
+// // "scss" (same parsers as "css", prefers postcss-scss) First available in v1.7.1
+// // "less" (same parsers as "css", prefers postcss-less) First available in v1.7.1
+// // "json" (via @babel/parser parseExpression) First available in v1.5.0
+// // "json5" (same parser as "json", but outputs as json5) First available in v1.13.0
+// // "json-stringify" (same parser as "json", but outputs like JSON.stringify) First available in v1.13.0
+// // "graphql" (via graphql/language) First available in v1.5.0
+// // "markdown" (via remark-parse) First available in v1.8.0
+// // "mdx" (via remark-parse and @mdx-js/mdx) First available in v1.15.0
+// // "html" (via angular-html-parser) First available in 1.15.0
+// // "vue" (same parser as "html", but also formats vue-specific syntax) First available in 1.10.0
+// // "angular" (same parser as "html", but also formats angular-specific syntax via angular-estree-parser) First available in 1.15.0
+// // "lwc" (same parser as "html", but also formats LWC-specific syntax for unquoted template attributes) First available in 1.17.0
+// // "yaml" (via yaml and yaml-unist-parser) First available in 1.14.0
+
+// // 17. htmlWhitespaceSensitivity: "<css|strict|ignore>" html中的空格敏感性
+
+// // 针对不同文件或目录设置不同配置的方法,json格式例子
+// // {
+// //   "semi": false,
+// //   "overrides": [
+// //     {
+// //       "files": "*.test.js",
+// //       "options": {
+// //         "semi": true
+// //       }
+// //     },
+// //     {
+// //       "files": ["*.html", "legacy/**/*.js"],
+// //       "options": {
+// //         "tabWidth": 4
+// //       }
+// //     }
+// //   ]
+// // }
+

+ 53 - 29
public/index.html

@@ -1,29 +1,53 @@
-<!DOCTYPE html>
-<html lang="zh-CN">
-
-    <head>
-        <meta charset="utf-8">
-        <meta http-equiv="X-UA-Compatible" content="IE=edge" viewport-fit="cover">
-        <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
-        <!-- <title>
-            <%= htmlWebpackPlugin.options.title %>
-        </title> -->
-        <title><%= webpackConfig.name %></title>
-        <script>
-            // CONFIGURATIONS_PLACEHOLDER
-        </script>
-        <script>
-            // var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') || CSS.supports('top: constant(a)'))
-            // document.write('<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + (coverSupport ? ', viewport-fit=cover' : '') + '" />')
-        </script>
-    </head>
-
-    <body>
-        <noscript>
-            <strong>Please enable JavaScript to continue.</strong>
-        </noscript>
-        <div id="app"></div>
-        <!-- built files will be auto injected -->
-    </body>
-
-</html>
+<!DOCTYPE html>
+<html lang="zh-CN">
+
+<head>
+  <meta charset="utf-8" />
+  <meta http-equiv="X-UA-Compatible" content="IE=edge" viewport-fit="cover" />
+  <meta name="viewport"
+    content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" />
+  <!-- <title>
+            <%= htmlWebpackPlugin.options.title %>
+        </title> -->
+  <title>
+    <%= webpackConfig.name %>
+  </title>
+  <script>
+    // CONFIGURATIONS_PLACEHOLDER
+    window.injectConfig = {
+      api: 'https://qa-crm-kpl.kerryprops.com.cn/',
+      TRACKING_API_URL:
+        'https://qa-tracking-cip.kerryplus.com/sa?project=kerry_tracking',
+      profileApi: 'https://qa-apim.kerryplus.com/c/api',
+      qaPayment: 'https://qa-payment.kerryonvip.com',
+    };
+  </script>
+  <script>
+      // var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') || CSS.supports('top: constant(a)'))
+      // document.write('<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + (coverSupport ? ', viewport-fit=cover' : '') + '" />')
+  </script>
+</head>
+
+<body>
+  <noscript>
+    <strong>Please enable JavaScript to continue.</strong>
+  </noscript>
+  <div id="app"></div>
+  <!-- built files will be auto injected -->
+</body>
+<script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
+
+</html>
+<script>
+  const debug = window.localStorage.getItem('H5_DEBUG');
+  if (debug) {
+    const script = document.createElement('script');
+    script.src = 'https://unpkg.com/vconsole@latest/dist/vconsole.min.js';
+    document.head.appendChild(script);
+    script.addEventListener('load', () => {
+      setTimeout(() => {
+        window.vConsole = new window.VConsole();
+      }, 200);
+    });
+  }
+</script>

+ 14 - 9
src/App.vue

@@ -14,7 +14,9 @@ import Stomp from '@/lib/stompjs/index';
 // import uni from '@/utils/uniHooks';
 import { Encrypt, Decrypt } from '@/utils/crypto';
 import CacheTool from '@/utils/cache-tool';
-import uni from '@/utils/uniHooks'
+import uni from '@/utils/uniHooks';
+import {initWxJsSdkConfig} from '@/utils/login.js';
+
 export default {
   data() {
     return {
@@ -30,15 +32,18 @@ export default {
   },
   methods: {
     async init() {
-      console.log(33333333)
+      // console.log(33333333)
+      // initWxJsSdkConfig(['chooseImage', 'uploadImage']);
+      // return
       // 当前页面是否是
-      // const token = uni.getStorageSync('kipAccessToken')
-      // console.log(!isMini() && !token, 35)
-      // if(!isMini() && !token) {
-      //   this.$router.push({
-      //     path: '/login'
-      //   })
-      // }
+      const token = uni.getStorageSync('kipAccessToken')
+      console.log(!isMini() && !token, 35)
+      if(!isMini() && !token && false) {
+        this.$router.push({
+          path: '/login'
+        })
+        return
+      }
       CacheTool.init()
       if (window.location.href.search(/pageId=|token=/g) < 0) {
         return;

+ 56 - 0
src/common/js/config.js

@@ -0,0 +1,56 @@
+// dev
+window.injectConfig={
+    BASE_URL: 'https://dev-crm-kpl.kerryprops.com.cn/xcrm-api/',
+    BASE_URL_H5: 'https://dev-crm-kpl.kerryprops.com.cn/aifengleh5/',
+    PIC_URL: 'https://dev-crm-kpl.kerryprops.com.cn/upload',
+    KIP_APPID: 'wx92c3e55fbef6b2af',
+    TRACKING_API_URL: "https://prod-tracking-cip.kerryplus.com/sa?project=kerry_tracking",
+    profileApi: 'https://dev-apim.kerryplus.com/c/api',
+    qaPayment: 'https://dev-payment.kerryonvip.com',
+    stage: 'dev',
+}
+// qa
+window.injectConfig={
+    BASE_URL: 'https://qa-crm-kpl.kerryprops.com.cn/xcrm-api/',
+    BASE_URL_H5: 'https://qa-crm-kpl.kerryprops.com.cn/aifengleh5/',
+    PIC_URL: 'https://cnsh-kerry-crm-le.oss-cn-shanghai.aliyuncs.com/',
+    KIP_APPID: 'wx92c3e55fbef6b2af',
+    TRACKING_API_URL: "https://qa-tracking-cip.kerryplus.com/sa?project=kerry_tracking",
+    profileApi: 'https://qa-apim.kerryplus.com/c/api',
+    qaPayment: 'https://qa-payment.kerryonvip.com',
+    stage: 'qa',
+}
+// prod
+window.injectConfig={
+    BASE_URL: 'https://crm.kerryplus.com/xcrm-api/',
+    BASE_URL_H5: 'https://crm.kerryplus.com/aifengleh5/',
+    PIC_URL: 'https://cnsh-kerry-crm-prod.oss-cn-shanghai.aliyuncs.com/',
+    KIP_APPID: 'wx92c3e55fbef6b2af',
+    TRACKING_API_URL: "https://prod-tracking-cip.kerryplus.com/sa?project=kerry_tracking",
+    profileApi: 'https://apim.kerryplus.com/c/api',
+    qaPayment: 'https://payment.kerryonvip.com',
+    stage: 'prod',
+}
+
+
+
+console.log(8989, curEnvConst.KIP_PAYMENT_URL)
+Vue.prototype.$baseURL = curEnvConst.BASE_URL;
+Vue.prototype.$baseURLH5 = curEnvConst.BASE_URL_H5;
+Vue.prototype.$wsBaseURL = curEnvConst.WS_BASE_URL;
+Vue.prototype.$picUrl = curEnvConst.PIC_URL;
+Vue.prototype.$kipPaymentUrl = curEnvConst.KIP_PAYMENT_URL;
+Vue.prototype.$kipAppId = curEnvConst.KIP_APPID;
+Vue.prototype.$kipAppPath = KIP_APP_PATH;
+Vue.prototype.$etcpAppId = curEnvConst.ETCP_APPID;
+Vue.prototype.$etcpAppPath = ETCP_APP_PATH;
+Vue.prototype.$etcpAppInvoicePath = ETCP_APP_INVOICE_PATH;
+
+
+export const isMini = () => {
+    // by: https://blog.csdn.net/txz_gray/article/details/103975818
+    //3.通过判断navigator.userAgent中包含miniProgram字样
+    var userAgent = navigator.userAgent;
+    // var isMini = /miniProgram/i.test(userAgent);
+    return /miniProgram/i.test(userAgent);
+}

+ 2 - 0
src/components/install.js

@@ -7,6 +7,7 @@ import checkboxGroup from './checkbox-group/checkbox-group'
 import uniCountdown from './uni-countdown/uni-countdown'
 import UniNumberBox from './uni-number-box/uni-number-box'
 import uniLoadMore from './uni-load-more/uni-load-more'
+import wybButton from './wyb-button/wyb-button'
 function plugins(Vue) {
     // console.log(33333, Vue)
     // Vue.component("View", View);
@@ -20,6 +21,7 @@ function plugins(Vue) {
     Vue.component("uni-countdown", uniCountdown);
     Vue.component("uni-number-box", UniNumberBox);
     Vue.component("uni-load-more", uniLoadMore);
+    Vue.component("wyb-button", wybButton);
 }
 
 export default plugins;

+ 482 - 0
src/components/wyb-button/wyb-button.vue

@@ -0,0 +1,482 @@
+<template>
+  <div :style="{
+  width: width,
+  height: height,
+  backgroundColor: disabled && type !== 'hollow' ? '#ffffff' : 'rgba(0, 0, 0, 0)',
+  borderTopLeftRadius: radius[0],
+  borderTopRightRadius: radius.length === 1 ? radius[0] : radius[1],
+  borderBottomRightRadius: radius.length === 1 ? radius[0] : radius[2],
+  borderBottomLeftRadius: radius.length === 1 ? radius[0] : radius[3],
+  transform: 'scale(0.99)'}">
+    <button class="wyb-button" :disabled="disabled" :data-param="dataParam" :hover-stop-propagation="true" :lang="lang"
+      :session-from="sessionFrom" :send-message-title="sendMessageTitle" :send-message-path="sendMessagePath"
+      :send-message-img="sendMessageImg" :show-message-card="showMessageCard" @touchstart="touch" @tap.stop="onClick"
+      :form-type="formType" @longtap.stop="onLongClick" @getphonenumber="getphonenumber" @getuserinfo="getuserinfo"
+      @error="error" @opensetting="opensetting" @launchapp="launchapp"
+      :hover-class="disabled || ripple || type === 'none' ? '' 
+      : (type === 'filled' ? 'btnHoverClass-filled' : (type === 'plain' ? 'btnHoverClass-plain' : 'btnHoverClass-hollow'))" :style="{
+			width: '100%',
+			height: height,
+			color: type === 'filled' ? '#ffffff' : color,
+			border: type === 'plain' || type === 'hollow' ? borderSize + 'px ' + color + ' ' + borderType : 'none',
+			backgroundColor: type === 'filled' ? color : (type === 'plain' ? RGBChange(color, 0.88, 'light') : 'rgba(0, 0, 0, 0)'),
+			borderTopLeftRadius: radius[0],
+			borderTopRightRadius: radius.length === 1 ? radius[0] : radius[1],
+			borderBottomRightRadius: radius.length === 1 ? radius[0] : radius[2],
+			borderBottomLeftRadius: radius.length === 1 ? radius[0] : radius[3],
+			transform: 'scale(1.01)',
+			opacity: disabled ? (type !== 'filled' ? 0.4 : 0.5) : 1.0,
+			fontSize: ftSize,
+			boxShadow: boxShadow}">
+      <div v-if="isShowLoading" class="load-container loading">
+        <div class="loader" :style="{
+        width: loaderSize + 'rpx', 
+        height: loaderSize + 'rpx',
+        borderTop: '1px solid ' + loadingColor.top,
+        borderRight: '1px solid ' + loadingColor.right,
+        borderBottom: '1px solid ' + loadingColor.bottom,
+        borderLeft: '1px solid ' + loadingColor.left,
+        transform: 'scale(0.5)'}" />
+      </div>
+      <image v-if="iconPath" :src="iconPath" :style="{
+      width: icSize,
+      height: icSize,
+      marginRight: iconMarginRight + 'rpx'}" />
+      <div v-if="!startCountDown">
+        <slot></slot>
+      </div>
+      <div v-if="countDown&&startCountDown" class="count-down">
+        <text>{{count}}秒{{countDownText}}</text>
+      </div>
+      <div v-if="ripple" class="waveRipple" :class="[isWaving?'waveActive':'']" :style="{
+      top: rippleToTop + 'px',
+      left: rippleToLeft + 'px',
+      width: domInfo.targetWidth + 'px',
+      height: domInfo.targetWidth + 'px',
+      backgroundColor: rippleBgColor}">
+      </div>
+    </button>
+  </div>
+</template>
+
+<script>
+import uni from '@/utils/uniHooks';
+
+export default {
+  computed: {
+    loadingColor() {
+      let color = this.color
+      if (this.type === 'filled') color = '#ffffff'
+      let rgbList = this.hexToRgb(color)
+      let top = 'rgba(' + rgbList[0] + ',' + rgbList[1] + ',' + rgbList[2] + ', 0.3)'
+      let bottom = 'rgba(' + rgbList[0] + ',' + rgbList[1] + ',' + rgbList[2] + ', 0.3)'
+      let right = 'rgba(' + rgbList[0] + ',' + rgbList[1] + ',' + rgbList[2] + ', 0.3)'
+      let left = 'rgb(' + rgbList[0] + ',' + rgbList[1] + ',' + rgbList[2] + ')'
+      return {
+        top,
+        bottom,
+        right,
+        left
+      }
+    },
+    loaderSize() {
+      return parseFloat(this.height.replace(/[^0-9]/ig, "")) * 0.3
+    },
+    ftSize() {
+      return (this.fontSize || (parseFloat(this.height.replace(/[^0-9]/ig, "")) * 0.388)) + 'rpx'
+    },
+    icSize() {
+      return (this.iconSize || (parseFloat(this.height.replace(/[^0-9]/ig, "")) * 0.388)) + 'rpx'
+    }
+  },
+  data() {
+    return {
+      rippleToTop: 0,
+      rippleToLeft: 0,
+      domInfo: {},
+      isWaving: false,
+      btnStyle: {},
+      basePlateStyle: {},
+      iconStyle: {},
+      timer: {},
+      flag: false,
+      startCountDown: false,
+      count: this.countDownNum,
+      timer: {}
+    }
+  },
+  props: {
+    type: {
+      type: String,
+      default: 'filled'
+    },
+    width: {
+      type: String,
+      default: uni.getSystemInfoSync().screenWidth * 0.9 + 'px'
+    },
+    height: {
+      type: String,
+      default: '80rpx'
+    },
+    color: {
+      type: String,
+      default: '#007aff'
+    },
+    fontSize: {
+      type: [String, Number],
+      default: ''
+    },
+    radius: {
+      type: Array,
+      default() {
+        return ['5px']
+      }
+    },
+    borderSize: {
+      type: [String, Number],
+      default: 1
+    },
+    borderType: {
+      type: String,
+      default: 'solid'
+    },
+    rippleBgColor: {
+      type: String,
+      default: 'rgba(0, 0, 0, 0.15)'
+    },
+    ripple: {
+      type: Boolean,
+      default: false
+    },
+    isShowLoading: {
+      type: Boolean,
+      default: false
+    },
+    disabled: {
+      type: Boolean,
+      default: false
+    },
+    iconPath: {
+      type: String,
+      default: ''
+    },
+    iconSize: {
+      type: [String, Number],
+      default: ''
+    },
+    iconMarginRight: {
+      type: [String, Number],
+      default: '15'
+    },
+    boxShadow: {
+      type: String,
+      default: ''
+    },
+    countDown: {
+      type: Boolean,
+      default: false
+    },
+    countDownNum: {
+      type: Number,
+      default: 60
+    },
+    countDownText: {
+      type: String,
+      default: '后重新获取'
+    },
+    formType: {
+      type: String,
+      default: ''
+    },
+    dataParam: {
+      type: String,
+      default: ''
+    },
+    openType: {
+      type: String,
+      default: ''
+    },
+    lang: {
+      type: String,
+      default: 'zh_CN'
+    },
+    sessionFrom: {
+      type: String,
+      default: ''
+    },
+    sendMessageTitle: {
+      type: String,
+      default: ''
+    },
+    sendMessagePath: {
+      type: String,
+      default: ''
+    },
+    sendMessageImg: {
+      type: String,
+      default: ''
+    },
+    showMessageCard: {
+      type: Boolean,
+      default: false
+    },
+    mobile: {
+      type: String,
+      default: '',
+    }
+  },
+  watch: {
+    count(val) {
+      if (val === 0) {
+        clearInterval(this.timer)
+        this.startCountDown = false
+        this.count = this.countDownNum
+      }
+    }
+  },
+  methods: {
+    touch(e) {
+      this.throttle(() => {
+        if (!this.disabled) {
+          if (this.ripple) {
+            this.isWaving = false
+            this.$nextTick(function () {
+              this.getWaveQuery(e)
+            })
+          }
+        }
+      })
+    },
+    checkMobile(mobile) {
+      if (mobile === '') {
+        return false
+      }
+      const regPhone = '/^1[3456789]d{9}$/'
+      let reg = /^1[3456789]\d{9}$/
+      if (!reg.test(mobile)) {
+        return false
+      }
+      return true
+    },
+    onClick(e) {
+      const mobile = this.mobile;
+      if (!this.checkMobile(mobile)) {
+        this.$emit('preClick', e)
+        return false;
+      }
+      if (!this.disabled && !this.startCountDown) {
+        this.$emit('click', e)
+      }
+      if (this.countDown && !this.startCountDown) {
+        this.startCountDown = true
+        this.timer = setInterval(() => {
+          this.count--
+        }, 1000)
+      }
+    },
+    onLongClick(e) {
+      if (!this.disabled && !this.startCountDown) {
+        this.$emit('longclick', e)
+      }
+    },
+    getWaveQuery(e) {
+      this.getElQuery().then(res => {
+        let data = res[0]
+        if (!data.width || !data.width) return
+        data.targetWidth = data.height > data.width ? data.height : data.width
+        if (!data.targetWidth) return
+        this.domInfo = data;
+        let touchesX = ''
+        let touchesY = ''
+        // #ifndef MP-BAIDU || MP-ALIPAY
+        touchesX = e.touches[0].clientX
+        touchesY = e.touches[0].clientY
+        // #endif
+        // #ifdef MP-BAIDU
+        touchesX = e.changedTouches[0].clientX
+        touchesY = e.changedTouches[0].clientY
+        // #endif
+        // #ifdef MP-ALIPAY
+        touchesX = e.detail.clientX
+        touchesY = e.detail.clientY
+        // #endif
+        this.rippleToTop = touchesY - data.top - data.targetWidth / 2
+        this.rippleToLeft = touchesX - data.left - data.targetWidth / 2
+        this.$nextTick(() => {
+          this.isWaving = true
+        })
+      })
+    },
+    getElQuery() {
+      return new Promise(resolve => {
+        let queryInfo = ''
+        queryInfo = uni.createSelectorQuery().in(this)
+        //#ifdef MP-ALIPAY
+        queryInfo = uni.createSelectorQuery()
+        //#endif
+        queryInfo.select('.wyb-button').boundingClientRect()
+        queryInfo.exec(data => {
+          resolve(data)
+        })
+      })
+    },
+    RGBChange(color, level, type) {
+      // hex转rgb
+      if (color.length === 4) {
+        let arr = color.split('')
+        color = '#' + arr[1] + arr[1] + arr[2] + arr[2] + arr[3] + arr[3]
+      }
+      let color16List = [color.substring(1, 3), color.substring(3, 5), color.substring(5, 7)]
+      let r = parseInt(color16List[0], 16)
+      let g = parseInt(color16List[1], 16)
+      let b = parseInt(color16List[2], 16)
+      let rgbc = [r, g, b]
+      // 减淡或加深
+      for (var i = 0; i < 3; i++)
+        type === 'light' ? rgbc[i] = Math.floor((255 - rgbc[i]) * level + rgbc[i]) : rgbc[i] = Math.floor(rgbc[i] * (1 -
+          level))
+      // rgb转hex
+      let R = rgbc[0].toString(16)
+      let G = rgbc[1].toString(16)
+      let B = rgbc[2].toString(16)
+      if (R.length === 1) R = '0' + R
+      if (G.length === 1) G = '0' + G
+      if (B.length === 1) B = '0' + B
+      return '#' + R + G + B
+    },
+    hexToRgb(color) {
+      if (color.length === 4) {
+        let arr = color.split('')
+        color = '#' + arr[1] + arr[1] + arr[2] + arr[2] + arr[3] + arr[3]
+      }
+      let color16List = [color.substring(1, 3), color.substring(3, 5), color.substring(5, 7)]
+      let r = parseInt(color16List[0], 16)
+      let g = parseInt(color16List[1], 16)
+      let b = parseInt(color16List[2], 16)
+      return [r, g, b]
+    },
+    throttle(fc, waitTime = 500, imme = true) {
+      if (imme) {
+        if (!this.flag) {
+          this.flag = true
+          typeof fc === 'function' && fc()
+          this.timer = setTimeout(() => {
+            this.flag = false
+          }, waitTime)
+        }
+      } else {
+        if (!this.flag) {
+          this.flag = true
+          this.timer = setTimeout(() => {
+            this.flag = false
+            typeof fc === 'function' && fc()
+          }, waitTime)
+        }
+      }
+    },
+    getphonenumber(res) {
+      this.$emit('getphonenumber', res)
+    },
+    getuserinfo(res) {
+      this.$emit('getuserinfo', res)
+    },
+    error(res) {
+      this.$emit('error', res)
+    },
+    opensetting(res) {
+      this.$emit('opensetting', res)
+    },
+    launchapp(res) {
+      this.$emit('launchapp', res)
+    }
+  }
+}
+</script>
+
+<style>
+.wyb-button {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  position: relative;
+  overflow: hidden;
+  line-height: 1;
+  z-index: 1;
+  box-sizing: border-box;
+  transition: all 0.12s;
+  white-space: nowrap;
+}
+
+.wyb-button::after {
+  border: none;
+  transform-origin: center;
+  transform: scale(1.5);
+}
+
+.btnHoverClass-plain::after {
+  background-color: rgba(0, 0, 0, 0.08) !important;
+}
+
+.btnHoverClass-hollow::after {
+  background-color: rgba(0, 0, 0, 0.08) !important;
+}
+
+.btnHoverClass-filled::after {
+  background-color: rgba(0, 0, 0, 0.12) !important;
+}
+
+.waveRipple {
+  z-index: 0;
+  position: absolute;
+  border-radius: 100%;
+  background-clip: padding-box;
+  transform-origin: center;
+  pointer-events: none;
+  transform: scale(0);
+  user-select: none;
+  opacity: 1;
+}
+
+.waveRipple.waveActive {
+  opacity: 0;
+  transform: scale(2);
+  transition: opacity 0.6s linear, transform 0.6s linear;
+}
+
+.loader {
+  font-size: 10px;
+  position: relative;
+  -webkit-animation: loading .75s infinite linear;
+  animation: loading .75s infinite linear;
+  margin-right: 20rpx;
+}
+
+.loader,
+.loader:after {
+  border-radius: 50%;
+}
+
+@-webkit-keyframes loading {
+  0% {
+    -webkit-transform: rotate(0deg);
+    transform: rotate(0deg);
+  }
+
+  100% {
+    -webkit-transform: rotate(360deg);
+    transform: rotate(360deg);
+  }
+}
+
+@keyframes loading {
+  0% {
+    -webkit-transform: rotate(0deg);
+    transform: rotate(0deg);
+  }
+
+  100% {
+    -webkit-transform: rotate(360deg);
+    transform: rotate(360deg);
+  }
+}
+</style>

+ 926 - 6
src/pages/login/login.vue

@@ -1,8 +1,928 @@
 <template>
-  <scroll-view
-    style="background-color: #F4F7FF"
-    scroll-y="true"
-  >
-    手机验证码登录
-  </scroll-view>
+  <div class="page">
+    <div class="authorize__head">
+      <div class="head__info">
+        <div class="head__logo">
+          <img :src="getLogo" mode="heightFix"/>
+        </div>
+      </div>
+    </div>
+    <div class="authorize__form">
+      <div class="form__item line" style="border-bottom: 1px solid #D8DAE0;">
+        <div class="form__label">
+          手机号码
+        </div>
+        <div class="form__input">
+          <!-- <input type="number" placeholder="请输入您的手机号" v-model="mobile" /> -->
+          <van-field
+            v-model="mobile"
+            type="number"
+            placeholder="请输入您的手机号"
+          />
+        </div>
+      </div>
+      <div class="form__item">
+        <div class="form__label">验证码</div>
+        <div class="form__input">
+          <!-- <input type="number" placeholder="请输入验证码" v-model="codeNum"> -->
+          <van-field
+            v-model="codeNum"
+            type="number"
+            placeholder="请输入验证码"
+          />
+        </div>
+        <div class="form__code">
+          <wyb-button type="hollow" :count-down="true" :count-down-num="59" width="240px" height="70px" color="#1D1D1D"
+                      font-size="28" border-size="1" :radius="['50px']" @click="onCode" :mobile="mobile"
+                      @pre-click="handlePreClick">
+            获取验证码
+          </wyb-button>
+        </div>
+      </div>
+    </div>
+
+    <div class="mgt40">
+      <button class="authorize_btn authorize_btn--phone" @click="onLogin">注册/登录</button>
+    </div>
+
+    <div class="mgt34">
+      <div style="margin: 0 30px;">
+        <div style="display: flex;align-items: flex-start;">
+          <!-- <checkbox-group @change="protocolChange">
+            <checkbox style="transform: scale(0.8);" color="#808080" value="protocol" :checked="protocolChecked" />
+          </checkbox-group> -->
+          <van-checkbox @change="protocolChange" :value="protocolChecked" color="#ED1C24" name="protocol" icon-size="17" checked-color="#064C8A" shape="square"></van-checkbox>
+          <div style="color: #666666; font-size: 32px; flex: 1;margin-left: 15px;" v-if="brandInfo && brandInfo.protocolName">
+            已阅读并同意<span style="color: #627ECF;" @click="gotoProtocol('protocol')">《{{ brandInfo.protocolName }}》</span>
+            和<span style="color: #627ECF;"
+                    @click="gotoProtocol('privacyPolicy')">《{{ brandInfo.privacyPolicyName }}》</span>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <uni-popup ref="popup" :mask-click="false" type="center" style="z-index: 999999;">
+      <div class="auth-popup">
+        <div class="auth-popup__head">
+          <span>微信授权</span>
+        </div>
+        <div class="auth-popup__main">
+          <div class="head__logo">
+            <img :src="getLogo" mode="heightFix"/>
+          </div>
+          <div style="margin-bottom:20px;font-size: 30px;">申请获取以下权限</div>
+          <div style="height:80px;line-height:80px;border-top:1px solid #F0F0F0; color: #999999; font-size: 32px;">
+            获得你的公开信息(个人信息等)
+          </div>
+        </div>
+        <div class="auth-popup__footer">
+          <div class="cancel" @click="noWechatAuthPhoneLogin">取消</div>
+          <div style="flex: 1; border-left: 1px solid #F0F0F0;">
+            <button class="phone-btn" @click="getWxProfile">确认授权</button>
+          </div>
+        </div>
+      </div>
+    </uni-popup>
+  </div>
 </template>
+
+
+<script>
+import log from '@/utils/log'
+// import wybButton from '@/components/wyb-button/wyb-button.vue'
+import {
+  kipSendRegisterSMS,
+  kipPhoneLogin,
+  kipUpdateWxMember,
+  kipGetUserDetail,
+  kipGetBrandInfo,
+  kipAgreementSave
+} from '@/utils/api-kip.js'
+import MemberCacheTool from '@/utils/member-cache-tool.js'
+import KipCacheTool from '@/utils/kip-cache-tool.js'
+import {
+  crmQueryMemberInfo,
+  crmSaveMemberSource,
+} from '@/utils/api-crm-member.js'
+// var app = getApp()
+import { mapState } from "vuex";
+import {
+  getUTMSource,
+} from '@/utils/utils.js'
+import CacheTool from '@/utils/cache-tool.js'
+
+const {KERRY_ON_BRAND_ID,HANGZHOU_LBS_ID} = CacheTool.getCurEnvConst();
+import { REG_SOURCE } from '@/constants.js'
+import uni from '@/utils/uniHooks.js'
+
+const app = {};
+
+export default {
+  name: 'Login',
+  data() {
+    return {
+      mobile: '', // 手机号
+      codeNum: '', // 验证码
+      timer: 60, // 时间
+      url: '',
+      protocolChecked: false,
+      brandInfo: null,
+      lbsInfo: null,
+      preUrl: '',
+    }
+  },
+  created() {
+    const option = this.$route.query;
+    if ( option && JSON.stringify(option) !== "{}" ) {
+      this.url = JSON.parse(decodeURIComponent(option?.url || '{}'))
+    }
+    this.preUrl = uni.getStorageSync('previousUrl')
+    uni.setStorageSync('previousUrl','/pages/wxLogin/login.vue')
+  },
+  computed: {
+    ...mapState({
+      custTypeId: state => state.custTypeId,
+      mallid: state => state.mallId,
+      groupId: state => state.groupId,
+      member: state => state.member,
+    }),
+    getLogo() {
+      // TODO: logo 需要更具lbs区分进入
+      // return CacheTool.getLogoByMallid(this.mallid)
+      return 'https://kip-public-qa.oss-cn-shanghai.aliyuncs.com/1634707859342-qldc5c.jpg'
+    },
+    isHangzhou() {
+      return uni.getStorageSync('mallid') == HANGZHOU_LBS_ID;
+    },
+    isKerryOn() {
+      return uni.getStorageSync('groupId') == KERRY_ON_BRAND_ID;
+    }
+  },
+  watch: {
+    groupId( val ) {
+      console.log('groupId',val)
+    },
+    mallid( val ) {
+      console.log('mallid',val)
+    }
+  },
+  mounted() {
+    // console.log(154,this.groupId,this.mallid);
+    this.getBrandInfo()
+  },
+  methods: {
+    // 埋点方法
+    sensorsClick( eventName,params ) {
+      let optionsQuery = uni.getStorageSync('options_query')
+      let fixedParams = {
+          cta_itemno: '',
+          cta_name: '',
+          previous_url: this.preUrl || '',
+          redirect_url: '',
+          // $brand_id: uni.getStorageSync('groupId'),
+          // $location: uni.getStorageSync('mallid'),
+          $channel: optionsQuery.channel || '',
+          // $utm_lbs: this.optionsQuery.utm_lbs || '',
+          $utm_channel: optionsQuery.utm_channel || '',
+          $utm_method: optionsQuery.utm_method || '',
+          $utm_source: optionsQuery.utm_source || '',
+          $utm_function: optionsQuery.utm_function || '',
+          $utm_user: optionsQuery.utm_user || '',
+        },
+        finalParams = Object.assign(fixedParams,params)
+      this.$sensors.track(eventName,finalParams)
+    },
+    // 获取验证码
+    onCode: function () {
+      if ( this.check() ) {
+        this.getCodeData()
+      }
+      return false;
+    },
+    // 获取验证码
+    getCodeData: function () {
+      uni.showLoading({
+        title: '加载中'
+      });
+      var datas = {
+        phoneNumber: this.mobile
+      }
+      kipSendRegisterSMS(datas).then(resp => {
+        uni.hideLoading();
+        // console.log(resp);
+        const result = resp.data;
+        if ( result.code == '000000' && result.data ) {
+          uni.showToast({
+            title: '获取验证码成功!',
+            duration: 2000,
+            icon: 'none'
+          })
+        } else {
+          const message = result.message || '发送失败';
+          uni.showToast({
+            title: message,
+            duration: 2000,
+            icon: 'none'
+          })
+          log.error(`短信发送失败, 手机号: ${ datas.phoneNumber }`)
+        }
+      }).catch(err => {
+        uni.hideLoading();
+        uni.showToast({
+          title: '发送注册信息错误',
+          duration: 2000,
+          icon: 'none'
+        })
+        log.error(err);
+      })
+    },
+    //授权
+    getWxProfile: function () {
+      let _this = this;
+      this.closeAuthPopup();
+      uni.getUserProfile({
+        desc: '用于完善会员资料', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
+        success: ( res ) => {
+          _this.updateKipMemberByWxProfile(res);
+        },
+        fail: ( res ) => {
+          console.warn(`用户取消授权, ${ JSON.stringify(res) }`)
+          log.warn(`用户取消授权`)
+          // 此时用户已注册,即使用户取消授权,也需要用随机头像昵称登录
+          const isClosePopup = false;
+          _this.noWechatAuthPhoneLogin(isClosePopup);
+        }
+      })
+    },
+    queryMember: function () {
+      let _this = this;
+      uni.showLoading({
+        title: '正在加载',
+        mask: true,
+      })
+      kipGetUserDetail().then(resp => {
+        uni.hideLoading()
+        const result = resp.data;
+        if ( result.code === '000000' && result.data ) {
+          const member = result.data;
+          if ( member ) {
+            _this.getKipMemberInfoAfter(member)
+          } else {
+            MemberCacheTool.cleanMemberCache(app);
+            uni.showToast({
+              title: result.message,
+              duration: 2000,
+              icon: 'none'
+            })
+            log.warn(`查询会员信息成功:没有会员信息`)
+          }
+        } else {
+          MemberCacheTool.cleanMemberCache(app);
+          uni.showToast({
+            title: result.message,
+            duration: 2000,
+            icon: 'none'
+          })
+          log.warn(`查询会员信息失败,${ result.message }`)
+        }
+
+      }).catch(err => {
+        uni.hideLoading()
+        console.error(err);
+        MemberCacheTool.cleanMemberCache(app);
+        uni.showToast({
+          title: '查询会员信息错误',
+          duration: 2000,
+          icon: 'none'
+        })
+        log.warn(`查询会员信息错误`)
+      })
+
+    },
+    // 登录
+    onLogin: function () {
+      let _this = this
+      // 判断会员协议
+      if ( !_this.protocolChecked ) {
+        uni.showModal({
+          title: '请阅读并勾选下方的协议',
+          showCancel: false,
+        })
+        return false;
+      }
+      if ( _this.check() ) {
+
+        if ( _this.codeNum === '' ) {
+          uni.showToast({
+            title: '请输入验证码',
+            duration: 2000,
+            icon: 'none'
+          })
+          return false
+        }
+
+        // 调登录接口
+        uni.showLoading({
+          title: '正在登录',
+          mask: true,
+        });
+        uni.login({
+          provider: 'weixin',
+          success: function ( loginRes ) {
+            console.log('===> 手机号登录 ',loginRes)
+            const curJsCode = loginRes.code;
+            const params = {
+              verifyCode: _this.codeNum,
+              phoneNumber: _this.mobile,
+              jsCode: curJsCode,
+              brandId: this.groupId,
+              lbsId: this.mallid
+            }
+            kipPhoneLogin(params).then(resp => {
+              uni.hideLoading()
+              const result = resp.data;
+              if ( result.code == '000000' && result.data ) {
+                log.info(`手机号登录成功:保存授权信息`)
+
+                const authInfo = result.data;
+                const needLogin = authInfo.needLogin;
+                // 此接口返回的needLogin暂时没有true
+                KipCacheTool.setKipCache(authInfo);
+
+
+                // if (!needLogin) {
+                // 	KipCacheTool.setKipCache(authInfo);
+                // 	// 请求用户信息
+                // 	_this.queryMember()
+                // }
+
+                if ( _this.isHangzhou ) {
+                  uni.setStorageSync("comfirLocation",'login.vue');
+                  uni.setStorageSync("comfirHangzhou",true);
+                } else if ( _this.isKerryOn ) {
+                  uni.setStorageSync("comfirLocation",'login.vue');
+                  uni.setStorageSync("comfirKerryOn",true);
+                }
+                _this.saveAgreementAction()
+                if ( authInfo.headEmpty ) {
+                  _this.openAuthPopup();
+                } else {
+                  _this.queryMember();
+                }
+
+              } else {
+                log.warn(`手机号登录请求成功: 未获取到授权信息`)
+                uni.showModal({
+                  title: '登录失败',
+                  content: result.message,
+                  showCancel: false,
+                })
+                KipCacheTool.cleanKipCache()
+                MemberCacheTool.cleanMemberCache(app);
+              }
+
+            }).catch(err => {
+              uni.hideLoading()
+              console.log(err);
+              uni.showToast({
+                title: '登录失败',
+                duration: 2000,
+                icon: 'none'
+              })
+              log.warn(`手机号登录请求失败`)
+              KipCacheTool.cleanKipCache()
+              MemberCacheTool.cleanMemberCache(app);
+            })
+
+          },
+          fail: function ( loginRes ) {
+            uni.showModal({
+              title: '登录失败',
+              content: loginRes.errMsg,
+              showCancel: false,
+            })
+            log.warn(`授权手机号失败`)
+            KipCacheTool.cleanKipCache()
+            MemberCacheTool.cleanMemberCache(app);
+          }
+        })
+
+      }
+    },
+    check: function () {
+      if ( this.mobile === '' ) {
+        uni.showToast({
+          title: '请输入手机号',
+          duration: 2000,
+          icon: 'none'
+        })
+        return false
+      }
+      const regPhone = '/^1[3456789]d{9}$/'
+      let reg = /^1[3456789]\d{9}$/
+      if ( !reg.test(this.mobile) ) {
+        uni.showToast({
+          title: '请输入正确的手机号',
+          duration: 2000,
+          icon: 'none'
+        })
+        return false
+      }
+      return true
+    },
+    handlePreClick( e ) {
+      uni.showToast({
+        title: '请输入正确的手机号',
+        duration: 2000,
+        icon: 'none'
+      })
+    },
+    gotoProtocol( type ) {
+      const brandId = this.brandInfo.id || ''
+      const lbsId = this.lbsInfo[0].id || ''
+      const isChecked = this.protocolChecked;
+      uni.navigateTo({
+        url: `/pages/protocol/protocol?type=${ type }&brandId=${ brandId }&lbsId=${ lbsId }&isChecked=${ isChecked }`
+      })
+    },
+    protocolChange( e ) {
+      console.log(e)
+      this.protocolChecked = !this.protocolChecked
+      const mallid = this.mallid
+      CacheTool.setAgreeProtocoByMallid(mallid,this.protocolChecked)
+    },
+    getBrandInfo() {
+      const _this = this;
+      const HZ_BRAND_ID = this.groupId;
+      const HZ_LBS_ID = this.mallid;
+      // return
+      const params = {
+        id: HZ_BRAND_ID,
+        lbsId: HZ_LBS_ID
+      }
+      uni.showLoading({
+        title: '正在加载',
+        mask: true,
+      })
+      kipGetBrandInfo(params).then(resp => {
+        uni.hideLoading()
+        // console.log(468, resp);
+        // return
+        if ( !resp || !resp.data.length || resp.code != '000000' ) {
+          log.warn(`获取会员绑定的brand请求成功:未获取到数据`)
+          console.log(`获取会员绑定的brand请求成功:未获取到数据`);
+          const message = resp?.data?.message || '服务不可用';
+          uni.showToast({
+            title: message,
+            duration: 2000,
+            icon: 'none'
+          });
+        } else {
+          const brandArray = resp.data;
+          if ( brandArray && brandArray.length > 0 && brandArray[0] ) {
+            const brandInfo = brandArray[0].brand;
+            _this.brandInfo = brandInfo;
+            const lbsInfo = brandArray[0].lbs;
+            _this.lbsInfo = lbsInfo;
+          }
+          console.log(487, _this.lbsInfo);
+        }
+
+      }).catch(err => {
+        uni.hideLoading()
+        console.error(err);
+      })
+    },
+    getKipMemberInfoAfter( kipMemberInfo ) {
+      MemberCacheTool.setKipMember(app,kipMemberInfo)
+
+      const _this = this;
+      // 查询 crm 会员
+      uni.showLoading({
+        title: '正在加载',
+        mask: true,
+      })
+      const newGroupId = uni.getStorageSync("groupId");
+      const newMallid = uni.getStorageSync("mallid")
+      const params = {
+        groupId: newGroupId,
+        kipUserId: kipMemberInfo.id,
+        mallId: newMallid
+      }
+      crmQueryMemberInfo(params).then(resp => {
+        uni.hideLoading()
+        log.info(`获取crm会员请求失败`)
+        const result = resp.data;
+        if ( result && result.code == '0' ) {
+          const member = result.data;
+          const optionsQuery = uni.getStorageSync('options_query') || {};
+          if ( member ) {
+            // 这里埋点-登录过但是清空缓存
+            console.log('==>这里走埋点--手机号码---crmQueryMemberInfo',member)
+            // TODO: 埋点公共属性重新赋值
+            _this.$sensors.registerApp({
+              $open_id: _this.globalData?.member?.openId || '',
+              $profile_id: _this.globalData?.member?.kipUserId || member?.kipUserId || '',
+              $member_id: _this.globalData?.member?.id || member?.id || '',
+              $union_id: _this.globalData?.member?.unionid || '',
+              // $location: _this.globalData?.mallid,
+              // $brand_id: _this.globalData?.groupId,
+              // $utm_source: JSON.stringify(uni.getStorageSync('options_query')) || '',
+              // $channel: optionsQuery?.channel || '',
+              $utm_lbs: optionsQuery?.utm_lbs || '',
+              // $utm_channel: optionsQuery?.utm_channel || '',
+              // $utm_method: optionsQuery?.utm_method || '',
+              // $utm_source: optionsQuery?.utm_source || '',
+              // $utm_function: optionsQuery?.utm_function || '',
+              // $utm_user: optionsQuery?.utm_user || '',
+            })
+            MemberCacheTool.setMemberInfoCache(app,member,kipMemberInfo);
+            _this.checkIsNewUser()
+          } else {
+            uni.hideLoading()
+            log.error(`获取crm会员请求失败`)
+            console.error(err)
+            uni.showToast({
+              title: "登录注册失败",
+              duration: 2000,
+              icon: 'none'
+            })
+            KipCacheTool.cleanKipCache()
+            MemberCacheTool.cleanMemberCache(app);
+          }
+        } else {
+          uni.hideLoading()
+          log.error(`获取crm会员请求失败`)
+          console.error(err)
+          uni.showToast({
+            title: "登录注册失败",
+            duration: 2000,
+            icon: 'none'
+          })
+          KipCacheTool.cleanKipCache()
+          MemberCacheTool.cleanMemberCache(app);
+        }
+      }).catch(err => {
+        uni.hideLoading()
+        log.error(`获取crm会员请求错误`)
+        console.error(err)
+        uni.showToast({
+          title: "登录注册错误",
+          duration: 2000,
+          icon: 'none'
+        })
+        KipCacheTool.cleanKipCache()
+        MemberCacheTool.cleanMemberCache(app);
+      })
+
+    },
+    openAuthPopup() {
+      this.$refs.popup.open();
+    },
+    closeAuthPopup() {
+      this.$refs.popup.close();
+    },
+    checkIsNewUser() {
+      // 除静安和浦东外,完善信息只显示一次
+      if ( this.custTypeId == '0' ) {
+        const isNewUser = KipCacheTool.getKipIsNewUser();
+        if ( isNewUser ) {
+          uni.navigateTo({
+            url: '/pages/personInfo/personInfo'
+          })
+        } else {
+          uni.redirectTo({
+            url: '/pages/automatic/automaticMy'
+          })
+        }
+
+      } else {
+        const member = this.member;
+        if ( member && ( !member.isCompleted || member.isCompleted == '0' ) ) {
+          uni.navigateTo({
+            url: '/pages/personInfo/personInfo'
+          })
+        } else {
+          uni.redirectTo({
+            url: '/pages/automatic/automaticMy'
+          })
+        }
+      }
+    },
+
+    updateKipMemberByWxProfile( wxProfile ) {
+      const _this = this;
+      const wxProfileParams = {
+        encryptedData: wxProfile.encryptedData,
+        iv: wxProfile.iv
+      }
+      uni.showLoading({
+        title: '正在加载',
+        mask: true,
+      })
+      // 根据微信授权更新kip会员信息
+      kipUpdateWxMember(wxProfileParams).then(updateResp => {
+        uni.hideLoading()
+        const updateRespResult = updateResp.data;
+        if ( updateRespResult.code === '000000' ) {
+          uni.showLoading({
+            title: '正在加载'
+          })
+          kipGetUserDetail().then(resp => {
+            uni.hideLoading()
+            const result = resp.data;
+            if ( result.code === '000000' && result.data ) {
+              // 存储用户信息
+              const member = result.data;
+              _this.saveMemberSource(member);
+              _this.getKipMemberInfoAfter(member);
+            } else {
+              MemberCacheTool.cleanMemberCache(app);
+              uni.showToast({
+                title: result.message,
+                duration: 2000,
+                icon: 'none'
+              })
+            }
+          }).catch(err => {
+            uni.hideLoading()
+            MemberCacheTool.cleanMemberCache(app);
+            console.log(err);
+          })
+        } else {
+          const message = updateRespResult.message || '更新会员失败';
+          uni.showToast({
+            title: message,
+            duration: 2000,
+            icon: 'none'
+          })
+        }
+      }).catch(err => {
+        uni.hideLoading()
+        uni.showToast({
+          title: '更新会员失败',
+          duration: 2000,
+          icon: 'none'
+        })
+        log.error('更新会员信息错误',err);
+      })
+    },
+    noWechatAuthPhoneLogin( isClosePopup = true ) {
+      if ( isClosePopup ) {
+        this.closeAuthPopup();
+      }
+
+      const _this = this;
+      uni.showLoading({
+        title: '正在加载',
+        mask: true,
+      })
+      kipGetUserDetail().then(resp => {
+        uni.hideLoading()
+        const result = resp.data;
+        if ( result.code === '000000' && result.data ) {
+          // 存储用户信息
+          const member = result.data;
+          _this.saveMemberSource(member);
+          _this.getKipMemberInfoAfter(member);
+        } else {
+          MemberCacheTool.cleanMemberCache(app);
+          uni.showToast({
+            title: result.message,
+            duration: 2000,
+            icon: 'none'
+          })
+        }
+      }).catch(err => {
+        uni.hideLoading()
+        MemberCacheTool.cleanMemberCache(app);
+        console.log(err);
+      })
+    },
+    saveMemberSource( kipMember ) {
+      const {phoneNumber,id} = kipMember;
+      const groupId = uni.getStorageSync("groupId");
+      const mallid = uni.getStorageSync("mallid");
+      const params = {
+        kipUserId: id,
+        mobile: phoneNumber,
+        groupId,
+        mallid,
+      }
+      const regSource = app?.globalData.regSource;
+      if ( regSource ) {
+        params.registerSource = regSource.value;
+        params.registerSourceLabel = regSource.label;
+      } else {
+        const defaultRegSource = REG_SOURCE.MINI_APP;
+        params.registerSource = defaultRegSource.value;
+        params.registerSourceLabel = defaultRegSource.label;
+      }
+
+      const tpName = app?.globalData?.tpName || '';
+      const tpId = app?.globalData?.tpId || '';
+      if ( tpName || tpId ) {
+        params.registerSourceRemark = tpName + ':' + tpId;
+      } else {
+        params.registerSourceRemark = '';
+      }
+      const utmStr = getUTMSource();
+      if ( utmStr ) {
+        params.regMemberSourceOriginalParams = JSON.stringify(utmStr);
+      }
+      crmSaveMemberSource(params).then(resp => {
+        if ( resp.data.code !== 0 ) {
+          console.error(resp.data.msg);
+        }
+      }).catch(err => {
+        console.error(err);
+      })
+    },
+    saveAgreementAction() {
+      const params = {
+        protocolStatus: 1,
+        privacyStatus: 1
+      }
+      kipAgreementSave(params).then(resp => {
+        const result = resp.data;
+        console.log('=>[kipAgreementSave]: ',result)
+      }).catch(err => {
+        console.error(err)
+      })
+    },
+  }
+}
+</script>
+
+
+<style scoped lang="less">
+.page {
+  background-color: #F4F7FF;
+  height: 100vh;
+}
+
+.authorize__head {
+  width: 100%;
+  justify-content: center;
+  align-items: center;
+  display: flex;
+  padding-top: 100px;
+  margin-bottom: 54px;
+
+  .head__info {
+    padding-top: 10px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    flex-wrap: wrap;
+    flex-flow: column;
+
+    .head__logo {
+      height: 75px;
+      text-align: center;
+
+      img {
+        height: 100%;
+      }
+    }
+
+    .head__text {
+      font-size: 26px;
+      color: #666;
+      margin-top: 16px;
+    }
+  }
+}
+
+.mgt40 {
+  margin-top: 54px;
+}
+
+.mgt34 {
+  margin-top: 34px;
+}
+
+.authorize_btn {
+  height: 100px;
+  width: calc(100% - 60px);
+  border-radius: 100px;
+  line-height: 100px;
+  font-size: 36px;
+  margin: 0 30px;
+}
+
+.authorize_btn--phone {
+  background-color: #333333;
+  color: #FFFFFF;
+}
+
+.authorize__form {
+  width: 100%;
+  border-top: 1px solid #D8DAE0;
+  border-bottom: 1px solid #D8DAE0;
+}
+
+.authorize__form > .form__item {
+  height: 130px;
+  line-height: 130px;
+  margin-left: 36px;
+  display: flex;
+  flex-direction: row;
+  &.line {
+    border-bottom: 1px solid #D8DAE0;
+  }
+}
+
+.authorize__form > .form__item > .form__label {
+  width: 190px;
+  font-size: 34px;
+}
+
+.authorize__form > .form__item > .form__input {
+  flex: 1;
+  margin-right: 30px;
+  height: 130px;
+  line-height: 130px;
+  display: flex;
+  align-items: center;
+
+  input {
+    height: 66px;
+    line-height: 66px;
+  }
+
+  .van-cell {
+    background-color: transparent;
+    font-size: 30px;
+    padding-right: 0;
+  }
+}
+
+.authorize__form > .form__item > .form__code {
+  display: flex;
+  align-items: center;
+  height: 130px;
+  line-height: 130px;
+  margin-right: 30px;
+}
+
+
+.auth-popup {
+  position: relative;
+  display: flex;
+  flex-direction: column;
+  align-content: space-between;
+  width: 600px;
+  background-color: #FFFFFF;
+  overflow: hidden;
+  border-radius: 10px;
+
+  .auth-popup__head {
+    height: 90px;
+    line-height: 90px;
+    text-align: center;
+    font-size: 34px;
+    font-weight: 600;
+    border-bottom: 1px solid #F0F0F0;
+  }
+
+  .auth-popup__main {
+    text-align: center;
+
+    .head__logo {
+      height: 75px;
+      margin-bottom: 40px;
+      margin: 52px auto 27px auto;
+      text-align: center;
+
+      img {
+        height: 100%;
+      }
+    }
+  }
+
+  .auth-popup__footer {
+    display: flex;
+    font-size: 34px;
+    text-align: center;
+    height: 92px;
+    line-height: 92px;
+    border-top: 1px solid #F0F0F0;
+
+    .cancel {
+      flex: 1;
+      line-height: 92px;
+    }
+
+    .phone-btn {
+      color: #6578C1;
+      background-color: transparent;
+
+      &::after {
+        border: none;
+      }
+    }
+
+  }
+}
+</style>

+ 120 - 210
src/pages/parkingFee/parkingFee.vue

@@ -1,172 +1,95 @@
 <template>
-  <scroll-view
-    style="background-color: #F4F7FF"
-    scroll-y="true"
-  >
+  <!-- scroll-view -->
+  <div style="background-color: #f4f7ff" scroll-y="true">
     <!--    <authorize ref="authorize"></authorize>-->
     <!--    <div v-if="userInfo && userInfo.vipcode">vipcode: {{userInfo.vipcode}}</div>-->
-    <div class="wrap">
+    <scroll-view class="wrap-box">
       <div class="parkingFee" ref="parkingFee">
-        <div
-          class="parkingFee-top bg"
-          :style="{
-            // backgroundImage: `url(${require('./static/images/parking-bgi.png')})`,
-            // backgroundAttachment: 'fixed',
-          }"
-        >
-          <div
-            :class="{
-              top_menu: true,
-              blue_top_menu: custTypeId === 1,
-              green_top_menu: custTypeId === 2,
-            }"
-            v-if="custTypeId >= 0"
-          >
+        <div class="parkingFee-top bg">
+          <div :class="{
+            top_menu: true,
+            blue_top_menu: custTypeId === 1,
+            green_top_menu: custTypeId === 2,
+          }" v-if="custTypeId >= 0">
             <div class="menu_item" @click="doRouter">
-              <img
-                :src="
-                  require(`./static/images/icon2${colorAry[custTypeId]}.png`)
-                "
-              />
+              <img :src="
+                require(`./static/images/icon2${colorAry[custTypeId]}.png`)
+              " />
               <span>缴费记录</span>
             </div>
-            <!--            <div class="menu_item" @click="doRouter3">-->
-            <!--              <img-->
-            <!--                :src="require(`./static/images/icon3${colorAry[custTypeId]}.png`)"-->
-            <!--              />-->
-            <!--              <span>停车劵兑换</span>-->
-            <!--            </div>-->
             <div class="menu_item" @click="doRouter1">
-              <img
-                :src="
-                  require(`./static/images/icon4${colorAry[custTypeId]}.png`)
-                "
-              />
+              <img :src="
+                require(`./static/images/icon4${colorAry[custTypeId]}.png`)
+              " />
               <span>停车开票</span>
             </div>
             <div class="menu_item" @click="doRouter2">
-              <img
-                :src="
-                  require(`./static/images/icon1${colorAry[custTypeId]}.png`)
-                "
-              />
+              <img :src="
+                require(`./static/images/icon1${colorAry[custTypeId]}.png`)
+              " />
               <span>车辆管理</span>
             </div>
           </div>
         </div>
-        <div
-          :class="{
-            'parkingFee-bottom': true,
-            'blue-parkingFee-bottom': custTypeId === 1,
-            'green-parkingFee-bottom': custTypeId === 2,
-            'pb65': carList.length < 1
-          }"
-        >
+        <div :class="{
+          'parkingFee-bottom': true,
+          'blue-parkingFee-bottom': custTypeId === 1,
+          'green-parkingFee-bottom': custTypeId === 2,
+          pb65: carList.length < 1,
+        }">
           <div class="parkingFee-search">
             <div class="search_tip" v-if="custTypeId === 0">
               <div>车辆类型</div>
               <div class="search_tip_pt">
-                <div
-                  :class="carType == 0 ? 'search_tip_pt_index' : ''"
-                  @click="toggleType(0)"
-                >
+                <div :class="carType == 0 ? 'search_tip_pt_index' : ''" @click="toggleType(0)">
                   燃油车牌
                 </div>
-                <div
-                  :class="carType == 1 ? 'search_tip_pt_index' : ''"
-                  @click="toggleType(1)"
-                >
+                <div :class="carType == 1 ? 'search_tip_pt_index' : ''" @click="toggleType(1)">
                   新能源
                 </div>
-                <div
-                  :class="carType == 2 ? 'search_tip_pt_index' : ''"
-                  @click="toggleType(2)"
-                >
+                <div :class="carType == 2 ? 'search_tip_pt_index' : ''" @click="toggleType(2)">
                   特殊车牌
                 </div>
               </div>
             </div>
-            <div
-              :class="{
-                blueClassify: custTypeId === 1,
-                greenClassify: custTypeId === 2,
-              }"
-              v-else
-            >
-              <div
-                :class="{ classifyItem: true, isChecked: carType === index }"
-                v-for="(item, index) in classifyList"
-                :key="index"
-              >
+            <div :class="{
+              blueClassify: custTypeId === 1,
+              greenClassify: custTypeId === 2,
+            }" v-else>
+              <div :class="{ classifyItem: true, isChecked: carType === index }" v-for="(item, index) in classifyList"
+                :key="index">
                 <div @click="toggleType(index)">{{ item }}</div>
               </div>
             </div>
             <div class="input-box">
-              <div
-                class="li"
-                @click="clickShowKeyboard(0)"
-                :class="[active === 0 ? 'active' : '']"
-              >
+              <div class="li" @click="clickShowKeyboard(0)" :class="[active === 0 ? 'active' : '']">
                 {{ numArr[0] }}
               </div>
-              <div
-                class="li"
-                @click="clickShowKeyboard(1)"
-                :class="[active === 1 ? 'active' : '']"
-              >
+              <div class="li" @click="clickShowKeyboard(1)" :class="[active === 1 ? 'active' : '']">
                 {{ numArr[1] }}
               </div>
               <div class="input_box_dian">·</div>
-              <div
-                class="li"
-                @click="clickShowKeyboard(2)"
-                :class="[active === 2 ? 'active' : '']"
-              >
+              <div class="li" @click="clickShowKeyboard(2)" :class="[active === 2 ? 'active' : '']">
                 {{ numArr[2] }}
               </div>
-              <div
-                class="li"
-                @click="clickShowKeyboard(3)"
-                :class="[active === 3 ? 'active' : '']"
-              >
+              <div class="li" @click="clickShowKeyboard(3)" :class="[active === 3 ? 'active' : '']">
                 {{ numArr[3] }}
               </div>
-              <div
-                class="li"
-                @click="clickShowKeyboard(4)"
-                :class="[active === 4 ? 'active' : '']"
-              >
+              <div class="li" @click="clickShowKeyboard(4)" :class="[active === 4 ? 'active' : '']">
                 {{ numArr[4] }}
               </div>
-              <div
-                class="li"
-                @click="clickShowKeyboard(5)"
-                :class="[active === 5 ? 'active' : '']"
-              >
+              <div class="li" @click="clickShowKeyboard(5)" :class="[active === 5 ? 'active' : '']">
                 {{ numArr[5] }}
               </div>
-              <div
-                class="li"
-                @click="clickShowKeyboard(6)"
-                :class="[active === 6 ? 'active' : '']"
-              >
+              <div class="li" @click="clickShowKeyboard(6)" :class="[active === 6 ? 'active' : '']">
                 {{ numArr[6] }}
               </div>
-              <div
-                class="li"
-                @click="clickShowKeyboard(7)"
-                :class="[active === 7 ? 'active' : '']"
-                v-if="carType == 1"
-              >
+              <div class="li" @click="clickShowKeyboard(7)" :class="[active === 7 ? 'active' : '']" v-if="carType == 1">
                 <span v-if="numArr[7]">{{ numArr[7] }}</span>
               </div>
             </div>
-            <button
-              class="search-btn"
-              :class="disabledBtn ? 'disabled-btn' : ''"
-              :disabled="disabledBtn"
-              @click="preHandleSearch"
-            >
+            <button class="search-btn" :class="disabledBtn ? 'disabled-btn' : ''" :disabled="disabledBtn"
+              @click="preHandleSearch">
               查询缴费
             </button>
           </div>
@@ -176,59 +99,43 @@
               <!-- <img src="static/images/icon5.png" class="vehicleMgt-title-img"/> -->
             </div>
             <div class="vehicleMgt-content" v-if="carList.length">
-              <div
-                class="item"
-                v-for="(item, index) in carList"
-                :key="index"
-                @click="toHandleSearch(item)"
-                :class="vehicleNumber == item ? 'vehicleMgt-content_cls' : ''"
-              >
+              <div class="item" v-for="(item, index) in carList" :key="index" @click="toHandleSearch(item)"
+                :class="vehicleNumber == item ? 'vehicleMgt-content_cls' : ''">
                 {{ item | formatCarno }}
               </div>
             </div>
           </div>
         </div>
-        <div
-          :class="{
-              top_content: true,
-              blue_top_content: custTypeId === 1,
-              green_top_content: custTypeId === 2,
-            }"
-          :style="{
-              'background-image':
-                custTypeId === 1 ? `url(${picUrl}${blueHeadBg});` : '',
-            }"
-        >
+        <div :class="{
+          top_content: true,
+          blue_top_content: custTypeId === 1,
+          green_top_content: custTypeId === 2,
+        }" :style="{
+            'background-image':
+              custTypeId === 1 ? `url(${picUrl}${blueHeadBg});` : '',
+          }">
           <div class="title_box">
             <span class="title">缴费说明</span>
           </div>
           <div class="info" :class="!init_ch ? 'info_show' : ''">
             <span>{{ parkInfoEntity.payinstruction }}</span>
           </div>
-          <div
-          class="top_down"
-          @click="top_display"
-          v-if="
-              !init_ch &&
-              parkInfoEntity.payinstruction &&
-              parkInfoEntity.payinstruction.length > 60
-            "
-        >
-        <van-icon name="arrow-down" />
-        </div>
-        <div class="top_down" @click="top_display" v-else><van-icon name="arrow-up" /></div>
+          <div class="top_down" @click="top_display" v-if="
+            !init_ch &&
+            parkInfoEntity.payinstruction &&
+            parkInfoEntity.payinstruction.length > 60
+          ">
+            <van-icon name="arrow-down" />
+          </div>
+          <div class="top_down" @click="top_display" v-else>
+            <van-icon name="arrow-up" />
+          </div>
         </div>
       </div>
-    </div>
-    <plate-number
-      ref="plateKeyboard"
-      :carType="carType"
-      :active="active"
-      :ind="ind"
-      :numArr="numArr"
-      @carnoArr="updateCarno"
-    ></plate-number>
-  </scroll-view>
+    </scroll-view>
+    <plate-number ref="plateKeyboard" :carType="carType" :active="active" :ind="ind" :numArr="numArr"
+      @carnoArr="updateCarno"></plate-number>
+  </div>
 </template>
 
 <script>
@@ -328,13 +235,13 @@ export default {
       path: 'shareLink',
     };
   },
-  async created(params) {},
+  async created(params) { },
   mounted() {
     setTimeout(() => {
       uni.setNavigationBarTitle({
-        title: "临时停车"
-      })
-    }, 300)
+        title: '临时停车',
+      });
+    }, 300);
     if (this.openid) {
       this.openId = this.openid;
       this.getParkInfo();
@@ -487,19 +394,19 @@ export default {
     sensorsClick(eventName, params) {
       let optionsQuery = uni.getStorageSync('options_query');
       let fixedParams = {
-          previous_url: this.preUrl || '',
-          // 原previous_url: uni.getStorageSync('previousUrl') || ''
-          // previous_url: 使用sdk预置参数$referrer,
-          $brand_id: uni.getStorageSync('groupId'),
-          $location: uni.getStorageSync('mallid'),
-          $channel: optionsQuery?.channel || '',
-          // $utm_lbs: this.optionsQuery.utm_lbs || '',
-          $utm_channel: optionsQuery?.utm_channel || '',
-          $utm_method: optionsQuery?.utm_method || '',
-          $utm_source: optionsQuery?.utm_source || '',
-          $utm_function: optionsQuery?.utm_function || '',
-          $utm_user: optionsQuery?.utm_user || '',
-        },
+        previous_url: this.preUrl || '',
+        // 原previous_url: uni.getStorageSync('previousUrl') || ''
+        // previous_url: 使用sdk预置参数$referrer,
+        $brand_id: uni.getStorageSync('groupId'),
+        $location: uni.getStorageSync('mallid'),
+        $channel: optionsQuery?.channel || '',
+        // $utm_lbs: this.optionsQuery.utm_lbs || '',
+        $utm_channel: optionsQuery?.utm_channel || '',
+        $utm_method: optionsQuery?.utm_method || '',
+        $utm_source: optionsQuery?.utm_source || '',
+        $utm_function: optionsQuery?.utm_function || '',
+        $utm_user: optionsQuery?.utm_user || '',
+      },
         finalParams = Object.assign(fixedParams, params);
       this.$sensors.track(eventName, finalParams);
     },
@@ -622,8 +529,8 @@ export default {
             this.$router.push({
               path: './parkingFeeHint/parkingFeeHint',
               query: {
-                carno
-              }
+                carno,
+              },
             });
 
             redirectUrl = '/pages/parkingFee/parkingFeeHint/parkingFeeHint.vue';
@@ -740,10 +647,11 @@ export default {
   },
 };
 </script>
-<style lang="less" scoped>
+<style lang="less">
 page {
-  background-color: #F4F7FF;
+  background-color: #f4f7ff;
 }
+
 .scroll-Y {
   width: 100%;
   // display: flex;
@@ -755,11 +663,11 @@ page {
   background: #e7e9ea;
 }
 
-.wrap {
+.wrap-box {
   display: flex;
   flex-direction: column;
   width: 100%;
-
+  font-size: 14px;
   .parkingFee {
     display: flex;
     flex-direction: column;
@@ -769,13 +677,11 @@ page {
       flex-direction: column;
       background-size: 100% 30%;
       // height: 350px;
-       margin-bottom: 24px;
-      background: #FAFBFF;
-      border: 1px solid #D8DAE0;
+      margin-bottom: 20px;
+      background: #fafbff;
+      border: 1px solid #d8dae0;
       border-top: none;
 
-
-
       .blue_top_content {
         .color_top_content('blue');
         background-position: 0 0;
@@ -790,14 +696,17 @@ page {
       .color_top_content(@value) {
         @color: 'color-@{value}';
         background-color: @@color;
+
         span {
           color: @color-white;
         }
+
         .title_box {
           .btn {
             color: @color-gold;
           }
         }
+
         .info {
           font-size: 24px;
         }
@@ -811,20 +720,12 @@ page {
     }
 
     .top_menu {
-      //margin: 10px auto 0;
-      background: #FAFBFF;
+      background: #fafbff;
       padding: 50px 40px 30px;
       box-sizing: border-box;
       display: flex;
       justify-content: space-between;
-      //border-radius: 15px;
-      // position: absolute;
-      // left: 50%;
-      //box-shadow: 0 0 5px #666;
-      // transform: translateX(-50%);
-      //top: 160px;
       width: 100%;
-      //height: 220px;
 
       .menu_item {
         display: flex;
@@ -864,6 +765,7 @@ page {
       color: @@color;
       border-radius: 0;
       align-items: center;
+
       .menu_item {
         width: 33.33333%;
 
@@ -884,11 +786,12 @@ page {
       display: flex;
       flex-direction: column;
       //padding: 14px 25px;
-      background: #FAFBFF;
-      border: 1px solid #D8DAE0;
+      background: #fafbff;
+      border: 1px solid #d8dae0;
       box-sizing: border-box;
       // padding-bottom: 65px;
       margin-bottom: 24px;
+
       &.pb65 {
         padding-bottom: 65px;
       }
@@ -912,12 +815,14 @@ page {
           justify-content: space-between;
           align-items: center;
           font-size: 30px;
-          &:first-child{
+
+          &:first-child {
             font-size: 36px;
             font-weight: 500;
             color: #333333;
             line-height: 50px;
           }
+
           .search_tip_pt {
             font-size: 24px;
             width: 470px;
@@ -953,7 +858,7 @@ page {
               color: #fff;
               //background-image: linear-gradient(to right, #7e4fa1, #433c7f);
               //background-image: linear-gradient(to right, #7e4fa1, #433c7f);
-              background-color: #064C8A;
+              background-color: #064c8a;
             }
           }
         }
@@ -963,7 +868,7 @@ page {
           width: 100%;
           height: 100px;
           margin: auto;
-          background: #F4F7FF;
+          background: #f4f7ff;
           border-radius: 0.4rem;
           margin: 1rem auto;
           display: flex;
@@ -986,7 +891,7 @@ page {
             }
 
             &.active {
-              border-color: #064C8A;
+              border-color: #064c8a;
             }
           }
 
@@ -1009,7 +914,7 @@ page {
           font-size: 36px;
           text-align: center;
           //background-image: linear-gradient(to right, #7e4fa1, #433c7f);
-          background-color: #064C8A;
+          background-color: #064c8a;
         }
 
         .disabled-btn {
@@ -1061,12 +966,12 @@ page {
             font-size: 28px;
             border-radius: 30px;
             color: #666666;
-            background-color: #F4F7FF;
+            background-color: #f4f7ff;
           }
 
           .vehicleMgt-content_cls {
-            color: #F4F7FF;
-            border: 2px solid #064C8A;
+            color: #f4f7ff;
+            border: 2px solid #064c8a;
           }
 
           // .item::after {
@@ -1115,6 +1020,7 @@ page {
         }
       }
     }
+
     .top_content {
       padding: 30px 30px;
       margin-bottom: constant(safe-area-inset-bottom); // 兼容 IOS<11.2
@@ -1123,11 +1029,10 @@ page {
       display: flex;
       flex-direction: column;
 
-
       //width: 750px;
       //height: 280px;
-      background: #FAFBFF;
-      border: 1px solid #D8DAE0;
+      background: #fafbff;
+      border: 1px solid #d8dae0;
 
       span {
         font-size: 24px;
@@ -1139,6 +1044,7 @@ page {
         display: flex;
         align-items: center;
         justify-content: space-between;
+
         // margin-bottom: 20px;
         .title {
           // padding: 0px 14px;
@@ -1168,6 +1074,7 @@ page {
         -webkit-line-clamp: 2;
         -webkit-box-orient: vertical;
       }
+
       .top_down {
         margin-top: 20px;
         width: 100%;
@@ -1177,6 +1084,7 @@ page {
         color: #999999;
       }
     }
+
     .blue-parkingFee-bottom {
       .color-parkingFee-bottom('blue');
     }
@@ -1190,6 +1098,7 @@ page {
       width: auto;
       padding-bottom: 0;
       padding: 22px 20px 0 20px;
+
       .parkingFee-search {
         padding: 0 0 31px 0;
 
@@ -1223,6 +1132,7 @@ page {
           background-color: @@color;
         }
       }
+
       .vehicleMgt-list {
         background-color: @color-white;
 

+ 200 - 228
src/pages/parkingFee/vehicleAddOrEdit.vue

@@ -1,219 +1,144 @@
 <template>
-  <div
-    class="wrap"
-    :style="{ padding: custTypeId === 0 ? '30px' : '18px 22px 0 16px' }"
-  >
-    <div :style="{ border: custTypeId === 0 ? '' : '1px solid #C69C6D' }">
-      <div class="switch-container" v-if="custTypeId === 0">
-        <div>车牌类型</div>
-        <div class="switch">
-          <div
-            v-for="(item, index) in licensePlateTypeArr"
-            :key="index"
-            :class="index == carType ? 'switch-active' : ''"
-            @click="toggleType(index)"
-          >
-            {{ item.label }}
+  <div style="background-color: #F4F7FF;">
+    <scroll-view class="wrap">
+      <div class="car-number-box">
+        <div :style="{ border: custTypeId === 0 ? '' : '1px solid #C69C6D' }">
+        <div class="switch-container" v-if="custTypeId === 0">
+          <div class="car-type">车牌类型</div>
+          <div class="switch">
+            <div v-for="(item, index) in licensePlateTypeArr" :key="index"
+              :class="index == carType ? 'switch-active' : ''" @click="toggleType(index)">
+              {{ item.label }}
+            </div>
           </div>
         </div>
-      </div>
-      <!--  -->
-      <div class="switch-container-else" v-else>
-        <div
-          v-for="(item, index) in licensePlateTypeArr"
-          :key="index"
-          class="switch-item"
-          :class="index == carType ? 'switch-selected' : 'switch-else'"
-          @click="toggleType(index)"
-        >
-          <div
-            :class="index == carType ? 'switch-blue-color' : 'switch-blue-bg'"
-            v-if="custTypeId === 1"
-          >
-            {{ item.label }}
-          </div>
-          <div
-            :class="index == carType ? 'switch-green-color' : 'switch-green-bg'"
-            v-if="custTypeId === 2"
-          >
-            {{ item.label }}
+        <!--  -->
+        <div class="switch-container-else" v-else>
+          <div v-for="(item, index) in licensePlateTypeArr" :key="index" class="switch-item"
+            :class="index == carType ? 'switch-selected' : 'switch-else'" @click="toggleType(index)">
+            <div :class="index == carType ? 'switch-blue-color' : 'switch-blue-bg'" v-if="custTypeId === 1">
+              {{ item.label }}
+            </div>
+            <div :class="index == carType ? 'switch-green-color' : 'switch-green-bg'" v-if="custTypeId === 2">
+              {{ item.label }}
+            </div>
+            <div class="switch-line" v-if="index == carType"></div>
           </div>
-          <div class="switch-line" v-if="index == carType"></div>
         </div>
-      </div>
-      <div
-        class="input-box"
-        :style="{ margin: custTypeId === 0 ? '' : '0 44px 0 35px' }"
-      >
-        <div
-          class="li"
-          @click="clickShowKeyboard(0)"
-          :style="{
+        <div class="input-box" :style="{ margin: custTypeId === 0 ? '' : '0 44px 0 35px' }">
+          <div class="li" @click="clickShowKeyboard(0)" :style="{
             color:
               custTypeId === 0
-                ? '#703a98'
+                ? '#333'
                 : custTypeId === 1
-                ? '#023694 '
-                : '#0D6B38',
-          }"
-          :class="[active === 0 ? 'active' : '']"
-        >
-          {{ numArr[0] }}
-        </div>
-        <div
-          class="li"
-          @click="clickShowKeyboard(1)"
-          :style="{
+                ? '#333 '
+                : '#333',
+          }" :class="[active === 0 ? 'active' : '']">
+            {{ numArr[0] }}
+          </div>
+          <div class="li" @click="clickShowKeyboard(1)" :style="{
             color:
               custTypeId === 0
-                ? '#703a98'
+                ? '#333'
                 : custTypeId === 1
-                ? '#023694 '
-                : '#0D6B38',
-          }"
-          :class="[active === 1 ? 'active' : '']"
-        >
-          {{ numArr[1] }}
-        </div>
-        <div
-          class="dot"
-          :style="{
+                ? '#333 '
+                : '#333',
+          }" :class="[active === 1 ? 'active' : '']">
+            {{ numArr[1] }}
+          </div>
+          <div class="dot" :style="{
             color:
               custTypeId === 0
-                ? '#703a98'
+                ? '#333'
                 : custTypeId === 1
-                ? '#023694 '
-                : '#0D6B38',
-          }"
-        >
-          ·
-        </div>
-        <div
-          class="li"
-          @click="clickShowKeyboard(2)"
-          :style="{
+                ? '#333 '
+                : '#333',
+          }">
+            ·
+          </div>
+          <div class="li" @click="clickShowKeyboard(2)" :style="{
             color:
               custTypeId === 0
-                ? '#703a98'
+                ? '#333'
                 : custTypeId === 1
-                ? '#023694 '
-                : '#0D6B38',
-          }"
-          :class="[active === 2 ? 'active' : '']"
-        >
-          {{ numArr[2] }}
-        </div>
-        <div
-          class="li"
-          @click="clickShowKeyboard(3)"
-          :style="{
+                ? '#333 '
+                : '#333',
+          }" :class="[active === 2 ? 'active' : '']">
+            {{ numArr[2] }}
+          </div>
+          <div class="li" @click="clickShowKeyboard(3)" :style="{
             color:
               custTypeId === 0
-                ? '#703a98'
+                ? '#333'
                 : custTypeId === 1
-                ? '#023694 '
-                : '#0D6B38',
-          }"
-          :class="[active === 3 ? 'active' : '']"
-        >
-          {{ numArr[3] }}
-        </div>
-        <div
-          class="li"
-          @click="clickShowKeyboard(4)"
-          :style="{
+                ? '#333 '
+                : '#333',
+          }" :class="[active === 3 ? 'active' : '']">
+            {{ numArr[3] }}
+          </div>
+          <div class="li" @click="clickShowKeyboard(4)" :style="{
             color:
               custTypeId === 0
-                ? '#703a98'
+                ? '#333'
                 : custTypeId === 1
-                ? '#023694 '
-                : '#0D6B38',
-          }"
-          :class="[active === 4 ? 'active' : '']"
-        >
-          {{ numArr[4] }}
-        </div>
-        <div
-          class="li"
-          @click="clickShowKeyboard(5)"
-          :style="{
+                ? '#333 '
+                : '#333',
+          }" :class="[active === 4 ? 'active' : '']">
+            {{ numArr[4] }}
+          </div>
+          <div class="li" @click="clickShowKeyboard(5)" :style="{
             color:
               custTypeId === 0
-                ? '#703a98'
+                ? '#333'
                 : custTypeId === 1
-                ? '#023694 '
-                : '#0D6B38',
-          }"
-          :class="[active === 5 ? 'active' : '']"
-        >
-          {{ numArr[5] }}
-        </div>
-        <div
-          class="li"
-          @click="clickShowKeyboard(6)"
-          :style="{
+                ? '#333 '
+                : '#333',
+          }" :class="[active === 5 ? 'active' : '']">
+            {{ numArr[5] }}
+          </div>
+          <div class="li" @click="clickShowKeyboard(6)" :style="{
             color:
               custTypeId === 0
-                ? '#703a98'
+                ? '#333'
                 : custTypeId === 1
-                ? '#023694 '
-                : '#0D6B38',
-          }"
-          :class="[active === 6 ? 'active' : '']"
-        >
-          {{ numArr[6] }}
-        </div>
-        <div
-          v-if="carType == 1"
-          class="li"
-          @click="clickShowKeyboard(7)"
-          :style="{
+                ? '#333 '
+                : '#333',
+          }" :class="[active === 6 ? 'active' : '']">
+            {{ numArr[6] }}
+          </div>
+          <div v-if="carType == 1" class="li" @click="clickShowKeyboard(7)" :style="{
             color:
               custTypeId === 0
-                ? '#703a98'
+                ? '#333'
                 : custTypeId === 1
-                ? '#023694 '
-                : '#0D6B38',
-          }"
-          :class="[active === 7 ? 'active' : '']"
-        >
-          <span v-if="numArr[7]">{{ numArr[7] }}</span>
+                ? '#333 '
+                : '#333',
+          }" :class="[active === 7 ? 'active' : '']">
+            <span v-if="numArr[7]">{{ numArr[7] }}</span>
+          </div>
         </div>
+       
       </div>
-      <div
-        class="confirm-btn"
-        :class="disabledBtn ? 'disabled-btn' : ''"
-        :disabled="disabledBtn"
-        @click="handleAddLicensePlateByKipMember"
-        v-if="custTypeId === 0"
-      >
-        确认添加0
+
+      <div class="reminder">
+        <div class="reminder-title">温馨提示:</div>
+        <div class="reminder-content">
+          ·用户可以添加多个"燃油车牌号"或"新能源车牌号"
+        </div>
+        <div class="reminder-content">·用户可以更改或删除已经绑定车牌</div>
       </div>
-      <div
-        class="confirm-btn-else"
-        :class="custTypeId === 1 ? 'confirm-btn-blue' : 'confirm-btn-green'"
-        @click="handleAddLicensePlateByKipMember"
-        v-else
-      >
-        确认添加1
       </div>
-    </div>
 
-    <div class="reminder">
-      <div class="reminder-title">温馨提示:</div>
-      <div class="reminder-content">
-        ·用户可以添加多个"燃油车牌号"或"新能源车牌号"
-      </div>
-      <div class="reminder-content">·用户可以更改或删除已经绑定车牌</div>
+    </scroll-view>
+    <div class="btn-box">
+      <div class="btnpb"></div>
+      <div class="confirm-btn" :class="disabledBtn ? 'disabled-btn' : ''" :disabled="disabledBtn"
+          @click="handleAddLicensePlateByKipMember" >
+          确认添加
+        </div>
     </div>
-    <plate-number
-      ref="plateKeyboard"
-      :carType="carType"
-      :active="active"
-      :ind="ind"
-      :numArr="numArr"
-      @carnoArr="updateCarno"
-    ></plate-number>
+    <plate-number ref="plateKeyboard" :carType="carType" :active="active" :ind="ind" :numArr="numArr"
+      @carnoArr="updateCarno"></plate-number>
   </div>
 </template>
 
@@ -261,13 +186,14 @@ export default {
     this.preUrl = uni.getStorageSync('previousUrl');
     uni.setStorageSync('previousUrl', '/pages/parkingFee/vehicleAddOrEdit.vue');
   },
-  onShow() {},
+  onShow() { },
   computed: {
     disabledBtn() {
+      console.log(190, this.numArr, this.numArr.findIndex((val) => !val));
       return this.numArr.findIndex((val) => !val) !== -1;
     },
     ...mapState({
-      custTypeId: (state) => state.custTypeId,
+      custTypeId: (state) => state.custTypeId, // custTypeId: 0 默认版本,1 上海静安 2 上海浦东
     }),
   },
   methods: {
@@ -444,21 +370,21 @@ export default {
     sensorsClick(eventName, params) {
       let optionsQuery = uni.getStorageSync('options_query');
       let fixedParams = {
-          cta_itemno: '',
-          cta_name: '',
-          previous_url: this.preUrl || '',
-          // 原previous_url: uni.getStorageSync('previousUrl') || ''
-          // previous_url: 使用sdk预置参数$referrer,
-          $brand_id: uni.getStorageSync('groupId'),
-          $location: uni.getStorageSync('mallid'),
-          $channel: optionsQuery.channel || '',
-          // $utm_lbs: this.optionsQuery.utm_lbs || '',
-          $utm_channel: optionsQuery.utm_channel || '',
-          $utm_method: optionsQuery.utm_method || '',
-          $utm_source: optionsQuery.utm_source || '',
-          $utm_function: optionsQuery.utm_function || '',
-          $utm_user: optionsQuery.utm_user || '',
-        },
+        cta_itemno: '',
+        cta_name: '',
+        previous_url: this.preUrl || '',
+        // 原previous_url: uni.getStorageSync('previousUrl') || ''
+        // previous_url: 使用sdk预置参数$referrer,
+        $brand_id: uni.getStorageSync('groupId'),
+        $location: uni.getStorageSync('mallid'),
+        $channel: optionsQuery.channel || '',
+        // $utm_lbs: this.optionsQuery.utm_lbs || '',
+        $utm_channel: optionsQuery.utm_channel || '',
+        $utm_method: optionsQuery.utm_method || '',
+        $utm_source: optionsQuery.utm_source || '',
+        $utm_function: optionsQuery.utm_function || '',
+        $utm_user: optionsQuery.utm_user || '',
+      },
         finalParams = Object.assign(fixedParams, params);
       this.$sensors.track(eventName, finalParams);
     },
@@ -468,7 +394,15 @@ export default {
 
 <style lang="less" scoped>
 .wrap {
-  padding: 30px;
+  // padding: 30px;
+  
+
+  .car-number-box {
+    margin-top: 24px;
+    padding: 30px;
+    background-color: #FAFBFF;
+    border: 1px solid #D8DAE0;
+  }
 
   .switch-container-else {
     margin-bottom: 72px;
@@ -537,22 +471,32 @@ export default {
     align-items: center;
     font-size: 30px;
 
+    .car-type {
+      font-size: 36px;
+      font-weight: 600;
+      color: #333333;
+      line-height: 50px;
+      width: 144px;
+      margin-right: 54px;
+    }
+
     .switch {
+      flex: 1;
       font-size: 28px;
       width: 470px;
       display: flex;
       justify-content: space-around;
       align-items: center;
-      border: 1px solid #4d4d4d;
-      height: 66px;
-      color: #4d4d4d;
+      border: 1px solid #999999;
+      height: 54px;
+      color: #999999;
       overflow: hidden;
       border-radius: 50px;
 
       div {
         height: 100%;
-        border-radius: 50px;
-        line-height: 65px;
+        border-radius: 27px;
+        line-height: 54px;
         text-align: center;
       }
 
@@ -571,6 +515,7 @@ export default {
       .switch-active {
         color: #fff;
         background-image: linear-gradient(to right, #7e4fa1, #433c7f);
+        background: #064C8A;
       }
     }
   }
@@ -579,15 +524,15 @@ export default {
     // width: 100%;
     height: 100px;
     margin: auto;
-    background: rgba(255, 255, 255, 1);
+    // background: rgba(255, 255, 255, 1);
     border-radius: 0.4rem;
     margin: 1rem auto;
     display: flex;
     justify-content: center;
 
     .li:first-child {
-      border-top-left-radius: 20px;
-      border-bottom-left-radius: 20px;
+      // border-top-left-radius: 20px;
+      // border-bottom-left-radius: 20px;
     }
 
     .li {
@@ -599,7 +544,10 @@ export default {
       display: flex;
       align-items: center;
       justify-content: center;
-      color: #703a98;
+      color: #333333;
+      border-radius: 4px;
+      background-color: #F4F7FF;
+      margin-right: 26px;
 
       img {
         width: 80%;
@@ -607,7 +555,10 @@ export default {
       }
 
       &.active {
-        border-color: #3e67ff;
+        border-color: #333333;
+      }
+      &:last-child {
+        margin-right: 0;
       }
     }
 
@@ -616,31 +567,63 @@ export default {
       justify-content: center;
       align-items: center;
       font-size: 120px;
-      color: #703a98;
+      color: #333333;
+      margin-right: 18px;
     }
   }
 
+  .reminder {
+    margin-top: 20px;
+
+    .reminder-title {
+      margin-bottom: 8px;
+    }
+
+    .reminder-content {
+      font-size: 26px;
+      padding-top: 3px;
+      color: #898989;
+    }
+  }
+}
+.btn-box {
+  position: fixed;
+  bottom: 0;
+  right: 0;
+  left: 0;
+  background-color: #F9F9FF;
+  padding: 30px;
+  box-shadow: 0px 13px 33px 0px rgba(190,187,187,0.2);
+
+  &.btnpb {
+    width: 100%;
+    padding-bottom: constant(safe-area-inset-bottom);
+    padding-bottom: env(safe-area-inset-bottom);
+  }
+
+
   .confirm-btn {
     color: #fff;
     margin: 0 auto;
     height: 90px;
     width: 98%;
     line-height: 90px;
-    border-radius: 80px;
-    font-size: 17px;
+    font-size: 34px;
     text-align: center;
-    background-image: linear-gradient(to right, #7e4fa1, #433c7f);
+    background: #064C8A;
+    border-radius: 45px;
   }
 
   .confirm-btn-else {
     width: 636px;
-    height: 87px;
+    height: 90px;
     color: white;
-    line-height: 87px;
+    line-height: 90px;
     text-align: center;
     font-size: 34px;
     opacity: 1;
-    border-radius: 43px;
+    border-radius: 45px;
+    background: #D8DAE0;
     margin: 64px auto 31px;
   }
 
@@ -653,22 +636,11 @@ export default {
   }
 
   .disabled-btn {
-    background-color: #c1c1c1;
+    background-color: #D8DAE0;
     background-image: none;
-  }
-
-  .reminder {
-    margin-top: 20px;
-
-    .reminder-title {
-      margin-bottom: 8px;
-    }
-
-    .reminder-content {
-      font-size: 26px;
-      padding-top: 3px;
-      color: #898989;
-    }
+    font-size: 34px;
+    font-weight: 400;
+    color: #FFFFFF;
   }
 }
 </style>

+ 109 - 97
src/pages/parkingFee/vehicleManagement.vue

@@ -4,78 +4,44 @@
     <div class="wrap">
       <div v-if="custTypeId === 0" class="wrap_plate">我的车牌</div>
       <div v-else class="wrap_plate">车牌号绑定</div>
-      <div
-        class="plate_plate"
-        :style="{ position: custTypeId === 0 ? '' : 'relative' }"
-        :class="
-          custTypeId === 0
-            ? 'linear-gradient-' + item.licensePlateType
-            : 'border-change'
-        "
-        v-for="item in licensePlateList"
-        :key="item.id"
-      >
+      <div class="plate_plate" :style="{ position: custTypeId === 0 ? '' : 'relative' }" :class="
+        custTypeId === 0
+          ? 'linear-gradient-' + item.licensePlateType
+          : 'border-change'
+      " v-for="item in licensePlateList" :key="item.id">
         <div class="plate_border">
-          <div
-            class="plate_tag"
-            :class="'bgc-' + item.licensePlateType"
-          ></div>
-          <div
-            class="plate_plate_index plate_plate_index1"
-            :style="{
-              padding: custTypeId === 0 ? '0 0 0 14px' : '14px 0 0 14px',
-            }"
-            >我的车牌</div
-          >
+          <div class="plate_tag" :class="'bgc-' + item.licensePlateType"></div>
+          <div class="plate_plate_index plate_plate_index1" :style="{
+            padding: custTypeId === 0 ? '0 0 0 14px' : '14px 0 0 14px',
+          }">我的车牌</div>
           <div class="plate_plate_index plate_plate_index2">{{
-            item.vehicleNo | formatCarno
+          item.vehicleNo | formatCarno
           }}</div>
           <div class="plate_plate_index plate_plate_index3">车牌类型</div>
-          <div
-            class="plate_tag-icon"
-            :class="
-              item.licensePlateType === 'NEW_ENERGY_CAR_NO'
-                ? 'plate_tag_icon_green'
-                : item.licensePlateType === 'ORDINARY_CAR_NO'
-                ? 'plate_tag_icon_blue'
-                : ''
-            "
-            v-if="custTypeId > 0"
-          ></div>
+          <div class="plate_tag-icon" :class="
+            item.licensePlateType === 'NEW_ENERGY_CAR_NO'
+              ? 'plate_tag_icon_green'
+              : item.licensePlateType === 'ORDINARY_CAR_NO'
+              ? 'plate_tag_icon_blue'
+              : ''
+          " v-if="custTypeId > 0"></div>
           <div class="plate_plate_index plate_plate_index4">
             <div class="">{{ item.licensePlateTypeDesc }}</div>
             <div class="plate_plate_index4_index2">
               <!-- <uni-icons type="compose" size="20" @click="toEdit(item)"></uni-icons> -->
               <!-- <uni-icons type="trash" size="20" class="mrg-left-20" @click="toDelete(item)"></uni-icons> -->
-              <img
-                src="static/images/money.png"
-                @click="toPay(item.vehicleNo)"
-              />
-              <img
-                src="static/images/update.png"
-                class="mrg-left-20"
-                @click="toEdit(item)"
-              />
-              <img
-                src="static/images/delete.png"
-                class="mrg-left-20"
-                @click="toDelete(item)"
-              />
+              <img src="static/images/money.png" @click="toPay(item.vehicleNo)" />
+              <img src="static/images/update.png" class="mrg-left-20" @click="toEdit(item)" />
+              <img src="static/images/delete.png" class="mrg-left-20" @click="toDelete(item)" />
             </div>
           </div>
         </div>
       </div>
-      <div class="add_plate" v-if="licensePlateList.length < 3" @click="toAdd"
-        >添加车牌+</div
-      >
-      <div class="wrap_plate" style="margin-bottom: 50px">
-        <div>温馨提示:</div>
-        <div style="padding-top: 25px; color: #898989; font-size: 28px"
-          >·用户可以添加多个"燃油车牌号"或"新能源车牌号"</div
-        >
-        <div style="color: #898989; font-size: 28px; padding-top: 5px"
-          >·用户可以更改或删除已经绑定车牌</div
-        >
+      <div class="add_plate" v-if="licensePlateList.length < 3" @click="toAdd">添加车牌+</div>
+      <div class="wrap_plate mt36">
+        <div class="title">温馨提示:</div>
+        <div class="desc">·用户可以添加多个"燃油车牌号"或"新能源车牌号"</div>
+        <div class="desc">·用户可以更改或删除已经绑定车牌</div>
       </div>
     </div>
     <uni-popup ref="deleteDialog" type="center">
@@ -100,11 +66,7 @@
     <uni-popup ref="deleteSuccessDialog" type="center">
       <div class="popup-dialog">
         <div class="dialog-content">
-          <uni-icons
-            type="checkbox-filled"
-            size="60"
-            color="#7DB124"
-          ></uni-icons>
+          <uni-icons type="checkbox-filled" size="60" color="#7DB124"></uni-icons>
           <span class="dialog-content-text">删除成功</span>
         </div>
         <div class="dialog-button-group">
@@ -120,18 +82,20 @@
 <script>
 import uniPop from '@/components/uni-popup/uni-popup.vue'
 // const app = getApp()
- const app = {}
+const app = {}
 import {
   kipGetMemberVehicles,
   kipDeleteMemberVehicles,
-} from '@/utils/api-kip.js'
-import { LICENSE_PLATE_TYPE_ARR } from '@/constants.js'
-import { mapState } from 'vuex'
-import authorize from '@/components/authorize/authorize.vue'
-import { isCruMarketByKey } from '@/utils/location-util.js'
-import MemberCacheTool from '@/utils/member-cache-tool.js'
-import { REG_SOURCE } from '@/constants.js'
-import uni from '../../utils/uniHooks'
+} from '@/utils/api-kip.js';
+import { LICENSE_PLATE_TYPE_ARR } from '@/constants.js';
+import { mapState } from 'vuex';
+import authorize from '@/components/authorize/authorize.vue';
+import { isCruMarketByKey } from '@/utils/location-util.js';
+import MemberCacheTool from '@/utils/member-cache-tool.js';
+import { REG_SOURCE } from '@/constants.js';
+import uni from '@/utils/uniHooks.js';
+import {vehicles as vehiclesList} from './list'
+
 export default {
   components: {
     uniPop,
@@ -332,7 +296,7 @@ export default {
           if (result && result.code == '000000') {
             this.sensorsClick('$ClickDeleteLicensePlate', {
               carno_old: this.activeCarno,
-              redirect_url :'',
+              redirect_url: '',
             })
             if (result.data) {
               _this.$refs.deleteDialog.close()
@@ -361,22 +325,22 @@ export default {
     sensorsClick(eventName, params) {
       let optionsQuery = uni.getStorageSync('options_query')
       let fixedParams = {
-          cta_itemno: '',
-          cta_name: '',
-          previous_url: this.preUrl || '',
-          // 原previous_url: uni.getStorageSync('previousUrl') || ''
-          // previous_url: 使用sdk预置参数$referrer,
-          $brand_id:uni.getStorageSync('groupId'),
-          redirect_url: params.redirect_url || '',
-          $location: uni.getStorageSync('mallid'),
-          $channel: optionsQuery.channel || '',
-          // $utm_lbs: this.optionsQuery.utm_lbs || '',
-          $utm_channel: optionsQuery.utm_channel || '',
-          $utm_method: optionsQuery.utm_method || '',
-          $utm_source: optionsQuery.utm_source || '',
-          $utm_function: optionsQuery.utm_function || '',
-          $utm_user: optionsQuery.utm_user || '',
-        },
+        cta_itemno: '',
+        cta_name: '',
+        previous_url: this.preUrl || '',
+        // 原previous_url: uni.getStorageSync('previousUrl') || ''
+        // previous_url: 使用sdk预置参数$referrer,
+        $brand_id: uni.getStorageSync('groupId'),
+        redirect_url: params.redirect_url || '',
+        $location: uni.getStorageSync('mallid'),
+        $channel: optionsQuery.channel || '',
+        // $utm_lbs: this.optionsQuery.utm_lbs || '',
+        $utm_channel: optionsQuery.utm_channel || '',
+        $utm_method: optionsQuery.utm_method || '',
+        $utm_source: optionsQuery.utm_source || '',
+        $utm_function: optionsQuery.utm_function || '',
+        $utm_user: optionsQuery.utm_user || '',
+      },
         finalParams = Object.assign(fixedParams, params)
       this.$sensors.track(eventName, finalParams)
     },
@@ -412,6 +376,7 @@ export default {
             } else {
               this.licensePlateList = []
             }
+            this.licensePlateList = vehiclesList;
           } else {
             const message = result.message || '获取信息失败'
             uni.showToast({
@@ -436,21 +401,45 @@ export default {
   display: flex;
   flex-direction: column;
   height: 100vh;
-  background: #fff;
+  background: #F4F7FF;
 }
 
 .wrap {
   display: flex;
   flex-direction: column;
   width: 100%;
+
   .wrap_plate {
-    margin-top: 50px;
+    margin-top: 24px;
     margin-left: 40px;
     font-size: 30px;
+
+    &.mt36 {
+      margin-top: 36px;
+    }
+
+    .title {
+      // width: 180px;
+      // height: 50px;
+      font-size: 36px;
+      // font-family: PingFangHK-Semibold, PingFangHK;
+      font-weight: 600;
+      color: #333333;
+      line-height: 50px;
+      margin-bottom: 20px;
+    }
+    .desc {
+      font-size: 30px;
+      font-weight: 400;
+      color: #999999;
+      line-height: 45px;
+    }
   }
+
   .border-change {
     border: 4px solid #707070;
   }
+
   .plate_tag-icon {
     position: absolute;
     left: 0;
@@ -460,63 +449,78 @@ export default {
     opacity: 1;
     border-radius: 0px 12px 1px 0px;
   }
+
   .plate_tag_icon_green {
     background: #39b54a;
   }
+
   .plate_tag_icon_blue {
     background: #29abe2;
   }
+
   .plate_plate {
     width: 670px;
     margin-left: 40px;
     margin-top: 20px;
     padding: 4px;
     border-radius: 20px 128px 20px 20px;
+
     .plate_border {
       border-radius: 17px 125px 17px 17px;
       background-color: #fff;
+
       .plate_tag {
         display: inline-block;
         width: 23px;
         height: 14px;
         border-top-right-radius: 18px;
       }
+
       .bgc-0 {
         background-color: #29abe2;
       }
+
       .bgc-1 {
         background-color: #39b54a;
       }
+
       .bgc-2 {
         background-color: #bc9f6d;
       }
     }
+
     .plate_plate_index {
       padding-left: 37px;
       padding-top: 10px;
       font-size: 26px;
     }
+
     .plate_plate_index1,
     .plate_plate_index3 {
       color: #666;
     }
+
     .plate_plate_index1 {
       display: inline-block;
       padding-left: 14px;
     }
+
     .plate_plate_index2 {
       font-size: 50px;
       font-weight: 500;
     }
+
     .plate_plate_index4 {
       padding-bottom: 20px;
       font-size: 30px;
       display: flex;
       align-items: center;
       justify-content: space-between;
+
       .plate_plate_index4_index2 {
         width: 164px;
       }
+
       img {
         width: 32px;
         height: 32px;
@@ -525,29 +529,37 @@ export default {
       }
     }
   }
+
   .add_plate {
     width: 90%;
-    height: 140px;
+    height: 200px;
     text-align: center;
-    line-height: 140px;
-    border: 1px dashed #eaeaea;
+    line-height: 200px;
+    // border: 1px dashed #eaeaea;
+    border: 1px solid #D8DAE0;
     margin-left: 40px;
-    margin-top: 40px;
-    color: #898989;
+    margin-top: 20px;
+    color: #999999;
+    background-color: #FAFBFF;
   }
+
   .linear-gradient-ORDINARY_CAR_NO {
     background-image: linear-gradient(#29abe2, #2e3393);
   }
+
   .linear-gradient-NEW_ENERGY_CAR_NO {
     background-image: linear-gradient(#8bc63f, #026937);
   }
+
   .linear-gradient-SPECIAL_CAR_NO {
     background-image: linear-gradient(#caa86e, #666666);
   }
+
   .mrg-left-20 {
     margin-left: 20px;
   }
 }
+
 .popup-dialog {
   width: 300px;
   border-radius: 10px;

+ 9 - 8
src/routes/index.js

@@ -1,12 +1,13 @@
 import VueRouter from 'vue-router';
 import qs from 'qs';
-
+import Home from '@/pages/parkingFee/parkingFee.vue'
 const routes = [
-  { path: '/', component: () => import('@/pages/parkingFee/parkingFee.vue') },
+  { path: '/', name: '首页', component: Home },
+  { path: '/home', name: '首页', component: Home },
   {
     path: '/parkingFeePayment',
     component: () => import('@/pages/parkingFee/parkingFeePayment.vue'),
-  },  {
+  }, {
     path: '/parkingFeeDetail',
     component: () => import('@/pages/parkingFee/parkingFeeDetail.vue'),
   },
@@ -92,14 +93,14 @@ const router = new VueRouter({
 });
 
 router.beforeEach((to, from, next) => {
-  let pageId  = ''
-  if(window.location.href.indexOf('pageId') > 0) {
-    pageId = `${window.location.href}`.replace(/.*pageId=([0-9A-Z]*).*/g,'$1')
+  let pageId = ''
+  if (window.location.href.indexOf('pageId') > 0) {
+    pageId = `${window.location.href}`.replace(/.*pageId=([0-9A-Z]*).*/g, '$1')
   }
   setTimeout(() => {
-    if (pageId && (window.location.href.indexOf('pageId') < 0 || to.fullPath.indexOf('pageId') < 0 )) {
+    if (pageId && (window.location.href.indexOf('pageId') < 0 || to.fullPath.indexOf('pageId') < 0)) {
       let url = `${window.location.origin}/#${to.path}?${qs.stringify(
-        {...to.query, pageId}
+        { ...to.query, pageId }
       )}`;
       window.history.replaceState('', '', url);
     }

+ 1 - 1
src/store/index.js

@@ -95,7 +95,7 @@ const store = new Vuex.Store({
         });
         const marketListRes = await kipAllCities();
         if (memberRes.code === 0) {
-          // dispatch('getUserDetail')
+          dispatch('getUserDetail')
           // commit('SET_USER_INFO', memberRes.data);
           commit('SET_MEMBER', memberRes.data);
         }

+ 5 - 0
src/utils/api-crm-member.js

@@ -100,3 +100,8 @@ export function kipGetUserDetail (params) {
   const url = `/profileApi/profile/v1/customer/crm/current`;
   return request.get(url, params, {...DEFAULT_CONFIG});
 }
+
+export function crmSaveMemberSource (params) {
+	const url = `${BASE_URL}api/1.0/login/updateRegister`;
+	return request.post(url, params);
+}

+ 5 - 0
src/utils/api-kip.js

@@ -177,3 +177,8 @@ export function kipBrandCheck (params) {
 	return request.get(url, params, {...DEFAULT_CONFIG});
 }
 
+// 检查当前会员是否同意协议
+export function kipAgreementSave (params) {
+	const url = `/profile/v1/customer/agreemen/save`;
+	return request.post(url, params, {...DEFAULT_CONFIG});
+}

+ 72 - 27
src/utils/cache-tool.js

@@ -1,26 +1,32 @@
-import { ENV_LIST, APPID } from '@/constants.js'
+import {
+	ENV_LIST,
+	APPID,
+	LOGO_DEFAULT,
+	APPID_MAP,
+	LOGO_KO_DEFAULT,
+} from '@/constants.js'
 import uni from './uniHooks'
 export default {
-  init() {
-    const href = `${window.location.href}`
-    // dev
-    if(/8080|dev-crm-kpl/g.test(href)) {
-      this.setEnv('qa')
-      return
-    }
-    // qa
-    if(/qa-crm-kpl/g.test(href)) {
-      this.setEnv('qa')
-      return
-    }
-    // prod
-    this.setEnv('prod')
-  },
-	setEnv (env) {
-    console.log(2020202020, env)
+	init() {
+		const href = `${window.location.href}`
+		// dev
+		if (/8080|dev-crm-kpl/g.test(href)) {
+			this.setEnv('qa')
+			return
+		}
+		// qa
+		if (/qa-crm-kpl/g.test(href)) {
+			this.setEnv('qa')
+			return
+		}
+		// prod
+		this.setEnv('prod')
+	},
+	setEnv(env) {
+		console.log(2020202020, env)
 		uni.setStorageSync("env", env);
 	},
-	getEnv () {
+	getEnv() {
 		const env = uni.getStorageSync("env");
 		if (!env) {
 			const env = ENV_LIST[0];
@@ -29,23 +35,28 @@ export default {
 		}
 		return env;
 	},
-	cleanAllCache () {
+	cleanAllCache() {
 		uni.clearStorageSync()
 	},
-	getCurEnvConst (key) {
+	getCurEnvConst(key) {
 		const curEnvName = this.getEnv();
-    	console.log(373737, curEnvName)
-		const curEnvConst =  ENV_LIST.find( item => item.name == curEnvName);
-    	console.log('curEnvConst37', curEnvConst)
+		const curEnvConst = ENV_LIST.find(item => item.name == curEnvName);
 		// 如果是来自 window.injectConfig
-		
+		if (window?.injectConfig) {
+			console.log(464646, window?.injectConfig);
+			console.log(474747, key);
+			if (key === 'KIP_API') {
+				return window?.injectConfig?.profileApi
+			}
+			// return
+		}
 		if (key) {
 			return curEnvConst?.constants[key];
 		} else {
 			return curEnvConst?.constants;
 		}
 	},
-	setMiniAppOptions (options) {
+	setMiniAppOptions(options) {
 		if (!options) {
 			return;
 		}
@@ -56,7 +67,7 @@ export default {
 		}
 
 	},
-	setMiniAppOptionsQuery (query) {
+	setMiniAppOptionsQuery(query) {
 		if (!query || JSON.stringify(query) == '{}') {
 			// 直接进入的utm_lbs是空的
 			// const mallid = uni.getStorageSync("mallid")
@@ -72,4 +83,38 @@ export default {
 		query.channel = APPID;
 		uni.setStorageSync("options_query", query);
 	},
+	getLogoByMallid(mallid) {
+		const defaultLogo = isKerryOnAppid() ? LOGO_KO_DEFAULT : LOGO_DEFAULT
+		if (!mallid) {
+			console.error("=>[getLogoByMallid]mallid is null")
+			return defaultLogo
+		}
+		const marketList = this.getMarketList()
+		if (!marketList) {
+			console.error("=>[setMarketList]marketList is null")
+			return defaultLogo;
+		}
+		const market = marketList.find(item => item.mallid == mallid)
+		if (!market) {
+			console.error("=>[setMarketList]market is null")
+			return defaultLogo;
+		}
+		return market?.logoPicture || defaultLogo;
+	},
+	getMarketList() {
+		const marketList = uni.getStorageSync("marketList");
+		if (!marketList || marketList.length ===0) {
+			console.error("=>[getMarketList]marketList is empty")
+			return []
+		}
+		return marketList;
+	},
 }
+
+function isKerryOnAppid() {
+	if (APPID == APPID_MAP.kerryMall) {
+		return true;
+	} else {
+		return false;
+	}
+}

+ 46 - 0
src/utils/index.js

@@ -0,0 +1,46 @@
+export function getMobileOperatingSystem() {
+  // #ifdef H5
+  const userAgent = navigator.userAgent || navigator.vendor || window.opera;
+
+  // Windows Phone must come first because its UA also contains "Android"
+  if (/windows phone/i.test(userAgent)) {
+    return "Windows Phone";
+  }
+
+  if (/android/i.test(userAgent)) {
+    return "Android";
+  }
+
+  // iOS detection from: http://stackoverflow.com/a/9039885/177710
+  if (/iPad|iPhone|iPod/.test(userAgent) && !window.MSStream) {
+    return "iOS";
+  }
+
+  return "unknown";
+  // #endif
+
+  // #ifndef H5
+  return "unknown";
+  // #endif
+}
+
+
+export function getQueryParam() {
+  // let query: Record<string, string> = {};
+  let query = {};
+  query = location.search
+    .slice(1)
+    .split('&')
+    .map((p) => p.split('='))
+    // .reduce((obj: Record<string, string>, pair) => {
+    .reduce((obj, pair) => {
+      const [key, value] = pair.map(decodeURIComponent);
+      obj[key] = value;
+      return obj;
+    }, {});
+  return query;
+}
+
+export function isInWeixinH5() {
+  return navigator.userAgent.toLowerCase().indexOf("micromessenger") !== -1;
+}

+ 298 - 0
src/utils/login.js

@@ -0,0 +1,298 @@
+// import { ApiResponse, get, post } from './request';
+// import { get,post } from '@/utils/request-kip.js'
+import request from '@/utils/request-kip.js'
+const get = request.get
+const post = request.post
+import store from '@/store';
+import { getMobileOperatingSystem,getQueryParam,isInWeixinH5 } from '@/utils';
+// import { Token } from './config/tokenManager';
+
+const OAUTH_PREFIX = '/oauth/v1';
+
+/*
+ 手机号+验证码登录
+ params: {
+ phoneNumber: string;
+ jsCode?: string;
+ verifyCode: string;
+ }
+ */
+export function login() {
+  // request.post(url, params, {contentType: 'form', ...DEFAULT_CONFIG, noToken: true});
+  return request.post(`${ OAUTH_PREFIX }/auth/phone-login`,params,{isAuthRequest: true,isHandleError: false});
+}
+
+//
+/*
+ 手机号+验证码登录,微信公众号内H5页面用
+ params: {
+ phoneNumber: string;
+ authCode: string;
+ verifyCode: string;
+ }
+ : Promise<{ code: string, data: Token }>
+ */
+export function loginWeixinH5() {
+  return request.post(`${ OAUTH_PREFIX }/auth/subscription-phone-login`,params,{isAuthRequest: true,isHandleError: false});
+}
+
+/*
+ params: {
+ encryptedData: string;
+ iv: string;
+ jsCode: string;
+ }
+
+ : Promise<{ code: string, data: Token }>
+ */
+export function loginByWxOnClick() {
+  return request.post(`${ OAUTH_PREFIX }/auth/authorized-phone-login`,params,{isAuthRequest: true,isHandleError: false});
+}
+
+/*
+ jsCode: string
+ : Promise<{ code: string, data: Token }>
+ */
+export function getLoginTokenByWxCode( jsCode ) {
+  return request.post(`${ OAUTH_PREFIX }/auth/openid-login`,{jsCode,},{isAuthRequest: true,isHandleError: false});
+}
+
+/*
+ 微信公众号内H5页面用
+ authCode: string
+ : Promise<{ code: string, data: Token }>
+ */
+export function getLoginTokenByWxCodeH5( authCode ) {
+  return request.post(`${ OAUTH_PREFIX }/auth/subscription-code-login`,{authCode},{isAuthRequest: true,isHandleError: false});
+}
+
+/*
+ refresh_token: string
+
+ : Promise<ApiResponse<Token>>
+ */
+export function updateToken( refresh_token ) {
+  return request.post(`${ OAUTH_PREFIX }/oauth/renewToken`,{refreshToken: refresh_token},{isAuthRequest: true,isHandleError: false})
+}
+
+/*
+ TODO mp-weixin中logout需要解绑手机号和openid;app中logout需要吗?
+ : Promise<{ code: string, data: Token }>
+ */
+export function logout() {
+  let data = undefined;
+  // #ifdef MP-WEIXIN
+  data = {'removeBinding': 1};
+  // #endif
+  // #ifdef H5
+  if ( isInWeixinH5() ) {
+    data = {'removeBinding': 1};
+  }
+  // #endif
+  return post(`${ OAUTH_PREFIX }/auth/logout`,data,{isLogout: true});
+}
+
+// 微信公众号H5获取用户openId - 需要登录
+/*
+ 微信公众号H5获取用户openId - 需要登录
+ param: { code: string }
+
+ : Promise<{
+ code: string,
+ data: string
+ }>
+ */
+export function WxJsOpenId( param ) {
+  return request.post(`/oauth/v1/wx/config/openId`,param);
+}
+
+// H5获取微信签名信息Api - 需要登录
+
+/*
+ H5获取微信签名信息Api - 需要登录
+ param: { url: string }): Promise<{
+ code: string,
+ data: {
+ appId: string,
+ nonceStr: string,
+ signature: string,
+ timestamp: string,
+ url: string
+ }
+ }>
+ */
+function WxJsSdkSignature( param ) {
+  return request.post(`/oauth/v1/wx/config/signature`,param);
+}
+
+/*
+ jsApiList: string[], openTagList?: string[]
+
+
+ */
+export function initWxJsSdkConfig( jsApiList = [],openTagList = [] ) {
+  let url = location.href;
+  // https://developers.weixin.qq.com/community/develop/doc/000ae2cb950808f90d8bc415551800
+  if ( getMobileOperatingSystem() === 'iOS' && window.H5_LAUNCH_URL ) {
+    url = window.H5_LAUNCH_URL;
+  }
+  window.wxJsSdkConfigInitPromise = null;
+  window.wxJsSdkConfigInitPromise = WxJsSdkConfig(jsApiList,url,openTagList);
+}
+
+/*
+ weixin jssdk: 通过config接口注入权限验证配置
+ jsApiList: string[], url?: string, openTagList?: string[]
+ : Promise<{ errMsg: "wx.config:OK" }>
+ */
+async function WxJsSdkConfig( jsApiList = [],url = '',openTagList = [] ) {
+  const res = await WxJsSdkSignature({url: url ? url : location.href}); // 这个接口需要登录!
+  let debug = false;
+  try {
+    debug = uni.getStorageSync("WX_JSSDK_DEBUG");
+  } catch { }
+  return new Promise(( resolve,reject ) => {
+    wx.config({
+      debug,
+      appId: res.data.appId,
+      timestamp: res.data.timestamp,
+      nonceStr: res.data.nonceStr,
+      signature: res.data.signature,
+      jsApiList,
+      openTagList: openTagList ? openTagList : []
+    });
+    wx.ready(function () {
+      // 来自微信官方文档:
+      // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,
+      // 所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
+      // eslint-disable-next-line no-console
+      console.log('wx.ready');
+      resolve({errMsg: 'wx.config:OK'});
+    });
+    wx.error(function ( err ) {
+      // eslint-disable-next-line no-console
+      console.log(err);
+      reject(err);
+    });
+  });
+}
+
+// 将 wx.uploadImage 上传的图片转存到阿里云OSS
+// 后端调用的
+
+
+/*
+ param: { appId: string, mediaId: string }
+
+ : Promise<{
+ videoUrl: string
+ }>
+ */
+export function WxJsUploadMediaToOSS( param ) {
+  return request.get(`/oauth/v1/wx/config/wechat/h5/mediaUrl`,param);
+}
+
+/*
+ // 使用微信 jssdk 选择及上传图片
+ // https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html#17
+
+
+ count: number,
+ sizeType: ['original', 'compressed'] | ['compressed'] | ['original'],
+ sourceType: ['album', 'camera'] | ['album'] | ['album'],
+ loadingText?: string
+
+ : Promise<{ message: string, ossUrls: string[] }>
+ */
+export async function wxChooseImageAndUpload( count,sizeType,sourceType,loadingText ) {
+  return new Promise(( resolve,reject ) => {
+    wx.chooseImage({
+      count: count,
+      sizeType,
+      sourceType,
+      // : { localIds: string[] }
+      success: ( res ) => {
+        if ( loadingText ) {
+          setTimeout(() => {
+            uni.showLoading({
+              title: loadingText,
+            });
+          },100);
+        }
+        const localIds = res.localIds;
+        // eslint-disable-next-line no-console
+        console.log("----00---",res.localIds);
+        const serverIds = [];
+        const ossUrls = [];
+        let i = 0;
+        const length = localIds.length;
+        const upload = () => {
+          wx.uploadImage({
+            localId: localIds[i],
+            isShowProgressTips: 0,
+            // : { serverId : string}
+            success: async ( resUpload ) => {
+              serverIds.push(resUpload.serverId);
+              // eslint-disable-next-line no-console
+              console.log("----01---",serverIds.join(';'));
+              const resOssUpload = await WxJsUploadMediaToOSS({appId: store.state.appId,mediaId: resUpload.serverId});
+              ossUrls.unshift(resOssUpload.videoUrl);
+              // eslint-disable-next-line no-console
+              console.log("----02---",serverIds.join(';'),ossUrls);
+              //如果还有照片,继续上传
+              i++;
+              if ( i < length ) {
+                upload();
+              } else {
+                resolve({message: '',ossUrls: ossUrls});
+              }
+            },
+            fail: ( resFail ) => {
+              // eslint-disable-next-line no-console
+              console.log("----03---",resFail);
+              reject(resFail);
+            }
+          });
+        };
+        upload();
+      },
+      fail: ( resFail ) => {
+        // eslint-disable-next-line no-console
+        console.log("----04---",resFail);
+        reject(resFail);
+      }
+    });
+  });
+}
+
+// 微信H5 - 获取openId
+// TODO 临时方案,微信H5登录做好后要改
+export function getOpenIdInH5() {
+  // #ifdef H5
+  const OPENID_KEY = store.state.appId + '-openid';
+  const LANDING_PAGE = '/pages/weixin-h5/order';
+  const openId = uni.getStorageSync(OPENID_KEY);
+  if ( openId ) {
+    // eslint-disable-next-line no-console
+    console.log('openId in H5:',openId);
+    return;
+  }
+
+  const query = getQueryParam();
+  const fullPath = location.href.replace(location.origin,'');
+  if ( fullPath.indexOf(LANDING_PAGE) == 0 ) {
+    return;
+  }
+
+  const redirect_uri = location.origin + LANDING_PAGE
+    + "?appId=" + store.state.appId
+    + "&redirect_uri=" + encodeURIComponent(fullPath);
+  const state = 'abc123';
+
+  const url = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${ store.state.appId }` +
+    `&redirect_uri=${ encodeURIComponent(redirect_uri) }&response_type=code&scope=snsapi_userinfo` +
+    `&state=${ state }#wechat_redirect`;
+
+  location.href = url;
+  // #endif
+}

+ 171 - 174
src/utils/request-kip.js

@@ -1,196 +1,193 @@
-import { APPID, SOURCE_KEY } from '@/constants.js'
+import { APPID,SOURCE_KEY } from '@/constants.js'
 import CacheTool from '@/utils/cache-tool.js'
 import log from './log.js'
 import { getUTMSource } from '@/utils/utils.js'
 import uni from './uniHooks'
+
 const CONTENT_TYPE_ARRAY = {
-	'json': 'application/json',
-	'form': 'application/x-www-form-urlencoded'
+  'json': 'application/json',
+  'form': 'application/x-www-form-urlencoded'
 }
 
-function getHeaders (config = {}) {
-	const {contentType = 'json' } = config;
-	const ct = CONTENT_TYPE_ARRAY[contentType];
-    let header = {
-        'appId': APPID,
-		'Content-Type': ct
-    };
-	const token = getToken()
-	if (token) {
-		header['Authorization'] = `Bearer ${token}`;
-	}
+function getHeaders( config = {} ) {
+  const {contentType = 'json'} = config;
+  const ct = CONTENT_TYPE_ARRAY[contentType];
+  let header = {
+    'appId': APPID,
+    'Content-Type': ct
+  };
+  const token = getToken()
+  if ( token ) {
+    header['Authorization'] = `Bearer ${ token }`;
+  }
 
-	const groupId = uni.getStorageSync("groupId");
-	const mallId = uni.getStorageSync("mallid");
-	if (groupId) {
-		header['brandId'] = groupId
-	}
-	if (mallId) {
-		header['lbsId'] = mallId
-	}
-	const sourceObj = getUTMSource();
-	return Object.assign(header, sourceObj);
+  const groupId = uni.getStorageSync("groupId");
+  const mallId = uni.getStorageSync("mallid");
+  if ( groupId ) {
+    header['brandId'] = groupId
+  }
+  if ( mallId ) {
+    header['lbsId'] = mallId
+  }
+  const sourceObj = getUTMSource();
+  return Object.assign(header,sourceObj);
 }
 
-function handleConfig (config = {}) {
-	const header = getHeaders(config)
-	const noToken = config.noToken
-	if (noToken) {
-		delete header.Authorization;
-	}
-	return {header, ...config};
+function handleConfig( config = {} ) {
+  const header = getHeaders(config)
+  const noToken = config.noToken
+  if ( noToken ) {
+    delete header.Authorization;
+  }
+  return {header,...config};
 }
 
 function getToken() {
-	const token = uni.getStorageSync('kipAccessToken')
-	// if (!token || token?.trim() == '' || token == 'null' || token == 'undefined') {
-	if (!token || token == 'null' || token == 'undefined') {
-		return false;
-	}
-	return token
+  const token = uni.getStorageSync('kipAccessToken')
+  // if (!token || token?.trim() == '' || token == 'null' || token == 'undefined') {
+  if ( !token || token == 'null' || token == 'undefined' ) {
+    return false;
+  }
+  return token
 }
 
-function getUrl(url) {
-	if (url.indexOf('http') > -1 && url.indexOf('/profileApi') > -1) {
-		return url;
-	} else {
-		return CacheTool.getCurEnvConst('KIP_API') + url
-	}
+function getUrl( url ) {
+  if ( url.indexOf('http') > -1 && url.indexOf('/profileApi') > -1 ) {
+    return url;
+  } else {
+    return CacheTool.getCurEnvConst('KIP_API') + url
+  }
 }
 
-function cleanCacheAndGoLogin () {
-	// 删除token以及会员数据
-	uni.removeStorageSync('kipAccessToken');
-	uni.removeStorageSync('isNewUser');
-	uni.removeStorageSync('kipRefreshToken')
-	// 直接跳转到登录页面
-	uni.removeStorageSync('member')
-	uni.removeStorageSync('wxMember')
-	uni.removeStorageSync("openId");
-	uni.removeStorageSync("userInfo");
-	uni.reLaunch({
-		url: '/pages/automatic/automaticMy.vue'
-	})
+function cleanCacheAndGoLogin() {
+  // 删除token以及会员数据
+  uni.removeStorageSync('kipAccessToken');
+  uni.removeStorageSync('isNewUser');
+  uni.removeStorageSync('kipRefreshToken')
+  // 直接跳转到登录页面
+  uni.removeStorageSync('member')
+  uni.removeStorageSync('wxMember')
+  uni.removeStorageSync("openId");
+  uni.removeStorageSync("userInfo");
+  uni.reLaunch({
+    url: '/pages/automatic/automaticMy.vue'
+  })
 }
 
-function handleKipResponse(resp, request) {
-	if (resp && resp.data) {
-		const { statusCode, errMsg } = resp;
-		console.log(`kip request resp => ${errMsg} ${statusCode}`)
-		const { path } = request.detail;
-		let isLogout = false;
-		if (path.indexOf("/logout") > -1) {
-			isLogout = true;
-		}
-
-		if (!resp || !resp.data) {
-			return resp;
-		}
-		const result = resp.data;
-		if (result) {
-			const { message, code } = result || {}
-			console.log(`kip api resul => message: ${message} code: ${code}`)
-			if (result.code == '300000' && !isLogout) {
-				console.warn('===> kip的access_token已过期')
-				log.info(`kip的access_token已过期`, result)
-			}
-
-		}
-	}
-	return resp;
+function handleKipResponse( resp,request ) {
+  if ( resp && resp.data ) {
+    const {status} = resp;
+    console.log(`kip request resp => errMsg ${ status }`)
+    const {path} = request.detail;
+    let isLogout = false;
+    if ( path.indexOf("/logout") > -1 ) {
+      isLogout = true;
+    }
+    if ( !resp || !resp.data ) {
+      return resp;
+    }
+    const result = resp.data;
+    if ( result ) {
+      const {message,code} = result || {}
+      console.log(`kip api resul => message: ${ message } code: ${ code }`)
+      if ( result.code == '300000' && !isLogout ) {
+        console.warn('===> kip的access_token已过期')
+        log.info(`kip的access_token已过期`,result)
+      }
+    }
+  }
+  return resp.data;
 }
 
-const request = {
-	detail: null,
-	base(method, path, param = {}, config) {
-		const _this = this;
-		_this.detail = {
-			method,
-			path,
-			param,
-			config
-		}
-		return new Promise((resolve, reject) => {
-			const url = getUrl(path);
-			const { header } = handleConfig(config)
-			log.info(`===>request-kip url: ${url}`)
-			log.info(`===>request-kip header: ${JSON.stringify(header)}`)
-			uni.request({
-				header: header,
-				method: method,
-				url: url,
-				data: param,
-			}).then(res => {
-				log.info(`===>request-kip response: ${JSON.stringify(res[1])}`)
-				resolve(handleKipResponse(res[1], _this))
-				if(res[1].statusCode == 581){
-					uni.navigateTo({
-						url: '/pages/errorPage/errorLimit?msg=当前访问太火爆了,稍后试试吧~'
-					})
-				}
-			}).catch((response) => {
-				log.error(`===>request-kip error: ${JSON.stringify(response)}`)
-				reject(response)
-			})
-		})
-	},
-	get(path, param= {}, config) {
-		return this.base('GET', path, param, config)
-	},
-	post(path, param = {}, config) {
-		return this.base('POST', path, param, config)
-	},
-	put(path, param= {}, config) {
-		return this.base('PUT', path, param, config)
-	},
-	delete(path, param= {}, config) {
-		return this.base('DELETE', path, param, config)
-	},
-	uploadFile(path, param = {}, config) {
-		const _this = this;
-		_this.detail = {
-			method: 'POST',
-			path,
-			param,
-			config
-		}
-		return new Promise((resolve, reject) => {
-			const url = getUrl(path);
-			const { fileType, file, formData } = param
-			let header = getHeaders(config)
-			header["Content-Type"] = "multipart/form-data"
-			uni.uploadFile({
-				header: header,
-				method: 'POST',
-				url: url,
-				name: "file",
-				fileType: fileType,
-				filePath: file.path,
-				file: file,
-				formData: formData
-			}).then(res => {
-				resolve(handleKipResponse(res[1], _this))
-			}).catch((response) => {
-				reject(response)
-			})
-		})
-	},
-	refreshToken(path) {
-		return new Promise((resolve, reject) => {
-			const url = getUrl(path);
-			const header = getHeaders()
-			delete header.Authorization;
-			uni.request({
-				header: header,
-				method: 'POST',
-				url: url,
-			}).then(res => {
-				resolve(res[1])
-			}).catch((response) => {
-				reject(response)
-			})
-		})
-	}
+export default {
+  detail: null,
+  base( method,path,param = {},config ) {
+    const _this = this;
+    _this.detail = {
+      method,
+      path,
+      param,
+      config
+    }
+    return new Promise(( resolve,reject ) => {
+      const url = getUrl(path);
+      const {header} = handleConfig(config)
+      log.info(`===>request-kip url: ${ url }`)
+      log.info(`===>request-kip header: ${ JSON.stringify(header) }`)
+      uni.request({
+        header: header,
+        method: method,
+        url: url,
+        data: param,
+      }).then(res => {
+        log.info(`===>request-kip response: ${ JSON.stringify(res.data) }`)
+        resolve(handleKipResponse(res, _this))
+        if ( res.status == 581 ) {
+          uni.navigateTo({
+            url: '/pages/errorPage/errorLimit?msg=当前访问太火爆了,稍后试试吧~'
+          })
+        }
+      }).catch(( response ) => {
+        log.error(`===>request-kip error: ${ JSON.stringify(response) }`)
+        reject(response)
+      })
+    })
+  },
+  get( path,param = {},config ) {
+    return this.base('GET',path,param,config)
+  },
+  post( path,param = {},config ) {
+    return this.base('POST',path,param,config)
+  },
+  put( path,param = {},config ) {
+    return this.base('PUT',path,param,config)
+  },
+  delete( path,param = {},config ) {
+    return this.base('DELETE',path,param,config)
+  },
+  uploadFile( path,param = {},config ) {
+    const _this = this;
+    _this.detail = {
+      method: 'POST',
+      path,
+      param,
+      config
+    }
+    return new Promise(( resolve,reject ) => {
+      const url = getUrl(path);
+      const {fileType,file,formData} = param
+      let header = getHeaders(config)
+      header["Content-Type"] = "multipart/form-data"
+      uni.uploadFile({
+        header: header,
+        method: 'POST',
+        url: url,
+        name: "file",
+        fileType: fileType,
+        filePath: file.path,
+        file: file,
+        formData: formData
+      }).then(res => {
+        resolve(handleKipResponse(res[1],_this))
+      }).catch(( response ) => {
+        reject(response)
+      })
+    })
+  },
+  refreshToken( path ) {
+    return new Promise(( resolve,reject ) => {
+      const url = getUrl(path);
+      const header = getHeaders()
+      delete header.Authorization;
+      uni.request({
+        header: header,
+        method: 'POST',
+        url: url,
+      }).then(res => {
+        resolve(res[1])
+      }).catch(( response ) => {
+        reject(response)
+      })
+    })
+  }
 }
-
-export default request

+ 10 - 2
src/utils/uniHooks.js

@@ -98,6 +98,7 @@ function request({ url, data, method, header, success, fail }) {
   if (success) {
     axios(params)
       .then((res) => {
+        console.log(101, res);
         if (_.isFunction(success)) {
           success(res);
           return;
@@ -113,7 +114,7 @@ function request({ url, data, method, header, success, fail }) {
       });
     return;
   }
-  // console.log(7272727272, params);
+  console.log(7272727272, params);
   return axios(params);
 }
 
@@ -133,6 +134,12 @@ function requestPayment(options) {
   );
 }
 
+function getSystemInfoSync () {
+  return {
+    screenWidth: window.document.documentElement.offsetWidth
+  }
+}
+
 export default {
   getStorageSync,
   setStorageSync,
@@ -145,5 +152,6 @@ export default {
   login,
   request,
   requestPayment,
-  setNavigationBarTitle
+  setNavigationBarTitle,
+  getSystemInfoSync
 };

+ 10 - 1
yarn.lock

@@ -8028,7 +8028,7 @@ postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.2, postcss-value-parser@^
   resolved "https://nexus-internal.kerryonvip.com/repository/kerry-npm-group/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
   integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
 
-postcss@>=5.0.2, postcss@^8.4.14, postcss@^8.4.16:
+postcss@>=5.0.2, postcss@^8.4.14:
   version "8.4.17"
   resolved "https://nexus-internal.kerryonvip.com/repository/kerry-npm-group/postcss/-/postcss-8.4.17.tgz#f87863ec7cd353f81f7ab2dec5d67d861bbb1be5"
   integrity sha512-UNxNOLQydcOFi41yHNMcKRZ39NeXlr8AxGuZJsdub8vIb12fHzcq37DTU/QtbI6WLxNg2gF9Z+8qtRwTj1UI1Q==
@@ -8054,6 +8054,15 @@ postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.27, postcss@^7.0.3
     picocolors "^0.2.1"
     source-map "^0.6.1"
 
+postcss@^8.4.18:
+  version "8.4.18"
+  resolved "https://nexus-internal.kerryonvip.com/repository/kerry-npm-group/postcss/-/postcss-8.4.18.tgz#6d50046ea7d3d66a85e0e782074e7203bc7fbca2"
+  integrity sha512-Wi8mWhncLJm11GATDaQKobXSNEYGUHeQLiQqDFG1qQ5UTDPTEvKw0Xt5NsTpktGTwLps3ByrWsBrG0rB8YQ9oA==
+  dependencies:
+    nanoid "^3.3.4"
+    picocolors "^1.0.0"
+    source-map-js "^1.0.2"
+
 prelude-ls@~1.1.2:
   version "1.1.2"
   resolved "https://nexus-internal.kerryonvip.com/repository/kerry-npm-group/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"