| | |
| | | <template> |
| | | <div>购物车</div> |
| | | <div class="personalPage-box"> |
| | | <div class="personalPage-title">我的购物车</div> |
| | | <div class="personalPage-content"> |
| | | <div class="deleteBox"> |
| | | <el-dialog |
| | | v-model="dialogVisible" |
| | | width="30%" |
| | | draggable |
| | | align-center |
| | | :modal="false" |
| | | > |
| | | <span> |
| | | <el-icon style="color: orange"> <Warning /> </el-icon |
| | | >确认要删除选中的商品吗?</span |
| | | > |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button @click="dialogVisible = false">取消</el-button> |
| | | <el-button type="primary" @click="handleDelete"> 确定 </el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <el-dialog v-model="showHide" width="30%" draggable align-center :modal="false"> |
| | | <span |
| | | ><el-icon style="color: orange"> <Warning /> </el-icon |
| | | >确认要删除选中的商品吗?</span |
| | | > |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button @click="showHide = false">取消</el-button> |
| | | <el-button type="primary" @click="confirmEvent"> 确定 </el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | |
| | | <div class="breadcrumbsBox"> |
| | | <p> |
| | | 位置: <span>购物车({{ total }})</span> |
| | | </p> |
| | | </div> |
| | | <div class="selectproduct"> |
| | | <el-table |
| | | ref="multipleTableRef" |
| | | :data="shoppingCartData" |
| | | style="width: 100%" |
| | | @selection-change="handleSelectionChange" |
| | | :cell-style="cellStyle" |
| | | v-loading="loading" |
| | | > |
| | | <template v-slot:empty> |
| | | <el-empty class="noData" image-size="100" description="暂无数据" /> |
| | | </template> |
| | | |
| | | <el-table-column type="selection" width="30" /> |
| | | |
| | | <el-table-column label="全选" width="200"> |
| | | <template #default="scope"> |
| | | <div style="position: relative; width: 110px"> |
| | | <el-image |
| | | :src="scope.row.imgUrl ? scope.row.imgUrl : defaultImg" |
| | | class="bookImg" |
| | | > |
| | | </el-image> |
| | | <div |
| | | class="labelBox" |
| | | :style="{ |
| | | background: scope.row.type == 'product' ? '#019e58 ' : '#5f92fd', |
| | | }" |
| | | > |
| | | <p>{{ scope.row.typeTxt }}</p> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | property="name" |
| | | label="商品信息" |
| | | width="300" |
| | | :cell-style="{ margin: '30px' }" |
| | | /> |
| | | <el-table-column property="productType" label="商品类型" width="300" /> |
| | | <el-table-column label="价格"> |
| | | <template #default="scope">¥{{ scope.row.unitprice.toFixed(2) }}</template> |
| | | </el-table-column> |
| | | <el-table-column label="操作"> |
| | | <template #default="scope"> |
| | | <span @click="dialog(scope.$index, scope.row)" class="deleteBtn">删除</span> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </div> |
| | | <div class="settlement"> |
| | | <div class="box"> |
| | | <div class="gaugeOutfit"> |
| | | <div class="leftBox"> |
| | | <el-checkbox |
| | | v-if="shoppingCartData.length" |
| | | class="checkbox" |
| | | v-model="selectAll" |
| | | label="全选" |
| | | name="type" |
| | | @change="toggleAllSelection" |
| | | /> |
| | | <el-checkbox |
| | | v-else |
| | | class="checkbox" |
| | | v-model="select" |
| | | disabled |
| | | label="全选" |
| | | name="type" |
| | | @change="toggleAllSelection" |
| | | /> |
| | | <el-button class="buttonBox" @click="batchDelete">批量删除</el-button> |
| | | </div> |
| | | |
| | | <div class="rightBox"> |
| | | <p> |
| | | 已选择 <span>{{ selectedItemCount }}</span> 件商品 |
| | | </p> |
| | | <p> |
| | | 总价:<span v-if="sumUnitprice">¥{{ sumUnitprice.toFixed(2) }}</span> |
| | | <span v-else>¥0.00</span> |
| | | </p> |
| | | <el-button class="button" type="warning" @click="goPaymentPage" |
| | | >结算</el-button |
| | | > |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { onMounted, ref, inject, watch } from "vue"; |
| | | import { ElTable, ElMessage } from "element-plus"; |
| | | import { reactive } from "vue"; |
| | | import { useRouter } from "vue-router"; |
| | | import { InfoFilled } from "@element-plus/icons-vue"; |
| | | import { useUserStore, useBreadcrumbStore } from "@/store"; |
| | | import { getPublicImage } from "@/assets/js/middleGround/tool.js"; |
| | | import defaultImg from "@/assets/images/default-book-img.png"; |
| | | const dialogVisible = ref(false); |
| | | const crumbStore = useBreadcrumbStore(); |
| | | const router = useRouter(); |
| | | const userStore = useUserStore(); |
| | | const MG = inject("MG"); |
| | | const total = ref(); |
| | | const multipleTableRef = ref(); |
| | | const loading = ref(true); |
| | | const selectAll = ref(false); |
| | | const multipleSelection = ref([]); |
| | | const orderNumber = ref(); |
| | | const select = ref(false); |
| | | const showHide = ref(false); |
| | | const selectedItemCount = ref(0); // 新增一个变量用于存储已选商品数量 |
| | | const sumUnitprice = ref(); |
| | | |
| | | watch(multipleSelection, (newSelection) => { |
| | | // 当 multipleSelection.value 发生变化时触发的回调函数 |
| | | let sum = 0; |
| | | newSelection.forEach((item) => { |
| | | sum += item.unitprice; |
| | | }); |
| | | |
| | | sumUnitprice.value = sum; |
| | | |
| | | selectedItemCount.value = newSelection.length; |
| | | }); |
| | | |
| | | onMounted(() => { |
| | | shoppingCartGet(); |
| | | // totalPrice() |
| | | }); |
| | | const batchDelete = (evt) => { |
| | | let target = evt.target; |
| | | if (target.nodeName == "SPAN") { |
| | | target = evt.target.parentNode; |
| | | } |
| | | target.blur(); |
| | | if (multipleSelection.value.length === 0) { |
| | | // 如果没有选择任何商品,可以在此处给出提示或者直接返回 |
| | | ElMessage({ |
| | | message: "未选择商品", |
| | | type: "warning", |
| | | }); |
| | | } else { |
| | | showHide.value = true; |
| | | // showHide.value = false |
| | | } |
| | | }; |
| | | |
| | | const handleSelectionChange = (val) => { |
| | | // console.log(val); |
| | | |
| | | multipleSelection.value = val; |
| | | // 判断是否全部选择 |
| | | if (!delShoppingSelec.value) { |
| | | if (val.length === shoppingCartData.length) { |
| | | selectAll.value = true; |
| | | } else { |
| | | selectAll.value = false; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // 切换所有行选中状态的方法 |
| | | const toggleAllSelection = () => { |
| | | if (shoppingCartData.length === 0) { |
| | | selectAll.value = false; |
| | | |
| | | ElMessage({ |
| | | message: "没有可选择的商品", |
| | | type: "warning", |
| | | }); |
| | | } else { |
| | | multipleTableRef.value.toggleAllSelection(); |
| | | } |
| | | }; |
| | | const selectedRow = ref(); |
| | | const dialog = (index, row) => { |
| | | dialogVisible.value = true; |
| | | |
| | | // 将当前行数据存储起来,以备删除时使用 |
| | | selectedRow.value = row; |
| | | }; |
| | | |
| | | const handleDelete = () => { |
| | | const row = selectedRow.value; |
| | | dialogVisible.value = false; |
| | | MG.store |
| | | .delShoppingCart({ |
| | | ids: [row.id], |
| | | }) |
| | | .then((res) => { |
| | | shoppingCartGet(); |
| | | ElMessage({ |
| | | message: "删除成功", |
| | | type: "success", |
| | | }); |
| | | //更新购物车数量 |
| | | userStore.updateRightPop(); |
| | | }) |
| | | .catch((error) => { |
| | | ElMessage.error("删除失败"); |
| | | }); |
| | | }; |
| | | |
| | | //表单的样式 |
| | | const cellStyle = ({ row, column, rowIndex, columnIndex }) => { |
| | | if (columnIndex === 4) { |
| | | return { color: "#FF6C00" }; |
| | | } |
| | | }; |
| | | |
| | | const shoppingCartData = reactive([]); |
| | | |
| | | const shoppingCartGet = () => { |
| | | let query = { |
| | | start: 0, |
| | | size: 999, |
| | | filterList: [], |
| | | searchList: [], |
| | | }; |
| | | MG.store.getShoppingCartProductList(query).then((res) => { |
| | | const newData = res.datas.map((item) => { |
| | | console.log(item.saleMethod.type, "item.saleMethod.type"); |
| | | if (item.productMonWithLinkDto.links[0].storeRefCode == "jsek_digitalTextbooks") { |
| | | item.typeTxt = "数字教材"; |
| | | item.productType = "数字教材"; |
| | | } else if ( |
| | | item.productMonWithLinkDto.links[0].storeRefCode == "jsek_digitalCourses" |
| | | ) { |
| | | item.typeTxt = "数字课程"; |
| | | item.productType = "数字课程"; |
| | | } else { |
| | | item.typeTxt = "电子书"; |
| | | item.productType = "图书服务-电子书"; |
| | | } |
| | | |
| | | // console.log(item.saleMethod.id); |
| | | console.log(item.saleMethod.type, "item.saleMethod.type"); |
| | | return { |
| | | saleMethodId: item.saleMethod.id, |
| | | id: item.id, |
| | | name: |
| | | item.linkCmsItems.length && item.linkCmsItems[0].name |
| | | ? item.productMonWithLinkDto.product.name + ":" + item.linkCmsItems[0].name |
| | | : item.productMonWithLinkDto.product.name, |
| | | type: item.saleMethod.type == "createProductItemSaleMethod" ? "item" : "product", |
| | | typeTxt: item.typeTxt, |
| | | productType: item.productType, |
| | | imgUrl: getPublicImage(item.productMonWithLinkDto.product.icon, "", "160"), |
| | | unitprice: item.saleMethod.price, |
| | | expire: |
| | | new Date(item.saleMethod.endDate).getTime() < new Date().getTime() || |
| | | new Date().getTime() < new Date(item.saleMethod.beginDate).getTime() |
| | | ? true |
| | | : false, |
| | | }; |
| | | }); |
| | | |
| | | // 重新赋值 shoppingCartData.value |
| | | shoppingCartData.splice(0, shoppingCartData.length, ...newData); |
| | | loading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | //跳转面包屑 |
| | | const goPaymentPage = async () => { |
| | | try { |
| | | // console.log(multipleSelection.value, 346588998) |
| | | let expire = multipleSelection.value.filter((item) => item.expire == true); |
| | | if (expire.length > 0) { |
| | | ElMessage({ |
| | | message: "您选择的商品有不在有效期内的,请重新选择可购买商品!", |
| | | type: "warning", |
| | | }); |
| | | } else { |
| | | const selectedIds = multipleSelection.value.map((item) => item.id); |
| | | const saleMethodId = multipleSelection.value.map((item) => item.saleMethodId); |
| | | |
| | | console.log(saleMethodId, 789); |
| | | |
| | | let queryCreateOrder = { linkIds: selectedIds }; |
| | | const createOrderResult = await MG.store.shoppingCartCreateOrder(queryCreateOrder); |
| | | orderNumber.value = createOrderResult.orderNumber; |
| | | |
| | | if (selectedIds.length) { |
| | | let crumbs = { |
| | | name: "订单支付", // 面包屑名称 |
| | | pathName: "paymentPage", // 面包屑跳转路由,可传递 pathName 或 path |
| | | isCrumbs: true, // 面包屑点击跳转时是否创建新的面包屑记录 |
| | | type: "shoppingCart", // 如果需要创建新的面包屑记录,创建的type |
| | | }; |
| | | // 在全局数据中设置面包屑 |
| | | crumbStore.setCrumbs({ |
| | | type: "shoppingCart", |
| | | data: [crumbs], |
| | | callback: (key) => { |
| | | router.push({ |
| | | name: "paymentPage", |
| | | query: { |
| | | crumbsKey: key, |
| | | orderNumber: orderNumber.value, |
| | | // type: route.query.type, |
| | | type: "shoppingCart", |
| | | onNorderSaleMethod: saleMethodId, |
| | | }, |
| | | }); |
| | | }, |
| | | }); |
| | | } else { |
| | | ElMessage({ |
| | | message: "请选择商品", |
| | | type: "warning", |
| | | }); |
| | | } |
| | | } |
| | | } catch (error) { |
| | | console.error(error); |
| | | // 错误处理逻辑 |
| | | } |
| | | }; |
| | | |
| | | const delShoppingSelec = ref(); |
| | | |
| | | const confirmEvent = () => { |
| | | showHide.value = false; |
| | | if (multipleSelection.value.length === 0) { |
| | | // 如果没有选择任何商品,可以在此处给出提示或者直接返回 |
| | | return; |
| | | } else { |
| | | const selectedIds = multipleSelection.value.map((item) => item.id); |
| | | MG.store |
| | | .delShoppingCart({ ids: selectedIds }) |
| | | .then((res) => { |
| | | delShoppingSelec.value = res; |
| | | ElMessage({ |
| | | message: "批量删除成功", |
| | | type: "success", |
| | | }); |
| | | selectAll.value = false; |
| | | // 删除成功后,刷新购物车列表 |
| | | shoppingCartGet(); |
| | | //更新购物车数量 |
| | | userStore.updateRightPop(); |
| | | }) |
| | | .catch((error) => { |
| | | console.error("批量删除失败", error); |
| | | ElMessage.error("批量删除失败"); |
| | | }); |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="less" scoped> |
| | | .deleteBtn { |
| | | cursor: pointer; |
| | | color: #019e58; |
| | | } |
| | | |
| | | page { |
| | | position: relative; |
| | | min-height: calc(100vh - 430px); |
| | | } |
| | | |
| | | .bookImg { |
| | | box-shadow: 0px 3px 6px 1px rgba(0, 0, 0, 0.16); |
| | | |
| | | /deep/ .el-image__inner { |
| | | object-fit: contain !important; |
| | | } |
| | | } |
| | | |
| | | .settlement { |
| | | width: 100%; |
| | | box-shadow: 0px -2px 10px 1px rgba(0, 0, 0, 0.08); |
| | | |
| | | position: sticky; |
| | | |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | background-color: #fff; |
| | | z-index: 2; |
| | | |
| | | .box { |
| | | position: relative; |
| | | |
| | | .gaugeOutfit { |
| | | padding-left: 12px; |
| | | box-shadow: 0px -2px 5px 1px rgba(0, 0, 0, 0.02); |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | position: sticky; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | z-index: 2; |
| | | background-color: #fff; |
| | | height: 60px; |
| | | |
| | | .leftBox { |
| | | display: flex; |
| | | flex-direction: row; |
| | | |
| | | .checkbox { |
| | | margin-right: 20px; |
| | | } |
| | | |
| | | /deep/ .el-checkbox__input.is-checked + .el-checkbox__label { |
| | | color: #000 !important; |
| | | } |
| | | } |
| | | |
| | | .rightBox { |
| | | display: flex; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | |
| | | p { |
| | | margin: 0 10px; |
| | | font-size: 14px; |
| | | |
| | | span { |
| | | color: #019e58; |
| | | font-size: 18px; |
| | | } |
| | | } |
| | | |
| | | .button { |
| | | margin-left: 50px; |
| | | background-color: #019e58; |
| | | width: 150px; |
| | | height: 50px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .selected { |
| | | display: flex; |
| | | justify-content: center; |
| | | height: 200px; |
| | | min-width: 1370px; |
| | | width: 1370px; |
| | | margin: 0 auto; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .selectproduct { |
| | | margin-top: 30px; |
| | | } |
| | | |
| | | ::v-deep { |
| | | .el-checkbox__label { |
| | | margin-left: 6px; |
| | | color: #000; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .el-table td.el-table__cell div { |
| | | margin-right: 20px; |
| | | } |
| | | |
| | | .el-table th { |
| | | background-color: #f3f3f3; |
| | | color: #000; |
| | | } |
| | | |
| | | .el-table td { |
| | | color: #333333; |
| | | } |
| | | |
| | | .el-table--enable-row-transition .el-table__body td.el-table__cell { |
| | | height: 180px; |
| | | } |
| | | |
| | | .el-checkbox__inner { |
| | | width: 16px; |
| | | height: 16px; |
| | | } |
| | | |
| | | .el-image__inner { |
| | | box-shadow: 0px 0px 20px 1px #ccc; |
| | | object-fit: contain !important; |
| | | width: 110px; |
| | | height: 140px; |
| | | } |
| | | |
| | | .el-icon { |
| | | margin-right: 10px; |
| | | font-size: 20px; |
| | | position: relative; |
| | | top: 3px; |
| | | left: 0px; |
| | | } |
| | | |
| | | .deleteBox { |
| | | .el-dialog.is-align-center { |
| | | width: 350px; |
| | | } |
| | | |
| | | .el-dialog__body { |
| | | display: flex; |
| | | justify-content: center; |
| | | font-size: 16px; |
| | | } |
| | | } |
| | | |
| | | .el-table__inner-wrapper::before { |
| | | height: 0px; |
| | | } |
| | | } |
| | | |
| | | .labelBox { |
| | | // width: 50px; |
| | | padding: 0 4px; |
| | | height: 25px; |
| | | color: #fff; |
| | | position: absolute; |
| | | top: 0; |
| | | right: 0; |
| | | margin: 0 !important; |
| | | border-radius: 0px 0px 0px 5px; |
| | | |
| | | p { |
| | | display: flex; |
| | | justify-content: center; |
| | | } |
| | | } |
| | | |
| | | .breadcrumbsBox { |
| | | height: 60px; |
| | | border-bottom: 1px solid #f5f5f5; |
| | | |
| | | p { |
| | | line-height: 60px; |
| | | font-size: 14px; |
| | | color: #545c63; |
| | | } |
| | | } |
| | | |
| | | .noData { |
| | | font-size: 26px; |
| | | font-weight: bold; |
| | | display: flex; |
| | | justify-content: center; |
| | | margin: 0 auto; |
| | | } |
| | | </style> |