一、购物车添加失败
选择"加入购物车",点击"确认加入"后

显示"加入购物车失败"

但是可以在购物车查看到刚添加的商品
原因在于购物车新增接口处有一个 if 判断,后端已经成功执行了 "添加商品到购物车" 的业务逻辑,但返回的响应数据不符合前端的成功 if 判断条件

最简单粗暴的方法:
将
javascript
context?.$toolUtil.message(res.data.msg || '加入购物车失败', 'error')
改为
javascript
context?.$toolUtil.message(res.data.msg || '加入购物车成功', 'success')
二、购物车页面选中多个商品并核算总金额进行支付
修改购物车(cart)的list.vue文件
2.1 模板部分(template)
javascript
<template>
<div>
<div class="app-contain">
<div class="list_search_view">
<el-form :model="searchQuery" class="search_form"></el-form>
<br>
<!-- 按钮+金额核算+支付按钮 容器 -->
<div class="btn_amount_wrap">
<div class="btn_view">
<el-button type="success" @click="addClick" v-if="btnAuth('cart','新增')">新增</el-button>
<el-button v-if="btnAuth('cart','查看')" type="info" :disabled="selRows.length!==1" @click="infoClick(null)">详情</el-button>
<el-button type="primary" :disabled="selRows.length!==1" @click="editClick" v-if="btnAuth('cart','修改')">修改</el-button>
<el-button type="danger" :disabled="!selRows.length" @click="delClick(null)" v-if="btnAuth('cart','删除')">删除</el-button>
</div>
<!-- 金额核算+支付按钮 -->
<div class="amount_view" v-if="btnAuth('cart','查看')">
<span class="amount_item">选中商品数:{{ selRows.length }}</span>
<span class="amount_item">原价总计:¥{{ totalOriginalPrice }}</span>
<span class="amount_item">折扣价总计:¥{{ totalDiscountPrice }}</span>
<el-button type="primary" :disabled="!selRows.length" @click="payClick" v-if="btnAuth('cart','支付')">支付</el-button>
</div>
</div>
</div>
<br>
<!-- 原有表格逻辑不变 -->
<el-table
v-loading="listLoading"
border
:stripe='true'
@selection-change="handleSelectionChange"
ref="table"
v-if="btnAuth('cart','查看')"
:data="list"
@row-click="listChange">
<el-table-column :resizable='true' align="left" header-align="left" type="selection" width="55" />
<!-- 原有列配置全部保留 -->
</el-table>
<!-- 原有分页逻辑不变 -->
<el-pagination
background
:layout="layouts.join(',')"
:total="total"
:page-size="listQuery.limit"
prev-text="上一页"
next-text="下一页"
:hide-on-single-page="false"
:style='{"width":"100%","padding":"0","margin":"20px 0 0","whiteSpace":"nowrap","color":"#333","fontWeight":"500"}'
@size-change="sizeChange"
@current-change="currentChange"
@prev-click="prevClick"
@next-click="nextClick" />
</div>
<formModel ref="formRef" @formModelChange="formModelChange"></formModel>
</div>
</template>
2.2 脚本部分(script setup)
javascript
<script setup>
import axios from 'axios'
import {
reactive,
ref,
getCurrentInstance,
nextTick,
onMounted,
watch,
computed // 新增:导入计算属性
} from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ElMessageBox } from 'element-plus'
const context = getCurrentInstance()?.appContext.config.globalProperties;
import formModel from './formModel.vue'
// 基础信息
const tableName = 'cart'
const formName = '购物车'
const route = useRoute()
// 列表数据
const list = ref(null)
const table = ref(null)
const listQuery = ref({
page: 1,
limit: 20,
sort: 'id',
order: 'desc'
})
const searchQuery = ref({})
const selRows = ref([]) // 选中的商品行
const listLoading = ref(false)
// 新增:计算选中商品的金额(响应式,实时更新)
const totalOriginalPrice = computed(() => {
if (!selRows.value.length) return '0.00';
// 原价总和 = 单价 × 购买数量 求和
return selRows.value.reduce((sum, item) => {
const price = Number(item.price) || 0;
const buynumber = Number(item.buynumber) || 0;
return sum + (price * buynumber);
}, 0).toFixed(2);
});
const totalDiscountPrice = computed(() => {
if (!selRows.value.length) return '0.00';
// 折扣价总和 = 折扣价 × 购买数量 求和
return selRows.value.reduce((sum, item) => {
const discountprice = Number(item.discountprice) || 0;
const buynumber = Number(item.buynumber) || 0;
return sum + (discountprice * buynumber);
}, 0).toFixed(2);
});
// 原有方法:行点击选中
const listChange = (row) =>{
nextTick(()=>{
table.value.clearSelection()
table.value.toggleRowSelection(row)
})
}
// 原有方法:获取列表数据
const getList = () => {
listLoading.value = true
let params = JSON.parse(JSON.stringify(listQuery.value))
params['sort'] = 'id'
params['order'] = 'desc'
context?.$http({
url: `${tableName}/page`,
method: 'get',
params: params
}).then(res => {
listLoading.value = false
list.value = res.data.data.list
total.value = Number(res.data.data.total)
})
}
// 新增:支付点击事件
const payClick = () => {
const selectedIds = selRows.value.map(item => item.id); // 选中商品ID
// 支付确认弹窗
ElMessageBox.confirm(
`确认支付选中的${selRows.value.length}件商品?
原价总计:¥${totalOriginalPrice.value} | 折扣价总计:¥${totalDiscountPrice.value}`,
'支付确认',
{
confirmButtonText: '确认支付',
cancelButtonText: '取消',
type: 'warning'
}
).then(() => {
// 调用支付接口(需后端配合实现 /cart/pay)
context?.$http({
url: `${tableName}/pay`,
method: 'post',
data: {
ids: selectedIds, // 选中商品ID数组
totalAmount: totalDiscountPrice.value, // 支付金额
originalAmount: totalOriginalPrice.value // 原价(备用)
}
}).then(res => {
context?.$toolUtil.message('支付成功', 'success', () => {
getList(); // 支付成功后刷新列表
});
}).catch(err => {
const errMsg = err?.response?.data?.msg || '支付失败,请稍后重试';
context?.$toolUtil.message(errMsg, 'error');
});
}).catch(() => {
context?.$toolUtil.message('已取消支付', 'info');
});
}
// 原有方法:删除、多选、分页、权限、表单等逻辑全部保留
const delClick = (id) => { /* 原有逻辑 */ }
const handleSelectionChange = (e) => { selRows.value = e }
const sizeChange = (size) => { /* 原有逻辑 */ }
const currentChange = (page) => { /* 原有逻辑 */ }
const prevClick = () => { /* 原有逻辑 */ }
const nextClick = () => { /* 原有逻辑 */ }
const btnAuth = (e,a)=>{ return context?.$toolUtil.isAuth(e,a) }
const searchClick = () => { /* 原有逻辑 */ }
const addClick = ()=>{ /* 原有逻辑 */ }
const editClick = ()=>{ /* 原有逻辑 */ }
const infoClick = (id=null)=>{ /* 原有逻辑 */ }
const preClick = (file) =>{ /* 原有逻辑 */ }
const download = (file) => { /* 原有逻辑 */ }
// 初始化
const init = () => { getList() }
init()
</script>
2.3 样式部分(scss)
javascript
<style lang="scss" scoped>
// 新增:按钮+金额容器样式
.btn_amount_wrap {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
flex-wrap: wrap;
gap: 10px;
}
// 新增:金额展示区域
.amount_view {
display: flex;
align-items: center;
gap: 15px;
flex-wrap: wrap;
.amount_item {
color: #333;
font-size: 14px;
font-weight: 500;
&:nth-child(2) {
color: #d26558; // 原价红色突出
}
&:nth-child(3) {
color: #5B8DEE; // 折扣价蓝色突出
font-weight: bold;
}
}
}
// 原有样式全部保留(以下仅展示关键部分)
.list_search_view {
margin: 0 0 20px;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
.btn_view {
margin: 0;
display: flex;
// 原有按钮样式...
}
}
.el-table { /* 原有表格样式 */ }
.el-pagination { /* 原有分页样式 */ }
</style>

2.4 修改说明
2.4.1 金额计算逻辑
- 原价总和:每个商品的「单价 × 购买数量」求和,保留 2 位小数
- 折扣价总和:每个商品的「折扣价 × 购买数量」求和,保留 2 位小数
- 使用computed计算属性,监听selRows变化,实现金额实时更新
2.4.2 支付功能核心
- 支付按钮仅在selRows.length > 0(选中商品)时启用
- 点击支付弹出确认弹窗,展示选中商品数和金额
- 调用后端/cart/pay接口(需后端实现),传递选中商品 ID 和支付金额
- 支付成功 / 失败均给出提示,成功后刷新列表
2.4.3 兼容性与鲁棒性
- 对price/discountprice/buynumber做Number()转换,避免 NaN
- 空值处理:未选中商品时金额默认显示0.00
- 样式适配:使用flex-wrap: wrap,适配小屏幕布局
2.4.4 后端接口
- 需后端新增/cart/pay接口
2.5 第二次修改
核心修改:复用项目统一的 payForm 支付组件(和订单页面保持一致),而非直接调用接口;优化金额计算、参数传递逻辑,保证代码规范和可维护性。
2.5.1 模板部分(template)

2.5.2 (script setup)


