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

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