shareLive.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. <template>
  2. <view>
  3. <!-- 搜索框 -->
  4. <view class="top-fixed">
  5. <view class="search-cont">
  6. <view class="inner">
  7. <image class="icon-search" src="https://kntobs.jnmyunl.com/shop/images/search.png" mode=""></image>
  8. <input type="text" @confirm="goSearch" :value="searchKey" placeholder="输入直播间名称" placeholder-style="font-size:28rpx;color:#BBBBBB;font-family: PingFang SC;" />
  9. </view>
  10. </view>
  11. </view>
  12. <mescroll-body top="108rpx" ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback" :down="downOption"
  13. :up="upOption">
  14. <view class="live-list">
  15. <view v-for="(item,index) in dataList" :key="index" class="item">
  16. <view class="bottom-box">
  17. <view class="left">
  18. <image class="img" v-if="item.liveImgUrl" :src="item.liveImgUrl"></image>
  19. <text class="ml30 label">{{item.liveName}}</text>
  20. </view>
  21. <view class="btn-box">
  22. <view class="btn pay" @click.stop="showDetail(item)">
  23. 分享直播间
  24. </view>
  25. <u-popup :show="show" @close="close">
  26. <view class="pop">
  27. <!-- 确保这里正确绑定方法 -->
  28. <view class="item" @click="generateAndCopyLink(currentItem)">
  29. <image class="w72 h72 mr20" src="/static/share_link.png"></image>
  30. <text>复制链接</text>
  31. </view>
  32. <view class="item">
  33. <button open-type="share" class="button"
  34. :data-item="JSON.stringify(currentItem)" @click="setShareItem(currentItem)">
  35. <image class="w72 h72 mr20" src="https://kntobs.jnmyunl.com/userapp/images/weixin1.png">
  36. </image>
  37. <text>分享直播间</text>
  38. </button>
  39. </view>
  40. <view class="cancel" @click="close">取消</view>
  41. </view>
  42. </u-popup>
  43. </view>
  44. </view>
  45. </view>
  46. </view>
  47. </mescroll-body>
  48. </view>
  49. </template>
  50. <script>
  51. import {
  52. getGotoWxAppLiveLink,
  53. liveShareList
  54. } from '@/api/living.js'
  55. import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
  56. export default {
  57. mixins: [MescrollMixin],
  58. data() {
  59. return {
  60. show: false,
  61. userinfo: {},
  62. currentShareItem: null,
  63. currentItem: null, // 添加当前项存储
  64. searchKey: "",
  65. mescroll: null,
  66. // 上拉加载的配置
  67. upOption: {
  68. onScroll: true,
  69. use: true, // 是否启用上拉加载; 默认true
  70. page: {
  71. num: 0, // 当前页码,默认0,回调之前会加1,即callback(page)会从1开始
  72. size: 10 // 每页数据的数量,默认10
  73. },
  74. noMoreSize: 10, // 配置列表的总数量要大于等于5条才显示'-- END --'的提示
  75. empty: {
  76. icon: '/static/images/no_data.png',
  77. tip: '暂无数据'
  78. }
  79. },
  80. item: null,
  81. companyId: null,
  82. companyUserId: null,
  83. // 列表数据
  84. dataList: [],
  85. };
  86. },
  87. onLoad(options) {
  88. console.log("分享直播间options", options)
  89. var that = this;
  90. // uni.$on('refreshOrder', () => {
  91. that.mescroll.resetUpScroll()
  92. // })
  93. this.companyId = options.companyId;
  94. this.companyUserId = options.companyUserId;
  95. this.userinfo = uni.getStorageSync("userInfo")
  96. },
  97. computed: {
  98. appid() {
  99. return this.$store.state.appid
  100. },
  101. imgPath() {
  102. return this.$store.state.imgpath
  103. }
  104. },
  105. onShareAppMessage() {
  106. const item = this.currentShareItem || {};
  107. console.log("item.liveId", item.liveId)
  108. console.log("this.companyUserId", this.companyUserId)
  109. return {
  110. title: '邀请你来观看直播:' + item.liveName,
  111. path: `/pages_course/living?companyId=${this.companyId}&companyUserId=${this.companyUserId}&liveId=${item.liveId}`,
  112. // imageUrl: this.products.image,
  113. imageUrl: '/static/logo.png',
  114. success(res) {
  115. console.log("分享成功", res);
  116. },
  117. fail(err) {
  118. console.error("分享失败", err);
  119. }
  120. };
  121. },
  122. methods: {
  123. async generateAndCopyLink(item) {
  124. console.log("复制链接被点击>>>", item);
  125. if (!item) {
  126. uni.showToast({
  127. title: '请先选择直播项目',
  128. icon: 'none'
  129. });
  130. return;
  131. }
  132. try {
  133. // 等待获取短链接
  134. const shareLink = await this.getGotoWxAppLiveLink(item);
  135. console.log("获取到的分享链接:", shareLink);
  136. if (!shareLink) {
  137. uni.showToast({
  138. title: '暂无链接',
  139. icon: 'none'
  140. });
  141. return;
  142. }
  143. // 复制到剪贴板
  144. await this.copyToClipboard(shareLink);
  145. this.close()
  146. } catch (error) {
  147. console.error('获取短链接失败:', error);
  148. uni.showToast({
  149. title: '暂无链接',
  150. icon: 'none'
  151. });
  152. }
  153. },
  154. getGotoWxAppLiveLink(item) {
  155. return new Promise((resolve, reject) => {
  156. if (!this.companyId) {
  157. reject(new Error('companyId 不存在'));
  158. return;
  159. }
  160. if (!item || !item.liveId) {
  161. reject(new Error('直播项目信息不完整'));
  162. return;
  163. }
  164. const data = {
  165. liveId: item.liveId,
  166. companyUserId: this.companyUserId,
  167. }
  168. console.log("请求短链接参数:", data);
  169. getGotoWxAppLiveLink(data).then(res => {
  170. console.log("短链接口返回:", res);
  171. if (res.code == 200) {
  172. // 正确使用 resolve 返回数据
  173. resolve( res.result.link || res.result || res);
  174. } else {
  175. uni.showToast({
  176. icon: 'none',
  177. title: "获取链接失败",
  178. });
  179. reject(new Error('请求失败: ' + (res.message || res.msg || '未知错误')));
  180. }
  181. }).catch(err => {
  182. console.error("获取链接异常:", err);
  183. reject(err);
  184. });
  185. });
  186. },
  187. // 复制到剪贴板
  188. copyToClipboard(text) {
  189. return new Promise((resolve, reject) => {
  190. if (!text) {
  191. uni.showToast({
  192. title: '暂无链接',
  193. icon: 'none'
  194. });
  195. reject(new Error('链接为空'));
  196. return;
  197. }
  198. uni.setClipboardData({
  199. data: text,
  200. success: () => {
  201. uni.showToast({
  202. title: '链接已复制',
  203. icon: 'success'
  204. });
  205. resolve();
  206. },
  207. fail: (err) => {
  208. uni.showToast({
  209. title: '复制失败',
  210. icon: 'none'
  211. });
  212. reject(err);
  213. }
  214. });
  215. });
  216. },
  217. close() {
  218. this.show = false
  219. this.currentItem = null; // 关闭时清空当前项
  220. },
  221. // 记录当前要分享的item
  222. setShareItem(item) {
  223. console.log("setShareItem接收到的参数:", item);
  224. // 如果item是字符串,需要解析;如果是对象,直接使用
  225. if (typeof item === 'string') {
  226. try {
  227. this.currentShareItem = JSON.parse(item);
  228. } catch (error) {
  229. console.error("JSON解析失败:", error);
  230. this.currentShareItem = null;
  231. }
  232. } else if (typeof item === 'object' && item !== null) {
  233. // 如果已经是对象,直接赋值
  234. this.currentShareItem = item;
  235. } else {
  236. console.error("setShareItem接收到无效的参数:", item);
  237. this.currentShareItem = null;
  238. }
  239. console.log("设置后的currentShareItem:", this.currentShareItem);
  240. },
  241. goSearch(e) {
  242. this.searchKey = e.detail.value;
  243. this.mescroll.resetUpScroll()
  244. },
  245. mescrollInit(mescroll) {
  246. this.mescroll = mescroll;
  247. },
  248. /*下拉刷新的回调 */
  249. downCallback(mescroll) {
  250. mescroll.resetUpScroll()
  251. },
  252. upCallback(page) {
  253. //联网加载数据
  254. var that = this;
  255. if (!this.companyId) return;
  256. var data = {
  257. pageNum: page.num,
  258. pageSize: page.size,
  259. liveName:this.searchKey
  260. };
  261. liveShareList( data).then(res => {
  262. if (res.code == 200) {
  263. //设置列表数据
  264. if (page.num == 1) {
  265. that.dataList = res.rows;
  266. } else {
  267. that.dataList = that.dataList.concat(res.rows);
  268. }
  269. that.mescroll.endBySize(res.rows.length, res.total);
  270. } else {
  271. uni.showToast({
  272. icon: 'none',
  273. title: "请求失败",
  274. });
  275. that.dataList = null;
  276. that.mescroll.endErr();
  277. }
  278. });
  279. },
  280. showDetail(item) {
  281. console.log(item)
  282. this.currentItem = item; // 存储当前点击的item
  283. this.show = !this.show
  284. },
  285. }
  286. }
  287. </script>
  288. <style lang="scss">
  289. .top-fixed{
  290. width: 100%;
  291. position: fixed;
  292. top: 0;
  293. left: 0;
  294. z-index: 10;
  295. }
  296. .search-cont {
  297. padding: 16rpx 30rpx;
  298. background-color: #FFFFFF;
  299. .inner {
  300. box-sizing: border-box;
  301. width: 100%;
  302. height: 72rpx;
  303. background: #F7F7F7;
  304. border-radius: 36rpx;
  305. display: flex;
  306. align-items: center;
  307. padding: 0 30rpx;
  308. .icon-search {
  309. width: 28rpx;
  310. height: 28rpx;
  311. margin-right: 20rpx;
  312. }
  313. input {
  314. height: 60rpx;
  315. line-height: 60rpx;
  316. flex: 1;
  317. }
  318. }
  319. }
  320. .live-list {
  321. padding: 20rpx;
  322. .item {
  323. background: #FFFFFF;
  324. border-radius: 16rpx;
  325. padding: 20rpx 30rpx;
  326. margin-bottom: 20rpx;
  327. .bottom-box {
  328. display: flex;
  329. align-items: center;
  330. justify-content: space-between;
  331. .left {
  332. display: flex;
  333. align-items: center;
  334. .img {
  335. width: 140rpx;
  336. height: 140rpx;
  337. }
  338. .label {
  339. max-width: 300rpx;
  340. font-size: 28rpx;
  341. font-weight: 500;
  342. color: #999999;
  343. line-height: 1;
  344. }
  345. .price-box {
  346. display: flex;
  347. align-items: flex-end;
  348. .unit {
  349. font-size: 24rpx;
  350. font-family: PingFang SC;
  351. font-weight: 500;
  352. color: #FF6633;
  353. line-height: 1.2;
  354. margin-right: 4rpx;
  355. }
  356. .num {
  357. font-size: 32rpx;
  358. font-family: PingFang SC;
  359. font-weight: bold;
  360. color: #FF6633;
  361. line-height: 1;
  362. }
  363. }
  364. }
  365. .btn-box {
  366. box-sizing: border-box;
  367. display: flex;
  368. align-items: center;
  369. .btn {
  370. font-size: 28rpx;
  371. color: #F7F7F7;
  372. padding: 12rpx 20rpx;
  373. background-color: #2BC7B9;
  374. font-weight: 500;
  375. border-radius: 15rpx;
  376. }
  377. button {
  378. background-color: transparent !important;
  379. width: 100% !important;
  380. display: flex;
  381. justify-content: flex-start;
  382. padding: 0;
  383. font-size: 30rpx;
  384. }
  385. button:after {
  386. border: none !important;
  387. border-radius: 10px;
  388. box-sizing: border-box;
  389. }
  390. .pop {
  391. display: flex;
  392. flex-direction: column;
  393. background-color: #f1f1f1;
  394. padding: 40rpx 30rpx;
  395. .item {
  396. display: flex;
  397. align-items: center;
  398. padding: 20rpx;
  399. font-size: 30rpx;
  400. }
  401. .cancel {
  402. width: 100%;
  403. height: 100rpx;
  404. line-height: 100rpx;
  405. text-align: center;
  406. background-color: #FFFFFF;
  407. border-radius: 50rpx;
  408. font-weight: 500;
  409. font-size: 34rpx;
  410. }
  411. }
  412. }
  413. }
  414. }
  415. }
  416. </style>