Home.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  1. <template>
  2. <div class="home-points" ref="homePoints">
  3. <Jbanner wordState="long" :pointNum="pointInfo.balance" source="home"></Jbanner>
  4. <!-- <Jsign :signDays="signInfo.days" :isSign="signInfo.state"></Jsign> -->
  5. <div class="sign">
  6. <div class="continuous">
  7. <div class="days">
  8. 已连续签到 <em>{{ signInfo.days || 0 }}</em> 天
  9. </div>
  10. <van-button class="btn" :disabled="signInfo.state" :class="btnClass" @click="signHandle">{{ btnText }}</van-button>
  11. </div>
  12. <div class="sign-data">
  13. <div class="sign-list" v-for="(item,index) in signData" :key="index">
  14. <div :class="['circle', index <= getToday - 1 ? 'circle-active' : '', index == getToday && !signInfo.state ? 'circle-today' : '']">+{{item}}</div>
  15. <div :class="['sun', index == getToday - 1 && showAnimate ? 'animate' : '']"></div>
  16. </div>
  17. </div>
  18. </div>
  19. <div class="task" v-if="!$env.isWeiXinBrowser">
  20. <div class="task-header">完成任务,赚剑鱼币</div>
  21. <div class="task-content">
  22. <div v-for="item in taskData" :key="item.type" class="task-list" @click="goTask(item)">
  23. <div :class="['task-img', item.type === 'friend' ? 'invite-img' : 'share-img']"></div>
  24. <div class="task-title">{{ item.title }}</div>
  25. <p class="task-end">立得 <em>{{ item.num }}</em> 剑鱼币</p>
  26. </div>
  27. </div>
  28. </div>
  29. <div class="hot">
  30. <div class="hot-header">
  31. <span class="header-left">文库兑换<em>HOT</em>榜</span>
  32. </div>
  33. <div class="hot-content">
  34. <div v-if="hotData && hotData.length > 0">
  35. <div class="hot-list" v-for="hot in hotData" :key="hot.docId" @click="goDetail(hot.docId)">
  36. <div class="hot-left">
  37. <div class="thumbnail" v-lazy:background-image="hot.docImg">
  38. <span :class="['mask', hot.docFileType == 1 ? 'm-word' : '',hot.docFileType == 2 ? 'm-pdf': '', hot.docFileType == 3 ? 'm-excel': '', hot.docFileType == 4 ? 'ppt': '']"></span>
  39. </div>
  40. </div>
  41. <div class="hot-right">
  42. <div class="ellipsis-2 title">{{ hot.docTitle }}</div>
  43. <div class="time">{{ hot.uploadDate }}</div>
  44. <div class="price">
  45. <span>{{ hot.costPrice }}</span>
  46. </div>
  47. </div>
  48. </div>
  49. </div>
  50. <Empty v-else>
  51. <div class="tip-sub-text">暂无数据</div>
  52. </Empty>
  53. </div>
  54. </div>
  55. </div>
  56. </template>
  57. <script lang="ts">
  58. import { Component, Vue } from 'vue-property-decorator'
  59. import { mapMutations, mapActions } from 'vuex'
  60. import { Button, Toast } from 'vant'
  61. import Empty from '@/components/common/Empty.vue'
  62. import Jbanner from '@/components/common/Banner.vue'
  63. // import Jsign from '@/components/common/Sign.vue'
  64. @Component({
  65. name: 'home-points',
  66. components: {
  67. [Button.name]: Button,
  68. Empty,
  69. Jbanner
  70. // Jsign
  71. },
  72. methods: {
  73. ...mapMutations({
  74. updateHeader: 'updateLayoutConfig'
  75. }),
  76. ...mapActions({
  77. getPointsSign: 'home/getPointsSign',
  78. signUpdate: 'home/signUpdate',
  79. getDocHot: 'home/getDocHotList'
  80. })
  81. }
  82. })
  83. export default class Home extends Vue {
  84. protected updateHeader!: any
  85. protected getPointsSign!: any
  86. protected signUpdate!: any
  87. protected getDocHot!: any
  88. pointInfo = {}
  89. todayAddPoint = 0
  90. showAnimate = false
  91. signData: Array<number> = []
  92. signInfo = {
  93. days: 0,
  94. state: false
  95. }
  96. typeArr = {
  97. one: [1, 1, 3, 5, 10, 15, 15], // 0-6
  98. two: [1, 3, 5, 10, 15, 15, 15], // 7
  99. three: [3, 5, 10, 15, 15, 15, 15], // 8
  100. four: [5, 10, 15, 15, 15, 15, 15], // 9
  101. five: [10, 15, 15, 15, 15, 15, 15], // 10
  102. six: [15, 15, 15, 15, 15, 15, 15] // >= 11
  103. }
  104. taskData = [
  105. {
  106. type: 'friend',
  107. title: '邀请好友',
  108. num: 500
  109. },
  110. {
  111. type: 'share',
  112. title: '好友分享',
  113. num: 5
  114. }
  115. ]
  116. hotData = []
  117. get getToday () {
  118. const days = this.signInfo.days
  119. const bool = this.signInfo.state
  120. if (days < 7) {
  121. // 今天已签到 || 未签到
  122. return days
  123. } else {
  124. // 今天已签到 = 7 未签到 = 6
  125. return bool ? 7 : 6
  126. }
  127. }
  128. get btnClass () {
  129. if (this.signInfo.state) {
  130. return 'normal-btn'
  131. } else {
  132. return 'sign-btn'
  133. }
  134. }
  135. get btnText () {
  136. if (this.signInfo.state) {
  137. return '已签到'
  138. } else {
  139. return '立即签到'
  140. }
  141. }
  142. mounted () {
  143. this.updateHeader({
  144. transparentHeader: true,
  145. titleStyle: {
  146. 'font-size': 0
  147. }
  148. })
  149. }
  150. created () {
  151. this.getPointsInfo()
  152. this.getHotData()
  153. this.getScrollTop()
  154. }
  155. getPointsInfo () {
  156. this.getPointsSign(
  157. { B: true }
  158. ).then((res: any) => {
  159. if (res.error_code === 0 && res.data.points) {
  160. this.pointInfo = res.data.points
  161. this.signInfo.days = res.data.points.signInfo.c_days
  162. this.signInfo.state = res.data.points.signInfo.s_bool
  163. this.everyDayPoints()
  164. } else {
  165. Toast(res.error_msg)
  166. }
  167. }).catch((err) => {
  168. console.log(err)
  169. })
  170. }
  171. signHandle () {
  172. if (this.signInfo.state) return
  173. // 更新积分
  174. this.signUpdate({
  175. mode: 1004,
  176. score: this.addHowPoints()
  177. }).then((v) => {
  178. console.log(v)
  179. if (v.error_code === 0 && v.data.code === 1) {
  180. this.signInfo.days++
  181. this.$nextTick(() => {
  182. this.signInfo.state = true
  183. this.showAnimate = true
  184. this.todayAddPoint = this.addHowPoints()
  185. this.getPointsInfo()
  186. setTimeout(() => {
  187. this.showAnimate = false
  188. }, 4000)
  189. })
  190. } else {
  191. Toast(v.error_msg)
  192. }
  193. }).catch((err) => {
  194. console.log(err)
  195. })
  196. }
  197. // 渲染最近七天的积分
  198. everyDayPoints () {
  199. let days = this.signInfo.days
  200. if (days <= 6) {
  201. days = 6
  202. } else if (days >= 12) {
  203. days = 11
  204. }
  205. switch (days) {
  206. case 6 :
  207. this.signData = this.typeArr.one
  208. break
  209. case 7 :
  210. this.signData = this.typeArr.two
  211. break
  212. case 8 :
  213. this.signData = this.typeArr.three
  214. break
  215. case 9 :
  216. this.signData = this.typeArr.four
  217. break
  218. case 10 :
  219. this.signData = this.typeArr.five
  220. break
  221. case 11 :
  222. this.signData = this.typeArr.six
  223. break
  224. default:
  225. this.signData = this.typeArr.one
  226. break
  227. }
  228. }
  229. // 今天签到增加多少分
  230. addHowPoints () {
  231. const days = this.signInfo.days
  232. let points
  233. if (days <= 2) {
  234. points = 1
  235. } else if (days === 3) {
  236. points = 3
  237. } else if (days === 4) {
  238. points = 5
  239. } else if (days === 5) {
  240. points = 10
  241. } else if (days >= 6) {
  242. points = 15
  243. }
  244. return points
  245. }
  246. // 文库兑换hot榜
  247. getHotData () {
  248. this.getDocHot({
  249. num: 1,
  250. size: 10,
  251. code: 4
  252. }).then((res) => {
  253. if (res.error_code === 0 && res.data) {
  254. res.data.forEach(v => {
  255. if (v.uploadDate) {
  256. v.uploadDate = v.uploadDate.replace(/\s[\x00-\xff]*/g, '')
  257. }
  258. })
  259. this.hotData = res.data
  260. } else {
  261. this.$toast(res.error_msg)
  262. }
  263. }).catch((err) => {
  264. console.log(err)
  265. })
  266. }
  267. // 跳转到详情页
  268. goDetail (id) {
  269. window.location.href = '/page_docs_mobile/details/' + id
  270. }
  271. // 邀请或分享
  272. goTask (item) {
  273. if (item.type === 'friend') {
  274. this.$router.push('/invite')
  275. } else {
  276. this.$router.push('/share')
  277. }
  278. }
  279. getScrollTop () {
  280. setTimeout(() => {
  281. window.addEventListener('scroll', this.handleScroll, true)
  282. }, 0)
  283. }
  284. // 监听滚动条变化
  285. handleScroll (e) {
  286. const scrollHeight = (this.$refs.homePoints as any).scrollTop || e.target.scrollTop
  287. if (scrollHeight > 50) {
  288. this.updateHeader({
  289. transparentHeader: false,
  290. positionStyle: {
  291. position: 'fixed',
  292. width: '100%',
  293. zIndex: 12
  294. }
  295. })
  296. } else {
  297. this.updateHeader({
  298. transparentHeader: true,
  299. titleStyle: {
  300. 'font-size': 0
  301. }
  302. })
  303. }
  304. }
  305. beforeDestroy () {
  306. window.removeEventListener('scroll', this.handleScroll, true)
  307. }
  308. }
  309. </script>
  310. <style lang="scss">
  311. .home-points{
  312. height: auto;
  313. .task{
  314. padding: 16px 16px 0 16px;
  315. .task-header{
  316. font-size: 18px;
  317. color: #171826;
  318. line-height: 26px;
  319. }
  320. .task-content{
  321. display: flex;
  322. align-items: center;
  323. justify-content: space-between;
  324. padding: 6px 2px;
  325. }
  326. .task-list{
  327. border-radius: 8px;
  328. background: #fff;
  329. }
  330. .task-img{
  331. width: 168px;
  332. height: 96px;
  333. }
  334. .invite-img{
  335. background: url(~@/assets/image/inviteHome@2x.png) no-repeat center center transparent;
  336. background-size: 100% 100%;
  337. }
  338. .share-img{
  339. background: url(~@/assets/image/shareHome@2x.png) no-repeat center center transparent;
  340. background-size: 100% 100%;
  341. }
  342. .task-title{
  343. padding: 10px 10px 0;
  344. font-size: 13px;
  345. color: #171826;
  346. }
  347. .task-end{
  348. padding: 2px 10px 10px;
  349. font-size: 12px;
  350. color: #5F5E64;
  351. em{
  352. color: #FB483D;
  353. font-size: 13px;
  354. }
  355. }
  356. }
  357. .hot{
  358. margin-top: 16px;
  359. padding: 0 16px;
  360. .hot-header{
  361. display: flex;
  362. justify-content: space-between;
  363. align-items: center;
  364. padding-bottom: 6px;
  365. line-height: 26px;
  366. }
  367. .header-left{
  368. font-size: 18px;
  369. color: #171826;
  370. em{
  371. color: #FB483D;
  372. }
  373. }
  374. .header-right{
  375. color: #1B1A2A;
  376. font-size: 14px;
  377. em{
  378. color: #C0C4CC;
  379. }
  380. }
  381. .hot-content{
  382. .hot-list{
  383. display: flex;
  384. justify-content: space-between;
  385. align-items: center;
  386. margin-bottom: 10px;
  387. background-color: #fff;
  388. border-radius: 8px;
  389. }
  390. .hot-left{
  391. padding: 4px 0 4px 4px;
  392. .thumbnail{
  393. position: relative;
  394. width: 100px;
  395. height: 124px;
  396. border-radius: 4px;
  397. border: 1px solid #ECECEC;
  398. background-repeat: no-repeat;
  399. background-position: center center;
  400. background-size: 100% 100%;
  401. .mask{
  402. position: absolute;
  403. right: 0;
  404. bottom: 0;
  405. width: 24px;
  406. height: 24px;
  407. background: url(~@/assets/image/ppt@2x.png) center center no-repeat;
  408. }
  409. .m-pdf{
  410. background: url(~@/assets/image/pdf@2x.png) no-repeat center center;
  411. background-size: 100% 100%;
  412. }
  413. .m-word{
  414. background: url(~@/assets/image/word@2x.png) no-repeat center center;
  415. background-size: 100% 100%;
  416. }
  417. .m-excel{
  418. background: url(~@/assets/image/excel@2x.png) no-repeat center center;
  419. background-size: 100% 100%;
  420. }
  421. .m-ppt{
  422. background: url(~@/assets/image/ppt@2x.png) no-repeat center center;
  423. background-size: 100% 100%;
  424. }
  425. }
  426. }
  427. .hot-right{
  428. flex: 1;
  429. padding: 12px 16px 12px 20px;
  430. .title{
  431. font-size: 14px;
  432. line-height: 20px;
  433. color: #171826;
  434. flex: 1;
  435. }
  436. .time{
  437. margin-top: 8px;
  438. color: #9B9CA3;
  439. font-size: 12px;
  440. line-height: 18px;
  441. }
  442. .price{
  443. margin-top: 22px;
  444. text-align: right;
  445. span{
  446. background: url(~@/assets/image/iconJianYu@2x.png) no-repeat left center transparent;
  447. background-size: 20px 20px;
  448. padding-left: 24px;
  449. color: #FB483D;
  450. font-size: 14px;
  451. line-height: 20px;
  452. }
  453. }
  454. }
  455. }
  456. }
  457. }
  458. .sign{
  459. position: relative;
  460. margin: -68px 16px 0;
  461. padding: 16px 16px 6px 16px;
  462. border-radius: 8px;
  463. background: url(~@/assets/image/dateGetBg@2x.png) no-repeat center center;
  464. background-size: cover;
  465. box-shadow: 0px 2px 8px 0px rgba(54,147,179,0.05);
  466. z-index: 10;
  467. .continuous{
  468. display: flex;
  469. justify-content: space-between;
  470. align-items: center;
  471. .days{
  472. font-size: 16px;
  473. color: #5F5E64;
  474. & em{
  475. color: #FF7A00;
  476. font-weight: 600;
  477. }
  478. }
  479. .btn{
  480. display: flex;
  481. align-items: center;
  482. justify-content: center;
  483. height: 24px;
  484. padding: 0;
  485. border-radius: 4px;
  486. font-size: 12px;
  487. box-sizing: border-box;
  488. }
  489. .sign-btn{
  490. min-width: 60px;
  491. background: #33323A;
  492. color: #F1D090;
  493. }
  494. .normal-btn{
  495. width: 48px;
  496. border: 1px solid #D69E55;
  497. color: #D69E55;
  498. box-sizing: border-box;
  499. }
  500. }
  501. .sign-data{
  502. display: flex;
  503. justify-content: space-between;
  504. align-items: center;
  505. padding: 6px 0;
  506. .sign-list{
  507. position: relative;
  508. display: flex;
  509. align-items: center;
  510. justify-content: center;
  511. width: 46px;
  512. height: 46px;
  513. border-radius: 50%;
  514. }
  515. .sun{
  516. position: absolute;
  517. top: 0;
  518. left: 0;
  519. right: 0;
  520. bottom: 0;
  521. }
  522. .sun.animate{
  523. animation: turn 6s linear infinite;
  524. background: url(~@/assets/image/dateGetClick@2x.png) center center no-repeat transparent;
  525. background-size: 100% 100%;
  526. }
  527. .circle{
  528. width: 32px;
  529. height: 32px;
  530. line-height: 32px;
  531. text-align: center;
  532. border-radius: 50%;
  533. background: url(~@/assets/image/iconUnGot@2x.png) center center no-repeat;
  534. background-size: contain;
  535. font-size: 12px;
  536. overflow: hidden;
  537. }
  538. .circle-today{
  539. background: url(~@/assets/image/iconGetToday@2x.png) center center no-repeat;
  540. background-size: contain;
  541. }
  542. .circle-active{
  543. background: url(~@/assets/image/iconGot@2x.png) center center no-repeat;
  544. background-size: contain;
  545. color: #fff;
  546. }
  547. @keyframes turn{
  548. 0%{-webkit-transform:rotate(0deg);}
  549. 25%{-webkit-transform:rotate(90deg);}
  550. 50%{-webkit-transform:rotate(180deg);}
  551. 75%{-webkit-transform:rotate(270deg);}
  552. 100%{-webkit-transform:rotate(360deg);}
  553. }
  554. }
  555. }
  556. </style>