瑶都万能墙
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.

486 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. this.rewardedRecordConfig.type = 9 // 9群聊
  97. this.rewardedRecordConfig.formId = this.groupId // 目标对象ID
  98. },
  99. methods: {
  100. // 广告观看完成回调
  101. onAdWatchComplete() {
  102. console.log('用户看完广告,显示群聊二维码')
  103. this.showQrCodeAfterAd()
  104. },
  105. // 广告观看取消回调
  106. onAdWatchCancel() {
  107. uni.showToast({
  108. title: '请观看完整广告才能获取二维码',
  109. icon: 'none'
  110. })
  111. },
  112. // 广告播放完成后显示二维码
  113. showQrCodeAfterAd() {
  114. this.showQrCode = true
  115. this.$api('groupJoin', {id : this.groupId})
  116. uni.showToast({
  117. title: '恭喜获得群聊二维码!',
  118. icon: 'success'
  119. })
  120. },
  121. // 获取群组详情
  122. getGroupDetail() {
  123. this.$api('groupDetail', { id: this.groupId }, res => {
  124. if (res.code === 200 && res.result) {
  125. this.groupInfo = res.result
  126. // 设置分享信息
  127. this.share.title = res.result.shareMsg || res.result.title || '群组详情'
  128. this.share.imageUrl = this.$utils.getImageOne(res.result.image)
  129. } else {
  130. uni.showToast({
  131. title: res.message || '获取群组详情失败',
  132. icon: 'none'
  133. })
  134. }
  135. })
  136. },
  137. // 观看广告
  138. watchAd() {
  139. console.log('watchAd 方法被调用')
  140. console.log('isWatchingAd:', this.isWatchingAd)
  141. console.log('rewardedVideoAd:', this.rewardedVideoAd)
  142. if (this.isWatchingAd) {
  143. console.log('正在观看广告,直接返回')
  144. return
  145. }
  146. console.log('开始显示激励视频广告')
  147. // 显示激励视频广告
  148. this.showRewardedVideoAd({
  149. onSuccess: this.onAdWatchComplete,
  150. onCancel: this.onAdWatchCancel,
  151. fallbackTitle: '广告加载失败',
  152. fallbackContent: '无法加载广告,是否直接显示二维码?'
  153. })
  154. },
  155. // 查看成员资料
  156. viewMemberProfile(member) {
  157. // this.$utils.navigateTo('/pages_order/profile/userProfile?id=' + member.id)
  158. },
  159. // 管理群组
  160. manageGroup() {
  161. this.$utils.navigateTo('/pages_order/group/createGroup?id=' + this.groupId)
  162. },
  163. // 删除群组
  164. deleteGroup() {
  165. uni.showModal({
  166. title: '确认删除',
  167. content: '确定要删除这个群组吗?删除后无法恢复!',
  168. confirmText: '删除',
  169. confirmColor: '#ff4757',
  170. success: (res) => {
  171. if (res.confirm) {
  172. this.confirmDeleteGroup()
  173. }
  174. }
  175. })
  176. },
  177. // 确认删除群组
  178. confirmDeleteGroup() {
  179. uni.showLoading({
  180. title: '删除中...'
  181. })
  182. this.$api('deleteGroup', { id: this.groupId }, res => {
  183. uni.hideLoading()
  184. if (res.code === 200) {
  185. uni.showToast({
  186. title: '删除成功',
  187. icon: 'success'
  188. })
  189. setTimeout(() => {
  190. this.$utils.navigateBack()
  191. }, 1500)
  192. } else {
  193. uni.showToast({
  194. title: res.message || '删除失败',
  195. icon: 'none'
  196. })
  197. }
  198. })
  199. }
  200. }
  201. }
  202. </script>
  203. <style scoped>
  204. .page {
  205. background-color: #f5f5f5;
  206. min-height: 100vh;
  207. }
  208. .group-info {
  209. background: #fff;
  210. margin: 20rpx;
  211. border-radius: 20rpx;
  212. padding: 30rpx;
  213. box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
  214. }
  215. .group-header {
  216. display: flex;
  217. align-items: center;
  218. margin-bottom: 30rpx;
  219. }
  220. .group-avatar {
  221. width: 120rpx;
  222. height: 120rpx;
  223. border-radius: 20rpx;
  224. margin-right: 30rpx;
  225. }
  226. .group-details {
  227. flex: 1;
  228. }
  229. .group-name {
  230. font-size: 36rpx;
  231. font-weight: bold;
  232. color: #333;
  233. margin-bottom: 10rpx;
  234. }
  235. .group-desc {
  236. font-size: 28rpx;
  237. color: #666;
  238. margin-bottom: 15rpx;
  239. }
  240. .group-stats {
  241. display: flex;
  242. align-items: center;
  243. }
  244. .member-count {
  245. font-size: 24rpx;
  246. color: #999;
  247. background: #f0f0f0;
  248. padding: 8rpx 16rpx;
  249. border-radius: 20rpx;
  250. }
  251. .group-actions {
  252. display: flex;
  253. flex-direction: column;
  254. gap: 20rpx;
  255. }
  256. .qr-code-section {
  257. background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  258. border-radius: 20rpx;
  259. padding: 40rpx;
  260. text-align: center;
  261. color: #fff;
  262. animation: fadeIn 0.5s ease-in-out;
  263. }
  264. .qr-code-title {
  265. font-size: 32rpx;
  266. font-weight: bold;
  267. margin-bottom: 30rpx;
  268. }
  269. .qr-code-image {
  270. width: 300rpx;
  271. height: 300rpx;
  272. background: #fff;
  273. border-radius: 20rpx;
  274. margin: 0 auto 30rpx;
  275. padding: 20rpx;
  276. box-sizing: border-box;
  277. }
  278. .qr-code-tip {
  279. font-size: 24rpx;
  280. opacity: 0.8;
  281. }
  282. .watch-ad-btn {
  283. background: linear-gradient(135deg, #ff6b6b 0%, #ee5a24 100%);
  284. border-radius: 20rpx;
  285. padding: 30rpx;
  286. display: flex;
  287. align-items: center;
  288. justify-content: center;
  289. gap: 15rpx;
  290. color: #fff;
  291. font-size: 30rpx;
  292. font-weight: bold;
  293. box-shadow: 0 8rpx 25rpx rgba(255, 107, 107, 0.3);
  294. transition: all 0.3s ease;
  295. }
  296. .watch-ad-btn:active {
  297. transform: translateY(2rpx);
  298. box-shadow: 0 4rpx 15rpx rgba(255, 107, 107, 0.3);
  299. }
  300. .admin-buttons {
  301. display: flex;
  302. gap: 20rpx;
  303. margin-top: 20rpx;
  304. }
  305. .manage-btn {
  306. background: linear-gradient(135deg, #5baaff 0%, #4285f4 100%);
  307. border-radius: 15rpx;
  308. padding: 15rpx 20rpx;
  309. display: flex;
  310. align-items: center;
  311. justify-content: center;
  312. gap: 8rpx;
  313. color: #fff;
  314. font-size: 24rpx;
  315. box-shadow: 0 4rpx 15rpx rgba(91, 170, 255, 0.3);
  316. flex: 1;
  317. transition: all 0.3s ease;
  318. }
  319. .manage-btn:active {
  320. transform: translateY(2rpx);
  321. box-shadow: 0 2rpx 10rpx rgba(91, 170, 255, 0.3);
  322. }
  323. .delete-btn {
  324. background: linear-gradient(135deg, #ff4757 0%, #ff3742 100%);
  325. border-radius: 15rpx;
  326. padding: 15rpx 20rpx;
  327. display: flex;
  328. align-items: center;
  329. justify-content: center;
  330. gap: 8rpx;
  331. color: #fff;
  332. font-size: 24rpx;
  333. box-shadow: 0 4rpx 15rpx rgba(255, 71, 87, 0.3);
  334. flex: 1;
  335. transition: all 0.3s ease;
  336. }
  337. .delete-btn:active {
  338. transform: translateY(2rpx);
  339. box-shadow: 0 4rpx 15rpx rgba(255, 71, 87, 0.3);
  340. }
  341. .announcement {
  342. background: #fff;
  343. margin: 20rpx;
  344. border-radius: 20rpx;
  345. padding: 30rpx;
  346. box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
  347. }
  348. .announcement-title {
  349. display: flex;
  350. align-items: center;
  351. gap: 15rpx;
  352. font-size: 32rpx;
  353. font-weight: bold;
  354. color: #333;
  355. margin-bottom: 20rpx;
  356. }
  357. .announcement-content {
  358. font-size: 28rpx;
  359. line-height: 1.6;
  360. color: #666;
  361. }
  362. .member-section {
  363. background: #fff;
  364. margin: 20rpx;
  365. border-radius: 20rpx;
  366. padding: 30rpx;
  367. box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
  368. }
  369. .section-header {
  370. display: flex;
  371. align-items: center;
  372. gap: 10rpx;
  373. margin-bottom: 30rpx;
  374. }
  375. .section-title {
  376. font-size: 32rpx;
  377. font-weight: bold;
  378. color: #333;
  379. }
  380. .member-count-text {
  381. font-size: 24rpx;
  382. color: #999;
  383. }
  384. .member-list {
  385. display: flex;
  386. flex-direction: column;
  387. gap: 20rpx;
  388. }
  389. .member-item {
  390. display: flex;
  391. align-items: center;
  392. padding: 20rpx;
  393. border-radius: 15rpx;
  394. background: #f8f9fa;
  395. transition: all 0.3s ease;
  396. }
  397. .member-item:active {
  398. background: #e9ecef;
  399. transform: scale(0.98);
  400. }
  401. .member-avatar {
  402. width: 80rpx;
  403. height: 80rpx;
  404. border-radius: 50%;
  405. margin-right: 20rpx;
  406. }
  407. .member-info {
  408. flex: 1;
  409. }
  410. .member-name {
  411. font-size: 28rpx;
  412. color: #333;
  413. }
  414. .empty-member {
  415. padding: 60rpx 0;
  416. text-align: center;
  417. }
  418. @keyframes fadeIn {
  419. from {
  420. opacity: 0;
  421. transform: translateY(20rpx);
  422. }
  423. to {
  424. opacity: 1;
  425. transform: translateY(0);
  426. }
  427. }
  428. </style>