XiaBx пре 2 година
родитељ
комит
0ee309016a

+ 1 - 1
config/index.js

@@ -28,7 +28,7 @@ module.exports = {
     },
 
     // Various Dev Server settings
-    host: "10.20.50.140", // can be overwritten by process.env.HOST
+    host: "127.0.0.1", // can be overwritten by process.env.HOST
     port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
     autoOpenBrowser: false,
     errorOverlay: true,

+ 2 - 0
package.json

@@ -10,9 +10,11 @@
     "build": "node build/build.js"
   },
   "dependencies": {
+    "@fingerprintjs/fingerprintjs": "^3.3.3",
     "axios": "^0.17.1",
     "babel-polyfill": "^6.26.0",
     "clipboard": "^2.0.4",
+    "cross-storage": "^1.0.0",
     "fundebug-javascript": "^1.2.3",
     "html2canvas": "^1.0.0-rc.4",
     "js-md5": "^0.7.3",

+ 71 - 14
src/App.vue

@@ -12,6 +12,9 @@
     <div class="package-wrap" @touchmove.prevent v-if="showWrap">
       <img @click.stop="closeWrap" :src="imgs" alt="" />
     </div>
+    <div class="blank_page" v-if="showBlank">
+      <p class="ting">{{ toastMsg }}</p>
+    </div>
     <!--  <div class="package-wrap" @touchmove.prevent v-if="showAd">
       
       <img
@@ -24,7 +27,10 @@
 </template>
 
 <script>
-import { setUserMode } from "./api";
+import { setUserMode, setFingerprint } from "./api";
+import getFingerPrintFunc from "./util/fingerprint";
+import { getKeyByWay, setKeyByWay, getQueryString } from "./util/index";
+
 import Vue from "vue";
 
 export default {
@@ -39,7 +45,9 @@ export default {
       showWrap: false,
       // todayDate: new Date().toLocaleDateString(),
       isTargetChannel: window.options.is_show_ad_frame,
-      showIframe: false
+      showIframe: false,
+      showBlank: false,
+      toastMsg: "系统维护中~~~~~~~~~~"
     };
   },
   watch: {
@@ -47,6 +55,9 @@ export default {
       if (v.name === "BookCity") {
         v.query.sex && (this.theme = v.query.sex);
       }
+      if (v.name != "Yun" && v.name !== "Reader") {
+        this.testToken();
+      }
     }
   },
   async created() {
@@ -73,22 +84,33 @@ export default {
 
     //获取是否加桌过
     //const { is_add_desk } = window.options;
-    const token = localStorage.getItem("token");
-    const sendId = Vue.prototype.sendid || localStorage.getItem("sendid") || "";
-    if (token && sendId) {
+    const token = getKeyByWay("token");
+    const hashuser = getQueryString("hashuser") || getKeyByWay("hashuser");
+    const send_order_id =
+      getKeyByWay("send_order_id") || getQueryString("send_order_id");
+    if (token && send_order_id) {
       setUserMode(Number(window.navigator.standalone) || 0).then(res => {});
     }
-    localStorage.setItem("userMode", Number(window.navigator.standalone));
 
-    /*  if (
-      !showBanner &&
-      !is_add_desk &&
-      ! &&
-      showList.includes(window.nextName)
+    setKeyByWay("addDestop", window.navigator.standalone);
+
+    //有token 加过桌 上传最新密钥
+    if (
+      token &&
+      hashuser &&
+      hashuser != "hashuser" &&
+      window.navigator.standalone
     ) {
-      this.showAd = true;
-      sessionStorage.setItem("showBanner", true);
-    } */
+      let fingerprint = await getFingerPrintFunc();
+      try {
+        await setFingerprint({
+          hashuser,
+          fingerprint
+        });
+      } catch (e) {
+        this.$Toast(e.data.msg);
+      }
+    }
   },
 
   methods: {
@@ -103,6 +125,20 @@ export default {
         this.showWrap = false;
       }
     },
+    testToken() {
+      const token = getKeyByWay("token");
+      //非加桌模式下,并且没有token 并且不是访问派单落地页和阅读器直接白屏
+      if (!window.navigator.standalone) {
+        if (!token) {
+          if (this.$route.name == "Pay") {
+            this.showBlank = true;
+            this.toastMsg = "支付完成后,请从桌面链接重新打开,畅享阅读~";
+          }else{
+            this.showBlank = true;
+          }
+        }
+      }
+    },
     initWrap() {
       if (window.options.fission) {
         // 红包弹窗弹出
@@ -115,6 +151,27 @@ export default {
 </script>
 
 <style lang="scss" scoped>
+.blank_page {
+  position: fixed;
+  background-color: #fff;
+  width: 100vw;
+  height: 100vh;
+  top: 0;
+  left: 0;
+  z-index: 9999;
+  .ting {
+    position: absolute;
+    width: 300px;
+    height: 300px;
+    line-height: 300px;
+    text-align: center;
+    margin: auto;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+  }
+}
 .package-wrap {
   position: fixed;
   top: 0;

+ 17 - 10
src/api/axios.js

@@ -3,6 +3,9 @@ import router from "../router/index.js";
 import { Undertheshelf } from "../view/namespace.js";
 import { undefinedCollect } from "./index.js";
 import { getToken, refreshToken } from "./config";
+
+import { setKeyByWay, getKeyByWay,getQueryString } from "../util/index";
+
 import { addPendingRequest, removePendingRequest } from "./cancelRepeatRquest";
 import { Toast } from "mint-ui";
 
@@ -11,12 +14,17 @@ import { Toast } from "mint-ui";
 //     ? {
 //         baseURL: "http://site1.aizhuishu.com/api",
 //         withCredentials: true
-//       }   
+//       }
 //     : {
 //         baseURL: "/api"
 //       }
 // );
-const whiteList = ["/login", "/hashuserToToken"];
+const whiteList = [
+  "/login",
+  "/hashuserToToken",
+  "/register",
+  "/loginByFingerprint"
+];
 
 var instance = axios.create({
   baseURL: "/api"
@@ -24,7 +32,7 @@ var instance = axios.create({
 
 instance.interceptors.response.use(
   async res => {
-    if (res.data.code === 0) { 
+    if (res.data.code === 0) {
       //removePendingRequest(res);
       return res.data.data;
     }
@@ -49,20 +57,19 @@ instance.interceptors.response.use(
   }
 );
 instance.interceptors.request.use(async function(config) {
-  let token = localStorage.getItem("token");
+  let token = getKeyByWay("token") || getQueryString('token');
 
-  if (!whiteList.includes(config.url) && !token) {
-    console.log(config.url);
+  //加桌链接,非阅读器和派单链接(已单独注册),接口白名单之外,没有token的情况下,请求登录
+  if (!whiteList.includes(config.url) && !token && !location.pathname.includes('/reader') && !location.pathname.includes('/yun')) {
     token = await getToken(config);
-  }else{
+  } else {
     config.cancelRequest = true;
     //addPendingRequest(config);
-
   }
 
   if (token) {
     config.headers.Authorization = `bearer ${token}`;
-    config.headers.version = 'v1.0.1';
+    config.headers.version = "v1.0.1";
   }
   if (
     config.method === "get" &&
@@ -81,7 +88,7 @@ instance.interceptors.request.use(async function(config) {
       })
     });
   }
-  
+
   return config;
 });
 

+ 28 - 5
src/api/config.js

@@ -1,8 +1,28 @@
-import { userLogin } from "./index";
+import { userLogin, newLogin } from "./index";
 import Qs from "qs";
-import Vue from 'vue'
+import Vue from "vue";
+import { setKeyByWay, getKeyByWay, getQueryString } from "../util/index";
+import getFingerPrintFunc from "../util/fingerprint";
+
 export async function getToken(config) {
-  return login();
+  let send_order_id =
+    getQueryString("send_order_id") || getKeyByWay("send_order_id");
+  let hashusers = getQueryString("hashuser") || getKeyByWay("hashuser");
+
+  const fingerprint = await getFingerPrintFunc();
+  let { token, hashuser: hashUser } = await newLogin({
+    send_order_id,
+    fingerprint,
+    hashuser: hashusers
+  });
+  setKeyByWay("token", token);
+  setKeyByWay("hashuser", hashUser);
+  if(token){
+    return Promise.resolve(token);
+  }else{
+    return Promise.resolve('');
+  }
+ 
 }
 
 export async function login() {
@@ -10,7 +30,11 @@ export async function login() {
   const timestamp = parseInt(new Date().valueOf() / 1000);
   let data = {
     timestamp,
-    send_order_id: Vue.prototype.sendid || localStorage.getItem("sendid") || sessionStorage.getItem('sendid')||'',
+    send_order_id:
+      Vue.prototype.send_order_id ||
+      localStorage.getItem("send_order_id") ||
+      sessionStorage.getItem("send_order_id") ||
+      "",
     form_url: location.href
   };
   let ret = await userLogin(data);
@@ -24,7 +48,6 @@ export async function login() {
 }
 
 export async function refreshToken() {
-  localStorage.removeItem("token");
   await getToken();
 }
 

+ 73 - 33
src/api/index.js

@@ -18,6 +18,7 @@ import {
 import cache from "../util/cache.js";
 import { Subscribe, Pay } from "../view/namespace.js";
 import bus from "../util/bus";
+import { getKeyByWay } from "../util/index";
 
 //获取首页(书城)内容
 let index = {};
@@ -226,8 +227,7 @@ export function getSignRecord(page = 1) {
   return axios(`/user/sign_record?page=${page}`);
 }
 
-
-const sendid = localStorage.getItem('sendid')
+const send_order_id = localStorage.getItem("send_order_id");
 //获取章节内容
 // 创建一个同款推荐的缓存池
 
@@ -254,10 +254,10 @@ let content = new cache({
 
 export function getContent(bid, cid, adStatus = 0, from, code = "") {
   let url = options.adTargetId
-    ? `/books/${bid}/chapters/${cid}?ad_status=${adStatus}&page_from=${from}&send_oerder_id=${sendid}&code=${encodeURIComponent(
+    ? `/books/${bid}/chapters/${cid}?ad_status=${adStatus}&page_from=${from}&send_oerder_id=${send_order_id}&code=${encodeURIComponent(
         code
       )}`
-    : `/books/${bid}/chapters/${cid}?page_from=${from}&send_oerder_id=${sendid}&code=${encodeURIComponent(
+    : `/books/${bid}/chapters/${cid}?page_from=${from}&send_oerder_id=${send_order_id}&code=${encodeURIComponent(
         code
       )}`;
   return content
@@ -347,33 +347,45 @@ export function getProductList(bid) {
 }
 
 //充值
-export function recharge({ product_id, bid, cid, use_coupon, from_detail_catalog, last_bid, last_cid, sequence, sendid, yun }) {
+export function recharge({
+  product_id,
+  bid,
+  cid,
+  use_coupon,
+  from_detail_catalog,
+  last_bid,
+  last_cid,
+  sequence,
+  send_order_id,
+  yun
+}) {
   const a = document.createElement("a");
+  const token = getKeyByWay('token');
   const redirect =
-  bid && cid
-    ?{
-        host: location.origin,
-        pathname: "/pay",
-        query: {
-          bid,
-          cid,
-          from_detail_catalog,
-          last_bid,
-          last_cid,
-          sequence,
-          sendid,
-          yun,
-          isRecharge: true // 微信充值完回到充值中心,如果从目录或阅读页跳转过来,回去时需要传入上一页id或目录进行判断
-        }
-      }
-    : {
-        host: location.origin,
-        pathname: "/pay",
-        query: {
-          isRecharge: true // 微信充值完回到充值中心,如果从个人中心来充值,无需传入其他参数
+    bid && cid
+      ? {
+          host: location.origin,
+          pathname: "/pay",
+          query: {
+            bid,
+            cid,
+            from_detail_catalog,
+            last_bid,
+            last_cid,
+            sequence,
+            send_order_id,
+            yun,
+            isRecharge: true // 微信充值完回到充值中心,如果从目录或阅读页跳转过来,回去时需要传入上一页id或目录进行判断
+          }
         }
-      };
-  const token = localStorage.getItem("token");
+      : {
+          host: location.origin,
+          pathname: "/pay",
+          query: {
+            isRecharge: true // 微信充值完回到充值中心,如果从个人中心来充值,无需传入其他参数
+          }
+        };
+  
 
   const href = {
     host: window.options.pay_url,
@@ -642,11 +654,39 @@ export function uuidsGetTokens(uuid) {
 }
 
 //记录用户加桌状态
-export function setUserMode(status,send_order_id) {
-  return axios.post(`/setAddDeskStatus`, {  add_desk_status: status,send_order_id  });
+export function setUserMode(status, send_order_id) {
+  return axios.post(`/setAddDeskStatus`, {
+    add_desk_status: status,
+    send_order_id
+  });
 }
 
 //强加桌模型切换
-export function changeAddMode(){
-  return axios('/getAddDeskImage');
-}
+export function changeAddMode() {
+  return axios("/getAddDeskImage");
+}
+
+//新版登录
+export function newLogin(params) {
+  return axios.post("/loginByFingerprint", params);
+}
+
+//新版注册
+export function newRegister(data) {
+  return axios.post("/register", data);
+}
+
+//新版刷新token
+export function newRefreshToken(params) {
+  return axios("/refreshToken", { params });
+}
+
+//新版销毁旧token
+export function newDestoryToken(data) {
+  return axios.post("/destroyToken", data);
+}
+
+//更新token的指纹
+export function setFingerprint(data) {
+  return axios.post("/setFingerprint", data);
+}

+ 4 - 0
src/base/base.css

@@ -197,3 +197,7 @@ body.dialog-open {
   position: fixed;
   width: 100%;
 }
+
+.mint-toast{
+  z-index: 8888!important;
+}

+ 22 - 8
src/components/gologin/GoLogin.vue

@@ -1,11 +1,17 @@
 <template>
   <div>
-    <mt-popup v-model="show" popup-transition="popup-fade">
-      <img src="../../assets/gotologin.png" alt=""  class="gotologin"/>
-      <div class="login_success">您还尚未绑定手机号</div>
-      <div class="login_message">绑定手机号方便下次继续阅读</div>
-      <div class="go_back_btn" @click="goBind">去绑定</div>
-      <div class="close_icon" @click="close"><img src="../../assets/cancellogin.png" alt=""></div>
+    <mt-popup
+      v-model="show"
+      popup-transition="popup-fade"
+      :closeOnClickModal="false"
+    >
+      <img src="../../assets/gotologin.png" alt="" class="gotologin" />
+      <div class="login_success">您还尚未登录</div>
+      <div class="login_message">登录后账号信息不丢失,阅读更顺畅</div>
+      <div class="go_back_btn" @click="goBind">立即登录</div>
+      <div class="close_icon" @click="closePop" v-if="showCloseIcon">
+        <img src="../../assets/cancellogin.png" alt="" />
+      </div>
     </mt-popup>
   </div>
 </template>
@@ -28,6 +34,11 @@ export default {
       type: Boolean,
       default: true
     },
+    showCloseIcon: {
+      required: false,
+      type: Boolean,
+      default: true
+    },
     close: {
       required: false,
       type: Function
@@ -39,9 +50,12 @@ export default {
   },
   methods: {
     goBind() {
-      router.push("/login");
-      this.close();
+      //router.push("/login");
+      //this.close();
       this.callback("success");
+    },
+    closePop() {
+      this.close && this.close();
     }
   }
 };

+ 10 - 2
src/components/gologin/index.js

@@ -16,13 +16,21 @@ const initInstance = () => {
   document.body.appendChild(instance.$el);
 };
 
-const goLogin = () => {
+const goLogin = props => {
   //不存在就创建
   if (!instance) {
     initInstance();
   }
   instance.show = true;
-
+  //todo 遍历props并传给
+  console.log(props);
+  if (props) {
+    for (let item in props) {
+      setTimeout(() => {
+        instance[item] = Boolean(props[item]);
+      }, 200);
+    }
+  }
   //增加回调访法方便以后异步调用
   instance.callback = action => {
     instance[action === "success" ? "resolve" : "reject"](action);

+ 1 - 1
src/components/prompt/children/server.vue

@@ -3,7 +3,7 @@
   <x-prompt :visible="visible">
     <div class="head">联系客服</div>
     <div class="body">
-      <p>长按识别二维码,添加客服微信</p>
+      <p>截图后至微信“扫一扫”打开,添加客服</p>
       <img :src="src"
            style="width: 60%;margin-top: .3rem;">
     </div>

+ 3 - 1
src/main.js

@@ -16,7 +16,7 @@ fundebug.apikey =
 // import './api'
 // import vconsole from 'vconsole'
 Vue.config.productionTip = false;
-Vue.prototype.sendid = '';
+Vue.prototype.send_order_id = '';
 if (process.env.NODE_ENV === "production") {  
   // fundebug.silentVideo = false
   // 事件过滤 过滤掉一些不必要的错误
@@ -57,6 +57,8 @@ if (process.env.NODE_ENV === "production") {
   };
 }
 
+
+
 window.signUrl = window.location.href;
 
 // var vConsole = new vconsole()

+ 36 - 7
src/router/index.js

@@ -1,7 +1,9 @@
 import Vue from "vue";
 import Router from "vue-router";
 import * as namespace from "../view/namespace.js";
-import { uuidsGetTokens } from "../api/index";
+import { newLogin } from "../api/index";
+import { setKeyByWay, getKeyByWay } from "../util/index";
+
 // import BookCity from '../view/book-city.vue'
 // import BookStock from '../view/book-stock.vue'
 // import BookShelf from '../view/book-shelf.vue'
@@ -138,16 +140,35 @@ router.beforeEach(async (to, from, next) => {
   //alert('即将前往'+document.domain+to.fullPath);
   window.nextPage = to.fullPath;
   window.nextName = to.name;
+  //获取token,send_order_id,hashuser
+  const token = to.query.token || getKeyByWay("token");
+  const hashuser = to.query.hashuser || getKeyByWay("hashuser");
+  const send_order_id = to.query.send_order_id || getKeyByWay("send_order_id");
 
   if (!window.firstName) {
     window.firstName = to.name;
-    const token = localStorage.getItem("token");
-    const uuids = localStorage.getItem("uuids") || to.query.uuids;
-    if (uuids && !token) {
-      let source = await uuidsGetTokens(uuids);
-      if (source.token ) localStorage.setItem("token", source.token);
-    }
+    //获取token
+    /*  const token = to.query.token || getKeyByWay("token");
+     const hashuser = to.query.hashuser || getKeyByWay("hashuser");
+    //如果url有hashuser 没有token就重新给用户登录
+    if (hashuser && !token) {
+      let source = await newLogin({});
+      if (source.token) localStorage.setItem("token", source.token);
+    } */
+  }
+
+  //派单链接不需要带参数,不属于页面内容体系,添加默认值防止死循环
+  if ((!to.query.hashuser || !to.query.send_order_id) && to.name != "Yun") {
+    let toQuery = JSON.parse(JSON.stringify(to.query));
+    toQuery.send_order_id = from.send_order_id || send_order_id || "send_order_id";
+    toQuery.hashuser = from.hashuser || hashuser || "hashuser";
+    to.meta ? (to.meta.behavior = behavior) : (to.meta = { behavior });
+    next({
+      path: to.path,
+      query: toQuery
+    });
   }
+
   to.meta ? (to.meta.behavior = behavior) : (to.meta = { behavior });
   behavior = "user";
   next();
@@ -160,4 +181,12 @@ router.afterEach(function(router, from) {
   }
 });
 
+//高版本vue 重定向会error,重写push方法,捕获catch
+const originalPush = Router.prototype.push;
+Router.prototype.push = function push(location, resolve, reject) {
+  if (resolve || reject)
+    return originalPush.call(this, location, resolve, reject);
+  return originalPush.call(this, location).catch(err => err);
+};
+
 export default router;

+ 134 - 0
src/util/fingerprint.js

@@ -0,0 +1,134 @@
+import FingerprintJS from "@fingerprintjs/fingerprintjs";
+
+//用于生成的配置信息
+/* const components = [
+  { key: "userAgent", getData: UserAgent }, //用户代理
+  { key: "webdriver", getData: webdriver }, //网页内驱动软件
+  { key: "language", getData: languageKey }, //语言种类
+  { key: "colorDepth", getData: colorDepthKey }, //目标设备或缓冲器上的调色板的比特深度
+  { key: "deviceMemory", getData: deviceMemoryKey }, //设备内存
+  { key: "pixelRatio", getData: pixelRatioKey }, //设备像素比
+  { key: "hardwareConcurrency", getData: hardwareConcurrencyKey }, //可用于运行在用户的计算机上的线程的逻辑处理器的数量。
+  { key: "screenResolution", getData: screenResolutionKey }, //当前屏幕分辨率
+  { key: "availableScreenResolution", getData: availableScreenResolutionKey }, //屏幕宽高(空白空间)
+  { key: "timezoneOffset", getData: timezoneOffset }, //本地时间与 GMT 时间之间的时间差,以分钟为单位
+  { key: "timezone", getData: timezone }, //时区
+  { key: "sessionStorage", getData: sessionStorageKey }, //是否会话存储
+  { key: "localStorage", getData: localStorageKey }, //是否具备本地存储
+  { key: "indexedDb", getData: indexedDbKey }, //是否具备索引DB
+  { key: "addBehavior", getData: addBehaviorKey }, //IE是否指定AddBehavior
+  { key: "openDatabase", getData: openDatabaseKey }, //是否有打开的DB
+  { key: "cpuClass", getData: cpuClassKey }, //浏览器系统的CPU等级
+  { key: "platform", getData: platformKey }, //运行浏览器的操做系统和(或)硬件平台
+  { key: "doNotTrack", getData: doNotTrackKey }, //do-not-track设置
+  { key: "plugins", getData: pluginsComponent }, //浏览器的插件信息
+  { key: "canvas", getData: canvasKey }, //使用 Canvas 绘图
+  { key: "webgl", getData: webglKey }, //WebGL指纹信息
+  { key: "webglVendorAndRenderer", getData: webglVendorAndRendererKey }, //具备大量熵的WebGL指纹的子集
+  { key: "adBlock", getData: adBlockKey }, //是否安装AdBlock
+  { key: "hasLiedLanguages", getData: hasLiedLanguagesKey }, //用户是否篡改了语言
+  { key: "hasLiedResolution", getData: hasLiedResolutionKey }, //用户是否篡改了屏幕分辨率
+  { key: "hasLiedOs", getData: hasLiedOsKey }, //用户是否篡改了操做系统
+  { key: "hasLiedBrowser", getData: hasLiedBrowserKey }, //用户是否篡改了浏览器
+  { key: "touchSupport", getData: touchSupportKey }, //触摸屏检测和能力
+  { key: "fonts", getData: jsFontsKey, pauseBefore: true }, //使用JS/CSS检测到的字体列表
+  { key: "fontsFlash", getData: flashFontsKey, pauseBefore: true }, //已安装的Flash字体列表
+  { key: "audio", getData: audioKey }, //音频处理
+  { key: "enumerateDevices", getData: enumerateDevicesKey } //可用的多媒体输入和输出设备的信息。
+]; */
+
+//闭包存储FingerPrint 降低性能开销
+const getFingerPrint = () => {
+  let fingerPrintKey;
+  return () => {
+    if (fingerPrintKey) {
+      return Promise.resolve(fingerPrintKey);
+    } else {
+      return new Promise((resolve, reject) => {
+        //保证指纹一致性,创建宏任务线程操作时间保证 配置项获取值一致
+        if (window.requestIdleCallback) {
+          requestIdleCallback(async () => {
+            fingerPrintKey = await createFingerPrint();
+            resolve(fingerPrintKey);
+          });
+        } else {
+          setTimeout(async () => {
+            fingerPrintKey = await createFingerPrint();
+            resolve(fingerPrintKey);
+          }, 500);
+        }
+      });
+    }
+  };
+};
+
+//调用指纹库生成指纹
+const createFingerPrint = async () => {
+  //配置默认项 v2有 V3无配置项
+  /* const defaultOptions = {
+    preprocessor: null,
+    audio: {
+      timeout: 1000,
+      // 在iOS 11上,音频上下文只能用于响应用户交互。我们要求用户在iOS 11上显式启用音频指纹https://stackoverflow.com/questions/46363048/onaudioprocess-not-called-on-ios11#46534088
+      excludeIOS11: true
+    },
+    screen: {
+      // 当用户旋转移动设备时确保指纹一致
+      detectScreenOrientation: true
+    },
+    //包含项稳定的参数来源https://github.com/Valve/fingerprintjs2/wiki/Stable-components
+    excludes: {
+      language: true,
+      colorDepth: true,
+      deviceMemory: true,
+      pixelRatio: true,
+      availableScreenResolution: true,
+      timezoneOffset: true,
+      timezone: true,
+      sessionStorage: true,
+      localStorage: true,
+      indexedDb: true,
+      addBehavior: true,
+      openDatabase: true,
+      cpuClass: true,
+      doNotTrack: true,
+      plugins: true,
+      canvas: true,
+      webglVendorAndRenderer: true, 
+      adBlock: true,
+      hasLiedLanguages: true,
+      hasLiedResolution: true,
+      hasLiedOs: true,
+      hasLiedBrowser: true,
+      touchSupport: true,
+      audio: false,
+      enumerateDevices: true,
+      hardwareConcurrency: true
+    }
+  }; */
+
+  //免费版无密钥初始化
+  const fpPromise = FingerprintJS.load();
+  //获取回调对象
+  const fp = await fpPromise;
+  //获取指纹密钥
+  try {
+    const { visitorId } = await fp.get();
+    return visitorId;
+  } catch (error) {
+    switch (error.message) {
+      case FingerprintJS.ERROR_GENERAL_SERVER_FAILURE:
+        console.log("Unknown server error. Request id:", error.requestId);
+        break;
+      case FingerprintJS.ERROR_CLIENT_TIMEOUT:
+        console.log("Identification time limit of 10 seconds is exceeded");
+        break;
+      default:
+        console.log("Other error");
+    }
+  }
+};
+
+const getFingerPrintFunc = getFingerPrint();
+
+export default getFingerPrintFunc;

+ 39 - 0
src/util/index.js

@@ -1,3 +1,7 @@
+import Vue from 'vue';
+
+
+
 const chapterReg = /^[0-9]+$/;
 export function clearStorageChapter() {
   Object.keys(window.localStorage).forEach(value => {
@@ -99,3 +103,38 @@ export function clipboard(text, event) {
   });
   cb.onClick(event);
 }
+
+
+//获取参数
+export function getKeyByWay(key){
+  return localStorage.getItem(key) || sessionStorage.getItem(key) || Vue.prototype[key] || undefined;
+}
+
+//设置参数
+export function setKeyByWay(key,value){
+  localStorage.setItem(key,value);
+  sessionStorage.setItem(key,value);
+  Vue.prototype[key] = value;
+}
+
+
+
+export function getQueryString(name) {
+  // 获取url上的参数(使用decodeURIComponent对url参数进行解码)
+  let search = decodeURIComponent(window.location.search).replace('?', '');
+  const tempArr = search !== '' ? search.split('&') : [];
+  
+  // 将参数名转小写,参数值保留原大小写
+  tempArr.forEach((item) => {
+      if (item) {
+          const itemArr = item.split('=');
+          search = search.replace(itemArr[0], itemArr[0].toLowerCase());
+      }
+  });
+
+  // 正则匹配指定的参数
+    const reg = new RegExp(`(^|&)${name.toLowerCase()}=([^&]*)(&|$)`);
+    const result = search.match(reg);
+
+    return result != null ? result[2] : '';
+}

+ 75 - 12
src/view/Login.vue

@@ -1,12 +1,20 @@
 <template>
   <div>
-    <x-header />
+    <x-header v-if="needHeader" />
     <div class="Login">
       <div class="Login_message">
         <div class="Login_message_phone">绑定手机号</div>
         <div class="Login_message_notfiy">
           已绑定过的手机号将自动同步原有账号记录
         </div>
+        <div class="Login_message_notfiy">
+          如对登录绑定操作有疑问,请到<a
+            href="javascript:;"
+            style="color: #a862ea"
+            @click="$router.replace('/person')"
+            >个人中心</a
+          >-客服中添加客服微信咨询
+        </div>
       </div>
       <div class="Login_form">
         <div class="Login_form_item">
@@ -65,7 +73,11 @@
 </template>
 <script>
 import { Login } from "./namespace.js";
-import { getCode, bindUserPhone } from "../api/index";
+import { getCode, bindUserPhone, phoneBind } from "../api/index";
+import getFingerPrintFunc from "../util/fingerprint";
+import { getQueryString, setKeyByWay, getKeyByWay } from "../util/index";
+import { Toast } from "mint-ui";
+
 import qs from "qs";
 import md5 from "js-md5";
 export default {
@@ -83,19 +95,39 @@ export default {
       countTime: "",
       isGoToLogin: false,
       timer: null,
-      send: false
+      send: false,
+      needBind: true
     };
   },
+
   mounted() {
     this.$once("hook:beforeDestroy", () => {
       clearInterval(this.timer);
     });
   },
+  props: {
+    needHeader: {
+      required: false,
+      type: Boolean,
+      default: true
+    },
+    needEmit: {
+      required: false,
+      type: Boolean,
+      default: true
+    },
+    isBind: {
+      required: false,
+      type: Boolean,
+      default: false
+    }
+  },
   methods: {
     //当手机号未填时
     getCodePhoneWrong() {
       this.$Toast("请填写正确的手机号码");
     },
+
     //点击获取二维码
     async getCode() {
       if (this.send) return false;
@@ -119,13 +151,18 @@ export default {
         //验证码倒计时
         this.timer = setInterval(() => {
           if (this.countTime == 0) {
-            clearTimeout(timer);
+            clearTimeout(this.timer);
             this.isPhoneCurrect = 1;
           } else {
             this.countTime--;
           }
         }, 1000);
       } catch (e) {
+        Toast({
+          message: e.data.msg,
+          position: "bottom",
+          duration: 5000
+        });
         this.$Toast(e.data.msg);
         this.send = false;
       }
@@ -135,7 +172,7 @@ export default {
       console.log(this.isAgree);
     },
     //登入操作
-    goToLogin() {
+    async goToLogin() {
       //验证手机号
       let myreg = /^[1][3,4,5,7,8,9][0-9]{9}$/;
       if (!myreg.test(this.phone)) {
@@ -152,19 +189,42 @@ export default {
         this.$Toast("请先阅读用户协议、隐私政策");
         return;
       }
+
+      let fingerprint = await getFingerPrintFunc();
+      let hashuser = getKeyByWay("hashuser") || getQueryString("hashuser");
       //弹出框
-      bindUserPhone({ phone: this.phone, code: this.code })
-        .then(res => {
+      if (this.needBind) {
+        try {
+          await phoneBind({ phone: this.phone, code: this.code });
           this.popupVisible = !this.popupVisible;
-        })
-        .catch(e => {
-          console.log(e);
+        } catch (e) {
           this.$Toast(e.data.msg);
-        });
+        }
+      } else {
+        try {
+          await bindUserPhone({
+            phone: this.phone,
+            code: this.code,
+            fingerprint,
+            hashuser
+          });
+          setKeyByWay("token", res.token);
+          setKeyByWay("hashuser", res.hashuser);
+          this.popupVisible = !this.popupVisible;
+        } catch (e) {
+          this.$Toast(e.data.msg);
+        }
+      }
     },
     //返回上级路由
     goBackRouter() {
-      this.$router.back();
+      //需要头则会跳上极路由
+      if (this.needHeader) {
+        this.$router.back();
+      } else {
+        this.popupVisible = false;
+        this.$emit("loginSuccess", true);
+      }
     },
     phoneChange() {
       console.log(1);
@@ -199,6 +259,9 @@ export default {
       } else {
         this.isGoToLogin = false;
       }
+    },
+    isBind(val) {
+      this.needBind = val;
     }
   },
   computed: {

+ 1 - 7
src/view/book-catalog.vue

@@ -95,7 +95,6 @@ export default {
           defaultIndex: 0,
         },
       ],
-      uuids:'',
       meta: {},
       tempPage: 1,
       handler: function (e) {
@@ -207,7 +206,6 @@ export default {
             chapter_id: cid,
             fee: chapter_cost,
             code: 10021,
-            uuids:this.uuids,
             from_detail_catalog,
             sequence: this.sequence,
             last_cid
@@ -219,8 +217,7 @@ export default {
           query: {
             bid,
             cid,
-            uuids:this.uuids,
-            sendid:this.$route.query.sendid || localStorage.getItem('sendid') || sessionStorage.getItem('sendid'),
+            send_order_id:this.$route.query.send_order_id || localStorage.getItem('send_order_id') || sessionStorage.getItem('send_order_id'),
             from_detail_catalog,
             sequence: this.sequence,
             last_cid
@@ -243,9 +240,6 @@ export default {
   },
   created() {
     if (catalog) {
-      let uuid = localStorage.getItem("uuids");
-      let {uuids } = this.$route.query;
-      this.uuids = uuids || uuid;
       this.catalogs = catalog.data;
       this.meta = catalog.meta;
       if (this.catalogs.length > catalog.meta.per_page) {

+ 1 - 6
src/view/book-detail.vue

@@ -126,7 +126,6 @@ export default {
       prevTime: 0,
       endTime: 0,
       showDebug: false,
-      uuids:''
     };
   },
   methods: {
@@ -144,7 +143,6 @@ export default {
         query: {
           bid: this.book.book_id,
           cid: cid,
-          uuids:this.uuids
         }
       });
     },
@@ -188,9 +186,6 @@ export default {
   },
   created() {
     this.init();
-    let uuid = localStorage.getItem("uuids");
-    let {uuids } = this.$route.query;
-    this.uuids = uuids || uuid;
   },
   beforeRouteUpdate(to, from, next) {
     getDetail(to.query.id, "detail")
@@ -209,7 +204,7 @@ export default {
       pos = to.params.pos;
     }
     let id = to.query.id;
-    if (!id) next({ path: "/", replace: true,query:{uuids:this.uuids} });
+    if (!id) next({ path: "/", replace: true,});
     getDetail(id, "detail", pos)
       .catch(e => {
         let replace_url = e.data.data.url + location.pathname + location.search;

+ 1 - 6
src/view/book-recent.vue

@@ -121,7 +121,6 @@ export default {
       hideBookName: !!window.options.hide_book_name,
       showFreeEntry: window.options.guidepersonalaccount,
       activity_link: window.options.activity_link,
-      uuids:'',
     };
   },
   methods: {
@@ -162,7 +161,6 @@ export default {
         query: {
           bid: book.bid,
           cid: book.cid,
-          uuids:this.uuids
         },
       });
     },
@@ -198,7 +196,7 @@ export default {
         this.ClickStatistics(book.book_id);
         this.$router.push({
           name: BookDetail.name,
-          query: { id: book.book_id,uuids:this.uuids },
+          query: { id: book.book_id },
           params:{pos:'recent_banner'}
         });
       }
@@ -210,9 +208,6 @@ export default {
       this.books = r;
       this.getRecentSwiperList();
     });
-    let uuid = localStorage.getItem("uuids");
-      let {uuids } = this.$route.query;
-      this.uuids = uuids || uuid;
   },
 };
 </script>

+ 1 - 6
src/view/book-shelf.vue

@@ -43,7 +43,6 @@ export default {
       BookRecent: BookRecent.route,
       books: [],
       edit: false,
-      uuids:""
     };
   },
   methods: {
@@ -53,7 +52,6 @@ export default {
         query: {
           bid: book.bid,
           cid: book.last_cid,
-          uuids:this.uuids
         }
       });
     },
@@ -63,7 +61,7 @@ export default {
       });
     },
     addBook() {
-      this.$router.push({name:BookCity.route, query: {uuids:this.uuids }});
+      this.$router.push({name:BookCity.route});
     },
     editChange() {
       this.edit = !this.edit;
@@ -73,9 +71,6 @@ export default {
     getShelf().then(r => {
       this.books = r;
     });
-    let uuid = localStorage.getItem("uuids");
-      let {uuids } = this.$route.query;
-      this.uuids = uuids || uuid;
   }
 };
 </script>

+ 3 - 3
src/view/pay.vue

@@ -518,7 +518,7 @@ export default {
       const last_cid = this.$route.query.last_cid; 
       const bid = this.$route.query.bid;
       const cid = this.$route.query.cid;
-      const sendid = this.$route.query.sendid || localStorage.getItem("sendid");
+      const send_order_id = this.$route.query.send_order_id || localStorage.getItem("send_order_id");
       const yun = this.$route.query.yun;
       const sequence = this.$route.query.sequence
       if(this.$route.query.isRecharge){
@@ -556,7 +556,7 @@ export default {
                   query: {
                     bid: last_bid,
                     cid: last_cid,
-                    sendid,
+                    send_order_id,
                     yun,
                   }
                 })
@@ -580,7 +580,7 @@ export default {
         last_bid: this.$route.query.last_bid,
         last_cid: this.$route.query.last_cid,
         sequence: this.$route.query.sequence,
-        sendid: this.$route.query.sendid,
+        send_order_id: this.$route.query.send_order_id,
         yun: this.$route.query.yun
       })
     },

+ 2 - 5
src/view/person.vue

@@ -42,14 +42,14 @@
         </div>
       </router-link>
       <div style="height: 0.2rem;background-color: #F5F5F5;"></div>
-      <router-link class="person-entry__shelf" :to="{name:Coupon.name,query:{uuids}}" tag="div">
+      <router-link class="person-entry__shelf" :to="{name:Coupon.name}" tag="div">
         <img class="person-entry__icon" src="../assets/my_coupon.png" />
         <span class="person-entry__text">我的优惠券</span>
         <img class="person-entry__arrow" src="../assets/个人中心-进入.png" />
       </router-link>
 
       <hr />
-      <router-link class="person-entry__shelf" :to="{name:BookRecent.name,query:{uuids}}" tag="div">
+      <router-link class="person-entry__shelf" :to="{name:BookRecent.name}" tag="div">
         <img class="person-entry__icon" src="../assets/个人中心-书架.png" />
         <span class="person-entry__text">我的书架</span>
         <img class="person-entry__arrow" src="../assets/个人中心-进入.png" />
@@ -159,9 +159,6 @@ export default {
     getUserInfo().then(r => {
       this.user = r;
     });
-    let uuid = localStorage.getItem("uuids");
-      let {uuids } = this.$route.query;
-      this.uuids = uuids || uuid;
   }
 };
 </script>

+ 271 - 98
src/view/reader.vue

@@ -123,9 +123,9 @@
         </div>
       </transition>
     </div>
-    <div class="add_desk" @touchmove.prevent v-if="addDesktop && !isStandalone">
+    <div class="add_desk" @touchmove.prevent v-if="addDesktop && !isStandalone && !addDesktops">
       <div class="addgif">
-        <template v-if="modes == 'B' ">
+        <template v-if="modes == 'B'">
           <div class="addpng">
             <img src="../../src/assets/addtips.png" width="100%" />
           </div>
@@ -148,7 +148,18 @@
     >
       <img src="../assets/分享.png" />
     </div>
-
+    <mt-popup v-model="loginPop" class="login-pop" position="bottom">
+      <Login
+        :needHeader="false"
+        :needEmit="true"
+        :isBind="isBind"
+        @loginSuccess="loginSuccess"
+      ></Login>
+    </mt-popup>
+    <!--空白页-->
+    <div class="blank_page" v-if="showBlank">
+      <p class="ting">系统维护中~~~~~~~~~~</p>
+    </div>
     <!-- 签到提示入口 -->
     <!-- <template v-if="showSignNoticeWrap">
       <div class="sign-notice__wrap" @click="showSignNoticeWrap = false" @touchmove.prevent>
@@ -172,7 +183,7 @@ import {
   BookShare,
   BookRecent
 } from "./namespace.js";
-import Vue from 'vue';
+import Vue from "vue";
 import {
   SingActive,
   Book1,
@@ -184,6 +195,7 @@ import {
   WeakSubscribe,
   Sign
 } from "../components/prompt";
+import Login from "../view/Login.vue";
 import { popupGift } from "../components/popup";
 import {
   getContent,
@@ -205,7 +217,11 @@ import {
   getRecentReader,
   getUserInfo,
   setUserMode,
-  changeAddMode
+  changeAddMode,
+  newLogin,
+  newRegister,
+  newRefreshToken,
+  newDestoryToken
 } from "../api";
 import {
   clearStorageChapter,
@@ -220,10 +236,16 @@ import {
 import XReader from "../components/reader";
 import bus from "../components/reader/bus.js";
 import goLogin from "../../src/components/gologin";
+import { setKeyByWay, getKeyByWay } from "../util/index";
+import getFingerPrintFunc from "../util/fingerprint";
+import { Popup } from "mint-ui";
+
 export default {
   name: Reader.name,
   components: {
-    "x-reader": XReader
+    "x-reader": XReader,
+    mtPopup: Popup,
+    Login
   },
   data() {
     return {
@@ -235,10 +257,12 @@ export default {
       new_reader: false,
       new_reader_guide1: false,
       new_reader_guide2: false,
+      loginPop: false,
       active: window.options.is_show_activity,
       active_img: window.options.activity_img,
       active_horizontal: false,
       weakSubscribe: false,
+      isBind: false,
       weakSubscribeHorizontal: false,
       weakSubscribeHorizontalNum: 0,
       weakSubscribeStyle: {},
@@ -269,6 +293,7 @@ export default {
       randomBannerIndex: 0,
       guidepersonalaccount: window.options.guidepersonalaccount,
       banners: window.options.banners,
+      showBlank: false,
       showSignNoticeWrap: false,
       collectAndroidBg:
         "//zhuishuyun.oss-cn-hangzhou.aliyuncs.com/h5/android_collect.png",
@@ -278,11 +303,11 @@ export default {
       five_template: "",
       five_template_clicked: true,
       copyVal: "",
-      uuids: "",
+      hashuser: "",
       addDesktop: false,
+      addDestops: false,
       yun: 0,
-      isStandalone:
-        Number(localStorage.getItem("userMode")) || window.navigator.standalone
+      isStandalone: window.navigator.standalone
     };
   },
   computed: {
@@ -306,6 +331,13 @@ export default {
       getRecordShare(this.$route.query.bid, this.$route.query.cid).then(r => {
       }); */
     },
+    loginSuccess(e) {
+      if (e) {
+        this.loginPop = false;
+        goLogin.close();
+        this.getInfo();
+      }
+    },
     activeEv(index) {
       window.location.href = `${
         this.banners[index].jump_url
@@ -336,33 +368,23 @@ export default {
           break;
         case "home":
           this.$router.push({
-            name: BookCity.route,
-            query: {
-              uuids: this.uuids
-            }
+            name: BookCity.route
           });
           break;
         case "category":
           this.$router.push({
-            name: BookStock.route,
-            query: {
-              uuids: this.uuids,
-              sendid: this.$route.query.sendid
-            }
+            name: BookStock.route
           });
           break;
         case "rank":
           this.$router.push({
-            name: Rank.route,
-            query: {
-              uuids: this.uuids
-            }
+            name: Rank.route
           });
           break;
         case "detail":
           this.$router.push({
             name: BookDetail.name,
-            query: { id: this.text.bid, uuids: this.uuids }
+            query: { id: this.text.bid }
           });
           break;
         case "catalog":
@@ -372,20 +394,71 @@ export default {
               ? {
                   id: this.text.bid,
                   sequence: this.text.sequence,
-                  uuids: this.uuids,
-                  sendid: this.$route.query.sendid,
                   yun: this.yun
                 }
               : {
                   id: this.$route.query.bid,
-                  uuids: this.uuids,
-                  sendid: this.$route.query.sendid,
                   yun: this.yun
                 }
           });
           break;
       }
     },
+    async getInfo() {
+      //获取AB测试
+      let modes = await changeAddMode();
+      this.modes = modes.type;
+      let data = await getUserInfo();
+      //老逻辑 没有绑定手机弹窗绑定并且是加桌模式
+      if (!data.bind_phone && window.navigator.standalone) {
+        //付费用户直接强加桌非付费用户弱加桌
+        if (data.paymented && data.paymented >= 1) {
+          goLogin({ showCloseIcon: false }).then(res => {
+            this.loginPop = true;
+            this.isBind = true;
+          });
+        } else {
+          goLogin({ showCloseIcon: true }).then(res => {
+            this.loginPop = true;
+            this.isBind = true;
+          });
+        }
+      }
+
+      // 获取书籍详情
+
+      getDetail(this.$route.query.bid).then(m => {
+        this.bookdetail = m;
+        this.is_on = !!m.is_on_user_shelf;
+      });
+
+      // 获取章节内容
+      let isFromCatalog = !!~window.prevPage.indexOf("/catalog");
+      let page_from = isFromCatalog ? "chapter_dir" : "";
+
+      this.getContent(
+        this.$route.query.bid,
+        this.$route.query.cid,
+        "",
+        page_from
+      )
+        .then(r => {
+          this.text = r;
+          this.isFromSubscribe = false;
+          if (this.text.force_add_desk_type) {
+            if (!this.addDesktop) this.addDesktop = true;
+          }
+          if (r.sign_status) {
+            this.showSignNoticeWrap = true;
+          }
+        })
+        .catch(r => {
+          console.log("get content err", r);
+          this.text = {
+            content: r.msg
+          };
+        });
+    },
     addShelf() {
       addShelf(this.text.bid).then(r => {
         this.is_on = true;
@@ -403,19 +476,16 @@ export default {
             query: {
               bid: this.text.bid,
               cid: this.text.next_cid,
-              uuids: this.uuids,
-              sendid:
-                this.$route.query.sendid || localStorage.getItem("sendid"),
               yun: this.yun,
               last_bid: this.text.bid,
               last_cid: this.text.prev_cid,
-              from_detail_catalog:3
+              from_detail_catalog: 3
             }
           });
         } else if (this.text.next_cid === 0) {
           this.$router.push({
             name: BookRecommend.name,
-            query: { bid: this.$route.query.bid, uuids: this.uuids }
+            query: { bid: this.$route.query.bid }
           });
         } else {
           this.$Toast("系统错误");
@@ -429,10 +499,8 @@ export default {
           query: {
             bid: this.text.bid,
             cid: this.text.prev_cid,
-            uuids: this.uuids,
-            sendid: this.$route.query.sendid || localStorage.getItem("sendid"),
             yun: this.yun,
-            from_detail_catalog:3
+            from_detail_catalog: 3
           },
           params: {
             jump: -1
@@ -470,8 +538,7 @@ export default {
           name: Reader.name,
           query: {
             bid: bid,
-            cid: cid,
-            uuids: this.uuids
+            cid: cid
           }
         });
       }
@@ -498,12 +565,12 @@ export default {
         .catch(r => {
           this.loading = false;
           const data = r.data.data;
-          const sequence = this.$route.query.sequence
-          const last_bid = this.$route.query.bid
-          const last_cid = this.$route.query.cid
-          const from_detail_catalog = this.$route.query.from_detail_catalog
-          const sendid = this.$route.query.sendid
-          const yun = this.$route.query.yun
+          const sequence = this.$route.query.sequence;
+          const last_bid = this.$route.query.bid;
+          const last_cid = this.$route.query.cid;
+          const from_detail_catalog = this.$route.query.from_detail_catalog;
+          const send_order_id = this.$route.query.send_order_id;
+          const yun = this.$route.query.yun;
           switch (r.data.code) {
             case 10012:
               if (this.is_update) {
@@ -532,7 +599,16 @@ export default {
               break;
             case 10015:
               Chapter1(data).then(r => {
-                this.$router.push({ name: Pay.name, query: data, sequence, last_bid, last_cid, sendid, yun, from_detail_catalog });
+                this.$router.push({
+                  name: Pay.name,
+                  query: data,
+                  sequence,
+                  last_bid,
+                  last_cid,
+                  send_order_id,
+                  yun,
+                  from_detail_catalog
+                });
               });
               break;
             case 10016:
@@ -565,7 +641,16 @@ export default {
             case 10019:
               Book3(r.data.data)
                 .then(r => {
-                  this.$router.push({ name: Pay.name, query: data, sequence, last_bid, last_cid, sendid, yun, from_detail_catalog });
+                  this.$router.push({
+                    name: Pay.name,
+                    query: data,
+                    sequence,
+                    last_bid,
+                    last_cid,
+                    send_order_id,
+                    yun,
+                    from_detail_catalog
+                  });
                 })
                 .catch(e => {
                   if (e === "close") {
@@ -580,7 +665,16 @@ export default {
             case 10021:
               this.$router.push({
                 name: Pay.name,
-                query: { ...data, code: r.data.code, sequence, last_bid, last_cid, sendid, yun, from_detail_catalog }
+                query: {
+                  ...data,
+                  code: r.data.code,
+                  sequence,
+                  last_bid,
+                  last_cid,
+                  send_order_id,
+                  yun,
+                  from_detail_catalog
+                }
               });
               break;
             case 10022:
@@ -707,7 +801,7 @@ export default {
     },
     justifyRouter(router) {
       if (!router.query.bid) {
-        this.$router.replace({ path: "/", query: { uuids: this.uuids } });
+        this.$router.replace({ path: "/" });
         return false;
       }
       if (typeof router.query.bid !== "string") {
@@ -715,8 +809,7 @@ export default {
           name: Reader.name,
           query: {
             bid: router.query.bid[0],
-            cid: router.query.cid,
-            uuids: this.uuids
+            cid: router.query.cid
           }
         });
         return false;
@@ -726,7 +819,6 @@ export default {
           query: {
             bid: router.query.bid.split(",")[0],
             cid: router.query.cid,
-            uuids: this.uuids,
             yun: this.yun
           }
         });
@@ -758,78 +850,133 @@ export default {
     }
   },
   async created() {
-    let uuid = localStorage.getItem("uuids");
-    let { yun, bid, cid, uuids, sendid = 0, isreplace = 0 } = this.$route.query;
-    if (sendid){
-      localStorage.setItem("sendid", this.$route.query.sendid);
-      sessionStorage.setItem("sendid", this.$route.query.sendid);
-       Vue.prototype.sendid = sendid;
-    } 
-    this.uuids = uuids || uuid;
+    let {
+      yun,
+      bid,
+      cid,
+      send_order_id = 0,
+      hashuser: hashUser,
+      isreplace = 0,
+      token: urlToken
+    } = this.$route.query;
+    //存入派单id
+    if (send_order_id) setKeyByWay("send_order_id", send_order_id);
+    //获取
+    //是否从派单链接进来的标识
     if (yun) this.yun = yun;
 
-    let data = await getUserInfo();
-    if (!data.bind_phone && window.navigator.standalone) {
-      goLogin();
+    let addDestops = getKeyByWay("addDestop");
+    if (addDestops == "true" || addDestops == true) {
+      this.addDestops = true;
     }
-
-    const token = localStorage.getItem("token");
-    if (token) {
+    //处理用户逻辑
+    const token = getKeyByWay("token");
+    if (token) { 
+      //有token 上报加桌状态
       setUserMode(
         Number(window.navigator.standalone) || 0,
-        sendid
+        send_order_id
       ).then(res => {});
+
+      this.getInfo();
+    } else {
+      //如果不是加桌图标进入阅读器,无token直接空白
+      if (!window.navigator.standalone) {
+        if (urlToken) {
+          //先存本地
+          setKeyByWay("token", urlToken);
+          try {
+            const { token, hashuser } = await newRefreshToken({
+              hashuser: hashUser,
+              token: urlToken
+            });
+            setKeyByWay("token", token);
+            setKeyByWay("hashuser", hashuser);
+            this.getInfo();
+          } catch (e) {
+            this.$Toast(e.data.msg);
+          }
+          //拿到token 先作废旧token在保存新token;
+          try {
+            await newDestoryToken({ destroy_token: urlToken });
+          } catch (e) {
+            this.$Toast(e.data.msg);
+          }
+        } else {
+          this.showBlank = true;
+        }
+      } else {
+        //加桌状态下分为url带token和url不带token,url带token用url token去进行登录,不带token 前端通过hashuser去登陆
+        if (urlToken) {
+          //先存本地
+          setKeyByWay("token", urlToken);
+          try {
+            const { token, hashuser } = await newRefreshToken({
+              hashuser: hashUser,
+              token: urlToken
+            });
+            setKeyByWay("token", token);
+            setKeyByWay("hashuser", hashuser);
+            this.getInfo();
+          } catch (e) {
+            this.$Toast(e.data.msg);
+          }
+
+          //拿到token 先作废旧token在保存新token;
+          try {
+            await newDestoryToken({ destroy_token: urlToken });
+          } catch (e) {
+            this.$Toast(e.data.msg);
+          }
+        } else {
+          //url没有token用本地的密钥尝试登录
+          let fingerprint = await getFingerPrintFunc();
+          const params = {
+            send_order_id: send_order_id,
+            fingerprint,
+            hashuser: hashUser
+          };
+
+          //登陆成功说明就是这个用户登录失败弹出手机号进一步校验
+          try {
+            const { token, hashuser } = await newLogin(params);
+            setKeyByWay("token", token);
+            setKeyByWay("hashuser", hashuser);
+            this.getInfo();
+          } catch (e) {
+            goLogin({ showCloseIcon: false }).then(res => {
+              this.loginPop = true;
+              this.isBind = false;
+            });
+          }
+        }
+      }
     }
 
+    //加桌用户每次都打开同一个链接为了阅读体验 只有第一页面是阅读器 && 全屏模式下&& 有加桌标识(证明是派单链接强加桌加桌)&&是否替换标识(--避免版权跳转重新走逻辑回到上一章阅读记录死循环)才会加载用户阅读记录
     if (
       yun == "1" &&
       window.firstName == this.$route.name &&
       window.navigator.standalone &&
       isreplace != "1"
     ) {
+      //获取阅读记录并且跳转
       let sare = await getRecentReader();
 
       if (sare.bid && sare.cid != cid) {
         this.$router.replace(
-          `/reader?bid=${sare.bid}&cid=${sare.cid}&yun=${yun}&uuids=${this.uuids}&sendid=${sendid}`
+          `/reader?bid=${sare.bid}&cid=${sare.cid}&yun=${yun}&hashuser=${this.hashuser}&send_order_id=${send_order_id}`
         );
         return;
       }
     }
+
     if (!this.justifyRouter(this.$route)) return;
     this.href = window.location.href;
-    // 获取书籍详情
-
-    //获取AB测试
-    let modes = await changeAddMode();
-    this.modes = modes.type;
-
-    getDetail(this.$route.query.bid).then(m => {
-      this.bookdetail = m;
-      this.is_on = !!m.is_on_user_shelf;
-    });
-
-    // 获取章节内容
-    let isFromCatalog = !!~window.prevPage.indexOf("/catalog");
-    let page_from = isFromCatalog ? "chapter_dir" : "";
-
-    this.getContent(this.$route.query.bid, this.$route.query.cid, "", page_from)
-      .then(r => {
-        this.text = r;
-        this.isFromSubscribe = false;
-        if (this.text.force_add_desk_type) {
-          if (!this.addDesktop) this.addDesktop = true;
-        }
-        if (r.sign_status) {
-          this.showSignNoticeWrap = true;
-        }
-      })
-      .catch(r => {
-        console.log("get content err", r);
-        this.text = {
-          content: r.msg
-        };
-      });
+  },
+  //路由销毁时,直接关闭弹窗
+  beforeDestroy() {
+    goLogin.close();
   },
   async beforeRouteEnter(to, from, next) {
     if (from.name !== BookCatalog.name && from.name !== Subscribe.name) {
@@ -913,6 +1060,27 @@ export default {
 };
 </script>
 <style lang="scss">
+.blank_page {
+  position: fixed;
+  background-color: #fff;
+  width: 100vw;
+  height: 100vh;
+  top: 0;
+  left: 0;
+  z-index: 9999;
+  .ting {
+    position: absolute;
+    width: 300px;
+    height: 300px;
+    line-height: 300px;
+    text-align: center;
+    margin: auto;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+  }
+}
 .reader-active {
   font-size: 17px;
   color: #ff3b00;
@@ -1276,4 +1444,9 @@ export default {
     width: 100%;
   }
 }
+
+.login-pop {
+  width: 100%;
+  height: 100%;
+}
 </style>

+ 39 - 9
src/view/yun.vue

@@ -4,20 +4,49 @@
 
 <script>
 import { Yun } from "./namespace";
-import { getYun,login } from "../api";
-import Vue from 'vue';
+import { getYun, newLogin, newRegister } from "../api";
+import { setKeyByWay, getKeyByWay } from "../util/index";
+import getFingerPrintFunc from "../util/fingerprint";
+
+import Vue from "vue";
 export default {
   name: Yun.name,
   data() {
     return {};
   },
-  created() {
+  async created() {
     if (this.$route.params.id) {
-      Vue.prototype.sendid = this.$route.params.id;
-      localStorage.setItem("sendid", this.$route.params.id);
-      sessionStorage.setItem("sendid", this.$route.params.id);
-      this.getYun();
-      
+      //存入send_order_id,并且获取token;
+      setKeyByWay("send_order_id", this.$route.params.id);
+      let token = getKeyByWay("token");
+      //如果不存在token
+      if (!token) {
+        //生成指纹
+        let fingerprint = await getFingerPrintFunc();
+        const params = {
+          send_order_id: this.$route.params.id,
+          fingerprint
+        };
+        //尝试注册新用户
+        const data = await newRegister(params);
+        //判断是否老用户老用户直接去看书
+        if (data && data.old_user == 1) {
+          setKeyByWay("token", data.token);
+          setKeyByWay("hashuser", data.hashuser);
+          this.getYun();
+        } else {
+          //不是老用户还要登录
+          const loginParams = Object.assign(params, {
+            hashuser: data.hashuser
+          });
+          const { token, hashuser } = await newLogin(loginParams);
+          setKeyByWay("token", token);
+          setKeyByWay("hashuser", hashuser);
+          this.getYun();
+        }
+      } else {
+        this.getYun();
+      }
     } else {
       this.$router.replace("/");
     }
@@ -30,7 +59,8 @@ export default {
           this.$router.replace("/");
         } else {
           this.$router.replace(
-            `/reader?yun=1&bid=${bid}&cid=${cid}&sendid=${this.$route.params.id  || 0}`
+            `/reader?yun=1&bid=${bid}&cid=${cid}&send_order_id=${this.$route
+              .params.id || 0}`
           );
         }
       });

+ 17 - 0
yarn.lock

@@ -2,6 +2,13 @@
 # yarn lockfile v1
 
 
+"@fingerprintjs/fingerprintjs@^3.3.3":
+  version "3.3.3"
+  resolved "https://registry.npmmirror.com/@fingerprintjs/fingerprintjs/-/fingerprintjs-3.3.3.tgz#ead445032c92a79d5f585953019402ed223edc7d"
+  integrity sha512-HH6KqZnopF3NIXypYG4f2qxoSRmGCSzp81wJMfWjSTtvsX3cAg12RFJcm+a6Az3XadcZUrXKW3p5Dv0wyCUeuA==
+  dependencies:
+    tslib "^2.0.1"
+
 "@types/q@^1.5.1":
   version "1.5.4"
   resolved "https://registry.npm.taobao.org/@types/q/download/@types/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24"
@@ -1909,6 +1916,11 @@ cross-spawn@^5.0.1:
     shebang-command "^1.2.0"
     which "^1.2.9"
 
+cross-storage@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.npmmirror.com/cross-storage/-/cross-storage-1.0.0.tgz#70950377241484f17ce9559b05d2e08448e17660"
+  integrity sha512-PkAi+2MD6T17klbIjRSGs5ku4AM97/1CYrWEJtClrw8UYLXq709+o92FfW+Q2uDPlv4PMMsa59dJNRIwjWReuw==
+
 crypto-browserify@^3.11.0:
   version "3.12.0"
   resolved "https://registry.npm.taobao.org/crypto-browserify/download/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec"
@@ -7186,6 +7198,11 @@ tryer@^1.0.0:
   resolved "https://registry.npm.taobao.org/tryer/download/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8"
   integrity sha1-8shUBoALmw90yfdGW4HqrSQSUvg=
 
+tslib@^2.0.1:
+  version "2.4.0"
+  resolved "https://registry.npmmirror.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3"
+  integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==
+
 tty-browserify@0.0.0:
   version "0.0.0"
   resolved "https://registry.npm.taobao.org/tty-browserify/download/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"