瑶都万能墙
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

483 lines
10 KiB

  1. <template>
  2. <view class="page">
  3. <navbar title="群组详情" bgColor="#5baaff" color="#fff" leftClick @leftClick="$utils.navigateBack" />
  4. <!-- 群组信息 -->
  5. <view class="group-info">
  6. <view class="group-header">
  7. <image :src="groupInfo.image || '/static/image/logo.jpg'" class="group-avatar" mode="aspectFill"></image>
  8. <view class="group-details">
  9. <view class="group-name">{{ groupInfo.title || '群组名称' }}</view>
  10. <view class="group-desc">{{ groupInfo.titleText || '群组描述' }}</view>
  11. <view class="group-stats">
  12. <text class="member-count">{{ groupInfo.num || 0 }}</text>
  13. </view>
  14. </view>
  15. </view>
  16. <view class="group-actions">
  17. <view v-if="showQrCode" class="qr-code-section">
  18. <view class="qr-code-title">扫码加入群聊</view>
  19. <image
  20. :src="groupInfo.qrCode || '/static/image/qr/default.jpg'"
  21. show-menu-by-longpress
  22. class="qr-code-image" mode="aspectFit"></image>
  23. <view class="qr-code-tip">长按保存二维码微信扫码加入</view>
  24. </view>
  25. <view v-else class="watch-ad-btn" @click="watchAd">
  26. <uv-icon name="play-circle" size="30rpx" color="#fff"></uv-icon>
  27. <text>观看广告获取二维码</text>
  28. </view>
  29. <view v-if="userInfo.id == groupInfo.userId" class="admin-buttons">
  30. <view class="manage-btn" @click="manageGroup">
  31. <uv-icon name="setting" size="24rpx" color="#fff"></uv-icon>
  32. <text>编辑</text>
  33. </view>
  34. <view class="delete-btn" @click="deleteGroup">
  35. <uv-icon name="trash" size="24rpx" color="#fff"></uv-icon>
  36. <text>删除</text>
  37. </view>
  38. </view>
  39. </view>
  40. </view>
  41. <!-- 群组公告 -->
  42. <view v-if="groupInfo.notice" class="announcement">
  43. <view class="announcement-title">
  44. <uv-icon name="volume" size="30rpx" color="#5baaff"></uv-icon>
  45. <text>群组公告</text>
  46. </view>
  47. <view class="announcement-content">
  48. <uv-parse :content="groupInfo.notice"></uv-parse>
  49. </view>
  50. </view>
  51. <!-- 成员列表 -->
  52. <view class="member-section">
  53. <view class="section-header">
  54. <text class="section-title">群组成员</text>
  55. <text class="member-count-text">({{ groupInfo.num || 0 }})</text>
  56. </view>
  57. <view class="member-list" v-if="groupInfo.userList && groupInfo.userList.length > 0">
  58. <view
  59. v-for="(member, index) in groupInfo.userList"
  60. :key="index"
  61. class="member-item"
  62. @click="viewMemberProfile(member)"
  63. >
  64. <image :src="member.image || '/static/image/logo.jpg'" class="member-avatar" mode="aspectFill"></image>
  65. <view class="member-info">
  66. <view class="member-name">{{ member.userName || '用户' }}</view>
  67. </view>
  68. </view>
  69. </view>
  70. <view v-else class="empty-member">
  71. <uv-empty mode="list" text="暂无成员信息"></uv-empty>
  72. </view>
  73. </view>
  74. </view>
  75. </template>
  76. <script>
  77. import rewardedVideoAdMixin from '@/mixins/rewardedVideoAd.js'
  78. export default {
  79. mixins: [rewardedVideoAdMixin],
  80. data() {
  81. return {
  82. groupId: '',
  83. showQrCode: false, // 是否显示二维码
  84. groupInfo: {}
  85. // 视频广告相关数据已移至混入中
  86. }
  87. },
  88. onLoad(options) {
  89. if (options.id) {
  90. this.groupId = options.id
  91. this.getGroupDetail()
  92. }
  93. // initRewardedVideoAd() 已在混入的mounted中处理
  94. // 设置分享路径
  95. this.share.path = '/pages_order/group/groupDetail?id=' + options.id
  96. },
  97. methods: {
  98. // 广告观看完成回调
  99. onAdWatchComplete() {
  100. console.log('用户看完广告,显示群聊二维码')
  101. this.showQrCodeAfterAd()
  102. },
  103. // 广告观看取消回调
  104. onAdWatchCancel() {
  105. uni.showToast({
  106. title: '请观看完整广告才能获取二维码',
  107. icon: 'none'
  108. })
  109. },
  110. // 广告播放完成后显示二维码
  111. showQrCodeAfterAd() {
  112. this.showQrCode = true
  113. this.$api('groupJoin', {id : this.groupId})
  114. uni.showToast({
  115. title: '恭喜获得群聊二维码!',
  116. icon: 'success'
  117. })
  118. },
  119. // 获取群组详情
  120. getGroupDetail() {
  121. this.$api('groupDetail', { id: this.groupId }, res => {
  122. if (res.code === 200 && res.result) {
  123. this.groupInfo = res.result
  124. // 设置分享信息
  125. this.share.title = res.result.shareMsg || res.result.title || '群组详情'
  126. this.share.imageUrl = this.$utils.getImageOne(res.result.image)
  127. } else {
  128. uni.showToast({
  129. title: res.message || '获取群组详情失败',
  130. icon: 'none'
  131. })
  132. }
  133. })
  134. },
  135. // 观看广告
  136. watchAd() {
  137. console.log('watchAd 方法被调用')
  138. console.log('isWatchingAd:', this.isWatchingAd)
  139. console.log('rewardedVideoAd:', this.rewardedVideoAd)
  140. if (this.isWatchingAd) {
  141. console.log('正在观看广告,直接返回')
  142. return
  143. }
  144. console.log('开始显示激励视频广告')
  145. // 显示激励视频广告
  146. this.showRewardedVideoAd({
  147. onSuccess: this.onAdWatchComplete,
  148. onCancel: this.onAdWatchCancel,
  149. fallbackTitle: '广告加载失败',
  150. fallbackContent: '无法加载广告,是否直接显示二维码?'
  151. })
  152. },
  153. // 查看成员资料
  154. viewMemberProfile(member) {
  155. // this.$utils.navigateTo('/pages_order/profile/userProfile?id=' + member.id)
  156. },
  157. // 管理群组
  158. manageGroup() {
  159. this.$utils.navigateTo('/pages_order/group/createGroup?id=' + this.groupId)
  160. },
  161. // 删除群组
  162. deleteGroup() {
  163. uni.showModal({
  164. title: '确认删除',
  165. content: '确定要删除这个群组吗?删除后无法恢复!',
  166. confirmText: '删除',
  167. confirmColor: '#ff4757',
  168. success: (res) => {
  169. if (res.confirm) {
  170. this.confirmDeleteGroup()
  171. }
  172. }
  173. })
  174. },
  175. // 确认删除群组
  176. confirmDeleteGroup() {
  177. uni.showLoading({
  178. title: '删除中...'
  179. })
  180. this.$api('deleteGroup', { id: this.groupId }, res => {
  181. uni.hideLoading()
  182. if (res.code === 200) {
  183. uni.showToast({
  184. title: '删除成功',
  185. icon: 'success'
  186. })
  187. setTimeout(() => {
  188. this.$utils.navigateBack()
  189. }, 1500)
  190. } else {
  191. uni.showToast({
  192. title: res.message || '删除失败',
  193. icon: 'none'
  194. })
  195. }
  196. })
  197. }
  198. }
  199. }
  200. </script>
  201. <style scoped>
  202. .page {
  203. background-color: #f5f5f5;
  204. min-height: 100vh;
  205. }
  206. .group-info {
  207. background: #fff;
  208. margin: 20rpx;
  209. border-radius: 20rpx;
  210. padding: 30rpx;
  211. box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
  212. }
  213. .group-header {
  214. display: flex;
  215. align-items: center;
  216. margin-bottom: 30rpx;
  217. }
  218. .group-avatar {
  219. width: 120rpx;
  220. height: 120rpx;
  221. border-radius: 20rpx;
  222. margin-right: 30rpx;
  223. }
  224. .group-details {
  225. flex: 1;
  226. }
  227. .group-name {
  228. font-size: 36rpx;
  229. font-weight: bold;
  230. color: #333;
  231. margin-bottom: 10rpx;
  232. }
  233. .group-desc {
  234. font-size: 28rpx;
  235. color: #666;
  236. margin-bottom: 15rpx;
  237. }
  238. .group-stats {
  239. display: flex;
  240. align-items: center;
  241. }
  242. .member-count {
  243. font-size: 24rpx;
  244. color: #999;
  245. background: #f0f0f0;
  246. padding: 8rpx 16rpx;
  247. border-radius: 20rpx;
  248. }
  249. .group-actions {
  250. display: flex;
  251. flex-direction: column;
  252. gap: 20rpx;
  253. }
  254. .qr-code-section {
  255. background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  256. border-radius: 20rpx;
  257. padding: 40rpx;
  258. text-align: center;
  259. color: #fff;
  260. animation: fadeIn 0.5s ease-in-out;
  261. }
  262. .qr-code-title {
  263. font-size: 32rpx;
  264. font-weight: bold;
  265. margin-bottom: 30rpx;
  266. }
  267. .qr-code-image {
  268. width: 300rpx;
  269. height: 300rpx;
  270. background: #fff;
  271. border-radius: 20rpx;
  272. margin: 0 auto 30rpx;
  273. padding: 20rpx;
  274. box-sizing: border-box;
  275. }
  276. .qr-code-tip {
  277. font-size: 24rpx;
  278. opacity: 0.8;
  279. }
  280. .watch-ad-btn {
  281. background: linear-gradient(135deg, #ff6b6b 0%, #ee5a24 100%);
  282. border-radius: 20rpx;
  283. padding: 30rpx;
  284. display: flex;
  285. align-items: center;
  286. justify-content: center;
  287. gap: 15rpx;
  288. color: #fff;
  289. font-size: 30rpx;
  290. font-weight: bold;
  291. box-shadow: 0 8rpx 25rpx rgba(255, 107, 107, 0.3);
  292. transition: all 0.3s ease;
  293. }
  294. .watch-ad-btn:active {
  295. transform: translateY(2rpx);
  296. box-shadow: 0 4rpx 15rpx rgba(255, 107, 107, 0.3);
  297. }
  298. .admin-buttons {
  299. display: flex;
  300. gap: 20rpx;
  301. margin-top: 20rpx;
  302. }
  303. .manage-btn {
  304. background: linear-gradient(135deg, #5baaff 0%, #4285f4 100%);
  305. border-radius: 15rpx;
  306. padding: 15rpx 20rpx;
  307. display: flex;
  308. align-items: center;
  309. justify-content: center;
  310. gap: 8rpx;
  311. color: #fff;
  312. font-size: 24rpx;
  313. box-shadow: 0 4rpx 15rpx rgba(91, 170, 255, 0.3);
  314. flex: 1;
  315. transition: all 0.3s ease;
  316. }
  317. .manage-btn:active {
  318. transform: translateY(2rpx);
  319. box-shadow: 0 2rpx 10rpx rgba(91, 170, 255, 0.3);
  320. }
  321. .delete-btn {
  322. background: linear-gradient(135deg, #ff4757 0%, #ff3742 100%);
  323. border-radius: 15rpx;
  324. padding: 15rpx 20rpx;
  325. display: flex;
  326. align-items: center;
  327. justify-content: center;
  328. gap: 8rpx;
  329. color: #fff;
  330. font-size: 24rpx;
  331. box-shadow: 0 4rpx 15rpx rgba(255, 71, 87, 0.3);
  332. flex: 1;
  333. transition: all 0.3s ease;
  334. }
  335. .delete-btn:active {
  336. transform: translateY(2rpx);
  337. box-shadow: 0 4rpx 15rpx rgba(255, 71, 87, 0.3);
  338. }
  339. .announcement {
  340. background: #fff;
  341. margin: 20rpx;
  342. border-radius: 20rpx;
  343. padding: 30rpx;
  344. box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
  345. }
  346. .announcement-title {
  347. display: flex;
  348. align-items: center;
  349. gap: 15rpx;
  350. font-size: 32rpx;
  351. font-weight: bold;
  352. color: #333;
  353. margin-bottom: 20rpx;
  354. }
  355. .announcement-content {
  356. font-size: 28rpx;
  357. line-height: 1.6;
  358. color: #666;
  359. }
  360. .member-section {
  361. background: #fff;
  362. margin: 20rpx;
  363. border-radius: 20rpx;
  364. padding: 30rpx;
  365. box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
  366. }
  367. .section-header {
  368. display: flex;
  369. align-items: center;
  370. gap: 10rpx;
  371. margin-bottom: 30rpx;
  372. }
  373. .section-title {
  374. font-size: 32rpx;
  375. font-weight: bold;
  376. color: #333;
  377. }
  378. .member-count-text {
  379. font-size: 24rpx;
  380. color: #999;
  381. }
  382. .member-list {
  383. display: flex;
  384. flex-direction: column;
  385. gap: 20rpx;
  386. }
  387. .member-item {
  388. display: flex;
  389. align-items: center;
  390. padding: 20rpx;
  391. border-radius: 15rpx;
  392. background: #f8f9fa;
  393. transition: all 0.3s ease;
  394. }
  395. .member-item:active {
  396. background: #e9ecef;
  397. transform: scale(0.98);
  398. }
  399. .member-avatar {
  400. width: 80rpx;
  401. height: 80rpx;
  402. border-radius: 50%;
  403. margin-right: 20rpx;
  404. }
  405. .member-info {
  406. flex: 1;
  407. }
  408. .member-name {
  409. font-size: 28rpx;
  410. color: #333;
  411. }
  412. .empty-member {
  413. padding: 60rpx 0;
  414. text-align: center;
  415. }
  416. @keyframes fadeIn {
  417. from {
  418. opacity: 0;
  419. transform: translateY(20rpx);
  420. }
  421. to {
  422. opacity: 1;
  423. transform: translateY(0);
  424. }
  425. }
  426. </style>