Quellcode durchsuchen

完成购物车

sslyg vor 3 Jahren
Ursprung
Commit
7dd9f0c889

+ 107 - 1
App.vue

@@ -1,15 +1,121 @@
 <script>
 	export default {
+		data() {
+			return {
+				progress: 0
+			}
+		},
 		onLaunch: function() {
 			console.log('App Launch')
+			// #ifdef APP-PLUS
+			// this.checkUpdate();
+			// #endif
+
+			const value = uni.getStorageSync('launchFlag');
+			if (!value) {
+				// launchFlag=true直接跳转到首页
+				uni.reLaunch({
+					url: '/pages/index/index'
+				});
+			}
 		},
 		onShow: function() {
 			console.log('App Show')
-			this.$store.commit("user/save", uni.getStorageSync("userinfo"))
+			this.$store.commit("user/load")
+			this.$store.dispatch("cart/load");			
 		},
 		onHide: function() {
 			console.log('App Hide')
 		},
+		methods: {
+			checkUpdate() {
+				this.$http.get({
+					url: '/update',
+					success: (res) => {
+
+						let temp = [];
+						let last_version = res.data.data.versionName.substring(1);
+						temp = last_version.substring(1).split(".");
+						let last_version_code = parseInt(temp[0]) * 10000 + parseInt(temp[1]) * 100 + parseInt(
+							temp[2]);
+
+						let cur_version = plus.runtime.version;
+						temp = cur_version.substring(1).split(".");
+						let cur_version_code = parseInt(temp[0]) * 10000 + parseInt(temp[1]) * 100 + parseInt(
+							temp[2]);
+
+						console.log(`最新版本:${last_version} 当前版本${cur_version}`)
+						// uni.showModal({
+						// 	content:`最新版本:${last_version} 当前版本${cur_version} 当前环境 ${process.env.NODE_ENV}`
+						// })
+						if (last_version_code > cur_version_code || process.env.NODE_ENV === 'development') {
+							uni.showModal({
+								title: "版本更新",
+								content: `检测到新版本,是否更新?`,
+								confirmText: "立即更新",
+								success: (e) => {
+									if (e.confirm) {
+										console.log('用户点击确定');
+										if (plus.os.name === 'iOS') {
+											plus.runtime.openURL(
+												"https://apps.apple.com/cn/app/id387682726")
+										}
+										if (plus.os.name === 'Android') {
+											let downloadTask = uni.downloadFile({
+												url: this.$http.baseUrl + res.data.data
+													.apk_file,
+												success: (downloadResult) => {
+													if (downloadResult.statusCode ===
+														200) {
+														plus.runtime.install(
+															downloadResult
+															.tempFilePath, {
+																force: false
+															},
+															function() {
+																console.log(
+																	'install success...'
+																	);
+																plus.runtime
+																	.restart();
+															},
+															function(e) {
+																console.error(
+																	'install fail...'
+																	);
+															});
+													}
+												}
+											});
+											let loading = plus.nativeUI.showWaiting("已下载0%", {
+												width: "30%",
+												height: "15%"
+											})
+											downloadTask.onProgressUpdate((e) => {
+												// console.log('下载进度' + e.progress);
+												// console.log('已经下载的数据长度' + e.totalBytesWritten);
+												// console.log('预期需要下载的数据总长度' + e.totalBytesExpectedToWrite);
+												if (e.progress % 5 === 0) {
+													loading.setTitle("已下载" + e.progress +
+														"%")
+												}
+												if (e.progress === 100) {
+													loading.close();
+												}
+											})
+										}
+
+									} else if (e.cancel) {
+										console.log('用户点击取消');
+									}
+								}
+							})
+
+						}
+					}
+				});
+			}
+		}
 	}
 </script>
 

+ 131 - 0
components/code-elf-guide/code-elf-guide.vue

@@ -0,0 +1,131 @@
+<template>
+	<view class="content">
+		<swiper class="swiper" 
+		:autoplay="autoplay" 
+		:duration="duration">
+			<swiper-item>
+				<view class="swiper-item">
+					<!-- <view class="swiper-item-img"><image src="../../static/guide/title_01.png" mode="aspectFit"></image></view> -->
+					<view class="swiper-item-img"><image src="../../static/images/material/sp1.png" mode="scaleToFill"></image></view>
+				</view>
+				<view class="jump-over" @tap="launchFlag()">{{jumpover}}</view>
+			</swiper-item>
+			<swiper-item>
+				<view class="swiper-item">
+					<view class="swiper-item-img"><image src="../../static/images/material/sp2.png" mode="scaleToFill"></image></view>
+					<!-- <view class="swiper-item-img"><image src="../../static/guide/icon_02.png" mode="aspectFit"></image></view> -->
+				</view>
+				<view class="jump-over" @tap="launchFlag()">{{jumpover}}</view>
+			</swiper-item>
+			<!-- <swiper-item>
+				<view class="swiper-item">
+					<view class="swiper-item-img"><image src="../../static/guide/title_03.png" mode="aspectFit"></image></view>
+					<view class="swiper-item-img"><image src="../../static/guide/icon_03.png" mode="aspectFit"></image></view>
+				</view>
+				<view class="jump-over" @tap="launchFlag()">{{jumpover}}</view>
+			</swiper-item> -->
+			<swiper-item>
+				<view class="swiper-item">
+					<view class="swiper-item-img"><image src="../../static/images/material/sp3.png" mode="scaleToFill"></image></view>
+					<!-- <view class="swiper-item-img"><image src="../../static/guide/icon_04.png" mode="aspectFit"></image></view> -->
+				</view>
+				<view class="experience" @tap="launchFlag()">{{experience}}</view>
+			</swiper-item>
+		</swiper>
+		<!-- <view class="uniapp-img"><image src="../../static/guide/uniapp4@2x.png" mode="aspectFit"></image></view> -->
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				background: ['color1', 'color2', 'color3'],
+				autoplay: false,
+				duration: 500,
+				jumpover: '跳过',
+				experience: '立即体验'
+			}
+		},
+		methods: {
+			launchFlag: function(){
+				/**
+				 * 向本地存储中设置launchFlag的值,即启动标识;
+				 */
+				uni.setStorage({
+						key: 'launchFlag',
+						data: true,
+				});
+				uni.switchTab({
+					url: '/pages/home/home'
+				});
+				
+			}
+		}
+	}
+</script>
+<style>
+	page,
+	.content{
+		width: 100%;
+		height: 100%;
+		background-size: 100% auto ;
+		padding: 0;
+	}
+	.swiper{
+		width: 100%;
+		height: 100%;
+		background: #FFFFFF;
+	}
+	.swiper-item {
+		width: 100%;
+		height: 100%;
+		text-align: center;
+		position: relative;
+		display: flex;
+		/* justify-content: center; */
+		align-items:flex-end;
+		flex-direction:column-reverse
+	}
+	.swiper-item-img{
+		width: 100%;
+		height: 100vh;
+		margin: 0 auto;
+	}
+	.swiper-item-img image{
+		width: 750upx;
+		height: 100vh;
+	}
+	.uniapp-img{
+		height: 20%;
+		background: #FFFFFF;
+		display: flex;
+		justify-content: center;
+		align-items:center;
+		overflow: hidden;
+	}
+	.uniapp-img image{
+		width: 40%;
+	}
+	
+	.jump-over,.experience{
+		position: absolute;
+		height: 60upx;
+		line-height: 60upx;
+		padding: 0 40upx;
+		border-radius: 30upx;
+		font-size: 32upx;
+		color: #454343;
+		border: 1px solid #454343;
+		z-index: 999;
+	}
+	.jump-over{
+		right: 45upx;
+		top: 65upx;
+	}
+	.experience{
+		right: 50%;
+		margin-right: -105upx;
+		bottom: 80upx;
+	}
+</style>

