mahjong_group/pages/me/me-page.vue
2025-09-14 00:07:26 +08:00

427 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>
<container-base ref="_containerBase">
<view class="content column">
<!-- 加载状态 -->
<view v-if="loading" class="loading-container">
<text>加载中...</text>
</view>
<view v-if="userInfo != null" class="row"
style="margin-top: 150rpx; align-items: center; margin-left: 40rpx;">
<image :src="userInfo.avatarImage" style="width: 80rpx; height: 80rpx; border-radius: 50%;" mode="">
</image>
<view class="column" style="margin-left: 50rpx; font-size: 24rpx;">
<view class="row" @click="toEditInfo()" style="align-items: center;">
<text>{{ userInfo.nickName }}</text>
</view>
<text style="margin-top: 10rpx;">UID{{ userInfo.id }}</text>
</view>
</view>
<view v-else class="row" style="margin-top: 150rpx; align-items: center; margin-left: 40rpx;">
<image src="@@:app/nouser.png" style="width: 80rpx; height: 80rpx; border-radius: 50%;" mode="">
</image>
<view class="column" style="margin-left: 50rpx; font-size: 24rpx;">
<view class="row" @click="toEditInfo()" style="align-items: center;">
<text>未登录</text>
</view>
<text style="margin-top: 10rpx; color: #999;" @click="toLogin()">点击登录</text>
</view>
</view>
<view style="height: 15rpx;"></view>
<view class="column" v-if="myUseReservation.length == 0"
style="width: 90%; border-radius: 30rpx; background: linear-gradient(to bottom, #D7F0DD, #FFFFFF); box-shadow: 0 0 3px 3px rgba(0, 0, 0, 0.1); margin: 40rpx auto 0;">
<!-- 无预约状态 -->
<view class="row" style="align-items: center; margin: 20rpx;">
<image src="@@:app/static/no_content.png" style="width: 150rpx; height: 150rpx;" mode=""></image>
<text style="margin-left: 40rpx;">当前没有预约</text>
</view>
</view>
<view v-else style="overflow: auto;max-height: 600rpx;">
<view class="column " style="width: 90%;margin: 0 auto;" v-for="(item, index) in myUseReservation"
:key="index">
<reservation-item :reservation="item" @evaluate="_containerBase.openEvaluatePop"
@click="_containerBase.openReservationPopup" />
</view>
</view>
<view v-if="userInfo != null" class="column"
style="width: 90%; border-radius: 30rpx; background-color: #FFFFFF; box-shadow: 0 0 3px 3px rgba(0, 0, 0, 0.1); margin: 40rpx auto 0;">
<view class="row" style="align-items: center; margin-top: 30rpx; margin-left: 20rpx;"
@click="toMyRecord()">
<text style="font-size: 24rpx;">我的信誉</text>
<text v-if="userInfo.credit_score > 0"
style="font-size: 34rpx; color: #ED3535; margin-left: 10rpx;">{{
userInfo.credit_score }}</text>
<text v-else style="font-size: 24rpx; color: #999; margin-left: 10rpx;">未评分</text>
</view>
<view class="row" style="align-items: center; margin-top: 20rpx; margin-left: 20rpx;">
<text style="font-size: 24rpx;">牌品</text>
<uni-rate style="margin-left: 20rpx;" :readonly="true" v-model="userInfo.play_level" />
</view>
<view class="row" style="align-items: center; margin-top: 20rpx; margin-left: 20rpx;">
<text style="font-size: 24rpx;">牌技</text>
<uni-rate style="margin-left: 20rpx;" :readonly="true" v-model="userInfo.skills_level" />
</view>
<text style="font-size: 24rpx; margin: 20rpx;">鸽子数 {{ userInfo.dove_count }} 次</text>
</view>
<view v-else class="column"
style="width: 90%; border-radius: 30rpx; background-color: #FFFFFF; box-shadow: 0 0 3px 3px rgba(0, 0, 0, 0.1); margin: 40rpx auto 0;">
<view class="row" style="align-items: center; margin-top: 30rpx; margin-left: 20rpx;">
<text style="font-size: 24rpx;">我的评分</text>
<text style="font-size: 24rpx; color: #999; margin-left: 10rpx;">未评分</text>
<text style="font-size: 24rpx; margin-left: 180rpx;">我的信誉</text>
<text style="font-size: 24rpx; color: #999; margin-left: 10rpx;">未评级</text>
</view>
<view class="row" style="align-items: center; margin-top: 20rpx; margin-left: 20rpx;">
<text style="font-size: 24rpx;">牌品</text>
<uni-rate style="margin-left: 20rpx;" :readonly="true" />
</view>
<view class="row" style="align-items: center; margin-top: 20rpx; margin-left: 20rpx;">
<text style="font-size: 24rpx;">牌技</text>
<uni-rate style="margin-left: 20rpx;" :readonly="true" />
</view>
<text style="font-size: 24rpx; margin: 20rpx;">鸽子数 0次</text>
</view>
<view class="column"
style="width: 90%; margin: 40rpx auto 0; border-radius: 30rpx; background-color: #FFFFFF; box-shadow: 0 0 3px 3px rgba(0, 0, 0, 0.1);">
<text style="font-size: 30rpx; margin-top: 26rpx; margin-left: 36rpx;">常用功能</text>
<view class="row" style=" justify-content: space-between; margin: 40rpx;">
<view class="column" @click="toAppointment()" style="align-items: center;">
<image src="@@:app/static/appoin_record.png" style="width: 50rpx; height: 50rpx;" mode="">
</image>
<text style="font-size: 24rpx; margin-top: 20rpx;">预约记录</text>
</view>
<view class="column" style="align-items: center;">
<image src="@@:app/static/problem.png" style="width: 50rpx; height: 50rpx;" mode=""></image>
<text style="font-size: 24rpx; margin-top: 20rpx;">常见问题</text>
</view>
<view class="column" style="align-items: center;">
<image src="@@:app/static/customer_s.png" style="width: 50rpx; height: 50rpx;" mode=""></image>
<text style="font-size: 24rpx; margin-top: 20rpx;">联系我们</text>
</view>
<view class="column" @click="toBlacklist()" style="align-items: center;">
<image src="@@:app/static/blacklist.png" style="width: 50rpx; height: 50rpx;" mode=""></image>
<text style="font-size: 24rpx; margin-top: 20rpx;">黑名单</text>
</view>
</view>
</view>
</view>
</container-base>
<uni-popup ref="infoPop" type="center">
<view class="column center"
style="width: 680rpx; background-color: white; border-radius: 10rpx; padding: 20rpx;">
<text style="">预约信息</text>
<view class="column"
style="width: 100%; height: 180rpx; background-color: #E3E2E2; margin-top: 20rpx; border-radius: 10rpx;">
<view class="row" style="margin-top: 20rpx; align-items: center; margin-left: 20rpx;">
<text style="font-size: 22rpx;">发起者</text>
<image :src="appointmentDetail.organizer.avatar"
style="width: 50rpx; height: 50rpx; background-color: antiquewhite; border-radius: 50%; margin-left: 20rpx;"
mode=""></image>
<text style="font-size: 20rpx; margin-left: 15rpx;">{{ appointmentDetail.organizer.name }}</text>
</view>
<view class="row" style="margin-top: 30rpx; align-items: center; margin-left: 20rpx;">
<text style="font-size: 22rpx;">参与者</text>
<view class="row" v-for="(participant, index) in appointmentDetail.participants" :key="index"
style="align-items: center;">
<view class="" style="position: relative; width: 50rpx; height: 50rpx; display: flex;">
<image :src="participant.avatar" @click="openUserPop()"
style="width: 50rpx; height: 50rpx; background-color: antiquewhite; border-radius: 50%; margin-left: 20rpx; position: absolute;"
mode=""></image>
<view v-if="participant.isBlacklisted" class="center"
style="width: 50rpx; height: 20rpx; background-color: #FFB7B7; position: absolute; left: 40%; top: -10rpx;">
<text style="font-size: 10rpx;">黑名单</text>
</view>
</view>
<text
style="font-size: 20rpx; margin-left: 30rpx; width: 100rpx; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">{{
participant.name }}</text>
</view>
</view>
</view>
<view class="column"
style="width: 100%; height: 180rpx; background-color: #E3E2E2; margin-top: 20rpx; border-radius: 10rpx;font-size: 22rpx;">
<view class="row" style="justify-content: space-between; margin: 20rpx;">
<text>开始时间</text>
<text>{{ appointmentDetail.timeInfo.startTime }}</text>
</view>
<view class="row" style="justify-content: space-between; margin: 0 20rpx;">
<text>结束时间</text>
<text>{{ appointmentDetail.timeInfo.endTime }}</text>
</view>
<text style="margin: 30rpx 20rpx 0;">合计:{{ appointmentDetail.timeInfo.duration }}</text>
</view>
<view class="column"
style="width: 100%; background-color: #E3E2E2; margin-top: 20rpx; border-radius: 10rpx; font-size: 22rpx;">
<text style="margin: 20rpx 20rpx 10rpx; font-size: 24rpx;">房间号:{{ appointmentDetail.roomInfo.roomNumber
}}{{ appointmentDetail.roomInfo.price }}</text>
<text style="margin: 10rpx 20rpx;">人数:{{ appointmentDetail.roomInfo.playerCount }}人</text>
<text style="margin: 10rpx 20rpx;">玩法类型:{{ appointmentDetail.roomInfo.gameType }}</text>
<text style="margin: 10rpx 20rpx;">具体规则:{{ appointmentDetail.roomInfo.rules }}</text>
<text style="margin: 10rpx 20rpx 20rpx;">补充信息:{{ appointmentDetail.roomInfo.additionalInfo }}</text>
</view>
<view class="column"
style="width: 100%; background-color: #E3E2E2; margin-top: 20rpx; border-radius: 10rpx; font-size: 22rpx;">
<text style="margin: 20rpx 20rpx 10rpx; font-size: 24rpx;">是否禁烟:{{
appointmentDetail.requirements.smoking
}}</text>
<text style="margin: 10rpx 20rpx;">性别:{{ appointmentDetail.requirements.gender }}</text>
<text style="margin: 10rpx 20rpx 20rpx;">信誉:{{ appointmentDetail.requirements.reputation }}</text>
</view>
<view class="column"
style="width: 100%; background-color: #E3E2E2; margin-top: 20rpx; border-radius: 10rpx; font-size: 22rpx;">
<text style="margin: 20rpx 20rpx 10rpx; font-size: 24rpx;">鸽子费:{{ appointmentDetail.pigeonFee }}</text>
<text
style="margin: 10rpx 20rpx 20rpx; color: #9F9F9F;">组局成功后若有牌友未赴约,其鸽子费平均分给其他牌友。组局成功或失败后鸽子费将全额返还。</text>
</view>
<view class="row" style="width: 100%; margin-top: 30rpx;">
<view class="center" @click="clasePop()"
style="height: 80rpx; flex: 1; background-color: #9F9F9F; border-radius: 10rpx;">
<text style="font-size: 24rpx; font-weight: 600; color: white;">关闭</text>
</view>
</view>
</view>
</uni-popup>
</template>
<script setup>
import {
userInfo,
loadUserInfo,
isLogin
} from '@/common/server/user'
import { sqInterface } from '@/common/server/interface/sq'
import ReservationEvaluate from '@/components/com/page/reservation-evaluate.vue'
import ContainerBase from '@/components/com/page/container-base.vue'
import {
ref,
reactive,
onMounted
} from 'vue'
import ReservationItem from '@/components/com/page/reservation-item.vue'
// 响应式数据
const rateValue = ref(4.5)
const infoPop = ref(null)
const loading = ref(false)
const _containerBase = ref(null)
// 当前预约信息
const currentAppointment = ref(null)
// 预约详情数据
const appointmentDetail = reactive({
organizer: {
name: '苏家辉',
avatar: '',
isBlacklisted: false
},
participants: [{
name: '树下的胖子',
avatar: '',
isBlacklisted: true
},
{
name: '张三',
avatar: '',
isBlacklisted: false
},
{
name: '李四',
avatar: '',
isBlacklisted: false
}
],
timeInfo: {
startTime: '2025/08/27 1530',
endTime: '2025/08/27 1730',
duration: '2小时'
},
roomInfo: {
roomNumber: '304号-大包',
price: '30元/小时',
playerCount: 3,
gameType: '扑克',
rules: '斗地主',
additionalInfo: '无'
},
requirements: {
smoking: '禁烟',
gender: '不限',
reputation: '≧4.0'
},
pigeonFee: '0元'
})
// 方法
const openPop = () => {
infoPop.value.open();
}
const clasePop = () => {
infoPop.value.close();
}
const openReservationPopup = (item) => {
console.log("openReservationPopup", item)
// _containerBase.value.openReservationPopup(item)
}
const toAppointment = () => {
if (userInfo.value == null) {
uni.navigateTo({
url: '/pages/me/login'
});
return;
}
uni.navigateTo({
url: '/pages/me/appointment-record-page'
});
}
const toMyRecord = async () => {
var _isLogin = await isLogin();
if (_isLogin) {
uni.navigateTo({
url: '/pages/me/my-record'
});
} else {
uni.navigateTo({
url: '/pages/me/login'
});
}
}
const toEditInfo = () => {
// 未登录状态,跳转到登录页面
if (userInfo.value == null) {
uni.navigateTo({
url: '/pages/me/login'
});
return;
}
uni.navigateTo({
url: '/pages/me/edit-info'
});
}
const toBlacklist = () => {
if (userInfo.value == null) {
uni.navigateTo({
url: '/pages/me/login'
});
return;
}
uni.navigateTo({
url: '/pages/me/blacklist-page'
});
}
const openUserPop = () => {
// 打开用户详情弹窗的逻辑
console.log('打开用户详情弹窗');
}
const toLogin = () => {
uni.navigateTo({
url: '/pages/me/login'
});
}
const myUseReservation = ref([]);
// 加载当前预约信息 - 未登录状态
const loadCurrentAppointment = async () => {
var _isLogin = await isLogin();
if (!_isLogin) {
return;
}
try {
var res = await sqInterface.getMyUseReservation();
console.log("getMyUseReservation", res);
if (res != null) {
myUseReservation.value = myUseReservation.value.splice(0, myUseReservation.value.length);
myUseReservation.value.push(...res);
}
} catch (error) {
console.error('加载预约信息失败:', error)
}
}
// 组件挂载时加载数据
onMounted(() => {
loadCurrentAppointment()
})
// 页面显示时重新加载数据(用于登录后刷新)
onShow(() => {
// 检查是否有登录状态
// getUserInfoData();
})
onLoad(async () => {
await loadUserInfo();
});
</script>
<style lang="scss">
.content {
width: 100%;
height: 100vh;
background-color: #F7F7F7;
}
.loading-container {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: rgba(0, 0, 0, 0.7);
color: white;
padding: 20rpx 40rpx;
border-radius: 10rpx;
z-index: 9999;
}
</style>