Selaa lähdekoodia

Merge branch 'master' of http://git.ycjcjy.com/dianyang/colmo-h5

李志伟 3 vuotta sitten
vanhempi
commit
b51752dfde

+ 1
- 0
.npmrc Näytä tiedosto

@@ -0,0 +1 @@
1
+registry=https://registry.npmmirror.com

+ 0
- 16
index.html Näytä tiedosto

@@ -1,16 +0,0 @@
1
-<!DOCTYPE html>
2
-<html>
3
-
4
-<head>
5
-  <meta charset="utf-8">
6
-  <meta name="viewport" content="width=device-width,initial-scale=1.0">
7
-  <title>cpmloh5</title>
8
-
9
-</head>
10
-
11
-<body>
12
-  <div id="app"></div>
13
-  <!-- built files will be auto injected -->
14
-</body>
15
-
16
-</html>

+ 11873
- 0
package-lock.json
File diff suppressed because it is too large
Näytä tiedosto


+ 3
- 1
package.json Näytä tiedosto

@@ -10,11 +10,13 @@
10 10
     "lint": "vue-cli-service lint"
11 11
   },
12 12
   "dependencies": {
13
+    "axios": "^0.26.0",
13 14
     "core-js": "^3.6.5",
14 15
     "swiper": "6.8.4",
15 16
     "vant": "^2.12.44",
16 17
     "vue": "^2.6.11",
17
-    "vue-router": "^3.0.1"
18
+    "vue-router": "^3.0.1",
19
+    "vuex": "^3.6.2"
18 20
   },
19 21
   "devDependencies": {
20 22
     "@vue/cli-plugin-babel": "~4.5.0",

BIN
public/images/Loading.png Näytä tiedosto


BIN
public/images/share.png Näytä tiedosto


+ 61
- 0
public/index.html Näytä tiedosto

@@ -0,0 +1,61 @@
1
+<!DOCTYPE html>
2
+<html>
3
+
4
+<head>
5
+  <meta charset="utf-8">
6
+  <meta name="viewport" content="width=device-width,initial-scale=1.0">
7
+  <title>干洗护理 诠释新生</title>
8
+  <style>
9
+    .page-loading-wrapper {
10
+      position: absolute;
11
+      left: 0;
12
+      top: 0;
13
+      width: 100vw;
14
+      height: 100vh;
15
+      overflow: hidden;
16
+      z-index: 99999;
17
+      /* background: url(./images/loadingBgc.jpg) no-repeat 100% 100%; */
18
+      display: flex;
19
+      /* display: none; */
20
+      justify-content: center;
21
+      align-items: center;
22
+    }
23
+
24
+    .page-loading {
25
+      width: 100vw;
26
+      /* height: 100vw; */
27
+    }
28
+
29
+    .page-loading .loading-image {
30
+      width: 15vw;
31
+      height: 15vw;
32
+      animation: loadingrotate 1.5s linear infinite;
33
+      margin: auto;
34
+    }
35
+
36
+    .page-loading .loading-tips {
37
+      width: 100%;
38
+      margin-top: 2em;
39
+    }
40
+
41
+    @keyframes loadingrotate {
42
+      100% {
43
+        transform: rotate(360deg);
44
+      }
45
+    }
46
+  </style>
47
+</head>
48
+
49
+<body>
50
+  <div class="page-loading-wrapper">
51
+    <div class="page-loading">
52
+      <div class="loading-image">
53
+        <img src="./images/Loading.png" width="100%" alt="">
54
+      </div>
55
+    </div>
56
+  </div>
57
+  <div id="app"></div>
58
+  <!-- built files will be auto injected -->
59
+</body>
60
+
61
+</html>

+ 10
- 0
public/js/vconsole.min.js
File diff suppressed because it is too large
Näytä tiedosto


+ 4
- 2
src/App.vue Näytä tiedosto

@@ -11,9 +11,11 @@ export default {
11 11
 </script>
12 12
 
13 13
 <style>
14
-html, body, #app {
14
+html,
15
+body,
16
+#app {
15 17
   margin: 0;
16 18
   height: 100%;
17
-  background: linear-gradient(to left, rgb(14, 14, 14), rgb(6, 6, 6));
19
+  /* background: linear-gradient(to left, rgb(14, 14, 14), rgb(6, 6, 6)); */
18 20
 }
19 21
 </style>

+ 33
- 18
src/components/AreaPicker/index.vue Näytä tiedosto

@@ -1,6 +1,13 @@
1 1
 <template>
2 2
   <van-popup v-model="visible" position="bottom">
3
-    <van-area title="地区" v-model="value" :area-list="areaList" :loading="loading" @cancel='handleCancel' @confirm="handleConfirm" />
3
+    <van-area
4
+      title="地区"
5
+      v-model="value"
6
+      :area-list="areaList"
7
+      :loading="loading"
8
+      @cancel="handleCancel"
9
+      @confirm="handleConfirm"
10
+    />
4 11
   </van-popup>
5 12
 </template>
6 13
 
@@ -27,24 +34,27 @@ export default {
27 34
       }
28 35
     },
