bookPeruseItem.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649
  1. <template>
  2. <div class="bookItem">
  3. <Header
  4. :headerBg="headerBg"
  5. :headerBorder="headerBorder"
  6. :userBg="userBg"
  7. :LoginNavIndex="LoginNavIndex"
  8. ref="header"
  9. />
  10. <div class="navBar" v-if="info">
  11. <div class="navBar-left">
  12. <a class="goback" @click="$router.go(-1)"><i class="el-icon-arrow-left"></i>精读课堂</a>
  13. <div class="border"></div>
  14. <p>{{'第 '+info.batch+' 期'}}{{info.cn_title}}</p>
  15. </div>
  16. <!-- <div class="navBar-right">
  17. <a @click="handleShare">
  18. <svg-icon icon-class="share-personal" className="icon-share"></svg-icon>
  19. <span>分享</span>
  20. </a>
  21. <a @click="handlelike">
  22. <svg-icon icon-class="like-line" className="icon-like"></svg-icon>
  23. <span>收藏</span>
  24. </a>
  25. </div> -->
  26. </div>
  27. <div class="main-top" v-if="info">
  28. <div class="main-top-inner">
  29. <el-carousel class="swiper-container" trigger="click" arrow="never" height="414px">
  30. <!-- <el-carousel-item v-for="(item1, index) in data.imgList" :key="index"> -->
  31. <el-image
  32. class="image"
  33. :src="info.cover_img?info.cover_img:bookType==='baozhi'?require('../../assets/baozhi'+(Math.floor(Math.random()*2)+1)+'.png'):require('../../assets/kecheng'+(Math.floor(Math.random()*3)+1)+'.png')"
  34. :fit="'cover'">
  35. </el-image>
  36. <!-- </el-carousel-item> -->
  37. </el-carousel>
  38. <div class="book-info-right">
  39. <h1 class="title">{{info.cn_title}}</h1>
  40. <!-- <b class="org">{{data.org}}</b><span class="date">2023.07.01-2023.07.21</span> -->
  41. <div class="sales-box">
  42. <div class="sales-left">
  43. <span>优惠价</span>
  44. <span class="OPPOSans">¥{{info.price|cutMoneyFiter}}</span>
  45. </div>
  46. <span class="sales-right" v-if="sales>=1000">累计销售 {{salesCn}}</span>
  47. </div>
  48. <!-- <div class="book-describe">
  49. <h2 class="title">{{data.describe.title}}</h2>
  50. <span class="author">{{'BY '+data.describe.author}}</span>
  51. <p class="describe">{{data.describe.describe}}</p>
  52. </div> -->
  53. <div class="info-box">
  54. <div class="info-item">
  55. <label>机构</label>
  56. <span>二十一世纪英文报</span>
  57. </div>
  58. <div class="info-item">
  59. <label>学段</label>
  60. <span>{{info.study_phase_name}}版</span>
  61. </div>
  62. <div class="info-item">
  63. <label>期数</label>
  64. <span>{{info.batch}} 期</span>
  65. </div>
  66. <div class="info-item">
  67. <label>有效期</label>
  68. <span>永久有效</span>
  69. </div>
  70. <div class="info-item">
  71. <label>主题</label>
  72. <span>{{info.label}}</span>
  73. </div>
  74. </div>
  75. <div class="btn-box">
  76. <a class="continue" v-if="isBuy==='true'" @click="handleLink">继续学习</a>
  77. <template v-else>
  78. <a class="el-button" @click="handleChangeWay('wei')">立即购买</a>
  79. <a class="upgrade" @click="handleChangeWay('dui')">使用兑换码</a>
  80. </template>
  81. </div>
  82. </div>
  83. </div>
  84. </div>
  85. <div class="main-center" v-if="info">
  86. <el-tabs type="card" style="margin-bottom:24px;">
  87. <el-tab-pane label="简介">
  88. <div v-html="info.introduction"></div>
  89. </el-tab-pane>
  90. </el-tabs>
  91. <div class="banner-box-close" v-if="bannerFlag">
  92. <a v-if="1==2" href="#" target="_blank">
  93. <img class="banner-item" src="../../assets/banner4.png" />
  94. </a>
  95. <img v-else class="banner-item" src="../../assets/banner4.png" />
  96. <div class="close-box">
  97. <a class="close-btn" @click="bannerFlag=false"><i class="el-icon-close"></i></a>
  98. <span class="close-tips">广告</span>
  99. </div>
  100. </div>
  101. </div>
  102. <el-dialog
  103. :visible.sync="paymentShow"
  104. :show-close="false"
  105. :close-on-click-modal="false"
  106. width="712px"
  107. class="bookItem-dialog"
  108. v-if="paymentShow">
  109. <Payment :data="info" :payWay="payWay" @handleClose="handleClose" :orderId="orderId" :qr_code_url="qr_code_url" />
  110. </el-dialog>
  111. </div>
  112. </template>
  113. <script>
  114. //这里可以导入其它文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
  115. //例如:import 《组件名称》from ‘《组件路径》';
  116. import Header from "../../components/Header.vue";
  117. import BookCard from "@/components/common/BookCard.vue"
  118. import Payment from "./components/Payment.vue"
  119. import TreeList from "./components/TreeList"
  120. import CourseList from "./components/CourseList.vue"
  121. import { cutMoneyFiter } from '@/utils/defined';
  122. import { getLogin, getNoToken } from "@/api/ajax";
  123. import { getToken } from '@/utils/auth'
  124. export default {
  125. //import引入的组件需要注入到对象中才能使用
  126. components: { Header, BookCard, Payment, TreeList, CourseList },
  127. props: [],
  128. filters:{
  129. cutMoneyFiter
  130. },
  131. data() {
  132. //这里存放数据
  133. return {
  134. config: this.$route.query.headerConfig?decodeURIComponent(this.$route.query.headerConfig):'',
  135. LoginNavIndex: 0,
  136. userBg: 'rgba(0, 0, 0, 0.24)',
  137. headerBorder: '#5C5C5C',
  138. headerBg: '#1F1F1F',
  139. previousPage: '商城',
  140. tagBg:['#C9EBFF','#FFFAC9','#D7C9FF'], // 标签背景色
  141. tagColor:['#006DAA','#AA8500','#7849C4'], // 标签字体颜色
  142. paymentShow: false, // 支付弹窗
  143. payWay:this.$route.query.paywei?this.$route.query.paywei:'dui',
  144. bookType: this.$route.query.cardType?this.$route.query.cardType:'baozhi', // 书籍类型
  145. bannerFlag: true, // 是否展示广告
  146. id: this.$route.query.id?this.$route.query.id:'',
  147. info: null, // 信息
  148. courseList:[],
  149. sales: null,
  150. salesCn: '',
  151. isBuy: 'false',
  152. userMessage: getToken()?JSON.parse(getToken()):null,
  153. orderId: '',
  154. qr_code_url: '',
  155. pre_play_cs_item_id: '', //上次阅读课节id
  156. pre_play_index: null, // 上次阅读索引
  157. }
  158. },
  159. //计算属性 类似于data概念
  160. computed: {},
  161. //监控data中数据变化
  162. watch: {},
  163. //方法集合
  164. methods: {
  165. // 分享
  166. handleShare(){
  167. },
  168. // 收藏
  169. handlelike(){
  170. },
  171. handleChangeWay(type){
  172. if(!this.userMessage){
  173. this.$refs.header.handleLogin('/bookItem?headerConfig='+this.$route.query.headerConfig+'&cardType='+this.bookType+'&id='+this.id+'&paywei='+type,'url')
  174. return false
  175. }
  176. this.payWay = type;
  177. this.handleOrder()
  178. },
  179. // 关闭弹窗
  180. handleClose(){
  181. this.paymentShow = false
  182. this.getInfo()
  183. },
  184. // 详情
  185. getInfo(){
  186. let MethodName = "/PaperServer/Client/Iread/GetIreadBriefInfo";
  187. let data = {
  188. id: this.id,
  189. }
  190. getLogin(MethodName, data)
  191. .then((res) => {
  192. if(res.status===1){
  193. this.info = res.data
  194. }
  195. })
  196. .catch(() => {
  197. });
  198. if(this.userMessage){
  199. getLogin('/ShopServer/Client/BookshelfQuery/GetGoodsBuyStatus', {
  200. goods_type: 3,
  201. goods_id: this.id
  202. })
  203. .then((res) => {
  204. if(res.status===1){
  205. this.isBuy = res.buy_info.is_buy
  206. this.sales = res.data.sold_count
  207. if(this.sales<1000){
  208. this.salesCn = ''
  209. }else if(1000<=this.sales&&this.sales<10000){
  210. this.salesCn = this.sales.toString().substring(0,1)+'000+'
  211. }else if(10000<=this.sales&&this.sales<100000){
  212. this.salesCn = this.sales.toString().substring(0,1)+'万+'
  213. }else if(100000<=this.sales&&this.sales<1000000){
  214. this.salesCn = this.sales.toString().substring(0,1)+'0万+'
  215. }else if(1000000<=this.sales&&this.sales<10000000){
  216. this.salesCn = this.sales.toString().substring(0,1)+'00万+'
  217. }else if(10000000<=this.sales&&this.sales<100000000){
  218. this.salesCn = this.sales.toString().substring(0,1)+'000万+'
  219. }else if(100000000<=this.sales){
  220. this.salesCn = this.sales.toString().substring(0,1)+'亿+'
  221. }
  222. }
  223. })
  224. .catch(() => {
  225. });
  226. }else{
  227. getNoToken('/ShopServer/Client/BookshelfQuery/GetGoodsBuyStatus', {
  228. goods_type: 3,
  229. goods_id: this.id
  230. }, 'VOID')
  231. .then((res) => {
  232. if(res.status===1){
  233. this.isBuy = res.buy_info.is_buy
  234. this.sales = res.data.sold_count
  235. if(this.sales<1000){
  236. this.salesCn = ''
  237. }else if(1000<=this.sales&&this.sales<10000){
  238. this.salesCn = this.sales.toString().substring(0,1)+'000+'
  239. }else if(10000<=this.sales&&this.sales<100000){
  240. this.salesCn = this.sales.toString().substring(0,1)+'万+'
  241. }else if(100000<=this.sales&&this.sales<1000000){
  242. this.salesCn = this.sales.toString().substring(0,1)+'0万+'
  243. }else if(1000000<=this.sales&&this.sales<10000000){
  244. this.salesCn = this.sales.toString().substring(0,1)+'00万+'
  245. }else if(10000000<=this.sales&&this.sales<100000000){
  246. this.salesCn = this.sales.toString().substring(0,1)+'000万+'
  247. }else if(100000000<=this.sales){
  248. this.salesCn = this.sales.toString().substring(0,1)+'亿+'
  249. }
  250. }
  251. })
  252. .catch(() => {
  253. });
  254. }
  255. },
  256. // 生成订单
  257. handleOrder(){
  258. let MethodName = "/ShopServer/Client/OrderManager/CreateOrder";
  259. let data = {
  260. goods_type: 3,
  261. goods_id_list: [this.id],
  262. pay_type: this.payWay==='wei'?3:this.payWay==='zhi'?4:null
  263. }
  264. getLogin(MethodName, data)
  265. .then((res) => {
  266. if(res.status === 1){
  267. this.orderId = res.id
  268. this.qr_code_url = res.qr_code_url
  269. this.paymentShow = true;
  270. }
  271. })
  272. // this.paymentShow = true;
  273. },
  274. // 跳转
  275. handleLink(){
  276. let url = this.LoginNavIndex +'&&&'+ this.userBg +'&&&'+ this.headerBorder +'&&&'+ this.headerBg
  277. this.$router.push({
  278. path: "/articlePeruseDetail",
  279. query: {
  280. headerConfig: encodeURIComponent(url),
  281. peruseId: this.id
  282. },
  283. });
  284. }
  285. },
  286. //生命周期 - 创建完成(可以访问当前this实例)
  287. created() {
  288. if(this.config){
  289. let arr = this.config.split('&&&')
  290. this.LoginNavIndex = arr[0] * 1
  291. this.userBg = arr[1] ? arr[1] : 'rgba(0, 0, 0, 0.24)'
  292. this.headerBorder = arr[2] ? arr[2] : '#5C5C5C'
  293. this.headerBg = arr[3] ? arr[3] : '#1F1F1F'
  294. this.previousPage = arr[4] ? arr[4] : '商城'
  295. }
  296. this.getInfo()
  297. if(this.$route.query.paywei){
  298. this.handleOrder()
  299. }
  300. },
  301. //生命周期 - 挂载完成(可以访问DOM元素)
  302. mounted() {
  303. },
  304. //生命周期-创建之前
  305. beforeCreated() { },
  306. //生命周期-挂载之前
  307. beforeMount() { },
  308. //生命周期-更新之前
  309. beforUpdate() { },
  310. //生命周期-更新之后
  311. updated() { },
  312. //生命周期-销毁之前
  313. beforeDestory() { },
  314. //生命周期-销毁完成
  315. destoryed() { },
  316. //如果页面有keep-alive缓存功能,这个函数会触发
  317. activated() { }
  318. }
  319. </script>
  320. <style lang="scss" scoped>
  321. /* @import url(); 引入css类 */
  322. .bookItem {
  323. background: #F7F8FA;
  324. min-height: 100%;
  325. .main-top {
  326. background: #FFFFFF;
  327. padding: 48px 0;
  328. margin-top: 56px;
  329. &-inner{
  330. width: 1200px;
  331. margin: 0 auto;
  332. display: flex;
  333. .swiper-container{
  334. width: 416px;
  335. height: 440px;
  336. text-align: center;
  337. .el-image{
  338. width: 297px;
  339. height: 414px;
  340. border: 1px solid #F3F3F3;
  341. }
  342. }
  343. .book-info-right{
  344. flex: 1;
  345. padding-left: 88px;
  346. .title{
  347. color: #2F3742;
  348. font-weight: 500;
  349. font-size: 32px;
  350. line-height: 44px;
  351. margin: 0 0 16px 0;
  352. }
  353. .org,.date{
  354. font-weight: 500;
  355. font-size: 14px;
  356. line-height: 22px;
  357. color: rgba(0, 0, 0, 0.4);
  358. }
  359. .date{
  360. margin-left: 32px;
  361. line-height: 24px;
  362. }
  363. .label-box{
  364. display: flex;
  365. flex-flow: wrap;
  366. margin: 16px 0;
  367. label{
  368. margin: 0 8px 8px 0;
  369. border-radius: 20px;
  370. padding: 4px 12px;
  371. font-weight: 400;
  372. font-size: 14px;
  373. line-height: 22px;
  374. }
  375. }
  376. .book-describe{
  377. border-top: 1px solid #E5E6EB;
  378. border-bottom: 1px solid #E5E6EB;
  379. padding: 16px 0;
  380. .title{
  381. font-weight: 500;
  382. font-size: 16px;
  383. line-height: 24px;
  384. color: #000000;
  385. margin-bottom: 8px;
  386. }
  387. .author{
  388. font-weight: 400;
  389. font-size: 12px;
  390. line-height: 20px;
  391. color: #000000;
  392. margin-bottom: 8px;
  393. display: block;
  394. }
  395. .describe{
  396. font-weight: 400;
  397. font-size: 14px;
  398. line-height: 22px;
  399. color: #000000;
  400. margin: 0;
  401. }
  402. }
  403. .price-box{
  404. padding: 20px 0 16px 0;
  405. display: flex;
  406. align-items: flex-end;
  407. .price{
  408. font-weight: 500;
  409. font-size: 32px;
  410. line-height: 40px;
  411. color: #EA5939;
  412. }
  413. .oldPrice{
  414. padding: 0 0 2px 7px;
  415. font-weight: 500;
  416. font-size: 14px;
  417. line-height: 22px;
  418. color: rgba(0, 0, 0, 0.4);
  419. text-decoration-line: line-through;
  420. }
  421. }
  422. .info-box{
  423. display: flex;
  424. flex-flow: wrap;
  425. border-bottom: 1px solid #EBEBEB;
  426. margin: 24px 0;
  427. .info-item{
  428. width: 50%;
  429. margin-bottom: 15px;
  430. font-size: 14px;
  431. line-height: 22px;
  432. display: flex;
  433. label{
  434. color: #C2C2C2;
  435. font-weight: 400;
  436. margin-right: 16px;
  437. width: 58px;
  438. display: block;
  439. text-align:justify;
  440. text-justify:distribute-all-lines;
  441. text-align-last:justify;
  442. -moz-text-align-last:justify;
  443. -webkit-text-align-last:justify;
  444. }
  445. }
  446. }
  447. .btn-box{
  448. display: flex;
  449. .el-button{
  450. width: 112px;
  451. height: 40px;
  452. background: #EA5939;
  453. box-shadow: 0px 8px 16px rgba(234, 89, 57, 0.24);
  454. border-radius: 4px;
  455. font-weight: 500;
  456. font-size: 16px;
  457. color: #FFFFFF;
  458. border: none;
  459. }
  460. .svg-icon{
  461. margin-left: 7px;
  462. }
  463. .continue{
  464. width: 112px;
  465. height: 40px;
  466. background: #175DFF;
  467. border-radius: 4px;
  468. font-weight: 500;
  469. font-size: 16px;
  470. line-height: 40px;
  471. color: rgba(255, 255, 255, 1);
  472. display: block;
  473. text-align: center;
  474. box-shadow: 0px 8px 16px rgba(23, 93, 255, 0.24);
  475. }
  476. .upgrade{
  477. margin-left: 16px;
  478. display: block;
  479. padding: 0px 24px;
  480. height: 40px;
  481. background: #E9E9E9;
  482. box-shadow: 0px 8px 16px rgba(0, 0, 0, 0.06);
  483. border-radius: 4px;
  484. color: #595959;
  485. font-weight: 500;
  486. font-size: 16px;
  487. line-height: 40px;
  488. text-align: center;
  489. }
  490. }
  491. }
  492. }
  493. }
  494. .main-center{
  495. width: 1200px;
  496. margin: 0 auto;
  497. padding: 40px 0;
  498. .el-tabs--card>.el-tabs__header .el-tabs__item.is-active{
  499. border-color: #E7E7E7;
  500. }
  501. }
  502. .main-bottom{
  503. width: 1200px;
  504. margin: 0 auto;
  505. padding-bottom: 40px;
  506. &-top{
  507. display: flex;
  508. justify-content: space-between;
  509. p{
  510. margin: 0;
  511. font-weight: 500;
  512. font-size: 24px;
  513. line-height: 32px;
  514. color: #1F2C5C;
  515. font-family: initial;
  516. }
  517. .right{
  518. color: rgba(0, 0, 0, 0.88);
  519. font-weight: 400;
  520. font-size: 16px;
  521. line-height: 24px;
  522. cursor: pointer;
  523. a{
  524. margin-right: 8px;
  525. }
  526. }
  527. }
  528. }
  529. .list {
  530. margin-top: 24px;
  531. display: flex;
  532. flex-wrap: wrap;
  533. > div {
  534. width: 200px;
  535. border-radius: 8px;
  536. overflow: hidden;
  537. background: #ffffff;
  538. margin-bottom: 24px;
  539. }
  540. }
  541. }
  542. .banner-box-close{
  543. margin-top: 40px;
  544. }
  545. .sales-box{
  546. display: flex;
  547. width: 592px;
  548. padding: 16px;
  549. border-radius: 4px;
  550. background: #F5F5F5;
  551. justify-content: space-between;
  552. align-items: flex-end;
  553. color: #ADADAD;
  554. font-size: 14px;
  555. font-weight: 400;
  556. line-height: 22px;
  557. .OPPOSans{
  558. margin: 0 8px 0 16px;
  559. color: #EA5939;
  560. font-size: 32px;
  561. font-weight: 500;
  562. line-height: 40px;
  563. }
  564. .old-price{
  565. color: rgba(0, 0, 0, 0.40);
  566. font-size: 14px;
  567. font-weight: 500;
  568. line-height: 22px;
  569. text-decoration: line-through;
  570. }
  571. }
  572. </style>
  573. <style lang="scss">
  574. .bookItem{
  575. .el-carousel__button{
  576. width: 8px;
  577. height: 8px;
  578. background: #D9D9D9;
  579. opacity: 1;
  580. border-radius: 4px;
  581. }
  582. .el-carousel__indicator.is-active{
  583. .el-carousel__button{
  584. background: #5E5E5E;
  585. }
  586. }
  587. .el-tabs__header{
  588. margin: 0;
  589. }
  590. .el-tab-pane{
  591. background: #F8F8F8;
  592. border: 1px solid #E7E7E7;
  593. border-top: none;
  594. padding: 24px;
  595. }
  596. .el-tabs__item{
  597. width: 160px;
  598. height: 38px;
  599. text-align: center;
  600. font-weight: 500;
  601. font-size: 14px;
  602. line-height: 38px;
  603. color: #1F2C5C;
  604. &:hover{
  605. background: #E7E7E7;
  606. }
  607. &.is-active{
  608. // background: #3459D2;
  609. // color: #EEF3FF;
  610. border-bottom: none;
  611. background: #E7E7E7;
  612. }
  613. }
  614. }
  615. .bookitem-dropdown.el-dropdown-menu{
  616. padding: 4px;
  617. .el-dropdown-menu__item{
  618. font-weight: 500;
  619. font-size: 16px;
  620. line-height: 40px;
  621. color: #000000;
  622. }
  623. .el-dropdown-menu__item:focus, .el-dropdown-menu__item:not(.is-disabled):hover{
  624. background: #FDECEE;
  625. border-radius: 4px;
  626. color: #EA5939;
  627. }
  628. }
  629. .bookItem-dialog{
  630. .el-dialog__header,.el-dialog__body{
  631. padding: 0;
  632. }
  633. .el-dialog{
  634. border: 1px solid #EBEBEB;
  635. box-shadow: 0px 6px 30px 5px rgba(0, 0, 0, 0.05), 0px 16px 24px 2px rgba(0, 0, 0, 0.04), 0px 8px 10px -5px rgba(0, 0, 0, 0.08);
  636. border-radius: 8px;
  637. overflow: hidden;
  638. }
  639. }
  640. </style>