下面看一下开发的这个系统。
一,系统界面
二,系统核心代码展示
// 小孟v:jishulearn <template> <view class="cart"> <!--<view class="header" :style="{ position: headerPosition, top: headerTop }">--> <!--<view class="title">购物车</view>--> <!--</view>--> <!--<!– 占位 –>--> <!--<view class="place"></view>--> <!-- 购物车为空 --> <view v-if="cartList.length === 0" class="empty"> <text class="iconfont icongouwuche" :class="'text-'+themeColor.name"></text> <view v-if="hasLogin" class="empty-tips"> 空空如也 <navigator class="navigator" :class="'text-'+themeColor.name" v-if="hasLogin" url="../category/category" open-type="switchTab" >随便逛逛></navigator > </view> <view v-else class="empty-tips"> 空空如也 <view class="navigator" :class="'text-'+themeColor.name" @tap="navTo('/pages/public/logintype')" >登录/注册 ></view > </view> </view> <!-- 购物车列表 --> <view class="goods-list" v-else> <view class="rf-cart-row" v-for="(row, index) in cartList" :key="index"> <!-- 删除按钮 --> <view class="menu" @tap.stop="deleteCartItem(row.id, 'one')" :class="'bg-'+themeColor.name"> <text class="iconfont icon iconiconfontshanchu1"></text> </view> <!-- 商品 --> <view class="carrier" :class="[ theIndex === index ? 'open' : oldIndex === index ? 'close' : '' ]" @touchstart="touchStart(index, $event)" @touchmove="touchMove(index, $event)" @touchend="touchEnd(index, $event)" > <!-- checkbox --> <view class="checkbox-box" @tap="selected(index, row)"> <view class="checkbox" :class="[ parseInt(row.status, 10) === 0 ? `checkbox-disabled ${'text-'+themeColor.name}` : 'text-'+themeColor.name ]" > <view :class="[row.selected ? `on ${'bg-'+themeColor.name}` : '']"></view> </view> </view> <!-- 商品信息 --> <view class="goods-info"> <view class="img"> <image :src="row.productPic"></image> </view> <view class="info"> <view class="title in2line" @tap="navTo(`/pages/product/product?id=${row.product.id}`)" > {{ row.productName }} </view> <view class="state-wrapper"> <view class="spec" @tap.stop="toggleSpec(row)">{{ row.productAttr|attrFilter}}</view> <view class="state" v-if="parseInt(row.status, 10) === 0"> 已失效 </view> </view> <view class="price-number"> <view class="price">{{ moneySymbol }}{{ row.price }}</view> <view class="remark" >{{ row.remark }}</view> <view class="number" > <view class="sub" @tap.stop="sub(row, index)"> <text class="iconfont icon icon-jianhao"></text> </view> <view class="input" @tap.stop="discard"> <input type="number" :class="'text-'+themeColor.name" v-model="row.quantity" @input.stop="numberChange(row, $event, index)" /> </view> <view class="add" @tap.stop="add(row, index)"> <text class="iconfont icon iconjia1"></text> </view> </view> </view> </view> </view> </view> </view> </view> <!-- 脚部菜单 --> <view class="footer" :style="{ bottom: footerbottom }" v-if="cartList.length !== 0" > <view class="checkbox-box" @tap="allSelect"> <view class="checkbox" :class="'text-'+themeColor.name"> <view :class="[isAllselected ? `on ${'bg-'+themeColor.name}` : '']"></view> </view> <view class="text">全选</view> </view> <view class="delBtn" :class="'text-'+themeColor.name" @tap="deleteCartItem" v-if="selectedList.length > 0" >删除</view > <view class="settlement"> <view class="sum" >合计: <view class="money">{{ moneySymbol }}{{ sumPrice }}</view> </view> <view class="btn" :class="'bg-'+themeColor.name" @tap="createOrder" >结算({{ selectedList.length }})</view > </view> </view> <!-- 规格-模态层弹窗 --> <view class="popup spec show" v-if="specClass === 'show'" @touchmove.stop.prevent="stopPrevent" @tap="hideSpec" > <!-- 遮罩层 --> <view class="mask" @tap="hideSpec"></view> <view class="layer" @tap.stop="stopPrevent"> <rf-attr-content :isSelectedNum="false" :product="productDetail" @toggle="toggleSpec" ></rf-attr-content> </view> </view> <!--页面加载动画--> <rfLoading isFullScreen :active="loading"></rfLoading> </view> </template> <script> import { cartItemClear, cartItemDel, cartItemList, cartItemUpdateNum, cartItemUpdateSku, productDetail } from '@/api/product'; import rfAttrContent from '@/components/rf-attr-content'; import { mapMutations } from 'vuex'; export default { components: { rfAttrContent }, filters:{ attrFilter(val){ if(!val) return ; val = JSON.parse(val); let res = []; val.map(v=>{ res.push(v.value); }) return res.join(','); } }, data() { return { sumPrice: '0.00', headerPosition: 'fixed', headerTop: null, statusTop: null, showHeader: true, selectedList: [], isAllselected: false, // 控制滑动效果 theIndex: null, oldIndex: null, isStop: false, cartList: [], hasLogin: null, footerbottom: 0, specClass: 'none', productDetail: { base_attribute_format: [], sku: [] }, specSelected: [], specChildList: [], specList: [], currentSkuId: '', moneySymbol: this.moneySymbol, loading: true, singleSkuText: this.singleSkuText }; }, onPageScroll(e) { // 兼容iOS端下拉时顶部漂移 this.headerPosition = e.scrollTop >= 0 ? 'fixed' : 'absolute'; this.headerTop = e.scrollTop >= 0 ? null : 0; this.statusTop = e.scrollTop >= 0 ? null : -this.statusHeight + 'px'; }, // 下拉刷新,需要自己在page.json文件中配置开启页面下拉刷新 "enablePullDownRefresh": true onPullDownRefresh() { this.selectedList.length = 0; this.isAllselected = false; this.sumPrice = 0; this.getCartItemList('refresh'); }, onShow() { // 兼容H5下结算条位置 // #ifdef H5 this.footerbottom = document.getElementsByTagName('uni-tabbar')[0].offsetHeight + 'px'; // #endif // #ifdef APP-PLUS this.showHeader = false; // eslint-disable-next-line this.statusHeight = plus.navigator.getStatusbarHeight(); // #endif this.initData(); }, methods: { ...mapMutations(['setCartNum']), // 规格弹窗开关 toggleSpec(row) { if (parseInt(row.status, 10) === 0) return; if (this.specClass === 'show') { if (!this.hasLogin) { this.specClass = 'none'; this.$mHelper.toast('请先登录!'); return; } this.handleCartItemUpdateSku(this.currentSkuId, row.skuId); this.specClass = 'hide'; setTimeout(() => { this.specClass = 'none'; }, 250); } else if (this.specClass === 'none') { if (row) { this.getProductDetail(row); } } }, // 获取产品详情 async getProductDetail(row) { this.currentSkuId = row.sku_id; await this.$http .get(`${productDetail}`, { id: row.product_id }) .then(async r => { this.productDetail = r.data; this.productDetail.sku_name = row.sku_name; this.specClass = 'show'; }); }, hideSpec() { this.specClass = 'hide'; setTimeout(() => { this.specClass = 'none'; }, 250); }, stopPrevent() {}, // 删除选中购物车商品 async deleteCartItem(id, type) { let ids = []; for (let i = 0; i < this.cartList.length; i++) { if (this.cartList[i].selected) { ids.push(parseInt(this.cartList[i].id, 10)); } } await this.$http2.post("cart/delete",{ids},{ header:{ 'content-type':'application/x-www-form-urlencoded' } }); this.selectedList.length = 0; this.isAllselected = false; this.sumPrice = 0; this.getCartItemList(); this.oldIndex = null; this.theIndex = null; // await this.$http // .post(`${cartItemDel}`, { // sku_ids: JSON.stringify(skuIds) // }) // .then(() => { // this.selectedList.length = 0; // this.isAllselected = false; // this.sumPrice = 0; // this.getCartItemList(); // this.oldIndex = null; // this.theIndex = null; // }); }, // 修改购物车商品sku async handleCartItemUpdateSku(skuId, newSkuId) { await this.$http .post(`${cartItemUpdateSku}`, { sku_id: skuId, new_sku_id: newSkuId }) .then(() => { this.selectedList.length = 0; this.isAllselected = false; this.sumPrice = 0; this.getCartItemList(); }); }, // 数据初始化 initData() { this.hasLogin = this.$mStore.getters.hasLogin; if (this.hasLogin) { this.theIndex = null; this.oldIndex = null; this.selectedList.length = 0; this.isAllselected = false; this.sumPrice = 0; this.getCartItemList(); } else { this.cartList = []; this.selectedList.length = 0; this.loading = false; } }, // 通用跳转 navTo(route) { if (!this.$mStore.getters.hasLogin) { uni.setStorageSync('backToPage', JSON.stringify({ route: '/pages/cart/cart' })); } this.$mRouter.push({ route }); }, // 获取购物车列表 async getCartItemList(type) { let r = await this.$http2.get('cart/list').catch(() => { this.cartList = []; this.loading = false; if (type === 'refresh') { uni.stopPullDownRefresh(); } }); this.loading = false; this.cartList = r.data; this.$set(this,'cartList',[...r.data]); // 清空购物车 clearCart(params) { const content = params ? '清空失效商品?' : '清空购物车?'; uni.showModal({ content, success: async e => { if (e.confirm) { await this.$http.post(`${cartItemClear}`, params).then(() => { this.selectedList.length = 0; this.isAllselected = false; this.sumPrice = 0; this.getCartItemList(); }); } } }); }, // 控制左滑删除效果 touchStart(index, event) { // 多点触控不触发 if (event.touches.length > 1) { this.isStop = true; return; } this.oldIndex = this.theIndex; this.theIndex = null; // 初始坐标 this.initXY = [event.touches[0].pageX, event.touches[0].pageY]; },