Files
yusheng-h5/pages/union/list.vue
2026-01-09 19:01:04 +08:00

602 lines
14 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="view-page" :style="{backgroundImage: `url('${ThemeData ? ThemeData.app_bg : baseBgUrl }')`}">
<navBar :style="{marginTop: `${statusBarHeight}${uni.getSystemInfoSync().platform === 'ios' ? 'px': 'dp'}`}"
:navTitle="'公会中心'">
<template #rightView>
<view class="icon-right flex-line" @click="exit" v-if="isHasUnicon && !isLeader">
<img :src="logout" alt="" />
</view>
</template>
</navBar>
<view class="content">
<view class="flex-input">
<uni-easyinput prefixIcon="search" clearSize="18" v-model="searchValue" placeholder="请输入公会ID/昵称">
</uni-easyinput>
<view class="search-button" @click="search">
搜索
</view>
</view>
<view class="hotspot-view">
<view class="hotspot-box" v-for="data in listData" :key="data.id">
<view class="flex-line">
<view class="head-portrait">
<img :src="data.cover || logo" alt="" />
</view>
<view class="info-box ml-20">
<view class="flex-line">
<span class="truncate">{{data.guild_name}}</span><span
class="id-title">ID:{{data.guild_special_id}}</span>
<img @click.stop="copyData(data.guild_special_id)" class="icon-box"
src="@/static/image/union/copy.png" alt="" />
</view>
<view class="subhead-title truncate">
{{data.intro}}
</view>
<view class="chairman">
<view class="chairman-portrait">
<img :src="data.user_avatar" alt="暂无头像" />
</view>
<view class="chairman-name">
{{data.user_name}}
</view>
</view>
</view>
</view>
<view class="right-button">
<view class="apply-button" @click="applyUnion(data)">
申请
</view>
<view class="online-view">
<view v-show="data.guild_user_list.length">
<view class="avatars-container">
<view class="avatar" v-for="ele in data.guild_user_list.slice(0,3)" :key="ele.id">
<img :src="ele.avatar" alt="" />
</view>
</view>
</view>
<view class="online-people">
{{data.num}}
</view>
</view>
</view>
</view>
</view>
</view>
<!-- 弹窗 -->
<uni-popup ref="message" type="message">
<uni-popup-message :type="msgType" :message="messageText" :duration="2000"></uni-popup-message>
</uni-popup>
<uni-popup ref="popup" type="center">
<view class="popup_view">
<view class="color-3 font-32 popup_title">
温馨提示
</view>
<view class="color-3 font-24 messageContent">
{{ messageContent }}
</view>
<view class="popup_button flex-line">
<view class="close_button flex-line" @click="closePopup">
取消
</view>
<view class="confirm-button flex-line" @click="confirmPopup">
确认
</view>
</view>
</view>
</uni-popup>
</view>
</template>
<script>
import navBar from '@/component/nav.vue';
import http from '@/until/http.js';
import logo from '@/static/image/logo.png';
import config from '@/until/config.js';
import logout from '@/static/image/union/logout.png'
export default {
components: {
navBar
},
data() {
return {
searchValue: '',
noUnionImage: config.not_unionUrl,
baseBgUrl: config.new_unionUrl,
unionBgUrl: config.unicon_url,
logo,
logout,
loading: false,
noMore: false,
isMerber: null,
listData: [],
UnionByUser: null,
statusBarHeight: 0,
ThemeData: null,
// 是否實名
isAuth: false,
// 是否为公会长,
isLeader: false,
// 是否有公会
isHasUnicon: false,
messageContent: '',
popupStstus: 0,
messageText: "",
msgType: "success",
detailData: null,
// 上次刷新用户信息的时间戳
lastRefreshTime: 0
}
},
onShow(options) {
if (uni.getStorageSync('token')) {
// this.getUserInfo()
if (uni.getStorageSync('BarHeight')) {
this.statusBarHeight = uni.getStorageSync('BarHeight')
}
if (uni.getStorageSync('Theme_Data')) {
this.ThemeData = JSON.parse(uni.getStorageSync('Theme_Data'))
}
// 每次页面显示时都刷新用户信息处理从APP实名认证返回的情况
this.refreshUserInfo()
if (options && options.guild_id) {
//如果有传入公会id 把工会ID放到搜索框去
this.searchValue = options.guild_id
this.getUnionList(options.guild_id)
}
} else {
uni.navigateBack()
}
},
methods: {
// 刷新用户信息(获取最新的实名状态)
async refreshUserInfo(force = false) {
// 防抖:如果距离上次刷新不到 3 秒,且不是强制刷新,则跳过
const now = Date.now()
if (!force && now - this.lastRefreshTime < 3000) {
console.log('跳过频繁刷新')
return
}
try {
const response = await http.get('/api/User/get_user_info', {
token: uni.getStorageSync('token') || ''
})
if (response.code) {
this.isAuth = response.data.auth || false
// 可以将实名状态缓存起来,避免频繁请求
uni.setStorageSync('user_auth_status', this.isAuth)
this.lastRefreshTime = now
}
} catch (error) {
console.error('获取用户信息失败:', error)
// 如果请求失败,尝试从缓存读取
this.isAuth = uni.getStorageSync('user_auth_status') || false
}
},
async getUnionList(name) {
this.loading = true
http.get('/api/Guild/guild_list', {
page: 1,
limit: 1000,
search_id: name,
token: uni.getStorageSync('token') || ''
}).then(response => {
const {
data,
code
} = response
if (code) {
this.loading = false
this.listData = data.list || []
}
}).catch(error => {
this.loading = false
});
},
search() {
if (this.searchValue) {
// 搜索
this.getUnionList(this.searchValue)
}
},
// 申請加入工會
async applyUnion(rowData) {
// 显示加载状态
uni.showLoading({
title: '检查实名状态...',
mask: true
})
try {
// 强制获取最新的用户信息和实名状态
const response = await http.get('/api/User/get_user_info', {
token: uni.getStorageSync('token') || ''
})
uni.hideLoading()
if (response.code) {
const isRealNameAuth = response.data.auth || false
// 更新实名状态和刷新时间
this.isAuth = isRealNameAuth
this.lastRefreshTime = Date.now()
uni.setStorageSync('user_auth_status', isRealNameAuth)
if (isRealNameAuth) {
// 已实名,弹出加入公会确认框
this.detailData = rowData
this.popupStstus = 1
this.messageContent = "是否选择加入当前公会"
this.$refs.popup.open('center')
} else {
// 未实名,弹出实名认证提示框
this.detailData = rowData // 保存公会数据,实名后可能需要
this.popupStstus = 3
this.messageContent = "当前尚未实名认证,是否跳转到实名认证页面?"
this.$refs.popup.open('center')
}
} else {
uni.showToast({
title: response.msg || '获取用户信息失败',
icon: 'none',
duration: 2000
})
}
} catch (error) {
uni.hideLoading()
console.error('获取用户信息失败:', error)
this.messageText = '请求失败,请重试!'
this.msgType = 'error'
this.$refs.message.open()
}
},
closePopup() {
this.popupStstus = null
this.detailData = null
this.messageContent = ""
this.$refs.popup.close()
},
confirmPopup() {
if (this.popupStstus !== null) {
if (this.popupStstus === 1) {
this.joinUnionize()
} else if (this.popupStstus === 3) {
// 实名认证页面
this.authConfirm()
}
}
},
authConfirm() {
// 去实名认证页面
const platform = uni.getSystemInfoSync().platform;
if (platform === 'ios') {
window.webkit.messageHandlers.nativeHandler.postMessage({
'action': 'enterAuthent'
});
} else if (platform === 'android') {
window.Android.enterAuthent();
}
this.closePopup()
// 提示用户完成实名后返回
uni.showToast({
title: '请完成实名认证后返回',
icon: 'none',
duration: 3000
})
},
// 申请加入公会
async joinUnionize() {
http.post('/api/Guild/join_guild', {
guild_id: this.detailData.id,
token: uni.getStorageSync('token') || ''
}).then(response => {
const {
data,
code,
msg
} = response
if (code) {
this.messageText = `加入成功`
this.$refs.message.open()
this.msgType = 'success'
uni.$emit('refreshList');
uni.navigateBack()
} else {
this.messageText = msg
this.msgType = 'error'
this.$refs.message.open()
}
this.closePopup()
})
}
}
}
</script>
<style lang="scss" scoped>
.view-page {
// padding: 32rpx;
// min-height: 100vh;
min-height: 100vh;
font-family: Source Han Sans CN, Source Han Sans CN;
// background-image: url('@/static/image/help/bg.png');
background-repeat: no-repeat;
background-size: 100% 100%;
.popup_view {
width: 550rpx;
// height: 40vh;
background-color: #fff;
border-radius: 32rpx;
padding: 32rpx;
.popup_title {
text-align: center;
}
.messageContent {
margin: 24rpx 0;
}
.popup_button {
margin-top: 24rpx;
width: 100%;
justify-content: space-around;
.close_button,
.confirm-button {
width: 200rpx;
height: 84rpx;
background: #F3F3F3;
border-radius: 106rpx;
color: #999999;
justify-content: center;
}
.confirm-button {
background: var(--primary-color);
color: var(--font-button-color);
}
}
}
.content {
padding: 0 32rpx;
}
// /* 搜索框 */
.flex-input {
width: 100%;
display: inline-flex;
align-items: center;
flex-wrap: nowrap;
flex-direction: row;
.search-button {
padding: 0 0 0 20rpx;
}
}
/* 热门公会 */
.hotspot-view {
margin-top: 28rpx;
.hotspot-box {
width: calc(100% - 48rpx);
padding: 24rpx;
position: relative;
// min-height: calc(268rpx - 48rpx);
background: #FFFFFF;
border-radius: 20rpx;
margin-bottom: 24rpx;
/* */
display: inline-flex;
align-items: center;
flex-wrap: nowrap;
justify-content: space-between;
flex-direction: row;
/* 头像 */
.head-portrait {
width: 120rpx;
height: 120rpx;
border-radius: 50%;
img {
width: 100%;
height: 100%;
border-radius: 50%;
}
}
/* 中间信息 */
.info-box {
padding: 0 24rpx;
// max-width: 40%;
width: 55%;
.icon-box {
width: 20rpx;
height: 20rpx;
margin-left: 5rpx;
}
/* 会长样式 */
.chairman {
min-width: 106rpx;
height: 36rpx;
padding: 0 12rpx;
color: #fff;
font-size: 24rpx;
text-align: right;
background: var(--subss-color);
border-radius: 116rpx 116rpx 116rpx 116rpx;
border: 2rpx solid var(--subss-color);
position: relative;
left: 10rpx;
margin: 32rpx 0;
display: inline-flex;
.truncate-three {
text-align: left;
}
.chairman-portrait {
width: 50rpx;
height: 50rpx;
border-radius: 50%;
border: 2rpx solid #FFFFFF;
position: absolute;
top: -10rpx;
left: -20rpx;
img {
width: 100%;
height: 100%;
border-radius: 50%;
}
}
.chairman-name {
margin-left: 0.9rem;
}
}
.id-title {
font-size: 24rpx;
color: #666666;
margin-left: 24rpx;
}
.subhead-title {
display: block;
font-weight: 400;
font-size: 24rpx;
color: #666666;
margin: 8rpx 0;
}
.like-box {
display: inline-flex;
align-items: center;
flex-wrap: nowrap;
flex-direction: row;
padding: 6rpx 24rpx;
background: #2AFEC0;
border-radius: 35rpx;
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 400;
font-size: 28rpx;
color: #333333;
margin: 8rpx 0;
}
}
/* 右边按钮 */
.right-button {
text-align: right;
position: absolute;
right: 30rpx;
bottom: 50rpx;
.apply-button {
display: inline-block;
background: var(--primary-color);
font-size: var(--font-button-size);
color: var(--font-button-color);
border-radius: 68rpx;
text-align: center;
padding: 4rpx 30rpx;
}
.online-view {
.avatar {
width: 44rpx;
height: 44rpx;
border-radius: 50%;
position: absolute;
border: 2px solid white;
/* 白色边框 */
background-size: cover;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
transition: all 0.4s ease;
img {
width: 100%;
height: 100%;
border-radius: 50%;
}
}
/* 头像位置 */
.avatar:nth-child(1) {
left: calc(50% - 60rpx);
z-index: 3;
}
.avatar:nth-child(2) {
left: calc(50% - 35rpx);
z-index: 2;
}
.avatar:nth-child(3) {
left: calc(50% - 10rpx);
z-index: 1;
}
/* 悬停效果 */
.avatar:hover {
transform: translateY(-10px);
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.25);
z-index: 10;
}
// display: inline-block;
margin-top: 24rpx;
padding: 12rpx 8rpx;
text-align: right;
width: 160rpx;
height: 44rpx;
line-height: 44rpx;
// background: #333333;
border-radius: 92rpx 92rpx 92rpx 92rpx;
position: relative;
.avatars-container {
position: absolute;
top: 10rpx;
left: 40%;
}
.online-people {
color: rgba(0, 0, 0, 0.5);
font-size: 24rpx;
text-align: left;
display: inline-block;
/* width: 6ch; */
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
word-break: keep-all;
}
}
}
}
}
}
</style>