29 36
     areaList() {
30
-      return this.list.reduce((acc, x) => {
31
-        const { province_list, city_list, county_list } = acc
37
+      return this.list.reduce(
38
+        (acc, x) => {
39
+          const { province_list, city_list, county_list } = acc
32 40
 
33
-        province_list[x.adcode] = x.name
34
-        x.districts.forEach(y => {
35
-          city_list[y.adcode] = y.name
41
+          province_list[x.adcode] = x.name
42
+          x.districts.forEach((y) => {
43
+            city_list[y.adcode] = y.name
36 44
 
37
-          y.districts.forEach(z => {
38
-            county_list[z.adcode] = z.name
45
+            y.districts.forEach((z) => {
46
+              county_list[z.adcode] = z.name
47
+            })
39 48
           })
40
-        })
41 49
 
42
-        return { province_list, city_list, county_list }
43
-      }, {
50
+          return { province_list, city_list, county_list }
51
+        },
52
+        {
44 53
           province_list: {},
45 54
           city_list: {},
46 55
           county_list: {}
47
-        })
56
+        }
57
+      )
48 58
     }
49 59
   },
50 60
   mounted() {
@@ -64,14 +74,19 @@ export default {
64 74
       this.loading = true
65 75
 
66 76
       // 如果不存在
67
-      fetch('https://restapi.amap.com/v3/config/district?keywords=中国&subdistrict=3&key=194d2c8d01a9084e3b0bbb62d2d5fad0').then(res => res.json()).then(res => {
68
-        this.list = res.districts[0].districts
69
-        localStorage.setItem('area', this.list)
70
-        this.loading = false
71
-      })
77
+      fetch(
78
+        'https://restapi.amap.com/v3/config/district?keywords=中国&subdistrict=3&key=194d2c8d01a9084e3b0bbb62d2d5fad0'
79
+      )
80
+        .then((res) => res.json())
81
+        .then((res) => {
82
+          console.log('🚀 ~ file: index.vue ~ line 84 ~ .then ~ res', res)
83
+          this.list = res.districts[0].districts
84
+          localStorage.setItem('area', this.list)
85
+          this.loading = false
86
+        })
72 87
     },
73 88
     handleCancel() {
74
-      this.$emit('cancel',true)
89
+      this.$emit('cancel', true)
75 90
     }
76 91
   }
77 92
 }

+ 18
- 5
src/main.js Näytä tiedosto

@@ -4,7 +4,8 @@ import Vue from 'vue'
4 4
 import App from './App'
5 5
 import 'regenerator-runtime/runtime'
6 6
 import 'swiper/swiper-bundle.css'
7
-
7
+import { Login, redirect } from './utils/initial'
8
+import store from './store';//状态管理
8 9
 
9 10
 import router from './router'
10 11
 import Swiper from './components/Swiper'
@@ -19,8 +20,20 @@ Vue.config.productionTip = false
19 20
 Vue.component('swiper', Swiper)
20 21
 Vue.component('swiper-slide', SwiperSlide)
21 22
 /* eslint-disable no-new */
22
-new Vue({
23
-  router,
24
-  render: h => h(App),
25
-}).$mount('#app')
23
+redirect()
24
+
25
+
26
+Login().then(e => {
27
+
28
+
29
+  new Vue({
30
+    router,
31
+    store,
32
+    render: h => h(App),
33
+  }).$mount('#app')
34
+
35
+
36
+})
37
+
38
+
26 39
 

+ 1
- 1
src/pages/Test.vue Näytä tiedosto

@@ -76,7 +76,7 @@ export default {
76 76
       display: flex;
77 77
       align-items: center;
78 78
       margin: 0 auto;
79
-      height: 33vh;
79
+      height: 44vh;
80 80
       z-index: 2;
81 81
     }