+ 111 - 0
components/code-elf-guide/uni-guide.md

@@ -0,0 +1,111 @@
+# 引导页
+
+###  基于uni-app框架的swiper组件打开的时候启动。
+
+> 首次启动展示引导页,之后启动不再展示。那么就意味着,我们需要一个标识来确定,App是否已经启动过。
+
+> 我们可以在本地存储一个key来做为已经启动过App的标识。那么,我们在入口这里,就可以读取这个key,来决定是否展示引导页。
+
+> 因工作繁忙目前该程序金对安卓做了适配,IOS可根据环境自己适配。谢谢
+
+## 目录结构
+* /pages/index/index.vue //入口页
+### 存储key
+* 向本地存储中设置launchFlag的值,即启动标识;
+### 获取key
+* 向本地存储中设置launchFlag的值,即启动标识;
+* 获取本地存储中launchFlag的值
+* 若存在,说明不是首次启动,直接进入首页;
+* 若不存在,说明是首次启动,进入引导页;
+
+```html
+	<view class="main">
+		<code-elf-guide v-if="guidePages"></code-elf-guide>
+	</view>
+
+```
+
+```javascript
+	import codeElfGuide from '@/components/code-elf-guide/code-elf-guide.vue'
+	export default {
+		components: {
+			codeElfGuide
+		  },
+		data() {
+			return {
+				guidePages:true
+			}
+		},
+		onLoad(){
+			this.loadExecution()
+		},
+		methods: {
+			loadExecution: function(){
+				/**
+				 * 获取本地存储中launchFlag的值
+				 * 若存在,说明不是首次启动,直接进入首页;
+				 * 若不存在,说明是首次启动,进入引导页;
+				 */
+				try {
+					// 获取本地存储中launchFlag标识
+					const value = uni.getStorageSync('launchFlag');
+					if (value) {
+						// launchFlag=true直接跳转到首页
+						uni.switchTab({
+							url: '/pages/tabBar/component/component'
+						});
+					} else {
+						// launchFlag!=true显示引导页
+						this.guidePages = true
+					}
+				} catch(e) { 
+					// error 
+					uni.setStorage({ 
+						key: 'launchFlag', 
+						data: true, 
+						success: function () {
+							console.log('error时存储launchFlag');
+						} 
+					}); 
+					this.guidePages = true
+				}
+			}
+		}
+	}
+```
+```css
+	page,.main{
+		width: 100%;
+		height: 100%;
+	}
+
+```
+
+### 首页清除key,进行测试
+* 清除本地存储中设置launchFlag的值,即启动标识;
+* 两秒后重启APP,进行测试
+```javascript
+	uni.showModal({
+        title: '清除launchFlag值',
+        content: '确定要清除launchFlag值,进行重启测试?',
+        success: function (res) {
+            if (res.confirm) {
+                console.log('用户点击确定');
+                // 清除缓存
+                uni.clearStorage();
+                uni.showToast({
+                    icon: 'none',
+                    duration:3000,
+                    title: '清除成功2秒后重启'
+                });
+                // 两秒后重启
+                setTimeout(function() {
+                    uni.hideToast();
+                    plus.runtime.restart();
+                }, 2000);
+            } else if (res.cancel) {
+                console.log('用户点击取消');
+            }
+        }
+    });
+```

+ 19 - 5
components/product-item/product-item.vue

@@ -1,5 +1,5 @@
 <template>
-	<view :class="type==='swiper'?'product-swiper-item':'product-list-item'" class="product-item">
+	<view :class="type==='swiper'?'product-swiper-item':'product-list-item'" class="product-item" @tap="openDetails">
 		<image class="image" :src="image" mode="scaleToFill"></image>
 		<view class="row row-1">
 			<text class="title"><text class="sxzg-icon">省心直供</text>{{title}}</text>
@@ -23,6 +23,10 @@
 			};
 		},
 		props: {
+			id: {
+				type: [String, Number],
+				default: 0
+			},
 			title: {
 				type: String,
 				default: "【工厂直营】加厚款手提垃圾袋加厚款手提垃圾袋加厚款手提垃圾袋加厚款手提垃圾袋*50支"
@@ -47,6 +51,13 @@
 				type: [String, Number],
 				default: 0
 			}
+		},
+		methods: {
+			openDetails() {
+				uni.navigateTo({
+					url: "/pages/product/product-details?id=" + this.id
+				})
+			}
 		}
 	}
 </script>
