SharePopup.vue 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. <template>
  2. <view class="share-modal" v-if="visible">
  3. <view class="modal-overlay" @click="handleClose"></view>
  4. <view class="modal-content">
  5. <view class="share-options">
  6. <view v-for="option in shareOptions" :key="option.id" class="share-item" @click="handleShare(option.id)">
  7. <view class="share-icon">
  8. <image :src="option.icon" :alt="option.title" mode="aspectFit"></image>
  9. </view>
  10. <text class="option-title">{{ option.title }}</text>
  11. </view>
  12. </view>
  13. </view>
  14. </view>
  15. </template>
  16. <script>
  17. export default {
  18. name: 'ShareModal',
  19. props: {
  20. visible: {
  21. type: Boolean,
  22. default: false
  23. },
  24. shareUrl: {
  25. type: String,
  26. required: true
  27. },
  28. shareTitle: {
  29. type: String,
  30. default: ''
  31. },
  32. shareDesc: {
  33. type: String,
  34. default: ''
  35. },
  36. shareImg: {
  37. type: String,
  38. default: ''
  39. }
  40. },
  41. data() {
  42. return {
  43. shareOptions: [
  44. { id: 'wechat', title: '微信好友', icon: '/static/icon/sy_icon_weixin.png' },
  45. { id: 'moments', title: '朋友圈', icon: '/static/icon/sy_icon_pengyouquan.png' },
  46. { id: 'qq', title: 'QQ好友', icon: '../../static/icon/sy_icon_qq.png' },
  47. { id: 'copy', title: '复制链接', icon: '/static/icon/sy_icon_fuzhilianjie.png' },
  48. { id: 'report', title: '举报', icon: '/static/icon/sy_icon_jubao01.png' },
  49. { id: 'more', title: '更多', icon: '../../static/icon/sy_icon_gengduo.png' }
  50. ]
  51. }
  52. },
  53. methods: {
  54. handleClose() {
  55. this.$emit('close')
  56. },
  57. handleShare(type) {
  58. switch (type) {
  59. case 'copy':
  60. this.copyToClipboard(this.shareUrl)
  61. break
  62. case 'wechat':
  63. this.shareToWechat()
  64. break
  65. case 'moments':
  66. this.shareToMoments()
  67. break
  68. case 'report':
  69. this.handleReport()
  70. break
  71. case 'qq':
  72. this.qqShare()
  73. break
  74. case 'more':
  75. this.moreShare()
  76. break
  77. }
  78. },
  79. copyToClipboard(text) {
  80. // #ifdef H5
  81. const input = document.createElement('input')
  82. input.value = text
  83. document.body.appendChild(input)
  84. input.select()
  85. document.execCommand('copy')
  86. document.body.removeChild(input)
  87. // #endif
  88. // #ifdef APP-PLUS || MP
  89. uni.setClipboardData({
  90. data: text,
  91. success: () => {
  92. uni.showToast({
  93. title: '链接已复制',
  94. icon: 'success'
  95. })
  96. },
  97. fail: () => {
  98. uni.showToast({
  99. title: '复制失败',
  100. icon: 'none'
  101. })
  102. }
  103. })
  104. // #endif
  105. },
  106. shareToWechat() {
  107. // #ifdef APP-PLUS
  108. uni.share({
  109. provider: 'weixin',
  110. scene: 'WXSceneSession',
  111. type: 0,
  112. title: this.shareTitle,
  113. summary: this.shareDesc,
  114. imageUrl: this.shareImg,
  115. href: this.shareUrl,
  116. success: () => {
  117. uni.showToast({
  118. title: '分享成功',
  119. icon: 'success'
  120. })
  121. },
  122. fail: (err) => {
  123. uni.showToast({
  124. title: '分享失败',
  125. icon: 'none'
  126. })
  127. console.error('分享失败:', err)
  128. }
  129. })
  130. // #endif
  131. // #ifdef H5
  132. if (typeof wx !== 'undefined') {
  133. wx.ready(() => {
  134. wx.updateAppMessageShareData({
  135. title: this.shareTitle,
  136. desc: this.shareDesc,
  137. link: this.shareUrl,
  138. imgUrl: this.shareImg,
  139. success: () => {
  140. uni.showToast({
  141. title: '分享成功',
  142. icon: 'success'
  143. })
  144. },
  145. fail: (err) => {
  146. uni.showToast({
  147. title: '分享失败',
  148. icon: 'none'
  149. })
  150. console.error('分享失败:', err)
  151. }
  152. })
  153. })
  154. } else {
  155. uni.showToast({
  156. title: '请在微信中打开',
  157. icon: 'none'
  158. })
  159. }
  160. // #endif
  161. // #ifdef MP-WEIXIN
  162. uni.showShareMenu({
  163. withShareTicket: true,
  164. menus: ['shareAppMessage']
  165. })
  166. // #endif
  167. },
  168. shareToMoments() {
  169. // #ifdef APP-PLUS
  170. uni.share({
  171. provider: 'weixin',
  172. scene: 'WXSenceTimeline',
  173. type: 0,
  174. title: this.shareTitle,
  175. summary: this.shareDesc,
  176. imageUrl: this.shareImg,
  177. href: this.shareUrl,
  178. success: () => {
  179. uni.showToast({
  180. title: '分享成功',
  181. icon: 'success'
  182. })
  183. },
  184. fail: (err) => {
  185. uni.showToast({
  186. title: '分享失败',
  187. icon: 'none'
  188. })
  189. console.error('分享失败:', err)
  190. }
  191. })
  192. // #endif
  193. // #ifdef H5
  194. if (typeof wx !== 'undefined') {
  195. wx.ready(() => {
  196. wx.updateTimelineShareData({
  197. title: this.shareTitle,
  198. link: this.shareUrl,
  199. imgUrl: this.shareImg,
  200. success: () => {
  201. uni.showToast({
  202. title: '分享成功',
  203. icon: 'success'
  204. })
  205. },
  206. fail: (err) => {
  207. uni.showToast({
  208. title: '分享失败',
  209. icon: 'none'
  210. })
  211. console.error('分享失败:', err)
  212. }
  213. })
  214. })
  215. } else {
  216. uni.showToast({
  217. title: '请在微信中打开',
  218. icon: 'none'
  219. })
  220. }
  221. // #endif
  222. // #ifdef MP-WEIXIN
  223. uni.showShareMenu({
  224. withShareTicket: true,
  225. menus: ['shareTimeline']
  226. })
  227. // #endif
  228. },
  229. handleReport() {
  230. // 实现举报功能
  231. uni.$emit('check_login', () => {
  232. uni.navigateTo({
  233. url: '/pages/my/feedback'
  234. })
  235. })
  236. uni.showToast({
  237. title: '举报功能开发中',
  238. icon: 'none'
  239. })
  240. },
  241. qqShare() {
  242. // #ifdef APP-PLUS
  243. uni.share({
  244. provider: 'qq',
  245. type: 0,
  246. title: this.shareTitle,
  247. summary: this.shareDesc,
  248. imageUrl: this.shareImg,
  249. href: this.shareUrl,
  250. success: () => {
  251. uni.showToast({
  252. title: '分享成功',
  253. icon: 'success'
  254. })
  255. }
  256. })
  257. // #endif
  258. },
  259. moreShare() {
  260. // 更多分享方式
  261. uni.showToast({
  262. title: '更多分享功能开发中',
  263. icon: 'none'
  264. })
  265. }
  266. }
  267. }
  268. </script>
  269. <style scoped>
  270. .share-modal {
  271. position: fixed;
  272. left: 0;
  273. right: 0;
  274. top: 0;
  275. bottom: 0;
  276. z-index: 1000;
  277. }
  278. .modal-overlay {
  279. position: absolute;
  280. left: 0;
  281. right: 0;
  282. top: 0;
  283. bottom: 0;
  284. background-color: rgba(0, 0, 0, 0.4);
  285. }
  286. .modal-content {
  287. position: absolute;
  288. left: 0;
  289. right: 0;
  290. bottom: 0;
  291. background-color: #f2f6f2;
  292. border-top-left-radius: 12px;
  293. border-top-right-radius: 12px;
  294. padding: 16px;
  295. }
  296. .share-options {
  297. display: flex;
  298. flex-wrap: wrap;
  299. padding: 8px 16px;
  300. }
  301. .share-item {
  302. width: 25%;
  303. display: flex;
  304. flex-direction: column;
  305. align-items: center;
  306. gap: 8px;
  307. padding: 8px 0;
  308. }
  309. .share-icon {
  310. width: 44px;
  311. height: 44px;
  312. display: flex;
  313. justify-content: center;
  314. align-items: center;
  315. }
  316. .share-icon image {
  317. width: 100%;
  318. height: 100%;
  319. }
  320. .option-title {
  321. font-size: 13px;
  322. color: #333333;
  323. text-align: center;
  324. }
  325. </style>