reader.vue 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279
  1. <template>
  2. <div
  3. ref="reader-wrap"
  4. :class="[
  5. 'reader',
  6. { 'reader-fixed': five_template && !five_template_clicked }
  7. ]"
  8. >
  9. <x-reader
  10. ref="reader"
  11. :class="{
  12. 'x-reader--subscribe': weakSubscribe,
  13. 'x-reader--subscribe__qrcode':
  14. (subscribeQRcode && !subscribeQRcodeHorizontal) || active
  15. }"
  16. :text="text"
  17. :ad="showAdStatus"
  18. :adframe="showAdIframe"
  19. :gift="true"
  20. :shelf="is_on"
  21. :showFans="showFans"
  22. @route="go"
  23. @addShelf="addShelf"
  24. @next="next"
  25. @prev="prev"
  26. @direction="direction"
  27. @horizontal-mounted="horizontalMounted"
  28. @closeBanner="closeBanner"
  29. @vertical-mounted="verticalMounted"
  30. >
  31. <!-- 底部标题 -->
  32. <template v-if="text.push_title && text.push_title.length">
  33. <v-touch slot="ufooter" class="title_list">
  34. <div class="title">猜你喜欢</div>
  35. <div class="title-list-box">
  36. <v-touch
  37. class="title-item"
  38. v-for="(t, i) in text.push_title"
  39. :key="i"
  40. @tap="jumpNovel(t.link)"
  41. >
  42. <p>{{ t.title }}</p>
  43. <img :src="t.img" :alt="t.title" />
  44. </v-touch>
  45. </div>
  46. </v-touch>
  47. </template>
  48. <!-- 活动添加 -->
  49. <template v-if="banners.length">
  50. <mt-swipe
  51. slot="ufooter"
  52. v-show="!loading"
  53. class="reader-footer__banners"
  54. >
  55. <mt-swipe-item v-for="(b, index) in banners" :key="index">
  56. <v-touch @tap="activeEv(index)">
  57. <img v-lazy="b.img" alt="" />
  58. </v-touch>
  59. </mt-swipe-item>
  60. </mt-swipe>
  61. </template>
  62. <!-- <template>
  63. <v-touch class="click-toCollection" @tap="showCollectionWrap = true"
  64. >&gt;&gt;点击此处,收藏本书&lt;&lt;</v-touch
  65. >
  66. </template> -->
  67. <!-- 引导文字链 -->
  68. <template v-if="bannerSubText.title">
  69. <v-touch class="click-toCollection" @tap="bannerSubEv">{{
  70. bannerSubText.title
  71. }}</v-touch>
  72. </template>
  73. </x-reader>
  74. <div class="reader-loading" v-show="loading">
  75. <mt-spinner
  76. class="reader-loading-icon"
  77. type="fading-circle"
  78. color="#32a1ff"
  79. ></mt-spinner>
  80. </div>
  81. <div class="reader-guide" v-if="new_reader && !hideGuide">
  82. <transition name="fade" @after-leave="new_reader_guide2 = true">
  83. <div
  84. class="reader-guide-1"
  85. v-if="new_reader_guide1"
  86. @click="new_reader_guide1 = false"
  87. >
  88. <div class="reader-guide-1-1"></div>
  89. <div class="reader-guide-1-2"></div>
  90. <div class="reader-guide-1-3"></div>
  91. <div class="reader-guide-1-4">
  92. <img
  93. src="https://zhuishuyun.oss-cn-hangzhou.aliyuncs.com/static/img/uppage.png"
  94. />
  95. </div>
  96. <div class="reader-guide-1-5">
  97. <img
  98. src="https://zhuishuyun.oss-cn-hangzhou.aliyuncs.com/static/img/readermiddel.png"
  99. />
  100. </div>
  101. <div class="reader-guide-1-6">
  102. <img
  103. src="https://zhuishuyun.oss-cn-hangzhou.aliyuncs.com/static/img/downpage.png"
  104. />
  105. </div>
  106. <div class="reader-guide-1-7"></div>
  107. <div class="reader-guide-1-8"></div>
  108. <div class="reader-guide-1-9"></div>
  109. </div>
  110. </transition>
  111. <transition name="fade" @after-leave="new_reader = false">
  112. <div
  113. v-if="new_reader_guide2"
  114. @click="new_reader_guide2 = false"
  115. class="reader-guide-2"
  116. >
  117. <img
  118. src="https://zhuishuyun.oss-cn-hangzhou.aliyuncs.com/static/img/readremind.png"
  119. />
  120. </div>
  121. </transition>
  122. </div>
  123. <div class="add_desk" @touchmove.prevent v-if="addDesktop && !isStandalone">
  124. <div class="addgif">
  125. <template v-if="modes == 'B' ">
  126. <div class="addpng">
  127. <img src="../../src/assets/addtips.png" width="100%" />
  128. </div>
  129. <div class="add-gif">
  130. <img src="../../src/assets/adddeskot.gif" />
  131. </div>
  132. </template>
  133. <template v-else>
  134. <div class="popimg">
  135. <img src="../assets/popimg.png" width="100%" />
  136. </div>
  137. </template>
  138. </div>
  139. </div>
  140. <div
  141. class="share"
  142. @touchmove.prevent
  143. v-show="isshowshare"
  144. @click="isshowshare = !isshowshare"
  145. >
  146. <img src="../assets/分享.png" />
  147. </div>
  148. <!-- 签到提示入口 -->
  149. <!-- <template v-if="showSignNoticeWrap">
  150. <div class="sign-notice__wrap" @click="showSignNoticeWrap = false" @touchmove.prevent>
  151. <img src="../assets/sign_notice__wrap.png"
  152. alt="">
  153. </div>
  154. </template> -->
  155. </div>
  156. </template>
  157. <script>
  158. import {
  159. Reader,
  160. BookCity,
  161. BookStock,
  162. Rank,
  163. BookDetail,
  164. BookCatalog,
  165. BookRecommend,
  166. Pay,
  167. Subscribe,
  168. BookShare,
  169. BookRecent
  170. } from "./namespace.js";
  171. import Vue from 'vue';
  172. import {
  173. SingActive,
  174. Book1,
  175. Book2,
  176. Book3,
  177. Book4,
  178. Chapter1,
  179. Chapter2,
  180. WeakSubscribe,
  181. Sign
  182. } from "../components/prompt";
  183. import { popupGift } from "../components/popup";
  184. import {
  185. getContent,
  186. addShelf,
  187. getDetail,
  188. getError,
  189. subscribeByRMB,
  190. subscribeByBalance,
  191. getweakSubscribeQR,
  192. chapterComment,
  193. getChapterComment,
  194. getGiftList,
  195. sendGift,
  196. getSendGiftRecord,
  197. getRecordShare,
  198. getWechatJsConfig,
  199. recordAdClickStatus,
  200. getReaderAdBanner,
  201. getRecentReader,
  202. getUserInfo,
  203. setUserMode,
  204. changeAddMode
  205. } from "../api";
  206. import {
  207. clearStorageChapter,
  208. loadIframeAsync,
  209. removeIframe,
  210. crmBannerRandom,
  211. getRandomCode,
  212. clipboard,
  213. needToCopy,
  214. recordCode
  215. } from "../util";
  216. import XReader from "../components/reader";
  217. import bus from "../components/reader/bus.js";
  218. import goLogin from "../../src/components/gologin";
  219. export default {
  220. name: Reader.name,
  221. components: {
  222. "x-reader": XReader
  223. },
  224. data() {
  225. return {
  226. showFans: false,
  227. readerOptions: bus.preset,
  228. text: {},
  229. is_on: true,
  230. loading: true,
  231. new_reader: false,
  232. new_reader_guide1: false,
  233. new_reader_guide2: false,
  234. active: window.options.is_show_activity,
  235. active_img: window.options.activity_img,
  236. active_horizontal: false,
  237. weakSubscribe: false,
  238. weakSubscribeHorizontal: false,
  239. weakSubscribeHorizontalNum: 0,
  240. weakSubscribeStyle: {},
  241. firstReader: false,
  242. modes: "A",
  243. weakSubscribeText: [
  244. "【更多精彩内容 请点击阅读】",
  245. "【点击阅读海量小说】"
  246. ],
  247. subscribeQRcode: true,
  248. subscribeQRcodeHorizontal: true,
  249. isChannel123: window.options.distribution_channel_id === 123,
  250. subscribeQrcodeImg: window.options.special_bottom_sub_banner,
  251. chooseTap: "",
  252. canTap: true,
  253. hideGuide: window.options.hidden_reader_bootstrap,
  254. showComment: false,
  255. showGift: false,
  256. isshowshare: false,
  257. bookdetail: {},
  258. href: "",
  259. showAdStatus: false,
  260. showAdIframe: false,
  261. canBeClickToNext: true,
  262. isFree: require("../assets/to_free.png"),
  263. isOrder: require("../assets/to_pay.png"),
  264. freeTimes: 0,
  265. randomBannerIndex: 0,
  266. guidepersonalaccount: window.options.guidepersonalaccount,
  267. banners: window.options.banners,
  268. showSignNoticeWrap: false,
  269. collectAndroidBg:
  270. "//zhuishuyun.oss-cn-hangzhou.aliyuncs.com/h5/android_collect.png",
  271. collectIOSBg:
  272. "//zhuishuyun.oss-cn-hangzhou.aliyuncs.com/h5/iphone_collect.png",
  273. bannerSubText: {},
  274. five_template: "",
  275. five_template_clicked: true,
  276. copyVal: "",
  277. uuids: "",
  278. addDesktop: false,
  279. yun: 0,
  280. isStandalone:
  281. Number(localStorage.getItem("userMode")) || window.navigator.standalone
  282. };
  283. },
  284. computed: {
  285. chapterText() {
  286. return this.text.content;
  287. }
  288. },
  289. methods: {
  290. closeBanner() {
  291. let readQuery = localStorage.getItem("readQuery");
  292. if (readQuery) {
  293. readQuery = JSON.parse(readQuery);
  294. readQuery.isClose = true;
  295. localStorage.setItem("readQuery", JSON.stringify(readQuery));
  296. }
  297. this.showFans = false;
  298. },
  299. share() {
  300. /* this.isshowshare = !this.isshowshare;
  301. getRecordShare(this.$route.query.bid, this.$route.query.cid).then(r => {
  302. }); */
  303. },
  304. activeEv(index) {
  305. window.location.href = `${
  306. this.banners[index].jump_url
  307. }&redirect_url=${encodeURIComponent(window.location.href)}`;
  308. },
  309. bannerSubEv() {
  310. window.location.href = `${
  311. this.bannerSubText.jump_url
  312. }&redirect_url=${encodeURIComponent(window.location.href)}`;
  313. },
  314. getUuid() {
  315. var s = [];
  316. var hexDigits = "0123456789abcdef";
  317. for (var i = 0; i < 36; i++) {
  318. s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
  319. }
  320. s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
  321. s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
  322. s[8] = s[13] = s[18] = s[23] = "-";
  323. var uuid = s.join("");
  324. return uuid;
  325. },
  326. go(name) {
  327. switch (name) {
  328. case "back":
  329. history.back(-1);
  330. break;
  331. case "home":
  332. this.$router.push({
  333. name: BookCity.route,
  334. query: {
  335. uuids: this.uuids
  336. }
  337. });
  338. break;
  339. case "category":
  340. this.$router.push({
  341. name: BookStock.route,
  342. query: {
  343. uuids: this.uuids,
  344. sendid: this.$route.query.sendid
  345. }
  346. });
  347. break;
  348. case "rank":
  349. this.$router.push({
  350. name: Rank.route,
  351. query: {
  352. uuids: this.uuids
  353. }
  354. });
  355. break;
  356. case "detail":
  357. this.$router.push({
  358. name: BookDetail.name,
  359. query: { id: this.text.bid, uuids: this.uuids }
  360. });
  361. break;
  362. case "catalog":
  363. this.$router.push({
  364. name: BookCatalog.name,
  365. query: this.text.bid
  366. ? {
  367. id: this.text.bid,
  368. sequence: this.text.sequence,
  369. uuids: this.uuids,
  370. sendid: this.$route.query.sendid,
  371. yun: this.yun
  372. }
  373. : {
  374. id: this.$route.query.bid,
  375. uuids: this.uuids,
  376. sendid: this.$route.query.sendid,
  377. yun: this.yun
  378. }
  379. });
  380. break;
  381. }
  382. },
  383. addShelf() {
  384. addShelf(this.text.bid).then(r => {
  385. this.is_on = true;
  386. this.$Toast("加入书架成功");
  387. });
  388. },
  389. next() {
  390. // 静默复制
  391. if (this.text.next_jump) {
  392. location.href = this.text.next_jump_url;
  393. } else {
  394. if (this.text.next_cid) {
  395. this.$router.replace({
  396. path: `/reader/${this.getUuid()}/`,
  397. query: {
  398. bid: this.text.bid,
  399. cid: this.text.next_cid,
  400. uuids: this.uuids,
  401. sendid:
  402. this.$route.query.sendid || localStorage.getItem("sendid"),
  403. yun: this.yun,
  404. last_bid: this.text.bid,
  405. last_cid: this.text.prev_cid,
  406. from_detail_catalog:3
  407. }
  408. });
  409. } else if (this.text.next_cid === 0) {
  410. this.$router.push({
  411. name: BookRecommend.name,
  412. query: { bid: this.$route.query.bid, uuids: this.uuids }
  413. });
  414. } else {
  415. this.$Toast("系统错误");
  416. }
  417. }
  418. },
  419. prev() {
  420. if (this.text.prev_cid) {
  421. this.$router.replace({
  422. name: Reader.name,
  423. query: {
  424. bid: this.text.bid,
  425. cid: this.text.prev_cid,
  426. uuids: this.uuids,
  427. sendid: this.$route.query.sendid || localStorage.getItem("sendid"),
  428. yun: this.yun,
  429. from_detail_catalog:3
  430. },
  431. params: {
  432. jump: -1
  433. }
  434. });
  435. } else {
  436. this.$Toast("第一章!");
  437. }
  438. },
  439. direction(val) {
  440. if (val === "horizontal" && !localStorage.getItem("old_reader")) {
  441. this.bus.$emit("menu");
  442. localStorage.setItem("old_reader", "true");
  443. this.new_reader = true;
  444. this.$nextTick(() => {
  445. this.new_reader_guide1 = true;
  446. });
  447. }
  448. this.weakSubscribeStyle = {};
  449. },
  450. subscribe({ bid, chapter_id: cid }) {
  451. if (this.$route.query.bid == bid && this.$route.query.cid == cid) {
  452. this.getContent(this.$route.query.bid, this.$route.query.cid)
  453. .then(r => {
  454. this.text = r;
  455. if (this.text.force_add_desk_type) {
  456. if (!this.addDesktop) this.addDesktop = true;
  457. }
  458. })
  459. .catch(r => {
  460. this.text = {};
  461. });
  462. } else {
  463. this.$router.replace({
  464. name: Reader.name,
  465. query: {
  466. bid: bid,
  467. cid: cid,
  468. uuids: this.uuids
  469. }
  470. });
  471. }
  472. },
  473. getContent(bid, cid, next, from, code) {
  474. //由于beforeRouteUpdate钩子函数会调用getContent,所以路由或者页面跳转不应该在在此函数,不然会造beforeRouteUpdate钩子函数的next不被调用
  475. /*
  476. 错误处理
  477. 10012 未关注
  478. 10014 全本订阅余额不足(rmb)
  479. 10015 章订余额不足(充值)
  480. 10016 购买章节(书币)
  481. 10017 购买图书(书币)
  482. 10019 全本订阅余额不足(充值)
  483. 10023 未关注 (跳转渠道接诶)
  484. ----- 以上是弹窗 -------
  485. 10020 全本订阅余额不足,直接进入充值页
  486. 10021 章节订阅余额不足,直接进入充值页
  487. 10022 进入版权站
  488. */
  489. this.loading = true;
  490. let adStatus = 0;
  491. return getContent(bid, cid, adStatus, from, code)
  492. .catch(r => {
  493. this.loading = false;
  494. const data = r.data.data;
  495. const sequence = this.$route.query.sequence
  496. const last_bid = this.$route.query.bid
  497. const last_cid = this.$route.query.cid
  498. const from_detail_catalog = this.$route.query.from_detail_catalog
  499. const sendid = this.$route.query.sendid
  500. const yun = this.$route.query.yun
  501. switch (r.data.code) {
  502. case 10012:
  503. if (this.is_update) {
  504. r.url = data.src;
  505. } else {
  506. // this.$router.push({
  507. // name: Subscribe.name,
  508. // query: { src: data.src, head_img: data.head_img }
  509. // });
  510. location.replace(data.src);
  511. }
  512. break;
  513. case 10014:
  514. Book2(data)
  515. .then(r => {
  516. subscribeByRMB(data);
  517. })
  518. .catch(e => {
  519. if (e === "close") {
  520. if (!localStorage.getItem("rc")) {
  521. // this.$router.back();
  522. history.back();
  523. }
  524. }
  525. });
  526. break;
  527. case 10015:
  528. Chapter1(data).then(r => {
  529. this.$router.push({ name: Pay.name, query: data, sequence, last_bid, last_cid, sendid, yun, from_detail_catalog });
  530. });
  531. break;
  532. case 10016:
  533. Chapter2(data).then(r => {
  534. this.loading = true;
  535. subscribeByBalance(
  536. data.book_id,
  537. data.chapter_id,
  538. r.checked
  539. ).then(r => {
  540. this.subscribe(r);
  541. });
  542. });
  543. break;
  544. case 10017:
  545. Book4(data)
  546. .then(r => {
  547. this.loading = true;
  548. subscribeByBalance(data.book_id, data.chapter_id).then(r => {
  549. this.subscribe(r);
  550. });
  551. })
  552. .catch(e => {
  553. if (!localStorage.getItem("rc")) {
  554. // this.$router.back();
  555. history.back();
  556. }
  557. });
  558. break;
  559. case 10019:
  560. Book3(r.data.data)
  561. .then(r => {
  562. this.$router.push({ name: Pay.name, query: data, sequence, last_bid, last_cid, sendid, yun, from_detail_catalog });
  563. })
  564. .catch(e => {
  565. if (e === "close") {
  566. if (!localStorage.getItem("rc")) {
  567. // this.$router.back();
  568. history.back();
  569. }
  570. }
  571. });
  572. break;
  573. case 10020:
  574. case 10021:
  575. this.$router.push({
  576. name: Pay.name,
  577. query: { ...data, code: r.data.code, sequence, last_bid, last_cid, sendid, yun, from_detail_catalog }
  578. });
  579. break;
  580. case 10022:
  581. location.replace(
  582. `${data.url}&yun=${this.yun}&isreplace=${
  583. window.navigator.standalone ? 1 : 0
  584. }`
  585. );
  586. break;
  587. case 10023:
  588. location.assign(data.url);
  589. break;
  590. default:
  591. break;
  592. }
  593. return Promise.reject(r);
  594. })
  595. .then(r => {
  596. this.subscribeQRcode = r.is_had_subscribe;
  597. this.loading = false;
  598. this.weakSubscribe = !!r.is_show_subscribe_link;
  599. this.canTap = !!r.chapter_comment;
  600. this.chooseTap = r.chapter_comment;
  601. this.recordReadChapter();
  602. //是否显示个人banner
  603. let readQuery = localStorage.getItem("readQuery");
  604. if (readQuery) {
  605. readQuery = JSON.parse(readQuery);
  606. let cur = new Date().toDateString();
  607. let time = new Date(readQuery.lastReadTime).toDateString();
  608. if (cur != time) {
  609. localStorage.removeItem("readTemp");
  610. readQuery.lastReadTime = new Date();
  611. readQuery.isClose = false;
  612. localStorage.setItem("readQuery", JSON.stringify(readQuery));
  613. }
  614. } else {
  615. let data = {
  616. lastReadTime: new Date(),
  617. firstReadTime: new Date(),
  618. isClose: false
  619. };
  620. localStorage.setItem("readQuery", JSON.stringify(data));
  621. }
  622. let readerTemp = localStorage.getItem("readTemp");
  623. if (readerTemp) {
  624. let temp = JSON.parse(readerTemp);
  625. let same = false;
  626. let allweek = false;
  627. temp.map(item => {
  628. if (item.bid == bid && item.cid == cid) same = true;
  629. });
  630. if (!same) {
  631. temp.push({ bid: bid, cid: cid });
  632. localStorage.setItem("readTemp", JSON.stringify(temp));
  633. }
  634. if (readQuery) {
  635. let firstTime = new Date(
  636. JSON.parse(localStorage.getItem("readQuery")).firstReadTime
  637. );
  638. let firstTimeZero = new Date(firstTime.toLocaleDateString());
  639. if (Math.abs(firstTimeZero - new Date()) < 7 * 24 * 3600 * 1000) {
  640. allweek = false;
  641. } else {
  642. allweek = true;
  643. }
  644. if (
  645. temp.length >= 4 &&
  646. temp.length <= 22 &&
  647. temp.length % 2 == 0 &&
  648. !readQuery.isClose &&
  649. !allweek
  650. ) {
  651. this.showFans = true;
  652. } else {
  653. this.showFans = false;
  654. }
  655. }
  656. } else {
  657. let temp = [
  658. { bid: this.$route.query.bid, cid: this.$route.query.cid }
  659. ];
  660. localStorage.setItem("readTemp", JSON.stringify(temp));
  661. }
  662. return r;
  663. });
  664. },
  665. weakSubscribeTextRandom() {
  666. return this.weakSubscribeText[Math.floor(Math.random() * 3)];
  667. },
  668. weakSubscribeEv() {
  669. WeakSubscribe();
  670. },
  671. horizontalMounted(page) {
  672. if (this.weakSubscribe) {
  673. this.weakSubscribeHorizontal = true;
  674. this.weakSubscribeStyle = {
  675. width: page.scrollWidth + "px"
  676. };
  677. this.weakSubscribeHorizontalNum = page.total;
  678. }
  679. if (this.subscribeQRcode) this.subscribeQRcodeHorizontal = true;
  680. if (this.active) this.active_horizontal = true;
  681. },
  682. verticalMounted() {
  683. this.weakSubscribeHorizontal = false;
  684. this.subscribeQRcodeHorizontal = false;
  685. this.active_horizontal = false;
  686. },
  687. getChapterComment(bid, cid) {
  688. return getChapterComment(bid, cid);
  689. },
  690. jumpNovel(url) {
  691. let options = {
  692. bg: this.readerOptions.bg,
  693. font: this.readerOptions.font.default,
  694. night: this.readerOptions.night
  695. };
  696. location.href = `${url}&bg=${options.bg}&font=${options.font}&night=${options.night}`;
  697. },
  698. justifyRouter(router) {
  699. if (!router.query.bid) {
  700. this.$router.replace({ path: "/", query: { uuids: this.uuids } });
  701. return false;
  702. }
  703. if (typeof router.query.bid !== "string") {
  704. this.$router.replace({
  705. name: Reader.name,
  706. query: {
  707. bid: router.query.bid[0],
  708. cid: router.query.cid,
  709. uuids: this.uuids
  710. }
  711. });
  712. return false;
  713. } else if (router.query.bid.split(",").length > 1) {
  714. this.$router.replace({
  715. name: Reader.name,
  716. query: {
  717. bid: router.query.bid.split(",")[0],
  718. cid: router.query.cid,
  719. uuids: this.uuids,
  720. yun: this.yun
  721. }
  722. });
  723. return false;
  724. }
  725. return true;
  726. },
  727. isIphone() {
  728. const u = navigator.userAgent;
  729. // return u.indexOf("iPhone") !== -1;
  730. return true;
  731. },
  732. recordReadChapter() {
  733. localStorage.setItem("rc", this.$route.query.cid);
  734. },
  735. clearReadChapter() {
  736. localStorage.removeItem("rc");
  737. },
  738. changeFirst(val) {
  739. this.firstReader = val;
  740. },
  741. replaceURLAfterChange(cid, newCid) {
  742. console.log("cid", cid);
  743. console.log("newCid", newCid);
  744. let url = window.location.href.replace(`cid=${cid}`, `cid=${newCid}`);
  745. console.log("replace url", url);
  746. window.history.replaceState({}, "", url);
  747. }
  748. },
  749. async created() {
  750. let uuid = localStorage.getItem("uuids");
  751. let { yun, bid, cid, uuids, sendid = 0, isreplace = 0 } = this.$route.query;
  752. if (sendid){
  753. localStorage.setItem("sendid", this.$route.query.sendid);
  754. sessionStorage.setItem("sendid", this.$route.query.sendid);
  755. Vue.prototype.sendid = sendid;
  756. }
  757. this.uuids = uuids || uuid;
  758. if (yun) this.yun = yun;
  759. let data = await getUserInfo();
  760. if (!data.bind_phone && window.navigator.standalone) {
  761. goLogin();
  762. }
  763. const token = localStorage.getItem("token");
  764. if (token) {
  765. setUserMode(
  766. Number(window.navigator.standalone) || 0,
  767. sendid
  768. ).then(res => {});
  769. }
  770. if (
  771. yun == "1" &&
  772. window.firstName == this.$route.name &&
  773. window.navigator.standalone &&
  774. isreplace != "1"
  775. ) {
  776. let sare = await getRecentReader();
  777. if (sare.bid && sare.cid != cid) {
  778. this.$router.replace(
  779. `/reader?bid=${sare.bid}&cid=${sare.cid}&yun=${yun}&uuids=${this.uuids}&sendid=${sendid}`
  780. );
  781. return;
  782. }
  783. }
  784. if (!this.justifyRouter(this.$route)) return;
  785. this.href = window.location.href;
  786. // 获取书籍详情
  787. //获取AB测试
  788. let modes = await changeAddMode();
  789. this.modes = modes.type;
  790. getDetail(this.$route.query.bid).then(m => {
  791. this.bookdetail = m;
  792. this.is_on = !!m.is_on_user_shelf;
  793. });
  794. // 获取章节内容
  795. let isFromCatalog = !!~window.prevPage.indexOf("/catalog");
  796. let page_from = isFromCatalog ? "chapter_dir" : "";
  797. this.getContent(this.$route.query.bid, this.$route.query.cid, "", page_from)
  798. .then(r => {
  799. this.text = r;
  800. this.isFromSubscribe = false;
  801. if (this.text.force_add_desk_type) {
  802. if (!this.addDesktop) this.addDesktop = true;
  803. }
  804. if (r.sign_status) {
  805. this.showSignNoticeWrap = true;
  806. }
  807. })
  808. .catch(r => {
  809. console.log("get content err", r);
  810. this.text = {
  811. content: r.msg
  812. };
  813. });
  814. },
  815. async beforeRouteEnter(to, from, next) {
  816. if (from.name !== BookCatalog.name && from.name !== Subscribe.name) {
  817. // 清除所有和章节相关的缓存
  818. clearStorageChapter();
  819. }
  820. if (!from.name) {
  821. next(vm => {
  822. vm.changeFirst(true);
  823. });
  824. }
  825. next();
  826. },
  827. beforeRouteUpdate(to, from, next) {
  828. // * 移除iframe
  829. removeIframe();
  830. if (!this.justifyRouter(to)) return;
  831. this.is_update = true;
  832. localStorage.removeItem("is_views");
  833. this.getContent(
  834. to.query.bid,
  835. to.query.cid,
  836. "",
  837. "chapter_info",
  838. this.copyVal
  839. )
  840. .then(r => {
  841. // * 重新加载iframe
  842. loadIframeAsync();
  843. r.jump = to.params.jump;
  844. this.text = r;
  845. if (this.text.force_add_desk_type) {
  846. if (!this.addDesktop) this.addDesktop = true;
  847. }
  848. this.$nextTick(() => {
  849. this.$nextTick(() => {
  850. delete this.text.jump;
  851. });
  852. });
  853. next();
  854. })
  855. .catch(r => {
  856. next(false);
  857. if (r.url) {
  858. location.assign(r.url);
  859. // location.href = r.url
  860. }
  861. // if (r.url) {
  862. // let a = document.createElement('a')
  863. // a.href = r.url
  864. // a.click()
  865. // }
  866. });
  867. },
  868. beforeRouteLeave(to, from, next) {
  869. if (to.name !== BookCatalog.name && to.name !== Subscribe.name) {
  870. // 清除所有和章节相关的缓存
  871. clearStorageChapter();
  872. }
  873. this.clearReadChapter();
  874. localStorage.removeItem("is_views");
  875. // * 离开阅读器后移除iframe
  876. removeIframe();
  877. next();
  878. },
  879. beforeMount() {
  880. // 重置lazyload设置
  881. this.$Lazyload.config({
  882. preLoad: 1.3,
  883. loading: "",
  884. error: ""
  885. });
  886. },
  887. mounted() {
  888. this.bus = this.$refs.reader.getBus();
  889. },
  890. destroyed() {
  891. document.title = window.options.title;
  892. }
  893. };
  894. </script>
  895. <style lang="scss">
  896. .reader-active {
  897. font-size: 17px;
  898. color: #ff3b00;
  899. text-align: center;
  900. margin-top: 0.8em;
  901. }
  902. .x-reader--subscribe {
  903. .weak-subscribe {
  904. text-align: center;
  905. font-size: 17px;
  906. color: #2572ff;
  907. }
  908. .x-reader-text--horizontal {
  909. .x-reader-text-wrap {
  910. padding-bottom: 1.3rem;
  911. }
  912. .weak-subscribe-wrap--horizontal {
  913. position: fixed;
  914. bottom: 0.7rem;
  915. left: 0;
  916. }
  917. .weak-subscribe--horizontal {
  918. width: 7.5rem;
  919. float: left;
  920. }
  921. }
  922. .weak-subscribe--vertical {
  923. margin-top: 0.8em;
  924. }
  925. }
  926. .reader .qr_img {
  927. height: 4rem;
  928. width: 4rem;
  929. padding: 1rem;
  930. display: block;
  931. margin: 0 auto;
  932. }
  933. .x-reader--subscribe__qrcode {
  934. .x-reader-text--vertical {
  935. padding-bottom: 0;
  936. }
  937. }
  938. .subscribe-qrcode {
  939. font-size: 0;
  940. img {
  941. width: 100%;
  942. margin-top: 0.4rem;
  943. }
  944. }
  945. .active_img {
  946. font-size: 0;
  947. margin: 0.3rem 0.24rem 0.2rem;
  948. img {
  949. width: 100%;
  950. }
  951. }
  952. .click-box {
  953. margin: 0.24rem 0.24rem 0;
  954. padding: 0.24rem 0;
  955. display: flex;
  956. justify-content: space-between;
  957. align-items: center;
  958. background: #dadada;
  959. .click-box__item {
  960. flex: 1;
  961. text-align: center;
  962. font-size: 0.28rem;
  963. color: #333;
  964. &:not(:last-child) {
  965. border-right: 1px solid #333;
  966. }
  967. span {
  968. width: 0.36rem;
  969. height: 0.36rem;
  970. display: inline-block;
  971. vertical-align: middle;
  972. margin-right: 0.2rem;
  973. vertical-align: sub;
  974. }
  975. .tap-icon {
  976. background: url("~@/assets/tap.png") center / contain no-repeat;
  977. }
  978. .zan-icon {
  979. background: url("~@/assets/zan.png") center / contain no-repeat;
  980. }
  981. }
  982. .click-box__item.cur {
  983. .tap-icon {
  984. background: url("~@/assets/tap-check.png") center / contain no-repeat;
  985. }
  986. .zan-icon {
  987. background: url("~@/assets/zan-check.png") center / contain no-repeat;
  988. }
  989. }
  990. }
  991. </style>
  992. <style lang="scss" scoped>
  993. .share {
  994. background: rgba(0, 0, 0, 0.6);
  995. position: fixed;
  996. top: 0;
  997. left: 0;
  998. right: 0;
  999. bottom: 0;
  1000. z-index: 100;
  1001. text-align: center;
  1002. padding: 0 0.2rem;
  1003. img {
  1004. width: 100%;
  1005. }
  1006. }
  1007. .send-gift {
  1008. display: flex;
  1009. justify-content: flex-end;
  1010. font-size: 0.28rem;
  1011. margin: 0.3rem 0.24rem;
  1012. .send-gift__btn {
  1013. padding: 0.05rem 0.3rem;
  1014. border: 1px solid #dca46a;
  1015. border-radius: 0.3rem;
  1016. background: #ecddd3;
  1017. color: #826b50;
  1018. }
  1019. }
  1020. .title_list {
  1021. margin: 1rem 0.24rem 0.1rem;
  1022. background: rgba(#fff, 0.4);
  1023. .title {
  1024. font-size: 0.36rem;
  1025. font-weight: bold;
  1026. margin: 0 0.24rem;
  1027. padding: 0.3rem 0;
  1028. color: #333;
  1029. border-bottom: 1px solid rgba(#000, 0.04);
  1030. }
  1031. .title-list-box {
  1032. margin: 0 0.24rem;
  1033. .title-item {
  1034. padding: 0.3rem 0;
  1035. display: flex;
  1036. justify-content: space-between;
  1037. align-items: center;
  1038. font-size: 0.3rem;
  1039. color: #666;
  1040. cursor: pointer;
  1041. img {
  1042. width: 30%;
  1043. margin-left: 0.3rem;
  1044. border-radius: 2px;
  1045. }
  1046. &:not(:last-child) {
  1047. border-bottom: 1px solid rgba(#000, 0.04);
  1048. }
  1049. }
  1050. }
  1051. }
  1052. .reader {
  1053. position: relative;
  1054. }
  1055. .ad-status {
  1056. position: fixed;
  1057. width: 1.14rem;
  1058. height: 1.14rem;
  1059. right: 0.24rem;
  1060. bottom: 50%;
  1061. font-size: 0;
  1062. z-index: 9999;
  1063. &.with-no-activity {
  1064. bottom: 50%;
  1065. }
  1066. img {
  1067. width: 100%;
  1068. }
  1069. }
  1070. .to-share__entry {
  1071. text-align: right;
  1072. margin: 0 0.24rem;
  1073. font-size: 0;
  1074. img {
  1075. width: 1.8rem;
  1076. }
  1077. }
  1078. .weak-subscribe {
  1079. text-align: center;
  1080. font-size: 17px;
  1081. color: #2572ff;
  1082. }
  1083. .weak-subscribe--vertical {
  1084. margin-top: 0.8em;
  1085. }
  1086. .coupon-entry__wrap {
  1087. width: 1.2rem;
  1088. height: 1.2rem;
  1089. font-size: 0;
  1090. border-radius: 50%;
  1091. position: fixed;
  1092. bottom: 30%;
  1093. right: 2%;
  1094. img {
  1095. width: 100%;
  1096. }
  1097. }
  1098. .reader-footer__banners {
  1099. height: 1.9rem;
  1100. font-size: 0;
  1101. margin: 0.3rem 0.24rem 0.2rem;
  1102. &:not(:first-child) {
  1103. margin-top: 0;
  1104. }
  1105. img {
  1106. width: 100%;
  1107. height: 1.9rem;
  1108. }
  1109. }
  1110. .sign-notice__wrap {
  1111. position: fixed;
  1112. top: 0;
  1113. left: 0;
  1114. bottom: 0;
  1115. width: 100%;
  1116. background: rgba($color: #000000, $alpha: 0.8);
  1117. z-index: 999;
  1118. img {
  1119. width: 100%;
  1120. }
  1121. }
  1122. .click-toCollection {
  1123. font-size: 0.34rem;
  1124. color: #2572ff;
  1125. text-align: center;
  1126. margin-top: 0.8em;
  1127. }
  1128. .reader-fixed {
  1129. padding-top: 2.6rem;
  1130. transition: all 0.3s;
  1131. }
  1132. .add_desk {
  1133. position: fixed;
  1134. width: 100vw;
  1135. height: 100vh;
  1136. background: rgba(0, 0, 0, 0.6);
  1137. top: 0;
  1138. left: 0;
  1139. right: 0;
  1140. bottom: 0;
  1141. z-index: 1001;
  1142. .addgif {
  1143. position: absolute;
  1144. top: 0;
  1145. left: 0;
  1146. right: 0;
  1147. bottom: 0;
  1148. width: 80%;
  1149. height: 9.8rem;
  1150. margin: auto;
  1151. .addpng {
  1152. margin-bottom: 0.2rem;
  1153. }
  1154. .add-gif {
  1155. background: #fff;
  1156. display: flex;
  1157. justify-content: center;
  1158. align-items: flex-start;
  1159. img {
  1160. width: 100%;
  1161. }
  1162. }
  1163. .add-title {
  1164. width: 100%;
  1165. height: 1rem;
  1166. display: flex;
  1167. align-items: center;
  1168. background-color: #ff6920;
  1169. justify-content: space-between;
  1170. > p {
  1171. font-size: 0.4rem;
  1172. color: #fff;
  1173. font-weight: bold;
  1174. text-align: center;
  1175. flex-grow: 1;
  1176. }
  1177. .closed {
  1178. width: 0.36rem;
  1179. height: 0.36rem;
  1180. background: url("../assets/close_pop.png");
  1181. margin-right: 0.3rem;
  1182. background-size: cover;
  1183. }
  1184. }
  1185. }
  1186. }
  1187. .five_template_entry {
  1188. font-size: 0;
  1189. position: fixed;
  1190. top: 0;
  1191. left: 0;
  1192. z-index: 999;
  1193. height: 2.6rem;
  1194. transition: height 0.3s;
  1195. overflow: hidden;
  1196. img {
  1197. width: 100%;
  1198. }
  1199. .close-area {
  1200. position: absolute;
  1201. right: 0.15rem;
  1202. top: 0.12rem;
  1203. width: 0.85rem;
  1204. height: 0.4rem;
  1205. }
  1206. .close-text-area {
  1207. position: absolute;
  1208. bottom: 0;
  1209. left: 0;
  1210. height: 0.4rem;
  1211. width: 100%;
  1212. }
  1213. }
  1214. </style>