reader.vue 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278
  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. console.log('上一页cid',this.text)
  391. // 静默复制
  392. if (this.text.next_jump) {
  393. location.href = this.text.next_jump_url;
  394. } else {
  395. if (this.text.next_cid) {
  396. this.$router.replace({
  397. path: `/reader/${this.getUuid()}/`,
  398. query: {
  399. bid: this.text.bid,
  400. cid: this.text.next_cid,
  401. uuids: this.uuids,
  402. sendid:
  403. this.$route.query.sendid || localStorage.getItem("sendid"),
  404. yun: this.yun,
  405. last_bid: this.text.bid,
  406. last_cid: this.text.chapter_id,
  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. },
  430. params: {
  431. jump: -1
  432. }
  433. });
  434. } else {
  435. this.$Toast("第一章!");
  436. }
  437. },
  438. direction(val) {
  439. if (val === "horizontal" && !localStorage.getItem("old_reader")) {
  440. this.bus.$emit("menu");
  441. localStorage.setItem("old_reader", "true");
  442. this.new_reader = true;
  443. this.$nextTick(() => {
  444. this.new_reader_guide1 = true;
  445. });
  446. }
  447. this.weakSubscribeStyle = {};
  448. },
  449. subscribe({ bid, chapter_id: cid }) {
  450. if (this.$route.query.bid == bid && this.$route.query.cid == cid) {
  451. this.getContent(this.$route.query.bid, this.$route.query.cid)
  452. .then(r => {
  453. this.text = r;
  454. if (this.text.force_add_desk_type) {
  455. if (!this.addDesktop) this.addDesktop = true;
  456. }
  457. })
  458. .catch(r => {
  459. this.text = {};
  460. });
  461. } else {
  462. this.$router.replace({
  463. name: Reader.name,
  464. query: {
  465. bid: bid,
  466. cid: cid,
  467. uuids: this.uuids
  468. }
  469. });
  470. }
  471. },
  472. getContent(bid, cid, next, from, code) {
  473. //由于beforeRouteUpdate钩子函数会调用getContent,所以路由或者页面跳转不应该在在此函数,不然会造beforeRouteUpdate钩子函数的next不被调用
  474. /*
  475. 错误处理
  476. 10012 未关注
  477. 10014 全本订阅余额不足(rmb)
  478. 10015 章订余额不足(充值)
  479. 10016 购买章节(书币)
  480. 10017 购买图书(书币)
  481. 10019 全本订阅余额不足(充值)
  482. 10023 未关注 (跳转渠道接诶)
  483. ----- 以上是弹窗 -------
  484. 10020 全本订阅余额不足,直接进入充值页
  485. 10021 章节订阅余额不足,直接进入充值页
  486. 10022 进入版权站
  487. */
  488. this.loading = true;
  489. let adStatus = 0;
  490. return getContent(bid, cid, adStatus, from, code)
  491. .catch(r => {
  492. this.loading = false;
  493. const data = r.data.data;
  494. const sequence = this.$route.query.sequence
  495. const last_bid = this.$route.query.last_bid
  496. const last_cid = this.$route.query.last_cid
  497. const sendid = this.$route.query.sendid
  498. const yun = this.$route.query.yun
  499. const from_detail_catalog = 3
  500. switch (r.data.code) {
  501. case 10012:
  502. if (this.is_update) {
  503. r.url = data.src;
  504. } else {
  505. // this.$router.push({
  506. // name: Subscribe.name,
  507. // query: { src: data.src, head_img: data.head_img }
  508. // });
  509. location.replace(data.src);
  510. }
  511. break;
  512. case 10014:
  513. Book2(data)
  514. .then(r => {
  515. subscribeByRMB(data);
  516. })
  517. .catch(e => {
  518. if (e === "close") {
  519. if (!localStorage.getItem("rc")) {
  520. // this.$router.back();
  521. history.back();
  522. }
  523. }
  524. });
  525. break;
  526. case 10015:
  527. Chapter1(data).then(r => {
  528. this.$router.push({ name: Pay.name, query: data, sequence, last_bid, last_cid, sendid, yun, from_detail_catalog });
  529. });
  530. break;
  531. case 10016:
  532. Chapter2(data).then(r => {
  533. this.loading = true;
  534. subscribeByBalance(
  535. data.book_id,
  536. data.chapter_id,
  537. r.checked
  538. ).then(r => {
  539. this.subscribe(r);
  540. });
  541. });
  542. break;
  543. case 10017:
  544. Book4(data)
  545. .then(r => {
  546. this.loading = true;
  547. subscribeByBalance(data.book_id, data.chapter_id).then(r => {
  548. this.subscribe(r);
  549. });
  550. })
  551. .catch(e => {
  552. if (!localStorage.getItem("rc")) {
  553. // this.$router.back();
  554. history.back();
  555. }
  556. });
  557. break;
  558. case 10019:
  559. Book3(r.data.data)
  560. .then(r => {
  561. this.$router.push({ name: Pay.name, query: data, sequence, last_bid, last_cid, sendid, yun, from_detail_catalog });
  562. })
  563. .catch(e => {
  564. if (e === "close") {
  565. if (!localStorage.getItem("rc")) {
  566. // this.$router.back();
  567. history.back();
  568. }
  569. }
  570. });
  571. break;
  572. case 10020:
  573. case 10021:
  574. this.$router.push({
  575. name: Pay.name,
  576. query: { ...data, code: r.data.code, sequence, last_bid, last_cid, sendid, yun, from_detail_catalog }
  577. });
  578. break;
  579. case 10022:
  580. location.replace(
  581. `${data.url}&yun=${this.yun}&isreplace=${
  582. window.navigator.standalone ? 1 : 0
  583. }`
  584. );
  585. break;
  586. case 10023:
  587. location.assign(data.url);
  588. break;
  589. default:
  590. break;
  591. }
  592. return Promise.reject(r);
  593. })
  594. .then(r => {
  595. this.subscribeQRcode = r.is_had_subscribe;
  596. this.loading = false;
  597. this.weakSubscribe = !!r.is_show_subscribe_link;
  598. this.canTap = !!r.chapter_comment;
  599. this.chooseTap = r.chapter_comment;
  600. this.recordReadChapter();
  601. //是否显示个人banner
  602. let readQuery = localStorage.getItem("readQuery");
  603. if (readQuery) {
  604. readQuery = JSON.parse(readQuery);
  605. let cur = new Date().toDateString();
  606. let time = new Date(readQuery.lastReadTime).toDateString();
  607. if (cur != time) {
  608. localStorage.removeItem("readTemp");
  609. readQuery.lastReadTime = new Date();
  610. readQuery.isClose = false;
  611. localStorage.setItem("readQuery", JSON.stringify(readQuery));
  612. }
  613. } else {
  614. let data = {
  615. lastReadTime: new Date(),
  616. firstReadTime: new Date(),
  617. isClose: false
  618. };
  619. localStorage.setItem("readQuery", JSON.stringify(data));
  620. }
  621. let readerTemp = localStorage.getItem("readTemp");
  622. if (readerTemp) {
  623. let temp = JSON.parse(readerTemp);
  624. let same = false;
  625. let allweek = false;
  626. temp.map(item => {
  627. if (item.bid == bid && item.cid == cid) same = true;
  628. });
  629. if (!same) {
  630. temp.push({ bid: bid, cid: cid });
  631. localStorage.setItem("readTemp", JSON.stringify(temp));
  632. }
  633. if (readQuery) {
  634. let firstTime = new Date(
  635. JSON.parse(localStorage.getItem("readQuery")).firstReadTime
  636. );
  637. let firstTimeZero = new Date(firstTime.toLocaleDateString());
  638. if (Math.abs(firstTimeZero - new Date()) < 7 * 24 * 3600 * 1000) {
  639. allweek = false;
  640. } else {
  641. allweek = true;
  642. }
  643. if (
  644. temp.length >= 4 &&
  645. temp.length <= 22 &&
  646. temp.length % 2 == 0 &&
  647. !readQuery.isClose &&
  648. !allweek
  649. ) {
  650. this.showFans = true;
  651. } else {
  652. this.showFans = false;
  653. }
  654. }
  655. } else {
  656. let temp = [
  657. { bid: this.$route.query.bid, cid: this.$route.query.cid }
  658. ];
  659. localStorage.setItem("readTemp", JSON.stringify(temp));
  660. }
  661. return r;
  662. });
  663. },
  664. weakSubscribeTextRandom() {
  665. return this.weakSubscribeText[Math.floor(Math.random() * 3)];
  666. },
  667. weakSubscribeEv() {
  668. WeakSubscribe();
  669. },
  670. horizontalMounted(page) {
  671. if (this.weakSubscribe) {
  672. this.weakSubscribeHorizontal = true;
  673. this.weakSubscribeStyle = {
  674. width: page.scrollWidth + "px"
  675. };
  676. this.weakSubscribeHorizontalNum = page.total;
  677. }
  678. if (this.subscribeQRcode) this.subscribeQRcodeHorizontal = true;
  679. if (this.active) this.active_horizontal = true;
  680. },
  681. verticalMounted() {
  682. this.weakSubscribeHorizontal = false;
  683. this.subscribeQRcodeHorizontal = false;
  684. this.active_horizontal = false;
  685. },
  686. getChapterComment(bid, cid) {
  687. return getChapterComment(bid, cid);
  688. },
  689. jumpNovel(url) {
  690. let options = {
  691. bg: this.readerOptions.bg,
  692. font: this.readerOptions.font.default,
  693. night: this.readerOptions.night
  694. };
  695. location.href = `${url}&bg=${options.bg}&font=${options.font}&night=${options.night}`;
  696. },
  697. justifyRouter(router) {
  698. if (!router.query.bid) {
  699. this.$router.replace({ path: "/", query: { uuids: this.uuids } });
  700. return false;
  701. }
  702. if (typeof router.query.bid !== "string") {
  703. this.$router.replace({
  704. name: Reader.name,
  705. query: {
  706. bid: router.query.bid[0],
  707. cid: router.query.cid,
  708. uuids: this.uuids
  709. }
  710. });
  711. return false;
  712. } else if (router.query.bid.split(",").length > 1) {
  713. this.$router.replace({
  714. name: Reader.name,
  715. query: {
  716. bid: router.query.bid.split(",")[0],
  717. cid: router.query.cid,
  718. uuids: this.uuids,
  719. yun: this.yun
  720. }
  721. });
  722. return false;
  723. }
  724. return true;
  725. },
  726. isIphone() {
  727. const u = navigator.userAgent;
  728. // return u.indexOf("iPhone") !== -1;
  729. return true;
  730. },
  731. recordReadChapter() {
  732. localStorage.setItem("rc", this.$route.query.cid);
  733. },
  734. clearReadChapter() {
  735. localStorage.removeItem("rc");
  736. },
  737. changeFirst(val) {
  738. this.firstReader = val;
  739. },
  740. replaceURLAfterChange(cid, newCid) {
  741. console.log("cid", cid);
  742. console.log("newCid", newCid);
  743. let url = window.location.href.replace(`cid=${cid}`, `cid=${newCid}`);
  744. console.log("replace url", url);
  745. window.history.replaceState({}, "", url);
  746. }
  747. },
  748. async created() {
  749. let uuid = localStorage.getItem("uuids");
  750. let { yun, bid, cid, uuids, sendid = 0, isreplace = 0 } = this.$route.query;
  751. if (sendid){
  752. localStorage.setItem("sendid", this.$route.query.sendid);
  753. sessionStorage.setItem("sendid", this.$route.query.sendid);
  754. Vue.prototype.sendid = sendid;
  755. }
  756. this.uuids = uuids || uuid;
  757. if (yun) this.yun = yun;
  758. let data = await getUserInfo();
  759. if (!data.bind_phone && window.navigator.standalone) {
  760. goLogin();
  761. }
  762. const token = localStorage.getItem("token");
  763. if (token) {
  764. setUserMode(
  765. Number(window.navigator.standalone) || 0,
  766. sendid
  767. ).then(res => {});
  768. }
  769. if (
  770. yun == "1" &&
  771. window.firstName == this.$route.name &&
  772. window.navigator.standalone &&
  773. isreplace != "1"
  774. ) {
  775. let sare = await getRecentReader();
  776. if (sare.bid && sare.cid != cid) {
  777. this.$router.replace(
  778. `/reader?bid=${sare.bid}&cid=${sare.cid}&yun=${yun}&uuids=${this.uuids}&sendid=${sendid}`
  779. );
  780. return;
  781. }
  782. }
  783. if (!this.justifyRouter(this.$route)) return;
  784. this.href = window.location.href;
  785. // 获取书籍详情
  786. //获取AB测试
  787. let modes = await changeAddMode();
  788. this.modes = modes.type;
  789. getDetail(this.$route.query.bid).then(m => {
  790. this.bookdetail = m;
  791. this.is_on = !!m.is_on_user_shelf;
  792. });
  793. // 获取章节内容
  794. let isFromCatalog = !!~window.prevPage.indexOf("/catalog");
  795. let page_from = isFromCatalog ? "chapter_dir" : "";
  796. this.getContent(this.$route.query.bid, this.$route.query.cid, "", page_from)
  797. .then(r => {
  798. this.text = r;
  799. this.isFromSubscribe = false;
  800. if (this.text.force_add_desk_type) {
  801. if (!this.addDesktop) this.addDesktop = true;
  802. }
  803. if (r.sign_status) {
  804. this.showSignNoticeWrap = true;
  805. }
  806. })
  807. .catch(r => {
  808. console.log("get content err", r);
  809. this.text = {
  810. content: r.msg
  811. };
  812. });
  813. },
  814. async beforeRouteEnter(to, from, next) {
  815. if (from.name !== BookCatalog.name && from.name !== Subscribe.name) {
  816. // 清除所有和章节相关的缓存
  817. clearStorageChapter();
  818. }
  819. if (!from.name) {
  820. next(vm => {
  821. vm.changeFirst(true);
  822. });
  823. }
  824. next();
  825. },
  826. beforeRouteUpdate(to, from, next) {
  827. // * 移除iframe
  828. removeIframe();
  829. if (!this.justifyRouter(to)) return;
  830. this.is_update = true;
  831. localStorage.removeItem("is_views");
  832. this.getContent(
  833. to.query.bid,
  834. to.query.cid,
  835. "",
  836. "chapter_info",
  837. this.copyVal
  838. )
  839. .then(r => {
  840. // * 重新加载iframe
  841. loadIframeAsync();
  842. r.jump = to.params.jump;
  843. this.text = r;
  844. if (this.text.force_add_desk_type) {
  845. if (!this.addDesktop) this.addDesktop = true;
  846. }
  847. this.$nextTick(() => {
  848. this.$nextTick(() => {
  849. delete this.text.jump;
  850. });
  851. });
  852. next();
  853. })
  854. .catch(r => {
  855. next(false);
  856. if (r.url) {
  857. location.assign(r.url);
  858. // location.href = r.url
  859. }
  860. // if (r.url) {
  861. // let a = document.createElement('a')
  862. // a.href = r.url
  863. // a.click()
  864. // }
  865. });
  866. },
  867. beforeRouteLeave(to, from, next) {
  868. if (to.name !== BookCatalog.name && to.name !== Subscribe.name) {
  869. // 清除所有和章节相关的缓存
  870. clearStorageChapter();
  871. }
  872. this.clearReadChapter();
  873. localStorage.removeItem("is_views");
  874. // * 离开阅读器后移除iframe
  875. removeIframe();
  876. next();
  877. },
  878. beforeMount() {
  879. // 重置lazyload设置
  880. this.$Lazyload.config({
  881. preLoad: 1.3,
  882. loading: "",
  883. error: ""
  884. });
  885. },
  886. mounted() {
  887. this.bus = this.$refs.reader.getBus();
  888. },
  889. destroyed() {
  890. document.title = window.options.title;
  891. }
  892. };
  893. </script>
  894. <style lang="scss">
  895. .reader-active {
  896. font-size: 17px;
  897. color: #ff3b00;
  898. text-align: center;
  899. margin-top: 0.8em;
  900. }
  901. .x-reader--subscribe {
  902. .weak-subscribe {
  903. text-align: center;
  904. font-size: 17px;
  905. color: #2572ff;
  906. }
  907. .x-reader-text--horizontal {
  908. .x-reader-text-wrap {
  909. padding-bottom: 1.3rem;
  910. }
  911. .weak-subscribe-wrap--horizontal {
  912. position: fixed;
  913. bottom: 0.7rem;
  914. left: 0;
  915. }
  916. .weak-subscribe--horizontal {
  917. width: 7.5rem;
  918. float: left;
  919. }
  920. }
  921. .weak-subscribe--vertical {
  922. margin-top: 0.8em;
  923. }
  924. }
  925. .reader .qr_img {
  926. height: 4rem;
  927. width: 4rem;
  928. padding: 1rem;
  929. display: block;
  930. margin: 0 auto;
  931. }
  932. .x-reader--subscribe__qrcode {
  933. .x-reader-text--vertical {
  934. padding-bottom: 0;
  935. }
  936. }
  937. .subscribe-qrcode {
  938. font-size: 0;
  939. img {
  940. width: 100%;
  941. margin-top: 0.4rem;
  942. }
  943. }
  944. .active_img {
  945. font-size: 0;
  946. margin: 0.3rem 0.24rem 0.2rem;
  947. img {
  948. width: 100%;
  949. }
  950. }
  951. .click-box {
  952. margin: 0.24rem 0.24rem 0;
  953. padding: 0.24rem 0;
  954. display: flex;
  955. justify-content: space-between;
  956. align-items: center;
  957. background: #dadada;
  958. .click-box__item {
  959. flex: 1;
  960. text-align: center;
  961. font-size: 0.28rem;
  962. color: #333;
  963. &:not(:last-child) {
  964. border-right: 1px solid #333;
  965. }
  966. span {
  967. width: 0.36rem;
  968. height: 0.36rem;
  969. display: inline-block;
  970. vertical-align: middle;
  971. margin-right: 0.2rem;
  972. vertical-align: sub;
  973. }
  974. .tap-icon {
  975. background: url("~@/assets/tap.png") center / contain no-repeat;
  976. }
  977. .zan-icon {
  978. background: url("~@/assets/zan.png") center / contain no-repeat;
  979. }
  980. }
  981. .click-box__item.cur {
  982. .tap-icon {
  983. background: url("~@/assets/tap-check.png") center / contain no-repeat;
  984. }
  985. .zan-icon {
  986. background: url("~@/assets/zan-check.png") center / contain no-repeat;
  987. }
  988. }
  989. }
  990. </style>
  991. <style lang="scss" scoped>
  992. .share {
  993. background: rgba(0, 0, 0, 0.6);
  994. position: fixed;
  995. top: 0;
  996. left: 0;
  997. right: 0;
  998. bottom: 0;
  999. z-index: 100;
  1000. text-align: center;
  1001. padding: 0 0.2rem;
  1002. img {
  1003. width: 100%;
  1004. }
  1005. }
  1006. .send-gift {
  1007. display: flex;
  1008. justify-content: flex-end;
  1009. font-size: 0.28rem;
  1010. margin: 0.3rem 0.24rem;
  1011. .send-gift__btn {
  1012. padding: 0.05rem 0.3rem;
  1013. border: 1px solid #dca46a;
  1014. border-radius: 0.3rem;
  1015. background: #ecddd3;
  1016. color: #826b50;
  1017. }
  1018. }
  1019. .title_list {
  1020. margin: 1rem 0.24rem 0.1rem;
  1021. background: rgba(#fff, 0.4);
  1022. .title {
  1023. font-size: 0.36rem;
  1024. font-weight: bold;
  1025. margin: 0 0.24rem;
  1026. padding: 0.3rem 0;
  1027. color: #333;
  1028. border-bottom: 1px solid rgba(#000, 0.04);
  1029. }
  1030. .title-list-box {
  1031. margin: 0 0.24rem;
  1032. .title-item {
  1033. padding: 0.3rem 0;
  1034. display: flex;
  1035. justify-content: space-between;
  1036. align-items: center;
  1037. font-size: 0.3rem;
  1038. color: #666;
  1039. cursor: pointer;
  1040. img {
  1041. width: 30%;
  1042. margin-left: 0.3rem;
  1043. border-radius: 2px;
  1044. }
  1045. &:not(:last-child) {
  1046. border-bottom: 1px solid rgba(#000, 0.04);
  1047. }
  1048. }
  1049. }
  1050. }
  1051. .reader {
  1052. position: relative;
  1053. }
  1054. .ad-status {
  1055. position: fixed;
  1056. width: 1.14rem;
  1057. height: 1.14rem;
  1058. right: 0.24rem;
  1059. bottom: 50%;
  1060. font-size: 0;
  1061. z-index: 9999;
  1062. &.with-no-activity {
  1063. bottom: 50%;
  1064. }
  1065. img {
  1066. width: 100%;
  1067. }
  1068. }
  1069. .to-share__entry {
  1070. text-align: right;
  1071. margin: 0 0.24rem;
  1072. font-size: 0;
  1073. img {
  1074. width: 1.8rem;
  1075. }
  1076. }
  1077. .weak-subscribe {
  1078. text-align: center;
  1079. font-size: 17px;
  1080. color: #2572ff;
  1081. }
  1082. .weak-subscribe--vertical {
  1083. margin-top: 0.8em;
  1084. }
  1085. .coupon-entry__wrap {
  1086. width: 1.2rem;
  1087. height: 1.2rem;
  1088. font-size: 0;
  1089. border-radius: 50%;
  1090. position: fixed;
  1091. bottom: 30%;
  1092. right: 2%;
  1093. img {
  1094. width: 100%;
  1095. }
  1096. }
  1097. .reader-footer__banners {
  1098. height: 1.9rem;
  1099. font-size: 0;
  1100. margin: 0.3rem 0.24rem 0.2rem;
  1101. &:not(:first-child) {
  1102. margin-top: 0;
  1103. }
  1104. img {
  1105. width: 100%;
  1106. height: 1.9rem;
  1107. }
  1108. }
  1109. .sign-notice__wrap {
  1110. position: fixed;
  1111. top: 0;
  1112. left: 0;
  1113. bottom: 0;
  1114. width: 100%;
  1115. background: rgba($color: #000000, $alpha: 0.8);
  1116. z-index: 999;
  1117. img {
  1118. width: 100%;
  1119. }
  1120. }
  1121. .click-toCollection {
  1122. font-size: 0.34rem;
  1123. color: #2572ff;
  1124. text-align: center;
  1125. margin-top: 0.8em;
  1126. }
  1127. .reader-fixed {
  1128. padding-top: 2.6rem;
  1129. transition: all 0.3s;
  1130. }
  1131. .add_desk {
  1132. position: fixed;
  1133. width: 100vw;
  1134. height: 100vh;
  1135. background: rgba(0, 0, 0, 0.6);
  1136. top: 0;
  1137. left: 0;
  1138. right: 0;
  1139. bottom: 0;
  1140. z-index: 1001;
  1141. .addgif {
  1142. position: absolute;
  1143. top: 0;
  1144. left: 0;
  1145. right: 0;
  1146. bottom: 0;
  1147. width: 80%;
  1148. height: 9.8rem;
  1149. margin: auto;
  1150. .addpng {
  1151. margin-bottom: 0.2rem;
  1152. }
  1153. .add-gif {
  1154. background: #fff;
  1155. display: flex;
  1156. justify-content: center;
  1157. align-items: flex-start;
  1158. img {
  1159. width: 100%;
  1160. }
  1161. }
  1162. .add-title {
  1163. width: 100%;
  1164. height: 1rem;
  1165. display: flex;
  1166. align-items: center;
  1167. background-color: #ff6920;
  1168. justify-content: space-between;
  1169. > p {
  1170. font-size: 0.4rem;
  1171. color: #fff;
  1172. font-weight: bold;
  1173. text-align: center;
  1174. flex-grow: 1;
  1175. }
  1176. .closed {
  1177. width: 0.36rem;
  1178. height: 0.36rem;
  1179. background: url("../assets/close_pop.png");
  1180. margin-right: 0.3rem;
  1181. background-size: cover;
  1182. }
  1183. }
  1184. }
  1185. }
  1186. .five_template_entry {
  1187. font-size: 0;
  1188. position: fixed;
  1189. top: 0;
  1190. left: 0;
  1191. z-index: 999;
  1192. height: 2.6rem;
  1193. transition: height 0.3s;
  1194. overflow: hidden;
  1195. img {
  1196. width: 100%;
  1197. }
  1198. .close-area {
  1199. position: absolute;
  1200. right: 0.15rem;
  1201. top: 0.12rem;
  1202. width: 0.85rem;
  1203. height: 0.4rem;
  1204. }
  1205. .close-text-area {
  1206. position: absolute;
  1207. bottom: 0;
  1208. left: 0;
  1209. height: 0.4rem;
  1210. width: 100%;
  1211. }
  1212. }
  1213. </style>