初始化

This commit is contained in:
2024-07-10 13:50:01 +08:00
commit e30966c6c5
1073 changed files with 143076 additions and 0 deletions
+294
View File
@@ -0,0 +1,294 @@
<template>
<view class="page">
<!-- 顶部距离 -->
<view class="header" :style="'margin-top: ' + statusBarHeight + 'px'"></view>
<!-- 用户信息 -->
<ws-admin-card :merchantList="merchantList" :merchantId="merchantId" :data="userInfo" :is-login="isLogin" @openLogin="openLogin" />
<block v-if="hideTools">
<uni-card :border="false" :padding="'18px 8px'">
<uv-skeleton rows="2" :loading="hideTools" :title="false">
</uv-skeleton>
</uni-card>
<uni-card :border="false" :padding="'18px 8px'">
<uv-skeleton rows="9" :loading="hideTools" :title="false">
</uv-skeleton>
</uni-card>
</block>
<block v-else>
<!-- 收藏|关注|足迹|作品 -->
<!-- <ws-user-collect></ws-user-collect> -->
<!-- 我的订单 -->
<!-- <ws-user-order :order="order" :is-login="isLogin" @done="openLogin"></ws-user-order> -->
<!-- 其他功能 -->
<uni-card :border="false" :padding="0">
<!-- 场馆管理可见-->
<block v-if="hasMerchantRole || hasMerchantClerkRole">
<view class="server" style="min-height: 200px;">
<uni-list :border="false">
<block v-for="(item,index) in server" :key="index">
<uni-list-item :thumb="item.icon" link @click="navTo(item)">
<template v-slot:body>
<view class="slot-box">
<text class="slot-text"
:style="{color: item.color ? item.color : '#333333'}">{{ item.title }}</text>
</view>
</template>
</uni-list-item>
</block>
</uni-list>
</view>
</block>
</uni-card>
<!-- <view class="debug">
<view>条码类型: {{ scanType }}</view>
<view>条码内容: {{ scanResult }}</view>
</view> -->
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
<!-- 返回 -->
<view class="logout" @click="goBack">
<view size="20" class="btn">返回</view>
</view>
</block>
</view>
</template>
<script>
import {
useUserStore
} from '@/store/modules/user';
import * as UserApi from '@/api/booking/users';
import * as MpMenuApi from '@/api/cms/mp-menu/index';
import * as MerchantApi from '@/api/shop/merchant';
import {
updateUsers
} from '@/api/shop/users';
import {
openUrl
} from '@/utils/common';
import {
getWxOpenId
} from '@/api/passport/login';
import {
useTenantStore
} from '@/store/modules/tenant';
const tenantStore = useTenantStore();
const userStore = useUserStore();
export default {
data() {
return {
orderNo: undefined,
statusBarHeight: 104,
isLogin: false,
userInfo: {},
currMerchant: {},
merchantId: null,
fields: {},
logo: '',
bookingUser: {},
server: [],
order: [],
hideUser: true,
hideTools: true,
// 是否拥有场馆管理员权限
hasMerchantRole: false,
// 是否拥有场馆职员权限
hasMerchantClerkRole: false,
// 是否拥有超级管理员权限
hasSuperAdminRole: false,
scanType: '',
scanResult: ''
}
},
onLoad(option) {
if(option.orderNo){
this.orderNo = option.orderNo;
}
this.reload()
},
methods: {
async reload(e) {
const app = this
// 获取系统信息
uni.getSystemInfo({
success(data) {
if (data) {
app.statusBarHeight = data.statusBarHeight
}
}
})
// 当前租户信息
const tenantInfo = await tenantStore.fetchTenantInfo();
app.logo = tenantInfo.websiteLogo;
if (tenantInfo.fields) {
tenantInfo.fields.map(d => {
const key = d.name;
app.fields[key] = d.value;
})
}
// 当前登录用户信息
const userInfo = await userStore.fetchUserInfo();
if (Object.keys(userInfo).length > 0) {
app.isLogin = true
if(app.orderNo && app.orderNo != undefined){
return uni.redirectTo({
url: '/package/admin/order-scan?orderNo=' + app.orderNo
})
}
app.userInfo = userInfo
uni.setStorageSync('user_id', app.userInfo.userId);
// 判断用户角色
app.hasMerchantRole = userInfo.roles.find(d => d.roleCode == 'merchant');
app.hasMerchantClerkRole = userInfo.roles.find(d => d.roleCode == 'merchantClerk');
app.hasSuperAdminRole = userInfo.roles.find(d => d.roleCode == 'superAdmin');
// 可管理的场馆
MerchantApi.pageMerchant({merchantIds: userInfo.merchants,limit: 50}).then((res) => {
app.merchantList = res.list.map((d,i) => {
if(i == 0){
app.currMerchant = d;
app.merchantId = d.merchantId;
}
return {
text: d.merchantName,
value: d.merchantId
}
})
});
// 获取用户副表信息
UserApi.getByPhone({
phone: userInfo.phone
}).then(data => {
if (data) {
app.hideUser = false
app.userInfo.ouid = data.userId;
app.userInfo = Object.assign({}, app.userInfo, data);
}
})
} else {
app.isLogin = false
app.userInfo = {}
}
// 菜单数据
MpMenuApi.pageMpMenu({ type: 4, limit: 100 })
.then((res) => {
app.order = res.list.filter((d) => d.rows == 0);
app.server = res.list.filter((d) => d.rows == 0);
app.hideTools = false;
})
.catch(() => {
uni.showToast({
title: '请检查您的网络.',
icon: 'none'
});
app.hideTools = false;
});
// #ifdef MP-WEIXIN
uni.login({
success: (res) => {
getWxOpenId({
code: res.code
}).then(response => {
// console.log("response401: ", response);
// console.log('app.userInfo.openid: ', app.userInfo.openid);
if (!app.userInfo.openid) {
updateUsers({
userId: app.userInfo.ouid,
openid: response.openid,
sessionKey: response.session_key,
unionid: response.unionid
})
}
})
}
})
// #endif
},
navTo(item) {
const app = this
if (!this.isLogin) {
this.$refs.login.open('bottom')
return false;
} else {
if(item.path == '/package/admin/order-scan'){
uni.showModal({
title: '直接使用微信扫一扫功能完成核销'
})
return false
console.log('item.path: ',item.path);
console.log('app.orderNo: ',app.orderNo);
// 允许从相机和相册扫码
uni.scanCode({
success: function (res) {
app.scanType = res.scanType
app.scanResult = res.result
if(res.scanType){
console.log('/package/admin/order-scan?orderNo=' + app.orderNo);
uni.redirectTo({
url: '/package/admin/order-scan?orderNo=' + app.orderNo
})
}
}
});
return false;
}else{
openUrl(item);
}
}
},
// 弹出登录提示框
openLogin() {
if (!this.isLogin) {
this.$refs.login.open('bottom')
return false;
}
},
goBack(){
return uni.switchTab({
url: '/pages/user/user'
});
}
}
}
</script>
<style>
page {
/* background: url('https://oss.wsdns.cn/20240502/75fc744657544a38a32f83a825688286.png') no-repeat; */
background-size: 100%;
background-repeat: no-repeat;
background-color: #f0f2f5;
width: 750rpx;
overflow-x: hidden;
}
</style>
<style lang="scss">
.logout{
width: 300rpx;
margin: 0 auto;
padding: 10rpx 0 20rpx 0;
.btn {
display: flex;
justify-content: center;
background-color: #fff;
border-radius: 30rpx;
padding: 12rpx 0;
color: $uni-text-color-placeholder;
}
}
</style>
+397
View File
@@ -0,0 +1,397 @@
<template>
<view class="order" v-if="isLogin">
<uni-card title="预定信息" :border="false" :is-shadow="false" :padding="0">
<view class="order-body web-cell web-cell-align-top">
<view class="web-cell-content">
<uv-cell-group :customStyle="{ backgroundColor: '#ffffff' }" :border="false">
<uv-cell :title="`${form.merchantName}`" :label="` `" :cellStyle="{ padding: '0', paddingBottom: '5px' }" :border="false" />
<block v-for="(item, index) in form.orderInfo" :key="index">
<uv-cell
:title="`${item.fieldName}`"
:label="`${item.comments}`"
:cellStyle="{ padding: '0', paddingBottom: '5px' }"
:value="`¥${item.price}`"
:border="false"
/>
</block>
</uv-cell-group>
</view>
</view>
<view slot="actions" class="card-actions">
<view class="web-text-heading">合计:¥{{ form.totalPrice }}</view>
<view class="web-text-danger">实付:¥{{ form.payPrice }}</view>
</view>
</uni-card>
<block v-if="form.orderNo">
<uni-card :border="false" :is-shadow="false" :padding="0">
<view class="web-cell web-cell-align-top">
<uv-cell-group :customStyle="{ backgroundColor: '#ffffff', padding: '8px 0' }" :border="false">
<uv-cell :title="`姓名`" :value="`${form.realName}`" :cellStyle="{ padding: '8px' }" />
<uv-cell :title="`手机号码`" :value="`${form.phone}`" :cellStyle="{ padding: '8px' }" />
<uv-cell :title="`订单号`" :value="`${form.orderId}`" :cellStyle="{ padding: '8px' }" />
<uv-cell :title="`订单编号`" :cellStyle="{ padding: '8px' }">
<template v-slot:value>
<uv-parse :content="form.orderNo" :selectable="true"></uv-parse>
</template>
</uv-cell>
<uv-cell :title="`订单状态`" :cellStyle="{ padding: '8px' }">
<template v-slot:value>
<text class="web-text-primary" v-if="form.orderStatus == 0">{{ `${orderStatus[form.orderStatus]}` }}</text>
<text class="web-text-success" v-if="form.orderStatus == 1">{{ `${orderStatus[form.orderStatus]}` }}</text>
</template>
</uv-cell>
<uv-cell :title="`下单时间`" :value="`${form.createTime}`" :cellStyle="{ padding: '8px' }" />
<uv-cell :title="`支付方式`" :value="`${payType[form.payType]}`" :cellStyle="{ padding: '8px' }" />
<uv-cell :title="`优惠说明`" :value="`${form.couponDesc ? form.couponDesc : '无'}`" :cellStyle="{ padding: '8px' }" :border="false" />
</uv-cell-group>
</view>
</uni-card>
</block>
<uv-gap height="20"></uv-gap>
<view class="save-btn" v-if="form.orderStatus == 0">
<uv-button
:customStyle="{ background: 'linear-gradient(to right, #ccff66, #008e04)', borderRadius: '30px', color: '#ffffff' }"
text="确认核销"
@click="save"
></uv-button>
</view>
</view>
<view v-else>
<view class="login-bar">
<view class="login-btn">
<uv-button
:customStyle="{ background: 'linear-gradient(to right, #ccff66, #008e04)', borderRadius: '30px', color: '#ffffff' }"
text="请先登录"
@click="openLogin"
></uv-button>
</view>
</view>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
</view>
</template>
<script>
import * as OrderApi from '@/api/shop/order';
import * as FieldApi from '@/api/booking/field';
import { pageWechatDeposit } from '@/api/shop/wechatDeposit';
import { useUserStore } from '@/store/modules/user';
const userStore = useUserStore();
export default {
components: {},
data() {
return {
isLogin: false,
orderNo: '',
userId: 0,
form: {},
where: {
page: 1
},
canReset: false,
loadMore: 'more',
logo: '',
items: ['全部订单', '未支付', '已支付', '已完成', '押金'],
orderStatus: ['未使用', '已完成', '已取消', '取消中', '退款申请中', '退款被拒绝', '退款成功', '客户端申请退款'],
payType: [
'余额支付',
'微信支付',
'会员卡支付',
'支付宝',
'现金',
'POS机',
'VIP月卡',
'VIP年卡',
'VIP次卡',
'IC月卡',
'IC年卡',
'IC次卡',
'免费',
'VIP充值卡',
'IC充值卡',
'积分支付',
'VIP季卡',
'IC季卡'
],
orderList: [],
styles: [
{
value: 'button',
text: '按钮',
checked: true
},
{
value: 'text',
text: '文字'
}
],
colors: ['#333333', '#4cd964', '#dd524d'],
current: 0,
colorIndex: 0,
activeColor: '#108001',
styleType: 'text'
};
},
onLoad(option) {
this.orderNo = option.orderNo;
this.logo = uni.getStorageSync('app_logo') ? uni.getStorageSync('app_logo') : 'https://oss.wsdns.cn/20240423/7f6878104a6d4427884721f412ab5441.png?x-oss-process=image/resize,m_fixed,w_100,h_100/quality,Q_90'
// 判断是否登录
// this.openLogin();
// 加载数据
this.reload();
},
onShow() {
// 判断是否登录
// this.openLogin();
},
// 触底函数
onReachBottom() {
const app = this;
const { where } = this;
if (app.canReset) {
app.where.page = ++where.page;
app.reload();
}
},
methods: {
async reload() {
const app = this;
// 当前登录用户信息
const userInfo = await userStore.fetchUserInfo();
if (Object.keys(userInfo).length > 0) {
app.isLogin = true
}
const { where, userId, orderNo } = this;
console.log('userId: ',userId);
where.userId = userId;
OrderApi.getByOrderNo(orderNo)
.then((data) => {
app.form = data;
// 页面标题
if (data.orderStatus == 1) {
uni.setNavigationBarTitle({
title: '订单核销'
});
}
uni.hideLoading();
})
.catch((err) => {
console.log('err: ', err);
app.form = {};
uni.hideLoading();
});
},
onClickItem(e) {
const app = this;
const { where, userId } = this;
const index = e.currentIndex;
if (this.current !== e.currentIndex) {
this.current = e.currentIndex;
}
if (userId == 0) {
app.openLogin();
return;
}
// 全部
if (index == 0) {
where.payStatus = undefined;
where.orderStatus = undefined;
}
// 未支付
if (index == 1) {
where.payStatus = 2;
}
// 已支付
if (index == 2) {
where.payStatus = 1;
}
// 已完成
if (index == 3) {
where.orderStatus = 1;
}
// 押金
if (index == 4) {
pageWechatDeposit({
uid: uni.getStorageSync('user_id')
}).then((res) => {
console.log('res: ', res);
app.orderList = res.list;
});
return false;
}
this.reload();
},
// 弹出登录提示框
// openLogin() {
// if (!this.isLogin) {
// this.$refs.login.open('bottom');
// return false;
// }
// },
// 弹出登录提示框
async openLogin() {
if (!this.isLogin) {
this.$refs.login.open('bottom');
// uni.showToast({
// title: '请先登录',
// icon: 'error'
// });
// setTimeout(() => {
// return uni.redirectTo({
// url: '/package/admin/index?orderNo=' + this.orderNo
// })
// },2000)
}
},
save() {
const app = this;
const { orderNo } = this;
uni.showLoading({
title: '请求中.'
});
FieldApi.verification(orderNo)
.then((res) => {
uni.showToast({
title: '核销成功',
icon: 'success'
});
uni.hideLoading();
app.reload()
})
.catch((res) => {
uni.showToast({
title: res.message || '请检查您的网络.',
icon: 'none'
});
uni.hideLoading();
app.reload()
});
}
}
};
</script>
<style lang="scss">
.content {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
justify-content: center;
align-items: center;
height: 150px;
text-align: center;
}
.content-text {
font-size: 14px;
color: #666;
}
.color-tag {
width: 25px;
height: 25px;
}
.uni-list {
flex: 1;
}
.order {
.order-title {
padding: 20rpx 0;
border-bottom: 1px #eee solid;
.merchant-avatar {
margin-right: 12rpx;
}
.merchant-name {
// padding-left: 12rpx;
}
.btn-status {
font-size: 30rpx;
display: flex;
}
}
.order-body {
padding: 16px 0;
}
}
.ele-flex {
display: flex;
justify-content: space-between;
}
.card-actions {
display: flex;
flex-direction: row;
justify-content: space-between;
padding: 0 10px;
align-items: center;
height: 45px;
border-top: 1px #eee solid;
.web-text-heading {
font-size: 30rpx;
font-weight: 500;
}
.web-text-danger {
font-size: 30rpx;
font-weight: 500;
}
}
.card-actions-item {
display: flex;
flex-direction: row;
align-items: center;
}
.card-actions-item-text {
font-size: 12px;
color: #666;
margin-left: 5px;
}
.btn-status {
font-size: 30rpx;
display: flex;
}
.close {
top: 60rpx !important;
}
.save-btn {
width: 700rpx;
left: 25rpx;
height: 80rpx;
position: fixed;
bottom: 30rpx;
}
.qrcode {
margin-top: 30rpx;
text-align: center;
align-items: center;
display: flex;
flex-direction: column;
justify-content: center;
}
.login-bar{
width: 600rpx;
height: 40vh;
margin: auto;
display: flex;
.login-btn{
width: 500rpx;
margin: auto;
}
}
</style>
+63
View File
@@ -0,0 +1,63 @@
<template>
<view class="article-content" v-html="record.content"></view>
</template>
<script>
import * as ArticleApi from '@/api/cms/article'
export default {
data() {
return {
articleId: 0,
record: {}
}
},
onLoad(e) {
const {
articleId,
id
} = e
if (id) {
this.articleId = id
}
if (articleId) {
this.articleId = articleId
}
this.getArticle()
},
methods: {
getArticle() {
ArticleApi.getArticle(this.articleId).then(data => {
data.content = this.formatRichText(data.content)
this.record = data
uni.setNavigationBarTitle({
title: data.title
})
})
},
formatRichText(html) {
let newContent = html.replace(/<img[^>]*>/gi, function(match, capture) {
match = match.replace(/style="[^"]+"/gi, '').replace(/style='[^']+'/gi, '');
match = match.replace(/width="[^"]+"/gi, '').replace(/width='[^']+'/gi, '');
match = match.replace(/height="[^"]+"/gi, '').replace(/height='[^']+'/gi, '');
return match;
});
newContent = newContent.replace(/style="[^"]+"/gi, function(match, capture) {
match = match.replace(/width:[^;]+;/gi, 'max-width:100%;').replace(/width:[^;]+;/gi,
'max-width:100%;');
return match;
});
newContent = newContent.replace(/<br[^>]*\/>/gi, '');
newContent = newContent.replace(/\<img/gi,
'<img style="max-width:100%;height:auto;display:inline-block;margin:10rpx auto;"');
return newContent;
},
}
}
</script>
<style lang="scss" scoped>
.article-content {
padding: 20rpx;
line-height: 1.8rem;
}
</style>
+57
View File
@@ -0,0 +1,57 @@
<template>
<view>
<block v-for="(item,index) in list" :key="index">
<uni-card :border="false" :is-shadow="false" :padding="0">
<view class="web-cell web-cell-align-top">
<uv-cell-group :customStyle="{backgroundColor: '#ffffff', padding: '8px 0'}" :border="false">
<uv-cell :title="`${item.title}`" :label="item.createTime" :cellStyle="{padding: '8px'}"
:border="false" @click="openUrl('/package/article/detail?id='+item.articleId)">
<template v-slot:value>
<uv-image :src="item.image" width="80px" height="80px"></uv-image>
</template>
</uv-cell>
</uv-cell-group>
</view>
</uni-card>
</block>
</view>
</template>
<script>
import * as ArticleApi from '@/api/cms/article'
export default {
data() {
return {
id: 0,
list: []
}
},
onLoad(e) {
const {
id
} = e
ArticleApi.pageArticle({
categoryId: id
}).then(res => {
if (res.count > 0) {
this.list = res.list;
const item = res.list[0]
uni.setNavigationBarTitle({
title: item.categoryName
})
}
})
},
methods: {
openUrl(url) {
uni.navigateTo({
url
});
},
}
}
</script>
<style>
</style>
+163
View File
@@ -0,0 +1,163 @@
用户协议
 
生效日期:2021-12-20
 
“网宿软件”用户服务协议
 
“网宿软件”网站平台系南宁市网宿信息科技有限公司(以下简称“网宿软件”)旗下所有的一个平台,其旨在为单身用户提供安全、可靠、高品质的信息化服务,用户申请使用“网宿软件”服务前须完成平台注册。请用户仔细阅读以下本服务条款全部内容(特别是粗体下划线标注的内容),本服务条款的效力范围及于“网宿软件”平台的所有产品和服务。
如用户不同意本服务条款任意内容,请不要注册或使用“网宿软件”服务。如用户通过进入注册程序并勾选“我同意“网宿软件”服务条款”,即表示用户与南宁市网宿信息科技有限公司已达成协议并自愿接受本服务条款的所有内容。此后,用户不得以未阅读本服务条款内容作任何形式的抗辩。在此注册为平台用户并在之后进行的使用中应遵守以下用户注册条款:
1、用户注册条件
(1)申请注册成为“网宿软件”的用户应同时满足下列全部条件:在注册之日以及此后用“网宿软件”平台服务期间必须以合法经营为目的;在注册之日以及此后使用“网宿软件”平台服务期间必须是年满18周岁以上。
(2)为更好的享有“网宿软件”提供的服务,用户应:向“网宿软件”提供本人真实、正确、最新及完整的资料;随时更新登记资料,保持其真实性及有效性;提供真实有效的联系人手机号码;经营过程中,务必保持账号的唯一性。
(3)若用户提供任何错误、不实或不完整的资料,或“网宿软件”有理由怀疑资料为错误、不实或不完整及违反用户注册条款的,或“网宿软件”有理由怀疑其用户资料、言行等有悖于“网宿软件”主题的,“网宿软件”有权修改用户的注册昵称、独白等,或暂停或终止该用户的帐号,或暂停或终止提供“网宿软件”提供的全部或部分服务。
(4)在用户完成注册程序或以其他“网宿软件”允许的方式实际使用“网宿软件”服务时,用户应当是具备完全民事权利能力和完全民事行为能力的自然人、法人或其他组织。若用户不具备前述主体资格,则用户及用户的监护人应承担因此而导致的一切后果,同时“网宿软件”将保留追究用户及其监护人民事、刑事责任等权利,且“网宿软件”有权关闭(永久冻结)用户的“网宿软件”账号,账号所支付的相关用户费用不予退回,并有权向用户及企业索赔。
2、用户账号名称安全
任何注册和使用的“网宿软件”账号名称,不得有下列情形:
(一)违反宪法或法律法规规定的;
(二)危害国家安全,泄露国家秘密,颠覆国家政权,破坏国家统一的;
(三)损害国家荣誉和利益的,损害公共利益的;
(四)煽动民族仇恨、民族歧视,破坏民族团结的;
(五)破坏国家宗教政策,宣扬邪教和封建迷信的;
(六)散布谣言,扰乱社会秩序,破坏社会稳定的;
(七)散布淫秽、色情、赌博、暴力、凶杀、恐怖或者教唆犯罪的;
(八)侮辱或者诽谤他人,侵害他人合法权益的;
(九)含有法律、行政法规禁止的其他内容的。
用户以虚假信息骗取账号名称注册,或其账号头像、简介等注册信息存在违法和不良信息的,“网宿软件”有权采取通知限期改正、暂停使用、注销登记等措施。
对冒用关联机构或社会名人注册账号名称的用户,“网宿软件”有权注销其账号。
3、服务说明
(1)“网宿软件”在提供网络服务时,可能会对部分网络服务收取一定的费用,在此情况下,会在相关页面上做明确的提示。如用户拒绝支付该等费用,则不能使用相关的网络服务。付费业务将在本注册条款的基础上另行规定服务条款,以规范付费业务的内容和双方的权利义务,用户应认真阅读,如用户购买付费业务,则视为接受付费业务的服务条款。用户注册的相关费用无须支付给本公司的相关代理商。
(2)无论是付费业务还是“网宿软件”免费提供服务,上述服务均有有效期,有效期结束后服务将自动终止,且有效期不可中断或延期。
针对“网宿软件”提供的在线付费服务项目,必须成为本网站的付费用户,方能予以享受。有关当前收费服务内容及其价格说明,请在购买前仔细阅读网站服务说明页面。该服务说明页面上所载之内容构成本协议的一部分。除“网宿软件”另有说明外,所有付费业务均不支持退费。
(3)对于利用“网宿软件”服务进行非法活动,或其言行(无论线上或者线下的)背离企业合法经营目的,“网宿软件”将严肃处理,包括将其列入黑名单、将其被投诉的情形公之于众、删除用户帐号等处罚措施。
(4)“网宿软件”有权向其用户发送广告信,或为组织线下活动等目的,向其用户发送电子邮件、短信或电话通知。由于手机网络的特殊性,“网宿软件”有权获取用户的手机信息,如手机号码或用户的基站位置等。
(5)为提高“网宿软件”用户的效率目的,“网宿软件”有权将“网宿软件”用户的信息在“网宿软件”的合作网站、官方网站上进行展示或其他类似行为。
(6)用户知悉并同意用户帐号的唯一性和不可转让性,因此,用户成为“网宿软件”的用户后,不得以任何形式转让,包括但不限于以转让、出借、出租等形式将用户身份提供他人使用。
(7)用户有义务采取各种措施保管好自己的账号及密码,如果用户未保管好自己的账号和密码而对用户、公司或第三方造成的损害,用户将负全部责任。用户同意若发现任何非法使用用户帐号或安全漏洞的情况,有义务立即通告本公司。
4、免责条款
(1)“网宿软件”不保证其提供的服务一定能满足用户的要求和期望,也不保证服务不会中断,对服务的及时性、安全性、准确性都不作保证。
(2)对于用户通过“网宿软件”提供的服务传送的内容,“网宿软件”会尽合理努力按照国家有关规定严格审查,但无法完全控制经由网站服务传送的内容,不保证内容的正确性、完整性或品质。因此用户在使用“网宿软件”服务时,可能会接触到令人不快、不适当或令人厌恶的内容。在任何情况下,“网宿软件”均不为用户经由网站服务以张贴、发送电子邮件或其它方式传送的任何内容负责。但“网宿软件”有权依法停止传输任何前述内容并采取相应行动,包括但不限于暂停用户使用网站服务的全部或部分,保存有关记录,并根据国家法律法规、相关政策在必要时向有关机关报告并配合有关机关的行动。
(3)对于“网宿软件”网站提供的各种广告信息、链接、资讯等,“网宿软件”会对广告内容进行初步审核,但是“网宿软件”难以确保对方产品真实性、合法性或可靠性,由于产品购买导致的相关责任主要由广告商承担;敬告用户理性看待,如需购买或者交易,请谨慎考虑。并且,对于用户经由“网宿软件”服务与广告商进行联系或商业往来,完全属于用户和广告商之间的行为,与“网宿软件”无关。对于前述商业往来所产生的任何损害或损失,“网宿软件”不承担任何责任。
(4)对于用户上传的照片、资料、证件等,“网宿软件”已采用相关措施并已尽合理努力进行审核,但不保证其内容的正确性、合法性或可靠性,相关责任由上传上述内容的用户负责。
(5)用户以自己的独立判断从事与违法相关的行为,并独立承担可能产生的不利后果和责任,“网宿软件”不承担任何法律责任。
(6)依据有关法律法规的规定或依据行政机关、司法机关、检察机关的要求,向其提供用户的基本信息或站内聊天信息,上述行为侵犯用户隐私权的,“网宿软件”不承担任何法律责任。
(7)“网宿软件”作为技术平台,帮助用户实现信息化建设及企业经营是我们的服务内容。“网宿软件”推出的相关服务,不能保证用户通过此类服务授权由系统自动发出或接收到的信息完全满足用户需求。
(8)“网宿软件”为了促进用户互动,产品上的组件应用或小游戏都带有触发营销的功能。用户在玩此功能的组件或小游戏的同时会给符合自己要求的发起。“网宿软件”不能保证用户通过此类组件或小游戏发出或接受到的信息完全满足
5、用户应遵守以下法律法规:
(1)“网宿软件”提醒用户在使用“网宿软件”服务时,遵守《中华人民共和国合同法》、《中华人民共和国著作权法》、《全国人民代表大会常务委员会关于维护互联网安全的决定》、《中华人民共和国保守国家秘密法》、《中华人民共和国电信条例》、《中华人民共和国计算机信息系统安全保护条例》、《中华人民共和国计算机信息网络国际联网管理暂行规定》及其实施办法、《计算机信息系统国际联网保密管理规定》、《互联网信息服务管理办法》、《计算机信息网络国际联网安全保护管理办法》、《互联网电子公告服务管理规定》、《互联网用户账号名称管理规定》等相关中国法律法规的规定。
(2)在任何情况下,如果“网宿软件”有理由认为用户使用“网宿软件”服务过程中的任何行为,包括但不限于用户的任何言论和其它行为违反或可能违反上述法律和法规的任何规定,“网宿软件”可在任何时候不经任何事先通知终止向该用户提供服务。
(3)用户独立承担其行为和发布内容的责任,用户对服务的使用必须遵守上诉法律规定,用户在使用“网宿软件”服务中(如发布或传送信息)不得违背严肃的合法经营目的;不得侵犯任何人合法权益,包括但不限于肖像权、隐私权、名誉权及知识产权等,不得违反本服务条款;不得进行任何非法活动,包括不限于对其他用户进行诈骗的行为。否则由此产生的一切责任由用户独立承担,如因此造成公司损失的,用户应负责全部赔偿。公司将根据国家法律法规、相关政策在必要时向有关机关报告并配合有关机关的行动。
6、禁止用户从事下列行为:
(1)发布信息或者利用“网宿软件”的服务时在“网宿软件”的网页上或者利用“网宿软件”的服务制作、复制、发布、传播以下信息:反对宪法所确定的基本原则的;危害国家安全,泄露国家秘密,颠覆国家政权,破坏国家统一的;损害国家荣誉和利益的;煽动民族仇恨、民族歧视、破坏民族团结的;破坏国家宗教政策,宣扬邪教和封建迷信的;散布谣言,扰乱社会秩序,破坏社会稳定的;散布淫秽、色情、赌博、暴力、凶杀、恐怖或者教唆犯罪的;侮辱或者诽谤他人,侵害他人合法权利的;含有虚假、有害、胁迫、侵害他人隐私、骚扰、侵害、中伤、粗俗、猥亵、或其它有悖道德、令人反感的内容;含有中国法律、法规、规章、条例以及任何具有法律效力的规范所限制或禁止的其它内容的。
(2)使用“网宿软件”服务的过程中,以任何方式危害未成年人的利益的。
(3)冒充任何人或机构,包含但不限于冒充“网宿软件”工作人员,或以虚伪不实的方式陈述或谎称与任何人或机构右关的
(4)将侵犯任何人的肖像权、名誉权、隐私权、专利权、商标权、著作权、商业秘密或其它专属权利的内容上载、张贴、发送电子邮件或以其它方式传送的。
(5)将病毒或其它计算机代码、档案和程序,加以上载、张贴、发送电子邮件或以其它方式传送的。
(6)跟踪或以其它方式骚扰其他用户的。
(7)未经合法授权而截获、篡改、收集、储存或删除他人个人信息、电子邮件或其它数据资料,或将获知的此类资料用于任何非法或不正当目的。
(8)以任何方式干扰“网宿软件”服务的。
7、关于用户在“网宿软件”的上传或张贴的内容
(1)用户在“网宿软件”上传或张贴的内容(包括照片、文字、视频等),视为用户授予“网宿软件”免费、非独家的使用权,“网宿软件”有权为展示、传播及推广前述张贴内容的目的,对上述内容进行复制、修改、出版等。该使用权持续至用户书面通知“网宿软件”不得继续使用,且“网宿软件”实际收到该等书面通知时止。“网宿软件”代理商使用或在现场活动中使用,“网宿软件”将事先征得用户的同意,但在网页、app及小程序内使用不受此限。
(2)因用户进行上述上传或张贴,而导致任何第三方提出侵权或索赔要求的,用户承担全部责任。
(3)任何第三方对于用户在“网宿软件”的公开使用区域张贴的内容进行复制、修改、编辑、传播等行为的,该行为产生的法律后果和责任均由行为人承担,与“网宿软件”无关。
8、用户注册条款的变更和修改
本《协议》可由本公司随时进行变更和修改。一旦发生注册条款的变动,“网宿软件”将在页面上提示修改的内容,或将最新版本的用户注册条款以邮件的形式发送给用户。用户如果不同意用户注册条款的修改,可以主动取消用户资格(如注销账号),如对部分服务支付了额外的费用,可以申请将费用全额或部分退回。如果用户继续使用用户帐号,则视为用户已经接受用户注册条款的修改。
9、不可抗力条款
“网宿软件”对不可抗力导致的损失不承担责任。本服务条款所指不可抗力包括:天灾、法律法规或政府指令的变更,因网络服务特性而特有的原因,例如境内外基础电信运营商的故障、计算机或互联网相关技术缺陷、互联网覆盖范围限制、计算机病毒、黑客攻击等因素,及其他合法范围内的不能预见、不能避免并不能克服的客观情况。
10、法律适用及争议解决
本服务条款的生效、履行、解释及争议的解决适用中华人民共和国的现行法律。如用户使用本服务过程中出现纠纷,应进行友好协商,若协商不成,用户同意将纠纷提交海口市龙华区人民法院诉讼解决。
11、权利声明
“网宿软件”服务涉及到的产品所有权以及相关软件的知识产权归南宁市网宿信息科技有限公司所有,南宁市网宿信息科技有限公司保留所有的权利。南宁市网宿信息科技有限公司对“网宿软件”网站及相关软件有唯一的升级修改权限,并有权终止一部分版本的使用,请及时升级最新版本。
特别声明
鉴于:我国《合同法》第39条规定:采用格式条款订立合同的,提供格式条款的一方应当遵循公平原则确定当事人之间的权利和义务,并采取合理的方式提请对方注意免除或者限制其责任的条款,按照对方的要求,对该条款予以说明。
“网宿软件”在此依法做出特别声明如下:
“网宿软件”采取合理的方式提请您注意的义务将通过如下方式实现:在本协议中“网宿软件”以明确的足以引起您注意的加重字体、斜体、下划线、颜色标记等合理方式提醒用户注意相关条款(需要强调的是,还包括用户应特别注意任何未明确标记的含有“不承担”、“免责”“不得”等形式用语的条款),该等条款的确认将导致您在特定情况下的被动、不便、损失,请您在确认同意本协议之前再次阅读上述条款。双方确认上述条款非属于《合同法》第40条规定的“免除其责任、加重对方责任、排除对方主要权利的”的条款,“网宿软件”尊重用户的权利尤其是诉讼的权利,但作为在线网络信息服务提供方,“网宿软件”在尊重用户诉讼权利的同时建议争议由海口市龙华区人民法院诉讼解决,用户选择同意合同并使用服务即视为双方对此约定达成了一致意见
鉴于“网宿软件”已依法明确了上述条款、履行了格式条款制订方的义务,您进行下一步,将被视为且应当被视为您已经完全注意并同意了本协议所有条款尤其是提醒用户注意的条款的合法性及有效性,用户不应当以“网宿软件”未对格式条款以合理方式提醒用户注意,或未根据用户要求尽到说明义务为理由而声称或要求法院或其它任何第三方确认相关条款非法或无效。我已阅读并充分理解了以上协议中各条款,特别是涉及免除或者限制“网宿软件”责任的免责条款,对用户的权利限制的条款、约定争议解决方式、司法管辖、法律适用的条款,并且同意以上协议的全部内容。
更新日期:2022-02-18
生效日期:2021-12-20
+599
View File
@@ -0,0 +1,599 @@
隐私政策
 
更新日期:2023年4月17日
生效日期:2023年6月19日
本政策适用于南宁市网宿信息科技有限公司旗下所有的一个网站平台产品及相关服务。
您所使用的“网宿软件”应用的运营者的公司名称为南宁市网宿信息科技有限公司,注册地址为:南宁市民族大道155号荣和山水美地东盟国际B座21-G号,个人信息保护相关负责人联系方式为:603684184@qq.com。
如您对本政策或相关事宜有疑问或建议等,您可以通过如下投诉渠道与我们取得联系:
举报邮箱:603684184@qq.com
本隐私政策将帮助您了解以下内容:
0、引言
1、我们如何收集和使用您的个人信息
2、我们如何使用Cookie、同类技术和SDK技术
3、我们如何共享、转让、公开披露您的个人信息
4、我们如何保护您的个人信息
5、您如何管理您的个人信息/您的权利
6、我们如何处理未成年人的个人信息
7、存储信息的地点和期限,您的个人信息如何在全球范围转移
8、本隐私政策如何更新
9、如何联系我们/用户申诉渠道和反馈机制
10、广告/我们向您发送的信息
11、适用范围
南宁市网宿信息科技有限公司(以下统称“我们”)深知个人信息对您的重要性,并会尽力保护您的个人信息安全可靠,我们致力于维持您对我们的信任,恪守以下原则,保护您的个人信息:权责一致原则,目的明确原则,选择同意原则,最少够用原则,确保安全原则,主体参与原则,公开透明原则等等。同时熟的安全解决方案,采取相应的安全保护措施来保护您的个人信息。
我们承诺,我们将按业界成请在使用我们的产品、服务前,仔细阅读并了解本《隐私政策》。
0、引言
网宿软件对其收集的用户信息严格保密,并建立健全用户信息保护制度,以便为每一位用户提供可靠、放心的服务:
1、清晰明确
我们将尽可能采用通俗易懂的文字为您阐释隐私政策,以便您能更清晰地了解我们如何保护和处理所收集的您的信息。
2、保障权益
我们将采取充分、合理的措施保障您的隐私权益。
3、尊重用户
我们尊重用户的选择权、知情权等权利的自由行使,允许您管理您的个人信息。
4、必要安全
我们将仅收取必要的信息,并利用这些信息为您提供安全、详实的服务。
5、及时贴心
我们将随时聆听您的询问,并尽快为您解答您的疑问。
希望您仔细阅读《隐私政策》(以下简称“本政策”),详细了解我们对信息的收集、使用方式,以便您更好地了解我们的服务并在是否选择服务以及选择何种服务时更加符合您的真实意思表示。
请您在注册或使用我们的服务前仔细阅读本政策,若您使用我们提供的服务,即表示您认同我们在本政策中所述内容。
如您有问题,请联系我们。
为更好的说明,本政策中的下列概念是指:
个人常用设备信息:指包括硬件序列号、设备MAC地址、软件列表、唯一设备识别码(如IMEI/android ID/IDFA/OPENUDID/GUID、SIM卡IMSI信息等)等在内的描述个人常用设备基本情况的信息。
个人位置信息:指包括行踪轨迹、精准定位信息、住宿信息、经纬度等。
1、我们如何收集和使用您的个人信息
个人信息是指以电子或者其他方式记录的能够单独或者与其他信息结合识别特定自然人身份或者反映特定自然人活动情况的各种信息,我们会出于本政策所述的以下目的,收集和使用您的个人信息:
收集个人信息的业务功能以及收集的个人信息
我们将向您提供下列服务,并在提供下列服务时分别收集如下所列的信息:
1.为帮助您使用网宿软件的相关服务。
为完成创建账号,并保护您的账号安全,您需要提供以下信息:手机权限、手机号码授权。
为了网宿软件的用户都拥有完善的资料,您还需提供昵称、性别、自我介绍等权限或存储权限(如您选择拍摄头像则需相机权限)。
为了满足国家法律法规的网络实名制要求,并保证网宿软件真实、安全的社交环境,您需要提供真实姓名、身份证号、个人生物信息中的面部特征信息并授权身份证核验以完成实名认证。
手机号码、真实姓名及身份证号、身高、现居地、年收入、个人生物识别信息中的面部特征信息属于敏感信息,收集此类信息是为了满足国家法律法规的网络实名制要求,同时保证网宿软件产品真实、安全、资料丰富的社交氛围。
若您不提供这类信息,您可能无法正常使用我们的全部服务。
如果您提供以下额外信息,将有助于我们给您提供更好的服务和体验:麦克风权限(个人生物识别信息中的声纹特征信息)、学历认证材料(能证明您学历学校的相关信息)。以上信息主要为帮助您使用语音自我介绍功能以及完成您的学历认证。声纹特征信息属于敏感信息。但如果您不提供这些信息,将不会影响使用本服务的基本业务功能。
您提供的上述信息,将在您使用本服务期间持续授权我们使用。我们会一直保存您的信息直至您注销账号。在您注销账号时,我们将停止使用并删除或匿名化处理上述信息。
上述信息仅存储于中华人民共和国境内,如需跨境传输,我们将会单独征得您的授权同意。
2.为帮助您与其他用户进行聊天。
当您使用聊天服务时,我们没有要求您必须提供的信息。
如果您提供以下额外信息,将有助于我们给您提供更好的服务和体验:相册权限、相机权限、麦克风权限。但如果您不提供这些信息,将不会影响使用本服务的基本业务功能。
您提供的上述信息,将在您使用本服务期间持续授权我们使用。我们会一直保存您的信息直至您注销账号。在您注销账号时,我们将停止使用并删除或匿名化处理上述信息。
上述信息仅存储于中华人民共和国境内,如需跨境传输,我们将会单独征得您的授权同意。
3.为帮助您使用滑动卡片服务。
当您使用滑动卡片服务时,您需要提供以下功能、信息以保证功能正常使用:个人位置信息。收集此类信息是为实现基于地理位置的社交推荐。
若您不提供这类信息,您可能无法正常使用滑动卡片的服务。
在使用过程中,如果您提供以下额外信息,将有助于我们给您提供更好的服务和体验:我的生活、婚姻状态、车产、房产。但如果您不提供这些信息,将不会影响使用本服务的基本业务功能。
个人位置信息、我的生活、婚姻状态、车产、房产属于敏感信息。
您提供的上述信息,将在您使用本服务期间持续授权我们使用。我们会一直保存您的信息直至您注销账号。在您注销账号时,我们将停止使用并删除或匿名化处理上述信息。
上述信息仅存储于中华人民共和国境内,如需跨境传输,我们将会单独征得您的授权同意。
4.为帮助您使用视频约会功能。当您使用视频约会功能时,您需要提供以下功能、信息以保证功能正常使用:相册权限、摄像头权限、麦克风权限、视频的留存与内容查验授权。
若您不提供这类信息,您可能无法正常使用短视频的服务。
视频的留存与内容查验授权属于敏感信息,收集此类信息是为保证网络视频社交的安全性。
在使用过程中,如果您提供以下额外信息,将有助于我们给您提供更好的服务和体验:日历权限。但如果您不提供这些信息,将不会影响使用本服务的基本业务功能。
您提供的上述信息,将在您使用本服务期间持续授权我们使用。我们会一直保存您的信息直至您注销账号。在您注销账号时,我们将停止使用并删除或匿名化处理上述信息。
上述信息仅存储于中华人民共和国境内,如需跨境传输,我们将会单独征得您的授权同意。
5.为帮助您使用红娘服务。
当您使用红娘服务时,我们没有要求您必须提供的信息。
为帮助您使用分享服务。
当您使用分享服务时,如果您提供以下额外信息,将有助于我们给您提供更好的服务和体验:剪切板信息、粘贴板信息。如果您不提供这些信息,将会一定程度影响使用本服务的体验。
7.为帮助您使用支付功能。
支付功能由与我们合作的第三方支付机构向您提供服务,第三方支付机构将会需要收集您的信息,我们将无法获取您的信息。拒绝提供信息仅会使您无法使用上述支付功能,但不影响您使用网宿软件的其他功能。
8.为保障软件与服务的安全运营和运营质量。
为了保障软件与服务的安全运营、运行的质量及效率,我们会收集您的硬件型号、操作系统版本、国际移动设备识别码、唯一设备标识符、网络设备硬件地址、IP地址、软件版本号和网络接入方式。为预防恶意程序、保障运营质量及效率,我们还会收集软件的崩溃情、操作日志、性能数据及应用来源。我们可能使用您的账户信息、设备信息、服务日志信息及我们关联方、合作方在取得您授权或依法可以共享的信息,用于判断账户安全、进行身份验证、检测及防范安全事件。
9.为向您提供个性化服务。
为向您提供某些个性化服务,我们会在取得您授权的前提下,收集您提供给与我们合作的第三方的您的信息。如您不授权我们获取您的相关信息,您将无法享受某些个性化服务,但不影响您使用 网宿软件的其他功能。
您知悉并同意,当发现您正在遭受电信诈骗或处于其他可能损害您的人身或财产安全的情况时,您同意我们通过电话、短信或其他可以联系到您的方式与您取得联系,以保护您不受侵害。
 
用户画像、个性化推送的说明
为了实现个性化推荐的功能,我们会根据上述功能中所收集的信息进行综合统计并通过算法做特征与偏好性分析,用以向您定向推送可能感兴趣的其他用户,以及推送可能感兴趣的社区内容。如您不需要个性化推送服务,您可在“我的-设置-账号安全”中关闭个性化推送服务。
我们如何使用收集的信息
我们将按照前述的用途使用您的信息。当我们要将信息用于本政策未载明的其他用途时,会事先征得您的同意。当我们要将基于特定目的收集的信息用于其他目的时,会事先征得您的同意。
2、我们如何使用Cookie、同类技术和SDK技术
Cookie
为确保网站正常运转、为您获得更轻松的访问体验、向您推荐您可能感兴趣的内容,我们可能会在您的计算机或移动设备上存储名为Cookie的小数据文件。Cookie通常包含标识符、站点名称以及一些号码和字符。您可以在浏览器中进行相应的数据清除操作。
其他技术
除Cookie外,我们还会在网站上使用其他同类技术。我们向您发送的会员短信通知或网宿软件小助手站内通知可能含有链接至我们网站内容的地址链接,如果您点击该链接,我们则会跟踪此次点击,帮助我们了解您的产品或服务偏好以便于我们主动改善客户服务体验。如果您不希望自己的活动以这种方式被追踪,则可以随时从我们的寄信名单中退订。
SDK技术
SDK技术由与我们合作的第三方机构提供,我们仅能知悉其要求获得授权的权限。第三方机构将会需要收集您的信息,我们无法获取您的信息,除非第三方机构明确向我们披露的要收集的敏感信息。我们会对合作方获取个人信息的行为进行严格的安全监测,以保护您的个人信息安全。
我们对接入的相关第三方SDK及其他第三方主体收集信息的情况在以下目录中列明。您可以通过相关链接查看第三方的数据使用和保护规则。请注意,第三方SDK可能由于版本升级、策略调整等原因导致其个人信息处理类型发生变化,请以其公示的官方说明为准。Alipay(支付宝)SDK
第三方名称:支付宝网络有限公司
使用目的:支付功能
处理方式:通过去标识化、加密传输和处理的安全处理方式
收集的个人信息类型:MAC地址、IMEI、IMSI、SIM卡序列号、IDFA、ICCID、Android id、硬件序列号、设备识别信息、设备状态信息、设备环境信息、网络连接信息。申请读取及写入存储器权限,目的是为了保障支付功能的稳定运行
第三方隐私政策或官网链接:
https://opendocs.alipay.com/open/54/01g6qm
高德地图 SDK
第三方名称:高德软件有限公司
使用目的:帮助用户发布信息时定位位置
处理方式:通过去标识化、加密传输和处理的安全处理方式收集的个人信息类型:设备标识符
(Android如Android ID、IMEI、MEID、
IMSI、OAID、Serial,iOS如IDFV、
IDFA)、MAC地址、IP地址、位置信息
(如GPS、WLAN接入点、蓝牙和基站)、
设备传感器、当前应用信息(应用名、应用版本号)
第三方隐私政策或官网链接:
https://lbs.amap.com/pages/privacy/
微信 SDK
第三方名称:深圳市腾讯计算机系统有限公司
使用目的:支持微信分享
处理方式:通过去标识化、加密传输和处理的安全处理方式
收集的个人信息类型:设备标识符
(Android如IMEI、Android ID、Serial, iOS如IDFV)、MAC地址、WLAN接入点、分享图片或内容
第三方隐私政策或官网链接:https://support.weixin.qq.com/cgi-
bin/mmsupportacctnodeweb-
bin/pages/RYiYJkLOrQwu0nb8
微信支付SDK
第三方名称:财富通支付科技有限公司
使用目的:支持微信支付
处理方式:通过去标识化、加密传输和处理的安全处理方式
收集个人信息类型:设备标识符(Android如IMEI、Android ID、Serial)、MAC地址、WLAN接入点
第三方隐私政策或官网链接:
https://www.tenpay.com/v3/helpcenter/low/priv
融云消息SDK
第三方名称:北京云中融信网络科技有限公司
使用目的:实现单群聊、系统通知等通信能力,安全可靠、全球互通。处理方式:通过去标识化、加密传输和处
理的安全处理方式
收集的个人信息类型:设备ID
(iOS:deviceToken / Android:AndroidId)、
操作系统版本、网络类型、手机机型、MNO
第三方隐私政策或官网链接:
https://docs.rongcloud.cn/v4/views/im/noui/intr
推送通知消息(OPPO推送SDK)
第三方名称:广东欢太科技有限公司
使用目的:用于在OPPO设备上推送消息
处理方式:通过去标识化、加密传输和处理的安全处理方式
收集个人信息类型:设备标识信息、网络信息、设备状态信息、应用使用信息
第三方隐私政策或官网链接:
https://open.oppomobile.com/wiki/doc#id=104
推送通知消息(华为推送SDK)
第三方名称:华为软件技术有限公司使用目的:
1.提供消息推送服务;
2.统计华为推送SDK接口调用成功率。
处理方式:通过去标识化、加密传输和处理的安全处理方式
收集个人信息类型:应用基本信息、应用内设备标识符、设备的硬件信息、系统基本信息和系统设置信息
第三方隐私政策或官网链接:
https://developer.huawei.com/consumer/cn/doc/ Guides/privacy-statement-0000001050042021
推送通知消息(VIVO推送SDK)
第三方名称:维沃移动通信有限公司
使用目的:用于在VIVO设备上推送消息
处理方式:通过去标识化、加密传输和处理的安全处理方式
收集个人信息类型:设备标识信息、网络状态信息第三方隐私政策或官网链接:
https://dev.vivo.com.cn
腾讯浏览服务(TBS腾讯浏览服务;腾讯浏览服务;腾讯X5浏览器;腾讯浏览器)等SDK
第三方名称:深圳市腾讯计算机系统有限公司
使用目的:浏览word,excel,PPT,txt等格式文件
示例:用户在于他/她人聊天是可在线打开对方发送的相关文件进行预览。
处理方式:通过去标识化、加密传输和处理的安全处理方式
收集个人信息类型:设备信息(设备名称、设备型号、MAC地址、设备识别码、操作系统和应用程序版本、语言设置、分辨率、服务提供商网络ID(PLMN))、设备所在位置相关信息(包括您授权的GPS位置信息以及WLAN接入点、蓝牙和基站传感器信息)
第三方隐私政策或官网链接:
https://x5.tencent.com/tbs/guide/develop.html#5
3、我们如何共享、转让、公开披露您的个人信息
共享
我们不会与网宿软件服务提供者以外的公司、组织和个人共享您的个人信息,但以下情况除外:
1、在获取明确同意的情况下共享:获得您的明确同意后,我们会与其他方共享您的个人信息;
2、在法定情形下的共享:我们可能会根据法律法规规定、诉讼争议解决需要,或按行政、司法机关依法提出的要求,对外共享您的个人信息;
3、与关联公司间共享:为便于我们基于关联账号共同向您提供服务,推荐您可能感兴趣的信息或保护网宿软件关联公司或其他用户或公众的人身财产安全免遭侵害,您的个人信息可能会与我们的关联公司共享。我们只会共享必要的个人信息(如为便于您通过网宿软件账号使用我们关联公司产品或服务,我们会向关联公司共享您必要的账户信息),如果我们共享您的个人敏感信息或关联公司改变个人信息的使用及处理目的,将再次征求您的授权同意;
4、与授权合作伙伴共享:仅为实现本隐私政策中声明的目的,我们的某些服务将由我们和授权合作伙伴共同提供。我们可能会与合作伙伴共享您的某些个人信息,以提供更好的客户服务和用户体验。例如涉及用户身份验证时,我们需要收集姓名、身份证号、身份证照片、个人生物识别信息中的面部特征信息等,并将前述信息提供给第三方公司(包括但不限于北京旷视科技有限公司,以下第三方公司含义与此相同);第三方公司有权获得上述信息用于验证服务,并向我们返回识别结果;第三方公司有权保存用户的上述身份信息及身份信息的验证记录,并有权用于与用户相关的身份验证业务。我们仅会出于合法、正当、必要、特定、明确的目的共享您的个人信息,并且只会共享提供服务所必要的个人信息。我们的合作伙伴无权将共享的个人信息用于与产品或服务无关的其他用途。
我们将信息发送给支持我们业务的供应商、服务提供商和其他合作伙伴,这些支持包括提供技术基础设施服务、分析我们服务的使用方式、衡量广告和服务的有效性、提供客户服务、支付便利或进行学术研究和调查。
对我们与之共享个人信息的公司、组织和个人,我们会与其签署严格的数据保护协定,要求其按照我们的说明、本隐私政策以及其他任何相关的保密和安全措施来处理个人信息。
转让
我们不会将您的个人信息转让给任何公司、组织和个人,但以下情况除外:
1、在获取明确同意的情况下转让:获得您的明确同意后,我们会向其他方转让您的个人信息;
2、在涉及合并、收购或破产清算情形,或其他涉及合并、收购或破产清算情形时,如涉及到个人信息转让,我们会要求新的持有您个人信息的公司、组织继续受本政策的约束,否则我们将要求该公司、组织和个人重新向您征求授权同意。
公开披露
我们仅会在以下情况,公开披露您的个人信息:
1、获得您明确同意或基于您的主动选择,我们可能会公开披露您的个人信息;
2、如果我们确定您出现违反法律法规或严重违反网宿软件相关协议规则的情况,或为保护网宿软件及其关联公司用户或公众的人身财产安全免遭侵害,我们可能依据法律法规或网宿软件相关协议规则征得您同意的情况下披露关于您的个人信息,包括相关违规行为以及网宿软件已对您采取的措施。
共享、转让、公开披露个人信息时事先征得授权同意的例外
以下情形中,共享、转让、公开披露您的个人信息无需事先征得您的授权同意:
1、与国家安全、国防安全有关的;
2、与公共安全、公共卫生、重大公共利益有关的;
3、与犯罪侦查、起诉、审判和判决执行等有关的;
4、出于维护您或其他个人的生命、财产等重大合法权益但又很难得到本人同意的;
5、您自行向社会公众公开的个人信息;
6、从合法公开披露的信息中收集个人信息的,如合法的新闻报道、政府信息公开等渠道。
根据法律规定,共享、转让经去标识化处理的个人信息,且确保数据接收方无法复原并重新识别个人信息主体的,不属于个人信息的对外共享、转让及公开披露行为,对此类数据的保存及处理将无需另行向您通知并征得您的同意。
4、我们如何保护您的个人信息
为了保护您的信息安全,我们将严格遵守法律法规等规范性文件要求的技术措施和操作流程保护您的信息秘密,同时:
1.我们已采取符合业界通用解决方案、合理可行的安全防护措施保护您提供的个人信息安全,防止个人信息遭到未经授权访问、公开披露、使用、修改、损坏或丢失。我们会使用加密技术提高个人信息的安全性;我们会使用受信赖的保护机制防止个人信息遭到恶意攻击;我们建立严格的内部控制制度,建立完善、充分的管理流程,我们会部署访问控制机制,尽力确保只有授权人员才可访问个人信息;以及我们会举办安全和隐私保护培训课程,加强员工对于保护个人信息重要性的认识。
2.我们有行业先进的以数据为核心,围绕数据生命周期进行的数据安全管理体系,从组织建设、制度设计、人员管理、产品技术等方面多维度提升整个系统的安全性。
3.我们会采取合理可行的措施,尽力避免收集无关的个人信息。我们只会在达成本政策所述目的所需的期限内保留您的个人信息,除非需要延长保留期或受到法律的允许。
4.互联网并非绝对安全的环境,我们强烈建议您不要使用非网宿软件推荐的通信方式发送个人信息。您可以通过我们的服务建立联系和相互分享。当您通过我们的服务创建交流、交易或分享时,您可以自主选择沟通、交易或分享的对象,作为能够看到您的交易内容、联络方式、交流信息或分享内容等相关信息的第三方。
如您发现自己的个人信息尤其是您的账户或密码发生泄露,请您立即联络网宿软件客服,以便我们根据您的申请采取相应措施。
请注意,您在使用我们服务时自愿共享甚至公开分享的信息,可能会涉及您或他人的个人信息甚至个人敏感信息,如您在发表动态或者在群聊天、圈子等公众场合选择上传包含个人信息的图片。请您更加谨慎地考虑,是否在使用我们的服务时共享甚至公开分享相关信息。
请使用复杂密码,协助我们保证您的账号安全。我们将尽力保障您发送给我们的任何信息的安全性。
我们将按照法律法规的要求更新并公开安全风险、个人信息安全影响评估等报告的内容。
互联网环境并非百分之百安全,我们将尽力确保或担保您发送给我们的任何信息的安全性。如果我们的物理、技术或管理防护设施遭到破坏,导致信息被非授权访问、公开披露、篡改或毁坏,导致您的合法权益受损,我们将承担相应的法律责任。
在不幸发生个人信息安全事件后,我们将依照法律法规的要求,及时向您告知:安全事件的基本情况和可能的影响、我们已采取或将要采取的处置措施,您可自主防范和降低风险的建议、对您的补救措施等。我们将及时将事件相关情况以推送通知的方式告知您,并采取合理有效的方式发送公告。
同时,我们还将按照监管部门要求,主动上报个人信息安全事件的处置情况。
5、您如何管理您的个人信息/您的权利
个人信息查询
您有权访问您的个人信息,法律法规规定的例外情况除外。您可以通过以下方式自行访问您的个人信息:
账户信息——如果您希望访问或编辑您的账户中的个人信息、设置隐私与权限、设置消息提醒与聊天、更改您的绑定手机号与密码、关闭您的账户等,您可以通过登录账号通过“我的”-“设置”执行此类操作。
个人资料——如果您希望访问或编辑您个人资料中的昵称、头像、家乡、出生年月日、职业、学校、兴趣爱好以及其他资料,您可以通过登录账户通过“我的”-“查看/编辑资料”执行此类操作。
如果您无法通过上述路径访问该等个人信息,您可以随时通过网宿软件客服与我们取得联系。我们将在15天内回复您的访问请求。
对于您在使用我们的产品或服务过程中产生的其他个人信息,我们将根据相关安排向您提供。
您可以通过与网宿软件客服联系的方式,申请个人信息副本。
个人信息更正
当您发现我们处理的关于您的个人信息有错误时,您有权要求我们做出更正或补充。您可以通过本条“个人信息查询”中列明的方式提出更正或补充申请。
个人信息删除
您可以通过本条“个人信息查询”中列明的方式删除您的部分个人信息。
在以下情形中,您可以向我们提出删除个人信息的请求:
1、如果我们处理个人信息的行为违反法律法规;
2、如果我们收集、使用您的个人信息,却未征得您的明确同意;
3、如果我们处理个人信息的行为严重违反了与您的约定;
4、如果您不再使用我们的产品或服务,或您主动注销了账号;
5、如果我们永久不再为您提供产品或服务。
若我们决定响应您的删除请求,我们还将同时尽可能通知从我们处获得您的个人信息的主体,要求其及时删除,除非法律法规另有规定,或这些主体获得您的独立授权。
当您从我们的服务中删除信息后,我们可能不会立即从备份系统中删除相应的信息,但会在备份更新时删除这些信息。
用户账号注销
您可以自行在“注销账户”页面(例如,网宿软件手机APP“我的-设置-账户与安全-注销账户”)提交账户注销申请。
在您主动注销账户之后,我们将停止为您提供产品或服务,根据相应法律的要求删除您的个人信息,或使其匿名化处理。
撤回已同意的授权
每个业务功能需要一些基本的个人信息才能得以完成。除此之外,对于额外个人信息的收集和使用,您可以自行或与网宿软件客服联系给予或收回您的授权同意。
当您收回同意后,我们将不再处理相应的个人信息。但您收回同意的决定,不会影响此前基于您的授权而开展的个人信息处理。
约束信息系统自动决策
在某些业务功能中,我们可能仅依据信息系统、算法等在内的非人工自动决策机制做出决定。如果这些决定显著影响您的合法权益,您有权要求我们做出解释,我们也将在不侵害网宿软件商业秘密或其他用户权益、社会公共利益的前提下提供申诉方法。
响应您的上述请求
为保障安全,您可能需要提供书面请求,或以其他方式证明您的身份。我们可能会先要求您验证自己的身份,然后再处理您的请求。
我们将在15天内做出答复。如您对我们的答复不满意,还可以通过网宿软件客服发起投诉。
对于您合理的请求,我们原则上不收取费用,但对多次重复、超出合理限度的请求,我们将视情况收取一定成本费用。对于无端重复、需要过多技术手段(例如,需要开发新系统或从根本上改变现行惯例)、给他人合法权益带来风险或者非常不切实际的请求,我们可能会予以拒绝。
相关限制
在以下情形中,按照法律法规要求,我们将无法响应您的请求:
1、与国家安全、国防安全有关的;
2、与公共安全、公共卫生、重大公共利益有关的;
3、与犯罪侦查、起诉、审判和执行判决等有关的;
4、有充分证据表明个人信息主体存在主观恶意或滥用权利的;
5、响应您的请求将导致您或其他个人、组织的合法权益受到严重损害的;
6、涉及商业秘密的。
 
6、我们如何处理未成年人的个人信息
本软件禁止未成年人注册、使用。如我们发现收集了未成年人的个人信息,我们将会设法尽快删除相关数据。
7、存储信息的地点和期限,您的个人信息如何在全球范围转移
个人信息存放的地域
我们严格按照法律法规的规定,将中华人民共和国境内收集和产生的用户个人信息存放于中华人民共和国境内。
个人信息出境的情况
我们在中华人民共和国境内运营中收集和产生的个人信息,存储在中华人民共和国境内。如果在未来出现个人信息出境的情况,我们将严格遵守中华人民共和国法律法规的相关规定,同时对出境信息的信息安全进行评估,并获取您的明确授权,但是您通过互联网进行跨境发布动态等个人主动行为除外。
针对以上情形,我们会确保依据本隐私政策对您的个人信息提供足够的保护。
存储信息的期限
一般而言,我们仅在为实现目的所必需的最短时间内保留您的个人信息,超过相应期限内的个人信息将会删除或匿名化进行处理。但在下列情况下,我们有可能因需符合法律要求,更改个人信息的存储时间:
1.为遵守适用的法律法规或政策等规范性文件的有关规定;
2.为遵守行政机关或类似授权组织的决定等、司法机关判决、裁定、仲裁机关的裁决或其他法律程序的规定;
3.我们有理由确信需要遵守法律法规等有关规定;
4.为执行相关服务协议或本政策、维护社会公共利益,为保护们的客户、我们或我们的关联公司、其他用户或雇员等第三方的人身财产安全或其他合法权益所合理必需的用途。
当网宿软件发生停止运营的情形时,我们将采取推送通知、网站或程序内公告等形式通知您,并在合理的期限内删除或匿名化处理您的个人信息。
8、本隐私政策如何更新
我们的隐私政策可能变更。如果发生业务功能变更、使用目的变更、个人信息保护相关负责人联络方式变更等情形,我们将相应修订隐私政策。
未经您明确同意,我们不会限制您按照本隐私政策所应享有的权利。对于重大变更,我们会提供显著的通知(包括我们会通过网宿软件公示的方式、网宿软件小助手等进行通知)。您也可以定期查看本隐私政策,以获取最新的条款。
本政策所指的重大变更包括但不限于:
1、我们的服务模式发生重大变化。如处理个人信息的目的、处理的个人信息类型、个人信息的使用方式等;
2、个人信息共享、转让或公开披露的主要对象发生变化;
3、您参与个人信息处理方面的权利及其行使方式发生重大变化;
4、我们负责处理个人信息安全的责任部门、联络方式及投诉渠道发生变化时;
5、个人信息安全影响评估报告表明存在高风险时。
如果您在接到通知后,选择继续使用我们的服务,即表示同意受经修订的政策约束。
我们还会将本政策的旧版本存档,供您查阅,您可通过前述的联系方式向我们申请查阅。
9、如何联系我们/用户申诉渠道和反馈机制
如您对本政策或相关事宜有疑问或建议等,我们建立了个人信息保护专职部门,您可以通过如下投诉渠道与我们取得联系:
举报邮箱:1241498785@qq.com
我们将妥善受理并及时反馈您的申诉,并在验证您的用户身份后的十五天内予以回复。
如果您对我们的回复不满意,特别是您认为我们的个人信息处理行为损害了您的合法权益,您还可以通过向被告住所地有管辖权的法院提起诉讼来寻求解决方案。
10、广告/我们向您发送的信息
我们可能使用您的相关信息,在相关网站、应用、及其他渠道向您发送商业广告。
如果您不想接受我们给您发送的商业广告,您可随时通过相应产品退订功能取消。
11、适用范围
网宿软件提供的所有服务均使用本隐私政策。但是,请您注意,本隐私政策不适用由其他公司或个人提供的服务,且该服务适用其他公司或个人的隐私政策。
南宁市网宿信息科技有限公司
+560
View File
@@ -0,0 +1,560 @@
<template>
<view class="container">
<!-- deBug信息 -->
<view v-if="merchant" class="web-debug web-text-success" style="display: ">
场馆ID:{{ merchant.merchantId }}
场馆编号:{{ merchant.merchantCode }}
场馆名称:{{ merchant.merchantName }}
日期:{{ dateTime }}
星期:{{ week }}
订单总金额:{{ totalPrice }}
类型:{{
type
}}
场地信息:{{ orderInfo }}
表单信息:{{ form }}
</view>
<uni-card title="预约人信息" :border="false" :is-shadow="false">
<uv-cell-group :customStyle="{ backgroundColor: '#ffffff' }" :border="false">
<uv-cell title="真实姓名" :cellStyle="{ padding: '10px 5px' }" :value="userInfo.realName" :border="false" />
<uv-cell title="手机号码" :cellStyle="{ padding: '10px 5px' }" :value="userInfo.phone" :border="false" />
</uv-cell-group>
</uni-card>
<uni-card title="订单信息" :border="false" :is-shadow="false">
<uv-cell-group :customStyle="{ backgroundColor: '#ffffff' }" :border="false">
<block v-if="orderInfo.length == 0">
<span class="web-text-secondary">订单不存在</span>
</block>
<block v-if="orderInfo">
<uv-cell :title="`场馆`" :label="form.merchantName" :cellStyle="{ padding: '10px 5px' }" :border="false" />
<block v-for="(item, index) in orderInfo" :key="index">
<uv-cell
:title="`${item.fieldName}`"
:label="`${item.dateTime} ${getWeek(this.week)} ${item.timePeriod}`"
:value="`¥${item.price}`"
:cellStyle="{ padding: '10px 5px' }"
:border="false"
/>
</block>
</block>
</uv-cell-group>
</uni-card>
<!-- <uni-card title="选择优惠券" :border="false" :is-shadow="false">
<uv-cell-group :customStyle="{ backgroundColor: '#ffffff' }" :border="false">
<uv-cell
title="可用优惠券"
icon="https://oss.wsdns.cn/20240502/b13bb4162f44473eb2e05052f7c26b0e.png?x-oss-process=image/resize,m_fixed,w_100,h_100/quality,Q_90"
:cellStyle="{ padding: '10px 5px' }"
isLink
:value="`0 张`"
:border="false"
/>
<uv-cell
title="可用会员卡"
icon="https://oss.wsdns.cn/20240502/1017dc754cde4d108cebcca147a4ce9d.png?x-oss-process=image/resize,m_fixed,w_100,h_100/quality,Q_90"
:cellStyle="{ padding: '10px 5px' }"
isLink
:value="`${cardList.length} 张`"
:border="false"
/>
<uv-cell
title="可用IC卡"
icon="https://oss.wsdns.cn/20240502/6ee5122fd32440c996ed86154d656e04.png?x-oss-process=image/resize,m_fixed,w_100,h_100/quality,Q_90"
:cellStyle="{ padding: '10px 5px' }"
isLink
:value="`0 张`"
:border="false"
/>
</uv-cell-group>
<view slot="actions" class="card-actions">
<view class="card-actions-item" @click="actionsClick('分享')">
<span class="web-text-danger">已优惠¥{{ reducePrice }}</span>
<span class="web-text-heading">¥{{ totalPrice || 0.0 }}</span>
</view>
</view>
</uni-card> -->
<uni-card title="选择支付方式" :border="false" :is-shadow="false">
<uv-cell-group :customStyle="{ backgroundColor: '#ffffff' }" :border="false">
<block v-for="(item, index) in payment" :key="index"></block>
<uv-cell
title="微信支付"
icon="https://oss.wsdns.cn/20240511/8d7af0f0374040cb9b9255eff5fb812d.png?x-oss-process=image/resize,m_fixed,w_100,h_100/quality,Q_90"
:cellStyle="{ padding: '20rpx 10rpx', borderRadius: '8rpx', backgroundColor: form.payType == 1 ? '#f6fff1' : '' }"
:border="false"
@click="onPayType(1)"
>
<template v-slot:right-icon>
<uv-icon v-if="form.payType == 1" size="30rpx" name="checkbox-mark"></uv-icon>
</template>
</uv-cell>
<uv-cell
:title="`余额支付(${userInfo.balance})`"
icon="https://oss.wsdns.cn/20240511/fae57a94fa0042b9bceb721421304db1.png?x-oss-process=image/resize,m_fixed,w_100,h_100/quality,Q_90"
:cellStyle="{ padding: '10px 5px', borderRadius: '8rpx', backgroundColor: form.payType == 0 ? '#f6fff1' : '' }"
:border="false"
@click="onPayType(0)"
>
<template v-slot:right-icon>
<uv-icon v-if="form.payType == 0" size="30rpx" name="checkbox-mark"></uv-icon>
</template>
</uv-cell>
<uv-cell
title="优惠券"
icon="https://oss.wsdns.cn/20240502/b13bb4162f44473eb2e05052f7c26b0e.png?x-oss-process=image/resize,m_fixed,w_100,h_100/quality,Q_90"
:cellStyle="{ padding: '10px 5px' }"
isLink
:value="`0 张`"
:border="false"
/>
<uv-cell
:title="`会员卡`"
icon="https://oss.wsdns.cn/20240502/1017dc754cde4d108cebcca147a4ce9d.png?x-oss-process=image/resize,m_fixed,w_100,h_100/quality,Q_90"
:cellStyle="{ padding: '10px 5px', borderRadius: '8rpx', backgroundColor: form.payType == 6 || form.payType == 7 || form.payType == 8 ? '#f6fff1' : '' }"
:border="false"
isLink
:value="`${currentCard.name ? currentCard.name : '0 张'}`"
@click="onPayType(7)"
>
</uv-cell>
<uv-cell
title="IC卡"
icon="https://oss.wsdns.cn/20240502/6ee5122fd32440c996ed86154d656e04.png?x-oss-process=image/resize,m_fixed,w_100,h_100/quality,Q_90"
:cellStyle="{ padding: '10px 5px' }"
isLink
:value="`0 张`"
:border="false"
/>
<view slot="actions" class="card-actions">
<view class="card-actions-item" @click="actionsClick('分享')">
<span class="web-text-danger">已优惠¥{{ form.reducePrice }}</span>
<span class="web-text-heading">¥{{ form.payPrice || 0.0 }}</span>
</view>
</view>
</uv-cell-group>
</uni-card>
<view class="xieyi web-cell web-text-secondary web-cell-align-top">
<view class="web-cell web-cell-content web-cell-align-top">
<uni-icons type="circle" size="20" color="#a4a5a7" v-if="!disabled" @click="onDisabled"></uni-icons>
<uni-icons type="checkbox" size="20" color="#11a954" v-else @click="onDisabled"></uni-icons>
<view class="text" @click="onDisabled">
<text>同意以下服务条款</text>
<text class="link" @click.stop="navTo('/package/article/detail?articleId=501')">《广西体育中心预定条款》</text>
<text class="link" @click.stop="navTo('/package/article/detail?articleId=502')">《用户服务协议和隐私政策》</text>
</view>
</view>
</view>
<!-- 支付按钮 -->
<uv-gap height="50"></uv-gap>
<view class="checkout-car">
<view class="car-total">
<text style="color: #ebcf00">合计¥</text>
<uv-count-to :startVal="0" decimals="2" duration="100" color="#ebcf00" bold :endVal="form.payPrice"></uv-count-to>
</view>
<!--:disabled="!disabled || orderInfo.length == 0" -->
<uv-button
class="save-btn"
:disabled="!disabled"
:customStyle="{ background: 'linear-gradient(to right, #70b915, #008e04)', borderRadius: '0 30px 30px 0', color: '#ffffff', border: 'none', padding: '22px 30px' }"
text="提交订单"
@click="save"
></uv-button>
</view>
</view>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
<!-- 支付密码弹窗 -->
<uni-popup ref="payPasswordForm" type="center" border-radius="10px 10px 0 0">
<uni-card title="请输入支付密码" :border="false" :is-shadow="false" :padding="0">
<view class="pay-password-card">
<uni-forms ref="form" :label-width="80">
<uni-forms-item label="支付密码" name="payPassword" required>
<uv-code-input mode="box" :space="0" :maxlength="6" hairline v-model="payPassword"></uv-code-input>
</uni-forms-item>
<uv-button class="to-pay-btn"
:customStyle="{background: 'linear-gradient(to right, #70b915, #008e04)',borderRadius: '30px',color: '#ffffff'}"
text="确定支付" :disabled="disabledPayPayPassword" @click="onPayPassword"></uv-button>
</uni-forms>
<text @click="navTo(`/package/user/pay-password`)" class="web-text-primary">忘记支付密码?</text>
</view>
</uni-card>
</uni-popup>
</template>
<script>
import * as Api from '@/api/shop/order';
import * as UserCardApi from '@/api/booking/userCard';
import { checkPayPassword } from '@/api/passport/login';
import { storeToRefs } from 'pinia';
import { cal } from '@/utils/decimal'
import { getWeek, getKey } from '@/utils/common';
import { useCarStore } from '@/store/modules/car';
import { useUserStore } from '@/store/modules/user';
const userStore = useUserStore();
const carStore = useCarStore();
const { orderInfo, totalPrice, carNum, merchant, type, dateTime } = storeToRefs(carStore);
export default {
data() {
return {
orderId: 0,
userInfo: {},
// 表单信息
form: {},
// 场馆信息
merchant,
orderInfo,
totalPrice,
carNum,
week: 0,
reducePrice: 0,
payPrice: 0,
cardId: 0,
getWeek,
// payType: 1,
isLogin: false,
disabled: false,
cardList: [],
currentCard: {},
// 支付密码是否正确
isPayPasswordCorrect: false,
disabledPayPayPassword: false,
payPassword: ''
};
},
onLoad(option) {
this.orderId = option.id;
this.reload();
// this.getUserCard();
},
onShow() {
// 登录状态
if (uni.getStorageSync('user_id') && uni.getStorageSync('access_token')) {
this.isLogin = true;
}
this.openLogin();
},
methods: {
async reload() {
const app = this;
const { orderId, merchant, orderInfo } = this;
// 当前登录用户信息
const userInfo = await userStore.fetchUserInfo();
app.userInfo = userInfo;
// 整理订单信息
app.form = Object.assign({}, app.form, carStore);
if(orderInfo.length > 0){
app.form.orderInfo = orderInfo
app.form.merchantId = merchant.merchantId
app.form.merchantName = merchant.merchantName
app.form.merchantCode = merchant.merchantCode
app.form.comments = merchant.merchantName + ' ' + orderInfo[0].fieldName + ' ' + orderInfo[0].dateTime;
app.form.payPrice = totalPrice
app.form.type = 1 // 订单类型 0商城订单 1预定订单
app.form.payType = 1 // 支付方式 0余额支付 2微信支付
}
if (orderId > 0) {
Api.getOrder(orderId).then((data) => {
app.form = Object.assign({}, app.form, data);
});
}
},
// 读取会员卡信息
getUserCard(){
const app = this
const { form } = this
const { userId } = userInfo
UserCardApi.pageUserCard({userId,sid: app.merchantId}).then(res => {
app.cardList = res.list
const item = res.list[0]
app.currentCard = item
// 年卡
if(item.type == 1){
// 支付方式
app.form.payType = 7
app.form.cardId = item.cardId
// 折扣率
const discount = cal.cheng(item.discount,0.1)
// 折后金额
const lastTotalPrice = cal.cheng(form.totalPrice,discount)
// 减少的金额
app.form.reducePrice = cal.jian(form.totalPrice,lastTotalPrice)
// 实付额
app.form.payPrice = lastTotalPrice
}
})
},
onDisabled() {
this.disabled = !this.disabled;
},
navTo(url) {
uni.navigateTo({
url
});
},
// 切换支付方式
onPayType(index) {
this.form.payType = index;
},
openUrl(url) {
if (!this.isLogin) {
this.$refs.login.open('bottom');
return false;
} else {
uni.navigateTo({
url
});
}
},
// 弹出登录提示框
openLogin() {
if (!this.isLogin) {
this.$refs.login.open('bottom');
return false;
}
},
// 验证支付密码
onPayPassword(){
if(this.payPassword == '' || !this.payPassword){
uni.showToast({
title: '请输入支付密码',
icon: 'none'
});
return false;
}
this.disabledPayPayPassword = true
const { payPassword } = this
checkPayPassword({payPassword}).then(res => {
this.disabledPayPayPassword = false
this.isPayPasswordCorrect = true
this.save()
}).catch(err => {
uni.showToast({
title: err.message,
icon: 'none'
});
this.disabledPayPayPassword = false
})
},
save() {
const app = this;
const { form } = this
if (!this.disabled) {
uni.showToast({
title: '请先阅读并同意服务协议',
icon: 'none'
});
return false;
}
// if (carStore.orderInfo.length == 0) {
// uni.showToast({
// title: '订单信息不存在',
// icon: 'none'
// });
// return false;
// }
if(form.payType == 0 && !this.isPayPasswordCorrect){
this.$refs.payPasswordForm.open('center');
return false;
}
uni.showLoading({
title: '订单提交中.'
});
Api.addOrder(form)
.then((data) => {
const orderInfo = data;
// 调起微信支付
if (form.payType == 1) {
// #ifdef MP-WEIXIN
uni.requestPayment({
provider: orderInfo.provider, // 服务提供商
timeStamp: orderInfo.timeStamp, // 时间戳
nonceStr: orderInfo.nonceStr, // 随机字符串
package: orderInfo.package,
signType: orderInfo.signType, // 签名算法
paySign: orderInfo.paySign, // 签名
success: function (res) {
// 业务逻辑。。。
uni.showToast({
title: '支付成功',
icon: 'success'
});
setTimeout(function () {
app.disabled = false;
uni.reLaunch({
url: '/pages/order/order',
success: function (e) {
var page = getCurrentPages()[0];
if (page == undefined || page == null) return;
page.onLoad();
}
});
}, 1500);
},
fail: function (err) {
console.log('支付失败', err);
app.disabled = false;
uni.reLaunch({
url: '/pages/order/order',
success: function (e) {
var page = getCurrentPages()[0];
if (page == undefined || page == null) return;
page.onLoad();
}
});
// uni.switchTab({
// url: '/pages/order/order'
// })
}
});
// #endif
}
// 使用余额支付
if (form.payType == 0) {
if (!orderInfo) {
return uni.showToast({
title: '支付失败',
icon: 'error'
});
}
if (orderInfo) {
uni.showToast({
title: '支付成功',
icon: 'success'
});
setTimeout(function () {
app.disabled = false;
uni.reLaunch({
url: '/pages/order/order',
success: function (e) {
var page = getCurrentPages()[0];
if (page == undefined || page == null) return;
page.onLoad();
}
});
}, 1500);
}
}
uni.hideLoading();
})
.catch((res) => {
uni.showToast({
title: res.message || '请检查您的网络.',
icon: 'none'
});
uni.hideLoading();
});
}
}
};
</script>
<style>
page {
background-size: 100%;
background-repeat: no-repeat;
background-color: #f0f2f5;
width: 750rpx;
overflow-x: hidden;
}
</style>
<style lang="scss" scoped>
.container {
}
.checkout-car {
width: 700rpx;
left: 25rpx;
position: fixed;
bottom: 30rpx;
display: flex;
justify-content: space-between;
background-color: #000000;
border-radius: 100px;
align-items: center;
.car-selected {
color: #ccc;
display: flex;
align-items: center;
padding: 0 20rpx;
}
.car-total {
display: flex;
color: #ebcf00;
align-items: center;
padding-left: 40rpx;
.save-btn {
}
}
}
.card-actions {
display: flex;
flex-direction: row;
justify-content: flex-end;
height: 45px;
border-top: 1px #eee solid;
}
.card-actions-item {
display: flex;
flex-direction: row;
align-items: center;
.web-text-heading {
font-size: 38rpx;
margin-left: 28rpx;
}
}
.card-actions-item-text {
font-size: 12px;
color: #666;
margin-left: 5px;
}
.xieyi {
margin-bottom: 80rpx;
padding: 0 30rpx;
.text {
margin-left: 5rpx;
.link {
color: #0f80ff;
}
}
}
.pay-password-card{
width: 600rpx;
height: 400rpx;
margin: 30rpx auto;
line-height: 2rem;
background-color: #ffffff;
text-align: center;
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
}
.to-pay-btn {
width: 500rpx !important;
margin: 40rpx auto;
}
</style>
+772
View File
@@ -0,0 +1,772 @@
<template>
<view class="container">
<!-- <view class="merchant-name">{{ merchant.merchantName }}</view> -->
<uv-tabs :list="list" :itemStyle="{height: '58px'}" :activeStyle="{ color: '#2ba91c'}" lineColor="#2ba91c"
:inactiveStyle="{ color: '#808080' }"></uv-tabs>
<view class="uni-padding-wrap uni-common-mt">
<uni-segmented-control :current="current" :values="items" activeColor="#2ba91c" inActiveColor="#ff0000"
@clickItem="onClickItem" />
</view>
<view class="uni-badge-wrap">
<view class="badge-item">
<uv-badge :isDot="true" type="blank"></uv-badge>
<text class="web-text-secondary">可预约</text>
</view>
<view class="badge-item">
<uv-badge :isDot="true" type="info"></uv-badge>
<text class="web-text-secondary">已出售</text>
</view>
<view class="badge-item">
<uv-badge :isDot="true" type="success"></uv-badge>
<text class="web-text-secondary">我的选择</text>
</view>
<view class="badge-item">
<uv-badge :isDot="true" type="warning"></uv-badge>
<text class="web-text-secondary">已预定半场</text>
</view>
<!-- error | warning | success | primary | info -->
</view>
{{ order }}
<view class="checkout-body web-text-primary">
<template v-for="(item,index) in periodList" :key="index">
<view class="period-item">
<view class="period">{{ item.timePeriod }}</view>
<view class="field-list">
<template v-for="(item2,index2) in fieldList" :key="index2">
<view class="field" :class="isActive(`${item.periodId}_${item2.fieldId}`) ? 'active web-bg-success' : ''" @click="onField(index,index2)">
<text class="field-name">{{ item2.fieldName }}</text>
<text class="price">{{ item.price }}元</text>
</view>
</template>
</view>
</view>
</template>
<!-- 排版样式备份 -->
<view class="period-item" style="display: none;">
<view class="period">18:00 - 20:00</view>
<view class="field-list">
<view class="field web-bg-info">
<text class="field-name">1号场地</text>
<text class="price">580元</text>
</view>
<view class="field web-bg-success active">
<text class="field-name">2号场地</text>
<text class="price">580元</text>
</view>
<view class="field web-bg-warning">
<text class="field-name">3号场地</text>
<text class="price">580元</text>
</view>
</view>
</view>
</view>
</view>
<view class="checkout-car">
<view class="car-selected">
<uv-icon name="shopping-cart" size="36" color="#ffffff"></uv-icon>
<uv-badge type="error" max="99" :value="order.length"></uv-badge>
<!-- <text>已选</text> -->
</view>
<view class="car-total">
<text style="color: #ebcf00;">¥</text>
<uv-count-to :startVal="0" decimals="2" duration="100" color="#ebcf00" bold :endVal="total"></uv-count-to>
</view>
<uv-button class="save-btn"
:customStyle="{background: 'linear-gradient(to right, #70b915, #008e04)',borderRadius: '0 30px 30px 0',color: '#ffffff', order: 'none', padding: '22px 30px'}"
text="去支付" @click="save"></uv-button>
</view>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
</template>
<script>
import * as GoodsApi from '@/api/shop/goods';
import * as Api from '@/api/layout';
import * as MerchantApi from '@/api/shop/merchant';
import * as MpMenuApi from '@/api/cms/mp-menu/index';
import * as FieldApi from '@/api/booking/field';
import * as PeriodApi from '@/api/booking/period';
import {
useTenantStore
} from '@/store/modules/tenant';
const tenantStore = useTenantStore();
const lineBg =
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAOCAYAAABdC15GAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAFxSURBVHgBzZNRTsJAEIb/WTW+lpiY+FZPIDew3ABP4GJ8hxsI9zBpOYHeQDwBPQI+mRiRvpLojtPdYhCorQqF/6GdbGd2vvwzBXZcNAt4oj1ANeUoAT5iqkUjbEFLHNmhD1YPEvpZ3ghkGlVDCkc94/BmHMq998I5ONiY1ZBfpKAyuOtgAc5yOEDmYEWNh32BHF91sGHZHmwW4azciN9aQwnz3SJEgOmte+R2tdLprTYoa50mvuomlLpD4Y3oQZnov6D2RzCqI93bWOHaEmAGqQUyRBlZR1WfarcD/EJ2z8DtzDGvsMCwpm8XOCfDUsVOCYhiqRxI/CTQo4UOvjzO7Pow18vfywneuUHHUUxLn55lLw5JFpZ8bEUcY8oXdOLWiHLTxvoGpLqoUmy6dBT15o/ox3znpoycAmxUsiJTbs1cmxeVKp+0zmFIS7bGWiVghC7Vwse8jFKAX9eljh4ggKLLv7uaQvG9/F59Oo2SouxPu7OTCxN/s8wAAAAASUVORK5CYII=";
export default {
data() {
return {
id: 0,
list: [{
name: '周三',
value: '05月08日'
}, {
name: '周四',
value: '05月09日'
}, {
name: '周五',
value: '05月10日'
}, {
name: '周六',
value: '05月11日'
}, {
name: '周日',
value: '05月12日'
}, {
name: '周一',
value: '05月13日'
}, {
name: '周二',
value: '05月14日'
}],
week: 0,
items: ['全场', '半场'],
lineBg: lineBg,
// 时段
periodList: [],
// 场地
fieldList: [],
order: [],
// 订单总金额
total: 0,
keys: [],
// 场馆列表
merchant: {},
// 网站参数
fields: {},
// 幻灯片广告
ads: [],
// 小程序导航图标
navigation: [],
// 小程序导航图标(双排)
doubleNavigation: [],
isLogin: false,
disabled: false,
styleType: {
color: '#ff0000',
},
activeColor: {
color: '#303133',
}
}
},
onLoad(option) {
this.id = option.id
this.reload();
},
computed: {
total() {
const app = this
app.total = 0
app.order.map(d => {
console.log(d.totalPrice);
app.total = app.total + d.totalPrice
})
return app.total;
},
},
methods: {
async reload() {
const app = this
// 获取服务租户信息包
const info = await tenantStore.fetchTenantInfo();
// 登录状态
if (uni.getStorageSync('user_id') && uni.getStorageSync('access_token')) {
app.isLogin = true;
}
// 解析网站参数
if (info.fields) {
info.fields.map(d => {
const key = d.name;
app.fields[key] = d.value;
})
}
if (info.serverTime) {
this.week = info.serverTime.week
}
// 解析幻灯片数据
// if (info.ads) {
// const ad = info.ads.filter(d => d.adType == '幻灯片');
// const adsList = JSON.parse(ad[0].images);
// adsList.map(d => {
// app.ads.push(d.url);
// });
// }
// 解析网站logo
if (info.websiteLogo) {
uni.setStorageSync('app_logo', info.websiteLogo)
app.logo = info.websiteLogo
}
// 解析小程序导航图标
if (info.mpMenus) {
console.log('info.mpMenus: ', info.mpMenus);
const arr = info.mpMenus.filter(d => d.type == 2 && d.rows == 0)
const arr1 = info.mpMenus.filter(d => (d.type == 2 && d.rows == 1))
const arr2 = info.mpMenus.filter(d => (d.type == 2 && d.rows == 2))
if (arr) {
app.navigation = arr
}
if (arr1) {
app.doubleNavigation.push(arr1)
}
if (arr2) {
app.doubleNavigation.push(arr2)
}
}
// 请求数据
Promise.all([app.getMerchant(), app.getBookingField(), app.getBookingPeriod()])
.then((res) => {
app.merchant = res[0];
console.log('Promise.all', app.merchant);
})
},
getSiteInfo() {
const app = this
return new Promise((resolve, reject) => {
Api.getSiteInfo()
.then(result => {
resolve(result)
})
.catch(reject)
})
},
onDisabled() {
this.disabled = !this.disabled;
},
navTo(url) {
uni.navigateTo({
url
})
},
listAdList() {
},
pageGoods() {
const app = this
return new Promise((resolve, reject) => {
GoodsApi.pageGoods({})
.then(result => {
resolve(result.list)
})
.catch(reject)
})
},
getMerchantList() {
const app = this
return new Promise((resolve, reject) => {
MerchantApi.listMerchant({})
.then(result => {
resolve(result)
})
.catch(reject)
})
},
getMerchant() {
MerchantApi.getMerchant(this.id).then(data => {
app.merchant = data
if (data.files) {
app.ads = JSON.parse(data.files)
}
uni.setNavigationBarTitle({
title: data.merchantName
})
})
},
getBookingField() {
FieldApi.listField({
merchantId: this.id,
isStatus: 1
}).then(list => {
this.fieldList = list;
})
},
getBookingPeriod() {
const {
week
} = this
const merchantId = this.id
const isStatus = 1
PeriodApi.listPeriod({
merchantId,
isStatus,
week
}).then(list => {
this.periodList = list;
})
},
change(e) {
const {
index
} = e.detail;
const id = this.merchant[index].merchantId
this.openUrl(`/package/booking/booking?id=${id}`)
},
callPhone(phone) {
uni.makePhoneCall({
phoneNumber: phone
});
},
onMap() {
uni.getLocation({
type: 'gcj02', //返回可以用于uni.openLocation的经纬度
success: function(res) {
console.log('返回可以用于uni.openLocation的经纬度: ', res);
const latitude = this.merchant.latitude;
const longitude = this.merchant.longitude;
uni.openLocation({
latitude: latitude,
longitude: longitude,
success: function() {
console.log('success');
}
});
}
});
},
openUrl(url) {
if (!this.isLogin) {
this.$refs.login.open('bottom')
return false;
} else {
uni.navigateTo({
url
});
}
},
onField(i,i2) {
const app = this
const p = this.periodList[i]
const f = this.fieldList[i2]
const key = `${p.periodId}_${f.fieldId}`
const index = app.order.findIndex(d => d.key == key)
console.log('index: ',index);
console.log('app.order.length: ',app.order.length);
if(index >= 0){
app.order.splice(index,1)
}else{
if(app.order.length > 1){
uni.showToast({
title: '最多预定两个场地!',
icon: 'none'
})
return false
}
// 添加到购物车
app.order.push({
key,
fid: f.fieldId,
pid: p.periodId,
totalPrice: p.price
})
}
// this.periodList[i].key = key
// this.fieldList[i2].key = key
// console.log('this.: ',this.fieldList[i2]);
// if(!f.selected){
// app.fieldList[i].key = key
// app.order.push({
// key: key,
// fid: f.fieldId,
// pid: p.periodId
// })
// }else{
// app.fieldList[i].key = undefined
// const index = app.order.filter((d) => d.fid == f.fid && d.pid == p.pid)
// app.order.splice(index,1)
// }
// f.selected = !f.selected
},
isActive(text){
const index = this.order.find(d => d.key == text)
if(index){
return true
}
},
save(){
uni.navigateTo({
url: '/package/booking/cashier'
})
}
}
}
</script>
<style>
page {
background-size: 100%;
background-repeat: no-repeat;
background-color: #f0f2f5;
width: 750rpx;
overflow-x: hidden;
}
</style>
<style lang="scss" scoped>
.container {}
.merchant-name {
padding: 30rpx;
font-weight: 500;
font-size: 42rpx;
background-color: #ffffff;
}
.checkout-car{
width: 700rpx;
left: 25rpx;
position: fixed;
bottom: 30rpx;
display: flex;
justify-content: space-between;
background-color: #000000;
border-radius: 100px;
align-items: center;
.car-selected{
color: #ccc;
display: flex;
align-items: center;
padding: 0 20rpx;
}
.car-total{
display: flex;
color: #ebcf00;
align-items: center;
.save-btn{
}
}
}
.booking-tel {
position: fixed;
z-index: 1;
top: 270px;
right: 0;
width: 80px;
height: 38px;
border-radius: 50px 0 0 50px;
background: linear-gradient(to right, #ccff66, #008e04);
display: flex;
align-items: center;
justify-content: center;
color: #ffffff;
font-size: 26rpx;
}
.popup-booking-tel {
background-color: #ffffff;
width: 560rpx;
min-height: 400rpx;
border-radius: 20rpx;
margin: auto;
padding: 20px;
z-index: 9999;
display: flex;
flex-direction: column;
.title {
font-weight: bold;
font-size: 38rpx;
text-align: center;
padding: 10px 0;
}
.desc {
line-height: 2rem;
}
}
.uni-padding-wrap {
width: 180rpx;
margin: 20rpx auto;
}
.uni-badge-wrap {
display: flex;
justify-content: space-around;
.badge-item {
display: flex;
justify-content: center;
align-items: center;
font-size: 28rpx;
text {
padding: 2rpx;
}
.web-text-secondary {
padding-left: 8rpx;
}
}
}
.checkout-body {
padding: 20rpx;
.period-item {
margin: 12rpx 0;
.period {
line-height: 2rem;
padding-left: 12rpx;
font-size: 28rpx;
}
.field-list {
display: flex;
flex-wrap: wrap;
.web-bg-info {
// color: #cccccc !important;
background-color: #e6e6e6 !important;
// border: none !important;
}
.web-bg-success {
// color: #ffffff !important;
// background-color: #2ba91c !important;
// border: none !important;
color: #2ba91c !important;
border: 1px solid #2ba91c !important;
}
.web-bg-warning {
// color: #ffffff !important;
// background-color: #8fe01e !important;
// border: none !important;
background-color: #c9e294 !important;
}
.active {
&:before {
border-radius: 0 0 12rpx 0;
content: "";
position: absolute;
right: 0;
bottom: 0;
border: 24rpx solid #2ba91c;
border-top-color: transparent;
border-left-color: transparent;
}
&:after {
content: "";
width: 5px;
height: 10px;
position: absolute;
right: 3px;
bottom: 4px;
border: 1px solid #fff;
border-top-color: transparent;
border-left-color: transparent;
transform: rotate(45deg);
border-radius: 4rpx;
}
}
.field {
width: 118rpx;
height: 118rpx;
margin: 9rpx;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
border-radius: 16rpx;
line-height: 1.3rem;
position: relative;
color: #333333;
background-color: #ffffff;
border: 1px solid #808080;
.field-name {
font-size: 23rpx;
}
.price {
font-size: 25rpx;
}
}
}
}
}
.xieyi {
margin: 30rpx auto;
padding: 20rpx 30rpx;
.text {
margin-left: 5rpx;
.link {
color: #0f80ff;
}
}
}
// .segmented {
// display: block;
// justify-content: space-around;
// text-align: center;
// width: 200rpx;
// margin: auto;
// color: #ffffff;
// .item {
// color: #666;
// font-size: 28rpx;
// padding: 0 12rpx;
// }
// .active {
// color: #333;
// font-size: 30rpx;
// font-weight: 500;
// }
// }
.user-oreder {
padding: 16px 0;
.web-cell-content {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.web-text-center {
text-align: center;
}
}
.card-title {
width: 700rpx;
margin: 12rpx auto;
font-size: 38rpx;
font-weight: 500;
margin-top: 32rpx;
}
.merchant-card-title {
width: 700rpx;
margin: 12rpx auto;
font-size: 40rpx;
font-weight: 500;
margin-top: 32rpx;
}
.card-body {
width: 740rpx;
margin: auto;
.merchant-card {
margin: 12rpx auto;
background: #ffffff;
border-radius: 10rpx;
border-color: slategrey;
border-radius: 16rpx;
.merchant-image {
width: 200rpx;
border-radius: 16rpx 16rpx 0 0;
height: 140rpx !important;
}
.merchant-name {
padding: 12rpx;
font-weight: 500;
font-size: 26rpx;
text-align: center;
}
.merchant-desc {
width: 400rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
@mixin flex($direction: row) {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: $direction;
}
.navigation {
padding: 0 30rpx 0 30rpx;
}
.scroll-list {
@include flex(column);
&__item {
margin-right: 20px;
&__image {
width: 60px;
height: 60px;
border-radius: 4px;
}
&__text {
color: $uni-text-color-placeholder;
text-align: center;
font-size: 12px;
margin-top: 5px;
}
}
&__line {
@include flex;
margin-top: 10px;
&__item {
margin-right: 30px;
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
&__image {
width: 61px;
height: 48px;
}
&__text {
margin-top: 5px;
color: $uni-text-color-placeholder;
font-size: 12px;
text-align: center;
}
&--no-margin-right {
margin-right: 0;
}
}
}
&__line__item__text {
white-space: nowrap;
}
}
</style>
+701
View File
@@ -0,0 +1,701 @@
<template>
<view class="container">
<!-- deBug信息 -->
<view v-if="merchant" class="web-debug web-text-success" style="display: none;">
场馆ID:{{ merchant.merchantId }} 场馆编号:{{ merchant.merchantCode }} 场馆名称:{{ merchant.merchantName }}
日期:{{ dateTime }}
星期:{{ week }}
订单总金额:{{ totalPrice }}
类型:{{ type }}
场地信息:{{ orderInfo }}
</view>
<!-- <view class="merchant-name">{{ merchant.merchantName }}</view> -->
<uv-tabs :list="next7day" :itemStyle="{height: '58px'}" :activeStyle="{ color: '#2ba91c'}" lineColor="#2ba91c"
:inactiveStyle="{ color: '#808080' }" @change="onDateTime"></uv-tabs>
<view class="uni-padding-wrap uni-common-mt">
<uni-segmented-control :current="current" :values="items" activeColor="#2ba91c" inActiveColor="#ff0000"
@clickItem="onType" />
</view>
<!-- 状态说明 -->
<view class="uni-badge-wrap">
<view class="badge-item">
<uv-badge :isDot="true" type="blank"></uv-badge>
<text class="web-text-secondary">可预约</text>
</view>
<view class="badge-item">
<uv-badge :isDot="true" type="info"></uv-badge>
<text class="web-text-secondary">已出售</text>
</view>
<view class="badge-item">
<uv-badge :isDot="true" type="success"></uv-badge>
<text class="web-text-secondary">我的选择</text>
</view>
<view class="badge-item">
<uv-badge :isDot="true" type="warning"></uv-badge>
<text class="web-text-secondary">已预定半场</text>
</view>
</view>
<!-- 场地列表 -->
<!-- <uv-empty mode="data" v-if="periodList.length == 0"
icon="https://cdn.uviewui.com/uview/empty/data.png"></uv-empty> -->
<view class="checkout-body web-text-primary" v-if="periodList.length > 0">
<template v-for="(item,index) in periodList" :key="index">
<view class="period-item">
<view class="period">{{ item.timePeriod }}</view>
<view class="field-list">
<template v-for="(field,index2) in item.fieldList" :key="index2">
<view class="field"
:class="isActive(field)"
@click="onField(field,item)">
<text class="field-name">{{ field.fieldName }}</text>
<text class="price">{{ item.price }}元</text>
</view>
</template>
</view>
</view>
</template>
<!-- 排版样式备份 -->
<view class="period-item" style="display: none;">
<view class="period">18:00 - 20:00</view>
<view class="field-list">
<view class="field web-bg-info">
<text class="field-name">1号场地</text>
<text class="price">580元</text>
</view>
<view class="field web-bg-success active">
<text class="field-name">2号场地</text>
<text class="price">580元</text>
</view>
<view class="field web-bg-warning">
<text class="field-name">3号场地</text>
<text class="price">580元</text>
</view>
</view>
</view>
</view>
</view>
<!-- 支付按钮 -->
<uv-gap height="50"></uv-gap>
<view class="checkout-car">
<view class="car-selected" @click="openCarInfo">
<uv-icon name="shopping-cart" size="36" color="#ffffff"></uv-icon>
<uv-badge type="error" max="99" :value="carNum"></uv-badge>
</view>
<view class="car-total">
<text style="color: #ebcf00;">¥</text>
<uv-count-to :startVal="0" decimals="2" duration="100" color="#ebcf00" bold
:endVal="totalPrice"></uv-count-to>
</view>
<uv-button class="save-btn"
:disabled="orderInfo.length == 0"
:customStyle="{background: 'linear-gradient(to right, #70b915, #008e04)',borderRadius: '0 30px 30px 0',color: '#ffffff', border: 'none', padding: '22px 30px'}"
text="下一步" @click="save"></uv-button>
</view>
<!-- 展示购物车 -->
<uni-popup ref="popup" style="margin-bottom: 200px;">
<uni-card :title="`购物车`" extra="关闭" :border="false" :is-shadow="false" :padding="0" @click="closeCarInfo">
<uv-cell-group :customStyle="{backgroundColor: '#ffffff'}" :border="false">
<block v-for="(item,index) in orderInfo" :key="index">
<uv-cell :title="`${item.fieldName} ¥${item.price}`" :label="`${item.dateTime}`"
:cellStyle="{padding: '10px 5px'}">
<template v-slot:right-icon>
<uni-icons type="trash" size="20" color="#f76b4e" @click="remove(item)"></uni-icons>
<text class="web-text-secondary" style="font-size: 24rpx;" @click="remove(item)">移除</text>
</template>
</uv-cell>
</block>
</uv-cell-group>
</uni-card>
<uv-gap height="70"></uv-gap>
</uni-popup>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
</template>
<script>
import * as Api from '@/api/layout';
import * as MerchantApi from '@/api/shop/merchant';
import * as FieldApi from '@/api/booking/field';
import * as PeriodApi from '@/api/booking/period';
import {
storeToRefs
} from 'pinia';
import {
useCarStore
} from '@/store/modules/car';
import {
getWeek,
getKey
} from '@/utils/common';
const carStore = useCarStore();
const {
orderInfo,
totalPrice,
carNum,
merchant,
type,
dateTime,
childrenPrice
} = storeToRefs(carStore)
export default {
data() {
return {
// 场馆ID
merchantId: 0,
// 场馆信息
merchant,
// 未来7天
next7day: [],
// 预定信息
orderInfo,
// 订单总金额
totalPrice,
// 儿童票价
childrenPrice,
// 预定日期
dateTime: null,
// 0全场 1半场
type: 0,
// 星期几
week: 0,
// 是否可以预定半场
isHalf: 0,
// 服务器时间
serverTime: {},
items: ['全场', '半场'],
// 搜索条件
where: {},
// 时段
periodList: [],
// 场地
fieldList: [],
// 选中的场地
selection: [],
// 是否已登录
isLogin: false,
// 是否同意协议
disabled: false,
// 购物车信息
showCarInfo: false
}
},
onLoad(option) {
this.merchantId = option.id
this.reload();
},
onShow() {
// 登录状态
if (uni.getStorageSync('user_id') && uni.getStorageSync('access_token')) {
this.isLogin = true;
}
},
computed: {
totalPrice() {
const app = this
let totalPrice = 0;
app.selection.map(d => {
totalPrice = totalPrice + d.price
})
carStore.totalPrice = totalPrice
console.log('totalPrice: ',totalPrice);
return totalPrice;
},
carNum() {
return this.selection.length;
}
},
methods: {
async reload() {
const app = this
// 请求数据
uni.showLoading({
title: '数据读取中.'
})
Promise.all([app.getServerTime(), app.getNext7day(), app.getMerchant()]).then(res => {
const serverTime = res[0];
const next7day = res[1];
const merchant = res[2];
app.serverTime = serverTime;
app.next7day = next7day;
app.merchant = merchant;
// 修改标题
uni.setNavigationBarTitle({
title: merchant.merchantName
})
// 保存场馆信息
carStore.setMerchant(merchant)
// 加载预定日期
app.next7day = next7day.map((d, i) => {
if (!app.dateTime && i == 0) {
app.dateTime = d.dateTime
app.week = d.week
carStore.dateTime = d.dateTime
}
d.name = getWeek(d.week);
d.value = d.date;
return d
})
// 加载时段列表
app.getBookingPeriod();
// 加载场地列表
// app.getBookingField();
// 关闭加载状态
}).catch(() => {
uni.showToast({
title: '请检查您的网络.',
icon: 'none'
})
uni.hideLoading()
})
},
onDisabled() {
this.disabled = !this.disabled;
},
onDateTime(e) {
console.log('e: ', e);
const {
serverTime
} = this
this.week = e.week
this.dateTime = e.dateTime
carStore.dateTime = e.dateTime
carStore.orderInfo = []
this.selection = []
this.reload()
},
onType(e) {
const index = e.currentIndex
if (index == 0) {
this.type = 0;
this.isHalf = 0;
}
if (index == 1) {
this.type = 1;
this.isHalf = 1;
}
this.reload()
},
getMerchant() {
return new Promise((resolve, reject) => {
MerchantApi.getMerchant(this.merchantId).then(result => {
resolve(result)
}).catch(reject)
})
},
getServerTime() {
return new Promise((resolve, reject) => {
Api.getServerTime()
.then(result => {
resolve(result)
})
.catch(reject)
})
},
getNext7day() {
return new Promise((resolve, reject) => {
Api.getNext7day()
.then(result => {
resolve(result)
})
.catch(reject)
})
},
// getBookingField() {
// FieldApi.listField({
// merchantId: this.merchantId,
// isStatus: 1,
// isHalf: this.isHalf,
// dateTime: `${this.dateTime}`
// }).then(list => {
// this.fieldList = list;
// })
// },
getBookingPeriod() {
const {
serverTime
} = this
const now = new Date();
const hours = now.getHours();
const minutes = now.getMinutes()
const startTime = serverTime.today == this.dateTime ? String(hours) + String(minutes) : undefined
const week = this.week == 0 ? 7 : this.week
PeriodApi.listPeriod({
merchantId: this.merchantId,
isStatus: 0,
week,
dateTime: `${this.dateTime}`,
startTime,
half: this.isHalf
}).then(list => {
this.periodList = list;
uni.hideLoading()
}).catch(err => {
this.periodList = [];
uni.showToast({
title: err.message,
icon: 'none'
})
uni.hideLoading()
if(err.message == '您还有未支付订单,请先支付'){
setTimeout(() => {
return uni.switchTab({
url: '/pages/order/order'
});
}, 1000)
}
})
},
callPhone(phone) {
uni.makePhoneCall({
phoneNumber: phone
});
},
openCarInfo() {
// this.showCarInfo = !this.showCarInfo;
// 通过组件定义的ref调用uni-popup方法 ,如果传入参数 ,type 属性将失效 ,仅支持 ['top','left','bottom','right','center']
this.$refs.popup.open('bottom')
},
closeCarInfo() {
this.$refs.popup.close()
},
onMap() {
uni.getLocation({
type: 'gcj02', //返回可以用于uni.openLocation的经纬度
success: function(res) {
console.log('返回可以用于uni.openLocation的经纬度: ', res);
const latitude = this.merchant.latitude;
const longitude = this.merchant.longitude;
uni.openLocation({
latitude: latitude,
longitude: longitude,
success: function() {
console.log('success');
}
});
}
});
},
onField(item, period) {
// 已被预定
if(item.sold){
return
}
const app = this
const { merchant } = this
// 时段
// const p = this.periodList[i]
// 场地
// const f = this.fieldList[i2]
const key = getKey(`${this.dateTime}${item.timePeriod}${this.merchantId}${item.fieldId}`)
const index = app.selection.findIndex(d => d.key == key)
if (index >= 0) {
app.selection.splice(index, 1)
} else {
if (app.selection.length > 1) {
uni.showToast({
title: '最多预定两个场地!',
icon: 'none'
})
return false
}
// 计算订单总金额
// let totalPrice = 0
// app.selection.map(d => {
// console.log(d);
// totalPrice = totalPrice + d.totalPrice
// })
const split = item.timePeriod.split('-')
// console.log('aaaaaaaaa',{
// key,
// merchantId: this.merchantId,
// merchantCode: this.merchantCode,
// fieldId: item.fieldId,
// fieldName: item.fieldName,
// price: item.price,
// merchantName: this.merchantName,
// isChildren: item.isChildren,
// isHalf: this.type,
// timePeriod: item.timePeriod,
// periodId: item.periodId,
// startTime: `${split[0].trim()}:00`,
// endTime: `${split[1].trim()}:00`,
// orderCode: key,
// dateTime: `${this.dateTime}`,
// comments: `${this.dateTime} (${getWeek(this.week)}) ${item.timePeriod}`,
// });
// 添加到购物车
app.selection.push({
key,
merchantId: this.merchantId,
merchantCode: merchant.merchantCode,
fieldId: item.fieldId,
fieldName: item.fieldName,
price: item.price,
childrenPrice: period.childrenPrice,
adultNum: 1,
childrenNum: 0,
merchantName: merchant.merchantName,
isChildren: item.isChildren,
isHalf: this.type,
timePeriod: item.timePeriod,
periodId: item.periodId,
startTime: `${split[0].trim()}:00`,
endTime: `${split[1].trim()}:00`,
orderCode: key,
dateTime: `${this.dateTime}`,
comments: `${this.dateTime} (${getWeek(this.week)}) ${item.timePeriod}`,
})
console.log(app.selection);
console.log('period: ',period);
// 是否支持儿童票
console.log('item.isChildren: ',item.isChildren);
if(item.isChildren == 1){
console.log('item.isChildren2: ',item.isChildren);
carStore.childrenPrice = period.childrenPrice
}else{
carStore.childrenPrice = 0
}
carStore.orderInfo = app.selection
carStore.carNum = app.selection.length
carStore.totalPrice = totalPrice
carStore.payPrice = totalPrice
carStore.setPeriod(period)
}
},
getStratTime(value){
const split = value.split('-')
const timeText = split[0].replace(' ', '')
const startTime = new Date(`${this.dateTime} ${timeText}:00`).getTime()
return startTime / 1000 || 0;
},
isActive(item) {
const index = this.selection.find(d => d.key == getKey(`${this.dateTime}${item.timePeriod}${this.merchantId}${item.fieldId}`))
if(item.sold){
if(item.isHalf == 1){
return 'web-bg-warning'
}
return 'web-bg-info'
}
if (index) {
return 'active web-bg-success'
}
},
// isActive(text,item) {
// const index = this.selection.find(d => d.key == getKey(text))
// if(item.sold){
// if(item.isHalf == 1){
// return 'web-bg-warning'
// }
// return 'web-bg-info'
// }
// if (index) {
// return 'active web-bg-success'
// }
// },
remove(item) {
const index = this.selection.findIndex(d => d.key == item.key)
this.selection.splice(index, 1)
carStore.orderInfo = this.selection
},
save() {
const {
selection
} = this
uni.$uv.route({
url: '/package/booking/confirm'
})
}
}
}
</script>
<style>
page {
background-size: 100%;
background-repeat: no-repeat;
background-color: #f0f2f5;
width: 750rpx;
overflow-x: hidden;
}
</style>
<style lang="scss" scoped>
.container {}
.merchant-name {
padding: 30rpx;
font-weight: 500;
font-size: 42rpx;
background-color: #ffffff;
}
.checkout-car {
width: 700rpx;
left: 25rpx;
position: fixed;
bottom: 30rpx;
display: flex;
justify-content: space-between;
background-color: #000000;
border-radius: 100px;
align-items: center;
.car-selected {
color: #ccc;
display: flex;
align-items: center;
padding: 0 20rpx;
position: relative;
}
.car-total {
display: flex;
color: #ebcf00;
align-items: center;
.save-btn {}
}
}
.popup-car-info {
margin-bottom: 100px;
padding: 20rpx;
background-color: #ffffff;
width: 660rpx;
margin: 150rpx auto;
}
.uni-padding-wrap {
width: 180rpx;
margin: 20rpx auto;
}
.uni-badge-wrap {
display: flex;
justify-content: space-around;
.badge-item {
display: flex;
justify-content: center;
align-items: center;
font-size: 28rpx;
text {
padding: 2rpx;
}
.web-text-secondary {
padding-left: 8rpx;
}
}
}
.checkout-body {
padding: 24rpx;
.period-item {
margin: 12rpx 0;
.period {
line-height: 2rem;
padding-left: 12rpx;
font-size: 28rpx;
}
.field-list {
display: flex;
flex-wrap: wrap;
.web-bg-info {
background-color: #909399 !important;
color: #ffffff !important;
}
.web-bg-success {
color: #2ba91c !important;
border: 1px solid #2ba91c !important;
}
.web-bg-warning {
// background-color: #c9e294 !important;
}
.active {
&:before {
border-radius: 0 0 12rpx 0;
content: "";
position: absolute;
right: 0;
bottom: 0;
border: 24rpx solid #2ba91c;
border-top-color: transparent;
border-left-color: transparent;
}
&:after {
content: "";
width: 5px;
height: 10px;
position: absolute;
right: 3px;
bottom: 4px;
border: 1px solid #fff;
border-top-color: transparent;
border-left-color: transparent;
transform: rotate(45deg);
border-radius: 4rpx;
}
}
.field {
width: 118rpx;
height: 118rpx;
margin: 9rpx;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
border-radius: 16rpx;
line-height: 1.3rem;
position: relative;
color: #333333;
background-color: #ffffff;
border: 1px solid #808080;
.field-name {
font-size: 23rpx;
}
.price {
font-size: 25rpx;
}
}
}
}
}
.xieyi {
margin: 30rpx auto;
padding: 20rpx 30rpx;
.text {
margin-left: 5rpx;
.link {
color: #0f80ff;
}
}
}
</style>
+804
View File
@@ -0,0 +1,804 @@
<template>
<view class="container">
<!-- deBug信息 -->
<!-- <view >
{{ payPrice }}
{{ totalPrice }}
{{ orderInfo }}
</view> -->
<view style="display: none;">
{{ radiolist }}
{{ carNum }} {{ childrenPrice }} {{ orderInfo }}
</view>
<view v-if="merchant" class="web-debug web-text-success" style="display: none">
场馆ID:{{ merchant.merchantId }} 场馆编号:{{ merchant.merchantCode }} 场馆名称:{{ merchant.merchantName }} 日期:{{ dateTime }} 星期:{{ week }} 订单总金额:{{
totalPrice
}}
类型:{{ type }} 实付金额:{{ payPrice }} 时段: {{ period }} 场地信息:{{ orderInfo }}
</view>
<uni-card title="预约人信息" :border="false" :is-shadow="false">
<uv-cell-group :customStyle="{ backgroundColor: '#ffffff' }" :border="false">
<uv-cell title="真实姓名" :cellStyle="{ padding: '10px 5px' }" :border="false">
<template v-slot:value>
<text v-if="userInfo.realName">{{ userInfo.realName }}</text>
<text v-else class="text-blue-500" @click="navTo(`/package/user/personal`)">点击完善</text>
</template>
</uv-cell>
<uv-cell title="手机号码" :cellStyle="{ padding: '10px 5px' }" :value="userInfo.phone" :border="false" />
</uv-cell-group>
</uni-card>
<uni-card title="订单信息" :border="false" :is-shadow="false">
<uv-cell-group :customStyle="{ backgroundColor: '#ffffff' }" :border="false">
<block v-if="orderInfo.length == 0">
<span class="web-text-secondary">订单不存在</span>
</block>
<block v-if="orderInfo">
<uv-cell :title="`场馆`" :label="form.merchantName" :cellStyle="{ padding: '10px 5px' }" />
<block v-for="(item, index) in orderInfo" :key="index">
<uv-cell
:title="`${item.fieldName}`"
:label="`${item.dateTime} ${getWeek(this.week)} ${item.timePeriod}`"
:cellStyle="{ padding: '10px 5px' }"
v-if="childrenPrice > 0"
></uv-cell>
<uv-cell
:title="`${item.fieldName}`"
:label="`${item.dateTime} ${getWeek(this.week)} ${item.timePeriod}`"
:value="`¥${item.price}`"
:cellStyle="{ padding: '10px 5px' }"
v-else
/>
<!-- <uv-cell iconStyle="checkbox-mark" :cellStyle="{ padding: '10px 0' }" :border="false" v-if="childrenPrice > 0">
<template v-slot:title>
<uv-radio-group v-model="radiovalue" :disabled="orderId > 0" @change="onRadiovalue">
<uv-radio
:customStyle="{margin: '8px'}"
v-for="(val, index) in radiolist"
:key="index"
:label="`${val.name}¥${index == 0 ? item.price : childrenPrice}`"
:name="val.name">
</uv-radio>
</uv-radio-group>
</template>
</uv-cell> -->
<block v-for="(item,index) in radiolist" :key="index">
<uv-cell iconStyle="checkbox-mark" :cellStyle="{ padding: '10px 5px' }" :border="false" v-if="childrenPrice > 0">
<template v-slot:title>
<view class="flex">
<span style="margin-right: 40rpx;">{{ item.name }}</span>
<block v-if="item.name == '成人票'">
<span>¥{{ item.price }}</span>
<!-- <span style="padding-left:16rpx;"> x {{ carNum }}张</span> -->
</block>
<block v-if="item.name == '儿童票'">
<span>¥{{ item.price }}</span>
<!-- <span style="padding-left:16rpx;"> x {{ carNum2 }}张</span> -->
</block>
</view>
</template>
<template v-slot:value>
<view v-if="item.name === '成人票'">
<uv-number-box :min="0" :max="1000" v-model="carNum" :disabled="orderId > 0" @change="onAdultNum"></uv-number-box>
</view>
<view v-if="item.name === '儿童票'">
<uv-number-box :min="0" :max="1000" v-model="carNum2" :disabled="orderId > 0" @change="onAdultNum2"></uv-number-box>
</view>
</template>
</uv-cell>
</block>
</block>
</block>
</uv-cell-group>
</uni-card>
<uni-card :title="`选择支付方式`" :border="false" :is-shadow="false">
<uv-cell-group :customStyle="{ backgroundColor: '#ffffff' }" :border="false">
<block v-for="(item, index) in payment" :key="index">
<uv-cell
:title="`${item.name}`"
:icon="`${item.image}`"
:cellStyle="{ padding: '20rpx 10rpx', borderRadius: '8rpx', backgroundColor: item.type == payType ? '#f6fff1' : '' }"
:border="false"
@click="onPayType(item.type)"
>
<template v-slot:right-icon>
<uv-icon v-if="item.type == payType" size="30rpx" name="checkbox-mark"></uv-icon>
</template>
</uv-cell>
</block>
</uv-cell-group>
<view slot="actions" class="card-actions">
<view class="card-actions-item">
<span class="web-text-danger">已优惠¥{{ reducePrice }}</span>
<span class="web-text-heading">¥{{ payPrice || 0.0 }}</span>
</view>
</view>
</uni-card>
<view class="xieyi web-cell web-text-secondary web-cell-align-top">
<view class="web-cell web-cell-content web-cell-align-top">
<uni-icons type="circle" size="20" color="#a4a5a7" v-if="!disabled" @click="onDisabled"></uni-icons>
<uni-icons type="checkbox" size="20" color="#11a954" v-else @click="onDisabled"></uni-icons>
<view class="text" @click="onDisabled">
<text>同意以下服务条款</text>
<text class="link" @click.stop="navTo('/package/article/detail?articleId=501')">《广西体育中心预定条款》</text>
<text class="link" @click.stop="navTo('/package/article/detail?articleId=502')">《用户服务协议和隐私政策》</text>
</view>
</view>
</view>
<!-- 支付按钮 -->
<uv-gap height="50"></uv-gap>
<view class="checkout-car">
<view class="car-total">
<text style="color: #ebcf00">合计¥</text>
<uv-count-to decimals="2" duration="50" color="#ebcf00" bold :endVal="payPrice"></uv-count-to>
</view>
<uv-button
class="save-btn"
:disabled="!disabled"
:customStyle="{ background: 'linear-gradient(to right, #70b915, #008e04)', borderRadius: '0 30px 30px 0', color: '#ffffff', border: 'none', padding: '22px 30px' }"
text="提交订单"
@click="save"
></uv-button>
</view>
</view>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
<!-- 支付密码弹窗 -->
<uni-popup ref="payPasswordForm" type="center" border-radius="10px 10px 0 0">
<uni-card title="请输入支付密码" :border="false" :is-shadow="false" :padding="0">
<view class="pay-password-card">
<uni-forms ref="form" :label-width="80">
<uni-forms-item label="支付密码" name="payPassword" required>
<uv-code-input mode="box" dot :space="0" :maxlength="6" hairline v-model="payPassword" @finish="onPayPassword"></uv-code-input>
</uni-forms-item>
<!-- <uv-button
class="to-pay-btn"
:customStyle="{ background: 'linear-gradient(to right, #70b915, #008e04)', borderRadius: '30px', color: '#ffffff' }"
text="确定支付"
:disabled="disabledPayPayPassword"
@click="onPayPassword"
></uv-button> -->
</uni-forms>
<text @click="navTo(`/package/user/pay-password`)" class="web-text-primary">忘记支付密码?</text>
</view>
</uni-card>
</uni-popup>
</template>
<script>
import * as Api from '@/api/shop/order';
import * as UserApi from '@/api/booking/users';
import * as UserCardApi from '@/api/booking/userCard';
import * as PaymentApi from '@/api/system/payment';
import { checkPayPassword } from '@/api/passport/login';
import { storeToRefs } from 'pinia';
import { cal } from '@/utils/decimal';
import { getWeek, getKey } from '@/utils/common';
import { useCarStore } from '@/store/modules/car';
import { useUserStore } from '@/store/modules/user';
const userStore = useUserStore();
const carStore = useCarStore();
const { merchantId, orderInfo, period, totalPrice, reducePrice, payPrice, childrenPrice, carNum, carNum2, merchant, type, dateTime } = storeToRefs(carStore);
export default {
data() {
return {
orderId: 0,
userInfo: {},
// 表单信息
form: {
cardId: 0,
payType: 1
},
// 支付方式
payment: [],
// 场馆信息
merchant,
merchantId,
orderInfo,
carNum,
carNum2: 0,
week: 0,
totalPrice,
reducePrice: 0,
payPrice,
childrenPrice,
period,
cardId: 0,
getWeek,
payType: 1,
isLogin: false,
disabled: false,
cardList: [],
userCard: {},
// isRefresh: true,
// 支付密码是否正确
isPayPasswordCorrect: false,
disabledPayPayPassword: false,
payPassword: '',
// 折扣率
discount: 1,
// 票类型
radiolist: [
{
name: '成人票',
price: 50,
totalPrice: 50,
disabled: false
},
{
name: '儿童票',
price: 35,
totalPrice: 35,
disabled: false
}
],
radiovalue: '成人票'
};
},
onLoad(option) {
if (option.id) {
this.orderId = option.id;
this.form.orderId = option.id;
}
this.reload();
// this.getUserCard();
},
onShow() {
// 登录状态
if (uni.getStorageSync('user_id') && uni.getStorageSync('access_token')) {
this.isLogin = true;
}
this.openLogin();
},
// computed: {
// payPrice(){
// console.log('this.payPrice: ',this.payPrice);
// },
// carNum(){
// console.log('orderInfo[0].adultNum: ',this.adultNum);
// return this.adultNum;
// // return carStore.payPrice;
// }
// },
methods: {
async reload() {
const app = this;
const { form, orderId, merchant, totalPrice, orderInfo } = this;
// 当前登录用户信息
app.userInfo = await userStore.fetchUserInfo();
// 获取用户副表信息
UserApi.getByPhone({
phone: app.userInfo.phone
}).then((data) => {
if (data) {
app.hideUser = false;
app.userInfo.ouid = data.userId;
app.userInfo = Object.assign({}, app.userInfo, data);
}
});
// 整理订单信息
form.type = 1; // 订单类型 0商城订单 1预定订单
form.payPrice = totalPrice;
form.orderInfo = orderInfo;
app.payPrice = totalPrice;
if (merchant) {
app.merchantId = merchant.merchantId;
form.merchantId = merchant.merchantId;
form.merchantName = merchant.merchantName;
form.merchantCode = merchant.merchantCode;
form.comments = merchant.merchantName + ' ' + orderInfo[0].fieldName + ' ' + orderInfo[0].dateTime;
}
console.log('重新赋值订单信息: ', orderId);
// 重新赋值订单信息
if (orderId > 0) {
Api.getOrder(orderId).then((data) => {
app.form = data;
app.orderInfo = data.orderInfo;
app.totalPrice = data.totalPrice;
app.reducePrice = data.reducePrice;
app.payPrice = data.payPrice;
app.merchantId = data.merchantId;
app.childrenPrice = data.orderInfo[0].childrenPrice;
if(data.orderInfo[0].adultNum > 0){
app.radiovalue = '成人票'
app.carNum = data.orderInfo[0].adultNum
}
if(data.orderInfo[0].childrenNum > 0){
app.radiovalue = '儿童票'
app.carNum = data.orderInfo[0].childrenNum
}
carStore.setOrderInfo(data.orderInfo)
});
}
// 请求数据
Promise.all([app.getUserCard(), app.getPayment()]).then((res) => {
const userCard = res[0];
const payment = res[1];
// 当前可用会员卡
app.userCard = userCard;
// 支付方式列表
app.payment = payment.map((d) => {
if (d.type == 0) {
d.name = `${d.name} (余额¥${app.userInfo.balance})`;
}
if (d.type == 2 && userCard) {
d.name = `${userCard.name}(¥${userCard.remainingMoney})`;
}
return d;
});
if (userCard) {
// 整理表单字段
form.cardId = userCard.id;
form.payType = 2;
app.payType = 2;
// 1年卡
if (userCard.type == 1) {
}
// 2次卡
if (userCard.type == 2) {
}
// 3月卡
if (userCard.type == 3) {
}
// 4会员IC卡
if (userCard.type == 2) {
}
// 5充值卡
if (userCard.type == 5) {
// 折扣率
app.discount = cal.cheng(userCard.discount, 0.1);
// 订单金额
const orderPrice = totalPrice || form.totalPrice;
if (orderPrice) {
console.log('orderPrice: ', orderPrice);
// 折后金额
const lastTotalPrice = cal.cheng(orderPrice, app.discount);
console.log('折后金额: ', lastTotalPrice);
// 减少的金额
app.reducePrice = cal.jian(orderPrice, lastTotalPrice);
console.log('减少的金额: ', app.reducePrice);
// 实付额
app.payPrice = orderPrice * app.discount;
console.log('实付额: ', app.payPrice);
}
}
}
});
},
// 读取可用的会员卡
async getUserCard() {
const app = this;
return new Promise((resolve, reject) => {
const { merchantId } = this;
UserCardApi.findUseCard({
sid: merchantId
})
.then((result) => {
resolve(result);
})
.catch(reject);
});
},
// 读取支付方式列表
getPayment() {
const app = this;
return new Promise((resolve, reject) => {
PaymentApi.select({ status: true })
.then((result) => {
resolve(result);
})
.catch(reject);
});
},
onDisabled() {
this.disabled = !this.disabled;
},
navTo(url) {
uni.navigateTo({
url
});
},
// 切换支付方式
async onPayType(index) {
const app = this;
const { form, totalPrice, carNum, childrenPrice, radiovalue } = this;
app.payType = index;
app.form.payType = index;
app.form.cardId = 0;
console.log('childrenPrice: ', childrenPrice);
// 重新总金额
app.payPrice = 0;
app.reducePrice = 0;
await app.countTotalPrice()
if (index === 2) {
await app.reload();
}
},
openUrl(url) {
if (!this.isLogin) {
this.$refs.login.open('bottom');
return false;
} else {
uni.navigateTo({
url
});
}
},
// 弹出登录提示框
openLogin() {
if (!this.isLogin) {
this.$refs.login.open('bottom');
return false;
}
},
// 验证支付密码
onPayPassword() {
if (this.payPassword == '' || !this.payPassword) {
uni.showToast({
title: '请输入支付密码',
icon: 'none'
});
return false;
}
this.disabledPayPayPassword = true;
const { payPassword } = this;
checkPayPassword({ payPassword })
.then((res) => {
this.disabledPayPayPassword = false;
this.isPayPasswordCorrect = true;
this.save();
})
.catch((err) => {
uni.showToast({
title: err.message,
icon: 'none'
});
this.disabledPayPayPassword = false;
});
},
onAdultNum(e) {
const app = this;
const index = e.value;
app.carNum = index;
app.orderInfo[0].adultNum = index;
// 重新总金额
app.countTotalPrice()
},
onAdultNum2(e) {
const app = this;
const index = e.value;
app.carNum2 = index;
app.orderInfo[0].childrenNum = index;
// 重新总金额
app.countTotalPrice()
},
// 重新计算金额
countTotalPrice(){
const app = this
// 计算总金额
let total;
const prices = [];
app.orderInfo.map(d => {
prices.push(d.price * d.adultNum + d.childrenPrice * d.childrenNum);
})
// 使用reduce方法进行累加
const sum = prices.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
console.log(sum);
app.totalPrice = sum
app.payPrice = sum
},
save() {
const app = this;
console.log('payPrice000: ',app.payPrice);
console.log(carStore.payPrice)
const { form, merchant, orderInfo, totalPrice, payPrice } = this;
if (!this.disabled) {
uni.showToast({
title: '请先阅读并同意服务协议',
icon: 'none'
});
return false;
}
if (orderInfo.length == 0) {
uni.showToast({
title: '订单信息不存在',
icon: 'none'
});
return false;
}
if (form.payType == 2 && !app.userCard) {
uni.showToast({
title: '没有找到可用的会员卡',
icon: 'none'
});
return false;
}
if (form.payType == 0 && !this.isPayPasswordCorrect) {
app.$refs.payPasswordForm.open('center');
return false;
}
uni.showLoading({
title: '订单提交中.'
});
// console.log('payPrice22: ',carStore.payPrice);
form.payPrice = app.payPrice;
form.totalPrice = app.payPrice;
form.reducePrice = app.reducePrice;
// console.log('form: ',form);
// console.log({
// type: 1,
// orderId: form.orderId,
// merchantId: form.merchantId,
// merchantName: form.merchantName,
// merchantCode: form.merchantCode,
// // 订单金额
// totalPrice,
// // 实付金额
// payPrice,
// // 预定场地信息
// orderInfo: form.orderInfo,
// comments: form.comments,
// // 微信支付
// payType: form.payType,
// // 下单日期
// dateTime: form.dateTime,
// // 会员卡ID
// cardId: form.cardId
// });
// return false
Api.addOrder({
type: 1,
orderId: form.orderId,
merchantId: form.merchantId,
merchantName: form.merchantName,
merchantCode: form.merchantCode,
// 订单金额
totalPrice: app.payPrice,
// 实付金额
payPrice: app.payPrice,
// 预定场地信息
orderInfo: form.orderInfo,
comments: form.comments,
// 微信支付
payType: form.payType,
// 下单日期
dateTime: form.dateTime,
// 会员卡ID
cardId: form.cardId
})
.then((data) => {
const orderInfo = data;
// 调起微信支付
if (form.payType == 1) {
// #ifdef MP-WEIXIN
uni.requestPayment({
provider: orderInfo.provider, // 服务提供商
timeStamp: orderInfo.timeStamp, // 时间戳
nonceStr: orderInfo.nonceStr, // 随机字符串
package: orderInfo.package,
signType: orderInfo.signType, // 签名算法
paySign: orderInfo.paySign, // 签名
success: function (res) {
// 业务逻辑。。。
uni.showToast({
title: '支付成功',
icon: 'success'
});
setTimeout(function () {
app.disabled = false;
uni.reLaunch({
url: '/pages/order/order',
success: function (e) {
var page = getCurrentPages()[0];
if (page == undefined || page == null) return;
page.onLoad();
}
});
}, 1500);
},
fail: function (err) {
console.log('支付失败', err);
app.disabled = false;
uni.reLaunch({
url: '/pages/order/order',
success: function (e) {
var page = getCurrentPages()[0];
if (page == undefined || page == null) return;
page.onLoad();
}
});
// uni.switchTab({
// url: '/pages/order/order'
// })
}
});
// #endif
}
// 使用余额支付
if (form.payType == 0) {
if (!orderInfo) {
return uni.showToast({
title: '支付失败',
icon: 'error'
});
}
if (orderInfo) {
uni.showToast({
title: '支付成功',
icon: 'success'
});
setTimeout(function () {
app.disabled = false;
app.$refs.payPasswordForm.close();
uni.reLaunch({
url: '/pages/order/order',
success: function (e) {
var page = getCurrentPages()[0];
if (page == undefined || page == null) return;
page.onLoad();
}
});
}, 1500);
}
}
// 使用会员卡支付
if (form.payType == 2) {
if (!orderInfo) {
return uni.showToast({
title: '支付失败',
icon: 'error'
});
}
if (orderInfo) {
uni.showToast({
title: '支付成功',
icon: 'success'
});
setTimeout(function () {
app.disabled = false;
uni.reLaunch({
url: '/pages/order/order',
success: function (e) {
var page = getCurrentPages()[0];
if (page == undefined || page == null) return;
page.onLoad();
}
});
}, 1500);
}
}
uni.hideLoading();
})
.catch((res) => {
uni.showToast({
title: res.message || '请检查您的网络.',
icon: 'none'
});
uni.hideLoading();
});
}
}
};
</script>
<style>
page {
background-size: 100%;
background-repeat: no-repeat;
background-color: #f0f2f5;
width: 750rpx;
overflow-x: hidden;
}
</style>
<style lang="scss" scoped>
.container {
}
.checkout-car {
width: 700rpx;
left: 25rpx;
position: fixed;
bottom: 30rpx;
display: flex;
justify-content: space-between;
background-color: #000000;
border-radius: 100px;
align-items: center;
.car-selected {
color: #ccc;
display: flex;
align-items: center;
padding: 0 20rpx;
}
.car-total {
display: flex;
color: #ebcf00;
align-items: center;
padding-left: 40rpx;
.save-btn {
}
}
}
.card-actions {
display: flex;
flex-direction: row;
justify-content: flex-end;
height: 45px;
border-top: 1px #eee solid;
}
.card-actions-item {
display: flex;
flex-direction: row;
align-items: center;
.web-text-heading {
font-size: 38rpx;
margin-left: 28rpx;
}
}
.card-actions-item-text {
font-size: 12px;
color: #666;
margin-left: 5px;
}
.xieyi {
margin-bottom: 80rpx;
padding: 0 30rpx;
.text {
margin-left: 5rpx;
.link {
color: #0f80ff;
}
}
}
.pay-password-card {
width: 600rpx;
min-height: 300rpx;
margin: 30rpx auto;
background-color: #ffffff;
text-align: center;
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
.web-text-primary {
line-height: 2rem;
padding: 20rpx 0;
}
}
.to-pay-btn {
width: 400rpx !important;
margin: 40rpx auto;
}
</style>
+299
View File
@@ -0,0 +1,299 @@
<template>
<view class="container">
<view class="uv-demo-block">
<uv-swiper :list="photo" indicator indicatorMode="line" circular height="200" radius="0"></uv-swiper>
</view>
<!-- <view class="merchant-name">{{ merchant.merchantName }}</view> -->
<uni-card :title="merchant.merchantName" :border="false" :is-shadow="false" :padding="0">
<uv-cell-group :customStyle="{backgroundColor: '#ffffff'}" :border="false">
<uv-cell title="营业时间" :label="merchant.businessTime" :cellStyle="{padding: '10px 5px'}">
<!-- <template v-slot:label>
<view class="web-text-secondary">{{ merchant.businessTime }}</view>
</template>
<template v-slot:right-icon>
<text class="web-text-success"></text>
</template> -->
</uv-cell>
<uv-cell title="场馆地址" :label="merchant.address" :cellStyle="{padding: '10px 5px'}">
</uv-cell>
<uv-cell title="场馆位置" :label="`距离【${merchant.merchantName}】3.8公里·约7分钟`" isLink :cellStyle="{padding: '10px 5px'}" @click="mapTo(merchant)">
<template v-slot:right-icon>
<uv-icon size="50rpx" name="map-fill" color="#5ac725" style="color: #ff0000;"></uv-icon>
</template>
</uv-cell>
<uv-cell title="服务前台电话" :label="merchant.phone" :border="false" :cellStyle="{padding: '10px 5px'}" @click="callPhone(merchant.phone)">
</uv-cell>
</uv-cell-group>
</uni-card>
<uni-card title="场地介绍" :is-shadow="false" :border="false" :padding="0">
<view class="web-text-heading booking-content">
<view v-html="merchant.content"></view>
</view>
</uni-card>
<view class="xieyi web-cell web-text-secondary web-cell-align-top">
<view class="web-cell web-cell-content web-cell-align-top">
<uni-icons type="circle" size="20" color="#a4a5a7" v-if="!disabled" @click="onDisabled"></uni-icons>
<uni-icons type="checkbox" size="20" color="#11a954" v-else @click="onDisabled"></uni-icons>
<view class="text" @click="onDisabled">
<text>我已阅读并同意</text>
<text class="link"
@click.stop="navTo('/package/article/detail?articleId=503')">《订票协议》</text>
</view>
</view>
</view>
<view class="save-btn">
<uv-button
:customStyle="{background: 'linear-gradient(to right, #ccff66, #008e04)',borderRadius: '30px',color: '#ffffff'}"
text="预定场地" @click="save"></uv-button>
</view>
</view>
<uv-gap height="50"></uv-gap>
<view class="booking-tel" @click="openBookingTel">活动订场</view>
<!-- 活动订场弹窗 -->
<uni-popup ref="popup" type="center">
<view class="popup-booking-tel">
<text class="title">场馆热线</text>
<text class="desc">主体育场、足球训练场:0771-4953380</text>
<text class="desc">体育馆、综合训练馆、网球馆:0771-4953380</text>
<text class="desc">游泳跳水馆:0771-4736008</text>
<text class="title">参观接待</text>
<text class="desc">预约电话:0771-4736955</text>
<text class="desc">传真号码:0771-4736955</text>
<text class="title">大型活动订场</text>
<text class="desc">预约电话:0771-4736970、0771-4736994</text>
<text class="title">威拓普健身馆</text>
<text class="desc">联系电话:0771-5588699</text>
</view>
<view class="web-cell popup-close" @click="closeBookingTel">
<uv-icon name="close-circle" color="#ffffff" size="30"></uv-icon>
</view>
</uni-popup>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
</template>
<script>
import {
storeToRefs
} from 'pinia';
import * as MerchantApi from '@/api/shop/merchant';
import {
useCarStore
} from '@/store/modules/car';
const carStore = useCarStore();
export default {
data() {
return {
id: 0,
// 场馆信息
merchant: {},
// 场馆相册
photo: [],
isLogin: false,
disabled: true
}
},
onLoad(option) {
this.id = option.id
carStore.merchantId = option.id
this.reload();
},
onShow() {
// 登录状态
if (uni.getStorageSync('user_id') && uni.getStorageSync('access_token')) {
this.isLogin = true;
}
},
methods: {
async reload() {
const app = this
// 请求数据
Promise.all([app.getMerchant()]).then(res => {
const merchant = res[0];
app.merchant = merchant;
// 修改标题
uni.setNavigationBarTitle({
title: merchant.merchantName
})
// 加载场馆相册
if (merchant.files) {
app.photo = JSON.parse(merchant.files)
}
// 更新购物车状态
carStore.setMerchant(merchant)
carStore.merchantId = merchant.merchantId
carStore.merchantName = merchant.merchantName
carStore.merchantCode = merchant.merchantCode
})
},
getMerchant() {
return new Promise((resolve, reject) => {
MerchantApi.getMerchant(this.id).then(result => {
resolve(result)
}).catch(reject)
})
},
onDisabled() {
this.disabled = !this.disabled;
},
navTo(url) {
uni.navigateTo({
url
})
},
mapTo(item){
console.log('item: ',item.lngAndLat);
const arr = item.lngAndLat.split(',');
console.log('arr: ',arr);
uni.openLocation({
latitude: parseFloat(arr[1]),
longitude: parseFloat(arr[0]),
success: function () {
console.log('success');
}
});
},
openBookingTel() {
// 通过组件定义的ref调用uni-popup方法 ,如果传入参数 ,type 属性将失效 ,仅支持 ['top','left','bottom','right','center']
this.$refs.popup.open('center')
},
closeBookingTel() {
this.$refs.popup.close()
},
callPhone(phone) {
uni.makePhoneCall({
phoneNumber: phone
});
},
onMap() {
uni.getLocation({
type: 'gcj02', //返回可以用于uni.openLocation的经纬度
success: function(res) {
console.log('返回可以用于uni.openLocation的经纬度: ', res);
const latitude = this.merchant.latitude;
const longitude = this.merchant.longitude;
uni.openLocation({
latitude: latitude,
longitude: longitude,
success: function() {
console.log('success');
}
});
}
});
},
save() {
if (!this.disabled) {
uni.showToast({
title: '请先阅读并同意订票协议',
icon: 'none'
})
return false
}
uni.navigateTo({
url: '/package/booking/checkout?id=' + this.id
})
}
}
}
</script>
<style>
page {
background-size: 100%;
background-repeat: no-repeat;
background-color: #f0f2f5;
width: 750rpx;
overflow-x: hidden;
}
</style>
<style lang="scss" scoped>
.container {}
.merchant-name {
padding: 30rpx;
font-weight: 500;
font-size: 42rpx;
background-color: #ffffff;
}
.save-btn {
width: 700rpx;
left: 25rpx;
height: 80rpx;
position: fixed;
bottom: 30rpx;
}
.booking-tel {
position: fixed;
z-index: 1;
top: 270px;
right: 0;
width: 80px;
height: 38px;
border-radius: 50px 0 0 50px;
background: linear-gradient(to right, #ccff66, #008e04);
display: flex;
align-items: center;
justify-content: center;
color: #ffffff;
font-size: 13px;
}
.popup-booking-tel {
background-color: #ffffff;
width: 560rpx;
min-height: 400rpx;
border-radius: 20rpx;
margin: auto;
padding: 20px;
z-index: 9999;
display: flex;
flex-direction: column;
.title {
font-weight: bold;
font-size: 38rpx;
text-align: center;
padding: 10px 0;
}
.desc {
line-height: 2rem;
}
}
.popup-close {
display: flex;
margin-top: 24rpx;
justify-content: center;
}
.booking-content{
padding: 10px;
font-size: 30rpx;
line-height: 1.5rem;
}
.xieyi {
margin-bottom: 80rpx;
padding: 0 30rpx;
.text {
margin-left: 5rpx;
.link {
color: #0f80ff;
}
}
}
</style>
+419
View File
@@ -0,0 +1,419 @@
<template>
<view class="container">
<view class="card-body">
<block v-if="merchant.length > 0">
<uni-grid :column="3" borderColor="transparent" :highlight="true" @change="change">
<uni-grid-item v-for="(item, index) in merchant" :index="index" :key="index">
<view class="merchant-card" style="display: flex; flex-direction: column">
<image :src="item.image" mode="widthFix" class="merchant-image" />
<text class="merchant-name">{{ item.merchantName }}</text>
</view>
</uni-grid-item>
</uni-grid>
</block>
<block v-else>
<uni-card :border="false" :padding="'18px 6px'">
<uv-skeleton rows="2" avatar :loading="hideTools" :title="false"></uv-skeleton>
<uv-gap height="16"></uv-gap>
<uv-skeleton rows="2" avatar :loading="hideTools" :title="false"></uv-skeleton>
<uv-gap height="16"></uv-gap>
<uv-skeleton rows="2" avatar :loading="hideTools" :title="false"></uv-skeleton>
<uv-gap height="16"></uv-gap>
<uv-skeleton rows="2" avatar :loading="hideTools" :title="false"></uv-skeleton>
<uv-gap height="16"></uv-gap>
</uni-card>
</block>
</view>
</view>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
</template>
<script>
import * as GoodsApi from '@/api/shop/goods';
import * as Api from '@/api/layout';
import * as MerchantApi from '@/api/shop/merchant';
import * as MpMenuApi from '@/api/cms/mp-menu/index';
import * as ItemApi from '@/api/booking/item';
import { useTenantStore } from '@/store/modules/tenant';
import { openUrl } from '@/utils/common';
const tenantStore = useTenantStore();
export default {
data() {
return {
itemType: null,
items: ['关注', '推荐'],
// 场馆列表
merchant: [],
// 网站参数
fields: {},
// 幻灯片广告
ads: [],
// 幻灯片链接地址
pathList: [],
// 项目列表
itemList: [],
// 小程序导航图标
navigation: [],
// 小程序导航图标(双排)
doubleNavigation: [],
isLogin: false,
// 骨架屏
hideTools: true,
mp_menu_display_method: 0
};
},
onLoad(o) {
this.itemType = o.type
this.reload();
},
methods: {
async reload() {
const app = this;
// 获取服务租户信息包
const info = await tenantStore.fetchTenantInfo();
// 登录状态
if (uni.getStorageSync('user_id') && uni.getStorageSync('access_token')) {
app.isLogin = true;
}
// 解析网站参数
if (info.fields) {
info.fields.map((d) => {
const key = d.name;
app.fields[key] = d.value;
if (d.name == 'h5_url') {
// 缓存H5地址
uni.setStorageSync(d.name, d.value);
}
if (d.name == 'mp_menu_display_method') {
app.mp_menu_display_method = d.value;
}
});
}
// 解析幻灯片数据
if (info.ads) {
const ad = info.ads.filter((d) => d.adType == '幻灯片');
if (ad) {
const adsList = JSON.parse(ad[0].images);
adsList.map((d) => {
app.ads.push(d.url);
});
app.pathList = JSON.parse(ad[0].path);
}
app.hideTools = false;
}
// 解析小程序名称
if (info.websiteName) {
uni.setNavigationBarTitle({
title: info.websiteName
});
}
// 解析网站logo
if (info.websiteLogo) {
uni.setStorageSync('app_logo', info.websiteLogo);
app.logo = info.websiteLogo;
}
// 解析小程序导航图标
if (info.mpMenus) {
const arr = info.mpMenus.filter((d) => d.type == 2 && d.rows == 0);
const arr1 = info.mpMenus.filter((d) => d.type == 2 && d.rows == 1);
const arr2 = info.mpMenus.filter((d) => d.type == 2 && d.rows == 2);
app.navigation = [];
app.doubleNavigation = [];
if (arr1) {
app.doubleNavigation.push(arr);
app.doubleNavigation.push(arr1);
} else {
app.doubleNavigation.push(arr);
}
//
if (arr) {
app.navigation = arr;
}
}
// 请求数据
Promise.all([app.getMerchantList()]).then((res) => {
app.merchant = res[0];
});
},
getSiteInfo() {
const app = this;
return new Promise((resolve, reject) => {
Api.getSiteInfo()
.then((result) => {
resolve(result);
})
.catch(reject);
});
},
getMerchantList() {
const app = this
const { itemType } = this
return new Promise((resolve, reject) => {
MerchantApi.listMerchant({itemType})
.then((result) => {
resolve(result);
})
.catch(reject);
});
},
change(e) {
const { index } = e.detail;
const id = this.merchant[index].merchantId;
this.openUrl(`/package/booking/index?id=${id}`);
},
onAds(index) {
const { pathList } = this;
this.openUrl(pathList[index]);
},
openUrl(url) {
if (!this.isLogin) {
this.$refs.login.open('bottom');
return false;
} else {
uni.navigateTo({
url
});
}
}
}
};
</script>
<style>
page {
/* background: url('https://oss.wsdns.cn/20240502/75fc744657544a38a32f83a825688286.png') no-repeat; */
background-size: 100%;
background-repeat: no-repeat;
background-color: #f0f2f5;
width: 750rpx;
overflow-x: hidden;
}
</style>
<style lang="scss" scoped>
.container {
}
.segmented {
display: block;
justify-content: space-around;
text-align: center;
width: 200rpx;
margin: auto;
color: #ffffff;
.item {
color: #666;
font-size: 26rpx;
padding: 0 12rpx;
}
.active {
color: #333;
font-size: 30rpx;
font-weight: 500;
}
}
.user-oreder {
display: flex;
padding: 16px 0;
.scroll-item {
display: flex;
flex-direction: column;
align-items: center;
padding: 0 25rpx;
.scrool-item-text {
white-space: nowrap;
}
}
.web-cell-content {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.web-text-center {
text-align: center;
}
}
.menu-list {
display: flex;
padding: 16px 0;
flex-wrap: wrap;
.scroll-item {
display: flex;
flex-direction: column;
align-items: center;
padding: 0 25rpx;
.scrool-item-text {
white-space: nowrap;
}
}
.web-cell-content {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin: 10rpx 0;
}
.web-text-center {
text-align: center;
}
.menu-title {
white-space: nowrap;
font-size: 26rpx;
}
}
.card-title {
width: 700rpx;
margin: 12rpx auto;
font-size: 34rpx;
font-weight: 500;
margin-top: 32rpx;
}
.merchant-card-title {
width: 700rpx;
margin: 12rpx auto;
font-size: 40rpx;
font-weight: 500;
margin-top: 32rpx;
}
.card-body {
width: 740rpx;
margin: auto;
.merchant-card {
margin: 12rpx auto;
background: #ffffff;
border-radius: 10rpx;
border-color: slategrey;
border-radius: 16rpx;
.merchant-image {
width: 200rpx;
border-radius: 16rpx 16rpx 0 0;
height: 140rpx !important;
}
.merchant-name {
padding: 10rpx;
font-weight: 500;
font-size: 26rpx;
text-align: center;
}
.merchant-desc {
width: 400rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
.item-list {
display: flex;
flex-wrap: wrap;
width: 720rpx;
margin: auto;
.item-bar {
width: 138rpx;
height: 138rpx;
padding: 10rpx;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
background-color: #ffffff;
border-radius: 10rpx;
margin: 10rpx;
font-size: 26rpx;
}
}
@mixin flex($direction: row) {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: $direction;
}
.navigation {
padding: 0 30rpx 0 30rpx;
}
.scroll-list {
@include flex(column);
&__item {
margin-right: 20px;
&__image {
width: 60px;
height: 60px;
border-radius: 4px;
}
&__text {
color: $uni-text-color-placeholder;
text-align: center;
font-size: 12px;
margin-top: 5px;
}
}
&__line {
@include flex;
margin-top: 10px;
&__item {
margin-right: 30px;
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
&__image {
width: 61px;
height: 48px;
}
&__text {
margin-top: 5px;
color: $uni-text-color-placeholder;
font-size: 12px;
text-align: center;
}
&--no-margin-right {
margin-right: 0;
}
}
}
&__line__item__text {
white-space: nowrap;
}
}
</style>
+635
View File
@@ -0,0 +1,635 @@
<template>
<view class="container">
<!-- deBug信息 -->
<view class="web-debug web-text-success" style="display: none">
场馆ID:{{ merchantId }} 场馆编号:{{ merchantCode }} 场馆名称:{{ merchantName }} 日期:{{ dateTime }} 星期:{{ week }} 订单总金额:{{ totalPrice }} 类型:{{
type
}}
商品信息:{{ goodsList }} 表单信息:{{ form }}
</view>
<view class="card-list">
<view class="container" :style="{ background: `url(${form.image}) no-repeat center center`, backgroundSize: '100%', opacity: '0.85' }">
<view class="content web-cell web-cell-align-top">
<view class="merchant-avatar">
<uv-avatar :src="form.merchantAvatar" size="42" style="border: 3rpx solid #ffffff"></uv-avatar>
</view>
<view class="card-info web-cell-content">
<view class="title-bar">
<view class="web-text-heading" style="color: #ffffff; font-size: 17px; font-weight: 600">{{ form.cardName }}</view>
<block v-if="form.cardCode == '月/年卡'">
<view class="desc web-text-heading" style="color: #ffffff; font-size: 14px">{{ form.month }}个月</view>
</block>
<block v-if="form.cardCode == '次卡'">
<view class="desc web-text-heading" style="color: #ffffff; font-size: 14px">{{ form.number }}次</view>
</block>
<block v-if="form.cardCode == '充值卡'">
<view class="desc web-text-heading" style="color: #ffffff; font-size: 14px">{{ form.discount }}折</view>
</block>
</view>
<view class="price">
<view class="web-text-price">
<uv-avatar src="../../static/qrcode.png" size="30" shape="square"></uv-avatar>
</view>
</view>
</view>
</view>
<view class="card-num">0000 0000 0000</view>
</view>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
</view>
<uni-card title="会员卡说明" :border="false" :is-shadow="false">
<view v-html="form.comments"></view>
</uni-card>
<uni-card title="选择支付方式" :border="false" :is-shadow="false">
<uv-cell-group :customStyle="{ backgroundColor: '#ffffff' }" :border="false">
<block v-for="(item, index) in payment" :key="index"></block>
<uv-cell
title="微信支付"
icon="https://oss.wsdns.cn/20240511/8d7af0f0374040cb9b9255eff5fb812d.png?x-oss-process=image/resize,m_fixed,w_100,h_100/quality,Q_90"
:cellStyle="{ padding: '20rpx 10rpx', borderRadius: '8rpx', backgroundColor: payType == 1 ? '#f6fff1' : '' }"
:border="false"
@click="onPayType(1)"
>
<template v-slot:right-icon>
<uv-icon v-if="payType == 1" size="30rpx" name="checkbox-mark"></uv-icon>
</template>
</uv-cell>
<uv-cell
:title="`余额支付(${userInfo.balance})`"
icon="https://oss.wsdns.cn/20240511/fae57a94fa0042b9bceb721421304db1.png?x-oss-process=image/resize,m_fixed,w_100,h_100/quality,Q_90"
:cellStyle="{ padding: '10px 5px', borderRadius: '8rpx', backgroundColor: payType == 0 ? '#f6fff1' : '' }"
:border="false"
@click="onPayType(0)"
>
<template v-slot:right-icon>
<uv-icon v-if="payType == 0" size="30rpx" name="checkbox-mark"></uv-icon>
</template>
</uv-cell>
</uv-cell-group>
<view slot="actions" class="card-actions">
<view class="card-actions-item" @click="actionsClick('分享')">
<!-- <span class="web-text-danger">已优惠¥0.00</span> -->
<span class="web-text-heading">¥{{ form.price || 0.0 }}</span>
</view>
</view>
</uni-card>
<view class="xieyi web-cell web-text-secondary web-cell-align-top">
<view class="web-cell web-cell-content web-cell-align-top">
<uni-icons type="circle" size="20" color="#a4a5a7" v-if="!disabled" @click="onDisabled"></uni-icons>
<uni-icons type="checkbox" size="20" color="#11a954" v-else @click="onDisabled"></uni-icons>
<view class="text" @click="onDisabled">
<text>同意以下服务条款</text>
<text class="link" @click.stop="navTo('/package/article/detail?articleId=501')">《广西体育中心预定条款》</text>
<text class="link" @click.stop="navTo('/package/article/detail?articleId=502')">《用户服务协议和隐私政策》</text>
</view>
</view>
</view>
<!-- 支付按钮 -->
<uv-gap height="50"></uv-gap>
<view class="checkout-car">
<view class="car-total">
<text style="color: #ebcf00">合计¥</text>
<uv-count-to :startVal="0" decimals="2" duration="100" color="#ebcf00" bold :endVal="form.price"></uv-count-to>
</view>
<uv-button
class="save-btn"
:disabled="!disabled"
:customStyle="{ background: 'linear-gradient(to right, #70b915, #008e04)', borderRadius: '0 30px 30px 0', color: '#ffffff', border: 'none', padding: '22px 30px' }"
text="提交订单"
@click="save"
></uv-button>
</view>
</view>
<!-- 收货地址选择弹窗 -->
<uni-popup ref="addForm" type="center" border-radius="10px 10px 0 0">
<uni-card title="选择收货地址" :border="false" :is-shadow="false" :padding="0">
<view class="address-body web-cell web-cell-align-top">
<view class="web-cell-content">
<uv-cell-group :customStyle="{ backgroundColor: '#ffffff' }" :border="false">
<block v-for="(item, index) in addressList" :key="index">
<uv-cell :cellStyle="{ padding: '10px 0' }" :label="item.address" @click="onAddress(item)">
<template v-slot:icon>
<uv-avatar :text="item.type" fontSize="12" size="32" randomBgColor></uv-avatar>
</template>
<template v-slot:title>
<view class="title-bar">
<text class="web-text-heading" style="font-weight: 700">{{ item.name }}</text>
<text class="web-text-secondary">{{ item.phone }}</text>
<uni-tag v-if="item.isDefault" text="默认" size="mini" inverted type="success"></uni-tag>
</view>
</template>
<template v-slot:right-icon>
<uni-icons type="right" style="color: #999999"></uni-icons>
</template>
</uv-cell>
</block>
<uv-button class="add-address" :customStyle="{ borderRadius: '30px' }" text="收货地址管理" @click="navTo('/package/user/address')"></uv-button>
</uv-cell-group>
</view>
</view>
</uni-card>
</uni-popup>
<!-- 支付密码弹窗 -->
<uni-popup ref="payPasswordForm" type="center" border-radius="10px 10px 0 0">
<uni-card title="请输入支付密码" :border="false" :is-shadow="false" :padding="0">
<view class="pay-password-card">
<uni-forms ref="form" :label-width="80">
<uni-forms-item label="支付密码" name="payPassword" required>
<uv-code-input mode="box" dot :space="0" :maxlength="6" hairline v-model="payPassword"></uv-code-input>
</uni-forms-item>
<uv-button
class="to-pay-btn"
:customStyle="{ background: 'linear-gradient(to right, #70b915, #008e04)', borderRadius: '30px', color: '#ffffff' }"
text="确定支付"
:disabled="disabledPayPayPassword"
@click="onPayPassword"
></uv-button>
</uni-forms>
<text @click="navTo(`/package/user/pay-password`)" class="web-text-primary">忘记支付密码?</text>
</view>
</uni-card>
</uni-popup>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
</template>
<script>
import * as Api from '@/api/booking/card';
import * as OrderApi from '@/api/shop/order';
import { checkPayPassword } from '@/api/passport/login';
import { storeToRefs } from 'pinia';
import { getWeek, getKey } from '@/utils/common';
import { useCarStore } from '@/store/modules/car';
import { useUserStore } from '@/store/modules/user';
const userStore = useUserStore();
const carStore = useCarStore();
const { goodsList, totalPrice, carNum, merchantId, merchantName, merchantCode, type, dateTime } = storeToRefs(carStore);
export default {
data() {
return {
cardId: 0,
goodsId: 0,
userInfo: {},
form: {},
address: {},
addressList: [],
week: 0,
goodsList,
// 订单总金额
totalPrice,
reducePrice: 0,
merchantId,
merchantName,
merchantCode,
getWeek,
payType: 1,
isLogin: false,
disabled: false,
// 支付密码是否正确
isPayPasswordCorrect: false,
disabledPayPayPassword: false,
payPassword: ''
};
},
onLoad(option) {
this.cardId = option.cardId;
this.reload();
},
onShow() {
// 登录状态
if (uni.getStorageSync('user_id') && uni.getStorageSync('access_token')) {
this.isLogin = true;
}
this.openLogin();
},
methods: {
async reload() {
const app = this;
const { cardId } = this;
// 当前登录用户信息
const userInfo = await userStore.fetchUserInfo();
app.userInfo = userInfo;
Api.getCard(cardId).then((data) => {
app.form = data;
// console.log('res: ',res);
// app.addressList = res.list;
// const arr = res.list.filter((d) => d.isDefault === true);
// app.address = arr[0];
});
// if (cardId > 0) {
// Api.getOrder(cardId).then(data => {
// app.merchantId = data.merchantId
// app.merchantName = data.merchantName
// app.merchantCode = data.merchantCode
// app.payType = data.payType
// app.orderInfo = data.orderInfoList
// app.totalPrice = data.totalPrice
// app.dateTime = data.orderInfoList[0].dateTime
// })
// }
},
onDisabled() {
this.disabled = !this.disabled;
},
navTo(url) {
uni.navigateTo({
url
});
},
openUrl(url) {
if (!this.isLogin) {
this.$refs.login.open('bottom');
return false;
} else {
uni.navigateTo({
url
});
}
},
onAddress(item) {
this.address = item;
this.$refs.addForm.close();
},
// 切换支付方式
onPayType(index) {
console.log('e: ', index);
this.payType = index;
},
openAddressList() {
this.$refs.addForm.open('center');
},
// 弹出登录提示框
openLogin() {
if (!this.isLogin) {
this.$refs.login.open('bottom');
return false;
}
},
// 验证支付密码
onPayPassword() {
if (this.payPassword == '' || !this.payPassword) {
uni.showToast({
title: '请输入支付密码',
icon: 'none'
});
return false;
}
this.disabledPayPayPassword = true;
const { payPassword } = this;
checkPayPassword({ payPassword })
.then((res) => {
this.disabledPayPayPassword = false;
this.isPayPasswordCorrect = true;
this.save();
})
.catch((err) => {
uni.showToast({
title: err.message,
icon: 'none'
});
this.disabledPayPayPassword = false;
});
},
save() {
const app = this;
const { form, payType } = this;
if (!this.disabled) {
uni.showToast({
title: '请先阅读并同意服务协议',
icon: 'none'
});
return false;
}
if (payType == 0 && !this.isPayPasswordCorrect) {
this.$refs.payPasswordForm.open('center');
return false;
}
uni.showLoading({
title: '订单提交中.'
});
OrderApi.addOrder({
type: 2, // 0商城订单 1预定订单 2会员卡订单
cardId: form.cardId,
merchantId: form.merchantId,
merchantName: form.merchantName,
totalPrice: form.price,
payPrice: form.price,
comments: form.cardName,
payType
})
.then((data) => {
const orderInfo = data;
// 调起微信支付
if (payType == 1) {
// #ifdef MP-WEIXIN
uni.requestPayment({
provider: orderInfo.provider, // 服务提供商
timeStamp: orderInfo.timeStamp, // 时间戳
nonceStr: orderInfo.nonceStr, // 随机字符串
package: orderInfo.package,
signType: orderInfo.signType, // 签名算法
paySign: orderInfo.paySign, // 签名
success: function (res) {
// 业务逻辑。。。
uni.showToast({
title: '支付成功',
icon: 'success'
});
setTimeout(function () {
app.disabled = false;
uni.navigateTo({
url: '/package/user/card'
});
}, 500);
},
fail: function (err) {
console.log('支付失败', err);
app.disabled = false;
}
});
// #endif
}
// 使用余额支付
if (payType == 0) {
if (orderInfo) {
uni.showToast({
title: '支付成功',
icon: 'success'
});
setTimeout(function () {
app.disabled = false;
uni.navigateTo({
url: '/package/user/card'
});
}, 500);
return;
}
if (!orderInfo) {
return uni.showToast({
title: '支付失败',
icon: 'error'
});
}
}
uni.hideLoading();
})
.catch((res) => {
uni.showToast({
title: res.message || '请检查您的网络.',
icon: 'none'
});
uni.hideLoading();
});
}
}
};
</script>
<style>
page {
background-size: 100%;
background-repeat: no-repeat;
background-color: #f0f2f5;
width: 750rpx;
overflow-x: hidden;
}
</style>
<style lang="scss" scoped>
.checkout-car {
width: 700rpx;
left: 25rpx;
position: fixed;
bottom: 30rpx;
display: flex;
justify-content: space-between;
background-color: #000000;
border-radius: 100px;
align-items: center;
.car-selected {
color: #ccc;
display: flex;
align-items: center;
padding: 0 20rpx;
}
.car-total {
display: flex;
color: #ebcf00;
align-items: center;
padding-left: 40rpx;
.save-btn {
}
}
}
.card-list {
.container {
width: 700rpx;
position: relative;
margin: 25rpx auto;
display: flex;
justify-content: space-between;
align-items: center;
border-radius: 20rpx;
position: relative;
box-shadow: 0 0px 6px 0 rgba(0, 0, 0, 0.2);
// background: linear-gradient(to right, #70b915, #008e04);
color: #ffffff;
.card-num {
position: absolute;
z-index: 1;
bottom: 30rpx;
left: 30rpx;
}
}
.container::before {
content: '';
display: block;
position: absolute;
border-radius: 20rpx;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: #000000;
// background: url('https://oss.wsdns.cn/20240528/cf37a247603f489ba23d7d2a53b8da39.jpeg') no-repeat center bottom;
background-size: 100%;
opacity: 0.25; /* 设置透明度 */
}
.content {
position: relative;
z-index: 1;
width: 700rpx;
height: 380rpx;
display: flex;
justify-content: space-between;
.merchant-avatar {
margin-top: 30rpx;
margin-left: 30rpx;
}
.card-info {
height: 120rpx;
margin-top: 10rpx;
margin-left: 10rpx;
display: flex;
justify-content: space-between;
align-items: center;
.title-bar {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: flex-start;
}
.web-text-price {
padding-right: 40rpx;
font-size: 36rpx;
color: #fecc66;
}
}
.card-bg {
}
}
.card-item {
width: 700rpx;
margin: 20rpx auto;
border-radius: 20rpx;
position: relative;
// box-shadow: 0 0px 6px 1px rgba($color: #a5a5a5, $alpha: 0.2);
}
// .card-item::before {
// content: ''; /* 伪元素需要内容,即使它是空的 */
// position: absolute;
// top: 0;
// right: 0;
// bottom: 0;
// left: 0;
// background: url('https://oss.wsdns.cn/20240528/d5680e18210544a49dfa79f250f1997d.jpeg');
// background-size: cover; /* 或其他你需要的背景大小 */
// opacity: 0.5; /* 设置透明度 */
// z-index: -1; /* 确保伪元素在内容之下 */
// }
.order-title {
padding: 20rpx 0;
.merchant-avatar {
margin-right: 12rpx;
}
.card-name {
font-weight: 600;
}
.btn-status {
font-size: 30rpx;
display: flex;
}
}
.order-body {
padding: 16px 0;
}
}
.card-actions {
display: flex;
flex-direction: row;
justify-content: flex-end;
height: 45px;
border-top: 1px #eee solid;
}
.card-actions-item {
display: flex;
flex-direction: row;
align-items: center;
.web-text-heading {
font-size: 38rpx;
margin-left: 28rpx;
}
}
.card-actions-item-text {
font-size: 12px;
color: #666;
margin-left: 5px;
}
.address-body {
width: 660rpx;
margin: auto;
}
.add-address {
width: 600rpx !important;
margin: 40rpx auto;
}
.btn-bar {
width: 700rpx;
left: 25rpx;
position: fixed;
bottom: 30rpx;
margin: auto;
clear: both;
}
.title-bar {
display: flex;
.web-text-heading {
margin-right: 20rpx;
}
.web-text-secondary {
margin-right: 20rpx;
}
}
.xieyi {
margin-bottom: 80rpx;
padding: 0 30rpx;
.text {
margin-left: 5rpx;
.link {
color: #0f80ff;
}
}
}
.pay-password-card {
width: 600rpx;
min-height: 300rpx;
margin: 30rpx auto;
background-color: #ffffff;
text-align: center;
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
.web-text-primary {
line-height: 2rem;
padding: 20rpx 0;
}
}
.to-pay-btn {
width: 400rpx !important;
margin: 40rpx auto;
}
</style>
+416
View File
@@ -0,0 +1,416 @@
<template>
<view>
<view class="segmented">
<uni-segmented-control :current="current" :values="items" :styleType="styleType" :activeColor="activeColor" inActiveColor="#808080" @clickItem="onClickItem" />
</view>
<view class="card-list">
<block v-for="(item, index) in cardList" :key="index">
<view @click="openUrl('/package/card/checkout?cardId=' + item.cardId)" class="container" :style="{ background: `url(${item.image}) no-repeat center center`, backgroundSize: '100%', opacity: '0.85' }">
<view class="content web-cell">
<view class="merchant-avatar">
<uv-avatar :src="item.merchantAvatar" size="36" style="border: 3rpx solid #ffffff"></uv-avatar>
</view>
<view class="card-info web-cell-content">
<view class="title-bar">
<view class="web-text-heading" style="color: #ffffff; font-size: 17px; font-weight: 600;">{{ item.cardName }}</view>
<block v-if="item.cardCode == '月/年卡'">
<view class="desc web-text-heading" style="color: #ffffff;font-size: 14px;">{{ item.month }}个月</view>
</block>
<block v-if="item.cardCode == '次卡'">
<view class="desc web-text-heading" style="color: #ffffff;font-size: 14px;">{{ item.number }}次</view>
</block>
<block v-if="item.cardCode == '充值卡'">
<view class="desc web-text-heading" style="color: #ffffff;font-size: 14px;">{{ item.discount }}折</view>
</block>
</view>
<view class="price">
<text class="web-text-price">{{ `¥${item.price}` }}</text>
</view>
</view>
</view>
</view>
</block>
<block v-if="cardList.length == 0">
<uni-card :border="false" :padding="'18px 6px'">
<uv-skeleton rows="2" avatar :loading="hideTools" :title="false"></uv-skeleton>
</uni-card>
<uni-card :border="false" :padding="'18px 6px'">
<uv-skeleton rows="2" avatar :loading="hideTools" :title="false"></uv-skeleton>
</uni-card>
<uni-card :border="false" :padding="'18px 6px'">
<uv-skeleton rows="2" avatar :loading="hideTools" :title="false"></uv-skeleton>
</uni-card>
<uni-card :border="false" :padding="'18px 6px'">
<uv-skeleton rows="2" avatar :loading="hideTools" :title="false"></uv-skeleton>
</uni-card>
<uni-card :border="false" :padding="'18px 6px'">
<uv-skeleton rows="2" avatar :loading="hideTools" :title="false"></uv-skeleton>
</uni-card>
<uni-card :border="false" :padding="'18px 6px'">
<uv-skeleton rows="2" avatar :loading="hideTools" :title="false"></uv-skeleton>
</uni-card>
</block>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
</view>
</view>
</template>
<script>
import * as Api from '@/api/booking/card';
import { pageWechatDeposit } from '@/api/shop/wechatDeposit';
import { getWeek, getKey } from '@/utils/common';
export default {
components: {},
data() {
return {
isRefresh: false,
isLogin: false,
userId: 0,
where: {
page: 1,
cardCode: '月/年卡',
sceneType: 'showCanBuyVipCard'
},
canReset: false,
loadMore: 'more',
logo: '',
items: ['月/年卡', '次卡', '充值卡'],
cardList: [],
styles: [
{
value: 'button',
text: '按钮',
checked: true
},
{
value: 'text',
text: '文字'
}
],
colors: ['#333333', '#4cd964', '#dd524d'],
current: 0,
colorIndex: 0,
activeColor: '#108001',
styleType: 'text',
getWeek,
// 骨架屏
hideTools: true
};
},
onLoad(option) {
// 判断是否登录
this.openLogin();
// 加载数据
this.reload();
console.log('判断是否刷新: ', option);
if (option.isRefresh) {
this.isRefresh = true;
}
},
onShow(e) {
console.log('判断是否刷新: ', e);
// 判断是否登录
this.openLogin();
if (this.isRefresh) {
this.reload();
}
},
// 触底函数
onReachBottom() {
const app = this;
const { where } = this;
if (app.canReset) {
app.where.page = ++where.page;
app.reload();
}
},
methods: {
reload() {
const app = this;
const { where, userId } = this;
if (userId == 0) {
app.openLogin();
return;
}
// where.userId = userId;
// uni.showLoading({
// title: '数据读取中.'
// });
app.loadMore = 'loading';
Api.pageCard(where)
.then((res) => {
const list = res.list.map((d) => {
console.log(d);
return d;
});
if (app.cardList.length < res.count) {
app.cardList = app.cardList.concat(list);
app.canReset = true;
app.loadMore = 'no-more';
} else {
app.canReset = false;
app.loadMore = 'no-more';
}
// uni.hideLoading();
app.isRefresh = false;
app.hideTools = false;
})
.catch(() => {
uni.showToast({
title: '请检查您的网络.',
icon: 'none'
});
app.isRefresh = false;
app.hideTools = false;
});
},
onClickItem(e, text) {
const app = this;
const { where, userId } = this;
const index = e.currentIndex;
if (this.current !== e.currentIndex) {
this.current = e.currentIndex;
}
// 全部
if (index == 0) {
where.cardCode = '月/年卡';
}
// 未支付
if (index == 1) {
where.cardCode = '次卡';
}
// 已支付
if (index == 2) {
where.cardCode = '充值卡';
}
this.where.page = 1;
this.cardList = [];
this.hideTools = true
this.reload();
},
openUrl(url) {
uni.navigateTo({
url
});
},
toPay(orderId) {
uni.navigateTo({
url: '/package/booking/confirm?id=' + orderId
});
},
closeOrder(item) {
uni.showModal({
title: '确定取消此订单?',
success(o) {
if (o.confirm) {
// Api.updateOrder({
// orderStatus: 2,
// orderId: item.orderId
// })
// .then((msg) => {
// uni.showToast({
// title: msg,
// icon: 'none'
// });
// item.orderStatus = 2;
// })
// .catch(() => {
// uni.showToast({
// title: '请检查您的网络.',
// icon: 'none'
// });
// uni.hideLoading();
// });
}
}
});
},
// 弹出登录提示框
async openLogin() {
this.userId = uni.getStorageSync('user_id');
if (!this.userId) {
this.$refs.login.open('bottom');
return false;
}
}
}
};
</script>
<style lang="scss">
.content {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
justify-content: center;
align-items: center;
height: 150px;
text-align: center;
}
.segmented {
padding: 0 12rpx;
}
.content-text {
font-size: 14px;
color: #666;
}
.color-tag {
width: 25px;
height: 25px;
}
.uni-list {
flex: 1;
}
.card-list {
.container {
width: 700rpx;
height: 200rpx;
position: relative;
margin: 25rpx auto;
display: flex;
justify-content: space-between;
align-items: center;
border-radius: 20rpx;
position: relative;
box-shadow: 0 0px 6px 0 rgba(0, 0, 0, 0.2);
// background: linear-gradient(to right, #70b915, #008e04);
color: #ffffff;
}
.container::before {
content: '';
display: block;
position: absolute;
border-radius: 20rpx;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: #000000;
// background: url('https://oss.wsdns.cn/20240528/cf37a247603f489ba23d7d2a53b8da39.jpeg') no-repeat center bottom;
background-size: 100%;
opacity: 0.25; /* 设置透明度 */
}
.content {
position: relative;
z-index: 1;
width: 700rpx;
display: flex;
justify-content: space-between;
.merchant-avatar {
margin-left: 24rpx;
}
.card-info {
margin-left: 10rpx;
display: flex;
justify-content: space-between;
align-items: center;
.title-bar {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: flex-start;
}
.web-text-price {
padding-right: 30rpx;
font-size: 36rpx;
color: #fecc66;
}
}
.card-bg {
}
}
.card-item {
width: 700rpx;
margin: 20rpx auto;
border-radius: 20rpx;
position: relative;
// box-shadow: 0 0px 6px 1px rgba($color: #a5a5a5, $alpha: 0.2);
}
// .card-item::before {
// content: ''; /* 伪元素需要内容,即使它是空的 */
// position: absolute;
// top: 0;
// right: 0;
// bottom: 0;
// left: 0;
// background: url('https://oss.wsdns.cn/20240528/d5680e18210544a49dfa79f250f1997d.jpeg');
// background-size: cover; /* 或其他你需要的背景大小 */
// opacity: 0.5; /* 设置透明度 */
// z-index: -1; /* 确保伪元素在内容之下 */
// }
.order-title {
padding: 20rpx 0;
.merchant-avatar {
margin-right: 12rpx;
}
.card-name {
font-weight: 600;
}
.btn-status {
font-size: 30rpx;
display: flex;
}
}
.order-body {
padding: 16px 0;
}
}
.ele-flex {
display: flex;
justify-content: space-between;
}
.card-actions {
display: flex;
flex-direction: row;
justify-content: flex-end;
align-items: center;
height: 45px;
border-top: 1px #eee solid;
}
.card-actions-item {
display: flex;
flex-direction: row;
align-items: center;
}
.card-actions-item-text {
font-size: 12px;
color: #666;
margin-left: 5px;
}
.close {
top: 60rpx !important;
}
.total-price {
display: flex;
flex-direction: column;
justify-content: flex-start;
font-size: 30rpx;
align-items: flex-start;
padding-left: 6rpx;
margin-left: 450rpx;
.web-text-heading {
font-size: 30rpx !important;
}
}
</style>
+192
View File
@@ -0,0 +1,192 @@
<template>
<view>
<view class="card-title web-text-heading">商务合作</view>
<block v-if="list.length > 0">
<uni-card v-for="(item,index) in list" :key="index" title="游泳健身活动俱乐部" :border="false" :is-shadow="false" :padding="0">
<uv-cell-group :customStyle="{backgroundColor: '#ffffff'}" :border="false">
<uv-cell :label="`负责游泳跳水馆、包括游泳馆的日常经营管理工作`" :border="false" :cellStyle="{padding: '10px 5px'}">
<template v-slot:label>
<div class="text-gray-500">负责游泳跳水馆、包括游泳馆的日常经营管理工作</div>
</template>
</uv-cell>
<uv-cell title="电话咨询" :border="false" :cellStyle="{padding: '10px 5px'}">
<template v-slot:title>
<view class="flex justify-end">
<view class="ml-3">
<uv-button type="info" icon="phone" shape="circle" size="small" text="电话咨询"></uv-button>
</view>
<view class="ml-3">
<uv-button type="info" icon="edit-pen" shape="circle" size="small" text="合作留言"></uv-button>
</view>
</view>
</template>
</uv-cell>
</uv-cell-group>
</uni-card>
</block>
<block v-else>
<uni-card :border="false" :is-shadow="false" :padding="'12px 4px'">
<uv-skeleton rows="2" avatar :loading="hideTools" :title="false"></uv-skeleton>
<uv-gap height="16"></uv-gap>
<uv-skeleton rows="2" avatar :loading="hideTools" :title="false"></uv-skeleton>
<uv-gap height="16"></uv-gap>
<uv-skeleton rows="2" avatar :loading="hideTools" :title="false"></uv-skeleton>
<uv-gap height="16"></uv-gap>
<uv-skeleton rows="2" avatar :loading="hideTools" :title="false"></uv-skeleton>
<uv-gap height="16"></uv-gap>
</uni-card>
</block>
</view>
</template>
<script>
import * as CourseApi from '@/api/booking/course';
import * as ItemApi from '@/api/booking/item';
export default {
data() {
return {
list: [],
// 骨架屏
hideTools: true,
// 项目列表
itemList: []
};
},
onLoad() {
this.reload();
},
methods: {
reload() {
const app = this;
// 请求数据
Promise.all([app.getCourseList(), app.getItemList()]).then((res) => {
console.log('res: ', res);
app.list = res[0];
app.itemList = res[1];
});
},
getCourseList() {
const app = this;
const {categoryId} = this;
return new Promise((resolve, reject) => {
CourseApi.pageCourse({})
.then((result) => {
resolve(result.list);
})
.catch(reject);
});
},
getItemList() {
const app = this;
return new Promise((resolve, reject) => {
ItemApi.listItem({})
.then((result) => {
resolve(result);
})
.catch(reject);
});
},
onItem(e) {
const {index} = e.detail;
this.openUrl(`/package/match/list?categoryId=` + this.itemList[index].id)
},
openUrl(url) {
uni.navigateTo({
url
});
}
}
};
</script>
<style lang="scss" scoped>
.card-title {
width: 700rpx;
margin: 12rpx auto;
font-size: 34rpx;
font-weight: 500;
margin-top: 32rpx;
}
.match-list {
width: 700rpx;
margin: auto !important;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
.match-item {
width: 700rpx;
margin: 16rpx 0;
border-radius: 16rpx;
overflow: hidden;
background-color: #ffffff;
.match-info {
padding: 10rpx 16rpx;
line-height: 35rpx;
}
.match-name {
}
.price-bar {
padding: 0 16rpx;
display: flex;
justify-content: space-between;
}
.match-image {
}
}
}
.item-list {
width: 720rpx;
margin: auto;
}
.merchant-card-title {
width: 700rpx;
margin: 12rpx auto;
font-size: 40rpx;
font-weight: 500;
margin-top: 32rpx;
}
.card-body {
width: 700rpx;
margin: auto;
.merchant-card {
margin: 12rpx auto;
border-radius: 10rpx;
border-color: slategrey;
border-radius: 16rpx;
display: flex;
justify-content: space-between;
.merchant-image {
width: 45vw;
border-radius: 16rpx 16rpx 0 0;
}
.merchant-name {
padding: 10rpx;
overflow: hidden;
font-weight: 500;
font-size: 26rpx;
text-align: center;
}
.merchant-desc {
width: 400rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
</style>
+370
View File
@@ -0,0 +1,370 @@
<template>
<view>
<view class="coupon">
<block v-for="(item,index) in list" :key="index">
<view class="coupon-item web-cell">
<view class="coupon-bg">
<view class="title"><span class="price">8</span><span class="unit">元</span></view>
<view class="desc">满减劵</view>
</view>
<view class="coupon-info web-cell web-cell-content">
<view class="coupon-content">
<view class="title">优惠券名称</view>
<view class="desc web-text-secondary">有效期至:2024-05-29</view>
</view>
<uv-button class="save-btn" size="mini"
:customStyle="{background: 'linear-gradient(to right, #70b915, #008e04)',color: '#ffffff', border: 'none'}"
:text="item.disabled ? '已领取': '领取'" :disabled="item.disabled" @click="save(item,index)"></uv-button>
</view>
</view>
</block>
<!-- <uv-empty mode="order" v-if="list.length == 0"
icon="https://cdn.uviewui.com/uview/empty/data.png"></uv-empty> -->
<uni-load-more v-if="list.length > 0" :status="loadMore"></uni-load-more>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
</view>
</view>
</template>
<script>
import * as CouponApi from '@/api/booking/coupon'
import {
pageWechatDeposit
} from '@/api/shop/wechatDeposit'
import {
getWeek,
getKey
} from '@/utils/common';
import * as UserCouponApi from '@/api/booking/userCoupon'
export default {
components: {},
data() {
return {
isRefresh: false,
isLogin: false,
userId: 0,
where: {
page: 1,
status: 0
},
canReset: false,
loadMore: 'more',
logo: '',
items: ['待使用(0)', '已使用(0)', '已失效(0)'],
list: [],
styles: [{
value: 'button',
text: '按钮',
checked: true
},
{
value: 'text',
text: '文字'
}
],
colors: ['#333333', '#4cd964', '#dd524d'],
current: 0,
colorIndex: 0,
activeColor: '#108001',
styleType: 'text',
getWeek,
disabled: false
}
},
onLoad(option) {
// 判断是否登录
this.openLogin()
// 加载数据
this.reload()
// if(option.isRefresh){
// this.isRefresh = true
// }
},
onShow(e) {
// 判断是否登录
this.openLogin()
this.reload()
},
// 触底函数
onReachBottom() {
const app = this
const {
where
} = this
if (app.canReset) {
app.where.page = ++where.page;
app.reload()
}
},
methods: {
async reload() {
const app = this
const {
where
} = this
// where.userId = userId;
uni.showLoading({
title: '数据读取中.'
})
app.loadMore = 'loading'
const userCouponIds = []
const userCoupons = await app.getUserCoupon({
userId: uni.getStorageSync('user_id')
}).then(list => {
list.map(d => {
userCouponIds.push(d.couponId)
})
})
console.log('userCoupons: ',userCouponIds);
CouponApi.pageCoupon(where).then(res => {
const list = res.list.map(d => {
if(userCouponIds.indexOf(d.id) == 0){
d.disabled = true
}
return d;
});
if (app.list.length < res.count) {
app.list = app.list.concat(list)
app.canReset = true
app.loadMore = 'no-more'
} else {
app.canReset = false;
app.loadMore = 'no-more'
}
console.log('app.list: ',app.list);
uni.hideLoading()
app.isRefresh = false
}).catch(() => {
uni.showToast({
title: '请检查您的网络.',
icon: 'none'
})
uni.hideLoading()
app.isRefresh = false
})
},
getUserCoupon() {
const app = this;
return new Promise((resolve, reject) => {
UserCouponApi.listUserCoupon({})
.then((result) => {
resolve(result);
})
.catch(reject);
});
},
onClickItem(e) {
const app = this
const {
where,
userId
} = this
const index = e.currentIndex
if (this.current !== e.currentIndex) {
this.current = e.currentIndex
}
if (userId == 0) {
app.openLogin()
return;
}
// 全部
app.where.status = index;
this.where.page = 1;
this.list = [];
this.reload()
},
openUrl(url) {
uni.navigateTo({
url
})
},
toPay(orderId) {
uni.navigateTo({
url: '/package/booking/confirm?id=' + orderId
})
},
closeOrder(item) {
uni.showModal({
title: '确定取消此订单?',
success(o) {
if (o.confirm) {
OrderApi.updateOrder({
orderStatus: 2,
orderId: item.orderId
}).then(msg => {
uni.showToast({
title: msg,
icon: 'none'
})
item.orderStatus = 2;
}).catch(() => {
uni.showToast({
title: '请检查您的网络.',
icon: 'none'
})
uni.hideLoading()
})
}
}
});
},
// 弹出登录提示框
async openLogin() {
this.userId = uni.getStorageSync('user_id');
if (!this.userId) {
this.$refs.login.open('bottom')
return false;
}
},
save(item,index){
const app = this
item.couponId = item.id
app.list[index].disabled = true
UserCouponApi.addUserCoupon(item).then(msg => {
uni.showToast({
title: '领取成功',
icon: 'success'
})
setTimeout(() => {
app.reload()
},2000)
})
}
}
}
</script>
<style lang="scss">
.content {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
justify-content: center;
align-items: center;
height: 150px;
text-align: center;
}
.segmented {
padding: 0 12rpx;
}
.content-text {
font-size: 14px;
color: #666;
}
.color-tag {
width: 25px;
height: 25px;
}
.uni-list {
flex: 1;
}
.coupon {
.coupon-item {
width: 700rpx;
margin: 20rpx auto;
border-radius: 12rpx;
border-bottom: 1px #eee solid;
background: #fff;
.coupon-bg {
width: 140rpx;
height: 140rpx;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 26rpx;
color: #fff;
border-radius: 12rpx 0 0 12rpx;
background: linear-gradient(to right, #70b915, #008e04);
.price {
font-size: 50rpx;
}
}
.coupon-info {
padding: 20rpx;
display: flex;
justify-content: space-between;
.title{
line-height: 2rem;
}
}
.save-btn{
// margin-right: 20rpx;
}
.merchant-avatar {
margin-right: 12rpx;
}
.merchant-name {
// padding-left: 12rpx;
}
.btn-status {
font-size: 30rpx;
display: flex;
}
}
.order-body {
padding: 16px 0;
}
}
.ele-flex {
display: flex;
justify-content: space-between;
}
.card-actions {
display: flex;
flex-direction: row;
justify-content: flex-end;
align-items: center;
height: 45px;
border-top: 1px #eee solid;
}
.card-actions-item {
display: flex;
flex-direction: row;
align-items: center;
}
.card-actions-item-text {
font-size: 12px;
color: #666;
margin-left: 5px;
}
.close {
top: 60rpx !important;
}
.total-price {
display: flex;
flex-direction: column;
justify-content: flex-start;
font-size: 30rpx;
align-items: flex-start;
padding-left: 6rpx;
margin-left: 450rpx;
.web-text-heading {
font-size: 30rpx !important;
}
}
</style>
+535
View File
@@ -0,0 +1,535 @@
<template>
<view class="container">
<!-- deBug信息 -->
<view class="web-debug web-text-success" style="display: none">
场馆ID:{{ merchantId }} 场馆编号:{{ merchantCode }} 场馆名称:{{ merchantName }} 日期:{{ dateTime }} 星期:{{ week }} 订单总金额:{{ totalPrice }} 类型:{{
type
}}
商品信息:{{ goodsList }}
</view>
<!-- {{ address }} -->
<uni-card title="课程信息" :border="false" :is-shadow="false">
<uv-cell-group :customStyle="{ backgroundColor: '#ffffff' }" :border="false">
<uv-cell :title="`课程名称`" :label="form.courseName" :cellStyle="{ padding: '10px 0' }" :border="false" ></uv-cell>
<uv-cell :title="`上课课时`" :label="form.classPeriod" :cellStyle="{ padding: '10px 0' }" :border="false" ></uv-cell>
<uv-cell :title="`年龄限制`" :label="form.ageLimit" :cellStyle="{ padding: '10px 0' }" :border="false" ></uv-cell>
<uv-cell :title="`培训费用`" :label="`¥${form.price}`" :cellStyle="{ padding: '10px 0' }" :border="false" ></uv-cell>
<uv-cell :title="`上课时间`" :label="`${form.startTime}`" :cellStyle="{ padding: '10px 0' }" :border="false" ></uv-cell>
<uv-cell :title="`上课地点`" :label="`${form.address}`" :cellStyle="{ padding: '10px 0' }" :border="false" ></uv-cell>
</uv-cell-group>
</uni-card>
<uni-card title="报名学员" :border="false" :is-shadow="false">
<uv-cell
v-if="student"
:title="`${student.name}`"
icon="account"
:cellStyle="{ padding: '5px 0' }"
:border="false"
@click="openStudentList"
>
<template v-slot:right-icon>
<uv-icon name="arrow-right"></uv-icon>
</template>
</uv-cell>
<uv-cell
v-else
:title="`选择学员`"
icon="account"
:cellStyle="{ padding: '5px 0' }"
:border="false"
@click="openStudentList"
>
<template v-slot:right-icon>
<uv-icon name="arrow-right"></uv-icon>
</template>
</uv-cell>
</uni-card>
<uni-card title="选择支付方式" :border="false" :is-shadow="false">
<uv-cell-group :customStyle="{ backgroundColor: '#ffffff' }" :border="false">
<block v-for="(item, index) in payment" :key="index">
<uv-cell
:title="`${item.name}`"
:icon="`${item.image}`"
:cellStyle="{ padding: '20rpx 10rpx', borderRadius: '8rpx', backgroundColor: item.type == payType ? '#f6fff1' : '' }"
:border="false"
@click="onPayType(item.type)"
>
<template v-slot:right-icon>
<uv-icon v-if="item.type == payType" size="30rpx" name="checkbox-mark"></uv-icon>
</template>
</uv-cell>
</block>
</uv-cell-group>
<view slot="actions" class="card-actions">
<view class="card-actions-item" @click="actionsClick('分享')">
<span class="web-text-danger">已优惠¥0.00</span>
<span class="web-text-heading">¥{{ totalPrice || 0.0 }}</span>
</view>
</view>
</uni-card>
<view class="xieyi web-cell web-text-secondary web-cell-align-top">
<view class="web-cell web-cell-content web-cell-align-top">
<uni-icons type="circle" size="20" color="#a4a5a7" v-if="!disabled" @click="onDisabled"></uni-icons>
<uni-icons type="checkbox" size="20" color="#11a954" v-else @click="onDisabled"></uni-icons>
<view class="text" @click="onDisabled">
<text>同意以下服务条款</text>
<text class="link" @click.stop="navTo('/package/article/detail?articleId=501')">《广西体育中心预定条款》</text>
<text class="link" @click.stop="navTo('/package/article/detail?articleId=502')">《用户服务协议和隐私政策》</text>
</view>
</view>
</view>
<!-- 支付按钮 -->
<uv-gap height="50"></uv-gap>
<view class="checkout-car">
<view class="car-total">
<text style="color: #ebcf00">合计¥</text>
<uv-count-to :startVal="0" decimals="2" duration="100" color="#ebcf00" bold :endVal="totalPrice"></uv-count-to>
</view>
<uv-button
class="save-btn"
:disabled="!disabled || goodsList.length == 0"
:customStyle="{ background: 'linear-gradient(to right, #70b915, #008e04)', borderRadius: '0 30px 30px 0', color: '#ffffff', border: 'none', padding: '22px 30px' }"
text="提交订单"
@click="save"
></uv-button>
</view>
</view>
<!-- 学员选择弹窗 -->
<uni-popup ref="addForm" type="center" border-radius="10px 10px 0 0">
<uni-card title="选择学员" :border="false" :is-shadow="false" :padding="0">
<view class="address-body web-cell web-cell-align-top">
<view class="web-cell-content">
<uv-cell-group :customStyle="{ backgroundColor: '#ffffff' }" :border="false">
<block v-for="(item, index) in studentList" :key="index">
<uv-cell :cellStyle="{ padding: '10px 0' }" :label="item.address" @click="onAddress(item)">
<template v-slot:icon>
<uv-avatar :text="item.type" fontSize="12" size="32" randomBgColor></uv-avatar>
</template>
<template v-slot:title>
<view class="title-bar">
<text class="web-text-heading" style="font-weight: 700">{{ item.name }}</text>
<text class="web-text-secondary">{{ item.phone }}</text>
<uni-tag v-if="item.isDefault" text="默认" size="mini" inverted type="success"></uni-tag>
</view>
</template>
<template v-slot:right-icon>
<uni-icons type="right" style="color: #999999"></uni-icons>
</template>
</uv-cell>
</block>
<uv-button class="add-address" :customStyle="{ borderRadius: '30px' }" text="学员管理" @click="navTo('/package/course/student')"></uv-button>
</uv-cell-group>
</view>
</view>
</uni-card>
</uni-popup>
<!-- 支付密码弹窗 -->
<uni-popup ref="payPasswordForm" type="center" border-radius="10px 10px 0 0">
<uni-card title="请输入支付密码" :border="false" :is-shadow="false" :padding="0">
<view class="pay-password-card">
<uni-forms ref="form" :label-width="80">
<uni-forms-item label="支付密码" name="payPassword" required>
<uv-code-input mode="box" dot :space="0" :maxlength="6" hairline v-model="payPassword"></uv-code-input>
</uni-forms-item>
<uv-button
class="to-pay-btn"
:customStyle="{ background: 'linear-gradient(to right, #70b915, #008e04)', borderRadius: '30px', color: '#ffffff' }"
text="确定支付"
:disabled="disabledPayPayPassword"
@click="onPayPassword"
></uv-button>
</uni-forms>
<text @click="navTo(`/package/user/pay-password`)" class="web-text-primary">忘记支付密码?</text>
</view>
</uni-card>
</uni-popup>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
</template>
<script>
import * as Api from '@/api/shop/order';
import * as CourseApi from '@/api/booking/course';
import * as BookingStudentApi from '@/api/booking/student';
import * as PaymentApi from '@/api/system/payment';
import { checkPayPassword } from '@/api/passport/login';
import { storeToRefs } from 'pinia';
import { getWeek, getKey } from '@/utils/common';
import { useCarStore } from '@/store/modules/car';
import { useUserStore } from '@/store/modules/user';
const userStore = useUserStore();
const carStore = useCarStore();
const { goodsList, totalPrice, carNum, merchantId, merchantName, merchantCode, type, dateTime } = storeToRefs(carStore);
export default {
data() {
return {
courseId: 0,
form: {},
orderId: 0,
goodsId: 0,
userInfo: {},
student: {},
studentList: [],
week: 0,
goodsList,
// 骨架屏
hideTools: true,
// 订单总金额
totalPrice,
reducePrice: 0,
merchantId,
merchantName,
merchantCode,
getWeek,
payType: 1,
payment: [],
isLogin: false,
disabled: false,
// 支付密码是否正确
isPayPasswordCorrect: false,
disabledPayPayPassword: false,
payPassword: ''
};
},
onLoad(option) {
this.courseId = option.id;
this.reload();
},
onShow() {
// 登录状态
if (uni.getStorageSync('user_id') && uni.getStorageSync('access_token')) {
this.isLogin = true;
}
this.openLogin();
},
methods: {
async reload() {
const app = this;
const { orderId } = this;
// 当前登录用户信息
const userInfo = await userStore.fetchUserInfo();
app.userInfo = userInfo;
BookingStudentApi.pageStudent({userId: uni.getStorageSync('user_id')}).then(res => {
app.studentList = res.list
const arr = res.list.filter((d) => d.isDefault === true);
app.student = arr[0];
})
// UserAddressApi.pageUserAddress({}).then((res) => {
// app.addressList = res.list;
// const arr = res.list.filter((d) => d.isDefault === true);
// app.address = arr[0];
// });
// 读取支付方式列表
PaymentApi.select({ status: true }).then((list) => {
app.payment = list
.filter((d) => d.type < 2)
.map((d) => {
if (d.code == 'balancePay') {
d.name = `${d.name} (¥${userInfo.balance})`;
}
return d;
});
});
CourseApi.getCourse(app.courseId).then((data) => {
this.form = data;
});
// if (orderId > 0) {
// Api.getOrder(orderId).then(data => {
// app.merchantId = data.merchantId
// app.merchantName = data.merchantName
// app.merchantCode = data.merchantCode
// app.payType = data.payType
// app.orderInfo = data.orderInfoList
// app.totalPrice = data.totalPrice
// app.dateTime = data.orderInfoList[0].dateTime
// })
// }
},
onDisabled() {
this.disabled = !this.disabled;
},
navTo(url) {
uni.navigateTo({
url
});
},
openUrl(url) {
if (!this.isLogin) {
this.$refs.login.open('bottom');
return false;
} else {
uni.navigateTo({
url
});
}
},
onAddress(item) {
this.address = item;
this.$refs.addForm.close();
},
// 切换支付方式
onPayType(index) {
this.payType = index;
},
openStudentList() {
this.$refs.addForm.open('center');
},
// 弹出登录提示框
openLogin() {
if (!this.isLogin) {
this.$refs.login.open('bottom');
return false;
}
},
// 验证支付密码
onPayPassword() {
if (this.payPassword == '' || !this.payPassword) {
uni.showToast({
title: '请输入支付密码',
icon: 'none'
});
return false;
}
this.disabledPayPayPassword = true;
const { payPassword } = this;
checkPayPassword({ payPassword })
.then((res) => {
this.disabledPayPayPassword = false;
this.isPayPasswordCorrect = true;
this.save();
})
.catch((err) => {
uni.showToast({
title: err.message,
icon: 'none'
});
this.disabledPayPayPassword = false;
});
},
save() {
const app = this;
const { form, payType } = this;
if (!this.disabled) {
uni.showToast({
title: '请先阅读并同意服务协议',
icon: 'none'
});
return false;
}
if (carStore.goodsList.length == 0) {
uni.showToast({
title: '订单信息不存在',
icon: 'none'
});
return false;
}
if (app.payType == 0 && !this.isPayPasswordCorrect) {
this.$refs.payPasswordForm.open('center');
return false;
}
uni.showLoading({
title: '订单提交中.'
});
Api.addOrder({
type: 0, // 0商城订单
orderId: this.orderId,
merchantId: this.merchantId,
merchantCode: this.merchantCode,
merchantName: this.merchantName,
totalPrice: this.totalPrice,
payPrice: this.totalPrice - this.reducePrice,
goodsList: this.goodsList,
comments: this.goodsList[0].goodsName,
// 微信支付
payType: this.payType,
// 下单日期
dateTime: this.dateTime
})
.then((data) => {
const orderInfo = data;
// 调起微信支付
// #ifdef MP-WEIXIN
uni.requestPayment({
provider: orderInfo.provider, // 服务提供商
timeStamp: orderInfo.timeStamp, // 时间戳
nonceStr: orderInfo.nonceStr, // 随机字符串
package: orderInfo.package,
signType: orderInfo.signType, // 签名算法
paySign: orderInfo.paySign, // 签名
success: function (res) {
// 业务逻辑。。。
uni.showToast({
title: '支付成功',
icon: 'success'
});
setTimeout(function () {
app.disabled = false;
uni.navigateTo({
url: '/package/goods/order'
});
}, 500);
},
fail: function (err) {
console.log('支付失败', err);
app.disabled = false;
uni.navigateTo({
url: '/package/goods/order'
});
}
});
// #endif
uni.hideLoading();
})
.catch((res) => {
uni.showToast({
title: res.message || '请检查您的网络.',
icon: 'none'
});
uni.hideLoading();
});
}
}
};
</script>
<style>
page {
background-size: 100%;
background-repeat: no-repeat;
background-color: #f0f2f5;
width: 750rpx;
overflow-x: hidden;
}
</style>
<style lang="scss" scoped>
.container {
}
.checkout-car {
width: 700rpx;
left: 25rpx;
position: fixed;
bottom: 30rpx;
display: flex;
justify-content: space-between;
background-color: #000000;
border-radius: 100px;
align-items: center;
.car-selected {
color: #ccc;
display: flex;
align-items: center;
padding: 0 20rpx;
}
.car-total {
display: flex;
color: #ebcf00;
align-items: center;
padding-left: 40rpx;
.save-btn {
}
}
}
.card-actions {
display: flex;
flex-direction: row;
justify-content: flex-end;
height: 45px;
border-top: 1px #eee solid;
}
.card-actions-item {
display: flex;
flex-direction: row;
align-items: center;
.web-text-heading {
font-size: 38rpx;
margin-left: 28rpx;
}
}
.card-actions-item-text {
font-size: 12px;
color: #666;
margin-left: 5px;
}
.address-body {
width: 660rpx;
margin: auto;
}
.add-address {
width: 600rpx !important;
margin: 40rpx auto;
}
.btn-bar {
width: 700rpx;
left: 25rpx;
position: fixed;
bottom: 30rpx;
margin: auto;
clear: both;
}
.title-bar {
display: flex;
.web-text-heading {
margin-right: 20rpx;
}
.web-text-secondary {
margin-right: 20rpx;
}
}
.xieyi {
margin-bottom: 80rpx;
padding: 0 30rpx;
.text {
margin-left: 5rpx;
.link {
color: #0f80ff;
}
}
}
.pay-password-card {
width: 600rpx;
min-height: 300rpx;
margin: 30rpx auto;
background-color: #ffffff;
text-align: center;
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
.web-text-primary {
line-height: 2rem;
padding: 20rpx 0;
}
}
.to-pay-btn {
width: 400rpx !important;
margin: 40rpx auto;
}
</style>
+542
View File
@@ -0,0 +1,542 @@
<template>
<view class="container">
<view class="uv-demo-block">
<uv-swiper :list="photo" indicator indicatorMode="line" circular height="200" radius="0"></uv-swiper>
</view>
<uni-card v-if="course.courseName" :border="false" :is-shadow="false" :padding="0">
<uv-cell-group :customStyle="{ backgroundColor: '#ffffff' }" :border="false">
<uv-cell :cellStyle="{ padding: '10px 5px' }" :border="false">
<template v-slot:title>
<view class="merchant-name">{{ course.courseName }}</view>
</template>
</uv-cell>
<uv-cell :cellStyle="{ padding: '10px 5px' }" :border="false">
<template v-slot:title>
<view class="pirce-bar" style="display: flex">
<view class="web-text-danger">¥</view>
<view class="web-text-danger" style="font-size: 40rpx">{{ course.price }}</view>
<view style="margin-left: 30rpx"><uni-tag :text="`${course.classPeriod}课时`" inverted type="error"></uni-tag></view>
</view>
</template>
</uv-cell>
<uv-cell
:title="course.merchantName"
:label="`距离【${course.merchantName}】3.8公里·约7分钟`"
isLink
:border="false"
:cellStyle="{ padding: '10px 5px' }"
@click="mapTo(course)"
>
<template v-slot:right-icon>
<uv-icon size="50rpx" name="map-fill" color="#5ac725" style="color: #ff0000"></uv-icon>
</template>
</uv-cell>
<uv-cell title="年龄限制" :label="course.ageLimit" :border="false" :cellStyle="{ padding: '10px 5px' }"></uv-cell>
<uv-cell title="报名时间" :label="course.bmTime" :border="false" :cellStyle="{ padding: '10px 5px' }"></uv-cell>
</uv-cell-group>
</uni-card>
<uni-card title="课程介绍" :is-shadow="false" :border="false" :padding="0">
<view class="web-text-heading booking-content">
<uv-image :src="`https://oss.wsdns.cn/20240608/1ce5b3f9b33b48b2bc9d68644e8ba6f4.jpg`"></uv-image>
<view v-html="course.content"></view>
<!-- <uv-empty icon="https://cdn.uviewui.com/uview/empty/car.png"></uv-empty> -->
<!-- <uv-gap height="50"></uv-gap> -->
</view>
</uni-card>
<uni-card title="课程教练" :is-shadow="false" :border="false" :padding="0">
<view class="teacher-list">
<view class="teacher-item" @click="openUrl(`/package/teacher/detail?id=1`)">
<uv-avatar
src="https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTKf8Lvm8WN0LnV2B6vYzyGJVxk2XW3j1mtDzicA60KhWRRjyU8ORiascwInkbqhVibRm2A1O1tRRbzhA/132"
size="54"
></uv-avatar>
<view class="teacher-info">
<uv-text text="游泳教练" align="center" size="16"></uv-text>
<uv-text text="游泳企事业800" type="warning" size="12"></uv-text>
</view>
</view>
<!-- <view class="teacher-item">
<uv-avatar
src="https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTKf8Lvm8WN0LnV2B6vYzyGJVxk2XW3j1mtDzicA60KhWRRjyU8ORiascwInkbqhVibRm2A1O1tRRbzhA/132"
size="50"
></uv-avatar>
<view class="teacher-info">
<uv-text text="游泳教练" align="center" size="16"></uv-text>
<uv-text text="游泳企事业800" type="warning" size="12"></uv-text>
</view>
</view>
<view class="teacher-item">
<uv-avatar
src="https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTKf8Lvm8WN0LnV2B6vYzyGJVxk2XW3j1mtDzicA60KhWRRjyU8ORiascwInkbqhVibRm2A1O1tRRbzhA/132"
size="54"
></uv-avatar>
<view class="teacher-info">
<uv-text text="游泳教练" align="center" size="16"></uv-text>
<uv-text text="游泳企事业800" type="warning" size="12"></uv-text>
</view>
</view> -->
</view>
</uni-card>
<!-- <view class="xieyi web-cell web-text-secondary web-cell-align-top">
<view class="web-cell web-cell-content web-cell-align-top">
<uni-icons type="circle" size="20" color="#a4a5a7" v-if="!disabled" @click="onDisabled"></uni-icons>
<uni-icons type="checkbox" size="20" color="#11a954" v-else @click="onDisabled"></uni-icons>
<view class="text" @click="onDisabled">
<text>我已阅读并同意</text>
<text class="link"
@click.stop="navTo('/package/article/detail?articleId=503')">《订票协议》</text>
</view>
</view>
</view> -->
<uv-gap height="80"></uv-gap>
<view class="save-btn">
<uni-goods-nav :fill="true" :options="options" :button-group="buttonGroup" @click="onClick" @buttonClick="openBookingTel" />
</view>
<!-- <view class="save-btn">
<uv-button
:customStyle="{background: 'linear-gradient(to right, #ccff66, #008e04)',borderRadius: '30px',color: '#ffffff'}"
text="立即报名" @click="save"></uv-button>
</view> -->
</view>
<!-- <view class="booking-tel" @click="openBookingTel">活动订场</view> -->
<!-- 立即报名弹窗 -->
<uni-popup ref="popup" type="center">
<view class="popup-checkout">
<uv-gap height="10"></uv-gap>
<uv-cell-group :customStyle="{ backgroundColor: '#ffffff' }" :border="false">
<uv-cell :cellStyle="{ padding: '10px 15px' }" :border="false">
<template v-slot:title>
<view class="pirce-bar" style="display: flex">
<uv-text mode="price" color="#ff0000" bold size="20" :text="course.price"></uv-text>
</view>
</template>
</uv-cell>
<uv-cell title="规格" :border="false"></uv-cell>
<uv-cell :border="false" :cellStyle="{ padding: '0 15px' }">
<template v-slot:title>
<uni-data-checkbox mode="tag" v-model="radio2" :localdata="sex"></uni-data-checkbox>
</template>
</uv-cell>
<uv-cell title="班级/教练" :border="false"></uv-cell>
<uv-cell :border="false" :cellStyle="{ padding: '0 15px' }">
<template v-slot:title>
<uni-data-checkbox mode="tag" v-model="radio3" :localdata="teacher"></uni-data-checkbox>
</template>
</uv-cell>
<uv-cell title="报名学员" :border="false"></uv-cell>
<uv-cell :border="false" :cellStyle="{ padding: '0 15px' }">
<template v-slot:title>
<view style="display: flex">
<uni-data-checkbox mode="tag" v-model="radio4" :localdata="student"></uni-data-checkbox>
<uv-tags text="新增" type="info" size="mini" icon="plus" plain></uv-tags>
</view>
</template>
</uv-cell>
<view class="checkout-car">
<view class="car-total">
<text style="color: #ebcf00">合计¥</text>
<!-- <uv-count-to :startVal="0" decimals="2" duration="100" color="#ebcf00" bold :endVal="totalPrice"></uv-count-to> -->
</view>
<uv-button
:disabled="!disabled"
:customStyle="{
background: 'linear-gradient(to right, #FE6035, #EF1224)',
borderRadius: '0 30px 30px 0',
color: '#ffffff',
border: 'none',
padding: '22px 30px'
}"
text="下一步"
@click="save"
></uv-button>
</view>
</uv-cell-group>
</view>
</uni-popup>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
</template>
<script>
import { storeToRefs } from 'pinia';
import * as CourseApi from '@/api/booking/course';
import { useCarStore } from '@/store/modules/car';
const carStore = useCarStore();
export default {
data() {
return {
id: 0,
// 课程信息
course: {},
// 课程相册
photo: [],
isLogin: false,
disabled: true,
options: [
{
icon: 'headphones',
text: '客服'
},
{
icon: 'upload',
text: '分享'
}
],
buttonGroup: [
{
text: '立即报名',
backgroundColor: 'linear-gradient(90deg, #FE6035, #EF1224)',
color: '#fff'
}
],
radio2: 0,
sex: [
{
text: '幼儿基础班(10次课,10天连续上课)',
value: 0
},
{
text: '少年基础班(10次课,10天连续上课)',
value: 1
},
{
text: '少年基础班(10次课,10天连续上课)',
value: 2
},
{
text: '成人基础班(10次课,10天连续上课)',
value: 3
}
],
teacher: [
{
text: '姚教练',
value: 0
}
],
student: [
{
text: '全红婵',
value: 0
}
]
};
},
onLoad(option) {
this.id = option.id;
this.reload();
},
onShow() {
// 登录状态
if (uni.getStorageSync('user_id') && uni.getStorageSync('access_token')) {
this.isLogin = true;
}
},
methods: {
async reload() {
const app = this;
// 请求数据
Promise.all([app.getCourse()]).then((res) => {
const course = res[0];
app.course = course;
// 修改标题
uni.setNavigationBarTitle({
title: course.courseName
});
// 加载课程相册
if (course.files) {
app.photo = JSON.parse(course.files);
}
// 更新购物车状态
// carStore.setMerchant(merchant)
// carStore.merchantId = course.merchantId
// carStore.merchantName = course.merchantName
// carStore.merchantCode = course.merchantCode
});
},
getCourse() {
return new Promise((resolve, reject) => {
CourseApi.getCourse(this.id)
.then((result) => {
resolve(result);
})
.catch(reject);
});
},
onDisabled() {
this.disabled = !this.disabled;
},
navTo(url) {
uni.navigateTo({
url
});
},
onClick(e) {
const app = this;
const { course } = app;
console.log('e: ', e);
if (e.index == 0) {
// 企业微信客服
// #ifdef H5
window.open(`setting.config.wxqykf.url`);
// #endif
// #ifdef MP-WEIXIN
wx.openCustomerServiceChat({
extInfo: { url: `` },
corpId: `setting.config.wxqykf.corpId`,
success(res) {}
});
// #endif
// #ifdef APP-PLUS
uni.share({
provider: 'weixin',
scene: 'WXSceneSession',
type: 0,
openCustomerServiceChat: true,
corpid: `setting.config.wxqykf.corpId`,
customerUrl: `setting.config.wxqykf.url`,
success(res) {
console.log('success:' + JSON.stringify(res));
},
fail(e) {
console.log('errCode', e.errCode, e);
if (e.errCode === -8) {
app.$toast('很抱歉,您的手机没有安装微信~');
}
}
});
// #endif
}
if (e.index == 1) {
uni.share({
provider: 'weixin',
scene: "WXSceneSession",
type: 5,
imageUrl: '',
title: course.name,
miniProgram: {
id: 'gh_abcdefg',
path: 'package/course/detail?id=' + app.id,
type: 0,
webUrl: 'http://apps.gxwebsoft.com/gxtyzx-h5/#/package/course/detail?id=' + app.id
},
success: ret => {
console.log(JSON.stringify(ret));
}
});
}
// uni.showToast({
// title: `点击${e.content.text}`,
// icon: 'none'
// });
},
mapTo(item) {
// console.log('item: ',item.lngAndLat);
const arr = item.lngAndLat.split(',');
// console.log('arr: ',arr);
uni.openLocation({
latitude: parseFloat(arr[1]),
longitude: parseFloat(arr[0]),
success: function () {
console.log('success');
}
});
},
openBookingTel() {
uni.navigateTo({
url: '/package/course/checkout?id=' + this.id
})
// 通过组件定义的ref调用uni-popup方法 ,如果传入参数 ,type 属性将失效 ,仅支持 ['top','left','bottom','right','center']
// this.$refs.popup.open('bottom');
},
closeBookingTel() {
this.$refs.popup.close();
},
callPhone(phone) {
uni.makePhoneCall({
phoneNumber: phone
});
},
onMap() {
uni.getLocation({
type: 'gcj02', //返回可以用于uni.openLocation的经纬度
success: function (res) {
console.log('返回可以用于uni.openLocation的经纬度: ', res);
const latitude = this.course.latitude;
const longitude = this.course.longitude;
uni.openLocation({
latitude: latitude,
longitude: longitude,
success: function () {
console.log('success');
}
});
}
});
},
openUrl(url) {
uni.navigateTo({
url
});
},
save() {
if (!this.disabled) {
uni.showToast({
title: '请先阅读并同意订票协议',
icon: 'none'
});
return false;
}
uni.navigateTo({
url: '/package/course/checkout?id=' + this.id
});
}
}
};
</script>
<style>
page {
background-size: 100%;
background-repeat: no-repeat;
background-color: #f0f2f5;
width: 750rpx;
overflow-x: hidden;
}
</style>
<style lang="scss" scoped>
.container {
}
.merchant-name {
font-weight: 500;
font-size: 28rpx;
background-color: #ffffff;
}
.save-btn {
width: 750rpx;
background-color: #ffffff;
position: fixed;
padding-bottom: 30rpx;
bottom: 0;
}
.booking-tel {
position: fixed;
z-index: 1;
top: 270px;
right: 0;
width: 80px;
height: 38px;
border-radius: 50px 0 0 50px;
background: linear-gradient(to right, #ccff66, #008e04);
display: flex;
align-items: center;
justify-content: center;
color: #ffffff;
font-size: 13px;
}
.popup-checkout {
background-color: #ffffff;
width: 100vw;
height: 60vh;
border-radius: 20rpx 20rpx 0 0;
margin: auto;
z-index: 9999;
display: flex;
flex-direction: column;
.title {
font-weight: bold;
font-size: 38rpx;
text-align: center;
padding: 10px 0;
}
.desc {
line-height: 2rem;
}
}
.popup-close {
display: flex;
margin-top: 24rpx;
justify-content: center;
}
.booking-content {
padding: 10px;
font-size: 30rpx;
line-height: 1.5rem;
}
.xieyi {
margin-bottom: 80rpx;
padding: 0 30rpx;
.text {
margin-left: 5rpx;
.link {
color: #0f80ff;
}
}
}
.teacher-list {
display: flex;
flex-wrap: wrap;
.teacher-item {
margin: 20rpx 12rpx;
display: flex;
width: 160rpx;
height: 200rpx;
flex-direction: column;
justify-content: space-between;
align-items: center;
background-color: #f3f3f3;
border-radius: 12rpx;
padding: 16rpx;
.teacher-info {
text-align: center;
}
}
}
.checkout-car {
width: 700rpx;
left: 25rpx;
position: fixed;
z-index: 9999;
bottom: 30rpx;
display: flex;
justify-content: space-between;
background-color: #000000;
border-radius: 100px;
align-items: center;
.car-selected {
color: #ccc;
display: flex;
align-items: center;
padding: 0 20rpx;
}
.car-total {
display: flex;
color: #ebcf00;
align-items: center;
padding-left: 40rpx;
.save-btn {
}
}
}
</style>
+210
View File
@@ -0,0 +1,210 @@
<template>
<view>
<!-- 列表列表 -->
<block v-if="itemList.length > 0">
<uv-gap height="10"></uv-gap>
<view class="item-list">
<uni-grid :column="5" :highlight="true" :showBorder="false" @change="onItem">
<uni-grid-item v-for="(item, index) in itemList" :index="index" :key="index">
<view
class="grid-item-box"
style="
background-color: #ffffff;
margin: 10rpx;
border-radius: 10rpx;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 5rem;
"
>
<uv-avatar :src="item.image" :size="30" shape="square" fontSize="16" randomBgColor></uv-avatar>
<text class="text">{{ item.name }}</text>
</view>
</uni-grid-item>
</uni-grid>
</view>
</block>
<block v-else>
<uni-card :border="false" :is-shadow="false" :padding="'12px 4px'">
<uv-skeleton rows="3" :loading="hideTools" :title="false"></uv-skeleton>
</uni-card>
</block>
<!-- 热门培训 -->
<view class="card-title web-text-heading">热门培训</view>
<block v-if="list.length > 0">
<view class="course-list">
<block v-for="(item,index) in list" :key="index">
<view class="course-item" @click="openUrl(`/package/course/detail?id=` + item.courseId)">
<uv-image :src="item.image" width="200" height="110"></uv-image>
<view class="course-info">
<uv-text class="course-name" size="15" lineHeight="24" :lines="1" :text="item.courseName"></uv-text>
<uv-text class="course-name web-text-secondary" lineHeight="24" size="13" :text="`${item.classPeriod}课时`"></uv-text>
<view class="flex justify-between w-full">
<uv-text class="course-name web-text-danger" mode="price" color="#ff0000" :text="`${item.price}`"></uv-text>
<view>
<uv-text :text="`1.3km`" class="web-text-secondary px-2"></uv-text>
</view>
</view>
</view>
</view>
</block>
</view>
</block>
<block v-else>
<uni-card :border="false" :is-shadow="false" :padding="'12px 4px'">
<uv-skeleton rows="2" avatar :loading="hideTools" :title="false"></uv-skeleton>
<uv-gap height="16"></uv-gap>
<uv-skeleton rows="2" avatar :loading="hideTools" :title="false"></uv-skeleton>
<uv-gap height="16"></uv-gap>
<uv-skeleton rows="2" avatar :loading="hideTools" :title="false"></uv-skeleton>
<uv-gap height="16"></uv-gap>
<uv-skeleton rows="2" avatar :loading="hideTools" :title="false"></uv-skeleton>
<uv-gap height="16"></uv-gap>
</uni-card>
</block>
</view>
</template>
<script>
import * as CourseApi from '@/api/booking/course';
import * as ItemApi from '@/api/booking/item';
export default {
data() {
return {
list: [],
// 骨架屏
hideTools: true,
// 项目列表
itemList: []
};
},
onLoad() {
this.reload();
},
methods: {
reload() {
const app = this;
// 请求数据
Promise.all([app.getCourseList(), app.getItemList()]).then((res) => {
console.log('res: ', res);
app.list = res[0];
app.itemList = res[1];
});
},
getCourseList() {
const app = this;
const { categoryId } = this;
return new Promise((resolve, reject) => {
CourseApi.pageCourse({})
.then((result) => {
resolve(result.list);
})
.catch(reject);
});
},
getItemList() {
const app = this;
return new Promise((resolve, reject) => {
ItemApi.listItem({})
.then((result) => {
resolve(result);
})
.catch(reject);
});
},
onItem(e){
const { index } = e.detail;
this.openUrl(`/package/course/list?categoryId=${this.itemList[index].id}&categoryName=${this.itemList[index].name}`)
},
openUrl(url) {
uni.navigateTo({
url
});
}
}
};
</script>
<style lang="scss" scoped>
.card-title {
width: 700rpx;
margin: 12rpx auto;
font-size: 34rpx;
font-weight: 500;
margin-top: 32rpx;
}
.course-list {
width: 700rpx;
margin: auto !important;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
.course-item{
width: 335rpx;
margin: 16rpx 0;
border-radius: 16rpx;
overflow: hidden;
background-color: #ffffff;
.course-info{
padding: 10rpx 16rpx;
line-height: 35rpx;
}
.course-name{
}
.price-bar{
padding: 0 16rpx;
display: flex;
justify-content: space-between;
}
.course-image{
}
}
}
.item-list {
width: 720rpx;
margin: auto;
}
.merchant-card-title {
width: 700rpx;
margin: 12rpx auto;
font-size: 40rpx;
font-weight: 500;
margin-top: 32rpx;
}
.card-body {
width: 700rpx;
margin: auto;
.merchant-card {
margin: 12rpx auto;
border-radius: 10rpx;
border-color: slategrey;
border-radius: 16rpx;
display: flex;
justify-content: space-between;
.merchant-image {
width: 45vw;
border-radius: 16rpx 16rpx 0 0;
}
.merchant-name {
padding: 10rpx;
overflow: hidden;
font-weight: 500;
font-size: 26rpx;
text-align: center;
}
.merchant-desc {
width: 400rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
</style>
+182
View File
@@ -0,0 +1,182 @@
<template>
<view>
<block v-if="!hideTools">
<uv-gap height="5"></uv-gap>
<view class="course-list">
<block v-for="(item,index) in list" :key="index">
<view class="course-item" @click="openUrl(`/package/course/detail?id=` + item.courseId)">
<uv-image :src="item.image" width="200" height="110"></uv-image>
<uv-gap height="5"></uv-gap>
<uv-text class="course-name" size="15" :lines="1" :text="item.courseName"></uv-text>
<uv-text class="course-name web-text-secondary" size="13" :text="`${item.classPeriod}课时`"></uv-text>
<view class="flex justify-between w-full">
<uv-text class="course-name web-text-danger" mode="price" color="#ff0000" :text="`${item.price}`"></uv-text>
<view>
<uv-text :text="`1.3km`" class="web-text-secondary px-2"></uv-text>
</view>
</view>
<uv-gap height="5"></uv-gap>
</view>
</block>
</view>
</block>
<block v-else>
<uni-card :border="false" :is-shadow="false" :padding="'12px 4px'">
<uv-skeleton rows="2" avatar :loading="hideTools" :title="false"></uv-skeleton>
<uv-gap height="16"></uv-gap>
<uv-skeleton rows="2" avatar :loading="hideTools" :title="false"></uv-skeleton>
<uv-gap height="16"></uv-gap>
<uv-skeleton rows="2" avatar :loading="hideTools" :title="false"></uv-skeleton>
<uv-gap height="16"></uv-gap>
<uv-skeleton rows="2" avatar :loading="hideTools" :title="false"></uv-skeleton>
<uv-gap height="16"></uv-gap>
</uni-card>
</block>
</view>
</template>
<script>
import * as CourseApi from '@/api/booking/course';
import * as ItemApi from '@/api/booking/item';
export default {
data() {
return {
categoryId: 0,
categoryName: '',
list: [],
// 骨架屏
hideTools: true,
// 项目列表
itemList: []
};
},
onLoad(option) {
if (option) {
this.categoryId = option.categoryId;
this.categoryName = option.categoryName
uni.setNavigationBarTitle({
title: option.categoryName
})
}
this.reload();
},
methods: {
reload() {
const app = this;
// 请求数据
Promise.all([app.getCourseList(), app.getItemList()]).then((res) => {
console.log('res: ', res);
app.list = res[0];
app.itemList = res[1];
app.hideTools = false;
});
},
getCourseList() {
const app = this;
const { categoryId } = this;
return new Promise((resolve, reject) => {
CourseApi.pageCourse({ categoryId })
.then((result) => {
resolve(result.list);
})
.catch(reject);
});
},
getItemList() {
const app = this;
return new Promise((resolve, reject) => {
ItemApi.listItem({})
.then((result) => {
resolve(result);
})
.catch(reject);
});
},
openUrl(url) {
uni.navigateTo({
url
});
}
}
};
</script>
<style lang="scss" scoped>
.card-title {
width: 700rpx;
margin: 12rpx auto;
font-size: 34rpx;
font-weight: 500;
margin-top: 32rpx;
}
.course-list {
width: 700rpx;
margin: auto !important;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
.course-item{
width: 335rpx;
margin: 16rpx 0;
border-radius: 16rpx;
overflow: hidden;
background-color: #ffffff;
.course-name{
line-height: 1.4rem;
padding: 0 16rpx;
}
.price-bar{
padding: 0 16rpx;
display: flex;
justify-content: space-between;
}
.course-image{
}
}
}
.item-list {
width: 720rpx;
margin: auto;
}
.merchant-card-title {
width: 700rpx;
margin: 12rpx auto;
font-size: 40rpx;
font-weight: 500;
margin-top: 32rpx;
}
.card-body {
width: 700rpx;
margin: auto;
.merchant-card {
margin: 12rpx auto;
border-radius: 10rpx;
border-color: slategrey;
border-radius: 16rpx;
display: flex;
justify-content: space-between;
.merchant-image {
width: 45vw;
border-radius: 16rpx 16rpx 0 0;
}
.merchant-name {
padding: 10rpx;
overflow: hidden;
font-weight: 500;
font-size: 26rpx;
text-align: center;
}
.merchant-desc {
width: 400rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
</style>
+384
View File
@@ -0,0 +1,384 @@
<template>
<view class="page">
<!-- 其他功能 -->
<uni-card :border="false" :is-shadow="false" :padding="0">
<view class="order-body web-cell web-cell-align-top">
<view class="web-cell-content">
<uv-cell-group :customStyle="{backgroundColor: '#ffffff'}" :border="false">
<block v-for="(item,index) in list" :key="index">
<uv-cell :cellStyle="{padding: '10px 0'}">
<template v-slot:icon>
<uv-avatar :text="item.type" fontSize="12" size="32" randomBgColor></uv-avatar>
</template>
<template v-slot:title>
<view class="title-bar">
<text class="web-text-heading" style="font-weight: 700;">{{ item.name }}</text>
<text class="web-text-secondary">{{ item.phone }}</text>
<uni-tag v-if="item.isDefault" text="默认" size="mini" inverted type="success"></uni-tag>
</view>
</template>
<template v-slot:right-icon>
<uni-icons type="compose" style="color: #999999;" size="18"
@click="openEdit(item)"></uni-icons>
</template>
</uv-cell>
</block>
</uv-cell-group>
</view>
</view>
</uni-card>
<view class="btn-bar">
<uv-button class="save-user-profile"
:customStyle="{background: 'linear-gradient(to right, #70b915, #008e04)',borderRadius: '30px',color: '#ffffff'}"
text="添加学员" @click="add"></uv-button>
</view>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
<!-- addressEdit弹窗 -->
<uni-popup ref="addForm" type="center" border-radius="10px 10px 0 0">
<uni-card title="添加学员" :border="false" :is-shadow="false" :padding="'10px 6px'">
<uni-forms ref="form" :modelValue="formData" :rules="rules" :label-width="80">
<uni-forms-item label="收件人" name="name" required>
<uv-input placeholder="收件人姓名" v-model="formData.name" maxlength="5"></uv-input>
</uni-forms-item>
<uni-forms-item label="手机号码" name="phone" required>
<uv-input placeholder="收件人手机号码" v-model="formData.phone" maxlength="11"></uv-input>
</uni-forms-item>
<uni-forms-item label="所在地区" name="region" required>
<uni-data-picker placeholder="省、市、区、街道" popup-title="请选择所在地区" :localdata="regions"
:map="{text:'label',value: 'value'}" v-model="formData.region" @change="onchange" @nodeclick="onnodeclick"
@popupopened="onpopupopened" @popupclosed="onpopupclosed">
</uni-data-picker>
</uni-forms-item>
<uni-forms-item label="详细地址" name="address" required>
<uv-input placeholder="小区、写字楼、门牌号等" v-model="formData.address"></uv-input>
</uni-forms-item>
<uni-forms-item label="标签" name="type">
<uni-data-checkbox mode="tag" v-model="formData.type" :localdata="typeData" @change="onType"></uni-data-checkbox>
</uni-forms-item>
<uni-forms-item name="isDefault">
<view class="web-cell">
<uni-data-checkbox v-model="formData.isDefault"
:localdata="defaultData" @click="onIsDefault"></uni-data-checkbox>
<view v-if="formData.id" class="del-btn" @click="remove(formData)">
<uni-icons type="trash" class="web-cell" style="color: #999999;">
<text class="web-text-danger"
style="font-size: 22rpx; padding-left: 4rpx;">删除</text>
</uni-icons>
</view>
</view>
</uni-forms-item>
<uv-button class="add-address"
:customStyle="{background: 'linear-gradient(to right, #70b915, #008e04)',borderRadius: '30px',color: '#ffffff'}"
text="保存" @click="submit"></uv-button>
</uni-forms>
</uni-card>
</uni-popup>
</view>
</template>
<script>
import * as Api from '@/api/shop/userAddress';
import * as MpMenuApi from '@/api/cms/mp-menu/index';
import regions from '@/api/regions-data.json';
import {
getWxOpenId
} from '@/api/passport/login';
import {
openUrl
} from '@/utils/common';
import {
useUserStore
} from '@/store/modules/user';
import {
useCarStore
} from '@/store/modules/car';
const userStore = useUserStore();
const carStore = useCarStore();
export default {
data() {
return {
list: [],
statusBarHeight: 104,
isLogin: false,
form: {
name: '',
phone: ''
},
// 表单数据
formData: {},
fields: {},
logo: '',
bookingUser: {},
server: [],
order: [],
defaultData: [{
text: '默认学员',
value: true
}],
typeData: [{
text: '家',
value: '家'
},
{
text: '公司',
value: '公司'
},
{
text: '学校',
value: '学校'
}
],
regions,
dataTree: [{
text: "一年级",
value: "1-0",
children: [{
text: "1.1班",
value: "1-1"
},
{
text: "1.2班",
value: "1-2"
}
]
},
{
text: "二年级",
value: "2-0",
children: [{
text: "2.1班",
value: "2-1"
},
{
text: "2.2班",
value: "2-2"
}
]
},
{
text: "三年级",
value: "3-0",
disable: true
}
],
rules: {
// 对name字段进行必填验证
name: {
rules: [{
required: true,
errorMessage: '请输入收件人名称',
}]
},
phone: {
rules: [{
required: true,
format: 'number',
errorMessage: '请输入正确的手机号码',
}]
},
address: {
rules: [{
required: true,
errorMessage: '请输入详情地址',
}]
},
region: {
rules: [{
required: true,
errorMessage: '请选择所在地区',
}, {
validateFunction: function(rule, value, data, callback) {
console.log('value: ', value);
if (value.length < 2) {
callback('请至少勾选两个兴趣爱好')
}
return true
}
}]
}
}
}
},
onLoad() {
this.reload()
},
methods: {
async reload(e) {
const app = this
// 当前登录用户信息
const userInfo = await userStore.fetchUserInfo();
if (Object.keys(userInfo).length > 0) {
app.isLogin = true
app.userInfo = userInfo
} else {
app.isLogin = false
}
// 获取学员列表
Api.pageUserAddress({
userId: userInfo.userId
}).then(res => {
app.list = res.list;
})
// 获取地区选择数据
// this.regions = this.regions.map(d => {
// console.log('d: ',d);
// d.text = d.label
// return d;
// })
// Api.getRegions().then(res => {
// console.log('res: ',res);
// })
},
navTo(item) {
if (!this.isLogin) {
this.$refs.login.open('bottom')
return false;
}
openUrl(item);
},
// 弹出登录提示框
openLogin() {
if (!this.isLogin) {
this.$refs.login.open('bottom')
return false;
}
},
onType(e){
this.formData.type = e.detail.value;
},
onIsDefault(){
this.formData.isDefault = !this.formData.isDefault;
},
// 选用该地址
onAddres(item){
carStore.setAddress(item)
uni.navigateBack()
},
add() {
this.formData = {}
this.$refs.addForm.open('center')
},
openEdit(item) {
this.formData = item
this.$refs.addForm.open('center')
},
remove(item) {
const app = this
uni.showModal({
title: '确定要删除吗?',
success(o) {
if (o.confirm) {
uni.showLoading({
title: '请求中.'
})
Api.removeUserAddress(item.id).then(res => {
uni.showToast({
title: '操作成功',
icon: 'none'
})
app.$refs.addForm.close()
app.reload()
})
app.reload()
}
}
});
},
// 触发提交表单
submit() {
this.$refs.form.validate().then(res => {
const saveOrUpdate = this.formData.id ? Api.updateUserAddress : Api.addUserAddress
saveOrUpdate(this.formData).then(message => {
uni.showToast({
title: '保存成功',
icon: 'success'
})
this.$refs.addForm.close()
this.reload()
}).catch((err) => {
console.log(err);
})
console.log('表单数据信息:', res);
}).catch(err => {
console.log('表单错误信息:', err);
})
},
save() {
Api.addUserAddress(this.form).then(msg => {
uni.showToast({
title: msg,
icon: 'none'
})
this.$refs.addForm.close()
this.reload()
}).catch(() => {
uni.showToast({
title: '请检查您的网络.',
icon: 'none'
})
uni.hideLoading()
this.$refs.addForm.close()
this.reload()
})
}
}
}
</script>
<style>
page {
background-size: 100%;
background-repeat: no-repeat;
background-color: #f0f2f5;
width: 750rpx;
overflow-x: hidden;
}
</style>
<style lang="scss">
.avatar {
padding: 20px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 14px;
}
.save-user-profile {
width: 700rpx;
margin: 40rpx auto;
}
.add-address {
width: 600rpx !important;
margin: 40rpx auto;
}
.btn-bar {
width: 700rpx;
left: 25rpx;
position: fixed;
bottom: 30rpx;
margin: auto;
clear: both;
}
.title-bar {
display: flex;
.web-text-heading {
margin-right: 20rpx;
}
.web-text-secondary {
margin-right: 20rpx;
}
}
</style>
+549
View File
@@ -0,0 +1,549 @@
<template>
<view class="container">
<!-- deBug信息 -->
<view class="web-debug web-text-success" style="display: none">
场馆ID:{{ merchantId }} 场馆编号:{{ merchantCode }} 场馆名称:{{ merchantName }} 日期:{{ dateTime }} 星期:{{ week }} 订单总金额:{{ totalPrice }} 类型:{{
type
}}
商品信息:{{ goodsList }}
</view>
<!-- {{ address }} -->
<uni-card :border="false" :is-shadow="false">
<uv-cell
v-if="address.name"
:title="`${address.name} &nbsp; ${address.phone}`"
:label="`${address.address}`"
icon="map"
:cellStyle="{ padding: '5px 0' }"
:border="false"
@click="openAddressList"
>
<template v-slot:right-icon>
<uv-icon name="arrow-right"></uv-icon>
</template>
</uv-cell>
</uni-card>
<uni-card title="订单信息" :border="false" :is-shadow="false">
<uv-cell-group :customStyle="{ backgroundColor: '#ffffff' }" :border="false">
<block v-if="goodsList.length == 0">
<span class="web-text-secondary">商品不存在</span>
</block>
<block v-if="goodsList">
<block v-for="(item, index) in goodsList" :key="index">
<uv-cell :title="`${item.goodsName}`" :label="`${item.comments}`" :cellStyle="{ padding: '10px 0' }" :border="false" :value="`¥${item.price}`">
<template v-slot:icon>
<uv-avatar :src="item.image" size="60" shape="square"></uv-avatar>
</template>
</uv-cell>
</block>
</block>
</uv-cell-group>
</uni-card>
<uni-card title="选择支付方式" :border="false" :is-shadow="false">
<uv-cell-group :customStyle="{ backgroundColor: '#ffffff' }" :border="false">
<block v-for="(item, index) in payment" :key="index">
<uv-cell
:title="`${item.name}`"
:icon="`${item.image}`"
:cellStyle="{ padding: '20rpx 10rpx', borderRadius: '8rpx', backgroundColor: item.type == payType ? '#f6fff1' : '' }"
:border="false"
@click="onPayType(item.type)"
>
<template v-slot:right-icon>
<uv-icon v-if="item.type == payType" size="30rpx" name="checkbox-mark"></uv-icon>
</template>
</uv-cell>
</block>
</uv-cell-group>
<view slot="actions" class="card-actions">
<view class="card-actions-item" @click="actionsClick('分享')">
<span class="web-text-danger">已优惠¥0.00</span>
<span class="web-text-heading">¥{{ totalPrice || 0.0 }}</span>
</view>
</view>
</uni-card>
<view class="xieyi web-cell web-text-secondary web-cell-align-top">
<view class="web-cell web-cell-content web-cell-align-top">
<uni-icons type="circle" size="20" color="#a4a5a7" v-if="!disabled" @click="onDisabled"></uni-icons>
<uni-icons type="checkbox" size="20" color="#11a954" v-else @click="onDisabled"></uni-icons>
<view class="text" @click="onDisabled">
<text>同意以下服务条款</text>
<text class="link" @click.stop="navTo('/package/article/detail?articleId=501')">《广西体育中心预定条款》</text>
<text class="link" @click.stop="navTo('/package/article/detail?articleId=502')">《用户服务协议和隐私政策》</text>
</view>
</view>
</view>
<!-- 支付按钮 -->
<uv-gap height="50"></uv-gap>
<view class="checkout-car">
<view class="car-total">
<text style="color: #ebcf00">合计¥</text>
<uv-count-to :startVal="0" decimals="2" duration="100" color="#ebcf00" bold :endVal="totalPrice"></uv-count-to>
</view>
<uv-button
class="save-btn"
:disabled="!disabled || goodsList.length == 0"
:customStyle="{ background: 'linear-gradient(to right, #70b915, #008e04)', borderRadius: '0 30px 30px 0', color: '#ffffff', border: 'none', padding: '22px 30px' }"
text="提交订单"
@click="save"
></uv-button>
</view>
</view>
<!-- 收货地址选择弹窗 -->
<uni-popup ref="addForm" type="center" border-radius="10px 10px 0 0">
<uni-card title="选择收货地址" :border="false" :is-shadow="false" :padding="0">
<view class="address-body web-cell web-cell-align-top">
<view class="web-cell-content">
<uv-cell-group :customStyle="{ backgroundColor: '#ffffff' }" :border="false">
<block v-for="(item, index) in addressList" :key="index">
<uv-cell :cellStyle="{ padding: '10px 0' }" :label="item.address" @click="onAddress(item)">
<template v-slot:icon>
<uv-avatar :text="item.type" fontSize="12" size="32" randomBgColor></uv-avatar>
</template>
<template v-slot:title>
<view class="title-bar">
<text class="web-text-heading" style="font-weight: 700">{{ item.name }}</text>
<text class="web-text-secondary">{{ item.phone }}</text>
<uni-tag v-if="item.isDefault" text="默认" size="mini" inverted type="success"></uni-tag>
</view>
</template>
<template v-slot:right-icon>
<uni-icons type="right" style="color: #999999"></uni-icons>
</template>
</uv-cell>
</block>
<uv-button class="add-address" :customStyle="{ borderRadius: '30px' }" text="收货地址管理" @click="navTo('/package/user/address')"></uv-button>
</uv-cell-group>
</view>
</view>
</uni-card>
</uni-popup>
<!-- 支付密码弹窗 -->
<uni-popup ref="payPasswordForm" type="center" border-radius="10px 10px 0 0">
<uni-card title="请输入支付密码" :border="false" :is-shadow="false" :padding="0">
<view class="pay-password-card">
<uni-forms ref="form" :label-width="80">
<uni-forms-item label="支付密码" name="payPassword" required>
<uv-code-input mode="box" dot :space="0" :maxlength="6" hairline v-model="payPassword" @finish="onPayPassword"></uv-code-input>
</uni-forms-item>
<!-- <uv-button
class="to-pay-btn"
:customStyle="{ background: 'linear-gradient(to right, #70b915, #008e04)', borderRadius: '30px', color: '#ffffff' }"
text="确定支付"
:disabled="disabledPayPayPassword"
@click="onPayPassword"
></uv-button> -->
</uni-forms>
<text @click="navTo(`/package/user/pay-password`)" class="web-text-primary">忘记支付密码?</text>
</view>
</uni-card>
</uni-popup>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
</template>
<script>
import * as Api from '@/api/shop/order';
import * as UserAddressApi from '@/api/shop/userAddress';
import * as PaymentApi from '@/api/system/payment';
import { checkPayPassword } from '@/api/passport/login';
import { storeToRefs } from 'pinia';
import { getWeek, getKey } from '@/utils/common';
import { useCarStore } from '@/store/modules/car';
import { useUserStore } from '@/store/modules/user';
const userStore = useUserStore();
const carStore = useCarStore();
const { goodsList, totalPrice, carNum, merchantId, merchantName, merchantCode, type, dateTime } = storeToRefs(carStore);
export default {
data() {
return {
orderId: 0,
goodsId: 0,
userInfo: {},
address: {},
addressList: [],
week: 0,
goodsList,
// 订单总金额
totalPrice,
reducePrice: 0,
merchantId,
merchantName,
merchantCode,
getWeek,
payType: 1,
payment: [],
isLogin: false,
disabled: false,
// 支付密码是否正确
isPayPasswordCorrect: false,
disabledPayPayPassword: false,
payPassword: ''
};
},
onLoad(option) {
this.orderId = option.orderId;
this.reload();
},
onShow() {
// 登录状态
if (uni.getStorageSync('user_id') && uni.getStorageSync('access_token')) {
this.isLogin = true;
}
this.openLogin();
},
methods: {
async reload() {
const app = this;
const { orderId } = this;
// 当前登录用户信息
const userInfo = await userStore.fetchUserInfo();
app.userInfo = userInfo;
UserAddressApi.pageUserAddress({
userId: uni.getStorageSync('user_id')
}).then((res) => {
app.addressList = res.list;
const arr = res.list.filter((d) => d.isDefault === true);
app.address = arr[0];
});
// 读取支付方式列表
PaymentApi.select({ status: true }).then((list) => {
app.payment = list
.filter((d) => d.type < 2)
.map((d) => {
if (d.code == 'balancePay') {
d.name = `${d.name} (¥${userInfo.balance})`;
}
return d;
});
});
// if (orderId > 0) {
// Api.getOrder(orderId).then(data => {
// app.merchantId = data.merchantId
// app.merchantName = data.merchantName
// app.merchantCode = data.merchantCode
// app.payType = data.payType
// app.orderInfo = data.orderInfoList
// app.totalPrice = data.totalPrice
// app.dateTime = data.orderInfoList[0].dateTime
// })
// }
},
onDisabled() {
this.disabled = !this.disabled;
},
navTo(url) {
uni.navigateTo({
url
});
},
openUrl(url) {
if (!this.isLogin) {
this.$refs.login.open('bottom');
return false;
} else {
uni.navigateTo({
url
});
}
},
onAddress(item) {
this.address = item;
this.$refs.addForm.close();
},
// 切换支付方式
onPayType(index) {
this.payType = index;
},
openAddressList() {
this.$refs.addForm.open('center');
},
// 弹出登录提示框
openLogin() {
if (!this.isLogin) {
this.$refs.login.open('bottom');
return false;
}
},
// 验证支付密码
onPayPassword() {
if (this.payPassword == '' || !this.payPassword) {
uni.showToast({
title: '请输入支付密码',
icon: 'none'
});
return false;
}
this.disabledPayPayPassword = true;
const { payPassword } = this;
checkPayPassword({ payPassword })
.then((res) => {
this.disabledPayPayPassword = false;
this.isPayPasswordCorrect = true;
this.save();
})
.catch((err) => {
uni.showToast({
title: err.message,
icon: 'none'
});
this.disabledPayPayPassword = false;
});
},
save() {
const app = this;
const { form, payType } = this;
if (!this.disabled) {
uni.showToast({
title: '请先阅读并同意服务协议',
icon: 'none'
});
return false;
}
if (carStore.goodsList.length == 0) {
uni.showToast({
title: '订单信息不存在',
icon: 'none'
});
return false;
}
if (app.payType == 0 && !this.isPayPasswordCorrect) {
this.$refs.payPasswordForm.open('center');
return false;
}
uni.showLoading({
title: '订单提交中.'
});
Api.addOrder({
type: 0, // 0商城订单
orderId: this.orderId,
merchantId: this.merchantId,
merchantCode: this.merchantCode,
merchantName: this.merchantName,
totalPrice: this.totalPrice,
payPrice: this.totalPrice - this.reducePrice,
goodsList: this.goodsList,
comments: this.goodsList[0].goodsName,
// 微信支付
payType: this.payType,
// 下单日期
dateTime: this.dateTime
})
.then((data) => {
const orderInfo = data;
// 调起微信支付
if (app.payType == 1) {
// #ifdef MP-WEIXIN
uni.requestPayment({
provider: orderInfo.provider, // 服务提供商
timeStamp: orderInfo.timeStamp, // 时间戳
nonceStr: orderInfo.nonceStr, // 随机字符串
package: orderInfo.package,
signType: orderInfo.signType, // 签名算法
paySign: orderInfo.paySign, // 签名
success: function (res) {
// 业务逻辑。。。
uni.showToast({
title: '支付成功',
icon: 'success'
});
setTimeout(function () {
app.disabled = false;
uni.navigateTo({
url: '/package/goods/order'
});
}, 500);
},
fail: function (err) {
console.log('支付失败', err);
app.disabled = false;
uni.navigateTo({
url: '/package/goods/order'
});
}
});
// #endif
}
// 使用余额支付
if (app.payType == 0) {
if (!orderInfo) {
return uni.showToast({
title: '支付失败',
icon: 'error'
});
}
if (orderInfo) {
uni.showToast({
title: '支付成功',
icon: 'success'
});
setTimeout(function () {
app.disabled = false;
app.$refs.payPasswordForm.close();
uni.reLaunch({
url: '/package/goods/order',
success: function (e) {
var page = getCurrentPages()[0];
if (page == undefined || page == null) return;
page.onLoad();
}
});
}, 1500);
}
}
uni.hideLoading();
})
.catch((res) => {
uni.showToast({
title: res.message || '请检查您的网络.',
icon: 'none'
});
uni.hideLoading();
});
}
}
};
</script>
<style>
page {
background-size: 100%;
background-repeat: no-repeat;
background-color: #f0f2f5;
width: 750rpx;
overflow-x: hidden;
}
</style>
<style lang="scss" scoped>
.container {
}
.checkout-car {
width: 700rpx;
left: 25rpx;
position: fixed;
bottom: 30rpx;
display: flex;
justify-content: space-between;
background-color: #000000;
border-radius: 100px;
align-items: center;
.car-selected {
color: #ccc;
display: flex;
align-items: center;
padding: 0 20rpx;
}
.car-total {
display: flex;
color: #ebcf00;
align-items: center;
padding-left: 40rpx;
.save-btn {
}
}
}
.card-actions {
display: flex;
flex-direction: row;
justify-content: flex-end;
height: 45px;
border-top: 1px #eee solid;
}
.card-actions-item {
display: flex;
flex-direction: row;
align-items: center;
.web-text-heading {
font-size: 38rpx;
margin-left: 28rpx;
}
}
.card-actions-item-text {
font-size: 12px;
color: #666;
margin-left: 5px;
}
.address-body {
width: 660rpx;
margin: auto;
}
.add-address {
width: 600rpx !important;
margin: 40rpx auto;
}
.btn-bar {
width: 700rpx;
left: 25rpx;
position: fixed;
bottom: 30rpx;
margin: auto;
clear: both;
}
.title-bar {
display: flex;
.web-text-heading {
margin-right: 20rpx;
}
.web-text-secondary {
margin-right: 20rpx;
}
}
.xieyi {
margin-bottom: 80rpx;
padding: 0 30rpx;
.text {
margin-left: 5rpx;
.link {
color: #0f80ff;
}
}
}
.pay-password-card {
width: 600rpx;
min-height: 300rpx;
margin: 30rpx auto;
background-color: #ffffff;
text-align: center;
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
.web-text-primary {
line-height: 2rem;
padding: 20rpx 0;
}
}
.to-pay-btn {
width: 400rpx !important;
margin: 40rpx auto;
}
</style>
+357
View File
@@ -0,0 +1,357 @@
<template>
<view class="">
<view class="goods-info">
<uv-swiper :list="photo" indicator indicatorMode="line" circular height="750rpx" radius="0"></uv-swiper>
</view>
<!-- <view class="merchant-name">{{ form.merchantName }}</view> -->
<uni-card :border="false" :is-shadow="false" :padding="0">
<uv-cell-group :customStyle="{backgroundColor: '#ffffff'}" :border="false">
<uv-cell :cellStyle="{padding: '10px 5px'}">
<template v-slot:title>
<view class="pirce-bar" style="display: flex;">
<view class="web-text-danger">¥</view>
<view class="web-text-danger" style="font-size: 40rpx;">{{ form.price }}</view>
</view>
</template>
<template v-slot:right-icon>
<text class="web-text-secondary" style="text-decoration: line-through">划线价¥{{ form.price*2 }}</text>
</template>
</uv-cell>
<uv-cell :title="form.goodsName" label="商品名称" :cellStyle="{padding: '10px 5px'}">
</uv-cell>
<uv-cell title="选择款式" :label="`100zz【藏青色】、100zz【古红色】`" isLink
:cellStyle="{padding: '10px 5px'}">
<template v-slot:right-icon>
<!-- <uv-icon size="50rpx" name="map-fill" color="#5ac725" style="color: #ff0000;"></uv-icon> -->
</template>
</uv-cell>
<uv-cell title="参数" :label="form.goodsName" :cellStyle="{padding: '10px 5px'}">
</uv-cell>
<uv-cell title="客服电话" label="0771-8888888" :border="false" :cellStyle="{padding: '10px 5px'}"
@click="callPhone('0771-8888888')">
</uv-cell>
</uv-cell-group>
</uni-card>
<uni-card title="商品详情" :is-shadow="false" :border="false" :padding="0">
<view class="web-text-heading booking-content">
<view v-html="form.content"></view>
</view>
</uni-card>
<view class="xieyi web-cell web-text-secondary web-cell-align-top">
<view class="web-cell web-cell-content web-cell-align-top">
<uni-icons type="circle" size="20" color="#a4a5a7" v-if="!disabled" @click="onDisabled"></uni-icons>
<uni-icons type="checkbox" size="20" color="#11a954" v-else @click="onDisabled"></uni-icons>
<view class="text" @click="onDisabled">
<text>我已阅读并同意</text>
<text class="link"
@click.stop="navTo('/package/article/detail?articleId=503')">《购买协议》</text>
</view>
</view>
</view>
<uv-gap height="50"></uv-gap>
<view class="save-btn">
<uv-button
:customStyle="{background: 'linear-gradient(to right, #ccff66, #008e04)',borderRadius: '30px',color: '#ffffff'}"
text="立即购买" @click="save"></uv-button>
</view>
<!-- <view class="goods-nav-btn">
<uni-goods-nav :fill="true" :options="options" :button-group="buttonGroup" @click="onClick"
@buttonClick="buttonClick" />
</view> -->
</view>
<!-- 活动订场弹窗 -->
<uni-popup ref="popup" type="center">
<view class="popup-booking-tel">
<text class="title">场馆热线</text>
<text class="desc">主体育场、足球训练场:0771-4953380</text>
<text class="desc">体育馆、综合训练馆、网球馆:0771-4953380</text>
<text class="desc">游泳跳水馆:0771-4736008</text>
<text class="title">参观接待</text>
<text class="desc">预约电话:0771-4736955</text>
<text class="desc">传真号码:0771-4736955</text>
<text class="title">大型活动订场</text>
<text class="desc">预约电话:0771-4736970、0771-4736994</text>
<text class="title">威拓普健身馆</text>
<text class="desc">联系电话:0771-5588699</text>
</view>
<view class="web-cell popup-close" @click="closeBookingTel">
<uv-icon name="close-circle" color="#ffffff" size="30"></uv-icon>
</view>
</uni-popup>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
</template>
<script>
import {
storeToRefs
} from 'pinia';
import * as GoodsApi from '@/api/shop/goods';
import {
useCarStore
} from '@/store/modules/car';
const carStore = useCarStore();
const {
goodsList,
orderInfo,
totalPrice,
carNum,
merchantId,
merchantName,
merchantCode,
type,
dateTime
} = storeToRefs(carStore)
export default {
data() {
return {
id: 0,
form: {},
// 场馆相册
photo: [],
isLogin: false,
disabled: true,
orderInfo,
goodsList,
totalPrice,
carNum,
merchantId,
merchantName,
merchantCode,
type,
dateTime,
options: [{
icon: 'headphones',
text: '客服'
}, {
icon: 'cart',
text: '购物车',
info: 2
}],
buttonGroup: [
{
text: '立即购买',
backgroundColor: 'linear-gradient(90deg, #ccff66, #008e04)',
color: '#fff'
}
],
customButtonGroup1: [{
text: '立即购买',
backgroundColor: 'linear-gradient(90deg, #ccff66, #008e04)',
color: '#fff'
}]
}
},
onLoad(option) {
this.id = option.id
this.reload();
},
onShow() {
// 登录状态
if (uni.getStorageSync('user_id') && uni.getStorageSync('access_token')) {
this.isLogin = true;
}
},
methods: {
async reload() {
const app = this
// 请求数据
Promise.all([app.getGoods()]).then(data => {
console.log('data: ', data);
const form = data[0]
app.form = form;
carStore.merchantId = form.merchantId
carStore.merchantName = form.merchantName
carStore.merchantCode = form.merchantCode
// 修改标题
uni.setNavigationBarTitle({
title: form.goodsName
})
// 加载场馆相册
if (form.files) {
app.photo = JSON.parse(form.files)
}
})
},
getGoods() {
return new Promise((resolve, reject) => {
GoodsApi.getGoods(this.id).then(result => {
resolve(result)
}).catch(reject)
})
},
onDisabled() {
this.disabled = !this.disabled;
},
navTo(url) {
uni.navigateTo({
url
})
},
openBookingTel() {
// 通过组件定义的ref调用uni-popup方法 ,如果传入参数 ,type 属性将失效 ,仅支持 ['top','left','bottom','right','center']
this.$refs.popup.open('center')
},
closeBookingTel() {
this.$refs.popup.close()
},
callPhone(phone) {
uni.makePhoneCall({
phoneNumber: phone
});
},
onMap() {
uni.getLocation({
type: 'gcj02', //返回可以用于uni.openLocation的经纬度
success: function(res) {
console.log('返回可以用于uni.openLocation的经纬度: ', res);
const latitude = this.merchant.latitude;
const longitude = this.merchant.longitude;
uni.openLocation({
latitude: latitude,
longitude: longitude,
success: function() {
console.log('success');
}
});
}
});
},
save() {
if (!this.disabled) {
uni.showToast({
title: '请先阅读并同意订票协议',
icon: 'none'
})
return false
}
const app = this
const { form } = this
carStore.totalPrice = form.price
app.goodsList = []
form.image = JSON.parse(form.image)[0]
app.goodsList.push(form)
carStore.goodsList = app.goodsList
// 跳转页面
uni.navigateTo({
url: '/package/goods/checkout?goodsId=' + this.id
})
}
}
}
</script>
<style>
page {
background-size: 100%;
background-repeat: no-repeat;
background-color: #f0f2f5;
width: 750rpx;
overflow-x: hidden;
}
</style>
<style lang="scss" scoped>
.container {}
.goods-info {
width: 750rpx;
height: 750rpx;
background-color: #fff;
}
.merchant-name {
padding: 30rpx;
font-weight: 500;
font-size: 42rpx;
background-color: #ffffff;
}
.save-btn {
width: 700rpx;
left: 25rpx;
height: 80rpx;
position: fixed;
bottom: 30rpx;
}
.booking-tel {
position: fixed;
z-index: 1;
top: 270px;
right: 0;
width: 80px;
height: 38px;
border-radius: 50px 0 0 50px;
background: linear-gradient(to right, #ccff66, #008e04);
display: flex;
align-items: center;
justify-content: center;
color: #ffffff;
font-size: 13px;
}
.popup-booking-tel {
background-color: #ffffff;
width: 560rpx;
min-height: 400rpx;
border-radius: 20rpx;
margin: auto;
padding: 20px;
z-index: 9999;
display: flex;
flex-direction: column;
.title {
font-weight: bold;
font-size: 38rpx;
text-align: center;
padding: 10px 0;
}
.desc {
line-height: 2rem;
}
}
.popup-close {
display: flex;
margin-top: 24rpx;
justify-content: center;
}
.booking-content {
padding: 10px;
font-size: 30rpx;
line-height: 1.5rem;
}
.xieyi {
margin-bottom: 80rpx;
padding: 0 30rpx;
.text {
margin-left: 5rpx;
.link {
color: #0f80ff;
}
}
}
.goods-nav-btn {
width: 750rpx;
position: fixed;
bottom: 0;
background-color: #fff;
}
</style>
+410
View File
@@ -0,0 +1,410 @@
<template>
<view>
<view class="segmented">
<uni-segmented-control :current="current" :values="items" :styleType="styleType" :activeColor="activeColor" inActiveColor="#808080" @clickItem="onClickItem" />
</view>
<view class="order">
<block v-if="orderList.length > 0">
<block v-for="(item, index) in orderList" :key="index">
<uni-card :border="false" :is-shadow="false" :padding="0">
<template v-slot:title>
<div class="order-title web-cell">
<view class="web-cell web-cell-content">
<view class="merchant-avatar">
<uv-avatar :src="item.merchantAvatar" size="24"></uv-avatar>
</view>
<text class="merchant-name">{{ item.merchantName }}</text>
</view>
<block v-if="item.orderStatus == 2">
<text class="btn-status web-text-secondary">已取消</text>
</block>
<block v-else-if="item.orderStatus == 1">
<text class="btn-status web-text-success">已完成</text>
</block>
<block v-else>
<text v-if="item.payStatus == 1" class="btn-status web-text-success">已支付</text>
<view v-if="item.payStatus == 0" class="btn-status web-text-danger">
<uv-count-down :time="item.timestamp" format="mm:ss"></uv-count-down>
<text class="no-pay" style="margin-left: 10rpx">未支付</text>
</view>
</block>
</div>
</template>
<view class="order-body web-cell web-cell-align-top">
<view class="web-cell-content">
<uv-cell-group :customStyle="{ backgroundColor: '#ffffff' }" :border="false">
<block v-for="(sub, subIndex) in item.goodsList" :key="subIndex">
<uv-cell
:title="`${sub.goodsName}`"
:label="`${sub.comments}`"
:cellStyle="{ padding: '0', paddingBottom: '5px' }"
:border="false"
@click="openUrl(`/package/order/detail?id=${item.orderId}`)"
>
<template v-slot:icon>
<uv-avatar :src="sub.image" fontSize="12" size="50" shape="square"></uv-avatar>
</template>
<template v-slot:value>
<view class="goods-price-bar">
<view class="goods-price web-text-heading">¥{{sub.price}}</view>
<view class="total-num web-text-secondary" style="font-size: 13px;letter-spacing: 1px;">共{{ item.totalNum }}件</view>
</view>
</template>
</uv-cell>
</block>
</uv-cell-group>
<!-- <view class="total-price">
<view class="web-text-heading">合计:¥{{ item.totalPrice }}</view>
<view class="web-text-heading" style="font-weight: 500">实付:¥{{ item.totalPrice - item.reducePrice }}</view>
</view> -->
</view>
</view>
<view slot="actions" class="card-actions">
<view class="card-actions-item" v-if="item.payStatus == 0 && item.orderStatus == 0">
<button class="mini-btn" size="mini" @click="closeOrder(item)" style="margin-right: 20rpx">取消订单</button>
<button class="mini-btn" type="primary" size="mini" @click="toPay(item.orderId)">去支付</button>
</view>
<view class="card-actions-item" v-if="item.payStatus == 1 && item.isInvoice == 0" @click="onInvoice(item.orderId)">
<button class="mini-btn" size="mini">申请开票</button>
</view>
</view>
</uni-card>
</block>
</block>
<block v-if="orderList.length == 0 && loadMore != 'no-more'">
<uni-card :border="false" :padding="'18px 6px'">
<uv-skeleton rows="3" avatar :loading="hideTools" :title="false"></uv-skeleton>
<uv-gap height="16"></uv-gap>
</uni-card>
<uni-card :border="false" :padding="'18px 6px'">
<uv-skeleton rows="3" avatar :loading="hideTools" :title="false"></uv-skeleton>
<uv-gap height="16"></uv-gap>
</uni-card>
<uni-card :border="false" :padding="'18px 6px'">
<uv-skeleton rows="3" avatar :loading="hideTools" :title="false"></uv-skeleton>
<uv-gap height="16"></uv-gap>
</uni-card>
<uni-card :border="false" :padding="'18px 6px'">
<uv-skeleton rows="3" avatar :loading="hideTools" :title="false"></uv-skeleton>
<uv-gap height="16"></uv-gap>
</uni-card>
</block>
<uni-load-more v-if="orderList.length > 0" :status="loadMore"></uni-load-more>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
</view>
</view>
</template>
<script>
import * as OrderApi from '@/api/shop/order';
import { pageWechatDeposit } from '@/api/shop/wechatDeposit';
import { getWeek, getKey } from '@/utils/common';
export default {
components: {},
data() {
return {
isRefresh: false,
isLogin: false,
userId: 0,
where: {
page: 1,
type: 0, // 0商城订单 1场地预定
sceneType: 'showOrderGoods' // 查询订单附加场地信息
},
canReset: false,
loadMore: 'more',
logo: '',
items: ['全部', '待付款', '待发货', '待收货', '已完成'],
orderList: [],
styles: [
{
value: 'button',
text: '按钮',
checked: true
},
{
value: 'text',
text: '文字'
}
],
colors: ['#333333', '#4cd964', '#dd524d'],
current: 0,
colorIndex: 0,
activeColor: '#108001',
styleType: 'text',
getWeek,
// 骨架屏
hideTools: true
};
},
onLoad(option) {
// 判断是否登录
this.openLogin();
// 加载数据
// this.reload()
// if(option.isRefresh){
// this.isRefresh = true
// }
},
onShow(e) {
// 判断是否登录
this.openLogin();
this.reload();
},
// 触底函数
onReachBottom() {
const app = this;
const { where } = this;
if (app.canReset) {
app.where.page = ++where.page;
app.reload();
}
},
methods: {
reload() {
const app = this;
const { where, userId } = this;
if (userId == 0) {
app.openLogin();
return;
}
where.userId = userId;
// uni.showLoading({
// title: '数据读取中.'
// })
app.loadMore = 'loading';
OrderApi.pageOrder(where)
.then((res) => {
const list = res.list.map((d) => {
console.log(d);
return d;
});
if (app.orderList.length < res.count) {
console.log('11111: ', 11111);
app.orderList = app.orderList.concat(list);
app.canReset = true;
app.loadMore = 'no-more';
} else {
app.canReset = false;
app.loadMore = 'no-more';
console.log('22222: ', 22222);
}
uni.hideLoading();
app.isRefresh = false;
})
.catch(() => {
uni.showToast({
title: '请检查您的网络.',
icon: 'none'
});
uni.hideLoading();
app.isRefresh = false;
});
},
onClickItem(e) {
const app = this;
const { where, userId } = this;
const index = e.currentIndex;
if (this.current !== e.currentIndex) {
this.current = e.currentIndex;
}
if (userId == 0) {
app.openLogin();
return;
}
// 全部
if (index == 0) {
where.payStatus = undefined;
where.orderStatus = undefined;
}
// 未支付
if (index == 1) {
where.payStatus = 0;
where.orderStatus = undefined;
}
// 已支付
if (index == 2) {
where.payStatus = 1;
where.orderStatus = undefined;
}
// 已完成
if (index == 3) {
where.payStatus = 1;
where.orderStatus = 1;
}
// 押金
if (index == 4) {
pageWechatDeposit({
uid: uni.getStorageSync('user_id')
}).then((res) => {
app.orderList = res.list;
if (res.count == 0) {
app.loadMore = 'no-more';
}
uni.hideLoading();
});
return false;
}
this.where.page = 1;
this.orderList = [];
this.reload();
},
openUrl(url) {
uni.navigateTo({
url
});
},
toPay(orderId) {
uni.navigateTo({
url: '/package/booking/confirm?id=' + orderId
});
},
closeOrder(item) {
uni.showModal({
title: '确定取消此订单?',
success(o) {
if (o.confirm) {
OrderApi.updateOrder({
orderStatus: 2,
orderId: item.orderId
})
.then((msg) => {
uni.showToast({
title: msg,
icon: 'none'
});
item.orderStatus = 2;
})
.catch(() => {
uni.showToast({
title: '请检查您的网络.',
icon: 'none'
});
uni.hideLoading();
});
}
}
});
},
// 弹出登录提示框
async openLogin() {
this.userId = uni.getStorageSync('user_id');
if (!this.userId) {
this.$refs.login.open('bottom');
return false;
}
},
// 申请开票
onInvoice(id) {
uni.navigateTo({
url: '/package/user/invoice?id=' + id
});
}
}
};
</script>
<style lang="scss">
.content {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
justify-content: center;
align-items: center;
height: 150px;
text-align: center;
}
.segmented {
padding: 0 12rpx;
}
.content-text {
font-size: 14px;
color: #666;
}
.color-tag {
width: 25px;
height: 25px;
}
.uni-list {
flex: 1;
}
.order {
.order-title {
padding: 20rpx 0;
border-bottom: 1px #eee solid;
.merchant-avatar {
margin-right: 12rpx;
}
.merchant-name {
// padding-left: 12rpx;
}
.btn-status {
font-size: 30rpx;
display: flex;
}
}
.order-body {
padding: 16px 0;
}
}
.ele-flex {
display: flex;
justify-content: space-between;
}
.card-actions {
display: flex;
flex-direction: row;
justify-content: flex-end;
align-items: center;
height: 45px;
border-top: 1px #eee solid;
}
.card-actions-item {
display: flex;
flex-direction: row;
align-items: center;
}
.card-actions-item-text {
font-size: 12px;
color: #666;
margin-left: 5px;
}
.close {
top: 60rpx !important;
}
.total-price {
display: flex;
flex-direction: column;
justify-content: flex-start;
font-size: 30rpx;
align-items: flex-start;
padding-left: 6rpx;
margin-left: 450rpx;
.web-text-heading {
font-size: 30rpx !important;
}
}
.goods-price-bar{
display: flex;
flex-direction: column;
align-items: flex-end;
}
</style>
+387
View File
@@ -0,0 +1,387 @@
<template>
<view class="container">
<uni-forms ref="form" :label-width="80">
<uni-card v-for="(item, index) in formData" :key="index" :title="`报名人 ${index + 1}`" :border="false" :is-shadow="true" class="relative">
<view class="text-gray-100 absolute right-4 top-25">
<uni-icons type="closeempty" color="#999999" size="18" @click="removeUser(index)"></uni-icons>
</view>
<uni-forms-item label="姓名" name="name" required>
<uni-easyinput type="text" v-model="formData[index].name" placeholder="请输入姓名" />
</uni-forms-item>
<uni-forms-item label="性别" name="sex" required>
<uni-data-checkbox v-model="formData[index].sex" :localdata="sexs" />
</uni-forms-item>
<uni-forms-item label="手机号码" name="phone" required>
<uni-easyinput type="text" v-model="formData[index].phone" maxlength="11" placeholder="请输入手机号" />
</uni-forms-item>
<uni-forms-item label="身份证号" name="idCardNo" required>
<uv-input placeholder="请输入" v-model="formData[index].idCardNo"></uv-input>
</uni-forms-item>
</uni-card>
</uni-forms>
<view class="add-match-user">
<uv-button icon="plus" iconSize="16" :customStyle="{ borderRadius: '8px' }" text="新增报名人" @click="addUser"></uv-button>
</view>
<!-- 支付按钮 -->
<uv-gap height="50"></uv-gap>
<view class="save-btn">
<uv-button :customStyle="{ background: 'linear-gradient(to right, #ccff66, #008e04)', borderRadius: '30px', color: '#ffffff' }" text="确定" @click="submit"></uv-button>
</view>
</view>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
</template>
<script>
import * as MatchOrderApi from '@/api/booking/matchOrder';
import { useUserStore } from '@/store/modules/user';
const userStore = useUserStore();
export default {
data() {
return {
logo: '',
matchId: 0,
userInfo: {},
isLogin: false,
disabled: false,
// 表单数据
formData: [
{
name: undefined,
phone: undefined,
sex: undefined,
idCardNo: undefined,
userId: 0,
matchId: undefined
}
],
// 单选数据源
sexs: [
{
text: '男',
value: 0
},
{
text: '女',
value: 1
}
],
rules: {}
};
},
onLoad(option) {
this.matchId = option.id;
this.formData[0].matchId = option.id;
this.logo = uni.getStorageSync('app_logo')
? uni.getStorageSync('app_logo')
: 'https://oss.wsdns.cn/20240423/7f6878104a6d4427884721f412ab5441.png?x-oss-process=image/resize,m_fixed,w_100,h_100/quality,Q_90';
this.reload();
},
onShow() {
// 登录状态
if (uni.getStorageSync('user_id') && uni.getStorageSync('access_token')) {
this.isLogin = true;
}
this.openLogin();
},
methods: {
async reload() {
const app = this;
const { matchId } = this;
// 当前登录用户信息
const userInfo = await userStore.fetchUserInfo();
app.userInfo = userInfo;
if (userInfo.userId) {
this.isLogin = true;
}
},
onDisabled() {
this.disabled = !this.disabled;
},
navTo(url) {
uni.navigateTo({
url
});
},
openUrl(url) {
if (!this.isLogin) {
this.$refs.login.open('bottom');
return false;
} else {
uni.navigateTo({
url
});
}
},
onSexValue(text) {
this.formData.sex = text;
},
addUser() {
const app = this
this.formData.push({
name: undefined,
phone: undefined,
sex: undefined,
idCardNo: undefined,
matchId: app.id
});
},
removeUser(index) {
this.formData.splice(index, 1);
},
// 弹出登录提示框
openLogin() {
if (!this.isLogin) {
this.$refs.login.open('bottom');
return false;
}
},
submit() {
console.log('表单数据信息:', this.formData);
MatchOrderApi.addBatchMatchOrder(this.formData).then((res) => {
console.log('173',res);
if(res.code == 1){
uni.showToast({
title: res.message,
icon: 'none'
});
return false
}
uni.showToast({
title: `报名成功`,
icon: 'success'
});
this.formData = [
{
name: undefined,
phone: undefined,
sex: undefined,
idCardNo: undefined,
userId: undefined,
matchId: undefined
}
];
// uni.navigateBack();
}).catch(err => {
uni.showToast({
title: err.message,
icon: 'none'
})
console.log('err: ',err);
});
// this.$refs.form
// .validate()
// .then((res) => {
// this.openLogin();
// // this.formData.map((d) => {
// // if (d.name === undefined || !d.phone === undefined || !d.sex === undefined || !d.idCardNo === undefined) {
// // uni.showToast({
// // title: `必填项不能为空`,
// // icon: 'none'
// // });
// // return false;
// // }
// // if (!uni.$uv.test.mobile(d.phone)) {
// // uni.showToast({
// // title: `${d.phone ? d.phone : ''}手机号码不正确`,
// // icon: 'none'
// // });
// // return false;
// // }
// // if (!uni.$uv.test.idCard(`${d.idCardNo}`)) {
// // uni.showToast({
// // title: `身份证号码不正确`,
// // icon: 'none'
// // });
// // return false;
// // }
// // d.userId = uni.getStorageSync('UserId');
// // d.matchId = this.matchId;
// // });
// })
// .catch((err) => {
// console.log('199');
// // uni.showToast({
// // title: err.message,
// // icon: 'none'
// // });
// console.log('表单错误信息:', err);
// });
}
}
};
</script>
<style>
page {
background-size: 100%;
background-repeat: no-repeat;
background-color: #f0f2f5;
width: 750rpx;
overflow-x: hidden;
}
</style>
<style lang="scss" scoped>
.container {
}
.checkout-car {
width: 700rpx;
left: 25rpx;
position: fixed;
bottom: 30rpx;
display: flex;
justify-content: space-between;
background-color: #000000;
border-radius: 100px;
align-items: center;
.car-selected {
color: #ccc;
display: flex;
align-items: center;
padding: 0 20rpx;
}
.car-total {
display: flex;
color: #ebcf00;
align-items: center;
padding-left: 40rpx;
.save-btn {
}
}
}
.card-actions {
display: flex;
flex-direction: row;
justify-content: flex-end;
height: 45px;
border-top: 1px #eee solid;
}
.card-actions-item {
display: flex;
flex-direction: row;
align-items: center;
.web-text-heading {
font-size: 38rpx;
margin-left: 28rpx;
}
}
.card-actions-item-text {
font-size: 12px;
color: #666;
margin-left: 5px;
}
.address-body {
width: 660rpx;
margin: auto;
}
.add-match-user {
width: 700rpx !important;
margin: 40rpx auto;
}
.btn-bar {
width: 700rpx;
left: 25rpx;
position: fixed;
bottom: 30rpx;
margin: auto;
clear: both;
}
.title-bar {
display: flex;
.web-text-heading {
margin-right: 20rpx;
}
.web-text-secondary {
margin-right: 20rpx;
}
}
.xieyi {
margin-bottom: 80rpx;
padding: 0 30rpx;
.text {
margin-left: 5rpx;
.link {
color: #0f80ff;
}
}
}
.pay-password-card {
width: 600rpx;
min-height: 300rpx;
margin: 30rpx auto;
background-color: #ffffff;
text-align: center;
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
.web-text-primary {
line-height: 2rem;
padding: 20rpx 0;
}
}
.to-pay-btn {
width: 400rpx !important;
margin: 40rpx auto;
}
.example {
padding: 15px;
background-color: #fff;
}
.segmented-control {
margin-bottom: 15px;
}
.save-btn {
width: 700rpx;
left: 25rpx;
height: 80rpx;
position: fixed;
bottom: 30rpx;
}
.button-group {
margin-top: 15px;
display: flex;
justify-content: space-around;
}
.form-item {
display: flex;
align-items: center;
}
.button {
display: flex;
align-items: center;
height: 35px;
margin-left: 10px;
}
</style>
+408
View File
@@ -0,0 +1,408 @@
<template>
<view class="container">
<view class="uv-demo-block">
<uv-swiper :list="photo" indicator indicatorMode="line" circular height="200" radius="0"></uv-swiper>
</view>
<view class="match-name flex justify-between">
<view>{{ match.title }}</view>
<view></view>
</view>
<uni-card title="活动信息" :border="false" :is-shadow="false" :padding="0">
<uv-cell-group :customStyle="{ backgroundColor: '#ffffff' }" :border="false">
<uv-cell title="活动地点" :label="`${match.address}`" :cellStyle="{ padding: '10px 5px' }" @click="mapTo(match)">
<template v-slot:right-icon>
<uv-icon size="50rpx" name="map-fill" color="#5ac725" style="color: #ff0000"></uv-icon>
</template>
</uv-cell>
<uv-cell title="活动时间" :label="`2024-07-12 至 2024-08-12`" :cellStyle="{ padding: '10px 5px' }"></uv-cell>
<uv-cell title="报名时间" :label="`2024-07-12 至 2024-08-12`" :cellStyle="{ padding: '10px 5px' }"></uv-cell>
<uv-cell title="退款规则" :label="`${match.refundRule}`" :cellStyle="{ padding: '10px 5px' }"></uv-cell>
<uv-cell title="已报名" :border="false" :cellStyle="{ padding: '10px 5px' }">
<template v-slot:label>
<view class="flex flex-row items-center text-xs web-text-secondary">
<span>{{ match.users }}/{{ match.maxUsers }}</span>
</view>
</template>
<template v-slot:value>
<uv-tags text="未开始" plain size="mini" type="primary"></uv-tags>
</template>
</uv-cell>
</uv-cell-group>
</uni-card>
<uni-card title="活动介绍" :is-shadow="false" :border="false" :padding="0">
<view class="web-text-heading booking-content">
<view v-html="match.content"></view>
</view>
</uni-card>
</view>
<uv-gap height="100"></uv-gap>
<view class="fixed w-full bottom-0 bg-white">
<view class="flex justify-between items-center">
<view class="left flex">
<uv-button icon="server-fill">客服</uv-button>
<uv-button icon="share-square" open-type="share">分享</uv-button>
</view>
<view class="mx-10">
<uv-button
:customStyle="{ background: 'linear-gradient(to right, #ccff66, #008e04)', borderRadius: '30px', padding: '0 120rpx', color: '#ffffff' }"
text="立即报名"
@click="navTo(`/package/match/checkout?id=${match.matchId}`)"
></uv-button>
</view>
</view>
<!-- <uni-goods-nav :fill="true" :options="options" :button-group="buttonGroup" @click="onClick" @buttonClick="buttonClick" style="margin-top: 20px" /> -->
</view>
<!-- 活动订场弹窗 -->
<uni-popup ref="popup" type="center">
<uni-card is-full :border="false" :is-shadow="false" :padding="0">
<uv-cell-group :customStyle="{ backgroundColor: '#ffffff' }" :border="false">
<uv-cell :cellStyle="{ padding: '10px 5px' }">
<template v-slot:title>
<view class="merchant-name">选择规格</view>
</template>
</uv-cell>
<template v-for="(item, index) in specList" :key="index">
<uv-gap height="10"></uv-gap>
<uv-cell
:border="false"
:cellStyle="{ padding: '10px 5px', borderRadius: '4px', backgroundColor: item.id === selected ? 'rgb(254 242 242)' : 'rgb(249 250 251)' }"
@click="onSelect(item)"
>
<template v-slot:title>
<view class="flex flex-row">
<uv-tags v-if="item.type === 0" text="个人" size="mini" type="primary"></uv-tags>
<uv-tags v-if="item.type === 1" text="企业" size="mini" type="primary"></uv-tags>
<text class="ml-2">{{ item.name }}</text>
</view>
</template>
<template v-slot:label>
<view class="flex text-gray-500 py-2">
{{ item.time }}
</view>
<view class="flex text-red-500 justify-between">
<view>已报名 {{ item.users }}/{{ item.maxUsers }}</view>
<view class="price text-gray-800" v-if="item.price === 0">免费</view>
<view class="price text-gray-800" v-else>¥{{ item.price }}</view>
</view>
</template>
</uv-cell>
</template>
<uv-gap height="50"></uv-gap>
</uv-cell-group>
</uni-card>
<view class="flex flex-row justify-end w-full fixed bottom-0 bg-white">
<uv-button
:disabled="selected === 0"
:customStyle="{ width: '240rpx', background: 'linear-gradient(90deg, #FE6035, #EF1224)', borderRadius: '0', color: '#ffffff', border: 'none', padding: '0' }"
text="下一步"
@click="save"
></uv-button>
</view>
</uni-popup>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
</template>
<script>
import * as MatchApi from '@/api/booking/match';
import { useCarStore } from '@/store/modules/car';
const carStore = useCarStore();
export default {
data() {
return {
id: 0,
// 场馆信息
match: {},
// 场馆相册
photo: [],
isLogin: false,
disabled: true,
options: [
{
icon: 'headphones',
text: '客服'
},
{
icon: 'upload',
text: '分享'
}
],
buttonGroup: [
{
text: '立即报名',
backgroundColor: 'linear-gradient(90deg, #FE6035, #EF1224)',
color: '#fff'
}
],
specList: [
{
id: 1,
type: 0,
name: '周五(7.5)第一场',
time: '2024-07-05 14:30 至 2024-07-05 15:30',
users: 1,
maxUsers: 30,
price: 0
},
{
id: 2,
type: 0,
name: '周五(7.5)第二场',
time: '2024-07-06 14:30 至 2024-07-06 15:30',
users: 3,
maxUsers: 30,
price: 0
},
{
id: 3,
type: 0,
name: '周五(7.5)第三场',
time: '2024-07-07 14:30 至 2024-07-07 15:30',
users: 8,
maxUsers: 30,
price: 0
}
],
selected: 0
};
},
onLoad(option) {
this.id = option.id;
this.reload();
},
onShow() {
// 登录状态
if (uni.getStorageSync('user_id') && uni.getStorageSync('access_token')) {
this.isLogin = true;
}
},
onShareTimeline(res) {
if (res.from === 'button') {
// 来自页面内分享按钮
console.log('来自页面内分享按钮', res.target);
}
return {
title: this.match.title,
path: '/package/match/detail?id=' + this.match.matchId
};
},
onShareAppMessage(res) {
if (res.from === 'button') {
// 来自页面内分享按钮
console.log('来自页面内分享按钮', res.target);
}
return {
title: this.match.title,
path: '/package/match/detail?id=' + this.match.matchId
};
},
methods: {
async reload() {
const app = this;
// 请求数据
Promise.all([app.getMatch()]).then((res) => {
const match = res[0];
app.match = match;
// 修改标题
uni.setNavigationBarTitle({
title: match.title
});
uni.$uv.mpShare.title = match.title;
// 加载场馆相册
if (match.files) {
app.photo = JSON.parse(match.files);
}
// 更新购物车状态
// carStore.setMatch(match)
// carStore.matchId = match.matchId
// carStore.matchName = match.matchName
// carStore.matchCode = match.matchCode
});
},
getMatch() {
return new Promise((resolve, reject) => {
MatchApi.getMatch(this.id)
.then((result) => {
resolve(result);
})
.catch(reject);
});
},
onDisabled() {
this.disabled = !this.disabled;
},
navTo(url) {
uni.navigateTo({
url
});
},
openBookingTel() {
// 通过组件定义的ref调用uni-popup方法 ,如果传入参数 ,type 属性将失效 ,仅支持 ['top','left','bottom','right','center']
this.$refs.popup.open('bottom');
},
closeBookingTel() {
this.$refs.popup.close();
},
callPhone(phone) {
uni.makePhoneCall({
phoneNumber: phone
});
},
onSelect(item) {
this.selected = item.id;
},
mapTo() {
uni.getLocation({
type: 'gcj02', //返回可以用于uni.openLocation的经纬度
success: function (res) {
console.log('返回可以用于uni.openLocation的经纬度: ', res);
const latitude = this.match.latitude;
const longitude = this.match.longitude;
uni.openLocation({
latitude: latitude,
longitude: longitude,
success: function () {
console.log('success');
}
});
}
});
},
buttonClick() {
this.openBookingTel();
// uni.navigateTo({
// url: '/package/match/checkout?id=' + this.id
// })
},
onClick(e) {
const index = e.index;
if (index == 0) {
// 客服
}
if (index == 1) {
// 分享
uni.$uv.mpShare = {
title: '啦啦啦', // 默认为小程序名称,可自定义
path: '/package/match/detail?id=1' // 默认为当前页面路径,一般无需修改,QQ小程序不支持
// 分享图标,路径可以是本地文件路径、代码包文件路径或者网络图片路径。
// 支持PNG及JPG,默认为当前页面的截图
// imageUrl: ''
};
}
},
save() {
if (!this.disabled) {
uni.showToast({
title: '请先阅读并同意订票协议',
icon: 'none'
});
return false;
}
uni.navigateTo({
url: '/package/match/checkout?id=' + this.id
});
}
}
};
</script>
<style>
page {
background-size: 100%;
background-repeat: no-repeat;
background-color: #f0f2f5;
width: 750rpx;
overflow-x: hidden;
}
</style>
<style lang="scss" scoped>
.container {
}
.match-name {
padding: 30rpx;
font-weight: 500;
font-size: 42rpx;
background-color: #ffffff;
}
.save-btn {
width: 700rpx;
left: 25rpx;
height: 80rpx;
position: fixed;
bottom: 30rpx;
}
.booking-tel {
position: fixed;
z-index: 1;
top: 270px;
right: 0;
width: 80px;
height: 38px;
border-radius: 50px 0 0 50px;
background: linear-gradient(to right, #ccff66, #008e04);
display: flex;
align-items: center;
justify-content: center;
color: #ffffff;
font-size: 13px;
}
.popup-booking-tel {
background-color: #ffffff;
width: 750rpx;
min-height: 400rpx;
border-radius: 20rpx 20rpx 0 0;
margin: auto;
z-index: 9999;
display: flex;
flex-direction: column;
.title {
font-weight: bold;
font-size: 38rpx;
text-align: center;
padding: 10px 0;
}
.desc {
line-height: 2rem;
}
}
.popup-close {
display: flex;
margin-top: 24rpx;
justify-content: center;
}
.booking-content {
padding: 10px;
font-size: 30rpx;
line-height: 1.5rem;
}
.xieyi {
margin-bottom: 80rpx;
padding: 0 30rpx;
.text {
margin-left: 5rpx;
.link {
color: #0f80ff;
}
}
}
</style>
+182
View File
@@ -0,0 +1,182 @@
<template>
<view>
<!-- 热门培训 -->
<view class="card-title web-text-heading">最新赛事/活动</view>
<block v-if="list.length > 0">
<view class="match-list">
<block v-for="(item, index) in list" :key="index">
<view class="match-item flex" @click="openUrl(`/package/match/detail?id=` + item.matchId)">
<uv-image :src="item.image" width="120" height="120"></uv-image>
<view class="match-info flex flex-col">
<uv-text class="match-name" size="15" lineHeight="24" :lines="2" :text="item.title"></uv-text>
<uv-text class="match-name web-text-secondary" lineHeight="24" size="13" :text="`时间:2024-07-12 至 2024-08-12`"></uv-text>
<view class="flex flex-row items-center text-gray-400 items-center text-xs web-text-heading">
<uv-tags v-if="item.status == 0" text="未开始" plain size="mini" type="primary"></uv-tags>
<uv-tags v-if="item.status == 1" text="进行中" plain size="mini" type="error"></uv-tags>
<uv-tags v-if="item.status == 2" text="已结束" plain size="mini" type="info"></uv-tags>
<span class="pl-2 web-text-secondary">{{ item.users }}/{{ item.maxUsers }} 已报名</span>
</view>
</view>
</view>
</block>
</view>
</block>
<block v-else>
<uni-card :border="false" :is-shadow="false" :padding="'12px 4px'">
<uv-skeleton rows="2" avatar :loading="hideTools" :title="false"></uv-skeleton>
<uv-gap height="16"></uv-gap>
<uv-skeleton rows="2" avatar :loading="hideTools" :title="false"></uv-skeleton>
<uv-gap height="16"></uv-gap>
<uv-skeleton rows="2" avatar :loading="hideTools" :title="false"></uv-skeleton>
<uv-gap height="16"></uv-gap>
<uv-skeleton rows="2" avatar :loading="hideTools" :title="false"></uv-skeleton>
<uv-gap height="16"></uv-gap>
</uni-card>
</block>
</view>
</template>
<script>
import * as MatchApi from '@/api/booking/match';
import * as MatchOrderApi from '@/api/booking/matchOrder';
export default {
data() {
return {
list: [],
// 骨架屏
hideTools: true,
// 项目列表
itemList: []
};
},
onLoad() {
this.reload();
},
methods: {
reload() {
const app = this;
// 请求数据
Promise.all([app.getMatchList(), app.getMatchOrderList()]).then((res) => {
console.log('res: ', res);
app.list = res[0];
app.itemList = res[1];
});
},
getMatchList() {
const app = this;
const { categoryId } = this;
return new Promise((resolve, reject) => {
MatchApi.pageMatch({})
.then((result) => {
resolve(result.list);
})
.catch(reject);
});
},
getMatchOrderList() {
const app = this;
return new Promise((resolve, reject) => {
MatchOrderApi.pageMatchOrder({})
.then((result) => {
resolve(result);
})
.catch(reject);
});
},
onItem(e) {
const { index } = e.detail;
this.openUrl(`/package/match/list?categoryId=` + this.itemList[index].id);
},
openUrl(url) {
uni.navigateTo({
url
});
}
}
};
</script>
<style lang="scss" scoped>
.card-title {
width: 700rpx;
margin: 12rpx auto;
font-size: 34rpx;
font-weight: 500;
margin-top: 32rpx;
}
.match-list {
width: 700rpx;
margin: auto !important;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
.match-item {
width: 700rpx;
margin: 16rpx 0;
border-radius: 16rpx;
overflow: hidden;
background-color: #ffffff;
display: flex;
.match-info {
padding: 10rpx 16rpx;
line-height: 35rpx;
}
.match-name {
}
.price-bar {
padding: 0 16rpx;
display: flex;
justify-content: space-between;
}
.match-image {
}
}
}
.item-list {
width: 720rpx;
margin: auto;
}
.merchant-card-title {
width: 700rpx;
margin: 12rpx auto;
font-size: 40rpx;
font-weight: 500;
margin-top: 32rpx;
}
.card-body {
width: 700rpx;
margin: auto;
.merchant-card {
margin: 12rpx auto;
border-radius: 10rpx;
border-color: slategrey;
border-radius: 16rpx;
display: flex;
justify-content: space-between;
.merchant-image {
width: 45vw;
border-radius: 16rpx 16rpx 0 0;
}
.merchant-name {
padding: 10rpx;
overflow: hidden;
font-weight: 500;
font-size: 26rpx;
text-align: center;
}
.merchant-desc {
width: 400rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
</style>
+394
View File
@@ -0,0 +1,394 @@
<template>
<view class="order" v-if="form.orderId">
<view class="qrcode" v-if="form.payStatus == 1 && form.orderStatus == 0">
<uv-qrcode
ref="qrcode"
size="280rpx"
:options="{
data: form.orderNo,
foregroundImageSrc: form.merchantAvatar,
margin: 10,
foregroundImagePadding: 4,
foregroundImageHeight: 30,
foregroundImageWidth: 30,
foregroundImageBorderRadius: 4
}"
:value="`${h5_url}#/package/admin/order-scan?orderNo=${form.orderNo}`"
></uv-qrcode>
<text class="web-text-secondary">核销码</text>
</view>
<uni-card title="预定信息" :border="false" :is-shadow="false" :padding="0">
<view class="order-body web-cell web-cell-align-top">
<view class="web-cell-content">
<uv-cell-group :customStyle="{ backgroundColor: '#ffffff' }" :border="false">
<uv-cell :title="`${form.merchantName}`" :label="` `" :cellStyle="{ padding: '0', paddingBottom: '5px' }" :border="false" />
<block v-for="(item, index) in form.orderInfo" :key="index">
<uv-cell
:title="`${item.fieldName}`"
:label="`${item.comments}`"
:cellStyle="{ padding: '0', paddingBottom: '5px' }"
:value="`¥${item.price}`"
:border="item.isChildren"
/>
<uv-cell :label="`成人票 ¥50`" :value="`x ${item.adultNum}`" v-if="item.isChildren" :cellStyle="{ padding: '0', paddingBottom: '5px' }" :border="false" />
<uv-cell :label="`儿童票 ¥35`" :value="`x ${item.childrenNum}`" v-if="item.isChildren" :cellStyle="{ padding: '0', paddingBottom: '5px' }" :border="false" />
</block>
</uv-cell-group>
</view>
</view>
<view slot="actions" class="card-actions">
<view class="web-text-heading">合计:¥{{ form.totalPrice }}</view>
<view class="web-text-danger">实付:¥{{ form.payPrice }}</view>
</view>
</uni-card>
<block v-if="form.orderNo">
<uni-card :border="false" :is-shadow="false" :padding="0">
<view class="web-cell web-cell-align-top">
<uv-cell-group :customStyle="{ backgroundColor: '#ffffff', padding: '8px 0' }" :border="false">
<uv-cell :title="`姓名`" :value="`${form.realName}`" :cellStyle="{ padding: '8px' }" />
<uv-cell :title="`手机号码`" :value="`${form.phone}`" :cellStyle="{ padding: '8px' }" />
<uv-cell :title="`订单号`" :value="`${form.orderId}`" :cellStyle="{ padding: '8px' }" />
<uv-cell :title="`订单编号`" :cellStyle="{ padding: '8px' }">
<template v-slot:value>
<uv-parse :content="form.orderNo" :selectable="true"></uv-parse>
</template>
</uv-cell>
<uv-cell :title="`订单状态`" :cellStyle="{ padding: '8px' }">
<template v-slot:value>
<view v-if="form.payStatus == 0">
<!-- <uv-count-down :time="form.timestamp" format="mm:ss"></uv-count-down> -->
<span style="color: #ff0000">未支付</span>
</view>
<view v-else>{{ orderStatus[form.orderStatus] }}</view>
</template>
</uv-cell>
<uv-cell :title="`下单时间`" :value="`${form.createTime}`" :cellStyle="{ padding: '8px' }" />
<uv-cell :title="`支付方式`" :value="`${payType[form.payType]}`" :cellStyle="{ padding: '8px' }" />
<uv-cell :title="`优惠说明`" :value="`${form.couponDesc ? form.couponDesc : '无'}`" :cellStyle="{ padding: '8px' }" :border="false" />
</uv-cell-group>
</view>
</uni-card>
</block>
<uv-gap height="20"></uv-gap>
<view class="checkout-car" v-if="form.payStatus == 0">
<view class="car-total">
<text style="color: #ebcf00">¥</text>
<uv-count-to decimals="2" duration="30" color="#ebcf00" bold :endVal="form.payPrice"></uv-count-to>
</view>
<uv-button
class="save-btn"
:customStyle="{ background: 'linear-gradient(to right, #70b915, #008e04)', borderRadius: '0 30px 30px 0', color: '#ffffff', border: 'none', padding: '22px 30px' }"
text="去支付"
@click="navTo(`/package/booking/confirm?id=${form.orderId}`)"
></uv-button>
</view>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
</view>
</template>
<script>
import * as OrderApi from '@/api/shop/order';
import { pageWechatDeposit } from '@/api/shop/wechatDeposit';
export default {
components: {},
data() {
return {
isLogin: false,
orderId: 0,
userId: 0,
form: {},
where: {
page: 1
},
canReset: false,
loadMore: 'more',
logo: '',
items: ['全部订单', '未支付', '已支付', '已完成', '押金'],
orderStatus: ['未使用', '已完成', '已取消', '取消中', '退款申请中', '退款被拒绝', '退款成功', '客户端申请退款'],
payType: [
'余额支付',
'微信支付',
'会员卡支付',
'支付宝',
'现金',
'POS机',
'VIP月卡',
'VIP年卡',
'VIP次卡',
'IC月卡',
'IC年卡',
'IC次卡',
'免费',
'VIP充值卡',
'IC充值卡',
'积分支付',
'VIP季卡',
'IC季卡'
],
orderList: [],
styles: [
{
value: 'button',
text: '按钮',
checked: true
},
{
value: 'text',
text: '文字'
}
],
h5_url: '',
colors: ['#333333', '#4cd964', '#dd524d'],
current: 0,
colorIndex: 0,
activeColor: '#108001',
styleType: 'text'
};
},
onLoad(option) {
this.orderId = option.id;
// 判断是否登录
this.openLogin();
// 加载数据
this.reload();
},
onShow() {
// 判断是否登录
this.openLogin();
},
// 触底函数
onReachBottom() {
const app = this;
const { where } = this;
if (app.canReset) {
app.where.page = ++where.page;
app.reload();
}
},
methods: {
reload() {
const app = this;
const { where, userId, orderId } = this;
if (userId == 0) {
app.openLogin();
return;
}
where.userId = userId;
uni.showLoading({
title: '数据读取中.'
});
OrderApi.getOrder(orderId).then((data) => {
console.log('data: ', data);
app.form = data;
// 页面标题
if (data.orderStatus == 1) {
uni.setNavigationBarTitle({
title: '订单详情(已完成)'
});
}
uni.hideLoading();
});
// H5版网址
const h5_url = uni.getStorageSync('h5_url');
const tid = uni.getStorageSync('TenantId');
if (h5_url) {
app.h5_url = h5_url;
} else {
app.h5_url = `http://${tid}.h5.wsdns.cn`;
}
},
navTo(url) {
uni.navigateTo({
url
});
},
onClickItem(e) {
const app = this;
const { where, userId } = this;
const index = e.currentIndex;
if (this.current !== e.currentIndex) {
this.current = e.currentIndex;
}
if (userId == 0) {
app.openLogin();
return;
}
// 全部
if (index == 0) {
where.payStatus = undefined;
where.orderStatus = undefined;
}
// 未支付
if (index == 1) {
where.payStatus = 2;
}
// 已支付
if (index == 2) {
where.payStatus = 1;
}
// 已完成
if (index == 3) {
where.orderStatus = 1;
}
// 押金
if (index == 4) {
pageWechatDeposit({
uid: uni.getStorageSync('user_id')
}).then((res) => {
console.log('res: ', res);
app.orderList = res.list;
});
return false;
}
this.reload();
},
// 弹出登录提示框
async openLogin() {
this.userId = uni.getStorageSync('user_id');
if (!this.userId) {
this.$refs.login.open('bottom');
return false;
}
}
}
};
</script>
<style lang="scss">
.content {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
justify-content: center;
align-items: center;
height: 150px;
text-align: center;
}
.content-text {
font-size: 14px;
color: #666;
}
.color-tag {
width: 25px;
height: 25px;
}
.uni-list {
flex: 1;
}
.order {
.order-title {
padding: 20rpx 0;
border-bottom: 1px #eee solid;
.merchant-avatar {
margin-right: 12rpx;
}
.merchant-name {
// padding-left: 12rpx;
}
.btn-status {
font-size: 30rpx;
display: flex;
}
}
.order-body {
padding: 16px 0;
}
}
.ele-flex {
display: flex;
justify-content: space-between;
}
.card-actions {
display: flex;
flex-direction: row;
justify-content: space-between;
padding: 0 10px;
align-items: center;
height: 45px;
border-top: 1px #eee solid;
.web-text-heading {
font-size: 30rpx;
font-weight: 500;
}
.web-text-danger {
font-size: 30rpx;
font-weight: 500;
}
}
.card-actions-item {
display: flex;
flex-direction: row;
align-items: center;
}
.card-actions-item-text {
font-size: 12px;
color: #666;
margin-left: 5px;
}
.btn-status {
font-size: 30rpx;
display: flex;
}
.close {
top: 60rpx !important;
}
.qrcode {
margin-top: 30rpx;
text-align: center;
align-items: center;
display: flex;
flex-direction: column;
justify-content: center;
}
.checkout-car {
width: 700rpx;
left: 25rpx;
position: fixed;
bottom: 30rpx;
display: flex;
justify-content: space-between;
background-color: #000000;
border-radius: 100px;
align-items: center;
.car-selected {
color: #ccc;
display: flex;
align-items: center;
padding: 0 20rpx;
}
.car-total {
display: flex;
color: #ebcf00;
align-items: center;
padding-left: 40rpx;
.save-btn {
}
}
}
</style>
+67
View File
@@ -0,0 +1,67 @@
<template>
<view>
<uni-card title="店铺名称" thumbnail="https://oss.wsdns.cn/20230722/5e7d3ea18c7f43acae8b7ea82bab7cbc.png" extra="待支付">
<view class="order-info">
<view class="goods-image">
<image src="https://static.yoshop.xany6.com/20190610131953961df5569.PNG" mode="aspectFill"></image>
</view>
<view class="info">
<text>订单编号:11479</text>
<text>商品名称:脱单邮局二维码</text>
<text>商品金额:¥10</text>
<text>备注信息:获取微信</text>
<text>下单时间:2023-10-20 13:20:05</text>
</view>
</view>
</uni-card>
<uni-card title="店铺名称" thumbnail="https://oss.wsdns.cn/20230722/5e7d3ea18c7f43acae8b7ea82bab7cbc.png" extra="待支付">
<view class="order-info">
<view class="goods-image">
<image src="https://static.yoshop.xany6.com/20190610131953961df5569.PNG" mode="aspectFill"></image>
</view>
<view class="info">
<text>订单编号:11479</text>
<text>商品名称:脱单邮局二维码</text>
<text>商品金额:¥10</text>
<text>备注信息:获取微信</text>
<text>下单时间:2023-10-20 13:20:05</text>
</view>
</view>
</uni-card>
</view>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
}
}
</script>
<style lang="scss" scoped>
.order-info{
display: flex;
.goods-image{
image{
width: 180rpx;
height: 180rpx;
}
}
.info{
display: flex;
flex-direction: column;
flex: 1;
margin-left: 12rpx;
padding: 12rpx 20rpx;
line-height: 1.6rem;
border-radius: 10rpx;
background-color: $uni-bg-color-grey;
}
}
</style>
+212
View File
@@ -0,0 +1,212 @@
<template>
<view class="container">
<view class="teacher-avatar">
<uv-avatar src="https://oss.wsdns.cn/20240608/1de5f5c694de4e339957be8013ca1ab9.jpeg" size="100"></uv-avatar>
<view class="teacher-info">
<uv-text text="游泳教练" align="center" size="16"></uv-text>
<uv-text text="游泳企事业800" type="warning" size="12"></uv-text>
</view>
</view>
<uni-card title="教练简介" :is-shadow="false" :border="false" :padding="0">
<view class="web-text-heading booking-content">
<view v-html="course.content"></view>
<uv-empty icon="https://cdn.uviewui.com/uview/empty/car.png"></uv-empty>
<uv-gap height="50"></uv-gap>
</view>
</uni-card>
<uv-gap height="80"></uv-gap>
</view>
</template>
<script>
import { storeToRefs } from 'pinia';
import * as CourseApi from '@/api/booking/course';
import { useCarStore } from '@/store/modules/car';
const carStore = useCarStore();
export default {
data() {
return {
id: 0,
// 课程信息
course: {},
// 课程相册
photo: [],
isLogin: false,
disabled: true,
options: [
{
icon: 'headphones',
text: '客服'
},
{
icon: 'redo',
text: '分享'
}
],
buttonGroup: [
{
text: '立即报名',
backgroundColor: 'linear-gradient(90deg, #FE6035, #EF1224)',
color: '#fff'
}
],
radio2: 0,
sex: [
{
text: '幼儿基础班(10次课,10天连续上课)',
value: 0
},
{
text: '少年基础班(10次课,10天连续上课)',
value: 1
},
{
text: '少年基础班(10次课,10天连续上课)',
value: 2
},
{
text: '成人基础班(10次课,10天连续上课)',
value: 3
}
],
teacher: [
{
text: '姚教练',
value: 0
},
],
student: [
{
text: '全红婵',
value: 0
},
{
text: '新增',
value: 99
}
]
};
},
onLoad(option) {
this.id = option.id;
this.reload();
},
onShow() {
// 登录状态
if (uni.getStorageSync('user_id') && uni.getStorageSync('access_token')) {
this.isLogin = true;
}
},
methods: {
async reload() {
const app = this;
// 请求数据
Promise.all([app.getCourse()]).then((res) => {
const course = res[0];
app.course = course;
// 修改标题
uni.setNavigationBarTitle({
title: course.courseName
});
// 加载课程相册
if (course.files) {
app.photo = JSON.parse(course.files);
}
// 更新购物车状态
// carStore.setMerchant(merchant)
// carStore.merchantId = course.merchantId
// carStore.merchantName = course.merchantName
// carStore.merchantCode = course.merchantCode
});
},
getCourse() {
return new Promise((resolve, reject) => {
CourseApi.getCourse(this.id)
.then((result) => {
resolve(result);
})
.catch(reject);
});
},
onDisabled() {
this.disabled = !this.disabled;
},
navTo(url) {
uni.navigateTo({
url
});
},
openBookingTel() {
// 通过组件定义的ref调用uni-popup方法 ,如果传入参数 ,type 属性将失效 ,仅支持 ['top','left','bottom','right','center']
this.$refs.popup.open('bottom');
},
closeBookingTel() {
this.$refs.popup.close();
},
callPhone(phone) {
uni.makePhoneCall({
phoneNumber: phone
});
},
onMap() {
uni.getLocation({
type: 'gcj02', //返回可以用于uni.openLocation的经纬度
success: function (res) {
console.log('返回可以用于uni.openLocation的经纬度: ', res);
const latitude = this.course.latitude;
const longitude = this.course.longitude;
uni.openLocation({
latitude: latitude,
longitude: longitude,
success: function () {
console.log('success');
}
});
}
});
},
save() {
if (!this.disabled) {
uni.showToast({
title: '请先阅读并同意订票协议',
icon: 'none'
});
return false;
}
uni.navigateTo({
url: '/package/course/checkout?id=' + this.id
});
}
}
};
</script>
<style>
page {
background-size: 100%;
background-repeat: no-repeat;
background-color: #f0f2f5;
width: 750rpx;
overflow-x: hidden;
}
</style>
<style lang="scss" scoped>
.teacher-avatar {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 50rpx 0;
.teacher-info{
line-height: 1.4rem;
margin-top: 20rpx;
}
}
</style>
+384
View File
@@ -0,0 +1,384 @@
<template>
<view class="page">
<!-- 其他功能 -->
<uni-card :border="false" :is-shadow="false" :padding="0">
<view class="order-body web-cell web-cell-align-top">
<view class="web-cell-content">
<uv-cell-group :customStyle="{backgroundColor: '#ffffff'}" :border="false">
<block v-for="(item,index) in list" :key="index">
<uv-cell :cellStyle="{padding: '10px 0'}" :label="item.address">
<template v-slot:icon>
<uv-avatar :text="item.type" fontSize="12" size="32" randomBgColor></uv-avatar>
</template>
<template v-slot:title>
<view class="title-bar">
<text class="web-text-heading" style="font-weight: 700;">{{ item.name }}</text>
<text class="web-text-secondary">{{ item.phone }}</text>
<uni-tag v-if="item.isDefault" text="默认" size="mini" inverted type="success"></uni-tag>
</view>
</template>
<template v-slot:right-icon>
<uni-icons type="compose" style="color: #999999;" size="18"
@click="openEdit(item)"></uni-icons>
</template>
</uv-cell>
</block>
</uv-cell-group>
</view>
</view>
</uni-card>
<view class="btn-bar">
<uv-button class="save-user-profile"
:customStyle="{background: 'linear-gradient(to right, #70b915, #008e04)',borderRadius: '30px',color: '#ffffff'}"
text="添加收货地址" @click="add"></uv-button>
</view>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
<!-- addressEdit弹窗 -->
<uni-popup ref="addForm" type="center" border-radius="10px 10px 0 0">
<uni-card title="添加收货地址" :border="false" :is-shadow="false" :padding="'10px 6px'">
<uni-forms ref="form" :modelValue="formData" :rules="rules" :label-width="80">
<uni-forms-item label="收件人" name="name" required>
<uv-input placeholder="收件人姓名" v-model="formData.name" maxlength="5"></uv-input>
</uni-forms-item>
<uni-forms-item label="手机号码" name="phone" required>
<uv-input placeholder="收件人手机号码" v-model="formData.phone" maxlength="11"></uv-input>
</uni-forms-item>
<uni-forms-item label="所在地区" name="region" required>
<uni-data-picker placeholder="省、市、区、街道" popup-title="请选择所在地区" :localdata="regions"
:map="{text:'label',value: 'value'}" v-model="formData.region" @change="onchange" @nodeclick="onnodeclick"
@popupopened="onpopupopened" @popupclosed="onpopupclosed">
</uni-data-picker>
</uni-forms-item>
<uni-forms-item label="详细地址" name="address" required>
<uv-input placeholder="小区、写字楼、门牌号等" v-model="formData.address"></uv-input>
</uni-forms-item>
<uni-forms-item label="标签" name="type">
<uni-data-checkbox mode="tag" v-model="formData.type" :localdata="typeData" @change="onType"></uni-data-checkbox>
</uni-forms-item>
<uni-forms-item name="isDefault">
<view class="web-cell">
<uni-data-checkbox v-model="formData.isDefault"
:localdata="defaultData" @click="onIsDefault"></uni-data-checkbox>
<view v-if="formData.id" class="del-btn" @click="remove(formData)">
<uni-icons type="trash" class="web-cell" style="color: #999999;">
<text class="web-text-danger"
style="font-size: 22rpx; padding-left: 4rpx;">删除</text>
</uni-icons>
</view>
</view>
</uni-forms-item>
<uv-button class="add-address"
:customStyle="{background: 'linear-gradient(to right, #70b915, #008e04)',borderRadius: '30px',color: '#ffffff'}"
text="保存" @click="submit"></uv-button>
</uni-forms>
</uni-card>
</uni-popup>
</view>
</template>
<script>
import * as Api from '@/api/shop/userAddress';
import * as MpMenuApi from '@/api/cms/mp-menu/index';
import regions from '@/api/regions-data.json';
import {
getWxOpenId
} from '@/api/passport/login';
import {
openUrl
} from '@/utils/common';
import {
useUserStore
} from '@/store/modules/user';
import {
useCarStore
} from '@/store/modules/car';
const userStore = useUserStore();
const carStore = useCarStore();
export default {
data() {
return {
list: [],
statusBarHeight: 104,
isLogin: false,
form: {
name: '',
phone: ''
},
// 表单数据
formData: {},
fields: {},
logo: '',
bookingUser: {},
server: [],
order: [],
defaultData: [{
text: '默认收货地址',
value: true
}],
typeData: [{
text: '家',
value: '家'
},
{
text: '公司',
value: '公司'
},
{
text: '学校',
value: '学校'
}
],
regions,
dataTree: [{
text: "一年级",
value: "1-0",
children: [{
text: "1.1班",
value: "1-1"
},
{
text: "1.2班",
value: "1-2"
}
]
},
{
text: "二年级",
value: "2-0",
children: [{
text: "2.1班",
value: "2-1"
},
{
text: "2.2班",
value: "2-2"
}
]
},
{
text: "三年级",
value: "3-0",
disable: true
}
],
rules: {
// 对name字段进行必填验证
name: {
rules: [{
required: true,
errorMessage: '请输入收件人名称',
}]
},
phone: {
rules: [{
required: true,
format: 'number',
errorMessage: '请输入正确的手机号码',
}]
},
address: {
rules: [{
required: true,
errorMessage: '请输入详情地址',
}]
},
region: {
rules: [{
required: true,
errorMessage: '请选择所在地区',
}, {
validateFunction: function(rule, value, data, callback) {
console.log('value: ', value);
if (value.length < 2) {
callback('请至少勾选两个兴趣爱好')
}
return true
}
}]
}
}
}
},
onLoad() {
this.reload()
},
methods: {
async reload(e) {
const app = this
// 当前登录用户信息
const userInfo = await userStore.fetchUserInfo();
if (Object.keys(userInfo).length > 0) {
app.isLogin = true
app.userInfo = userInfo
} else {
app.isLogin = false
}
// 获取收货地址列表
Api.pageUserAddress({
userId: userInfo.userId
}).then(res => {
app.list = res.list;
})
// 获取地区选择数据
// this.regions = this.regions.map(d => {
// console.log('d: ',d);
// d.text = d.label
// return d;
// })
// Api.getRegions().then(res => {
// console.log('res: ',res);
// })
},
navTo(item) {
if (!this.isLogin) {
this.$refs.login.open('bottom')
return false;
}
openUrl(item);
},
// 弹出登录提示框
openLogin() {
if (!this.isLogin) {
this.$refs.login.open('bottom')
return false;
}
},
onType(e){
this.formData.type = e.detail.value;
},
onIsDefault(){
this.formData.isDefault = !this.formData.isDefault;
},
// 选用该地址
onAddres(item){
carStore.setAddress(item)
uni.navigateBack()
},
add() {
this.formData = {}
this.$refs.addForm.open('center')
},
openEdit(item) {
this.formData = item
this.$refs.addForm.open('center')
},
remove(item) {
const app = this
uni.showModal({
title: '确定要删除吗?',
success(o) {
if (o.confirm) {
uni.showLoading({
title: '请求中.'
})
Api.removeUserAddress(item.id).then(res => {
uni.showToast({
title: '操作成功',
icon: 'none'
})
app.$refs.addForm.close()
app.reload()
})
app.reload()
}
}
});
},
// 触发提交表单
submit() {
this.$refs.form.validate().then(res => {
const saveOrUpdate = this.formData.id ? Api.updateUserAddress : Api.addUserAddress
saveOrUpdate(this.formData).then(message => {
uni.showToast({
title: '保存成功',
icon: 'success'
})
this.$refs.addForm.close()
this.reload()
}).catch((err) => {
console.log(err);
})
console.log('表单数据信息:', res);
}).catch(err => {
console.log('表单错误信息:', err);
})
},
save() {
Api.addUserAddress(this.form).then(msg => {
uni.showToast({
title: msg,
icon: 'none'
})
this.$refs.addForm.close()
this.reload()
}).catch(() => {
uni.showToast({
title: '请检查您的网络.',
icon: 'none'
})
uni.hideLoading()
this.$refs.addForm.close()
this.reload()
})
}
}
}
</script>
<style>
page {
background-size: 100%;
background-repeat: no-repeat;
background-color: #f0f2f5;
width: 750rpx;
overflow-x: hidden;
}
</style>
<style lang="scss">
.avatar {
padding: 20px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 14px;
}
.save-user-profile {
width: 700rpx;
margin: 40rpx auto;
}
.add-address {
width: 600rpx !important;
margin: 40rpx auto;
}
.btn-bar {
width: 700rpx;
left: 25rpx;
position: fixed;
bottom: 30rpx;
margin: auto;
clear: both;
}
.title-bar {
display: flex;
.web-text-heading {
margin-right: 20rpx;
}
.web-text-secondary {
margin-right: 20rpx;
}
}
</style>
+74
View File
@@ -0,0 +1,74 @@
<template>
<view class="page">
<!-- 其他功能 -->
<block v-for="(item, index) in list" :key="index">
<uni-card :border="false" :is-shadow="false" :padding="0">
<uv-cell :title="item.remark" :label="item.createTime" :value="`-${item.money}`" :cellStyle="{ padding: '10px 0' }" :border="false"></uv-cell>
</uni-card>
</block>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
</view>
</template>
<script>
import * as Api from '@/api/user/balance-log';
import { openUrl } from '@/utils/common';
import { useUserStore } from '@/store/modules/user';
const userStore = useUserStore();
export default {
data() {
return {
userCardId: 0,
list: [],
isLogin: false,
logo: uni.getStorageSync('app_logo'),
};
},
onLoad(o) {
this.userCardId = o.id;
this.reload();
},
methods: {
async reload(e) {
const app = this;
const { userCardId } = this;
// 当前登录用户信息
const userInfo = await userStore.fetchUserInfo();
if (Object.keys(userInfo).length > 0) {
app.isLogin = true;
app.userInfo = userInfo;
} else {
app.isLogin = false;
app.$refs.login.open('bottom');
return false;
}
// 获取会员卡使用记录
Api.pageUserBalanceLog({}).then((res) => {
app.list = res.list;
});
},
navTo(item) {
if (!this.isLogin) {
this.$refs.login.open('bottom');
return false;
}
openUrl(item);
}
}
};
</script>
<style>
page {
background-size: 100%;
background-repeat: no-repeat;
background-color: #f0f2f5;
width: 750rpx;
overflow-x: hidden;
}
</style>
<style lang="scss">
</style>
+90
View File
@@ -0,0 +1,90 @@
<template>
<view class="container">
<uni-card :border="false" :is-shadow="false">
<view v-html="form.info"></view>
</uni-card>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
</view>
</template>
<script>
import * as Api from '@/api/booking/userCard';
import { useUserStore } from '@/store/modules/user';
const userStore = useUserStore();
export default {
data() {
return {
id: 0,
userInfo: {},
form: {},
isLogin: false,
disabled: false
};
},
onLoad(option) {
this.id = option.id;
this.reload();
},
onShow() {
// 登录状态
if (uni.getStorageSync('user_id') && uni.getStorageSync('access_token')) {
this.isLogin = true;
}
this.openLogin();
},
methods: {
async reload() {
const app = this;
const { id } = this;
// 当前登录用户信息
const userInfo = await userStore.fetchUserInfo();
app.userInfo = userInfo;
Api.getUserCard(id).then((data) => {
app.form = data;
});
},
onDisabled() {
this.disabled = !this.disabled;
},
navTo(url) {
uni.navigateTo({
url
});
},
openUrl(url) {
if (!this.isLogin) {
this.$refs.login.open('bottom');
return false;
} else {
uni.navigateTo({
url
});
}
},
// 弹出登录提示框
openLogin() {
if (!this.isLogin) {
this.$refs.login.open('bottom');
return false;
}
}
}
};
</script>
<style>
page {
background-size: 100%;
background-repeat: no-repeat;
background-color: #f0f2f5;
width: 750rpx;
overflow-x: hidden;
}
</style>
<style lang="scss" scoped>
</style>
+284
View File
@@ -0,0 +1,284 @@
<template>
<view class="page">
<!-- 其他功能 -->
<uni-card :border="false" :is-shadow="false" :padding="0">
<view class="order-body web-cell web-cell-align-top">
<view class="web-cell-content">
<uv-cell-group :customStyle="{backgroundColor: '#ffffff'}" :border="false">
<block v-for="(item,index) in list" :key="index">
<uv-cell :title="item.merchantName" :label="item.shopType" isLink :url="`/package/booking/index?id=${item.merchantId}`" :cellStyle="{padding: '10px 0'}">
<template v-slot:icon>
<uv-avatar :src="item.image" fontSize="12" size="50" randomBgColor></uv-avatar>
</template>
</uv-cell>
</block>
</uv-cell-group>
</view>
</view>
</uni-card>
<!-- <view class="btn-bar">
<uv-button class="save-user-profile"
:customStyle="{background: 'linear-gradient(to right, #70b915, #008e04)',borderRadius: '30px',color: '#ffffff'}"
text="添加收货地址" @click="add"></uv-button>
</view> -->
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
</view>
</template>
<script>
import * as Api from '@/api/shop/userAddress';
import * as MerchantApi from '@/api/shop/merchant';
import regions from '@/api/regions-data.json';
import {
getWxOpenId
} from '@/api/passport/login';
import {
openUrl
} from '@/utils/common';
import {
useUserStore
} from '@/store/modules/user';
import {
useCarStore
} from '@/store/modules/car';
const userStore = useUserStore();
const carStore = useCarStore();
export default {
data() {
return {
sid: '',
list: [],
statusBarHeight: 104,
isLogin: false,
form: {
name: '',
phone: ''
},
// 表单数据
formData: {},
fields: {},
logo: '',
server: [],
order: [],
regions,
rules: {
// 对name字段进行必填验证
name: {
rules: [{
required: true,
errorMessage: '请输入收件人名称',
}]
},
phone: {
rules: [{
required: true,
format: 'number',
errorMessage: '请输入正确的手机号码',
}]
},
address: {
rules: [{
required: true,
errorMessage: '请输入详情地址',
}]
},
region: {
rules: [{
required: true,
errorMessage: '请选择所在地区',
}, {
validateFunction: function(rule, value, data, callback) {
console.log('value: ', value);
if (value.length < 2) {
callback('请至少勾选两个兴趣爱好')
}
return true
}
}]
}
}
}
},
onLoad(o) {
this.sid = o.sid
this.reload()
},
methods: {
async reload(e) {
const app = this
// 当前登录用户信息
const userInfo = await userStore.fetchUserInfo();
if (Object.keys(userInfo).length > 0) {
app.isLogin = true
app.userInfo = userInfo
} else {
app.isLogin = false
}
// 获取收货地址列表
MerchantApi.pageMerchant({
merchantIds: app.sid
}).then(res => {
app.list = res.list;
})
// 获取地区选择数据
// this.regions = this.regions.map(d => {
// console.log('d: ',d);
// d.text = d.label
// return d;
// })
// Api.getRegions().then(res => {
// console.log('res: ',res);
// })
},
navTo(item) {
if (!this.isLogin) {
this.$refs.login.open('bottom')
return false;
}
openUrl(item);
},
// 弹出登录提示框
openLogin() {
if (!this.isLogin) {
this.$refs.login.open('bottom')
return false;
}
},
onType(e){
this.formData.type = e.detail.value;
},
onIsDefault(){
this.formData.isDefault = !this.formData.isDefault;
},
// 选用该地址
onAddres(item){
carStore.setAddress(item)
uni.navigateBack()
},
add() {
this.formData = {}
this.$refs.addForm.open('center')
},
openEdit(item) {
this.formData = item
this.$refs.addForm.open('center')
},
remove(item) {
const app = this
uni.showModal({
title: '确定要删除吗?',
success(o) {
if (o.confirm) {
uni.showLoading({
title: '请求中.'
})
Api.removeUserAddress(item.id).then(res => {
uni.showToast({
title: '操作成功',
icon: 'none'
})
app.$refs.addForm.close()
app.reload()
})
app.reload()
}
}
});
},
// 触发提交表单
submit() {
this.$refs.form.validate().then(res => {
const saveOrUpdate = this.formData.id ? Api.updateUserAddress : Api.addUserAddress
saveOrUpdate(this.formData).then(message => {
uni.showToast({
title: '保存成功',
icon: 'success'
})
this.$refs.addForm.close()
this.reload()
}).catch((err) => {
console.log(err);
})
console.log('表单数据信息:', res);
}).catch(err => {
console.log('表单错误信息:', err);
})
},
save() {
Api.addUserAddress(this.form).then(msg => {
uni.showToast({
title: msg,
icon: 'none'
})
this.$refs.addForm.close()
this.reload()
}).catch(() => {
uni.showToast({
title: '请检查您的网络.',
icon: 'none'
})
uni.hideLoading()
this.$refs.addForm.close()
this.reload()
})
}
}
}
</script>
<style>
page {
background-size: 100%;
background-repeat: no-repeat;
background-color: #f0f2f5;
width: 750rpx;
overflow-x: hidden;
}
</style>
<style lang="scss">
.avatar {
padding: 20px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 14px;
}
.save-user-profile {
width: 700rpx;
margin: 40rpx auto;
}
.add-address {
width: 600rpx !important;
margin: 40rpx auto;
}
.btn-bar {
width: 700rpx;
left: 25rpx;
position: fixed;
bottom: 30rpx;
margin: auto;
clear: both;
}
.title-bar {
display: flex;
.web-text-heading {
margin-right: 20rpx;
}
.web-text-secondary {
margin-right: 20rpx;
}
}
</style>
+74
View File
@@ -0,0 +1,74 @@
<template>
<view class="page">
<!-- 其他功能 -->
<block v-for="(item, index) in list" :key="index">
<uni-card :border="false" :is-shadow="false" :padding="0">
<uv-cell :title="item.comments" :label="item.createTime" :value="`-${item.money}`" :cellStyle="{ padding: '10px 0' }" :border="false"></uv-cell>
</uni-card>
</block>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
</view>
</template>
<script>
import * as Api from '@/api/booking/userCardLog';
import { openUrl } from '@/utils/common';
import { useUserStore } from '@/store/modules/user';
const userStore = useUserStore();
export default {
data() {
return {
userCardId: 0,
list: [],
isLogin: false,
logo: uni.getStorageSync('app_logo'),
};
},
onLoad(o) {
this.userCardId = o.id;
this.reload();
},
methods: {
async reload(e) {
const app = this;
const { userCardId } = this;
// 当前登录用户信息
const userInfo = await userStore.fetchUserInfo();
if (Object.keys(userInfo).length > 0) {
app.isLogin = true;
app.userInfo = userInfo;
} else {
app.isLogin = false;
app.$refs.login.open('bottom');
return false;
}
// 获取会员卡使用记录
Api.pageUserCardLog({userCardId}).then((res) => {
app.list = res.list;
});
},
navTo(item) {
if (!this.isLogin) {
this.$refs.login.open('bottom');
return false;
}
openUrl(item);
}
}
};
</script>
<style>
page {
background-size: 100%;
background-repeat: no-repeat;
background-color: #f0f2f5;
width: 750rpx;
overflow-x: hidden;
}
</style>
<style lang="scss">
</style>
+541
View File
@@ -0,0 +1,541 @@
<template>
<view class="container">
<!-- deBug信息 -->
<view class="web-debug web-text-success" style="display: none">
场馆ID:{{ merchantId }} 场馆编号:{{ merchantCode }} 场馆名称:{{ merchantName }} 日期:{{ dateTime }} 星期:{{ week }} 订单总金额:{{ totalPrice }} 类型:{{
type
}}
商品信息:{{ goodsList }}
</view>
<view class="card-list">
<view class="container" :style="{ background: `url(${form.image}) no-repeat center center`, backgroundSize: '100%', opacity: '0.85' }">
<view class="content web-cell web-cell-align-top">
<view class="merchant-avatar">
<uv-avatar :src="form.merchantAvatar" size="42" style="border: 3rpx solid #ffffff"></uv-avatar>
</view>
<view class="card-info web-cell-content">
<view class="title-bar">
<view class="web-text-heading" style="color: #ffffff; font-size: 17px; font-weight: 600">{{ form.name }}</view>
<view class="desc web-text-placeholder" style="font-size: 14px">{{ cardType[form.type] }}</view>
</view>
<view class="price" @click="openQrCode">
<view class="web-text-price">
<uv-avatar src="../../static/qrcode.png" size="30" shape="square"></uv-avatar>
</view>
</view>
</view>
</view>
<view class="card-num">{{ form.cardNum }}</view>
</view>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
</view>
<uni-card :border="false" :is-shadow="false" :padding="'12px 0'">
<view class="money-bar web-cell">
<view class="money-item web-cell-content">
<text>余额</text>
<text>{{ form.remainingMoney || 0.0 }}</text>
</view>
<view class="web-divider-vertical"></view>
<view class="money-item web-cell-content">
<text>剩余次数</text>
<text>{{ form.num || 0 }}</text>
</view>
<view class="web-divider-vertical"></view>
<view class="money-item web-cell-content">
<text>折扣</text>
<text>{{ form.discount || 0 }}</text>
</view>
</view>
</uni-card>
<view class="to-pay">
<uv-button :customStyle="{ width: '300rpx', borderRadius: '30px', color: '#3C8618' }" text="去使用" @click="navTo(`/package/user/card-detail-merchant?sid=${form.sid}`)"></uv-button>
</view>
<!-- <uni-card title="会员卡说明" :border="false" :is-shadow="false">
<view v-html="form.info"></view>
</uni-card> -->
<uni-card :border="false" :is-shadow="false" :padding="0">
<view class="server">
<uni-list :border="false">
<uni-list-item link @click="navTo(`/package/user/card-detail-about?id=${form.id}`)">
<template v-slot:body>
<view class="slot-box">
<text class="slot-text" :style="{ color: '#333333' }">会员卡详情</text>
</view>
</template>
</uni-list-item>
<uni-list-item link @click="navTo(`/package/user/card-detail-merchant?sid=${form.sid}`)">
<template v-slot:body>
<view class="slot-box">
<text class="slot-text" :style="{ color: '#333333' }">适用场馆</text>
</view>
</template>
</uni-list-item>
<uni-list-item link @click="navTo(`/package/user/card-detail-record?id=${form.id}`)">
<template v-slot:body>
<view class="slot-box">
<text class="slot-text" :style="{ color: '#333333' }">使用记录</text>
</view>
</template>
</uni-list-item>
</uni-list>
</view>
</uni-card>
</view>
<!-- 收货地址选择弹窗 -->
<uni-popup ref="addForm" type="center" border-radius="10px 10px 0 0">
<uni-card :border="false" :is-shadow="false" :padding="0">
<view class="qrcode">
<uv-qrcode ref="qrcode" size="390rpx"
:options="{data: form.cardNum,foregroundImageSrc: form.merchantAvatar, margin: 10,foregroundImagePadding: 4,foregroundImageHeight: 30,foregroundImageWidth: 30,foregroundImageBorderRadius: 4}"
:value="form.cardNum"></uv-qrcode>
<view class="card-num web-text-heading" style="font-size: 34rpx;">{{ form.cardNum }}</view>
<text class="web-text-secondary">请在结账前出示会员卡</text>
</view>
</uni-card>
</uni-popup>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
</template>
<script>
import * as Api from '@/api/booking/userCard';
import * as OrderApi from '@/api/shop/order';
import * as MerchantApi from '@/api/shop/merchant';
import { storeToRefs } from 'pinia';
import { getWeek, getKey } from '@/utils/common';
import { useCarStore } from '@/store/modules/car';
import { useUserStore } from '@/store/modules/user';
const userStore = useUserStore();
const carStore = useCarStore();
const { goodsList, totalPrice, carNum, merchantId, merchantName, merchantCode, type, dateTime } = storeToRefs(carStore);
const cardType = ['年卡', '次卡', '月卡', 'IC卡', '充值卡'];
export default {
data() {
return {
id: 0,
goodsId: 0,
userInfo: {},
form: {},
address: {},
addressList: [],
week: 0,
cardType,
goodsList,
// 订单总金额
totalPrice,
reducePrice: 0,
merchantId,
merchantName,
merchantCode,
getWeek,
payType: 1,
isLogin: false,
disabled: false
};
},
onLoad(option) {
this.id = option.cardId;
this.reload();
},
onShow() {
// 登录状态
if (uni.getStorageSync('user_id') && uni.getStorageSync('access_token')) {
this.isLogin = true;
}
this.openLogin();
},
methods: {
async reload() {
const app = this;
const { id } = this;
// 当前登录用户信息
const userInfo = await userStore.fetchUserInfo();
app.userInfo = userInfo;
Api.getUserCard(id).then((data) => {
app.form = data;
});
},
onDisabled() {
this.disabled = !this.disabled;
},
navTo(url) {
uni.navigateTo({
url
});
},
openUrl(url) {
if (!this.isLogin) {
this.$refs.login.open('bottom');
return false;
} else {
uni.navigateTo({
url
});
}
},
onAddress(item) {
this.address = item;
this.$refs.addForm.close();
},
// 切换支付方式
onPayType(index) {
console.log('e: ', index);
this.payType = index;
},
openQrCode() {
this.$refs.addForm.open('center');
},
// 弹出登录提示框
openLogin() {
if (!this.isLogin) {
this.$refs.login.open('bottom');
return false;
}
},
save() {
if (!this.disabled) {
uni.showToast({
title: '请先阅读并同意服务协议',
icon: 'none'
});
return false;
}
uni.showLoading({
title: '订单提交中.'
});
const app = this;
const { form, payType } = this;
OrderApi.addOrder({
type: 2, // 0商城订单 1预定订单 2会员卡订单
cardId: form.cardId,
merchantId: form.merchantId,
merchantName: form.merchantName,
totalPrice: form.price,
payPrice: form.price,
comments: form.cardName,
payType
})
.then((data) => {
const orderInfo = data;
// 调起微信支付
if (payType == 1) {
// #ifdef MP-WEIXIN
uni.requestPayment({
provider: orderInfo.provider, // 服务提供商
timeStamp: orderInfo.timeStamp, // 时间戳
nonceStr: orderInfo.nonceStr, // 随机字符串
package: orderInfo.package,
signType: orderInfo.signType, // 签名算法
paySign: orderInfo.paySign, // 签名
success: function (res) {
// 业务逻辑。。。
uni.showToast({
title: '支付成功',
icon: 'success'
});
setTimeout(function () {
app.disabled = false;
uni.navigateTo({
url: '/package/user/card'
});
}, 500);
},
fail: function (err) {
console.log('支付失败', err);
app.disabled = false;
}
});
// #endif
}
// 使用余额支付
if (payType == 0) {
if (orderInfo) {
uni.showToast({
title: '支付成功',
icon: 'success'
});
setTimeout(function () {
app.disabled = false;
uni.navigateTo({
url: '/package/user/card'
});
}, 500);
return;
}
if (!orderInfo) {
return uni.showToast({
title: '支付失败',
icon: 'error'
});
}
}
uni.hideLoading();
})
.catch((res) => {
uni.showToast({
title: res.message || '请检查您的网络.',
icon: 'none'
});
uni.hideLoading();
});
}
}
};
</script>
<style>
page {
background-size: 100%;
background-repeat: no-repeat;
background-color: #f0f2f5;
width: 750rpx;
overflow-x: hidden;
}
</style>
<style lang="scss" scoped>
.checkout-car {
width: 700rpx;
left: 25rpx;
position: fixed;
bottom: 30rpx;
display: flex;
justify-content: space-between;
background-color: #000000;
border-radius: 100px;
align-items: center;
.car-selected {
color: #ccc;
display: flex;
align-items: center;
padding: 0 20rpx;
}
.car-total {
display: flex;
color: #ebcf00;
align-items: center;
padding-left: 40rpx;
.save-btn {
}
}
}
.card-list {
.container {
width: 700rpx;
position: relative;
margin: 25rpx auto;
display: flex;
justify-content: space-between;
align-items: center;
border-radius: 20rpx;
position: relative;
box-shadow: 0 0px 6px 0 rgba(0, 0, 0, 0.2);
// background: linear-gradient(to right, #70b915, #008e04);
color: #ffffff;
.card-num {
position: absolute;
z-index: 1;
bottom: 30rpx;
left: 30rpx;
}
}
.container::before {
content: '';
display: block;
position: absolute;
border-radius: 20rpx;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: #000000;
// background: url('https://oss.wsdns.cn/20240528/cf37a247603f489ba23d7d2a53b8da39.jpeg') no-repeat center bottom;
background-size: 100%;
opacity: 0.25; /* 设置透明度 */
}
.content {
position: relative;
z-index: 1;
width: 700rpx;
height: 370rpx;
display: flex;
justify-content: space-between;
.merchant-avatar {
margin-top: 30rpx;
margin-left: 30rpx;
}
.card-info {
height: 120rpx;
margin-top: 10rpx;
margin-left: 10rpx;
display: flex;
justify-content: space-between;
align-items: center;
.title-bar {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: flex-start;
}
.web-text-price {
padding-right: 40rpx;
font-size: 36rpx;
color: #fecc66;
}
}
.card-bg {
}
}
.card-item {
width: 700rpx;
margin: 20rpx auto;
border-radius: 20rpx;
position: relative;
// box-shadow: 0 0px 6px 1px rgba($color: #a5a5a5, $alpha: 0.2);
}
// .card-item::before {
// content: ''; /* 伪元素需要内容,即使它是空的 */
// position: absolute;
// top: 0;
// right: 0;
// bottom: 0;
// left: 0;
// background: url('https://oss.wsdns.cn/20240528/d5680e18210544a49dfa79f250f1997d.jpeg');
// background-size: cover; /* 或其他你需要的背景大小 */
// opacity: 0.5; /* 设置透明度 */
// z-index: -1; /* 确保伪元素在内容之下 */
// }
.order-title {
padding: 20rpx 0;
.merchant-avatar {
margin-right: 12rpx;
}
.card-name {
font-weight: 600;
}
.btn-status {
font-size: 30rpx;
display: flex;
}
}
.order-body {
padding: 16px 0;
}
}
.card-actions {
display: flex;
flex-direction: row;
justify-content: flex-end;
height: 45px;
border-top: 1px #eee solid;
}
.card-actions-item {
display: flex;
flex-direction: row;
align-items: center;
.web-text-heading {
font-size: 38rpx;
margin-left: 28rpx;
}
}
.card-actions-item-text {
font-size: 12px;
color: #666;
margin-left: 5px;
}
.address-body {
width: 660rpx;
margin: auto;
}
.to-pay {
width: 600rpx !important;
margin: 40rpx auto;
display: flex;
justify-content: center;
}
.btn-bar {
width: 700rpx;
left: 25rpx;
position: fixed;
bottom: 30rpx;
margin: auto;
clear: both;
}
.title-bar {
display: flex;
.web-text-heading {
margin-right: 20rpx;
}
.web-text-secondary {
margin-right: 20rpx;
}
}
.xieyi {
margin-bottom: 80rpx;
padding: 0 30rpx;
.text {
margin-left: 5rpx;
.link {
color: #0f80ff;
}
}
}
.money-bar {
display: flex;
justify-content: space-around;
align-items: center;
.money-item {
text-align: center;
display: flex;
flex-direction: column;
}
.web-divider-vertical {
height: 60rpx;
width: 1rpx;
background-color: #e6e6e6;
}
}
.qrcode{
width: 600rpx;
height: 600rpx;
margin: 30rpx auto;
line-height: 2rem;
background-color: #ffffff;
text-align: center;
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
}
</style>
+422
View File
@@ -0,0 +1,422 @@
<template>
<view>
<!-- <view class="segmented">
<uni-segmented-control :current="current" :values="items" :styleType="styleType" :activeColor="activeColor" inActiveColor="#808080" @clickItem="onClickItem" />
</view> -->
<view class="card-list">
<block v-if="!hideTools || cardList.length > 0">
<view
class="container"
v-for="(item, index) in cardList"
:key="index"
@click="openUrl('/package/user/card-detail?cardId=' + item.id)"
:style="{ background: `url(${item.image}) no-repeat center center`, backgroundSize: '100%', opacity: '0.85' }"
>
<view class="content web-cell">
<view class="merchant-avatar">
<uv-avatar :src="item.merchantAvatar" size="36" style="border: 3rpx solid #ffffff"></uv-avatar>
</view>
<view class="card-info web-cell-content">
<view class="title-bar">
<view class="web-text-heading" style="color: #ffffff; font-size: 17px; font-weight: 600">{{ item.name }}</view>
<!-- <block v-if="item.type == 2">
<view class="desc web-text-heading" style="color: #ffffff; font-size: 14px">{{ item.month }}个月</view>
</block> -->
<block v-if="item.type == 2">
<view class="desc web-text-heading" style="color: #ffffff; font-size: 14px">剩余{{ item.number }}次</view>
</block>
<block v-if="item.type == 1 || item.type == 3 || item.type == 5">
<view class="desc web-text-heading" style="color: #ffffff; font-size: 14px">余额¥{{ item.remainingMoney }}</view>
</block>
</view>
<!-- <view class="price">
<text class="web-text-price">{{ `¥${item.price}` }}</text>
</view> -->
</view>
</view>
</view>
</block>
<block v-else>
<uni-card :border="false" :padding="'18px 6px'">
<uv-skeleton rows="2" avatar :loading="hideTools" :title="false"></uv-skeleton>
</uni-card>
<uni-card :border="false" :padding="'18px 6px'">
<uv-skeleton rows="2" avatar :loading="hideTools" :title="false"></uv-skeleton>
</uni-card>
<uni-card :border="false" :padding="'18px 6px'">
<uv-skeleton rows="2" avatar :loading="hideTools" :title="false"></uv-skeleton>
</uni-card>
<uni-card :border="false" :padding="'18px 6px'">
<uv-skeleton rows="2" avatar :loading="hideTools" :title="false"></uv-skeleton>
</uni-card>
<uni-card :border="false" :padding="'18px 6px'">
<uv-skeleton rows="2" avatar :loading="hideTools" :title="false"></uv-skeleton>
</uni-card>
<uni-card :border="false" :padding="'18px 6px'">
<uv-skeleton rows="2" avatar :loading="hideTools" :title="false"></uv-skeleton>
</uni-card>
</block>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
</view>
<view v-if="!hideTools && cardList.length == 0">
<uv-empty mode="list" icon="https://cdn.uviewui.com/uview/empty/list.png"></uv-empty>
</view>
</view>
</template>
<script>
import * as Api from '@/api/booking/userCard';
import { pageWechatDeposit } from '@/api/shop/wechatDeposit';
import { getWeek, getKey } from '@/utils/common';
export default {
components: {},
data() {
return {
isRefresh: false,
isLogin: false,
userId: 0,
where: {
page: 1
},
canReset: false,
loadMore: 'more',
logo: '',
items: ['月/年卡', '次卡', '充值卡'],
cardList: [],
styles: [
{
value: 'button',
text: '按钮',
checked: true
},
{
value: 'text',
text: '文字'
}
],
colors: ['#333333', '#4cd964', '#dd524d'],
current: 0,
colorIndex: 0,
activeColor: '#108001',
styleType: 'text',
getWeek,
// 骨架屏
hideTools: true
};
},
onLoad(option) {
// 判断是否登录
this.openLogin();
// 加载数据
this.reload();
console.log('判断是否刷新: ', option);
if (option.isRefresh) {
this.isRefresh = true;
}
},
onShow(e) {
console.log('判断是否刷新: ', e);
// 判断是否登录
this.openLogin();
if (this.isRefresh) {
this.reload();
}
},
// 触底函数
onReachBottom() {
const app = this;
const { where } = this;
if (app.canReset) {
app.where.page = ++where.page;
app.reload();
}
},
methods: {
reload() {
const app = this;
const { where, userId } = this;
if (userId == 0) {
app.openLogin();
return;
}
where.userId = userId;
where.payStatus = 1;
app.loadMore = 'loading';
Api.pageUserCard(where)
.then((res) => {
console.log('res: ', res);
const list = res.list.map((d) => {
console.log(d);
return d;
});
if (app.cardList.length < res.count) {
app.cardList = app.cardList.concat(list);
app.canReset = true;
app.loadMore = 'no-more';
} else {
app.canReset = false;
app.hideTools = false;
app.loadMore = 'no-more';
}
// uni.hideLoading();
app.isRefresh = false;
})
.catch(() => {
uni.showToast({
title: '请检查您的网络.',
icon: 'none'
});
app.hideTools = false;
app.isRefresh = false;
});
},
onClickItem(e, text) {
const app = this;
const { where, userId } = this;
const index = e.currentIndex;
if (this.current !== e.currentIndex) {
this.current = e.currentIndex;
}
// 全部
if (index == 0) {
where.cardCode = '月/年卡';
}
// 未支付
if (index == 1) {
where.cardCode = '次卡';
}
// 已支付
if (index == 2) {
where.cardCode = '充值卡';
}
this.where.page = 1;
this.cardList = [];
this.hideTools = true;
this.reload();
},
openUrl(url) {
uni.navigateTo({
url
});
},
toPay(orderId) {
uni.navigateTo({
url: '/package/booking/confirm?id=' + orderId
});
},
closeOrder(item) {
uni.showModal({
title: '确定取消此订单?',
success(o) {
if (o.confirm) {
// Api.updateOrder({
// orderStatus: 2,
// orderId: item.orderId
// })
// .then((msg) => {
// uni.showToast({
// title: msg,
// icon: 'none'
// });
// item.orderStatus = 2;
// })
// .catch(() => {
// uni.showToast({
// title: '请检查您的网络.',
// icon: 'none'
// });
// uni.hideLoading();
// });
}
}
});
},
// 弹出登录提示框
async openLogin() {
this.userId = uni.getStorageSync('user_id');
if (!this.userId) {
this.$refs.login.open('bottom');
return false;
}
}
}
};
</script>
<style lang="scss">
.content {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
justify-content: center;
align-items: center;
height: 150px;
text-align: center;
}
.segmented {
padding: 0 12rpx;
}
.content-text {
font-size: 14px;
color: #666;
}
.color-tag {
width: 25px;
height: 25px;
}
.uni-list {
flex: 1;
}
.card-list {
.container {
width: 700rpx;
height: 200rpx;
position: relative;
margin: 25rpx auto;
display: flex;
justify-content: space-between;
align-items: center;
border-radius: 20rpx;
position: relative;
box-shadow: 0 0px 6px 0 rgba(0, 0, 0, 0.2);
// background: linear-gradient(to right, #70b915, #008e04);
color: #ffffff;
}
.container::before {
content: '';
display: block;
position: absolute;
border-radius: 20rpx;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: #000000;
// background: url('https://oss.wsdns.cn/20240528/cf37a247603f489ba23d7d2a53b8da39.jpeg') no-repeat center bottom;
background-size: 100%;
opacity: 0.25; /* 设置透明度 */
}
.content {
position: relative;
z-index: 1;
width: 700rpx;
display: flex;
justify-content: space-between;
.merchant-avatar {
margin-left: 24rpx;
}
.card-info {
margin-left: 10rpx;
display: flex;
justify-content: space-between;
align-items: center;
.title-bar {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: flex-start;
}
.web-text-price {
padding-right: 30rpx;
font-size: 36rpx;
color: #fecc66;
}
}
.card-bg {
}
}
.card-item {
width: 700rpx;
margin: 20rpx auto;
border-radius: 20rpx;
position: relative;
// box-shadow: 0 0px 6px 1px rgba($color: #a5a5a5, $alpha: 0.2);
}
// .card-item::before {
// content: ''; /* 伪元素需要内容,即使它是空的 */
// position: absolute;
// top: 0;
// right: 0;
// bottom: 0;
// left: 0;
// background: url('https://oss.wsdns.cn/20240528/d5680e18210544a49dfa79f250f1997d.jpeg');
// background-size: cover; /* 或其他你需要的背景大小 */
// opacity: 0.5; /* 设置透明度 */
// z-index: -1; /* 确保伪元素在内容之下 */
// }
.order-title {
padding: 20rpx 0;
.merchant-avatar {
margin-right: 12rpx;
}
.card-name {
font-weight: 600;
}
.btn-status {
font-size: 30rpx;
display: flex;
}
}
.order-body {
padding: 16px 0;
}
}
.ele-flex {
display: flex;
justify-content: space-between;
}
.card-actions {
display: flex;
flex-direction: row;
justify-content: flex-end;
align-items: center;
height: 45px;
border-top: 1px #eee solid;
}
.card-actions-item {
display: flex;
flex-direction: row;
align-items: center;
}
.card-actions-item-text {
font-size: 12px;
color: #666;
margin-left: 5px;
}
.close {
top: 60rpx !important;
}
.total-price {
display: flex;
flex-direction: column;
justify-content: flex-start;
font-size: 30rpx;
align-items: flex-start;
padding-left: 6rpx;
margin-left: 450rpx;
.web-text-heading {
font-size: 30rpx !important;
}
}
</style>
+347
View File
@@ -0,0 +1,347 @@
<template>
<view>
<view class="segmented">
<uni-segmented-control :current="current" :values="items" :styleType="styleType" :activeColor="activeColor"
inActiveColor="#808080" @clickItem="onClickItem" />
</view>
<view class="coupon">
<block v-for="(item,index) in list" :key="index">
<view class="coupon-item web-cell">
<view class="coupon-bg">
<view class="title"><span class="price">8</span><span class="unit">元</span></view>
<view class="desc">满减劵</view>
</view>
<view class="coupon-info web-cell web-cell-content">
<view class="coupon-content">
<view class="title">优惠券名称</view>
<view class="desc web-text-secondary">有效期至:2024-05-29</view>
</view>
<uv-button class="save-btn" size="mini"
:customStyle="{background: 'linear-gradient(to right, #70b915, #008e04)',color: '#ffffff', border: 'none'}"
text="去使用" @click="save"></uv-button>
</view>
</view>
</block>
<!-- <uv-empty mode="order" v-if="list.length == 0"
icon="https://cdn.uviewui.com/uview/empty/data.png"></uv-empty> -->
<uni-load-more v-if="list.length > 0" :status="loadMore"></uni-load-more>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
</view>
</view>
</template>
<script>
import * as CouponApi from '@/api/booking/userCoupon'
import {
pageWechatDeposit
} from '@/api/shop/wechatDeposit'
import {
getWeek,
getKey
} from '@/utils/common';
export default {
components: {},
data() {
return {
isRefresh: false,
isLogin: false,
userId: 0,
where: {
page: 1,
status: 0
},
canReset: false,
loadMore: 'more',
logo: '',
items: ['待使用(0)', '已使用(0)', '已失效(0)'],
list: [],
styles: [{
value: 'button',
text: '按钮',
checked: true
},
{
value: 'text',
text: '文字'
}
],
colors: ['#333333', '#4cd964', '#dd524d'],
current: 0,
colorIndex: 0,
activeColor: '#108001',
styleType: 'text',
getWeek
}
},
onLoad(option) {
// 判断是否登录
this.openLogin()
// 加载数据
this.reload()
// if(option.isRefresh){
// this.isRefresh = true
// }
},
onShow(e) {
// 判断是否登录
this.openLogin()
this.reload()
},
// 触底函数
onReachBottom() {
const app = this
const {
where
} = this
if (app.canReset) {
app.where.page = ++where.page;
app.reload()
}
},
methods: {
reload() {
const app = this
const {
where,
userId
} = this
if (userId == 0) {
app.openLogin()
return;
}
// where.userId = userId;
uni.showLoading({
title: '数据读取中.'
})
app.loadMore = 'loading'
CouponApi.data().then(res => {
console.log('res: ',res);
app.items[0] = `待使用(${res.toBeUsed})`;
app.items[1] = `已使用(${res.used})`;
app.items[2] = `已失效(${res.invalid})`;
})
CouponApi.pageUserCoupon(where).then(res => {
const list = res.list.map(d => {
console.log(d);
return d;
});
if (app.list.length < res.count) {
console.log('11111: ', 11111);
app.list = app.list.concat(list)
app.canReset = true
app.loadMore = 'no-more'
} else {
app.canReset = false;
app.loadMore = 'no-more'
console.log('22222: ', 22222);
}
uni.hideLoading()
app.isRefresh = false
}).catch(() => {
uni.showToast({
title: '请检查您的网络.',
icon: 'none'
})
uni.hideLoading()
app.isRefresh = false
})
},
onClickItem(e) {
const app = this
const {
where,
userId
} = this
const index = e.currentIndex
if (this.current !== e.currentIndex) {
this.current = e.currentIndex
}
if (userId == 0) {
app.openLogin()
return;
}
// 全部
app.where.status = index;
this.where.page = 1;
this.list = [];
this.reload()
},
openUrl(url) {
uni.navigateTo({
url
})
},
toPay(orderId) {
uni.navigateTo({
url: '/package/booking/confirm?id=' + orderId
})
},
closeOrder(item) {
uni.showModal({
title: '确定取消此订单?',
success(o) {
if (o.confirm) {
OrderApi.updateOrder({
orderStatus: 2,
orderId: item.orderId
}).then(msg => {
uni.showToast({
title: msg,
icon: 'none'
})
item.orderStatus = 2;
}).catch(() => {
uni.showToast({
title: '请检查您的网络.',
icon: 'none'
})
uni.hideLoading()
})
}
}
});
},
// 弹出登录提示框
async openLogin() {
this.userId = uni.getStorageSync('user_id');
if (!this.userId) {
this.$refs.login.open('bottom')
return false;
}
}
}
}
</script>
<style lang="scss">
.content {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
justify-content: center;
align-items: center;
height: 150px;
text-align: center;
}
.segmented {
padding: 0 12rpx;
}
.content-text {
font-size: 14px;
color: #666;
}
.color-tag {
width: 25px;
height: 25px;
}
.uni-list {
flex: 1;
}
.coupon {
.coupon-item {
width: 700rpx;
margin: 20rpx auto;
border-radius: 12rpx;
border-bottom: 1px #eee solid;
background: #fff;
.coupon-bg {
width: 140rpx;
height: 140rpx;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 26rpx;
color: #fff;
border-radius: 12rpx 0 0 12rpx;
background: linear-gradient(to right, #70b915, #008e04);
.price {
font-size: 50rpx;
}
}
.coupon-info {
padding: 20rpx;
display: flex;
justify-content: space-between;
.title{
line-height: 2rem;
}
}
.save-btn{
// margin-right: 20rpx;
}
.merchant-avatar {
margin-right: 12rpx;
}
.merchant-name {
// padding-left: 12rpx;
}
.btn-status {
font-size: 30rpx;
display: flex;
}
}
.order-body {
padding: 16px 0;
}
}
.ele-flex {
display: flex;
justify-content: space-between;
}
.card-actions {
display: flex;
flex-direction: row;
justify-content: flex-end;
align-items: center;
height: 45px;
border-top: 1px #eee solid;
}
.card-actions-item {
display: flex;
flex-direction: row;
align-items: center;
}
.card-actions-item-text {
font-size: 12px;
color: #666;
margin-left: 5px;
}
.close {
top: 60rpx !important;
}
.total-price {
display: flex;
flex-direction: column;
justify-content: flex-start;
font-size: 30rpx;
align-items: flex-start;
padding-left: 6rpx;
margin-left: 450rpx;
.web-text-heading {
font-size: 30rpx !important;
}
}
</style>
+259
View File
@@ -0,0 +1,259 @@
<template>
<view class="page">
<!-- 其他功能 -->
<uni-card :border="false" :is-shadow="false" :padding="0">
<view class="order-body web-cell web-cell-align-top">
<view class="web-cell-content">
<uv-cell-group :customStyle="{ backgroundColor: '#ffffff' }" :border="false">
<block v-for="(item, index) in list" :key="index">
<uv-cell :cellStyle="{ padding: '10px 0' }" :title="item.name" :label="item.phone">
<template v-slot:right-icon>
<uv-icon size="40rpx" name="trash" @click="onDel(item)"></uv-icon>
</template>
</uv-cell>
</block>
</uv-cell-group>
</view>
</view>
</uni-card>
<view class="btn-bar">
<uv-button
class="save-user-profile"
:customStyle="{ background: 'linear-gradient(to right, #70b915, #008e04)', borderRadius: '30px', color: '#ffffff' }"
text="添加"
@click="add"
></uv-button>
</view>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
<!-- EmergencyEdit弹窗 -->
<uni-popup ref="addForm" type="center" border-radius="10px 10px 0 0">
<uni-card title="添加紧急联系人" :border="false" :is-shadow="false" :padding="'10px 6px'">
<uni-forms ref="form" :modelValue="form" :rules="rules" :label-width="80">
<uni-forms-item label="姓名" name="name">
<uv-input placeholder="请输入姓名" v-model="form.name" maxlength="11" :customStyle="{ margin: '10px 0' }"></uv-input>
</uni-forms-item>
<uni-forms-item label="手机号码" name="phone">
<uv-input placeholder="请输入手机号码" v-model="form.phone" maxlength="11" :customStyle="{ margin: '10px 0' }"></uv-input>
</uni-forms-item>
<uv-button
class="add-address"
:customStyle="{ background: 'linear-gradient(to right, #70b915, #008e04)', borderRadius: '30px', color: '#ffffff' }"
text="保存"
@click="submit"
></uv-button>
</uni-forms>
</uni-card>
</uni-popup>
</view>
</template>
<script>
import { useUserStore } from '@/store/modules/user';
import * as Api from '@/api/booking/emergency';
import * as MpMenuApi from '@/api/cms/mp-menu/index';
import { getWxOpenId } from '@/api/passport/login';
import { openUrl } from '@/utils/common';
import { useTenantStore } from '@/store/modules/tenant';
const tenantStore = useTenantStore();
const userStore = useUserStore();
export default {
data() {
return {
list: [],
statusBarHeight: 104,
isLogin: false,
form: {
name: '',
phone: ''
},
rules: {
// 对name字段进行必填验证
name: {
rules: [
{
required: true,
errorMessage: '请输入姓名'
},
{
minLength: 2,
maxLength: 10,
errorMessage: '输入的姓名不正确'
}
]
},
// 对email字段进行必填验证
phone: {
rules: [
{
required: true,
errorMessage: '请输入手机号码'
}
]
}
},
fields: {},
logo: '',
bookingUser: {},
server: [],
order: []
};
},
onLoad() {
this.reload();
},
methods: {
async reload(e) {
const app = this;
// 当前登录用户信息
const userInfo = await userStore.fetchUserInfo();
if (Object.keys(userInfo).length > 0) {
app.isLogin = true;
app.userInfo = userInfo;
} else {
app.isLogin = false;
}
// 获取联系人列表
Api.pageEmergency({
userId: userInfo.userId
}).then((res) => {
app.list = res.list;
});
},
navTo(item) {
if (!this.isLogin) {
this.$refs.login.open('bottom');
return false;
}
openUrl(item);
},
// 弹出登录提示框
openLogin() {
if (!this.isLogin) {
this.$refs.login.open('bottom');
return false;
}
},
add() {
this.$refs.addForm.open('center');
},
onDel(item) {
const app = this;
uni.showModal({
title: '确定要删除吗?',
success(o) {
if (o.confirm) {
uni.showLoading({
title: '请求中.'
});
Api.removeEmergency(item.emergencyId).then((res) => {
uni.showToast({
title: '操作成功',
icon: 'none'
});
});
app.reload();
}
}
});
},
// 触发提交表单
submit() {
this.$refs.form
.validate()
.then((res) => {
Api.addEmergency(this.form)
.then((msg) => {
uni.showToast({
title: msg,
icon: 'none'
});
this.$refs.addForm.close();
this.reload();
})
.catch(() => {
uni.showToast({
title: '请检查您的网络.',
icon: 'none'
});
uni.hideLoading();
this.$refs.addForm.close();
this.reload();
});
})
.catch((err) => {
console.log('表单错误信息:', err);
});
}
}
};
</script>
<style>
page {
background-size: 100%;
background-repeat: no-repeat;
background-color: #f0f2f5;
width: 750rpx;
overflow-x: hidden;
}
</style>
<style lang="scss">
.avatar {
padding: 20px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 14px;
}
.save-user-profile {
width: 700rpx;
margin: 40rpx auto;
}
.add-emergency {
width: 500rpx !important;
margin: 40rpx auto;
}
.btn-bar {
width: 700rpx;
left: 25rpx;
position: fixed;
bottom: 30rpx;
margin: auto;
clear: both;
}
.add-address {
width: 600rpx !important;
margin: 40rpx auto;
}
.btn-bar {
width: 700rpx;
left: 25rpx;
position: fixed;
bottom: 30rpx;
margin: auto;
clear: both;
}
.title-bar {
display: flex;
.web-text-heading {
margin-right: 20rpx;
}
.web-text-secondary {
margin-right: 20rpx;
}
}
</style>
+203
View File
@@ -0,0 +1,203 @@
<template>
<view class="page">
<!-- 其他功能 -->
<uni-card :border="false" :is-shadow="false" :padding="0">
<view class="order-body web-cell web-cell-align-top">
<view class="web-cell-content">
<uv-cell-group :customStyle="{backgroundColor: '#ffffff'}" :border="false">
<block v-for="(item,index) in list" :key="index">
<uv-cell :cellStyle="{padding: '10px 0'}" :title="item.name" :label="item.phone">
<template v-slot:right-icon>
<uv-icon size="40rpx" name="trash" @click="onDel(item)"></uv-icon>
</template>
</uv-cell>
</block>
</uv-cell-group>
</view>
</view>
</uni-card>
<view class="btn-bar">
<uv-button class="save-user-profile"
:customStyle="{background: 'linear-gradient(to right, #70b915, #008e04)',borderRadius: '30px',color: '#ffffff'}"
text="添加" @click="add"></uv-button>
</view>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
<!-- EmergencyEdit弹窗 -->
<uni-popup ref="addForm" type="center" border-radius="10px 10px 0 0">
<uni-card title="添加联系人" :border="false" :is-shadow="false" :padding="0">
<uv-form labelPosition="left" :model="form" :rules="rules" ref="form">
<uv-form-item label="姓名" prop="userInfo.name" borderBottom>
<uv-input placeholder="请输入姓名" v-model="form.name" maxlength="11"
:customStyle="{margin: '10px 0'}"></uv-input>
</uv-form-item>
<uv-form-item label="性别" prop="userInfo.sex" borderBottom @click="showSexSelect">
<uv-input placeholder="请输入手机号码" v-model="form.phone" maxlength="11"
:customStyle="{margin: '10px 0'}"></uv-input>
</uv-form-item>
<uv-button class="add-emergency"
:customStyle="{background: 'linear-gradient(to right, #70b915, #008e04)',borderRadius: '30px',color: '#ffffff'}"
text="保存" @click="save"></uv-button>
</uv-form>
</uni-card>
</uni-popup>
</view>
</template>
<script>
import {
useUserStore
} from '@/store/modules/user';
import * as Api from '@/api/booking/emergency';
import * as MpMenuApi from '@/api/cms/mp-menu/index';
import {
getWxOpenId
} from '@/api/passport/login';
import {
openUrl
} from '@/utils/common';
import {
useTenantStore
} from '@/store/modules/tenant';
const tenantStore = useTenantStore();
const userStore = useUserStore();
export default {
data() {
return {
list: [],
statusBarHeight: 104,
isLogin: false,
form: {
name: '',
phone: ''
},
fields: {},
logo: '',
bookingUser: {},
server: [],
order: [],
}
},
onLoad() {
this.reload()
},
methods: {
async reload(e) {
const app = this
// 当前登录用户信息
const userInfo = await userStore.fetchUserInfo();
if (Object.keys(userInfo).length > 0) {
app.isLogin = true
app.userInfo = userInfo
} else {
app.isLogin = false
}
// 获取联系人列表
Api.pageEmergency({
userId: userInfo.userId
}).then(res => {
app.list = res.list;
})
},
navTo(item) {
if (!this.isLogin) {
this.$refs.login.open('bottom')
return false;
}
openUrl(item);
},
// 弹出登录提示框
openLogin() {
if (!this.isLogin) {
this.$refs.login.open('bottom')
return false;
}
},
add() {
this.$refs.addForm.open('center')
},
onDel(item) {
const app = this
uni.showModal({
title: '确定要删除吗?',
success(o) {
if (o.confirm) {
uni.showLoading({
title: '请求中.'
})
Api.removeEmergency(item.emergencyId).then(res => {
uni.showToast({
title: '操作成功',
icon: 'none'
})
})
app.reload()
}
}
});
},
save() {
Api.addEmergency(this.form).then(msg => {
uni.showToast({
title: msg,
icon: 'none'
})
this.$refs.addForm.close()
this.reload()
}).catch(() => {
uni.showToast({
title: '请检查您的网络.',
icon: 'none'
})
uni.hideLoading()
this.$refs.addForm.close()
this.reload()
})
}
}
}
</script>
<style>
page {
background-size: 100%;
background-repeat: no-repeat;
background-color: #f0f2f5;
width: 750rpx;
overflow-x: hidden;
}
</style>
<style lang="scss">
.avatar {
padding: 20px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 14px;
}
.save-user-profile {
width: 700rpx;
margin: 40rpx auto;
}
.add-emergency {
width: 500rpx !important;
margin: 40rpx auto;
}
.btn-bar {
width: 700rpx;
left: 25rpx;
position: fixed;
bottom: 30rpx;
margin: auto;
clear: both;
}
</style>
+224
View File
@@ -0,0 +1,224 @@
<template>
<view class="page">
<!-- 其他功能 -->
<view class="ic-card-body web-cell web-cell-align-top">
<view class="web-cell-content"></view>
</view>
<uni-card title="卡片信息" :border="false" :is-shadow="false" :padding="'10px 6px'">
<uni-forms ref="form" :modelValue="formData" :rules="rules" :label-width="80">
<uni-forms-item label="卡号" name="careId" required>
<uv-input placeholder="请输入您的IC卡号" v-model="formData.careId" maxlength="20"></uv-input>
</uni-forms-item>
<uni-forms-item label="姓名" name="name" required>
<uv-input placeholder="请输入您的姓名" v-model="formData.name" maxlength="6"></uv-input>
</uni-forms-item>
<uni-forms-item label="手机号码" name="phone" required>
<uv-input placeholder="请输入您的手机号码" v-model="formData.phone" maxlength="11"></uv-input>
</uni-forms-item>
</uni-forms>
</uni-card>
<view class="card-desc web-text-secondary">
<view>温馨提示</view>
<view>1、请输入卡号和姓名及手机号码进行激活</view>
<view>2、如果忘记用户信息,请先联系场馆</view>
</view>
<view class="btn-bar">
<uv-button
class="save-user-profile"
:customStyle="{ background: 'linear-gradient(to right, #70b915, #008e04)', borderRadius: '30px', color: '#ffffff' }"
text="立即激活"
@click="submit"
></uv-button>
</view>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
<!-- EmergencyEdit弹窗 -->
<uni-popup ref="addForm" type="center" border-radius="10px 10px 0 0">
<uni-card title="添加联系人" :border="false" :is-shadow="false" :padding="0">
<uv-form labelPosition="left" :model="form" :rules="rules" ref="form">
<uv-form-item label="姓名" prop="userInfo.name" borderBottom>
<uv-input placeholder="请输入姓名" v-model="form.name" maxlength="11" :customStyle="{ margin: '10px 0' }"></uv-input>
</uv-form-item>
<uv-form-item label="性别" prop="userInfo.sex" borderBottom @click="showSexSelect">
<uv-input placeholder="请输入手机号码" v-model="form.phone" maxlength="11" :customStyle="{ margin: '10px 0' }"></uv-input>
</uv-form-item>
<uv-button
class="add-emergency"
:customStyle="{ background: 'linear-gradient(to right, #70b915, #008e04)', borderRadius: '30px', color: '#ffffff' }"
text="保存"
@click="save"
></uv-button>
</uv-form>
</uni-card>
</uni-popup>
</view>
</template>
<script>
import { useUserStore } from '@/store/modules/user';
import * as Api from '@/api/booking/emergency';
import * as MpMenuApi from '@/api/cms/mp-menu/index';
import { getWxOpenId } from '@/api/passport/login';
import { openUrl } from '@/utils/common';
import { useTenantStore } from '@/store/modules/tenant';
import { pad } from 'crypto-js';
const tenantStore = useTenantStore();
const userStore = useUserStore();
export default {
data() {
return {
list: [],
statusBarHeight: 104,
isLogin: false,
form: {
name: '',
phone: ''
},
// 表单数据
formData: {},
fields: {},
logo: '',
bookingUser: {},
server: [],
order: []
};
},
onLoad() {
this.reload();
},
methods: {
async reload(e) {
const app = this;
// 当前登录用户信息
const userInfo = await userStore.fetchUserInfo();
if (Object.keys(userInfo).length > 0) {
app.isLogin = true;
app.userInfo = userInfo;
} else {
app.isLogin = false;
}
// 获取联系人列表
// Api.pageEmergency({
// userId: userInfo.userId
// }).then((res) => {
// app.list = res.list;
// });
},
navTo(item) {
if (!this.isLogin) {
this.$refs.login.open('bottom');
return false;
}
openUrl(item);
},
// 弹出登录提示框
openLogin() {
if (!this.isLogin) {
this.$refs.login.open('bottom');
return false;
}
},
add() {
this.$refs.addForm.open('center');
},
onDel(item) {
const app = this;
uni.showModal({
title: '确定要删除吗?',
success(o) {
if (o.confirm) {
uni.showLoading({
title: '请求中.'
});
// Api.removeEmergency(item.emergencyId).then((res) => {
// uni.showToast({
// title: '操作成功',
// icon: 'none'
// });
// });
app.reload();
}
}
});
},
// 触发提交表单
submit() {
this.$refs.form.validate().then(res => {
// const saveOrUpdate = this.formData.id ? Api.updateICCard : Api.addICCard
// saveOrUpdate(this.formData).then(message => {
// uni.showToast({
// title: '保存成功',
// icon: 'success'
// })
// this.$refs.addForm.close()
// this.reload()
// }).catch((err) => {
// console.log(err);
// })
// console.log('表单数据信息:', res);
}).catch(err => {
console.log('表单错误信息:', err);
})
},
}
};
</script>
<style>
page {
background-size: 100%;
background-repeat: no-repeat;
background-color: #f0f2f5;
width: 750rpx;
overflow-x: hidden;
}
</style>
<style lang="scss">
.ic-card-body {
width: 692rpx;
margin: 20rpx auto;
height: 450rpx;
border-radius: 20rpx;
background: url('https://oss.wsdns.cn/20240528/a0a2eaa6073041bcb8ef182b87efe00a.jpg?x-oss-process=image/resize,m_fixed,w_750/quality,Q_90');
background-size: 100%;
}
.card-desc{
padding: 20rpx 40rpx;
line-height: 1.4rem;
font-size:24rpx;
}
.avatar {
padding: 20px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 14px;
}
.save-user-profile {
width: 700rpx;
margin: 40rpx auto;
}
.add-emergency {
width: 500rpx !important;
margin: 40rpx auto;
}
.btn-bar {
width: 700rpx;
left: 25rpx;
position: fixed;
bottom: 30rpx;
margin: auto;
clear: both;
}
</style>
+192
View File
@@ -0,0 +1,192 @@
<template>
<view class="page">
<!-- 其他功能 -->
<uni-card :border="false" :is-shadow="false" :padding="0">
<view class="order-body web-cell web-cell-align-top">
<view class="web-cell-content">
<view class="integral-bar web-cell web-cell-content">
<text class="web-text-placeholder">当前积分</text>
<text class="integral web-text-heading">{{ userInfo.points }}</text>
</view>
<view class="sign-in-btn">
<uv-button class="btn" :disabled="todaySign"
:customStyle="{background: 'linear-gradient(to right, #70b915, #008e04)',borderRadius: '30px',color: '#ffffff'}"
text="签到" @click="onSign"></uv-button>
</view>
</view>
</view>
</uni-card>
<!-- 日历 -->
<uni-calendar class="uni-calendar--hook" :selected="selected" :showMonth="true" @monthSwitch="onMonthSwitch" />
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
</view>
</template>
<script>
import {
useUserStore
} from '@/store/modules/user';
import * as Api from '@/api/booking/integral';
import {
getWxOpenId
} from '@/api/passport/login';
import {
openUrl
} from '@/utils/common';
import * as UserApi from '@/api/system/user'
import {
useTenantStore
} from '@/store/modules/tenant';
const tenantStore = useTenantStore();
const userStore = useUserStore();
const currentDate = new Date();
const currentMonth = currentDate.getFullYear() + '-' + (currentDate.getMonth() + 1).toString().padStart(2, '0');
export default {
data() {
return {
userInfo: {},
list: [],
statusBarHeight: 104,
isLogin: false,
form: {
name: '',
phone: ''
},
dateTime: currentMonth,
fields: {},
logo: '',
bookingUser: {},
server: [],
order: [],
showCalendar: false,
selected: [],
todaySign: false
}
},
onLoad() {
this.reload()
},
onReady() {
this.$nextTick(() => {
this.showCalendar = true
})
},
methods: {
async reload(e) {
const app = this
const { dateTime } = this
// uni.showLoading({
// title: '请求中.'
// })
// 当前登录用户信息
const userInfo = await userStore.fetchUserInfo();
if (Object.keys(userInfo).length > 0) {
app.isLogin = true
app.userInfo = userInfo
} else {
app.isLogin = false
}
// 获取积分明细
Api.getSignData({
dateTime
}).then(res => {
uni.hideLoading()
if (res.message == '您今天已经签到过了') {
app.todaySign = true
}
app.selected = []
res.data.map(d => {
app.selected.push({
date: d.dateTime,
info: '已签到'
})
})
})
},
navTo(item) {
if (!this.isLogin) {
this.$refs.login.open('bottom')
return false;
}
openUrl(item);
},
// 弹出登录提示框
openLogin() {
if (!this.isLogin) {
this.$refs.login.open('bottom')
return false;
}
},
onSign() {
const app = this
app.openLogin()
app.todaySign = true
Api.addIntegral({}).then(res => {
UserApi.updatePointsBySign()
app.userInfo.points++
uni.showToast({
title: '签到成功',
icon: 'success'
})
setTimeout(() => {
app.reload()
},1000)
}).catch((err) => {
// uni.showToast({
// title: err.message,
// icon: 'none'
// })
})
this.$forceUpdate();
},
onMonthSwitch(e) {
this.dateTime = e.year + "-" + e.month.toString().padStart(2, '0')
this.reload()
}
}
}
</script>
<style>
page {
background: url('https://oss.wsdns.cn/20240502/75fc744657544a38a32f83a825688286.png') no-repeat;
background-size: 100%;
background-repeat: no-repeat;
background-color: #f0f2f5;
width: 750rpx;
overflow-x: hidden;
}
</style>
<style lang="scss">
.integral-bar {
flex-direction: column;
padding: 30rpx 0;
.integral {
font-size: 50rpx;
line-height: 2rem;
}
}
.sign-in-btn {
margin-bottom: 30rpx;
.btn {
width: 200rpx;
margin: auto;
margin-bottom: 50rpx;
}
}
</style>
+268
View File
@@ -0,0 +1,268 @@
<template>
<view class="page">
<uni-card :border="false" :is-shadow="false" :padding="20">
<uni-forms ref="form" :modelValue="formData" :rules="rules" label-position="top">
<uni-forms-item label="抬头类型" name="isCompany">
<uni-data-checkbox v-model="formData.isCompany" :localdata="type" />
</uni-forms-item>
<block v-if="formData.isCompany == 0">
<uni-forms-item label="名称" name="name" required>
<uv-input class="input" v-model="formData.name" type="text" placeholder="真实姓名(必填)" />
</uni-forms-item>
<uni-forms-item label="手机号码" name="phone" required>
<uv-input class="input" v-model="formData.phone" type="text" placeholder="手机号码" />
</uni-forms-item>
<uni-forms-item label="电子邮箱" name="email" required>
<uv-input class="input" v-model="formData.email" type="text" placeholder="电子邮箱" />
</uni-forms-item>
</block>
<block v-if="formData.isCompany == 1">
<uni-forms-item label="名称" name="name" required>
<uv-input class="input" v-model="formData.name" type="text" placeholder="单位名称(必填)" />
</uni-forms-item>
<uni-forms-item label="税号" name="invoiceCode" required>
<uv-input class="input" v-model="formData.invoiceCode" type="text" placeholder="纳税人识别号(必填)" />
</uni-forms-item>
<uni-forms-item label="手机号码" name="phone" required>
<uv-input class="input" v-model="formData.phone" type="text" placeholder="手机号码" />
</uni-forms-item>
<uni-forms-item label="电子邮箱" name="email" required>
<uv-input class="input" v-model="formData.email" type="text" placeholder="电子邮箱" />
</uni-forms-item>
<uni-forms-item label="开户行" name="bankName" required>
<uv-input class="input" v-model="formData.bankName" type="text" placeholder="开户银行名称" />
</uni-forms-item>
<uni-forms-item label="银行账号" name="bankAccount" required>
<uv-input class="input" v-model="formData.bankAccount" type="text" placeholder="开户银行账号" />
</uni-forms-item>
<uni-forms-item label="单位地址" name="address" required>
<uv-input class="input" v-model="formData.address" type="text" placeholder="单位地址" />
</uni-forms-item>
<uni-forms-item label="单位电话" name="tel" required>
<uv-input class="input" v-model="formData.tel" type="text" placeholder="单位电话" />
</uni-forms-item>
<uni-forms-item label="备注" name="comments">
<uv-textarea v-model="formData.comments" placeholder="请输入备注信息" auto-height></uv-textarea>
</uni-forms-item>
</block>
<uv-button
class="add-emergency"
:customStyle="{ background: 'linear-gradient(to right, #70b915, #008e04)', borderRadius: '30px', color: '#ffffff' }"
text="保存"
@click="submit"
></uv-button>
</uni-forms>
</uni-card>
</view>
</template>
<script>
import { useUserStore } from '@/store/modules/user';
import * as Api from '@/api/booking/userInvoice';
import { openUrl } from '@/utils/common';
import { useTenantStore } from '@/store/modules/tenant';
const tenantStore = useTenantStore();
const userStore = useUserStore();
export default {
data() {
return {
list: [],
statusBarHeight: 104,
isLogin: false,
fields: {},
logo: '',
bookingUser: {},
server: [],
order: [],
// 表单数据
formData: {
type: 0,
invoiceType: 0
},
// 发票类型
type: [
{
text: '个人',
value: 0
},
{
text: '单位',
value: 1
}
],
// 开票类型
invoiceType: [
{
text: '普票',
value: 0
},
{
text: '专票',
value: 1
}
],
rules: {
// 对name字段进行必填验证
name: {
rules: [
{
required: true,
errorMessage: '请输入开票名称'
}
]
},
// 对email字段进行必填验证
email: {
rules: [
{
format: 'email',
errorMessage: '请输入正确的邮箱地址'
}
]
}
}
};
},
onLoad() {
this.reload();
},
methods: {
async reload() {
const app = this;
// 当前登录用户信息
const userInfo = await userStore.fetchUserInfo();
if (Object.keys(userInfo).length > 0) {
app.isLogin = true;
app.userInfo = userInfo;
} else {
app.isLogin = false;
}
// 读取最后一次
Api.pageUserInvoice({
userId: userInfo.userId,
limit: 1
}).then((res) => {
if (res.count > 0 && !app.formData.id) {
app.formData = res.list[0];
}
});
},
navTo(item) {
if (!this.isLogin) {
this.$refs.login.open('bottom');
return false;
}
openUrl(item);
},
// 弹出登录提示框
openLogin() {
if (!this.isLogin) {
this.$refs.login.open('bottom');
return false;
}
},
add() {
this.$refs.addForm.open('center');
},
onDel(item) {
const app = this;
uni.showModal({
title: '确定要删除吗?',
success(o) {
if (o.confirm) {
uni.showLoading({
title: '请求中.'
});
Api.removeUserInvoice(item.id).then((res) => {
uni.showToast({
title: '操作成功',
icon: 'none'
});
});
app.reload();
}
}
});
},
/**
* 复写 binddata 方法,如果只是为了校验,无复杂自定义操作,可忽略此方法
* @param {String} name 字段名称
* @param {String} value 表单域的值
*/
// binddata(name,value){
// // 通过 input 事件设置表单指定 name 的值
// this.$refs.form.setValue(name, value)
// },
// 触发提交表单
submit() {
this.$refs.form
.validate()
.then((res) => {
const saveOrUpdate = this.formData.id ? Api.updateUserInvoice : Api.addUserInvoice;
saveOrUpdate(this.formData)
.then((message) => {
uni.showToast({
title: '保存成功',
icon: 'success'
});
setTimeout(() => {
uni.navigateBack({
delta: 2
})
},1000)
})
.catch((err) => {
console.log(err);
});
console.log('表单数据信息:', res);
})
.catch((err) => {
console.log('表单错误信息:', err);
});
}
}
};
</script>
<style>
page {
background-size: 100%;
background-repeat: no-repeat;
background-color: #f0f2f5;
width: 750rpx;
overflow-x: hidden;
}
</style>
<style lang="scss">
.avatar {
padding: 20px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 14px;
}
.save-user-profile {
width: 700rpx;
margin: 40rpx auto;
}
.add-emergency {
width: 500rpx !important;
margin: 40rpx auto;
}
.btn-bar {
width: 700rpx;
left: 25rpx;
position: fixed;
bottom: 30rpx;
margin: auto;
clear: both;
}
</style>
+194
View File
@@ -0,0 +1,194 @@
<template>
<view class="container">
<image class="responsive-image" :src="imgUrls" mode="widthFix" @click="onDown(pdfUrl)"></image>
<uv-button @click="onDown(pdfUrl)">复制发票链接</uv-button>
</view>
</template>
<script>
// import { useUserStore } from '@/store/modules/user';
import * as Api from '@/api/booking/userInvoice';
import { copyText, openUrl } from '@/utils/common';
// import { useTenantStore } from '@/store/modules/tenant';
// const tenantStore = useTenantStore();
// const userStore = useUserStore();
export default {
data() {
return {
isLogin: false,
logo: '',
imgUrls: '',
pdfUrl: ''
};
},
onLoad(e) {
this.reload(e.id);
},
methods: {
async reload(orderNo) {
const app = this;
// 当前登录用户信息
// const userInfo = await userStore.fetchUserInfo();
// if (Object.keys(userInfo).length > 0) {
// app.isLogin = true;
// app.userInfo = userInfo;
// } else {
// app.isLogin = false;
// }
// 读取最后一次
await Api.showInvoice(orderNo).then((res) => {
if (res) {
const json = JSON.parse(res);
if (json.code) {
const result = json.result;
console.log('json: ', json);
console.log('json: ', json.code);
console.log('result: ', result);
if (result.length > 0) {
app.imgUrls = result[0].imgUrls;
app.pdfUrl = result[0].pdfUrl;
}
}
}
});
},
navTo(item) {
if (!this.isLogin) {
this.$refs.login.open('bottom');
return false;
}
openUrl(item);
},
// 弹出登录提示框
openLogin() {
if (!this.isLogin) {
this.$refs.login.open('bottom');
return false;
}
},
onDown(text) {
const app = this;
// 复制发票
console.log(text);
uni.setClipboardData({
data: app.pdfUrl,
success: function () {
console.log('success');
},
complete: function (res) {
console.log(1, res);
}
});
uni.getClipboardData({
success: function (res) {
console.log(2, res.data);
},
complete: function (res) {
console.log(3, res);
}
});
//
// wx.setClipboardData({
// data: 'data',
// success(res) {
// console.log('复制发票333: ',res);
// wx.getClipboardData({
// success(res) {
// console.log(res.data); // data
// }
// });
// }
// });
console.log('复制发票222', app.pdfUrl);
// uniCopy({
// content: `${app.pdfUrl}`,
// success: (res) => {
// uni.showToast({
// title: res,
// icon: 'none'
// });
// },
// error: (e) => {
// uni.showToast({
// title: e,
// icon: 'none',
// duration: 3000
// });
// }
// });
// uni.setClipboardData({
// data: app.pdfUrl, //text是要复制的文本
// success: function (res) {
// console.log(res, '收拾收拾');
// uni.getClipboardData({
// //这个api是把拿到的数据放到剪切板中的
// success: function (res) {
// uni.showModal({
// title: '提示',
// content: '发票地址复制成功,请在浏览器中粘贴进行下载'
// });
// }
// });
// },
// error(e) {
// console.log('e: ', e);
// }
// });
// uni.downloadFile({
// url: this.pdfUrl,
// success: (res) => {
// if (res.statusCode === 200) {
// var tempFilePath = res.tempFilePath;
// app.saveFile(tempFilePath);
// console.log('下载成功');
// }
// }
// });
},
saveFile(tempFilePath) {
//保存到本地
//文件保存到本地
uni.saveFile({
tempFilePath: tempFilePath, //临时路径
success: function (res) {
uni.showToast({
icon: 'none',
mask: true,
title: '文件已保存:' + res.savedFilePath, //保存路径
duration: 3000
});
setTimeout(() => {
//打开文档查看
uni.openDocument({
filePath: res.savedFilePath,
success: function (res) {
// console.log('打开文档成功');
}
});
}, 3000);
}
});
}
}
};
</script>
<style lang="scss">
.container {
width: 100%; /* 确保容器宽度为100% */
}
.responsive-image {
width: 750rpx; /* 图片宽度自适应容器宽度 */
height: auto; /* 图片高度自适应宽度保持比例 */
display: block; /* 避免图片下方出现空白 */
max-width: 100%; /* 最大宽度不超过父容器宽度 */
/* 可以设置最大高度限制,防止图片过高 */
// max-height: 300px; /* 根据需要设置最大高度 */
margin-bottom: 10px;
}
</style>
+293
View File
@@ -0,0 +1,293 @@
<template>
<view class="page">
<uni-card :border="false" :is-shadow="false">
<uv-cell
:title="`${formData.name ? formData.name : '请填写开票信息'}`"
:label="`${formData.isCompany == 1 ? '单位' : '个人'}`"
:cellStyle="{ padding: '5px 0' }"
:border="false"
@click="editInvoice"
>
<template v-slot:right-icon>
<uv-icon name="arrow-right"></uv-icon>
</template>
</uv-cell>
</uni-card>
<uni-card v-if="formData.name" :border="false" :is-shadow="false" :padding="20">
<uni-forms ref="form" :modelValue="formData" :rules="rules" :label-width="100" label-position="left">
<uni-forms-item label="发票类型" name="type">
<uni-data-checkbox v-model="formData.type" :localdata="type" />
</uni-forms-item>
<uni-forms-item label="开票类型" name="invoiceType">
<uni-data-checkbox v-model="formData.invoiceType" :localdata="invoiceType" />
</uni-forms-item>
<block v-if="formData.isCompany == 0">
<uni-forms-item label="名称" name="name" required>
<uv-input class="input" disabled v-model="formData.name" type="text" />
</uni-forms-item>
<uni-forms-item label="手机号码" name="phone" required>
<uv-input class="input" disabled v-model="formData.phone" type="text" placeholder="手机号码" />
</uni-forms-item>
<uni-forms-item label="电子邮箱" name="email" required>
<uv-input class="input" disabled v-model="formData.email" type="text" placeholder="电子邮箱" />
</uni-forms-item>
</block>
<block v-if="formData.isCompany == 1">
<uni-forms-item label="名称" name="name" required>
<uv-input class="input" v-model="formData.name" type="text" placeholder="单位名称(必填)" />
</uni-forms-item>
<uni-forms-item label="税号" name="invoiceCode" required>
<uv-input class="input" v-model="formData.invoiceCode" type="text" placeholder="纳税人识别号(必填)" />
</uni-forms-item>
<uni-forms-item label="手机号码" name="phone" required>
<uv-input class="input" v-model="formData.phone" type="text" placeholder="手机号码" />
</uni-forms-item>
<uni-forms-item label="电子邮箱" name="email" required>
<uv-input class="input" v-model="formData.email" type="text" placeholder="电子邮箱" />
</uni-forms-item>
<uni-forms-item label="开户行" name="bankName" required>
<uv-input class="input" v-model="formData.bankName" type="text" placeholder="开户银行名称" />
</uni-forms-item>
<uni-forms-item label="银行账号" name="bankAccount" required>
<uv-input class="input" v-model="formData.bankAccount" type="text" placeholder="开户银行账号" />
</uni-forms-item>
<uni-forms-item label="单位地址" name="address" required>
<uv-input class="input" v-model="formData.address" type="text" placeholder="单位地址" />
</uni-forms-item>
<uni-forms-item label="单位电话" name="tel" required>
<uv-input class="input" v-model="formData.tel" type="text" placeholder="单位电话" />
</uni-forms-item>
<uni-forms-item label="备注" name="comments">
<uv-textarea v-model="formData.comments" placeholder="请输入备注信息" auto-height></uv-textarea>
</uni-forms-item>
</block>
<uv-button
class="add-emergency"
:customStyle="{ background: 'linear-gradient(to right, #70b915, #008e04)', borderRadius: '30px', color: '#ffffff' }"
text="确认开票"
@click="submit"
></uv-button>
</uni-forms>
</uni-card>
</view>
</template>
<script>
import { useUserStore } from '@/store/modules/user';
import * as Api from '@/api/booking/userInvoice';
import { openUrl } from '@/utils/common';
import { useTenantStore } from '@/store/modules/tenant';
const tenantStore = useTenantStore();
const userStore = useUserStore();
export default {
data() {
return {
orderId: 0,
list: [],
statusBarHeight: 104,
isLogin: false,
fields: {},
logo: '',
bookingUser: {},
server: [],
order: [],
// 表单数据
formData: {
type: 0,
invoiceType: 0
},
// 发票类型
type: [
{
text: '电子',
value: 0
},
{
text: '纸质',
value: 1
}
],
// 开票类型
invoiceType: [
{
text: '普票',
value: 0
},
{
text: '专票',
value: 1
}
],
rules: {
// 对name字段进行必填验证
name: {
rules: [
{
required: true,
errorMessage: '请输入开票名称'
}
]
},
// 对email字段进行必填验证
email: {
rules: [
{
format: 'email',
errorMessage: '请输入正确的邮箱地址'
}
]
}
}
};
},
onLoad(e){
this.orderId = e.id
},
onShow() {
this.reload();
},
methods: {
async reload(e) {
const app = this;
// 当前登录用户信息
const userInfo = await userStore.fetchUserInfo();
if (Object.keys(userInfo).length > 0) {
app.isLogin = true;
app.userInfo = userInfo;
} else {
app.isLogin = false;
}
// 读取最后一次
Api.pageUserInvoice({
userId: userInfo.userId,
limit: 1
}).then((res) => {
if (res.count > 0 && !app.formData.id) {
app.formData = res.list[0];
app.formData.orderId = app.orderId
}
});
},
navTo(item) {
if (!this.isLogin) {
this.$refs.login.open('bottom');
return false;
}
openUrl(item);
},
// 弹出登录提示框
openLogin() {
if (!this.isLogin) {
this.$refs.login.open('bottom');
return false;
}
},
editInvoice(){
uni.navigateTo({
url: `/package/user/invoice-edit?id=${this.formData.id}`
})
},
add() {
this.$refs.addForm.open('center');
},
onDel(item) {
const app = this;
uni.showModal({
title: '确定要删除吗?',
success(o) {
if (o.confirm) {
uni.showLoading({
title: '请求中.'
});
Api.removeUserInvoice(item.id).then((res) => {
uni.showToast({
title: '操作成功',
icon: 'none'
});
});
app.reload();
}
}
});
},
/**
* 复写 binddata 方法,如果只是为了校验,无复杂自定义操作,可忽略此方法
* @param {String} name 字段名称
* @param {String} value 表单域的值
*/
// binddata(name,value){
// // 通过 input 事件设置表单指定 name 的值
// this.$refs.form.setValue(name, value)
// },
// 触发提交表单
submit() {
const { formData } = this
this.$refs.form
.validate()
.then((res) => {
Api.doInvoice(formData)
.then((message) => {
console.log('message: ',message);
uni.showToast({
title: '开票成功',
icon: 'success'
});
setTimeout(() => {
uni.navigateBack()
},1000)
})
.catch((err) => {
console.log(err);
});
console.log('表单数据信息:', res);
})
.catch((err) => {
console.log('表单错误信息:', err);
});
}
}
};
</script>
<style>
page {
background-size: 100%;
background-repeat: no-repeat;
background-color: #f0f2f5;
width: 750rpx;
overflow-x: hidden;
}
</style>
<style lang="scss">
.avatar {
padding: 20px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 14px;
}
.save-user-profile {
width: 700rpx;
margin: 40rpx auto;
}
.add-emergency {
width: 500rpx !important;
margin: 40rpx auto;
}
.btn-bar {
width: 700rpx;
left: 25rpx;
position: fixed;
bottom: 30rpx;
margin: auto;
clear: both;
}
</style>
+200
View File
@@ -0,0 +1,200 @@
<template>
<view class="page">
<uni-card title="设置支付密码" :border="false" :is-shadow="false" :padding="'10px 6px'">
<uni-forms ref="form" :modelValue="form" :rules="rules" :label-width="90">
<uni-forms-item label="支付密码" name="password" required>
<uv-code-input mode="box" :space="0" :maxlength="6" hairline v-model="form.password" dot @change="change" @finish="finish"></uv-code-input>
</uni-forms-item>
<uni-forms-item label="手机号码" name="phone" required>
<uv-input placeholder="手机号码" disabled v-model="userInfo.mobile" maxlength="11" border="bottom">
<!-- vue3模式下必须使用v-slot:suffix -->
<template v-slot:suffix>
<uv-code ref="uCode" @change="codeChange" :seconds="seconds" changeText="X秒重新获取"></uv-code>
<uv-button @click="getSmsCode" :text="tips" shape="circle"></uv-button>
</template>
</uv-input>
<!-- <uv-input placeholder="手机号码" disabled v-model="userInfo.mobile" maxlength="11"></uv-input> -->
</uni-forms-item>
<uni-forms-item label="短信验证码" name="code" required>
<uv-code-input mode="box" :space="0" :maxlength="6" hairline v-model="form.code" ></uv-code-input>
</uni-forms-item>
<uv-button class="submit-btn"
:customStyle="{background: 'linear-gradient(to right, #70b915, #008e04)',borderRadius: '30px',color: '#ffffff'}"
text="确定修改" @click="submit"></uv-button>
</uni-forms>
</uni-card>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
</view>
</template>
<script>
import * as Api from '@/api/shop/userAddress';
import * as MpMenuApi from '@/api/cms/mp-menu/index';
import { sendSmsCaptcha, updatePayPassword, getWxOpenId } from '@/api/passport/login';
import {
openUrl
} from '@/utils/common';
import {
useUserStore
} from '@/store/modules/user';
import {
useCarStore
} from '@/store/modules/car';
const userStore = useUserStore();
const carStore = useCarStore();
export default {
data() {
return {
list: [],
isLogin: false,
form: {
name: '',
phone: '',
code: '',
password: ''
},
tips: '点击获取',
logo: '',
userInfo: {},
rules: {
mobile: {
rules: [{
required: true,
format: 'number',
errorMessage: '请输入手机号码',
}]
},
password: {
rules: [{
required: true,
errorMessage: '请输入支付密码',
}]
},
code: {
rules: [{
required: true,
errorMessage: '请输入短信验证码',
}]
},
}
}
},
onLoad() {
this.reload()
},
onLoad() {
if(!this.isLogin){
this.reload()
}
},
methods: {
async reload(e) {
const app = this
// 当前登录用户信息
const userInfo = await userStore.fetchUserInfo();
if (Object.keys(userInfo).length > 0) {
app.isLogin = true
app.userInfo = userInfo
app.form.phone = userInfo.phone
} else {
app.isLogin = false
app.openLogin()
}
},
navTo(item) {
if (!this.isLogin) {
this.$refs.login.open('bottom')
return false;
}
openUrl(item);
},
// 弹出登录提示框
openLogin() {
if (!this.isLogin) {
this.$refs.login.open('bottom')
return false;
}
},
codeChange(text) {
this.tips = text;
},
getSmsCode() {
const {
phone
} = this.form
if (!phone || phone.length != 11) {
uni.showToast({
title: '请填写正确的手机号码',
icon: 'none'
})
return false;
}
if (this.$refs.uCode.canGetCode) {
sendSmsCaptcha({
phone
}).then(res => {
console.log('res: ', res);
})
// 模拟向后端请求验证码
uni.showLoading({
title: '正在获取验证码'
})
setTimeout(() => {
uni.hideLoading();
// 这里此提示会被this.start()方法中的提示覆盖
uni.showToast({
title: '验证码已发送'
});
// 通知验证码组件内部开始倒计时
this.$refs.uCode.start();
}, 1000);
} else {
uni.showToast({
title: '倒计时结束后再发送',
icon: 'none'
})
}
},
// 触发提交表单
submit() {
const { form } = this
this.$refs.form.validate().then(res => {
updatePayPassword(form).then(message => {
uni.showToast({
title: '设置成功',
icon: 'success'
})
setTimeout(() => {
uni.navigateBack()
}, 1500);
}).catch((err) => {
uni.showToast({
title: err.message,
icon: 'none'
})
})
}).catch(err => {
})
}
}
}
</script>
<style>
page {
background-size: 100%;
background-repeat: no-repeat;
background-color: #f0f2f5;
width: 750rpx;
overflow-x: hidden;
}
</style>
<style lang="scss">
.submit-btn {
width: 600rpx !important;
margin: 40rpx auto;
}
</style>
+205
View File
@@ -0,0 +1,205 @@
<template>
<view class="page" v-if="form">
<view class="flex justify-center"></view>
<button open-type="chooseAvatar" @chooseavatar="chooseAvatar" class="btn">
<uv-avatar :src="form.avatarUrl" size="100"></uv-avatar>
<text class="web-text-placeholder">更换头像</text>
</button>
<!-- 其他功能 -->
<uni-card :border="false" :is-shadow="false" :padding="0">
<view class="order-body web-cell-align-top">
<uv-form labelPosition="left" :model="form" :rules="rules" ref="form">
<uv-form-item prop="form.phone" borderBottom>
<uv-cell title="手机号码" :value="form.phone">
<template v-slot:value>
<uv-input placeholder="请输入手机号码" disabled v-model="form.phone" maxlength="11"></uv-input>
</template>
</uv-cell>
</uv-form-item>
<uv-form-item prop="form.realName" borderBottom>
<uv-cell title="真实姓名" :value="form.realName">
<template v-slot:value>
<uv-input placeholder="请输入真实姓名" v-model="form.realName" maxlength="11"></uv-input>
</template>
</uv-cell>
</uv-form-item>
<uv-form-item prop="form.idCard" borderBottom>
<uv-cell title="身份证号码" :value="form.idCard">
<template v-slot:value>
<uv-input placeholder="请输入身份证号" v-model="form.idCard" maxlength="18"></uv-input>
</template>
<!-- <template v-slot:right-icon>
<uv-icon size="40rpx" name="camera" @click="onIdCard(item)"></uv-icon>
</template> -->
</uv-cell>
</uv-form-item>
</uv-form>
</view>
</uni-card>
<view class="btn-bar">
<uv-button class="save-user-profile"
:customStyle="{background: 'linear-gradient(to right, #70b915, #008e04)',borderRadius: '30px',color: '#ffffff'}"
text="保存" @click="save"></uv-button>
</view>
<!-- 登录组件 -->
<ws-login ref="login" :logo="logo" @done="reload" />
</view>
</template>
<script>
import {
useUserStore
} from '@/store/modules/user';
import * as UserApi from '@/api/booking/users';
import * as MpMenuApi from '@/api/cms/mp-menu/index';
import {
getWxOpenId
} from '@/api/passport/login';
import {
openUrl
} from '@/utils/common';
import {
useTenantStore
} from '@/store/modules/tenant';
import {uploadOssByPath} from '@/api/system/file'
const tenantStore = useTenantStore();
const userStore = useUserStore();
export default {
data() {
return {
statusBarHeight: 104,
isLogin: false,
form: null,
userInfo: {},
fields: {},
logo: '',
bookingUser: {},
server: [],
order: [],
}
},
onLoad() {
this.reload()
},
methods: {
async reload(e) {
const app = this
// 当前登录用户信息
const userInfo = await userStore.fetchUserInfo();
if (Object.keys(userInfo).length > 0) {
app.isLogin = true
app.form = userInfo
// 获取用户副表信息
UserApi.getByPhone({
phone: userInfo.phone
}).then(data => {
if (data) {
app.form = Object.assign({}, app.form, data);
}
})
} else {
app.isLogin = false
app.form = {}
}
// 菜单数据
MpMenuApi.listMpMenu({}).then(res => {
app.server = res.filter(d => d.type == 0)
app.order = res.filter(d => d.type == 1)
})
},
navTo(item) {
if (!this.isLogin) {
this.$refs.login.open('bottom')
return false;
}
openUrl(item);
},
// 弹出登录提示框
openLogin() {
if (!this.isLogin) {
this.$refs.login.open('bottom')
return false;
}
},
async chooseAvatar({detail}) {
const url = detail.avatarUrl
this.form.avatarUrl = await uploadOssByPath(url)
UserApi.updateUsers({
uid: this.form.uid,
avatarUrl: `${this.form.avatarUrl}`
})
},
save() {
const app = this
const { form } = this
if(!uni.$uv.test.idCard(form.idCard)){
uni.showToast({
title: '请填写真实身份证号',
icon: 'none'
})
return false
}
UserApi.updateUsers({
phone: form.phone,
realName: form.realName,
idCard: form.idCard,
uid: form.uid
}).then(res => {
uni.showToast({
title: '保存成功',
icon: 'success'
})
})
}
}
}
</script>
<style>
page {
background-size: 100%;
background-repeat: no-repeat;
background-color: #f0f2f5;
width: 750rpx;
overflow-x: hidden;
}
</style>
<style lang="scss">
.avatar {
padding: 20px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 14px;
}
.save-user-profile {
width: 700rpx;
margin: 40rpx auto;
}
.btn-bar {
width: 700rpx;
margin: auto;
clear: both;
}
.btn {
background: none;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
padding: 20rpx 0;
}
.btn::after {
border: none;
}
</style>
+110
View File
@@ -0,0 +1,110 @@
<template>
<view class="page">
<uni-card :border="false" class="qrcode">
<image src="https://file.jimeigroup.cn/reg-code3/QYPEwCcU.png" mode="widthFix"></image>
</uni-card>
<view class="user-info">
<view class="nickname">{{ userInfo.nickname }}</view>
<view class="desc">APP扫一扫,立即关注我</view>
</view>
<uni-row class="qrcode-row" :width="nvueWidth">
<uni-col :span="8">
<view class="qrcode-row-col dark">
<view class="icon"><uni-icons type="scan" :size="30"></uni-icons></view>
<text>扫一扫</text>
</view>
</uni-col>
<uni-col :span="8">
<view class="qrcode-row-col dark">
<view class="icon"><uni-icons type="color" :size="30"></uni-icons></view>
<text>换个样式</text>
</view>
</uni-col>
<uni-col :span="8">
<view class="qrcode-row-col dark">
<view class="icon"><uni-icons custom-prefix="iconfont" type="icon-xiazai" :size="30"></uni-icons></view>
<text>保存</text>
</view>
</uni-col>
</uni-row>
</view>
</template>
<script>
import {
useUserStore
} from '@/store/modules/user';
const userStore = useUserStore();
export default {
data() {
return {
isLogin: false,
userInfo: {}
}
},
onLoad(){
this.reload()
},
methods: {
async reload(e) {
// 当前登录用户信息
const userInfo = await userStore.fetchUserInfo();
if (Object.keys(userInfo).length > 0) {
this.isLogin = true
this.userInfo = userInfo
}else{
this.isLogin = false
this.userInfo = {}
}
}
}
}
</script>
<style lang="scss" scoped>
.page{
height: 90vh;
display: flex;
flex-direction: column;
justify-content: center;
}
.qrcode {
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: center;
}
.user-info{
display: flex;
flex-direction: column;
align-items: center;
.nickname{
font-size: 48rpx;
padding: 12rpx 0;
}
.desc{
color: $uni-text-color-placeholder;
}
}
.qrcode-row-col {
margin: 100rpx auto;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text{
line-height: 2rem;
}
.icon{
width: 120rpx;
height: 120rpx;
border-radius: 120rpx;
display: flex;
justify-content: center;
align-items: center;
background-color: $uni-text-color-inverse;
}
}
</style>