detail.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576
  1. <template>
  2. <view class="">
  3. <!-- 顶部导航 -->
  4. <fa-navbar title="详情"></fa-navbar>
  5. <!-- 内容 -->
  6. <view class="" v-if="isRender">
  7. <view class="u-p-30 u-bg-white">
  8. <view class="u-font-40"><text v-text="archivesInfo.title"></text></view>
  9. <view class="u-m-t-20 u-font-22 u-tips-color"><text v-text="archivesInfo.create_date"></text></view>
  10. <!-- -->
  11. <view class="u-flex u-row-between u-m-t-20 u-font-24 detail-tag">
  12. <view class="u-flex">
  13. <view class="u-flex u-col-center u-m-r-30" v-if="archivesInfo.user" @click="toUser(archivesInfo.user_id)">
  14. <u-avatar size="40" :src="archivesInfo.user.avatar"></u-avatar>
  15. <view class="u-font-22 u-m-l-10 u-line-1" style="max-width: 70px;">{{ archivesInfo.user.nickname }}</view>
  16. </view>
  17. <view class="">
  18. <u-icon name="thumb-up-fill" color="#aaa" size="20"></u-icon>
  19. <text class="u-m-l-5 u-m-r-5" v-text="archivesInfo.likes"></text>
  20. 点赞
  21. </view>
  22. <!-- <view class="u-m-l-30">
  23. <u-icon name="chat-fill" color="#aaa" size="20"></u-icon>
  24. <text class="u-m-l-5 u-m-r-5" v-text="archivesInfo.comments"></text>
  25. 评论
  26. </view> -->
  27. <view class="u-m-l-30">
  28. <u-icon name="eye-fill" color="#aaa" size="20"></u-icon>
  29. <text class="u-m-l-5 u-m-r-5" v-text="archivesInfo.views"></text>
  30. 浏览
  31. </view>
  32. </view>
  33. <view class="">
  34. <!-- #ifdef MP-WEIXIN -->
  35. <button class="share-btn" open-type="share">
  36. <u-icon name="share-fill"></u-icon>
  37. <text class="u-p-l-5">分享</text>
  38. </button>
  39. <!-- #endif -->
  40. <!-- #ifdef H5 -->
  41. <button class="share-btn" @click="copyUrl">
  42. <u-icon name="share-fill"></u-icon>
  43. <text class="u-p-l-5">分享</text>
  44. </button>
  45. <!-- #endif -->
  46. <!-- #ifdef APP-PLUS -->
  47. <button class="share-btn" @click="openShare">
  48. <u-icon name="share-fill"></u-icon>
  49. <text class="u-p-l-5">分享</text>
  50. </button>
  51. <!-- #endif -->
  52. </view>
  53. </view>
  54. </view>
  55. <view class="u-flex u-flex-wrap u-p-l-30 u-p-r-30 u-p-t-30" v-if="isShow">
  56. <view class="product-images" v-for="(item, index) in imagesList" :key="index">
  57. <u-image width="100%" height="220" :src="item" @click="lookImage(index)"></u-image>
  58. </view>
  59. </view>
  60. <u-gap height="10" bg-color="#f4f6f8"></u-gap>
  61. <view class="u-flex u-row-center">
  62. <u-button
  63. type="primary"
  64. hover-class="none"
  65. :custom-style="{ backgroundColor: theme.bgColor, color: theme.color, width: '60vw' }"
  66. size="medium"
  67. v-if="archivesInfo.productid>0"
  68. @click="openproduct()"
  69. >
  70. 查看下载源码
  71. </u-button>
  72. </view>
  73. <u-gap height="10" bg-color="#f4f6f8"></u-gap>
  74. <view class="u-p-30 u-bg-white u-line-height">
  75. <u-parse
  76. :html="archivesInfo.content"
  77. :tag-style="vuex_parse_style"
  78. :domain="vuex_config.config ? vuex_config.config.upload.cdnurl : ''"
  79. @linkpress="navigate"
  80. ></u-parse>
  81. </view>
  82. <view class="u-p-30 u-bg-white">
  83. <view class="u-flex u-flex-wrap">
  84. <view class="u-m-r-10 u-m-b-15" v-for="(item, index) in archivesInfo.taglist" :key="index">
  85. <u-tag :text="item.name" shape="circle" type="info" mode="light" @click="goTag(item.name)" />
  86. </view>
  87. </view>
  88. <view class="u-flex u-row-right u-m-t-5">
  89. <view class="">
  90. <u-button
  91. type="primary"
  92. hover-class="none"
  93. :custom-style="{ backgroundColor: theme.bgColor, color: theme.color }"
  94. size="mini"
  95. shape="circle"
  96. @click="collection(id,'archives')"
  97. >
  98. <u-icon name="heart-fill"></u-icon>
  99. <text class="u-p-l-5" v-text="`收藏`"></text>
  100. </u-button>
  101. </view>
  102. <view class="u-m-l-15">
  103. <u-button
  104. type="primary"
  105. hover-class="none"
  106. :custom-style="{ backgroundColor: theme.bgColor, color: theme.color }"
  107. size="mini"
  108. shape="circle"
  109. @click="likes"
  110. >
  111. <u-icon name="thumb-up"></u-icon>
  112. <text class="u-p-l-5" v-text="`点赞(${archivesInfo.likes || 0})`"></text>
  113. </u-button>
  114. </view>
  115. </view>
  116. </view>
  117. <!-- 下载 -->
  118. <view class="u-flex u-border-top u-p-30 u-bg-white" v-if="archivesInfo.model_id == 3 && (archivesInfo.ispaid || archivesInfo.price == 0)">
  119. <view class="u-m-l-15" v-for="(item, index) in downloadurl" :key="index">
  120. <u-button
  121. hover-class="none"
  122. type="primary"
  123. :custom-style="{ backgroundColor: theme.bgColor, color: theme.color }"
  124. size="mini"
  125. shape="circle"
  126. @click="download(item)"
  127. >
  128. <text class="u-p-r-5" v-text="item.name == 'local' ? '本地下载' : item.name == 'baidu' ? '百度下载' : '其他下载'"></text>
  129. </u-button>
  130. </view>
  131. </view>
  132. <view class="u-p-30" v-if="downtips">
  133. <u-alert-tips
  134. type="warning"
  135. title="下载成功,保存路径为:"
  136. :close-able="true"
  137. :show="downtips"
  138. :description="description"
  139. @close="downtips = false"
  140. ></u-alert-tips>
  141. </view>
  142. <view class="u-border-top u-bg-white u-p-30 u-flex u-row-center" v-if="archivesInfo.price > 0 && !archivesInfo.ispaid">
  143. <u-button
  144. hover-class="none"
  145. type="primary"
  146. size="medium"
  147. :custom-style="{ backgroundColor: theme.bgColor, color: theme.color, width: '60vw' }"
  148. v-if="!vuex_token"
  149. @click="goLogin"
  150. >
  151. 请登录再进行付费
  152. </u-button>
  153. <u-button
  154. hover-class="none"
  155. type="primary"
  156. size="medium"
  157. :custom-style="{ backgroundColor: theme.bgColor, color: theme.color, width: '60vw' }"
  158. v-else
  159. @click="goPay"
  160. >
  161. 立即付费阅读
  162. </u-button>
  163. </view>
  164. <!-- <u-gap height="20" bg-color="#f4f6f8"></u-gap>
  165. <view class="u-bg-white u-p-30">
  166. <view class="u-p-b-10 u-tips-color">发表评论</view>
  167. <view class=""><u-input v-model="content" type="textarea" placeholder="请输入评论内容" :border="false" /></view>
  168. <view class="u-flex u-row-center">
  169. <u-button
  170. hover-class="none"
  171. type="primary"
  172. size="medium"
  173. :custom-style="{ backgroundColor: theme.bgColor, color: theme.color, width: '60vw' }"
  174. v-if="!vuex_token"
  175. @click="goLogin"
  176. >
  177. 立即登录
  178. </u-button>
  179. <u-button
  180. hover-class="none"
  181. type="primary"
  182. size="medium"
  183. :custom-style="{ backgroundColor: theme.bgColor, color: theme.color, width: '60vw' }"
  184. v-else
  185. @click="submit"
  186. >
  187. 立即评论
  188. </u-button>
  189. </view>
  190. </view> -->
  191. <!-- <u-gap height="20" bg-color="#f4f6f8"></u-gap>
  192. <view class="u-p-30 u-bg-white">
  193. <view class="u-p-b-10 u-tips-color">评论列表</view>
  194. <view class="comment" v-for="(item, index) in commentList" :key="item.id">
  195. <view class="left" @click="toUser(item.user_id)"><image :src="item.user && item.user.avatar" mode="aspectFill"></image></view>
  196. <view class="right">
  197. <view class="top">
  198. <view class="u-light-color">
  199. <u-icon name="account-fill" color="#c0c4cc"></u-icon>
  200. <text class="u-p-l-10 name u-line-1">{{ item.user && item.user.nickname }}</text>
  201. <text class="u-m-l-30">{{ item.create_date }}</text>
  202. </view>
  203. <view class="replay" @click="replay(item)">
  204. <u-icon name="chat" :size="30"></u-icon>
  205. <view class="opeate">回复</view>
  206. </view>
  207. </view>
  208. <view class="content"><rich-text :nodes="item.content"></rich-text></view>
  209. </view>
  210. </view>
  211. <view class="" v-if="!commentList.length"><u-empty text="暂无评论"></u-empty></view>
  212. </view> -->
  213. <!-- 支付 -->
  214. <fa-payment
  215. ref="faPayment"
  216. :article-id="id"
  217. :article-title="archivesInfo.title"
  218. :money="archivesInfo.price"
  219. :vip="(archivesInfo.channel && archivesInfo.channel.vip) || 0"
  220. @success="paySuccess"
  221. ></fa-payment>
  222. <!-- #ifdef APP-PLUS -->
  223. <view class="">
  224. <fa-app-share
  225. ref="faShare"
  226. :title="archivesInfo.title"
  227. :summary="archivesInfo.title"
  228. :imageUrl="archivesInfo.image"
  229. :href="archivesInfo.fullurl"
  230. ></fa-app-share>
  231. </view>
  232. <!-- #endif -->
  233. </view>
  234. <!-- 其他下载 -->
  235. <u-modal v-model="dowshow">
  236. <view class="u-p-30 u-flex u-row-center u-col-center">
  237. <u-link :href="downurl" font-size="35">点我下载</u-link>
  238. <text class="u-m-l-20 u-tips-color" v-if="baucode" v-text="'复制提取码:' + baucode" @click="copydown"></text>
  239. </view>
  240. </u-modal>
  241. <!-- 回到顶部 -->
  242. <u-back-top :scroll-top="scrollTop" :icon-style="{ color: theme.bgColor }" :custom-style="{ backgroundColor: lightColor }"></u-back-top>
  243. <!-- 底部导航 -->
  244. <fa-tabbar></fa-tabbar>
  245. </view>
  246. </template>
  247. <script>
  248. import { tools, vote } from '@/common/fa.mixin.js';
  249. // #ifdef H5
  250. import { weixinShare } from '@/common/fa.weixin.mixin.js';
  251. // #endif
  252. export default {
  253. mixins: [
  254. tools,
  255. vote,
  256. // #ifdef H5
  257. weixinShare
  258. // #endif
  259. ],
  260. onLoad(e) {
  261. let query = this.$Route.query || e || {};
  262. this.id = query.id || 0;
  263. this.diyname = query.diyname || '';
  264. this.getArchivesDetail();
  265. },
  266. onShow() {
  267. // #ifdef MP-BAIDU
  268. if(this.archivesInfo.id){
  269. this.setPagesInfo();
  270. }
  271. // #endif
  272. },
  273. computed: {
  274. isShow() {
  275. return this.archivesInfo.images != '';
  276. },
  277. isPay() {
  278. return parseInt(this.archivesInfo.price) > 0;
  279. }
  280. },
  281. watch: {
  282. content(newValue, oldValue) {
  283. if (!newValue) {
  284. this.pid = 0;
  285. }
  286. }
  287. },
  288. data() {
  289. return {
  290. id: 0,
  291. archivesInfo: {},
  292. channelInfo: {},
  293. commentList: [],
  294. imagesList: [],
  295. downloadurl: {},
  296. content: '',
  297. isRender: false,
  298. dowshow: false,
  299. downtips: false,
  300. pid: 0,
  301. description: '',
  302. downkey: '',
  303. downurl: '',
  304. baucode: '',
  305. diyname: '',
  306. scrollTop: 0,
  307. page: 1,
  308. has_more: true
  309. };
  310. },
  311. methods: {
  312. getArchivesDetail: async function() {
  313. let res = await this.$api.getArchivesDetail({ id: this.id, diyname: this.diyname });
  314. if (!res.code) {
  315. return;
  316. }
  317. this.archivesInfo = res.data.archivesInfo || {};
  318. this.channelInfo = res.data.channelInfo || [];
  319. this.commentList = res.data.commentList || [];
  320. this.downloadurl = res.data.archivesInfo.downloadurl || {};
  321. this.imagesList = res.data.archivesInfo.images.split(',');
  322. this.$u.mpShare.title = res.data.archivesInfo.title;
  323. this.isRender = true;
  324. this.$u.vuex('vuex__token__', res.data.__token__);
  325. uni.setNavigationBarTitle({
  326. title: this.archivesInfo.title
  327. });
  328. // #ifdef MP-BAIDU
  329. this.setPagesInfo();
  330. // #endif
  331. // #ifdef H5
  332. if (this.$util.isWeiXinBrowser()) {
  333. this.wxShare({
  334. title: this.archivesInfo.title,
  335. desc: this.archivesInfo.description,
  336. link: window.location.href,
  337. img: this.archivesInfo.image
  338. });
  339. }
  340. // #endif
  341. },
  342. // #ifdef MP-BAIDU
  343. setPagesInfo(){
  344. let sitename = (this.vuex_config && this.vuex_config.config && this.vuex_config.config.sitename) || '';
  345. swan.setPageInfo({
  346. title: this.archivesInfo.title+'-'+sitename,
  347. articleTitle: this.archivesInfo.title+'-'+sitename,
  348. keywords: this.archivesInfo.keywords,
  349. description: this.archivesInfo.description,
  350. releaseDate: this.$u.timeFormat(this.archivesInfo.publishtime, 'yyyy-mm-dd hh:MM:ss'),
  351. image: this.archivesInfo.images,
  352. likes: this.archivesInfo.likes,
  353. comments: this.archivesInfo.comments,
  354. collects: this.archivesInfo.views,
  355. success: res => {
  356. console.log('setPageInfo success', res);
  357. },
  358. fail: err => {
  359. console.log('setPageInfo fail', err);
  360. }
  361. });
  362. },
  363. // #endif
  364. goCommentIndex() {
  365. this.$api.goCommentIndex({ page: this.page, aid: this.archivesInfo.id }).then(res => {
  366. if (res.code == 1) {
  367. this.has_more = res.data.commentList.length > 0;
  368. this.commentList = [...this.commentList, ...res.data.commentList];
  369. }
  370. });
  371. },
  372. //回复
  373. replay(item) {
  374. if (!item.user) {
  375. this.$u.toast('用户不存在');
  376. return;
  377. }
  378. this.content = `@${item.user.nickname} `;
  379. this.pid = item.id;
  380. },
  381. //评论
  382. submit: async function() {
  383. if (!this.content) {
  384. this.$u.toast('请输入评论内容!');
  385. return;
  386. }
  387. let res = await this.$api.goCommentPost({
  388. content: this.content,
  389. aid: this.id,
  390. pid: this.pid //回复的用户上一条ID
  391. });
  392. this.$u.toast(res.msg);
  393. if (!res.code) {
  394. return;
  395. }
  396. this.content = '';
  397. if (res.data && res.data.comment) {
  398. this.commentList = [res.data.comment, ...this.commentList];
  399. }
  400. },
  401. //登录
  402. goLogin() {
  403. this.$Router.push('/pages/login/mobilelogin');
  404. },
  405. toUser(user_id) {
  406. this.$Router.push('/pages/user/user?user_id=' + user_id);
  407. },
  408. //支付
  409. goPay() {
  410. this.$refs.faPayment.show();
  411. },
  412. paySuccess() {
  413. this.getArchivesDetail();
  414. },
  415. //下载
  416. download(item) {
  417. let that = this;
  418. switch (item.name) {
  419. case 'local':
  420. // #ifndef H5
  421. uni.downloadFile({
  422. url: item.url,
  423. success: res => {
  424. if (res.statusCode === 200) {
  425. uni.saveFile({
  426. tempFilePath: res.tempFilePath,
  427. success: function(res) {
  428. that.downtips = true;
  429. that.description = res.savedFilePath;
  430. },
  431. fail(err) {
  432. console.log(err);
  433. }
  434. });
  435. }
  436. }
  437. });
  438. // #endif
  439. // #ifdef H5
  440. window.open(item.url);
  441. // #endif
  442. break;
  443. case 'baidu':
  444. // #ifdef APP-PLUS || H5
  445. if (item.password) {
  446. this.dowshow = true;
  447. this.downurl = item.url;
  448. this.baucode = item.password;
  449. } else {
  450. window.open(item.url);
  451. }
  452. // #endif
  453. // #ifdef MP
  454. this.dowshow = true;
  455. this.downurl = item.url;
  456. this.baucode = item.password;
  457. // #endif
  458. break;
  459. }
  460. },
  461. copydown() {
  462. this.$util.uniCopy({
  463. content: this.baucode,
  464. success: () => {
  465. this.$u.toast('提取码复制成功!');
  466. }
  467. });
  468. },
  469. goTag(name) {
  470. this.$Router.push({
  471. path: '/pages/tag/tag',
  472. query: { name: name }
  473. });
  474. },
  475. // #ifdef APP-PLUS
  476. openShare() {
  477. this.$refs.faShare.show();
  478. },
  479. // #endif
  480. openproduct(){
  481. this.$Router.push({
  482. path: '/pages/product/detail',
  483. query: { id: this.archivesInfo.productid }
  484. });
  485. }
  486. },
  487. onPageScroll(e) {
  488. this.scrollTop = e.scrollTop;
  489. },
  490. onReachBottom() {
  491. if (this.has_more) {
  492. this.page += 1;
  493. this.goCommentIndex();
  494. }
  495. }
  496. };
  497. </script>
  498. <style lang="scss">
  499. page {
  500. background-color: #f4f6f8;
  501. }
  502. .detail-tag {
  503. color: #aaa;
  504. }
  505. .comment {
  506. background-color: #ffffff;
  507. display: flex;
  508. padding: 30rpx;
  509. .left {
  510. image {
  511. width: 64rpx;
  512. height: 64rpx;
  513. border-radius: 50%;
  514. background-color: #f2f2f2;
  515. }
  516. }
  517. .right {
  518. flex: 1;
  519. padding-left: 20rpx;
  520. .top {
  521. display: flex;
  522. justify-content: space-between;
  523. align-items: center;
  524. margin-bottom: 10rpx;
  525. .replay {
  526. display: flex;
  527. align-items: center;
  528. color: #9a9a9a;
  529. font-size: 26rpx;
  530. .opeate {
  531. margin-right: 4rpx;
  532. color: #9a9a9a;
  533. }
  534. }
  535. .name {
  536. max-width: 100rpx;
  537. }
  538. }
  539. .content {
  540. margin-bottom: 10rpx;
  541. word-break: break-word;
  542. }
  543. }
  544. }
  545. .comment:not(:last-child) {
  546. border-bottom: 1px solid #eee;
  547. }
  548. .product-images {
  549. width: 50%;
  550. margin-bottom: 30rpx;
  551. }
  552. .product-images:nth-child(2n) {
  553. padding-left: 15rpx;
  554. }
  555. .product-images:nth-child(2n + 1) {
  556. padding-right: 15rpx;
  557. }
  558. .u-alert-desc {
  559. word-break: break-word;
  560. }
  561. </style>