82 82
     &-middle {

+ 61
- 5
src/pages/signup.vue Näytä tiedosto

@@ -32,8 +32,25 @@
32 32
           type="text"
33 33
           placeholder="请选择"
34 34
           v-model="formData.intendedProduct"
35
+          @click="showPicker=true"
35 36
         />
37
+
38
+        <van-popup
39
+          ref="accountTypePopup"
40
+          :lazy-render="false"
41
+          v-model="showPicker"
42
+          position="bottom"
43
+        >
44
+          <van-picker
45
+            title="意向产品"
46
+            show-toolbar
47
+            :columns="productList"
48
+            @confirm="onConfirm"
49
+            @cancel="onCancel"
50
+          />
51
+        </van-popup>
36 52
       </div>
53
+
37 54
       <div class="formItem addressdiv" @click="showArea = true">
38 55
         <label>所在地区</label>
39 56
         <input class="address" type="text" placeholder="请选择" v-model="address" />
@@ -55,6 +72,7 @@
55 72
 <script>
56 73
 
57 74
 import { register } from '../api/register'
75
+import { setRegister, getCity } from '../utils/api'
58 76
 export default {
59 77
   components: {
60 78
     AreaPicker: () => import('@/components/AreaPicker')
@@ -66,6 +84,7 @@ export default {
66 84
       checked: `./images/signup/checked.png`,
67 85
       Unchecked: `./images/signup/Unchecked.png`,
68 86
       ischecked: true,
87
+      showPicker: false,
69 88
       formData: {
70 89
         role: 'user',
71 90
         userName: undefined,
@@ -78,13 +97,23 @@ export default {
78 97
       address: undefined
79 98
     }
80 99
   },
100
+
101
+  mounted() {
102
+    this.getCity()
103
+  },
81 104
   methods: {
82 105
     onConfirm(value, index) {
83
-      this.formData.intendedProduct=value
106
+      this.formData.intendedProduct = value
84 107
       this.onCancel()
85 108
     },
109
+
86 110
     onCancel() {
87
-      this.visible = false
111
+      this.showPicker = false
112
+    },
113
+    getCity() {
114
+      getCity().then((e) => {
115
+        console.log(e)
116
+      })
88 117
     },
89 118
     handleUser() {
90 119
       this.ischecked = true
@@ -97,7 +126,10 @@ export default {
97 126
     handleArea(val) {
98 127
       this.showArea = false
99 128
       this.formData.address = val
100
-      this.address = this.formData.address[0].name+this.formData.address[1].name+this.formData.address[2].name
129
+      this.address =
130
+        this.formData.address[0].name +
131
+        this.formData.address[1].name +
132
+        this.formData.address[2].name
101 133
     },
102 134
     verification() {
103 135
       if (!this.formData.userName) {
@@ -119,9 +151,33 @@ export default {
119 151
     },
120 152
     sumbit() {
121 153
       if (this.verification()) {
122
-        register(this.formData).then(() => {
123
-          this.$router.push('/resultPage')
154
+        // register(this.formData).then(() => {
155
+        //   this.$router.push('/resultPage')
156
+        // })
157
+        const { userName, phone, intendedProduct, address, role } =
158
+          this.formData
159
+        let arrNew = address.map((item) => {
160
+          return {
161
+            areaCode: item.code,
162
+            areaName: item.name
163
+          }
164
+        })
165
+        // const obj = JSON.stringify(arrNew)
166
+        console.log(
167
+          '🚀 ~ file: signup.vue ~ line 148 ~ sumbit ~ obj',
168
+          this.formData
169
+        )
170
+        setRegister({
171
+          areaCode: arrNew[2].areaCode,
172
+          areaName: arrNew[2].areaName,
173
+          name: userName,
174
+          personType: role,
175
+          phone: phone,
176
+          interestTo: intendedProduct
177
+        }).then((e) => {
178
+          console.log(e)
124 179
         })
180
+        this.$router.replace('/resultPage')
125 181
       }
126 182
     }
127 183
   }

+ 2
- 0
src/router/index.js Näytä tiedosto

@@ -9,6 +9,8 @@ import Result from '@/pages/resultPage'
9 9
 Vue.use(Router)
10 10
 
11 11
 export default new Router({
12
+  mode: "history",
13
+
12 14
   routes: [
13 15
     {
14 16
       path: '/',

+ 57
- 0
src/store/index.js Näytä tiedosto

@@ -0,0 +1,57 @@
1
+import Vue from 'vue'
2
+import Vuex from 'vuex'
3
+// import user from './modules/user.js'
4
+
5
+
6
+Vue.use(Vuex)
7
+const store = new Vuex.Store({
8
+
9
+  // state 中存放的就是全局共享的数据
10
+  state: {
11
+    user: {
12
+      token: '',
13
+      code: '123',
14
+      name: '用户',
15
+      phone: '',
16
+      personId: '',
17
+    }
18
+  },
19
+
20
+
21
+  // Mutation 用户变更Store数据
22
+  mutations: {
23
+    SET_USER_INFO (state, value) {
24
+      state.user = {
25
+        ...state.user,
26
+        ...value
27
+      }
28
+      console.log('SET_USER_INFO被修改为:', state.user);
29
+    },
30
+
31
+
32
+  },
33
+  //Getter用于对Store中的数据进行加工处理,形成新的数据
34
+  getters: {
35
+    completedUserInfo (state) {
36
+      return state.user
37
+    }
38
+
39
+
40
+  },
41
+  //Action 是专门用于处理异步任务的
42
+  actions: {
43
+    getUserInfo ({ dispatch, commit }, value) {
44
+      console.log('actions---vaule', value);
45
+      //处理异步还得调用mutations里面的方法修改数据 mutations 不能处理异步
46
+      commit('SET_USER_INFO', value)
47
+      dispatch('SET_USER_INFO', value)
48
+    }
49
+  }
50
+
51
+
52
+});
53
+
54
+export default store;
55
+
56
+
57
+

+ 35
- 0
src/store/modules/user.js Näytä tiedosto

@@ -0,0 +1,35 @@
1
+
2
+// const state = {
3
+//   user: {
4
+//     appid: '1234',
5
+//     personId: '',
6
+//     phone: ''
7
+//   }
8
+// };
9
+
10
+// const mutations = {
11
+//   SET_USER_INFO (state, value) {
12
+//     state.userInfo = value;
13
+//   }
14
+// }
15
+
16
+// const getters = {
17
+//   conpletedUserInfo (state) {
18
+//     return state.userInfo;
19
+//   }
20
+// }
21
+
22
+// const actions = {
23
+//   getUserInfo ({ commit }, value) {
24
+//     commit('SET_USER_INFO', value)
25
+//   }
26
+// };
27
+// export default {
28
+//   state,
29
+//   mutations,
30
+//   getters,
31
+//   actions
32
+// }
33
+
34
+
35
+

+ 34
- 0
src/utils/api.js Näytä tiedosto

@@ -0,0 +1,34 @@
1
+import request from "./request";
2
+
3
+
4
+
5
+/**
6
+ * @login
7
+ *
8
+ */
9
+//  
10
+export const LoginUser = (params, data,) => request(`/api/wx/login?code=${params}`, { method: 'post' })
11
+
12
+
13
+/**
14
+ * @setRegister
15
+ *
16
+ */
17
+//  
18
+export const setRegister = (data,) => request(`/api/wx/register`, { method: 'post', data, })
19
+
20
+/**
21
+ * @setRegister
22
+ *
23
+ */
24
+// 
25
+export const getCity = (params, data,) => request(`/api/wx/city`, { method: 'get', data, })
26
+
27
+
28
+/**
29
+ * @PV浏览次数
30
+ *
31
+ */
32
+// 
33
+export const pv = (data,) => request(`/api/wx/pv`, { method: 'POST', data, })
34
+

+ 123
- 0
src/utils/initial.js Näytä tiedosto

@@ -0,0 +1,123 @@
1
+
2
+
3
+
4
+
5
+import { LoginUser, pv } from './api'
6
+
7
+import store from '../store'
8
+
9
+
10
+const jsApiList = [
11
+  'updateAppMessageShareData',
12
+  'updateTimelineShareData',
13
+  'onMenuShareTimeline',
14
+  'onMenuShareAppMessage',
15
+  'onMenuShareQQ',
16
+  'onMenuShareWeibo',
17
+  'onMenuShareQZone'
18
+]
19
+
20
+function initSDK (url) {
21
+  request(`https://api.h5.njyunzhi.com/mp/jssdk?url=${encodeURIComponent(url)}`).then((res) => {
22
+    window.wx.config({
23
+      debug: process.env.NODE_ENV === 'development', // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
24
+      appId: res.appId, // 必填,公众号的唯一标识
25
+      timestamp: res.timestamp, // 必填,生成签名的时间戳
26
+      nonceStr: res.nonceStr, // 必填,生成签名的随机串
27
+      signature: res.signature, // 必填,签名
28
+      jsApiList // 必填,需要使用的JS接口列表
29
+    })
30
+  })
31
+}
32
+// Vue.use(Vuex)
33
+
34
+/**
35
+ * 分享
36
+ * @param {*} opt
37
+ */
38
+export function share (opt) {
39
+  const { origin, pathname, search } = window.location
40
+  // const defaultLink = origin + pathname
41
+  const defaultImg = `${origin}${pathname}images/share.png`
42
+
43
+  const link = origin + pathname + search // opt.link || defaultLink
44
+  const imgUrl = opt.imgUrl || defaultImg
45
+
46
+  initSDK(link)
47
+  window.wx.ready(function () {
48
+    jsApiList.map((apiName) => {
49
+      const fn = window.wx[apiName]
50
+      if (typeof fn === 'function') {
51
+        fn({
52
+          title: opt.title || '开启干洗护理新时代', // 分享标题
53
+          link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
54
+          imgUrl, // 分享图标
55
+          desc: opt.desc || '即刻尊享'
56
+        })
57
+      }
58
+    })
59
+  })
60
+}
61
+
62
+
63
+
64
+
65
+
66
+
67
+export function Login () {
68
+  console.log(store);
69
+
70
+  return LoginUser('123',).then(e => {
71
+    // PVsum
72
+    console.log(e);
73
+    let userInfo = {
74
+      token: e.token,
75
+      name: e.person.name,
76
+      phone: e.person.phone,
77
+      personId: e.person.personId,
78
+    }
79
+    store.commit('SET_USER_INFO', userInfo)
80
+    let location = window.location.href
81
+
82
+    pv({ addr: location })
83
+
84
+
85
+    hideLoading()
86
+
87
+    return;
88
+  })
89
+
90
+}
91
+
92
+function hideLoading () {
93
+  document.getElementsByClassName('page-loading-wrapper')[0].style = "display: none"
94
+
95
+}
96
+
97
+/**
98
+ * 获取 code
99
+ * @returns 
100
+ */
101
+function getCode () {
102
+  const matched = /[?&]*code=([^&]+)/.exec(location.search)
103
+  if (matched) {
104
+    return decodeURIComponent(matched[1])
105
+  }
106
+}
107
+/**
108
+ * 跳转授权页面
109
+ */
110
+export function redirect (force) {
111
+  if (process.env.NODE_ENV === 'development') return;
112
+
113
+  const originCode = localStorage.getItem('wxcode');
114
+  const queryCode = getCode();
115
+  localStorage.setItem('wxcode', queryCode)
116
+
117
+  if (force || !queryCode || queryCode === originCode) {
118
+
119
+    const local = encodeURIComponent(location.origin + location.pathname)
120
+    const url = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxd3bab568bc42d1de&redirect_uri=${local}&response_type=code&scope=snsapi_userinfo&state=123#wechat_redirect`
121
+    window.location.href = url;
122
+  }
123
+}

+ 52
- 10
src/utils/request.js Näytä tiedosto

@@ -1,18 +1,60 @@
1 1
 
2
-export default function request (url, options = {}) {
3
-  const headers = new Headers();
4
-  headers.append('Content-Type', 'application/json;charset=utf8');
2
+// // import { getToken } from './token'
5 3
 
6
-  Object.keys(options.headers || {}).forEach(key => headers.append(key, options.headers[key]))
4
+// export default function request (url, options = {}) {
5
+//   const headers = new Headers();
6
+//   headers.append('Content-Type', 'application/json;charset=utf8');
7
+//   // headers.append('X-Authorization-JWT', getToken());
7 8
 
8
-  return fetch(url, { ...options, headers, credentials: 'include', mode: 'cors' })
9
-    .then(response => response.json())
10
-    .then(data => {
11
-      if (data.code === 1000) return data.data
12
-      return Promise.reject(data)
9
+//   Object.keys(options.headers || {}).forEach(key => headers.append(key, options.headers[key]))
10
+
11
+//   return fetch(url, { ...options, headers, credentials: 'include', mode: 'cors' })
12
+//     .then(response => response.json())
13
+//     .then(data => {
14
+//       if (data.code === 1000) return data.data
15
+//       return Promise.reject(data)
16
+//     })
17
+// }
18
+
19
+
20
+import axios from 'axios'
21
+import store from '../store'
22
+
23
+export const domain = process.env.NODE_ENV === 'development' ? '' : 'http://colmo-service.dianyang.njyunzhi.com'
24
+
25
+export default function (url, options) {
26
+  const { params, header, ...leftOptions } = options || {}
27
+
28
+  return new Promise((resolve, reject) => {
29
+    const { code, token } = store.state.user
30
+    let header = {
31
+      'X-Authorization-JWT': token,
32
+    }
33
+    axios.request({
34
+      ...leftOptions,
35
+      url: `${domain}${url}`,
36
+      // header: header,
37
+      headers: header,
38
+    }).then(res => {
39
+      const { code, data, message } = res.data
40
+      if (code === 1000) {
41
+        resolve(data)
42
+      }
43
+    }).catch(err => {
44
+      const message = err.message || err.errMsg || err
45
+      console.error("🚀 错误~ err", err)
46
+
47
+
48
+      if (err.message.includes('timeout')) {
49
+        // 请求超时
50
+        // Message.error('请求超时')
51
+      }
52
+      reject(message)
53
+    }).finally(() => {
54
+      // 请求结束
13 55
     })
56
+  })
14 57
 }
15 58
 
16 59
 export const domain = process.env.NODE_ENV === 'development' ? '' : 'http://colmo-service.dianyang.njyunzhi.com'
17 60
 
18
-export const baseURL = `${domain}/api/wx`

+ 1
- 1
vue.config.js Näytä tiedosto

@@ -8,7 +8,7 @@ module.exports = {
8 8
   devServer: {
9 9
     proxy: {
10 10
       '/api': {
11
-        target: "http://192.168.89.147:8081",
11
+        target: "http://192.168.89.147:8081/",
12 12
         // ws: true,
13 13
         changeOrigin: true,
14 14
         // pathRewrite: {

+ 17
- 0
yarn.lock Näytä tiedosto

@@ -1895,6 +1895,13 @@ aws4@^1.8.0:
1895 1895
   resolved "https://registry.npmmirror.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
1896 1896
   integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
1897 1897
 
1898
+axios@^0.26.0:
1899
+  version "0.26.0"
1900
+  resolved "https://registry.npmmirror.com/axios/-/axios-0.26.0.tgz#9a318f1c69ec108f8cd5f3c3d390366635e13928"
1901
+  integrity sha512-lKoGLMYtHvFrPVt3r+RBMp9nh34N0M8zEfCWqdWZx6phynIEhQqAdydpyBAAG211zlhX9Rgu08cOamy6XjE5Og==
1902
+  dependencies:
1903
+    follow-redirects "^1.14.8"
1904
+
1898 1905
 babel-eslint@^10.1.0:
1899 1906
   version "10.1.0"
1900 1907
   resolved "https://registry.npmmirror.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232"
@@ -3996,6 +4003,11 @@ follow-redirects@^1.0.0:
3996 4003
   resolved "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.14.8.tgz#016996fb9a11a100566398b1c6839337d7bfa8fc"
3997 4004
   integrity sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==
3998 4005
 
4006
+follow-redirects@^1.14.8:
4007
+  version "1.14.9"
4008
+  resolved "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.14.9.tgz#dd4ea157de7bfaf9ea9b3fbd85aa16951f78d8d7"
4009
+  integrity sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==
4010
+
3999 4011
 for-in@^1.0.2:
4000 4012
   version "1.0.2"
4001 4013
   resolved "https://registry.npmmirror.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
@@ -8349,6 +8361,11 @@ vue@^2.6.11:
8349 8361
   resolved "https://registry.npmmirror.com/vue/-/vue-2.6.14.tgz#e51aa5250250d569a3fbad3a8a5a687d6036e235"
8350 8362
   integrity sha512-x2284lgYvjOMj3Za7kqzRcUSxBboHqtgRE2zlos1qWaOye5yUmHn42LB1250NJBLRwEcdrB0JRwyPTEPhfQjiQ==
8351 8363
 
8364
+vuex@^3.6.2:
8365
+  version "3.6.2"
8366
+  resolved "https://registry.npmmirror.com/vuex/-/vuex-3.6.2.tgz#236bc086a870c3ae79946f107f16de59d5895e71"
8367
+  integrity sha512-ETW44IqCgBpVomy520DT5jf8n0zoCac+sxWnn+hMe/CzaSejb/eVw2YToiXYX+Ex/AuHHia28vWTq4goAexFbw==
8368
+
8352 8369
 watchpack-chokidar2@^2.0.1:
8353 8370
   version "2.0.1"
8354 8371
   resolved "https://registry.npmmirror.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz#38500072ee6ece66f3769936950ea1771be1c957"