完成购物车功能

This commit is contained in:
TOP糯米 2023-03-10 00:44:07 +08:00
parent 2ae6828745
commit e1b25a3d2a
12 changed files with 314 additions and 97 deletions

View File

@ -28,7 +28,13 @@
:style="{ height: index == data.length - 1 ? wrapHeight + 'px' : 'auto' }"
>
<cate-tmpl v-if="cateType === 'cate'" :parentId="item.id" :data="item" @clickItem="clickItem"></cate-tmpl>
<list-tmpl v-if="cateType === 'list'" :parentId="item.id" :data="item" @clickItem="clickItem"></list-tmpl>
<list-tmpl
v-if="cateType === 'list'"
:parentId="item.id"
:data="item"
@clickItem="clickItem"
@changeNumber="changeNumber"
></list-tmpl>
</view>
</view>
</scroll-view>
@ -199,6 +205,12 @@ export default {
clickItem(parentId, id) {
this.$emit("clickItem", parentId, id);
},
/**
* 改变数量
*/
changeNumber(e, id) {
this.$emit("changeNumber", e, id);
},
},
};
</script>

View File

@ -6,7 +6,11 @@
<view class="item-container">
<view class="thumb-box" v-for="(item, index) in data.child" :key="index">
<service-preview-item :data="item" @clickItem="clickItem" />
<widget-count-modify class="component-add" />
<widget-count-modify
:init="briefCart.list[item.id] || 0"
class="component-add"
@change="changeCount($event, item.id)"
/>
</view>
</view>
</view>
@ -15,6 +19,7 @@
<script>
import WidgetCountModify from "@/components/widgets/count-modify";
import ServicePreviewItem from "@/components/service/preview-item";
import { mapState } from "vuex";
export default {
name: "component-cate-template-list",
data() {
@ -30,6 +35,11 @@ export default {
default: [],
},
},
computed: {
...mapState({
briefCart: (state) => state.cart.briefCart,
}),
},
components: {
WidgetCountModify,
ServicePreviewItem,
@ -41,6 +51,9 @@ export default {
clickItem(id) {
this.$emit("clickItem", this.parentId, id);
},
changeCount(e, id) {
this.$emit("changeNumber", e, id);
}
},
};
</script>

View File

@ -38,6 +38,11 @@ export default {
},
mounted() {},
destroyed() {},
watch: {
init(value) {
this.number = value;
}
},
methods: {
sub() {
if (this.number > this.min) {

View File

@ -98,12 +98,25 @@ export default {
},
order: {
cart: {
add: {
count: {
url: "/order/myshoppingcarcount",
},
toCart: {
url: "/order/addshoppingcar",
showLoading: true,
},
add: {
url: "/order/shoppingcarpush",
},
sub: {
url: "/order/shoppingcarsend",
},
delete: {
url: "/order/deleteshoppingcar",
},
list: {
url: "/order/myshoppingcar"
url: "/order/myshoppingcar",
showLoading: true,
},
},
pay: {

View File

@ -3,33 +3,81 @@ let prototype = Vue.prototype;
export default {
/**
* 添加到购物车
* 获取总数
*/
add(id) {
count(id, type) {
return new Promise((resolve, reject) => {
prototype.$request({
api: "order.cart.add",
api: "order.cart.count",
}).then((response) => {
return resolve(response.data.count);
}).catch(e => { });
});
},
/**
* 添加到购物车
*/
toCart(id) {
return new Promise((resolve, reject) => {
prototype.$request({
api: "order.cart.toCart",
data: {
id: id,
}
}).then((response) => {
prototype.$utils.toast(response.msg);
if (response.code == 1) {
return resolve(response.msg);
return resolve();
}
return reject(response.msg);
}).catch(e => { });
});
},
/**
* 增加/减少数量
*/
change(id, type) {
return new Promise((resolve, reject) => {
prototype.$request({
api: "order.cart." + (type == 'sub' ? 'sub' : 'add'),
data: {
id: id,
}
}).then(() => {
return resolve();
}).catch(e => { });
});
},
/**
* 删除
*/
delete(id) {
return new Promise((resolve, reject) => {
prototype.$request({
api: "order.cart.delete",
data: {
id: id,
}
}).then(() => {
return resolve();
}).catch(e => { });
});
},
/**
* 列表
*/
list() {
list(refresh) {
return new Promise((resolve, reject) => {
let cacheList = uni.getStorageSync('USER_CART');
if ((typeof refresh === "undefined" || false === refresh) && cacheList) {
return resolve(cacheList);
}
prototype.$request({
api: "order.cart.list",
}).then(response => {
if (response.code == 1) {
uni.setStorageSync('USER_CART', response.data);
return resolve(response.data);
}
return reject(response.msg);

View File

@ -128,6 +128,9 @@ export default {
bindDateChange(e) {
this.datetime = e.detail.value;
},
/**
* 选择地址
*/
selectAddress() {
const that = this;
this.$utils.toPage("/pages/address/address?openType=choose&id=" + that.addressId, {
@ -139,6 +142,9 @@ export default {
},
});
},
/**
* 保险开关
*/
changeInsuranceState(state) {
if (state) {
this.total += this.insurancePrice;
@ -147,6 +153,9 @@ export default {
}
this.insurance = state;
},
/**
* 下单支付
*/
pay() {
if (!this.isAgree) {
uni.showToast({
@ -164,6 +173,7 @@ export default {
desc: this.content,
})
.then((id) => {
this.$store.dispatch("cart/updateAll");
this.$models.order.payOrder(id);
})
.catch((e) => {

View File

@ -5,7 +5,7 @@
</view>
<view class="cart-container">
<view class="cart-group" v-for="(item, index) in list" :key="index">
<view class="group-title limit-line clamp-1" @click="clickGroup(index)">
<view class="group-title limit-line clamp-1" @click="checkGroup(index)">
<view class="group-checkbox">
<widget-check-box :size="50" :checked="item.checked" />
</view>
@ -14,16 +14,17 @@
</view>
</view>
<view class="group-items">
<view class="cart-item" v-for="(v, i) in item.list" :key="i">
<view class="item-checkbox" @click="clickItem(index, i)">
<view class="cart-item" v-for="(v, i) in item.list" :key="i" @longpress="deleteCart(index, i)">
<view class="item-checkbox" @click="checkItem(index, i)">
<widget-check-box :size="50" :checked="v.checked" />
</view>
<view class="item-box">
<service-preview-item :data="v" />
<widget-count-modify
class="component-add"
:initNumber="v.number"
@change="changeNumber($event, { parentIndex: index, index: i })"
min="1"
:init="v.number"
@change="changeNumber($event, { parentIndex: index, itemIndex: i })"
/>
</view>
</view>
@ -31,17 +32,14 @@
<view class="bottom-btn-box">
<view class="total-price">
<text class="text">合计</text>
<text class="price">¥ {{ item.total }}</text>
<text class="price">¥ {{ utils.formatNumber(item.total, 2) }}</text>
</view>
<view class="button">
<view class="button" @click="createOrder(index)">
<text>去下单</text>
</view>
</view>
</view>
</view>
<view class="more">
<widget-load-more :hasMore="false" />
</view>
</app-layout>
</template>
@ -50,12 +48,12 @@ import AppLayout from "@/components/layout/layout";
import WidgetTips from "@/components/widgets/tips";
import WidgetCheckBox from "@/components/widgets/checkbox";
import WidgetCountModify from "@/components/widgets/count-modify";
import WidgetLoadMore from "@/components/widgets/loadmore";
import ServicePreviewItem from "@/components/service/preview-item";
export default {
name: "order-cart",
data() {
return {
utils: this.$utils,
list: [],
};
},
@ -64,11 +62,9 @@ export default {
WidgetTips,
WidgetCheckBox,
WidgetCountModify,
WidgetLoadMore,
ServicePreviewItem,
},
onLoad() {
let cartList = [];
this.$models.cart.list().then((list) => {
list.forEach((item) => {
let goods = [];
@ -76,79 +72,41 @@ export default {
goods.push({
id: v.gid,
name: v.title,
cover: require("@/static/temp/cate/1.png"),
times: v.post_hits,
cover: v.thumbnail,
price: v.money,
number: v.number,
checked: false,
});
});
cartList.push({
this.list.push({
name: item.cate,
list: [],
total: 0,
list: goods,
checked: false,
});
});
});
this.list = this.parseList([
{
id: 1,
name: "空调安装",
list: [
{
id: 1,
name: "格力空调安装",
cover: require("@/static/temp/cate/1.png"),
number: 1,
},
{
id: 2,
name: "美的空调安装",
cover: require("@/static/temp/cate/1.png"),
number: 1,
},
],
},
{
id: 2,
name: "管道疏通",
list: [
{
id: 3,
name: "厨房下水道",
cover: require("@/static/temp/cate/1.png"),
number: 10,
},
],
},
]);
},
onShow() {},
onReady() {},
onReachBottom() {},
onPullDownRefresh() {},
methods: {
parseList(list) {
let newList = [];
list.forEach((item, index) => {
list[index].checked = false;
list[index].total = 0;
list[index].list.forEach((v, i) => {
list[index].list[i].checked = false;
checkGroup(parentIndex) {
let currentItem = this.list[parentIndex];
let currentState = !currentItem.checked;
currentItem.list.forEach((item, itemIndex) => {
this.checkItem(parentIndex, itemIndex, currentState);
});
newList.push(list[index]);
});
return newList;
},
clickGroup(parentIndex) {
let state = !this.list[parentIndex].checked;
this.list[parentIndex].list.forEach((item, itemIndex) => {
this.checkedItem(parentIndex, itemIndex, state);
});
},
clickItem(parentIndex, itemIndex) {
this.checkedItem(parentIndex, itemIndex);
},
//
checkedItem(parentIndex, itemIndex, state) {
this.list[parentIndex].list[itemIndex].checked =
typeof state === "undefined" ? !this.list[parentIndex].list[itemIndex].checked : state;
checkItem(parentIndex, itemIndex, state) {
let currentItem = this.list[parentIndex].list[itemIndex];
let currentState = typeof state === "undefined" ? !currentItem.checked : state;
if (currentItem.checked != currentState) {
currentItem.checked = currentState;
//
let allChecked = true;
this.list[parentIndex].list.forEach((item, index) => {
@ -157,11 +115,82 @@ export default {
}
});
this.list[parentIndex].checked = allChecked;
// this.$forceUpdate();
this.updateTotal(parentIndex);
}
},
changeNumber(e, d) {
console.log(e);
console.log(d);
/**
* 更新总价
*/
updateTotal(parentIndex) {
let currentItem = this.list[parentIndex],
total = 0;
currentItem.list.forEach((item) => {
if (item.checked) {
total += item.price * item.number;
}
});
currentItem.total = total;
},
/**
* 改变数量
*/
changeNumber(e, idx) {
let currentItem = this.list[idx.parentIndex].list[idx.itemIndex];
if (currentItem.number != e.value) {
this.$models.cart.change(currentItem.id, e.type).then(() => {
this.$store.dispatch("cart/updateAll");
currentItem.number = e.value;
this.updateTotal(idx.parentIndex);
});
} else {
this.$utils.toast("亲,不能再" + (e.type == "sub" ? "减少" : "增加") + "了~");
}
},
/**
* 删除购物车
*/
deleteCart(parentIndex, itemIndex) {
const that = this;
uni.showModal({
title: "确定删除该商品?",
content: "数据删除后不可恢复,请谨慎操作!",
complete(res) {
if (res.confirm) {
let parentItem = that.list[parentIndex];
let currentItem = parentItem.list[itemIndex];
that.$models.cart.delete(currentItem.id).then(() => {
that.$store.dispatch("cart/updateAll");
parentItem.list.splice(itemIndex, 1);
if (parentItem.list.length > 0) {
that.updateTotal(parentIndex);
} else {
that.list.splice(parentIndex, 1);
}
});
}
},
});
},
/**
* 购物车下单
*/
createOrder(parentIndex) {
let orderdata = [];
let currentItem = this.list[parentIndex];
currentItem.list.forEach((item) => {
if (item.checked) {
orderdata.push({
id: item.id,
count: item.number,
});
}
});
if (orderdata.length > 0) {
this.$utils.toPage("/pages/order/create?orderData=" + encodeURIComponent(JSON.stringify(orderdata)));
} else {
this.$utils.toast("未选择任何商品");
}
},
},
};

View File

@ -25,7 +25,7 @@
<text class="iconfont icon-gouwuche"></text>
</view>
<view class="cart-number">
<text class="text">99</text>
<text class="text">{{ cartCount }}</text>
</view>
</movable-view>
</movable-area>
@ -56,10 +56,12 @@ export default {
computed: {
...mapState({
indexCateId: (state) => state.system.indexCateId,
cartCount: (state) => state.cart.count,
}),
},
async onLoad() {
let pageConfig = getApp().globalData.pageConfig;
this.$store.dispatch("cart/updateCount");
let x = pageConfig.windowWidth - this.$utils.rpx2px(94);
let y = pageConfig.windowHeight - this.$utils.rpx2px(94);

View File

@ -144,7 +144,9 @@ export default {
* 加入购物车
*/
addToCart() {
this.$models.cart.add(this.id);
this.$models.cart.toCart(this.id).then(() => {
this.$store.dispatch("cart/updateAll");
});
},
/**
* 创建订单

View File

@ -1,7 +1,14 @@
<template>
<app-layout minHeight="unset" btnType="back" title="服务列表" headerBackgroundColor="#FFFFFF" backgroundColor="#FFFFFF">
<view class="cate">
<app-cate :offsetHeight="0" :data="data" cateType="list" @clickItem="clickItem" :activeId="currentId" />
<app-cate
:offsetHeight="0"
:data="data"
cateType="list"
@clickItem="clickItem"
@changeNumber="changeNumber"
:activeId="currentId"
/>
</view>
<view class="common-bottom-components" :style="{ bottom: pageConfig.safeAreaInsets.bottom + 'px' }">
<view class="cart" @click="utils.toPage('/pages/service/cart')">
@ -9,10 +16,10 @@
<text class="iconfont icon-gouwuche"></text>
</view>
<view class="cart-number">
<text class="text">99</text>
<text class="text">{{ cartCount }}</text>
</view>
</view>
<view class="order-btn" @click="createOrder">
<view class="order-btn" @click="utils.toPage('/pages/service/cart')">
<text class="text">去下单</text>
</view>
</view>
@ -22,6 +29,7 @@
<script>
import AppLayout from "@/components/layout/layout";
import AppCate from "@/components/cate/cate";
import { mapState } from "vuex";
export default {
name: "service-list",
data() {
@ -37,8 +45,15 @@ export default {
AppLayout,
AppCate,
},
computed: {
...mapState({
cartCount: (state) => state.cart.count,
}),
},
onLoad(e) {
this.pageConfig = getApp().globalData.pageConfig;
this.$store.dispatch("cart/updateCount");
this.$store.dispatch("cart/briefCart");
if (!e.id) {
this.$utils.toast("参数错误");
@ -82,12 +97,32 @@ export default {
})
.catch((e) => {});
},
createOrder() {
this.$utils.toPage("/pages/order/create");
},
/**
* 详情
*/
clickItem(parentId, id) {
this.$utils.toPage("/pages/service/detail?id=" + id);
},
/**
* 数量改变
*/
changeNumber(e, id) {
if (e.value > 0) {
if (e.type == "add" && e.value == 1) {
this.$models.cart.toCart(id).then(() => {
this.$store.dispatch("cart/updateAll");
});
} else {
this.$models.cart.change(id, e.type).then(() => {
this.$store.dispatch("cart/updateAll");
});
}
} else {
this.$models.cart.delete(id).then(() => {
this.$store.dispatch("cart/updateAll");
});
}
},
},
};
</script>

View File

@ -4,6 +4,7 @@ import Vuex from 'vuex'
import system from "@/store/modules/system"
import user from "@/store/modules/user"
import service from "@/store/modules/service"
import cart from "@/store/modules/cart"
Vue.use(Vuex)
export default new Vuex.Store({
@ -11,5 +12,6 @@ export default new Vuex.Store({
system,
user,
service,
cart,
}
})

46
src/store/modules/cart.js Normal file
View File

@ -0,0 +1,46 @@
import cart from '@/core/models/cart';
export default {
namespaced: true,
state: {
count: 0,
briefCart: {},
},
getters: {},
mutations: {
count(state, data) {
state.count = data;
},
briefCart(state, data) {
state.briefCart = data;
}
},
actions: {
updateCount(context) {
cart.count().then(count => {
context.commit('count', count);
});
},
briefCart(context) {
cart.list().then((list) => {
let data = {
ids: [],
list: {},
};
list.forEach((item) => {
item.good.forEach((k) => {
data.list[k.gid] = k.number;
});
});
data.ids = Object.keys(data.list);
context.commit('briefCart', data);
});
},
updateAll(context) {
cart.list(true).then(() => {
context.dispatch('briefCart');
context.dispatch('updateCount');
});
}
}
}