32
This commit is contained in:
parent
d91eac13d1
commit
e0ba4f5d5b
|
|
@ -6,11 +6,11 @@
|
||||||
// 开发环境配置
|
// 开发环境配置
|
||||||
const development = {
|
const development = {
|
||||||
// API基础URL
|
// API基础URL
|
||||||
// baseUrl: 'https://ydsapi.zpc-xy.com',
|
baseUrl: 'https://sqqp.zpc-xy.com',
|
||||||
// baseUrl: 'http://1.15.21.245:2401',
|
// baseUrl: 'http://1.15.21.245:2401',
|
||||||
// host: ['http://1.15.21.245:2401'],
|
host: ['https://sqqp.zpc-xy.com'],
|
||||||
baseUrl: 'http://localhost:2015',
|
// baseUrl: 'http://192.168.1.21:2016',
|
||||||
host: ['http://localhost:2015'],
|
// host: ['http://192.168.1.21:2016'],
|
||||||
imageUrl: 'https://guyu-1308826010.cos.ap-shanghai.myqcloud.com',
|
imageUrl: 'https://guyu-1308826010.cos.ap-shanghai.myqcloud.com',
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,18 @@ export const interFaceTest = async () => {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取服务与说明数据
|
||||||
|
* @returns {Promise<any>}
|
||||||
|
*/
|
||||||
|
export const getServiceDescription = async () => {
|
||||||
|
const res = await request.post("Common/GetServiceDescription");
|
||||||
|
if (res.code == 0) {
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 上传附件通用接口
|
* 上传附件通用接口
|
||||||
* @param {FormData} formData 上传的表单数据
|
* @param {FormData} formData 上传的表单数据
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,21 @@
|
||||||
import request from '@/common/system/request';
|
import request from '@/common/system/request';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户是否可以创建预约(仅校验,不创建)
|
||||||
|
* @param {Object} reservationData 创建预约所需参数
|
||||||
|
* @returns {Promise<{canCreate:boolean,message?:string,code?:number}>}
|
||||||
|
*/
|
||||||
|
export const canCreateSQReservation = async (reservationData) => {
|
||||||
|
const res = await request.post("sq/CanCreateSQReservation", reservationData);
|
||||||
|
if (res && typeof res.code !== 'undefined') {
|
||||||
|
if (res.code === 0) {
|
||||||
|
return { canCreate: true, code: 0 };
|
||||||
|
}
|
||||||
|
return { canCreate: false, message: res.msg || '不可创建', code: res.code };
|
||||||
|
}
|
||||||
|
return { canCreate: false, message: '网络异常', code: 500 };
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取预约记录
|
* 获取预约记录
|
||||||
* @param {number} index
|
* @param {number} index
|
||||||
|
|
@ -95,6 +111,23 @@ export const getReputationByUser = async (pageIndex = 1, pageSize = 20) => {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取支付记录
|
||||||
|
* @param {number} pageIndex 起始页
|
||||||
|
* @param {number} pageSize 页大小
|
||||||
|
* @returns {Promise<any>} 返回支付记录数据
|
||||||
|
*/
|
||||||
|
export const getPaymentRecords = async (pageIndex = 1, pageSize = 20) => {
|
||||||
|
const res = await request.get("sq/GetPaymentRecords", {
|
||||||
|
pageIndex: pageIndex,
|
||||||
|
pageSize: pageSize
|
||||||
|
});
|
||||||
|
if (res.code == 0) {
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取可预约的房间列表
|
* 获取可预约的房间列表
|
||||||
* @param {number} startTime 开始时间 时间戳(秒)
|
* @param {number} startTime 开始时间 时间戳(秒)
|
||||||
|
|
@ -181,18 +214,45 @@ export const cancelReservation = async (reservation_id, cancel_reason) => {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预约签到接口(仅发起者可操作,且只能签到一次)
|
||||||
|
* @param {Object} checkInData 签到数据
|
||||||
|
* @param {number} checkInData.reservation_id 预约ID
|
||||||
|
* @param {Array} checkInData.attendeds 参会名单(不包含发起者)
|
||||||
|
* @param {number} checkInData.attendeds[].user_id 用户ID
|
||||||
|
* @param {boolean} checkInData.attendeds[].isAttended 是否到场
|
||||||
|
* @returns {Promise<any>} 返回签到结果
|
||||||
|
*/
|
||||||
|
export const checkInReservation = async (checkInData) => {
|
||||||
|
console.log("checkInReservation", checkInData);
|
||||||
|
const res = await request.post("sq/CheckInReservation", checkInData);
|
||||||
|
if (res.code == 0) {
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: res.msg || '签到成功'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: res.msg || '签到失败'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const sqInterface = {
|
export const sqInterface = {
|
||||||
|
canCreateSQReservation,
|
||||||
getReservationList,
|
getReservationList,
|
||||||
getMyReservation,
|
getMyReservation,
|
||||||
getMyUseReservation,
|
getMyUseReservation,
|
||||||
getEvaluateServices,
|
getEvaluateServices,
|
||||||
addEvaluateServices,
|
addEvaluateServices,
|
||||||
getReputationByUser,
|
getReputationByUser,
|
||||||
|
getPaymentRecords,
|
||||||
getReservationRoomList,
|
getReservationRoomList,
|
||||||
addSQReservation,
|
addSQReservation,
|
||||||
joinReservation,
|
joinReservation,
|
||||||
cancelReservation
|
cancelReservation,
|
||||||
|
checkInReservation
|
||||||
}
|
}
|
||||||
|
|
@ -32,3 +32,4 @@ export const navigateToAgreement = (type) => {
|
||||||
|
|
||||||
navigateTo(`/pages/other/agreement?type=${type}`);
|
navigateTo(`/pages/other/agreement?type=${type}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
1
components.d.ts
vendored
1
components.d.ts
vendored
|
|
@ -17,6 +17,7 @@ declare module 'vue' {
|
||||||
NoData: typeof import('./components/com/page/no-data.vue')['default']
|
NoData: typeof import('./components/com/page/no-data.vue')['default']
|
||||||
NoEmpty: typeof import('./components/com/index/NoEmpty.vue')['default']
|
NoEmpty: typeof import('./components/com/index/NoEmpty.vue')['default']
|
||||||
PickerData: typeof import('./components/com/appointment/picker-data.vue')['default']
|
PickerData: typeof import('./components/com/appointment/picker-data.vue')['default']
|
||||||
|
QiandaoPopup: typeof import('./components/com/page/qiandao-popup.vue')['default']
|
||||||
RadioSelect: typeof import('./components/com/appointment/radio-select.vue')['default']
|
RadioSelect: typeof import('./components/com/appointment/radio-select.vue')['default']
|
||||||
ReservationEvaluate: typeof import('./components/com/page/reservation-evaluate.vue')['default']
|
ReservationEvaluate: typeof import('./components/com/page/reservation-evaluate.vue')['default']
|
||||||
ReservationItem: typeof import('./components/com/page/reservation-item.vue')['default']
|
ReservationItem: typeof import('./components/com/page/reservation-item.vue')['default']
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,19 @@
|
||||||
<template>
|
<template>
|
||||||
<uni-popup ref="popup" type="center">
|
<uni-popup ref="popup" type="center">
|
||||||
<view class="column center"
|
<view class="column center" style="width: 680rpx; background: #F7F7F7; border-radius: 10rpx; padding: 20rpx;">
|
||||||
style="width: 680rpx; background-color: white; border-radius: 10rpx; padding: 20rpx;">
|
|
||||||
|
|
||||||
<text style="">预约信息</text>
|
<text style="">预约信息</text>
|
||||||
|
|
||||||
<view class="column"
|
<view class="column card" style="width: 100%; height: 180rpx;">
|
||||||
style="width: 100%; height: 180rpx; background-color: #E3E2E2; margin-top: 20rpx; border-radius: 10rpx;">
|
<view class="row lable" style="margin-top: 20rpx; align-items: center; margin-left: 20rpx;">
|
||||||
<view class="row" style="margin-top: 20rpx; align-items: center; margin-left: 20rpx;">
|
<text>发起者</text>
|
||||||
<text style="font-size: 22rpx;">发起者</text>
|
|
||||||
<image :src="initiatorInfo.avatarImage || ''"
|
<image :src="initiatorInfo.avatarImage || ''"
|
||||||
style="width: 50rpx; height: 50rpx; background-color: antiquewhite; border-radius: 50%; margin-left: 20rpx;"
|
style="width: 50rpx; height: 50rpx; background-color: antiquewhite; border-radius: 50%; margin-left: 20rpx;"
|
||||||
mode=""></image>
|
mode=""></image>
|
||||||
<text style="font-size: 20rpx; margin-left: 15rpx;">{{ initiatorInfo.userName || '' }}</text>
|
<text style="margin-left: 15rpx;">{{ initiatorInfo.userName || '' }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="row" style="margin-top: 30rpx; align-items: center; margin-left: 20rpx;">
|
<view class="row lable" style="margin-top: 30rpx; align-items: center; margin-left: 20rpx;">
|
||||||
<text style="font-size: 22rpx;">参与者</text>
|
<text>参与者</text>
|
||||||
|
|
||||||
<view class="row" v-for="(item, index) in participantList" :key="index"
|
<view class="row" v-for="(item, index) in participantList" :key="index"
|
||||||
style="align-items: center;">
|
style="align-items: center;">
|
||||||
|
|
@ -30,10 +28,6 @@
|
||||||
<text style="font-size: 10rpx;">黑名单</text>
|
<text style="font-size: 10rpx;">黑名单</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<text
|
|
||||||
style="font-size: 20rpx; margin-left: 30rpx; width: 100rpx; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">{{
|
|
||||||
item.userName || '' }}</text>
|
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
|
|
@ -41,25 +35,23 @@
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
|
||||||
<view class="column"
|
<view class="column card lable" style="width: 100%;padding-bottom:20rpx;">
|
||||||
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;">
|
<view class="row lable" style="justify-content: space-between; margin: 20rpx;">
|
||||||
<text>开始时间</text>
|
<text>开始时间</text>
|
||||||
<text>{{ formatTime(reservationData.start_time) }}</text>
|
<text>{{ formatTime(reservationData.start_time) }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="row" style="justify-content: space-between; margin: 0 20rpx;">
|
<view class="row lable" style="justify-content: space-between; margin: 0 20rpx;">
|
||||||
<text>结束时间</text>
|
<text>结束时间</text>
|
||||||
<text>{{ formatTime(reservationData.end_time) }}</text>
|
<text>{{ formatTime(reservationData.end_time) }}</text>
|
||||||
</view>
|
</view>
|
||||||
|
<text style="margin:20rpx 20rpx 0;">合计:{{
|
||||||
<text style="margin: 30rpx 20rpx 0;">合计:{{ formatDuration(reservationData.duration_minutes) }}</text>
|
formatDuration(reservationData.duration_minutes) }}</text>
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="column"
|
<view class="column card lable" style="width: 100%;">
|
||||||
style="width: 100%; background-color: #E3E2E2; margin-top: 20rpx; border-radius: 10rpx; font-size: 22rpx;">
|
<text style="margin: 20rpx 20rpx 10rpx;">房间号:{{ reservationData.room_name || ''
|
||||||
<text style="margin: 20rpx 20rpx 10rpx; font-size: 24rpx;">房间号:{{ reservationData.room_name || ''
|
|
||||||
}}</text>
|
}}</text>
|
||||||
<text style="margin: 10rpx 20rpx;">人数:{{ reservationData.player_count || 0 }}人</text>
|
<text style="margin: 10rpx 20rpx;">人数:{{ reservationData.player_count || 0 }}人</text>
|
||||||
<text style="margin: 10rpx 20rpx;">玩法类型:{{ reservationData.game_type || '' }}</text>
|
<text style="margin: 10rpx 20rpx;">玩法类型:{{ reservationData.game_type || '' }}</text>
|
||||||
|
|
@ -67,17 +59,17 @@
|
||||||
<text style="margin: 10rpx 20rpx 20rpx;">补充信息:{{ reservationData.extra_info || '无' }}</text>
|
<text style="margin: 10rpx 20rpx 20rpx;">补充信息:{{ reservationData.extra_info || '无' }}</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="column"
|
<view class="column card lable" style="width: 100%; ">
|
||||||
style="width: 100%; background-color: #E3E2E2; margin-top: 20rpx; border-radius: 10rpx; font-size: 22rpx;">
|
<text style="margin: 20rpx 20rpx 10rpx;">是否禁烟:{{
|
||||||
<text style="margin: 20rpx 20rpx 10rpx; font-size: 24rpx;">是否禁烟:{{
|
|
||||||
getSmokingText(reservationData.is_smoking) }}</text>
|
getSmokingText(reservationData.is_smoking) }}</text>
|
||||||
<text style="margin: 10rpx 20rpx;">性别:{{ getGenderText(reservationData.gender_limit) }}</text>
|
<text style="margin: 10rpx 20rpx;">性别:{{ getGenderText(reservationData.gender_limit) }}</text>
|
||||||
|
<text style="margin: 10rpx 20rpx;">年龄范围:{{
|
||||||
|
getAgeRangeText(reservationData.min_age, reservationData.max_age) }}</text>
|
||||||
<text style="margin: 10rpx 20rpx 20rpx;">信誉:≧{{ reservationData.credit_limit || 0 }}</text>
|
<text style="margin: 10rpx 20rpx 20rpx;">信誉:≧{{ reservationData.credit_limit || 0 }}</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="column"
|
<view class="column card lable" style="width: 100%; ">
|
||||||
style="width: 100%; background-color: #E3E2E2; margin-top: 20rpx; border-radius: 10rpx; font-size: 22rpx;">
|
<text style="margin: 20rpx 20rpx 10rpx; ">鸽子费:{{ reservationData.deposit_fee || 0
|
||||||
<text style="margin: 20rpx 20rpx 10rpx; font-size: 24rpx;">鸽子费:{{ reservationData.deposit_fee || 0
|
|
||||||
}}元</text>
|
}}元</text>
|
||||||
<text
|
<text
|
||||||
style="margin: 10rpx 20rpx 20rpx; color: #9F9F9F;">组局成功后若有牌友未赴约,其鸽子费平均分给其他牌友。组局成功或失败后鸽子费将全额返还。</text>
|
style="margin: 10rpx 20rpx 20rpx; color: #9F9F9F;">组局成功后若有牌友未赴约,其鸽子费平均分给其他牌友。组局成功或失败后鸽子费将全额返还。</text>
|
||||||
|
|
@ -113,6 +105,13 @@
|
||||||
<text style="font-size: 24rpx; font-weight: 600; color: white;">取消组局</text>
|
<text style="font-size: 24rpx; font-weight: 600; color: white;">取消组局</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
<view class="row" v-if="isAddhandleJoin == 3" style="width: 100%; margin-top: 30rpx;">
|
||||||
|
<view class="center" @click="close"
|
||||||
|
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>
|
</view>
|
||||||
</uni-popup>
|
</uni-popup>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -150,7 +149,9 @@ const participantList = computed(() => {
|
||||||
var isAddhandleJoin = ref(0);
|
var isAddhandleJoin = ref(0);
|
||||||
// 显示弹窗
|
// 显示弹窗
|
||||||
const show = (item) => {
|
const show = (item) => {
|
||||||
|
console.log("itemitemitemitem", item)
|
||||||
reservationData.value = item || {}
|
reservationData.value = item || {}
|
||||||
|
isAddhandleJoin.value = 0;
|
||||||
if (userInfo.value != null) {
|
if (userInfo.value != null) {
|
||||||
var _initiatorInfo = item.participants.find(p => p.role === 1);
|
var _initiatorInfo = item.participants.find(p => p.role === 1);
|
||||||
if (_initiatorInfo != null) {
|
if (_initiatorInfo != null) {
|
||||||
|
|
@ -158,6 +159,12 @@ const show = (item) => {
|
||||||
isAddhandleJoin.value = 2;
|
isAddhandleJoin.value = 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var _joinInfo = item.participants.find(p => p.role === 0);
|
||||||
|
if (_joinInfo != null) {
|
||||||
|
if (userInfo.value.id == _joinInfo.user_id) {
|
||||||
|
isAddhandleJoin.value = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
popup.value.open()
|
popup.value.open()
|
||||||
}
|
}
|
||||||
|
|
@ -209,7 +216,24 @@ const getGenderText = (genderLimit) => {
|
||||||
return '不限'
|
return '不限'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const getAgeRangeText = (minAge, maxAge) => {
|
||||||
|
if (minAge == 0 && maxAge == 0) {
|
||||||
|
return "不限";
|
||||||
|
}
|
||||||
|
let s = "";
|
||||||
|
if (minAge == 0) {
|
||||||
|
s = "不限";
|
||||||
|
} else {
|
||||||
|
s = minAge + "岁";
|
||||||
|
}
|
||||||
|
s += " ~ ";
|
||||||
|
if (maxAge == 0) {
|
||||||
|
s += "不限";
|
||||||
|
} else {
|
||||||
|
s += maxAge + "岁";
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
// 处理加入组局
|
// 处理加入组局
|
||||||
const handleJoin = async () => {
|
const handleJoin = async () => {
|
||||||
// 检查登录状态
|
// 检查登录状态
|
||||||
|
|
@ -424,4 +448,17 @@ defineExpose({
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
background: #FFFFFF;
|
||||||
|
box-shadow: 0rpx 0rpx 10rpx 4rpx rgba(0, 0, 0, 0.25);
|
||||||
|
border-radius: 30rpx 30rpx 30rpx 30rpx;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lable {
|
||||||
|
font-family: PingFang SC, PingFang SC;
|
||||||
|
font-size: 22rpx;
|
||||||
|
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
<view>
|
<view>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
<reservation-evaluate ref="_baseEvaluatePop" />
|
<reservation-evaluate ref="_baseEvaluatePop" />
|
||||||
|
<qiandao-popup ref="_qianDaoPopup" />
|
||||||
<!-- 预约信息弹窗组件 -->
|
<!-- 预约信息弹窗组件 -->
|
||||||
<ReservationPopup ref="_reservationPopup" />
|
<ReservationPopup ref="_reservationPopup" />
|
||||||
<up-datetime-picker :show="_upDatesTimePicker.show" :filter="_upDatesTimePicker.filter"
|
<up-datetime-picker :show="_upDatesTimePicker.show" :filter="_upDatesTimePicker.filter"
|
||||||
|
|
@ -16,9 +17,11 @@
|
||||||
import { ref, onMounted, provide } from 'vue'
|
import { ref, onMounted, provide } from 'vue'
|
||||||
import ReservationEvaluate from '@/components/com/page/reservation-evaluate.vue'
|
import ReservationEvaluate from '@/components/com/page/reservation-evaluate.vue'
|
||||||
import ReservationPopup from '@/components/com/index/ReservationPopup.vue'
|
import ReservationPopup from '@/components/com/index/ReservationPopup.vue'
|
||||||
|
import QiandaoPopup from '@/components/com/page/qiandao-popup.vue'
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
const _baseEvaluatePop = ref(null)
|
const _baseEvaluatePop = ref(null)
|
||||||
const _reservationPopup = ref(null)
|
const _reservationPopup = ref(null)
|
||||||
|
const _qianDaoPopup = ref(null);
|
||||||
|
|
||||||
const openEvaluatePop = async (reservation) => {
|
const openEvaluatePop = async (reservation) => {
|
||||||
_baseEvaluatePop.value && _baseEvaluatePop.value.show(reservation)
|
_baseEvaluatePop.value && _baseEvaluatePop.value.show(reservation)
|
||||||
|
|
@ -27,6 +30,10 @@ const openReservationPopup = async (reservation) => {
|
||||||
console.log("openReservationPopup", reservation)
|
console.log("openReservationPopup", reservation)
|
||||||
_reservationPopup.value && _reservationPopup.value.show(reservation)
|
_reservationPopup.value && _reservationPopup.value.show(reservation)
|
||||||
}
|
}
|
||||||
|
const openQianDaoPop = async (reservation) => {
|
||||||
|
console.log("openQianDaoPop", reservation)
|
||||||
|
_qianDaoPopup.value && _qianDaoPopup.value.show(reservation)
|
||||||
|
}
|
||||||
const _upDatesTimePicker = ref({
|
const _upDatesTimePicker = ref({
|
||||||
refId: null,
|
refId: null,
|
||||||
show: false,
|
show: false,
|
||||||
|
|
@ -105,7 +112,7 @@ const openUpDatesTimePicker = (value, minDate, title) => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
defineExpose({ openEvaluatePop, openReservationPopup, openUpDatesTimePicker })
|
defineExpose({ openEvaluatePop, openReservationPopup, openUpDatesTimePicker,openQianDaoPop })
|
||||||
|
|
||||||
|
|
||||||
// onMounted(() => {
|
// onMounted(() => {
|
||||||
|
|
|
||||||
329
components/com/page/qiandao-popup.vue
Normal file
329
components/com/page/qiandao-popup.vue
Normal file
|
|
@ -0,0 +1,329 @@
|
||||||
|
<template>
|
||||||
|
<uni-popup ref="_qiandaoPopupRef" type="center">
|
||||||
|
|
||||||
|
<view class="popup-container">
|
||||||
|
<view class="column popup-inner">
|
||||||
|
<view class="popup-title">到场确认</view>
|
||||||
|
<view style="height:40rpx;"></view>
|
||||||
|
<view class="popup-h1">请确认预约参与者是否已到场</view>
|
||||||
|
<view v-if="currentEvaluate.length > 0" class="participants-list">
|
||||||
|
<view v-for="(item, index) in currentEvaluate" :key="index" class="participant-item">
|
||||||
|
<view class="participant-info">
|
||||||
|
<image :src="item.avatarImage || '/static/default-avatar.png'" class="participant-avatar"
|
||||||
|
mode="aspectFill" />
|
||||||
|
<text class="participant-name">{{ item.userName }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="attendance-btn" :class="{ 'attended': item.isAttended }"
|
||||||
|
@click="toggleAttendance(item, index)">
|
||||||
|
<text class="attendance-text">
|
||||||
|
{{ item.isAttended ? '已到场' : '未到场' }}
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view style="height: 5rpx;"></view>
|
||||||
|
<view style="display: flex;justify-content: center;align-items: center;">
|
||||||
|
<view
|
||||||
|
style="background: #00AC4E;box-shadow: 0rpx 0rpx 10rpx 2rpx rgba(0,0,0,0.25);border-radius: 16rpx 16rpx 16rpx 16rpx;width: 478rpx;height: 70rpx;display: flex;justify-content: center;align-items: center;"
|
||||||
|
@click="submit">
|
||||||
|
<text
|
||||||
|
style="font-family: PingFang SC, PingFang SC;font-weight: 500;font-size: 28rpx;color: #FFFFFF;font-style: normal;text-transform: none;">提交</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</uni-popup>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {
|
||||||
|
ref,
|
||||||
|
computed
|
||||||
|
} from 'vue'
|
||||||
|
import {
|
||||||
|
sqInterface
|
||||||
|
} from '@/common/server/interface/sq.js'
|
||||||
|
import {
|
||||||
|
showModalConfirm
|
||||||
|
} from '@/common/utils'
|
||||||
|
import {
|
||||||
|
userInfo
|
||||||
|
} from '@/common/server/user.js'
|
||||||
|
const _qiandaoPopupRef = ref(null)
|
||||||
|
const evaluateList = ref([])
|
||||||
|
const currentReservation = ref(null)
|
||||||
|
|
||||||
|
const currentEvaluate = ref([])
|
||||||
|
|
||||||
|
// 计算是否全部到场
|
||||||
|
const isAllAttended = computed(() => {
|
||||||
|
if (currentEvaluate.value.length === 0) return false
|
||||||
|
return currentEvaluate.value.every(item => item.isAttended)
|
||||||
|
})
|
||||||
|
|
||||||
|
const show = async (reservation) => {
|
||||||
|
currentReservation.value = reservation
|
||||||
|
|
||||||
|
// 初始化参与者列表,过滤掉当前用户
|
||||||
|
if (reservation && reservation.participants) {
|
||||||
|
currentEvaluate.value = reservation.participants
|
||||||
|
.filter(item => item.user_id != userInfo.value.id)
|
||||||
|
.map(item => ({
|
||||||
|
...item,
|
||||||
|
isAttended: item.isAttended || true // 初始化签到状态
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
|
currentEvaluate.value = []
|
||||||
|
}
|
||||||
|
evaluateList.value = []
|
||||||
|
_qiandaoPopupRef.value.open()
|
||||||
|
}
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
_qiandaoPopupRef.value.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 切换参与者签到状态
|
||||||
|
const toggleAttendance = (participant, index) => {
|
||||||
|
participant.isAttended = !participant.isAttended
|
||||||
|
console.log('切换签到状态:', participant.userName, participant.isAttended)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置全部到场
|
||||||
|
const setAllAttended = () => {
|
||||||
|
currentEvaluate.value.forEach(item => {
|
||||||
|
item.isAttended = true
|
||||||
|
})
|
||||||
|
console.log('设置全部到场')
|
||||||
|
}
|
||||||
|
|
||||||
|
const submit = async () => {
|
||||||
|
var isSuccess = await showModalConfirm("签到提示", "确定提交签到数据吗?签到后将无法更改数据!");
|
||||||
|
if (!isSuccess) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uni.showLoading({
|
||||||
|
title: '签到提交中...'
|
||||||
|
})
|
||||||
|
const payload = {
|
||||||
|
reservation_id: currentReservation.value.id,
|
||||||
|
attendeds: currentEvaluate.value.map(item => {
|
||||||
|
return {
|
||||||
|
user_id: item.user_id,
|
||||||
|
isAttended: item.isAttended
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
console.log('签到数据:', payload)
|
||||||
|
|
||||||
|
const result = await sqInterface.checkInReservation(payload)
|
||||||
|
uni.hideLoading()
|
||||||
|
|
||||||
|
if (result.success) {
|
||||||
|
uni.showToast({
|
||||||
|
title: result.message || '签到提交成功',
|
||||||
|
icon: 'success'
|
||||||
|
})
|
||||||
|
close()
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: result.message || '签到提交失败',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
show,
|
||||||
|
close
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.popup-container {
|
||||||
|
width: 700rpx;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
height: 830rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-inner {
|
||||||
|
width: 90%;
|
||||||
|
height: 700rpx;
|
||||||
|
margin: 0 auto 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-title {
|
||||||
|
font-size: 26rpx;
|
||||||
|
margin-top: 30rpx;
|
||||||
|
text-align: center;
|
||||||
|
font-family: PingFang SC, PingFang SC;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 40rpx;
|
||||||
|
color: #000000;
|
||||||
|
font-style: normal;
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-h1 {
|
||||||
|
width: 476rpx;
|
||||||
|
height: 44rpx;
|
||||||
|
font-family: PingFang SC, PingFang SC;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #000000;
|
||||||
|
text-align: left;
|
||||||
|
font-style: normal;
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 参与者列表样式 */
|
||||||
|
.participants-list {
|
||||||
|
margin-top: 20rpx;
|
||||||
|
max-height: 300rpx;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.participant-item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 20rpx 0;
|
||||||
|
border-bottom: 1rpx solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.participant-item:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.participant-info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.participant-avatar {
|
||||||
|
width: 60rpx;
|
||||||
|
height: 60rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-right: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.participant-name {
|
||||||
|
font-family: PingFang SC, PingFang SC;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.attendance-btn {
|
||||||
|
width: 120rpx;
|
||||||
|
height: 50rpx;
|
||||||
|
border-radius: 25rpx;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
border: 2rpx solid #ddd;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.attendance-btn.attended {
|
||||||
|
background-color: #00AC4E;
|
||||||
|
border-color: #00AC4E;
|
||||||
|
}
|
||||||
|
|
||||||
|
.attendance-text {
|
||||||
|
font-family: PingFang SC, PingFang SC;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.attendance-btn.attended .attendance-text {
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 全部到场按钮样式 */
|
||||||
|
.all-attended-btn {
|
||||||
|
background: #6BB08A;
|
||||||
|
box-shadow: 0rpx 0rpx 10rpx 2rpx rgba(0, 0, 0, 0.25);
|
||||||
|
border-radius: 16rpx;
|
||||||
|
width: 180rpx;
|
||||||
|
height: 70rpx;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.all-attended-btn.all-attended {
|
||||||
|
background: #00AC4E;
|
||||||
|
}
|
||||||
|
|
||||||
|
.all-attended-text {
|
||||||
|
font-family: PingFang SC, PingFang SC;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #FFFFFF;
|
||||||
|
font-style: normal;
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -6,7 +6,8 @@
|
||||||
<text class="popup-title">牌友评价</text>
|
<text class="popup-title">牌友评价</text>
|
||||||
<text class="popup-desc">请对每位牌友进行评价</text>
|
<text class="popup-desc">请对每位牌友进行评价</text>
|
||||||
|
|
||||||
<view class="row panel-box" v-if="currentEvaluate" @click="index = 0, showPicker = true">
|
<view class="row panel-box" style="padding-left: 10rpx;" v-if="currentEvaluate"
|
||||||
|
@click="index = 0, showPicker = true">
|
||||||
{{ currentEvaluate.userName }}
|
{{ currentEvaluate.userName }}
|
||||||
<image src="/static/down.png" class="down-icon" mode=""></image>
|
<image src="/static/down.png" class="down-icon" mode=""></image>
|
||||||
</view>
|
</view>
|
||||||
|
|
@ -180,6 +181,7 @@ defineExpose({ show, close })
|
||||||
.mt-20 {
|
.mt-20 {
|
||||||
margin-top: 20rpx;
|
margin-top: 20rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mt-10 {
|
.mt-10 {
|
||||||
margin-top: 10rpx;
|
margin-top: 10rpx;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,12 @@
|
||||||
<text class="row-text ml-20">已约牌友:</text>
|
<text class="row-text ml-20">已约牌友:</text>
|
||||||
<image v-for="(participant, pIndex) in reservation.participants" :key="pIndex"
|
<image v-for="(participant, pIndex) in reservation.participants" :key="pIndex"
|
||||||
:src="participant.avatarImage || '/static/default-avatar.png'" class="avatar" mode="aspectFill" />
|
:src="participant.avatarImage || '/static/default-avatar.png'" class="avatar" mode="aspectFill" />
|
||||||
<view class="center evaluate-btn" v-if="reservation.status == 2" @click.stop="onEvaluate()">
|
<view class="center evaluate-btn" v-if="reservation.status == 3" @click.stop="onEvaluate()">
|
||||||
<text class="evaluate-btn-text">牌友评价</text>
|
<text class="evaluate-btn-text">牌友评价</text>
|
||||||
</view>
|
</view>
|
||||||
|
<view class="center evaluate-btn" v-else-if="isQianDaoVisible" @click.stop="onQianDao()">
|
||||||
|
<text class="evaluate-btn-text">签到</text>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="mt-20" style="height: 10rpx;"></view>
|
<view class="mt-20" style="height: 10rpx;"></view>
|
||||||
</view>
|
</view>
|
||||||
|
|
@ -33,7 +36,7 @@
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
// 仅负责展示与触发评价事件
|
// 仅负责展示与触发评价事件
|
||||||
import { inject } from 'vue'
|
import { inject, computed } from 'vue'
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
reservation: {
|
reservation: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
|
@ -46,6 +49,54 @@ const onEvaluate = () => {
|
||||||
emit('evaluate', props.reservation)
|
emit('evaluate', props.reservation)
|
||||||
// openEvaluatePop?.(props.reservation)
|
// openEvaluatePop?.(props.reservation)
|
||||||
}
|
}
|
||||||
|
const onQianDao = () => {
|
||||||
|
console.log(" props.reservation", props.reservation);
|
||||||
|
emit('qianDao', props.reservation)
|
||||||
|
// TODO: 实现签到逻辑
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算属性:判断是否显示签到按钮
|
||||||
|
const isQianDaoVisible = computed(() => {
|
||||||
|
const item = props.reservation;
|
||||||
|
console.log("计算签到按钮显示状态", item);
|
||||||
|
|
||||||
|
// 检查预约状态:1-待开始,2-进行中
|
||||||
|
if (item.status !== 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查用户权限:role为1表示有权限
|
||||||
|
if (item.role !== 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查开始时间是否存在
|
||||||
|
if (!item.start_time) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 检查结束时间是否存在
|
||||||
|
if (!item.end_time) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const now = new Date();
|
||||||
|
const startTime = new Date(item.start_time);
|
||||||
|
const endTime = new Date(item.end_time);
|
||||||
|
const tenMinutes = 10 * 60 * 1000; // 10分钟的毫秒数
|
||||||
|
|
||||||
|
// 计算时间差
|
||||||
|
const timeToStart = startTime.getTime() - now.getTime();
|
||||||
|
const timeToEnd = endTime.getTime() - now.getTime();
|
||||||
|
|
||||||
|
// 签到条件:
|
||||||
|
// 1. 开始时间前10分钟内可以签到
|
||||||
|
// 2. 在结束时间内也可以签到
|
||||||
|
// 3. 结束时间外无法签到
|
||||||
|
const canSignBeforeStart = timeToStart <= tenMinutes && timeToStart > 0; // 开始前10分钟内
|
||||||
|
const canSignDuringEvent = timeToStart <= 0 && timeToEnd > 0; // 活动进行中(开始后,结束前)
|
||||||
|
|
||||||
|
return canSignBeforeStart || canSignDuringEvent;
|
||||||
|
})
|
||||||
|
|
||||||
const formatTimeRange = (startTime, endTime) => {
|
const formatTimeRange = (startTime, endTime) => {
|
||||||
if (!startTime || !endTime) return '时间未设置'
|
if (!startTime || !endTime) return '时间未设置'
|
||||||
|
|
@ -57,11 +108,11 @@ const formatTimeRange = (startTime, endTime) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const getStatusText = (status) => {
|
const getStatusText = (status) => {
|
||||||
const map = { 0: '待开始', 1: '进行中', 2: '已结束', 3: "已取消" }
|
const map = { 0: '组局中', 1: '待开始', 2: '进行中', 3: "已结束", 4: "已取消" }
|
||||||
return map[status] || '未知状态'
|
return map[status] || '未知状态'
|
||||||
}
|
}
|
||||||
const getStatusStyle = (status) => {
|
const getStatusStyle = (status) => {
|
||||||
const map = { 0: 'color: #1989FA', 1: 'color: #999', 2: 'color: #999', 3: 'color: #999' }
|
const map = { 0: 'color: #999', 1: 'color: #1989FA', 2: 'color: #1989FA', 3: 'color: #999', 4: 'color: #999' }
|
||||||
return map[status] || 'color: #999'
|
return map[status] || 'color: #999'
|
||||||
}
|
}
|
||||||
const openReservationPopup = () => {
|
const openReservationPopup = () => {
|
||||||
|
|
|
||||||
|
|
@ -137,13 +137,13 @@ const statusName = computed(() => {
|
||||||
const count = joinPerson.length
|
const count = joinPerson.length
|
||||||
|
|
||||||
if (status === 0) {
|
if (status === 0) {
|
||||||
return personCount === count ? "待开始" : "组局中..."
|
return "组局中..."
|
||||||
} else if (status === 1) {
|
} else if (status === 1) {
|
||||||
return "进行中"
|
return "待开始"
|
||||||
} else if (status === 2) {
|
} else if (status === 2) {
|
||||||
return "已结束"
|
return "进行中"
|
||||||
} else if (status === 3) {
|
} else if (status === 3) {
|
||||||
return "取消"
|
return "已结束"
|
||||||
}
|
}
|
||||||
return "其它"
|
return "其它"
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name" : "mahjong_group",
|
"name" : "mahjong_group",
|
||||||
"appid" : "__UNI__60D9924",
|
"appid" : "__UNI__6A23109",
|
||||||
"description" : "",
|
"description" : "",
|
||||||
"versionName" : "1.0.0",
|
"versionName" : "1.0.0",
|
||||||
"versionCode" : "100",
|
"versionCode" : "100",
|
||||||
|
|
|
||||||
12
pages.json
12
pages.json
|
|
@ -85,6 +85,18 @@
|
||||||
"navigationBarTitleText": "",
|
"navigationBarTitleText": "",
|
||||||
"navigationStyle": "custom"
|
"navigationStyle": "custom"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/other/payment-records",
|
||||||
|
"style": {
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/other/faq",
|
||||||
|
"style": {
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"globalStyle": {
|
"globalStyle": {
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,7 @@ import TagSelect from '@/components/com/appointment/tag-select.vue'
|
||||||
import ComAppointmentPickerData from '@/components/com/appointment/picker-data.vue'
|
import ComAppointmentPickerData from '@/components/com/appointment/picker-data.vue'
|
||||||
import ComAppointmentRadioSelect from '@/components/com/appointment/radio-select.vue'
|
import ComAppointmentRadioSelect from '@/components/com/appointment/radio-select.vue'
|
||||||
import {
|
import {
|
||||||
getReservationRoomList, addSQReservation, cancelReservation
|
getReservationRoomList, addSQReservation, cancelReservation, canCreateSQReservation
|
||||||
} from '@/common/server/interface/sq'
|
} from '@/common/server/interface/sq'
|
||||||
const _containerBase = ref(null)
|
const _containerBase = ref(null)
|
||||||
// 年龄选择器状态
|
// 年龄选择器状态
|
||||||
|
|
@ -497,6 +497,23 @@ const submitReservation = async () => {
|
||||||
// 将玩法类型和具体规则从数字转换为字符串
|
// 将玩法类型和具体规则从数字转换为字符串
|
||||||
submitData.game_type = getGameTypeText(submitData.game_type);
|
submitData.game_type = getGameTypeText(submitData.game_type);
|
||||||
submitData.game_rule = getGameRuleText(submitData.game_rule);
|
submitData.game_rule = getGameRuleText(submitData.game_rule);
|
||||||
|
var important_data = "";
|
||||||
|
if (subscribeMessage.result != null) {
|
||||||
|
important_data = JSON.stringify(subscribeMessage.result);
|
||||||
|
}
|
||||||
|
submitData.important_data = important_data;
|
||||||
|
// 检测是否能创建预约 ,如果不能创建则提示并中断
|
||||||
|
const canCreateRes = await canCreateSQReservation(submitData)
|
||||||
|
if (!canCreateRes || canCreateRes.canCreate !== true) {
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.showToast({
|
||||||
|
title: (canCreateRes && canCreateRes.message) ? canCreateRes.message : '当前条件不可创建预约',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var resPay = null;
|
var resPay = null;
|
||||||
if (submitData.deposit_fee > 0) {
|
if (submitData.deposit_fee > 0) {
|
||||||
|
|
@ -509,13 +526,12 @@ const submitReservation = async () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
subscribeMessage.result.paymentId = resPay.paymentId;
|
subscribeMessage.result.paymentId = resPay.paymentId;
|
||||||
|
if (subscribeMessage.result != null) {
|
||||||
|
important_data = JSON.stringify(subscribeMessage.result);
|
||||||
|
}
|
||||||
|
submitData.important_data = important_data;
|
||||||
}
|
}
|
||||||
console.log('提交预约数据:', submitData)
|
|
||||||
var important_data = "";
|
|
||||||
if (subscribeMessage.result != null) {
|
|
||||||
important_data = JSON.stringify(subscribeMessage.result);
|
|
||||||
}
|
|
||||||
submitData.important_data = important_data;
|
|
||||||
// TODO: 调用后端API提交预约
|
// TODO: 调用后端API提交预约
|
||||||
// 调用后端API提交预约
|
// 调用后端API提交预约
|
||||||
const result = await addSQReservation(submitData)
|
const result = await addSQReservation(submitData)
|
||||||
|
|
|
||||||
|
|
@ -183,7 +183,9 @@ const queryList = (pageNo, pageSize) => {
|
||||||
|
|
||||||
// 手动刷新
|
// 手动刷新
|
||||||
const refreshData = () => {
|
const refreshData = () => {
|
||||||
pagePaging.value.reload()
|
if (pagePaging.value != null) {
|
||||||
|
pagePaging.value.reload()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 清空数据
|
// 清空数据
|
||||||
|
|
@ -226,7 +228,9 @@ onMounted(() => {
|
||||||
// 初始化模拟数据
|
// 初始化模拟数据
|
||||||
|
|
||||||
})
|
})
|
||||||
|
onShow(async () => {
|
||||||
|
refreshData();
|
||||||
|
});
|
||||||
onLoad(async () => {
|
onLoad(async () => {
|
||||||
if (!homeData.value) preloadHomeData();
|
if (!homeData.value) preloadHomeData();
|
||||||
if (!configData.value) preloadConfigData();
|
if (!configData.value) preloadConfigData();
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@
|
||||||
<view class="column " style="width: 90%;margin: 0 auto;" v-for="(item, index) in myUseReservation"
|
<view class="column " style="width: 90%;margin: 0 auto;" v-for="(item, index) in myUseReservation"
|
||||||
:key="index">
|
:key="index">
|
||||||
<reservation-item :reservation="item" @evaluate="_containerBase.openEvaluatePop"
|
<reservation-item :reservation="item" @evaluate="_containerBase.openEvaluatePop"
|
||||||
@click="_containerBase.openReservationPopup" />
|
@click="_containerBase.openReservationPopup" @qianDao="_containerBase.openQianDaoPop" />
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view v-if="userInfo != null" class="column"
|
<view v-if="userInfo != null" class="column"
|
||||||
|
|
@ -99,128 +99,19 @@
|
||||||
|
|
||||||
<text style="font-size: 30rpx; margin-top: 26rpx; margin-left: 36rpx;">常用功能</text>
|
<text style="font-size: 30rpx; margin-top: 26rpx; margin-left: 36rpx;">常用功能</text>
|
||||||
|
|
||||||
<view class="row" style=" justify-content: space-between; margin: 40rpx;">
|
<view class="row" style="flex-wrap: wrap; justify-content: flex-start; margin: 40rpx;">
|
||||||
|
<view class="column" v-for="item in commonActions" :key="item.label"
|
||||||
<view class="column" @click="toAppointment()" style="align-items: center;">
|
@click="handleCommonAction(item)"
|
||||||
<image src="@@:app/static/appoin_record.png" style="width: 50rpx; height: 50rpx;" mode="">
|
style="width: 25%; align-items: center; margin-bottom: 30rpx;">
|
||||||
</image>
|
<image :src="item.icon" style="width: 50rpx; height: 50rpx;" mode=""></image>
|
||||||
<text style="font-size: 24rpx; margin-top: 20rpx;">预约记录</text>
|
<text style="font-size: 24rpx; margin-top: 20rpx;">{{ item.label }}</text>
|
||||||
</view>
|
</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>
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
</container-base>
|
</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>
|
</template>
|
||||||
|
|
@ -231,6 +122,7 @@ import {
|
||||||
loadUserInfo,
|
loadUserInfo,
|
||||||
isLogin
|
isLogin
|
||||||
} from '@/common/server/user'
|
} from '@/common/server/user'
|
||||||
|
import { navigateToAgreement } from '@/common/system/router'
|
||||||
import { sqInterface } from '@/common/server/interface/sq'
|
import { sqInterface } from '@/common/server/interface/sq'
|
||||||
import ReservationEvaluate from '@/components/com/page/reservation-evaluate.vue'
|
import ReservationEvaluate from '@/components/com/page/reservation-evaluate.vue'
|
||||||
import ContainerBase from '@/components/com/page/container-base.vue'
|
import ContainerBase from '@/components/com/page/container-base.vue'
|
||||||
|
|
@ -242,7 +134,6 @@ import {
|
||||||
import ReservationItem from '@/components/com/page/reservation-item.vue'
|
import ReservationItem from '@/components/com/page/reservation-item.vue'
|
||||||
// 响应式数据
|
// 响应式数据
|
||||||
const rateValue = ref(4.5)
|
const rateValue = ref(4.5)
|
||||||
const infoPop = ref(null)
|
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const _containerBase = ref(null)
|
const _containerBase = ref(null)
|
||||||
|
|
||||||
|
|
@ -250,61 +141,58 @@ const _containerBase = ref(null)
|
||||||
// 当前预约信息
|
// 当前预约信息
|
||||||
const currentAppointment = ref(null)
|
const currentAppointment = ref(null)
|
||||||
|
|
||||||
// 预约详情数据
|
|
||||||
const appointmentDetail = reactive({
|
|
||||||
organizer: {
|
|
||||||
name: '苏家辉',
|
// 常用功能 - 动态项
|
||||||
avatar: '',
|
const commonActions = [
|
||||||
isBlacklisted: false
|
{ label: '预约记录', icon: '@@:app/static/me/wodd.png', action: 'appointment' },
|
||||||
},
|
{ label: '订单记录', icon: '@@:app/static/me/wodd.png', action: 'payment' },
|
||||||
participants: [{
|
{ label: '常见问题', icon: '@@:app/static/me/cjwt.png', action: 'faq' },
|
||||||
name: '树下的胖子',
|
{ label: '黑名单', icon: '@@:app/static/me/hmd.png', action: 'blacklist' },
|
||||||
avatar: '',
|
{ label: '联系我们', icon: '@@:app/static/me/lxwm.png', action: 'contact' },
|
||||||
isBlacklisted: true
|
|
||||||
},
|
]
|
||||||
{
|
|
||||||
name: '张三',
|
const handleCommonAction = (item) => {
|
||||||
avatar: '',
|
switch (item.action) {
|
||||||
isBlacklisted: false
|
case 'appointment':
|
||||||
},
|
toAppointment();
|
||||||
{
|
break;
|
||||||
name: '李四',
|
case 'blacklist':
|
||||||
avatar: '',
|
toBlacklist();
|
||||||
isBlacklisted: false
|
break;
|
||||||
|
case 'faq':
|
||||||
|
if (userInfo.value == null) {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/me/login'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/other/faq'
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'payment':
|
||||||
|
if (userInfo.value == null) {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/me/login'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/other/payment-records'
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'contact':
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/other/agreement?type=about'
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
uni.showToast({ title: '敬请期待', icon: 'none' });
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
],
|
|
||||||
timeInfo: {
|
|
||||||
startTime: '2025/08/27 15:30',
|
|
||||||
endTime: '2025/08/27 17:30',
|
|
||||||
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 = () => {
|
const toAppointment = () => {
|
||||||
|
|
@ -380,8 +268,10 @@ const loadCurrentAppointment = async () => {
|
||||||
var res = await sqInterface.getMyUseReservation();
|
var res = await sqInterface.getMyUseReservation();
|
||||||
console.log("getMyUseReservation", res);
|
console.log("getMyUseReservation", res);
|
||||||
if (res != null) {
|
if (res != null) {
|
||||||
myUseReservation.value = myUseReservation.value.splice(0, myUseReservation.value.length);
|
// console.log("myUseReservation.value.length", myUseReservation.value.length);
|
||||||
myUseReservation.value.push(...res);
|
// myUseReservation.value = myUseReservation.value.splice(0, myUseReservation.value.length);
|
||||||
|
// console.log("myUseReservation.value.length", myUseReservation.value.length);
|
||||||
|
myUseReservation.value = res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -390,19 +280,16 @@ const loadCurrentAppointment = async () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 组件挂载时加载数据
|
|
||||||
onMounted(() => {
|
|
||||||
loadCurrentAppointment()
|
|
||||||
})
|
|
||||||
|
|
||||||
// 页面显示时重新加载数据(用于登录后刷新)
|
// 页面显示时重新加载数据(用于登录后刷新)
|
||||||
onShow(() => {
|
onShow(async () => {
|
||||||
// 检查是否有登录状态
|
// 检查是否有登录状态
|
||||||
// getUserInfoData();
|
// getUserInfoData();
|
||||||
|
loadCurrentAppointment();
|
||||||
|
await loadUserInfo();
|
||||||
})
|
})
|
||||||
onLoad(async () => {
|
onLoad(async () => {
|
||||||
await loadUserInfo();
|
|
||||||
|
|
||||||
|
//loadCurrentAppointment();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<view class="content column">
|
<view class="content column">
|
||||||
|
|
||||||
<z-paging ref="pagePaging" v-model="repList" @query="queryList" :refresher-enabled="true"
|
<z-paging ref="pagePaging" v-model="repList" @query="queryList" :refresher-enabled="true"
|
||||||
:loading-more-enabled="true" :auto="true" :empty-view-text="'暂无记录'"
|
: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;">
|
:empty-view-img="'@@:app/static/index/no.png'" style="flex: 1; width: 100%; margin-top: 30rpx;">
|
||||||
|
|
@ -25,7 +24,7 @@
|
||||||
:key="index">
|
:key="index">
|
||||||
<view class="column reservation-inner">
|
<view class="column reservation-inner">
|
||||||
<view class="row title title-row">
|
<view class="row title title-row">
|
||||||
<view class="title">{{ item.title || '记录' }}</view>reservation-box
|
<view class="title">{{ item.title || '记录' }}</view>
|
||||||
<view
|
<view
|
||||||
:class="['value-text', Number(item.reputation_value) >= 0 ? 'value-pos' : 'value-neg']">
|
:class="['value-text', Number(item.reputation_value) >= 0 ? 'value-pos' : 'value-neg']">
|
||||||
{{ formatValue(item.reputation_value) }}
|
{{ formatValue(item.reputation_value) }}
|
||||||
|
|
|
||||||
|
|
@ -2,19 +2,29 @@
|
||||||
<view>
|
<view>
|
||||||
<com-page-container :title="title" showBack>
|
<com-page-container :title="title" showBack>
|
||||||
<view class="agreement-container">
|
<view class="agreement-container">
|
||||||
<rich-text v-if="article != null" :nodes="article.contentBody" class="agreement-content"></rich-text>
|
<rich-text v-if="article != null" :nodes="safeHtml" class="agreement-content"></rich-text>
|
||||||
</view>
|
</view>
|
||||||
</com-page-container>
|
</com-page-container>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, reactive } from 'vue'
|
import { ref, reactive, computed } from 'vue'
|
||||||
import { getArticleDetail } from '@/common/server/interface/article'
|
import { getArticleDetail } from '@/common/server/interface/article'
|
||||||
import { getConfigData } from '@/common/server/config'
|
import { getConfigData } from '@/common/server/config'
|
||||||
let title = ref('')
|
let title = ref('')
|
||||||
const article = ref(null)
|
const article = ref(null)
|
||||||
let configData = null;
|
let configData = null;
|
||||||
|
|
||||||
|
// 将不被 rich-text 支持的标签进行替换,并为缺失样式的图片补充样式
|
||||||
|
const safeHtml = computed(() => {
|
||||||
|
const html = article.value?.contentBody || ''
|
||||||
|
return html
|
||||||
|
.replace(/<figure\b[^>]*>/gi, '<div>')
|
||||||
|
.replace(/<\/figure>/gi, '</div>')
|
||||||
|
// 为没有 style 的 img 补充样式,避免超出
|
||||||
|
.replace(/<img(?![^>]*\bstyle=)([^>]*?)>/gi, '<img$1 style="max-width:100%;height:auto;display:block;">')
|
||||||
|
})
|
||||||
onLoad(async (option) => {
|
onLoad(async (option) => {
|
||||||
console.log(option);
|
console.log(option);
|
||||||
if (configData == null) {
|
if (configData == null) {
|
||||||
|
|
@ -24,11 +34,14 @@ onLoad(async (option) => {
|
||||||
|
|
||||||
if (option.type != null) {
|
if (option.type != null) {
|
||||||
if (option.type == 'userAgreement') {
|
if (option.type == 'userAgreement') {
|
||||||
title = "用户协议";
|
title.value = "用户协议";
|
||||||
article.value = await getArticleDetail(configData.config.userAgreementId)
|
article.value = await getArticleDetail(configData.config.userAgreementId)
|
||||||
} else if (option.type == 'privacyPolicy') {
|
} else if (option.type == 'privacyPolicy') {
|
||||||
title = "隐私协议";
|
title.value = "隐私协议";
|
||||||
article.value = await getArticleDetail(configData.config.privacyPolicyId)
|
article.value = await getArticleDetail(configData.config.privacyPolicyId)
|
||||||
|
} else if (option.type == 'about') {
|
||||||
|
title.value = "关于我们";
|
||||||
|
article.value = await getArticleDetail(configData.config.aboutArticleId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
||||||
232
pages/other/faq.vue
Normal file
232
pages/other/faq.vue
Normal file
|
|
@ -0,0 +1,232 @@
|
||||||
|
<template>
|
||||||
|
<view class="content column">
|
||||||
|
<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="list-wrapper">
|
||||||
|
<view v-if="loading" class="tip-text">加载中...</view>
|
||||||
|
<view v-else>
|
||||||
|
<view v-if="errorMsg" class="tip-text">{{ errorMsg }}</view>
|
||||||
|
<template v-else>
|
||||||
|
<view v-if="commonList.length" class="section">
|
||||||
|
<view class="section-title">常见问题</view>
|
||||||
|
<view class="column list-inner">
|
||||||
|
<view class="reservation-item reservation-box" v-for="(item, index) in commonList" :key="item.id || index">
|
||||||
|
<view class="column reservation-inner">
|
||||||
|
<view class="row title title-row">
|
||||||
|
<view class="title">{{ item.title }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="row row-text row-center mt-20">
|
||||||
|
<text class="ml-20">{{ item.description }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view v-if="serviceList.length" class="section">
|
||||||
|
<view class="section-title">服务问题</view>
|
||||||
|
<view class="column list-inner">
|
||||||
|
<view class="reservation-item reservation-box" v-for="(item, index) in serviceList" :key="item.id || index">
|
||||||
|
<view class="column reservation-inner">
|
||||||
|
<view class="row title title-row">
|
||||||
|
<view class="title">{{ item.title }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="row row-text row-center mt-20">
|
||||||
|
<text class="ml-20">{{ item.description }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view v-if="deliveryList.length" class="section">
|
||||||
|
<view class="section-title">订单问题</view>
|
||||||
|
<view class="column list-inner">
|
||||||
|
<view class="reservation-item reservation-box" v-for="(item, index) in deliveryList" :key="item.id || index">
|
||||||
|
<view class="column reservation-inner">
|
||||||
|
<view class="row title title-row">
|
||||||
|
<view class="title">{{ item.title }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="row row-text row-center mt-20">
|
||||||
|
<text class="ml-20">{{ item.description }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view v-if="!commonList.length && !serviceList.length && !deliveryList.length" class="tip-text">暂无内容</view>
|
||||||
|
</template>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted } from 'vue'
|
||||||
|
import { getServiceDescription } from '@/common/server/interface/common.js'
|
||||||
|
|
||||||
|
const statusBarHeight = ref(uni.getSystemInfoSync().statusBarHeight);
|
||||||
|
|
||||||
|
const loading = ref(true)
|
||||||
|
const errorMsg = ref('')
|
||||||
|
const commonList = ref([])
|
||||||
|
const serviceList = ref([])
|
||||||
|
const deliveryList = ref([])
|
||||||
|
|
||||||
|
const fetchData = async () => {
|
||||||
|
try {
|
||||||
|
loading.value = true
|
||||||
|
errorMsg.value = ''
|
||||||
|
const data = await getServiceDescription()
|
||||||
|
if (data) {
|
||||||
|
const filterSort = (arr = []) => arr
|
||||||
|
.filter(i => i && i.isShow)
|
||||||
|
.sort((a, b) => Number(a.sortId || 0) - Number(b.sortId || 0))
|
||||||
|
commonList.value = filterSort(data.commonQuestion || [])
|
||||||
|
serviceList.value = filterSort(data.service || [])
|
||||||
|
deliveryList.value = filterSort(data.delivery || [])
|
||||||
|
} else {
|
||||||
|
errorMsg.value = '获取失败'
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('获取服务与说明失败:', e)
|
||||||
|
errorMsg.value = '获取失败'
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(fetchData)
|
||||||
|
|
||||||
|
const goBack = () => {
|
||||||
|
uni.navigateBack({
|
||||||
|
delta: 1
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
overflow-y: auto;
|
||||||
|
margin-top: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-inner {
|
||||||
|
width: 90%;
|
||||||
|
margin: 0 auto 0;
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section {
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
width: 90%;
|
||||||
|
margin: 0 auto 20rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #322A2A;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
word-break: break-all;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tip-text {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
color: #999;
|
||||||
|
font-size: 26rpx;
|
||||||
|
margin-top: 60rpx;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
194
pages/other/payment-records.vue
Normal file
194
pages/other/payment-records.vue
Normal file
|
|
@ -0,0 +1,194 @@
|
||||||
|
<template>
|
||||||
|
<view class="content column">
|
||||||
|
<z-paging
|
||||||
|
ref="pagePaging"
|
||||||
|
v-model="orderList"
|
||||||
|
@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>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<view class="list-wrapper">
|
||||||
|
<view class="column list-inner">
|
||||||
|
<view class="reservation-item reservation-box" v-for="(item, index) in orderList" :key="index">
|
||||||
|
<view class="column reservation-inner">
|
||||||
|
<view class="row title title-row">
|
||||||
|
<view class="title">{{ item.title || '订单' }}</view>
|
||||||
|
<view :class="['status-text', statusClass(item)]">{{ item.is_refund_text || '' }}</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="row row-text row-center mt-20">
|
||||||
|
<text class="label">订单号:</text>
|
||||||
|
<text class="value">{{ item.paymentId || '' }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="row row-text row-center mt-10">
|
||||||
|
<text class="label">加入时间:</text>
|
||||||
|
<text class="value">{{ item.join_time || '' }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="row row-text row-center mt-10" v-if="item.status === 1">
|
||||||
|
<text class="label">预约状态:</text>
|
||||||
|
<text class="value status-quit">已退出</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</z-paging>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } 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 orderList = ref([])
|
||||||
|
const pagePaging = ref(null)
|
||||||
|
|
||||||
|
const queryList = async (pageNo, pageSize) => {
|
||||||
|
try {
|
||||||
|
const data = await sqInterface.getPaymentRecords(pageNo, pageSize) || []
|
||||||
|
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 statusClass = (item) => {
|
||||||
|
switch (Number(item?.is_refund)) {
|
||||||
|
case 1: return 'status-wait-pay'
|
||||||
|
case 2: return 'status-paid'
|
||||||
|
case 3: return 'status-wait-refund'
|
||||||
|
case 4: return 'status-refunded'
|
||||||
|
default: return ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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-10 { margin-top: 10rpx; }
|
||||||
|
.mt-20 { margin-top: 20rpx; }
|
||||||
|
|
||||||
|
.label { color: #888; }
|
||||||
|
.value { color: #333; }
|
||||||
|
|
||||||
|
.status-text { font-size: 26rpx; }
|
||||||
|
.status-wait-pay { color: #e67e22; }
|
||||||
|
.status-paid { color: #2ecc71; }
|
||||||
|
.status-wait-refund { color: #3498db; }
|
||||||
|
.status-refunded { color: #7f8c8d; }
|
||||||
|
.status-quit { color: #e74c3c; }
|
||||||
|
</style>
|
||||||
Loading…
Reference in New Issue
Block a user