Browse Source

微信无咨询版本

Your Name 1 month ago
parent
commit
ab3ef27776
61 changed files with 9870 additions and 1427 deletions
  1. 21 13
      .hbuilderx/launch.json
  2. 8 7
      src/App.vue
  3. 68 10
      src/common/api.ts
  4. 14 2
      src/common/store/base/index.ts
  5. 5 1
      src/common/store/types.ts
  6. 1 1
      src/components/AppShare/AppShare.vue
  7. 78 9
      src/components/ArticleItem/ArticleItem.vue
  8. 124 25
      src/components/GoodItem/GoodItem.vue
  9. 27 22
      src/components/GoodsShare/GoodsShare.vue
  10. 11 1
      src/components/Navbar/Navbar.vue
  11. 12 12
      src/components/TabBar/TabBar.vue
  12. 83 30
      src/packages/baby/add-baby.vue
  13. 7 2
      src/packages/baby/add-feed.vue
  14. 255 0
      src/packages/baby/add-poop.vue
  15. 3 2
      src/packages/baby/baby-feed.vue
  16. 446 0
      src/packages/baby/baby-poop.vue
  17. 4 2
      src/packages/baby/baby-remark.vue
  18. 2 2
      src/packages/baby/baby-weight.vue
  19. 2 2
      src/packages/baby/select-baby.vue
  20. 169 6
      src/packages/family/family-setting.vue
  21. 250 0
      src/packages/family/family-share.vue
  22. 34 2
      src/packages/family/family-transfer.vue
  23. 68 55
      src/packages/family/member-info.vue
  24. 296 0
      src/packages/goods/brand-article-search.vue
  25. 113 18
      src/packages/goods/brand-detail.vue
  26. 88 23
      src/packages/goods/brand-goods-search.vue
  27. 147 0
      src/packages/goods/brand-list.vue
  28. 17 4
      src/packages/goods/collect-list.vue
  29. 328 136
      src/packages/goods/filter.vue
  30. 572 252
      src/packages/goods/good-detail.vue
  31. 393 0
      src/packages/goods/select-good.vue
  32. 88 0
      src/packages/user/user/about-us-list.vue
  33. 107 0
      src/packages/user/user/about-us.vue
  34. 83 0
      src/packages/user/user/exchange-success.vue
  35. 178 0
      src/packages/user/user/exchange.vue
  36. 132 0
      src/packages/user/user/feedback.vue
  37. 57 1
      src/packages/user/user/info-setting.vue
  38. 392 0
      src/packages/user/user/member.vue
  39. 243 0
      src/packages/user/user/recharge-record.vue
  40. 90 0
      src/packages/user/user/recharge-success.vue
  41. 250 0
      src/packages/user/user/share - 副本.vue
  42. 19 10
      src/packages/user/user/share.vue
  43. 118 28
      src/packages/user/user/update-phone.vue
  44. 78 27
      src/packages/user/user/user-setting.vue
  45. 168 36
      src/pages.json
  46. 257 0
      src/pages/baby/baby-list.vue
  47. 24 28
      src/pages/category/category.vue
  48. 649 0
      src/pages/contrast/contrast - 副本 (4).vue
  49. 208 56
      src/pages/contrast/contrast-list.vue
  50. 628 184
      src/pages/contrast/contrast.vue
  51. 37 0
      src/pages/front/article - 副本.vue
  52. 220 27
      src/pages/front/article.vue
  53. 405 136
      src/pages/front/front.vue
  54. 385 0
      src/pages/login/baby.vue
  55. 91 25
      src/pages/login/login.vue
  56. 318 0
      src/pages/login/phone-login.vue
  57. 325 0
      src/pages/login/pregnant.vue
  58. 230 0
      src/pages/login/select-stage.vue
  59. 439 229
      src/pages/user/user.vue
  60. 4 0
      src/router/index.ts
  61. 1 1
      src/uni.scss

+ 21 - 13
.hbuilderx/launch.json

@@ -4,19 +4,27 @@
     "version" : "0.0",
     "configurations" : [
         {
-            "app-plus" : {
-                "launchtype" : "local"
-            },
-            "default" : {
-                "launchtype" : "local"
-            },
-            "h5" : {
-                "launchtype" : "local"
-            },
-            "mp-weixin" : {
-                "launchtype" : "local"
-            },
-            "type" : "uniCloud"
+        	"app-plus" : 
+        	{
+        		"launchtype" : "local"
+        	},
+        	"default" : 
+        	{
+        		"launchtype" : "local"
+        	},
+        	"h5" : 
+        	{
+        		"launchtype" : "local"
+        	},
+        	"mp-toutiao" : 
+        	{
+        		"launchtype" : "local"
+        	},
+        	"mp-weixin" : 
+        	{
+        		"launchtype" : "local"
+        	},
+        	"type" : "uniCloud"
         },
         {
             "openVueDevtools" : true,

+ 8 - 7
src/App.vue

@@ -38,15 +38,16 @@ export default {
 </script>
 
 <style lang="scss">
+	
 /* 在线链接服务仅供平台体验和调试使用,平台不承诺服务的稳定性,企业客户需下载字体包自行发布使用并做好备份。 */
-	@font-face {
-	  font-family: 'iconfont';  /* Project id 4894081 */
-	  src: url('https://at.alicdn.com/t/c/font_4894081_hp35y60av5.woff2?t=1744868650751') format('woff2'),
-	       url('https://at.alicdn.com/t/c/font_4894081_hp35y60av5.woff?t=1744868650751') format('woff'),
-	       url('https://at.alicdn.com/t/c/font_4894081_hp35y60av5.ttf?t=1744868650751') format('truetype');
-	}
+@font-face {
+  font-family: 'iconfont';  /* Project id 4894081 */
+  src: url('https://at.alicdn.com/t/c/font_4894081_5mocsocvcyo.woff2?t=1745990845888') format('woff2'),
+       url('https://at.alicdn.com/t/c/font_4894081_5mocsocvcyo.woff?t=1745990845888') format('woff'),
+       url('https://at.alicdn.com/t/c/font_4894081_5mocsocvcyo.ttf?t=1745990845888') format('truetype');
+}
 
 page {
-	background-color: #FAFAFA;
+	background-color: #F2F2F2;
 }
 </style>

+ 68 - 10
src/common/api.ts

@@ -8,14 +8,44 @@ export default {
 	Qrcode: '/common/wx/mini/code',					//生成二维码
 	sendCode: '/common/send/sms/code',				//发送验证码
 	verifyCode: '/common/verify/sms/code', 			//验证短信验证码
+	updateUserInfo: '/user/user/update/info',		//更新个人信息
+	getShareInfo: '/user/setup/share/info', 		//C端分享设置详情
+
+	finishRegister: '/user/user/register/create/finish',
 	
-	getUserInfo: '/user/user/info',
+	createPay: '/user/pay/create',
 	
+	updatePhone: '/user/user/bind/phone',
+
+	getUserInfo: '/user/user/info',
+	getAgreementInfo: '/user/agreement/info',		//用户协议隐私政策
+
+	// 意见反馈
+	addFeedback: '/user/feedback/add',
+
 	// 首页
 	getBannerList: '/user/setup/banner/get',		//轮播图
 	getPlatformBannerList: '/user/platform/banner/get',//获取首页文章轮播图
-	getArticleList:'/user/platform/article/get',	//获取文章列表
-	
+	getArticleList: '/user/platform/article/get',	//获取文章列表
+	getArticleInfo: '/user/platform/article/info', //获取文章详情
+	getArticleGategoryList: '/user/platform/classify/get',
+
+	//标签
+	//推荐分类
+	getRecommendLabel: '/user/label/recommend',
+	//筛选个更多标签
+	getFilterLabel: '/user/label/filter',
+	//标签项
+	getLabelItem: '/user/label/item/list/son',
+
+	//热门品牌
+	getHotBrandList: '/user/brand/set/hot/list',
+	getBrandList: '/user/brand/set/list',
+	getBrandInfo: '/user/brand/set/info',
+
+	//系列
+	getSeriesList: '/user/brand/set/series/list',
+
 	// 宝宝档案
 	getBabyList: '/user/baby/list',					//获取宝宝档案列表
 	addBaby: '/user/baby/add',						//添加宝宝档案
@@ -23,28 +53,35 @@ export default {
 	deleteBaby: '/user/baby/delete',				//删除宝宝档案
 	getBabyListBySelf: '/user/baby/all/list',		//获取用户管理的宝宝列表
 	getBabyInfo: '/user/baby/info',					//获取宝宝档案详情
-	
+
 	//喂养记录
 	getBabyFeedList: '/user/baby/feed/list',		//获取喂养记录列表
 	addBabyFeed: '/user/baby/feed/add',				//添加喂养记录
 	updateBabyFeed: '/user/baby/feed/update',		//编辑喂养记录
 	deleteBabyFeed: '/user/baby/feed/delete',		//删除喂养记录
 	getBabyFeedInfo: '/user/baby/feed/info',
-	
+
 	//身高体重
 	getBabyGrowthList: '/user/baby/growth/list',	//获取身高体重列表
-	addBabyGrowth: '/user/baby/growth/add',			
+	addBabyGrowth: '/user/baby/growth/add',
 	updateBabyGrowth: '/user/baby/growth/update',
 	deleteBabyGrowth: '/user/baby/growth/delete',
 	getBabyGrowthInfo: '/user/baby/growth/info',
-	
+
 	//成长备注
 	getBabyRemarkList: '/user/baby/remark/list',	//获取成长备注列表
 	addBabyRemark: '/user/baby/remark/add',
 	updateBabyRemark: '/user/baby/remark/update',
 	deleteBabyRemark: '/user/baby/remark/delete',
 	getBabyRemarkInfo: '/user/baby/remark/info',
-	
+
+	//便便
+	getBabyPoopList: '/user/baby/poop/list',	//获取便便列表
+	addBabyPoop: '/user/baby/poop/add',
+	updateBabyPoop: '/user/baby/poop/update',
+	deleteBabyPoop: '/user/baby/poop/delete',
+	getBabyPoopInfo: '/user/baby/poop/info',
+
 	// 家庭
 	getFamilyList: '/user/baby/family/all/list',
 	addFamily: '/user/baby/family/add',
@@ -57,5 +94,26 @@ export default {
 	agreeFamilyInvite: '/user/baby/family/invite/agree',
 	getFamilyInfo: '/user/baby/family/info',
 	getMemberListByFamily: '/user/baby/family/member/list',
-	
-}
+	entranceFamily: '/user/baby/family/entrance',
+
+	getFamilyMemberInfo: '/user/baby/family/member/info',
+
+	quitFamily: '/user/baby/family/member/quit',
+	deleteFamilyMember: '/user/baby/family/delete/member',
+
+
+	//会员
+	getMemberRechargeList: '/user/baby/money/recharge/list',
+	getConsultList: '/user/consult/list',
+	buyConsult: '/user/consult/buy',
+	getRechargeRecord: '/user/baby/money/recharge/history',
+	getRecharge: '/user/baby/money/recharge',
+
+	//产品
+	getGoodsList: '/user/goods/list',
+	getGoodInfo: '/user/goods/info',
+	addCollection: '/user/goods/collection/add',
+	moveCollection: '/user/goods/collection/remove',
+	emptyCollection: '/user/goods/collection/remove/all',
+	topCollection:'/user/goods/collection/pin',
+}

+ 14 - 2
src/common/store/base/index.ts

@@ -23,7 +23,9 @@ import {
 	SET_YES_NUM,
 	SET_ORDER_INFO,
 	SET_BANK_CARD,
-	SET_SELF_PICKUP_POINT
+	SET_SELF_PICKUP_POINT,
+	SET_GOOD,
+	SET_CONTRAST_GOOD_ID
 } from '@/common/store/types';
 
 const module = {
@@ -53,7 +55,9 @@ const module = {
 		   sumCount: 0,
 		   sumPrice: 0,
 		   data: []
-	   }
+	   },
+	   good: {},
+	   contrastGoodId: []
     }
   },
   getters: {
@@ -76,6 +80,8 @@ const module = {
 	_orderInfo:(state:any) => state.orderInfo,
 	_bankCard:(state:any) => state.bankCard,
 	_selfPickupPoint:(state:any) => state.selfPickupPoint,
+	_good:(state:any) => state.good,
+	_contrastGoodId:(state:any) => state.contrastGoodId,
   },
   mutations: {
     // 登录成功将, token保存在localStorage中
@@ -185,6 +191,12 @@ const module = {
 	[SET_SELF_PICKUP_POINT]: (state:any, data:any) => {
 	  state.selfPickupPoint = data;
 	},
+	[SET_GOOD]: (state:any, data:any) => {
+	  state.good = data;
+	},
+	[SET_CONTRAST_GOOD_ID]: (state:any, data:any) => {
+	  state.contrastGoodId = data;
+	},
   },
   actions: {
     [ADD_CARTGOODS]:({state,commit}:any,goodsInfo: any) => {

+ 5 - 1
src/common/store/types.ts

@@ -25,6 +25,8 @@ const SET_YES_NUM = 'setYesNum';
 const SET_ORDER_INFO = 'setOrderInfo';
 const SET_BANK_CARD = 'setBankCard';
 const SET_SELF_PICKUP_POINT = 'setSelfPickupPoint';
+const SET_GOOD = 'setGood';
+const SET_CONTRAST_GOOD_ID = 'setContrastGoodId';
 export {
   SET_TOKEN,
   SET_ISLOGIN,
@@ -52,5 +54,7 @@ export {
   SET_YES_NUM,
   SET_ORDER_INFO,
   SET_BANK_CARD,
-  SET_SELF_PICKUP_POINT
+  SET_SELF_PICKUP_POINT,
+  SET_GOOD,
+  SET_CONTRAST_GOOD_ID
 };

+ 1 - 1
src/components/AppShare/AppShare.vue

@@ -107,7 +107,7 @@
 			this.textSet(ctx, '爱润妍', '14px', 13, 365, '#000', 'bold ');
 			// // 小程序码
 			ctx.drawImage(that._canvasData.qr, 150, 295, 90, 90);
-			this.textSet(ctx, '长按识别进店铺', '10px', 90, 400, '#999999');
+			this.textSet(ctx, '长按识别进', '10px', 90, 400, '#999999');
 			ctx.draw(true, () => {
 				console.log('draw,true');
 				uni.hideLoading();

+ 78 - 9
src/components/ArticleItem/ArticleItem.vue

@@ -1,18 +1,22 @@
 <template>
-	<view class="article-item" v-if="article" :style="{background: bg,marginBottom: (marginBottom / 3.75) + 'vw'}"
+	<view class="article-item" :class="{'article-item2': collectShow || borderRadiusShow}" v-if="article && show" :style="{background: bg,marginBottom: (marginBottom / 3.75) + 'vw'}"
 		@click="handleDetail">
+		<view class="collect-box" v-if="collectShow" @click.stop="moveCollection">
+			已收藏
+			<image :src="staticUrl ? staticUrl + 'collect-btn-c.png' : ''" class="pic"
+				mode="heightFix"></image>
+		</view>
 		<view class="article-info">
-			<image :src="article.masterPic" class="pic" mode="aspectFill"></image>
+			<image :src="article.articlePic" class="pic" mode="aspectFill"></image>
 			<view class="article-name">
-				{{article.name}}
+				{{article.articleTitle}}
 			</view>
 		</view>
 		<view class="article-bottom">
 			<view class="left">
-				<view><text>#</text>母婴周报</view>
-				<view><text>#</text>孩子王</view>
+				<view v-for="(item, index) in article.linkName"><text>#</text>{{item}}</view>
 			</view>
-			<view class="date">6小时前</view>
+			<view class="date">{{article.updated | dateFormat}}</view>
 		</view>
 	</view>
 </template>
@@ -24,6 +28,7 @@
 		Mixins
 	} from 'vue-property-decorator';
 	import loginMixin from '@/common/mixins/loginMixin.ts';
+	import dayjs from 'dayjs';
 	@Component({
 		filters: {
 			moneyFormat(val : any) {
@@ -36,7 +41,25 @@
 					return (+val / 10000).toFixed(2) + 'w';
 				}
 				return (+val).toFixed(2);
-			}
+			},
+			dateFormat(val : any) {
+				if(val) {
+					let now = +new Date() / 1000;
+					let date = +new Date(val) / 1000;
+					let num = now - date;
+					if(num < 60 * 60){
+						return '刚刚发布';
+					} else if(num < 60 * 60 * 24){
+						return Math.floor(num / (60 * 60)) + '小时前';
+					} else if(num < 60 * 60 * 24 * 3){
+						return Math.floor(num / (60 * 60 * 24)) + '天前';
+					} else {
+						return dayjs(val).format('YYYY-MM-DD')
+					}
+				} else {
+					return '';
+				};
+			},
 		}
 	})
 	export default class Navbar extends Mixins(loginMixin) {
@@ -54,17 +77,44 @@
 			default: 0
 		})
 		private marginBottom ?: number; // 
+		@Prop({
+			default: false
+		})
+		private collectShow ?: boolean; // 
+		@Prop({
+			default: false
+		})
+		private borderRadiusShow ?: boolean; // 
 		staticUrl : string = this.$oss_url; //oss地址
+		show: any = true;
 
 		handleDetail() {
 			this.$Router.push({
-				path: '/packages/articles/article-detail',
+				path: '/pages/front/article',
 				query: {
 					id: this.article.id,
-					gid: this.article.gid
 				}
 			});
 		}
+		
+		moveCollection(){
+			this.$http
+				.post({
+					url: this.$api.moveCollection,
+					data: {
+						types: 2,
+						rid: this.article.id
+					}
+				})
+				.then((res : any) => {
+					uni.showToast({
+						title: '已取消收藏'
+					});
+					this.show = false;
+				}, (err : any) => {
+					console.log(err);
+				});
+		}
 	}
 </script>
 
@@ -76,6 +126,16 @@
 		padding-top: vw(16);
 		padding-bottom: vw(10);
 		box-sizing: border-box;
+		
+		.collect-box{
+			@include word-vw(12, #999);
+			font-weight: normal;
+			@include flex-x(flex-end);
+			.pic{
+				@include wh(14, 14);
+				margin-left: vw(5);
+			}
+		}
 	
 		.article-info {
 			@include flex-x();
@@ -99,8 +159,10 @@
 			.left{
 				@include word-vw(10, #333);
 				@include flex-x(flex-start);
+				flex-wrap: wrap;
 				view{
 					margin-right: vw(8);
+					white-space: nowrap;
 					text{
 						@include word-vw(12, #FF7E33);
 						margin-right: vw(1);
@@ -109,7 +171,14 @@
 			}
 			.date{
 				@include word-vw(10, #999);
+				white-space: nowrap;
+				margin-left: vw(12);
 			}
 		}
 	}
+	.article-item2{
+		border-radius: vw(10);
+		border-bottom-width: 0;
+		padding: vw(10);
+	}
 </style>

+ 124 - 25
src/components/GoodItem/GoodItem.vue

@@ -1,29 +1,36 @@
 <template>
-	<view class="good-item" v-if="good" :style="{background: bg,marginBottom: (marginBottom / 3.75) + 'vw'}"
-		@click="handleDetail">
-		<view class="good-name">{{good.name}}</view>
+	<view class="good-item" v-if="good && show" :style="{background: bg,marginBottom: (marginBottom / 3.75) + 'vw'}"
+		@click.stop="handleDetail" :key="timeStamp">
+		<view class="good-name">
+			{{good.name}}
+			<view class="collect-box" v-if="collectShow" @click.stop="moveCollection">
+				已收藏
+				<image :src="staticUrl ? staticUrl + 'collect-btn-c.png' : ''" class="pic"
+					mode="heightFix"></image>
+			</view>
+		</view>
 		<view class="good-info-box">
 			<image :src="good.masterPic" class="pic" mode="aspectFit"></image>
 			<view class="good-info">
 				<view class="area">
-					<view><text class="label">奶源:</text>中国</view>
-					<view><text class="label">产地:</text>中国</view>
+					<view><text class="label">奶源:</text>{{good.milkSourceName}}</view>
+					<view><text class="label">产地:</text>{{good.milkOriginName}}</view>
 				</view>
-				<view class="advantage">
+				<view class="advantage" v-if="good.advantageLabels && good.advantageLabels.length">
 					<text class="label">优点:</text>
-					<view class="advantage-item" v-for="(item, index) in ['α+β创新蛋白组合', '乳源HMO']"
-						:key="index">
-						{{item}}
+					<view class="advantage-item" v-for="(item, index) in good.advantageLabels" :key="index">
+						{{item.labelName}}
 					</view>
 				</view>
 				<view class="price">
 					<text class="label">参考价:</text>
 					<text class="price-icon">¥</text>
-					328
+					{{good.price}}
 				</view>
 			</view>
 		</view>
-		<view class="btn">+ 加入对比</view>
+		<view class="btn btn2" @click.stop v-if="beCompared === 1">已加入对比</view>
+		<view class="btn" @click.stop="addCollection" v-else>+ 加入对比</view>
 	</view>
 </template>
 
@@ -33,6 +40,13 @@
 		Prop,
 		Mixins
 	} from 'vue-property-decorator';
+	import {
+		types
+	} from '@/common/store/index';
+	import {
+		namespace
+	} from 'vuex-class';
+	const baseModule = namespace('base');
 	import loginMixin from '@/common/mixins/loginMixin.ts';
 	@Component({
 		filters: {
@@ -50,6 +64,8 @@
 		}
 	})
 	export default class Navbar extends Mixins(loginMixin) {
+		@baseModule.Getter('_contrastGoodId') _contrastGoodId: any;
+		@baseModule.Mutation(types.SET_CONTRAST_GOOD_ID) setContrastGoodId : any;
 		@Prop({
 			default: {}
 		})
@@ -64,17 +80,87 @@
 			default: 10
 		})
 		private marginBottom ?: number; // 
+		@Prop({
+			default: false
+		})
+		private collectShow ?: boolean; // 
+		@Prop({
+			default: ''
+		})
+		private type ?: string; // 
 		staticUrl : string = this.$oss_url; //oss地址
+		timeStamp : any = +new Date();
+		show: any = true;
+		beCompared: any = 0;
+		
+		created(){
+			// console.log(this.good)
+			this.beCompared = this.good.beCompared;
+		}
+		
+		updated(){
+			// console.log(this.good)
+			this.beCompared = this.good.beCompared;
+		}
 
 		handleDetail() {
 			this.$Router.push({
 				path: '/packages/goods/good-detail',
 				query: {
 					id: this.good.id,
-					gid: this.good.gid
+					type: this.type
 				}
 			});
 		}
+
+		addCollection() {
+			this.$http
+				.post({
+					url: this.$api.addCollection,
+					data: {
+						types: 3,
+						rid: this.good.id
+					}
+				})
+				.then((res : any) => {
+					uni.showToast({
+						title: '添加成功'
+					});
+					this.good.beCompared = 1;
+					this.$forceUpdate();
+					if(this.type === 'contrast'){
+						this.setContrastGoodId([...this._contrastGoodId, this.good.id]);
+						this.$Router.back(1);
+						// this.$Router.pushTab({
+						// 	path: '/pages/contrast/contrast-list',
+						// 	query: {
+						// 		type: 'contrast'
+						// 	}
+						// })
+					};
+				}, (err : any) => {
+					console.log(err);
+				});
+		}
+		
+		moveCollection(){
+			this.$http
+				.post({
+					url: this.$api.moveCollection,
+					data: {
+						types: 1,
+						rid: this.good.id
+					}
+				})
+				.then((res : any) => {
+					uni.showToast({
+						title: '已取消收藏'
+					});
+					this.show = false;
+				}, (err : any) => {
+					console.log(err);
+				});
+		}
 	}
 </script>
 
@@ -87,40 +173,49 @@
 		padding: vw(14);
 		box-sizing: border-box;
 		position: relative;
-	
+
 		.good-name {
 			@include word-vw(14, #333);
-			font-weight: 450;
+			font-weight: bold;
+			@include flex-x();
+			.collect-box{
+				@include word-vw(12, #999);
+				font-weight: normal;
+				.pic{
+					@include wh(14, 14);
+					margin-left: vw(5);
+				}
+			}
 		}
-	
+
 		.good-info-box {
 			margin-top: vw(12);
 			@include flex-x();
-	
+
 			.pic {
 				@include wh(80, 80);
 				display: block;
 			}
-	
+
 			.good-info {
 				flex: 1;
 				min-height: vw(80);
 				margin-left: vw(16);
 				@include flex-y(flex-start, flex-start);
-	
+
 				.label {
 					@include word-vw(12, #999);
 				}
-	
+
 				.area {
 					@include flex-x(flex-start);
 					@include word-vw(12, #333);
-	
+
 					view {
 						width: vw(90);
 					}
 				}
-	
+
 				.advantage {
 					margin-top: vw(8);
 					@include word-vw(10, #FF7E33);
@@ -128,7 +223,7 @@
 					flex-wrap: wrap;
 					line-height: vw(20);
 					flex: 1;
-	
+
 					.advantage-item {
 						height: vw(18);
 						padding: 0 vw(6);
@@ -137,17 +232,17 @@
 						margin-right: vw(6);
 					}
 				}
-	
+
 				.price {
 					@include word-vw(18, #FF5733);
-	
+
 					.price-icon {
 						@include word-vw(12, #FF5733);
 					}
 				}
 			}
 		}
-	
+
 		.btn {
 			@include wh(76, 26);
 			@include word-vw(12, #fff);
@@ -158,5 +253,9 @@
 			right: vw(12);
 			bottom: vw(12);
 		}
+
+		.btn2 {
+			background: #FF5733;
+		}
 	}
 </style>

+ 27 - 22
src/components/GoodsShare/GoodsShare.vue

@@ -45,9 +45,14 @@
 	export default class ShopShare extends Mixins(canvasMixin) {
 		@canvasModule.Getter('_canvasData') _canvasData: any;
 		@baseModule.Getter('_userInfo') _userInfo: any;
-		@baseModule.Getter('_goods') goodsInfo: any;
+		// @baseModule.Getter('_goods') goodsInfo: any;
 		popShow: boolean = false;
 		static: string = OSS_STATIC;
+		
+		@Prop({
+			default: {}
+		})
+		private goodsInfo! : any; // 
 
 		closePop(): void {
 			(this.$refs.popup as any).close();
@@ -72,10 +77,10 @@
 			// 绘制白色底
 			this.roundRect(ctx, 0, 0, 250, 460, '#ffffff', 8, 8, 8, 8);
 			// 绘制头像
-			this.drawCircular(ctx, 24, 24, 13, 15, that._canvasData.avatar);
+			this.drawCircular(ctx, 24, 24, 13, 15, that._canvasData.avatar || require('@/static/avatar.png'));
 			this.ellipsisText(
 				ctx,
-				that._userInfo.nickname,
+				that._userInfo.nickname || '用户',
 				// '爱润妍',
 				200,
 				43,
@@ -111,7 +116,7 @@
 			this.ellipsisText(
 				ctx,
 				that.goodsInfo.name,
-				180,
+				240,
 				11,
 				291,
 				'#000',
@@ -121,24 +126,24 @@
 				'bold '
 			);
 			// 商品副标题
-			this.ellipsisText(
-				ctx,
-				that.goodsInfo.tagline,
-				150,
-				11,
-				311,
-				'#999',
-				'10px',
-				14,
-				1
-			);
+			// this.ellipsisText(
+			// 	ctx,
+			// 	that.goodsInfo.tagline,
+			// 	150,
+			// 	11,
+			// 	311,
+			// 	'#999',
+			// 	'10px',
+			// 	14,
+			// 	1
+			// );
 			//  划线价
-			let linePrice:string = '¥0.00';
-			if (that.goodsInfo.linePrice) {
-				linePrice = '¥' + Number(that.goodsInfo.linePrice).toFixed(2);
+			let price:string = '¥0.00';
+			if (that.goodsInfo.price) {
+				price = '¥' + Number(that.goodsInfo.price).toFixed(2);
 			}
-			// this.textSet(ctx, linePrice, '12px', 11, 375, '#999');
-			// let lineH = ctx.measureText(linePrice).width;
+			// this.textSet(ctx, price, '12px', 11, 375, '#999');
+			// let lineH = ctx.measureText(price).width;
 			// ctx.moveTo(14, 382);
 			// ctx.lineTo(lineH + 14, 382);
 			// ctx.strokeStyle = '#999999';
@@ -147,7 +152,7 @@
 			this.textSet(ctx, '¥', '12px', 11, 362, '#000', 'bold ');
 			this.textSet(
 				ctx,
-				Number(that.goodsInfo.minPrice).toFixed(2),
+				Number(that.goodsInfo.price).toFixed(2),
 				'19px',
 				19,
 				356,
@@ -156,7 +161,7 @@
 			);
 			// // 小程序码
 			ctx.drawImage(that._canvasData.goodQr, 150, 295, 90, 90);
-			this.textSet(ctx, '长按识别进店铺', '10px', 90, 400, '#999999');
+			this.textSet(ctx, '长按识别进', '10px', 90, 400, '#999999');
 			ctx.draw(true, () => {
 				console.log('draw,true');
 				uni.hideLoading();

+ 11 - 1
src/components/Navbar/Navbar.vue

@@ -122,7 +122,7 @@
 
 		handle_click_back() : void {
 			console.log(this.$Router)
-			this.$Router.back(1);
+			this.backPage();
 		}
 
 		handle_click_search() {
@@ -130,6 +130,16 @@
 				path: '/packages/goods/search'
 			})
 		}
+		
+		backPage(){
+			if(getCurrentPages().length <= 1) {
+				this.$Router.pushTab({
+					path: '/pages/front/front'
+				});
+				return;
+			}
+			this.$Router.back(1);
+		}
 
 		handle_click_home() {
 			this.$Router.pushTab({

+ 12 - 12
src/components/TabBar/TabBar.vue

@@ -4,7 +4,7 @@
 			<view v-for="(item, index) in list.slice(0, 5)" :key="index" class="tab-bar-item"
 				@click="switchTab(item, index)">
 				<IconText :color="tabBarIndex === index ? selectedColor : color" :size="24"
-					:code="tabBarIndex === index ? item.selectedIconPath : item.iconPath" v-if="item.text !== '咨询'"></IconText>
+					:code="tabBarIndex === index ? item.selectedIconPath : item.iconPath" v-if="item.text !== '选奶咨询'"></IconText>
 				<view class="pic-box" v-else>
 					<view class="pic">
 						<IconText :code="`\ue89b`" color="#fff" size="28" class="icon"></IconText>
@@ -38,28 +38,28 @@
 				text: '首页'
 			},
 			{
-				pagePath: 'pages/category/category',
-				iconPath: '\ue89e',
-				selectedIconPath: '\ue89e',
-				text: '全部分类'
+				pagePath: 'pages/contrast/contrast-list',
+				iconPath: '\ue8b3',
+				selectedIconPath: '\ue8b3',
+				text: '比奶粉'
 			},
 			{
 				pagePath: 'pages/local/local-life',
 				iconPath: '\ue87f',
 				selectedIconPath: '\ue87f',
 				pic: 'tabber-index.png',
-				text: '咨询'
+				text: '选奶咨询'
 			},
 			{
-				pagePath: 'pages/contrast/contrast-list',
-				iconPath: '\ue8a4',
-				selectedIconPath: '\ue8a4',
-				text: '对比'
+				pagePath: 'pages/baby/baby-list',
+				iconPath: '\ue89a',
+				selectedIconPath: '\ue89a',
+				text: '宝宝档案'
 			},
 			{
 				pagePath: 'pages/user/user',
-				iconPath: '\ue89a',
-				selectedIconPath: '\ue89a',
+				iconPath: '\ue8b2',
+				selectedIconPath: '\ue8b2',
 				text: '我的'
 			}
 		];

+ 83 - 30
src/packages/baby/add-baby.vue

@@ -9,7 +9,7 @@
 				<view class="pic-box box">
 					<view class="label">
 						<view class="upload-pic-box" @click="chooseImg">
-							<image class="avatar" :src="form.avatar" mode="aspectFill"></image>
+							<image class="avatar" :src="form.babyAvatar" mode="scaleToFill"></image>
 							<view class="camera-box">
 								<IconText class="icon" :code="`\ue8a9`" size="14" color="#fff"></IconText>
 							</view>
@@ -21,16 +21,11 @@
 					<view class="label">
 						宝宝昵称
 					</view>
-					<input v-model="form.nickname" type="text" class="input" placeholder="此处输入宝宝昵称"/>
+					<input v-model="form.babyNickname" type="text" class="input" placeholder="此处输入宝宝昵称"/>
 				</view>
 				<view class="gender-box box">
 					<view class="label"></view>
 					<view class="gender-select">
-						<view class="item" @click="handleSelectGender(0)">
-							<IconText class="icon" :code="`\ue842`" v-if="!form.gender" size="12" color="#6B95FF"></IconText>
-							<IconText class="icon" :code="`\ue84e`" size="12" color="#999" v-else></IconText>
-							小孩
-						</view>
 						<view class="item" @click="handleSelectGender(1)">
 							<IconText class="icon" :code="`\ue842`" v-if="form.gender === 1" size="12" color="#6B95FF"></IconText>
 							<IconText class="icon" :code="`\ue84e`" size="12" color="#999" v-else></IconText>
@@ -74,30 +69,31 @@
 					<input v-model="form.constitution" type="text" class="input" placeholder="此处输入宝宝体质"/>
 				</view>
 			</view>
-			<view class="info-box">
+			<view class="info-box" :class="{'bottom-border-radius': !form.feedMode || form.feedMode === 1}">
 				<view class="label">喂养方式</view>
 				<view class="right">
 					<picker @change="changeFeedMode" :value="feedModeIndex" :range="feedModeList" range-key="name">
 						<view class="date">
-							{{feedModeList[feedModeIndex].name || '请选择'}}
+							{{feedModeMap[form.feedMode] || '请选择'}}
 							<IconText :code="`\ue88e`" class="icon" size="12" color="#C6C5CB"></IconText>
 						</view>
 					</picker>
 				</view>
 			</view>
-			<view class="info-box bottom-border-radius">
+			<view class="info-box bottom-border-radius" v-if="form.feedMode === 2 || form.feedMode === 3">
 				<view class="label">选择奶粉</view>
 				<view class="right select-milk-powder">
-					<input v-model="form.constitution" type="text" class="input" placeholder="此处输入奶粉名称"/>
-					<view class="btn">选择</view>
+					<input v-model="form.productName" type="text" class="input" placeholder="此处输入奶粉名称"/>
+					<!-- <view class="name" v-if="_good.id">{{_good.name}}</view> -->
+					<view class="btn" @click="toSelectGood">选择</view>
 				</view>
 			</view>
 			<view class="info-box top-border-radius bottom-border-radius top10">
 				<view class="label">所在家庭</view>
 				<view class="right">
-					<picker @change="changeFamily" :value="familyIndex" :range="familyList" range-key="name">
+					<picker @change="changeFamily" :value="familyIndex" :range="familyList" range-key="familyName">
 						<view class="date">
-							{{familyList[familyIndex].name || '请选择'}}
+							{{familyList[familyIndex].familyName || '请选择'}}
 							<IconText :code="`\ue88e`" class="icon" size="12" color="#C6C5CB"></IconText>
 						</view>
 					</picker>
@@ -105,7 +101,7 @@
 			</view>
 		</view>
 		<view class="fixed-bottom" >
-			<view class="btn" @click="deleteBabyModal" v-if="bid">删除</view>
+			<view class="btn" @click="deleteBabyModal" v-if="bid && uid === _userInfo.uid">删除</view>
 			<view class="solid-btn" @click="handleConfirm">保存</view>
 		</view>
 		<ShowModal ref="deletePopup" title="提示" @submit="deleteBaby" leftBtnText="取消" content="确认后宝宝数据将清空,是否确认删除?" btnText="确认" />
@@ -118,10 +114,13 @@
 		Mixins
 	} from 'vue-property-decorator';
 	import loginMixin from '@/common/mixins/loginMixin.ts';
-	// import {
-	// 	namespace
-	// } from 'vuex-class';
-	// const baseModule = namespace('base');
+	import {
+		types
+	} from '@/common/store/index';
+	import {
+		namespace
+	} from 'vuex-class';
+	const baseModule = namespace('base');
 	@Component({
 		filters: {
 			phoneFormat(val : any) {
@@ -144,18 +143,22 @@
 	})
 	export default class UserSetting extends Mixins(loginMixin) {
 		// @baseModule.Getter('_userInfo') _userInfo: any;
+		@baseModule.Getter('_good') _good: any;
+		@baseModule.Mutation(types.SET_GOOD) setGood : any;
 		gender: any = 1;
 		constitutionList: any = [];
 		familyList: any = []
 		form: any = {
-			avatar: '',
-			nickname: '',
+			babyAvatar: '',
+			babyNickname: '',
 			gender: 0,
 			birthday: '',
 			birthWeight: null,
 			allergy: 2,
 			constitution: '',
-			fId: null,
+			fid: null,
+			feedMode: null,
+			productName: ''
 		};
 		constitutionIndex: any = null;
 		familyIndex: any = null;
@@ -175,14 +178,31 @@
 				value: 3
 			}
 		];
+		feedModeMap: any = {
+			1: '母乳',
+			2: '配方奶',
+			3: '混合'
+		}
 		feedModeIndex: any = null;
+		uid:any = null;
+		isFirst: any = true;
+		// familyList: any = [];
 		
 		onShow() {
-			
+			if(this.isFirst) {
+				this.isFirst = false;
+				return;
+			};
+			this.form.productName = this._good.name || '';
+			this.form = {
+				...this.form
+			}
 		}
 		
-		onLoad(){
+		async onLoad(){
+			this.setGood({});
 			this.type = this.$Route.query.type;
+			await this.getFamilyList();
 			if (this.$Route.query.bid) {
 				this.bid = +this.$Route.query.bid;
 				this.getBabyInfo();
@@ -210,9 +230,24 @@
 					this.form[key] = res[key];
 				}
 				uni.hideLoading();
+				this.setGood({name: res.productName});
+				this.uid = res.uid;
+				this.familyIndex = this.familyList.findIndex((item: any) => item.fid === res.fid);
 			})
 		}
 		
+		getFamilyList() {
+			return this.$http
+				.get({
+					url: this.$api.getFamilyList
+				})
+				.then((res : any) => {
+					this.familyList = res.list;
+				}, (err : any) => {
+					console.log(err);
+				});
+		}
+		
 		changeFeedMode(e: any){
 			this.feedModeIndex = e.detail.value;
 			this.form.feedMode = this.feedModeList[e.detail.value].value;
@@ -252,7 +287,7 @@
 						})
 						.then((res : any) => {
 							uni.hideLoading();
-							this.form.avatar = res;
+							this.form.babyAvatar = res;
 						})
 						.catch((err : any) => {
 							uni.hideLoading();
@@ -270,7 +305,7 @@
 		
 		changeFamily(e: any){
 			this.familyIndex = e.detail.value;
-			this.form.fId = this.familyList[e.detail.value].id;
+			this.form.fid = this.familyList[e.detail.value].fid;
 		}
 		
 		changeAllergy(e: any){
@@ -297,6 +332,12 @@
 			})
 		}
 		
+		toSelectGood(){
+			this.$Router.push({
+				path: '/packages/goods/select-good'
+			})
+		}
+		
 		handleConfirm(){
 			console.log(this.form);
 			uni.showLoading({
@@ -306,7 +347,8 @@
 			let method : string = 'post';
 			let data: any = {
 				...this.form,
-				birthWeight: +this.form.birthWeight
+				birthWeight: +this.form.birthWeight,
+				// productName: this._good.name || ''
 			};
 			if (this.bid) {
 				url = 'updateBaby';
@@ -465,13 +507,24 @@
 							margin-left: vw(3);
 						}
 					}
-					&.select-milk-powder{
+					&.select-milk-powder {
+						height: vw(40);
 						background: #F6F6F6;
-						.input{
+					
+						.input {
 							flex: 1;
 							margin-right: vw(10);
 						}
-						.btn{
+						
+						.name{
+							flex:1;
+							padding: 0 vw(12);
+							box-sizing: border-box;
+							@include flex-x(center);
+							@include ellipsis();
+						}
+					
+						.btn {
 							@include wh(56, 30);
 							border-radius: vw(3);
 							background: #5283FF;

+ 7 - 2
src/packages/baby/add-feed.vue

@@ -9,7 +9,7 @@
 				<view class="right">
 					<picker @change="changeFeedMode" :value="feedModeIndex" :range="feedModeList" range-key="name">
 						<view class="date">
-							{{feedModeList[feedModeIndex].name || '请选择'}}
+							{{feedModeMap[form.feedMode] || '请选择'}}
 							<IconText :code="`\ue88e`" class="icon" size="12" color="#C6C5CB"></IconText>
 						</view>
 					</picker>
@@ -68,7 +68,12 @@
 				name: '混合',
 				value: 3
 			}
-		]
+		];
+		feedModeMap: any = {
+			1: '母乳',
+			2: '配方奶',
+			3: '混合'
+		};
 		form: any = {
 			feedAmount: null,
 			feedTime: '',

+ 255 - 0
src/packages/baby/add-poop.vue

@@ -0,0 +1,255 @@
+<template>
+	<view class="user-setting-box">
+		<Navbar background-color="#fff" color="#333" title="便便记录"></Navbar>
+		<view class="content">
+			<view class="info-box top-border-radius top10">
+				<view class="label">时间</view>
+				<view class="right">
+					<!-- <uni-datetime-picker v-model="form.poopTime" :border="false" type="date" class="date"/> -->
+					<uni-datetime-picker v-model="form.poopTime" :border="false" type="datetime" class="date-box">
+						<view class="date">
+							{{form.poopTime || '请选择时间'}}
+							<IconText :code="`\ue88e`" class="icon" size="12" color="#C6C5CB"></IconText>
+						</view>
+					</uni-datetime-picker>
+				</view>
+			</view>
+			<view class="info-box bottom-border-radius">
+				<view class="label">便便状态</view>
+				<view class="right">
+					<input v-model="form.poopStatus" type="text" class="input" placeholder="此处输入便便状态"/>
+				</view>
+			</view>
+			
+			<view class="bottom-box">
+				<textarea class="textarea" v-model="form.content" placeholder="点击输入详细信息"></textarea>
+				<MulImgUpload @update="getImgs" :imgs="form.pics" :max="1" :width="100 / 3.75" :height="100 / 3.75"
+					addColor="#999999">
+				</MulImgUpload>
+			</view>
+		</view>
+		<view class="fixed-bottom" >
+			<view class="btn" @click="deleteBabyPoopModal" v-if="id">删除</view>
+			<view class="solid-btn" @click="handleConfirm">保存</view>
+		</view>
+		<ShowModal ref="deletePopup" title="提示" @submit="deleteBabyPoop" leftBtnText="取消" content="是否确认删除?" btnText="确认" />
+	</view>
+</template>
+
+<script lang="ts">
+	import {
+		Component,
+		Mixins
+	} from 'vue-property-decorator';
+	import loginMixin from '@/common/mixins/loginMixin.ts';
+	// import {
+	// 	namespace
+	// } from 'vuex-class';
+	// const baseModule = namespace('base');
+	@Component({})
+	export default class UserSetting extends Mixins(loginMixin) {
+		form: any = {
+			poopTime: '',
+			poopStatus: '',
+			content: '',
+			pics: []
+		};
+		bid: any = null;
+		id: any = null;
+		
+		onShow() {
+			
+		}
+		
+		onLoad(){
+			this.bid = +this.$Route.query.bid;
+			if (this.$Route.query.id) {
+				this.id = +this.$Route.query.id;
+				this.getBabyPoopInfo();
+			}
+		}
+		
+		getBabyPoopInfo(){
+			uni.showLoading({
+				title: '加载中',
+			});
+			this.$http.get({
+				url: this.$api.getBabyPoopInfo,
+				data: {
+					id: this.id
+				}
+			}).then((res: any) => {
+				for(let key in this.form){
+					this.form[key] = res[key];
+				}
+				uni.hideLoading();
+			})
+		}
+		
+		getImgs(pics: any) {
+			this.form.pics = pics;
+		}
+
+		getCode() {
+			return new Promise((resolve : any, reject : any) => {
+				uni.login({
+					provider: 'weixin',
+					success: (eve) => {
+						resolve(eve);
+					},
+					fail: (err) => {
+						console.log(err);
+						reject();
+					}
+				});
+			})
+		}
+		
+		deleteBabyPoopModal(){
+			(this.$refs.deletePopup as any).open();
+		}
+		
+		deleteBabyPoop(){
+			uni.showLoading({
+				title: '加载中',
+			});
+			this.$http.delete({
+				url: this.$api.deleteBabyPoop,
+				data: {
+					id: this.id
+				}
+			}).then((res: any) => {
+				this.$Router.back(1);
+				uni.hideLoading();
+			})
+		}
+		
+		handleConfirm(){
+			console.log(this.form);
+			uni.showLoading({
+				title: '加载中',
+			});
+			let url : string = 'addBabyPoop';
+			let method : string = 'post';
+			let data: any = {
+				...this.form,
+				bid: this.bid,
+			};
+			if (this.id) {
+				url = 'updateBabyPoop';
+				method = 'put';
+				data.id = this.id;
+			}
+			this.$http[method]({
+				url: this.$api[url],
+				data: data
+			}).then((res: any) => {
+				this.$Router.back(1);
+				uni.hideLoading();
+			})
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	page{
+		background: #f5f5f5;
+	}
+	.user-setting-box {
+		// background: #F5F5F5;
+		height: 100vh;
+		@include flex-y(flex-start);
+
+		.content {
+			width: 100%;
+			flex: 1;
+			// padding: 0 vw(10);
+			box-sizing: border-box;
+			@include flex-y(flex-start);
+			.info-box{
+				width: vw(355);
+				height: vw(56);
+				background: #fff;
+				@include flex-x();
+				padding-left: vw(20);
+				padding-right: vw(10);
+				box-sizing: border-box;
+				@include word-vw(14, #333);
+				margin-top: vw(1);
+				&.top10{
+					margin-top: vw(10);
+				}
+				&.top-border-radius{
+					border-top-right-radius: vw(10);
+					border-top-left-radius: vw(10);
+				}
+				&.bottom-border-radius{
+					border-bottom-right-radius: vw(10);
+					border-bottom-left-radius: vw(10);
+				}
+				.right{
+					width: vw(210);
+					@include flex-x(flex-end);
+					.input{
+						width: 100%;
+						height: vw(40);
+						border-radius: vw(5);
+						background: #F6F6F6;
+						text-align: center;
+						font-size: vw(14);
+					}
+					/deep/.uni-date{
+						@include flex-x(flex-end);
+					}
+					.date{
+						// width: vw(100);
+						@include flex-x(flex-end);
+						.icon{
+							margin-left: vw(3);
+						}
+					}
+				}
+			}
+			.bottom-box{
+				width: vw(355);
+				background: #fff;
+				border-radius: vw(10);
+				margin-top: vw(10);
+				padding: vw(10);
+				box-sizing: border-box;
+				.textarea{
+					width: 100%;
+					height: vw(120);
+					background: #F6F6F6;
+					padding: vw(8) vw(12);
+					font-size: vw(14);
+					box-sizing: border-box;
+					margin-bottom: vw(16);
+				}
+			}
+		}
+		.fixed-bottom {
+			height: vw(60);
+			width: 100%;
+			// background: #fff;
+			@include flex-x(center);
+			padding: 0 vw(15);
+			box-sizing: border-box;
+			
+			.btn{
+				@include solid-btn(125, 50, #787878);
+				border-radius: vw(25);
+				margin-right: vw(15);
+				background: #fff;
+			}
+		
+			.solid-btn {
+				background: $bk-color;
+				@include solid-btn(345, 50, #333);
+				border-radius: vw(25);
+				@include word-vw(14, #fff);
+				flex: 1;
+			}
+		}
+	}
+</style>

+ 3 - 2
src/packages/baby/baby-feed.vue

@@ -8,9 +8,9 @@
 				<view class="nav-top">
 					<IconText style="padding: 5px;" @click.native="handleBack" color="#666" :code="`\ue8be`"
 						size="16" />
-					<image :src="babyInfo.avatar" class="pic" mode="heightFix"></image>
+					<image :src="babyInfo.babyAvatar" class="pic" mode="aspectFit"></image>
 					<view class="baby-info">
-						{{babyInfo.nickname}}
+						{{babyInfo.babyNickname}}
 						<text>{{babyInfo.age | ageFormat}}</text>
 					</view>
 				</view>
@@ -278,6 +278,7 @@
 				.pic {
 					@include wh(30, 30);
 					border-radius: vw(15);
+					flex-shrink: 0;
 				}
 
 				.baby-info {

+ 446 - 0
src/packages/baby/baby-poop.vue

@@ -0,0 +1,446 @@
+<template>
+	<view class="user-setting-box">
+		<uni-nav-bar :status-bar="false" :border="false" :fixed="true" color="#333" background-color="" height="205px"
+			leftWidth="0" rightWidth="0">
+			<view class="nav-bg">
+				<view class="status-bar"></view>
+				<view class="nav-top">
+					<IconText style="padding: 5px;" @click.native="handleBack" color="#666" :code="`\ue8be`"
+						size="16" />
+					<image :src="babyInfo.babyAvatar" class="pic" mode="heightFix"></image>
+					<view class="baby-info">
+						{{babyInfo.babyNickname}}
+						<text>{{babyInfo.age | ageFormat}}</text>
+					</view>
+				</view>
+				<view class="date-box">
+					<uni-datetime-picker v-model="date" :border="false" type="date" class="date-box"
+						@change="handleChangeDate">
+						<view class="date">
+							{{date}}
+							<IconText :code="`\ue88e`" class="icon" size="12" color="#333"></IconText>
+						</view>
+					</uni-datetime-picker>
+				</view>
+				<view class="week-box">
+					<view class="week-item" v-for="(item, index) in weekDays" :key="index"
+						@click="changeSelectDate(item)">
+						{{weekMap[item.week]}}
+						<view>
+							<view :class="{active: currentDate === item.date}">
+								<text v-if="now === item.date">今</text>
+								<text v-else>{{item.day}}</text>
+							</view>
+						</view>
+					</view>
+				</view>
+			</view>
+		</uni-nav-bar>
+		<view class="content">
+			<view class="list">
+				<view class="item" v-for="(item, index) in record" :key="index" @click="toDetail(item)">
+					<view class="item-top">
+						<view class="user-info">
+							<image :src="item.avatar" class="pic" mode="aspectFill"></image>
+							<view class="right">
+								<view class="nickname">{{item.nickname}}</view>
+								<view class="role" v-if="item.familyRole">{{item.familyRole}}</view>
+							</view>
+						</view>
+						<view class="status">
+							便便状态:{{item.poopStatus}}
+						</view>
+					</view>
+					<view class="text">
+						{{item.content}}
+					</view>
+					<view class="pic-list">
+						<view class="pic-item" v-for="(pic, picIndex) in item.pics" :key="picIndex">
+							<image :src="pic" class="pic" mode="aspectFill"></image>
+						</view>
+					</view>
+					<view class="date">
+						{{item.poopTime}}
+					</view>
+				</view>
+			</view>
+		</view>
+		<view class="add-btn" @click="toAddPoop">增加<br>记录</view>
+		<ShowModal ref="deletePopup" title="提示" @submit="deleteBabyPoop" leftBtnText="取消" content="是否确认删除?"
+			btnText="确认" />
+	</view>
+</template>
+
+<script lang="ts">
+	import {
+		Component,
+		Mixins
+	} from 'vue-property-decorator';
+	import loginMixin from '@/common/mixins/loginMixin.ts';
+	import dayjs from 'dayjs';
+	// import {
+	// 	namespace
+	// } from 'vuex-class';
+	// const baseModule = namespace('base');
+	@Component({
+		filters: {
+			ageFormat(age : any) {
+				let year = Math.floor(age / 365);
+				let month = Math.floor((age % 365) / 30);
+				let day = age % 30;
+				if (age < 30) {
+					return day + '天';
+				} else if (day < 100) {
+					return month + '个月' + (day ? (day + '天') : '')
+				} else if (day < 365) {
+					return month + '个月';
+				} else if (day < 365 * 3) {
+					return year + '年' + (month ? (month + '个月') : '')
+				} else {
+					return year + '年'
+				}
+			},
+			timeFormat(date : any) {
+				return dayjs(date).format("hh:mm")
+			}
+		}
+	})
+	export default class SelectBaby extends Mixins(loginMixin) {
+		// @baseModule.Getter('_userInfo') _userInfo: any;
+		staticUrl : string = this.$oss_url; 	//oss地址
+		date : any = '';
+		weekDays : any = [];
+		now : any = null;
+		weekMap : any = [
+			'日',
+			'一',
+			'二',
+			'三',
+			'四',
+			'五',
+			'六'
+		];
+		record : any = [];
+		bid : any = null;
+		currentDate : any = '';
+		babyInfo : any = {};
+		feedModeMap : any = {
+			1: '母乳',
+			2: '配方奶',
+			3: '混合'
+		};
+		id : any = null;
+
+		onShow() {
+			this.bid = +this.$Route.query.bid;
+			this.date = dayjs().format('YYYY-MM-DD');
+			this.now = dayjs().format('YYYY-MM-DD');
+			this.currentDate = this.now;
+			this.getWeekData(dayjs());
+			this.getBabyInfo();
+			this.getBabyPoopList();
+		}
+
+		getWeekData(date : any) {
+			this.weekDays = [];
+			let startOfWeek = date.startOf('week'); // 默认周日为一周的开始
+			// 获取当前星期的七天信息
+			for (let i = 0; i < 7; i++) {
+				this.weekDays.push({
+					day: startOfWeek.add(i, 'day').format('D'),
+					week: startOfWeek.add(i, 'day').day(),
+					date: startOfWeek.add(i, 'day').format('YYYY-MM-DD')
+				});
+			}
+		}
+
+		changeSelectDate(item : any) {
+			this.currentDate = item.date;
+			this.getBabyPoopList();
+		}
+
+		handleChangeDate(e : any) {
+			this.currentDate = e;
+			this.getWeekData(dayjs(e));
+			this.getBabyPoopList();
+		}
+
+		handleBack() {
+			this.$Router.back(1);
+		}
+
+		getBabyInfo() {
+			this.$http.get({
+				url: this.$api.getBabyInfo,
+				data: {
+					bid: this.bid
+				}
+			}).then((res : any) => {
+				this.babyInfo = res;
+			})
+		}
+
+		getBabyPoopList() {
+			uni.showLoading({
+				title: '加载中',
+			});
+			this.$http.get({
+				url: this.$api.getBabyPoopList,
+				data: {
+					bid: this.bid,
+					start: this.currentDate + ' 00:00:00',
+					end: this.currentDate + ' 23:59:59',
+				}
+			}).then((res : any) => {
+				this.record = res.list;
+				uni.hideLoading();
+			})
+		}
+
+		deleteBabyPoopModal(id : any) {
+			this.id = id;
+			(this.$refs.deletePopup as any).open();
+		}
+
+		deleteBabyPoop() {
+			uni.showLoading({
+				title: '加载中',
+			});
+			this.$http.delete({
+				url: this.$api.deleteBabyPoop,
+				data: {
+					id: this.id
+				}
+			}).then((res : any) => {
+				this.getBabyPoopList();
+				uni.hideLoading();
+			})
+		}
+
+		toDetail(item : any) {
+			this.$Router.push({
+				path: '/packages/baby/add-poop',
+				query: {
+					bid: this.bid,
+					id: item.id
+				}
+			})
+		}
+
+		toAddPoop() {
+			this.$Router.push({
+				path: '/packages/baby/add-poop',
+				query: {
+					bid: this.bid
+				}
+			})
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	/deep/.uni-navbar__header {
+		padding: 0 !important;
+
+		.uni-navbar__header-container {
+			padding: 0 !important;
+		}
+	}
+
+	/deep/.uni-popup {
+		z-index: 1000;
+		/* 确保这个值高于 uni-nav-bar 的 z-index */
+		position: relative;
+	}
+
+	page {
+		background: #f5f5f5;
+	}
+
+	.user-setting-box {
+		width: 100%;
+		// background: #F5F5F5;
+		height: 100vh;
+		@include flex-y(flex-start);
+
+		.nav-bg {
+			width: 100%;
+			background: linear-gradient(184.24deg, rgba(232, 237, 255, 1) 0%, rgba(255, 230, 255, 1) 51.31%, rgba(247, 242, 255, 1) 78.42%, rgba(255, 255, 255, 1) 100%);
+
+			&.dy {
+				background: #fff;
+			}
+
+			.status-bar {
+				// height: var(--status-bar-height);
+				height: 44px;
+			}
+
+			.nav-top {
+				@include flex-x(flex-start);
+				padding-left: vw(8);
+
+				.pic {
+					@include wh(30, 30);
+					border-radius: vw(15);
+				}
+
+				.baby-info {
+					@include flex-y(space-between, flex-start);
+					@include word-vw(12, #333);
+					margin-left: vw(3);
+
+					text {
+						@include word-vw(12, #666);
+						margin-top: vw(1);
+					}
+				}
+			}
+
+			.date-box {
+				margin-top: vw(20);
+				padding: 0 vw(18);
+
+				.date {
+					@include flex-x(flex-start);
+					font-weight: bold;
+					@include word-vw(14, #333);
+				}
+			}
+
+			.week-box {
+				@include flex-x();
+				margin-top: vw(15);
+				padding: 0 vw(10);
+				box-sizing: border-box;
+
+				.week-item {
+					@include flex-y();
+					flex: 1;
+					@include word-vw(12, #888);
+
+					view {
+						@include wh(24, 24);
+						margin-top: vw(8);
+						@include flex-x(center);
+						@include word-vw(12, #333);
+
+						.active {
+							border-radius: vw(12);
+							background: linear-gradient(90deg, rgba(82, 105, 255, 1) 0%, rgba(125, 125, 255, 1) 100%);
+							@include word-vw(12, #fff);
+						}
+					}
+				}
+			}
+		}
+
+		.content {
+			width: 100%;
+			// padding: 0 vw(10);
+			box-sizing: border-box;
+			@include flex-y(flex-start);
+
+			.list {
+				width: 100%;
+				padding: 0 vw(15);
+				box-sizing: border-box;
+
+				.item {
+					border-radius: vw(10);
+					background: #fff;
+					@include flex-y();
+					padding: vw(16) vw(12);
+					margin-top: vw(10);
+					
+					.item-top{
+						width: 100%;
+						@include flex-x(flex-start);
+						.status{
+							@include word-vw(14, #6B95FF);
+							white-space: nowrap;
+						}
+					}
+
+					.user-info {
+						width: 100%;
+						@include flex-x(flex-start);
+
+						.pic {
+							@include wh(40, 40);
+							border-radius: vw(20);
+							margin-right: vw(3);
+						}
+
+						.right {
+							.nickname {
+								@include word-vw(14, #333);
+							}
+
+							.role {
+								height: vw(20);
+								padding: 0 vw(8);
+								border-radius: vw(10);
+								background: #FFF5EB;
+								@include flex-x(center);
+								@include word-vw(12, #FF8D1A);
+								margin-top: vw(3);
+							}
+						}
+					}
+
+					.text {
+						width: 100%;
+						@include word-vw(12, #333);
+						margin-top: vw(6);
+						@include flex-x(flex-start);
+					}
+
+					.pic-list {
+						width: 100%;
+						@include flex-x(flex-start);
+						flex-wrap: wrap;
+
+						.pic-item {
+							width: 1 / 3 * 100%;
+							margin-top: vw(10);
+							@include flex-x(flex-start);
+
+							.pic {
+								@include wh(100, 100);
+								border-radius: vw(2);
+								display: block;
+							}
+
+							&:nth-of-type(3n) {
+								@include flex-x(flex-end);
+							}
+
+							&:nth-of-type(3n + 2) {
+								@include flex-x(center);
+							}
+						}
+					}
+
+					.date {
+						width: 100%;
+						margin-top: vw(10);
+						@include word-vw(12, #999);
+					}
+				}
+			}
+		}
+
+		.add-btn {
+			@include wh(44, 44);
+			border-radius: vw(22);
+			position: fixed;
+			bottom: vw(20);
+			right: vw(12);
+			background: #fff;
+			box-shadow: 0px 1.38px 5.5px rgba(0, 0, 0, 0.11);
+			@include word-vw(12, #6B95FF);
+			@include flex-y(center);
+		}
+	}
+</style>

+ 4 - 2
src/packages/baby/baby-remark.vue

@@ -8,9 +8,9 @@
 				<view class="nav-top">
 					<IconText style="padding: 5px;" @click.native="handleBack" color="#666" :code="`\ue8be`"
 						size="16" />
-					<image :src="babyInfo.avatar" class="pic" mode="aspectFill"></image>
+					<image :src="babyInfo.babyAvatar" class="pic" mode="aspectFill"></image>
 					<view class="baby-info">
-						{{babyInfo.nickname}}
+						{{babyInfo.babyNickname}}
 						<text>{{babyInfo.age | ageFormat}}</text>
 					</view>
 				</view>
@@ -273,8 +273,10 @@
 						}
 					}
 					.text{
+						width: 100%;
 						@include word-vw(12, #333);
 						margin-top: vw(6);
+						@include flex-x(flex-start);
 					}
 					.pic-list{
 						width: 100%;

+ 2 - 2
src/packages/baby/baby-weight.vue

@@ -8,9 +8,9 @@
 				<view class="nav-top">
 					<IconText style="padding: 5px;" @click.native="handleBack" color="#666" :code="`\ue8be`"
 						size="16" />
-					<image :src="babyInfo.avatar" class="pic" mode="aspectFill"></image>
+					<image :src="babyInfo.babyAvatar" class="pic" mode="aspectFill"></image>
 					<view class="baby-info">
-						{{babyInfo.nickname}}
+						{{babyInfo.babyNickname}}
 						<text>{{babyInfo.age | ageFormat}}</text>
 					</view>
 				</view>

+ 2 - 2
src/packages/baby/select-baby.vue

@@ -6,9 +6,9 @@
 		<view class="content">
 			<view class="baby-item" v-for="item in babyList" :key="item.bid">
 				<view class="left">
-					<image class="avatar" :src="item.avatar" mode="aspectFill"></image>
+					<image class="avatar" :src="item.babyAvatar" mode="aspectFill"></image>
 					<view class="info">
-						<view class="name">{{item.nickname}}</view>
+						<view class="name">{{item.babyNickname}}</view>
 						<view class="age">
 							{{item.age | ageFormat}}
 							<view class="line" v-if="item.family"></view>

+ 169 - 6
src/packages/family/family-setting.vue

@@ -38,9 +38,14 @@
 							</view>
 						</view>
 					</view>
-					<IconText :code="`\ue88e`" color="#ccc" size="16" class="icon"></IconText>
+					<view v-if="item.invite === -1" class="right">
+						邀请中
+					</view>
+					<view v-else>
+						<IconText :code="`\ue88e`" color="#ccc" size="16" class="icon"></IconText>
+					</view>
 				</view>
-				<view class="add-item" @click="toAddMember">
+				<view class="add-item" @click="handlePhoneModal">
 					+ 添加成员
 				</view>
 			</view>
@@ -48,6 +53,29 @@
 		<!-- <view class="fixed-bottom" >
 			<view class="solid-btn" @click="handleConfirm">保存</view>
 		</view> -->
+		<uni-popup ref="phonePopup" type="center">
+			<view class="show-modal">
+				<Icon class="close" @click="handleClose" :code="`\ue76b`" color="#999" size="10"></Icon>
+				<view class="title">邀请成员</view>
+				<view class="popup-content">
+					<view class="input-box">
+						手机号:
+						<input type="number" class="input" v-model="phone" placeholder="输入手机号"/>
+					</view>
+					<view class="tip">
+						请输入家庭成员手机号,生成家庭邀请码
+					</view>
+				</view>
+				<view class="btn-box btn-styl">
+					<view class="btn cancel-btn" @click="handleClose">
+						取消
+					</view>
+					<view class="btn" @click="inviteFamily">
+						确认
+					</view>
+				</view>
+			</view>
+		</uni-popup>
 	</view>
 </template>
 
@@ -74,6 +102,7 @@
 		fid: any = null;
 		info: any = {};
 		list: any = [];
+		phone: any = '';
 		
 		onShow() {
 			if (this.$Route.query.fid) {
@@ -85,7 +114,6 @@
 		
 		onLoad(){
 			// this.fid = +this.$Route.query.fid;
-			
 		}
 		
 		getFamilyInfo(){
@@ -146,14 +174,52 @@
 			})
 		}
 		
-		toUserInfo(){
+		toUserInfo(item: any){
+			if(item.invite === -1){
+				uni.showToast({
+					title: '该用户暂未加入家庭',
+					icon: 'none'
+				})
+				return;
+			}
 			this.$Router.push({
 				path: '/packages/family/member-info',
 				query: {
 					fid: this.info.fid,
+					uid: item.uid
 				}
 			})
 		}
+		
+		handlePhoneModal(){
+			this.phone = '';
+			(this.$refs.phonePopup as any).open();
+		}
+		
+		handleClose(){
+			(this.$refs.phonePopup as any).close();
+		}
+		
+		inviteFamily(){
+			uni.showLoading({
+				title: '加载中',
+			});
+			this.$http.post({
+				url: this.$api.inviteFamily,
+				data: {
+					fid: this.fid,
+					phone: this.phone
+				}
+			}).then((res: any) => {
+				this.$Router.push({
+					path: '/packages/family/family-share',
+					query: {
+						fid: this.info.fid,
+					}
+				})
+				uni.hideLoading();
+			})
+		}
 	}
 </script>
 
@@ -252,6 +318,7 @@
 				@include flex-y();
 				border-radius: vw(10);
 				overflow: hidden;
+				padding-bottom: vw(30);
 				.item{
 					width: 100%;
 					height: vw(80);
@@ -266,11 +333,11 @@
 						.avatar{
 							@include wh(56, 56);
 							border-radius: vw(28);
-							background: red;
+							// background: red;
 						}
 						.info{
 							margin-left: vw(10);
-							@include flex-y();
+							@include flex-y(center, flex-start);
 							.nickname{
 								@include word-vw(14, #333);
 							}
@@ -282,6 +349,9 @@
 							}
 						}
 					}
+					.right{
+						@include word-vw(14, #FF8D1A);
+					}
 					// &:nth-of-type(1){
 					// 	margin-top: 0;
 					// }
@@ -318,5 +388,98 @@
 				flex: 1;
 			}
 		}
+		.show-modal {
+			background: #fff;
+			width: vw(300);
+			@include flex-y();
+			border-radius: vw(10);
+			position: relative;
+		
+			.close {
+				position: absolute;
+				right: vw(5);
+				top: vw(5);
+				padding: vw(5);
+			}
+		
+			.title {
+				@include word-vw(16, #333);
+				margin-top: vw(25);
+			}
+		
+			.popup-content {
+				@include word-vw(14, #666);
+				margin-top: vw(12);
+				text-align: center;
+				
+				.input-box{
+					@include word-vw(14, #333);
+					@include flex-x();
+					.input{
+						@include word-vw(14, #333);
+						background: #F6F6F6;
+						@include wh(180, 40);
+						border-radius: vw(6);
+						margin-left: vw(3);
+					}
+				}
+				.tip{
+					@include flex-x(center);
+					@include word-vw(12, #999);
+					margin-top: vw(5);
+				}
+			}
+		
+			.btn {
+				width: vw(65);
+				height: vw(35);
+				line-height: vw(35);
+				text-align: center;
+				background: $btn-color;
+				@include word-vw(14, #fff);
+				border-radius: vw(5);
+				margin-top: vw(16);
+				margin-bottom: vw(20);
+			}
+		
+			.cancel-btn {
+				margin-right: 32px;
+				background: #EBEBEB;
+				color: #333;
+			}
+		
+			.btn-cancel {
+				width: vw(150);
+				height: vw(35);
+				line-height: vw(35);
+				text-align: center;
+				background: #1A1A1A;
+				@include word-vw(14, #fff);
+				border-radius: vw(4);
+				margin-top: vw(28);
+				margin-bottom: vw(15);
+			}
+		
+			.btn-box {
+				border-top: vw(1) solid #F5F5F5;
+				margin-top: vw(10);
+				width: vw(200);
+				@include flex-x(center);
+			}
+		
+			.btn-styl {
+				@include flex-x(center);
+		
+				.btn {
+					width: vw(90);
+				}
+		
+				.btn-cancel {
+					width: vw(90);
+					margin-right: vw(20);
+				}
+			}
+		
+		}
 	}
 </style>

+ 250 - 0
src/packages/family/family-share.vue

@@ -0,0 +1,250 @@
+<template>
+	<view class="share-box">
+		<Navbar title="分享页"></NavBar>
+		<view class="content">
+			<canvas canvas-id="shareCanvas" class="canvas" style="width: 275px;height:550px;"></canvas>
+			<!-- #ifdef APP -->
+			<view class="qr-box">
+				<uqrcode ref="qRCode" canvas-id="qRCode" :value="qr" @complete="complete"
+					:options="{ foregroundImageSrc: static ? static + 'logo.png' : '' }" v-show="true"></uqrcode>
+			</view>
+			<!-- #endif -->
+			<view class="bottom">
+				<view class="btn" @click="saveImageToPhotos('shareCanvas')">保存图片至相册</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script lang="ts">
+	// @ts-nocheck
+	import {
+		Component,
+		Prop,
+		Vue,
+		Emit,
+		Mixins
+	} from 'vue-property-decorator';
+	import {
+		types
+	} from '@/common/store';
+	import {
+		OSS_STATIC
+	} from '@/common/constants';
+	import canvasMixin from '@/common/mixins/canvasMixin.ts';
+	import {
+		namespace
+	} from 'vuex-class';
+	const baseModule = namespace('base');
+	@Component({})
+	export default class ShopShare extends Mixins(canvasMixin) {
+		@baseModule.Getter('_userInfo') _userInfo : any;
+
+		avatar : string = "";
+		pic : string = "";
+		qr : string = "";
+		shareInfo : string = "";
+		static : string = OSS_STATIC;
+		qrPic : any = '';
+
+		async onLoad() {
+			let res = await this.getShareInfo();
+			let shareUrl = await this.downLoadImg(res.pic);
+			this.pic = shareUrl;
+			// #ifdef MP-WEIXIN
+			this.handleShare();
+			// #endif
+			// #ifdef APP
+			this.getCode();
+			// #endif
+		}
+
+		getShareInfo() {
+			return this.$http
+				.get({
+					url: this.$api.getShareInfo,
+					data: {
+						way: 1
+					}
+				})
+				.then(async (res : any) => {
+					this.shareInfo = res;
+					return res;
+				}, (err : any) => {
+					console.log(err);
+				});
+		}
+
+		complete(res : any) {
+			console.log(res.success, 'complete');
+			if (res.success) {
+				this.toImage();
+			}
+		}
+
+		toImage() {
+			// @ts-ignore
+			this.$refs.qRCode.toTempFilePath({
+				success: (res : any) => {
+					console.log(res, 'toImage');
+					this.qrPic = res.tempFilePath;
+					this.$nextTick(() => {
+						console.log('start')
+						this.drawPoster();
+					})
+					// ctx.drawImage(that.qrPic, 158, 392, 105, 105);
+					// ctx.draw(true, () => {
+					// 	console.log('draw,true');
+					// 	uni.hideLoading();
+					// });
+				},
+				fail: (err : any) => {
+					console.log(err);
+				}
+			});
+		}
+
+		getCode() {
+			this.$http
+				.get({
+					url: this.$api.getShareCode,
+					data: {
+						rid: this._userInfo.uid + ''
+					}
+				})
+				.then(async (res : any) => {
+					console.log(res, 'share')
+					this.qr = res.qr;
+					let avatarUrl = await this.downLoadImg(this._userInfo.avatar);
+					// let shareUrl = await this.downLoadImg(this.static + 'share.png');
+					this.avatar = avatarUrl;
+					// this.pic = shareUrl;
+					console.log('start')
+					this.$nextTick(() => {
+						console.log('start')
+						this.qrPic && this.drawPoster();
+					})
+				}, (err : any) => {
+					console.log(err);
+				});
+		}
+		drawPoster() : void {
+			// 绘制海报
+			// 注意:page页面canvas-id获取ctx,组件需传this
+			const that = this;
+			const ctx = uni.createCanvasContext('shareCanvas', this);
+			// 绘制白色底
+			this.roundRect(ctx, 0, 255, 275, 295, '#ffffff', 0, 20, 20, 0);
+			// 绘制店铺图片
+			// this.drawImgInfo(
+			// 	ctx,
+			// 	0,
+			// 	0,
+			// 	275,
+			// 	275,
+			// 	that.pic
+			// );
+			this.roundImg(ctx, 0, 0, 275, 275, 20, '', that.pic);
+			// 绘制头像
+			this.drawCircular(ctx, 40, 40, 15, 160, that.avatar);
+			// this.roundRect(ctx, 0, 397, 44, 44, '#000');
+			// this.roundRect(ctx, 0, 454, 50, 16, '#f00');
+			// this.roundRect(ctx, 0, 483, 50, 16, '#f00');
+			ctx.textAlign = "left";
+			this.textSet(ctx, '育百通', '12px', 60, 175, '#fff', 'bold ');
+			this.textSet(ctx, (that._userInfo.nickname + '推荐' || '用户推荐'), '12px', 60, 191, '#fff', 'bold ');
+			// this.textSet(ctx, that.shareInfo.slogan + '', '10px', 78, 494, '#8F8F8F', '');
+			// this.textSet(ctx, '推荐', '10px', 180, 450, '#000', 'bold ');
+			// // 小程序码
+			// #ifdef MP-WEIXIN
+			ctx.drawImage(that.qr, 64.5, 300, 150, 150);
+			// #endif
+			// #ifndef MP-WEIXIN
+			that.qrPic && ctx.drawImage(that.qrPic, 158, 392, 105, 105);
+			// #endif
+			// ctx.textAlign = "center";
+			this.textCenterSet(ctx, that.shareInfo.slogan + '', '14px', 137.5, 480, '#999', 275, '');
+			this.textCenterSet(ctx, '扫一扫二维码加入我们', '18px', 137.5, 510, '#4A4A4A', 275, 'bold ');
+			ctx.draw(true, () => {
+				console.log('draw,true');
+				uni.hideLoading();
+			});
+		}
+
+		async handleShare() {
+			// 获取小程序码
+			let data = {
+				page: 'pages/front/front',
+				scene: `family,${this.$Route.query.fid}`
+			};
+			uni.showLoading({
+				title: '加载中',
+			});
+			this.getQr(data, async (url : any) => {
+				this.qr = url;
+				let avatarUrl = await this.downLoadImg(this._userInfo.avatar);
+				// let shareUrl = await this.downLoadImg(this.static + 'share.png');
+				this.avatar = avatarUrl;
+				// this.pic = avatarUrl;
+				uni.showLoading({
+					title: '加载中'
+				});
+				this.drawPoster();
+			});
+		}
+		downLoadImg(url : any) {
+			return new Promise((resolve : any, reject : any) => {
+				uni.downloadFile({
+					url,
+					complete: (result : any) => {
+						if (result.statusCode === 200) {
+							resolve(result.tempFilePath);
+						} else {
+							reject(false);
+						}
+					}
+				});
+			})
+		}
+	}
+</script>
+
+<style lang='scss' scoped>
+	.share-box {
+		background: #F5F5F5;
+		height: 100vh;
+		box-sizing: border-box;
+		@include flex-y();
+
+		.content {
+			width: 100%;
+			@include flex-y(center);
+			padding-top: vw(20);
+			padding-bottom: vw(80);
+			
+			.qr-box{
+				position: absolute;
+				left: 1000px;
+			}
+
+			.bottom {
+				width: 100%;
+				position: fixed;
+				bottom: 0;
+				height: vw(70);
+				background: #fff;
+				@include flex-x(center);
+
+				.btn {
+					@include flex-x(center);
+					@include solid-btn(335, 50, #fff, 25);
+				}
+			}
+
+			.img {
+				width: 300px;
+				margin-top: vw(16);
+			}
+		}
+	}
+</style>

+ 34 - 2
src/packages/family/family-transfer.vue

@@ -4,7 +4,7 @@
 		<Navbar background-color="#fff" color="#333" title="管理员转让"></Navbar>
 		<!-- #endif -->
 		<view class="content">
-			<view class="baby-item" v-for="item in list" :key="item.bid">
+			<view class="baby-item" v-for="item in list" :key="item.uid" @click="uid = item.uid">
 				<view class="left">
 					<image class="avatar" :src="item.avatar" mode="aspectFill"></image>
 					<view class="info">
@@ -20,6 +20,9 @@
 				</view>
 			</view>
 		</view>
+		<view class="fixed-bottom" >
+			<view class="solid-btn" @click="transferFamily">确认转让</view>
+		</view>
 	</view>
 </template>
 
@@ -76,7 +79,10 @@
 					}
 				})
 				.then((res : any) => {
-					this.$Route.back(1);
+					this.$Router.back(1);
+					uni.showToast({
+						title: '操作成功'
+					})
 				}, (err : any) => {
 					console.log(err);
 				});
@@ -91,6 +97,7 @@
 	.user-setting-box {
 		// background: #F5F5F5;
 		height: 100vh;
+		@include flex-y(flex-start);
 		// @include flex-y(flex-start);
 
 		.content {
@@ -98,6 +105,8 @@
 			padding: 0 vw(15);
 			box-sizing: border-box;
 			@include flex-y(flex-start);
+			overflow-y: auto;
+			flex: 1;
 			.baby-item{
 				width: 100%;
 				@include flex-x();
@@ -139,5 +148,28 @@
 				}
 			}
 		}
+		.fixed-bottom {
+			height: vw(60);
+			width: 100%;
+			// background: #fff;
+			@include flex-x(center);
+			padding: 0 vw(15);
+			box-sizing: border-box;
+			
+			.btn{
+				@include solid-btn(125, 50, #787878);
+				border-radius: vw(25);
+				margin-right: vw(15);
+				background: #fff;
+			}
+		
+			.solid-btn {
+				background: $bk-color;
+				@include solid-btn(345, 50, #333);
+				border-radius: vw(25);
+				@include word-vw(14, #fff);
+				flex: 1;
+			}
+		}
 	}
 </style>

+ 68 - 55
src/packages/family/member-info.vue

@@ -4,36 +4,49 @@
 		<Navbar background-color="#fff" color="#333" title="成员信息"></Navbar>
 		<!-- #endif -->
 		<view class="content">
-			<view class="info-box top-border-radius top10">
+			<view class="info-box top-border-radius top10 avatar-box">
+				<view class="label">头像</view>
+				<view class="right">
+					<image :src="info.avatar" class="pic" mode="aspectFit">
+				</view>
+			</view>
+			<view class="info-box">
 				<view class="label">昵称</view>
 				<view class="right">
-					<!-- {{}} -->
+					{{info.nickname}}
 				</view>
 			</view>
 			<view class="info-box">
-				<view class="label">体重/kg</view>
+				<view class="label">id</view>
 				<view class="right">
-					<input v-model="form.weight" type="text" class="input" placeholder="此处输入体重"/>
+					{{info.uid}}
 				</view>
 			</view>
 			<view class="info-box bottom-border-radius">
-				<view class="label">时间</view>
+				<view class="label">角色</view>
+				<view class="right">
+					{{info.familyRole}}
+				</view>
+			</view>
+			<view class="info-box top-border-radius top10">
+				<view class="label">联系电话</view>
 				<view class="right">
-					<!-- <uni-datetime-picker v-model="form.feedTime" :border="false" type="date" class="date"/> -->
-					<uni-datetime-picker v-model="form.feedTime" :border="false" type="datetime" class="date-box">
-						<view class="date">
-							{{form.feedTime || '请选择时间'}}
-							<IconText :code="`\ue88e`" class="icon" size="12" color="#C6C5CB"></IconText>
-						</view>
-					</uni-datetime-picker>
+					{{info.phone}}
+				</view>
+			</view>
+			<view class="info-box bottom-border-radius">
+				<view class="label">家庭权限</view>
+				<view class="right">
+					{{info.isManger ? '管理员' : '普通家庭成员'}}
 				</view>
 			</view>
 		</view>
 		<view class="fixed-bottom" >
-			<view class="btn" @click="deleteBabyWeightModal" v-if="id">删除</view>
-			<view class="solid-btn" @click="handleConfirm">保存</view>
+			<view class="solid-btn" @click="handleDeleteModal" v-if="!info.isSelf && info.mangerUid === _userInfo.uid">删除成员</view>
+			<view class="solid-btn" @click="handleQuitModal" v-if="info.isSelf && info.mangerUid !== _userInfo.uid">退出家庭</view>
 		</view>
-		<ShowModal ref="deletePopup" title="提示" @submit="deleteBabyWeight" leftBtnText="取消" content="是否确认删除?" btnText="确认" />
+		<ShowModal ref="deletePopup" title="提示" @submit="deleteFamilyMember" leftBtnText="取消" content="是否确认删除该成员?" btnText="确认" />
+		<ShowModal ref="quitPopup" title="提示" @submit="quitFamily" leftBtnText="取消" content="是否确认退出该家庭?" btnText="确认" />
 	</view>
 </template>
 
@@ -50,88 +63,81 @@
 	@Component({})
 	export default class UserSetting extends Mixins(loginMixin) {
 		// @baseModule.Getter('_userInfo') _userInfo: any;
-		form: any = {
-			weight: null,
-			height: null,
-			feedTime: '',
-		};
-		bid: any = null;
-		id: any = null;
+		info: any = {};
+		uid: any = null;
+		fid: any = null;
 		
 		onShow() {
 			
 		}
 		
 		onLoad(){
-			this.bid = +this.$Route.query.bid;
-			if (this.$Route.query.id) {
-				this.id = +this.$Route.query.id;
-				this.getBabyWeightInfo();
-			}
+			this.fid = +this.$Route.query.fid;
+			this.uid = +this.$Route.query.uid;
+			this.getFamilyMemberInfo();
 		}
 		
-		getBabyWeightInfo(){
+		getFamilyMemberInfo(){
 			uni.showLoading({
 				title: '加载中',
 			});
 			this.$http.get({
-				url: this.$api.getBabyGrowthInfo,
+				url: this.$api.getFamilyMemberInfo,
 				data: {
-					id: this.id
+					fid: this.fid,
+					uid: this.uid
 				}
 			}).then((res: any) => {
-				for(let key in this.form){
-					this.form[key] = res[key];
-				}
+				this.info = res;
 				uni.hideLoading();
 			})
 		}
 		
-		deleteBabyWeightModal(){
+		handleDeleteModal(){
 			(this.$refs.deletePopup as any).open();
 		}
 		
-		deleteBabyWeight(){
+		deleteFamilyMember(){
 			uni.showLoading({
 				title: '加载中',
 			});
 			this.$http.delete({
-				url: this.$api.deleteBabyGrowth,
+				url: this.$api.deleteFamilyMember,
 				data: {
-					id: this.id
+					uid: this.info.uid,
+					fid: this.fid
 				}
 			}).then((res: any) => {
 				this.$Router.back(1);
+				uni.showToast({
+					title: '操作成功'
+				})
 				uni.hideLoading();
 			})
 		}
 		
-		handleConfirm(){
-			console.log(this.form);
+		handleQuitModal(){
+			(this.$refs.quitPopup as any).open();
+		}
+		
+		quitFamily(){
 			uni.showLoading({
 				title: '加载中',
 			});
-			let url : string = 'addBabyGrowth';
-			let method : string = 'post';
-			let data: any = {
-				...this.form,
-				bid: this.bid,
-				weight: +this.form.weight,
-				height: +this.form.height,
-			};
-			if (this.id) {
-				url = 'updateBabyGrowth';
-				method = 'put';
-				data.id = this.id;
-			}
-			this.$http[method]({
-				url: this.$api[url],
-				data: data
+			this.$http.put({
+				url: this.$api.quitFamily,
+				data: {
+					fid: this.fid
+				}
 			}).then((res: any) => {
 				this.$Router.back(1);
+				uni.showToast({
+					title: '操作成功'
+				})
 				uni.hideLoading();
 			})
 		}
+		
 	}
 </script>
 
@@ -194,6 +200,13 @@
 					}
 				}
 			}
+			.avatar-box{
+				height: vw(72);
+				.pic{
+					@include wh(48, 48);
+					border-radius: vw(24);
+				}
+			}
 		}
 		.fixed-bottom {
 			height: vw(60);

+ 296 - 0
src/packages/goods/brand-article-search.vue

@@ -0,0 +1,296 @@
+<template>
+	<view class="good-detail-box">
+		<uni-nav-bar :status-bar="false" :shadow="false" :border="false" :fixed="true" color="#333" background-color=""
+			height="145px" leftWidth="0" rightWidth="0">
+			<view class="nav-bg">
+				<view class="status-bar"></view>
+				<view class="nav-title">
+					<view class="left">
+						<IconText style="padding: 5px;" @click.native="handleBack" color="#666" :code="`\ue8be`"
+							size="16" />
+						<IconText style="padding: 5px;" @click.native="handleFront" color="#333" :code="`\ue8a0`"
+							size="18" />
+					</view>
+					<view class="title">{{brandName}}</view>
+					<view class="right"></view>
+				</view>
+				<view class="filter-box">
+					<view class="category-filter filter">
+						<view>
+							<view class="filter-item" :class="{active: categoryId === item.id}"
+								v-for="(item, index) in articleGategoryList" :key="index" @click="changeCategory(item)">
+								{{item.classifyName}}
+							</view>
+						</view>
+					</view>
+				</view>
+			</view>
+		</uni-nav-bar>
+		<view class="goods-list">
+			<!-- <GoodItem v-for="(good, index) in articleList" :good="good" :key="index" class="good-item"></GoodItem> -->
+			<ArticleItem v-for="(article, index) in articleList" :article="article" :key="index"
+				style="width: 100%" :marginBottom="10" :borderRadiusShow="true"></ArticleItem>
+		</view>
+	</view>
+</template>
+
+<script lang="ts">
+	import {
+		Component,
+		Mixins
+	} from 'vue-property-decorator';
+	import {
+		namespace
+	} from 'vuex-class';
+	import {
+		APP_BASE_URL
+	} from '@/common/constants';
+	import {
+		types
+	} from '@/common/store/index';
+	const baseModule = namespace('base');
+	const canvasModule = namespace('canvas');
+	import loginMixin from '@/common/mixins/loginMixin.ts';
+	@Component({})
+	export default class GoodDetail extends Mixins(loginMixin) {
+		staticUrl : string = this.$oss_url; 	//oss地址
+		shareInfo : any = {};
+		articleList : any = [];
+		brandName : any = '';
+		articleGategoryList : any = [];
+		ageFilter : any = [];
+		product : any = '全部产品';
+		age : any = 0;
+		categoryId : any = 0;
+		current : any = 1;
+		size : any = 20;
+		brandId : any = null;
+		finish : any = false;
+		loading : any = false;
+
+		// async onPullDownRefresh() {
+		// 	// console.log('下拉');
+		// 	// this.getShareInfo();
+		// 	uni.stopPullDownRefresh();
+		// }
+
+		onReachBottom() {
+			if (this.finish || this.loading) return;
+			this.current++;
+			this.getArticleList();
+		}
+
+		onLoad(opt : any) {
+			let query = this.$Route.query;
+			this.brandName = query.brandName;
+			this.brandId = query.brandId;
+			this.getArticleGategoryList();
+			this.getArticleList();
+		}
+
+		onShow() {
+
+		}
+
+		onShareAppMessage() {
+			return {
+				title: '育百通',
+				path: '/pages/front/front?s=1&uid=' + this._userInfo.uid,
+				imageUrl: this.shareInfo.pic
+			};
+		}
+
+		getArticleGategoryList() {
+			this.$http.get({
+				url: this.$api.getArticleGategoryList,
+				data: {
+					classifyType: 3
+				}
+			}).then((res : any) => {
+				this.articleGategoryList = [
+					{
+						classifyName: '全部分类',
+						id: 0,
+					},
+					...res.list
+				];
+			})
+		}
+
+		changeCategory(item : any) {
+			this.categoryId = item.id;
+			this.current = 1;
+			this.finish = false;
+			this.articleList = [];
+			this.getArticleList();
+		}
+
+		changeAge(item : any) {
+			this.age = item.id;
+			this.current = 1;
+			this.finish = false;
+			this.articleList = [];
+			this.getArticleList();
+		}
+
+		handleBack() {
+			this.$Router.back(1);
+		}
+
+		handleFront() {
+			this.$Router.pushTab({
+				path: '/pages/front/front'
+			})
+		}
+
+		getArticleList() {
+			this.loading = true;
+			return this.$http
+				.get({
+					url: this.$api.getArticleList,
+					data: {
+						page: this.current,
+						size: this.size,
+						brandId: this.brandId,
+						classifyId: this.categoryId,
+						articleType: 3
+					}
+				})
+				.then((res : any) => {
+					this.articleList = [...this.articleList, ...res.list];
+					if (res.list.length < this.size) {
+						this.finish = true;
+					};
+					this.loading = false;
+				}, (err : any) => {
+					this.loading = false;
+					console.log(err);
+				});
+		}
+
+		toPage(path : any) {
+			if (!path) {
+				uni.showToast({
+					title: '敬请期待',
+					icon: 'none'
+				});
+				return;
+			}
+			this.$Router.push({
+				path: path
+			})
+		}
+
+		getCode() {
+			return new Promise((resolve : any, reject : any) => {
+				uni.login({
+					provider: 'weixin',
+					success: (eve) => {
+						resolve(eve);
+					},
+					fail: (err) => {
+						console.log(err);
+						reject();
+					}
+				});
+			})
+		}
+	}
+</script>
+<style lang="scss" scoped>
+	page {
+		height: 100vh;
+		background: #F6F8FB;
+	}
+
+	/deep/.uni-navbar__header {
+		padding: 0 !important;
+
+		.uni-navbar__header-container {
+			padding: 0 !important;
+		}
+	}
+
+	.good-detail-box {}
+
+	.nav-bg {
+		width: 100%;
+		background: #fff;
+		// background: linear-gradient(180deg, #FFD9F9 0%, #F1E6FF 67.19%, #F1E9FE 82.84%, #FBF6FC 100%);
+
+		.status-bar {
+			// height: var(--status-bar-height);
+			height: 44px;
+		}
+
+		.nav-title {
+			width: 100%;
+			box-sizing: border-box;
+			height: 44px;
+			padding: 0 vw(3);
+			@include flex-x();
+			@include word-vw(16, #000);
+
+			.left,
+			.right {
+				width: vw(60);
+				@include flex-x(flex-satrt);
+			}
+
+			.title {
+				flex: 1;
+				@include flex-x(center);
+			}
+		}
+
+		.filter-box {
+			height: 88px;
+			width: 100%;
+			background: #fff;
+			padding: vw(12);
+			box-sizing: border-box;
+			@include flex-y(space-between, flex-start);
+
+			.filter {
+				width: 100%;
+				@include flex-x(flex-start);
+				overflow-x: auto;
+
+				&::-webkit-scrollbar {
+					width: 0px;
+					height: 0px;
+				}
+
+				>view {
+					@include flex-x(flex-start);
+				}
+
+				.filter-item {
+					height: vw(28);
+					padding: 0 vw(12);
+					background: #F2F2F2;
+					white-space: nowrap;
+					margin: 0 vw(3);
+					@include flex-x(center);
+					border-radius: vw(4);
+					@include word-vw(12, #333);
+
+					&.active {
+						background: #7698FF;
+						@include word-vw(12, #fff);
+					}
+				}
+			}
+		}
+	}
+
+	.goods-list {
+		padding: 0 vw(10);
+		margin-top: vw(10);
+		padding-bottom: vw(50);
+
+		.good-item {
+			width: 100%;
+		}
+	}
+</style>

+ 113 - 18
src/packages/goods/brand-detail.vue

@@ -1,5 +1,33 @@
 <template>
 	<view class="good-detail-box">
+		<!-- #ifdef MP-TOUTIAO -->
+		<uni-nav-bar :status-bar="false" :shadow="false" :border="false" :fixed="true" color="#333" background-color=""
+			height="42px" leftWidth="0" rightWidth="0">
+			<view class="nav-bg">
+				<scroll-view
+				  class="tab-scroll"
+				  scroll-x="true"
+				  :scroll-into-view="'tab' + navActive"
+				  :scroll-with-animation="true"
+				  
+				  :enable-flex="true"
+				>
+				  <view class="nav-list">
+				  	<view class="nav-item" 
+						:class="{active: navActive === index}" 
+						v-for="(item, index) in navList" 
+						:key="index" 
+						:id="'nav' + index"
+						@click="changeNavActive(index, item)">
+				  		{{item.name}}
+				  		<view class="bar"></view>
+				  	</view>
+				  </view>
+				</scroll-view>
+			</view>
+		</uni-nav-bar>
+		<!-- #endif -->
+		<!-- #ifndef MP-TOUTIAO -->
 		<uni-nav-bar :status-bar="false" :shadow="false" :border="false" :fixed="true" color="#333" background-color=""
 			height="125px" leftWidth="0" rightWidth="0">
 			<view class="nav-bg">
@@ -36,6 +64,7 @@
 				</scroll-view>
 			</view>
 		</uni-nav-bar>
+		<!-- #endif -->
 		<view class="bg"></view>
 		<scroll-view
 		  :scroll-y="true"
@@ -50,12 +79,12 @@
 			  	:id="'content' + 0">
 			  	<view class="info">
 			  		<view class="top">
-						<image :src="staticUrl ? staticUrl + 'logo.png' : ''" class="pic" mode="heightFix"></image>
-						<view class="name">金领冠</view>
+						<image :src="info.logo" class="pic" mode="heightFix"></image>
+						<view class="name">{{info.brandName}}</view>
 					</view>
 					<view class="bottom">
 						<view class="label">主营品类:</view>
-						牛奶粉、A2有机、儿童奶粉、羊奶粉、孕妇奶粉、山羊奶粉
+						<text v-if="info.categoryName">{{info.categoryName.join('、')}}</text>
 					</view>
 			  	</view>
 			  </view>
@@ -63,7 +92,7 @@
 				:id="'content' + 1">
 				<view class="title" :style="{backgroundImage: `url(${staticUrl ? staticUrl + 'title-bg.png' : ''})`}">品牌简介</view>
 				<view class="text-box">
-					品牌简介品牌简介品牌简介品牌简介品牌简介品牌简介品牌简介品牌简介品牌简介品牌简介品牌简介品牌简介品牌简介品牌简介品牌简介品牌简介品牌简介品牌简介品牌简介品牌简介品牌简介品牌简介品牌简介品牌简介
+					{{info.brandIntroduce}}
 				</view>
 			</view>
 			<view class="box product-box"
@@ -73,14 +102,14 @@
 					<view class="more-btn" @click="toSearch">查看更多 &gt;</view>
 				</view>
 				<view class="list" style="margin: 0">
-					<GoodItem v-for="(good, index) in articleList" :good="good" :key="index" style="width: 100%"></GoodItem>
+					<GoodItem v-for="(good, index) in goodsList" :good="good" :key="index" style="width: 100%"></GoodItem>
 				</view>
 			</view>
 			<view class="box product-box"
 				:id="'content' + 3">
 				<view class="title" :style="{backgroundImage: `url(${staticUrl ? staticUrl + 'title-bg.png' : ''})`}">
 					品牌资讯
-					<view class="more-btn">查看更多 &gt;</view>
+					<view class="more-btn" @click="toArticleSearch">查看更多 &gt;</view>
 				</view>
 				<view class="list" style="margin: 0">
 					<ArticleItem v-for="(article, index) in articleList" :article="article" :key="index" style="width: 100%"></ArticleItem>
@@ -88,7 +117,7 @@
 			</view>
 		  </view>
 		</scroll-view>
-		<GoodsShare ref="share" :goodsInfo="goodsInfo" :key="shareKey"></GoodsShare>
+		<GoodsShare ref="share" :goodsInfo="info" :key="shareKey"></GoodsShare>
 		<uni-popup ref="infoPopup" type="bottom" border-radius="10px 10px 0 0" :safeArea="false">
 			<view class="info-popup">
 				<view class="title">更多信息</view>
@@ -135,7 +164,9 @@
 		@canvasModule.Mutation(types.SET_CANVASDATA) setCanvasData : any;
 		staticUrl : string = this.$oss_url; 	//oss地址
 		navActive: any = 0;
-		goodsInfo : any = {}; //商品信息
+		info : any = {
+			categoryName: []
+		}; //商品信息
 		shareKey : any = +new Date();
 		navList: any = [
 			{
@@ -157,6 +188,8 @@
 		articleList: any = [];
 		contentList: any = [];
 		windowWidth: any = 0;
+		id: any = null;
+		goodsList: any = [];
 		// itemWidths: any = []
 		
 		async onPullDownRefresh() {
@@ -166,13 +199,18 @@
 		}
 		
 		async onLoad(opt : any) {
+			this.id = +this.$Route.query.id;
 			// this.getShareInfo();
 			this.$nextTick(()=> {
 				this.getItemsWidth();
 				const res = uni.getSystemInfoSync(); // 同步获取系统信息
 				this.windowWidth = res.windowWidth; // 获取屏幕宽度
 			});
-			await this.getArticleList();
+			await Promise.all([
+				this.getBrandInfo(),
+				this.getGoodsList(),
+				this.getArticleList()
+			]);
 			this.$nextTick(()=> {
 				const query = uni.createSelectorQuery().in(this);
 				query.selectAll('.box').boundingClientRect((res: any) => {
@@ -228,6 +266,12 @@
 		}
 		
 		handleBack(){
+			if(getCurrentPages().length <= 1) {
+				this.$Router.pushTab({
+					path: '/pages/front/front'
+				});
+				return;
+			}
 			this.$Router.back(1);
 		}
 		
@@ -261,13 +305,47 @@
 			}
 		}
 		
-		getArticleList() {
+		getBrandInfo(){
+			return this.$http
+				.get({
+					url: this.$api.getBrandInfo,
+					data: {
+						id: this.id
+					}
+				})
+				.then((res : any) => {
+					this.info = res;
+				}, (err : any) => {
+					console.log(err);
+				});
+		}
+		
+		getGoodsList() {
 			return this.$http
 				.get({
 					url: this.$api.getGoodsList,
 					data: {
+						size: 5,
 						page: 1,
-						size: 5
+						status: '3',
+						brand: this.id
+					}
+				})
+				.then((res : any) => {
+					this.goodsList = res.list;
+				}, (err : any) => {
+					console.log(err);
+				});
+		}
+		
+		getArticleList() {
+			return this.$http
+				.get({
+					url: this.$api.getArticleList,
+					data: {
+						page: 1,
+						size: 5,
+						brandId: this.id
 					}
 				})
 				.then((res : any) => {
@@ -281,10 +359,10 @@
 			if (this.isAuthorization()) return;
 			let data = {
 				page: 'packages/goods/good-detail',
-				scene: `isShare,${this._userInfo.uid},${this.goodsInfo.id},${this.goodsInfo.gid}`
+				scene: `isShare,${this._userInfo.uid},${this.info.id},${this.info.gid}`
 			};
-			!this.goodsInfo.goodImg && await this.downLoadGoodPic();
-			if (!this.goodsInfo.goodImg) {
+			!this.info.goodImg && await this.downLoadGoodPic();
+			if (!this.info.goodImg) {
 				uni.showToast({
 					title: "网络连接失败,请重试",
 					icon: 'none'
@@ -313,7 +391,7 @@
 								type: 'avatar',
 								data: result.tempFilePath
 							});
-							// console.log(this.goodsInfo, 'goodsInfo');
+							// console.log(this.info, 'info');
 							// console.log(this.spuInfo, 'spuInfo');
 							(this.$refs.share as any).openPop();
 						}
@@ -324,7 +402,7 @@
 		
 		downLoadGoodPic() {
 			return new Promise((resolve : any, reject : any) => {
-				let info = { ...this.goodsInfo };
+				let info = { ...this.info };
 				let count = 0;
 				uni.downloadFile({
 					url: info.slideshow.length ? info.slideshow[0].url : info.masterPic,
@@ -374,7 +452,21 @@
 		
 		toSearch(){
 			this.$Router.push({
-				path: '/packages/goods/brand-goods-search'
+				path: '/packages/goods/brand-goods-search',
+				query: {
+					brandId: this.id,
+					brandName: this.info.brandName
+				}
+			})
+		}
+		
+		toArticleSearch(){
+			this.$Router.push({
+				path: '/packages/goods/brand-article-search',
+				query: {
+					brandId: this.id,
+					brandName: this.info.brandName
+				}
 			})
 		}
 
@@ -419,6 +511,9 @@
 
 	.nav-bg {
 		width: 100%;
+		/* #ifdef MP-TOUTIAO */
+		padding: vw(3) 0;
+		/* #endif */
 		// background: linear-gradient(180deg, #FFD9F9 0%, #F1E6FF 67.19%, #F1E9FE 82.84%, #FBF6FC 100%);
 
 		.status-bar {
@@ -526,7 +621,7 @@
 				background-size: auto vw(6);
 				background-position: left bottom;
 				background-repeat: no-repeat;
-				margin-left: vw(5);
+				margin-left: vw(-5);
 				padding-left: vw(5);
 				.more-btn {
 					@include word-vw(12, #999);

+ 88 - 23
src/packages/goods/brand-goods-search.vue

@@ -17,15 +17,15 @@
 				<view class="filter-box">
 					<view class="product-filter filter">
 						<view>
-							<view class="filter-item" :class="{active: product === item}" v-for="(item, index) in productFilter" :key="index">
-								{{item}}
+							<view class="filter-item" :class="{active: series === item.id}" v-for="(item, index) in seriesFilter" :key="index" @click="changeSeries(item)">
+								{{item.seriesName}}
 							</view>
 						</view>
 					</view>
 					<view class="age-filter filter">
 						<view>
-							<view class="filter-item" :class="{active: age === item}" v-for="(item, index) in ageFilter" :key="index">
-								{{item}}
+							<view class="filter-item" :class="{active: age === item.id}" v-for="(item, index) in ageFilter" :key="index" @click="changeAge(item)">
+								{{item.labelName}}
 							</view>
 						</view>
 					</view>
@@ -60,23 +60,17 @@
 		staticUrl : string = this.$oss_url; 	//oss地址
 		shareInfo: any = {};
 		goodsList: any = [];
-		brandName: any = '金领冠';
-		productFilter: any = [
-			'全部产品',
-			'金领冠珍护',
-			'金领冠珍护铂萃',
-			'育护',
-			'金领冠珍护铂萃'
-		];
-		ageFilter: any = [
-			'年龄不限',
-			'0-6个月',
-			'6-12个月',
-			'12-36个月',
-			'儿童'
-		];
+		brandName: any = '';
+		seriesFilter: any = [];
+		ageFilter: any = [];
 		product: any = '全部产品';
-		age: any = '年龄不限';
+		age: any = 0;
+		series: any = 0;
+		current: any = 1;
+		size: any = 20;
+		brandId: any = null;
+		finish: any = false;
+		loading: any = false;
 		
 		// async onPullDownRefresh() {
 		// 	// console.log('下拉');
@@ -84,7 +78,19 @@
 		// 	uni.stopPullDownRefresh();
 		// }
 		
+		onReachBottom() {
+			if (this.finish || this.loading) return;
+			this.current++;
+			this.getGoodsList();
+		}
+		
 		onLoad(opt : any) {
+			let query = this.$Route.query;
+			this.brandName = query.brandName;
+			this.brandId = query.brandId;
+			+query.seriesId && (this.series = +query.seriesId);
+			this.getSeriesList();
+			this.getLabelItemByAge();
 			this.getGoodsList();
 		}
 
@@ -100,6 +106,57 @@
 			};
 		}
 		
+		getLabelItemByAge() {
+			this.$http.get({
+				url: this.$api.getLabelItem,
+				data: {
+					dataName: "age"
+				}
+			}).then((res : any) => {
+				this.ageFilter = [
+					{
+						labelName: '年龄不限',
+						fid: 0,
+						id: 0,
+					},
+					...res.list
+				];
+			})
+		}
+		
+		getSeriesList() {
+			this.$http.get({
+				url: this.$api.getSeriesList,
+				data: {
+					brandId: this.brandId
+				}
+			}).then((res : any) => {
+				this.seriesFilter = [
+					{
+						seriesName: '全部产品',
+						id: 0,
+					},
+					...res
+				];
+			})
+		}
+		
+		changeSeries(item: any){
+			this.series = item.id;
+			this.current = 1;
+			this.finish = false;
+			this.goodsList = [];
+			this.getGoodsList();
+		}
+		
+		changeAge(item: any){
+			this.age =item.id;
+			this.current = 1;
+			this.finish = false;
+			this.goodsList = [];
+			this.getGoodsList();
+		}
+		
 		handleBack(){
 			this.$Router.back(1);
 		}
@@ -111,17 +168,25 @@
 		}
 		
 		getGoodsList() {
+			this.loading = true;
 			return this.$http
 				.get({
 					url: this.$api.getGoodsList,
 					data: {
-						page: 1,
-						size: 5
+						page: this.current,
+						size: this.size,
+						age: this.age,
+						series: this.series
 					}
 				})
 				.then((res : any) => {
-					this.goodsList = res.list;
+					this.goodsList = [...this.goodsList, ...res.list];
+					if (res.list.length < this.size) {
+						this.finish = true;
+					};
+					this.loading = false;
 				}, (err : any) => {
+					this.loading = false;
 					console.log(err);
 				});
 		}

+ 147 - 0
src/packages/goods/brand-list.vue

@@ -0,0 +1,147 @@
+<template>
+	<view class="user-setting-box">
+		<!-- #ifndef MP-TOUTIAO -->
+		<Navbar background-color="#fff" color="#333" title="热门品牌"></Navbar>
+		<!-- #endif -->
+		<view class="content">
+			<view class="brand-item" v-for="item in brandList" :key="item.id" @click="toBrandDetail(item)">
+				<view class="left">
+					<image class="logo" :src="item.logo" mode="aspectFill"></image>
+					<view class="info">
+						<view class="name">{{item.brandName}}</view>
+						<view class="category-box">
+							主营品类:
+							<view class="list" v-if="item.categoryName && item.categoryName.length">
+								<!-- <view class="item" v-for="(category, categoryIndex) in item.categoryName" :key="categoryIndex">
+									{{category}}
+									<text v-if="categoryIndex !== item.categoryName.length - 1">、</text>
+								</view> -->
+								{{item.categoryName.join('、')}}
+							</view>
+						</view>
+					</view>
+				</view>
+				<view class="right">
+					更多信息
+					<IconText :code="`\ue8a1`" color="#5383FC" size="10" class="icon"></IconText>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script lang="ts">
+	import {
+		Component,
+		Mixins
+	} from 'vue-property-decorator';
+	import loginMixin from '@/common/mixins/loginMixin.ts';
+	// import {
+	// 	namespace
+	// } from 'vuex-class';
+	// const baseModule = namespace('base');
+	@Component({})
+	export default class SelectBaby extends Mixins(loginMixin) {
+		// @baseModule.Getter('_userInfo') _userInfo: any;
+		brandList: any = [{}];
+		
+		onShow() {
+			this.getHotBrandList();
+		}
+		
+		getHotBrandList() {
+			// uni.showLoading({
+			// 	title: '加载中',
+			// });
+			return this.$http
+				.get({
+					url: this.$api.getHotBrandList
+				})
+				.then((res : any) => {
+					this.brandList = res.list;
+					// uni.hideLoading();
+				}, (err : any) => {
+					console.log(err);
+					// uni.hideLoading();
+				});
+		}
+		
+		toBrandDetail(item: any){
+			this.$Router.push({
+				path: "/packages/goods/brand-detail",
+				query: {
+					id: item.id
+				}
+			})
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	page{
+		background: #f5f5f5;
+	}
+	.user-setting-box {
+		// background: #F5F5F5;
+		height: 100vh;
+		// @include flex-y(flex-start);
+
+		.content {
+			width: 100%;
+			padding: 0 vw(15);
+			box-sizing: border-box;
+			@include flex-y(flex-start);
+			.brand-item{
+				width: 100%;
+				@include flex-x();
+				padding: vw(12) vw(18);
+				box-sizing: border-box;
+				background: #fff;
+				border-radius: vw(10);
+				margin-top: vw(10);
+				.left{
+					@include flex-x();
+					flex: 1;
+					.logo{
+						@include wh(64, 64);
+						margin-right: vw(20);
+						font-weight: 550;
+					}
+					.info{
+						flex: 1;
+						.name{
+							@include word-vw(20, #333);
+						}
+						.category-box{
+							margin-top: vw(3);
+							@include flex-y(flex-start, flex-start);
+							@include word-vw(12, #999);
+							@include ellipsis();
+							.list{
+								@include flex-x(flex-start);
+								margin-top: vw(3);
+								flex-wrap: wrap;
+								white-space: pre-wrap;
+								margin-right: vw(3);
+								.item{
+									@include flex-x(flex-start);
+								}
+							}
+						}
+					}
+				}
+				.right{
+					// align-self: flex-start;
+					@include word-vw(12, $btn-color);
+					@include flex-x();
+					white-space: nowrap;
+					flex-wrap: nowrap;
+					flex-shrink: 0;
+					.icon{
+						margin-left: vw(3);
+					}
+				}
+			}
+		}
+	}
+</style>

+ 17 - 4
src/packages/goods/collect-list.vue

@@ -39,14 +39,14 @@
 			<swiper-item>
 				<scroll-view class="swiper-item" :scroll-y="true" @scrolltolower="loadGoods">
 					<view class="goods-list">
-						<GoodItem v-for="(good, index) in goodsList" :good="good" :key="index" style="width: 100%"></GoodItem>
+						<GoodItem v-for="(good, index) in goodsList" :good="good" :key="index" style="width: 100%" :collectShow="true"></GoodItem>
 					</view>
 				</scroll-view>
 			</swiper-item>
 			<swiper-item>
 				<scroll-view class="swiper-item" :scroll-y="true" @scrolltolower="loadArticle">
 					<view class="article-list">
-						<ArticleItem v-for="(article, index) in articleList" :article="article" :key="index" style="width: 100%"></ArticleItem>
+						<ArticleItem v-for="(article, index) in articleList" :article="article" :key="index" :marginBottom="10" class="article-item" style="width: 100%" :collectShow="true"></ArticleItem>
 					</view>
 				</scroll-view>
 			</swiper-item>
@@ -115,7 +115,7 @@
 		}
 		
 		initList(){
-			this.articleCurrent = 1;
+			this.goodsCurrent = 1;
 			this.goodsFinish = false;
 			this.goodsList = [];
 			this.getGoodsList();
@@ -184,6 +184,7 @@
 						size: this.size,
 						page: this.goodsCurrent,
 						status: '3',
+						queryCollected: 1,
 					}
 				})
 				.then((res : any) => {
@@ -204,9 +205,10 @@
 			this.articleLoading = true;
 			this.$http
 				.get({
-					url: this.$api.getGoodsList,
+					url: this.$api.getArticleList,
 					data: {
 						page: this.articleCurrent,
+						way: 1,
 						size: this.size
 					}
 				})
@@ -255,6 +257,10 @@
 				path: path
 			})
 		}
+		
+		handleBack() {
+			this.$Router.back(1);
+		}
 	}
 </script>
 <style lang="scss" scoped>
@@ -334,6 +340,13 @@
 			box-sizing: border-box;
 			overflow-y: auto;
 		}
+		
+		.goods-list, .article-list{
+			padding: 0 vw(10);
+			// .article-item{
+			// 	margin-bottom: vw(10);
+			// }
+		}
 	}
 
 	

+ 328 - 136
src/packages/goods/filter.vue

@@ -1,7 +1,7 @@
 <template>
 	<view class="user-setting-box">
 		<uni-nav-bar :status-bar="false" :shadow="false" :border="false" :fixed="true" color="#333" background-color=""
-			height="130px" leftWidth="0" rightWidth="0">
+			height="165px" leftWidth="0" rightWidth="0">
 			<view class="nav-bg">
 				<view class="status-bar"></view>
 				<view class="nav-title">
@@ -15,71 +15,66 @@
 					<view class="right"></view>
 				</view>
 				<view class="filter-box">
-					<view class="filter-item" :class="{active: activePopup === 'brandPopup' || brandCheched}" @click="handleFilterModal('brandPopup')">
+					<view class="filter-item"
+						:class="{active: activePopup === 'brandPopup', checked: brandCheched.length}"
+						@click="handleFilterModal('brandPopup')">
 						品牌
 						<view class="arrow"></view>
 					</view>
-					<view class="filter-item" :class="{active: activePopup === 'pricePopup' || priceActive}" @click="handleFilterModal('pricePopup')">
+					<view class="filter-item"
+						:class="{active: activePopup === 'pricePopup', checked: filter.minPrice || filter.maxPrice}"
+						@click="handleFilterModal('pricePopup')">
 						价格
 						<view class="arrow"></view>
 					</view>
-					<view class="filter-item" :class="{active: activePopup === 'agePopup' || ageActive}" @click="handleFilterModal('agePopup')">
+					<view class="filter-item" :class="{active: activePopup === 'agePopup', checked: filter.age}"
+						@click="handleFilterModal('agePopup')">
 						年龄
 						<view class="arrow"></view>
 					</view>
-					<view class="filter-item" :class="{active: activePopup === 'labelPopup'}" @click="handleFilterModal('labelPopup')">
+					<view class="filter-item" :class="{active: activePopup === 'labelPopup', checked: labelActive}"
+						@click="handleFilterModal('labelPopup')">
 						更多
 						<view class="arrow"></view>
 					</view>
-					<view class="filter-item" :class="{active: activePopup === 'sortPopup' || sortActive}" @click="handleFilterModal('sortPopup')">
+					<view class="filter-item" :class="{active: activePopup === 'sortPopup', checked: filter.rank}"
+						@click="handleFilterModal('sortPopup')">
 						排序
 						<view class="arrow"></view>
 					</view>
 				</view>
-
+				<view class="goods-num-box">
+					共 {{total}} 款奶粉
+					<view class="reset" @click="handleReset">
+						重置
+					</view>
+				</view>
 			</view>
 		</uni-nav-bar>
 		<view class="content">
-			<view class="goods-num-box">
-				共 19 款奶粉
-				<view class="reset">
-					重置
-				</view>
-			</view>
 			<view class="list">
-				<GoodItem v-for="(good, index) in goodsList" :good="good" :key="index" style="width: 100%"></GoodItem>
+				<GoodItem v-for="(good, index) in goodsList" :good="good" :key="index" :type="type" style="width: 100%"></GoodItem>
 			</view>
 		</view>
 		<uni-popup ref="brandPopup" type="top" :safeArea="false">
 			<view class="brand-popup popup-box">
 				<view class="letter-list">
-					<view class="letter-item" v-for="(letterItem, letterIndex) in letterList" :key="letterIndex">
+					<view class="letter-item" v-for="(letterItem, letterIndex) in letterList" :key="letterIndex"
+						v-if="brandListFormat[letterItem] && brandListFormat[letterItem].length">
 						<view class="title">{{letterItem}}</view>
 						<view class="brand-list">
-							<view class="brand-item">
-								<checkbox value="cb" style="transform:scale(0.6)" activeBackgroundColor="#618EFF"
-									iconColor="#fff" />加多宝
-							</view>
-							<view class="brand-item">
-								<checkbox value="cb" style="transform:scale(0.6)" activeBackgroundColor="#618EFF"
-									iconColor="#fff" />加多宝
-							</view>
-							<view class="brand-item">
-								<checkbox value="cb" style="transform:scale(0.6)" activeBackgroundColor="#618EFF"
-									iconColor="#fff" />加多宝
-							</view>
-							<view class="brand-item">
-								<checkbox value="cb" style="transform:scale(0.6)" activeBackgroundColor="#618EFF"
-									iconColor="#fff" />加多宝
-							</view>
-							<view class="brand-item">
-								<checkbox value="cb" style="transform:scale(0.6)" activeBackgroundColor="#618EFF"
-									iconColor="#fff" />加多宝
+							<view class="brand-item" v-for="(item, index) in brandListFormat[letterItem]" :key="item.id"
+								@click="()=> handleChangeBrandItem(index, letterItem)">
+								<IconText class="icon" :code="`\ue8a6`" v-if="item.checked" size="14" color="#618EFF">
+								</IconText>
+								<IconText class="icon" :code="`\ue85a`" size="14" color="#DEDEDE" v-else></IconText>
+								<image :src="item.logo" class="pic" mode="aspectFit">
+									{{item.brandName}}
 							</view>
 						</view>
 					</view>
 				</view>
-				<view class="btn">
+				<view class="btn" @click="handleBrandPopup">
 					确认
 				</view>
 			</view>
@@ -103,11 +98,11 @@
 							<view class="line"></view>
 						</view>
 					</view>
-					
+
 					<view v-if="activePopup === 'pricePopup'">
-						<kw-slider v-model="priceRange" :showLabel="false" :min="0" :max="500" :step="10" :showTip="false"
-							backgroundColor="#C2C2C2" :customBlock="true" activeColor="#7698FF" barHeight="6"
-							style="width: 100%;" @change="changePrice">
+						<kw-slider v-model="priceRange" :showLabel="false" :min="0" :max="500" :step="10"
+							:showTip="false" backgroundColor="#C2C2C2" :customBlock="true" activeColor="#7698FF"
+							barHeight="6" style="width: 100%;" @change="changePrice">
 							<view slot="minBlock">
 								<view class="slider-block"></view>
 							</view>
@@ -117,7 +112,7 @@
 						</kw-slider>
 					</view>
 				</view>
-				<view class="btn">
+				<view class="btn" @click="handlePricePopup">
 					确认
 				</view>
 			</view>
@@ -125,43 +120,32 @@
 		<uni-popup ref="agePopup" type="top" :safeArea="false" @maskClick="maskClick">
 			<view class="age-popup popup-box">
 				<view class="age-list">
-					<view class="age-item" :class="{active: ageActive === index}" v-for="(item, index) in ageList"
-						:key="index" @click="changeAge(index)">
-						{{item.name}}
+					<view class="age-item" :class="{active: ageActive === item.id}" v-for="(item, index) in ageList"
+						:key="index" @click="changeAge(item)">
+						{{item.labelName}}
 					</view>
 				</view>
-				<view class="btn">
+				<view class="btn" @click="handleAgePopup">
 					确认
 				</view>
 			</view>
 		</uni-popup>
 		<uni-popup ref="labelPopup" type="top" :safeArea="false" @maskClick="maskClick">
 			<view class="label-popup popup-box">
-				<view class="label-box">
-					<view class="label-title">
-						<view class="line"></view>
-						标签
-					</view>
-					<view class="label-list">
-						<view class="label-item" :class="{active: ageActive === index}" v-for="(item, index) in ageList"
-							:key="index" @click="changeAge(index)">
-							{{item.name}}
-						</view>
-					</view>
-				</view>
-				<view class="label-box">
+				<view class="label-box" v-for="(item, index) in filterLabel" :key="index">
 					<view class="label-title">
 						<view class="line"></view>
-						标签
+						{{item.name}}
 					</view>
 					<view class="label-list">
-						<view class="label-item" :class="{active: ageActive === index}" v-for="(item, index) in ageList"
-							:key="index" @click="changeAge(index)">
-							{{item.name}}
+						<view class="label-item" :class="{active: item.active === label.id}"
+							v-for="(label, labelIndex) in item.labelDetail" :key="label.id"
+							@click="changeLabel(item, label)">
+							{{label.labelName}}
 						</view>
 					</view>
 				</view>
-				<view class="btn">
+				<view class="btn" @click="handleLabelPopup">
 					确认
 				</view>
 			</view>
@@ -169,11 +153,12 @@
 		<uni-popup ref="sortPopup" type="top" :safeArea="false" @maskClick="maskClick">
 			<view class="sort-popup popup-box">
 				<view class="sort-list">
-					<view class="sort-item" v-for="(item, index) in sortList" :key="index" @click="changeSort(index)">
-						<view class="name" :class="{active: sortActive === index}">
+					<view class="sort-item" v-for="(item, index) in sortList" :key="index" @click="changeSort(item)">
+						<view class="name" :class="{active: sortActive === item.value}">
 							{{item.name}}
 						</view>
-						<IconText class="icon" :code="`\ue842`" v-if="sortActive === index" size="14" color="#6B95FF">
+						<IconText class="icon" :code="`\ue842`" v-if="sortActive === item.value" size="14"
+							color="#6B95FF">
 						</IconText>
 						<IconText class="icon" :code="`\ue84e`" size="14" color="#999" v-else></IconText>
 					</view>
@@ -197,6 +182,8 @@
 	export default class SelectBaby extends Mixins(loginMixin) {
 		// @baseModule.Getter('_userInfo') _userInfo: any;
 		goodsList : any = [];
+		size : any = 20;
+		current : any = 1;
 		letterList : any = [
 			"A",
 			"B",
@@ -257,45 +244,10 @@
 				value: [450, 500]
 			},
 		];
-		brandCheched : any = {
-
-		};
+		brandCheched : any = [];
 		priceActive : any = 0;
 		priceRange : any = [0, 500];
-		ageList : any = [
-			{
-				name: '年龄不限',
-				value: 1
-			},
-			{
-				name: '0-6个月',
-				value: 1
-			},
-			{
-				name: '6-12个月',
-				value: 1
-			},
-			{
-				name: '12-36个月',
-				value: 1
-			},
-			{
-				name: '儿童',
-				value: 1
-			},
-			{
-				name: '孕产妇',
-				value: 1
-			},
-			{
-				name: '青少年',
-				value: 1
-			},
-			{
-				name: '成人',
-				value: 1
-			}
-		];
+		ageList : any = [];
 		ageActive : any = 0;
 		sortList : any = [
 			{
@@ -304,19 +256,48 @@
 			},
 			{
 				name: '价格由低到高',
-				value: 1
+				value: 2
 			},
 			{
 				name: '价格由高到低',
-				value: 2
+				value: 3
 			}
 		];
 		sortActive : any = 0;
-		activePopup: any = '';
+		activePopup : any = '';
+		filterLabel : any = [];
+		brandListFormat : any = [];
+		total : any = 0;
+		filter : any = {
+			minPrice: 0,
+			maxPrice: 0,
+			age: 0,
+			rank: 0
+		};
+		labelActive : any = false;
+		type: any = '';
+		// brandSelected : any = [];
 
-		onShow() {
-			// this.getGoodsList();
+		async onLoad() {
 			// this.handleFilterModal('sortPopup');
+			this.type = this.$Route.query.type;
+			this.getBrandList();
+			this.getLabelItemByAge();
+			await this.getFilterLabel();
+			let query = this.$Route.query;
+			if (query.name === 'age') {
+				this.ageActive = +query.id;
+				this.filter.age = +query.id;
+			} else if (query.id) {
+				this.labelActive = true;
+				this.filterLabel.forEach((item : any) => {
+					if (item.id === +query.fid) {
+						item.active = +query.id;
+					}
+				});
+				this.filter[query.name] = +query.id;
+			};
+			this.getGoodsList();
 		}
 
 		handleBack() {
@@ -329,13 +310,95 @@
 			})
 		}
 
+		getBrandList() {
+			// uni.showLoading({
+			// 	title: '加载中',
+			// });
+			return this.$http
+				.get({
+					url: this.$api.getBrandList
+				})
+				.then((res : any) => {
+					let brandListFormat : any = {};
+					res.list.forEach((item : any) => {
+						if (brandListFormat[item.abc]) {
+							brandListFormat[item.abc].push({ ...item, checked: false });
+						} else {
+							brandListFormat[item.abc] = [{ ...item, checked: false }];
+						}
+					});
+					this.brandListFormat = brandListFormat;
+				}, (err : any) => {
+					console.log(err);
+					// uni.hideLoading();
+				});
+		}
+
 		getGoodsList() {
 			this.$http
 				.get({
-					url: this.$api.getGoodsList
+					url: this.$api.getGoodsList,
+					data: {
+						status: '3',
+						size: this.size,
+						page: this.current,
+						brand: this.brandCheched.join(','),
+						...this.filter
+					}
 				})
 				.then((res : any) => {
 					this.goodsList = res.list;
+					this.total = res.total;
+				}, (err : any) => {
+					console.log(err);
+				});
+		}
+
+		getLabelItemByAge() {
+			// uni.showLoading({
+			// 	title: '加载中',
+			// });
+			this.$http.get({
+				url: this.$api.getLabelItem,
+				data: {
+					dataName: "age"
+				}
+			}).then((res : any) => {
+				// let obj : any = {};
+				// res.list.forEach((item : any) => {
+				// 	obj[item.value] = item.labelName
+				// })
+				this.ageList = [
+					{
+						labelName: '年龄不限',
+						fid: 0,
+						id: 0,
+					},
+					...res.list
+				];
+				// uni.hideLoading();
+			})
+		}
+
+		getFilterLabel() {
+			return this.$http
+				.get({
+					url: this.$api.getFilterLabel
+				})
+				.then((res : any) => {
+					this.filterLabel = res.list.map((item : any) => {
+						return {
+							...item,
+							active: 0,
+							labelDetail: [
+								{
+									labelName: '不限',
+									id: 0
+								},
+								...item.labelDetail
+							]
+						}
+					});
 				}, (err : any) => {
 					console.log(err);
 				});
@@ -363,17 +426,115 @@
 			this.priceActive = null;
 		}
 
-		changeAge(index : any) {
-			this.ageActive = index;
+		changeAge(item : any) {
+			this.ageActive = item.id;
+		}
+
+		changeLabel(item : any, label : any) {
+			item.active = label.id;
+		}
+
+		changeSort(item : any) {
+			this.sortActive = item.value;
+			this.filter.rank = item.value;
+			(this.$refs.sortPopup as any).close();
+			this.currentPopup = null;
+			this.activePopup = '';
+			this.getGoodsList();
+		}
+
+		maskClick() {
+			this.currentPopup = null;
+			this.activePopup = '';
+		}
+
+		handleChangeBrandItem(index : any, letterItem : any) {
+			this.brandListFormat[letterItem][index].checked = !this.brandListFormat[letterItem][index].checked;
+		}
+
+		handleReset() {
+			//品牌
+			this.brandCheched = [];
+			for (let key in this.brandListFormat) {
+				this.brandListFormat[key].forEach((item : any) => {
+					item.checked = false;
+				})
+			};
+			//价格
+			this.priceRange = [0, 500];
+			this.priceActive = 0;
+			//年龄
+			this.ageActive = 0;
+			//更多
+			this.filterLabel = this.filterLabel.map((item : any) => {
+				return {
+					...item,
+					active: 0
+				}
+			});
+			this.labelActive = false;
+			//排序
+			this.sortActive = 0;
+			this.filter = {
+				minPrice: 0,
+				maxPrice: 0,
+				rank: 0,
+				age: 0,
+			};
+			this.getGoodsList();
+		}
+
+		handleBrandPopup() {
+			let list : any = [];
+			for (let key in this.brandListFormat) {
+				this.brandListFormat[key].forEach((item : any) => {
+					item.checked && (list.push(item.id));
+				})
+			};
+			this.brandCheched = list;
+			(this.$refs.brandPopup as any).close();
+			this.currentPopup = null;
+			this.activePopup = '';
+			this.getGoodsList();
 		}
-		
-		changeSort(index : any) {
-			this.sortActive = index;
+
+		handlePricePopup() {
+			this.filter.minPrice = +this.priceRange[0];
+			this.filter.maxPrice = this.priceRange[1] === 500 ? 0 : +this.priceRange[1];
+			(this.$refs.pricePopup as any).close();
+			this.currentPopup = null;
+			this.activePopup = '';
+			this.getGoodsList();
 		}
-		
-		maskClick(){
+
+		handleAgePopup() {
+			this.filter.age = this.ageActive;
+			(this.$refs.agePopup as any).close();
 			this.currentPopup = null;
 			this.activePopup = '';
+			this.getGoodsList();
+		}
+
+		handleLabelPopup() {
+			let obj : any = {};
+			let flag = false;
+			this.filterLabel.forEach((item : any) => {
+				if (item.active) {
+					flag = true;
+					obj[item.dataName] = item.active;
+				} else {
+					obj[item.dataName] = ''
+				}
+			});
+			this.labelActive = flag;
+			this.filter = {
+				...this.filter,
+				...obj
+			};
+			(this.$refs.labelPopup as any).close();
+			this.currentPopup = null;
+			this.activePopup = '';
+			this.getGoodsList();
 		}
 
 		bindClick() {
@@ -412,6 +573,7 @@
 		width: 100%;
 		background: #fff;
 		@include flex-y(flex-start);
+		box-shadow: 0px 2px 4px  rgba(0, 0, 0, 0.03);
 		// background: linear-gradient(180deg, #FFD9F9 0%, #F1E6FF 67.19%, #F1E9FE 82.84%, #FBF6FC 100%);
 
 		.status-bar {
@@ -460,9 +622,10 @@
 					margin-left: vw(3);
 					margin-top: vw(1.5);
 				}
+
 				&.active {
 					@include word-vw(14, #6B95FF);
-					
+
 					.arrow {
 						width: 0;
 						height: 0;
@@ -475,9 +638,24 @@
 						margin-bottom: vw(1.5);
 					}
 				}
+
+				&.checked {
+					@include word-vw(14, #6B95FF);
+				}
 			}
 		}
 
+		.goods-num-box {
+			width: vw(345);
+			height: 35px;
+			@include flex-x();
+			@include word-vw(14, #666);
+			border-top: vw(0.5) solid #F2F2F2;
+
+			.reset {
+				@include word-vw(14, #6B95FF);
+			}
+		}
 	}
 
 	.user-setting-box {
@@ -487,27 +665,22 @@
 
 		.content {
 			width: 100%;
-			padding: 0 vw(15);
+			padding: 0 vw(10);
 			box-sizing: border-box;
 			@include flex-y(flex-start);
 
-			.goods-num-box {
-				width: vw(345);
-				height: vw(35);
-				@include flex-x();
-				@include word-vw(14, #666);
-				border-top: vw(0.5) solid #F2F2F2;
 
-				.reset {
-					@include word-vw(14, #6B95FF);
-				}
+
+			.list {
+				width: 100%;
+				margin-top: vw(10);
 			}
 		}
 	}
 
 	.popup-box {
 		width: 100%;
-		padding-top: 130px;
+		padding-top: 165px;
 		background: #fff;
 		position: relative;
 		@include flex-y(flex-start);
@@ -523,7 +696,7 @@
 
 	.brand-popup {
 		height: 100%;
-		height: calc(100vh - 130px);
+		height: calc(100vh - 165px);
 
 		.letter-list {
 			width: 100%;
@@ -549,6 +722,15 @@
 						@include word-vw(14, #333);
 						padding: 0 vw(15);
 						@include flex-x(flex-start);
+
+						.icon {
+							margin-right: vw(12);
+						}
+
+						.pic {
+							@include wh(28, 28);
+							margin-right: vw(12);
+						}
 					}
 				}
 			}
@@ -561,6 +743,7 @@
 	}
 
 	.price-popup {
+		@include flex-y(center);
 
 		.price-list {
 			width: 100%;
@@ -575,7 +758,7 @@
 				padding: 0 vw(10);
 				background: #F2F2F2;
 				@include word-vw(12, #333);
-				@include flex-x(center);
+				@include flex-y(center);
 				border-radius: vw(4);
 				margin-right: vw(6);
 				margin-bottom: vw(6);
@@ -596,7 +779,7 @@
 
 		.slider-box {
 			margin: 0 auto;
-			width: vw(330);
+			width: vw(300);
 			position: relative;
 
 			.ruler-box {
@@ -604,6 +787,8 @@
 				position: absolute;
 				top: 0;
 				@include flex-x();
+				padding: 0 30rpx;
+				box-sizing: border-box;
 
 				.item {
 					@include word-vw(10, #666);
@@ -627,13 +812,13 @@
 
 					&:nth-of-type(1) {
 						.line {
-							border-right-width: 0;
+							// border-right-width: 0;
 						}
 					}
 
 					&:nth-last-of-type(1) {
 						.line {
-							border-right-width: 0;
+							// border-right-width: 0;
 						}
 					}
 				}
@@ -653,6 +838,8 @@
 	}
 
 	.age-popup {
+		@include flex-y(center);
+
 		.age-list {
 			width: 100%;
 			box-sizing: border-box;
@@ -667,7 +854,7 @@
 				box-sizing: border-box;
 				background: #F2F2F2;
 				@include word-vw(12, #333);
-				@include flex-x(center);
+				@include flex-y(center);
 				border-radius: vw(4);
 				margin: vw(3);
 
@@ -685,10 +872,14 @@
 
 	.label-popup {
 		.label-box {
+			width: 100%;
 			margin-bottom: vw(16);
+			@include flex-y(flex-start, flex-start);
 
 			.label-title {
+				width: 100%;
 				padding: 0 vw(15);
+				box-sizing: border-box;
 				@include flex-x(flex-start);
 				@include word-vw(14, #333);
 				margin-bottom: vw(8);
@@ -718,7 +909,7 @@
 				box-sizing: border-box;
 				background: #F2F2F2;
 				@include word-vw(12, #333);
-				@include flex-x(center);
+				@include flex-y(center);
 				border-radius: vw(4);
 				margin: vw(3);
 
@@ -745,11 +936,12 @@
 				width: 100%;
 				height: vw(36);
 				@include flex-x();
-				box-shadow:inset 0px -1px 0px  rgba(0, 0, 0, 0.03);
+				box-shadow: inset 0px -1px 0px rgba(0, 0, 0, 0.03);
 
 				.name {
 					@include word-vw(14, #333);
-					&.active{
+
+					&.active {
 						color: #5781FF;
 					}
 				}

File diff suppressed because it is too large
+ 572 - 252
src/packages/goods/good-detail.vue


+ 393 - 0
src/packages/goods/select-good.vue

@@ -0,0 +1,393 @@
+<template>
+	<view class='content'>
+		<Navbar title='选择奶粉'></Navbar>
+		<!-- 筛选框 -->
+		<view class="search-styl">
+			<view class="search-box">
+				<view class="search-left">
+					<text class="icon1">&#xe89f;</text>
+					<input type="text" class="input-styl" placeholder-class="placeholder" confirm-type="search"
+						v-model="searchContent" @confirm="searchGoods" @focus="focus = true" placeholder="搜索商品名称" />
+					<text class="icon1" v-if="searchContent" @click="deleteContent">&#xe8ac;</text>
+				</view>
+				<view class="search-btn" @click="clickCancel">取消</view>
+			</view>
+		</view>
+		<view class="goods-module" :class="{'goods-module2': sortType === 2}">
+			<!-- <GoodItem v-for="(good, index) in goodsList" :good="good" :key="index" style="width: 100%"></GoodItem> -->
+			<view class="good-item" v-if="good" v-for="(good, index) in goodsList" :good="good" @click="handleSelect(good)">
+				<view class="good-name">{{good.name}}</view>
+				<view class="good-info-box">
+					<image :src="good.masterPic" class="pic" mode="aspectFit"></image>
+					<view class="good-info">
+						<view class="area">
+							<view><text class="label">奶源:</text>{{good.milkSource}}</view>
+							<view><text class="label">产地:</text>{{good.milkOrigin}}</view>
+						</view>
+						<view class="advantage">
+							<text class="label">优点:</text>
+							<view class="advantage-item" v-for="(item, index) in good.advantage.split(',')"
+								:key="index">
+								{{item}}
+							</view>
+						</view>
+						<view class="price">
+							<text class="label">参考价:</text>
+							<text class="price-icon">¥</text>
+							{{good.price}}
+						</view>
+					</view>
+				</view>
+				<view></view>
+			</view>
+			<view class="no-data" v-if="!goodsList.length">
+				<NoData :show="!goodsList.length" topNum="10" title="没有搜到商品!" ></NoData>
+			</view>
+		</view>
+	</view>
+</template>
+<script lang='ts'>
+	import {
+		Component,
+		// Prop,
+		Vue
+	} from 'vue-property-decorator';
+	import {
+		namespace
+	} from 'vuex-class';
+	import {
+		types
+	} from '@/common/store';
+	const baseModule = namespace('base');
+	@Component({})
+
+	export default class Name extends Vue {
+		@baseModule.Mutation(types.SET_GOOD) setGood: any;
+		// @baseModule.Mutation(types.ADD_CARTGOODS) addCartGoods: any;
+		// data------------------------
+		goodsList: Array < any > = []; //商品列表
+		searchContent: string = ''; //搜索内容
+		showHistory: boolean = true; //历史搜索数据展示
+		nodataShow: boolean = false; //空数据展示
+		total: number = 0;
+		finish: boolean = false;
+		loading: boolean = false;
+		current: number = 1;
+		size: number = 20;
+		name: any = '';
+		iconShow: boolean = false;
+		sortType: number = 1;
+		onLoad() {
+			
+		}
+		onReachBottom() {
+			if (this.finish || this.loading) return;
+			this.current++;
+			this.getGoodsList('', 'load');
+		}
+		//methods----------------------
+		clickCancel() {
+			this.$Router.back(1);
+		}
+		deleteContent() {
+			this.searchContent = '';
+			this.goodsList = [];
+			this.current = 1;
+			this.finish = false;
+			this.getGoodsList('');
+		}
+		//获取商品列表
+		getGoodsList(val ? : string, isLoad ? : any) {
+			this.loading = true;
+			// return
+			let data: object = {
+				name: val,
+				status: '3',
+				page: this.current,
+				size: this.size,
+			}
+			uni.showLoading({
+				title: '加载中',
+			});
+			return this.$http.get({
+				url: this.$api.getGoodsList,
+				data: data
+			}).then((res: any) => {
+				this.goodsList = [...this.goodsList, ...res.list];
+				this.total = res.total;
+				if (res.list.length < this.size) this.finish = true;
+				this.loading = false;
+				uni.hideLoading();
+			}).catch((err: any) => {
+				console.log(err);
+				this.loading = false;
+				uni.hideLoading();
+			})
+		}
+		//搜索商品内容
+		searchGoods(e: any) {
+			let value = e.detail.value;
+			this.goodsList = [];
+			this.current = 1;
+			this.finish = false;
+			this.getGoodsList(value);
+		}
+		handleSelect(item: any){
+			this.setGood(item);
+			this.$Router.back(1);
+		}
+	}
+</script>
+
+<style lang='scss' scoped>
+	.content {
+		width: 100%;
+		min-height: 100vh;
+		@include flex-y();
+		background: #F6F6F6;
+
+		.search-styl {
+			width: 100%;
+			padding-top: vw(6);
+			padding-bottom: vw(8);
+			background-color: #ffffff;
+
+			.search-box {
+				@include flex-x();
+				@include wh(348, 32);
+				margin: 0 auto;
+
+				.search-left {
+					@include flex-x(flex-start);
+					@include wh(310, 32);
+					border-radius: vw(16);
+					background-color: #F6F6F6;
+
+					.icon1 {
+						margin: 0 vw(10);
+						@include icon(14);
+					}
+
+					.input-styl {
+						width: vw(315);
+						font-size: vw(14);
+					}
+
+					.placeholder {
+						color: #999;
+					}
+				}
+
+				.search-btn {
+					/* padding-left: vw(12);
+					margin-right: vw(13); */
+					flex: 1;
+					text-align: center;
+					color: $btn-color;
+					font-size: vw(14);
+				}
+			}
+		}
+
+		.sort-box {
+			height: vw(40);
+			width: 100%;
+			@include flex-x();
+			margin-top: vw(1);
+			background: #fff;
+
+			.sort-item {
+				flex: 1;
+				@include flex-x(center);
+				background: #fff;
+				height: vw(20);
+				@include word-vw(14, #999);
+				border-right: vw(1) solid #F5F5F5;
+
+				&:nth-last-of-type(1) {
+					border-width: 0;
+				}
+
+				.sj {
+					position: relative;
+					@include flex-y(center);
+					margin-left: vw(3);
+				}
+
+				.ssj {
+					border-top: vw(5) solid transparent;
+					border-bottom: vw(5) solid #ccc;
+					border-left: vw(5) solid transparent;
+					border-right: vw(5) solid transparent;
+
+					&.active {
+						border-bottom: vw(5) solid $btn-color;
+					}
+				}
+
+				.xsj {
+					border-top: vw(5) solid #ccc;
+					border-bottom: vw(5) solid transparent;
+					border-left: vw(5) solid transparent;
+					border-right: vw(5) solid transparent;
+					margin-top: vw(3);
+
+					&.active {
+						border-top: vw(5) solid $btn-color;
+					}
+				}
+
+				&.active {
+					color: $btn-color;
+				}
+			}
+		}
+
+		.search-history {
+			width: 100%;
+			flex: 1;
+			box-sizing: border-box;
+			padding: vw(12) vw(23) 0 vw(16);
+			@include word-vw(12, $gray6);
+
+			.search-title {
+				width: 100%;
+				@include flex-x();
+			}
+
+			.search-content {
+				@include flex-x(flex-start);
+				flex-flow: row wrap;
+				margin-top: vw(18);
+
+				.search-font {
+					padding: vw(8) vw(14);
+					margin: 0 vw(10) vw(10) 0;
+					background-color: #ffffff;
+					position: relative;
+				}
+
+				.delete {
+					position: absolute;
+					right: -6px;
+					top: -6px;
+				}
+			}
+		}
+
+		.goods-module {
+			width: 100%;
+			padding: vw(10) vw(10) 0;
+			box-sizing: border-box;
+			/* flex: 1;
+			overflow-y: auto; */
+			@include flex-x(space-between, flex-start);
+			flex-wrap: wrap;
+
+			&.goods-module2 {
+				@include flex-y();
+				padding: vw(10) 0 0;
+			}
+
+			.no-data {
+				width: 100%;
+				height: 100%;
+				padding-top: 20%;
+				@include flex-y();
+			}
+
+			.total {
+				padding: 0 vw(10);
+				margin-top: vw(6);
+				@include word-vw(14, #999);
+				height: vw(30);
+				line-height: vw(30);
+
+				text {
+					color: #333;
+					padding: 0 vw(3);
+				}
+			}
+		}
+	}
+	.good-item {
+		width: 100%;
+		background: #fff;
+		border-radius: vw(10);
+		margin-bottom: vw(10);
+		padding: vw(14);
+		box-sizing: border-box;
+		position: relative;
+	
+		.good-name {
+			@include word-vw(14, #333);
+			font-weight: 450;
+		}
+	
+		.good-info-box {
+			margin-top: vw(12);
+			@include flex-x();
+	
+			.pic {
+				@include wh(80, 80);
+				display: block;
+			}
+	
+			.good-info {
+				flex: 1;
+				min-height: vw(80);
+				margin-left: vw(16);
+				@include flex-y(flex-start, flex-start);
+	
+				.label {
+					@include word-vw(12, #999);
+				}
+	
+				.area {
+					@include flex-x(flex-start);
+					@include word-vw(12, #333);
+	
+					view {
+						width: vw(90);
+					}
+				}
+	
+				.advantage {
+					margin-top: vw(8);
+					@include word-vw(10, #FF7E33);
+					@include flex-x(flex-start, flex-start);
+					flex-wrap: wrap;
+					line-height: vw(20);
+					flex: 1;
+	
+					.advantage-item {
+						height: vw(18);
+						padding: 0 vw(6);
+						border-radius: vw(4);
+						background: #FFEEDE;
+						margin-right: vw(6);
+					}
+				}
+	
+				.price {
+					@include word-vw(18, #FF5733);
+	
+					.price-icon {
+						@include word-vw(12, #FF5733);
+					}
+				}
+			}
+		}
+	
+		.btn {
+			@include wh(76, 26);
+			@include word-vw(12, #fff);
+			@include flex-x(center);
+			border-radius: vw(4);
+			background: $btn-color;
+			position: absolute;
+			right: vw(12);
+			bottom: vw(12);
+		}
+	}
+</style>

+ 88 - 0
src/packages/user/user/about-us-list.vue

@@ -0,0 +1,88 @@
+<template>
+	<view class="user-setting-box">
+		<!-- #ifndef MP-TOUTIAO -->
+		<Navbar background-color="#fff" color="#333" title="关于我们"></Navbar>
+		<!-- #endif -->
+		<view class="content">
+			<view class="baby-item" v-for="(item, index) in list" :key="index" @click="toAboutUs(item)">
+				<view class="left">
+					{{item.title}}
+				</view>
+				<view class="right">
+					<IconText :code="`\ue88e`" class="icon" size="14" color="#94B2FF"></IconText>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script lang="ts">
+	import {
+		Component,
+		Mixins
+	} from 'vue-property-decorator';
+	import loginMixin from '@/common/mixins/loginMixin.ts';
+	// import {
+	// 	namespace
+	// } from 'vuex-class';
+	// const baseModule = namespace('base');
+	@Component({})
+	export default class SelectBaby extends Mixins(loginMixin) {
+		// @baseModule.Getter('_userInfo') _userInfo: any;
+		list: any = [{
+			title: '关于我们',
+			value: '公司介绍'
+		},{
+			title: '商务合作',
+			value: '商务合作'
+		}];
+		
+		onShow() {
+			
+		}
+		
+		toAboutUs(item: any){
+			this.$Router.push({
+				path: '/packages/user/user/about-us',
+				query: {
+					...item
+				}
+			})
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	page{
+		background: #f5f5f5;
+	}
+	.user-setting-box {
+		// background: #F5F5F5;
+		height: 100vh;
+		// @include flex-y(flex-start);
+
+		.content {
+			width: 100%;
+			padding: 0 vw(15);
+			box-sizing: border-box;
+			@include flex-y(flex-start);
+			.baby-item{
+				width: 100%;
+				height: vw(56);
+				@include flex-x();
+				padding: vw(12) vw(18);
+				box-sizing: border-box;
+				background: #fff;
+				border-radius: vw(10);
+				margin-top: vw(10);
+				.left{
+					@include flex-x();
+					@include word-vw(14, #333);
+				}
+				.right{
+					
+				}
+			}
+		}
+	}
+</style>

+ 107 - 0
src/packages/user/user/about-us.vue

@@ -0,0 +1,107 @@
+<template>
+	<view class="classroom-box">
+		<Navbar :title="title" background-color="#fff" color="#333"></NavBar>
+		<view class="container">
+			<view class="title">{{info.title}}</view>
+			<!-- <view class="date">{{info.created}}</view> -->
+			<!-- <view class="text" v-html="info.content"></view> -->
+			<u-parse :content="info.content" @preview="preview" />
+		</view>
+	</view>
+</template>
+
+<script lang='ts'>
+	import uParse from '@/components/gaoyia-parse/parse.vue'
+	import {
+		Component,
+		Vue
+	} from 'vue-property-decorator';
+	@Component({
+		components: {
+			uParse
+		},
+		filters: {
+			moneyFormat(val: any) {
+				if (!+val) return '0.00';
+				return (+val).toFixed(2);
+			}
+		}
+	})
+	export default class Classroom extends Vue {
+		info: any = '';
+		title: any = '';
+
+		onShow() {
+			this.title = this.$Route.query.title;
+			this.getAgreementInfo();
+		}
+
+		preview(src: any, e: any) {
+			// do something
+		}
+		// navigate(href: any, e: any) {
+		// 	// console.log(href, 123);
+		// 	// do something
+		// 	this.$Router.push({
+		// 		path: '/pages/front/article',
+		// 		query: {
+		// 			link: href
+		// 		}
+		// 	})
+		// }
+
+		getAgreementInfo() {
+			this.$http
+				.get({
+					url: this.$api.getAgreementInfo,
+					data: {
+						title: this.$Route.query.value
+					}
+				})
+				.then((res: any) => {
+					this.info = res;
+				}, (err: any) => {
+					console.log(err);
+				});
+		}
+	}
+</script>
+<style lang='scss'>
+	.video {
+		@include flex-y(center);
+	}
+</style>
+<style lang='scss' scoped>
+	page {
+		background: #fff;
+	}
+
+	.classroom-box {
+		min-height: 100vh;
+		@include flex-y();
+		background: #fff;
+
+		.container {
+			flex: 1;
+			width: 100%;
+			box-sizing: border-box;
+			overflow-y: auto;
+			padding: 0 vw(18);
+
+			.title {
+				@include word-vw(24, #333);
+				margin-top: vw(30);
+				font-weight: 550;
+			}
+
+			.date {
+				@include word-vw(12, #999);
+				margin-top: vw(24);
+			}
+
+			.text {
+				margin-top: vw(24);
+			}
+		}
+	}
+</style>

+ 83 - 0
src/packages/user/user/exchange-success.vue

@@ -0,0 +1,83 @@
+<template>
+	<view class="success">
+		<Navbar title="支付成功" background-color="#fff" color="#333"></Navbar>
+		<view class="container">
+			<view class="tip">
+				<IconText :code="`\ue842`" color="#5786FF" size="80" class="icon"></IconText>
+				<text>
+					您消耗{{amount}}宝宝币, 成功兑换{{name}}次数
+				</text>
+			</view>
+			<view class="btn" @click="handleBack">继续兑换</view>
+			<view class="btn btn2" @click="handleUser">返回个人中心</view>
+		</view>
+	</view>
+</template>
+
+<script lang='ts'>
+	import {
+		Component,
+		Vue
+	} from 'vue-property-decorator';
+	@Component({})
+	export default class RechargeSuccess extends Vue {
+		amount: any = null;
+		name: any = '';
+		
+		onShow() {
+			let query = this.$Route.query;
+			this.amount = query.amount;
+			this.name = query.name;
+		}
+
+		// 返回首页
+		handleUser() {
+			this.$Router.pushTab({
+				path: '/pages/user/user'
+			})
+		}
+
+		handleBack() {
+			this.$Router.back(1);
+		}
+	}
+</script>
+
+<style lang='scss' scoped>
+	.success {
+		height: 100vh;
+		@include flex-y();
+
+		.container {
+			height: 100%;
+			width: 100%;
+			@include flex-y();
+
+			.tip {
+				@include word-vw(14, #333);
+				@include flex-y();
+				width: vw(220);
+				text-align: center;
+				margin: vw(80) 0 vw(20);
+
+				text {
+					margin-top: vw(24);
+				}
+			}
+
+			.btn {
+				width: vw(335);
+				height: vw(50);
+				background: #5786FF;
+				border-radius: vw(25);
+				@include word-vw(14, #fff);
+				@include flex-x(center);
+				margin-top: vw(16);
+			}
+			.btn2{
+				background: #D9E4FF;
+				color: #333;
+			}
+		}
+	}
+</style>

+ 178 - 0
src/packages/user/user/exchange.vue

@@ -0,0 +1,178 @@
+<template>
+	<view class="user-setting-box">
+		<!-- #ifndef MP-TOUTIAO -->
+		<Navbar background-color="transparent" color="#333" title="兑换咨询次数"></Navbar>
+		<!-- #endif -->
+		<view class="bg"></view>
+		<view class="content">
+			<view class="bottom">
+				<view class="list">
+					<view class="item" v-for="(item, index) in list" :key="index">
+						<view class="item-left">
+							<view class="price">
+								{{item.cells[1].value}}
+								<image :src="staticUrl ? staticUrl + 'front-gold.png' : ''" class="pic" mode="heightFix">
+							</view>
+							<view class="title">
+								{{item.key}}
+							</view>
+							<view class="tip">
+								{{item.cells[0].value === 'AI' ? '(最专业的奶粉人工智能)' : ''}}
+								{{item.cells[0].value === '人工' ? `(单次${item.cells[3].value}分钟)` : ''}}
+							</view>
+						</view>
+						<view class="btn" @click="handleBuy(index, item)">
+							立即兑换
+						</view>
+					</view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script lang="ts">
+	import {
+		Component,
+		Mixins
+	} from 'vue-property-decorator';
+	import loginMixin from '@/common/mixins/loginMixin.ts';
+	// import {
+	// 	namespace
+	// } from 'vuex-class';
+	// const baseModule = namespace('base');
+	@Component({})
+	export default class UserSetting extends Mixins(loginMixin) {
+		// @baseModule.Getter('_userInfo') _userInfo: any;
+		staticUrl : string = this.$oss_url; 	//oss地址
+		list : any = [];
+		channel : any = 'wx_jsapi';
+		providerMap : any = {
+			wx_jsapi: 'wxpay',
+			aliPayApp: 'alipay'
+		};
+		onShow() {
+			this.getUserInfo();
+			this.getConsultList();
+		}
+
+		getConsultList() {
+			this.$http
+				.get({
+					url: this.$api.getConsultList
+				})
+				.then((res : any) => {
+					this.list = res.list;
+				}, (err : any) => {
+					console.log(err);
+				});
+		}
+		
+		handleBuy(index: any, item: any){
+			this.$http
+				.post({
+					url: this.$api.buyConsult,
+					data: {
+						index
+					}
+				})
+				.then((res : any) => {
+					this.$Router.push({
+						path: '/packages/user/user/exchange-success',
+						query: {
+							amount: item.cells[1].value,
+							name: item.key
+						}
+					})
+				}, (err : any) => {
+					console.log(err);
+				});
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	page {
+		background: #f5f5f5;
+	}
+
+	.user-setting-box {
+		// background: #F5F5F5;
+		height: 100vh;
+		@include flex-y(flex-start);
+
+		.bg {
+			width: 100%;
+			height: vw(320);
+			background: linear-gradient(184.24deg, rgba(232, 237, 255, 1) 0%, rgba(212, 236, 253, 1) 51.31%, rgba(247, 242, 255, 1) 79.11%, rgba(246, 243, 250, 1) 88.2%, rgba(245, 245, 245, 1) 100%);
+			position: absolute;
+			top: 0;
+			z-index: -1;
+		}
+
+		.content {
+			width: 100%;
+			flex: 1;
+			padding: 0 vw(10);
+			box-sizing: border-box;
+			@include flex-y(flex-start);
+
+			.bottom {
+				width: 100%;
+				margin-top: vw(10);
+
+				.list {
+					width: 100%;
+					@include flex-y(flex-start);
+					padding: vw(24) vw(20) vw(10);
+					background: #fff;
+					box-sizing: border-box;
+					border-radius: vw(10);
+
+					.item {
+						width: 100%;
+						height: vw(80);
+						border-radius: vw(10);
+						background: linear-gradient(90deg, rgba(230, 242, 255, 1) 0%, rgba(230, 233, 255, 1) 73.9%, rgba(230, 239, 255, 1) 100%);
+						border: 1px solid rgba(218, 234, 255, 1);
+						@include flex-x();
+						box-sizing: border-box;
+						margin-bottom: vw(10);
+						padding: 0 vw(16);
+
+						.item-left {
+							@include flex-y(center, flex-start);
+
+							.price{
+								@include word-vw(24, #FF661A);
+								font-weight: bold;
+								.pic{
+									@include wh(16, 16);
+									margin-left: vw(3);
+								}
+							}
+							
+							.title{
+								@include word-vw(14, #333);
+								font-weight: bold;
+							}
+							
+							.tip{
+								margin-top: vw(3);
+								@include word-vw(12, #999);
+							}
+						}
+
+						.btn {
+							@include wh(70, 24);
+							border-radius: vw(12);
+							background: #6B95FF;
+							@include flex-x(center);
+							@include word-vw(12, #fff);
+						}
+					}
+				}
+			}
+		}
+	}
+</style>

+ 132 - 0
src/packages/user/user/feedback.vue

@@ -0,0 +1,132 @@
+<template>
+	<view class="agent-box">
+		<Navbar title="意见反馈" background-color="#fff" color="#333"></NavBar>
+		<view class="container">
+			<view class="content">
+				<textarea class="text" v-model="content" placeholder="点击输入文字" />
+			</view>
+			<view class="pics">
+				<view class="tip">图片(选填, 最多9张)</view>
+				<MulImgUpload @update="getImgs" :imgs="pics" :max="9" :width="100 / 3.75" :height="100 / 3.75"
+					addColor="#999999">
+				</MulImgUpload>
+			</view>
+		</view>
+		<view class="bottom-btn-box">
+			<view class="bottom-btn" @click="handleConfirm">提交申请</view>
+		</view>
+	</view>
+</template>
+
+<script lang='ts'>
+	import {
+		Component,
+		Vue
+	} from 'vue-property-decorator';
+	// import {
+	// 	namespace
+	// } from 'vuex-class';
+	// import {
+	// 	types
+	// } from '@/common/store/index';
+	// const baseModule = namespace('base');
+	import {
+		OSS_STATIC
+	} from '@/common/constants';
+	@Component({})
+	export default class Agent extends Vue {
+		static: string = OSS_STATIC;
+		pics: any = [];
+		content: any = "";
+		onShow() {
+
+		}
+
+		onLoad() {
+
+		}
+
+		getImgs(pics: any) {
+			console.log(pics)
+			this.pics = pics;
+		}
+		handleConfirm() {
+			this.$http
+				.post({
+					url: this.$api.addFeedback,
+					data: {
+						content: this.content,
+						pics: this.pics
+					}
+				})
+				.then((res: any) => {
+					this.$Router.back(1);
+				}, (err: any) => {
+					console.log(err);
+				});
+		}
+	}
+</script>
+
+<style lang='scss' scoped>
+	page {
+		/* background: #fff; */
+	}
+
+	.agent-box {
+		background: #f5f5f5;
+		/* padding: 0 vw(16); */
+		min-height: 100vh;
+
+		.container {
+			/* background: #fff; */
+			/* @include flex-y(flex-start); */
+			margin-top: vw(10);
+
+			.content {
+				background: #fff;
+				padding: vw(15);
+				border-radius: vw(10);
+				font-size: vw(14);
+
+				.text {
+					background: #F6F6F6;
+					height: vw(200);
+					width: 100%;
+					border-radius: vw(10);
+					padding: vw(12);
+					box-sizing: border-box;
+				}
+			}
+
+			.pics {
+				background: #fff;
+				padding: vw(15);
+				border-radius: vw(10);
+				margin-top: vw(10);
+
+				.tip {
+					@include word-vw(14, #333);
+					margin-bottom: vw(16);
+				}
+			}
+		}
+
+		.bottom-btn-box {
+			height: vw(70);
+			width: 100%;
+			background: #fff;
+			@include flex-x(center);
+			position: fixed;
+			bottom: 0;
+
+			.bottom-btn {
+				background: #1C8A64;
+				@include solid-btn(335, 50, #333);
+				border-radius: vw(10);
+				@include word-vw(16, #fff);
+				font-weight: 450;
+			}
+		}
+	}
+</style>

+ 57 - 1
src/packages/user/user/info-setting.vue

@@ -19,6 +19,15 @@
 					<view class="time">{{date || '请选择生日'}}</view>
 				</picker>
 			</view>
+			<view v-if="type === 'familyRole'" class="date">
+				<view class="label">角色</view>
+				<picker @change="changeRole" :value="roleIndex" :range="roleList" range-key="labelName">
+					<view class="role">
+						{{roleList[roleIndex].labelName || '请选择角色'}}
+						<IconText :code="`\ue88e`" class="icon" size="12" color="#C6C5CB"></IconText>
+					</view>
+				</picker>
+			</view>
 			<view v-if="type === 'location'" class="city">
 				<view class="label">所在城市</view>
 				<uni-data-picker :localdata="items" placeholder="点击选择" popup-title="请选择地区" v-model="area"
@@ -67,8 +76,11 @@
 		address: any = {};
 		userName: string = '';
 		nickname: string = '';
+		roleList : any = [];
+		roleIndex : any = null;
+		familyRole: any = '';
 		onLoad() {
-			this.getAllArea();
+			// this.getAllArea();
 			let query = this.$Route.query;
 			this.title = query.title;
 			this.type = query.type;
@@ -86,6 +98,10 @@
 				case "location":
 					if (query.value) this.area = query.value.split('/');
 					break;
+				case "familyRole":
+					this.familyRole = query.value;
+					this.getLabelItemByRole();
+					break;
 				default:
 					return;
 			}
@@ -98,6 +114,30 @@
 		changeDate(val: any) {
 			this.date = val.detail.value;
 		}
+		
+		getLabelItemByRole() {
+			// uni.showLoading({
+			// 	title: '加载中',
+			// });
+			this.$http.get({
+				url: this.$api.getLabelItem,
+				data: {
+					dataName: "role"
+				}
+			}).then((res : any) => {
+				let obj : any = {};
+				res.list.forEach((item : any) => {
+					obj[item.value] = item.labelName
+				})
+				this.roleList = res.list;
+				// uni.hideLoading();
+			})
+		}
+		
+		changeRole(e : any) {
+			this.roleIndex = e.detail.value;
+			this.familyRole = this.roleList[e.detail.value].value;
+		}
 
 		getNow() {
 			let now = new Date();
@@ -180,6 +220,18 @@
 						location: this.area.join('/')
 					}
 					break;
+				case "familyRole":
+					// if (!this.userName) {
+					// 	uni.showToast({
+					// 		title: '请填写姓名',
+					// 		icon: 'none'
+					// 	})
+					// 	return;
+					// }
+					data = {
+						familyRole: this.familyRole
+					}
+					break;
 				default:
 					data = {};
 			}
@@ -273,6 +325,10 @@
 			.time {
 				@include word-vw(15, #999);
 			}
+			
+			.role{
+				@include flex-x();
+			}
 		}
 
 		.tip {

+ 392 - 0
src/packages/user/user/member.vue

@@ -0,0 +1,392 @@
+<template>
+	<view class="user-setting-box">
+		<!-- #ifndef MP-TOUTIAO -->
+		<Navbar background-color="transparent" color="#333" title="会员"></Navbar>
+		<!-- #endif -->
+		<view class="bg"></view>
+		<view class="content">
+			<view class="top">
+				<view class="left">
+					<view>
+						可用宝宝币
+						<image :src="staticUrl ? staticUrl + 'front-gold.png' : ''" class="pic" mode="heightFix">
+						</image>
+					</view>
+					<text>{{_userInfo.balance}}</text>
+				</view>
+				<view class="line"></view>
+				<view class="right">
+					<view class="item">
+						剩余AI咨询数
+						<text>{{_userInfo.aiWaitNumber}}</text>
+					</view>
+					<view class="item">
+						剩余人工咨询数
+						<text>{{_userInfo.manualWaitNumber}}</text>
+					</view>
+				</view>
+			</view>
+			<view class="bottom">
+				<view class="title-box"
+					:style="{backgroundImage: `url(${staticUrl ? staticUrl + 'member-title-bg.png' : ''})`}">
+					<view class="title-item">
+						会员套餐
+						<view class="bar"></view>
+					</view>
+					<view class="title-item" @click="toRecord">权益历史</view>
+				</view>
+				<view class="list">
+					<view class="item" v-for="(item, index) in list" :key="index">
+						<view class="item-left">
+							<view class="name">
+								<text>{{item.cells[0].value}}</text>
+								元会员套餐
+							</view>
+							<view class="tip">
+								购买得{{item.cells[1].value}}宝宝币
+							</view>
+						</view>
+						<view class="btn" @click="handlePay(index)">
+							购卡
+						</view>
+					</view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script lang="ts">
+	import {
+		Component,
+		Mixins
+	} from 'vue-property-decorator';
+	import loginMixin from '@/common/mixins/loginMixin.ts';
+	// import {
+	// 	namespace
+	// } from 'vuex-class';
+	// const baseModule = namespace('base');
+	@Component({})
+	export default class UserSetting extends Mixins(loginMixin) {
+		// @baseModule.Getter('_userInfo') _userInfo: any;
+		staticUrl : string = this.$oss_url; 	//oss地址
+		list : any = [];
+		channel : any = 'wx_jsapi';
+		providerMap : any = {
+			wx_jsapi: 'wxpay',
+			aliPayApp: 'alipay'
+		};
+		payInfo: any = {};
+		onShow() {
+			this.getUserInfo();
+			this.getMemberRechargeList();
+		}
+
+		getMemberRechargeList() {
+			this.$http
+				.get({
+					url: this.$api.getMemberRechargeList
+				})
+				.then((res : any) => {
+					this.list = res.list;
+				}, (err : any) => {
+					console.log(err);
+				});
+		}
+		
+		toRecord(){
+			this.$Router.push({
+				path: '/packages/user/user/recharge-record'
+			})
+		}
+
+		async handlePay(index: any) {
+			let eve : any = {};
+			// #ifdef MP-WEIXIN
+			eve = await this.getCode();
+			// #endif
+			uni.showLoading({
+				title: '加载中',
+			});
+			this.$http.post({
+				url: this.$api.getRecharge,
+				data: {
+					index
+				}
+			}).then((res : any) => {
+				this.payInfo = res;
+				this.$http.post({
+					url: this.$api.createPay,
+					data: {
+						payBill: {
+							payType: 5,
+							id: res.payBillId,
+							// sid: 0,
+							mode: 'wxPayMini'
+						},
+						third: {
+							code: eve.code || ''
+						}
+					}
+				}).then((res2 : any) => {
+					uni.hideLoading();
+					this.moneyPay(res2);
+				});
+			}, (err: any) => {
+				uni.hideLoading();
+			});
+		}
+
+		getCode() {
+			return new Promise((resolve : any, reject : any) => {
+				uni.login({
+					provider: 'weixin',
+					success: (eve) => {
+						resolve(eve);
+					},
+					fail: (err) => {
+						console.log(err);
+						reject();
+						// this.canSubmit = true;
+					}
+				});
+			})
+		}
+
+		moneyPay(pay_info : any) : any {
+			// 拉起微信支付
+			let option = {};
+			// #ifdef MP-WEIXIN
+			option = {
+				timeStamp: pay_info.timeStamp,
+				nonceStr: pay_info.nonceStr,
+				package: pay_info.package,
+				signType: pay_info.signType,
+				paySign: pay_info.paySign,
+			};
+			// #endif
+			// #ifdef APP-PLUS
+			option = {
+				appid: pay_info.appId,
+				partnerid: pay_info.partnerid,
+				prepayid: pay_info.prepay_id,
+				sign: pay_info.paySign,
+				timestamp: pay_info.timeStamp,
+				noncestr: pay_info.nonceStr,
+				package: pay_info.package,
+			};
+			// #endif
+			let orderInfo : any = JSON.stringify(option);
+			if (this.channel === 'aliPayApp') orderInfo = this.objToCookie(pay_info);
+			uni.requestPayment({
+				"provider": this.providerMap[this.channel],
+				...option,
+				"orderInfo": orderInfo,
+				success: (result : any) => {
+					if (result.errMsg == "requestPayment:ok") {
+						uni.showToast({
+							title: "支付成功!",
+							icon: "none",
+							duration: 2000,
+						});
+						this.$Router.push({
+							path: '/packages/user/user/recharge-success',
+							query: {
+								amount: this.payInfo.amount,
+								balance: this.payInfo.balance,
+							}
+						})
+					}
+				},
+				fail: (err : any) => {
+					console.log('支付失败', err);
+					// that.canSubmit = true;
+				}
+			});
+		}
+		objToCookie(obj : any) {
+			{
+				if (obj.constructor == Object) {
+					var cssStr = '';
+					for (var key in obj) {
+						cssStr += key + '=' + encodeURIComponent(obj[key]) + '&';
+					}
+					return cssStr.substring(0, cssStr.length - 1);
+				}
+			}
+		}
+
+		handleConfirm() {
+			this.$Router.push({
+				path: '/packages/user/user/recharge-success'
+			})
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	page {
+		background: #f5f5f5;
+	}
+
+	.user-setting-box {
+		// background: #F5F5F5;
+		height: 100vh;
+		@include flex-y(flex-start);
+
+		.bg {
+			width: 100%;
+			height: vw(320);
+			background: linear-gradient(184.24deg, rgba(232, 237, 255, 1) 0%, rgba(212, 236, 253, 1) 51.31%, rgba(247, 242, 255, 1) 79.11%, rgba(246, 243, 250, 1) 88.2%, rgba(245, 245, 245, 1) 100%);
+			position: absolute;
+			top: 0;
+			z-index: -1;
+		}
+
+		.content {
+			width: 100%;
+			flex: 1;
+			padding: 0 vw(10);
+			box-sizing: border-box;
+			@include flex-y(flex-start);
+
+			.top {
+				width: 100%;
+				height: vw(90);
+				background: linear-gradient(90deg, rgba(117, 156, 254, 1) 0%, rgba(115, 133, 255, 1) 53.47%, rgba(125, 125, 255, 1) 100%);
+				box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.08);
+				border-radius: vw(10);
+				margin-top: vw(20);
+				padding: vw(16);
+				box-sizing: border-box;
+				@include flex-x(flex-start);
+
+				.left {
+					@include flex-y(flex-start, flex-start);
+					min-width: vw(100);
+					margin-right: vw(16);
+
+					view {
+						@include word-vw(12, #fff);
+						@include flex-x(flex-start);
+
+						.pic {
+							@include wh(14, 14);
+							margin-left: vw(5);
+						}
+					}
+
+					text {
+						margin-top: vw(3);
+						@include word-vw(26, #fff);
+						font-weight: bold;
+					}
+				}
+
+				.line {
+					width: 0;
+					height: vw(36);
+					border-right: vw(1) solid rgba(255, 255, 255, 0.25);
+
+				}
+
+				.right {
+					@include flex-x(flex-start, flex-start);
+					height: 100%;
+					flex: 1;
+
+					.item {
+						flex: 1;
+						@include flex-y(flex-start);
+						@include word-vw(12, #fff);
+
+						text {
+							@include word-vw(26, #fff);
+							font-weight: bold;
+							margin-top: vw(3);
+						}
+					}
+				}
+			}
+
+			.bottom {
+				width: 100%;
+				margin-top: vw(10);
+
+				.title-box {
+					width: 100%;
+					height: vw(60);
+					background-size: 100% 100%;
+					background-repeat: no-repeat;
+					@include flex-x();
+
+					.title-item {
+						flex: 1;
+						height: 100%;
+						@include flex-x(center);
+						@include word-vw(14, #666);
+						position: relative;
+
+						.bar {
+							@include wh(26, 4);
+							border-radius: vw(2);
+							background: #6B95FF;
+							position: absolute;
+							bottom: vw(8);
+						}
+					}
+				}
+
+				.list {
+					width: 100%;
+					@include flex-y(flex-start);
+					padding: vw(24) vw(20);
+					background: #fff;
+					box-sizing: border-box;
+					border-bottom-left-radius: vw(10);
+					border-bottom-right-radius: vw(10);
+
+					.item {
+						width: 100%;
+						height: vw(80);
+						border-radius: vw(10);
+						background: linear-gradient(90deg, rgba(230, 242, 255, 1) 0%, rgba(230, 233, 255, 1) 73.9%, rgba(230, 239, 255, 1) 100%);
+						border: 1px solid rgba(218, 234, 255, 1);
+						@include flex-x();
+						padding-left: vw(20);
+						padding-right: vw(16);
+						box-sizing: border-box;
+						margin-bottom: vw(10);
+
+						.item-left {
+							@include flex-y(flex-start, flex-start);
+
+							.name {
+								@include word-vw(14, #333);
+								font-weight: bold;
+
+								text {
+									@include word-vw(24, #FF661A);
+									margin-right: vw(2);
+								}
+							}
+
+							.tip {
+								@include word-vw(14, #999);
+								margin-top: vw(6);
+							}
+						}
+
+						.btn {
+							@include wh(56, 24);
+							border-radius: vw(12);
+							background: #6B95FF;
+							@include flex-x(center);
+							@include word-vw(12, #fff);
+						}
+					}
+				}
+			}
+		}
+	}
+</style>

+ 243 - 0
src/packages/user/user/recharge-record.vue

@@ -0,0 +1,243 @@
+<template>
+	<view class="record-box">
+		<Navbar title="权益历史" background-color="#fff" color="#333"></NavBar>
+		<view class="container">
+			<!-- <view class="top">
+				<view class="title">
+					余额明细
+				</view>
+				<view class="status" @click="openSearch">
+					{{typeMap[fundType] || '全部'}}
+					<IconText :code="`\ue63c`" :size="8" color="#666" class="icon"></IconText>
+				</view>
+			</view> -->
+			<view class="noData" v-if="!list.length && !isLoading">
+				<NoData :show="!list.length" topNum="10"></NoData>
+			</view>
+			<view class="list" v-else>
+				<view class="item" v-for="item in list" :key="item.id">
+					<view class="left">
+						<text>{{item.describe}}</text>
+						{{item.created}}
+					</view>
+					<view class="right">
+						<image :src="staticUrl ? staticUrl + 'front-gold.png' : ''" class="pic" mode="heightFix">
+						<text v-if="item.direction === 1" style="color: #FF3333;">-{{item.amount | moneyFormat}}</text>
+						<text v-else style="color: #2FAD61;">+{{item.amount | moneyFormat}}</text>
+					</view>
+				</view>
+				<view class="data-tips">
+					<text v-if="final">没有更多了</text>
+					<text v-else>加载更多</text>
+				</view>
+			</view>
+		</view>
+		<BottomPopup ref="bottom_popup" title="请选择" :dataList="typeList" @selected="popupSelected" keyName="name">
+		</BottomPopup>
+	</view>
+</template>
+
+<script lang='ts'>
+	import {
+		Component,
+		Vue
+	} from 'vue-property-decorator';
+	import {
+		namespace
+	} from 'vuex-class';
+	const baeModule = namespace('base');
+	import {
+		types
+	} from '@/common/store';
+	@Component({
+		filters: {
+			moneyFormat(val: any) {
+				if (!+val) return '0.00';
+				return (+val).toFixed(2);
+			}
+		}
+	})
+	export default class RechargeRecord extends Vue {
+		staticUrl : string = this.$oss_url; 	//oss地址
+		img: string = this.$oss_url + 'zwdd.png';
+		isLoading: boolean = false;
+		list: any[] = [];
+		sum: number = 0;
+		isLoad: boolean = false;
+		final: boolean = false;
+		current: number = 1;
+		size: number = 20;
+		type: any = 'balance';
+		fundType: any = '';
+		typeList: any[] = [];
+		typeMap: any = {};
+		balanceInfo: any = {};
+
+		onShow() {
+			this.list = [];
+			this.current = 1;
+			this.final = false;
+			this.getList();
+			// this.getFundTypeMap();
+			// this.getBalance();
+		}
+
+		onReachBottom() {
+			if (this.final) return;
+			this.current++;
+			this.getList();
+			// this.getFundTypeMap();
+			// this.getBalance();
+		}
+		
+		getFundTypeMap(){
+			this.$http
+				.get({
+					url: this.$api.getFundTypeMap
+				})
+				.then((res: any) => {
+					this.typeMap = res.balanceLog.balance;
+					let list = [
+						{
+							value: '',
+							name: '全部'
+						}
+					];
+					for(let key in this.typeMap){
+						list.push({
+							value: key,
+							name: this.typeMap[key]
+						});
+					};
+					this.typeList = list;
+				}, (err: any) => {
+					console.log(err);
+				});
+		}
+
+		getList() {
+			uni.showLoading({
+				title: '加载中',
+			});
+			this.isLoading = true;
+			return this.$http.get({
+				url: this.$api.getRechargeRecord,
+				data: {
+					page: this.current,
+					size: this.size,
+					// fundType: this.fundType,
+					// type: this.type
+				}
+			}).then((res: any) => {
+				this.list = [...this.list, ...res.list];
+				this.isLoading = false;
+				if (!res.list || (res.list.length < this.size)) {
+					this.final = true;
+				}
+				uni.hideLoading();
+			}).catch((err: any) => {
+				console.log(err)
+				uni.hideLoading();
+				this.isLoading = false;
+			})
+		}
+
+		openSearch() {
+			(this.$refs.bottom_popup as any).open();
+		}
+
+		popupSelected(val: any) {
+			this.fundType = val.value;
+			this.list = [];
+			this.current = 1;
+			this.final = false;
+			this.getList();
+		}
+	}
+</script>
+
+<style lang='scss' scoped>
+	.record-box {
+		min-height: 100%;
+		@include flex-y();
+		background: #F6F6F6;
+
+		.container {
+			flex: 1;
+			width: 100%;
+			box-sizing: border-box;
+			overflow-y: auto;
+
+			.top {
+				@include flex-x();
+				background: #fff;
+				/* position: fixed; */
+				width: 100%;
+				z-index: 20;
+				height: vw(55);
+				padding: 0 vw(18);
+				box-sizing: border-box;
+				margin-top: vw(1);
+			}
+
+			.noData {
+				padding-top: vw(55);
+			}
+
+			.status {
+				/* padding-right: vw(18); */
+				@include word-vw(14, #666);
+				@include flex-x(flex-start);
+
+				.icon {
+					margin-left: vw(6);
+				}
+			}
+
+			.list {
+				box-sizing: border-box;
+				margin-top: vw(10);
+				/* padding-top: vw(55); */
+
+				.item {
+					/* box-shadow: 0px 1px 5px rgba(225, 225, 225, 0.5); */
+					background: #fff;
+					margin-top: vw(1);
+					/* border-radius: vw(10); */
+					height: vw(60);
+					@include flex-x();
+
+					view {
+						padding: 0 vw(18);
+						@include flex-y(center, flex-start);
+						@include word-vw(12, #999);
+
+						text {
+							margin-bottom: vw(5);
+							@include word-vw(16, #333);
+							font-weight: 450;
+						}
+
+						&.right {
+							align-items: flex-end;
+							@include flex-x();
+							.pic{
+								@include wh(24, 24);
+								margin-right: vw(3);
+							}
+							.oid{
+								@include word-vw(12, #999);
+							}
+						}
+					}
+				}
+			}
+		}
+		.data-tips {
+			width: 100%;
+			text-align: center;
+			@include word-vw(12, $gray9);
+			margin-top: 10px;
+		}
+	}
+</style>

+ 90 - 0
src/packages/user/user/recharge-success.vue

@@ -0,0 +1,90 @@
+<template>
+	<view class="success">
+		<Navbar title="支付成功" background-color="#fff" color="#333"></Navbar>
+		<view class="container">
+			<view class="tip">
+				<IconText :code="`\ue842`" color="#5786FF" size="80" class="icon"></IconText>
+				<text>
+					成功购买{{amount}}元会员套餐,获得{{balance}}宝宝币
+				</text>
+			</view>
+			<view class="btn" @click="handleBack">继续购买会员套餐</view>
+			<view class="btn" @click="handleExchange">去兑换</view>
+			<view class="btn btn2" @click="handleUser">返回个人中心</view>
+		</view>
+	</view>
+</template>
+
+<script lang='ts'>
+	import {
+		Component,
+		Vue
+	} from 'vue-property-decorator';
+	@Component({})
+	export default class RechargeSuccess extends Vue {
+		amount: any = '';
+		balance: any = '';
+		
+		onShow() {
+			let query = this.$Route.query;
+			this.balance = query.balance;
+			this.amount = query.amount;
+		}
+
+		// 返回首页
+		handleUser() {
+			this.$Router.pushTab({
+				path: '/pages/user/user'
+			})
+		}
+		
+		handleExchange() {
+			this.$Router.replace({
+				path: '/packages/user/user/exchange'
+			})
+		}
+
+		handleBack() {
+			this.$Router.back(1);
+		}
+	}
+</script>
+
+<style lang='scss' scoped>
+	.success {
+		height: 100vh;
+		@include flex-y();
+
+		.container {
+			height: 100%;
+			width: 100%;
+			@include flex-y();
+
+			.tip {
+				@include word-vw(14, #333);
+				@include flex-y();
+				width: vw(220);
+				text-align: center;
+				margin: vw(80) 0 vw(20);
+
+				text {
+					margin-top: vw(24);
+				}
+			}
+
+			.btn {
+				width: vw(335);
+				height: vw(50);
+				background: #5786FF;
+				border-radius: vw(25);
+				@include word-vw(14, #fff);
+				@include flex-x(center);
+				margin-top: vw(16);
+			}
+			.btn2{
+				background: #D9E4FF;
+				color: #333;
+			}
+		}
+	}
+</style>

+ 250 - 0
src/packages/user/user/share - 副本.vue

@@ -0,0 +1,250 @@
+<template>
+	<view class="share-box">
+		<Navbar title="分享页"></NavBar>
+		<view class="content">
+			<canvas canvas-id="shareCanvas" class="canvas" style="width: 275px;height:550px;"></canvas>
+			<!-- #ifdef APP -->
+			<view class="qr-box">
+				<uqrcode ref="qRCode" canvas-id="qRCode" :value="qr" @complete="complete"
+					:options="{ foregroundImageSrc: static ? static + 'logo.png' : '' }" v-show="true"></uqrcode>
+			</view>
+			<!-- #endif -->
+			<view class="bottom">
+				<view class="btn" @click="saveImageToPhotos('shareCanvas')">保存图片至相册</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script lang="ts">
+	// @ts-nocheck
+	import {
+		Component,
+		Prop,
+		Vue,
+		Emit,
+		Mixins
+	} from 'vue-property-decorator';
+	import {
+		types
+	} from '@/common/store';
+	import {
+		OSS_STATIC
+	} from '@/common/constants';
+	import canvasMixin from '@/common/mixins/canvasMixin.ts';
+	import {
+		namespace
+	} from 'vuex-class';
+	const baseModule = namespace('base');
+	@Component({})
+	export default class ShopShare extends Mixins(canvasMixin) {
+		@baseModule.Getter('_userInfo') _userInfo : any;
+
+		avatar : string = "";
+		pic : string = "";
+		qr : string = "";
+		shareInfo : string = "";
+		static : string = OSS_STATIC;
+		qrPic : any = '';
+
+		async onLoad() {
+			let res = await this.getShareInfo();
+			let shareUrl = await this.downLoadImg(res.pic);
+			this.pic = shareUrl;
+			// #ifdef MP-WEIXIN
+			this.handleShare();
+			// #endif
+			// #ifdef APP
+			this.getCode();
+			// #endif
+		}
+
+		getShareInfo() {
+			return this.$http
+				.get({
+					url: this.$api.getShareInfo,
+					data: {
+						way: 1
+					}
+				})
+				.then(async (res : any) => {
+					this.shareInfo = res;
+					return res;
+				}, (err : any) => {
+					console.log(err);
+				});
+		}
+
+		complete(res : any) {
+			console.log(res.success, 'complete');
+			if (res.success) {
+				this.toImage();
+			}
+		}
+
+		toImage() {
+			// @ts-ignore
+			this.$refs.qRCode.toTempFilePath({
+				success: (res : any) => {
+					console.log(res, 'toImage');
+					this.qrPic = res.tempFilePath;
+					this.$nextTick(() => {
+						console.log('start')
+						this.drawPoster();
+					})
+					// ctx.drawImage(that.qrPic, 158, 392, 105, 105);
+					// ctx.draw(true, () => {
+					// 	console.log('draw,true');
+					// 	uni.hideLoading();
+					// });
+				},
+				fail: (err : any) => {
+					console.log(err);
+				}
+			});
+		}
+
+		getCode() {
+			this.$http
+				.get({
+					url: this.$api.getShareCode,
+					data: {
+						rid: this._userInfo.uid + ''
+					}
+				})
+				.then(async (res : any) => {
+					console.log(res, 'share')
+					this.qr = res.qr;
+					let avatarUrl = await this.downLoadImg(this._userInfo.avatar);
+					// let shareUrl = await this.downLoadImg(this.static + 'share.png');
+					this.avatar = avatarUrl;
+					// this.pic = shareUrl;
+					console.log('start')
+					this.$nextTick(() => {
+						console.log('start')
+						this.qrPic && this.drawPoster();
+					})
+				}, (err : any) => {
+					console.log(err);
+				});
+		}
+		drawPoster() : void {
+			// 绘制海报
+			// 注意:page页面canvas-id获取ctx,组件需传this
+			const that = this;
+			const ctx = uni.createCanvasContext('shareCanvas', this);
+			// 绘制白色底
+			this.roundRect(ctx, 0, 255, 275, 295, '#ffffff', 0, 20, 20, 0);
+			// 绘制店铺图片
+			// this.drawImgInfo(
+			// 	ctx,
+			// 	0,
+			// 	0,
+			// 	275,
+			// 	275,
+			// 	that.pic
+			// );
+			this.roundImg(ctx, 0, 0, 275, 275, 20, '', that.pic);
+			// 绘制头像
+			this.drawCircular(ctx, 40, 40, 15, 160, that.avatar);
+			// this.roundRect(ctx, 0, 397, 44, 44, '#000');
+			// this.roundRect(ctx, 0, 454, 50, 16, '#f00');
+			// this.roundRect(ctx, 0, 483, 50, 16, '#f00');
+			ctx.textAlign = "left";
+			this.textSet(ctx, '育百通', '12px', 60, 175, '#fff', 'bold ');
+			this.textSet(ctx, (that._userInfo.nickname + '推荐' || '用户推荐'), '12px', 60, 191, '#fff', 'bold ');
+			// this.textSet(ctx, that.shareInfo.slogan + '', '10px', 78, 494, '#8F8F8F', '');
+			// this.textSet(ctx, '推荐', '10px', 180, 450, '#000', 'bold ');
+			// // 小程序码
+			// #ifdef MP-WEIXIN
+			ctx.drawImage(that.qr, 64.5, 300, 150, 150);
+			// #endif
+			// #ifndef MP-WEIXIN
+			that.qrPic && ctx.drawImage(that.qrPic, 158, 392, 105, 105);
+			// #endif
+			// ctx.textAlign = "center";
+			this.textCenterSet(ctx, that.shareInfo.slogan + '', '14px', 137.5, 480, '#999', 275, '');
+			this.textCenterSet(ctx, '扫一扫二维码加入我们', '18px', 137.5, 510, '#4A4A4A', 275, 'bold ');
+			ctx.draw(true, () => {
+				console.log('draw,true');
+				uni.hideLoading();
+			});
+		}
+
+		async handleShare() {
+			// 获取小程序码
+			let data = {
+				page: 'pages/front/front',
+				scene: `isShare,${this._userInfo.uid}`
+			};
+			uni.showLoading({
+				title: '加载中',
+			});
+			this.getQr(data, async (url : any) => {
+				this.qr = url;
+				let avatarUrl = await this.downLoadImg(this._userInfo.avatar);
+				// let shareUrl = await this.downLoadImg(this.static + 'share.png');
+				this.avatar = avatarUrl;
+				// this.pic = avatarUrl;
+				uni.showLoading({
+					title: '加载中'
+				});
+				this.drawPoster();
+			});
+		}
+		downLoadImg(url : any) {
+			return new Promise((resolve : any, reject : any) => {
+				uni.downloadFile({
+					url,
+					complete: (result : any) => {
+						if (result.statusCode === 200) {
+							resolve(result.tempFilePath);
+						} else {
+							reject(false);
+						}
+					}
+				});
+			})
+		}
+	}
+</script>
+
+<style lang='scss' scoped>
+	.share-box {
+		background: #F5F5F5;
+		height: 100vh;
+		box-sizing: border-box;
+		@include flex-y();
+
+		.content {
+			width: 100%;
+			@include flex-y(center);
+			padding-top: vw(20);
+			padding-bottom: vw(80);
+			
+			.qr-box{
+				position: absolute;
+				left: 1000px;
+			}
+
+			.bottom {
+				width: 100%;
+				position: fixed;
+				bottom: 0;
+				height: vw(70);
+				background: #fff;
+				@include flex-x(center);
+
+				.btn {
+					@include flex-x(center);
+					@include solid-btn(335, 50, #fff, 25);
+				}
+			}
+
+			.img {
+				width: 300px;
+				margin-top: vw(16);
+			}
+		}
+	}
+</style>

+ 19 - 10
src/packages/user/user/share.vue

@@ -2,7 +2,7 @@
 	<view class="share-box">
 		<Navbar title="分享页"></NavBar>
 		<view class="content">
-			<canvas canvas-id="shareCanvas" class="canvas" style="width: 275px;height:515px;"></canvas>
+			<canvas canvas-id="shareCanvas" class="canvas" style="width: 275px;height:550px;"></canvas>
 			<!-- #ifdef APP -->
 			<view class="qr-box">
 				<uqrcode ref="qRCode" canvas-id="qRCode" :value="qr" @complete="complete"
@@ -62,7 +62,10 @@
 		getShareInfo() {
 			return this.$http
 				.get({
-					url: this.$api.getShareInfo
+					url: this.$api.getShareInfo,
+					data: {
+						way: 1
+					}
 				})
 				.then(async (res : any) => {
 					this.shareInfo = res;
@@ -130,33 +133,39 @@
 			// 注意:page页面canvas-id获取ctx,组件需传this
 			const that = this;
 			const ctx = uni.createCanvasContext('shareCanvas', this);
+			this.roundRect(ctx, 0, 0, 275, 50, '#ffffff', 20, 0, 0, 20);
 			// 绘制白色底
-			this.roundRect(ctx, 0, 375, 275, 140, '#ffffff', 0, 10, 10, 0);
+			this.roundRect(ctx, 0, 255, 275, 300, '#ffffff', 0, 20, 20, 0);
 			// 绘制店铺图片
 			this.drawImgInfo(
 				ctx,
 				0,
-				0,
+				50,
+				275,
 				275,
-				375,
 				that.pic
 			);
+			// this.roundImg(ctx, 0, 0, 275, 275, 20, '', that.pic);
 			// 绘制头像
-			this.drawCircular(ctx, 44, 44, 56, 397, that.avatar);
+			this.drawCircular(ctx, 32, 32, 10, 8, that.avatar);
 			// this.roundRect(ctx, 0, 397, 44, 44, '#000');
 			// this.roundRect(ctx, 0, 454, 50, 16, '#f00');
 			// this.roundRect(ctx, 0, 483, 50, 16, '#f00');
-			ctx.textAlign = "center";
-			this.textSet(ctx, that._userInfo.nickname || '商城用户', '16px', 78, 468, '#000', 'bold ');
-			this.textSet(ctx, that.shareInfo.slogan + '', '10px', 78, 494, '#8F8F8F', '');
+			ctx.textAlign = "left";
+			this.textSet(ctx, '育百通', '12px', 48, 21, '#333', 'bold ');
+			this.textSet(ctx, (that._userInfo.nickname + '推荐' || '用户推荐'), '12px', 48, 36, '#333', 'bold ');
+			// this.textSet(ctx, that.shareInfo.slogan + '', '10px', 78, 494, '#8F8F8F', '');
 			// this.textSet(ctx, '推荐', '10px', 180, 450, '#000', 'bold ');
 			// // 小程序码
 			// #ifdef MP-WEIXIN
-			ctx.drawImage(that.qr, 158, 392, 105, 105);
+			ctx.drawImage(that.qr, 75, 340, 125, 125);
 			// #endif
 			// #ifndef MP-WEIXIN
 			that.qrPic && ctx.drawImage(that.qrPic, 158, 392, 105, 105);
 			// #endif
+			// ctx.textAlign = "center";
+			this.textCenterSet(ctx, that.shareInfo.slogan + '', '14px', 137.5, 490, '#999', 275, '');
+			this.textCenterSet(ctx, '扫一扫二维码加入我们', '18px', 137.5, 525, '#4A4A4A', 275, 'bold ');
 			ctx.draw(true, () => {
 				console.log('draw,true');
 				uni.hideLoading();

+ 118 - 28
src/packages/user/user/update-phone.vue

@@ -5,20 +5,22 @@
 		<!-- #endif -->
 		<view class="bg"></view>
 		<view class="content">
-			<view class="tip">系统向183****7798发送了验证码,请输入</view>
-			<view class="code-box">
+			<!-- <view class="tip">系统向{{_userInfo.phone | phoneFormat}}发送了验证码,请输入</view> -->
+			<!-- <view class="code-box">
 				<input type="text" class="input" placeholder="请输入验证码"/>
 				<view class="btn">重新获取</view>
-			</view>
+			</view> -->
 			<view class="box">
 				<view class="input-box">
 					<view class="label">新手机号</view>
-					<input type="text" class="input" placeholder="此处输入新手机号"/>
+					<input v-model="phone" type="number" class="input" placeholder="此处输入新手机号" />
 				</view>
 				<view class="input-box code">
 					<view class="label">验证码</view>
-					<input type="text" class="input" placeholder="请输入验证码"/>
-					<view class="btn">重新获取</view>
+					<input v-model="code" type="number" class="input" placeholder="请输入验证码" />
+					<view class="code-btn btn" @click="getCode" :class="{disabled: isWaiting}">
+						{{ isWaiting ? `${countDown}秒后重试` : '获取验证码' }}
+					</view>
 				</view>
 			</view>
 		</view>
@@ -60,9 +62,20 @@
 	})
 	export default class UserSetting extends Mixins(loginMixin) {
 		// @baseModule.Getter('_userInfo') _userInfo: any;
-		
+		code : any = null;
+		isWaiting : boolean = false; //是否已发送验证码
+		timer : number | null = null; //定时器
+		countDown : number = 0; //倒计时
+		defaultTime : number = 60; //初始倒计时时间
+		setTime : any = 0;
+		phone: any = '';
+
+
 		onShow() {
-			
+			this.getUserInfo();
+			// this.$nextTick(() => {
+			// 	this.getCode();
+			// })
 		}
 
 		updatePhone() {
@@ -72,7 +85,53 @@
 			// })
 		}
 
-		getCode() {
+		//获取验证码
+		getCode() : void {
+			if (this.isWaiting) return;
+			if (!/^[1][0-9]{10}$/.test(this.phone)) {
+				uni.showToast({
+					title: '请输入正确的手机号',
+					duration: 2000,
+					icon: 'none'
+				});
+				return;
+			}
+			uni.showLoading({
+				title: '加载中'
+			});
+			this.$http
+				.post({
+					url: this.$api.sendCode,
+					data: {
+						phone: this.phone,
+						type: 1
+					}
+				})
+				.then(() => {
+					//验证码获取倒计时
+					uni.hideLoading();
+					uni.showToast({
+						title: '已发送',
+						duration: 2000,
+						icon: 'none'
+					});
+					this.isWaiting = true;
+					this.timer && clearInterval(this.timer);
+					this.countDown = this.defaultTime;
+					this.setTime = +new Date() + 60000;
+					this.timer = setInterval(() => {
+						this.countDown--;
+						if (this.countDown <= 0) {
+							this.timer && clearInterval(this.timer);
+							this.isWaiting = false;
+						}
+					}, 1000);
+				}, () => {
+					uni.hideLoading();
+				});
+		}
+
+		getWxCode() {
 			return new Promise((resolve : any, reject : any) => {
 				uni.login({
 					provider: 'weixin',
@@ -86,23 +145,37 @@
 				});
 			})
 		}
-		
-		handleConfirm(){
-			
+
+		handleConfirm() {
+			this.$http
+				.get({
+					url: this.$api.updatePhone,
+					data: {
+						page: 1,
+						size: 5,
+						
+					}
+				})
+				.then((res : any) => {
+					
+				}, (err : any) => {
+					console.log(err);
+				});
 		}
 	}
 </script>
 
 <style lang="scss" scoped>
-	page{
+	page {
 		background: #f5f5f5;
 	}
+
 	.user-setting-box {
 		// background: #F5F5F5;
 		height: 100vh;
 		@include flex-y(flex-start);
-		
-		.bg{
+
+		.bg {
 			width: 100%;
 			height: vw(200);
 			background: linear-gradient(173.24deg, rgba(232, 237, 255, 1) 0%, rgba(230, 230, 255, 1) 47.75%, rgba(247, 242, 255, 1) 82.84%, rgba(251, 246, 252, 1) 100%);
@@ -118,22 +191,23 @@
 			box-sizing: border-box;
 			@include flex-y(flex-start);
 
-			.tip{
+			.tip {
 				width: 100%;
 				margin-top: vw(18);
 				@include word-vw(14, #666);
 				padding: 0 vw(15);
 				box-sizing: border-box;
 			}
-			
-			.code-box{
+
+			.code-box {
 				width: 100%;
 				height: vw(44);
 				padding: 0 vw(10);
 				box-sizing: border-box;
 				@include flex-x();
 				margin-top: vw(15);
-				.input{
+
+				.input {
 					flex: 1;
 					height: 100%;
 					background: #fff;
@@ -142,7 +216,8 @@
 					padding: 0 vw(20);
 					font-size: vw(14);
 				}
-				.btn{
+
+				.btn {
 					@include wh(96, 44);
 					// border-radius: vw(5);
 					background: $btn-color;
@@ -152,24 +227,28 @@
 					border-bottom-right-radius: vw(5);
 				}
 			}
-			.box{
+
+			.box {
 				width: vw(355);
 				margin-top: vw(24);
 				background: #fff;
 				border-radius: vw(10);
 				@include flex-y(flex-start);
-				.input-box{
+
+				.input-box {
 					width: 100%;
 					height: vw(56);
 					padding-left: vw(18);
 					padding-right: vw(12);
 					box-sizing: border-box;
 					@include flex-x();
-					.label{
+
+					.label {
 						width: vw(90);
 						@include word-vw(14, #333);
 					}
-					.input{
+
+					.input {
 						flex: 1;
 						height: vw(40);
 						font-size: vw(14);
@@ -177,7 +256,8 @@
 						background: #F6F6F6;
 						border-radius: vw(5);
 					}
-					.btn{
+
+					.btn {
 						@include wh(96, 40);
 						// border-radius: vw(5);
 						background: $btn-color;
@@ -186,21 +266,31 @@
 						border-top-right-radius: vw(5);
 						border-bottom-right-radius: vw(5);
 					}
+
+					.code-btn {
+						// @include word-vw(14, $btn-color);
+
+						&.disabled {
+							background: $gray9;
+						}
+					}
 				}
-				.code{
-					.input{
+
+				.code {
+					.input {
 						border-top-right-radius: 0;
 						border-bottom-right-radius: 0;
 					}
 				}
 			}
 		}
+
 		.fixed-bottom {
 			height: vw(60);
 			width: 100%;
 			background: #fff;
 			@include flex-x(center);
-		
+
 			.solid-btn {
 				background: $bk-color;
 				@include solid-btn(345, 48, #333);

+ 78 - 27
src/packages/user/user/user-setting.vue

@@ -20,13 +20,13 @@
 				<!-- #ifdef MP-WEIXIN -->
 				<button class="avatar-wrapper" open-type="chooseAvatar" @chooseavatar="updateInfo">
 					<image class="avatar" :src="_userInfo.avatar"></image>
-					<!-- <IconText :code="`\ue88e`" class="icon" size="14" color="#C6C5CB"></IconText> -->
+					<IconText :code="`\ue88e`" class="icon" size="14" color="#C6C5CB"></IconText>
 				</button>
 				<!-- #endif -->
 				<!-- #ifndef MP-WEIXIN -->
 				<view class="avatar-wrapper" @click="chooseImg">
 					<image class="avatar" :src="_userInfo.avatar"></image>
-					<!-- <IconText :code="`\ue88e`" class="icon" size="14" color="#C6C5CB"></IconText> -->
+					<IconText :code="`\ue88e`" class="icon" size="14" color="#C6C5CB"></IconText>
 				</view>
 				<!-- #endif -->
 			</view>
@@ -49,12 +49,14 @@
 						{{_userInfo.phone}}
 					</view> -->
 				</view>
-				<view class="right">
-					{{roleMap[_userInfo.roleTypeOne]}}
+				<view class="right"
+					@click="toPage('/packages/user/user/info-setting', {title: '角色', type: 'familyRole', value: 'familyRole'})">
+					{{_userInfo.familyRole || '请选择角色'}}
 					<IconText :code="`\ue88e`" class="icon" size="14" color="#C6C5CB"></IconText>
 				</view>
 			</view>
-			<view class="phone info info2 top-border-radius bottom-border-radius" @click="toPage('/packages/user/user/update-phone')">
+			<view class="phone info info2 top-border-radius bottom-border-radius"
+				@click="toPage('/packages/user/user/update-phone')">
 				<view class="left">
 					手机号
 					<!-- <view class="phone-num">
@@ -66,7 +68,8 @@
 					<IconText :code="`\ue88e`" class="icon" size="14" color="#C6C5CB"></IconText>
 				</view>
 			</view>
-			<view class="phone info info2 top-border-radius">
+			<view class="phone info info2 top-border-radius"
+				@click="toPage('/packages/user/user/about-us', {title:'用户协议', value: '用户协议'})">
 				<view class="left">
 					用户协议
 				</view>
@@ -74,7 +77,8 @@
 					<IconText :code="`\ue88e`" class="icon" size="14" color="#C6C5CB"></IconText>
 				</view>
 			</view>
-			<view class="phone info bottom-border-radius">
+			<view class="phone info bottom-border-radius"
+				@click="toPage('/packages/user/user/about-us', {title:'隐私政策', value: '隐私政策'})">
 				<view class="left">
 					隐私政策
 				</view>
@@ -82,6 +86,9 @@
 					<IconText :code="`\ue88e`" class="icon" size="14" color="#C6C5CB"></IconText>
 				</view>
 			</view>
+			<view class="logout" @click="handleLogoutModal">
+				退出登录
+			</view>
 			<!-- <view class="info info2">
 				<view class="left">
 					登录密码
@@ -102,6 +109,7 @@
 			</view> -->
 		</view>
 		<ShowModal ref="bindOpenId" title="提示" @submit="bindOpenId" leftBtnText="取消" content="是否绑定微信" btnText="确认" />
+		<ShowModal ref="logout" title="提示" @submit="handleLogout" leftBtnText="取消" content="是否确定退出" btnText="确认" />
 	</view>
 </template>
 
@@ -111,10 +119,13 @@
 		Mixins
 	} from 'vue-property-decorator';
 	import loginMixin from '@/common/mixins/loginMixin.ts';
-	// import {
-	// 	namespace
-	// } from 'vuex-class';
-	// const baseModule = namespace('base');
+	import {
+		types
+	} from '@/common/store/index';
+	import {
+		namespace
+	} from 'vuex-class';
+	const baseModule = namespace('base');
 	@Component({
 		filters: {
 			phoneFormat(val : any) {
@@ -137,11 +148,14 @@
 	})
 	export default class UserSetting extends Mixins(loginMixin) {
 		// @baseModule.Getter('_userInfo') _userInfo: any;
+		@baseModule.Mutation(types.LOGOUT) logout : any;
 		pic : string = '';
 		isPayPassword : any = false;
-		roleMap: any = {};
+		roleMap : any = {};
+		roleList : any = [];
 		onShow() {
-			// this.getUserInfo();
+			this.getUserInfo();
+			this.getLabelItemByRole();
 			// this.getIsPayPassword();
 			// this.getDictionaryList();
 		}
@@ -157,7 +171,7 @@
 					console.log(err);
 				});
 		}
-		
+
 		getDictionaryList() {
 			// uni.showLoading({
 			// 	title: '加载中',
@@ -167,16 +181,35 @@
 				data: {
 					dataName: "role"
 				}
-			}).then((res: any) => {
-				let obj: any = {};
-				res.list.forEach((item: any) => {
+			}).then((res : any) => {
+				let obj : any = {};
+				res.list.forEach((item : any) => {
 					obj[item.value] = item.labelName
 				})
 				this.roleMap = obj;
 				// uni.hideLoading();
 			})
 		}
-		
+
+		getLabelItemByRole() {
+			// uni.showLoading({
+			// 	title: '加载中',
+			// });
+			this.$http.get({
+				url: this.$api.getLabelItem,
+				data: {
+					dataName: "role"
+				}
+			}).then((res : any) => {
+				let obj : any = {};
+				res.list.forEach((item : any) => {
+					obj[item.value] = item.labelName
+				})
+				this.roleList = res.list;
+				// uni.hideLoading();
+			})
+		}
+
 		chooseImg() {
 			uni.chooseImage({
 				count: 1, //默认9
@@ -314,18 +347,30 @@
 				});
 			})
 		}
+
+		handleLogoutModal() {
+			(this.$refs.logout as any).open();
+		}
+
+		handleLogout() {
+			this.logout();
+			this.$Router.pushTab({
+				path: '/pages/front/front'
+			})
+		}
 	}
 </script>
 
 <style lang="scss" scoped>
-	page{
+	page {
 		background: #f5f5f5;
 	}
+
 	.user-setting-box {
 		// background: #f5f5f5;
 		min-height: 100vh;
-		
-		.bg{
+
+		.bg {
 			width: 100%;
 			height: vw(190);
 			background: linear-gradient(180deg, rgba(222, 231, 255, 1) 0%, rgba(241, 220, 247, 1) 49.31%, rgba(248, 228, 248, 0.31) 77.08%, rgba(253, 241, 240, 0.42) 100%);
@@ -346,13 +391,13 @@
 				background: #fff;
 				padding: 0 vw(15);
 				margin-top: vw(1);
-				
-				&.top-border-radius{
+
+				&.top-border-radius {
 					border-top-right-radius: vw(10);
 					border-top-left-radius: vw(10);
 				}
-				
-				&.bottom-border-radius{
+
+				&.bottom-border-radius {
 					border-bottom-right-radius: vw(10);
 					border-bottom-left-radius: vw(10);
 				}
@@ -399,8 +444,8 @@
 					}
 				}
 			}
-			
-			.avatar-box{
+
+			.avatar-box {
 				height: vw(72);
 			}
 
@@ -412,6 +457,12 @@
 					margin-left: vw(10);
 				}
 			}
+
+			.logout {
+				@include word-vw(14, #999);
+				margin-top: vw(50);
+				@include flex-x(center);
+			}
 		}
 	}
 </style>

+ 168 - 36
src/pages.json

@@ -25,8 +25,18 @@
 				"visitor": true
 			},
 			"style": {
-				"navigationStyle": "custom",
-				"enablePullDownRefresh": true
+				"navigationStyle": "custom"
+				// "enablePullDownRefresh": true
+			}
+		}, {
+			"path": "pages/front/article",
+			"name": "front",
+			"meta": {
+				"visitor": true
+			},
+			"style": {
+				"navigationStyle": "custom"
+				// "enablePullDownRefresh": true
 			}
 		}, {
 			"path": "pages/user/user",
@@ -59,7 +69,41 @@
 			"style": {
 				"navigationStyle": "custom"
 			}
-		}, 
+		},
+		{
+			"path": "pages/login/phone-login",
+			"name": "login",
+			"style": {
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path": "pages/login/select-stage",
+			"meta": {
+				"visitor": true
+			},
+			"style": {
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path": "pages/login/pregnant",
+			"meta": {
+				"visitor": true
+			},
+			"style": {
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path": "pages/login/baby",
+			"meta": {
+				"visitor": true
+			},
+			"style": {
+				"navigationStyle": "custom"
+			}
+		},
 		// {
 		// 	"path": "pages/login/register",
 		// 	"name": "register",
@@ -90,6 +134,11 @@
 			"meta": {
 				"visitor": true
 			}
+		}, {
+			"path": "pages/baby/baby-list",
+			"style": {
+				"navigationStyle": "custom"
+			}
 		}
 	],
 	"subPackages": [{
@@ -110,7 +159,15 @@
 			"style": {
 				"navigationStyle": "custom"
 			}
-		},{
+		}, {
+			"path": "brand-list", //商品搜索页
+			"meta": {
+				"visitor": true
+			},
+			"style": {
+				"navigationStyle": "custom"
+			}
+		}, {
 			"path": "brand-detail", //商品搜索页
 			"meta": {
 				"visitor": true
@@ -118,7 +175,7 @@
 			"style": {
 				"navigationStyle": "custom"
 			}
-		},{
+		}, {
 			"path": "brand-goods-search", //商品搜索页
 			"meta": {
 				"visitor": true
@@ -141,6 +198,25 @@
 			}
 		}, {
 			"path": "filter", //商品搜索页
+			"meta": {
+				"visitor": true
+			},
+			"style": {
+				"navigationStyle": "custom"
+			}
+		}, {
+			"path": "select-good", //商品搜索页
+			"meta": {
+				"visitor": true
+			},
+			"style": {
+				"navigationStyle": "custom"
+			}
+		}, {
+			"path": "brand-article-search", //商品搜索页
+			"meta": {
+				"visitor": true
+			},
 			"style": {
 				"navigationStyle": "custom"
 			}
@@ -185,6 +261,46 @@
 				"style": {
 					"navigationStyle": "custom"
 				}
+			}, {
+				"path": "about-us-list", //
+				"style": {
+					"navigationStyle": "custom"
+				}
+			}, {
+				"path": "about-us", //
+				"style": {
+					"navigationStyle": "custom"
+				}
+			}, {
+				"path": "feedback", //
+				"style": {
+					"navigationStyle": "custom"
+				}
+			}, {
+				"path": "member", //
+				"style": {
+					"navigationStyle": "custom"
+				}
+			}, {
+				"path": "recharge-success", //
+				"style": {
+					"navigationStyle": "custom"
+				}
+			}, {
+				"path": "exchange", //
+				"style": {
+					"navigationStyle": "custom"
+				}
+			}, {
+				"path": "exchange-success", //
+				"style": {
+					"navigationStyle": "custom"
+				}
+			}, {
+				"path": "recharge-record", //
+				"style": {
+					"navigationStyle": "custom"
+				}
 			}
 		]
 	}, {
@@ -236,42 +352,58 @@
 				"style": {
 					"navigationStyle": "custom"
 				}
-			}
-		]
-	}, {
-		"root": "packages/family",
-		"pages": [{
-				"path": "family-list", //
-				"style": {
-					"navigationStyle": "custom"
-				}
-			},{
-				"path": "add-family", //
-				"style": {
-					"navigationStyle": "custom"
-				}
-			},{
-				"path": "family-setting", //
-				"style": {
-					"navigationStyle": "custom"
-				}
-			},{
-				"path": "family-transfer", //
-				"style": {
-					"navigationStyle": "custom"
-				}
-			},{
-				"path": "add-member", //
+			},
+			{
+				"path": "baby-poop", //
 				"style": {
 					"navigationStyle": "custom"
 				}
-			},{
-				"path": "member-info", //
+			},
+			{
+				"path": "add-poop", //
 				"style": {
 					"navigationStyle": "custom"
 				}
 			}
 		]
+	}, {
+		"root": "packages/family",
+		"pages": [{
+			"path": "family-list", //
+			"style": {
+				"navigationStyle": "custom"
+			}
+		}, {
+			"path": "add-family", //
+			"style": {
+				"navigationStyle": "custom"
+			}
+		}, {
+			"path": "family-setting", //
+			"style": {
+				"navigationStyle": "custom"
+			}
+		}, {
+			"path": "family-transfer", //
+			"style": {
+				"navigationStyle": "custom"
+			}
+		}, {
+			"path": "add-member", //
+			"style": {
+				"navigationStyle": "custom"
+			}
+		}, {
+			"path": "member-info", //
+			"style": {
+				"navigationStyle": "custom"
+			}
+		}, {
+			"path": "family-share", //
+			"style": {
+				"navigationStyle": "custom"
+			}
+		}]
 	}],
 	"tabBar": {
 		"color": "#333333",
@@ -281,12 +413,12 @@
 		"list": [{
 			"pagePath": "pages/front/front",
 			"text": "首页"
-		}, {
-			"pagePath": "pages/category/category",
-			"text": "全部分类"
 		}, {
 			"pagePath": "pages/contrast/contrast-list",
 			"text": "对比"
+		}, {
+			"pagePath": "pages/baby/baby-list",
+			"text": "宝宝档案"
 		}, {
 			"pagePath": "pages/user/user",
 			"text": "我的"

+ 257 - 0
src/pages/baby/baby-list.vue

@@ -0,0 +1,257 @@
+<template>
+	<view class="user-setting-box">
+		<!-- #ifndef MP-TOUTIAO -->
+		<Navbar background-color="transparent" color="#333" title="宝宝档案" :showBack="false"></Navbar>
+		<!-- #endif -->
+		<view class="bg"></view>
+		<view class="content">
+			<view class="baby-item" v-for="item in babyList" :key="item.bid" @click="toPage('/packages/baby/add-baby', {bid: item.bid})">
+				<view class="left">
+					<view class="top">
+						<image class="avatar" :src="item.babyAvatar" mode="scaleToFill"></image>
+						<view class="info">
+							<view class="name">{{item.babyNickname}}</view>
+							<view class="age">
+								{{genderMap[item.gender]}}
+								<view class="line" v-if="item.family"></view>
+								{{item.age | ageFormat}}
+							</view>
+						</view>
+					</view>
+					<view class="bottom">
+						<view class="option-item"
+							@click="toPage('/packages/baby/baby-feed', {bid: item.bid})">
+							<image :src="staticUrl ? staticUrl + 'baby-list-01.png' : ''" class="pic" mode="aspectFill">
+							</image>
+							喂奶记录
+						</view>
+						<view class="option-item"
+							@click="toPage('/packages/baby/baby-poop', {bid: item.bid})">
+							<image :src="staticUrl ? staticUrl + 'baby-list-02.png' : ''" class="pic" mode="aspectFill">
+							</image>
+							便便记录
+						</view>
+						<view class="option-item"
+							@click="toPage('/packages/baby/baby-weight', {bid: item.bid})">
+							<image :src="staticUrl ? staticUrl + 'baby-list-03.png' : ''" class="pic" mode="aspectFill">
+							</image>
+							身高体重
+						</view>
+						<view class="option-item"
+							@click="toPage('/packages/baby/baby-remark', {bid: item.bid})">
+							<image :src="staticUrl ? staticUrl + 'baby-list-04.png' : ''" class="pic" mode="aspectFill">
+							</image>
+							成长备注
+						</view>
+					</view>
+				</view>
+				<view class="btn" @click="handleStep(item)">
+					<image :src="staticUrl ? staticUrl + 'right-arrow.png' : ''" class="pic" mode="heightFix"></image>
+				</view>
+			</view>
+		</view>
+		<TabBar></TabBar>
+	</view>
+</template>
+
+<script lang="ts">
+	import {
+		Component,
+		Mixins
+	} from 'vue-property-decorator';
+	import loginMixin from '@/common/mixins/loginMixin.ts';
+	import {
+		types
+	} from '@/common/store/index';
+	import {
+		namespace
+	} from 'vuex-class';
+	const baseModule = namespace('base');
+	@Component({
+		filters: {
+			ageFormat(age : any) {
+				let year = Math.floor(age / 365);
+				let month = Math.floor((age % 365) / 30);
+				let day = age % 30;
+				if (age < 30) {
+					return day + '天';
+				} else if (day < 100) {
+					return month + '个月' + (day ? (day + '天') : '')
+				} else if (day < 365) {
+					return month + '个月';
+				} else if (day < 365 * 3) {
+					return year + '年' + (month ? (month + '个月') : '')
+				} else {
+					return year + '年'
+				}
+			}
+		}
+	})
+	export default class SelectBaby extends Mixins(loginMixin) {
+		// @baseModule.Getter('_userInfo') _userInfo: any;
+		@baseModule.Mutation(types.SET_TABBARINDEX) setTabBarIndex : any;
+		staticUrl : string = this.$oss_url; 	//oss地址
+		babyList : any = [];
+		genderMap: any = {
+			1: '小王子',
+			2: '小公主'
+		};
+		shareInfo: any = {};
+
+		onShow() {
+			this.setTabBarIndex(3);
+			this.getBabyListBySelf();
+			this.getShareInfo();
+		}
+		
+		onShareAppMessage() {
+			return {
+				title: '育百通',
+				path: '/pages/front/front',
+				imageUrl: this.shareInfo.pic
+			};
+		}
+		
+		onShareTimeline() {
+			return {
+				title: '育百通', // 分享标题
+				imageUrl: this.shareInfo.pic, // 分享的图片路径,可选
+			};
+		}
+
+		getBabyListBySelf() {
+			this.$http
+				.get({
+					url: this.$api.getBabyListBySelf
+				})
+				.then((res : any) => {
+					this.babyList = res.list;
+				}, (err : any) => {
+					console.log(err);
+				});
+		}
+		
+		getShareInfo() {
+			this.$http
+				.get({
+					url: this.$api.getShareInfo
+				})
+				.then((res : any) => {
+					this.shareInfo = res;
+				}, (err : any) => {
+					console.log(err);
+				});
+		}
+
+		handleStep(item : any) {
+			this.$Router.push({
+				path: this.$Route.query.path,
+				query: {
+					bid: item.bid
+				}
+			})
+		}
+
+		toPage(path : any, data : any) {
+			this.$Router.push({
+				path: path,
+				query: data
+			})
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	page {
+		background: #f5f5f5;
+	}
+
+	.user-setting-box {
+		// background: #F5F5F5;
+		height: 100vh;
+		// @include flex-y(flex-start);
+
+		.bg {
+			width: 100%;
+			height: vw(280);
+			background: linear-gradient(180deg, rgba(222, 231, 255, 1) 0%, rgba(249, 235, 252, 1) 49.31%, rgba(248, 228, 248, 0.31) 77.08%, rgba(253, 241, 240, 0) 100%);
+			position: absolute;
+			top: 0;
+			z-index: -1;
+		}
+
+		.content {
+			width: 100%;
+			padding: 0 vw(15);
+			box-sizing: border-box;
+			@include flex-y(flex-start);
+
+			.baby-item {
+				width: 100%;
+				@include flex-x();
+				padding: vw(12) vw(18);
+				box-sizing: border-box;
+				border-radius: vw(10);
+				margin-top: vw(10);
+				background: linear-gradient(90deg, rgba(242, 251, 255, 1) 0%, rgba(255, 255, 255, 1) 64.58%, rgba(255, 255, 255, 1) 100%);
+				box-shadow: 0px 1px 5px rgba(0, 0, 0, 0.1);
+
+				.left {
+					@include flex-y(flex-start, flex-start);
+
+					.top {
+						@include flex-x();
+
+						.avatar {
+							@include wh(44, 44);
+							border-radius: vw(22);
+							margin-right: vw(10);
+						}
+
+						.info {
+							.name {
+								@include word-vw(14, #333);
+								font-weight: bold;
+							}
+
+							.age {
+								@include flex-x(flex-start);
+								@include word-vw(12, #666);
+								margin-top: vw(6);
+
+								.line {
+									width: 0;
+									height: vw(6);
+									border-right: vw(1) solid #C7C7C7;
+									margin: 0 vw(3);
+								}
+							}
+						}
+					}
+
+					.bottom {
+						@include flex-x(flex-start);
+						margin-top: vw(20);
+
+						.option-item {
+							@include flex-y();
+							@include word-vw(12, #9DB2CE);
+							margin-right: vw(12);
+
+							.pic {
+								@include wh(24, 24);
+								margin-bottom: vw(6);
+							}
+						}
+					}
+				}
+
+				.btn {
+					.pic{
+						height: vw(24);
+					}
+				}
+			}
+		}
+	}
+</style>

+ 24 - 28
src/pages/category/category.vue

@@ -32,29 +32,12 @@
 				</view>
 				<scroll-view class="right" scroll-with-animation :scroll-y="true" @scroll="handleScroll"
 					:scroll-into-view="scrollIntoView">
-					<view class="right-item" v-for="(item, index) in letterList" :key="index" :id="'letter' + index">
-						<view class="title">{{item}}</view>
+					<view class="right-item" v-for="(letter, index) in letterList" :key="index" :id="'letter' + index">
+						<view class="title">{{letter}}</view>
 						<view class="brand-list">
-							<view class="brand-item">
-								加多宝
-							</view>
-							<view class="brand-item">
-								加多宝
-							</view>
-							<view class="brand-item">
-								加多宝
-							</view>
-							<view class="brand-item">
-								加多宝
-							</view>
-							<view class="brand-item">
-								加多宝
-							</view>
-							<view class="brand-item">
-								加多宝
-							</view>
-							<view class="brand-item">
-								加多宝
+							<view class="brand-item" v-for="(item) in brandListFormat[letter]" :key="item.id">
+								<image :src="item.logo" class="logo" mode="aspectFit"></image>
+								{{item.brandName}}
 							</view>
 						</view>
 					</view>
@@ -117,11 +100,11 @@
 				value: 0,
 			},
 			{
-				name: '¥200-300',
+				name: '¥300-350',
 				value: 1,
 			},
 			{
-				name: '¥200-300',
+				name: '¥350-400',
 				value: 2,
 			}
 		];
@@ -153,6 +136,7 @@
 			"Y",
 			"Z",
 		];
+		brandListFormat:any = {};
 		letterActive : any = 0;
 		scrollIntoView : any = '';
 		intoViewScroll : any = false;
@@ -167,7 +151,7 @@
 			});
 			this.setTabBarIndex(1);
 			// this.getShareInfo();
-			// await this.getCategoryList();
+			await this.getBrandList();
 			this.$nextTick(()=> {
 				this.getLeftHeight();
 				const query = uni.createSelectorQuery().in(this);
@@ -223,16 +207,24 @@
 		// 	};
 		// }
 		//获取商品分类
-		getCategoryList() {
+		getBrandList() {
 			// uni.showLoading({
 			// 	title: '加载中',
 			// });
 			return this.$http
 				.get({
-					url: this.$api.getCategoryList
+					url: this.$api.getBrandList
 				})
 				.then((res : any) => {
-
+					let brandListFormat:any = {};
+					res.list.forEach((item: any) => {
+						if(brandListFormat[item.abc]){
+							brandListFormat[item.abc].push(item);
+						} else {
+							brandListFormat[item.abc] = [item];
+						}
+					});
+					this.brandListFormat = brandListFormat;
 				}, (err : any) => {
 					console.log(err);
 					// uni.hideLoading();
@@ -417,6 +409,10 @@
 								@include word-vw(12, #333);
 								padding-left: vw(12);
 								@include flex-x(flex-start);
+								.logo{
+									@include wh(24, 24);
+									margin-right: vw(6);
+								}
 							}
 						}
 					}

+ 649 - 0
src/pages/contrast/contrast - 副本 (4).vue

@@ -0,0 +1,649 @@
+<template>
+	<view class="user-setting-box">
+		<uni-nav-bar :status-bar="false" :shadow="false" :border="false" :fixed="true" color="#333" background-color=""
+			height="88px" leftWidth="0" rightWidth="0">
+			<view class="nav-bg">
+				<view class="status-bar"></view>
+				<view class="nav-title">
+					<view class="left">
+						<IconText style="padding: 5px;" @click.native="handleBack" color="#666" :code="`\ue709`"
+							size="16" />
+						<IconText style="padding: 5px;" @click.native="handleFront" color="#333" :code="`\ue8a0`"
+							size="18" />
+					</view>
+					<view class="title">比奶粉</view>
+					<view class="right"></view>
+				</view>
+			</view>
+		</uni-nav-bar>
+		<view class="content">
+			<!-- <view class="left-fixed">
+				<view class="info">
+					
+				</view>
+			</view> -->
+			<view class="top-goods-box">
+				<view>
+					<view class="left">
+						<view class="info"></view>
+					</view>
+					<view class="goods-list">
+						<view class="good-item" v-for="(item, index) in goodsList" :key="index">
+							<image :src="item.masterPic" class="pic" mode="aspectFill">
+							</image>
+							<view class="name">{{item.name}}</view>
+							<view class="price-box">参考价:<view class="price">¥{{item.price}}</view>
+							</view>
+						</view>
+					</view>
+				</view>
+			</view>
+			<view class="bottom-info-box">
+				<view class="left">
+					<view class="title"
+						:style="{backgroundImage: `url(${staticUrl ? staticUrl + 'title-bg.png' : ''})`}">基础概况</view>
+					<view class="table">
+						<view class="row" v-for="(item, index) in baseInfo" :key="index">
+							<view class="ceil">
+								{{item.name}}
+								<view class="hidden-box">
+									
+								</view>
+							</view>
+						</view>
+					</view>
+					<view class="title"
+						:style="{backgroundImage: `url(${staticUrl ? staticUrl + 'title-bg.png' : ''})`}">综合对比</view>
+					<view class="table">
+						<view class="row" v-for="(item, index) in comprehensiveInfo" :key="index">
+							<view class="ceil">
+								{{item.name}}
+							</view>
+						</view>
+					</view>
+					<view class="title"
+						:style="{backgroundImage: `url(${staticUrl ? staticUrl + 'title-bg.png' : ''})`}">营养成分</view>
+					<view class="table">
+						<view class="row">
+							<view class="ceil head-ceil">基础营养</view>
+						</view>
+						<view class="row" v-for="(item, index) in componentInfo1" :key="index">
+							<view class="ceil ceil2">
+								{{item.name}}
+							</view>
+						</view>
+					</view>
+					<view class="table">
+						<view class="row">
+							<view class="ceil head-ceil">基础营养</view>
+						</view>
+						<view class="row" v-for="(item, index) in componentInfo2" :key="index">
+							<view class="ceil ceil2">
+								{{item.name}}
+							</view>
+						</view>
+					</view>
+				</view>
+				<view class="right">
+					<view class="title"></view>
+					<view class="table">
+						<view class="row" v-for="(item, index) in baseInfo" :key="index">
+							<view class="ceil" v-for="(ceil, ceilIndex) in goodsList" :key="ceilIndex">
+								{{ceil[item.key] || '-'}}
+							</view>
+						</view>
+					</view>
+					<view class="title"></view>
+					<view class="table">
+						<view class="row" v-for="(item, index) in comprehensiveInfo" :key="index">
+							<view class="ceil" v-for="(ceil, ceilIndex) in goodsList" :key="ceilIndex">
+								<view v-if="item.type === 'list'">
+									<view v-if="ceil[item.key] && ceil[item.key].length" class="ceil-list">
+										<view v-for="(i,j) in ceil[item.key]" :key="j" class="ceil-list-item">
+											{{i.labelName}}
+										</view>
+									</view>
+									<view v-else>
+										-
+									</view>
+								</view>
+								<view v-else>
+									{{ceil[item.key] || '-'}}
+								</view>
+							</view>
+						</view>
+					</view>
+					<view class="title"></view>
+					<view class="table">
+						<view class="row">
+							<view class="ceil head-ceil" v-for="(ceil, ceilIndex) in goodsList" :key="ceilIndex">
+								每100g
+							</view>
+						</view>
+						<view class="row" v-for="(item, index) in componentInfo1" :key="index">
+							<view class="ceil ceil2" v-for="(ceil, ceilIndex) in goodsList" :key="ceilIndex">
+								{{item.name}}
+							</view>
+						</view>
+					</view>
+					<view class="table">
+						<view class="row">
+							<view class="ceil head-ceil" v-for="(ceil, ceilIndex) in goodsList" :key="ceilIndex">
+								每100g
+							</view>
+						</view>
+						<view class="row" v-for="(item, index) in componentInfo2" :key="index">
+							<view class="ceil ceil2" v-for="(ceil, ceilIndex) in goodsList" :key="ceilIndex">
+								{{item.name}}
+							</view>
+						</view>
+					</view>
+				</view>
+			</view>
+		</view>
+		<!-- <TabBar></TabBar> -->
+	</view>
+</template>
+
+<script lang="ts">
+	import {
+		Component,
+		Mixins
+	} from 'vue-property-decorator';
+	import loginMixin from '@/common/mixins/loginMixin.ts';
+	import {
+		types
+	} from '@/common/store/index';
+	import {
+		namespace
+	} from 'vuex-class';
+	const baseModule = namespace('base');
+	@Component({})
+	export default class SelectBaby extends Mixins(loginMixin) {
+		// @baseModule.Getter('_userInfo') _userInfo: any;
+		@baseModule.Mutation(types.SET_TABBARINDEX) setTabBarIndex : any;
+		staticUrl : string = this.$oss_url; 	//oss地址\
+		goodsList : any = []
+		baseInfo : any = [
+			{
+				name: '品牌',
+				key: 'brandName'
+			},
+			{
+				name: '产地',
+				key: 'milkOriginName'
+			},
+			{
+				name: '版本',
+				key: 'milkVersionName'
+			},
+			{
+				name: '类别',
+				key: 'milkCategoryName'
+			},
+			{
+				name: '奶源',
+				key: 'milkSourceName'
+			},
+			{
+				name: '价格',
+				key: 'price'
+			},
+			{
+				name: '段位',
+				key: 'milkStageName'
+			},
+			{
+				name: '规格',
+				key: 'milkSpecificationName'
+			},
+			{
+				name: '适用年龄',
+				key: 'milkRecommendedAgeName'
+			},
+		];
+
+		comprehensiveInfo : any = [
+			{
+				name: '优点',
+				key: 'advantageLabels',
+				type: 'list'
+			},
+			{
+				name: '常规配方',
+				key: 'normalLabels',
+				type: 'list'
+			},
+			{
+				name: '强化配方',
+				key: 'fortifyLabels',
+				type: 'list'
+			},
+			// {
+			// 	name: '注意',
+			// 	key: 'a'
+			// },
+			{
+				name: '奶源分析',
+				key: 'sourceReview'
+			},
+			{
+				name: '原料分析',
+				key: 'materialReview'
+			},
+		];
+
+		componentInfo1 : any = [
+			{
+				name: '能量(kJ)',
+				key: 'a'
+			},
+			{
+				name: '蛋白质(g)',
+				key: 'a'
+			},
+			{
+				name: '脂肪(g)',
+				key: 'a'
+			},
+			{
+				name: '亚油酸(g)',
+				key: 'a'
+			},
+			{
+				name: 'α-亚麻酸(mg)',
+				key: 'a'
+			},
+			{
+				name: '碳水化合物(g)',
+				key: 'a'
+			},
+		];
+
+		componentInfo2 : any = [
+			{
+				name: '维生素A(μgRE)',
+				key: 'a'
+			},
+			{
+				name: '维生素D(μg)',
+				key: 'a'
+			},
+			{
+				name: '维生素E(mgα-TE)',
+				key: 'a'
+			},
+			{
+				name: '牛磺酸(mg)',
+				key: 'a'
+			},
+			{
+				name: '左旋肉碱(mg)',
+				key: 'a'
+			},
+			{
+				name: 'DHA(mg)',
+				key: 'a'
+			},
+			{
+				name: 'ARA/AA(mg)',
+				key: 'a'
+			},
+			{
+				name: '低聚半乳糖(g)',
+				key: 'a'
+			},
+			{
+				name: '低聚果糖(g)',
+				key: 'a'
+			},
+			{
+				name: 'OPO(g)',
+				key: 'a'
+			},
+			{
+				name: '叶黄素(μg)',
+				key: 'a'
+			},
+			{
+				name: '核苷酸(mg)',
+				key: 'a'
+			},
+			{
+				name: '乳铁蛋白(mg)',
+				key: 'a'
+			},
+			{
+				name: 'HMO(g)',
+				key: 'a'
+			},
+		];
+		scrollLeft : any = 0;
+		scrollTop : any = 0;
+		ids : any = [];
+
+		onShow() {
+			console.log(this.$Route.query.ids)
+			this.ids = [21, 19, 20];
+			let promise = this.ids.map((item : any) => {
+				return this.getGoodDetail(item);
+			});
+			Promise.all(promise).then((res : any) => {
+				this.goodsList = res;
+			})
+		}
+
+		getGoodDetail(id : any) {
+			return this.$http
+				.get({
+					url: this.$api.getGoodInfo,
+					data: {
+						id
+					}
+				})
+				.then((res : any) => {
+					return res;
+				}, (err : any) => {
+					console.log(err);
+				});
+		}
+
+		handleBack() {
+			this.$Router.back(1);
+		}
+
+		handleFront() {
+			this.$Router.pushTab({
+				path: '/pages/front/front'
+			})
+		}
+
+		scrollInfo(e : any) {
+			console.log(e)
+			this.scrollTop = e.detail.scrollTop;
+			this.scrollLeft = e.detail.scrollLeft;
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	page {
+		background: #f5f5f5;
+	}
+
+	/deep/.uni-navbar__header {
+		padding: 0 !important;
+
+		.uni-navbar__header-container {
+			padding: 0 !important;
+		}
+	}
+
+	.user-setting-box {
+		height: 100vh;
+		@include flex-y(flex-start);
+
+		.nav-bg {
+			width: 100%;
+			background: #fff;
+			@include flex-y(flex-start);
+			background: linear-gradient(180deg, #FFD9F9 0%, #F1E6FF 67.19%, #F1E9FE 82.84%, #FBF6FC 100%);
+
+			.status-bar {
+				// height: var(--status-bar-height);
+				height: 44px;
+			}
+
+			.nav-title {
+				width: 100%;
+				box-sizing: border-box;
+				height: 40px;
+				padding: 0 vw(3);
+				@include flex-x();
+				@include word-vw(16, #000);
+
+				.left,
+				.right {
+					width: vw(60);
+					@include flex-x(flex-satrt);
+				}
+
+				.title {
+					flex: 1;
+					@include flex-x(center);
+				}
+			}
+		}
+
+		.content {
+			width: 100%;
+			height: 100%;
+			overflow: auto;
+			// padding: 0 vw(15);
+			box-sizing: border-box;
+			@include flex-y(flex-start, flex-start);
+
+			&::-webkit-scrollbar {
+				width: 0px;
+				height: 0px;
+			}
+
+			.left-fixed {
+				box-sizing: border-box;
+				position: sticky;
+				left: 0;
+				top: 0;
+				// top: 88px;
+				// left: 0;
+				z-index: 999;
+				padding-top: vw(16);
+				background: #F6F8FB;
+
+				.info {
+					width: vw(110);
+					height: vw(144);
+					border: vw(1) solid #EBEBEB;
+					background: #fff;
+					box-sizing: border-box;
+				}
+			}
+
+			// padding-bottom: vw(50);
+			.top-goods-box {
+				width: 100%;
+				height: vw(160);
+				padding-top: vw(16);
+				background: #F6F8FB;
+				@include flex-x(flex-start, flex-end);
+				box-sizing: border-box;
+				position: sticky;
+				top: 0;
+				background: #F6F8FB;
+				z-index: 100;
+
+				.left {
+					width: vw(110);
+					padding-top: 16px;
+					height: vw(160);
+					flex-shrink: 0;
+					box-sizing: border-box;
+					position: sticky;
+					left: 0;
+					top: 0;
+
+					.info {
+						width: vw(110);
+						height: vw(144);
+						background: #fff;
+						border: vw(1) solid #EBEBEB;
+						border-left-width: 0;
+						box-sizing: border-box;
+					}
+
+					// top: 104px;
+				}
+
+				.goods-list {
+					@include flex-x(flex-start);
+					padding-top: 16px;
+					background: #F6F8FB;
+					padding-left: vw(110);
+
+					.good-item {
+						width: vw(100);
+						height: vw(144);
+						border: vw(1) solid #EBEBEB;
+						border-left-width: 0;
+						box-sizing: border-box;
+						flex-shrink: 0;
+						@include flex-y(flex-start);
+						background: #fff;
+
+						.pic {
+							@include wh(64, 64);
+							margin-top: vw(16);
+							background: red;
+						}
+
+						.name {
+							@include flex-x(center);
+							text-align: center;
+							@include word-vw(10, #333);
+							margin-top: vw(5);
+							padding: 0 vw(3);
+							box-sizing: border-box;
+							font-weight: bold;
+							@include multi(2);
+						}
+
+						.price-box {
+							@include word-vw(10, #999);
+							@include flex-x(center);
+							margin-top: vw(5);
+
+							.price {
+								@include word-vw(12, #FF5733);
+							}
+						}
+					}
+				}
+			}
+
+			.title {
+				// width: vw(98);
+				background: #F6F8FB;
+				@include word-vw(14, #333);
+				font-weight: bold;
+				height: vw(35);
+				@include flex-x(flex-start);
+				background-size: auto vw(6);
+				background-position: vw(12) vw(22);
+				background-repeat: no-repeat;
+				// margin-left: vw(12);
+				padding-left: vw(18);
+				box-sizing: border-box;
+			}
+
+			.table {
+				border-bottom: vw(1) solid #EBEBEB;
+
+				.row {
+					@include flex-x(flex-start);
+					align-items: stretch;
+
+					.ceil {
+						width: vw(100);
+						min-height: vw(32);
+						// height: 100%;
+						flex: 1;
+						border-top: vw(1) solid #EBEBEB;
+						border-right: vw(1) solid #EBEBEB;
+						box-sizing: border-box;
+						@include word-vw(12, #999);
+						@include flex-x(center);
+						flex-shrink: 0;
+						background: #fff;
+
+						&.ceil2 {
+							min-height: vw(40);
+						}
+
+						&.head-ceil {
+							min-height: vw(40);
+							background: #6389FF;
+							border: vw(1) solid #618AFF;
+							box-sizing: border-box;
+							@include word-vw(12, #fff);
+						}
+						.ceil-list{
+							@include flex-y(flex-start);
+						}
+						.ceil-list-item{
+							width: vw(86);
+							background: #FFEEDE;
+							@include word-vw(12, #FF7E33);
+							border-radius: vw(5);
+							height: vw(22);
+							@include flex-x(center);
+							margin: vw(3) 0;
+						}
+					}
+				}
+			}
+
+			.bottom-info-box {
+				// width: 100vw;
+				// flex: 1;
+				// overflow: auto;
+				// padding-bottom: 80px;
+				box-sizing: border-box;
+				@include flex-x(flex-start, flex-start);
+
+				.bottom-info-scroll {
+					// width: vw(110);
+					width: 100%;
+					height: 100%;
+
+					&::-webkit-scrollbar {
+						width: 0px;
+						height: 0px;
+					}
+				}
+
+				.bottom-info-a {
+					@include flex-x(flex-start);
+				}
+
+				.left {
+					width: vw(110);
+					position: sticky;
+					left: 0;
+
+					.ceil {
+						width: vw(110);
+						@include flex-x(center);
+						.hidden-box{
+							width: 0;
+						}
+					}
+
+					.title {
+						width: vw(110);
+					}
+				}
+
+				.right {
+
+					// flex:1;
+					.ceil {
+						width: vw(100);
+					}
+
+					.title {
+						width: vw(100);
+					}
+				}
+			}
+		}
+	}
+</style>

+ 208 - 56
src/pages/contrast/contrast-list.vue

@@ -9,33 +9,35 @@
 					<image :src="staticUrl ? staticUrl + 'vs.png' : ''" class="pic" mode="heightFix"></image>
 					我的对比
 				</view>
-				<view class="empty-btn">
+				<view class="empty-btn" @click="emptyCollection">
 					清空
 				</view>
 			</view>
 			<view class="goods-list">
 				<view class="good-item" v-for="item in goodsList" :key="item.id">
 					<view class="left">
-						<IconText class="icon" :code="`\ue842`" v-if="1" size="14" color="#6B95FF">
+						<IconText class="icon" :code="`\ue842`" v-if="item.checked" size="14" color="#6B95FF"
+							@click.native="handleChange(item)">
 						</IconText>
-						<IconText class="icon" :code="`\ue84e`" size="14" color="#999" v-else></IconText>
-						<image :src="staticUrl ? staticUrl + 'vs.png' : ''" class="pic" mode="heightFix"></image>
+						<IconText class="icon" :code="`\ue84e`" size="14" color="#999" v-else
+							@click.native="handleChange(item)"></IconText>
+						<image :src="item.masterPic" class="pic" mode="aspectFill"></image>
 						<view class="info">
 							<view class="name">{{item.name}}</view>
 							<view class="price">参考价:<text>¥{{item.price}}</text></view>
 						</view>
 					</view>
 					<view class="right">
-						<view @click.stop="optionModal(item)">
-							<IconText :code="`\ue8ac`" color="#94B2FF" size="20" class="icon"></IconText>
+						<view @click.stop="optionModal(item)" class="option-btn">
+							··
 						</view>
 						<view class="option-box" v-if="optionActive === item.id">
 							<view class="arrow"></view>
-							<view class="option">
+							<view class="option" @click="topCollection(item)">
 								<IconText class="icon" :code="`\ue61e`" size="14" color="#fff"></IconText>
 								顶置
 							</view>
-							<view class="option">
+							<view class="option" @click="moveCollection(item, index)">
 								<IconText class="icon" :code="`\ue8a7`" size="14" color="#fff"></IconText>
 								删除
 							</view>
@@ -44,7 +46,7 @@
 				</view>
 			</view>
 		</view>
-		<view class="btn" @click="toContrast">开始对比(3)</view>
+		<view class="btn" @click="toContrast">开始对比({{selected.length}})</view>
 		<TabBar></TabBar>
 	</view>
 </template>
@@ -55,57 +57,181 @@
 		Mixins
 	} from 'vue-property-decorator';
 	import loginMixin from '@/common/mixins/loginMixin.ts';
-	// import {
-	// 	namespace
-	// } from 'vuex-class';
-	// const baseModule = namespace('base');
+	import {
+		types
+	} from '@/common/store/index';
+	import {
+		namespace
+	} from 'vuex-class';
+	const baseModule = namespace('base');
 	@Component({})
 	export default class SelectBaby extends Mixins(loginMixin) {
-		// @baseModule.Getter('_userInfo') _userInfo: any;
+		@baseModule.Getter('_contrastGoodId') _contrastGoodId: any;
+		@baseModule.Mutation(types.SET_TABBARINDEX) setTabBarIndex : any;
+		@baseModule.Mutation(types.SET_CONTRAST_GOOD_ID) setContrastGoodId : any;
 		staticUrl : string = this.$oss_url; 	//oss地址
-		goodsList: any = [{
-			id: 1,
-			name: '港版雀巢超启能恩1段',
-			price: 45.6
-		}, {
-			id: 2,
-			name: '港版雀巢超启能恩1段',
-			price: 45.6
-		}];
-		optionActive: any = null;
-		
+		goodsList : any = [];
+		optionActive : any = null;
+		selected : any = [];
+		shareInfo : any = {};
+
 		onShow() {
+			this.selected = [];
+			this.setTabBarIndex(1);
 			this.getGoodsList();
+			this.getShareInfo();
+		}
+
+		onShareAppMessage() {
+			return {
+				title: '育百通',
+				path: '/pages/front/front',
+				imageUrl: this.shareInfo.pic
+			};
 		}
-		
+
+		onShareTimeline() {
+			return {
+				title: '育百通', // 分享标题
+				imageUrl: this.shareInfo.pic, // 分享的图片路径,可选
+			};
+		}
+
 		getGoodsList() {
 			this.$http
 				.get({
-					url: this.$api.getFamilyList
+					url: this.$api.getGoodsList,
+					data: {
+						queryCompared: 1,
+						status: '3',
+					}
+				})
+				.then((res : any) => {
+					this.goodsList = res.list.map((item : any) => {
+						return {
+							...item,
+							checked: this._contrastGoodId.includes(item.id)
+						}
+					});
+					if(this._contrastGoodId.length){
+						this.selected = this.goodsList.filter((item : any) => {
+							return item.checked;
+						});
+					}
+				}, (err : any) => {
+					console.log(err);
+				});
+		}
+
+		getShareInfo() {
+			this.$http
+				.get({
+					url: this.$api.getShareInfo
 				})
 				.then((res : any) => {
-					this.goodsList = res.list;
+					this.shareInfo = res;
 				}, (err : any) => {
 					console.log(err);
 				});
 		}
-		
-		optionModal(item: any){
+
+		optionModal(item : any) {
 			this.optionActive = item.id;
 		}
-		
-		toContrast(item: any){
+
+		handleChange(item : any) {
+			item.checked = !item.checked;
+			this.selected = this.goodsList.filter((item : any) => {
+				return item.checked;
+			})
+		}
+
+		moveCollection(item : any, index: any) {
+			this.$http
+				.post({
+					url: this.$api.moveCollection,
+					data: {
+						types: 3,
+						rid: item.id
+					}
+				})
+				.then((res : any) => {
+					uni.showToast({
+						title: '已取消对比'
+					});
+					let arr = [...this._contrastGoodId];
+					arr.splice(index, 1);
+					this.setContrastGoodId(arr);
+					this.getGoodsList();
+				}, (err : any) => {
+					console.log(err);
+				});
+		}
+
+		topCollection(item : any) {
+			this.$http
+				.post({
+					url: this.$api.topCollection,
+					data: {
+						types: 3,
+						rid: item.id
+					}
+				})
+				.then((res : any) => {
+					// uni.showToast({
+					// 	title: '已取消对比'
+					// });
+					this.getGoodsList();
+				}, (err : any) => {
+					console.log(err);
+				});
+		}
+
+		emptyCollection() {
+			this.$http
+				.post({
+					url: this.$api.emptyCollection,
+					data: {
+						types: 3,
+					}
+				})
+				.then((res : any) => {
+					// uni.showToast({
+					// 	title: '已取消对比'
+					// });
+					this.setContrastGoodId([]);
+					this.getGoodsList();
+				}, (err : any) => {
+					console.log(err);
+				});
+		}
+
+		toContrast(item : any) {
+			if (!this.selected.length) {
+				uni.showToast({
+					title: '请选择需要对比的产品',
+					icon: 'none'
+				})
+				return;
+			};
+			// console.log(this.selected.map((item : any) => item.id) )
+			let ids = this.selected.map((item : any) => item.id);
+			this.setContrastGoodId(ids);
 			this.$Router.push({
 				path: '/pages/contrast/contrast',
+				query: { 
+					ids
+				}
 			})
 		}
 	}
 </script>
 
 <style lang="scss" scoped>
-	page{
+	page {
 		background: #f5f5f5;
 	}
+
 	.user-setting-box {
 		// background: #F5F5F5;
 		height: 100vh;
@@ -113,36 +239,40 @@
 
 		.content {
 			width: 100%;
-			padding: 0 vw(15);
+			// padding: 0 vw(15);
 			box-sizing: border-box;
 			@include flex-y(flex-start);
 			padding-bottom: vw(50);
-			
-			.top{
+
+			.top {
 				width: 100%;
 				height: vw(42);
 				@include flex-x();
 				padding: 0 vw(12);
 				box-sizing: border-box;
-				.left{
+
+				.left {
 					@include word-vw(14, #333);
-					.pic{
-						height: vw(12);
+					@include flex-x(flex-start);
+
+					.pic {
+						height: vw(16);
 						margin-right: vw(6);
 					}
 				}
-				.empty-btn{
+
+				.empty-btn {
 					@include word-vw(12, #999);
 				}
 			}
-			
-			.goods-list{
+
+			.goods-list {
 				width: 100%;
 				border-radius: vw(5);
 				// overflow: hidden;
 			}
-			
-			.good-item{
+
+			.good-item {
 				width: 100%;
 				height: vw(80);
 				@include flex-x();
@@ -151,31 +281,48 @@
 				background: #fff;
 				margin-top: vw(1);
 				@include flex-x();
-				.left{
+
+				.left {
 					@include flex-x();
-					.pic{
+
+					.pic {
 						@include wh(64, 64);
 						margin: 0 vw(10);
 					}
-					.info{
+
+					.info {
 						@include flex-y(center, flex-start);
-						.name{
+
+						.name {
 							@include word-vw(14, #333);
 							font-weight: bold;
 						}
-						.price{
+
+						.price {
 							margin-top: vw(6);
 							@include word-vw(12, #999);
-							text{
+
+							text {
 								@include word-vw(14, #FF5733);
 								font-weight: bold;
 							}
 						}
 					}
 				}
-				.right{
+
+				.right {
 					position: relative;
-					.option-box{
+
+					.option-btn {
+						@include wh(32, 18);
+						border-radius: vw(4);
+						background: #F2F2F2;
+						@include flex-x(center);
+						@include word-vw(14, #BDBDBD);
+						font-weight: bold;
+					}
+
+					.option-box {
 						width: vw(85);
 						background: #424242;
 						position: absolute;
@@ -183,18 +330,22 @@
 						right: vw(-8);
 						border-radius: vw(4);
 						z-index: 10;
-						.option{
+
+						.option {
 							width: vw(72);
 							height: vw(36);
 							@include word-vw(12, #fff);
 							@include flex-x(center);
-							.icon{
+
+							.icon {
 								margin-right: vw(10);
 							}
-							&:nth-last-of-type(1){
+
+							&:nth-last-of-type(1) {
 								border-top: vw(1) solid rgba(232, 232, 232, 0.11);
 							}
 						}
+
 						.arrow {
 							width: 0;
 							height: 0;
@@ -211,7 +362,8 @@
 				}
 			}
 		}
-		.btn{
+
+		.btn {
 			@include wh(150, 50);
 			border-radius: vw(25);
 			background: #618EFF;

File diff suppressed because it is too large
+ 628 - 184
src/pages/contrast/contrast.vue


+ 37 - 0
src/pages/front/article - 副本.vue

@@ -0,0 +1,37 @@
+<template>
+	<view class="box">
+		<Navbar :title="name" background-color="#fff" color="#333"></NavBar>
+		<!-- #ifdef APP -->
+		<web-view :src="link" :webview-styles="{top: webWTop,height: webWHeight}"></web-view>
+		<!-- #endif -->
+		<!-- #ifndef APP -->
+		<web-view :src="link"></web-view>
+		<!-- #endif -->
+	</view>
+</template>
+
+<script lang="ts">
+	import { Component, Prop, Vue } from 'vue-property-decorator';
+	let windowHeight : any = uni.getSystemInfoSync().windowHeight;
+	let statusBarHeight : any = uni.getSystemInfoSync().statusBarHeight;
+	let top = statusBarHeight + uni.upx2px(88);// 根据自身情况 计算。uni.upx2px(88) 是标题栏高度
+	let height = windowHeight;// 根据自身情况 计算。uni.upx2px(115) 是底部导航栏高度
+	@Component({})
+	export default class Article extends Vue {
+		link : string = '';
+		webWTop : any = top;//底部导航切换TabBar页面,沉浸式状态栏,没有标题栏,所示为0.
+		webWHeight : any = height;
+		onLoad(opt : any) {
+			this.link = decodeURIComponent(opt.link);
+		}
+	}
+</script>
+
+<style>
+	/* #ifdef APP */
+	.box {
+		padding-top: vw(80);
+	}
+
+	/* #endif */
+</style>

+ 220 - 27
src/pages/front/article.vue

@@ -1,37 +1,230 @@
 <template>
-	<view class="box">
-		<Navbar :title="name" background-color="#fff" color="#333"></NavBar>
-		<!-- #ifdef APP -->
-		<web-view :src="link" :webview-styles="{top: webWTop,height: webWHeight}"></web-view>
-		<!-- #endif -->
-		<!-- #ifndef APP -->
-		<web-view :src="link"></web-view>
-		<!-- #endif -->
+	<view class="classroom-box">
+		<Navbar title="文章详情" background-color="#fff" color="#333"></NavBar>
+		<view class="container">
+			<view class="title">{{info.articleTitle}}</view>
+			<view class="date">{{info.created}}</view>
+			<!-- <view class="text" v-html="info.content"></view> -->
+			<u-parse :content="info.content" @preview="preview" />
+		</view>
+		<view class="btn-box">
+			<view class="item" @click="toBrand">
+				<image :src="staticUrl ? staticUrl + 'hot-brand-btn.png' : ''" class="pic" mode="heightFix"></image>
+			</view>
+			<view class="item" @click="moveCollection" v-if="info.isCollect">
+				<image :src="staticUrl ? staticUrl + 'collect-btn-c.png' : ''" class="pic" mode="heightFix"></image>
+			</view>
+			<view class="item" @click="addCollection" v-else>
+				<image :src="staticUrl ? staticUrl + 'collect-btn.png' : ''" class="pic" mode="heightFix"></image>
+			</view>
+			<view class="item">
+				<button open-type="share" class="share-btn">
+					<image :src="staticUrl ? staticUrl + 'share-btn.png' : ''" class="pic" mode="heightFix">
+				</button>
+			</view>
+		</view>
 	</view>
 </template>
 
-<script lang="ts">
-	import { Component, Prop, Vue } from 'vue-property-decorator';
-	let windowHeight : any = uni.getSystemInfoSync().windowHeight;
-	let statusBarHeight : any = uni.getSystemInfoSync().statusBarHeight;
-	let top = statusBarHeight + uni.upx2px(88);// 根据自身情况 计算。uni.upx2px(88) 是标题栏高度
-	let height = windowHeight;// 根据自身情况 计算。uni.upx2px(115) 是底部导航栏高度
-	@Component({})
-	export default class Article extends Vue {
-		link : string = '';
-		webWTop : any = top;//底部导航切换TabBar页面,沉浸式状态栏,没有标题栏,所示为0.
-		webWHeight : any = height;
-		onLoad(opt : any) {
-			this.link = decodeURIComponent(opt.link);
+<script lang='ts'>
+	import uParse from '@/components/gaoyia-parse/parse.vue'
+	import {
+		Component,
+		Vue
+	} from 'vue-property-decorator';
+	@Component({
+		components: {
+			uParse
+		},
+		filters: {
+			moneyFormat(val: any) {
+				if (!+val) return '0.00';
+				return (+val).toFixed(2);
+			}
+		}
+	})
+	export default class Classroom extends Vue {
+		info: any = '';
+		staticUrl: string = this.$oss_url; //oss地址
+		shareInfo: any = {};
+
+		onShow() {
+			this.getClassroomInfo();
+			this.getShareInfo();
+		}
+
+		onShareAppMessage() {
+			return {
+				title: '育百通',
+				// path: '/pages/front/front',
+				imageUrl: this.shareInfo.pic,
+				// title: this.info.name,
+				path: '/pages/front/front?type=good&path=/pages/front/article&data=' + JSON.stringify({
+					id: this.info.id
+				}),
+			};
+		}
+
+		onShareTimeline() {
+			return {
+				title: '育百通', // 分享标题
+				imageUrl: this.shareInfo.pic, // 分享的图片路径,可选
+			};
+		}
+
+		preview(src: any, e: any) {
+			// do something
+		}
+		navigate(href: any, e: any) {
+			// console.log(href, 123);
+			// do something
+			this.$Router.push({
+				path: '/pages/front/article',
+				query: {
+					link: href
+				}
+			})
+		}
+
+		getShareInfo() {
+			this.$http
+				.get({
+					url: this.$api.getShareInfo
+				})
+				.then((res: any) => {
+					this.shareInfo = res;
+				}, (err: any) => {
+					console.log(err);
+				});
+		}
+
+		getClassroomInfo() {
+			this.$http
+				.get({
+					url: this.$api.getArticleInfo,
+					data: {
+						id: this.$Route.query.id
+					}
+				})
+				.then((res: any) => {
+					this.info = res;
+				}, (err: any) => {
+					console.log(err);
+				});
+		}
+
+		addCollection() {
+			this.$http
+				.post({
+					url: this.$api.addCollection,
+					data: {
+						types: 2,
+						rid: this.info.id
+					}
+				})
+				.then((res: any) => {
+					uni.showToast({
+						title: '已加入收藏'
+					})
+					this.getClassroomInfo();
+				}, (err: any) => {
+					console.log(err);
+				});
+		}
+
+		moveCollection() {
+			this.$http
+				.post({
+					url: this.$api.moveCollection,
+					data: {
+						types: 2,
+						rid: this.info.id
+					}
+				})
+				.then((res: any) => {
+					uni.showToast({
+						title: '已取消收藏'
+					})
+					this.getClassroomInfo();
+				}, (err: any) => {
+					console.log(err);
+				});
+		}
+		
+		toBrand(){
+			this.$Router.push({
+				path: '/packages/goods/brand-list',
+			})
 		}
 	}
 </script>
-
-<style>
-	/* #ifdef APP */
-	.box {
-		padding-top: vw(80);
+<style lang='scss'>
+	.video {
+		@include flex-y(center);
 	}
+</style>
+<style lang='scss' scoped>
+	page {
+		background: #fff;
+	}
+
+	.classroom-box {
+		min-height: 100vh;
+		@include flex-y();
+		background: #fff;
+
+		.container {
+			flex: 1;
+			width: 100%;
+			box-sizing: border-box;
+			overflow-y: auto;
+			padding: 0 vw(18);
 
-	/* #endif */
+			.title {
+				@include word-vw(24, #333);
+				margin-top: vw(30);
+				font-weight: 550;
+			}
+
+			.date {
+				@include word-vw(12, #999);
+				margin-top: vw(24);
+			}
+
+			.text {
+				margin-top: vw(24);
+			}
+		}
+
+		.btn-box {
+			width: vw(32);
+			border-radius: vw(32);
+			background: #fff;
+			position: fixed;
+			bottom: vw(30);
+			right: vw(10);
+			box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.12);
+			@include flex-y(center);
+			padding: vw(5) 0;
+			
+			.item{
+				height: vw(36);
+				@include flex-y(center);
+			}
+
+			.pic {
+				@include wh(20, 20);
+				margin: vw(5) 0;
+			}
+			.share-btn{
+				width: auto;
+				height: 100%;
+				background: transparent;
+				padding: 0;
+				&::after {
+					border-width: 0;
+				}
+			}
+		}
+	}
 </style>

+ 405 - 136
src/pages/front/front.vue

@@ -18,7 +18,8 @@
 					</view>
 				</view>
 				<view class="nav-list">
-					<view class="nav-item" :class="{active: navActive === index}" v-for="(item, index) in navList" :key="index" @click="changeNavActive(index)">
+					<view class="nav-item" :class="{active: navActive === index}" v-for="(item, index) in navList"
+						:key="index" @click="changeNavActive(index)">
 						{{item.name}}
 						<view class="bar"></view>
 					</view>
@@ -37,7 +38,8 @@
 					</view>
 				</view>
 				<view class="nav-list">
-					<view class="nav-item" :class="{active: navActive === index}" v-for="(item, index) in navList" :key="index" @click="changeNavActive(index)">
+					<view class="nav-item" :class="{active: navActive === index}" v-for="(item, index) in navList"
+						:key="index" @click="changeNavActive(index)">
 						{{item.name}}
 						<view class="bar"></view>
 					</view>
@@ -55,13 +57,15 @@
 								@changeSwiper="changeRecommendSwiper">
 							</SwiperBanner1>
 						</view>
-						<view class="category-swiper-box">
-							<swiper class="category-swiper">
+						<view class="category-swiper-box" :class="{more: categoryList && categoryList.length > 5}">
+							<swiper class="category-swiper" :indicator-dots="true" indicator-color="#ffffff"
+								indicator-active-color="#6B95FF">
 								<swiper-item v-for="(item, index) in categoryFormatList" :key="index">
 									<view class="category-box">
-										<view class="category-item" v-for="categoryItem in item" :key="categoryItem.id">
+										<view class="category-item" v-for="categoryItem in item" :key="categoryItem.id"
+											@click="handleCategoryItem(categoryItem)">
 											<image :src="categoryItem.pic" class="pic" mode="aspectFit"></image>
-											{{categoryItem.name}}
+											{{categoryItem.labelName}}
 										</view>
 									</view>
 								</swiper-item>
@@ -69,27 +73,30 @@
 						</view>
 						<view class="title-box">
 							<view class="left">
-								<image :src="staticUrl ? staticUrl + 'front-01.png' : ''" class="pic" mode="heightFix"></image>
+								<image :src="staticUrl ? staticUrl + 'front-01.png' : ''" class="pic" mode="heightFix">
+								</image>
 								热门品牌
 							</view>
-							<view class="more-btn">查看更多 &gt;</view>
+							<view class="more-btn" @click="toPage('/packages/goods/brand-list')">查看更多 &gt;</view>
 						</view>
 						<scroll-view class="brand-box" :scroll-x="true">
 							<view class="brand-list">
-								<view class="brand-item" v-for="item in brandList" :key="item.id">
-									<image :src="item.pic" class="pic" mode="aspectFit"></image>
-									{{item.name}}
+								<view class="brand-item" v-for="item in brandList" :key="item.id"
+									@click="toPage('/packages/goods/brand-detail', { id: item.id })">
+									<image :src="item.logo" class="pic" mode="aspectFit"></image>
+									{{item.brandName}}
 								</view>
 							</view>
 						</scroll-view>
 						<view class="title-box">
 							<view class="left">
-								<image :src="staticUrl ? staticUrl + 'front-02.png' : ''" class="pic" mode="heightFix"></image>
+								<image :src="staticUrl ? staticUrl + 'front-02.png' : ''" class="pic" mode="heightFix">
+								</image>
 								热门产品
 							</view>
-							<view class="more-btn">查看更多 &gt;</view>
+							<view class="more-btn" @click="toPage('/packages/goods/filter')">查看更多 &gt;</view>
 						</view>
-						<view class="goods-box">
+						<view class="goods-box" v-if="goodShow">
 							<!-- <view class="good-item" v-for="good in goodsList" :key="good.id">
 								<view class="good-name">{{good.name}}</view>
 								<view class="good-info-box">
@@ -115,15 +122,17 @@
 								</view>
 								<view class="btn">+ 加入对比</view>
 							</view> -->
-							<GoodItem v-for="(good, index) in goodsList" :good="good" :key="index" style="width: 100%"></GoodItem>
+							<GoodItem v-for="(good, index) in goodsList" :good="good" :key="index" style="width: 100%">
+							</GoodItem>
 						</view>
 						<view class="article-list-box">
 							<view class="title-box">
 								<view class="left">
-									<image :src="staticUrl ? staticUrl + 'front-03.png' : ''" class="pic" mode="heightFix"></image>
+									<image :src="staticUrl ? staticUrl + 'front-03.png' : ''" class="pic"
+										mode="heightFix"></image>
 									最新文章
 								</view>
-								<view class="more-btn">查看更多 &gt;</view>
+								<!-- <view class="more-btn">查看更多 &gt;</view> -->
 							</view>
 							<view class="article-list">
 								<!-- <view class="article-item" v-for="item in articleList" :key="item.id">
@@ -141,7 +150,8 @@
 										<view class="date">6小时前</view>
 									</view>
 								</view> -->
-								<ArticleItem v-for="(article, index) in articleList" :article="article" :key="index" style="width: 100%"></ArticleItem>
+								<ArticleItem v-for="(article, index) in recommendArticleList" :article="article"
+									:key="index" style="width: 100%"></ArticleItem>
 							</view>
 						</view>
 					</view>
@@ -151,13 +161,14 @@
 				<scroll-view class="swiper-item" :scroll-y="true" @scrolltolower="loadEvaluatingArticle">
 					<view class="evaluating-box">
 						<view class="banner-box">
-							<SwiperBanner1 class="banner" :bannerDetail="bannerList" indicatorColor="#7698FF"
+							<SwiperBanner1 class="banner" :bannerDetail="evaluatingBannerList" indicatorColor="#7698FF"
 								:bannerH="150" imgKey="pic" previousNext="0rpx" :imgWidth="355" radius="10"
 								@changeSwiper="changeRecommendSwiper">
 							</SwiperBanner1>
 						</view>
 						<view class="article-list">
-							<ArticleItem v-for="(article, index) in articleList" :article="article" :key="index" style="width: 100%"></ArticleItem>
+							<ArticleItem v-for="(article, index) in evaluatingArticleList" :article="article"
+								:key="index" style="width: 100%"></ArticleItem>
 						</view>
 					</view>
 				</scroll-view>
@@ -166,13 +177,14 @@
 				<scroll-view class="swiper-item" :scroll-y="true" @scrolltolower="loadInformationArticle">
 					<view class="information-box">
 						<view class="banner-box">
-							<SwiperBanner1 class="banner" :bannerDetail="bannerList" indicatorColor="#7698FF"
+							<SwiperBanner1 class="banner" :bannerDetail="informationBannerList" indicatorColor="#7698FF"
 								:bannerH="150" imgKey="pic" previousNext="0rpx" :imgWidth="355" radius="10"
 								@changeSwiper="changeRecommendSwiper">
 							</SwiperBanner1>
 						</view>
 						<view class="article-list">
-							<ArticleItem v-for="(article, index) in articleList" :article="article" :key="index" style="width: 100%"></ArticleItem>
+							<ArticleItem v-for="(article, index) in informationArticleList" :article="article"
+								:key="index" style="width: 100%"></ArticleItem>
 						</view>
 					</view>
 				</scroll-view>
@@ -181,13 +193,14 @@
 				<scroll-view class="swiper-item" :scroll-y="true" @scrolltolower="loadKnowArticle">
 					<view class="know-box">
 						<view class="banner-box">
-							<SwiperBanner1 class="banner" :bannerDetail="bannerList" indicatorColor="#7698FF"
+							<SwiperBanner1 class="banner" :bannerDetail="knowBannerList" indicatorColor="#7698FF"
 								:bannerH="150" imgKey="pic" previousNext="0rpx" :imgWidth="355" radius="10"
 								@changeSwiper="changeRecommendSwiper">
 							</SwiperBanner1>
 						</view>
 						<view class="article-list">
-							<ArticleItem v-for="(article, index) in articleList" :article="article" :key="index" style="width: 100%"></ArticleItem>
+							<ArticleItem v-for="(article, index) in knowArticleList" :article="article" :key="index"
+								style="width: 100%"></ArticleItem>
 						</view>
 					</view>
 				</scroll-view>
@@ -216,6 +229,7 @@
 	@Component({})
 	export default class Front extends Mixins(loginMixin) {
 		@baseModule.Mutation(types.SET_TABBARINDEX) setTabBarIndex : any;
+		@baseModule.Mutation(types.SET_REFERRERID) setReferrerId : any;
 		bannerList : any = [];					//轮播图列表
 		staticUrl : string = this.$oss_url; 	//oss地址
 		categoryList : any = [];				//分类列表
@@ -231,8 +245,8 @@
 		articleList : any = [];					//文章列表
 		brandList : any = [];					//品牌列表
 		shareInfo : any = {};					//分享信息
-		navActive: any = 0;
-		navList: any = [
+		navActive : any = 0;
+		navList : any = [
 			{
 				name: '推荐',
 			},
@@ -246,29 +260,34 @@
 				name: '奶粉知道',
 			}
 		];
-		recommendCurrent: any = 1;
-		recommendFinish: any = false;
-		recommendLoading: any = false;
-		evaluatingCurrent: any = 1;
-		evaluatingFinish: any = false;
-		evaluatingLoading: any = false;
-		informationCurrent: any = 1;
-		informationFinish: any = false;
-		informationLoading: any = false;
-		knowCurrent: any = 1;
-		knowFinish: any = false;
-		knowLoading: any = false;
-		
+		recommendCurrent : any = 1;
+		recommendFinish : any = false;
+		recommendLoading : any = false;
+		recommendArticleList : any = [];
+		evaluatingCurrent : any = 1;
+		evaluatingFinish : any = false;
+		evaluatingLoading : any = false;
+		evaluatingArticleList : any = [];
+		evaluatingBannerList : any = [];
+		informationCurrent : any = 1;
+		informationFinish : any = false;
+		informationLoading : any = false;
+		informationArticleList : any = [];
+		informationBannerList : any = [];
+		knowCurrent : any = 1;
+		knowFinish : any = false;
+		knowLoading : any = false;
+		knowArticleList : any = [];
+		knowBannerList : any = [];
+		timeStamp : any = +new Date();
+		goodShow: any = true;
+
 		async onPullDownRefresh() {
 			// console.log('下拉');
-			// this.getBannerList();
-			// this.getCategoryList();
-			// this.getBrandList();
-			// this.getGoodsList();
-			this.current = 1;
-			this.articleList = [];
-			// this.getArticleList();
-			// this.getShareInfo();
+			this.getCategoryList();
+			this.getHotBrandList();
+			this.getGoodsList();
+			this.getShareInfo();
 			uni.stopPullDownRefresh();
 		}
 		// onReachBottom() {
@@ -281,15 +300,11 @@
 			// @ts-ignore
 			this.$Router.forceGuardEach();
 			// #endif
-			// this.getSuperior(opt);
-			// this.getBannerList();
-			// this.getCategoryList();
-			// this.getBrandList();
-			// this.getGoodsList();
-			this.current = 1;
-			this.articleList = [];
-			// this.getArticleList();
-			// this.getShareInfo();
+			this.getSuperior(opt);
+			this.getCategoryList();
+			this.getHotBrandList();
+			this.initList();
+			this.getShareInfo();
 			// #ifdef MP-WEIXIN
 			this.$nextTick(() => {
 				this.checkPrivacySetting();
@@ -299,33 +314,60 @@
 
 		onShow() {
 			this.setTabBarIndex(0);
+			this.getGoodsList();
 			this.$nextTick(() => {
 				uni.hideTabBar();
 			});
 		}
 
 		getSuperior(opt : any) {
+			// console.log(decodeURIComponent(opt.scene))
 			if (opt.scene) {
-				let sceneArr = decodeURIComponent(opt.scene).split('&');
-				let scene : any = {};
-				sceneArr.forEach((item : any) => {
-					let arr = item.split('=');
-					if (arr[0]) scene[arr[0]] = arr[1];
-				});
+				// let sceneArr = decodeURIComponent(opt.scene).split('&');
+				// let scene : any = {};
+				// sceneArr.forEach((item : any) => {
+				// 	let arr = item.split('=');
+				// 	if (arr[0]) scene[arr[0]] = arr[1];
+				// });
+				let arr = decodeURIComponent(opt.scene).split(',');
+				if (arr[0] === 'family') {
+					if (this._token) {
+						this.entranceFamily(arr[1]);
+						this.setReferrerId('');
+						uni.setStorageSync('referrerId', '');
+					} else {
+						this.setReferrerId(arr[1]);
+						uni.setStorageSync('referrerId', arr[1]);
+					}
+				}
 			}
-			if (opt.s === '1' && opt.uid) {
-				// console.log(opt);
-				uni.setStorageSync('referrerId', opt.uid);
+			if (opt.path) {
+				this.$Router.push({
+					path: opt.path,
+					query: opt.data && JSON.parse(opt.data)
+				})
 			}
+			// if (opt.s === '1' && opt.uid) {
+			// 	// console.log(opt);
+			// 	uni.setStorageSync('referrerId', opt.uid);
+			// }
 		}
+
 		onShareAppMessage() {
 			return {
 				title: '育百通',
-				path: '/pages/front/front?s=1&uid=' + this._userInfo.uid,
+				path: '/pages/front/front',
 				imageUrl: this.shareInfo.pic
 			};
 		}
 
+		onShareTimeline() {
+			return {
+				title: '育百通', // 分享标题
+				imageUrl: this.shareInfo.pic, // 分享的图片路径,可选
+			};
+		}
+
 		checkPrivacySetting() {
 			// @ts-ignore
 			wx.getPrivacySetting({
@@ -358,6 +400,29 @@
 			})
 		}
 
+		initList() {
+			this.recommendArticleList = [];
+			this.recommendCurrent = 1;
+			this.recommendFinish = false;
+			this.getRecommendArticleList();
+			this.getBannerList();
+			this.evaluatingArticleList = [];
+			this.evaluatingCurrent = 1;
+			this.evaluatingFinish = false;
+			this.getEvaluatingArticleList();
+			this.getEvaluatingBannerList();
+			this.informationArticleList = [];
+			this.informationCurrent = 1;
+			this.informationFinish = false;
+			this.getInformationArticleList();
+			this.getInformationBannerList();
+			this.knowArticleList = [];
+			this.knowCurrent = 1;
+			this.knowFinish = false;
+			this.getKnowArticleList();
+			this.getKnowBannerList();
+		}
+
 		getShareInfo() {
 			this.$http
 				.get({
@@ -383,12 +448,12 @@
 				}
 			})
 		}
-		
-		changeNavActive(index: any){
+
+		changeNavActive(index : any) {
 			this.navActive = index;
 		}
-		
-		changeSwiper(e: any){
+
+		changeSwiper(e : any) {
 			// console.log(e.detail);
 			this.navActive = e.detail.current;
 		}
@@ -407,6 +472,7 @@
 		}
 
 		changeRecommendSwiper(val : any) {
+			console.log(val)
 			if (val.way === 1) {
 				this.$Router.push({
 					path: '/packages/goods/good-detail',
@@ -414,11 +480,11 @@
 						id: val.link
 					}
 				});
-			} else if (val.way === 2) {
+			} else if (val.way === 3) {
 				this.$Router.push({
-					path: '/pages/front/article',
+					path: '/packages/goods/brand-detail',
 					query: {
-						link: val.link
+						id: val.link
 					}
 				})
 			}
@@ -432,14 +498,20 @@
 			// });
 			return this.$http
 				.get({
-					url: this.$api.getCategoryList
+					url: this.$api.getRecommendLabel
 				})
 				.then((res : any) => {
-					this.categoryList = res.list;
-					let length = Math.ceil(res.list.length / this.categorySize);
+					this.categoryList = [...res.list,
+					{
+						labelName: '全部',
+						id: 0,
+						fid: 0,
+						pic: this.staticUrl + 'all-category.png'
+					}];
+					let length = Math.ceil(this.categoryList.length / this.categorySize);
 					let categoryFormatList = Array.from({ length });
 					this.categoryFormatList = categoryFormatList.map((item : any, index : any) => {
-						return res.list.slice(index * this.categorySize, (index + 1) * this.categorySize);
+						return this.categoryList.slice(index * this.categorySize, (index + 1) * this.categorySize);
 					});
 					// uni.hideLoading();
 				}, (err : any) => {
@@ -448,15 +520,27 @@
 				});
 		}
 
+		handleCategoryItem(item : any) {
+			// console.log(item)
+			this.$Router.push({
+				path: '/packages/goods/filter',
+				query: {
+					fid: item.fid || '',
+					id: item.id || '',
+					name: item.firstDataName || ''
+				}
+			})
+		}
+
 		//获取品牌分类
-		getBrandList() {
+		getHotBrandList() {
 			this.categoryList = [];
 			// uni.showLoading({
 			// 	title: '加载中',
 			// });
 			return this.$http
 				.get({
-					url: this.$api.getCategoryList
+					url: this.$api.getHotBrandList
 				})
 				.then((res : any) => {
 					this.brandList = res.list;
@@ -470,6 +554,7 @@
 		//获取商品列表
 		getGoodsList() {
 			this.loading = true;
+			this.goodShow = false;
 			// uni.showLoading({
 			// 	title: '加载中',
 			// });
@@ -477,13 +562,16 @@
 				.get({
 					url: this.$api.getGoodsList,
 					data: {
-						size: 4,
+						size: 999,
 						page: 1,
 						status: '3',
+						isHot: 1,
 					}
 				})
 				.then((res : any) => {
 					this.goodsList = res.list;
+					this.goodShow = true;
+					this.timeStamp = +new Date();
 					// uni.hideLoading();
 					return res.list;
 				}, (err : any) => {
@@ -496,7 +584,7 @@
 			this.loading = true;
 			this.$http
 				.get({
-					url: this.$api.getGoodsList,
+					url: this.$api.getArticleList,
 					data: {
 						page: this.current,
 						size: this.size
@@ -513,33 +601,170 @@
 					console.log(err);
 				});
 		}
-		
-		loadRecommendArticle(){
+
+		getRecommendArticleList() {
+			this.recommendLoading = true;
+			this.$http
+				.get({
+					url: this.$api.getArticleList,
+					data: {
+						page: this.recommendCurrent,
+						size: this.size,
+						articleTypeStr: '1,3'
+					}
+				})
+				.then((res : any) => {
+					this.recommendArticleList = [...this.recommendArticleList, ...res.list];
+					this.recommendLoading = false;
+					if (res.list.length < this.size) {
+						this.recommendFinish = true;
+					}
+				}, (err : any) => {
+					this.recommendFinish = true;
+					console.log(err);
+				});
+		}
+
+		loadRecommendArticle() {
 			console.log("loadRecommendArticle")
 			if (this.recommendFinish || this.recommendLoading) return;
 			this.recommendCurrent++;
-			this.getArticleList();
+			this.getRecommendArticleList();
 		}
-		
-		loadEvaluatingArticle(){
+
+		getEvaluatingBannerList() {
+			return this.$http
+				.get({
+					url: this.$api.getPlatformBannerList,
+					data: {
+						bannerType: 1
+					}
+				})
+				.then((res : any) => {
+					this.evaluatingBannerList = res.list;
+				}, (err : any) => {
+					console.log(err);
+				});
+		}
+
+		getEvaluatingArticleList() {
+			this.evaluatingLoading = true;
+			this.$http
+				.get({
+					url: this.$api.getArticleList,
+					data: {
+						page: this.evaluatingCurrent,
+						size: this.size,
+						articleType: 1
+					}
+				})
+				.then((res : any) => {
+					this.evaluatingArticleList = [...this.evaluatingArticleList, ...res.list];
+					this.evaluatingLoading = false;
+					if (res.list.length < this.size) {
+						this.evaluatingFinish = true;
+					}
+				}, (err : any) => {
+					this.evaluatingFinish = true;
+					console.log(err);
+				});
+		}
+
+		loadEvaluatingArticle() {
 			console.log("loadEvaluatingArticle")
 			if (this.evaluatingFinish || this.evaluatingLoading) return;
 			this.evaluatingCurrent++;
-			this.getArticleList();
+			this.getEvaluatingArticleList();
+		}
+
+		getInformationBannerList() {
+			return this.$http
+				.get({
+					url: this.$api.getPlatformBannerList,
+					data: {
+						bannerType: 2
+					}
+				})
+				.then((res : any) => {
+					this.informationBannerList = res.list;
+				}, (err : any) => {
+					console.log(err);
+				});
 		}
-		
-		loadInformationArticle(){
+
+		getInformationArticleList() {
+			this.informationLoading = true;
+			this.$http
+				.get({
+					url: this.$api.getArticleList,
+					data: {
+						page: this.informationCurrent,
+						size: this.size,
+						articleType: 2
+					}
+				})
+				.then((res : any) => {
+					this.informationArticleList = [...this.informationArticleList, ...res.list];
+					this.informationLoading = false;
+					if (res.list.length < this.size) {
+						this.informationFinish = true;
+					}
+				}, (err : any) => {
+					this.informationFinish = true;
+					console.log(err);
+				});
+		}
+
+		loadInformationArticle() {
 			console.log("loadInformationArticle")
 			if (this.informationFinish || this.informationLoading) return;
 			this.informationCurrent++;
-			this.getArticleList();
+			this.getInformationArticleList();
 		}
-		
-		loadKnowArticle(){
+
+		getKnowBannerList() {
+			return this.$http
+				.get({
+					url: this.$api.getPlatformBannerList,
+					data: {
+						bannerType: 3
+					}
+				})
+				.then((res : any) => {
+					this.knowBannerList = res.list;
+				}, (err : any) => {
+					console.log(err);
+				});
+		}
+
+		getKnowArticleList() {
+			this.knowLoading = true;
+			this.$http
+				.get({
+					url: this.$api.getArticleList,
+					data: {
+						page: this.knowCurrent,
+						size: this.size,
+						articleType: 3
+					}
+				})
+				.then((res : any) => {
+					this.knowArticleList = [...this.knowArticleList, ...res.list];
+					this.knowLoading = false;
+					if (res.list.length < this.size) {
+						this.knowFinish = true;
+					}
+				}, (err : any) => {
+					this.knowFinish = true;
+					console.log(err);
+				});
+		}
+
+		loadKnowArticle() {
 			console.log("loadKnowArticle")
 			if (this.knowFinish || this.knowLoading) return;
 			this.knowCurrent++;
-			this.getArticleList();
+			this.getKnowArticleList();
 		}
 
 		toArticle(link : any) {
@@ -551,7 +776,7 @@
 			})
 		}
 
-		toPage(path : any) {
+		toPage(path : any, data : any = {}) {
 			if (!path) {
 				uni.showToast({
 					title: '敬请期待',
@@ -560,7 +785,8 @@
 				return;
 			}
 			this.$Router.push({
-				path: path
+				path: path,
+				query: data
 			})
 		}
 
@@ -578,6 +804,21 @@
 				});
 			})
 		}
+
+		entranceFamily(fid : any) {
+			this.$http
+				.post({
+					url: this.$api.entranceFamily,
+					data: {
+						fid: +fid
+					}
+				})
+				.then((res : any) => {
+
+				}, (err : any) => {
+					console.log(err);
+				});
+		}
 	}
 </script>
 <style lang="scss" scoped>
@@ -588,9 +829,10 @@
 
 	.nav-bg {
 		width: 100%;
-		background: linear-gradient(180deg, rgba(255, 217, 249, 1) 0%, rgba(241, 230, 255, 1) 67.19%, rgba(241, 233, 254, 1) 82.84%, rgba(251, 246, 252, 1) 100%);;
-		
-		&.dy{
+		background: linear-gradient(180deg, rgba(255, 217, 249, 1) 0%, rgba(241, 230, 255, 1) 67.19%, rgba(241, 233, 254, 1) 82.84%, rgba(251, 246, 252, 1) 100%);
+		;
+
+		&.dy {
 			background: #fff;
 		}
 
@@ -603,7 +845,8 @@
 			height: 40px;
 			padding: 0 vw(18);
 			@include flex-x(flex-start);
-			.pic{
+
+			.pic {
 				height: vw(28);
 			}
 		}
@@ -614,8 +857,8 @@
 			height: 36px;
 			padding: 0 vw(10);
 			box-sizing: border-box;
-			
-			&.dy{
+
+			&.dy {
 				height: 40px;
 			}
 
@@ -628,8 +871,8 @@
 				padding-left: vw(12);
 				padding-right: vw(4);
 				box-sizing: border-box;
-				
-				&.dy{
+
+				&.dy {
 					border: vw(1) solid #DEDEDE;
 					background: #F2F2F2;
 				}
@@ -637,7 +880,8 @@
 				.left {
 					@include word-vw(14, #C2C2C2);
 					@include flex-x(flex-start);
-					.icon{
+
+					.icon {
 						margin-right: vw(8);
 					}
 				}
@@ -651,19 +895,23 @@
 				}
 			}
 		}
-		.nav-list{
+
+		.nav-list {
 			height: vw(36);
 			@include flex-x(flex-start);
 			padding: 0 vw(12);
 			box-sizing: border-box;
-			.nav-item{
+
+			.nav-item {
 				padding: 0 vw(12);
 				@include flex-y(center, center);
 				position: relative;
 				@include word-vw(14, #2E2E2E);
-				&.active{
+
+				&.active {
 					font-weight: bold;
-					.bar{
+
+					.bar {
 						height: vw(3);
 						border-radius: vw(2);
 						width: vw(18);
@@ -707,10 +955,11 @@
 			@include flex-x();
 			@include word-vw(14, #333);
 			flex-shrink: 0;
-			
-			.left{
+
+			.left {
 				@include flex-x(flex-start);
-				.pic{
+
+				.pic {
 					height: vw(20);
 					margin-right: vw(6);
 				}
@@ -727,23 +976,28 @@
 
 		.category-swiper-box {
 			width: vw(355);
-			height: vw(160);
+			height: vw(100);
 			margin-top: vw(5);
+			
+			&.more{
+				height: vw(170);
+			}
 
 			.category-swiper {
 				width: 100%;
 				height: 100%;
+				// padding-bottom: vw(12);
 			}
 		}
 
 		.category-box {
 			width: 100%;
-			height: vw(160);
+			height: vw(180);
 			border-radius: vw(10);
 			background: #fff;
 			@include flex-x(flex-start, flex-start);
 			flex-wrap: wrap;
-			padding: vw(10) vw(5);
+			padding: vw(10) vw(5) vw(30);
 			box-sizing: border-box;
 
 			.category-item {
@@ -880,7 +1134,7 @@
 
 			.article-list {
 				width: 100%;
-				padding: 0 vw(15);
+				padding: 0 vw(15) vw(15);
 				box-sizing: border-box;
 				margin-top: vw(6);
 
@@ -894,10 +1148,12 @@
 
 					.article-info {
 						@include flex-x();
-						.pic{
+
+						.pic {
 							@include wh(104, 65);
 						}
-						.article-name{
+
+						.article-name {
 							flex: 1;
 							height: vw(65);
 							margin-left: vw(10);
@@ -910,18 +1166,22 @@
 					.article-bottom {
 						@include flex-x();
 						margin-top: vw(5);
-						.left{
+
+						.left {
 							@include word-vw(10, #333);
 							@include flex-x(flex-start);
-							view{
+
+							view {
 								margin-right: vw(8);
-								text{
+
+								text {
 									@include word-vw(12, #FF7E33);
 									margin-right: vw(1);
 								}
 							}
 						}
-						.date{
+
+						.date {
 							@include word-vw(10, #999);
 						}
 					}
@@ -929,46 +1189,55 @@
 			}
 		}
 	}
-	
-	.evaluating-box{
+
+	.evaluating-box {
 		@include flex-y(flex-start);
-		.banner-box{
+		padding-bottom: vw(100);
+
+		.banner-box {
 			width: vw(355);
 		}
-		.article-list{
+
+		.article-list {
 			margin-top: vw(10);
 			width: 100%;
-			padding: 0 vw(15);
+			padding: 0 vw(15) vw(15);
 			box-sizing: border-box;
 			background: #fff;
 			border-radius: vw(6);
 		}
 	}
-	
-	.information-box{
+
+	.information-box {
 		@include flex-y(flex-start);
-		.banner-box{
+		padding-bottom: vw(100);
+
+		.banner-box {
 			width: vw(355);
 		}
-		.article-list{
+
+		.article-list {
 			margin-top: vw(10);
 			width: 100%;
-			padding: 0 vw(15);
+			padding: 0 vw(15) vw(15);
 			box-sizing: border-box;
 			background: #fff;
 			border-radius: vw(6);
 		}
 	}
-	
-	.know-box{
+
+	.know-box {
 		@include flex-y(flex-start);
-		.banner-box{
+		padding-bottom: vw(100);
+
+		.banner-box {
 			width: vw(355);
 		}
-		.article-list{
+
+		.article-list {
 			margin-top: vw(10);
 			width: 100%;
-			padding: 0 vw(15);
+			padding: 0 vw(15) vw(15);
 			box-sizing: border-box;
 			background: #fff;
 			border-radius: vw(6);

+ 385 - 0
src/pages/login/baby.vue

@@ -0,0 +1,385 @@
+<template>
+	<view class="user-setting-box">
+		<!-- #ifndef MP-TOUTIAO -->
+		<Navbar background-color="transparent" color="#333" title=" "></Navbar>
+		<!-- #endif -->
+		<view class="bg"></view>
+		<view class="content">
+			<image class="bg-pic" :src="staticUrl ? staticUrl + 'baby-bg.png' : ''" mode="heightFix"></image>
+			<view class="title">宝宝已出生</view>
+			<view class="info-box top-border-radius bottom-border-radius">
+				<view class="label">你的角色</view>
+				<view class="right">
+					<picker @change="changeRole" :value="roleIndex" :range="roleList" range-key="labelName">
+						<view class="date">
+							{{roleList[roleIndex].labelName || '请选择'}}
+							<IconText :code="`\ue88e`" class="icon" size="12" color="#C6C5CB"></IconText>
+						</view>
+					</picker>
+				</view>
+			</view>
+			<view class="info-box top10 top-border-radius">
+				<view class="label">宝宝性别</view>
+				<view class="gender-select right">
+					<view class="item" @click="handleSelectGender(1)">
+						<IconText class="icon" :code="`\ue842`" v-if="form.gender === 1" size="12" color="#6B95FF">
+						</IconText>
+						<IconText class="icon" :code="`\ue84e`" size="12" color="#999" v-else></IconText>
+						小王子
+					</view>
+					<view class="item" @click="handleSelectGender(2)">
+						<IconText class="icon" :code="`\ue842`" v-if="form.gender === 2" size="12" color="#6B95FF">
+						</IconText>
+						<IconText class="icon" :code="`\ue84e`" size="12" color="#999" v-else></IconText>
+						小公主
+					</view>
+				</view>
+			</view>
+			<view class="info-box">
+				<view class="label">宝宝生日</view>
+				<view class="right">
+					<!-- <uni-datetime-picker v-model="form.birthday" :border="false" type="date" class="date"/> -->
+					<uni-datetime-picker v-model="form.birthday" :border="false" type="date" class="date-box">
+						<view class="date">
+							{{form.birthday || '请选择日期'}}
+							<IconText :code="`\ue88e`" class="icon" size="12" color="#C6C5CB"></IconText>
+						</view>
+					</uni-datetime-picker>
+				</view>
+			</view>
+			<view class="info-box bottom-border-radius">
+				<view class="label">出生孕周</view>
+				<view class="right">
+					<input v-model="week" type="number" class="input"/>
+					<text style="margin: 0 10px;">周</text>
+					<input v-model="day" type="number" class="input"/>
+					<text style="margin-left: 10px;">天</text>
+				</view>
+			</view>
+			<view class="info-box" :class="{'bottom-border-radius': !form.feedMode || form.feedMode === 1}">
+				<view class="label">喂养方式</view>
+				<view class="right">
+					<picker @change="changeFeedMode" :value="feedModeIndex" :range="feedModeList" range-key="name">
+						<view class="date">
+							{{feedModeList[feedModeIndex].name || '请选择'}}
+							<IconText :code="`\ue88e`" class="icon" size="12" color="#C6C5CB"></IconText>
+						</view>
+					</picker>
+				</view>
+			</view>
+			<view class="info-box bottom-border-radius" v-if="form.feedMode === 2 || form.feedMode === 3">
+				<view class="label">选择奶粉</view>
+				<view class="right select-milk-powder">
+					<input v-model="form.productName" type="text" class="input" placeholder="此处输入奶粉名称" />
+					<!-- <view class="name" v-if="_good.id">{{_good.name}}</view> -->
+					<view class="btn" @click="toSelectGood">选择</view>
+				</view>
+			</view>
+		</view>
+		<view class="fixed-bottom">
+			<view class="btn" @click="deleteBabyModal" v-if="bid">删除</view>
+			<view class="solid-btn" @click="handleConfirm">保存</view>
+		</view>
+		<ShowModal ref="deletePopup" title="提示" @submit="deleteBaby" leftBtnText="取消" content="确认后宝宝数据将清空,是否确认删除?"
+			btnText="确认" />
+	</view>
+</template>
+
+<script lang="ts">
+	import {
+		Component,
+		Mixins
+	} from 'vue-property-decorator';
+	import loginMixin from '@/common/mixins/loginMixin.ts';
+	import {
+		types
+	} from '@/common/store/index';
+	import {
+		namespace
+	} from 'vuex-class';
+	const baseModule = namespace('base');
+	@Component({})
+	export default class UserSetting extends Mixins(loginMixin) {
+		@baseModule.Getter('_good') _good: any;
+		@baseModule.Mutation(types.SET_GOOD) setGood : any;
+		@baseModule.Mutation(types.SET_TOKEN) setToken : any;
+		staticUrl : string = this.$oss_url; 	//oss地址
+		gender : any = 1;
+		form : any = {
+			familyRole: '',
+			gender: null,
+			birthday: '',
+			birthDay: null,
+			feedMode: null,
+			productName: ''
+		};
+		week : any = null;
+		day : any = null;
+		feedModeList : any = [
+			{
+				name: '母乳',
+				value: 1
+			},
+			{
+				name: '配方奶',
+				value: 2
+			},
+			{
+				name: '混合',
+				value: 3
+			}
+		];
+		feedModeIndex : any = null;
+		roleList : any = [];
+		roleIndex : any = null;
+		registerToken : any = '';
+		isFirst: any = true;
+
+		onShow() {
+			if(this.isFirst) {
+				this.isFirst = false;
+				return;
+			};
+			this.form.productName = this._good.name || '';
+			this.form = {
+				...this.form
+			}
+		}
+
+		onLoad() {
+			this.setGood({});
+			this.registerToken = this.$Route.query.registerToken;
+			this.getLabelItemByRole();
+		}
+
+		getLabelItemByRole() {
+			// uni.showLoading({
+			// 	title: '加载中',
+			// });
+			this.$http.get({
+				url: this.$api.getLabelItem,
+				data: {
+					dataName: "role"
+				}
+			}).then((res : any) => {
+				let obj : any = {};
+				res.list.forEach((item : any) => {
+					obj[item.value] = item.labelName
+				})
+				this.roleList = res.list;
+				// uni.hideLoading();
+			})
+		}
+
+		changeFeedMode(e : any) {
+			this.feedModeIndex = e.detail.value;
+			this.form.feedMode = this.feedModeList[e.detail.value].value;
+		}
+
+		handleSelectGender(gender : any) {
+			this.form.gender = gender;
+		}
+
+		changeRole(e : any) {
+			this.roleIndex = e.detail.value;
+			this.form.familyRole = this.roleList[e.detail.value].value;
+		}
+
+		handleConfirm() {
+			uni.showLoading({
+				title: '加载中',
+			});
+			this.$http.post({
+				url: this.$api.finishRegister,
+				data: {
+					way: 3,
+					registerToken: this.registerToken,
+					...this.form,
+					birthDay: this.week * 7 + Number(this.day),
+					// productName: this._good.name || ''
+				}
+			}).then((res : any) => {
+				if(res){
+					this.setToken(res);
+					this.$Router.pushTab({
+						path: '/pages/front/front'
+					})
+				};
+				uni.hideLoading();
+			})
+		}
+		
+		toSelectGood(){
+			this.$Router.push({
+				path: '/packages/goods/select-good'
+			})
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	page {
+		background: #f5f5f5;
+	}
+
+	.user-setting-box {
+		// background: #F5F5F5;
+		height: 100vh;
+		@include flex-y(flex-start);
+
+		.bg {
+			width: 100%;
+			height: vw(300);
+			background: linear-gradient(162.34deg, rgba(232, 237, 255, 1) 0%, rgba(244, 230, 255, 1) 47.75%, rgba(247, 242, 255, 1) 82.84%, rgba(251, 246, 252, 1) 100%);
+			position: absolute;
+			top: 0;
+			z-index: -1;
+		}
+
+		.content {
+			width: 100%;
+			flex: 1;
+			// padding: 0 vw(10);
+			box-sizing: border-box;
+			@include flex-y(flex-start);
+			position: relative;
+
+			.bg-pic {
+				height: vw(96);
+				align-self: flex-start;
+				margin-left: vw(24);
+				position: absolute;
+				z-index: -1;
+				top: vw(-10);
+			}
+
+			.title {
+				width: 100%;
+				height: vw(60);
+				padding: 0 vw(40);
+				box-sizing: border-box;
+				@include flex-x(flex-end);
+				@include word-vw(22, #FFBB78);
+				margin-top: vw(20);
+			}
+
+			.info-box {
+				width: vw(355);
+				height: vw(56);
+				background: #fff;
+				@include flex-x();
+				padding-left: vw(20);
+				padding-right: vw(10);
+				box-sizing: border-box;
+				@include word-vw(14, #333);
+				margin-top: vw(1);
+
+				&.top10 {
+					margin-top: vw(10);
+				}
+
+				&.top-border-radius {
+					border-top-right-radius: vw(10);
+					border-top-left-radius: vw(10);
+				}
+
+				&.bottom-border-radius {
+					border-bottom-right-radius: vw(10);
+					border-bottom-left-radius: vw(10);
+				}
+
+				.right {
+					width: vw(210);
+					@include flex-x(flex-end);
+
+					.input {
+						width: 100%;
+						height: vw(40);
+						border-radius: vw(5);
+						background: #F6F6F6;
+						text-align: center;
+						font-size: vw(14);
+					}
+
+					/deep/.uni-date {
+						@include flex-x(flex-end);
+					}
+
+					.date {
+						width: vw(100);
+						@include flex-x(flex-end);
+
+						.icon {
+							margin-left: vw(3);
+						}
+					}
+
+					&.select-milk-powder {
+						height: vw(40);
+						background: #F6F6F6;
+
+						.input {
+							flex: 1;
+							margin-right: vw(10);
+						}
+						
+						.name{
+							flex:1;
+							padding: 0 vw(12);
+							box-sizing: border-box;
+							@include flex-x(center);
+							@include ellipsis();
+						}
+
+						.btn {
+							@include wh(56, 30);
+							border-radius: vw(3);
+							background: #5283FF;
+							@include word-vw(12, #fff);
+							@include flex-x(center);
+							margin-right: vw(5);
+						}
+					}
+				}
+
+				.gender-select {
+					@include flex-x(flex-end);
+					@include word-vw(14, #333);
+
+					.item {
+						@include flex-x(flex-start);
+						margin-left: vw(12);
+
+						.icon {
+							margin-right: vw(3);
+						}
+					}
+				}
+			}
+		}
+
+		.fixed-bottom {
+			height: vw(60);
+			width: 100%;
+			// background: #fff;
+			@include flex-x(center);
+			padding: 0 vw(15);
+			box-sizing: border-box;
+
+			.btn {
+				@include solid-btn(125, 50, #787878);
+				border-radius: vw(25);
+				margin-right: vw(15);
+				background: #fff;
+			}
+
+			.solid-btn {
+				background: $bk-color;
+				@include solid-btn(345, 50, #333);
+				border-radius: vw(25);
+				@include word-vw(14, #fff);
+				flex: 1;
+			}
+		}
+	}
+</style>

+ 91 - 25
src/pages/login/login.vue

@@ -1,9 +1,20 @@
 <template>
 	<view class="login-box">
+		<!-- #ifndef MP-TOUTIAO -->
 		<Navbar title='登录'></Navbar>
+		<!-- #endif -->
 		<image class="logo" :src="static ? static + 'logo.png' : ''" mode="heightFix"></image>
 		<!-- <view class="login-btn" @click="handleLogin">一键登录</view> -->
-		<button type="default" class="login-btn" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">获取手机号</button>
+		
+		<!-- #ifdef MP-TOUTIAO -->
+		<button type="default" class="login-btn" open-type="getUserInfo"
+			@getuserinfo="getUserInfo">抖音授权登录</button>
+		<!-- #endif -->
+		<!-- #ifndef MP-TOUTIAO -->
+		<button type="default" v-if="isAgree" class="login-btn" open-type="getPhoneNumber"
+			@getphonenumber="getPhoneNumber">授权手机号快捷登录</button>
+		<view class="login-btn" @click="handleAgreeTip" v-else>授权手机号快捷登录</view>
+		<!-- #endif -->
 		<view class="register-btn" @click="toBack">暂不登录</view>
 		<view class="agree">
 			<IconText class="icon" size="18" v-if="isAgree" :code="`\ue842`" color="#D3325C"
@@ -11,7 +22,7 @@
 			</IconText>
 			<IconText class="icon" size="18" v-else :code="`\ue84e`" color="#999" @click.native="isAgree = true">
 			</IconText>
-			 阅读并同意<text @click="handleAgree(1)"> 《用户协议》</text>和<text @click="handleAgree(2)"> 《隐私政策》</text>
+			阅读并同意<text @click="handleAgree(1)"> 《用户协议》</text>和<text @click="handleAgree(2)"> 《隐私政策》</text>
 		</view>
 		<uni-popup ref="agreement" :safe-area="false">
 			<scroll-view class="agreement-box" :scroll-y="true">
@@ -55,15 +66,20 @@
 		userAgreement : any = '';
 		isShare : any = false;
 		agreementObj : any = {};
-		
+
 		onShow() {
 			this.getAgreementInfo("用户协议");
 			this.getAgreementInfo("隐私政策");
 		}
 		onLoad(opt : any) {
-			this.getSuperior(opt);
+			// this.getSuperior(opt);
+			uni.login({
+				complete: (res : any) => {
+					console.log(res);
+				}
+			})
 		}
-		
+
 		getSuperior(opt : any) {
 			if (opt.scene) {
 				let sceneArr = decodeURIComponent(opt.scene).split('&');
@@ -81,7 +97,7 @@
 				this.isShare = true;
 			}
 		}
-		
+
 		handleAgree(way : any) {
 			if (way === 1) {
 				this.agreement = this.agreementObj["用户协议"] ? this.agreementObj["用户协议"].content : '';
@@ -109,15 +125,36 @@
 					console.log(err);
 				});
 		}
+
+		handleAgreeTip() {
+			uni.showToast({
+				title: "请同意用户协议",
+				icon: 'none'
+			})
+		}
+
+		getPhoneNumber(val : any) {
+			console.log(val);
+			this.handleLogin(val.detail.code);
+			// this.$Router.push({
+			// 	path: '/packages/user/user/set-user-info'
+			// })
+		}
 		
-		getPhoneNumber(val: any){
-			console.log(val)
+		getUserInfo(){
+			if (!this.isAgree) {
+				uni.showToast({
+					title: "请同意用户协议",
+					icon: 'none'
+				})
+				return;
+			};
 			this.$Router.push({
-				path: '/packages/user/user/set-user-info'
+				path: '/pages/login/phone-login',
 			})
 		}
-		
-		async handleLogin() {
+
+		async handleLogin(phoneCode : any) {
 			if (!this.isAgree) {
 				uni.showToast({
 					title: "请同意用户协议",
@@ -125,17 +162,18 @@
 				})
 				return;
 			};
-			
+
 			// uni.showLoading({
 			// 	title: '加载中',
 			// });
-			let obj = {};
+			// let obj = {};
 			// #ifdef MP-WEIXIN
-			let eve: any = await this.getWxCode();
-			obj = {
-				code: eve.code
-			};
+			// let eve: any = await this.getWxCode();
+			// obj = {
+			// 	code: eve.code
+			// };
 			// #endif
+			// console.log(this.referrerId)
 			this.$http
 				.post({
 					url: this.$api.login,
@@ -143,28 +181,54 @@
 						auth: {
 							// sid: 0,
 							agent: 1,
+							way: 2,
 						},
 						third: {
-							...obj
+							way: 1,
+							phoneCode: phoneCode,
+							referrer: +this.referrerId || 0
 						}
 					},
 				})
 				.then((res : any) => {
-					// uni.hideLoading();
-					this.setToken(res.token);
-					if (this.isShare) {
-						this.$Router.pushTab({
-							path: '/pages/front/front'
+					uni.setStorageSync('referrerId', '');
+					if (res.token) {
+						this.setToken(res.token);
+						this.backPage();
+					};
+					if (res.registerToken) {
+						this.$Router.push({
+							path: '/pages/login/select-stage',
+							query: {
+								registerToken: res.registerToken
+							}
 						})
-					} else {
-						this.$Router.back(1);
 					}
+					// uni.hideLoading();
+					// this.setToken(res.token);
+					// if (this.isShare) {
+					// 	this.$Router.pushTab({
+					// 		path: '/pages/front/front'
+					// 	})
+					// } else {
+					// 	this.$Router.back(1);
+					// }
 				}, (err : any) => {
 					// uni.hideLoading();
 					console.log(err);
 				});
 		}
 
+		backPage() {
+			if (getCurrentPages().length <= 1) {
+				this.$Router.pushTab({
+					path: '/pages/front/front'
+				});
+				return;
+			}
+			this.$Router.back(1);
+		}
+
 		getWxCode() {
 			return new Promise((resolve : any, reject : any) => {
 				uni.login({
@@ -186,11 +250,13 @@
 		background: transparent !important;
 		background-color: "F5F5F5" !important;
 	}
+
 	/* #ifdef H5 */
 	>>>.uni-easyinput__content {
 		background: transparent !important;
 		background-color: "F5F5F5" !important;
 	}
+
 	/* #endif */
 </style>
 <style lang="scss" scoped>

+ 318 - 0
src/pages/login/phone-login.vue

@@ -0,0 +1,318 @@
+<template>
+	<view class="user-setting-box">
+		<!-- #ifndef MP-TOUTIAO -->
+		<Navbar background-color="transparent" color="#333" title="手机验证"></Navbar>
+		<!-- #endif -->
+		<view class="bg"></view>
+		<view class="content">
+			<!-- <view class="tip">系统向{{_userInfo.phone | phoneFormat}}发送了验证码,请输入</view> -->
+			<!-- <view class="code-box">
+				<input type="text" class="input" placeholder="请输入验证码"/>
+				<view class="btn">重新获取</view>
+			</view> -->
+			<view class="box">
+				<view class="input-box">
+					<view class="label">手机号</view>
+					<input v-model="phone" type="number" class="input" placeholder="此处输入手机号" />
+				</view>
+				<view class="input-box code">
+					<view class="label">验证码</view>
+					<input v-model="code" type="number" class="input" placeholder="请输入验证码" />
+					<view class="code-btn btn" @click="getCode" :class="{disabled: isWaiting}">
+						{{ isWaiting ? `${countDown}秒后重试` : '获取验证码' }}
+					</view>
+				</view>
+			</view>
+		</view>
+		<view class="fixed-bottom" @click="handleConfirm">
+			<view class="solid-btn">登录</view>
+		</view>
+	</view>
+</template>
+
+<script lang="ts">
+	import {
+		Component,
+		Mixins
+	} from 'vue-property-decorator';
+	import loginMixin from '@/common/mixins/loginMixin.ts';
+	import {
+		types
+	} from '@/common/store/index';
+	import {
+		namespace
+	} from 'vuex-class';
+	const baseModule = namespace('base');
+	@Component({})
+	export default class UserSetting extends Mixins(loginMixin) {
+		@baseModule.Getter('_referrerId') referrerId : any;
+		@baseModule.Mutation(types.SET_TOKEN) setToken : any;
+		// @baseModule.Getter('_userInfo') _userInfo: any;
+		code : any = null;
+		isWaiting : boolean = false; //是否已发送验证码
+		timer : number | null = null; //定时器
+		countDown : number = 0; //倒计时
+		defaultTime : number = 60; //初始倒计时时间
+		setTime : any = 0;
+		phone : any = '';
+
+
+		onShow() {
+			// this.getUserInfo();
+			// this.$nextTick(() => {
+			// 	this.getCode();
+			// })
+		}
+
+		updatePhone() {
+			// uni.showToast({
+			// 	title: '请联系后台客服修改手机号',
+			// 	icon: 'none'
+			// })
+		}
+
+		//获取验证码
+		getCode() : void {
+			if (this.isWaiting) return;
+			if (!/^[1][0-9]{10}$/.test(this.phone)) {
+				uni.showToast({
+					title: '请输入正确的手机号',
+					duration: 2000,
+					icon: 'none'
+				});
+				return;
+			}
+			uni.showLoading({
+				title: '加载中'
+			});
+			this.$http
+				.post({
+					url: this.$api.sendCode,
+					data: {
+						phone: this.phone,
+						type: 5
+					}
+				})
+				.then(() => {
+					//验证码获取倒计时
+					uni.hideLoading();
+					uni.showToast({
+						title: '已发送',
+						duration: 2000,
+						icon: 'none'
+					});
+					this.isWaiting = true;
+					this.timer && clearInterval(this.timer);
+					this.countDown = this.defaultTime;
+					this.setTime = +new Date() + 60000;
+					this.timer = setInterval(() => {
+						this.countDown--;
+						if (this.countDown <= 0) {
+							this.timer && clearInterval(this.timer);
+							this.isWaiting = false;
+						}
+					}, 1000);
+				}, () => {
+					uni.hideLoading();
+				});
+		}
+
+		getWxCode() {
+			return new Promise((resolve : any, reject : any) => {
+				uni.login({
+					provider: 'weixin',
+					success: (eve) => {
+						resolve(eve);
+					},
+					fail: (err) => {
+						console.log(err);
+						reject();
+					}
+				});
+			})
+		}
+
+		handleConfirm() {
+			this.$http
+				.post({
+					url: this.$api.login,
+					data: {
+						auth: {
+							// sid: 0,
+							agent: 1,
+							way: 5,
+							identity: this.phone
+						},
+						third: {
+							way: 2,
+							smsCode: this.code,
+							referrer: +this.referrerId || 0
+						}
+					}
+				})
+				.then((res : any) => {
+					uni.setStorageSync('referrerId', '');
+					if (res.token) {
+						this.setToken(res.token);
+						this.backPage();
+					};
+					if (res.registerToken) {
+						this.$Router.push({
+							path: '/pages/login/select-stage',
+							query: {
+								registerToken: res.registerToken
+							}
+						})
+					}
+				}, (err : any) => {
+					console.log(err);
+				});
+		}
+
+		backPage() {
+			if (getCurrentPages().length <= 1) {
+				this.$Router.pushTab({
+					path: '/pages/front/front'
+				});
+				return;
+			}
+			this.$Router.back(1);
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	page {
+		background: #f5f5f5;
+	}
+
+	.user-setting-box {
+		// background: #F5F5F5;
+		height: 100vh;
+		@include flex-y(flex-start);
+
+		.bg {
+			width: 100%;
+			height: vw(200);
+			background: linear-gradient(173.24deg, rgba(232, 237, 255, 1) 0%, rgba(230, 230, 255, 1) 47.75%, rgba(247, 242, 255, 1) 82.84%, rgba(251, 246, 252, 1) 100%);
+			position: absolute;
+			top: 0;
+			z-index: -1;
+		}
+
+		.content {
+			width: 100%;
+			flex: 1;
+			// padding: 0 vw(10);
+			box-sizing: border-box;
+			@include flex-y(flex-start);
+
+			.tip {
+				width: 100%;
+				margin-top: vw(18);
+				@include word-vw(14, #666);
+				padding: 0 vw(15);
+				box-sizing: border-box;
+			}
+
+			.code-box {
+				width: 100%;
+				height: vw(44);
+				padding: 0 vw(10);
+				box-sizing: border-box;
+				@include flex-x();
+				margin-top: vw(15);
+
+				.input {
+					flex: 1;
+					height: 100%;
+					background: #fff;
+					border-top-left-radius: vw(5);
+					border-bottom-left-radius: vw(5);
+					padding: 0 vw(20);
+					font-size: vw(14);
+				}
+
+				.btn {
+					@include wh(96, 44);
+					// border-radius: vw(5);
+					background: $btn-color;
+					@include word-vw(14, #fff);
+					@include flex-x(center);
+					border-top-right-radius: vw(5);
+					border-bottom-right-radius: vw(5);
+				}
+			}
+
+			.box {
+				width: vw(355);
+				margin-top: vw(24);
+				background: #fff;
+				border-radius: vw(10);
+				@include flex-y(flex-start);
+
+				.input-box {
+					width: 100%;
+					height: vw(56);
+					padding-left: vw(18);
+					padding-right: vw(12);
+					box-sizing: border-box;
+					@include flex-x();
+
+					.label {
+						width: vw(90);
+						@include word-vw(14, #333);
+					}
+
+					.input {
+						flex: 1;
+						height: vw(40);
+						font-size: vw(14);
+						padding: 0 vw(12);
+						background: #F6F6F6;
+						border-radius: vw(5);
+					}
+
+					.btn {
+						@include wh(96, 40);
+						// border-radius: vw(5);
+						background: $btn-color;
+						@include word-vw(14, #fff);
+						@include flex-x(center);
+						border-top-right-radius: vw(5);
+						border-bottom-right-radius: vw(5);
+					}
+
+					.code-btn {
+						// @include word-vw(14, $btn-color);
+
+						&.disabled {
+							background: $gray9;
+						}
+					}
+				}
+
+				.code {
+					.input {
+						border-top-right-radius: 0;
+						border-bottom-right-radius: 0;
+					}
+				}
+			}
+		}
+
+		.fixed-bottom {
+			height: vw(60);
+			width: 100%;
+			background: #fff;
+			@include flex-x(center);
+
+			.solid-btn {
+				background: $bk-color;
+				@include solid-btn(345, 48, #333);
+				border-radius: vw(24);
+				@include word-vw(14, #fff);
+			}
+		}
+	}
+</style>

+ 325 - 0
src/pages/login/pregnant.vue

@@ -0,0 +1,325 @@
+<template>
+	<view class="user-setting-box">
+		<!-- #ifndef MP-TOUTIAO -->
+		<Navbar background-color="transparent" color="#333" title=" "></Navbar>
+		<!-- #endif -->
+		<view class="bg"></view>
+		<view class="content">
+			<image class="bg-pic" :src="staticUrl ? staticUrl + 'pregnant-bg.png' : ''" mode="heightFix"></image>
+			<view class="title">怀孕中</view>
+			<view class="info-box top-border-radius">
+				<view class="label">用户角色</view>
+				<view class="right">
+					<picker @change="changeRole" :value="roleIndex" :range="roleList" range-key="labelName">
+						<view class="date">
+							{{roleList[roleIndex].labelName || '请选择'}}
+							<IconText :code="`\ue88e`" class="icon" size="12" color="#C6C5CB"></IconText>
+						</view>
+					</picker>
+				</view>
+			</view>
+			<view class="info-box bottom-border-radius">
+				<view class="label">出生日期</view>
+				<view class="right">
+					<uni-datetime-picker v-model="form.expectedTime" :border="false" type="date" class="date-box">
+						<view class="date">
+							{{form.expectedTime || '请选择日期'}}
+							<IconText :code="`\ue88e`" class="icon" size="12" color="#C6C5CB"></IconText>
+						</view>
+					</uni-datetime-picker>
+				</view>
+			</view>
+		</view>
+		<view class="fixed-bottom" >
+			<view class="solid-btn" @click="handleConfirm">保存</view>
+		</view>
+	</view>
+</template>
+
+<script lang="ts">
+	import {
+		Component,
+		Mixins
+	} from 'vue-property-decorator';
+	import loginMixin from '@/common/mixins/loginMixin.ts';
+	import {
+		types
+	} from '@/common/store/index';
+	import {
+		namespace
+	} from 'vuex-class';
+	const baseModule = namespace('base');
+	@Component({})
+	export default class UserSetting extends Mixins(loginMixin) {
+		// @baseModule.Getter('_userInfo') _userInfo: any;
+		@baseModule.Mutation(types.SET_TOKEN) setToken : any;
+		staticUrl : string = this.$oss_url; 	//oss地址
+		form: any = {
+			familyRole: '',
+			expectedTime: '',
+		};
+		roleList: any = [];
+		roleIndex: any = null;
+		registerToken: any = '';
+		
+		onShow() {
+			
+		}
+		
+		onLoad(){
+			this.registerToken = this.$Route.query.registerToken;
+			this.getLabelItemByRole();
+		}
+		
+		getLabelItemByRole() {
+			// uni.showLoading({
+			// 	title: '加载中',
+			// });
+			this.$http.get({
+				url: this.$api.getLabelItem,
+				data: {
+					dataName: "role"
+				}
+			}).then((res : any) => {
+				let obj : any = {};
+				res.list.forEach((item : any) => {
+					obj[item.value] = item.labelName
+				})
+				this.roleList = res.list;
+				// uni.hideLoading();
+			})
+		}
+		
+		changeRole(e: any){
+			this.roleIndex = e.detail.value;
+			this.form.familyRole = this.roleList[e.detail.value].value;
+		}
+		
+		handleConfirm(){
+			uni.showLoading({
+				title: '加载中',
+			});
+			this.$http.post({
+				url: this.$api.finishRegister,
+				data: {
+					way: 2,
+					registerToken: this.registerToken,
+					...this.form
+				}
+			}).then((res: any) => {
+				if(res){
+					this.setToken(res);
+					this.$Router.pushTab({
+						path: '/pages/front/front'
+					})
+				};
+				uni.hideLoading();
+			})
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	page{
+		background: #f5f5f5;
+	}
+	.user-setting-box {
+		// background: #F5F5F5;
+		height: 100vh;
+		@include flex-y(flex-start);
+		
+		.bg{
+			width: 100%;
+			height: vw(240);
+			background: linear-gradient(162.34deg, rgba(232, 237, 255, 1) 0%, rgba(244, 230, 255, 1) 47.75%, rgba(247, 242, 255, 1) 82.84%, rgba(251, 246, 252, 1) 100%);
+			position: absolute;
+			top: 0;
+			z-index: -1;
+		}
+
+		.content {
+			width: 100%;
+			flex: 1;
+			// padding: 0 vw(10);
+			box-sizing: border-box;
+			@include flex-y(flex-start);
+			position: relative;
+			
+			.bg-pic{
+				height: vw(96);
+				align-self: flex-start;
+				margin-left: vw(24);
+				position: absolute;
+				z-index: -1;
+				top: vw(-10);
+			}
+			
+			.title{
+				width: 100%;
+				height: vw(60);
+				padding: 0 vw(40);
+				box-sizing: border-box;
+				@include flex-x(flex-end);
+				@include word-vw(22, #C09FE0);
+				margin-top: vw(20);
+			}
+
+			.baby-top{
+				width: vw(355);
+				background: #fff;
+				margin-top: vw(60);
+				border-radius: vw(10);
+				.box{
+					padding-left: vw(20);
+					padding-right: vw(10);
+					@include flex-x(flex-start);
+					.label{
+						width: vw(110);
+						@include word-vw(14, #333);
+						@include flex-x(flex-start);
+					}
+				}
+				.pic-box{
+					height: vw(60);
+					.label{
+						height: 100%;
+						position: relative;
+					}
+					.upload-pic-box{
+						@include wh(88, 88);
+						border-radius: vw(44);
+						border: vw(2) solid #fff;
+						box-shadow: 0px 6px 16px  rgba(44, 0, 242, 0.16);
+						background: #E3E3E3;
+						position: absolute;
+						bottom: vw(10);
+						// overflow: hidden;
+						.avatar{
+							@include wh(88, 88);
+							border-radius: vw(44);
+						}
+						.camera-box{
+							@include wh(24, 24);
+							border-radius: vw(12);
+							background: #333;
+							@include flex-x(center);
+							position: absolute;
+							bottom: vw(3);
+							right: vw(3);
+						}
+					}
+					.tip{
+						@include word-vw(14, #ccc);
+					}
+				}
+				.name-box{
+					height: vw(60);
+					.input{
+						flex: 1;
+						height: vw(40);
+						background: #F6F6F6;
+						border-radius: vw(5);
+						text-align: center;
+						font-size: vw(14);
+					}
+				}
+				.gender-box{
+					height: vw(44);
+					.gender-select{
+						@include flex-x(flex-start);
+						@include word-vw(14, #333);
+						.item{
+							@include flex-x(flex-start);
+							margin-right: vw(12);
+							.icon{
+								margin-right: vw(3);
+							}
+						}
+					}
+				}
+			}
+			.info-box{
+				width: vw(355);
+				height: vw(56);
+				background: #fff;
+				@include flex-x();
+				padding-left: vw(20);
+				padding-right: vw(10);
+				box-sizing: border-box;
+				@include word-vw(14, #333);
+				margin-top: vw(1);
+				&.top10{
+					margin-top: vw(10);
+				}
+				&.top-border-radius{
+					border-top-right-radius: vw(10);
+					border-top-left-radius: vw(10);
+				}
+				&.bottom-border-radius{
+					border-bottom-right-radius: vw(10);
+					border-bottom-left-radius: vw(10);
+				}
+				.right{
+					width: vw(210);
+					@include flex-x(flex-end);
+					.input{
+						width: 100%;
+						height: vw(40);
+						border-radius: vw(5);
+						background: #F6F6F6;
+						text-align: center;
+						font-size: vw(14);
+					}
+					/deep/.uni-date{
+						@include flex-x(flex-end);
+					}
+					.date{
+						width: vw(100);
+						@include flex-x(flex-end);
+						.icon{
+							margin-left: vw(3);
+						}
+					}
+					&.select-milk-powder{
+						background: #F6F6F6;
+						.input{
+							flex: 1;
+							margin-right: vw(10);
+						}
+						.btn{
+							@include wh(56, 30);
+							border-radius: vw(3);
+							background: #5283FF;
+							@include word-vw(12, #fff);
+							@include flex-x(center);
+							margin-right: vw(5);
+						}
+					}
+				}
+			}
+		}
+		.fixed-bottom {
+			height: vw(60);
+			width: 100%;
+			// background: #fff;
+			@include flex-x(center);
+			padding: 0 vw(15);
+			box-sizing: border-box;
+			
+			.btn{
+				@include solid-btn(125, 50, #787878);
+				border-radius: vw(25);
+				margin-right: vw(15);
+				background: #fff;
+			}
+		
+			.solid-btn {
+				background: $bk-color;
+				@include solid-btn(345, 50, #333);
+				border-radius: vw(25);
+				@include word-vw(14, #fff);
+				flex: 1;
+			}
+		}
+	}
+</style>

+ 230 - 0
src/pages/login/select-stage.vue

@@ -0,0 +1,230 @@
+<template>
+	<view class="user-setting-box">
+		<!-- #ifndef MP-TOUTIAO -->
+		<Navbar title=' ' backgroundColor="transparent"></Navbar>
+		<!-- #endif -->
+		<view class="bg"></view>
+		<view class="content">
+			<view class="title">选择所处阶段</view>
+			<view class="baby-item" @click="toPregnant">
+				<view class="left">
+					<image class="pic" :src="staticUrl ? staticUrl + 'stage-01.png' : ''" mode="aspectFill"></image>
+					<view class="info">
+						<view class="name">怀孕中</view>
+					</view>
+				</view>
+				<view class="btn">
+					<IconText :code="`\ue88e`" color="#5283FF" size="10" class="icon"></IconText>
+				</view>
+			</view>
+			<view class="baby-item" @click="toBaby">
+				<view class="left">
+					<image class="pic" :src="staticUrl ? staticUrl + 'stage-02.png' : ''" mode="aspectFill"></image>
+					<view class="info">
+						<view class="name">宝宝已出生</view>
+					</view>
+				</view>
+				<view class="btn">
+					<IconText :code="`\ue88e`" color="#5283FF" size="10" class="icon"></IconText>
+				</view>
+			</view>
+			<!-- <view class="add-btn" @click="handleRegister">
+				以后再选择,先去逛逛
+				<IconText :code="`\ue88e`" color="#999" size="12" class="icon"></IconText>
+			</view> -->
+		</view>
+		<!-- <view class="fixed-bottom" v-if="referrerId">
+			<view class="solid-btn" @click="handleSkip">受邀请亲友,直接登录</view>
+		</view> -->
+	</view>
+</template>
+
+<script lang="ts">
+	import {
+		Component,
+		Mixins
+	} from 'vue-property-decorator';
+	import loginMixin from '@/common/mixins/loginMixin.ts';
+	import {
+		types
+	} from '@/common/store/index';
+	import {
+		namespace
+	} from 'vuex-class';
+	const baseModule = namespace('base');
+	@Component({})
+	export default class SelectBaby extends Mixins(loginMixin) {
+		// @baseModule.Getter('_userInfo') _userInfo: any;
+		@baseModule.Getter('_referrerId') referrerId : any;
+		@baseModule.Mutation(types.SET_TOKEN) setToken : any;
+		staticUrl : string = this.$oss_url; 	//oss地址
+		registerToken: any = '';
+		
+		onShow() {
+			// this.getBabyListBySelf();
+			this.registerToken = this.$Route.query.registerToken;
+		}
+		
+		getBabyListBySelf() {
+			
+		}
+		
+		toPregnant(){
+			this.$Router.push({
+				path: '/pages/login/pregnant',
+				query: {
+					registerToken: this.registerToken
+				}
+			})
+		}
+		
+		toBaby(){
+			this.$Router.push({
+				path: '/pages/login/baby',
+				query: {
+					registerToken: this.registerToken
+				}
+			})
+		}
+		
+		handleRegister(){
+			this.$http
+				.post({
+					url: this.$api.finishRegister,
+					data: {
+						registerToken: this.registerToken,
+						way: 4
+					}
+				})
+				.then((res : any) => {
+					if(res){
+						this.setToken(res);
+						this.$Router.pushTab({
+							path: '/pages/front/front'
+						})
+					};
+				}, (err : any) => {
+					console.log(err);
+				});
+		}
+		
+		handleSkip(){
+			
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	page{
+		background: #f5f5f5;
+	}
+	.user-setting-box {
+		// background: #F5F5F5;
+		height: 100vh;
+		@include flex-y(flex-start);
+		
+		.bg{
+			width: 100%;
+			height: vw(240);
+			background: linear-gradient(162.34deg, rgba(232, 237, 255, 1) 0%, rgba(244, 230, 255, 1) 47.75%, rgba(247, 242, 255, 1) 82.84%, rgba(251, 246, 252, 1) 100%);;
+			position: absolute;
+			top: 0;
+			z-index: -1;
+			/* #ifdef MP-TOUTIAO */
+			height: vw(160);
+			/* #endif */
+		}
+
+		.content {
+			width: 100%;
+			padding: 0 vw(15);
+			box-sizing: border-box;
+			@include flex-y(flex-start);
+			flex: 1;
+			.title{
+				width: 100%;
+				@include flex-x(flex-start);
+				@include word-vw(20, #333);
+				margin-bottom: vw(8);
+			}
+			.baby-item{
+				width: 100%;
+				@include flex-x();
+				padding: vw(12) vw(18);
+				box-sizing: border-box;
+				background: #fff;
+				border-radius: vw(10);
+				margin-top: vw(10);
+				.left{
+					@include flex-x();
+					.pic{
+						@include wh(56, 56);
+						border-radius: vw(28);
+						margin-right: vw(12);
+					}
+					.info{
+						.name{
+							@include word-vw(14, #333);
+							font-weight: bold;
+						}
+						.age{
+							@include flex-x(flex-start);
+							@include word-vw(12, #666);
+							margin-top: vw(6);
+							.line{
+								width: 0;
+								height: vw(6);
+								border-right: vw(1) solid #C7C7C7;
+								margin: 0 vw(3);
+							}
+						}
+					}
+				}
+				.btn{
+					@include wh(24, 24);
+					border-radius: vw(14);
+					background: #DBE5FF;
+					border-radius: vw(1) solid #C9D8FF;
+					box-sizing: border-box;
+					@include word-vw(12, #fff);
+					@include flex-x(center);
+				}
+			}
+			.add-btn{
+				width: 100%;
+				height: vw(64);
+				background: #fff;
+				border-radius: vw(10);
+				@include flex-x(center);
+				margin-top: vw(10);
+				@include word-vw(14, #999);
+				.icon{
+					margin-left: vw(3);
+				}
+			}
+		}
+		.fixed-bottom {
+			height: vw(60);
+			width: 100%;
+			// background: #fff;
+			@include flex-x(center);
+			padding: 0 vw(15);
+			box-sizing: border-box;
+			
+			.btn{
+				@include solid-btn(125, 50, #787878);
+				border-radius: vw(25);
+				margin-right: vw(15);
+				background: #fff;
+			}
+		
+			.solid-btn {
+				background: $bk-color;
+				@include solid-btn(345, 50, #333);
+				border-radius: vw(25);
+				@include word-vw(14, #fff);
+				flex: 1;
+			}
+		}
+	}
+</style>

+ 439 - 229
src/pages/user/user.vue

@@ -6,135 +6,186 @@
 		<view class="bg"></view>
 		<view class="container">
 			<view class="user-info">
-				<image :src="_userInfo.avatar" class="pic" mode="aspectFill"></image>
+				<view class="pic-box">
+					<image :src="_userInfo.avatar" class="pic" mode="aspectFill"></image>
+					<view class="level">{{roleMap[_userInfo.roleTypeOne]}}</view>
+				</view>
 				<view class="info">
-					<view class="name">{{_userInfo.nickname}}<view class="level"></view></view>
-					<view class="role">{{_userInfo.familyRole}}</view>
-					<view class="id">ID:{{_userInfo.uid}}</view>
+					<view class="name">{{_userInfo.nickname}}
+						<view class="level"></view>
+					</view>
+					<view class="role" v-if="_userInfo.familyRole">{{_userInfo.familyRole}}</view>
+					<view class="id">ID:{{_userInfo.uid}}</view>
 				</view>
-				<view class="btn" @click="toPage('/packages/user/user/user-setting')">
+				<!-- <view class="btn" >
 					<image :src="static ? static + 'user-setting.png' : ''" class="pic" mode="widthFix"></image>
-				</view>
+				</view> -->
 			</view>
-			<view class="member-box">
-				<view class="num">
-					<text>{{_userInfo.consultNumber}}</text>
-					剩余咨询次数
-				</view>
-				<view class="vertical-line"></view>
-				<view class="tip-box">
-					<view class="tip-top">
-						<text>升级会员</text>
-						获取更多咨询次数
+			<view class="monery-box">
+				<view class="item-box">
+					<view class="item" @click="toPage('/packages/user/user/member')">
+						<view class="item-top">
+							<view>
+								<text>{{_userInfo.balance}}</text>
+								可用宝宝币
+							</view>
+						</view>
+						<view class="item-bottom">
+							<view class="btn">
+								充值
+								<IconText :code="`\ue753`" color="#fff" size="16" class="icon"></IconText>
+							</view>
+						</view>
+						<image :src="static ? static + 'user-money-01.png' : ''" class="pic" mode="heightFix"></image>
 					</view>
-					<view class="tip-bottom">
-						<text>会员权益</text>
-						<text>会员权益</text>
-						<text>会员权益</text>
+					<view class="item" @click="toPage('/packages/user/user/exchange')">
+						<view class="item-top">
+							<view>
+								<text>{{_userInfo.aiWaitNumber + _userInfo.manualWaitNumber}}</text>
+								剩余咨询次数
+							</view>
+						</view>
+						<view class="item-bottom">
+							<view class="btn">
+								去兑换
+								<IconText :code="`\ue753`" color="#fff" size="16" class="icon"></IconText>
+							</view>
+						</view>
+						<image :src="static ? static + 'user-money-02.png' : ''" class="pic" mode="heightFix"></image>
 					</view>
 				</view>
-				<image :src="static ? static + 'member-btn.png' : ''" class="pic" mode="widthFix"></image>
 			</view>
 			<view class="baby-box">
 				<view class="baby-list">
 					<swiper class="baby-swiper" indicator-dots indicator-active-color="#5E8CFF">
 						<swiper-item v-for="item in babyList" :key="item.bid">
 							<view class="baby-item" @click="toPage('/packages/baby/add-baby', {bid: item.bid})">
-								<image :src="item.avatar" class="pic" mode="aspectFill"></image>
-								<view class="info">
-									<view class="baby-name">{{item.nickname}}</view>
-									<view class="family-name" v-if="item.family">{{item.family}}</view>
+								<view class="baby-info-box">
+									<image :src="item.babyAvatar" class="pic" mode="scaleToFill"></image>
+									<view class="info">
+										<view class="baby-name">{{item.babyNickname}}</view>
+										<view class="gender">{{genderMap[item.gender]}}</view>
+									</view>
+									<view class="age">
+										年龄:{{item.age | ageFormat}}
+										<IconText :code="`\ue88e`" color="#999" size="10" class="icon"></IconText>
+									</view>
 								</view>
-								<view class="age">
-									年龄:{{item.age | ageFormat}}
-									<IconText :code="`\ue88e`" color="#999" size="10" class="icon"></IconText>
+								<view class="baby-option-box">
+									<view class="option-item"
+										@click="toPage('/packages/baby/baby-feed', {bid: item.bid})">
+										<image :src="static ? static + 'baby-option-01.png' : ''" class="pic"
+											mode="aspectFill"></image>
+										喂奶记录
+									</view>
+									<view class="option-item"
+										@click="toPage('/packages/baby/baby-poop', {bid: item.bid})">
+										<image :src="static ? static + 'baby-option-02.png' : ''" class="pic"
+											mode="aspectFill"></image>
+										便便记录
+									</view>
+									<view class="option-item"
+										@click="toPage('/packages/baby/baby-weight', {bid: item.bid})">
+										<image :src="static ? static + 'baby-option-03.png' : ''" class="pic"
+											mode="aspectFill"></image>
+										身高体重
+									</view>
+									<view class="option-item"
+										@click="toPage('/packages/baby/baby-remark', {bid: item.bid})">
+										<image :src="static ? static + 'baby-option-04.png' : ''" class="pic"
+											mode="aspectFill"></image>
+										成长备注
+									</view>
 								</view>
 							</view>
 						</swiper-item>
+						<swiper-item>
+							<view class="baby-item add-baby" @click="toPage('/packages/baby/add-baby')">
+								<IconText :code="`\ue878`" color="#A8BAFF" size="48" class="icon"></IconText>
+								添加宝宝
+							</view>
+						</swiper-item>
 					</swiper>
 				</view>
-				<view class="baby-option-box">
-					<view class="option-item" @click="toPage('/packages/baby/add-baby')">
-						<image :src="static ? static + 'user-01.png' : ''" class="pic" mode="aspectFill"></image>
-						添加宝宝
-					</view>
-					<view class="option-item" @click="toPage('/packages/baby/select-baby', {path: '/packages/baby/baby-feed'})">
-						<image :src="static ? static + 'user-02.png' : ''" class="pic" mode="aspectFill"></image>
-						喂奶记录
-					</view>
-					<view class="option-item" @click="toPage('/packages/baby/select-baby', {path: '/packages/baby/baby-weight'})">
-						<image :src="static ? static + 'user-03.png' : ''" class="pic" mode="aspectFill"></image>
-						身高体重
-					</view>
-					<view class="option-item" @click="toPage('/packages/baby/select-baby', {path: '/packages/baby/baby-remark'})">
-						<image :src="static ? static + 'user-04.png' : ''" class="pic" mode="aspectFill"></image>
-						成长备注
-					</view>
-				</view>
 			</view>
 			<view class="option-box">
-				<view class="option-item" @click="toPage('/packages/family/family-list')">
-					<view class="left">
-						<view class="icon-box" style="background: #618EFF;">
-							<IconText :code="`\ue896`" color="#fff" size="16" class="icon"></IconText>
+				<view class="option-title">
+					更多功能
+				</view>
+				<view class="option-list">
+					<view class="option-item" @click="toPage('/packages/family/family-list')">
+						<view class="left">
+							<view class="icon-box" style="background: #618EFF;">
+								<IconText :code="`\ue896`" color="#fff" size="16" class="icon"></IconText>
+							</view>
+							我的家庭
 						</view>
-						我的家庭
+						<!-- <IconText :code="`\ue88e`" color="#999" size="12" class="icon"></IconText> -->
 					</view>
-					<IconText :code="`\ue88e`" color="#999" size="12" class="icon"></IconText>
-				</view>
-				<view class="option-item">
-					<view class="left">
-						<view class="icon-box" style="background: #00BAAD;">
-							<IconText :code="`\ue895`" color="#fff" size="16" class="icon"></IconText>
+					<view class="option-item">
+						<view class="left">
+							<view class="icon-box" style="background: #00BAAD;">
+								<IconText :code="`\ue895`" color="#fff" size="16" class="icon"></IconText>
+							</view>
+							咨询记录
 						</view>
-						咨询记录
+						<!-- <IconText :code="`\ue88e`" color="#999" size="12" class="icon"></IconText> -->
 					</view>
-					<IconText :code="`\ue88e`" color="#999" size="12" class="icon"></IconText>
-				</view>
-				<view class="option-item">
-					<view class="left">
-						<view class="icon-box" style="background: #FF8D1A;">
-							<IconText :code="`\ue8a3`" color="#fff" size="16" class="icon"></IconText>
+					<view class="option-item" @click="toPage('/packages/user/user/share')">
+						<view class="left">
+							<view class="icon-box" style="background: #FF8D1A;">
+								<IconText :code="`\ue8a3`" color="#fff" size="16" class="icon"></IconText>
+							</view>
+							分享
 						</view>
-						分享
+						<!-- <IconText :code="`\ue88e`" color="#999" size="12" class="icon"></IconText> -->
 					</view>
-					<IconText :code="`\ue88e`" color="#999" size="12" class="icon"></IconText>
-				</view>
-				<view class="option-item" @click="toPage('/packages/goods/collect-list')">
-					<view class="left">
-						<view class="icon-box" style="background: #FF5733;">
-							<IconText :code="`\ue8a8`" color="#fff" size="16" class="icon"></IconText>
+					<view class="option-item" @click="toPage('/packages/user/user/feedback')">
+						<view class="left">
+							<view class="icon-box" style="background: #618EFF;">
+								<IconText :code="`\ue89d`" color="#fff" size="16" class="icon"></IconText>
+							</view>
+							意见反馈
 						</view>
-						收藏
+						<!-- <IconText :code="`\ue88e`" color="#999" size="12" class="icon"></IconText> -->
 					</view>
-					<IconText :code="`\ue88e`" color="#999" size="12" class="icon"></IconText>
-				</view>
-				<view class="option-item">
-					<view class="left">
-						<view class="icon-box" style="background: #00BAAD;">
-							<IconText :code="`\ue893`" color="#fff" size="16" class="icon"></IconText>
+					<view class="option-item" @click="toPage('/packages/goods/collect-list')">
+						<view class="left">
+							<view class="icon-box" style="background: #FF5733;">
+								<IconText :code="`\ue8a8`" color="#fff" size="16" class="icon"></IconText>
+							</view>
+							收藏
 						</view>
-						关于我们
+						<!-- <IconText :code="`\ue88e`" color="#999" size="12" class="icon"></IconText> -->
 					</view>
-					<IconText :code="`\ue88e`" color="#999" size="12" class="icon"></IconText>
-				</view>
-				<view class="option-item">
-					<view class="left">
-						<view class="icon-box" style="background: #618EFF;">
-							<IconText :code="`\ue89d`" color="#fff" size="16" class="icon"></IconText>
+					<view class="option-item" @click="toPage('/packages/user/user/about-us-list')">
+						<view class="left">
+							<view class="icon-box" style="background: #00BAAD;">
+								<IconText :code="`\ue893`" color="#fff" size="16" class="icon"></IconText>
+							</view>
+							关于我们
 						</view>
-						意见反馈
+						<!-- <IconText :code="`\ue88e`" color="#999" size="12" class="icon"></IconText> -->
 					</view>
-					<IconText :code="`\ue88e`" color="#999" size="12" class="icon"></IconText>
-				</view>
-				<view class="option-item">
-					<view class="left">
-						<view class="icon-box" style="background: #FF8D1A;">
-							<IconText :code="`\ue8a2`" color="#fff" size="16" class="icon"></IconText>
+					<view class="option-item">
+						<button class="left" open-type="contact"
+							:session-from="`7moor|${_userInfo.nickname}|${_userInfo.avatar}|${JSON.stringify({'用户ID': _userInfo.uid,'用户手机号': _userInfo.phone})}`">
+							<view class="icon-box" style="background: #FF5733;">
+								<IconText :code="`\ue8a2`" color="#fff" size="16" class="icon"></IconText>
+							</view>
+							客服
+						</button>
+						<!-- <IconText :code="`\ue88e`" color="#999" size="12" class="icon"></IconText> -->
+					</view>
+					<view class="option-item" @click="toPage('/packages/user/user/user-setting')">
+						<view class="left">
+							<view class="icon-box" style="background: #4F7AFC;">
+								<IconText :code="`\ue8a2`" color="#fff" size="16" class="icon"></IconText>
+							</view>
+							设置
 						</view>
-						设置
+						<!-- <IconText :code="`\ue88e`" color="#999" size="12" class="icon"></IconText> -->
 					</view>
-					<IconText :code="`\ue88e`" color="#999" size="12" class="icon"></IconText>
 				</view>
 			</view>
 		</view>
@@ -180,17 +231,17 @@
 				}
 				return 'QY' + str;
 			},
-			ageFormat(age: any){
+			ageFormat(age : any) {
 				let year = Math.floor(age / 365);
 				let month = Math.floor((age % 365) / 30);
 				let day = age % 30;
-				if(age < 30){
+				if (age < 30) {
 					return day + '天';
-				} else if(day < 100){
+				} else if (day < 100) {
 					return month + '个月' + (day ? (day + '天') : '')
-				} else if(day < 365){
+				} else if (day < 365) {
 					return month + '个月';
-				} else if(day < 365 * 3){
+				} else if (day < 365 * 3) {
 					return year + '年' + (month ? (month + '个月') : '')
 				} else {
 					return year + '年'
@@ -205,14 +256,22 @@
 		static : string = OSS_STATIC;
 		superiorInfo : any = {};
 		shareInfo : any = {};
-		babyList: any = [];
+		babyList : any = [];
+		genderMap : any = {
+			1: '小王子',
+			2: '小公主'
+		};
+		roleMap : any = {
+			0: '普通用户',
+			1: '会员'
+		}
 		onLoad() {
 			// uni.setNavigationBarColor({
 			// 	frontColor: '#ffffff', //文字颜色
 			// 	backgroundColor: '#ffffff' //底部背景色
 			// });
 		}
-		
+
 		async onShow() {
 			this.$nextTick(function () {
 				uni.hideTabBar();
@@ -220,6 +279,7 @@
 			this.setTabBarIndex(4);
 			this.getUserInfo();
 			this.getBabyListBySelf();
+			this.getShareInfo();
 			// #ifdef MP-WEIXIN
 			this.$nextTick(() => {
 				setTimeout(() => {
@@ -232,10 +292,17 @@
 		onShareAppMessage() {
 			return {
 				title: '育百通',
-				path: '/pages/front/front?s=1&uid=' + this._userInfo.uid,
+				path: '/pages/front/front',
 				imageUrl: this.shareInfo.pic
 			};
 		}
+		
+		onShareTimeline() {
+			return {
+				title: '育百通', // 分享标题
+				imageUrl: this.shareInfo.pic, // 分享的图片路径,可选
+			};
+		}
 
 		checkPrivacySetting() {
 			// @ts-ignore
@@ -268,7 +335,7 @@
 				complete: () => { }
 			})
 		}
-		
+
 		// getBabyList(){
 		// 	this.$http
 		// 		.get({
@@ -280,6 +347,17 @@
 		// 			console.log(err);
 		// 		});
 		// }
+		getShareInfo() {
+			this.$http
+				.get({
+					url: this.$api.getShareInfo
+				})
+				.then((res : any) => {
+					this.shareInfo = res;
+				}, (err : any) => {
+					console.log(err);
+				});
+		}
 
 		getBabyListBySelf() {
 			this.$http
@@ -292,8 +370,8 @@
 					console.log(err);
 				});
 		}
-		
-		toPage(path : any, data: any) {
+
+		toPage(path : any, data : any) {
 			if (!path) {
 				uni.showToast({
 					title: '敬请期待',
@@ -311,21 +389,22 @@
 <style lang="scss" scoped>
 	/deep/.uni-navbar__header {
 		padding: 0 !important;
-	
+
 		.uni-navbar__header-container {
 			padding: 0 !important;
 		}
 	}
-	.user-box{
+
+	.user-box {
 		.nav-bg {
 			width: 100%;
 			// background: linear-gradient(180deg, #FFD9F9 0%, #F1E6FF 67.19%, #F1E9FE 82.84%, #FBF6FC 100%);
-		
+
 			.status-bar {
 				// height: var(--status-bar-height);
 				height: 44px;
 			}
-		
+
 			.nav-title {
 				width: 100%;
 				box-sizing: border-box;
@@ -333,30 +412,36 @@
 				padding: 0 vw(3);
 				@include flex-x();
 				@include word-vw(16, #000);
-				.left, .right{
+
+				.left,
+				.right {
 					width: vw(60);
 					@include flex-x(flex-satrt);
 				}
-				.title{
+
+				.title {
 					flex: 1;
 					@include flex-x(center);
 				}
 			}
-			.tab-scroll{
+
+			.tab-scroll {
 				margin: vw(1) 0 vw(5);
 			}
-			.nav-list{
+
+			.nav-list {
 				height: vw(36);
 				@include flex-x(flex-start);
 				width: fit-content;
 				// padding: 0 vw(12);
 				box-sizing: border-box;
+
 				// overflow-x: auto;
 				// &::-webkit-scrollbar {
 				//   width: 0px;
 				//   height: 0px;
 				// }
-				.nav-item{
+				.nav-item {
 					padding: 0 vw(12);
 					height: vw(32);
 					border-radius: vw(16);
@@ -364,11 +449,13 @@
 					position: relative;
 					@include word-vw(12, #666);
 					white-space: nowrap;
-					&.active{
+
+					&.active {
 						font-weight: bold;
 						color: #000;
 						background: #fff;
-						.bar{
+
+						.bar {
 							height: vw(3);
 							border-radius: vw(2);
 							width: vw(12);
@@ -377,16 +464,19 @@
 							bottom: vw(0);
 						}
 					}
-					&:nth-of-type(1){
+
+					&:nth-of-type(1) {
 						margin-left: vw(12);
 					}
-					&:nth-last-of-type(1){
+
+					&:nth-last-of-type(1) {
 						margin-right: vw(12);
 					}
 				}
 			}
 		}
-		.bg{
+
+		.bg {
 			width: 100%;
 			height: vw(240);
 			background: linear-gradient(180deg, #DEE7FF 0%, #F1DCF7 49.31%, #F8E4F8 77.08%, #FDF1F0 100%);
@@ -397,29 +487,53 @@
 			height: vw(160);
 			/* #endif */
 		}
-		.container{
+
+		.container {
 			padding-bottom: vw(150);
 			@include flex-y();
-			.user-info{
+
+			.user-info {
 				width: 100%;
 				height: vw(90);
 				@include flex-x();
 				padding: 0 vw(16);
 				box-sizing: border-box;
-				.pic{
-					@include wh(64, 64);
-					border-radius: vw(32);
+
+				.pic-box {
 					margin-right: vw(6);
+					position: relative;
+
+					.pic {
+						@include wh(64, 64);
+						border-radius: vw(32);
+					}
+
+					.level {
+						height: vw(20);
+						border-radius: vw(10);
+						background: linear-gradient(90deg, rgba(79, 161, 255, 1) 0%, rgba(111, 151, 252, 1) 100%);
+						padding: 0 vw(12);
+						position: absolute;
+						bottom: vw(-5);
+						white-space: nowrap;
+						left: 50%;
+						transform: translateX(-50%);
+						@include word-vw(12, #fff);
+						@include flex-x(center);
+					}
 				}
-				.info{
+
+				.info {
 					flex: 1;
 					height: vw(64);
 					@include flex-y(space-between, flex-start);
-					.name{
+
+					.name {
 						@include word-vw(18, #333);
 						font-weight: 550;
 					}
-					.role{
+
+					.role {
 						height: vw(18);
 						padding: 0 vw(5);
 						border-radius: vw(9);
@@ -427,152 +541,248 @@
 						@include word-vw(10, #fff);
 						@include flex-x(center);
 					}
-					.id{
+
+					.id {
 						@include word-vw(12, #333);
 					}
 				}
-				.btn{
-					.pic{
+
+				.btn {
+					.pic {
 						width: vw(18);
 					}
 				}
 			}
-			.member-box{
-				width: vw(345);
-				height: vw(64);
-				background: #333;
-				box-shadow: 0 vw(2) vw(4) rgba(0, 0, 0, 0.25);
-				@include flex-x(flex-start);
+
+			.monery-box {
+				width: 100%;
+				height: vw(80);
 				border-radius: vw(10);
+				background: #fff;
+				@include flex-x(center);
 				position: relative;
-				.num{
-					width: vw(90);
-					@include flex-y();
-					@include word-vw(10, #fff);
-					text{
-						@include word-vw(30, #fff);
-						line-height: vw(30);
-						margin-bottom: vw(2);
-					}
-				}
-				.vertical-line{
-					width: 0;
-					height: vw(25);
-					border-right: vw(1) solid rgba(255, 255, 255, 0.22);
+				margin-top: vw(45);
+
+				.item-box {
+					width: 100%;
+					position: absolute;
+					@include flex-x(center);
+					bottom: vw(16);
 				}
-				.tip-box{
-					padding-left: vw(18);
-					@include flex-y(space-between, flex-start);
-					.tip-top{
-						@include word-vw(12, #FAFAFA);
-						text{
-							@include word-vw(16, #fff);
-							margin-right: vw(10);
+
+				.item {
+					width: vw(170);
+					height: vw(100);
+					position: relative;
+					border-radius: vw(10);
+					overflow: hidden;
+					box-shadow: 0px -4px 12px rgba(0, 0, 0, 0.09);
+
+					.pic {
+						height: vw(60);
+						bottom: vw(6);
+						right: vw(10);
+						position: absolute;
+					}
+
+					.item-top {
+						height: vw(50);
+						background: linear-gradient(90deg, rgba(255, 87, 51, 1) 0%, rgba(255, 163, 51, 1) 100%);
+
+						view {
+							width: 100%;
+							height: vw(30);
+							box-sizing: border-box;
+							@include flex-x();
+							padding: vw(12) vw(8) 0;
+							// margin-top: vw(8);
+							@include word-vw(12, #fff);
+
+							text {
+								@include word-vw(24, #fff);
+								font-weight: bold;
+							}
 						}
 					}
-					.tip-bottom{
-						@include word-vw(10, rgba(255, 255, 255, 0.6));
-						margin-top: vw(6);
-						text{
-							margin-right: vw(10);
+
+					.item-bottom {
+						height: vw(50);
+						background: #FFF0ED;
+						@include flex-x(flex-start);
+
+						.btn {
+							padding: 0 vw(10);
+							height: vw(26);
+							border-radius: vw(13);
+							background: #FF5733;
+							@include flex-x(center);
+							@include word-vw(14, #fff);
+							margin-left: vw(8);
+
+							.arrow {}
+						}
+					}
+
+					&:nth-of-type(2) {
+						margin-left: vw(10);
+
+						.item-top {
+							background: linear-gradient(90deg, rgba(124, 151, 255, 1) 0%, rgba(155, 125, 255, 1) 100%);
+							;
+						}
+
+						.item-bottom {
+							background: #EBF0FF;
+
+							.btn {
+								background: #7C97FF;
+							}
 						}
 					}
-				}
-				.pic{
-					width: vw(32);
-					position: absolute;
-					bottom: vw(12);
-					right: vw(12);
 				}
 			}
-			.baby-box{
+
+			.baby-box {
 				width: 100%;
-				height: vw(184);
+				height: vw(190);
 				margin-top: vw(10);
 				border-radius: vw(10);
 				background: #fff;
 				padding: vw(12) 0;
 				box-sizing: border-box;
-				.baby-list{
-					.baby-swiper{
-						height: vw(100);
-						.baby-item{
+
+				.baby-list {
+					.baby-swiper {
+						height: vw(180);
+
+						.baby-item {
 							margin: 0 vw(15);
 							// width: vw(290);
-							height: vw(72);
-							background: linear-gradient(90deg, #E6F3FF 0%, #E6E9FF 100%);
-							border-radius: vw(5);
-							@include flex-x();
+							height: vw(150);
+							background: #E6EAFF;
+							border-radius: vw(10);
+							@include flex-y(center);
 							padding: 0 vw(12);
-							.pic{
-								@include wh(44, 44);
-								border: vw(2) solid #fff;
-								border-radius: vw(22);
-							}
-							.info{
-								flex: 1;
-								margin-left: vw(10);
-								height: vw(40);
-								@include flex-y(center, flex-start);
-								.baby-name{
-									@include word-vw(16, #333);
-									font-weight: bold;
+
+							.baby-info-box {
+								width: 100%;
+								@include flex-x();
+
+								.pic {
+									@include wh(44, 44);
+									border: vw(2) solid #fff;
+									border-radius: vw(22);
 								}
-								.family-name{
-									@include word-vw(12, #8C8C8C);
-									margin-top: vw(3);
+
+								.info {
+									flex: 1;
+									margin-left: vw(10);
+									height: vw(40);
+									@include flex-y(center, flex-start);
+
+									.baby-name {
+										@include word-vw(16, #333);
+										font-weight: bold;
+									}
+
+									.gender {
+										@include word-vw(12, #8C8C8C);
+										margin-top: vw(3);
+									}
+								}
+
+								.age {
+									@include word-vw(12, #333);
+									@include flex-x(flex-start);
+									font-weight: bold;
+
+									.icon {
+										margin-left: vw(3);
+									}
 								}
 							}
-							.age{
-								@include word-vw(12, #333);
-								@include flex-x(flex-start);
-								font-weight: bold;
-								.icon{
-									margin-left: vw(3);
+
+							.baby-option-box {
+								width: 100%;
+								// flex: 1;
+								@include flex-x();
+								// padding: 0 vw(12);
+								box-sizing: border-box;
+								margin-top: vw(12);
+
+								.option-item {
+									@include flex-y();
+									width: 25%;
+									@include word-vw(12, #333);
+
+									.pic {
+										@include wh(36, 36);
+										margin-bottom: vw(6);
+									}
 								}
 							}
 						}
-					}
-				}
-				.baby-option-box{
-					width: 100%;
-					flex: 1;
-					@include flex-x();
-					padding: 0 vw(12);
-					box-sizing: border-box;
-					margin-top: vw(3);
-					.option-item{
-						@include flex-y();
-						width: 25%;
-						@include word-vw(12, #333);
-						.pic{
-							@include wh(32, 32);
-							margin-bottom: vw(6);
+
+						.add-baby {
+							@include word-vw(20, #A8BAFF);
+
+							.icon {
+								margin-top: vw(12);
+							}
 						}
 					}
 				}
 			}
-			.option-box{
+
+			.option-box {
 				width: 100%;
 				margin-top: vw(10);
-				.option-item{
-					height: vw(44);
-					width: 100%;
+				background: #fff;
+				padding: vw(8) vw(20);
+				box-sizing: border-box;
+				border-radius: vw(10);
+
+				.option-title {
+					height: vw(20);
+					@include word-vw(16, #333);
+					font-weight: bold;
+					margin: vw(10) 0;
+				}
+
+				.option-list {
+					@include flex-x(flex-start);
+					flex-wrap: wrap;
+				}
+
+				.option-item {
+					// height: vw(44);
+					width: vw(67);
 					margin-bottom: vw(1);
-					@include flex-x();
+					// @include flex-y(center, center);
 					background: #fff;
-					padding: 0 vw(18);
 					box-sizing: border-box;
-					.left{
-						@include flex-x();
+					margin: vw(12) 0;
+
+					.left {
+						@include flex-y(center, center);
 						@include word-vw(14, #333);
-						.icon-box{
+						background: transparent;
+						margin: 0;
+						padding: 0;
+						line-height: inherit;
+
+						&::after {
+							border-width: 0;
+						}
+
+						.icon-box {
 							@include wh(24, 24);
 							@include flex-x(center);
-							margin-right: vw(12);
+							// margin-right: vw(12);
 							border-radius: vw(4);
-							.icon{
-							}
+							margin-bottom: vw(8);
+
+							.icon {}
 						}
 					}
 				}

+ 4 - 0
src/router/index.ts

@@ -40,6 +40,10 @@ const router = createRouter({
 router.beforeEach(async (to: any, from: any, next: any) => {
 	let referrer = getSuperior(from, to);
 	referrer && Store.commit(`base/${types.SET_REFERRERID}`, referrer);
+	// console.log(from, to);
+	// if(to.name === 'login' && from.name === 'login') {
+	// 	return;
+	// };
 	if (to.name === 'login' || to.name === 'register' || to.name === 'password') {
 		next();
 		return;

+ 1 - 1
src/uni.scss

@@ -104,7 +104,7 @@ $grayD8: #d8d8d8;
 $grayD: #dddddd;
 $line-color: #f8f8f8;
 $bk-color: #17A272;
-$btn-color: #1C8A64;
+$btn-color: #5383FC;
 //外边距
 $small-margin: (10 / 375) *100vw;
 $middle-margin: (20 / 375) *100vw;

Some files were not shown because too many files changed in this diff