This commit is contained in:
zpc 2025-09-13 09:49:10 +08:00
parent 50cb078e68
commit ea51b8b508
14 changed files with 1437 additions and 809 deletions

View File

@ -77,6 +77,25 @@ export const addEvaluateServices = async (evaluate) => {
return false;
}
/**
* 获取我的声誉记录
* @param {number} pageIndex 起始页
* @param {number} pageSize 页大小
* @returns {Promise<any>}
*/
export const getReputationByUser = async (pageIndex = 1, pageSize = 20) => {
const res = await request.get("sq/GetReputationByUser", {
pageIndex: pageIndex,
pageSize: pageSize
});
if (res.code == 0) {
//data:[{title:"标题",reputation_value:"变化值","created_at":"变化时间"}]
return res.data;
}
return null;
}
export const sqInterface = {
@ -84,5 +103,6 @@ export const sqInterface = {
getMyReservation,
getMyUseReservation,
getEvaluateServices,
addEvaluateServices
addEvaluateServices,
getReputationByUser
}

View File

@ -222,7 +222,8 @@ export const addBlack = async (userId) => {
}
return false;
}

View File

@ -1,3 +1,5 @@
import dayjs from 'dayjs';
/**
* 将时间字符串格式化为时间对象
* @param {string} timeStr - 时间字符串格式2025/09/03 04:05:40
@ -72,4 +74,33 @@ function calculateTimeRange(time1, time2) {
return result;
}
export { parseTimeString, formatTime, calculateTimeRange }
/**
* 判断给定日期是今天明天还是后天
* @param {string|number|Date|dayjs} input - 目标日期可以是时间戳日期字符串Date 对象等
* @returns {string} - 返回 '今天' | '明天' | '后天' | '其他'
*/
function getDayDescription(input) {
if (input == null || input == "" || input == 0) {
return "请选择时间";
}
const target = dayjs(input); // 解析输入日期
const today = dayjs().startOf('day'); // 今天的 00:00:00
const tomorrow = today.add(1, 'day'); // 明天的 00:00:00
const dayAfterTomorrow = today.add(2, 'day'); // 后天的 00:00:00
let tips = "";
if (target.isSame(today, 'day')) {
tips = '(今天)';
} else if (target.isSame(tomorrow, 'day')) {
tips = '(明天)';
} else if (target.isSame(dayAfterTomorrow, 'day')) {
tips = '(后天)';
} else {
tips = '';
}
return target.format('MM-DD ' + tips + ' HH:mm')
}
export { parseTimeString, formatTime, calculateTimeRange, getDayDescription }

View File

