wangwei 4 vuotta sitten
vanhempi
commit
6b0b4cf3c4

+ 3 - 3
package-lock.json

@@ -6998,9 +6998,9 @@
       }
     },
     "js-cookie": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.0.tgz",
-      "integrity": "sha512-oUbbplKuH07/XX2YD2+Q+GMiPpnVXaRz8npE7suhBH9QEkJe2W7mQ6rwuMXHue3fpfcftQwzgyvGzIHyfCSngQ=="
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz",
+      "integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ=="
     },
     "js-tokens": {
       "version": "4.0.0",

+ 1 - 1
package.json

@@ -15,7 +15,7 @@
   "dependencies": {
     "axios": "^0.21.1",
     "element-ui": "^2.15.3",
-    "js-cookie": "^3.0.0",
+    "js-cookie": "^2.2.1",
     "localforage": "^1.9.0",
     "socket.io-client": "^4.1.3",
     "socketio-file-upload": "^0.7.3",

+ 89 - 0
src/api/http.js

@@ -1,6 +1,8 @@
 // 导入axios
 import axios from 'axios';
 import cookie from 'js-cookie';
+import store from '@/store'
+import Vue from 'vue'
 
 
 // 进行一些全局配置
@@ -13,6 +15,93 @@ axios.defaults.timeout = 5000;
 // 设置请求头
 // axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
 
+// 设置请求超时
+axios.defaults.timeout = 5000 //设置超时时间为5s```
+
+// 设置post请求方式请求头
+// axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
+// 请求拦截器
+axios.interceptors.request.use(    
+  config => {     
+    console.log(`请求拦截器=====`)   
+    // 每次发送请求之前判断vuex中是否存在token        
+    // 如果存在,则统一在http请求的header都加上token,这样后台根据token判断你的登录情况
+    // 即使本地存在token,也有可能token是过期的,所以在响应拦截器中要对返回状态进行判断 
+    const token = store.state.app.token;  
+    token && (config.headers.Authorization = token);      
+    return config;    
+},    
+error => {        
+    return Promise.error(error);    
+})
+
+// 响应拦截器
+axios.interceptors.response.use(    
+  response => {
+      // 如果返回的状态码为200,说明接口请求成功,可以正常拿到数据     
+      // 否则的话抛出错误
+      if (response.status === 200) {            
+          return Promise.resolve(response);        
+      } else {            
+          return Promise.reject(response);        
+      }    
+  },    
+  // 服务器状态码不是2开头的的情况
+  // 这里可以跟你们的后台开发人员协商好统一的错误状态码    
+  // 然后根据返回的状态码进行一些操作,例如登录过期提示,错误提示等等
+  // 下面列举几个常见的操作,其他需求可自行扩展
+  error => {
+      console.log(`error.response.status`, error.response.status)         
+      if (error.response.status) {     
+          console.log(`error`, error)       
+          console.log(`error`, error)       
+          switch (error.response.status) {                
+              // 401: 未登录
+              // 未登录则跳转登录页面,并携带当前页面的路径
+              // 在登录成功后返回当前页面,这一步需要在登录页操作。                
+              case 401:                    
+                  router.replace({                        
+                      path: '/login',                        
+                      query: { 
+                          redirect: router.currentRoute.fullPath 
+                      }
+                  });
+                  break;
+
+              // 403 token过期
+              // 登录过期对用户进行提示
+              // 清除本地token和清空vuex中token对象
+              // 跳转登录页面                
+              case 403:
+                  Vue.prototype.$message.error('登录过期,请重新登录')
+                  // 清空token,user
+                  store.commit(`app/clear_user`, {}, { root: true });
+                  setTimeout(() => {
+                    window.location.reload();
+                  }, 1000);                   
+                  break; 
+
+              // 404请求不存在
+              case 404:
+                  Vue.prototype.$message.error('404 not found');
+                  break;
+
+              // 404请求不存在
+              case 500:
+                  Vue.prototype.$message.error('Internal Server Error');
+                  break;
+
+              // 其他错误,直接抛出错误提示
+              default:
+                  console.log(`error`, error)
+                  
+          }
+          return Promise.reject(error.response);
+      }
+  })
+
+
+
 // 封装自己的get/post方法
 export default {
   get: function(path = '', data = {}) {

+ 21 - 34
src/components/ChatFrame.vue

@@ -267,7 +267,7 @@
       <div class="send-msg-wrap">
         <div class="send-header">
           <div class="tools" style="margin: 10px">
-            <el-popover placement="top" width="300" trigger="click">
+            <el-popover placement="top" width="300" trigger="click" v-model="popoverShow">
               <Emoji @addEmoji="addEmoji" />
               <el-button
                 class="iconfont open_emoji_icon"
@@ -329,9 +329,10 @@
 <script>
 import { isUrl, parseHtml } from "@/utils/common";
 import Emoji from "./Emoji.vue";
-import { mapState, mapActions } from "vuex";
-let emojiData = require("./../assets/emoji/emoji.json");
+import { mapState, mapMutations } from "vuex";
 import request from "@/api/require";
+
+let emojiData = require("./../assets/emoji/emoji.json");
 export default {
   name: "ChatFrame",
   props: ["selected", "tab"],
@@ -345,6 +346,7 @@ export default {
       inputRange: "", // 光标
       emojiPath: new Map(), // emoji表情地址map对象,
       msg: "",
+      popoverShow: false,
       friend_record_list: [],
       room_record_list: [],
       messageType: "",
@@ -353,16 +355,11 @@ export default {
   },
   computed: {
     ...mapState({
-      self: state => state.app.user
-    }),
-    ...mapState({
-      socket: state => state.chat.socket
-    }),
-    ...mapState({
-      friendRecord: state => state.chat.friendRecord
-    }),
-    ...mapState({
+      self: state => state.app.user,
+      socket: state => state.chat.socket,
+      friendRecord: state => state.chat.friendRecord,
       roomRecord: state => state.chat.roomRecord
+
     })
   },
   watch: {
@@ -371,20 +368,15 @@ export default {
         if (this.friendRecord[newVal.id]) {
           this.friend_record_list = this.friendRecord[newVal.id];
         } else {
-          this.$store.commit("chat/set_friend_record", [newVal.id]);
+          this.set_friend_record([newVal.id])
           this.friend_record_list = this.friendRecord[newVal.id];
-          console.log(`this.friendRecord`, this.friendRecord);
         }
       } else {
         if (this.roomRecord[newVal.id]) {
           this.room_record_list = this.roomRecord[newVal.id];
         } else {
-          this.$store.commit("chat/set_room_record", newVal.id);
+          this.set_room_record(newVal.id)
           this.room_record_list = this.roomRecord[newVal.id];
-          console.log(
-            `this.room_record_list[newVal.id]`,
-            this.room_record_list
-          );
         }
       }
       this.$nextTick(() => {
@@ -397,6 +389,10 @@ export default {
     }
   },
   methods: {
+    ...mapMutations('chat', [
+      'set_friend_record',
+      'set_room_record',
+    ]),
     handleSuccess(res, file) {
       console.log(`res`, res);
       this.imageUrl = URL.createObjectURL(file.raw);
@@ -727,15 +723,18 @@ export default {
         msgInfo.toid = this.selected.id;
         this.socket.emit("private message", this.selected.id, msgInfo);
         const msgData = [this.selected.id, msgInfo];
-        this.$store.commit("chat/set_friend_record", msgData);
+        this.set_friend_record(msgData);
         this.friend_record_list = this.friendRecord[this.selected.id];
       } else {
         console.log("=======ROOM CHAT========");
         msgInfo.roomId = this.selected.id;
         this.socket.emit("chat-room", this.selected.id, msgInfo);
-        this.$store.commit("chat/set_room_record", msgInfo);
+        this.set_room_record(msgInfo);
         this.room_record_list = this.roomRecord[this.selected.id];
       }
+      // 发送消息后关闭表情选择弹窗
+      this.popoverShow = false
+
       this.$nextTick(() => {
         // 输入enter后置空
         document.getElementById("charInput").innerText = "";
@@ -745,21 +744,9 @@ export default {
         this.$refs["myScrollbar"].wrap.scrollTop = this.$refs["myScrollbar"].wrap.scrollHeight;
       });
     },
-
-    closeScoket() {
-      // 断开连接
-      this.$socket.close();
-    }
   },
   created() {
-    // const room_record_str = getCookie("room_record");
-    // const friend_record_str = getCookie("friend_record");
-    // if (room_record_str) {
-    //   this.room_record = JSON.parse(room_record_str);
-    // }
-    // if (friend_record_str) {
-    //   this.friend_record = JSON.parse(friend_record_str);
-    // }
+    
   },
   mounted() {
     this.initEmojiPic();

+ 22 - 21
src/components/ChatList.vue

@@ -81,17 +81,17 @@
           placeholder="请输入群聊名"
           v-model="group_name"
         />
-        <el-button
+        <button
           v-if="dialog_title === '创建群聊'"
           class="create-btn"
           @click="create"
-          >创建</el-button
+          >创建</button
         >
-        <el-button
+        <button
           v-else-if="dialog_title === '加入群聊'"
           class="create-btn"
           @click="join"
-          >加入</el-button
+          >加入</button
         >
       </div>
     </el-dialog>
@@ -99,8 +99,7 @@
 </template>
 
 <script>
-import { addCookie, getCookie } from "@/utils/setCookie.js";
-import { mapState, mapActions } from "vuex";
+import { mapState } from "vuex";
 export default {
   name: "ChatList",
   data() {
@@ -109,26 +108,17 @@ export default {
       selected_id: "",
       dialogVisible: false,
       dialog_title: "创建群聊",
-      // self: null,
-      // friend_list: [],
-      // group_list: [],
       group_name: "",
       room_member: []
     };
   },
   computed: {
     ...mapState({
-      socket: state => state.chat.socket
+      self: state => state.app.user,
+      socket: state => state.chat.socket,
+      friend_list: state => state.chat.userList,
+      group_list: state => state.chat.roomList,
     }),
-    ...mapState({
-      self: state => state.app.user
-    }),
-    ...mapState({
-      friend_list: state => state.chat.userList
-    }),
-    ...mapState({
-      group_list: state => state.chat.roomList
-    })
   },
   watch: {
     // //监听值改变
@@ -184,8 +174,7 @@ export default {
     },
   },
   mounted() {
-    // this.friend_list = this.$store.getters['chat/userList']
-    // console.log(`this.friend_list`, this.friend_list)
+    
   },
 };
 </script>
@@ -232,6 +221,17 @@ export default {
   justify-content: space-around;
 }
 
+.create-room button, .create-btn {
+  border: none;
+  color: #fff;
+  background: #4097ce;
+  padding: 4px 6px;
+  border-radius: 2px;
+}
+.create-room button:hover, .create-btn:hover{
+  background: #70bfef;
+}
+
 .create-room-wrap {
   margin: 0 auto;
   text-align: center;
@@ -245,6 +245,7 @@ export default {
 }
 .create-btn {
   margin-top: 20px;
+  padding: 6px 18px;
 }
 .leave-room-btn {
     width: 20px;

+ 0 - 1
src/components/Emoji.vue

@@ -72,7 +72,6 @@ export default {
           );
         });
       }
-      console.log(`map`, map)
 
       this.emojiPath = map;
     },

+ 0 - 143
src/components/Entry.vue

@@ -1,143 +0,0 @@
-<template>
-  <div class="message-input" v-if="activeRoom">
-    <div class="message-tool">
-      <a-popover placement="topLeft" trigger="click" class="message-popver">
-        <template slot="content">
-          <emoji @addEmoji="addEmoji"></emoji>
-        </template>
-        <div class="message-tool-item">
-          <div class="messagte-tool-icon" v-if="mobile">😃</div>
-          <a-icon v-else type="smile" />
-        </div>
-      </a-popover>
-      <div class="message-tool-item" v-if="!mobile">
-        <a-upload :show-upload-list="false" :before-upload="beforeFileUpload">
-          <a-icon type="folder-open" />
-        </a-upload>
-      </div>
-    </div>
-
-    <a-input
-      v-if="mobile"
-      autocomplete="off"
-      type="text"
-      autoFocus
-      placeholder="say hello..."
-      v-model="text"
-      ref="input"
-      style="color: #000"
-      @pressEnter="throttle(preSendMessage)"
-    />
-    <a-textarea
-      v-else
-      autocomplete="off"
-      v-model="text"
-      ref="input"
-      autoFocus
-      style="color: #000"
-      @pressEnter="
-        (e) => {
-          // 此处拦截enter后光标换行
-          e.preventDefault();
-          throttle(preSendMessage);
-        }
-      "
-    />
-    <img class="message-input-button" v-if="mobile" @click="throttle(preSendMessage)" src="~@/assets/send.png" alt="" />
-  </div>
-</template>
-
-<script>
-import Emoji from './Emoji.vue';
-export default {
-  name: 'Entry',
-  components: {
-    Emoji,
-  },
-  data() {
-    return {
-    };
-  },
-  computed: {
-  },
-  watch: {
-  },
-  methods: {},
-};
-</script>
-
-<style lang="scss" scoped>
-@import '@/styles/theme';
-
-.message-input {
-  display: flex;
-  // border-top: 1px solid #d1d1d1;
-  background: $message-bg-color;
-  flex-wrap: nowrap;
-  width: 100%;
-  textarea {
-    border-left: none !important;
-    border-top-left-radius: 0;
-    border-top-right-radius: 0;
-    border-bottom-left-radius: 0;
-  }
-  .message-input-button {
-    width: 30px;
-    cursor: pointer;
-    position: absolute;
-    right: 10px;
-    top: 4px;
-  }
-}
-//输入框样式
-.ant-input {
-  padding: 50px 10px 0 20px !important;
-  height: 180px;
-  border-top: 1px solid #d6d6d6;
-  background: $message-bg-color;
-  border-left: none;
-  border-right: none;
-  border-bottom: none;
-  border-radius: 0;
-  &:focus {
-    box-shadow: none !important;
-  }
-}
-
-// 移动端样式
-@media screen and (max-width: 768px) {
-  .ant-input {
-    padding: 0 50px 0 35px !important;
-    height: 40px;
-  }
-  .message-tool {
-    right: unset !important;
-    padding: 0 0 0 10px !important;
-    .message-tool-item {
-      .anticon {
-        margin-right: 0 !important;
-      }
-    }
-  }
-}
-
-// 消息工具样式
-.message-tool {
-  position: absolute;
-  left: 0;
-  right: 0;
-  display: flex;
-  align-items: center;
-  height: 50px;
-  line-height: 42px;
-  font-size: 22px;
-  padding: 0 20px;
-  z-index: 99;
-  color: #828282;
-  .message-tool-item {
-    .anticon {
-      margin-right: 25px;
-    }
-  }
-}
-</style>

+ 32 - 41
src/components/Login.vue

@@ -14,21 +14,22 @@
         type="text"
         placeholder="请输入昵称"
         v-model="username"
-        @keyup.enter.native="login"
+        @keyup.enter.native="handleLogin"
       />
       <el-input
         type="password"
         placeholder="请输入密码"
         v-model="password"
-        @keyup.enter.native="login"
+        @keyup.enter.native="handleLogin"
       />
-      <el-button class="login-btn" @click="login">登录</el-button>
+      <button class="login-btn" @click="handleLogin">登录</button>
     </div>
   </el-dialog>
 </template>
 
 <script>
 
+import { mapState, mapGetters, mapActions } from "vuex";
 export default {
   data() {
     return {
@@ -37,62 +38,43 @@ export default {
       password: ""
     };
   },
+  computed: {
+    ...mapGetters("app", [
+      'user'
+    ]),
+  },
   methods: {
+    ...mapActions('chat',[ 
+      'connectSocket' // --> this.connectSocket
+    ]),
+    ...mapActions('app',[ 
+      'login'
+    ]),
     init() {
-      const self = JSON.parse(localStorage.getItem("self"));
-      console.log(`self`, self);
-      // if (self) {
-      //   this.$socket.id = self.id;
+      // if (this.user.token) {
+      //      this.connectSocket() 
       //   this.dialogVisible = false;
-      //   this.$socket.emit("list");
       // } else {
-        this.dialogVisible = true;
+      //   this.dialogVisible = true;
       // }
-      // console.log(`init===`, this.$socket.id);
+      this.dialogVisible = true;
     },
-    async login() {
-      // const socket = this.$store.getters['chat/socket']
-      // console.log(`socket`, socket)
+    async handleLogin() {
       if (this.username !== "") {
         const userInfo = {
           // id: this.$socket.id,
           username: this.username
         };
-        await this.$store.dispatch('app/login', userInfo).then((res) => {
+        await this.login(userInfo).then((res) => {
           
-          this.$store.dispatch('chat/connectSocket', res) // 登录成功连接socket.io
+          this.connectSocket() // 登录成功连接socket.io
           this.dialogVisible = false;
         })
         .catch((err) => {
+          console.log('=======连接失败==========')
           console.log(`err`, err)
         })
       }
-      return;
-
-
-
-
-      // this.$store.dispatch('app/login',{nick: 'hihihih'})
-      // this.$store.commit('app/set_user', {test: 'xixixixi'})
-      // const apiurl = process.env.API_URL
-      // console.log(`apiurl`, apiurl)
-      console.log(`this.$socket`, this.$socket)
-      this.$socket.auth.token = '55555df'
-      if (this.$socket.id) {
-        if (this.username !== "") {
-          const userInfo = {
-            id: this.$socket.id,
-            username: this.username
-          };
-          this.$socket.emit("login", userInfo);
-          localStorage.setItem("self", JSON.stringify(userInfo));
-          this.$socket.emit("list");
-          this.$socket.emit("join-test-room");
-          this.dialogVisible = false;
-        }
-      } else {
-        this.$message.error("socket.io服务器连接失败");
-      }
     }
   },
   created() {
@@ -117,7 +99,16 @@ export default {
 .login-wrap .username-input {
   margin-bottom: 10px;
 }
+
 .login-btn {
   margin-top: 20px;
+  border: none;
+  color: #fff;
+  background: #4097ce;
+  padding: 4px 16px;
+  border-radius: 2px;
+}
+.login-btn:hover{
+  background: #70bfef;
 }
 </style>

+ 0 - 131
src/components/test.vue

@@ -1,131 +0,0 @@
-<template>
-  <div class="emoji-content">
-    <div class="emoji-content-item">
-      <span @click="addEmoji('😃')">😃</span>
-      <span @click="addEmoji('😁')">😁</span>
-      <span @click="addEmoji('😂')">😂</span>
-      <span @click="addEmoji('😄')">😄</span>
-      <span @click="addEmoji('😅')">😅</span>
-      <span @click="addEmoji('😆')">😆</span>
-      <span @click="addEmoji('😇')">😇</span>
-      <span @click="addEmoji('😈')">😈</span>
-      <span @click="addEmoji('😉')">😉</span>
-    </div>
-    <div class="emoji-content-item">
-      <span @click="addEmoji('😊')">😊</span>
-      <span @click="addEmoji('😋')">😋</span>
-      <span @click="addEmoji('😌')">😌</span>
-      <span @click="addEmoji('😍')">😍</span>
-      <span @click="addEmoji('😎')">😎</span>
-      <span @click="addEmoji('😏')">😏</span>
-      <span @click="addEmoji('😐')">😐</span>
-      <span @click="addEmoji('😒')">😒</span>
-      <span @click="addEmoji('😓')">😓</span>
-    </div>
-    <div class="emoji-content-item">
-      <span @click="addEmoji('❓')">❓</span>
-      <span @click="addEmoji('😕')">😕</span>
-      <span @click="addEmoji('😖')">😖</span>
-      <span @click="addEmoji('😗')">😗</span>
-      <span @click="addEmoji('😘')">😘</span>
-      <span @click="addEmoji('😙')">😙</span>
-      <span @click="addEmoji('😚')">😚</span>
-      <span @click="addEmoji('😜')">😜</span>
-      <span @click="addEmoji('😝')">😝</span>
-    </div>
-    <div class="emoji-content-item">
-      <span @click="addEmoji('😞')">😞</span>
-      <span @click="addEmoji('😟')">😟</span>
-      <span @click="addEmoji('😠')">😠</span>
-      <span @click="addEmoji('😡')">😡</span>
-      <span @click="addEmoji('😢')">😢</span>
-      <span @click="addEmoji('😣')">😣</span>
-      <span @click="addEmoji('😤')">😤</span>
-      <span @click="addEmoji('😥')">😥</span>
-      <span @click="addEmoji('😦')">😦</span>
-    </div>
-    <div class="emoji-content-item">
-      <span @click="addEmoji('😨')">😨</span>
-      <span @click="addEmoji('😩')">😩</span>
-      <span @click="addEmoji('😪')">😪</span>
-      <span @click="addEmoji('😫')">😫</span>
-      <span @click="addEmoji('😬')">😬</span>
-      <span @click="addEmoji('😭')">😭</span>
-      <span @click="addEmoji('😮')">😮</span>
-      <span @click="addEmoji('😯')">😯</span>
-      <span @click="addEmoji('😰')">😰</span>
-    </div>
-    <div class="emoji-content-item">
-      <span @click="addEmoji('😲')">😲</span>
-      <span @click="addEmoji('😳')">😳</span>
-      <span @click="addEmoji('😴')">😴</span>
-      <span @click="addEmoji('😵')">😵</span>
-      <span @click="addEmoji('🧐')">🧐</span>
-      <span @click="addEmoji('😷')">😷</span>
-      <span @click="addEmoji('🙁')">🙁</span>
-      <span @click="addEmoji('🙂')">🙂</span>
-      <span @click="addEmoji('🙃')">🙃</span>
-    </div>
-    <div class="emoji-content-item">
-      <span @click="addEmoji('🤐')">🤐</span>
-      <span @click="addEmoji('🤑')">🤑</span>
-      <span @click="addEmoji('🤒')">🤒</span>
-      <span @click="addEmoji('🤓')">🤓</span>
-      <span @click="addEmoji('🤔')">🤔</span>
-      <span @click="addEmoji('🤕')">🤕</span>
-      <span @click="addEmoji('🤠')">🤠</span>
-      <span @click="addEmoji('🤡')">🤡</span>
-      <span @click="addEmoji('🤢')">🤢</span>
-    </div>
-    <div class="emoji-content-item">
-      <span @click="addEmoji('🤤')">🤤</span>
-      <span @click="addEmoji('🤥')">🤥</span>
-      <span @click="addEmoji('🤧')">🤧</span>
-      <span @click="addEmoji('🤨')">🤨</span>
-      <span @click="addEmoji('🤩')">🤩</span>
-      <span @click="addEmoji('🤪')">🤪</span>
-      <span @click="addEmoji('🤫')">🤫</span>
-      <span @click="addEmoji('🤬')">🤬</span>
-      <span @click="addEmoji('🤭')">🤭</span>
-    </div>
-  </div>
-</template>
-
-<script>
-export default {
-  name: 'Emoji',
-  data() {
-    return {};
-  },
-  methods: {
-    addEmoji(emoji) {
-      this.$emit('addEmoji', emoji);
-    }
-  },
-};
-</script>
-
-<style lang="scss" scoped>
-.emoji-content {
-  color: #000;
-  font-size: 20px;
-  width: 250px;
-  /* 禁止文字被鼠标选中 */
-  moz-user-select: -moz-none;
-  -moz-user-select: none;
-  -o-user-select: none;
-  -khtml-user-select: none;
-  -webkit-user-select: none;
-  -ms-user-select: none;
-  user-select: none;
-}
-  
-  .emoji-content-item {
-    display: flex;
-    justify-content: space-evenly;
-    flex-wrap: nowrap;
-  }
-  .emoji-content-item span {
-      cursor: pointer;
-  }
-</style>

+ 1 - 3
src/store/modules/chat/actions.js

@@ -27,12 +27,10 @@ import {
 
 const actions = {
   // 初始化socket连接和监听socket事件
-  async connectSocket({ commit, state, dispatch, rootState }, payload) {
+  async connectSocket({ commit, state, dispatch, rootState }) {
     const { user, token } = rootState.app;
-    console.log(`payloadddd`, payload)
     // const socket = io.connect('/', {
     const socket = io.connect('http://127.0.0.1:3000', { // 本地
-      
       reconnection: true,
       auth: {
         token: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsImlhdCI6MTYyOTk2MTE2NywiZXhwIjoxNjMyNTUzMTY3fQ.JfitLCzjEwjBL-EY0wqcjFj4F-VnOas_VU60kSZdAVU',