@@ -63,6 +74,7 @@
 
 	.product-list-item {
 		width: 350rpx;
+
 		.image {
 			width: 350rpx;
 			height: 300rpx;
@@ -97,16 +109,16 @@
 	.title {
 		font-size: 24rpx;
 		display: inline-block;
-		white-space:normal;
+		white-space: normal;
 		display: -webkit-box;
 		-webkit-box-orient: vertical;
 		-webkit-line-clamp: 2;
 		overflow: hidden;
-
+		height: 68upx;
 	}
 
 	.row {
-		padding: 0 10upx;
+		padding: 0 10upx;		
 	}
 
 	.row-2 {
@@ -119,9 +131,11 @@
 		font-size: 22rpx;
 		color: #cccccc;
 	}
-	.org-price{
+
+	.org-price {
 		text-decoration: line-through;
 	}
+
 	.sxj-icon {
 		background: $primary-color;
 		color: white;

+ 10 - 6
http.js

@@ -1,19 +1,23 @@
 import store from './store'
 
-const baseUrl = "http://192.168.1.101:8000/api";
-const baseImageUrl = "http://192.168.1.101:8000/";
+const baseUrl = "http://192.168.1.101:8000";
+const baseApiUrl = baseUrl + "/api";
 
 function initPramas() {
-	arguments[0].url = baseUrl + arguments[0].url;
+	arguments[0].url = baseApiUrl + arguments[0].url;
+	arguments[0].timeout = 10000
 	// console.log(typeof arguments[0].fail)
 	if (typeof arguments[0].fail === "undefined") {
 		arguments[0].fail = (res) => {
 			console.log(res)
+			let msg = '请求失败'
+			if (res.data && res.data.msg) {
+				msg = res.data.msg
+			}
 			uni.showToast({
-				title: res.data.msg,
+				title: msg,
 				icon: "none"
 			})
-			console.log(res.data.code)
 		}
 	}
 	const success = arguments[0].success
@@ -46,7 +50,7 @@ function initPramas() {
 	return arguments[0];
 }
 export default {
-	baseImageUrl: baseImageUrl,
+	baseUrl: baseUrl,
 	get: function() {
 		let obj = initPramas(arguments[0]);
 		obj.method = "GET";

+ 6 - 1
main.js

@@ -17,12 +17,17 @@ Vue.filter('imagesFilter', (images) => {
 		image = images.split(',')[0]
 	}
 	if (image.indexOf("http") !== 0) {
-		image = http.baseImageUrl + image;		
+		image = http.baseUrl + image;
 	}
 	return image;
 })
 
 
+Vue.filter('priceFilter', (price) => {
+	return price.toFixed(2);
+})
+
+
 const app = new Vue({
 	...App,
 	store

+ 4 - 1
manifest.json

@@ -14,7 +14,7 @@
             "alwaysShowBeforeRender" : true,
             "waiting" : true,
             "autoclose" : true,
-            "delay" : 0
+            "delay" : 3000
         },
         /* 模块配置 */
         "modules" : {},
@@ -45,6 +45,9 @@
             /* SDK配置 */
             "sdkConfigs" : {
                 "ad" : {}
+            },
+            "splashscreen" : {
+                "androidStyle" : "common"
             }
         }
     },

+ 66 - 75
pages.json

@@ -18,12 +18,19 @@
 							"text": "\ue847",
 							"fontSrc": "/static/uni.ttf",
 							"width": "auto",
-							"fontSize":"26px"
+							"fontSize": "26px"
 						}]
 					}
 				}
 			}
 		}, {
+			"path": "pages/index/index",
+			"style": {
+				"bounce":"none",
+				"navigationStyle": "custom"
+			}
+		},
+		{
 			"path": "pages/order/order",
 			"style": {
 				"navigationBarTitleText": "订单管理",
@@ -126,82 +133,66 @@
 
 			}
 
-		}
-	    ,{
-            "path" : "pages/user/setting",
-            "style" :                                                                                    
-            {
-                "navigationBarTitleText": "设置",
-                "enablePullDownRefresh": false,
+		}, {
+			"path": "pages/user/setting",
+			"style": {
+				"navigationBarTitleText": "设置",
+				"enablePullDownRefresh": false,
 				"backgroundColorTop": "#ff5d5b"
-            }
-            
-        }
-        ,{
-            "path" : "pages/message/message",
-            "style" :                                                                                    
-            {
-                "navigationBarTitleText": "消息",
-                "enablePullDownRefresh": false
-            }
-            
-        }
-        ,{
-            "path" : "pages/product/product-details",
-            "style" :                                                                                    
-            {
-                "navigationBarTitleText": "订单详情",
-                "enablePullDownRefresh": false
-            }
-            
-        }
-        ,{
-            "path" : "pages/order/order-details",
-            "style" :                                                                                    
-            {
-                "navigationBarTitleText": "订单详情",
-                "enablePullDownRefresh": false
-            }
-            
-        }
-        ,{
-            "path" : "pages/user/notice",
-            "style" :                                                                                    
-            {
-                "navigationBarTitleText": "官方公告",
-                "enablePullDownRefresh": false
-            }
-            
-        }
-        ,{
-            "path" : "pages/user/strategy",
-            "style" :                                                                                    
-            {
-                "navigationBarTitleText": "新手攻略",
-                "enablePullDownRefresh": false
-            }
-            
-        }
-        ,{
-            "path" : "pages/user/problem",
-            "style" :                                                                                    
-            {
-                "navigationBarTitleText": "常见问题",
-                "enablePullDownRefresh": false
-            }
-            
-        }
-        ,{
-            "path" : "pages/user/kefu",
-            "style" :                                                                                    
-            {
-                "navigationBarTitleText": "联系客服",
+			}
+
+		}, {
+			"path": "pages/message/message",
+			"style": {
+				"navigationBarTitleText": "消息",
+				"enablePullDownRefresh": false
+			}
+
+		}, {
+			"path": "pages/product/product-details",
+			"style": {
+				"navigationBarTitleText": "商品详情",
+				"enablePullDownRefresh": false
+			}
+
+		}, {
+			"path": "pages/order/order-details",
+			"style": {
+				"navigationBarTitleText": "订单详情",
+				"enablePullDownRefresh": false
+			}
+
+		}, {
+			"path": "pages/user/notice",
+			"style": {
+				"navigationBarTitleText": "官方公告",
+				"enablePullDownRefresh": false
+			}
+
+		}, {
+			"path": "pages/user/strategy",
+			"style": {
+				"navigationBarTitleText": "新手攻略",
+				"enablePullDownRefresh": false
+			}
+
+		}, {
+			"path": "pages/user/problem",
+			"style": {
+				"navigationBarTitleText": "常见问题",
+				"enablePullDownRefresh": false
+			}
+
+		}, {
+			"path": "pages/user/kefu",
+			"style": {
+				"navigationBarTitleText": "联系客服",
 				"backgroundColorTop": "#ff5d5b",
-                "enablePullDownRefresh": false
-            }
-            
-        }
-    ],
+				"enablePullDownRefresh": false
+			}
+
+		}
+	],
 	"globalStyle": {
 		"navigationBarTextStyle": "white",
 		"navigationBarTitleText": "省心直供",

+ 29 - 4
pages/home/home.vue

@@ -23,7 +23,7 @@
 			<view class="hot-rank">
 				<scroll-view scroll-x="true" :show-scrollbar="false" :enable-flex="true" style="white-space: nowrap;">
 					<template v-for="product in rankProducts">
-						<product-item type="swiper" :image="product.images|imagesFilter" :title="product.name" :org-price="product.org_price"
+						<product-item type="swiper" :id="product.id" :image="product.images|imagesFilter" :title="product.name" :org-price="product.org_price"
 						 :price="product.price"></product-item>
 					</template>
 				</scroll-view>
@@ -37,7 +37,7 @@
 			<view class="new-rank">
 				<scroll-view scroll-x="true" :show-scrollbar="false" :enable-flex="true" style="white-space: nowrap;">
 					<template v-for="product in newProducts">
-						<product-item type="swiper" :image="product.images|imagesFilter" :title="product.name" :org-price="product.org_price"
+						<product-item type="swiper" :id="product.id" :image="product.images|imagesFilter" :title="product.name" :org-price="product.org_price"
 						 :price="product.price"></product-item>
 					</template>
 				</scroll-view>
@@ -50,11 +50,11 @@
 			</view>
 			<view class="like">
 				<template v-for="product in likeProducts">
-					<product-item type="list" :image="product.images|imagesFilter" :title="product.name" :org-price="product.org_price"
+					<product-item type="list" :id="product.id" :image="product.images|imagesFilter" :title="product.name" :org-price="product.org_price"
 					 :price="product.price"></product-item>
 				</template>
 			</view>
-		</view>
+		</view>		
 	</view>
 </template>
 
@@ -74,6 +74,31 @@
 			this.getRankProductData();
 			this.getNewProductData();
 			this.getLikeProductsData();
+			
+			uni.showModal({
+			    title: '清除launchFlag值',
+			    content: '确定要清除launchFlag值,进行重启测试?',
+			    success: function (res) {
+			        if (res.confirm) {
+			            console.log('用户点击确定');
+			            // 清除缓存
+			            uni.clearStorage();
+			            uni.showToast({
+			                icon: 'none',
+			                duration:3000,
+			                title: '清除成功2秒后重启'
+			            });
+			            // 两秒后重启
+			            setTimeout(function() {
+			                uni.hideToast();
+			                plus.runtime.restart();
+			            }, 2000);
+			        } else if (res.cancel) {
+			            console.log('用户点击取消');
+			        }
+			    }
+			});
+
 		},
 		onShow() {},
 		onPageScroll(e) {

+ 63 - 0
pages/index/index.vue

@@ -0,0 +1,63 @@
+<template>
+	<view class="main">
+		<code-elf-guide v-if="guidePages"></code-elf-guide>
+	</view>
+</template>
+
+<script>
+	import codeElfGuide from '@/components/code-elf-guide/code-elf-guide.vue'
+
+	export default {
+		components: {
+			codeElfGuide
+		},
+		data() {
+			return {
+				guidePages: true
+			}
+		},
+		onLoad() {
+			this.loadExecution()
+		},
+		methods: {
+			loadExecution: function() {
+				/**
+				 * 获取本地存储中launchFlag的值
+				 * 若存在,说明不是首次启动,直接进入首页;
+				 * 若不存在,说明是首次启动,进入引导页;
+				 */
+				try {
+					// 获取本地存储中launchFlag标识
+					const value = uni.getStorageSync('launchFlag');
+					if (value) {
+						// launchFlag=true直接跳转到首页
+						uni.switchTab({
+							url: '/pages/home/home'
+						});
+					} else {
+						// launchFlag!=true显示引导页
+						this.guidePages = true
+					}
+				} catch (e) {
+					// error 
+					uni.setStorage({
+						key: 'launchFlag',
+						data: true,
+						success: function() {
+							console.log('error时存储launchFlag');
+						}
+					});
+					this.guidePages = true
+				}
+			}
+		}
+	}
+</script>
+
+<style>
+	page,
+	.main {
+		width: 100%;
+		height: 100%;
+	}
+</style>

+ 486 - 5
pages/product/product-details.vue

@@ -1,6 +1,130 @@
 <template>
-	<view>
-		
+	<view style="padding-bottom: 100upx;">		
+		<view style="background: white;padding-bottom: 10upx;">
+			<view class="section carousel-wrapper">
+				<swiper class="carousel" :indicator-dots="true" :autoplay="true" :interval="3000" :duration="1000"
+					circular>
+					<swiper-item v-for="image in product.images">
+						<view class="swiper-item">
+							<image class="image" :src="image|imagesFilter" mode=""></image>
+						</view>
+					</swiper-item>
+				</swiper>
+			</view>
+
+			<view class="row row-1">
+				<text class="title"><text class="sxzg-icon">省心直供</text>{{product.name}}</text>
+			</view>
+			<view class="row row-2">
+				<text class="org-price">¥{{product.org_price}}</text>
+				<text class="stock">剩余库存{{product.stock}}</text>
+			</view>
+			<view class="row row-3">
+				<text class="sxj-icon">省心价</text>
+				<text class="price">¥{{product.price}}</text>
+			</view>
+		</view>
+
+		<view class="details">
+			<view class="btn" @tap="detailsIsOpen=!detailsIsOpen">
+				<view>点击查看商品详情</view>
+				<view class="arrow" :class="{'rotate':detailsIsOpen}">
+					<uni-icons type="arrowright"></uni-icons>
+				</view>
+			</view>
+			<view class="content" :class="{'show':detailsIsOpen}">
+				<rich-text :nodes="product.details"></rich-text>
+			</view>
+		</view>
+
+		<view class="section" style="margin-top: 20upx;">
+			<view class="col-img-title">
+				<image src="../../static/images/like.png" mode="scaleToFill" style="height: 28rpx;width: 363rpx;">
+				</image>
+			</view>
+			<view class="like">
+				<scroll-view scroll-x="true" :show-scrollbar="false" :enable-flex="true" style="white-space: nowrap;">
+					<template v-for="product in likeProducts">
+						<product-item type="swiper" :id="product.id" :image="product.images|imagesFilter"
+							:title="product.name" :org-price="product.org_price" :price="product.price"></product-item>
+					</template>
+				</scroll-view>
+			</view>
+
+		</view>
+
+		<view class="footer">
+			<view class="collect">
+				<view>
+					<uni-icons type="heart" size="24"></uni-icons>
+				</view>
+				<view style="font-size: 24upx;">收藏</view>
+			</view>
+
+			<view class="btn-group">
+				<view class="btn" @tap="option = 'addcart',popupVisible=true">
+					<uni-icons type="cart" color="white" style="margin-right: 10upx;"></uni-icons>加入购物车
+				</view>
+				<view class="line"></view>
+				<view class="btn" @tap="option = 'buy',popupVisible=true">立即下单</view>
+			</view>
+
+		</view>
+
+		<view class="popup" v-if="popupVisible" @touchmove.stop.prevent>
+			<view class="popup-wrapper">
+				<view class="close" @tap="popupVisible=false">
+					<uni-icons type="closeempty" size="30"></uni-icons>
+				</view>
+				<view class="row row-1">
+					<view class="spec-image">
+						<image class="image" :src="product.specs[curSpecIndex].image|imagesFilter" mode=""></image>
+					</view>
+					<view class="">
+						<view class="title">
+							已选择 {{product.specs[curSpecIndex].name}}
+						</view>
+						<view class="org-price">
+							¥{{product.specs[curSpecIndex].org_price|priceFilter}}
+						</view>
+						<view>
+							<text class="sxj-icon">省心价</text>
+							<text class="price">¥{{product.specs[curSpecIndex].price|priceFilter}}</text>
+						</view>
+					</view>
+				</view>
+				<view class="row row-2">
+					<view class="label">
+						选择规格
+					</view>
+				</view>
+				<view class="row row-3 spec-list">
+					<template v-for="(spec,i) in product.specs">
+						<view class="spec-item" :class="{'active':curSpecIndex===i}" @tap="curSpecIndex=i">{{spec.name}}
+						</view>
+					</template>
+				</view>
+
+				<view class="row row-4">
+					<view class="label">
+						选择数量
+					</view>
+					<view class="counter">
+						<view class="sub" @tap="num>1?num--:0">-</view>
+						<input class="num" type="text" v-model="num" />
+						<view class="plus" @tap="num++">+</view>
+					</view>
+				</view>
+				<view class="row row-5 total-price">
+					合计:<text class="total-price-text">¥{{totalPrice}}</text>
+				</view>
+				<view class="row row-6 option">
+					<button v-if="option === 'addcart'" class="btn" type="default" @tap="addCart">加入购物车</button>
+					<button v-if="option === 'buy'" class="btn" type="default" @tap="">立即购买</button>
+				</view>
+				
+			</view>
+		</view>
 	</view>
 </template>
 
@@ -8,15 +132,372 @@
 	export default {
 		data() {
 			return {
-				
+				popupVisible: false,
+				option: "addcart",
+				likeProducts: [],
+				product: {
+					id: 0
+				},
+				detailsIsOpen: false,
+				curSpecIndex: 0,
+				num: 1,
 			}
 		},
+		computed: {
+			totalPrice() {
+				return (this.product.specs[this.curSpecIndex].price * this.num).toFixed(2);
+			}
+		},
+		onLoad(option) {
+			this.getLikeProductsData();
+			this.product.id = option.id;
+			this.getProductData();
+		},
 		methods: {
-			
+			getLikeProductsData() {
+				this.$http.get({
+					url: "/product/rand",
+					data: {
+						limit: 10
+					},
+					success: (res) => {
+						this.likeProducts = res.data.data
+					}
+				})
+			},
+			getProductData() {
+				this.$http.get({
+					url: "/product",
+					data: {
+						id: this.product.id
+					},
+					success: (res) => {
+						this.product = res.data.data
+						this.product.images = this.product.images.split(",")
+						this.product.specs = JSON.parse(this.product.specs)
+					}
+				})
+			},
+			addCart() {
+				this.$store.dispatch("cart/add", {
+					id: this.product.id,
+					num: this.num,
+					specIndex: this.curSpecIndex
+				}).then(uni.showToast({
+					title:"加入购物车成功",
+					icon:"none"
+				}))
+			}
 		}
 	}
 </script>
 
-<style>
+<style lang="scss" scoped>
+	.carousel-wrapper {
+		.carousel {
+			margin: auto;
+			overflow: hidden;
+			transform: translateY(0);
+			width: 750rpx;
+			height: 750rpx;
+
+			.image {
+				width: 750rpx;
+				height: 750rpx;
+			}
+		}
+	}
+
+	.title {
+		font-size: 30upx;
+		font-weight: bold;
+		color: #333333;
+		display: inline-block;
+		white-space: normal;
+		display: -webkit-box;
+		-webkit-box-orient: vertical;
+		-webkit-line-clamp: 2;
+		overflow: hidden;
+
+	}
+
+	.sxzg-icon {
+		color: $primary-color;
+		font-size: 22rpx;
+		width: 120rpx;
+		text-align: center;
+		line-height: normal;
+		border: 2rpx solid $primary-color;
+		border-radius: 20rpx;
+		display: inline-block;
+		position: relative;
+		top: -4rpx;
+		margin-right: 10upx;
+		// transform: scale(0.9);
+	}
+
+	.sxj-icon {
+		background: $primary-color;
+		color: white;
+		font-size: 20upx;
+		padding: 0 5upx;
+		border-radius: 5upx;
+		vertical-align: middle;
+	}
+
+	.row {
+		margin: 20upx;
+		display: flex;
+		align-items: center;
+	}
+
+	.row-2 {
+		justify-content: space-between;
+	}
+
+	.org-price,
+	.stock {
+		font-size: 28rpx;
+		color: #999999;
+	}
+
+	.org-price {
+		text-decoration: line-through;
+	}
+
+	.price {
+		font-size: 28rpx;
+		color: $primary-color;
+		font-weight: bold;
+	}
+
+	.details {
+		background: white;
+		margin-top: 20upx;
+		font-size: 30upx;
+
+		.btn {
+			padding: 20upx;
+			display: flex;
+			justify-content: space-between;
+		}
+	}
+
+	.col-img-title {
+		text-align: center;
+		background: white;
+		height: 80upx;
+		line-height: 80upx;
+		margin-bottom: 10upx;
+	}
+
+	.like .product-item {
+		margin: 5rpx;
+
+		&:first-child {
+			margin-left: 10upx;
+		}
+
+		&:last-child {
+			margin-right: 10upx;
+		}
+	}
+
+
+	.content {
+		max-height: 0;
+		overflow: hidden;
+		transition: max-height 0.5s;
+
+		&.show {
+			max-height: 10000upx;
+		}
+
+	}
+
+	.arrow {
+		transform: rotate(0deg);
+		transition: all 0.5s;
+	}
+
+	.arrow.rotate {
+		transform: rotate(90deg);
+		// animation:myRotate 10s linear infinite;
+
+	}
+
+	.footer {
+		display: flex;
+		position: fixed;
+		height: 100upx;
+		background: white;
+		bottom: 0;
+		width: 100%;
+		box-shadow: 0 0 10upx #999999;
+		align-items: center;
+		// color: white;
+		padding: 0upx 20upx;
+		box-sizing: border-box;
+		justify-content: space-between;
+
+		.btn-group {
+			background: $primary-color;
+			display: flex;
+			color: white;
+			width: 580upx;
+			border-radius: 50upx;
+			height: 80upx;
+			align-items: center;
+
+			.btn {
+				flex: 1;
+				text-align: center;
+				font-size: 30upx;
+				font-weight: bold;
+			}
+
+			.line {
+				background: white;
+				width: 1upx;
+				height: 60upx;
+			}
+		}
+
+		.collect {
+			margin-left: 20upx;
+			display: flex;
+			flex-direction: column;
+			align-items: center;
+
+			& :last-child {
+				margin-top: -8upx;
+			}
+		}
+	}
+
+	.popup {
+		position: fixed;
+		top: 0;
+		left: 0;
+		bottom: 0;
+		width: 750upx;
+		background: rgba(0, 0, 0, 0.6);
+		overflow: hidden;
+
+		.popup-wrapper {
+			.close {
+				position: absolute;
+				right: 5upx;
+				top: 0;
+				transform: scale(0.6);
+			}
+
+			background: white;
+			position: absolute;
+			bottom: 0;
+			width: 750upx;
+			min-height: 300upx;
+			border-radius: 20upx 20upx 0 0;
+		}
+
+		.spec-image {
+			margin-right: 20upx;
+
+			.image {
+				width: 180upx;
+				height: 180upx;
+				background: #EEEEEE;
+			}
+		}
+
+		.row-1 {
+			align-items: flex-start;
 
+			.org-price {
+				margin-top: 20upx;
+			}
+		}
+
+		.label {
+			font-size: 28upx;
+		}
+
+		.spec-list {
+			display: flex;
+			justify-content: flex-start;
+			flex-wrap: wrap;
+			margin-bottom: 0;
+
+			.spec-item {
+				text-align: center;
+				background: #CCCCCC;
+				color: white;
+				padding: 5upx 30upx;
+				margin: 0 20upx 20upx 20upx;
+				font-size: 28upx;
+				border-radius: 10upx;
+
+				&.active {
+					background: $primary-color;
+				}
+			}
+		}
+
+		.row-4 {
+			justify-content: space-between;
+		}
+
+		.counter {
+			margin-right: 40upx;
+			display: flex;
+
+			border: 2upx solid #CCCCCC;
+			font-size: 28upx;
+			align-items: center;
+			border-radius: 10upx;
+
+			.sub,
+			.plus {
+				// transform: scale(0.5);
+				font-weight: 0;
+				width: 42upx;
+				text-align: center;
+
+				&:active {
+					background: rgba(0, 0, 0, .1);
+				}
+			}
+
+			.num {
+				text-align: center;
+				font-size: 24upx;
+				border-left: 2upx solid #EEEEEE;
+				border-right: 2upx solid #EEEEEE;
+				width: 50upx;
+			}
+		}
+
+		.total-price {
+			font-size: 30upx;
+			justify-content: flex-end;
+			margin-right: 60upx;
+
+			.total-price-text {
+				color: $primary-color;
+				font-weight: bold;
+			}
+		}
+
+		.option {
+			.btn {
+				width: 600upx;
+				line-height: 80upx;
+				font-size: 30upx;
+				background: $primary-color;
+				color: white;
+				border-radius: 40upx;
+				font-weight: bold;
+			}
+		}
+	}
 </style>

+ 99 - 267
pages/shopping-cart/shopping-cart.vue

@@ -1,291 +1,55 @@
 <template>
 	<view class="shopping-cart">
-		<view class="shopping-cart-item">
+		<view class="shopping-cart-item" v-for="seller in cart">
 			<view class="shopping-cart-item-head">
-				<view class="select"><checkbox class="checkbox" value="cb" checked="true" /></view>
-				<view class="factory-name">省心一号工厂</view>
-			</view>
-			<view class="shopping-cart-info">
-				<view class="product-item">
-									<view class="select"><checkbox class="checkbox" value="cb" checked="true" /></view>
-
-					<view class="product-image">
-						<image class="image" src="https://img.alicdn.com/imgextra/i1/392147177/O1CN01Bh2NP022t7Dv5zazW_!!392147177.jpg"
-						 mode="scaleToFill"></image>
-					</view>
-					<view class="product-info">
-						<view class="row row-1">
-							<text class="title"><text class="sxzg-icon">省心直供</text>白金打开链接分厘卡圣诞节防空雷达数据</text>
-						</view>
-						<view class="row">
-							<view class="spec">白色</view>
-						</view>
-						<view class="row row-2">
-							<text class="org-price">¥2.9</text>
-						</view>
-						<view class="row">
-							<text class="sxj-icon">省心价</text>
-							<text class="price">¥1.99</text>
-						</view>
-					</view>
-					<view class="counter">
-						<view class="sub">-</view>
-						<input class="num" type="text" value="0" />
-						<view class="plus">+</view>
-					</view>
-				</view>
-				<view class="product-item">
-									<view class="select"><checkbox class="checkbox" value="cb" checked="true" /></view>
-
-					<view class="product-image">
-						<image class="image" src="https://img.alicdn.com/imgextra/i1/392147177/O1CN01Bh2NP022t7Dv5zazW_!!392147177.jpg"
-						 mode="scaleToFill"></image>
-					</view>
-					<view class="product-info">
-						<view class="row row-1">
-							<text class="title"><text class="sxzg-icon">省心直供</text>白金打开链接分厘卡圣诞节防空雷达数据</text>
-						</view>
-						<view class="row">
-							<view class="spec">白色</view>
-						</view>
-						<view class="row row-2">
-							<text class="org-price">¥2.9</text>
-						</view>
-						<view class="row">
-							<text class="sxj-icon">省心价</text>
-							<text class="price">¥1.99</text>
-						</view>
-					</view>
-					<view class="counter">
-						<view class="sub">-</view>
-						<input class="num" type="text" value="0" />
-						<view class="plus">+</view>
-					</view>
+				<view class="select">
+					<checkbox class="checkbox" :checked="seller.checked" @tap="selectSeller(seller.seller_id)" />
 				</view>
-				<view class="product-item">
-									<view class="select"><checkbox class="checkbox" value="cb" checked="true" /></view>
-
-					<view class="product-image">
-						<image class="image" src="https://img.alicdn.com/imgextra/i1/392147177/O1CN01Bh2NP022t7Dv5zazW_!!392147177.jpg"
-						 mode="scaleToFill"></image>
-					</view>
-					<view class="product-info">
-						<view class="row row-1">
-							<text class="title"><text class="sxzg-icon">省心直供</text>白金打开链接分厘卡圣诞节防空雷达数据</text>
-						</view>
-						<view class="row">
-							<view class="spec">白色</view>
-						</view>
-						<view class="row row-2">
-							<text class="org-price">¥2.9</text>
-						</view>
-						<view class="row">
-							<text class="sxj-icon">省心价</text>
-							<text class="price">¥1.99</text>
-						</view>
-					</view>
-					<view class="counter">
-						<view class="sub">-</view>
-						<input class="num" type="text" value="0" />
-						<view class="plus">+</view>
-					</view>
-				</view>
-			</view>
-		</view>
-
-		<view class="shopping-cart-item">
-			<view class="shopping-cart-item-head">
-				<view class="checkbox"></view>
-				<view class="factory-name">省心一号工厂</view>
+				<view class="factory-name">{{seller.seller_nickname?seller.seller_nickname:'省心直供(该厂家暂未设置昵称)'}}</view>
 			</view>
 			<view class="shopping-cart-info">
-				<view class="product-item">
-									<view class="select"><checkbox class="checkbox" value="cb" checked="true" /></view>
-
-					<view class="product-image">
-						<image class="image" src="https://img.alicdn.com/imgextra/i1/392147177/O1CN01Bh2NP022t7Dv5zazW_!!392147177.jpg"
-						 mode="scaleToFill"></image>
-					</view>
-					<view class="product-info">
-						<view class="row row-1">
-							<text class="title"><text class="sxzg-icon">省心直供</text>白金打开链接分厘卡圣诞节防空雷达数据</text>
-						</view>
-						<view class="row">
-							<view class="spec">白色</view>
-						</view>
-						<view class="row row-2">
-							<text class="org-price">¥2.9</text>
-						</view>
-						<view class="row">
-							<text class="sxj-icon">省心价</text>
-							<text class="price">¥1.99</text>
-						</view>
-					</view>
-					<view class="counter">
-						<view class="sub">-</view>
-						<input class="num" type="text" value="0" />
-						<view class="plus">+</view>
-					</view>
-				</view>
-				<view class="product-item">
-									<view class="select"><checkbox class="checkbox" value="cb" checked="true" /></view>
-
-					<view class="product-image">
-						<image class="image" src="https://img.alicdn.com/imgextra/i1/392147177/O1CN01Bh2NP022t7Dv5zazW_!!392147177.jpg"
-						 mode="scaleToFill"></image>
-					</view>
-					<view class="product-info">
-						<view class="row row-1">
-							<text class="title"><text class="sxzg-icon">省心直供</text>白金打开链接分厘卡圣诞节防空雷达数据</text>
-						</view>
-						<view class="row">
-							<view class="spec">白色</view>
-						</view>
-						<view class="row row-2">
-							<text class="org-price">¥2.9</text>
-						</view>
-						<view class="row">
-							<text class="sxj-icon">省心价</text>
-							<text class="price">¥1.99</text>
-						</view>
+				<view class="product-item" v-for="product in seller.products">
+					<view class="select">
+						<checkbox class="checkbox" :checked="product.checked"
+							@tap="select(product.id,product.spec_index)" />
 					</view>
-					<view class="counter">
-						<view class="sub">-</view>
-						<input class="num" type="text" value="0" />
-						<view class="plus">+</view>
-					</view>
-				</view>
-				<view class="product-item">
-									<view class="select"><checkbox class="checkbox" value="cb" checked="true" /></view>
 
 					<view class="product-image">
-						<image class="image" src="https://img.alicdn.com/imgextra/i1/392147177/O1CN01Bh2NP022t7Dv5zazW_!!392147177.jpg"
-						 mode="scaleToFill"></image>
+						<image class="image" :src="product.spec_image|imagesFilter" mode="scaleToFill"></image>
 					</view>
 					<view class="product-info">
 						<view class="row row-1">
-							<text class="title"><text class="sxzg-icon">省心直供</text>白金打开链接分厘卡圣诞节防空雷达数据</text>
+							<text class="title"><text class="sxzg-icon">省心直供</text>{{product.name}}</text>
 						</view>
 						<view class="row">
-							<view class="spec">白色</view>
+							<view class="spec">{{product.spec_name}}</view>
 						</view>
 						<view class="row row-2">
-							<text class="org-price">¥2.9</text>
+							<text class="org-price">¥{{product.spec_org_price}}</text>
 						</view>
 						<view class="row">
 							<text class="sxj-icon">省心价</text>
-							<text class="price">¥1.99</text>
+							<text class="price">¥{{product.spec_price}}</text>
 						</view>
 					</view>
 					<view class="counter">
-						<view class="sub">-</view>
-						<input class="num" type="text" value="0" />
-						<view class="plus">+</view>
+						<view class="sub" @tap="subnum(product.id,product.num,product.spec_index)">-</view>
+						<input class="num" type="text" v-model="product.num" />
+						<view class="plus" @tap="plusnum(product.id,product.num,product.spec_index)">+</view>
 					</view>
 				</view>
 			</view>
 		</view>
 
-		<view class="shopping-cart-item">
-			<view class="shopping-cart-item-head">
-				<view class="checkbox"></view>
-				<view class="factory-name">省心一号工厂</view>
-			</view>
-			<view class="shopping-cart-info">
-				<view class="product-item">
-									<view class="select"><checkbox class="checkbox" value="cb" checked="true" /></view>
 
-					<view class="product-image">
-						<image class="image" src="https://img.alicdn.com/imgextra/i1/392147177/O1CN01Bh2NP022t7Dv5zazW_!!392147177.jpg"
-						 mode="scaleToFill"></image>
-					</view>
-					<view class="product-info">
-						<view class="row row-1">
-							<text class="title"><text class="sxzg-icon">省心直供</text>白金打开链接分厘卡圣诞节防空雷达数据</text>
-						</view>
-						<view class="row">
-							<view class="spec">白色</view>
-						</view>
-						<view class="row row-2">
-							<text class="org-price">¥2.9</text>
-						</view>
-						<view class="row">
-							<text class="sxj-icon">省心价</text>
-							<text class="price">¥1.99</text>
-						</view>
-					</view>
-					<view class="counter">
-						<view class="sub">-</view>
-						<input class="num" type="text" value="0" />
-						<view class="plus">+</view>
-					</view>
-				</view>
-				<view class="product-item">
-									<view class="select"><checkbox class="checkbox" value="cb" checked="true" /></view>
-
-					<view class="product-image">
-						<image class="image" src="https://img.alicdn.com/imgextra/i1/392147177/O1CN01Bh2NP022t7Dv5zazW_!!392147177.jpg"
-						 mode="scaleToFill"></image>
-					</view>
-					<view class="product-info">
-						<view class="row row-1">
-							<text class="title"><text class="sxzg-icon">省心直供</text>白金打开链接分厘卡圣诞节防空雷达数据</text>
-						</view>
-						<view class="row">
-							<view class="spec">白色</view>
-						</view>
-						<view class="row row-2">
-							<text class="org-price">¥2.9</text>
-						</view>
-						<view class="row">
-							<text class="sxj-icon">省心价</text>
-							<text class="price">¥1.99</text>
-						</view>
-					</view>
-					<view class="counter">
-						<view class="sub">-</view>
-						<input class="num" type="text" value="0" />
-						<view class="plus">+</view>
-					</view>
-				</view>
-				<view class="product-item">
-									<view class="select"><checkbox class="checkbox" value="cb" checked="true" /></view>
-
-					<view class="product-image">
-						<image class="image" src="https://img.alicdn.com/imgextra/i1/392147177/O1CN01Bh2NP022t7Dv5zazW_!!392147177.jpg"
-						 mode="scaleToFill"></image>
-					</view>
-					<view class="product-info">
-						<view class="row row-1">
-							<text class="title"><text class="sxzg-icon">省心直供</text>白金打开链接分厘卡圣诞节防空雷达数据</text>
-						</view>
-						<view class="row">
-							<view class="spec">白色</view>
-						</view>
-						<view class="row row-2">
-							<text class="org-price">¥2.9</text>
-						</view>
-						<view class="row">
-							<text class="sxj-icon">省心价</text>
-							<text class="price">¥1.99</text>
-						</view>
-					</view>
-					<view class="counter">
-						<view class="sub">-</view>
-						<input class="num" type="text" value="0" />
-						<view class="plus">+</view>
-					</view>
-				</view>
-			</view>
-		</view>
 
 		<view class="footer">
 			<view class="select-all">
-				<label>
-					<checkbox color="#ff5d5b" class="checkbox" value="cb" checked="true" />全选
+				<label @tap="selectAll()">
+					<checkbox color="#ff5d5b" class="checkbox" :checked="checkall" />全选
 				</label>
 			</view>
-			<view class="total">合计 <text>¥26.26</text></view>
+			<view class="total">合计 <text>¥{{total}}</text></view>
 			<view class="settlement"><button class="settlement-btn" type="default">结算</button></view>
 		</view>
 	</view>
@@ -293,14 +57,76 @@
 </template>
 
 <script>
+	import {
+		mapState
+	} from 'vuex'
+
 	export default {
 		data() {
 			return {
-
+				checkall: false
 			}
 		},
+		computed: mapState({
+			cart: state => state.cart,
+			total() {
+				return this.$store.getters['cart/total']
+			}
+		}),
+		onLoad() {
+			// uni.removeStorageSync("cart")
+		},
 		methods: {
-
+			selectSeller(seller_id) {
+				this.$store.commit("cart/selectSeller", {
+					seller_id: seller_id
+				})
+			},
+			select(id, spec_index) {
+				this.$store.commit("cart/select", {
+					id: id,
+					spec_index: spec_index
+				})
+			},
+			selectAll() {
+				this.checkall = !this.checkall;
+				this.$store.commit("cart/selectAll", {
+					checked: this.checkall
+				})
+			},
+			subnum(id, num, spec_index) {
+				if (num === 0) {
+					uni.showModal({
+						title: "移除商品",
+						content: "确认移除该商品?",
+						success: (res) => {
+							if (res.confirm) {
+								this.$store.commit("cart/remove", {
+									id: id,
+									num: num,
+									spec_index: spec_index
+
+								})
+							}
+						}
+					})
+				} else {
+					num--
+				}
+				this.$store.commit("cart/numchange", {
+					id: id,
+					num: num,
+					spec_index: spec_index
+				})
+			},
+			plusnum(id, num, spec_index) {
+				num++
+				this.$store.commit("cart/numchange", {
+					id: id,
+					num: num,
+					spec_index: spec_index
+				})
+			}
 		}
 	}
 </script>
@@ -325,25 +151,29 @@
 			font-weight: bold;
 			position: relative;
 			display: flex;
-		
+
 
 		}