@ -1,3 +1,4 @@
/**
* 延迟执行
* @param {Number} ms

3
components.d.ts vendored
View File

@ -9,9 +9,12 @@ export {}
declare module 'vue' {
export interface GlobalComponents {
Container: typeof import('./components/com/page/container.vue')['default']
ContainerBase: typeof import('./components/com/page/container-base.vue')['default']
MahjongCard: typeof import('./components/index/MahjongCard.vue')['default']
NoData: typeof import('./components/com/page/no-data.vue')['default']
NoEmpty: typeof import('./components/com/index/NoEmpty.vue')['default']
ReservationEvaluate: typeof import('./components/com/page/reservation-evaluate.vue')['default']
ReservationItem: typeof import('./components/com/page/reservation-item.vue')['default']
ReservationPopup: typeof import('./components/com/index/ReservationPopup.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']

View File

@ -0,0 +1,116 @@
<template>
<view>
<slot></slot>
<reservation-evaluate ref="_baseEvaluatePop" />
<!-- 预约信息弹窗组件 -->
<ReservationPopup ref="_reservationPopup" />
<up-datetime-picker hasInput :show="_upDatesTimePicker.show" :filter="_upDatesTimePicker.filter"
:formatter="_upDatesTimePicker.formatter" v-model="_upDatesTimePicker.value" mode="datetime"
:minDate="_upDatesTimePicker.minDate" @cancel="_upDatesTimePicker.onCancel"
@confirm="_upDatesTimePicker.onConfirm"></up-datetime-picker>
</view>
</template>
<script setup>
import { ref, onMounted, provide } from 'vue'
import ReservationEvaluate from '@/components/com/page/reservation-evaluate.vue'
import ReservationPopup from '@/components/com/index/ReservationPopup.vue'
import dayjs from 'dayjs';
const _baseEvaluatePop = ref(null)
const _reservationPopup = ref(null)
const openEvaluatePop = async (reservation) => {
_baseEvaluatePop.value && _baseEvaluatePop.value.show(reservation)
}
const openReservationPopup = async (reservation) => {
console.log("openReservationPopup", reservation)
_reservationPopup.value && _reservationPopup.value.show(reservation)
}
const _upDatesTimePicker = ref({
refId: null,
show: false,
value: Date.now(),
minDate: Date.now(),
filter: (mode, options) => {
// console.log("filter", mode, options)
if (mode == "minute") {
return options.filter((option) => option % 5 === 0);
}
return options;
},
formatter(type, value) {
if (type === 'year') {
return `${value}`
}
if (type === 'month') {
return `${value}`
}
if (type === 'day') {
return `${value}`
}
if (type === 'hour') {
return `${value}`
}
if (type === 'minute') {
return `${value}`
}
return value
},
onCancel: () => {
if (_upDatesTimePicker.value.onError != null) {
_upDatesTimePicker.value.onError();
}
_upDatesTimePicker.value.show = false;
},
onConfirm: (options) => {
if (_upDatesTimePicker.value.onCallback != null) {
// const date = dayjs(options.value);
_upDatesTimePicker.value.onCallback(options.value);
}
_upDatesTimePicker.value.show = false;
},
onCallback: null,
onError: null
});
const openUpDatesTimePicker = (value, minDate) => {
return new Promise((resolve, reject) => {
// 1.
const now = dayjs();
// 2. 1
const oneHourLater = now.add(1, 'hour');
const timestamp = oneHourLater.valueOf();
_upDatesTimePicker.value.onCallback = resolve;
_upDatesTimePicker.value.onError = reject;
if (value != null && value != "" && value != 0) {
_upDatesTimePicker.value.value = value;
} else {
_upDatesTimePicker.value.value = timestamp;
}
if (minDate != null && minDate != "" && minDate != 0) {
_upDatesTimePicker.value.minDate = minDate;
} else {
_upDatesTimePicker.value.minDate = timestamp;
}
_upDatesTimePicker.value.show = true;
})
}
defineExpose({ openEvaluatePop, openReservationPopup, openUpDatesTimePicker })
// onMounted(() => {
// console.log("container-basecontainer-basecontainer-basecontainer-base onMounted")
// // _containerBase
// provide('openEvaluatePop', (reservation) => {
// _baseEvaluatePop.value.show(reservation)
// })
// provide('openReservationPopup', (reservation) => {
// _reservationPopup.value.show(reservation)
// })
// });
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,190 @@
<template>
<uni-popup ref="popupRef" type="center">
<view class="popup-container">
<view class="column popup-inner">
<text class="popup-title">牌友评价</text>
<text class="popup-desc">请对每位牌友进行评价</text>
<view class="row panel-box" v-if="currentEvaluate" @click="index = 0, showPicker = true">
{{ currentEvaluate.userName }}
<image src="/static/down.png" class="down-icon" mode=""></image>
</view>
<view class="column panel-box" v-if="currentEvaluate">
<view class="row row-center mt-20 ml-20">
<text class="font-24">牌品</text>
<uni-rate :readonly="currentEvaluate.is_evaluate" class="ml-20"
v-model="currentEvaluate.play_level" />
<text class="font-24">当前评分:{{ currentEvaluate.user_play_level }}</text>
</view>
<view class="row row-center mt-20 ml-20">
<text class="font-24">牌技</text>
<uni-rate :readonly="currentEvaluate.is_evaluate" v-model="currentEvaluate.skills_level"
class="ml-20" />
<text class="font-24">当前评分:{{ currentEvaluate.user_skills_level }}</text>
</view>
</view>
<view class="row action-row" v-if="currentEvaluate">
<view class="center action-btn" v-if="!currentEvaluate.userBlackStatus"
@click="async () => { var f = await addBlack(currentEvaluate.user_id); f ? currentEvaluate.userBlackStatus = true : currentEvaluate.userBlackStatus = false; }">
拉入黑名单
</view>
<view class="center action-btn" v-if="currentEvaluate.userBlackStatus"
@click="async () => { var f = await cancelBlack(currentEvaluate.user_id); f ? currentEvaluate.userBlackStatus = false : currentEvaluate.userBlackStatus = true; }">
移出黑名单
</view>
<view class="center action-btn ml-20" v-if="!currentEvaluate.is_evaluate"
@click="submitEvaluate(currentEvaluate)">
提交
</view>
<view class="center action-btn ml-20" v-if="currentEvaluate.is_evaluate">
已提交
</view>
</view>
<text class="info-tip">加入黑名单后双方将看不到对方发起的组局</text>
</view>
<view style="height: 5rpx;"></view>
</view>
<up-picker v-if="evaluateList.length > 0" @cancel="closePicker" @confirm="confirmPicker" :show="showPicker"
:columns="[evaluateList]" keyName="userName" valueName="user_id" :defaultIndex="[index]"></up-picker>
</uni-popup>
</template>
<script setup>
import { ref, computed } from 'vue'
import { sqInterface } from '@/common/server/interface/sq.js'
import { cancelBlack, addBlack } from '@/common/server/user.js'
const popupRef = ref(null)
const index = ref(0)
const showPicker = ref(false)
const evaluateList = ref([])
const currentReservation = ref(null)
const currentEvaluate = computed(() => {
if (!evaluateList.value || evaluateList.value.length === 0) return null
return evaluateList.value[index.value]
})
const show = async (reservation) => {
currentReservation.value = reservation
uni.showLoading({ title: '加载中...' })
const data = await sqInterface.getEvaluateServices(reservation.id)
uni.hideLoading()
if (!data || data.length === 0) {
uni.showToast({ title: '暂无评价', icon: 'none' })
return
}
evaluateList.value = []
evaluateList.value.push(...data)
popupRef.value.open()
}
const close = () => {
popupRef.value.close()
}
const closePicker = () => { showPicker.value = false }
const confirmPicker = () => { showPicker.value = false }
const submitEvaluate = async (evaluate) => {
uni.showLoading({ title: '评价提交中...' })
const payload = {
reservation_id: currentReservation.value.id,
to_user_id: evaluate.user_id,
play_level: evaluate.play_level,
skills_level: evaluate.skills_level
}
const ok = await sqInterface.addEvaluateServices(payload)
uni.hideLoading()
if (ok) {
uni.showToast({ title: '评价提交成功', icon: 'success' })
evaluate.is_evaluate = true
} else {
uni.showToast({ title: '评价提交失败', icon: 'none' })
}
}
defineExpose({ show, close })
</script>
<style lang="scss" scoped>
.popup-container {
width: 650rpx;
background-color: #FFFFFF;
border-radius: 20rpx;
}
.popup-inner {
width: 90%;
margin: 0 auto 0;
}
.popup-title {
font-size: 26rpx;
margin-top: 30rpx;
text-align: center;
}
.popup-desc {
font-size: 24rpx;
margin-top: 20rpx;
}
.panel-box {
width: 100%;
background-color: #F2F3F5;
border-radius: 10rpx;
padding-top: 20rpx;
padding-bottom: 20rpx;
margin-top: 20rpx;
}
.down-icon {
width: 40rpx;
height: 40rpx;
margin-left: auto;
margin-right: 20rpx;
}
.font-24 {
font-size: 24rpx;
}
.action-row {
margin-top: 50rpx;
height: 80rpx;
color: #FFFFFF;
font-size: 28rpx;
}
.action-btn {
flex: 1;
background-color: #1989FA;
border-radius: 10rpx;
}
.info-tip {
font-size: 24rpx;
text-align: center;
margin-top: 20rpx;
margin-bottom: 20rpx;
}
.row-center {
align-items: center;
}
.mt-20 {
margin-top: 20rpx;
}
.mt-10 {
margin-top: 10rpx;
}
.ml-20 {
margin-left: 20rpx;
}
</style>

View File

@ -0,0 +1,222 @@
<template>
<view class="reservation-item reservation-box">
<view class="column reservation-inner" @click="openReservationPopup()">
<view class="row title title-row mt-10">
<view class="title">{{ reservation.title || '麻将预约' }}</view>
<view class="status-text" :style="getStatusStyle(reservation.status)">
{{ getStatusText(reservation.status) }}
</view>
</view>
<view class="row row-text row-center mt-10">
<text class="ml-20">{{ formatTimeRange(reservation.start_time, reservation.end_time) }}</text>
</view>
<view class="row row-center mt-10">
<text class="row-text ml-20">{{ reservation.room_name || '' }}</text>
</view>
<view class="row row-center mt-10">
<text class="row-text ml-20">已约牌友</text>
<image v-for="(participant, pIndex) in reservation.participants" :key="pIndex"
:src="participant.avatarImage || '/static/default-avatar.png'" class="avatar" mode="aspectFill" />
<view class="center evaluate-btn" v-if="reservation.status == 2" @click.stop="onEvaluate()">
<text class="evaluate-btn-text">牌友评价</text>
</view>
</view>
<view class="mt-20" style="height: 10rpx;"></view>
</view>
<!-- 评价弹窗由父页面控制 -->
</view>
</template>
<script setup>
//
import { inject } from 'vue'
const props = defineProps({
reservation: {
type: Object,
required: true
}
})
const emit = defineEmits(['evaluate', 'click'])
const onEvaluate = () => {
emit('evaluate', props.reservation)
// openEvaluatePop?.(props.reservation)
}
const formatTimeRange = (startTime, endTime) => {
if (!startTime || !endTime) return '时间未设置'
const start = new Date(startTime)
const end = new Date(endTime)
const startStr = `${start.getFullYear()}-${String(start.getMonth() + 1).padStart(2, '0')}-${String(start.getDate()).padStart(2, '0')} ${String(start.getHours()).padStart(2, '0')}:${String(start.getMinutes()).padStart(2, '0')}`
const endStr = `${end.getFullYear()}-${String(end.getMonth() + 1).padStart(2, '0')}-${String(end.getDate()).padStart(2, '0')} ${String(end.getHours()).padStart(2, '0')}:${String(end.getMinutes()).padStart(2, '0')}`
return `${startStr} ~ ${endStr}`
}
const getStatusText = (status) => {
const map = { 0: '待开始', 1: '进行中', 2: '已结束', 3: "已取消" }
return map[status] || '未知状态'
}
const getStatusStyle = (status) => {
const map = { 0: 'color: #1989FA', 1: 'color: #999', 2: 'color: #999', 3: 'color: #999' }
return map[status] || 'color: #999'
}
const openReservationPopup = () => {
emit('click', props.reservation)
// openReservationPopupf?.(props.reservation)
}
</script>
<style lang="scss" scoped>
.reservation-item {
background: linear-gradient(180deg, #D7F0DD 0%, #FFFFFF 100%);
box-shadow: 0rpx 0rpx 10rpx 0rpx rgba(0, 0, 0, 0.25);
border-radius: 46rpx 46rpx 46rpx 46rpx;
transition: transform 0.2s;
&:active {
transform: scale(0.98);
}
}
.reservation-box {
width: 100%;
border-radius: 25rpx;
background-color: #F2F3F5;
}
.reservation-inner {
width: 95%;
margin: 20rpx auto 20rpx;
}
.title {
font-family: PingFang SC, PingFang SC;
font-weight: 500;
font-size: 35rpx;
color: #322A2A;
text-align: left;
font-style: normal;
text-transform: none;
}
.title-row {
justify-content: space-between;
}
.row-text {
font-family: PingFang SC, PingFang SC;
font-weight: 400;
font-size: 30rpx;
color: #575757;
text-align: left;
font-style: normal;
text-transform: none;
}
.row-center {
align-items: center;
}
.mt-20 {
margin-top: 20rpx;
}
.mt-10 {
margin-top: 10rpx;
}
.ml-20 {
margin-left: 20rpx;
}
.avatar {
width: 40rpx;
height: 40rpx;
border-radius: 50%;
margin-right: 20rpx;
}
.status-text {
font-size: 24rpx;
}
.evaluate-btn {
width: 120rpx;
height: 30px;
background-color: #1989FA;
border-radius: 10rpx;
margin-left: auto;
}
.evaluate-btn-text {
font-size: 24rpx;
color: #FFFFFF;
}
.popup-container {
width: 650rpx;
background-color: #FFFFFF;
border-radius: 10rpx;
}
.popup-inner {
width: 90%;
margin: 0 auto 0;
}
.popup-title {
font-size: 26rpx;
margin-top: 30rpx;
text-align: center;
}
.popup-desc {
font-size: 24rpx;
margin-top: 20rpx;
}
.panel-box {
width: 100%;
background-color: #F2F3F5;
border-radius: 10rpx;
padding-top: 20rpx;
padding-bottom: 20rpx;
margin-top: 20rpx;
}
.down-icon {
width: 40rpx;
height: 40rpx;
margin-left: auto;
margin-right: 20rpx;
}
.font-24 {
font-size: 24rpx;
}
.action-row {
margin-top: 50rpx;
height: 80rpx;
color: #FFFFFF;
font-size: 28rpx;
}
.action-btn {
flex: 1;
background-color: #1989FA;
border-radius: 10rpx;
}
.info-tip {
font-size: 24rpx;
text-align: center;
margin-top: 20rpx;
margin-bottom: 20rpx;
}
</style>

View File

@ -78,6 +78,13 @@
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "pages/me/my-record",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
}
],
"globalStyle": {
@ -92,8 +99,7 @@
"selectedColor": "#59AB6D",
"borderStyle": "black",
"height": "129.17rpx",
"list": [
{
"list": [{
"pagePath": "pages/index/index",
"iconPath": "/static/tabbar/home.png",
"selectedIconPath": "/static/tabbar/home_s.png",

View File

@ -1,321 +1,341 @@
<template>
<view class="content column">
<com-page-container-base ref="_containerBase">
<view class="content column">
<text style="margin-top: 100rpx; text-align: center;">发起预约</text>
<view class=""
style="width: 90%; background-color: #FFFFFF; border-radius: 10rpx; margin: 30rpx auto 0; display: flex; justify-content: center; box-shadow: 0 0 10px 3px rgba(0, 0, 0, 0.1);">
<view class="column" style="width: 95%; margin-bottom: 20rpx; margin-top: 25rpx;">
<view class="row" style="align-items: center;">
<text style="font-size: 27.85rpx; margin-right: 23rpx;">开始时间</text>
<view class="" style="width: 80%;">
<uni-datetime-picker style="width: 50px;" type="datetime" v-model="startTimeStr"
@change="changeLog" />
</view>
</view>
<view class="row" style="align-items: center; margin-top: 30rpx;">
<text style="font-size: 27.85rpx; margin-right: 23rpx;">结束时间</text>
<view class="" style="width: 80%;">
<uni-datetime-picker style="margin-top: 10rpx;" type="datetime" v-model="endTimeStr"
@change="changeLog2" />
</view>
</view>
<text v-if="hours!=''" style="font-size: 26rpx; margin-top: 20rpx;">合计{{hours}}小时{{minutes}}分钟</text>
</view>
</view>
<view class="column"
style="width: 90%; border-radius: 10rpx; margin: 40rpx auto 0; background-color: #FFFFFF; box-shadow: 0 0 10px 3px rgba(0, 0, 0, 0.1);">
<text style="font-size: 26rpx; margin-top: 20rpx; margin-left: 20rpx;">组局名称</text>
<text style="margin-top: 100rpx; text-align: center;">发起预约</text>
<view class=""
style="width: 89%; background-color: white; margin: 20rpx auto 0; height: 70rpx; border-radius: 10rpx; display: flex; align-items: center; padding-left: 20rpx; border: 1rpx solid #515151;">
<input class="uni-input" placeholder="请输入组局名称" style="font-size: 24rpx; width: 100%;" />
</view>
style="width: 90%; background-color: #FFFFFF; border-radius: 10rpx; margin: 30rpx auto 0; display: flex; justify-content: center; box-shadow: 0 0 10px 3px rgba(0, 0, 0, 0.1);">
<view class="column" style="width: 95%; margin-bottom: 20rpx; margin-top: 25rpx;">
<text style="font-size: 26rpx; margin-top: 20rpx; margin-left: 20rpx;">房间</text>
<view class="row" style="display: flex;">
<view class="" style="width: 92%; margin: 20rpx auto 0; border-radius: 50rpx;">
<uni-data-select class="custom-select" v-model="roomValue" :localdata="range"
@change="change"></uni-data-select>
</view>
<view style="width:130rpx;line-height:50rpx;height: 60rpx;">
<text
style="font-size: 28rpx;color: #515151;text-transform:none;font-style: normal;font-family: PingFang SC, PingFang SC;">开始时间</text>
</view>
<text style="font-size: 26rpx; margin-top: 20rpx; margin-left: 20rpx;">人数</text>
<view class="" style="flex: 1;line-height: 60rpx;height: 60rpx;">
<view
style="height:50rpx;line-height: 50rpx;border-radius:15rpx;border:2rpx solid #515151;padding-left: 20rpx;display: flex;"
@click="openUpDatesTimePicker()">
<view style="flex: 1;">{{ getDayDescription(startTimeStr) }}</view>
<view style="width:70rpx;display: flex;justify-content: center;align-items: center;">
<image src="@@:app/static/time_start.png" style="width: 40rpx;height: 40rpx;">
</image>
</view>
</view>
<view class="" style="width: 92%; margin: 20rpx auto 0;border-radius: 50rpx;">
<uni-data-select v-model="peopleValue" :localdata="peopleRange" @change="change"></uni-data-select>
</view>
<text style="font-size: 26rpx; margin-top: 20rpx; margin-left: 20rpx;">玩法类型</text>
<view class="" style="width: 92%; margin: 20rpx auto 0;border-radius: 50rpx;">
<uni-data-select v-model="peopleValue" :localdata="peopleRange" @change="change"></uni-data-select>
</view>
<text style="font-size: 26rpx; margin-top: 20rpx; margin-left: 20rpx;">具体规则</text>
<view class="" style="width: 92%; margin: 20rpx auto 0;border-radius: 50rpx;">
<uni-data-select v-model="peopleValue" :localdata="peopleRange" @change="change"></uni-data-select>
</view>
<text style="font-size: 26rpx; margin-top: 20rpx; margin-left: 20rpx;">其他补充</text>
<view class=""
style="width: 89%; background-color: white; border-radius: 10rpx; margin: 20rpx auto 20rpx; height: 70rpx; display: flex; align-items: center; padding-left: 20rpx; border: 1rpx solid #515151;">
<input class="uni-input" placeholder="请输入补充信息" style="font-size: 24rpx; width: 100%;" />
</view>
</view>
<view class="column" style="width: 90%; border-radius: 10rpx; margin: 40rpx auto 0; background-color: #FFFFFF; box-shadow: 0 0 10px 3px rgba(0, 0, 0, 0.1);">
<view class="row" style="margin-top: 20rpx; margin-left: 20rpx;">
<view class="" style="width: 120rpx; font-size: 26rpx; align-items: center;">
是否禁烟
</view>
<radio-group class="" style="margin-left: 50rpx;">
<label class="" style="font-size: 24rpx;">
<radio value="r1" color="#00AC4E" style="transform:scale(0.7);" :checked="true" />禁烟
</label>
<label class="" style="font-size: 24rpx; margin-left: 90rpx;">
<radio value="r2" color="#00AC4E" style="transform:scale(0.7);" />不禁烟
</label>
</radio-group>
</view>
<view class="row" style="margin-top: 20rpx; margin-left: 20rpx;">
<view class="" style="width: 120rpx; font-size: 26rpx; align-items: center;">
性别
</view>
<radio-group class="" style="margin-left: 50rpx;">
<label class="" style="font-size: 24rpx;">
<radio value="r1" color="#00AC4E" style="transform:scale(0.7);" :checked="true" />不限
</label>
<label class="" style="font-size: 24rpx; margin-left: 90rpx;">
<radio value="r2" color="#00AC4E" style="transform:scale(0.7);" />
</label>
<label class="" style="font-size: 24rpx; margin-left: 90rpx;">
<radio value="r3" color="#00AC4E" style="transform:scale(0.7);" />
</label>
</radio-group>
</view>
<view class="row" style="margin-top: 20rpx; margin-left: 20rpx; margin-bottom: 20rpx;">
<view class="" style="width: 120rpx; font-size: 26rpx; align-items: center;">
信誉
</view>
<text style="font-size: 25.86rpx; margin-left: 55rpx;">大于等于</text>
<view class="counter-container">
<!-- 减号按钮 -->
<view class="" @click="decrement" :disabled="currentValue <= 0">
<uni-icons type="minus" size="24" color="#00AC4E" />
</view>
</view>
<view style="height:20rpx;"></view>
<view class="row" style="display: flex;">
<!-- 数值显示 -->
<view class="counter-value">
{{ currentValue.toFixed(1) }}
</view>
<!-- 加号按钮 -->
<view class="" @click="increment" :disabled="currentValue >= 5">
<uni-icons type="plus" size="24" color="#00AC4E" />
<view style="width:130rpx;line-height:50rpx;height: 60rpx;">
<text
style="font-size: 28rpx;color: #515151;text-transform: none;font-style: normal;font-family: PingFang SC, PingFang SC;">结束时间</text>
</view>
<view class="" style="flex: 1;line-height: 60rpx;height: 60rpx;">
<view
style="height:50rpx;line-height: 50rpx;border-radius:15rpx;border:2rpx solid #515151;padding-left: 20rpx;display: flex;"
@click="openUpDatesTimePickerEnd()">
<view style="flex: 1;">{{ getDayDescription(endTimeStr) }}</view>
<view style="width:70rpx;display: flex;justify-content: center;align-items: center;">
<image src="@@:app/static/time_end.png" style="width: 40rpx;height: 40rpx;">
</image>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
<view class="column"
style="width: 90%; border-radius: 10rpx; margin: 40rpx auto 0; background-color: #FFFFFF; box-shadow: 0 0 10px 3px rgba(0, 0, 0, 0.1);">
<text style="font-size: 26rpx; margin-top: 20rpx; margin-left: 20rpx;">组局名称</text>
<view class="column" style="width: 90%; border-radius: 10rpx; margin: 20rpx auto 0; background-color: #FFFFFF; box-shadow: 0 0 10px 3px rgba(0, 0, 0, 0.1);">
<view class="row" style="margin-top: 20rpx; margin-left: 20rpx;">
<view class="" style=" font-size: 26rpx; align-items: center;">
鸽子费保证金
<view class=""
style="width: 89%; background-color: white; margin: 20rpx auto 0; height: 70rpx; border-radius: 10rpx; display: flex; align-items: center; padding-left: 20rpx; border: 1rpx solid #515151;">
<input class="uni-input" placeholder="请输入组局名称" style="font-size: 24rpx; width: 100%;" />
</view>
<radio-group class="" style="margin-left: 50rpx;">
<label class="" style="font-size: 24rpx;">
<radio value="r1" color="#00AC4E" style="transform:scale(0.7);" :checked="true" />0
</label>
<label class="" style="font-size: 24rpx;">
<radio value="r2" color="#00AC4E" style="transform:scale(0.7);" />5
</label>
<label class="" style="font-size: 24rpx;">
<radio value="r3" color="#00AC4E" style="transform:scale(0.7);" />10
</label>
</radio-group>
<text style="font-size: 26rpx; margin-top: 20rpx; margin-left: 20rpx;">房间</text>
<view class="" style="width: 92%; margin: 20rpx auto 0; border-radius: 50rpx;">
<uni-data-select class="custom-select" v-model="roomValue" :localdata="range"
@change="change"></uni-data-select>
</view>
<text style="font-size: 26rpx; margin-top: 20rpx; margin-left: 20rpx;">人数</text>
<view class="" style="width: 92%; margin: 20rpx auto 0;border-radius: 50rpx;">
<uni-data-select v-model="peopleValue" :localdata="peopleRange" @change="change"></uni-data-select>
</view>
<text style="font-size: 26rpx; margin-top: 20rpx; margin-left: 20rpx;">玩法类型</text>
<view class="" style="width: 92%; margin: 20rpx auto 0;border-radius: 50rpx;">
<uni-data-select v-model="peopleValue" :localdata="peopleRange" @change="change"></uni-data-select>
</view>
<text style="font-size: 26rpx; margin-top: 20rpx; margin-left: 20rpx;">具体规则</text>
<view class="" style="width: 92%; margin: 20rpx auto 0;border-radius: 50rpx;">
<uni-data-select v-model="peopleValue" :localdata="peopleRange" @change="change"></uni-data-select>
</view>
<text style="font-size: 26rpx; margin-top: 20rpx; margin-left: 20rpx;">其他补充</text>
<view class=""
style="width: 89%; background-color: white; border-radius: 10rpx; margin: 20rpx auto 20rpx; height: 70rpx; display: flex; align-items: center; padding-left: 20rpx; border: 1rpx solid #515151;">
<input class="uni-input" placeholder="请输入补充信息" style="font-size: 24rpx; width: 100%;" />
</view>
</view>
<text
style="font-size: 24rpx; margin-left: 20rpx; margin-bottom: 20rpx;">除发起者外其他参与人需缴纳鸽子费若有参与者在预约后没有赴约其鸽子费由在场的所有人平分组局成功或失败后鸽子费将全额返还</text>
<view class="column"
style="width: 90%; border-radius: 10rpx; margin: 40rpx auto 0; background-color: #FFFFFF; box-shadow: 0 0 10px 3px rgba(0, 0, 0, 0.1);">
<view class="row" style="margin-top: 20rpx; margin-left: 20rpx;">
<view class="" style="width: 120rpx; font-size: 26rpx; align-items: center;">
是否禁烟
</view>
<radio-group class="" style="margin-left: 50rpx;">
<label class="" style="font-size: 24rpx;">
<radio value="r1" color="#00AC4E" style="transform:scale(0.7);" :checked="true" />禁烟
</label>
<label class="" style="font-size: 24rpx; margin-left: 90rpx;">
<radio value="r2" color="#00AC4E" style="transform:scale(0.7);" />不禁烟
</label>
</radio-group>
</view>
<view class="row" style="margin-top: 20rpx; margin-left: 20rpx;">
<view class="" style="width: 120rpx; font-size: 26rpx; align-items: center;">
性别
</view>
<radio-group class="" style="margin-left: 50rpx;">
<label class="" style="font-size: 24rpx;">
<radio value="r1" color="#00AC4E" style="transform:scale(0.7);" :checked="true" />不限
</label>
<label class="" style="font-size: 24rpx; margin-left: 90rpx;">
<radio value="r2" color="#00AC4E" style="transform:scale(0.7);" />
</label>
<label class="" style="font-size: 24rpx; margin-left: 90rpx;">
<radio value="r3" color="#00AC4E" style="transform:scale(0.7);" />
</label>
</radio-group>
</view>
<view class="row" style="margin-top: 20rpx; margin-left: 20rpx; margin-bottom: 20rpx;">
<view class="" style="width: 120rpx; font-size: 26rpx; align-items: center;">
信誉
</view>
<text style="font-size: 25.86rpx; margin-left: 55rpx;">大于等于</text>
<view class="counter-container">
<!-- 减号按钮 -->
<view class="" @click="decrement" :disabled="currentValue <= 0">
<uni-icons type="minus" size="24" color="#00AC4E" />
</view>
<!-- 数值显示 -->
<view class="counter-value">
{{ currentValue.toFixed(1) }}
</view>
<!-- 加号按钮 -->
<view class="" @click="increment" :disabled="currentValue >= 5">
<uni-icons type="plus" size="24" color="#00AC4E" />
</view>
</view>
</view>
</view>
<view class="column"
style="width: 90%; border-radius: 10rpx; margin: 20rpx auto 0; background-color: #FFFFFF; box-shadow: 0 0 10px 3px rgba(0, 0, 0, 0.1);">
<view class="row" style="margin-top: 20rpx; margin-left: 20rpx;">
<view class="" style=" font-size: 26rpx; align-items: center;">
鸽子费保证金
</view>
<radio-group class="" style="margin-left: 50rpx;">
<label class="" style="font-size: 24rpx;">
<radio value="r1" color="#00AC4E" style="transform:scale(0.7);" :checked="true" />0
</label>
<label class="" style="font-size: 24rpx;">
<radio value="r2" color="#00AC4E" style="transform:scale(0.7);" />5
</label>
<label class="" style="font-size: 24rpx;">
<radio value="r3" color="#00AC4E" style="transform:scale(0.7);" />10
</label>
</radio-group>
</view>
<text
style="font-size: 24rpx; margin-left: 20rpx; margin-bottom: 20rpx;">除发起者外其他参与人需缴纳鸽子费若有参与者在预约后没有赴约其鸽子费由在场的所有人平分组局成功或失败后鸽子费将全额返还</text>
</view>
<view class="center"
style="width: 90%; border-radius: 10rpx; margin: 20rpx auto 0; background-color: #00AC4E;">
<text style="margin: 20rpx; color: white;">发起预约</text>
</view>
<view class="center" style="width: 90%; margin: 20rpx auto 20rpx;">
<text style="color: #979797; font-size: 24rpx;">组局成功后发起者可通过店员领取线下红包</text>
</view>
</view>
</com-page-container-base>
<view class="center" style="width: 90%; border-radius: 10rpx; margin: 20rpx auto 0; background-color: #00AC4E;">
<text style="margin: 20rpx; color: white;">发起预约</text>
</view>
<view class="center" style="width: 90%; margin: 20rpx auto 20rpx;">
<text style="color: #979797; font-size: 24rpx;">组局成功后发起者可通过店员领取线下红包</text>
</view>
</view>
</template>
<script>
export default {
data() {
return {
startTimeStr: "",
endTimeStr: "",
hours: "",
minutes: "",
roomValue: "",
peopleValue: "",
range: [{
"value": 0,
"text": "808号-大包30元/小时",
}, {
"value": 1,
"text": "807号-大包30元/小时",
}, {
"value": 2,
"text": "806号-大包30元/小时",
}, {
"value": 3,
"text": "805号-大包30元/小时",
}, ],
<script setup>
import { ref } from 'vue';
import { getDayDescription } from '@/common/system/timeUtile';
import { union } from 'lodash';
const _containerBase = ref(null)
const startTimeStr = ref(0)
const endTimeStr = ref(0)
const hours = ref("")
const minutes = ref("")
const roomValue = ref("")
const peopleValue = ref("")
peopleRange: [{
"value": 0,
"text": "1人",
}, {
"value": 1,
"text": "2人",
}, {
"value": 2,
"text": "3人",
}, {
"value": 3,
"text": "4人",
}, ],
currentValue: 0,
// 0.5
increment() {
if (this.currentValue < 5) {
this.currentValue += 0.5;
// 5
if (this.currentValue > 5) {
this.currentValue = 5;
}
}
},
const openUpDatesTimePicker = async () => {
var now = startTimeStr.value;
if (startTimeStr.value == 0) {
now = Date.now();
now += 1000 * 60 * 30;
}
const startTime = await _containerBase.value.openUpDatesTimePicker(now, now)
startTimeStr.value = startTime
}
const openUpDatesTimePickerEnd = async () => {
if (startTimeStr.value == 0) {
uni.showToast({
title: '请先选择开始时间',
icon: 'none'
})
return;
}
var now = (startTimeStr.value + 1000 * 60 * 30);
//minDate+1000*60*30 30
const endTime = await _containerBase.value.openUpDatesTimePicker(now, now)
endTimeStr.value = endTime
}
// 0.5
decrement() {
if (this.currentValue > 0) {
this.currentValue -= 0.5;
// 0
if (this.currentValue < 0) {
this.currentValue = 0;
}
}
}
}
},
methods: {
changeLog(e) {
console.log('change事件:', e);
this.setTime();
},
changeLog2(e) {
console.log('change事件2:', e);
this.setTime();
},
const range = ref([
{ value: 0, text: '808号-大包30元/小时' },
{ value: 1, text: '807号-大包30元/小时' },
{ value: 2, text: '806号-大包30元/小时' },
{ value: 3, text: '805号-大包30元/小时' },
])
const peopleRange = ref([
{ value: 0, text: '1人' },
{ value: 1, text: '2人' },
{ value: 2, text: '3人' },
{ value: 3, text: '4人' },
])
setTime() {
if (this.startTimeStr == "" || this.endTimeStr == "") {
return;
}
// Date
const startTime = new Date(this.startTimeStr.replace(/-/g, '/'));
const endTime = new Date(this.endTimeStr.replace(/-/g, '/'));
//
const timeDiff = endTime - startTime;
//
const totalMinutes = Math.floor(timeDiff / 1000 / 60);
//
this.hours = Math.floor(totalMinutes / 60);
this.minutes = totalMinutes % 60;
console.log(`两个时间相差 ${this.hours} 小时 ${this.minutes} 分钟`);
}
const currentValue = ref(0)
const increment = () => {
if (currentValue.value < 5) {
currentValue.value += 0.5
if (currentValue.value > 5) {
currentValue.value = 5
}
}
}
const decrement = () => {
if (currentValue.value > 0) {
currentValue.value -= 0.5
if (currentValue.value < 0) {
currentValue.value = 0
}
}
}
const changeLog = (e) => {
console.log('change事件:', e)
setTime()
}
const changeLog2 = (e) => {
console.log('change事件2:', e)
setTime()
}
const setTime = () => {
if (startTimeStr.value === "" || endTimeStr.value === "") {
return
}
const startTime = new Date(startTimeStr.value.replace(/-/g, '/'))
const endTime = new Date(endTimeStr.value.replace(/-/g, '/'))
const timeDiff = endTime.getTime() - startTime.getTime()
const totalMinutes = Math.floor(timeDiff / 1000 / 60)
hours.value = Math.floor(totalMinutes / 60)
minutes.value = totalMinutes % 60
console.log(`两个时间相差 ${hours.value} 小时 ${minutes.value} 分钟`)
}
</script>
<style lang="scss">
.content {
width: 100%;
height: 100vh;
overflow-y: auto;
background-color: #F7F7F7;
}
.content {
width: 100%;
height: 100vh;
overflow-y: auto;
background-color: #F7F7F7;
}
.counter-container {
display: flex;
align-items: center;
justify-content: center;
margin-left: 90rpx;
}
.counter-container {
display: flex;
align-items: center;
justify-content: center;
margin-left: 90rpx;
}
.counter-btn {
width: 80rpx;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
padding: 0;
line-height: 1;
}
.counter-btn {
width: 80rpx;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
padding: 0;
line-height: 1;
}
.minus-btn {
background-color: #f5f5f5;
border: 1px solid #eee;
}
.minus-btn {
background-color: #f5f5f5;
border: 1px solid #eee;
}
.counter-value {
width: 90rpx;
text-align: center;
font-size: 28rpx;
font-weight: 500;
color: #333;
}
.counter-value {
width: 90rpx;
text-align: center;
font-size: 28rpx;
font-weight: 500;
color: #333;
}
.custom-select ::v-deep .uni-input-input {
/* 正常状态下的边框颜色 */
border: 1px solid #007aff !important;
border-radius: 6px;
}
.custom-select ::v-deep .uni-input-input {
/* 正常状态下的边框颜色 */
border: 1px solid #007aff !important;
border-radius: 6px;
}
</style>

