|
|
@@ -1,465 +1,626 @@
|
|
|
<template>
|
|
|
- <view class="content">
|
|
|
- <!-- 商品列表 -->
|
|
|
- <view class="goods-list">
|
|
|
- <view class="item" v-for="(item,index) in carts" :key="index">
|
|
|
- <label style="margin-right: 30upx;">
|
|
|
- <checkbox :value="item.checked" :checked="item.checked" @click="checkChange(item)" />
|
|
|
- </label>
|
|
|
- <image class="goods-img" :src="item.productAttrImage==null||item.productAttrImage==''?item.productImage:item.productAttrImage" mode="aspectFit"></image>
|
|
|
- <view class="info-box">
|
|
|
- <view>
|
|
|
- <view class="title-box">
|
|
|
- <view class="tag">{{utils.getDictLabelName("storeProductType",item.productType)}}</view>
|
|
|
- <view class="title ellipsis">{{ item.productName }}</view>
|
|
|
- </view>
|
|
|
- <view class="intro ellipsis">{{item.productAttrName}}</view>
|
|
|
- </view>
|
|
|
- <view class="price-num">
|
|
|
- <view class="price">
|
|
|
- <text class="unit">¥</text>
|
|
|
- <text class="text">{{item.price}}</text>
|
|
|
- </view>
|
|
|
- <view class="num-box">
|
|
|
- <view class="img-box" @click="delNum(item)">
|
|
|
- <image v-if="item.cartNum <= 1" src="../../static/images/jian.png" mode=""></image>
|
|
|
- <image v-else src="../../static/images/jian2.png" mode=""></image>
|
|
|
- </view>
|
|
|
- <input type="number" @change="changeNum($event,item)" :value="item.cartNum" />
|
|
|
- <view class="img-box" @click="addNum(item)">
|
|
|
- <image src="../../static/images/add.png" mode=""></image>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
-
|
|
|
- <view v-if="carts.length == 0" class="no-data-box">
|
|
|
- <image src="../../static/images/no_data.png" mode="aspectFit"></image>
|
|
|
- <view class="empty-title">暂无数据</view>
|
|
|
- </view>
|
|
|
- <!-- 猜你喜欢 -->
|
|
|
-
|
|
|
- <view class="like-product">
|
|
|
- <likeProduct ref="product" />
|
|
|
- </view>
|
|
|
- <!-- 底部按钮 -->
|
|
|
- <view class="btn-foot">
|
|
|
- <view class="left">
|
|
|
- <label>
|
|
|
- <checkbox :checked="checkAll" @click="handleCheckAll()" />
|
|
|
- </label>
|
|
|
- <text class="text">全选</text>
|
|
|
- <text class="text" @click="delCart()">删除</text>
|
|
|
- </view>
|
|
|
- <view class="right">
|
|
|
- <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="btn" @click="submit">结算</view>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
-
|
|
|
- </view>
|
|
|
+ <view class="content">
|
|
|
+ <!-- 商品列表:按仓库分组展示 -->
|
|
|
+ <view class="goods-list">
|
|
|
+ <block v-for="(group, gIndex) in cartsByWarehouse" :key="gIndex">
|
|
|
+ <view class="warehouse-header">{{ group.warehouseName || '默认仓库' }}</view>
|
|
|
+ <view class="item" v-for="(item, index) in group.list" :key="item.id">
|
|
|
+ <!-- 🔥 替换原生checkbox为自定义样式,解决渲染隔离 -->
|
|
|
+ <view
|
|
|
+ class="checkbox-wrap"
|
|
|
+ style="margin-right: 30upx;"
|
|
|
+ :data-id="item && item.id"
|
|
|
+ @tap.stop="onItemCheckTap($event)"
|
|
|
+ >
|
|
|
+ <view class="custom-checkbox" :class="{checked: item.checked}">
|
|
|
+ <text v-if="item.checked" class="check-icon">✓</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <image class="goods-img" :src="item.productAttrImage||item.productImage" mode="aspectFit"></image>
|
|
|
+ <view class="info-box">
|
|
|
+ <view>
|
|
|
+ <view class="title-box">
|
|
|
+ <view class="tag">{{utils.getDictLabelName("storeProductType",item.productType)}}</view>
|
|
|
+ <view class="title ellipsis">{{ item.productName }}</view>
|
|
|
+ </view>
|
|
|
+ <view class="intro ellipsis">{{item.productAttrName}}</view>
|
|
|
+ </view>
|
|
|
+ <view class="price-num">
|
|
|
+ <view class="price">
|
|
|
+ <text class="unit">¥</text>
|
|
|
+ <text class="text">{{item.price}}</text>
|
|
|
+ </view>
|
|
|
+ <view class="num-box">
|
|
|
+ <view class="img-box" @click="delNum(item)">
|
|
|
+ <image v-if="item.cartNum <= 1" src="../../static/images/jian.png" mode=""></image>
|
|
|
+ <image v-else src="../../static/images/jian2.png" mode=""></image>
|
|
|
+ </view>
|
|
|
+ <input type="number" @change="changeNum($event,item)" :value="item.cartNum" />
|
|
|
+ <view class="img-box" @click="addNum(item)">
|
|
|
+ <image src="../../static/images/add.png" mode=""></image>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </block>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view v-if="carts.length == 0" class="no-data-box">
|
|
|
+ <image src="../../static/images/no_data.png" mode="aspectFit"></image>
|
|
|
+ <view class="empty-title">暂无数据</view>
|
|
|
+ </view>
|
|
|
+ <!-- 猜你喜欢 -->
|
|
|
+ <view class="like-product">
|
|
|
+ <likeProduct ref="product" />
|
|
|
+ </view>
|
|
|
+ <!-- 底部按钮 -->
|
|
|
+ <view class="btn-foot">
|
|
|
+ <view class="left">
|
|
|
+ <!-- 🔥 全选也替换为自定义checkbox -->
|
|
|
+ <view class="checkbox-wrap" @tap.stop="onCheckAllTap()">
|
|
|
+ <view class="custom-checkbox" :class="{checked: checkAll}">
|
|
|
+ <text v-if="checkAll" class="check-icon">✓</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <text class="text">全选</text>
|
|
|
+ <text class="text" @click="delCart()">删除</text>
|
|
|
+ </view>
|
|
|
+ <view class="right">
|
|
|
+ <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="btn" @click="submit">结算</view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
- import {getCarts,cartNum,delCart} from '@/api/product'
|
|
|
- import likeProduct from '@/components/likeProduct.vue'
|
|
|
- export default {
|
|
|
- components: {
|
|
|
- likeProduct
|
|
|
- },
|
|
|
- data() {
|
|
|
- return {
|
|
|
-
|
|
|
- totalMoney:0.00,
|
|
|
- carts:[],
|
|
|
- checkAll:false,
|
|
|
- }
|
|
|
- },
|
|
|
- onLoad() {
|
|
|
- // this.getCarts();
|
|
|
- },
|
|
|
- onShow() {
|
|
|
- if(uni.getStorageSync('AppToken')){
|
|
|
- this.getCarts();
|
|
|
- }
|
|
|
- },
|
|
|
- onReachBottom() {
|
|
|
- this.$refs.product.getGoodsProducts();
|
|
|
- },
|
|
|
- methods: {
|
|
|
- delCart(){
|
|
|
- var selectCarts=this.carts.filter(ele => ele.checked==true).map(ele => {
|
|
|
- return ele.id
|
|
|
- });
|
|
|
- if(selectCarts.length==0){
|
|
|
- uni.showToast({
|
|
|
- icon:'none',
|
|
|
- title: "请选择商品删除",
|
|
|
- });
|
|
|
- return;
|
|
|
- }
|
|
|
- let data = {ids:selectCarts};
|
|
|
- delCart(data).then(
|
|
|
- res => {
|
|
|
- if(res.code==200){
|
|
|
- uni.showToast({
|
|
|
- icon:'success',
|
|
|
- title: "操作成功",
|
|
|
- });
|
|
|
- this.getCarts()
|
|
|
- }else{
|
|
|
-
|
|
|
- uni.showToast({
|
|
|
- icon:'none',
|
|
|
- title: res.msg,
|
|
|
- });
|
|
|
- }
|
|
|
- },
|
|
|
- rej => {}
|
|
|
- );
|
|
|
- console.log(selectCarts)
|
|
|
- },
|
|
|
- computedMoney(){
|
|
|
- var money=0;
|
|
|
- var that=this;
|
|
|
- this.carts.forEach((item,index,arr)=>{
|
|
|
- if(item.checked){
|
|
|
- money+=item.price*item.cartNum;
|
|
|
- }
|
|
|
- })
|
|
|
- console.log(money);
|
|
|
- this.totalMoney=money;
|
|
|
- },
|
|
|
- handleCheckAll(){
|
|
|
- this.checkAll=!this.checkAll;
|
|
|
- var that=this;
|
|
|
- this.carts.forEach((item,index,arr)=>{
|
|
|
- item.checked=that.checkAll;
|
|
|
- })
|
|
|
- this.computedMoney();
|
|
|
- },
|
|
|
- checkChange(item){
|
|
|
- item.checked=!item.checked;
|
|
|
- this.computedMoney();
|
|
|
- },
|
|
|
- changeNum(e,item) {
|
|
|
- item.cartNum = e.detail.value.replace(/\D/g, '')
|
|
|
- if (item.cartNum <= 1) {
|
|
|
- uni.showToast({
|
|
|
- title: "已经是底线啦!",
|
|
|
- icon: "none",
|
|
|
- duration: 2000
|
|
|
- });
|
|
|
- return;
|
|
|
- }
|
|
|
- if(item.cartNum < 1) {
|
|
|
- item.cartNum = 1
|
|
|
- }
|
|
|
- if(item.cartNum>=item.stock){
|
|
|
- item.cartNum=item.stock;
|
|
|
- }
|
|
|
- this.changeCartNum(item)
|
|
|
- },
|
|
|
- changeCartNum(item){
|
|
|
- let data = {number:item.cartNum,id:item.id};
|
|
|
- cartNum(data).then(
|
|
|
- res => {
|
|
|
- if(res.code==200){
|
|
|
- uni.showToast({
|
|
|
- icon:'none',
|
|
|
- title: "操作成功",
|
|
|
- });
|
|
|
- this.computedMoney();
|
|
|
-
|
|
|
- }else{
|
|
|
-
|
|
|
- uni.showToast({
|
|
|
- icon:'none',
|
|
|
- title: res.msg,
|
|
|
- });
|
|
|
- }
|
|
|
- },
|
|
|
- rej => {}
|
|
|
- );
|
|
|
- },
|
|
|
- getCarts(){
|
|
|
- getCarts().then(
|
|
|
- res => {
|
|
|
- if(res.code==200){
|
|
|
- this.carts=res.carts;
|
|
|
- this.carts.forEach((item,index,arr)=>{
|
|
|
- item.checked=false;
|
|
|
- })
|
|
|
- this.computedMoney();
|
|
|
- }else{
|
|
|
- uni.showToast({
|
|
|
- icon:'none',
|
|
|
- title: "请求失败",
|
|
|
- });
|
|
|
- }
|
|
|
- },
|
|
|
- rej => {}
|
|
|
- );
|
|
|
- },
|
|
|
- // 购物车减法
|
|
|
- delNum(item) {
|
|
|
- if (item.cartNum <= 1) {
|
|
|
- uni.showToast({
|
|
|
- title: "已经是底线啦!",
|
|
|
- icon: "none",
|
|
|
- duration: 2000
|
|
|
- });
|
|
|
- return;
|
|
|
- }
|
|
|
- item.cartNum --
|
|
|
- if(item.cartNum < 1) {
|
|
|
- item.cartNum = 1
|
|
|
- }
|
|
|
-
|
|
|
- this.changeCartNum(item)
|
|
|
- },
|
|
|
- // 购物车加法
|
|
|
- addNum(item) {
|
|
|
- console.log(item)
|
|
|
- item.cartNum++
|
|
|
- if(item.cartNum>=item.stock){
|
|
|
- item.cartNum=item.stock;
|
|
|
- }
|
|
|
- this.changeCartNum(item)
|
|
|
- },
|
|
|
- // 结算
|
|
|
- submit() {
|
|
|
- var selectCarts=this.carts.filter(ele => ele.checked==true).map(ele => {
|
|
|
- return ele.id
|
|
|
- });
|
|
|
- if(selectCarts.length==0){
|
|
|
- uni.showToast({
|
|
|
- icon:'none',
|
|
|
- title: "请选择商品",
|
|
|
- });
|
|
|
- return;
|
|
|
- }
|
|
|
- uni.navigateTo({
|
|
|
- url: '/pages_shopping/shopping/confirmOrder?type=cart&cartIds='+selectCarts.toString()
|
|
|
- })
|
|
|
- },
|
|
|
- showProduct(item){
|
|
|
- uni.navigateTo({
|
|
|
- url: '/pages_shopping/shopping/productDetails?productId='+item.productId
|
|
|
- })
|
|
|
- },
|
|
|
- }
|
|
|
- }
|
|
|
+import {getCarts,cartNum,delCart} from '@/api/product'
|
|
|
+import likeProduct from '@/components/likeProduct.vue'
|
|
|
+export default {
|
|
|
+ components: {
|
|
|
+ likeProduct
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ carts:[],
|
|
|
+ cartsByWarehouse: [],
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onLoad() {
|
|
|
+ // this.getCarts();
|
|
|
+ },
|
|
|
+ onShow() {
|
|
|
+ if(uni.getStorageSync('AppToken')){
|
|
|
+ this.getCarts();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onReachBottom() {
|
|
|
+ this.$refs.product.getGoodsProducts();
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ carts: {
|
|
|
+ deep: true,
|
|
|
+ handler() {
|
|
|
+ this.formatCartsByWarehouse();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ totalMoney() {
|
|
|
+ let money = 0;
|
|
|
+ (this.carts || []).forEach(item => {
|
|
|
+ if (item.checked) {
|
|
|
+ money += (Number(item.price) || 0) * (Number(item.cartNum) || 0);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return money;
|
|
|
+ },
|
|
|
+ checkAll() {
|
|
|
+ if (!this.carts || this.carts.length === 0) return false;
|
|
|
+ return this.carts.every(item => item.checked);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ formatCartsByWarehouse() {
|
|
|
+ const map = {};
|
|
|
+ (this.carts || []).filter(item => !!item).forEach(item => {
|
|
|
+ const code = item.warehouseCode || '_default_';
|
|
|
+ const name = item.warehouseName || '默认仓库';
|
|
|
+ if (!map[code]) {
|
|
|
+ map[code] = { warehouseCode: code, warehouseName: name, list: [] };
|
|
|
+ }
|
|
|
+ map[code].list.push({ ...item });
|
|
|
+ });
|
|
|
+ // 🔥 强制替换数组,触发视图刷新
|
|
|
+ this.cartsByWarehouse = Object.values(map);
|
|
|
+ },
|
|
|
+ getSelectedWarehouseCount() {
|
|
|
+ const codes = new Set();
|
|
|
+ this.carts.forEach(item => {
|
|
|
+ if (item.checked) {
|
|
|
+ const code = item.warehouseCode || '_default_';
|
|
|
+ codes.add(code);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return codes.size;
|
|
|
+ },
|
|
|
+ delCart(){
|
|
|
+ var selectCarts=this.carts.filter(ele => ele.checked==true).map(ele => ele.id);
|
|
|
+ if(selectCarts.length==0){
|
|
|
+ uni.showToast({
|
|
|
+ icon:'none',
|
|
|
+ title: "请选择商品删除",
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ let data = {ids:selectCarts};
|
|
|
+ delCart(data).then(
|
|
|
+ res => {
|
|
|
+ if(res.code==200){
|
|
|
+ uni.showToast({
|
|
|
+ icon:'success',
|
|
|
+ title: "操作成功",
|
|
|
+ });
|
|
|
+ this.getCarts();
|
|
|
+ }else{
|
|
|
+ uni.showToast({
|
|
|
+ icon:'none',
|
|
|
+ title: res.msg,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ rej => {}
|
|
|
+ );
|
|
|
+ },
|
|
|
+ wouldHaveMultiWarehouseIfItemChecked(item) {
|
|
|
+ if (!item) return false;
|
|
|
+ const code = item.warehouseCode || '_default_';
|
|
|
+ const selectedCodes = new Set();
|
|
|
+ this.carts.forEach(c => {
|
|
|
+ if (c && c.checked) {
|
|
|
+ selectedCodes.add(c.warehouseCode || '_default_');
|
|
|
+ }
|
|
|
+ });
|
|
|
+ selectedCodes.add(code);
|
|
|
+ return selectedCodes.size > 1;
|
|
|
+ },
|
|
|
+ wouldHaveMultiWarehouseIfCheckAll() {
|
|
|
+ const codes = new Set();
|
|
|
+ this.carts.forEach(c => {
|
|
|
+ if (c) codes.add(c.warehouseCode || '_default_');
|
|
|
+ });
|
|
|
+ return codes.size > 1;
|
|
|
+ },
|
|
|
+ // 🔥 修复全选方法:统一用数组索引替换元素
|
|
|
+ onCheckAllTap() {
|
|
|
+ const newVal = !this.checkAll;
|
|
|
+ if (newVal && this.wouldHaveMultiWarehouseIfCheckAll()) {
|
|
|
+ uni.showToast({
|
|
|
+ icon: 'none',
|
|
|
+ title: '暂不支持多仓库购买,请选择同仓库商品',
|
|
|
+ duration: 2500
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 深拷贝数组,批量替换元素
|
|
|
+ let newCarts = [...this.carts];
|
|
|
+ newCarts = newCarts.map(item => ({...item, checked: newVal}));
|
|
|
+ // 响应式替换整个carts数组
|
|
|
+ this.carts = newCarts;
|
|
|
+ // 手动触发分组 + 强制刷新
|
|
|
+ this.formatCartsByWarehouse();
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.$forceUpdate();
|
|
|
+ });
|
|
|
+ },
|
|
|
+ onItemCheckTap(e) {
|
|
|
+ const id = e?.currentTarget?.dataset?.id;
|
|
|
+ if (!id) return false;
|
|
|
+
|
|
|
+ const itemIndex = this.carts.findIndex(c => c?.id === id);
|
|
|
+ if (itemIndex === -1) return false;
|
|
|
+ const oldItem = this.carts[itemIndex];
|
|
|
+ const willBeChecked = !oldItem.checked;
|
|
|
+
|
|
|
+ // 多仓库校验失败
|
|
|
+ if (willBeChecked && this.wouldHaveMultiWarehouseIfItemChecked(oldItem)) {
|
|
|
+ // 响应式替换元素
|
|
|
+ this.$set(this.carts, itemIndex, {
|
|
|
+ ...oldItem,
|
|
|
+ checked: false
|
|
|
+ });
|
|
|
+ // 强制更新分组和视图
|
|
|
+ this.formatCartsByWarehouse();
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.$forceUpdate();
|
|
|
+ });
|
|
|
+ uni.showToast({
|
|
|
+ icon: 'none',
|
|
|
+ title: '暂不支持多仓库购买,请选择同仓库商品',
|
|
|
+ duration: 2500
|
|
|
+ });
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 正常勾选
|
|
|
+ this.$set(this.carts, itemIndex, {
|
|
|
+ ...oldItem,
|
|
|
+ checked: willBeChecked
|
|
|
+ });
|
|
|
+ this.formatCartsByWarehouse();
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.$forceUpdate();
|
|
|
+ });
|
|
|
+ },
|
|
|
+ findCartItemIndex(id) {
|
|
|
+ return this.carts.findIndex(c => c && c.id === id);
|
|
|
+ },
|
|
|
+ changeNum(e,item) {
|
|
|
+ // 🔥 修复:先找索引,再替换元素
|
|
|
+ const idx = this.carts.findIndex(c => c.id === item.id);
|
|
|
+ if(idx === -1) return;
|
|
|
+ let newNum = e.detail.value.replace(/\D/g, '') || 1;
|
|
|
+ newNum = Number(newNum);
|
|
|
+ if (newNum <= 1) {
|
|
|
+ newNum = 1;
|
|
|
+ uni.showToast({
|
|
|
+ title: "已经是底线啦!",
|
|
|
+ icon: "none",
|
|
|
+ duration: 2000
|
|
|
+ });
|
|
|
+ }
|
|
|
+ if(newNum >= item.stock){
|
|
|
+ newNum = item.stock;
|
|
|
+ }
|
|
|
+ // 响应式更新
|
|
|
+ this.$set(this.carts, idx, {
|
|
|
+ ...item,
|
|
|
+ cartNum: newNum
|
|
|
+ });
|
|
|
+ this.changeCartNum(this.carts[idx]);
|
|
|
+ },
|
|
|
+ changeCartNum(item){
|
|
|
+ let data = {number:item.cartNum,id:item.id};
|
|
|
+ cartNum(data).then(
|
|
|
+ res => {
|
|
|
+ if(res.code==200){
|
|
|
+ uni.showToast({
|
|
|
+ icon:'none',
|
|
|
+ title: "操作成功",
|
|
|
+ });
|
|
|
+ }else{
|
|
|
+ uni.showToast({
|
|
|
+ icon:'none',
|
|
|
+ title: res.msg,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ rej => {}
|
|
|
+ );
|
|
|
+ },
|
|
|
+ // 🔥 修复初始化:响应式赋值 + 批量替换元素
|
|
|
+ getCarts(){
|
|
|
+ getCarts().then(
|
|
|
+ res => {
|
|
|
+ if(res.code==200){
|
|
|
+ // 深拷贝并初始化checked为false
|
|
|
+ let newCarts = (res.carts || []).map(item => ({
|
|
|
+ ...item,
|
|
|
+ checked: false
|
|
|
+ }));
|
|
|
+ // 响应式赋值
|
|
|
+ this.carts = newCarts;
|
|
|
+ // 初始化分组
|
|
|
+ this.formatCartsByWarehouse();
|
|
|
+ }else{
|
|
|
+ uni.showToast({
|
|
|
+ icon:'none',
|
|
|
+ title: "请求失败",
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ rej => {}
|
|
|
+ );
|
|
|
+ },
|
|
|
+ delNum(item) {
|
|
|
+ const idx = this.carts.findIndex(c => c.id === item.id);
|
|
|
+ if(idx === -1) return;
|
|
|
+ let newNum = item.cartNum - 1;
|
|
|
+ if (newNum <= 1) {
|
|
|
+ newNum = 1;
|
|
|
+ uni.showToast({
|
|
|
+ title: "已经是底线啦!",
|
|
|
+ icon: "none",
|
|
|
+ duration: 2000
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 响应式更新
|
|
|
+ this.$set(this.carts, idx, {
|
|
|
+ ...item,
|
|
|
+ cartNum: newNum
|
|
|
+ });
|
|
|
+ this.changeCartNum(this.carts[idx]);
|
|
|
+ },
|
|
|
+ addNum(item) {
|
|
|
+ const idx = this.carts.findIndex(c => c.id === item.id);
|
|
|
+ if(idx === -1) return;
|
|
|
+ let newNum = item.cartNum + 1;
|
|
|
+ if(newNum >= item.stock){
|
|
|
+ newNum = item.stock;
|
|
|
+ }
|
|
|
+ // 响应式更新
|
|
|
+ this.$set(this.carts, idx, {
|
|
|
+ ...item,
|
|
|
+ cartNum: newNum
|
|
|
+ });
|
|
|
+ this.changeCartNum(this.carts[idx]);
|
|
|
+ },
|
|
|
+ submit() {
|
|
|
+ var selectCarts = this.carts.filter(ele => ele.checked === true);
|
|
|
+ if (selectCarts.length === 0) {
|
|
|
+ uni.showToast({
|
|
|
+ icon: 'none',
|
|
|
+ title: '请选择商品'
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (this.getSelectedWarehouseCount() > 1) {
|
|
|
+ uni.showToast({
|
|
|
+ icon: 'none',
|
|
|
+ title: '暂不支持多仓库购买,请选择同仓库商品',
|
|
|
+ duration: 2500
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ var cartIds = selectCarts.map(ele => ele.id).join(',');
|
|
|
+ uni.navigateTo({
|
|
|
+ url: '/pages_shopping/shopping/confirmOrder?type=cart&cartIds=' + cartIds
|
|
|
+ });
|
|
|
+ },
|
|
|
+ showProduct(item){
|
|
|
+ uni.navigateTo({
|
|
|
+ url: '/pages_shopping/shopping/productDetails?productId='+item.productId
|
|
|
+ })
|
|
|
+ },
|
|
|
+ }
|
|
|
+}
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss">
|
|
|
- page {
|
|
|
- height: 100%;
|
|
|
- }
|
|
|
- .content{
|
|
|
- height: 100%;
|
|
|
- padding: 20upx;
|
|
|
- .goods-list{
|
|
|
- .item{
|
|
|
- box-sizing: border-box;
|
|
|
- height: 221upx;
|
|
|
- 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{
|
|
|
- height: 160upx;
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- justify-content: space-between;
|
|
|
- width: calc(100% - 255upx);
|
|
|
- .title-box{
|
|
|
- width: 100%;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- .tag{
|
|
|
- padding: 0 6upx;
|
|
|
- height: 30upx;
|
|
|
- line-height: 30upx;
|
|
|
- font-size: 22upx;
|
|
|
- font-family: PingFang SC;
|
|
|
- font-weight: bold;
|
|
|
- color: #FFFFFF;
|
|
|
- background: linear-gradient(90deg, #2BC7B9 0%, #77cbf3 100%);
|
|
|
- border-radius: 4upx;
|
|
|
- margin-right: 10upx;
|
|
|
- flex-shrink: 0;
|
|
|
- }
|
|
|
- .title{
|
|
|
- flex: 1;
|
|
|
- font-size: 28upx;
|
|
|
- font-family: PingFang SC;
|
|
|
- font-weight: 500;
|
|
|
- color: #111111;
|
|
|
- line-height: 1;
|
|
|
- }
|
|
|
- }
|
|
|
- .intro{
|
|
|
- font-size: 24upx;
|
|
|
- font-family: PingFang SC;
|
|
|
- font-weight: 500;
|
|
|
- color: #999999;
|
|
|
- margin-top: 22upx;
|
|
|
- line-height: 1;
|
|
|
- }
|
|
|
- .price-num{
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: space-between;
|
|
|
- .price{
|
|
|
- display: flex;
|
|
|
- align-items: flex-end;
|
|
|
- .unit{
|
|
|
- font-size: 24upx;
|
|
|
- font-family: PingFang SC;
|
|
|
- font-weight: 500;
|
|
|
- color: #FF6633;
|
|
|
- line-height: 1.2;
|
|
|
- margin-right: 4upx;
|
|
|
- }
|
|
|
- .text{
|
|
|
- font-size: 32upx;
|
|
|
- font-family: PingFang SC;
|
|
|
- font-weight: bold;
|
|
|
- color: #FF6633;
|
|
|
- line-height: 1;
|
|
|
- }
|
|
|
- }
|
|
|
- .num-box{
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- .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 60upx;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: space-between;
|
|
|
- position: fixed;
|
|
|
- left: 0;
|
|
|
- bottom: 0rpx;
|
|
|
- z-index: 99;
|
|
|
- .left{
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- .text{
|
|
|
- margin-left: 14upx;
|
|
|
- font-size: 28upx;
|
|
|
- font-family: PingFang SC;
|
|
|
- font-weight: 500;
|
|
|
- color: #666666;
|
|
|
- line-height: 1;
|
|
|
- }
|
|
|
- }
|
|
|
- .right{
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- .total{
|
|
|
- display: flex;
|
|
|
- align-items: flex-end;
|
|
|
- margin-right: 36upx;
|
|
|
- .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: 32upx;
|
|
|
- font-family: PingFang SC;
|
|
|
- font-weight: bold;
|
|
|
- color: #FF6633;
|
|
|
- line-height: 1.2;
|
|
|
- margin-right: 10upx;
|
|
|
- }
|
|
|
- .num{
|
|
|
- font-size: 30upx;
|
|
|
- font-family: PingFang SC;
|
|
|
- font-weight: bold;
|
|
|
- color: #FF6633;
|
|
|
- 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: #2BC7B9;
|
|
|
- border-radius: 44upx;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+page {
|
|
|
+ height: 100%;
|
|
|
+}
|
|
|
+.content{
|
|
|
+ height: 100%;
|
|
|
+ padding: 20upx;
|
|
|
+ // 🔥 自定义checkbox样式
|
|
|
+ .custom-checkbox {
|
|
|
+ width: 40upx;
|
|
|
+ height: 40upx;
|
|
|
+ border: 2px solid #ddd;
|
|
|
+ border-radius: 50%;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ &.checked {
|
|
|
+ background: #2BC7B9;
|
|
|
+ border-color: #2BC7B9;
|
|
|
+ .check-icon {
|
|
|
+ color: #fff;
|
|
|
+ font-size: 24upx;
|
|
|
+ font-weight: bold;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .goods-list{
|
|
|
+ .warehouse-header{
|
|
|
+ font-size: 28upx;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #333;
|
|
|
+ padding: 16upx 0 12upx 0;
|
|
|
+ border-bottom: 1px solid #eee;
|
|
|
+ margin-bottom: 12upx;
|
|
|
+ }
|
|
|
+ .item{
|
|
|
+ box-sizing: border-box;
|
|
|
+ height: 221upx;
|
|
|
+ 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{
|
|
|
+ height: 160upx;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ justify-content: space-between;
|
|
|
+ width: calc(100% - 255upx);
|
|
|
+ .title-box{
|
|
|
+ width: 100%;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ .tag{
|
|
|
+ padding: 0 6upx;
|
|
|
+ height: 30upx;
|
|
|
+ line-height: 30upx;
|
|
|
+ font-size: 22upx;
|
|
|
+ font-family: PingFang SC;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #FFFFFF;
|
|
|
+ background: linear-gradient(90deg, #2BC7B9 0%, #77cbf3 100%);
|
|
|
+ border-radius: 4upx;
|
|
|
+ margin-right: 10upx;
|
|
|
+ flex-shrink: 0;
|
|
|
+ }
|
|
|
+ .title{
|
|
|
+ flex: 1;
|
|
|
+ font-size: 28upx;
|
|
|
+ font-family: PingFang SC;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #111111;
|
|
|
+ line-height: 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .intro{
|
|
|
+ font-size: 24upx;
|
|
|
+ font-family: PingFang SC;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #999999;
|
|
|
+ margin-top: 22upx;
|
|
|
+ line-height: 1;
|
|
|
+ }
|
|
|
+ .price-num{
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ .price{
|
|
|
+ display: flex;
|
|
|
+ align-items: flex-end;
|
|
|
+ .unit{
|
|
|
+ font-size: 24upx;
|
|
|
+ font-family: PingFang SC;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #FF6633;
|
|
|
+ line-height: 1.2;
|
|
|
+ margin-right: 4upx;
|
|
|
+ }
|
|
|
+ .text{
|
|
|
+ font-size: 32upx;
|
|
|
+ font-family: PingFang SC;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #FF6633;
|
|
|
+ line-height: 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .num-box{
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ .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 60upx;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ position: fixed;
|
|
|
+ left: 0;
|
|
|
+ bottom: 0rpx;
|
|
|
+ z-index: 99;
|
|
|
+ .left{
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ .text{
|
|
|
+ margin-left: 14upx;
|
|
|
+ font-size: 28upx;
|
|
|
+ font-family: PingFang SC;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #666666;
|
|
|
+ line-height: 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .right{
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ .total{
|
|
|
+ display: flex;
|
|
|
+ align-items: flex-end;
|
|
|
+ margin-right: 36upx;
|
|
|
+ .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: 32upx;
|
|
|
+ font-family: PingFang SC;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #FF6633;
|
|
|
+ line-height: 1.2;
|
|
|
+ margin-right: 10upx;
|
|
|
+ }
|
|
|
+ .num{
|
|
|
+ font-size: 30upx;
|
|
|
+ font-family: PingFang SC;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #FF6633;
|
|
|
+ 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: #2BC7B9;
|
|
|
+ border-radius: 44upx;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
</style>
|