-		.select{			
+
+		.select {
 			align-self: center;
 			position: relative;
 			margin-top: -4upx;
 			margin-right: 20upx;
 		}
+
 		.checkbox {
 			transform: scale(0.7);
-			/deep/ .uni-checkbox-input{
+
+			/deep/ .uni-checkbox-input {
 				border: 2upx solid #CCCCCC;
-				&.uni-checkbox-input-checked{
-					color: $primary-color!important;
+
+				&.uni-checkbox-input-checked {
+					color: $primary-color !important;
 				}
 			}
 
-			/deep/ .uni-checkbox-input:hover{
+			/deep/ .uni-checkbox-input:hover {
 				border: 2upx solid #CCCCCC;
 			}
 		}
@@ -376,7 +206,7 @@
 				-webkit-box-orient: vertical;
 				-webkit-line-clamp: 2;
 				overflow: hidden;
-				height: 80upx;
+				height: 68upx;
 
 			}
 
@@ -490,12 +320,14 @@
 			.checkbox {
 				transform: scale(0.7);
 				position: relative;
-				top:-4upx
+				top: -4upx
 			}
-			/deep/ .uni-checkbox-input{
+
+			/deep/ .uni-checkbox-input {
 				border: none;
 			}
-			/deep/ .uni-checkbox-input:hover{
+
+			/deep/ .uni-checkbox-input:hover {
 				border: none;
 			}
 		}

BIN
static/images/material/sp1.png


BIN
static/images/material/sp2.png


BIN
static/images/material/sp3.png


+ 3 - 1
store/index.js

@@ -1,12 +1,14 @@
 import Vue from 'vue'
 import Vuex from 'vuex'
 import user from './modules/user'
+import cart from './modules/cart'
 
 Vue.use(Vuex)
 
 export default new Vuex.Store({
 	modules: {
-		user
+		user,
+		cart
 	},
 	strict: true
 })

+ 184 - 0
store/modules/cart.js

@@ -0,0 +1,184 @@
+// [{
+// 	seller_id: 0,
+// 	seller_nickname: "店铺名称",
+// 	products: [{
+// 		id: 0
+// 	}]
+// }]
+
+const defaults = []
+const state = JSON.parse(JSON.stringify(defaults));
+
+const getters = {
+	total(state) {
+		let sum = 0;
+		console.log(state)
+		for (let sellerIndex in state) {
+			for (let productIndex in state[sellerIndex].products) {
+				if (state[sellerIndex].products[productIndex].checked) {
+					sum += state[sellerIndex].products[productIndex].spec_price * state[sellerIndex].products[
+						productIndex].num
+				}
+			}
+		}
+		return sum.toFixed(2);
+	}
+
+}
+const mutations = {
+	add(state, payload) {
+		let sellerIsExist = false;
+		let productIsExist = false;
+		for (let sellerIndex in state) {
+			if (payload.seller_id === state[sellerIndex].seller_id) {
+				sellerIsExist = true;
+				for (let productIndex in state[sellerIndex].products) {
+					if (payload.id === state[sellerIndex].products[productIndex].id &&
+						payload.spec_index === state[sellerIndex].products[productIndex].spec_index) {
+						productIsExist = true;
+						state[sellerIndex].products[productIndex].num = payload.num;
+						break;
+					}
+				}
+
+				if (!productIsExist) {
+					state[sellerIndex].products.unshift(payload)
+				}
+				break;
+			}
+		}
+		if (!sellerIsExist) {
+			state.unshift({
+				seller_id: payload.seller_id,
+				seller_nickname: payload.seller_nickname,
+				products: [payload],
+				checked: false
+			})
+		}
+		console.log(this)
+		this.commit("cart/save", state)
+	},
+	remove(state, payload) {
+		for (let sellerIndex in state) {
+			for (let productIndex in state[sellerIndex].products) {
+				if (payload.id === state[sellerIndex].products[productIndex].id &&
+					payload.spec_index === state[sellerIndex].products[productIndex].spec_index) {
+					//如果商品已经存在于购物车
+					state[sellerIndex].products.splice(productIndex, 1)
+					if (state[sellerIndex].products.length === 0) {
+						state.splice(sellerIndex, 1)
+					}
+				}
+			}
+		}
+	},
+	selectSeller(state, payload) {
+		for (let sellerIndex in state) {
+			if (payload.seller_id === state[sellerIndex].seller_id) {
+				state[sellerIndex].checked = !state[sellerIndex].checked
+			}
+			for (let productIndex in state[sellerIndex].products) {
+				if (state[sellerIndex].seller_id === payload.seller_id) {
+					state[sellerIndex].products[productIndex].checked = state[sellerIndex].checked
+					// this._vm.$set(state[sellerIndex].products[productIndex],"checked",state[sellerIndex].checked)
+				}
+			}
+		}
+		this.commit("cart/save", state)
+	},
+	selectAll(state, payload) {
+		console.log(payload)
+		for (let sellerIndex in state) {
+			state[sellerIndex].checked = payload.checked
+			for (let productIndex in state[sellerIndex].products) {
+				state[sellerIndex].products[productIndex].checked = payload.checked
+			}
+		}
+		this.commit("cart/save", state)
+	},
+	select(state, payload) {
+		console.log(payload)
+		for (let sellerIndex in state) {
+			for (let productIndex in state[sellerIndex].products) {
+				if (payload.id === state[sellerIndex].products[productIndex].id &&
+					payload.spec_index === state[sellerIndex].products[productIndex].spec_index) {
+					state[sellerIndex].products[productIndex].checked = !state[sellerIndex].products[productIndex]
+						.checked
+				}
+			}
+		}
+		this.commit("cart/save", state)
+	},
+	numchange(context, payload) {
+		for (let sellerIndex in state) {
+			for (let productIndex in state[sellerIndex].products) {
+				if (payload.id === state[sellerIndex].products[productIndex].id &&
+					payload.spec_index === state[sellerIndex].products[productIndex].spec_index) {
+					state[sellerIndex].products[productIndex].num = payload.num
+				}
+			}
+		}
+		this.commit("cart/save", state)
+
+	},
+	save(state) {
+		uni.setStorageSync("cart", state)
+	}
+}
+const actions = {
+	add(context, payload) {
+		return new Promise((resolve, reject) => {
+			this._vm.$http.get({
+				url: "/product",
+				data: {
+					id: payload.id
+				},
+				success: (res) => {
+					console.log(res.data.data.specs)
+					const spec = JSON.parse(res.data.data.specs)[payload.specIndex];
+					const data = {
+						id: res.data.data.id,
+						images: res.data.data.images,
+						name: res.data.data.name,
+						spec_index: payload.specIndex,
+						spec_name: spec.name,
+						spec_image: spec.image,
+						spec_org_price: spec.org_price.toFixed(2),
+						spec_price: spec.price.toFixed(2),
+						spec_stock: spec.stock,
+						seller_id: res.data.data.user_id,
+						seller_nickname: res.data.data.user.nickname,
+						num: payload.num,
+						time: new Date().getTime(),
+						checked: false
+					}
+					context.commit('add', data)
+					resolve();
+				}
+			})
+		})
+	},
+	remove(context, payload) {
+		context.commit('remove', payload)
+	},
+	load(context) {
+		let cart = uni.getStorageSync("cart");
+		for (let sellerIndex in cart) {
+			for (let productIndex in cart[sellerIndex].products) {
+				context.dispatch("add", {
+					id: cart[sellerIndex].products[productIndex].id,
+					num: cart[sellerIndex].products[productIndex].num,
+					specIndex: cart[sellerIndex].products[productIndex].spec_index
+				})
+			}
+		}
+	}
+}
+
+export default {
+	namespaced: true,
+	state,
+	getters,
+	actions,
+	mutations
+}

+ 3 - 0
store/modules/user.js

@@ -10,6 +10,9 @@ const getters = {
 
 }
 const mutations = {
+	load(state) {
+		Object.assign(state, uni.getStorageSync("userinfo"))
+	},
 	save(state, payload) {
 		Object.assign(state, payload)
 	}