View File

@ -1,274 +1,78 @@
<template>
<view class="content column">
<com-page-container-base ref="_containerBase">
<view class="content column">
<z-paging ref="pagePaging" v-model="reservationList" @query="queryList" :refresher-enabled="true"
:loading-more-enabled="true" :auto="true" :empty-view-text="'暂无预约记录'"
:empty-view-img="'@@:app/static/index/no.png'" style="flex: 1; width: 100%; margin-top: 30rpx;">
<template #top>
<view class="row header-row">
<image src="/static/back.png" class="back-icon" @click="goBack()" mode=""></image>
<text class="page-title">预约记录</text>
<view class="spacer-40"></view>
</view>
<view class="row header-row" :style="{ marginTop: statusBarHeight + 'px' }">
<image src="/static/back.png" class="back-icon" @click="goBack()" mode=""></image>
<text class="page-title">预约记录</text>
<view class="spacer-40"></view>
</view>
<view class="row tab-row">
<text :style="currentIndex == 0 ? 'color:#FA0D0D' : 'color:#000000'" @click="click1()">我参与的</text>
<view class="row tab-row">
<up-tag text="预约记录" shape="circle" @click="currentIndex = 0;"
:plain="currentIndex == 0 ? false : true"></up-tag>
<text class="tab-second" :style="currentIndex == 1 ? 'color:#FA0D0D' : 'color:#000000'"
@click="click2()">我发起的</text>
</view>
<view class="list-wrapper">
<view class="column list-inner">
<!-- 加载状态 -->
<view v-if="loading" class="loading-container">
<text>加载中...</text>
</view>
<!-- 空状态 -->
<view v-else-if="reservationList.length === 0" class="empty-container">
<text>暂无预约记录</text>
</view>
<up-tag text="我发起的" shape="circle" @click="currentIndex = 1;" style="margin-left: 20rpx;"
:plain="currentIndex == 1 ? false : true"></up-tag>
</view>
</template>
<!-- 预约记录列表 -->
<view v-else class="reservation-item reservation-box" v-for="item in reservationList" :key="item.id">
<view class="column reservation-inner">
<view class="row title title-row">
<view class="title">{{ item.title || '麻将预约' }}</view>
<view class="status-text" :style="getStatusStyle(item.status)">
{{ getStatusText(item.status) }}
</view>
</view>
<view class="row row-text row-center mt-20">
<text class="ml-20">{{ formatTimeRange(item.start_time, item.end_time)
}}</text>
</view>
<view class="row row-center mt-20">
<text class="row-text ml-20">{{ item.room_name || '' }}</text>
</view>
<view class="row row-center mt-20">
<text class="row-text ml-20">已约牌友</text>
<image v-for="(participant, pIndex) in item.participants" :key="pIndex"
:src="participant.avatarImage || '/static/default-avatar.png'" class="avatar"
mode="aspectFill">
</image>
<view class="center evaluate-btn" @click="openEvaluatePop(item)">
<text class="evaluate-btn-text">牌友评价</text>
</view>
</view>
<view class="list-wrapper">
<view class="column list-inner">
<reservation-item v-for="item in reservationList" :key="item.id" :reservation="item"
@evaluate="_containerBase.openEvaluatePop" @click="_containerBase.openReservationPopup" />
</view>
</view>
</view>
</z-paging>
</view>
</view>
<uni-popup ref="evaluatePop" type="center">
<view class="popup-container">
<view class="column popup-inner">
<text class="popup-title">牌友评价</text>
<text class="popup-desc">
请对每位牌友进行评价
</text>
<view class="row panel-box" v-if="currentEvaluate" @click="index = 0, show = true">
{{ currentEvaluate.userName }}
<image src="/static/down.png" class="down-icon" mode=""></image>
</view>
<view class="column panel-box" v-if="currentEvaluate">
<view class="row row-center mt-20 ml-20">
<text class="font-24">牌品</text>
<uni-rate :readonly="currentEvaluate.is_evaluate" class="ml-20"
v-model="currentEvaluate.play_level" />
<text class="font-24">当前评分:{{ currentEvaluate.user_play_level }}</text>
</view>
<view class="row row-center mt-20 ml-20">
<text class="font-24">牌技</text>
<uni-rate :readonly="currentEvaluate.is_evaluate" v-model="currentEvaluate.skills_level"
class="ml-20" />
<text class="font-24">当前评分:{{ currentEvaluate.user_skills_level }}</text>
</view>
</view>
<view class="row action-row" v-if="currentEvaluate">
<view class="center action-btn" v-if="!currentEvaluate.userBlackStatus"
@click="async () => { var f = await addBlack(currentEvaluate.user_id); f ? currentEvaluate.userBlackStatus = true : currentEvaluate.userBlackStatus = false; }">
拉入黑名单
</view>
<view class="center action-btn" v-if="currentEvaluate.userBlackStatus"
@click="async () => { var f = await cancelBlack(currentEvaluate.user_id); f ? currentEvaluate.userBlackStatus = false : currentEvaluate.userBlackStatus = true; }">
移出黑名单
</view>
<view class="center action-btn ml-20" v-if="!currentEvaluate.is_evaluate"
@click="submitEvaluate(currentEvaluate)">
提交
</view>
<view class="center action-btn ml-20" v-if="currentEvaluate.is_evaluate">
已提交
</view>
</view>
<text class="info-tip">加入黑名单后双方将看不到对方发起的组局</text>
</view>
</view>
<up-picker v-if="evaluateList.length > 0" @cancel="cancel" @confirm="confirm" :show="show"
:columns="[evaluateList]" keyName="userName" valueName="user_id" :defaultIndex="[index]"></up-picker>
</uni-popup>
</com-page-container-base>
</template>
<script setup>
import { ref, onMounted, watch, computed } from 'vue'
import { sqInterface } from '@/common/server/interface/sq.js'
import { cancelBlack, addBlack } from '@/common/server/user.js'
import zPaging from '@/uni_modules/z-paging/components/z-paging/z-paging.vue'
import ReservationItem from '@/components/com/page/reservation-item.vue'
import ContainerBase from '@/components/com/page/container-base.vue'
//
const currentIndex = ref(0)
const loading = ref(false)
const reservationList = ref([])
const currentReservation = ref(null)
const statusBarHeight = ref(uni.getSystemInfoSync().statusBarHeight);
const pagePaging = ref(null)
const _containerBase = ref(null)
const index = ref(0);
const show = ref(false);
const evaluateList = ref([])
//
const evaluatePop = ref(null)
const cancel = () => {
show.value = false
}
const confirm = (e) => {
// console.log('confirm', e);
show.value = false
}
//
const getReservationList = async (type = 0) => {
// z-paging
const queryList = async (pageNo, pageSize) => {
try {
loading.value = true
const data = await sqInterface.getMyReservation(type, 1, 20)
if (data) {
reservationList.value = data
const data = await sqInterface.getMyReservation(currentIndex.value, pageNo, pageSize)
if (data && data.length > 0) {
pagePaging.value.complete(data)
} else {
pagePaging.value.complete([])
}
} catch (error) {
console.error('获取预约记录失败:', error)
pagePaging.value.complete(false)
uni.showToast({
title: '获取预约记录失败',
icon: 'none'
})
} finally {
loading.value = false
}
}
//
const click1 = () => {
currentIndex.value = 0
}
const click2 = () => {
currentIndex.value = 1
}
//
watch(currentIndex, (newIndex) => {
getReservationList(newIndex)
if (pagePaging.value) {
pagePaging.value.reload()
}
})
const currentEvaluate = computed(() => {
if (evaluateList.value.length == 0) {
return null;
}
return evaluateList.value[index.value]
})
//
const openEvaluatePop = async (reservation) => {
const data = await sqInterface.getEvaluateServices(reservation.id)
console.log('data', data);
if (data == null || data.length == 0) {
uni.showToast({
title: '暂无评价',
icon: 'none'
})
return;
}
currentReservation.value = reservation
evaluateList.value = evaluateList.value.splice(0, data.length);
evaluateList.value.push(...data);
console.log("evaluateList.value", evaluateList.value);
evaluatePop.value.open()
}
const submitEvaluate = async (evaluate) => {
uni.showLoading({
title: '评价提交中...',
})
const data = {
reservation_id: currentReservation.value.id,
to_user_id: evaluate.user_id,
play_level: evaluate.play_level,
skills_level: evaluate.skills_level
};
const isSuccess = await sqInterface.addEvaluateServices(data);
uni.hideLoading()
if (isSuccess) {
uni.showToast({
title: '评价提交成功',
icon: 'success'
})
evaluate.is_evaluate = true
}
else {
uni.showToast({
title: '评价提交失败',
icon: 'none'
})
}
}
//
const formatTimeRange = (startTime, endTime) => {
if (!startTime || !endTime) return '时间未设置'
const start = new Date(startTime)
const end = new Date(endTime)
const startStr = `${start.getFullYear()}-${String(start.getMonth() + 1).padStart(2, '0')}-${String(start.getDate()).padStart(2, '0')} ${String(start.getHours()).padStart(2, '0')}:${String(start.getMinutes()).padStart(2, '0')}`
const endStr = `${end.getFullYear()}-${String(end.getMonth() + 1).padStart(2, '0')}-${String(end.getDate()).padStart(2, '0')} ${String(end.getHours()).padStart(2, '0')}:${String(end.getMinutes()).padStart(2, '0')}`
//
const duration = end - start
const hours = Math.floor(duration / (1000 * 60 * 60))
const minutes = Math.floor((duration % (1000 * 60 * 60)) / (1000 * 60))
return `${startStr} ~ ${endStr}`
}
//
const getStatusText = (status) => {
const statusMap = {
0: '进行中',
1: '已结束',
2: '已结束'
}
return statusMap[status] || '未知状态'
}
//
const getStatusStyle = (status) => {
const styleMap = {
0: 'color: #1989FA',
1: 'color: #999',
2: 'color: #999'
}
return styleMap[status] || 'color: #999'
}
//
const goBack = () => {
@ -277,10 +81,8 @@ const goBack = () => {
})
}
//
onMounted(() => {
getReservationList(0)
})
// z-paging
onMounted(() => { })
</script>
<style lang="scss" scoped>
@ -311,7 +113,7 @@ onMounted(() => {
.tab-row {
width: 90%;
margin: 30rpx auto 0;
margin: 35rpx auto 0;
font-size: 26rpx;
}

View File

@ -1,151 +1,132 @@
<template>
<view class="content column">
<container-base ref="_containerBase">
<view class="content column">
<!-- 加载状态 -->
<view v-if="loading" class="loading-container">
<text>加载中...</text>
</view>
<!-- 加载状态 -->
<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 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 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>
<text style="margin-top: 10rpx; color: #999;" @click="toLogin()">点击登录</text>
</view>
</view>
<view class="column" @click="currentAppointment ? openPop() : null"
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 v-if="!currentAppointment" 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>
<!-- 有预约状态 -->
<template v-else>
<text style="font-size: 24rpx; margin-left: 20rpx; margin-top: 25rpx;">
{{ currentAppointment.startTime }} ~ {{ currentAppointment.endTime }} {{
currentAppointment.duration }}
</text>
<text style="font-size: 24rpx; margin-left: 20rpx; margin-top: 10rpx;">{{ currentAppointment.room
}}</text>
<view class="row"
style="font-size: 24rpx; margin-left: 20rpx; margin-top: 20rpx; align-items: center; margin-bottom: 20rpx;">
<text>已预约人员</text>
<image v-for="(participant, index) in currentAppointment.participants" :key="index"
:src="participant.avatar || ''"
style="width: 30rpx; height: 30rpx; background-color: antiquewhite; border-radius: 50%; margin-left: 10rpx;"
mode=""></image>
<text style="font-size: 24rpx; margin-left: auto; margin-right: 20rpx;">查看详情</text>
<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>
</template>
</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;">
<text style="font-size: 24rpx;">我的评分</text>
<text v-if="userInfo.rating > 0" style="font-size: 34rpx; color: #ED3535; margin-left: 10rpx;">{{
userInfo.rating }}</text>
<text v-else style="font-size: 24rpx; color: #999; margin-left: 10rpx;">未评分</text>
<text style="font-size: 24rpx; margin-left: 180rpx;">我的信誉</text>
<text v-if="userInfo.reputation > 0" style="font-size: 34rpx; color: #ED3535; margin-left: 10rpx;">{{
userInfo.reputation }}</text>
<text v-else style="font-size: 24rpx; color: #999; margin-left: 10rpx;">未评级</text>
</view>
<view v-else style="overflow: auto;max-height: 600rpx;">
<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.cardQuality" />
<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 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.cardSkill" />
</view>
<text style="font-size: 24rpx; margin: 20rpx;">鸽子数 {{ userInfo.pigeonCount }}</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 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="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 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="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 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="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 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>
<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>
<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>
</view>
</container-base>
<uni-popup ref="infoPop" type="center">
@ -245,181 +226,197 @@
</template>
<script setup>
import {
userInfo,
loadUserInfo
} from '@/common/server/user'
import {
ref,
reactive,
onMounted
} from 'vue'
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 rateValue = ref(4.5)
const infoPop = ref(null)
const loading = ref(false)
// -
// const userInfo = reactive({
// nickname: '',
// uid: '',
// avatar: '@@:app/nouser.png',
// rating: 0,
// reputation: 0,
// cardQuality: 0,
// cardSkill: 0,
// pigeonCount: 0
// })
//
const currentAppointment = 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 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 clasePop = () => {
infoPop.value.close();
}
//
const openPop = () => {
infoPop.value.open();
}
const toAppointment = () => {
if (userInfo.value == null) {
uni.navigateTo({
url: '/pages/me/login'
});
return;
}
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/appointment-record-page'
url: '/pages/me/login'
});
return;
}
const toEditInfo = () => {
//
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/edit-info'
url: '/pages/me/my-record'
});
}
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 = () => {
} else {
uni.navigateTo({
url: '/pages/me/login'
});
}
}
// -
const loadCurrentAppointment = async () => {
try {
//
currentAppointment.value = null
} catch (error) {
console.error('加载预约信息失败:', error)
currentAppointment.value = null
}
const toEditInfo = () => {
//
if (userInfo.value == null) {
uni.navigateTo({
url: '/pages/me/login'
});
return;
}
//
onMounted(() => {
loadCurrentAppointment()
})
//
onShow(() => {
//
// getUserInfoData();
})
onLoad(async () => {
await loadUserInfo();
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 res = await sqInterface.getMyUseReservation();
console.log("getMyUseReservation", res);
myUseReservation.value = myUseReservation.value.splice(0, myUseReservation.value.length);
myUseReservation.value.push(...res);
try {
//
currentAppointment.value = null
} catch (error) {
console.error('加载预约信息失败:', error)
currentAppointment.value = null
}
}
//
onMounted(() => {
loadCurrentAppointment()
})
//
onShow(() => {
//
// getUserInfoData();
})
onLoad(async () => {
await loadUserInfo();
});
</script>
<style lang="scss">
.content {
width: 100%;
height: 100vh;
background-color: #F7F7F7;
}
.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;
}
.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>

218
pages/me/my-record.vue Normal file
View File

@ -0,0 +1,218 @@
<template>
<view class="content column">
<z-paging ref="pagePaging" v-model="repList" @query="queryList" :refresher-enabled="true"
:loading-more-enabled="true" :auto="true" :empty-view-text="'暂无记录'"
:empty-view-img="'@@:app/static/index/no.png'" style="flex: 1; width: 100%; margin-top: 30rpx;">
<template #top>
<view class="row header-row" :style="{ marginTop: statusBarHeight + 'px' }">
<image src="/static/back.png" class="back-icon" @click="goBack()" mode=""></image>
<text class="page-title">我的记录</text>
<view class="spacer-40"></view>
</view>
<view class="row tab-row">
<up-tag text="信誉分记录" shape="circle" @click="switchTab(0)"
:plain="currentIndex == 0 ? false : true"></up-tag>
<up-tag text="其它记录" shape="circle" @click="switchTab(1)" style="margin-left: 20rpx;"
:plain="currentIndex == 1 ? false : true"></up-tag>
</view>
</template>
<view class="list-wrapper">
<view class="column list-inner">
<view class="reservation-item reservation-box" v-for="(item, index) in repList"
:key="index">
<view class="column reservation-inner">
<view class="row title title-row">
<view class="title">{{ item.title || '记录' }}</view>reservation-box
<view
:class="['value-text', Number(item.reputation_value) >= 0 ? 'value-pos' : 'value-neg']">
{{ formatValue(item.reputation_value) }}
</view>
</view>
<view class="row row-text row-center mt-20">
<text class="ml-20">{{ item.created_at || '' }}</text>
</view>
</view>
</view>
</view>
</view>
</z-paging>
</view>
</template>
<script setup>
import {
ref,
watch
} from 'vue'
import zPaging from '@/uni_modules/z-paging/components/z-paging/z-paging.vue'
import {
sqInterface
} from '@/common/server/interface/sq.js'
const statusBarHeight = ref(uni.getSystemInfoSync().statusBarHeight);
const currentIndex = ref(0)
const repList = ref([])
const pagePaging = ref(null)
const switchTab = (idx) => {
currentIndex.value = idx
}
watch(currentIndex, () => {
if (pagePaging.value) {
pagePaging.value.reload()
}
})
const queryList = async (pageNo, pageSize) => {
try {
let data = []
if (currentIndex.value === 0) {
data = await sqInterface.getReputationByUser(pageNo, pageSize) || []
} else {
data = []
}
pagePaging.value.complete(data)
} catch (error) {
console.error('获取记录失败:', error)
pagePaging.value.complete(false)
uni.showToast({
title: '获取记录失败',
icon: 'none'
})
}
}
const goBack = () => {
uni.navigateBack({
delta: 1
})
}
const formatValue = (val) => {
const num = Number(val)
if (isNaN(num)) return val
return num > 0 ? `+${num}` : `${num}`
}
</script>
<style lang="scss" scoped>
.content {
width: 100%;
height: 100vh;
background: #F7F7F7;
}
.header-row {
width: 90%;
margin: 100rpx auto 0;
justify-content: space-between;
}
.back-icon {
width: 40rpx;
height: 40rpx;
}
.page-title {
font-size: 30rpx;
}
.spacer-40 {
width: 40rpx;
}
.tab-row {
width: 90%;
margin: 35rpx auto 0;
font-size: 26rpx;
}
.list-wrapper {
width: 100%;
overflow-y: auto;
margin-top: 30rpx;
}
.list-inner {
width: 90%;
margin: 0 auto 0;
font-size: 24rpx;
}
.title {
font-family: PingFang SC, PingFang SC;
font-weight: 500;
font-size: 35rpx;
color: #322A2A;
text-align: left;
font-style: normal;
text-transform: none;
}
.title-row {
justify-content: space-between;
}
.row-text {
font-family: PingFang SC, PingFang SC;
font-weight: 400;
font-size: 30rpx;
color: #575757;
text-align: left;
font-style: normal;
text-transform: none;
}
.reservation-item {
background: linear-gradient(180deg, #D7F0DD 0%, #FFFFFF 100%);
box-shadow: 0rpx 0rpx 10rpx 0rpx rgba(0, 0, 0, 0.25);
border-radius: 46rpx 46rpx 46rpx 46rpx;
transition: transform 0.2s;
&:active {
transform: scale(0.98);
}
}
.reservation-box {
width: 100%;
border-radius: 10rpx;
background-color: #F2F3F5;
margin-bottom: 40rpx;
}
.reservation-inner {
width: 95%;
margin: 20rpx auto 20rpx;
}
.row-center {
align-items: center;
}
.mt-20 {
margin-top: 20rpx;
}
.ml-20 {
margin-left: 20rpx;
}
.value-text {
font-size: 26rpx;
}
.value-pos {
color: #2ecc71;
}
.value-neg {
color: #e74c3c;
}
</style>

View File

@ -1,6 +1,7 @@
<template>
<!-- #ifndef APP-NVUE -->
<view v-show="isShow" ref="ani" :animation="animationData" :class="customClass" :style="transformStyles" @click="onClick">
<view v-show="isShow" ref="ani" :animation="animationData" :class="customClass" :style="transformStyles" @click.stop="onClick">
<slot></slot>
</view>
<!-- #endif -->