| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604 |
- <template>
- <view class="content">
- <!-- 商品列表 -->
- <mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback" :down="downOption"
- :up="upOption">
- <view class="goods-list">
- <view class="item" v-for="(item,index) in carts" :key="index">
- <view class="choose" @click.stop="checkChange(item,index)">
- <image src="@/static/images/integral/sign_in_on_icon.png" v-show="item.checked"></image>
- <image src="https://hdtobs.obs.cn-north-4.myhuaweicloud.com/fs/20250729/1753758821601.png"
- v-show="!item.checked"></image>
- </view>
- <image class="goods-img" :src="item.imgUrl" mode="aspectFit" @click="showProduct(item)"></image>
- <view class="info-box">
- <view>
- <view class="title-box">
- <view class="title ellipsis">{{ item.goodsName }}</view>
- </view>
- </view>
- <view class="price-num">
- <view class="price">
- <text class="text">{{item.goodsIntegral}}</text>
- <text class="unit">健康币</text>
- <!-- <text class="unit">+</text> -->
- <text class="oldprice">¥{{item.otPrice.toFixed(2)}}</text>
- </view>
- <view class="num-box" @click.stop>
- <u-number-box v-model="item.quantity" buttonSize="48rpx" integer :step="1" :min="1"
- :max="100000" @input="val => changeCartNum(val, item)"></u-number-box>
- </view>
- </view>
- </view>
- </view>
- <!-- 自定义空数据 -->
- <view v-if="carts.length === 0 && isPostBack" class="no-data-box">
- <image src="https://cos.his.cdwjyyh.com/fs/20240423/cf4a86b913a04341bb44e34bb4d37aa2.png"
- mode="aspectFit"></image>
- <view class="empty-title">购物车为空</view>
- <view class="empty-cart-btn x-f" @click="goPage">去逛逛</view>
- </view>
- </view>
- <view style="height: 140rpx;"></view>
- </mescroll-body>
- <!-- 底部按钮 -->
- <view class="btn-foot">
- <view class="left">
- <view class="choose" @click="handleCheckAll()">
- <image src="@/static/images/integral/sign_in_on_icon.png" v-show="checkAll"></image>
- <image src="https://hdtobs.obs.cn-north-4.myhuaweicloud.com/fs/20250729/1753758821601.png"
- v-show="!checkAll"></image>
- </view>
- <text class="text">全选</text>
- <text class="text" @click="delCart()">删除</text>
- </view>
- <view class="right">
- <!-- <view> -->
- <!-- <view class="total">
- <text class="label">合计:</text>
- <view class="price">
- <text class="unit">¥</text>
- <text class="num">{{totalMoney.toFixed(2)}}</text>
- </view>
- </view> -->
- <view class="total">
- <text class="label">所需健康币</text>
- <view class="price">
- <text class="num">{{totalIntegral}}</text>
- </view>
- </view>
- <!-- </view> -->
- <view class="btn" @click="submit">结算</view>
- </view>
- </view>
-
- </view>
- </template>
- <script>
- import {
- getFsIntegralCartList,
- deleteCart,
- putGoodsQuantityFromCart
- } from '@/api/integral.js'
- // import likeProduct from '@/components/likeProduct.vue'
- export default {
- // components: {
- // likeProduct
- // },
- data() {
- return {
- totalMoney: 0.00,
- totalIntegral: 0,
- carts: [],
- checkAll: false,
- changeNumTimer: null, // 防抖定时器
- isPostBack: false, // 数据是否已加载完成
- downOption: {
- auto: false //不要自动加载
- },
- // 上拉加载的配置
- upOption: {
- onScroll: false,
- use: true, // 是否启用上拉加载; 默认true
- page: {
- pae: 0, // 当前页码,默认0,回调之前会加1,即callback(page)会从1开始
- size: 10 // 每页数据的数量,默认10
- },
- noMoreSize: 10, // 配置列表的总数量要大于等于5条才显示'-- END --'的提示
- textNoMore: "已经到底了",
- empty: {
- icon: '', // 隐藏默认图标
- tip: '' // 隐藏默认提示,使用自定义空数据
- }
- },
- }
- },
- onLoad() {
- // this.getCarts();
- },
- onShow() {
- //this.getCarts();
- },
- onReachBottom() {
- // this.$refs.product.getGoodsProducts();
- },
- onUnload() {
- // 组件销毁时清理定时器
- if (this.changeNumTimer) {
- clearTimeout(this.changeNumTimer);
- this.changeNumTimer = null;
- }
- },
- methods: {
- mescrollInit(mescroll) {
- this.mescroll = mescroll;
- },
- /*下拉刷新的回调 */
- downCallback(mescroll) {
- mescroll.resetUpScroll()
- },
- upCallback(page) {
- //联网加载数据
- var that = this;
- var data = {
- goodsName: this.searchKey,
- pageNum: page.num,
- pageSize: page.size
- };
- getFsIntegralCartList(data).then(res => {
- if (res.code == 200) {
- // 标记数据已加载
- this.isPostBack = true;
- this.carts = res.data.list;
- this.carts.forEach((item, index, arr) => {
- item.checked = false;
- })
- this.checkAll = this.carts.length > 0 && this.carts.every(item => item.checked)
- this.computedMoney();
- //设置列表数据
- if (page.num == 1) {
- that.cartst = res.data.list;
-
- } else {
- that.carts = that.carts.concat(res.data.list);
-
- }
- that.mescroll.endBySize(res.data.list.length, res.data.total);
-
- } else {
- uni.showToast({
- icon: 'none',
- title: "请求失败",
- });
- that.dataList = null;
- that.mescroll.endErr();
- }
- });
- },
- delCart() {
- var selectCarts = this.carts.filter(ele => ele.checked == true).map(ele => {
- return ele.cartId
- });
- if (selectCarts.length == 0) {
- uni.showToast({
- icon: 'none',
- title: "请选择商品删除",
- });
- return;
- }
- // 将数组转换为逗号拼接的字符串
- const cartIds = selectCarts.join(',');
- deleteCart(cartIds).then(
- res => {
- if (res.code == 200) {
- uni.showToast({
- icon: 'success',
- title: "操作成功",
- });
- this.mescroll.resetUpScroll()
- } else {
- uni.showToast({
- icon: 'none',
- title: res.msg || '删除失败',
- });
- }
- },
- rej => {
- uni.showToast({
- icon: 'none',
- title: rej.msg || '网络错误,请稍后重试',
- });
- }
- );
- },
- computedMoney() {
- let totalIntegral = 0;
- let totalMoney = 0;
- let arry = this.carts.filter(item => item.checked)
- arry.forEach(item => {
- totalIntegral += item.goodsIntegral * item.quantity;
- totalMoney += item.otPrice * item.quantity;
- });
- this.totalIntegral = totalIntegral;
- this.totalMoney = totalMoney;
- },
- handleCheckAll() {
- this.checkAll = !this.checkAll;
- var that = this;
- this.carts.forEach((item, index, arr) => {
- item.checked = that.checkAll;
- })
- this.computedMoney();
- },
- checkChange(item, index) {
- item.checked = !item.checked;
- this.checkAll = this.carts.length > 0 && this.carts.every(item => item.checked)
- this.computedMoney();
- },
- changeCartNum(val, item) {
- // 清除之前的定时器(防抖处理)
- if (this.changeNumTimer) {
- clearTimeout(this.changeNumTimer);
- }
- // 保存原始数量
- const originalNum = item.quantity;
- const maxQuantity = item.stock || 100000;
-
- // 验证并限制数量范围
- const newQuantity = Math.max(1, Math.min(parseInt(val) || 1, maxQuantity));
-
- // 显示提示
- if (newQuantity !== parseInt(val)) {
- uni.showToast({
- icon: 'none',
- title: newQuantity === 1 ? '数量不能小于1' : `库存不足,最多只能购买${maxQuantity}件`,
- duration: 2000
- });
- }
- // 更新本地UI并计算总积分
- item.quantity = newQuantity;
- this.computedMoney();
- // 防抖处理:延迟300ms执行API请求
- this.changeNumTimer = setTimeout(() => {
- if (!item.cartId) {
- item.quantity = originalNum;
- this.computedMoney();
- this.$forceUpdate();
- uni.showToast({
- icon: 'none',
- title: '购物车商品信息异常',
- duration: 2000
- });
- return;
- }
- putGoodsQuantityFromCart({
- cartId: item.cartId,
- quantity: item.quantity
- }).then(
- res => {
- if (res.code == 200) {
- // 同步服务器返回的数据
- if (res.data) {
- res.data.quantity !== undefined && (item.quantity = res.data.quantity);
- res.data.stock !== undefined && (item.stock = res.data.stock);
- }
- this.computedMoney();
- } else {
- // 失败时恢复原始数量
- item.quantity = originalNum;
- if (res.data?.stock !== undefined) {
- item.stock = res.data.stock;
- }
- this.computedMoney();
- this.$forceUpdate();
- uni.showToast({
- icon: 'none',
- title: res.msg || '操作失败',
- duration: 2000
- });
- }
- },
- err => {
- // 网络错误,恢复原始数量
- item.quantity = originalNum;
- this.computedMoney();
- this.$forceUpdate();
- uni.showToast({
- icon: 'none',
- title: err.msg || '网络错误,请稍后重试',
- duration: 2000
- });
- }
- );
- }, 300);
- },
- // 结算
- submit() {
- var selectCarts = this.carts.filter(ele => ele.checked == true).map(ele => {
- return ele.cartId
- });
- var selectGoods = this.carts.filter(ele => ele.checked == true).map(ele => {
- return ele.goodsId
- });
- if (selectCarts.length == 0) {
- uni.showToast({
- icon: 'none',
- title: "请选择商品",
- });
- return;
- }
- uni.navigateTo({
- url: '/pages/user/integral/integralOrderCartPay?cartIds=' + selectCarts
- })
- },
- showProduct(item) {
- console.log("这个item")
- uni.navigateTo({
- url: '/pages/user/integral/integralGoodsDetails?goodsId=' + item.goodsId
- })
- },
- goPage() {
- uni.navigateTo({
- url: '/pages/user/integral/integralGoodsList'
- })
- }
- }
- }
- </script>
- <style lang="scss">
- page {
- height: 100%;
- }
- .oldprice {
- font-size: 28rpx;
- font-family: PingFang SC;
- font-weight: 500;
- color: #999999;
- // margin-top: 27rpx;
- line-height: 1;
- text-decoration: line-through;
- margin-left: 24rpx;
- }
- .content {
- height: 100%;
- .goods-list {
- padding: 20upx;
- .item {
- box-sizing: border-box;
- background: #FFFFFF;
- border-radius: 16upx;
- margin-bottom: 20upx;
- padding: 30upx;
- display: flex;
- align-items: center;
- &:last-child {
- margin-bottom: 0;
- }
- .goods-img {
- width: 160upx;
- height: 160upx;
- background: #FFFFFF;
- margin-right: 30upx;
- flex-shrink: 0;
- }
- .info-box {
- display: flex;
- flex-direction: column;
- justify-content: space-between;
- width: calc(100% - 255upx);
- .title-box {
- width: 100%;
- display: flex;
- align-items: center;
- .title {
- flex: 1;
- font-size: 28upx;
- font-family: PingFang SC;
- font-weight: 500;
- color: #111111;
- line-height: 1;
- }
- }
- .price-num {
- margin-top: 24rpx;
- .price {
- margin-bottom: 24rpx;
- display: flex;
- align-items: flex-end;
- .unit {
- font-size: 24upx;
- font-family: PingFang SC;
- font-weight: 500;
- color: #FF5030;
- line-height: 1.2;
- margin-right: 4upx;
- }
- .text {
- font-size: 32upx;
- font-family: PingFang SC;
- font-weight: bold;
- color: #FF5030;
- line-height: 1;
- }
- }
- .num-box {
- display: flex;
- align-items: center;
- justify-content: flex-end;
- .img-box {
- width: 60upx;
- height: 60upx;
- // border-radius: 4upx;
- border: 1px solid #dddddd;
- display: flex;
- align-items: center;
- justify-content: center;
- image {
- width: 25rpx;
- height: 25rpx;
- }
- }
- input {
- width: 60upx;
- height: 60upx;
- line-height: 60upx;
- font-size: 28upx;
- font-family: PingFang SC;
- font-weight: 500;
- color: #111111;
- // border-radius: 4upx;
- border-top: 1px solid #dddddd;
- border-bottom: 1px solid #dddddd;
- text-align: center;
- // margin: 0 16upx;
- }
- }
- }
- }
- }
- }
- .like-product {
- padding-bottom: 120upx;
- }
- .btn-foot {
- box-sizing: border-box;
- width: 100%;
- height: 121upx;
- background: #FFFFFF;
- padding: 16upx 30upx 16upx 30upx;
- display: flex;
- align-items: center;
- justify-content: space-between;
- position: fixed;
- left: 0;
- bottom: 0;
- z-index: 99;
- .left {
- display: flex;
- align-items: center;
- .text {
- margin-left: 20upx;
- font-size: 28upx;
- font-family: PingFang SC;
- font-weight: 500;
- color: #666666;
- line-height: 1;
- }
- }
- .right {
- display: flex;
- align-items: center;
- .total {
- margin-right: 36upx;
- display: flex;
- flex-direction: column;
- align-items: flex-start;
- .label {
- font-size: 26upx;
- font-family: PingFang SC;
- font-weight: 500;
- color: #999999;
- line-height: 1.5;
- }
- .price {
- display: flex;
- align-items: flex-end;
- .unit {
- font-size: 24upx;
- font-family: PingFang SC;
- font-weight: bold;
- color: #FF5030;
- line-height: 1.2;
- margin-right: 10upx;
- }
- .num {
- font-size: 32rpx;
- font-family: PingFang SC;
- font-weight: bold;
- color: #FF5030;
- line-height: 1;
- }
- }
- }
- .btn {
- width: 200upx;
- height: 88upx;
- line-height: 88upx;
- text-align: center;
- font-size: 30upx;
- font-family: PingFang SC;
- font-weight: bold;
- color: #FFFFFF;
- background: #FF5030;
- border-radius: 44upx;
- }
- }
- }
- }
- .choose {
- margin-right: 20rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- image {
- width: 36rpx;
- height: 36rpx;
- flex-shrink: 0;
- }
- }
- .no-data-box {
- width: 100%;
- padding: 100rpx 50rpx;
- text-align: center;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- min-height: 400rpx;
- }
- .empty-cart-btn {
- border: 1rpx solid #FF5030;
- color: #FF5030;
- padding: 10rpx 30rpx;
- border-radius: 40rpx;
- margin-top: 50rpx;
- display: inline-block;
- }
- </style>
|