1.兼容中国台湾、中国香港手机号码 2.增加相关书籍模块

This commit is contained in:
liuyuan
2025-07-10 14:34:26 +08:00
parent f6e5da8dca
commit 4627e2bd01
15 changed files with 576 additions and 37 deletions

View File

@@ -288,7 +288,7 @@ export default {
validateFunction: (rule, value, data, callback) => {
// 异步需要返回 Promise 对象
return new Promise((resolve, reject) => {
if (!this.$base.phoneRegular.test(value)) {
if (!/^\d{5,15}$/.test(value)) {
reject(new Error("手机号格式不正确"));
} else {
resolve();

View File

@@ -91,6 +91,7 @@
</view>
</view>
</view>
<slot name="tjProList" :showTabs="showTabs"></slot>
</view>
</template>

View File

@@ -238,7 +238,7 @@
</view>
</template>
<template slot="leftSlot" slot-scope="slotProps1"> </template>
<template slot="leftSlot" slot-scope="slotProps1"></template>
<template slot="rightSlot" slot-scope="slotProps1">
<text
class="fdButtonBox aui-text-success"
@@ -318,6 +318,73 @@
</view>
</view>
</template>
<template slot="tjProList" slot-scope="slotProps">
<view class="linkPro" v-if="tjProList.length > 0">
<uni-section style="padding: 0 20rpx;" class="mb-10 graybg" title="相关书籍" type="line"></uni-section>
<view class="list supermarketBox">
<scroll-view class="scroll-view_H" scroll-x="true">
<view class="item" v-for="(item, index) in tjProList" :key="index" @click="goToGoodsList(item)">
<view class="imgcontainer" style="position: relative;">
<view v-if="item.isVipPrice==1&&item.vipPrice!=0&&item.vipPrice!=null"
style="z-index:10;position: absolute;top:0;left:0;text-align: center;font-size: 20rpx;background-color: #f94f04;color: #fff;font-weight: bold;border-radius:4px; line-height: 30rpx; padding:10rpx;box-sizing: border-box;">
VIP优惠</view>
<image :src="item.productImages" mode="aspectFit"></image>
</view>
<view class="name">
{{ item.productName }}
</view>
<text
class="price"
v-if="
item.isVipPrice == 1 &&
item.vipPrice != 0 &&
item.vipPrice != null
"
>
<text
style="color: #e97512; font-size: 12px; font-weight: bold"
>¥{{ item.vipPrice.toFixed(2) }}</text
>
<text
style="
color: #8a8a8a;
font-size: 10px;
margin-left: 4px;
font-weight: bold;
text-decoration: line-through;
"
>¥{{ Number(item.price) }}</text
>
</text>
<text
v-else-if="item.activityPrice && item.activityPrice > 0"
class="price"
>
<text
style="color: #e97512; font-size: 12px; font-weight: bold"
>¥{{ item.activityPrice }}</text
>
<text
style="
color: #8a8a8a;
font-size: 10px;
margin-left: 4px;
font-weight: bold;
text-decoration: line-through;
"
>¥{{ Number(item.price)}}</text
>
</text>
<text v-else class="price" style="color: #e97512 !important;"
>¥{{ Number(item.price) }}</text
>
</view>
</scroll-view>
</view>
</view>
</template>
</common-anchor-link>
<common-select-goods
:isFudu="isFudu"
@@ -477,10 +544,11 @@ export default {
goodsList: "sociology/product/getProductListForCourse",
startStudyForMF: "sociology/course/startStudyForMF",
newPayment:"common/courseRelearn/courseCatalogueCanRelearn", // 检查复读地址
newPaymentList:"common/courseRelearn/relearnShopProductList", // 获取复读列表
newPaymentList:"common/courseRelearn/relearnShopProductList", // 获取复读列表
},
userVip: null, //是否有vip
textList: [], //转化文字集合
tjProList: [], //相关书籍
};
},
onLoad(options) {
@@ -948,6 +1016,15 @@ export default {
courseList: [...list],
};
}
if (
res.data.shopProductList &&
res.data.shopProductList.length > 0
) {
this.tjProList = res.data.shopProductList;
} else {
this.tjProList = [];
}
setTimeout(() => {
that.$refs.commonAnchorLink.getDistanceArr();
@@ -983,6 +1060,17 @@ export default {
});
return result;
},
//相关书籍跳转
goToGoodsList(data) {
if (data.delFlag == -1) {
this.$commonJS.showToast("商品已下架");
} else {
uni.navigateTo({
url: `/pages/goods/index/index?isMiaosha=1&id=${data.productId}`,
});
}
},
},
onBackPress() {
// #ifdef APP-PLUS
@@ -1000,13 +1088,7 @@ export default {
padding: 20rpx;
border-bottom: 1px solid #dadbde;
}
}
.scroll-view_H {
background-color: #fff;
white-space: nowrap;
padding: 10rpx;
}
}
.contentBox {
height: calc(100% - 50px);
@@ -1861,4 +1943,56 @@ export default {
margin: 0 20rpx;
}
}
.linkPro {
padding-top: 20rpx;
margin-top: 20rpx;
background: linear-gradient(108deg, #f0fbf4 0%, #d1e8da 100%) !important;
.more {
font-size: 24rpx;
color: #666;
}
}
.scroll-view_H {
white-space: nowrap;
padding: 10rpx 10rpx 20rpx;
margin-top: 12rpx;
.item {
padding: 10rpx;
overflow: hidden;
display: inline-block;
padding-bottom: 0;
width: 210rpx !important;
margin-right: 8rpx;
border-radius: 10rpx;
image {
display: block;
width: 100%;
height: 260rpx;
}
.name {
display: block;
margin-top: 2rpx;
color: #666;
font-size: 28rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
/deep/.uni-section-header__decoration{
width: 14px;
height: 34px;
background-color: #018f89 !important;
}
/deep/.distraction{
font-size: 32rpx !important;
color: #018f89 !important;
font-weight: bold;
}
</style>

View File

@@ -353,6 +353,9 @@ export default {
</script>
<style lang="scss" scoped>
.commonPage, .commonPageBox {
height: calc(100vh - 50px);
}
.goodsvipLabel {
position: absolute;
z-index: 10;

View File

@@ -0,0 +1,384 @@
<template>
<view>
<z-nav-bar title="购物车" bgColor="#3AB3AE" fontColor="#fff"></z-nav-bar>
<view class="shopCarContent">
<scroll-view scroll-y="true" v-if="cartList.length>0">
<view class="cartItem" v-for="(item,index) in cartList" :key="index">
<view class="select">
<checkbox style="transform:scale(0.8)" :checked="item.checked" @click="checkboxGroupChange(index,item)" class="round checkedItem" />
</view>
<view class="cartContent" style="position: relative;">
<span v-if="item.isVipPrice==1&&item.vipPrice!=0&&item.vipPrice!=null"
style="position: absolute;z-index: 10;top: 4px;left: 0px; text-align: center;font-size: 18rpx;background-color: #f94f04;color: #fff; border-radius:4px; padding:2px 4px;line-height: 14px;">VIP优惠</span>
<image :src="item.image" mode="" @click="goDetail(item.productId)"></image>
<view class="itemCenter">
<view class="cartTitle" @click="goDetail(item.productId)" style="display: flex;align-items: center;">
<text>{{item.productName}}</text>
</view>
<view class="itemPrice">
<text v-if="item.isVipPrice==1&&item.vipPrice!=0&&item.vipPrice!=null">
<text style="color: #e97512;font-size: 16px;font-weight: bold;">{{(item.vipPrice).toFixed(2)}}</text>
<text style="color: #8a8a8a;font-size: 14px;margin-left: 4px;font-weight: bold;text-decoration: line-through;">{{(item.price).toFixed(2)}}</text>
</text>
<text
v-else-if="item.activityPrice && item.activityPrice > 0">
<text style="color: #e97512;font-size: 16px;font-weight: bold;">{{(item.activityPrice).toFixed(2)}}</text>
<text style="color: #8a8a8a;font-size: 14px;margin-left: 4px;font-weight: bold;text-decoration: line-through;">{{(item.price).toFixed(2)}}</text>
</text>
<text v-else style="color: #e97512;font-size: 16px;font-weight: bold;">{{item.price}}</text>
<u-number-box button-size="20" v-model="item.productAmount" @change="valChange($event,item)"
:input-width="25" :input-height="10" :min="1" :max="item.productStock" integer
@overlimit='overlimit'></u-number-box>
</view>
</view>
</view>
</view>
</scroll-view>
<view v-else style=" font-size: 28rpx; text-align: center; padding-top: 100rpx; color: #999;">暂无数据</view>
</view>
<!-- 底部操作区 -->
<view class="shopCarFooter">
<view class="selectAll">
<checkbox :checked="all" style="transform:scale(0.8)" @click="isSelectAll()" class="round checkedItem" />
<text class="cartCho">全选</text>
<button class="mini-btn"
style="border-radius: 10rpx; font-size: 26rpx; line-height: 30rpx; padding: 10rpx 25rpx; margin-left: 20rpx;"
v-if="isCartDelShow" @click="delCart()" type="warn" size="mini">删除</button>
</view>
<view class="exhibition">
<view class="total">合计: <b>{{totalPrice}}</b>
</view>
<view class="settlement" @click="setTment()">
结算
</view>
</view>
</view>
</view>
</template>
<script>
import $http from '@/config/requestConfig.js';
import {
mapState
} from 'vuex';
export default {
data() {
return {
playData: {},
totalPrice: 0, // 总价
all: false, // 是否全选
isCartDelShow: false, // 是否展示删除按钮
cartList: [] // 购物车列表
};
},
//第一次加载
onLoad(e) {
this.getCartList()
},
//页面显示
onShow() {
this.getCartList();
this.all = false;
this.isCartDelShow = false
this.totalPrice = 0
},
computed: {
...mapState(['userInfo']),
},
//方法
methods: {
// 获取购物车列表
getCartList() {
this.$http.post(`book/ordercart/getCartList?userId=${this.userInfo.id}`).then(res => {
this.cartList = res.cartList
if (res.cartList.length > 0) {
res.cartList.forEach((item, index) => {
item.checked = false
})
this.cartList = res.cartList
}
})
},
// 是否全选
isSelectAll(e) {
if (this.cartList.length > 0) {
this.all = !this.all
this.cartList.forEach((item, index) => {
item.checked = this.all
})
this.isCartDelShow = this.all
this.total()
} else {
this.all = false
}
},
// 选中单独商品
checkboxGroupChange(index, item) {
// 修改当前item的checked
this.cartList[index].checked = !item.checked
// 判断是否全选
this.all = this.cartList.every((item, index) => {
return item.checked == true
})
// 判断是否展示删除按钮
this.isCartDelShow = this.cartList.some((item, index) => {
return item.checked == true
})
// 计算总价
this.total()
},
// 计算总价
total() {
let allprice = 0;
this.cartList.forEach((item, index) => {
let price = 0;
if (item.checked) {
if (item.isVipPrice == 1 && item.vipPrice != 0) {
price = (item.productAmount * item.vipPrice).toFixed(2);
} else {
if (item.activityPrice && item.activityPrice > 0) {
price = (item.productAmount * item.activityPrice).toFixed(2);
} else {
price = (item.productAmount * item.price).toFixed(2);
}
}
}
allprice += Number(price)
})
this.totalPrice = allprice.toFixed(2)
},
// 超出阈值时
overlimit() {
uni.showToast({
title: '超出商品数量',
icon: 'error',
duration: 1000
})
},
valChange(e, item) {
console.log(e)
let productItem = {}
productItem = item
productItem.productAmount = e.value
this.updateCart(productItem)
setTimeout(() => {
this.total()
}, 300)
},
// 更新购物车
updateCart(shagnpin) {
// 已在购物车中添加
$http.request({
url: "book/ordercart/update",
method: "POST",
data: shagnpin,
header: {
'Content-Type': 'application/json'
}
}).then(res => {
if (res.code == 0) {
}
})
},
// 删除购物车
delCart() {
let cartIdArr = [];
this.cartList.forEach((item, index) => {
if (item.checked) {
cartIdArr.push(item.cartId)
}
})
uni.showModal({
title: '提示',
content: '是否删除这个商品',
confirmText: '确定',
success: (res) => {
if (res.confirm) {
uni.showLoading({
title: '加载中',
mask: true
})
console.log(cartIdArr)
$http.request({
url: "book/ordercart/delete",
method: "POST",
data: cartIdArr,
header: {
'Content-Type': 'application/json'
},
}).then(res => {
this.isCartDelShow = false
this.totalPrice = 0
this.getCartList()
uni.hideLoading();
this.all = false;
})
} else {
console.log('cancel') //点击取消之后执行的代码
}
}
})
},
// 跳转结算页面
setTment() {
let goods = []
this.cartList.forEach((item, index) => {
if (item.checked) {
goods.push({
productImages: item.productImages,
productId: item.productId,
productName: item.productName,
goodsType: item.goodsType,
productAmount: item.productAmount,
})
}
})
let mynavData = JSON.stringify({
goods: goods,
typeId: 1
})
// 如果没有勾选
if (goods.length == 0) {
uni.showToast({
title: "请先勾选商品",
icon: 'error',
duration: 1000,
})
} else {
uni.navigateTo({
url: '/pages/goods/order/index?data='+ mynavData
});
}
},
//商品内容跳转
goDetail(id) {
uni.navigateTo({
url: '/pages/goods/index/index?isMiaosha=1&id='+id
});
},
},
};
</script>
<style lang="scss" scoped>
@import '@/style/mixin.scss';
.shopCarContent {
width: 100%;
height: 100%;
padding-bottom: 104rpx;
padding-top: 20rpx;
.cartItem {
padding: 10rpx 10rpx 10rpx 10rpx;
margin-bottom: 20rpx;
display: flex;
align-items: center;
background-color: #fff;
.cartContent {
flex: 1;
display: flex;
image {
width: 130rpx;
height: 150rpx;
border-radius: 10rpx;
padding: 10rpx;
margin-right: 15rpx;
}
.itemCenter {
flex: 1;
flex-direction: column;
justify-content: space-around;
}
.cartTitle {
font-size: 30rpx;
margin: 35rpx 0 20rpx 0;
}
.itemPrice {
font-size: 28rpx;
display: flex;
justify-content: space-between;
}
}
}
}
.shopCarFooter {
width: 100%;
height: 100rpx;
padding: 20rpx;
background-color: #fff;
display: flex;
align-items: center;
justify-content: space-between;
position: fixed;
bottom: 0;
.selectAll {
display: flex;
.cartCho {
font-size: 26rpx;
color: #888;
}
.cartDel {
font-weight: bold;
color: #bf0c0c;
font-size: 14px;
margin: 12rpx 0 0 20rpx;
}
}
.exhibition {
display: flex;
align-items: center;
.total {
font-size: 15px;
padding: 0 40rpx 0 0;
color: #888;
b {
margin-left: 10rpx;
color: #ef1224;
font-size: 35rpx;
}
}
.settlement {
font-size: 28rpx;
font-weight: 700;
padding: 10rpx 50rpx;
background-image: linear-gradient(90deg, rgb(254, 96, 53), rgb(239, 18, 36));
color: #fff;
border-radius: 40rpx;
}
}
}
/deep/.uni-checkbox-input{
border-radius: 50rpx;
}
.shopCarFooter .selectAll{
display: flex;
align-items: center;
}
/deep/uni-checkbox .uni-checkbox-input.uni-checkbox-input-checked{
color: $themeColor !important;
}
</style>

View File

@@ -382,17 +382,22 @@ export default {
{
name: "我的订单",
url: "/pages/bookShop/orderList?type=mine",
type: "switchTab",
},{
name: "我的湖分",
url: "/pages/hufen/hufen",
type: "pageJump", contentType: "hufen",
},
},
{
name: "我的购物车",
url: "/pages/goods/shopping/index",
type: "pageJump",
},
{
name: "我的湖分",
url: "/pages/hufen/hufen",
type: "pageJump",
contentType: "hufen",
},
{
name: "个人资料",
url: "/pages/mine/userInfo/persData",
type: "pageJump",
},
{