index.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621
  1. <template>
  2. <app-layout>
  3. <cover-view v-if="friendModel" class="friend-box">
  4. <cover-view class="info main-center cross-center dir-top-nowrap">
  5. <cover-view class="dir-left-nowrap cross-center">
  6. <cover-image src="/static/image/icon/friend-v.png" class="icon"></cover-image>
  7. <cover-view class="text">文本已复制到剪贴板</cover-view>
  8. </cover-view>
  9. <cover-view class="dir-left-nowrap cross-center" style="margin-top: 30rpx">
  10. <cover-image src="/static/image/icon/friend-v.png" class="icon"></cover-image>
  11. <cover-view v-if="is_video" class="text">视频已保存到相册</cover-view>
  12. <cover-view v-else class="text">图片已保存到相册</cover-view>
  13. </cover-view>
  14. </cover-view>
  15. </cover-view>
  16. <view>
  17. <text id="opacity-hide" class="opacity-hide">
  18. 第一行
  19. 第二行
  20. 第三行
  21. 第四行
  22. 第五行
  23. </text>
  24. <view class="fixed">
  25. <view class="share-head-margin">
  26. <view class="share-head dir-left-nowrap">
  27. <view class="box-grow-1 main-center cross-center"
  28. :class="[`goods`, tab===`goods`? `${tab}-active`: '']"
  29. @click="tabChange(`goods`)">商品
  30. </view>
  31. <view class="box-grow-1 main-center cross-center"
  32. :class="[`dynamic`, tab===`dynamic`? `${tab}-active`: '']"
  33. @click="tabChange(`dynamic`)">动态
  34. </view>
  35. </view>
  36. </view>
  37. <view class="share-center dir-left-nowrap" v-if="tab === `goods`">
  38. <view class="dir-left-nowrap cross-center value">
  39. <view @click="sortChange(sort===1?2:1)" :class="[sort===1 || sort===2 ? `active`: ``]">最新商品
  40. </view>
  41. <icon v-if="sort === 1" class="sort-plus"></icon>
  42. <icon v-else-if="sort === 2" class="sort-less"></icon>
  43. <icon v-else class="sort-default"></icon>
  44. </view>
  45. <view class="dir-left-nowrap cross-center value">
  46. <view @click="sortChange(sort===3?4:3)" :class="[sort===3 || sort===4 ? `active`: ``]">最新素材
  47. </view>
  48. <icon v-if="sort === 3" class="sort-plus"></icon>
  49. <icon v-else-if="sort === 4" class="sort-less"></icon>
  50. <icon v-else class="sort-default"></icon>
  51. </view>
  52. <view class="dir-left-nowrap cross-center value">
  53. <view @click="sortChange(sort===5?6:5)" :class="[sort===5 || sort===6 ? `active`: ``]">销量
  54. </view>
  55. <icon v-if="sort === 5" class="sort-plus"></icon>
  56. <icon v-else-if="sort === 6" class="sort-less"></icon>
  57. <icon v-else class="sort-default"></icon>
  58. </view>
  59. </view>
  60. </view>
  61. <view :class="tab + `-margin`">
  62. <view class="share-goods" v-for="(item,index) in list" :key="index">
  63. <view v-if="item.is_top" class="goods-top dir-left-nowrap">
  64. <icon class="top box-grow-0"></icon>
  65. <view>置顶</view>
  66. </view>
  67. <view class="goods-head dir-left-nowrap">
  68. <view class="dir-top-nowrap">
  69. <view class="t-omit goods-name">{{item.mall_name}}</view>
  70. <view class="goods-time">{{item.format_time}}</view>
  71. </view>
  72. <view v-if="tab === `goods`" @click="navDetail(item)"
  73. class="goods-detail main-center box-grow-0 cross-center">商品详情
  74. </view>
  75. </view>
  76. <view class="goods-text">
  77. <text class="opacity-hide" space="nbsp" :id="`all_hide_text_` + index"
  78. v-text="item.share_text"></text>
  79. <text class="share-text" :class="{'limit': allTextList.indexOf(index) === -1}"
  80. space="nbsp" v-text="item.share_text"></text>
  81. <view v-if="item.is_all_btn" class="all" @click="showText(index)">
  82. <block v-if="allTextList.indexOf(index) === -1">全文</block>
  83. <block v-else>收起</block>
  84. </view>
  85. </view>
  86. <view v-if="item.goods_id ===0 && item.material_video_url" class="goods-video">
  87. <video :src="item.material_video_url" show-mute-btn
  88. :poster="item.material_cover_url"></video>
  89. </view>
  90. <view v-else class="goods-image dir-left-wrap">
  91. <view v-for="(item1,index1) in item.share_pic" :key="index1">
  92. <image @click="previewImage(item.share_pic, index1)" :src="item1.pic_url" lazy-load></image>
  93. </view>
  94. </view>
  95. <view class="goods-set cross-center dir-left-nowrap">
  96. <view class="box-grow-0" @click="copyText(item)">复制文本</view>
  97. <view class="box-grow-0 margin" @click="saveImage(item)"
  98. v-if="item.goods_id ===0 && item.material_video_url">下载视频
  99. </view>
  100. <view class="box-grow-0 margin" v-else @click="saveImage(item)">保存图片</view>
  101. <view class="box-grow-0" @click="setPoster(item)">生成海报</view>
  102. <view class="line"></view>
  103. <view class="box-grow-0">分享到</view>
  104. <image @click="batchCopy(item)" class="friend box-grow-0"></image>
  105. <app-jump-button open_type="share">
  106. <image @click="shareCard(item)" class="card"></image>
  107. </app-jump-button>
  108. </view>
  109. </view>
  110. </view>
  111. <view class="box" :class="{'app-show-hidden': posterShow}">
  112. <app-goods-preview-poster
  113. v-model="posterShow" @close="posterShow = false" :url="posterUrl"
  114. ></app-goods-preview-poster>
  115. </view>
  116. </view>
  117. </app-layout>
  118. </template>
  119. <script>
  120. import appGoodsPreviewPoster from '../../../components/page-component/goods/app-goods-preview-poster';
  121. export default {
  122. name: "index",
  123. components: {
  124. appGoodsPreviewPoster,
  125. },
  126. data() {
  127. return {
  128. friendModel: false,
  129. is_video: false,
  130. tab: 'goods',
  131. sort: 1,
  132. page: 1,
  133. args: false,
  134. load: false,
  135. list: [],
  136. allTextList: [],
  137. shareData: {},
  138. posterShow: false,
  139. posterUrl: '',
  140. }
  141. },
  142. onReachBottom: function () {
  143. const self = this;
  144. if (self.args || self.load)
  145. return;
  146. self.load = true;
  147. let page = self.page + 1;
  148. self.$request({
  149. url: self.$api.quick_share.goods,
  150. data: {
  151. type: self.tab,
  152. sort: self.sort,
  153. page,
  154. }
  155. }).then(info => {
  156. if (info.code === 0) {
  157. //todo
  158. info.data.list.forEach(v => {
  159. v.is_all_btn = false;
  160. });
  161. [self.page, self.args, self.list] = [page, info.data.list.length === 0, self.list.concat(info.data.list)];
  162. self.formatList();
  163. }
  164. self.load = false;
  165. });
  166. },
  167. onLoad: function (options) {
  168. this.loadData();
  169. },
  170. onShareAppMessage(params) {
  171. if (params.from === 'button') {
  172. return this.$shareAppMessage(this.shareData);
  173. }
  174. },
  175. methods: {
  176. navDetail(column) {
  177. uni.navigateTo({url: `/pages/goods/goods?id=` + column.goods_id});
  178. },
  179. previewImage(list, index) {
  180. const urls = list.map(item => {
  181. return item.pic_url;
  182. });
  183. uni.previewImage({
  184. urls: urls,
  185. current: index,
  186. });
  187. },
  188. showText(index) {
  189. let key = this.allTextList.indexOf(index);
  190. if (key === -1) {
  191. this.allTextList.splice(-1, 0, index);
  192. } else {
  193. this.allTextList.splice(key, 1);
  194. }
  195. },
  196. sortChange(sort) {
  197. [this.list, this.allTextList] = [[], []];
  198. [this.page, this.args, this.sort] = [1, false, sort];
  199. this.loadData();
  200. },
  201. tabChange(tab) {
  202. [this.list, this.allTextList] = [[], []];
  203. [this.page, this.args, this.tab] = [1, false, tab];
  204. this.loadData();
  205. },
  206. loadData() {
  207. const self = this;
  208. self.$showLoading({text: '加载中'});
  209. self.$request({
  210. url: self.$api.quick_share.goods,
  211. data: {
  212. page: 1,
  213. type: self.tab,
  214. sort: self.sort,
  215. }
  216. }).then(info => {
  217. self.$hideLoading();
  218. if (info.code === 0) {
  219. info.data.list.forEach(v => {
  220. v.is_all_btn = false;
  221. })
  222. self.list = info.data.list;
  223. self.formatList();
  224. }
  225. }).catch(info => {
  226. self.$hideLoading();
  227. })
  228. },
  229. formatList() {
  230. const self = this;
  231. setTimeout(() => {
  232. let list = JSON.parse(JSON.stringify(self.list));
  233. const query = uni.createSelectorQuery().in(this);
  234. query.select('#opacity-hide').boundingClientRect(item => {
  235. list.forEach((v, k) => {
  236. let key = uni.createSelectorQuery().in(self);
  237. key.select(`#all_hide_text_` + k).boundingClientRect(item1 => {
  238. v.is_all_btn = item1.height + 1 >= item.height;
  239. }).exec();
  240. });
  241. self.list = list;
  242. }).exec();
  243. })
  244. },
  245. saveImage(column, customize_success = false) {
  246. let self = this;
  247. self.is_video = column.goods_id === 0 && column.material_video_url;
  248. const customize_a = function () {
  249. uni.showToast({title: '保存成功'});
  250. };
  251. const customize_b = function () {
  252. self.friendModel = true;
  253. setTimeout(() => {
  254. self.friendModel = false;
  255. }, 1500)
  256. };
  257. if (self.is_video) {
  258. const share_video = column.material_video_url;
  259. self.$utils.batchSave(share_video, 'video').then(result => {
  260. customize_success ? customize_b() : customize_a();
  261. });
  262. } else {
  263. uni.showLoading({title: `图片保存中`});
  264. self.$request({
  265. url: self.$api.quick_share.poster_list,
  266. data: {
  267. id: column.id,
  268. }
  269. }).then(info => {
  270. if (info.code === 0) {
  271. let urls = column.share_pic.map(item => {
  272. return item.pic_url;
  273. })
  274. urls.splice(-1, 1, info.data.pic_url);
  275. console.log(urls);
  276. self.$utils.batchSave(urls, 'image').then(result => {
  277. customize_success ? customize_b() : customize_a();
  278. });
  279. }
  280. }).catch(e => {
  281. uni.hideLoading();
  282. })
  283. }
  284. },
  285. setPoster(column) {
  286. this.posterUrl = this.$api.quick_share.poster + `&id=` + column.id;
  287. this.posterShow = true;
  288. },
  289. copyText(column) {
  290. uni.setClipboardData({
  291. data: column.share_text,
  292. success() {
  293. //#ifndef MP-WEIXIN
  294. uni.showToast({title: '复制成功'});
  295. // #endif
  296. }
  297. });
  298. },
  299. batchCopy(column) {
  300. this.copyText(column);
  301. this.saveImage(column, true);
  302. },
  303. shareCard(column) {
  304. const title = column.app_share_title ? column.app_share_title : column.share_text;
  305. let imageUrl = '';
  306. if (column.share_pic[0].pic_url) {
  307. imageUrl = column.share_pic[0].pic_url;
  308. }
  309. if (column.app_share_pic) {
  310. imageUrl = column.app_share_pic;
  311. }
  312. this.shareData = {
  313. title: title,
  314. imageUrl: imageUrl,
  315. path: column.goods_id === 0 ? '/pages/index/index' : '/pages/goods/goods',
  316. params: column.goods_id === 0 ? {} : {id: column.goods_id},
  317. }
  318. }
  319. }
  320. }
  321. </script>
  322. <style scoped lang="scss">
  323. .friend-box {
  324. position: fixed;
  325. top: #{563rpx};
  326. width: 100%;
  327. left: 0;
  328. .info > cover-view:first-child {
  329. margin-bottom: #{30rpx};
  330. }
  331. .info {
  332. width: #{413rpx};
  333. height: #{209rpx};
  334. color: #ffffff;
  335. font-size: #{28rpx};
  336. border-radius: #{16rpx};
  337. margin: 0 auto;
  338. background: rgba(0, 0, 0, 0.8);
  339. .text {
  340. padding-left: #{13rpx};
  341. }
  342. .icon {
  343. display: block;
  344. height: #{28rpx};
  345. width: #{28rpx};
  346. }
  347. }
  348. }
  349. .opacity-hide {
  350. position: fixed;
  351. top: 0;
  352. z-index: -10;
  353. opacity: 0;
  354. word-break: break-all;
  355. text-overflow: ellipsis;
  356. display: -webkit-box;
  357. -webkit-box-orient: vertical;
  358. overflow: hidden;
  359. white-space: normal !important;
  360. -webkit-line-clamp: 5;
  361. }
  362. .fixed {
  363. position: fixed;
  364. top: 0;
  365. width: 100%;
  366. z-index: 10;
  367. .share-head-margin {
  368. padding: #{23rpx} 0;
  369. background: #ffffff;
  370. .share-head {
  371. text-align: center;
  372. width: #{323rpx};
  373. margin: 0 auto;
  374. font-size: #{28rpx};
  375. height: #{56rpx};
  376. color: #666666;
  377. .goods {
  378. border-top-left-radius: #{30rpx};
  379. border-bottom-left-radius: #{30rpx};
  380. border-top: 1px solid #446dfd;
  381. border-bottom: 1px solid #446dfd;
  382. border-left: 1px solid #446dfd;
  383. }
  384. .dynamic {
  385. border-top-right-radius: #{30rpx};
  386. border-bottom-right-radius: #{30rpx};
  387. border-top: 1px solid #446dfd;
  388. border-bottom: 1px solid #446dfd;
  389. border-right: 1px solid #446dfd;
  390. }
  391. .dynamic-active, .goods-active {
  392. background: #446dfd;
  393. color: #ffffff;
  394. }
  395. }
  396. }
  397. .share-center {
  398. padding: 0 #{60rpx};
  399. height: #{96rpx};
  400. font-size: #{28rpx};
  401. background: #FFFFFF;
  402. justify-content: space-between;
  403. .value > view {
  404. margin-right: #{9rpx};
  405. }
  406. .active {
  407. color: #446dfd;
  408. }
  409. icon {
  410. background-repeat: no-repeat;
  411. background-size: 100% 100%;
  412. width: #{16upx};
  413. height: #{26upx};
  414. }
  415. .sort-default {
  416. background-image: url("../image/sort-blue-default.png");
  417. }
  418. .sort-less {
  419. background-image: url("../image/sort-blue-less.png");
  420. }
  421. .sort-plus {
  422. background-image: url("../image/sort-blue-plus.png");
  423. }
  424. }
  425. }
  426. .goods-margin {
  427. margin-top: #{196rpx};
  428. }
  429. .dynamic-margin {
  430. margin-top: #{100rpx};
  431. }
  432. .box {
  433. position: fixed;
  434. z-index: 1700;
  435. left: 0;
  436. bottom: 0;
  437. width: #{750rpx};
  438. opacity: 0;
  439. visibility: hidden;
  440. height: 100%;
  441. background-color: rgba(153, 153, 153, 0.5);
  442. }
  443. .app-show-hidden {
  444. opacity: 1;
  445. visibility: visible;
  446. }
  447. .share-goods {
  448. background: #FFFFFF;
  449. margin-bottom: #{15rpx};
  450. .goods-top {
  451. background: #FFFFFF;
  452. padding: #{14rpx} #{24rpx};
  453. font-size: #{26rpx};
  454. color: #ff4544;
  455. .top {
  456. background-repeat: no-repeat;
  457. background-size: 100% 100%;
  458. background-image: url("../image/goods-top.png");
  459. height: #{32rpx};
  460. width: #{28rpx};
  461. display: block;
  462. margin-right: #{12rpx};
  463. }
  464. }
  465. .goods-head {
  466. padding: #{40rpx} #{24rpx} 0 #{24rpx};
  467. .goods-name {
  468. color: #212121;
  469. font-size: #{34rpx};
  470. max-width: #{540rpx};
  471. line-height: 1;
  472. }
  473. .goods-time {
  474. margin-top: #{20rpx};
  475. color: #a0a0a0;
  476. font-size: #{24rpx};
  477. line-height: 1;
  478. }
  479. .goods-detail {
  480. color: #446dfd;
  481. font-size: #{26rpx};
  482. border: 1px solid #446dfd;
  483. border-radius: #{6rpx};
  484. height: #{50rpx};
  485. width: #{135rpx};
  486. margin-left: auto;
  487. }
  488. }
  489. .goods-text {
  490. padding: 0 #{24rpx};
  491. font-size: #{32rpx};
  492. color: #212121;
  493. margin-top: #{40rpx};
  494. .share-text {
  495. word-break: break-all;
  496. text-overflow: ellipsis;
  497. display: -webkit-box;
  498. -webkit-box-orient: vertical;
  499. overflow: hidden;
  500. white-space: normal !important;
  501. }
  502. .share-text.limit {
  503. -webkit-line-clamp: 4;
  504. }
  505. .all {
  506. padding-top: #{10rpx};
  507. color: #5b6a91;
  508. }
  509. }
  510. .goods-video {
  511. padding-top: #{15rpx};
  512. padding-bottom: #{30rpx};
  513. video {
  514. width: 100%;
  515. height: #{422rpx};
  516. }
  517. }
  518. .goods-image {
  519. padding: #{10rpx} #{18rpx} #{30rpx} #{18rpx};
  520. view {
  521. height: #{226rpx};
  522. width: #{226rpx};
  523. margin: #{6rpx};
  524. }
  525. image {
  526. height: 100%;
  527. width: 100%;
  528. display: block;
  529. }
  530. }
  531. .goods-set {
  532. color: #a0a0a0;
  533. font-size: #{28rpx};
  534. border-top: #{1rpx} solid #e2e2e2;
  535. padding: #{15rpx} #{24rpx};
  536. .margin {
  537. margin: 0 auto;
  538. }
  539. .line {
  540. height: #{60rpx};
  541. width: #{1px};
  542. margin: 0 #{26rpx};
  543. background: #dcdfe6;
  544. }
  545. image {
  546. background-repeat: no-repeat;
  547. background-size: 100% 100%;
  548. height: #{50rpx};
  549. width: #{50rpx};
  550. }
  551. .friend {
  552. margin-right: #{15rpx};
  553. margin-left: #{20rpx};
  554. background-image: url("../image/friend.png");
  555. }
  556. .card {
  557. background-image: url("../image/wechat.png");
  558. }
  559. }
  560. }
  561. </style>