mahjong_group/pages/index/index.vue
2025-09-10 13:54:09 +08:00

368 lines
11 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="content" :style="getBackgroundImg()">
<!-- 使用 z-paging 组件实现分页功能 -->
<z-paging ref="pagePaging" v-model="dataList" @query="queryList" :refresher-enabled="true"
:loading-more-enabled="true" :auto="true" :empty-view-text="'暂无麻将局数据'" :empty-view-img="'/static/empty.png'"
:refresher-threshold="80" :loading-more-threshold="50" style="flex: 1; width: 95%; margin-top: 10rpx;">
<view style="z-index: 100;position: sticky;top :0;">
<view :style="{ height: statusBarHeight + 'px' }" style="background-color: #fff;" class="status-bar">
</view>
</view>
<view style="z-index: 100;margin-top:10rpx;height:532rpx;">
<view style="width: 100%;width:100%;display:flex;justify-content: center;"
v-if="homeData != null && homeData.advertList != null && homeData.advertList.length > 0">
<view class="" style="width:97%; height: 386rpx;border-radius: 25rpx;">
<swiper class="img-swiper" :indicator-dots="false" circular autoplay interval="3000">
<swiper-item v-for="(item, index) in homeData.advertList" :key="index">
<image :src="item.imageUrl" mode="scaleToFill" class="slide-img"
style="border-radius:25rpx;"> </image>
</swiper-item>
</swiper>
</view>
</view>
<view style="height: 10rpx;"></view>
</view>
<view class="grid-container">
<MahjongCard v-for="(item, index) in dataList" :key="index" :item="item" @click="openPop"
@join="handleJoin" />
</view>
</z-paging>
<uni-popup ref="cardInfo" 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=""
style="width: 50rpx; height: 50rpx; background-color: antiquewhite; border-radius: 50%; margin-left: 20rpx;"
mode=""></image>
<text style="font-size: 20rpx; margin-left: 15rpx;">苏家辉</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="(item, index) in 3" :key="index" style="align-items: center;">
<view class="" style="position: relative; width: 50rpx; height: 50rpx; display: flex;">
<image src="" @click="openUserPop()"
style="width: 50rpx; height: 50rpx; background-color: antiquewhite; border-radius: 50%; margin-left: 20rpx; position: absolute;"
mode=""></image>
<view 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;">树下的胖子</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>2025/08/27 1530</text>
</view>
<view class="row" style="justify-content: space-between; margin: 0 20rpx;">
<text>结束时间</text>
<text>2025/08/27 1730</text>
</view>
<text style="margin: 30rpx 20rpx 0;">合计2小时</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;">房间号304号-大包30元/小时</text>
<text style="margin: 10rpx 20rpx;">人数3人</text>
<text style="margin: 10rpx 20rpx;">玩法类型:扑克</text>
<text style="margin: 10rpx 20rpx;">具体规则:斗地主</text>
<text style="margin: 10rpx 20rpx 20rpx;">补充信息:无</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;">是否禁烟:禁烟</text>
<text style="margin: 10rpx 20rpx;">性别:不限</text>
<text style="margin: 10rpx 20rpx 20rpx;">信誉≧4.0</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;">鸽子费0元</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 class="center"
style="height: 80rpx; flex: 3; background-color: #1989FA; border-radius: 10rpx; margin-left: 20rpx;">
<text style="font-size: 24rpx; font-weight: 600; color: white;">参与组局</text>
</view>
</view>
</view>
</uni-popup>
<uni-popup ref="userInfo" type="center">
<view class="column" style="width: 500rpx; background-color: white; padding: 20rpx;">
<image @click="closeUserPop()" src="/static/ic_close.png"
style="width: 20rpx; height: 20rpx; margin-left: auto;" mode="">
</image>
<view class="row" style="align-items: center;">
<image src="" style="width: 80rpx; height: 80rpx; background-color: aquamarine; border-radius: 50%;"
mode="">
</image>
<view class="column" style="font-size: 24rpx; margin-left: 20rpx;">
<text>树下的胖子</text>
<text style="margin-top: 10rpx;">男30岁已参与20次信誉5.0</text>
</view>
</view>
<view class="row" style="align-items: center; margin-top: 20rpx;">
<text style="font-size: 24rpx;">Ta的评分 </text>
<text style="font-size: 40rpx; color: #ED3535; margin-left: 10rpx;">4.6</text>
</view>
<view class="row" style="align-items: center; margin-top: 20rpx;">
<text style="font-size: 24rpx;">牌品</text>
<uni-rate style="margin-left: 20rpx;" :readonly="true" v-model="rateValue" @change="onChange" />
</view>
<view class="row" style="align-items: center; margin-top: 20rpx;">
<text style="font-size: 24rpx;">牌技</text>
<uni-rate style="margin-left: 20rpx;" :readonly="true" v-model="rateValue" @change="onChange" />
</view>
<text style="font-size: 24rpx; margin-top: 20rpx;">鸽子数 0次</text>
</view>
</uni-popup>
</view>
</template>
<script setup>
import {
ref,
reactive,
onMounted
} from 'vue'
import zPaging from '@/uni_modules/z-paging/components/z-paging/z-paging.vue'
import MahjongCard from '@/components/index/MahjongCard.vue'
import {
homeData,
preloadHomeData
} from '@/common/server/index'
import {
configData,
getConfigData,
preloadConfigData
} from '@/common/server/config'
const statusBarHeight = ref(uni.getSystemInfoSync().statusBarHeight);
const getBackgroundImg = () => {
return {
background: `url(${configData.value.config.defaultImage}) 100% 100% `,
backgroundSize: '100%',
backgroundRepeat: "no-repeat",
backgroundRepeatX: "0px",
backgroundSize: "100%",
backgroundRepeatY: "0px",
backgroundPositionX: "0px",
backgroundPositionY: statusBarHeight.value + "px",
};
}
// 响应式数据
const title = ref('Hello')
const imgList = ref([1, 2, 3, 4, 5])
const dataList = ref([]) // 分页数据列表
const rateValue = ref(3.5)
const mockData = ref([]) // 模拟数据源
// 组件引用
const pagePaging = ref(null)
const cardInfo = ref(null)
const userInfo = ref(null)
// 初始化模拟数据
const initMockData = () => {
mockData.value = []
for (let i = 1; i <= 50; i++) {
// 随机生成不同人数的麻将局
const personCount = [2, 3, 4][Math.floor(Math.random() * 3)]
const joinedCount = Math.floor(Math.random() * (personCount + 1))
// 生成已加入的玩家
const joinPerson = []
for (let j = 0; j < joinedCount; j++) {
joinPerson.push({
id: j + 1,
name: `玩家${j + 1}`,
avatar: '',
phone: `138****${String(j + 1).padStart(4, '0')}`
})
}
mockData.value.push({
id: i,
title: `麻将局 ${i}`,
status: joinedCount >= personCount ? '已满员' : '组局中',
time: '2000 ~ 0430 共8小时30分钟',
room: `304包厢-大包,${personCount}人`,
description: '休闲局,随便来',
requirements: '麻将、斗地主、不可吸烟、性别不限、信誉≧4.0',
personCount: personCount,
joinPerson: joinPerson
})
}
}
// 分页查询方法
const queryList = (pageNo, pageSize) => {
console.log(`加载第${pageNo}页,每页${pageSize}条数据`)
// 模拟网络请求延迟
setTimeout(() => {
const startIndex = (pageNo - 1) * pageSize
const endIndex = startIndex + pageSize
const pageData = mockData.value.slice(startIndex, endIndex)
// 调用 z-paging 的完成方法
pagePaging.value.complete(pageData)
// 如果是第一页,显示加载完成提示
// if (pageNo === 1) {
// uni.showToast({
// title: '刷新成功',
// icon: 'success',
// duration: 1500
// })
// }
}, 100) // 模拟1秒网络延迟
}
// 手动刷新
const refreshData = () => {
pagePaging.value.reload()
}
// 清空数据
const clearData = () => {
pagePaging.value.clear()
}
// 弹窗相关方法
const openPop = () => {
cardInfo.value.open()
}
const clasePop = () => {
cardInfo.value.close()
}
const openUserPop = () => {
userInfo.value.open()
}
const closeUserPop = () => {
userInfo.value.close()
}
const onChange = (e) => {
console.log('rate发生改变:' + JSON.stringify(e))
}
// 处理加入麻将局事件
const handleJoin = (item) => {
console.log('加入麻将局:', item)
// 这里可以添加加入逻辑比如调用API
uni.showToast({
title: '加入成功',
icon: 'success',
duration: 1500
})
}
// 生命周期
onMounted(() => {
// 初始化模拟数据
initMockData()
})
onLoad(async () => {
if (!homeData.value) preloadHomeData();
if (!configData.value) preloadConfigData();
});
</script>
<style lang="scss">
.content {
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
}
.img-swiper {
width: 100%;
height: 386rpx;
}
.slide-img {
width: 100%;
height: 100%;
}
/* 网格容器 - 2列布局 */
.grid-container {
display: grid;
grid-template-columns: repeat(2, 1fr);
/* 2列每列宽度相等 */
gap: 20rpx;
/* 网格间距行列间距相同 */
padding: 0 15rpx;
}
/* 网格项内容 */
.item-content {
height: 630rpx;
// background-color: #E6E6E6;
color: white;
border-radius: 10rpx;
font-size: 32rpx;
}
</style>