gongdecai 2 tahun lalu
melakukan
3a1454ca79
100 mengubah file dengan 26306 tambahan dan 0 penghapusan
  1. TEMPAT SAMPAH
      .DS_Store
  2. 2 0
      .gitattributes
  3. 70 0
      .gitignore
  4. 149 0
      HX-SHOP/App.vue
  5. 51 0
      HX-SHOP/README.md
  6. 57 0
      HX-SHOP/common/appupgrade.js
  7. 0 0
      HX-SHOP/common/city.data.js
  8. 1658 0
      HX-SHOP/common/iconfont/iconfont.css
  9. 1115 0
      HX-SHOP/common/main.css
  10. 404 0
      HX-SHOP/common/pinyin/pinyin.js
  11. 37 0
      HX-SHOP/common/pinyin/pinyin2.js
  12. 57 0
      HX-SHOP/common/pinyin/pinyin3.js
  13. 627 0
      HX-SHOP/common/testdata.js
  14. 20 0
      HX-SHOP/common/vmeitime-http/app.js
  15. 15 0
      HX-SHOP/common/vmeitime-http/carpool.js
  16. 20 0
      HX-SHOP/common/vmeitime-http/code.js
  17. 188 0
      HX-SHOP/common/vmeitime-http/index.js
  18. 191 0
      HX-SHOP/common/vmeitime-http/interface.js
  19. 198 0
      HX-SHOP/common/vmeitime-http/readme.md
  20. 91 0
      HX-SHOP/common/vmeitime-http/user.js
  21. 90 0
      HX-SHOP/components/flyInCart.vue
  22. 287 0
      HX-SHOP/components/hx-comment/hx-comment.vue
  23. 125 0
      HX-SHOP/components/hx-jump-ball/README.md
  24. 239 0
      HX-SHOP/components/hx-jump-ball/hx-jump-ball - ╕▒▒╛.vue
  25. 266 0
      HX-SHOP/components/hx-jump-ball/hx-jump-ball.vue
  26. 86 0
      HX-SHOP/components/hx-load/hx-load.vue
  27. 255 0
      HX-SHOP/components/hx-navbar/README.md
  28. 635 0
      HX-SHOP/components/hx-navbar/hx-navbar.vue
  29. 215 0
      HX-SHOP/components/hx-preview-img/hx-preview-img.vue
  30. 202 0
      HX-SHOP/components/hx-share/hx-share.vue
  31. 55 0
      HX-SHOP/components/mescroll-uni/components/mescroll-down.css
  32. 47 0
      HX-SHOP/components/mescroll-uni/components/mescroll-down.vue
  33. 90 0
      HX-SHOP/components/mescroll-uni/components/mescroll-empty.vue
  34. 81 0
      HX-SHOP/components/mescroll-uni/components/mescroll-top.vue
  35. 46 0
      HX-SHOP/components/mescroll-uni/components/mescroll-up.css
  36. 39 0
      HX-SHOP/components/mescroll-uni/components/mescroll-up.vue
  37. 10 0
      HX-SHOP/components/mescroll-uni/mescroll-body.css
  38. 292 0
      HX-SHOP/components/mescroll-uni/mescroll-body.vue
  39. 60 0
      HX-SHOP/components/mescroll-uni/mescroll-mixins.js
  40. 34 0
      HX-SHOP/components/mescroll-uni/mescroll-uni-option.js
  41. 29 0
      HX-SHOP/components/mescroll-uni/mescroll-uni.css
  42. 862 0
      HX-SHOP/components/mescroll-uni/mescroll-uni.js
  43. 364 0
      HX-SHOP/components/mescroll-uni/mescroll-uni.vue
  44. 23 0
      HX-SHOP/components/mescroll-uni/mixins/mescroll-comp.js
  45. 48 0
      HX-SHOP/components/mescroll-uni/mixins/mescroll-more-item.js
  46. 56 0
      HX-SHOP/components/mescroll-uni/mixins/mescroll-more.js
  47. 119 0
      HX-SHOP/components/mix-list-cell.vue
  48. 96 0
      HX-SHOP/components/uni-icons/icons.js
  49. 10 0
      HX-SHOP/components/uni-icons/uni-icons.vue
  50. 209 0
      HX-SHOP/components/uni-number-box/uni-number-box.vue
  51. 263 0
      HX-SHOP/components/uni-popup/uni-popup.vue
  52. 141 0
      HX-SHOP/components/uni-rate/uni-rate.vue
  53. 279 0
      HX-SHOP/components/uni-transition/uni-transition.vue
  54. 36 0
      HX-SHOP/components/watch-login/css/icon.css
  55. 109 0
      HX-SHOP/components/watch-login/watch-button.vue
  56. 208 0
      HX-SHOP/components/watch-login/watch-input.vue
  57. 18 0
      HX-SHOP/config.js
  58. 37 0
      HX-SHOP/main.js
  59. 81 0
      HX-SHOP/manifest.json
  60. 11 0
      HX-SHOP/package-lock.json
  61. 222 0
      HX-SHOP/pages.json
  62. 193 0
      HX-SHOP/pages/base/about.vue
  63. 45 0
      HX-SHOP/pages/base/features.vue
  64. 65 0
      HX-SHOP/pages/base/help_feedback.vue
  65. 23 0
      HX-SHOP/pages/base/help_problem.vue
  66. 288 0
      HX-SHOP/pages/base/protocol/protocol.vue
  67. 36 0
      HX-SHOP/pages/base/release_notes.vue
  68. 15 0
      HX-SHOP/pages/index/detail.vue
  69. 812 0
      HX-SHOP/pages/index/index.vue
  70. 1568 0
      HX-SHOP/pages/index/index3.vue
  71. 342 0
      HX-SHOP/pages/map/location.nvue
  72. 153 0
      HX-SHOP/pages/market/market.vue
  73. 733 0
      HX-SHOP/pages/order/order.vue
  74. 336 0
      HX-SHOP/pages/order/pay.vue
  75. 869 0
      HX-SHOP/pages/order/preview.vue
  76. 2413 0
      HX-SHOP/pages/product/product.vue
  77. 49 0
      HX-SHOP/pages/search/search.vue
  78. 1762 0
      HX-SHOP/pages/store/index - ╕▒▒╛ (2).vue
  79. 2047 0
      HX-SHOP/pages/store/index.vue
  80. 404 0
      HX-SHOP/pages/user/account_security/address_book.vue
  81. 89 0
      HX-SHOP/pages/user/account_security/bind_phone.vue
  82. 52 0
      HX-SHOP/pages/user/account_security/forget_password.vue
  83. 96 0
      HX-SHOP/pages/user/account_security/phone.vue
  84. 62 0
      HX-SHOP/pages/user/account_security/security.vue
  85. 332 0
      HX-SHOP/pages/user/account_security/update_password.vue
  86. 125 0
      HX-SHOP/pages/user/account_security/update_phone.vue
  87. 322 0
      HX-SHOP/pages/user/account_security/verification_phone.vue
  88. 161 0
      HX-SHOP/pages/user/address/address.vue
  89. 174 0
      HX-SHOP/pages/user/address/addressManage.vue
  90. 26 0
      HX-SHOP/pages/user/bash/bash.vue
  91. 458 0
      HX-SHOP/pages/user/center/center.vue
  92. 446 0
      HX-SHOP/pages/user/coupon/coupon.vue
  93. 239 0
      HX-SHOP/pages/user/forget/forget.vue
  94. 81 0
      HX-SHOP/pages/user/login/login.vue
  95. 70 0
      HX-SHOP/pages/user/register/register.vue
  96. 95 0
      HX-SHOP/pages/user/setting/setting.vue
  97. TEMPAT SAMPAH
      HX-SHOP/static/img/coupon_dq.png
  98. TEMPAT SAMPAH
      HX-SHOP/static/img/coupon_gq.png
  99. TEMPAT SAMPAH
      HX-SHOP/static/img/coupon_lq.png
  100. TEMPAT SAMPAH
      HX-SHOP/static/img/index/cs.png

TEMPAT SAMPAH
.DS_Store


+ 2 - 0
.gitattributes

@@ -0,0 +1,2 @@
+*.sql linguist-language=java
+*.html linguist-language=java

+ 70 - 0
.gitignore

@@ -0,0 +1,70 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**
+!**/src/test/**
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+#/build/
+
+### VS Code ###
+.vscode/
+
+### maven ###
+.mvn
+mvnw
+mvnw.cmd
+
+###properties###
+/unimall-launcher/src/main/resources/application-dev.properties
+/unimall-launcher/src/main/resources/application-prd.properties
+
+### target ###
+/target/
+/unimall-admin-api/target/
+/unimall-app-api/target/
+/unimall-biz/target/
+/unimall-data/target/
+/unimall-core/target/
+/unimall-launcher/target/
+/unimall-plugin-core/target/
+/unimall-app/unpackage/dist/
+/unimall-app/unpackage/resources/
+/unimall-app/unpackage/debug/
+/unimall-admin/dist.zip
+
+###node_modules###
+/unimall-admin/node_modules/
+/unimall-app/node_modules/
+
+
+###logs###
+unimall.log
+unimall.log.*.gz
+unimall.log.*.tmp
+
+
+### plugins ###
+/plugins/
+/unimall-app/pages/plugins/
+/unimall-admin/src/views/plugins/

+ 149 - 0
HX-SHOP/App.vue

@@ -0,0 +1,149 @@
+<script>
+	import Vue from 'vue'
+	export default {
+		onLaunch: function() {
+			//检查是否登录
+			//this.$api.user.hasLogin();
+
+
+			//字符串加密
+			Vue.prototype.$strEncode = function($data) {
+					if (typeof $data == 'object') {
+						$data = JSON.stringify($data);
+					}
+					var key = CryptoJS.enc.Latin1.parse('BC1F5E3BAEE198AC');
+					var iv = CryptoJS.enc.Latin1.parse('1F5E3BAEE198ACE1');
+					var encoded = CryptoJS.AES.encrypt($data, key, {
+						iv: iv,
+						mode: CryptoJS.mode.CBC, //模式
+						adding: CryptoJS.pad.ZeroPadding
+					}).toString();
+					if (!encoded) {
+						return '';
+					}
+					return encoded
+				},
+
+
+				Vue.prototype.clientType = function() {
+					let c = 1; //默认为电脑
+					// #ifdef APP-PLUS
+					switch (uni.getSystemInfoSync().platform) {
+						case 'android':
+							c = 3;
+							break;
+						case 'ios':
+							c = 4;
+							break;
+						default:
+
+					}
+					// #endif	
+
+					// #ifdef h5
+					c = 2;
+					// #endif	
+
+					// #ifdef MP-WEIXIN
+					c = 5;
+					// #endif
+					return c
+				}
+
+			uni.getSystemInfo({
+				success: function(e) {
+					// #ifndef MP
+					Vue.prototype.StatusBar = e.statusBarHeight;
+					if (e.platform == 'android') {
+						Vue.prototype.CustomBar = e.statusBarHeight + 50;
+					} else {
+						Vue.prototype.CustomBar = e.statusBarHeight + 45;
+					};
+					// #endif
+
+					// #ifdef MP-WEIXIN
+					Vue.prototype.StatusBar = e.statusBarHeight;
+					let custom = wx.getMenuButtonBoundingClientRect();
+					Vue.prototype.Custom = custom;
+					Vue.prototype.CustomBar = custom.bottom + custom.top - e.statusBarHeight;
+					// #endif		
+
+					// #ifdef MP-ALIPAY
+					Vue.prototype.StatusBar = e.statusBarHeight;
+					Vue.prototype.CustomBar = e.statusBarHeight + e.titleBarHeight;
+					// #endif
+				}
+			})
+
+			//关闭页面
+			Vue.prototype.closePage = function() {
+				console.log(getCurrentPages());
+				if (getCurrentPages().length > 1) {
+					uni.navigateBack();
+				} else {
+					// #ifdef H5
+					history.back()
+					// #endif
+					// #ifndef H5
+					uni.reLaunch({
+						url: '/pages/index/index'
+					});
+					// #endif
+
+				}
+			}
+
+
+			/**
+			 * 统一跳转接口,拦截未登录路由
+			 * navigator标签现在默认没有转场动画,所以用view
+			 */
+			Vue.prototype.navTo = function(url) {
+				// if(!this.hasLogin){
+				// 	url = '/pages/user/login/login';
+				// }
+				uni.navigateTo({
+					url: url
+				})
+			}
+		},
+		onShow: function() {
+			try {
+				const value = uni.getStorageSync('userData');
+				if (value) {
+					//有登录信息
+					that.$store.dispatch("setUserData", value); //存入状态
+
+				} else {
+					//用户未登录
+					/* uni.navigateTo({
+						url: '/pages/user/login/login',
+					}); */
+				}
+			} catch (e) {
+				// error
+			}
+		},
+		onHide: function() {
+			console.log('App Hide')
+		}
+	}
+</script>
+
+<style>
+	@import "/common/iconfont/iconfont.css";
+	/* #ifndef APP-PLUS-NVUE */
+	@import "/common/main.css";
+	/* #endif */
+
+	/* 骨架屏方案 */
+	.Skeleton {
+		background-color: #f3f3f3;
+		padding: 20upx 0;
+		border-radius: 6upx;
+	}
+
+	body {
+		background: #F2F2F4;
+	}
+</style>

+ 51 - 0
HX-SHOP/README.md

@@ -0,0 +1,51 @@
+
+# 使用
+
+#### 关于测试数据
+在 common/testdata.js
+
+#### 注 :目前版本中仅商户页面不支持小程序,因为新增了多规格功能还不兼容小程序,后期会兼容
+
+
+# 效果图
+
+![](https://imgs.1op.cn/i/2020/04/06/119muu5.jpg)
+![](https://imgs.1op.cn/i/2020/04/06/119myep.jpg)
+![](https://imgs.1op.cn/i/2020/04/11/10vab3i.jpg)
+![](https://imgs.1op.cn/i/2020/04/11/10vafds.jpg)
+
+# 关于 HX-SHOP
+
+| 项目 | 技术栈 | 开源地址 | 
+| --- | --- | ---- |
+| uniapp 移动端| vue | [https://gitee.com/code_yu/hxshop-uni-app](https://gitee.com/code_yu/hxshop-uni-app) |
+| Admin前端(开发中) | vue-element-admin | [https://gitee.com/code_yu/hx-admin-web](https://gitee.com/code_yu/hx-admin-web) |
+| Admin后端(开发中) | ThinkPHP6+ | [https://gitee.com/code_yu/hx-admin](https://gitee.com/code_yu/hx-admin) |
+| HX 使用文档(规划中) | vuepress | [https://code_yu.gitee.io/hx-admin-docs/](https://code_yu.gitee.io/hx-admin-docs/) |
+
+
+### HX-SHOP 社区
+为方便交流,QQ群 954035921,有什么问题可以加群讨论
+
+### 觉得不错就打赏点吧!一毛五毛都随你!
+![](https://imgs.1op.cn/i/2020/04/15/zbq6cj.png)
+
+
+### 鸣谢
+
+| 打赏人/单位 | 金额 | 相关 |
+|:-----------:| :-----|:----:|
+|    掮客     |  ¥600 |  -   |
+|   笑宝宝    |   ¥50 |  -   |
+|   ~白色的梦    |   ¥30 |  -   |
+|    呦呦切克闹    |   ¥20 |  -   |
+|    天色    |   ¥10 |  -   |
+|    caiyu    |   ¥10 |  -   |
+|   JackLuo   |    ¥5 |  -   |
+|   命运之歌   |    ¥5 |  -   |
+
+如有遗漏请联系我,微信/QQ:1012083552
+
+
+
+

+ 57 - 0
HX-SHOP/common/appupgrade.js

@@ -0,0 +1,57 @@
+import api from '@/common/vmeitime-http/'
+import conf from '@/config.js'
+
+export default{
+	checkUpgrade(wgtVer){
+		let that = this;
+		plus.nativeUI.showWaiting("检测更新...");
+		api.app.upgrade({version:wgtVer}).then((res)=>{
+			plus.nativeUI.closeWaiting();
+			let resData = res.data;
+			if( parseInt(resData.code) ==0 ){                           
+				//可以升级
+				plus.nativeUI.confirm("检查到当前版本有最新更新,下载升级?",
+					function(event){
+						if(event.index ==0){
+							console.log('下载地址:'+ conf.server + resData.data.url)
+							that.downWgt(conf.server + resData.data.url); //下载更新版的地址
+						}                        
+					} ,'系统消息',['马上升级','下次再说']);                
+			} else{  
+				plus.nativeUI.toast("无新版本可更新!");
+			}
+		}).catch((e)=>{
+			plus.nativeUI.closeWaiting();
+			 plus.nativeUI.toast('检测更新失败!') ;
+		})
+	},
+	// 下载wgt文件
+	downWgt(wgtUrl){
+		let that = this;
+		plus.nativeUI.showWaiting("下载更新文件...");
+		plus.downloader.createDownload( wgtUrl, {filename:"_downloads/update/"}, function(d,status){
+			if ( status == 200 ) { 
+				//console.log("下载wgt成功:"+d.filename);
+				that.installWgt(d.filename); // 安装wgt包
+			} else {
+				//console.log("下载wgt失败!");
+				plus.nativeUI.alert("下载更新失败!");
+			}
+			plus.nativeUI.closeWaiting();
+		}).start();
+	},
+	
+	// 更新应用资源  
+	installWgt(path){
+		plus.nativeUI.showWaiting("正在安装更新文件...");
+		plus.runtime.install(path,{},function(){
+			plus.nativeUI.closeWaiting();        
+			plus.nativeUI.alert("应用资源更新完成!",function(){
+				plus.runtime.restart();
+			});
+		},function(e){
+			plus.nativeUI.closeWaiting();        
+			plus.nativeUI.alert("安装更新文件失败["+e.code+"]:"+e.message);
+		});
+	}	
+}

File diff ditekan karena terlalu besar
+ 0 - 0
HX-SHOP/common/city.data.js


+ 1658 - 0
HX-SHOP/common/iconfont/iconfont.css

@@ -0,0 +1,1658 @@
+@font-face {
+  font-family: 'iconfont';  /* project id 1380649 */
+  src: url('https://at.alicdn.com/t/font_1380649_u1j4yykb94h.eot');
+    src: url('https://at.alicdn.com/t/font_1380649_u1j4yykb94h.eot?#iefix') format('embedded-opentype'),
+    url('https://at.alicdn.com/t/font_1380649_u1j4yykb94h.woff2') format('woff2'),
+    url('https://at.alicdn.com/t/font_1380649_u1j4yykb94h.woff') format('woff'),
+    url('https://at.alicdn.com/t/font_1380649_u1j4yykb94h.ttf') format('truetype'),
+    url('https://at.alicdn.com/t/font_1380649_u1j4yykb94h.svg#iconfont') format('svg');
+}
+.hxicon{
+	font-family: iconfont;
+}
+/* #ifndef APP-PLUS-NVUE */
+[class*="hxicon-"] {
+	font-family: "iconfont" !important;
+	font-size: inherit;
+	font-style: normal;
+	/*抗锯齿*/
+	-webkit-font-smoothing: antialiased;
+	-moz-osx-font-smoothing: grayscale;
+}
+
+.hxicon-weixinzhifu:before {
+  content: "\e70c";
+}
+
+.hxicon-zhifubaozhifu:before {
+  content: "\e648";
+}
+
+.hxicon-jiashizheng:before {
+  content: "\ed14";
+}
+
+.hxicon-shenfenzhengrenzheng-:before {
+  content: "\ed12";
+}
+
+.hxicon-shenfenzheng:before {
+  content: "\ed13";
+}
+
+.hxicon-shuangxiangjiantou:before {
+  content: "\ed0f";
+}
+
+.hxicon-shengxianguoshu:before {
+  content: "\ed05";
+}
+
+.hxicon-zufangyuechifangzimianxing:before {
+  content: "\ed06";
+}
+
+.hxicon-zufangyuechifangzixianxing:before {
+  content: "\ed07";
+}
+
+.hxicon-zhaopin:before {
+  content: "\ed08";
+}
+
+.hxicon-zhaopin1:before {
+  content: "\ed09";
+}
+
+.hxicon-ershou:before {
+  content: "\ed04";
+}
+
+.hxicon-fuwu1:before {
+  content: "\ed03";
+}
+
+.hxicon-yaopin:before {
+  content: "\e600";
+}
+
+.hxicon-chuzu:before {
+  content: "\ed02";
+}
+
+.hxicon-qichepeijian:before {
+  content: "\e602";
+}
+
+.hxicon-shipinyinliao:before {
+  content: "\e603";
+}
+
+.hxicon-zhibojian:before {
+  content: "\e604";
+}
+
+.hxicon-roundright:before {
+  content: "\e65b";
+}
+
+.hxicon-my_light:before {
+  content: "\e7d6";
+}
+
+.hxicon-search:before {
+  content: "\e65c";
+}
+
+.hxicon-community_light:before {
+  content: "\e7d7";
+}
+
+.hxicon-taxi:before {
+  content: "\e65d";
+}
+
+.hxicon-cart_light:before {
+  content: "\e7d8";
+}
+
+.hxicon-timefill:before {
+  content: "\e65e";
+}
+
+.hxicon-we_light:before {
+  content: "\e7d9";
+}
+
+.hxicon-time:before {
+  content: "\e65f";
+}
+
+.hxicon-home_fill_light:before {
+  content: "\e7da";
+}
+
+.hxicon-unfold:before {
+  content: "\e661";
+}
+
+.hxicon-cart_fill_light:before {
+  content: "\e7db";
+}
+
+.hxicon-warnfill:before {
+  content: "\e662";
+}
+
+.hxicon-community_fill_light:before {
+  content: "\e7dc";
+}
+
+.hxicon-warn:before {
+  content: "\e663";
+}
+
+.hxicon-my_fill_light:before {
+  content: "\e7dd";
+}
+
+.hxicon-camerafill:before {
+  content: "\e664";
+}
+
+.hxicon-we_fill_light:before {
+  content: "\e7de";
+}
+
+.hxicon-camera:before {
+  content: "\e665";
+}
+
+.hxicon-skin_light:before {
+  content: "\e7df";
+}
+
+.hxicon-commentfill:before {
+  content: "\e666";
+}
+
+.hxicon-search_light:before {
+  content: "\e7e0";
+}
+
+.hxicon-comment:before {
+  content: "\e667";
+}
+
+.hxicon-scan_light:before {
+  content: "\e7e1";
+}
+
+.hxicon-likefill:before {
+  content: "\e668";
+}
+
+.hxicon-people_list_light:before {
+  content: "\e7e2";
+}
+
+.hxicon-like:before {
+  content: "\e669";
+}
+
+.hxicon-message_light:before {
+  content: "\e7e3";
+}
+
+.hxicon-notificationfill:before {
+  content: "\e66a";
+}
+
+.hxicon-close_light:before {
+  content: "\e7e4";
+}
+
+.hxicon-notification:before {
+  content: "\e66b";
+}
+
+.hxicon-add_light:before {
+  content: "\e7e5";
+}
+
+.hxicon-order:before {
+  content: "\e66c";
+}
+
+.hxicon-profile_light:before {
+  content: "\e7e6";
+}
+
+.hxicon-samefill:before {
+  content: "\e66d";
+}
+
+.hxicon-service_light:before {
+  content: "\e7e7";
+}
+
+.hxicon-same:before {
+  content: "\e66e";
+}
+
+.hxicon-friend_add_light:before {
+  content: "\e7e8";
+}
+
+.hxicon-deliver:before {
+  content: "\e671";
+}
+
+.hxicon-edit_light:before {
+  content: "\e7e9";
+}
+
+.hxicon-evaluate:before {
+  content: "\e672";
+}
+
+.hxicon-camera_light:before {
+  content: "\e7ea";
+}
+
+.hxicon-pay:before {
+  content: "\e673";
+}
+
+.hxicon-hot_light:before {
+  content: "\e7eb";
+}
+
+.hxicon-send:before {
+  content: "\e675";
+}
+
+.hxicon-refresh_light:before {
+  content: "\e7ec";
+}
+
+.hxicon-shop:before {
+  content: "\e676";
+}
+
+.hxicon-back_light:before {
+  content: "\e7ed";
+}
+
+.hxicon-ticket:before {
+  content: "\e677";
+}
+
+.hxicon-share_light:before {
+  content: "\e7ee";
+}
+
+.hxicon-back:before {
+  content: "\e679";
+}
+
+.hxicon-comment_light:before {
+  content: "\e7ef";
+}
+
+.hxicon-cascades:before {
+  content: "\e67c";
+}
+
+.hxicon-appreciate_light:before {
+  content: "\e7f0";
+}
+
+.hxicon-discover:before {
+  content: "\ed0a";
+}
+
+.hxicon-favor_light:before {
+  content: "\e7f1";
+}
+
+.hxicon-list:before {
+  content: "\e682";
+}
+
+.hxicon-appreciate_fill_light:before {
+  content: "\e7f2";
+}
+
+.hxicon-more:before {
+  content: "\e684";
+}
+
+.hxicon-comment_fill_light:before {
+  content: "\e7f3";
+}
+
+.hxicon-scan:before {
+  content: "\e689";
+}
+
+.hxicon-more_android_light:before {
+  content: "\e7f4";
+}
+
+.hxicon-settings:before {
+  content: "\e68a";
+}
+
+.hxicon-friend_light:before {
+  content: "\e7f5";
+}
+
+.hxicon-questionfill:before {
+  content: "\e690";
+}
+
+.hxicon-more_light:before {
+  content: "\e7f6";
+}
+
+.hxicon-question:before {
+  content: "\e691";
+}
+
+.hxicon-goods_favor_light:before {
+  content: "\e7f7";
+}
+
+.hxicon-shopfill:before {
+  content: "\e697";
+}
+
+.hxicon-goods_new_fill_light:before {
+  content: "\e7f8";
+}
+
+.hxicon-form:before {
+  content: "\e699";
+}
+
+.hxicon-goods_new_light:before {
+  content: "\e7f9";
+}
+
+.hxicon-pic:before {
+  content: "\e69b";
+}
+
+.hxicon-goods_light:before {
+  content: "\e7fa";
+}
+
+.hxicon-filter:before {
+  content: "\e69c";
+}
+
+.hxicon-medal_fill_light:before {
+  content: "\e7fb";
+}
+
+.hxicon-footprint:before {
+  content: "\e69d";
+}
+
+.hxicon-medal_light:before {
+  content: "\e7fc";
+}
+
+.hxicon-top:before {
+  content: "\e69e";
+}
+
+.hxicon-news_fill_light:before {
+  content: "\e7fd";
+}
+
+.hxicon-pulldown:before {
+  content: "\e69f";
+}
+
+.hxicon-news_hot_fill_light:before {
+  content: "\e7fe";
+}
+
+.hxicon-pullup:before {
+  content: "\e6a0";
+}
+
+.hxicon-news_hot_light:before {
+  content: "\e7ff";
+}
+
+.hxicon-right:before {
+  content: "\e6a3";
+}
+
+.hxicon-news_light:before {
+  content: "\e800";
+}
+
+.hxicon-refresh:before {
+  content: "\e6a4";
+}
+
+.hxicon-video_fill_light:before {
+  content: "\e801";
+}
+
+.hxicon-moreandroid:before {
+  content: "\e6a5";
+}
+
+.hxicon-message_fill_light:before {
+  content: "\e802";
+}
+
+.hxicon-deletefill:before {
+  content: "\e6a6";
+}
+
+.hxicon-form_light:before {
+  content: "\e803";
+}
+
+.hxicon-refund:before {
+  content: "\e6ac";
+}
+
+.hxicon-video_light:before {
+  content: "\e804";
+}
+
+.hxicon-cart:before {
+  content: "\e6af";
+}
+
+.hxicon-search_list_light:before {
+  content: "\e805";
+}
+
+.hxicon-qrcode:before {
+  content: "\e6b0";
+}
+
+.hxicon-form_fill_light:before {
+  content: "\e806";
+}
+
+.hxicon-remind:before {
+  content: "\e6b2";
+}
+
+.hxicon-global_light:before {
+  content: "\e807";
+}
+
+.hxicon-delete:before {
+  content: "\e6b4";
+}
+
+.hxicon-global:before {
+  content: "\e808";
+}
+
+.hxicon-profile:before {
+  content: "\e6b7";
+}
+
+.hxicon-favor_fill_light:before {
+  content: "\e809";
+}
+
+.hxicon-home:before {
+  content: "\e6b8";
+}
+
+.hxicon-delete_light:before {
+  content: "\e80a";
+}
+
+.hxicon-cartfill:before {
+  content: "\e6b9";
+}
+
+.hxicon-back_android:before {
+  content: "\e80b";
+}
+
+.hxicon-discoverfill:before {
+  content: "\ed0b";
+}
+
+.hxicon-back_android_light:before {
+  content: "\e80c";
+}
+
+.hxicon-homefill:before {
+  content: "\e6bb";
+}
+
+.hxicon-down_light:before {
+  content: "\e80d";
+}
+
+.hxicon-message:before {
+  content: "\e6bc";
+}
+
+.hxicon-round_close_light:before {
+  content: "\e80e";
+}
+
+.hxicon-addressbook:before {
+  content: "\e6bd";
+}
+
+.hxicon-round_close_fill_light:before {
+  content: "\e80f";
+}
+
+.hxicon-link:before {
+  content: "\e6bf";
+}
+
+.hxicon-evaluate_fill:before {
+  content: "\e810";
+}
+
+.hxicon-lock:before {
+  content: "\e6c0";
+}
+
+.hxicon-furniture:before {
+  content: "\e811";
+}
+
+.hxicon-unlock:before {
+  content: "\e6c2";
+}
+
+.hxicon-dress:before {
+  content: "\e812";
+}
+
+.hxicon-vip:before {
+  content: "\e6c3";
+}
+
+.hxicon-coffee:before {
+  content: "\e813";
+}
+
+.hxicon-activity:before {
+  content: "\e6c5";
+}
+
+.hxicon-group_light:before {
+  content: "\e814";
+}
+
+.hxicon-friendaddfill:before {
+  content: "\e6c9";
+}
+
+.hxicon-location_light:before {
+  content: "\e815";
+}
+
+.hxicon-friendadd:before {
+  content: "\e6ca";
+}
+
+.hxicon-attention_light:before {
+  content: "\e816";
+}
+
+.hxicon-friendfamous:before {
+  content: "\e6cb";
+}
+
+.hxicon-group_fill_light:before {
+  content: "\e817";
+}
+
+.hxicon-friend:before {
+  content: "\e6cc";
+}
+
+.hxicon-group_fill:before {
+  content: "\e818";
+}
+
+.hxicon-goods:before {
+  content: "\e6cd";
+}
+
+.hxicon-play_forward_fill:before {
+  content: "\e819";
+}
+
+.hxicon-selection:before {
+  content: "\e6ce";
+}
+
+.hxicon-subscription_light:before {
+  content: "\e81a";
+}
+
+.hxicon-explore:before {
+  content: "\e6d2";
+}
+
+.hxicon-deliver_fill:before {
+  content: "\ed0e";
+}
+
+.hxicon-present:before {
+  content: "\e6d3";
+}
+
+.hxicon-notice_forbid_fill:before {
+  content: "\e81c";
+}
+
+.hxicon-squarecheckfill:before {
+  content: "\e6d4";
+}
+
+.hxicon-qr_code_light:before {
+  content: "\e81d";
+}
+
+.hxicon-square:before {
+  content: "\e6d5";
+}
+
+.hxicon-settings_light:before {
+  content: "\e81e";
+}
+
+.hxicon-squarecheck:before {
+  content: "\e6d6";
+}
+
+.hxicon-pick:before {
+  content: "\e81f";
+}
+
+.hxicon-round:before {
+  content: "\e6d7";
+}
+
+.hxicon-form_favor_light:before {
+  content: "\e820";
+}
+
+.hxicon-roundaddfill:before {
+  content: "\e6d8";
+}
+
+.hxicon-round_comment_light:before {
+  content: "\e821";
+}
+
+.hxicon-roundadd:before {
+  content: "\e6d9";
+}
+
+.hxicon-phone_light:before {
+  content: "\e822";
+}
+
+.hxicon-add:before {
+  content: "\e6da";
+}
+
+.hxicon-round_down_light:before {
+  content: "\e823";
+}
+
+.hxicon-notificationforbidfill:before {
+  content: "\e6db";
+}
+
+.hxicon-friend_settings_light:before {
+  content: "\e824";
+}
+
+.hxicon-explorefill:before {
+  content: "\e6dd";
+}
+
+.hxicon-change:before {
+  content: "\e825";
+}
+
+.hxicon-fold:before {
+  content: "\e6de";
+}
+
+.hxicon-round_list_light:before {
+  content: "\e826";
+}
+
+.hxicon-game:before {
+  content: "\e6df";
+}
+
+.hxicon-ticket_fill:before {
+  content: "\e827";
+}
+
+.hxicon-redpacket:before {
+  content: "\e6e0";
+}
+
+.hxicon-round_friend_fill:before {
+  content: "\e828";
+}
+
+.hxicon-selectionfill:before {
+  content: "\e6e1";
+}
+
+.hxicon-round_crown_fill:before {
+  content: "\e829";
+}
+
+.hxicon-similar:before {
+  content: "\e6e2";
+}
+
+.hxicon-round_link_fill:before {
+  content: "\e82a";
+}
+
+.hxicon-appreciatefill:before {
+  content: "\e6e3";
+}
+
+.hxicon-round_light_fill:before {
+  content: "\e82b";
+}
+
+.hxicon-infofill:before {
+  content: "\e6e4";
+}
+
+.hxicon-round_favor_fill:before {
+  content: "\e82c";
+}
+
+.hxicon-info:before {
+  content: "\e6e5";
+}
+
+.hxicon-round_menu_fill:before {
+  content: "\e82d";
+}
+
+.hxicon-forwardfill:before {
+  content: "\e6ea";
+}
+
+.hxicon-round_location_fill:before {
+  content: "\e82e";
+}
+
+.hxicon-forward:before {
+  content: "\e6eb";
+}
+
+.hxicon-round_pay_fill:before {
+  content: "\e82f";
+}
+
+.hxicon-rechargefill:before {
+  content: "\e6ec";
+}
+
+.hxicon-round_like_fill:before {
+  content: "\e830";
+}
+
+.hxicon-recharge:before {
+  content: "\e6ed";
+}
+
+.hxicon-round_people_fill:before {
+  content: "\e831";
+}
+
+.hxicon-vipcard:before {
+  content: "\e6ee";
+}
+
+.hxicon-round_pay:before {
+  content: "\e832";
+}
+
+.hxicon-voice:before {
+  content: "\e6ef";
+}
+
+.hxicon-round_rank_fill:before {
+  content: "\e833";
+}
+
+.hxicon-voicefill:before {
+  content: "\e6f0";
+}
+
+.hxicon-round_redpacket_fill:before {
+  content: "\e834";
+}
+
+.hxicon-friendfavor:before {
+  content: "\e6f1";
+}
+
+.hxicon-round_skin_fill:before {
+  content: "\e835";
+}
+
+.hxicon-wifi:before {
+  content: "\e6f2";
+}
+
+.hxicon-round_record_fill:before {
+  content: "\e836";
+}
+
+.hxicon-share:before {
+  content: "\e6f3";
+}
+
+.hxicon-round_ticket_fill:before {
+  content: "\e837";
+}
+
+.hxicon-wefill:before {
+  content: "\e6f4";
+}
+
+.hxicon-round_redpacket:before {
+  content: "\e838";
+}
+
+.hxicon-we:before {
+  content: "\e6f5";
+}
+
+.hxicon-round_text_fill:before {
+  content: "\e839";
+}
+
+.hxicon-barcode:before {
+  content: "\e6fb";
+}
+
+.hxicon-round_ticket:before {
+  content: "\e83a";
+}
+
+.hxicon-service:before {
+  content: "\e6ff";
+}
+
+.hxicon-round_transfer_fill:before {
+  content: "\e83b";
+}
+
+.hxicon-sort:before {
+  content: "\e700";
+}
+
+.hxicon-subtitle_block_light:before {
+  content: "\e83c";
+}
+
+.hxicon-down:before {
+  content: "\e703";
+}
+
+.hxicon-warn_light:before {
+  content: "\e83d";
+}
+
+.hxicon-mobile:before {
+  content: "\e704";
+}
+
+.hxicon-round_transfer:before {
+  content: "\e83e";
+}
+
+.hxicon-mobilefill:before {
+  content: "\e705";
+}
+
+.hxicon-subtitle_unblock_light:before {
+  content: "\e83f";
+}
+
+.hxicon-copy:before {
+  content: "\e706";
+}
+
+.hxicon-round_shop_fill:before {
+  content: "\e840";
+}
+
+.hxicon-countdownfill:before {
+  content: "\e707";
+}
+
+.hxicon-oppose_fill_light:before {
+  content: "\e841";
+}
+
+.hxicon-countdown:before {
+  content: "\e708";
+}
+
+.hxicon-oppose_light:before {
+  content: "\e842";
+}
+
+.hxicon-noticefill:before {
+  content: "\e709";
+}
+
+.hxicon-living:before {
+  content: "\e843";
+}
+
+.hxicon-notice:before {
+  content: "\e70a";
+}
+
+.hxicon-goods_hot_fill:before {
+  content: "\e844";
+}
+
+.hxicon-qiang:before {
+  content: "\e70b";
+}
+
+.hxicon-ticket_money_fill:before {
+  content: "\e845";
+}
+
+.hxicon-upstagefill:before {
+  content: "\e70e";
+}
+
+.hxicon-arrow_left_fill:before {
+  content: "\e846";
+}
+
+.hxicon-upstage:before {
+  content: "\e70f";
+}
+
+.hxicon-arrow_up_fill:before {
+  content: "\e847";
+}
+
+.hxicon-babyfill:before {
+  content: "\e710";
+}
+
+.hxicon-auction:before {
+  content: "\e848";
+}
+
+.hxicon-baby:before {
+  content: "\e711";
+}
+
+.hxicon-return:before {
+  content: "\e849";
+}
+
+.hxicon-choicenessfill:before {
+  content: "\e714";
+}
+
+.hxicon-mall_light:before {
+  content: "\e84a";
+}
+
+.hxicon-choiceness:before {
+  content: "\e715";
+}
+
+.hxicon-mall_fill_light:before {
+  content: "\ed10";
+}
+
+.hxicon-clothesfill:before {
+  content: "\e716";
+}
+
+.hxicon-clothes:before {
+  content: "\e717";
+}
+
+.hxicon-creativefill:before {
+  content: "\e718";
+}
+
+.hxicon-creative:before {
+  content: "\e719";
+}
+
+.hxicon-female:before {
+  content: "\e71a";
+}
+
+.hxicon-male:before {
+  content: "\e71c";
+}
+
+.hxicon-newfill:before {
+  content: "\e71d";
+}
+
+.hxicon-new:before {
+  content: "\e71e";
+}
+
+.hxicon-pullleft:before {
+  content: "\e71f";
+}
+
+.hxicon-pullright:before {
+  content: "\e720";
+}
+
+.hxicon-rankfill:before {
+  content: "\e721";
+}
+
+.hxicon-rank:before {
+  content: "\e722";
+}
+
+.hxicon-cameraadd:before {
+  content: "\e724";
+}
+
+.hxicon-focus:before {
+  content: "\e725";
+}
+
+.hxicon-friendfill:before {
+  content: "\e726";
+}
+
+.hxicon-cameraaddfill:before {
+  content: "\e727";
+}
+
+.hxicon-apps:before {
+  content: "\e729";
+}
+
+.hxicon-paintfill:before {
+  content: "\e72a";
+}
+
+.hxicon-paint:before {
+  content: "\e72b";
+}
+
+.hxicon-picfill:before {
+  content: "\e72c";
+}
+
+.hxicon-refresharrow:before {
+  content: "\e72d";
+}
+
+.hxicon-markfill:before {
+  content: "\e730";
+}
+
+.hxicon-mark:before {
+  content: "\e731";
+}
+
+.hxicon-presentfill:before {
+  content: "\e732";
+}
+
+.hxicon-repeal:before {
+  content: "\e733";
+}
+
+.hxicon-album:before {
+  content: "\e734";
+}
+
+.hxicon-peoplefill:before {
+  content: "\e735";
+}
+
+.hxicon-people:before {
+  content: "\e736";
+}
+
+.hxicon-servicefill:before {
+  content: "\e737";
+}
+
+.hxicon-repair:before {
+  content: "\e738";
+}
+
+.hxicon-file:before {
+  content: "\e739";
+}
+
+.hxicon-repairfill:before {
+  content: "\e73a";
+}
+
+.hxicon-taoxiaopu:before {
+  content: "\e73b";
+}
+
+.hxicon-attentionfill:before {
+  content: "\e73c";
+}
+
+.hxicon-attention:before {
+  content: "\e73d";
+}
+
+.hxicon-commandfill:before {
+  content: "\e73e";
+}
+
+.hxicon-command:before {
+  content: "\e73f";
+}
+
+.hxicon-communityfill:before {
+  content: "\e740";
+}
+
+.hxicon-community:before {
+  content: "\e741";
+}
+
+.hxicon-read:before {
+  content: "\e742";
+}
+
+.hxicon-calendar:before {
+  content: "\e74a";
+}
+
+.hxicon-cut:before {
+  content: "\e74b";
+}
+
+.hxicon-backwardfill:before {
+  content: "\e74d";
+}
+
+.hxicon-playfill:before {
+  content: "\e74f";
+}
+
+.hxicon-stop:before {
+  content: "\e750";
+}
+
+.hxicon-tagfill:before {
+  content: "\e751";
+}
+
+.hxicon-tag:before {
+  content: "\e752";
+}
+
+.hxicon-group:before {
+  content: "\e753";
+}
+
+.hxicon-all:before {
+  content: "\e755";
+}
+
+.hxicon-backdelete:before {
+  content: "\e756";
+}
+
+.hxicon-hotfill:before {
+  content: "\e757";
+}
+
+.hxicon-hot:before {
+  content: "\e758";
+}
+
+.hxicon-post:before {
+  content: "\e759";
+}
+
+.hxicon-radiobox:before {
+  content: "\e75b";
+}
+
+.hxicon-rounddown:before {
+  content: "\e75c";
+}
+
+.hxicon-upload:before {
+  content: "\e75d";
+}
+
+.hxicon-writefill:before {
+  content: "\e760";
+}
+
+.hxicon-write:before {
+  content: "\e761";
+}
+
+.hxicon-radioboxfill:before {
+  content: "\e763";
+}
+
+.hxicon-add1:before {
+  content: "\e767";
+}
+
+.hxicon-move:before {
+  content: "\e768";
+}
+
+.hxicon-safe:before {
+  content: "\e769";
+}
+
+.hxicon-haodian:before {
+  content: "\e76d";
+}
+
+.hxicon-qi:before {
+  content: "\e76f";
+}
+
+.hxicon-activityfill:before {
+  content: "\e775";
+}
+
+.hxicon-crownfill:before {
+  content: "\e776";
+}
+
+.hxicon-crown:before {
+  content: "\e777";
+}
+
+.hxicon-goodsfill:before {
+  content: "\e778";
+}
+
+.hxicon-messagefill:before {
+  content: "\e779";
+}
+
+.hxicon-profilefill:before {
+  content: "\e77a";
+}
+
+.hxicon-sound:before {
+  content: "\e77b";
+}
+
+.hxicon-sponsorfill:before {
+  content: "\e77c";
+}
+
+.hxicon-sponsor:before {
+  content: "\e77d";
+}
+
+.hxicon-upblock:before {
+  content: "\e77e";
+}
+
+.hxicon-weblock:before {
+  content: "\e77f";
+}
+
+.hxicon-weunblock:before {
+  content: "\e780";
+}
+
+.hxicon-1111:before {
+  content: "\e782";
+}
+
+.hxicon-my:before {
+  content: "\e78b";
+}
+
+.hxicon-myfill:before {
+  content: "\e78c";
+}
+
+.hxicon-emojifill:before {
+  content: "\e78d";
+}
+
+.hxicon-emojiflashfill:before {
+  content: "\e78e";
+}
+
+.hxicon-flashbuyfill-copy:before {
+  content: "\e78f";
+}
+
+.hxicon-text:before {
+  content: "\e791";
+}
+
+.hxicon-goodsfavor:before {
+  content: "\e794";
+}
+
+.hxicon-musicfill:before {
+  content: "\e795";
+}
+
+.hxicon-musicforbidfill:before {
+  content: "\e796";
+}
+
+.hxicon-roundleftfill:before {
+  content: "\e799";
+}
+
+.hxicon-triangledownfill:before {
+  content: "\e79b";
+}
+
+.hxicon-triangleupfill:before {
+  content: "\e79c";
+}
+
+.hxicon-roundleftfill-copy:before {
+  content: "\e79e";
+}
+
+.hxicon-pulldown1:before {
+  content: "\e79f";
+}
+
+.hxicon-emojilight:before {
+  content: "\e7a1";
+}
+
+.hxicon-recordfill:before {
+  content: "\e7a4";
+}
+
+.hxicon-recordlight:before {
+  content: "\e7a5";
+}
+
+.hxicon-record:before {
+  content: "\e7a6";
+}
+
+.hxicon-roundaddlight:before {
+  content: "\e7a7";
+}
+
+.hxicon-soundlight:before {
+  content: "\e7a8";
+}
+
+.hxicon-cardboardfill:before {
+  content: "\e7a9";
+}
+
+.hxicon-cardboard:before {
+  content: "\e7aa";
+}
+
+.hxicon-formfill:before {
+  content: "\e7ab";
+}
+
+.hxicon-coin:before {
+  content: "\e7ac";
+}
+
+.hxicon-sortlight:before {
+  content: "\e7ad";
+}
+
+.hxicon-cardboardforbid:before {
+  content: "\e7af";
+}
+
+.hxicon-circlefill:before {
+  content: "\e7b0";
+}
+
+.hxicon-circle:before {
+  content: "\e7b1";
+}
+
+.hxicon-attentionforbid:before {
+  content: "\e7b2";
+}
+
+.hxicon-attentionforbidfill:before {
+  content: "\e7b3";
+}
+
+.hxicon-attentionfavorfill:before {
+  content: "\e7b4";
+}
+
+.hxicon-attentionfavor:before {
+  content: "\e7b5";
+}
+
+.hxicon-piclight:before {
+  content: "\e7b7";
+}
+
+.hxicon-shoplight:before {
+  content: "\e7b8";
+}
+
+.hxicon-voicelight:before {
+  content: "\e7b9";
+}
+
+.hxicon-attentionfavorfill-copy:before {
+  content: "\e7ba";
+}
+
+.hxicon-full:before {
+  content: "\e7bc";
+}
+
+.hxicon-mail:before {
+  content: "\e7bd";
+}
+
+.hxicon-peoplelist:before {
+  content: "\e7be";
+}
+
+.hxicon-goodsnewfill:before {
+  content: "\e7bf";
+}
+
+.hxicon-goodsnew:before {
+  content: "\e7c0";
+}
+
+.hxicon-medalfill:before {
+  content: "\e7c1";
+}
+
+.hxicon-medal:before {
+  content: "\e7c2";
+}
+
+.hxicon-newsfill:before {
+  content: "\e7c3";
+}
+
+.hxicon-newshotfill:before {
+  content: "\e7c4";
+}
+
+.hxicon-appreciate:before {
+  content: "\e644";
+}
+
+.hxicon-newshot:before {
+  content: "\e7c5";
+}
+
+.hxicon-check:before {
+  content: "\e645";
+}
+
+.hxicon-news:before {
+  content: "\e7c6";
+}
+
+.hxicon-close:before {
+  content: "\e646";
+}
+
+.hxicon-videofill:before {
+  content: "\e7c7";
+}
+
+.hxicon-edit:before {
+  content: "\e649";
+}
+
+.hxicon-video:before {
+  content: "\e7c8";
+}
+
+.hxicon-emoji:before {
+  content: "\e64a";
+}
+
+.hxicon-askfill:before {
+  content: "\e7c9";
+}
+
+.hxicon-favorfill:before {
+  content: "\e64b";
+}
+
+.hxicon-ask:before {
+  content: "\e7ca";
+}
+
+.hxicon-favor:before {
+  content: "\e64c";
+}
+
+.hxicon-exit:before {
+  content: "\e7cb";
+}
+
+.hxicon-loading:before {
+  content: "\e64f";
+}
+
+.hxicon-skinfill:before {
+  content: "\e7cc";
+}
+
+.hxicon-locationfill:before {
+  content: "\e650";
+}
+
+.hxicon-skin:before {
+  content: "\e7cd";
+}
+
+.hxicon-location:before {
+  content: "\e651";
+}
+
+.hxicon-moneybagfill:before {
+  content: "\e7ce";
+}
+
+.hxicon-phone:before {
+  content: "\e652";
+}
+
+.hxicon-usefullfill:before {
+  content: "\e7cf";
+}
+
+.hxicon-roundcheckfill:before {
+  content: "\e656";
+}
+
+.hxicon-usefull:before {
+  content: "\e7d0";
+}
+
+.hxicon-roundcheck:before {
+  content: "\e657";
+}
+
+.hxicon-moneybag:before {
+  content: "\e7d1";
+}
+
+.hxicon-roundclosefill:before {
+  content: "\e658";
+}
+
+.hxicon-redpacket_fill:before {
+  content: "\e7d3";
+}
+
+.hxicon-roundclose:before {
+  content: "\e659";
+}
+
+.hxicon-subscription:before {
+  content: "\e7d4";
+}
+
+.hxicon-roundrightfill:before {
+  content: "\e65a";
+}
+
+.hxicon-home_light:before {
+  content: "\e7d5";
+}
+
+.hxicon-shengxianshuiguo:before {
+  content: "\ed00";
+}
+/* #endif */

+ 1115 - 0
HX-SHOP/common/main.css

@@ -0,0 +1,1115 @@
+
+/*每个页面公共css */
+::-webkit-scrollbar {
+	display: none;  
+	width: 0 !important;  
+	height: 0 !important;  
+	-webkit-appearance: none;  
+	background: transparent;  
+}
+body {
+	background-color: #f1f1f1;
+	font-size: 14px;
+	color: #333333;
+	font-family: Helvetica Neue, Helvetica, sans-serif;
+}
+
+uni-view, 
+uni-scroll-view, 
+uni-swiper, 
+uni-swiper-item, 
+uni-cover-view, 
+uni-cover-image, 
+uni-icon, 
+uni-text, 
+uni-rich-text, 
+uni-progress, 
+uni-button, 
+uni-checkbox, 
+uni-form, 
+uni-input, 
+uni-label, uni-radio, uni-slider,
+uni-switch, uni-textarea, 
+uni-navigator, uni-audio, 
+uni-camera, uni-image, uni-video{
+	box-sizing: border-box;
+}
+ 
+ /*边框*/
+ .b-b{
+ 	position: relative;
+ }
+ .b-b:after,
+ .b-t:after {
+ 	position: absolute;
+ 	z-index: 3;
+ 	left: 0;
+ 	right: 0;
+ 	height: 0;
+ 	content: '';
+ 	transform: scaleY(.5);
+ 	border-bottom: 1px solid #E4E7ED;
+ }
+ 
+ .b-b:after {
+ 	bottom: 0;
+ }
+ 
+ .b-t:after {
+ 	top: 0;
+ }
+ 
+.margin-top {
+	margin-top: 15px;
+}
+.padding {
+	padding: 30upx;
+}
+.text-grey, .line-grey, .lines-grey {
+	color: #8799a3;
+}
+.text-sm {
+	font-size: 12px;
+}
+/* ==================
+		  列表
+ ==================== */
+.grayscale {
+	filter: grayscale(1);
+}
+
+.cu-list+.cu-list {
+	margin-top: 30upx
+}
+
+.cu-list>.cu-item {
+	transition: all .6s ease-in-out 0s;
+	transform: translateX(0upx)
+}
+
+.cu-list>.cu-item.move-cur {
+	transform: translateX(-260upx)
+}
+
+.cu-list>.cu-item .move {
+	position: absolute;
+	right: 0;
+	display: flex;
+	width: 260upx;
+	height: 100%;
+	transform: translateX(100%)
+}
+
+.cu-list>.cu-item .move view {
+	display: flex;
+	flex: 1;
+	justify-content: center;
+	align-items: center
+}
+
+.cu-list.menu-avatar {
+	overflow: hidden;
+} 
+
+.cu-list.menu-avatar>.cu-item {
+	position: relative;
+	display: flex;
+	padding-right: 10upx;
+	height: 140upx;
+	background-color: #ffffff;
+	justify-content: flex-end;
+	align-items: center
+}
+
+.cu-list.menu-avatar>.cu-item>.cu-avatar {
+	position: absolute;
+	left: 30upx
+}
+
+.cu-list.menu-avatar>.cu-item .flex .text-cut {
+	max-width: 510upx
+}
+
+.cu-list.menu-avatar>.cu-item .content {
+	position: absolute;
+	left: 146upx;
+	width: calc(100% - 96upx - 60upx - 120upx - 20upx);
+	line-height: 1.6em;
+}
+
+.cu-list.menu-avatar>.cu-item .content.flex-sub {
+	width: calc(100% - 96upx - 60upx - 20upx);
+}
+
+.cu-list.menu-avatar>.cu-item .content>view:first-child {
+	font-size: 30upx;
+	display: flex;
+	align-items: center
+}
+
+.cu-list.menu-avatar>.cu-item .content .cu-tag.sm {
+	display: inline-block;
+	margin-left: 10upx;
+	height: 28upx;
+	font-size: 16upx;
+	line-height: 32upx
+}
+
+.cu-list.menu-avatar>.cu-item .action {
+	width: 100upx;
+	text-align: center
+}
+
+.cu-list.menu-avatar>.cu-item .action view+view {
+	margin-top: 10upx
+}
+
+.cu-list.menu-avatar.comment>.cu-item .content {
+	position: relative;
+	left: 0;
+	width: auto;
+	flex: 1;
+}
+
+.cu-list.menu-avatar.comment>.cu-item {
+	padding: 30upx 30upx 30upx 120upx;
+	height: auto
+}
+
+.cu-list.menu-avatar.comment .cu-avatar {
+	align-self: flex-start
+}
+
+.cu-list.menu>.cu-item {
+	position: relative;
+	display: flex;
+	padding: 0 30upx;
+	min-height: 100upx;
+	background-color: #ffffff;
+	justify-content: space-between;
+	align-items: center
+}
+
+.cu-list.menu>.cu-item:last-child:after {
+	border: none
+}
+
+.cu-list.menu-avatar>.cu-item:after,
+.cu-list.menu>.cu-item:after {
+	position: absolute;
+	top: 0;
+	left: 0;
+	box-sizing: border-box;
+	width: 200%;
+	height: 200%;
+	border-bottom: 1upx solid #ddd;
+	border-radius: inherit;
+	content: " ";
+	transform: scale(.5);
+	transform-origin: 0 0;
+	pointer-events: none
+}
+
+.cu-list.menu>.cu-item.grayscale {
+	background-color: #f5f5f5
+}
+
+.cu-list.menu>.cu-item.cur {
+	background-color: #fcf7e9
+}
+
+.cu-list.menu>.cu-item.arrow {
+	padding-right: 90upx
+}
+
+.cu-list.menu>.cu-item.arrow:before {
+	position: absolute;
+	top: 0;
+	right: 30upx;
+	bottom: 0;
+	display: block;
+	margin: auto;
+	width: 30upx;
+	height: 30upx;
+	color: #8799a3;
+	content: "\e6a3";
+	text-align: center;
+	font-size: 34upx;
+	font-family: "hxicon";
+	line-height: 30upx
+}
+
+.cu-list.menu>.cu-item button.content {
+	padding: 0;
+	background-color: transparent;
+	justify-content: flex-start
+}
+
+.cu-list.menu>.cu-item button.content:after {
+	display: none
+}
+
+.cu-list.menu>.cu-item .cu-avatar-group .cu-avatar {
+	border-color: #ffffff
+}
+
+.cu-list.menu>.cu-item .content>view:first-child {
+	display: flex;
+	align-items: center
+}
+
+.cu-list.menu>.cu-item .content>text[class*=cuIcon] {
+	display: inline-block;
+	margin-right: 10upx;
+	width: 1.6em;
+	text-align: center
+}
+.cu-list.menu>.cu-item .content>text[class*=icon] {
+	display: inline-block;
+	margin-right: 10upx;
+	width: 1.6em;
+	text-align: center
+}
+
+.cu-list.menu>.cu-item .content>image {
+	display: inline-block;
+	margin-right: 10upx;
+	width: 1.6em;
+	height: 1.6em;
+	vertical-align: middle
+}
+
+.cu-list.menu>.cu-item .content {
+	font-size: 30upx;
+	line-height: 1.6em;
+	flex: 1
+}
+
+.cu-list.menu>.cu-item .content .cu-tag.sm {
+	display: inline-block;
+	margin-left: 10upx;
+	height: 28upx;
+	font-size: 16upx;
+	line-height: 32upx
+}
+
+.cu-list.menu>.cu-item .action .cu-tag:empty {
+	right: 10upx
+}
+
+.cu-list.menu {
+	display: block;
+	overflow: hidden
+}
+
+.cu-list.menu.sm-border>.cu-item:after {
+	left: 30upx;
+	width: calc(200% - 120upx)
+}
+
+.cu-list.grid>.cu-item {
+	position: relative;
+	display: flex;
+	padding: 20upx 0 30upx;
+	transition-duration: 0s;
+	flex-direction: column
+}
+
+.cu-list.grid>.cu-item:after {
+	position: absolute;
+	top: 0;
+	left: 0;
+	box-sizing: border-box;
+	width: 200%;
+	height: 200%;
+	border-right: 1px solid rgba(0, 0, 0, .1);
+	border-bottom: 1px solid rgba(0, 0, 0, .1);
+	border-radius: inherit;
+	content: " ";
+	transform: scale(.5);
+	transform-origin: 0 0;
+	pointer-events: none
+}
+
+.cu-list.grid>.cu-item text {
+	display: block;
+	margin-top: 10upx;
+	color: #888;
+	font-size: 26upx;
+	line-height: 40upx
+}
+
+.cu-list.grid>.cu-item [class*=cuIcon] {
+	position: relative;
+	display: block;
+	margin-top: 20upx;
+	width: 100%;
+	font-size: 48upx
+}
+.cu-list.grid>.cu-item [class*=icon] {
+	position: relative;
+	display: block;
+	margin-top: 20upx;
+	width: 100%;
+	font-size: 48upx
+}
+
+.cu-list.grid>.cu-item .cu-tag {
+	right: auto;
+	left: 50%;
+	margin-left: 20upx
+}
+
+.cu-list.grid {
+	background-color: #ffffff;
+	text-align: center
+}
+
+.cu-list.grid.no-border>.cu-item {
+	padding-top: 10upx;
+	padding-bottom: 20upx
+}
+
+.cu-list.grid.no-border>.cu-item:after {
+	border: none
+}
+
+.cu-list.grid.no-border {
+	padding: 20upx 10upx
+}
+
+.cu-list.grid.col-3>.cu-item:nth-child(3n):after,
+.cu-list.grid.col-4>.cu-item:nth-child(4n):after,
+.cu-list.grid.col-5>.cu-item:nth-child(5n):after {
+	border-right-width: 0
+}
+
+.cu-list.card-menu {
+	overflow: hidden;
+	margin-right: 30upx;
+	margin-left: 30upx;
+	border-radius: 20upx
+}
+
+/* ==================
+		  按钮
+ ==================== */
+
+.cu-btn {
+	position: relative;
+	border: 0upx;
+	display: inline-flex;
+	align-items: center;
+	justify-content: center;
+	box-sizing: border-box;
+	padding: 0 30upx;
+	font-size: 28upx;
+	height: 64upx;
+	line-height: 1;
+	text-align: center;
+	text-decoration: none;
+	overflow: visible;
+	margin-left: initial;
+	transform: translate(0upx, 0upx);
+	margin-right: initial;
+}
+
+.cu-btn::after {
+	display: none;
+}
+
+.cu-btn:not([class*="bg-"]) {
+	background-color: #f0f0f0;
+}
+
+.cu-btn[class*="line"] {
+	background-color: transparent;
+}
+
+.cu-btn[class*="line"]::after {
+	content: " ";
+	display: block;
+	width: 200%;
+	height: 200%;
+	position: absolute;
+	top: 0;
+	left: 0;
+	border: 1upx solid currentColor;
+	transform: scale(0.5);
+	transform-origin: 0 0;
+	box-sizing: border-box;
+	border-radius: 12upx;
+	z-index: 1;
+	pointer-events: none;
+}
+
+.cu-btn.round[class*="line"]::after {
+	border-radius: 1000upx;
+}
+
+.cu-btn[class*="lines"]::after {
+	border: 6upx solid currentColor;
+}
+
+.cu-btn[class*="bg-"]::after {
+	display: none;
+}
+
+.cu-btn.sm {
+	padding: 0 20upx;
+	font-size: 20upx;
+	height: 48upx;
+}
+
+.cu-btn.lg {
+	padding: 0 40upx;
+	font-size: 32upx;
+	height: 80upx;
+}
+
+.cu-btn.cuIcon.sm {
+	width: 48upx;
+	height: 48upx;
+}
+
+.cu-btn.cuIcon {
+	width: 64upx;
+	height: 64upx;
+	border-radius: 500upx;
+	padding: 0;
+}
+
+button.cuIcon.lg {
+	width: 80upx;
+	height: 80upx;
+}
+
+.cu-btn.shadow-blur::before {
+	top: 4upx;
+	left: 4upx;
+	filter: blur(6upx);
+	opacity: 0.6;
+}
+
+.cu-btn.button-hover {
+	transform: translate(1upx, 1upx);
+}
+
+.block {
+	display: block;
+}
+
+.cu-btn.block {
+	display: flex;
+}
+
+.cu-btn[disabled] {
+	opacity: 0.6;
+	color: #ffffff;
+}
+/* -- 浮动 --  */
+
+.cf::after,
+.cf::before {
+	content: " ";
+	display: table;
+}
+
+.cf::after {
+	clear: both;
+}
+
+.fl {
+	float: left;
+}
+
+.fr {
+	float: right;
+}
+
+/* ==================
+		  背景
+ ==================== */
+
+.line-red::after,
+.lines-red::after {
+	border-color: #e54d42;
+}
+
+.line-orange::after,
+.lines-orange::after {
+	border-color: #f37b1d;
+}
+
+.line-yellow::after,
+.lines-yellow::after {
+	border-color: #fbbd08;
+}
+
+.line-olive::after,
+.lines-olive::after {
+	border-color: #8dc63f;
+}
+
+.line-green::after,
+.lines-green::after {
+	border-color: #39b54a;
+}
+
+.line-cyan::after,
+.lines-cyan::after {
+	border-color: #1cbbb4;
+}
+
+.line-blue::after,
+.lines-blue::after {
+	border-color: #0081ff;
+}
+
+.line-purple::after,
+.lines-purple::after {
+	border-color: #6739b6;
+}
+
+.line-mauve::after,
+.lines-mauve::after {
+	border-color: #9c26b0;
+}
+
+.line-pink::after,
+.lines-pink::after {
+	border-color: #e03997;
+}
+
+.line-brown::after,
+.lines-brown::after {
+	border-color: #a5673f;
+}
+
+.line-grey::after,
+.lines-grey::after {
+	border-color: #8799a3;
+}
+
+.line-gray::after,
+.lines-gray::after {
+	border-color: #aaaaaa;
+}
+
+.line-black::after,
+.lines-black::after {
+	border-color: #333333;
+}
+
+.line-white::after,
+.lines-white::after {
+	border-color: #ffffff;
+}
+
+.bg-red {
+	background-color: #e54d42;
+	color: #ffffff;
+}
+
+.bg-orange {
+	background-color: #f37b1d;
+	color: #ffffff;
+}
+
+.bg-yellow {
+	background-color: #fbbd08;
+	color: #333333;
+}
+
+.bg-olive {
+	background-color: #8dc63f;
+	color: #ffffff;
+}
+
+.bg-green {
+	background-color: #39b54a;
+	color: #ffffff;
+}
+
+.bg-cyan {
+	background-color: #1cbbb4;
+	color: #ffffff;
+}
+
+.bg-blue {
+	background-color: #0081ff;
+	color: #ffffff;
+}
+
+.bg-purple {
+	background-color: #6739b6;
+	color: #ffffff;
+}
+
+.bg-mauve {
+	background-color: #9c26b0;
+	color: #ffffff;
+}
+
+.bg-pink {
+	background-color: #e03997;
+	color: #ffffff;
+}
+
+.bg-brown {
+	background-color: #a5673f;
+	color: #ffffff;
+}
+
+.bg-grey {
+	background-color: #8799a3;
+	color: #ffffff;
+}
+
+.bg-gray {
+	background-color: #f0f0f0;
+	color: #333333;
+}
+
+.bg-black {
+	background-color: #333333;
+	color: #ffffff;
+}
+
+.bg-white {
+	background-color: #ffffff;
+	color: #666666;
+}
+
+.bg-shadeTop {
+	background-image: linear-gradient(rgba(0, 0, 0, 1), rgba(0, 0, 0, 0.01));
+	color: #ffffff;
+}
+
+.bg-shadeBottom {
+	background-image: linear-gradient(rgba(0, 0, 0, 0.01), rgba(0, 0, 0, 1));
+	color: #ffffff;
+}
+
+.bg-red.light {
+	color: #e54d42;
+	background-color: #fadbd9;
+}
+
+.bg-orange.light {
+	color: #f37b1d;
+	background-color: #fde6d2;
+}
+
+.bg-yellow.light {
+	color: #fbbd08;
+	background-color: #fef2ced2;
+}
+
+.bg-olive.light {
+	color: #8dc63f;
+	background-color: #e8f4d9;
+}
+
+.bg-green.light {
+	color: #39b54a;
+	background-color: #d7f0dbff;
+}
+
+.bg-cyan.light {
+	color: #1cbbb4;
+	background-color: #d2f1f0;
+}
+
+.bg-blue.light {
+	color: #0081ff;
+	background-color: #cce6ff;
+}
+
+.bg-purple.light {
+	color: #6739b6;
+	background-color: #e1d7f0;
+}
+
+.bg-mauve.light {
+	color: #9c26b0;
+	background-color: #ebd4ef;
+}
+
+.bg-pink.light {
+	color: #e03997;
+	background-color: #f9d7ea;
+}
+
+.bg-brown.light {
+	color: #a5673f;
+	background-color: #ede1d9;
+}
+
+.bg-grey.light {
+	color: #8799a3;
+	background-color: #e7ebed;
+}
+
+.bg-gradual-red {
+	background-image: linear-gradient(45deg, #f43f3b, #ec008c);
+	color: #ffffff;
+}
+
+.bg-gradual-orange {
+	background-image: linear-gradient(45deg, #ff9700, #ed1c24);
+	color: #ffffff;
+}
+
+.bg-gradual-green {
+	background-image: linear-gradient(45deg, #39b54a, #8dc63f);
+	color: #ffffff;
+}
+
+.bg-gradual-purple {
+	background-image: linear-gradient(45deg, #9000ff, #5e00ff);
+	color: #ffffff;
+}
+
+.bg-gradual-pink {
+	background-image: linear-gradient(45deg, #ec008c, #6739b6);
+	color: #ffffff;
+}
+
+.bg-gradual-blue {
+	background-image: linear-gradient(45deg, #0081ff, #1cbbb4);
+	color: #ffffff;
+}
+
+.shadow[class*="-red"] {
+	box-shadow: 6upx 6upx 8upx rgba(204, 69, 59, 0.2);
+}
+
+.shadow[class*="-orange"] {
+	box-shadow: 6upx 6upx 8upx rgba(217, 109, 26, 0.2);
+}
+
+.shadow[class*="-yellow"] {
+	box-shadow: 6upx 6upx 8upx rgba(224, 170, 7, 0.2);
+}
+
+.shadow[class*="-olive"] {
+	box-shadow: 6upx 6upx 8upx rgba(124, 173, 55, 0.2);
+}
+
+.shadow[class*="-green"] {
+	box-shadow: 6upx 6upx 8upx rgba(48, 156, 63, 0.2);
+}
+
+.shadow[class*="-cyan"] {
+	box-shadow: 6upx 6upx 8upx rgba(28, 187, 180, 0.2);
+}
+
+.shadow[class*="-blue"] {
+	box-shadow: 6upx 6upx 8upx rgba(0, 102, 204, 0.2);
+}
+
+.shadow[class*="-purple"] {
+	box-shadow: 6upx 6upx 8upx rgba(88, 48, 156, 0.2);
+}
+
+.shadow[class*="-mauve"] {
+	box-shadow: 6upx 6upx 8upx rgba(133, 33, 150, 0.2);
+}
+
+.shadow[class*="-pink"] {
+	box-shadow: 6upx 6upx 8upx rgba(199, 50, 134, 0.2);
+}
+
+.shadow[class*="-brown"] {
+	box-shadow: 6upx 6upx 8upx rgba(140, 88, 53, 0.2);
+}
+
+.shadow[class*="-grey"] {
+	box-shadow: 6upx 6upx 8upx rgba(114, 130, 138, 0.2);
+}
+
+.shadow[class*="-gray"] {
+	box-shadow: 6upx 6upx 8upx rgba(114, 130, 138, 0.2);
+}
+
+.shadow[class*="-black"] {
+	box-shadow: 6upx 6upx 8upx rgba(26, 26, 26, 0.2);
+}
+
+.shadow[class*="-white"] {
+	box-shadow: 6upx 6upx 8upx rgba(26, 26, 26, 0.2);
+}
+
+.text-shadow[class*="-red"] {
+	text-shadow: 6upx 6upx 8upx rgba(204, 69, 59, 0.2);
+}
+
+.text-shadow[class*="-orange"] {
+	text-shadow: 6upx 6upx 8upx rgba(217, 109, 26, 0.2);
+}
+
+.text-shadow[class*="-yellow"] {
+	text-shadow: 6upx 6upx 8upx rgba(224, 170, 7, 0.2);
+}
+
+.text-shadow[class*="-olive"] {
+	text-shadow: 6upx 6upx 8upx rgba(124, 173, 55, 0.2);
+}
+
+.text-shadow[class*="-green"] {
+	text-shadow: 6upx 6upx 8upx rgba(48, 156, 63, 0.2);
+}
+
+.text-shadow[class*="-cyan"] {
+	text-shadow: 6upx 6upx 8upx rgba(28, 187, 180, 0.2);
+}
+
+.text-shadow[class*="-blue"] {
+	text-shadow: 6upx 6upx 8upx rgba(0, 102, 204, 0.2);
+}
+
+.text-shadow[class*="-purple"] {
+	text-shadow: 6upx 6upx 8upx rgba(88, 48, 156, 0.2);
+}
+
+.text-shadow[class*="-mauve"] {
+	text-shadow: 6upx 6upx 8upx rgba(133, 33, 150, 0.2);
+}
+
+.text-shadow[class*="-pink"] {
+	text-shadow: 6upx 6upx 8upx rgba(199, 50, 134, 0.2);
+}
+
+.text-shadow[class*="-brown"] {
+	text-shadow: 6upx 6upx 8upx rgba(140, 88, 53, 0.2);
+}
+
+.text-shadow[class*="-grey"] {
+	text-shadow: 6upx 6upx 8upx rgba(114, 130, 138, 0.2);
+}
+
+.text-shadow[class*="-gray"] {
+	text-shadow: 6upx 6upx 8upx rgba(114, 130, 138, 0.2);
+}
+
+.text-shadow[class*="-black"] {
+	text-shadow: 6upx 6upx 8upx rgba(26, 26, 26, 0.2);
+}
+
+.bg-img {
+	background-size: cover;
+	background-position: center;
+	background-repeat: no-repeat;
+}
+
+.bg-mask {
+	background-color: #333333;
+	position: relative;
+}
+
+.bg-mask::after {
+	content: "";
+	border-radius: inherit;
+	width: 100%;
+	height: 100%;
+	display: block;
+	background-color: rgba(0, 0, 0, 0.4);
+	position: absolute;
+	left: 0;
+	right: 0;
+	bottom: 0;
+	top: 0;
+}
+
+.bg-mask view,
+.bg-mask cover-view {
+	z-index: 5;
+	position: relative;
+}
+
+.bg-video {
+	position: relative;
+}
+
+.bg-video video {
+	display: block;
+	height: 100%;
+	width: 100%;
+	-o-object-fit: cover;
+	object-fit: cover;
+	position: absolute;
+	top: 0;
+	z-index: 0;
+	pointer-events: none;
+}
+
+/* ==================
+		  文本
+ ==================== */
+
+.text-xs {
+	font-size: 20upx;
+}
+
+.text-sm {
+	font-size: 24upx;
+}
+
+.text-df {
+	font-size: 28upx;
+}
+
+.text-lg {
+	font-size: 32upx;
+}
+
+.text-xl {
+	font-size: 36upx;
+}
+
+.text-xxl {
+	font-size: 44upx;
+}
+
+.text-sl {
+	font-size: 80upx;
+}
+
+.text-xsl {
+	font-size: 120upx;
+}
+
+.text-Abc {
+	text-transform: Capitalize;
+}
+
+.text-ABC {
+	text-transform: Uppercase;
+}
+
+.text-abc {
+	text-transform: Lowercase;
+}
+
+.text-price::before {
+	content: "¥";
+	font-size: 80%;
+	margin-right: 4upx;
+}
+
+.text-cut {
+	text-overflow: ellipsis;
+	white-space: nowrap;
+	overflow: hidden;
+}
+
+.text-bold {
+	font-weight: bold;
+}
+
+.text-center {
+	text-align: center;
+}
+
+.text-content {
+	line-height: 1.6;
+}
+
+.text-left {
+	text-align: left;
+}
+
+.text-right {
+	text-align: right;
+}
+
+.text-red,
+.line-red,
+.lines-red {
+	color: #e54d42;
+}
+
+.text-orange,
+.line-orange,
+.lines-orange {
+	color: #f37b1d;
+}
+
+.text-yellow,
+.line-yellow,
+.lines-yellow {
+	color: #fbbd08;
+}
+
+.text-olive,
+.line-olive,
+.lines-olive {
+	color: #8dc63f;
+}
+
+.text-green,
+.line-green,
+.lines-green {
+	color: #39b54a;
+}
+
+.text-cyan,
+.line-cyan,
+.lines-cyan {
+	color: #1cbbb4;
+}
+
+.text-blue,
+.line-blue,
+.lines-blue {
+	color: #0081ff;
+}
+
+.text-purple,
+.line-purple,
+.lines-purple {
+	color: #6739b6;
+}
+
+.text-mauve,
+.line-mauve,
+.lines-mauve {
+	color: #9c26b0;
+}
+
+.text-pink,
+.line-pink,
+.lines-pink {
+	color: #e03997;
+}
+
+.text-brown,
+.line-brown,
+.lines-brown {
+	color: #a5673f;
+}
+
+.text-grey,
+.line-grey,
+.lines-grey {
+	color: #8799a3;
+}
+
+.text-gray,
+.line-gray,
+.lines-gray {
+	color: #aaaaaa;
+}
+
+.text-black,
+.line-black,
+.lines-black {
+	color: #333333;
+}
+
+.text-white,
+.line-white,
+.lines-white {
+	color: #ffffff;
+}

+ 404 - 0
HX-SHOP/common/pinyin/pinyin.js

@@ -0,0 +1,404 @@
+ 
+export const pinyin = {
+  'a': '\u554a\u963f\u9515',
+  'ai': '\u57c3\u6328\u54ce\u5509\u54c0\u7691\u764c\u853c\u77ee\u827e\u788d\u7231\u9698\u8bf6\u6371\u55f3\u55cc\u5ad2\u7477\u66a7\u7839\u953f\u972d',
+  'an': '\u978d\u6c28\u5b89\u4ffa\u6309\u6697\u5cb8\u80fa\u6848\u8c19\u57ef\u63de\u72b4\u5eb5\u6849\u94f5\u9e4c\u9878\u9eef',
+  'ang': '\u80ae\u6602\u76ce',
+  'ao': '\u51f9\u6556\u71ac\u7ff1\u8884\u50b2\u5965\u61ca\u6fb3\u5773\u62d7\u55f7\u5662\u5c99\u5ed2\u9068\u5aaa\u9a9c\u8071\u87af\u93ca\u9ccc\u93d6',
+  'ba': '\u82ad\u634c\u6252\u53ed\u5427\u7b06\u516b\u75a4\u5df4\u62d4\u8dcb\u9776\u628a\u8019\u575d\u9738\u7f62\u7238\u8307\u83dd\u8406\u636d\u5c9c\u705e\u6777\u94af\u7c91\u9c85\u9b43',
+  'bai': '\u767d\u67cf\u767e\u6446\u4f70\u8d25\u62dc\u7a17\u859c\u63b0\u97b4',
+  'ban': '\u6591\u73ed\u642c\u6273\u822c\u9881\u677f\u7248\u626e\u62cc\u4f34\u74e3\u534a\u529e\u7eca\u962a\u5742\u8c73\u94a3\u7622\u764d\u8228',
+  'bang': '\u90a6\u5e2e\u6886\u699c\u8180\u7ed1\u68d2\u78c5\u868c\u9551\u508d\u8c24\u84a1\u8783',
+  'bao': '\u82de\u80de\u5305\u8912\u96f9\u4fdd\u5821\u9971\u5b9d\u62b1\u62a5\u66b4\u8c79\u9c8d\u7206\u52f9\u8446\u5b80\u5b62\u7172\u9e28\u8913\u8db5\u9f85',
+  'bo': '\u5265\u8584\u73bb\u83e0\u64ad\u62e8\u94b5\u6ce2\u535a\u52c3\u640f\u94c2\u7b94\u4f2f\u5e1b\u8236\u8116\u818a\u6e24\u6cca\u9a73\u4eb3\u8543\u5575\u997d\u6a97\u64d8\u7934\u94b9\u9e41\u7c38\u8ddb',
+  'bei': '\u676f\u7891\u60b2\u5351\u5317\u8f88\u80cc\u8d1d\u94a1\u500d\u72c8\u5907\u60eb\u7119\u88ab\u5b5b\u9642\u90b6\u57e4\u84d3\u5457\u602b\u6096\u789a\u9e4e\u8919\u943e',
+  'ben': '\u5954\u82ef\u672c\u7b28\u755a\u574c\u951b',
+  'beng': '\u5d29\u7ef7\u752d\u6cf5\u8e66\u8ff8\u552a\u5623\u750f',
+  'bi': '\u903c\u9f3b\u6bd4\u9119\u7b14\u5f7c\u78a7\u84d6\u853d\u6bd5\u6bd9\u6bd6\u5e01\u5e87\u75f9\u95ed\u655d\u5f0a\u5fc5\u8f9f\u58c1\u81c2\u907f\u965b\u5315\u4ef3\u4ffe\u8298\u835c\u8378\u5421\u54d4\u72f4\u5eb3\u610e\u6ed7\u6fde\u5f3c\u59a3\u5a62\u5b16\u74a7\u8d32\u7540\u94cb\u79d5\u88e8\u7b5a\u7b85\u7be6\u822d\u895e\u8df8\u9ac0',
+  'bian': '\u97ad\u8fb9\u7f16\u8d2c\u6241\u4fbf\u53d8\u535e\u8fa8\u8fa9\u8fab\u904d\u533e\u5f01\u82c4\u5fed\u6c74\u7f0f\u7178\u782d\u78a5\u7a39\u7a86\u8759\u7b3e\u9cca',
+  'biao': '\u6807\u5f6a\u8198\u8868\u5a4a\u9aa0\u98d1\u98d9\u98da\u706c\u9556\u9573\u762d\u88f1\u9cd4',
+  'bie': '\u9cd6\u618b\u522b\u762a\u8e69\u9cd8',
+  'bin': '\u5f6c\u658c\u6fd2\u6ee8\u5bbe\u6448\u50a7\u6d5c\u7f24\u73a2\u6ba1\u8191\u9554\u9acc\u9b13',
+  'bing': '\u5175\u51b0\u67c4\u4e19\u79c9\u997c\u70b3\u75c5\u5e76\u7980\u90b4\u6452\u7ee0\u678b\u69df\u71f9',
+  'bu': '\u6355\u535c\u54fa\u8865\u57e0\u4e0d\u5e03\u6b65\u7c3f\u90e8\u6016\u62ca\u535f\u900b\u74ff\u6661\u949a\u91ad',
+  'ca': '\u64e6\u5693\u7924',
+  'cai': '\u731c\u88c1\u6750\u624d\u8d22\u776c\u8e29\u91c7\u5f69\u83dc\u8521',
+  'can': '\u9910\u53c2\u8695\u6b8b\u60ed\u60e8\u707f\u9a96\u74a8\u7cb2\u9eea',
+  'cang': '\u82cd\u8231\u4ed3\u6ca7\u85cf\u4f27',
+  'cao': '\u64cd\u7cd9\u69fd\u66f9\u8349\u8279\u5608\u6f15\u87ac\u825a',
+  'ce': '\u5395\u7b56\u4fa7\u518c\u6d4b\u5202\u5e3b\u607b',
+  'ceng': '\u5c42\u8e6d\u564c',
+  'cha': '\u63d2\u53c9\u832c\u8336\u67e5\u78b4\u643d\u5bdf\u5c94\u5dee\u8be7\u7339\u9987\u6c4a\u59f9\u6748\u6942\u69ce\u6aab\u9497\u9538\u9572\u8869',
+  'chai': '\u62c6\u67f4\u8c7a\u4faa\u8308\u7625\u867f\u9f87',
+  'chan': '\u6400\u63ba\u8749\u998b\u8c17\u7f20\u94f2\u4ea7\u9610\u98a4\u5181\u8c04\u8c36\u8487\u5edb\u5fcf\u6f7a\u6fb6\u5b71\u7fbc\u5a75\u5b17\u9aa3\u89c7\u7985\u9561\u88e3\u87fe\u8e94',
+  'chang': '\u660c\u7316\u573a\u5c1d\u5e38\u957f\u507f\u80a0\u5382\u655e\u7545\u5531\u5021\u4f25\u9b2f\u82cc\u83d6\u5f9c\u6005\u60dd\u960a\u5a3c\u5ae6\u6636\u6c05\u9cb3',
+  'chao': '\u8d85\u6284\u949e\u671d\u5632\u6f6e\u5de2\u5435\u7092\u600a\u7ec9\u6641\u8016',
+  'che': '\u8f66\u626f\u64a4\u63a3\u5f7b\u6f88\u577c\u5c6e\u7817',
+  'chen': '\u90f4\u81e3\u8fb0\u5c18\u6668\u5ff1\u6c89\u9648\u8d81\u886c\u79f0\u8c0c\u62bb\u55d4\u5bb8\u741b\u6987\u809c\u80c2\u789c\u9f80',
+  'cheng': '\u6491\u57ce\u6a59\u6210\u5448\u4e58\u7a0b\u60e9\u6f84\u8bda\u627f\u901e\u9a8b\u79e4\u57d5\u5d4a\u5fb5\u6d48\u67a8\u67fd\u6a18\u665f\u584d\u77a0\u94d6\u88ce\u86cf\u9172',
+  'chi': '\u5403\u75f4\u6301\u5319\u6c60\u8fdf\u5f1b\u9a70\u803b\u9f7f\u4f88\u5c3a\u8d64\u7fc5\u65a5\u70bd\u50ba\u5880\u82aa\u830c\u640b\u53f1\u54e7\u557b\u55e4\u5f73\u996c\u6cb2\u5ab8\u6555\u80dd\u7719\u7735\u9e31\u761b\u892b\u86a9\u87ad\u7b1e\u7bea\u8c49\u8e05\u8e1f\u9b51',
+  'chong': '\u5145\u51b2\u866b\u5d07\u5ba0\u833a\u5fe1\u61a7\u94f3\u825f',
+  'chou': '\u62bd\u916c\u7574\u8e0c\u7a20\u6101\u7b79\u4ec7\u7ef8\u7785\u4e11\u4fe6\u5733\u5e31\u60c6\u6eb4\u59af\u7633\u96e0\u9c8b',
+  'chu': '\u81ed\u521d\u51fa\u6a71\u53a8\u8e87\u9504\u96cf\u6ec1\u9664\u695a\u7840\u50a8\u77d7\u6410\u89e6\u5904\u4e8d\u520d\u61b7\u7ecc\u6775\u696e\u6a17\u870d\u8e70\u9edc',
+  'chuan': '\u63e3\u5ddd\u7a7f\u693d\u4f20\u8239\u5598\u4e32\u63be\u821b\u60f4\u9044\u5ddb\u6c1a\u948f\u9569\u8221',
+  'chuang': '\u75ae\u7a97\u5e62\u5e8a\u95ef\u521b\u6006',
+  'chui': '\u5439\u708a\u6376\u9524\u5782\u9672\u68f0\u69cc',
+  'chun': '\u6625\u693f\u9187\u5507\u6df3\u7eaf\u8822\u4fc3\u83bc\u6c8c\u80ab\u6710\u9e51\u877d',
+  'chuo': '\u6233\u7ef0\u851f\u8fb6\u8f8d\u955e\u8e14\u9f8a',
+  'ci': '\u75b5\u8328\u78c1\u96cc\u8f9e\u6148\u74f7\u8bcd\u6b64\u523a\u8d50\u6b21\u8360\u5472\u5d6f\u9e5a\u8785\u7ccd\u8d91',
+  'cong': '\u806a\u8471\u56f1\u5306\u4ece\u4e1b\u506c\u82c1\u6dd9\u9aa2\u742e\u7481\u679e',
+  'cu': '\u51d1\u7c97\u918b\u7c07\u731d\u6b82\u8e59',
+  'cuan': '\u8e7f\u7be1\u7a9c\u6c46\u64ba\u6615\u7228',
+  'cui': '\u6467\u5d14\u50ac\u8106\u7601\u7cb9\u6dec\u7fe0\u8403\u60b4\u7480\u69b1\u96b9',
+  'cun': '\u6751\u5b58\u5bf8\u78cb\u5fd6\u76b4',
+  'cuo': '\u64ae\u6413\u63aa\u632b\u9519\u539d\u811e\u9509\u77ec\u75e4\u9e7e\u8e49\u8e9c',
+  'da': '\u642d\u8fbe\u7b54\u7629\u6253\u5927\u8037\u54d2\u55d2\u601b\u59b2\u75b8\u8921\u7b2a\u977c\u9791',
+  'dai': '\u5446\u6b79\u50a3\u6234\u5e26\u6b86\u4ee3\u8d37\u888b\u5f85\u902e\u6020\u57ed\u7519\u5454\u5cb1\u8fe8\u902f\u9a80\u7ed0\u73b3\u9edb',
+  'dan': '\u803d\u62c5\u4e39\u5355\u90f8\u63b8\u80c6\u65e6\u6c2e\u4f46\u60ee\u6de1\u8bde\u5f39\u86cb\u4ebb\u510b\u5369\u840f\u5556\u6fb9\u6a90\u6b9a\u8d55\u7708\u7605\u8043\u7baa',
+  'dang': '\u5f53\u6321\u515a\u8361\u6863\u8c20\u51fc\u83ea\u5b95\u7800\u94db\u88c6',
+  'dao': '\u5200\u6363\u8e48\u5012\u5c9b\u7977\u5bfc\u5230\u7a3b\u60bc\u9053\u76d7\u53e8\u5541\u5fc9\u6d2e\u6c18\u7118\u5fd1\u7e9b',
+  'de': '\u5fb7\u5f97\u7684\u951d',
+  'deng': '\u8e6c\u706f\u767b\u7b49\u77aa\u51f3\u9093\u5654\u5d9d\u6225\u78f4\u956b\u7c26',
+  'di': '\u5824\u4f4e\u6ef4\u8fea\u654c\u7b1b\u72c4\u6da4\u7fdf\u5ae1\u62b5\u5e95\u5730\u8482\u7b2c\u5e1d\u5f1f\u9012\u7f14\u6c10\u7c74\u8bcb\u8c1b\u90b8\u577b\u839c\u837b\u5600\u5a23\u67e2\u68e3\u89cc\u7825\u78b2\u7747\u955d\u7f9d\u9ab6',
+  'dian': '\u98a0\u6382\u6ec7\u7898\u70b9\u5178\u975b\u57ab\u7535\u4f43\u7538\u5e97\u60e6\u5960\u6dc0\u6bbf\u4e36\u963d\u576b\u57dd\u5dc5\u73b7\u765c\u766b\u7c1f\u8e2e',
+  'diao': '\u7889\u53fc\u96d5\u51cb\u5201\u6389\u540a\u9493\u8c03\u8f7a\u94de\u8729\u7c9c\u8c82',
+  'die': '\u8dcc\u7239\u789f\u8776\u8fed\u8c0d\u53e0\u4f5a\u57a4\u581e\u63f2\u558b\u6e2b\u8f76\u7252\u74de\u8936\u800b\u8e40\u9cbd\u9cce',
+  'ding': '\u4e01\u76ef\u53ee\u9489\u9876\u9f0e\u952d\u5b9a\u8ba2\u4e22\u4ec3\u5576\u738e\u815a\u7887\u753a\u94e4\u7594\u8035\u914a',
+  'dong': '\u4e1c\u51ac\u8463\u61c2\u52a8\u680b\u4f97\u606b\u51bb\u6d1e\u578c\u549a\u5cbd\u5cd2\u5902\u6c21\u80e8\u80f4\u7850\u9e2b',
+  'dou': '\u515c\u6296\u6597\u9661\u8c46\u9017\u75d8\u8538\u94ad\u7aa6\u7aac\u86aa\u7bfc\u9161',
+  'du': '\u90fd\u7763\u6bd2\u728a\u72ec\u8bfb\u5835\u7779\u8d4c\u675c\u9540\u809a\u5ea6\u6e21\u5992\u828f\u561f\u6e0e\u691f\u6a50\u724d\u8839\u7b03\u9ad1\u9ee9',
+  'duan': '\u7aef\u77ed\u953b\u6bb5\u65ad\u7f0e\u5f56\u6934\u7145\u7c16',
+  'dui': '\u5806\u5151\u961f\u5bf9\u603c\u619d\u7893',
+  'dun': '\u58a9\u5428\u8e72\u6566\u987f\u56e4\u949d\u76fe\u9041\u7096\u7818\u7905\u76f9\u9566\u8db8',
+  'duo': '\u6387\u54c6\u591a\u593a\u579b\u8eb2\u6735\u8dfa\u8235\u5241\u60f0\u5815\u5484\u54da\u7f0d\u67c1\u94ce\u88f0\u8e31',
+  'e': '\u86fe\u5ce8\u9e45\u4fc4\u989d\u8bb9\u5a25\u6076\u5384\u627c\u904f\u9102\u997f\u5669\u8c14\u57a9\u57ad\u82ca\u83aa\u843c\u5443\u6115\u5c59\u5a40\u8f6d\u66f7\u816d\u786a\u9507\u9537\u9e57\u989a\u9cc4',
+  'en': '\u6069\u84bd\u6441\u5514\u55ef',
+  'er': '\u800c\u513f\u8033\u5c14\u9975\u6d31\u4e8c\u8d30\u8fe9\u73e5\u94d2\u9e38\u9c95',
+  'fa': '\u53d1\u7f5a\u7b4f\u4f10\u4e4f\u9600\u6cd5\u73d0\u57a1\u781d',
+  'fan': '\u85e9\u5e06\u756a\u7ffb\u6a0a\u77fe\u9492\u7e41\u51e1\u70e6\u53cd\u8fd4\u8303\u8d29\u72af\u996d\u6cdb\u8629\u5e61\u72ad\u68b5\u6535\u71d4\u7548\u8e6f',
+  'fang': '\u574a\u82b3\u65b9\u80aa\u623f\u9632\u59a8\u4eff\u8bbf\u7eba\u653e\u531a\u90a1\u5f77\u94ab\u822b\u9c82',
+  'fei': '\u83f2\u975e\u5561\u98de\u80a5\u532a\u8bfd\u5420\u80ba\u5e9f\u6cb8\u8d39\u82be\u72d2\u60b1\u6ddd\u5983\u7ecb\u7eef\u69a7\u8153\u6590\u6249\u7953\u7829\u9544\u75f1\u871a\u7bda\u7fe1\u970f\u9cb1',
+  'fen': '\u82ac\u915a\u5429\u6c1b\u5206\u7eb7\u575f\u711a\u6c7e\u7c89\u594b\u4efd\u5fff\u6124\u7caa\u507e\u7035\u68fc\u610d\u9cbc\u9f22',
+  'feng': '\u4e30\u5c01\u67ab\u8702\u5cf0\u950b\u98ce\u75af\u70fd\u9022\u51af\u7f1d\u8bbd\u5949\u51e4\u4ff8\u9146\u8451\u6ca3\u781c',
+  'fu': '\u4f5b\u5426\u592b\u6577\u80a4\u5b75\u6276\u62c2\u8f90\u5e45\u6c1f\u7b26\u4f0f\u4fd8\u670d\u6d6e\u6daa\u798f\u88b1\u5f17\u752b\u629a\u8f85\u4fef\u91dc\u65a7\u812f\u8151\u5e9c\u8150\u8d74\u526f\u8986\u8d4b\u590d\u5085\u4ed8\u961c\u7236\u8179\u8d1f\u5bcc\u8ba3\u9644\u5987\u7f1a\u5490\u5310\u51eb\u90db\u8299\u82fb\u832f\u83a9\u83d4\u544b\u5e5e\u6ecf\u8274\u5b5a\u9a78\u7ec2\u6874\u8d59\u9efb\u9efc\u7f58\u7a03\u99a5\u864d\u86a8\u8709\u8760\u876e\u9eb8\u8dba\u8dd7\u9cc6',
+  'ga': '\u5676\u560e\u86e4\u5c2c\u5477\u5c15\u5c1c\u65ee\u9486',
+  'gai': '\u8be5\u6539\u6982\u9499\u76d6\u6e89\u4e10\u9654\u5793\u6224\u8d45\u80f2',
+  'gan': '\u5e72\u7518\u6746\u67d1\u7aff\u809d\u8d76\u611f\u79c6\u6562\u8d63\u5769\u82f7\u5c34\u64c0\u6cd4\u6de6\u6f89\u7ec0\u6a44\u65f0\u77f8\u75b3\u9150',
+  'gang': '\u5188\u521a\u94a2\u7f38\u809b\u7eb2\u5c97\u6e2f\u6206\u7f61\u9883\u7b7b',
+  'gong': '\u6760\u5de5\u653b\u529f\u606d\u9f9a\u4f9b\u8eac\u516c\u5bab\u5f13\u5de9\u6c5e\u62f1\u8d21\u5171\u857b\u5efe\u54a3\u73d9\u80b1\u86a3\u86e9\u89e5',
+  'gao': '\u7bd9\u768b\u9ad8\u818f\u7f94\u7cd5\u641e\u9550\u7a3f\u544a\u777e\u8bf0\u90dc\u84bf\u85c1\u7f1f\u69d4\u69c1\u6772\u9506',
+  'ge': '\u54e5\u6b4c\u6401\u6208\u9e3d\u80f3\u7599\u5272\u9769\u845b\u683c\u9601\u9694\u94ec\u4e2a\u5404\u9b32\u4ee1\u54ff\u5865\u55dd\u7ea5\u643f\u8188\u784c\u94ea\u9549\u88bc\u988c\u867c\u8238\u9abc\u9ac2',
+  'gei': '\u7ed9',
+  'gen': '\u6839\u8ddf\u4e98\u831b\u54cf\u826e',
+  'geng': '\u8015\u66f4\u5e9a\u7fb9\u57c2\u803f\u6897\u54fd\u8d53\u9ca0',
+  'gou': '\u94a9\u52fe\u6c9f\u82df\u72d7\u57a2\u6784\u8d2d\u591f\u4f5d\u8bdf\u5ca3\u9058\u5abe\u7f11\u89cf\u5f40\u9e32\u7b31\u7bdd\u97b2',
+  'gu': '\u8f9c\u83c7\u5495\u7b8d\u4f30\u6cbd\u5b64\u59d1\u9f13\u53e4\u86ca\u9aa8\u8c37\u80a1\u6545\u987e\u56fa\u96c7\u560f\u8bc2\u83f0\u54cc\u5d2e\u6c69\u688f\u8f71\u726f\u727f\u80cd\u81cc\u6bc2\u77bd\u7f5f\u94b4\u9522\u74e0\u9e2a\u9e44\u75fc\u86c4\u9164\u89da\u9cb4\u9ab0\u9e58',
+  'gua': '\u522e\u74dc\u5250\u5be1\u6302\u8902\u5366\u8bd6\u5471\u681d\u9e39',
+  'guai': '\u4e56\u62d0\u602a\u54d9',
+  'guan': '\u68fa\u5173\u5b98\u51a0\u89c2\u7ba1\u9986\u7f50\u60ef\u704c\u8d2f\u500c\u839e\u63bc\u6dab\u76e5\u9e73\u9ccf',
+  'guang': '\u5149\u5e7f\u901b\u72b7\u6844\u80f1\u7592',
+  'gui': '\u7470\u89c4\u572d\u7845\u5f52\u9f9f\u95fa\u8f68\u9b3c\u8be1\u7678\u6842\u67dc\u8dea\u8d35\u523d\u5326\u523f\u5e8b\u5b84\u59ab\u6867\u7085\u6677\u7688\u7c0b\u9c91\u9cdc',
+  'gun': '\u8f8a\u6eda\u68cd\u4e28\u886e\u7ef2\u78d9\u9ca7',
+  'guo': '\u9505\u90ed\u56fd\u679c\u88f9\u8fc7\u9998\u8803\u57da\u63b4\u5459\u56d7\u5e3c\u5d1e\u7313\u6901\u8662\u951e\u8052\u872e\u873e\u8748',
+  'ha': '\u54c8',
+  'hai': '\u9ab8\u5b69\u6d77\u6c26\u4ea5\u5bb3\u9a87\u54b4\u55e8\u988f\u91a2',
+  'han': '\u9163\u61a8\u90af\u97e9\u542b\u6db5\u5bd2\u51fd\u558a\u7f55\u7ff0\u64bc\u634d\u65f1\u61be\u608d\u710a\u6c57\u6c49\u9097\u83e1\u6496\u961a\u701a\u6657\u7113\u9894\u86b6\u9f3e',
+  'hen': '\u592f\u75d5\u5f88\u72e0\u6068',
+  'hang': '\u676d\u822a\u6c86\u7ed7\u73e9\u6841',
+  'hao': '\u58d5\u568e\u8c6a\u6beb\u90dd\u597d\u8017\u53f7\u6d69\u8585\u55e5\u5686\u6fe0\u704f\u660a\u7693\u98a2\u869d',
+  'he': '\u5475\u559d\u8377\u83cf\u6838\u79be\u548c\u4f55\u5408\u76d2\u8c89\u9602\u6cb3\u6db8\u8d6b\u8910\u9e64\u8d3a\u8bc3\u52be\u58d1\u85ff\u55d1\u55ec\u9616\u76cd\u86b5\u7fee',
+  'hei': '\u563f\u9ed1',
+  'heng': '\u54fc\u4ea8\u6a2a\u8861\u6052\u8a07\u8605',
+  'hong': '\u8f70\u54c4\u70d8\u8679\u9e3f\u6d2a\u5b8f\u5f18\u7ea2\u9ec9\u8ba7\u836d\u85a8\u95f3\u6cd3',
+  'hou': '\u5589\u4faf\u7334\u543c\u539a\u5019\u540e\u5820\u5f8c\u9005\u760a\u7bcc\u7cc7\u9c8e\u9aba',
+  'hu': '\u547c\u4e4e\u5ffd\u745a\u58f6\u846b\u80e1\u8774\u72d0\u7cca\u6e56\u5f27\u864e\u552c\u62a4\u4e92\u6caa\u6237\u51b1\u553f\u56eb\u5cb5\u7322\u6019\u60da\u6d52\u6ef9\u7425\u69f2\u8f77\u89f3\u70c0\u7173\u623d\u6248\u795c\u9e55\u9e71\u7b0f\u9190\u659b',
+  'hua': '\u82b1\u54d7\u534e\u733e\u6ed1\u753b\u5212\u5316\u8bdd\u5290\u6d4d\u9a85\u6866\u94e7\u7a1e',
+  'huai': '\u69d0\u5f8a\u6000\u6dee\u574f\u8fd8\u8e1d',
+  'huan': '\u6b22\u73af\u6853\u7f13\u6362\u60a3\u5524\u75ea\u8c62\u7115\u6da3\u5ba6\u5e7b\u90c7\u5942\u57b8\u64d0\u571c\u6d39\u6d63\u6f36\u5bf0\u902d\u7f33\u953e\u9ca9\u9b1f',
+  'huang': '\u8352\u614c\u9ec4\u78fa\u8757\u7c27\u7687\u51f0\u60f6\u714c\u6643\u5e4c\u604d\u8c0e\u968d\u5fa8\u6e5f\u6f62\u9051\u749c\u8093\u7640\u87e5\u7bc1\u9cc7',
+  'hui': '\u7070\u6325\u8f89\u5fbd\u6062\u86d4\u56de\u6bc1\u6094\u6167\u5349\u60e0\u6666\u8d3f\u79fd\u4f1a\u70e9\u6c47\u8bb3\u8bf2\u7ed8\u8bd9\u8334\u835f\u8559\u54d5\u5599\u96b3\u6d04\u5f57\u7f0b\u73f2\u6656\u605a\u867a\u87ea\u9ebe',
+  'hun': '\u8364\u660f\u5a5a\u9b42\u6d51\u6df7\u8be8\u9984\u960d\u6eb7\u7f17',
+  'huo': '\u8c41\u6d3b\u4f19\u706b\u83b7\u6216\u60d1\u970d\u8d27\u7978\u6509\u56af\u5925\u94ac\u952a\u956c\u8020\u8816',
+  'ji': '\u51fb\u573e\u57fa\u673a\u7578\u7a3d\u79ef\u7b95\u808c\u9965\u8ff9\u6fc0\u8ba5\u9e21\u59ec\u7ee9\u7f09\u5409\u6781\u68d8\u8f91\u7c4d\u96c6\u53ca\u6025\u75be\u6c72\u5373\u5ac9\u7ea7\u6324\u51e0\u810a\u5df1\u84df\u6280\u5180\u5b63\u4f0e\u796d\u5242\u60b8\u6d4e\u5bc4\u5bc2\u8ba1\u8bb0\u65e2\u5fcc\u9645\u5993\u7ee7\u7eaa\u5c45\u4e0c\u4e69\u525e\u4f76\u4f74\u8114\u58bc\u82a8\u82b0\u8401\u84ba\u857a\u638e\u53fd\u54ad\u54dc\u5527\u5c8c\u5d74\u6d0e\u5f50\u5c50\u9aa5\u757f\u7391\u696b\u6b9b\u621f\u6222\u8d4d\u89ca\u7284\u9f51\u77f6\u7f81\u5d47\u7a37\u7620\u7635\u866e\u7b08\u7b04\u66a8\u8dfb\u8dfd\u9701\u9c9a\u9cab\u9afb\u9e82',
+  'jia': '\u5609\u67b7\u5939\u4f73\u5bb6\u52a0\u835a\u988a\u8d3e\u7532\u94be\u5047\u7a3c\u4ef7\u67b6\u9a7e\u5ac1\u4f3d\u90cf\u62ee\u5cac\u6d43\u8fe6\u73c8\u621b\u80db\u605d\u94d7\u9553\u75c2\u86f1\u7b33\u8888\u8dcf',
+  'jian': '\u6b7c\u76d1\u575a\u5c16\u7b3a\u95f4\u714e\u517c\u80a9\u8270\u5978\u7f04\u8327\u68c0\u67ec\u78b1\u7877\u62e3\u6361\u7b80\u4fed\u526a\u51cf\u8350\u69db\u9274\u8df5\u8d31\u89c1\u952e\u7bad\u4ef6\u5065\u8230\u5251\u996f\u6e10\u6e85\u6da7\u5efa\u50ed\u8c0f\u8c2b\u83c5\u84b9\u641b\u56dd\u6e54\u8e47\u8b07\u7f23\u67a7\u67d9\u6957\u620b\u622c\u726e\u728d\u6bfd\u8171\u7751\u950f\u9e63\u88e5\u7b15\u7bb4\u7fe6\u8dbc\u8e3a\u9ca3\u97af',
+  'jiang': '\u50f5\u59dc\u5c06\u6d46\u6c5f\u7586\u848b\u6868\u5956\u8bb2\u5320\u9171\u964d\u8333\u6d1a\u7edb\u7f30\u729f\u7913\u8029\u7ce8\u8c47',
+  'jiao': '\u8549\u6912\u7901\u7126\u80f6\u4ea4\u90ca\u6d47\u9a84\u5a07\u56bc\u6405\u94f0\u77eb\u4fa5\u811a\u72e1\u89d2\u997a\u7f34\u7ede\u527f\u6559\u9175\u8f7f\u8f83\u53eb\u4f7c\u50ec\u832d\u6322\u564d\u5ce4\u5fbc\u59e3\u7e9f\u656b\u768e\u9e6a\u86df\u91ae\u8de4\u9c9b',
+  'jie': '\u7a96\u63ed\u63a5\u7686\u79f8\u8857\u9636\u622a\u52ab\u8282\u6854\u6770\u6377\u776b\u7aed\u6d01\u7ed3\u89e3\u59d0\u6212\u85c9\u82a5\u754c\u501f\u4ecb\u75a5\u8beb\u5c4a\u5048\u8ba6\u8bd8\u5588\u55df\u736c\u5a55\u5b51\u6840\u7352\u78a3\u9534\u7596\u88b7\u9889\u86a7\u7faf\u9c92\u9ab1\u9aeb',
+  'jin': '\u5dfe\u7b4b\u65a4\u91d1\u4eca\u6d25\u895f\u7d27\u9526\u4ec5\u8c28\u8fdb\u9773\u664b\u7981\u8fd1\u70ec\u6d78\u5c3d\u537a\u8369\u5807\u5664\u9991\u5ed1\u5997\u7f19\u747e\u69ff\u8d46\u89d0\u9485\u9513\u887f\u77dc',
+  'jing': '\u52b2\u8346\u5162\u830e\u775b\u6676\u9cb8\u4eac\u60ca\u7cbe\u7cb3\u7ecf\u4e95\u8b66\u666f\u9888\u9759\u5883\u656c\u955c\u5f84\u75c9\u9756\u7adf\u7ade\u51c0\u522d\u5106\u9631\u83c1\u734d\u61ac\u6cfe\u8ff3\u5f2a\u5a67\u80bc\u80eb\u8148\u65cc',
+  'jiong': '\u70af\u7a98\u5182\u8fe5\u6243',
+  'jiu': '\u63ea\u7a76\u7ea0\u7396\u97ed\u4e45\u7078\u4e5d\u9152\u53a9\u6551\u65e7\u81fc\u8205\u548e\u5c31\u759a\u50e6\u557e\u9604\u67e9\u6855\u9e6b\u8d73\u9b0f',
+  'ju': '\u97a0\u62d8\u72d9\u75bd\u9a79\u83ca\u5c40\u5480\u77e9\u4e3e\u6cae\u805a\u62d2\u636e\u5de8\u5177\u8ddd\u8e1e\u952f\u4ff1\u53e5\u60e7\u70ac\u5267\u5028\u8bb5\u82e3\u82f4\u8392\u63ac\u907d\u5c66\u741a\u67b8\u6910\u6998\u6989\u6a58\u728b\u98d3\u949c\u9514\u7aad\u88fe\u8d84\u91b5\u8e3d\u9f83\u96ce\u97ab',
+  'juan': '\u6350\u9e43\u5a1f\u5026\u7737\u5377\u7ee2\u9104\u72f7\u6d93\u684a\u8832\u9529\u954c\u96bd',
+  'jue': '\u6485\u652b\u6289\u6398\u5014\u7235\u89c9\u51b3\u8bc0\u7edd\u53a5\u5282\u8c32\u77cd\u8568\u5658\u5d1b\u7357\u5b53\u73cf\u6877\u6a5b\u721d\u9562\u8e76\u89d6',
+  'jun': '\u5747\u83cc\u94a7\u519b\u541b\u5cfb\u4fca\u7ae3\u6d5a\u90e1\u9a8f\u6343\u72fb\u76b2\u7b60\u9e87',
+  'ka': '\u5580\u5496\u5361\u4f67\u5494\u80e9',
+  'ke': '\u54af\u5777\u82db\u67ef\u68f5\u78d5\u9897\u79d1\u58f3\u54b3\u53ef\u6e34\u514b\u523b\u5ba2\u8bfe\u5ca2\u606a\u6e98\u9a92\u7f02\u73c2\u8f72\u6c2a\u778c\u94b6\u75b4\u7aa0\u874c\u9ac1',
+  'kai': '\u5f00\u63e9\u6977\u51ef\u6168\u5240\u57b2\u8488\u5ffe\u607a\u94e0\u950e',
+  'kan': '\u520a\u582a\u52d8\u574e\u780d\u770b\u4f83\u51f5\u83b0\u83b6\u6221\u9f9b\u77b0',
+  'kang': '\u5eb7\u6177\u7ce0\u625b\u6297\u4ea2\u7095\u5751\u4f09\u95f6\u94aa',
+  'kao': '\u8003\u62f7\u70e4\u9760\u5c3b\u6832\u7292\u94d0',
+  'ken': '\u80af\u5543\u57a6\u6073\u57a0\u88c9\u9880',
+  'keng': '\u542d\u5fd0\u94ff',
+  'kong': '\u7a7a\u6050\u5b54\u63a7\u5025\u5d06\u7b9c',
+  'kou': '\u62a0\u53e3\u6263\u5bc7\u82a4\u853b\u53e9\u770d\u7b58',
+  'ku': '\u67af\u54ed\u7a9f\u82e6\u9177\u5e93\u88e4\u5233\u5800\u55be\u7ed4\u9ab7',
+  'kua': '\u5938\u57ae\u630e\u8de8\u80ef\u4f89',
+  'kuai': '\u5757\u7b77\u4fa9\u5feb\u84af\u90d0\u8489\u72ef\u810d',
+  'kuan': '\u5bbd\u6b3e\u9acb',
+  'kuang': '\u5321\u7b50\u72c2\u6846\u77ff\u7736\u65f7\u51b5\u8bd3\u8bf3\u909d\u5739\u593c\u54d0\u7ea9\u8d36',
+  'kui': '\u4e8f\u76d4\u5cbf\u7aa5\u8475\u594e\u9b41\u5080\u9988\u6127\u6e83\u9997\u532e\u5914\u9697\u63c6\u55b9\u559f\u609d\u6126\u9615\u9035\u668c\u777d\u8069\u8770\u7bd1\u81fe\u8dec',
+  'kun': '\u5764\u6606\u6346\u56f0\u6083\u9603\u7428\u951f\u918c\u9cb2\u9ae1',
+  'kuo': '\u62ec\u6269\u5ed3\u9614\u86de',
+  'la': '\u5783\u62c9\u5587\u8721\u814a\u8fa3\u5566\u524c\u647a\u908b\u65ef\u782c\u760c',
+  'lai': '\u83b1\u6765\u8d56\u5d03\u5f95\u6d9e\u6fd1\u8d49\u7750\u94fc\u765e\u7c41',
+  'lan': '\u84dd\u5a6a\u680f\u62e6\u7bee\u9611\u5170\u6f9c\u8c30\u63fd\u89c8\u61d2\u7f06\u70c2\u6ee5\u5549\u5c9a\u61d4\u6f24\u6984\u6593\u7f71\u9567\u8934',
+  'lang': '\u7405\u6994\u72fc\u5eca\u90ce\u6717\u6d6a\u83a8\u8497\u5577\u9606\u9512\u7a02\u8782',
+  'lao': '\u635e\u52b3\u7262\u8001\u4f6c\u59e5\u916a\u70d9\u6d9d\u5520\u5d02\u6833\u94d1\u94f9\u75e8\u91aa',
+  'le': '\u52d2\u4e50\u808b\u4ec2\u53fb\u561e\u6cd0\u9cd3',
+  'lei': '\u96f7\u956d\u857e\u78ca\u7d2f\u5121\u5792\u64c2\u7c7b\u6cea\u7fb8\u8bd4\u837d\u54a7\u6f2f\u5ad8\u7f27\u6a91\u8012\u9179',
+  'ling': '\u68f1\u51b7\u62ce\u73b2\u83f1\u96f6\u9f84\u94c3\u4f36\u7f9a\u51cc\u7075\u9675\u5cad\u9886\u53e6\u4ee4\u9143\u5844\u82d3\u5464\u56f9\u6ce0\u7eeb\u67c3\u68c2\u74f4\u8046\u86c9\u7fce\u9cae',
+  'leng': '\u695e\u6123',
+  'li': '\u5398\u68a8\u7281\u9ece\u7bf1\u72f8\u79bb\u6f13\u7406\u674e\u91cc\u9ca4\u793c\u8389\u8354\u540f\u6817\u4e3d\u5389\u52b1\u783e\u5386\u5229\u5088\u4f8b\u4fd0\u75e2\u7acb\u7c92\u6ca5\u96b6\u529b\u7483\u54e9\u4fea\u4fda\u90e6\u575c\u82c8\u8385\u84e0\u85dc\u6369\u5456\u5533\u55b1\u7301\u6ea7\u6fa7\u9026\u5a0c\u5ae0\u9a8a\u7f21\u73de\u67a5\u680e\u8f79\u623e\u783a\u8a48\u7f79\u9502\u9e42\u75a0\u75ac\u86ce\u870a\u8821\u7b20\u7be5\u7c9d\u91b4\u8dde\u96f3\u9ca1\u9ce2\u9ee7',
+  'lian': '\u4fe9\u8054\u83b2\u8fde\u9570\u5ec9\u601c\u6d9f\u5e18\u655b\u8138\u94fe\u604b\u70bc\u7ec3\u631b\u8539\u5941\u6f4b\u6fc2\u5a08\u740f\u695d\u6b93\u81c1\u81a6\u88e2\u880a\u9ca2',
+  'liang': '\u7cae\u51c9\u6881\u7cb1\u826f\u4e24\u8f86\u91cf\u667e\u4eae\u8c05\u589a\u690b\u8e09\u9753\u9b49',
+  'liao': '\u64a9\u804a\u50da\u7597\u71ce\u5be5\u8fbd\u6f66\u4e86\u6482\u9563\u5ed6\u6599\u84fc\u5c25\u5639\u7360\u5bee\u7f2d\u948c\u9e69\u8022',
+  'lie': '\u5217\u88c2\u70c8\u52a3\u730e\u51bd\u57d2\u6d0c\u8d94\u8e90\u9b23',
+  'lin': '\u7433\u6797\u78f7\u9716\u4e34\u90bb\u9cde\u6dcb\u51db\u8d41\u541d\u853a\u5d99\u5eea\u9074\u6aa9\u8f9a\u77b5\u7cbc\u8e8f\u9e9f',
+  'liu': '\u6e9c\u7409\u69b4\u786b\u998f\u7559\u5218\u7624\u6d41\u67f3\u516d\u62a1\u507b\u848c\u6cd6\u6d4f\u905b\u9a9d\u7efa\u65d2\u7198\u950d\u954f\u9e68\u938f',
+  'long': '\u9f99\u804b\u5499\u7b3c\u7abf\u9686\u5784\u62e2\u9647\u5f04\u5785\u830f\u6cf7\u73d1\u680a\u80e7\u783b\u7643',
+  'lou': '\u697c\u5a04\u6402\u7bd3\u6f0f\u964b\u55bd\u5d5d\u9542\u7618\u8027\u877c\u9ac5',
+  'lu': '\u82a6\u5362\u9885\u5e90\u7089\u63b3\u5364\u864f\u9c81\u9e93\u788c\u9732\u8def\u8d42\u9e7f\u6f5e\u7984\u5f55\u9646\u622e\u5786\u6445\u64b8\u565c\u6cf8\u6e0c\u6f09\u7490\u680c\u6a79\u8f73\u8f82\u8f98\u6c07\u80ea\u9565\u9e2c\u9e6d\u7c0f\u823b\u9c88',
+  'lv': '\u9a74\u5415\u94dd\u4fa3\u65c5\u5c65\u5c61\u7f15\u8651\u6c2f\u5f8b\u7387\u6ee4\u7eff\u634b\u95fe\u6988\u8182\u7a06\u891b',
+  'luan': '\u5ce6\u5b6a\u6ee6\u5375\u4e71\u683e\u9e3e\u92ae',
+  'lue': '\u63a0\u7565\u950a',
+  'lun': '\u8f6e\u4f26\u4ed1\u6ca6\u7eb6\u8bba\u56f5',
+  'luo': '\u841d\u87ba\u7f57\u903b\u9523\u7ba9\u9aa1\u88f8\u843d\u6d1b\u9a86\u7edc\u502e\u8366\u645e\u7321\u6cfa\u6924\u8136\u9559\u7630\u96d2',
+  'ma': '\u5988\u9ebb\u739b\u7801\u8682\u9a6c\u9a82\u561b\u5417\u551b\u72b8\u5b37\u6769\u9ebd',
+  'mai': '\u57cb\u4e70\u9ea6\u5356\u8fc8\u8109\u52a2\u836c\u54aa\u973e',
+  'man': '\u7792\u9992\u86ee\u6ee1\u8513\u66fc\u6162\u6f2b\u8c29\u5881\u5e54\u7f26\u71b3\u9558\u989f\u87a8\u9cd7\u9794',
+  'mang': '\u8292\u832b\u76f2\u5fd9\u83bd\u9099\u6f2d\u6726\u786d\u87d2',
+  'meng': '\u6c13\u840c\u8499\u6aac\u76df\u9530\u731b\u68a6\u5b5f\u52d0\u750d\u77a2\u61f5\u791e\u867b\u8722\u8813\u824b\u8268\u9efe',
+  'miao': '\u732b\u82d7\u63cf\u7784\u85d0\u79d2\u6e3a\u5e99\u5999\u55b5\u9088\u7f08\u7f2a\u676a\u6dfc\u7707\u9e4b\u8731',
+  'mao': '\u8305\u951a\u6bdb\u77db\u94c6\u536f\u8302\u5192\u5e3d\u8c8c\u8d38\u4f94\u88a4\u52d6\u8306\u5cc1\u7441\u6634\u7266\u8004\u65c4\u61cb\u7780\u86d1\u8765\u87ca\u9ae6',
+  'me': '\u4e48',
+  'mei': '\u73ab\u679a\u6885\u9176\u9709\u7164\u6ca1\u7709\u5a92\u9541\u6bcf\u7f8e\u6627\u5bd0\u59b9\u5a9a\u5776\u8393\u5d4b\u7338\u6d7c\u6e44\u6963\u9545\u9e5b\u8882\u9b45',
+  'men': '\u95e8\u95f7\u4eec\u626a\u739f\u7116\u61d1\u9494',
+  'mi': '\u772f\u919a\u9761\u7cdc\u8ff7\u8c1c\u5f25\u7c73\u79d8\u89c5\u6ccc\u871c\u5bc6\u5e42\u8288\u5196\u8c27\u863c\u5627\u7315\u736f\u6c68\u5b93\u5f2d\u8112\u6549\u7cf8\u7e3b\u9e8b',
+  'mian': '\u68c9\u7720\u7ef5\u5195\u514d\u52c9\u5a29\u7f05\u9762\u6c94\u6e4e\u817c\u7704',
+  'mie': '\u8511\u706d\u54a9\u881b\u7bfe',
+  'min': '\u6c11\u62bf\u76bf\u654f\u60af\u95fd\u82e0\u5cb7\u95f5\u6cef\u73c9',
+  'ming': '\u660e\u879f\u9e23\u94ed\u540d\u547d\u51a5\u8317\u6e9f\u669d\u7791\u9169',
+  'miu': '\u8c2c',
+  'mo': '\u6478\u6479\u8611\u6a21\u819c\u78e8\u6469\u9b54\u62b9\u672b\u83ab\u58a8\u9ed8\u6cab\u6f20\u5bde\u964c\u8c1f\u8309\u84e6\u998d\u5aeb\u9546\u79e3\u763c\u8031\u87c6\u8c8a\u8c98',
+  'mou': '\u8c0b\u725f\u67d0\u53b6\u54de\u5a7a\u7738\u936a',
+  'mu': '\u62c7\u7261\u4ea9\u59c6\u6bcd\u5893\u66ae\u5e55\u52df\u6155\u6728\u76ee\u7766\u7267\u7a46\u4eeb\u82dc\u5452\u6c90\u6bea\u94bc',
+  'na': '\u62ff\u54ea\u5450\u94a0\u90a3\u5a1c\u7eb3\u5185\u637a\u80ad\u954e\u8872\u7bac',
+  'nai': '\u6c16\u4e43\u5976\u8010\u5948\u9f10\u827f\u8418\u67f0',
+  'nan': '\u5357\u7537\u96be\u56ca\u5583\u56e1\u6960\u8169\u877b\u8d67',
+  'nao': '\u6320\u8111\u607c\u95f9\u5b6c\u57b4\u7331\u7459\u7847\u94d9\u86f2',
+  'ne': '\u6dd6\u5462\u8bb7',
+  'nei': '\u9981',
+  'nen': '\u5ae9\u80fd\u6798\u6041',
+  'ni': '\u59ae\u9713\u502a\u6ce5\u5c3c\u62df\u4f60\u533f\u817b\u9006\u6eba\u4f32\u576d\u730a\u6029\u6ee0\u6635\u65ce\u7962\u615d\u7768\u94cc\u9cb5',
+  'nian': '\u852b\u62c8\u5e74\u78be\u64b5\u637b\u5ff5\u5eff\u8f87\u9ecf\u9c87\u9cb6',
+  'niang': '\u5a18\u917f',
+  'niao': '\u9e1f\u5c3f\u8311\u5b32\u8132\u8885',
+  'nie': '\u634f\u8042\u5b7d\u556e\u954a\u954d\u6d85\u4e5c\u9667\u8616\u55eb\u8080\u989e\u81ec\u8e51',
+  'nin': '\u60a8\u67e0',
+  'ning': '\u72de\u51dd\u5b81\u62e7\u6cde\u4f5e\u84e5\u549b\u752f\u804d',
+  'niu': '\u725b\u626d\u94ae\u7ebd\u72c3\u5ff8\u599e\u86b4',
+  'nong': '\u8113\u6d53\u519c\u4fac',
+  'nu': '\u5974\u52aa\u6012\u5476\u5e11\u5f29\u80ec\u5b65\u9a7d',
+  'nv': '\u5973\u6067\u9495\u8844',
+  'nuan': '\u6696',
+  'nuenue': '\u8650',
+  'nue': '\u759f\u8c11',
+  'nuo': '\u632a\u61e6\u7cef\u8bfa\u50a9\u6426\u558f\u9518',
+  'ou': '\u54e6\u6b27\u9e25\u6bb4\u85d5\u5455\u5076\u6ca4\u6004\u74ef\u8026',
+  'pa': '\u556a\u8db4\u722c\u5e15\u6015\u7436\u8469\u7b62',
+  'pai': '\u62cd\u6392\u724c\u5f98\u6e43\u6d3e\u4ff3\u848e',
+  'pan': '\u6500\u6f58\u76d8\u78d0\u76fc\u7554\u5224\u53db\u723f\u6cee\u88a2\u897b\u87e0\u8e52',
+  'pang': '\u4e53\u5e9e\u65c1\u802a\u80d6\u6ec2\u9004',
+  'pao': '\u629b\u5486\u5228\u70ae\u888d\u8dd1\u6ce1\u530f\u72cd\u5e96\u812c\u75b1',
+  'pei': '\u5478\u80da\u57f9\u88f4\u8d54\u966a\u914d\u4f69\u6c9b\u638a\u8f94\u5e14\u6de0\u65c6\u952b\u9185\u9708',
+  'pen': '\u55b7\u76c6\u6e53',
+  'peng': '\u7830\u62a8\u70f9\u6f8e\u5f6d\u84ec\u68da\u787c\u7bf7\u81a8\u670b\u9e4f\u6367\u78b0\u576f\u580b\u562d\u6026\u87db',
+  'pi': '\u7812\u9739\u6279\u62ab\u5288\u7435\u6bd7\u5564\u813e\u75b2\u76ae\u5339\u75de\u50fb\u5c41\u8b6c\u4e15\u9674\u90b3\u90eb\u572e\u9f19\u64d7\u567c\u5e80\u5ab2\u7eb0\u6787\u7513\u7765\u7f74\u94cd\u75e6\u7656\u758b\u868d\u8c94',
+  'pian': '\u7bc7\u504f\u7247\u9a97\u8c1d\u9a88\u728f\u80fc\u890a\u7fe9\u8e41',
+  'piao': '\u98d8\u6f02\u74e2\u7968\u527d\u560c\u5ad6\u7f25\u6b8d\u779f\u87b5',
+  'pie': '\u6487\u77a5\u4e3f\u82e4\u6c15',
+  'pin': '\u62fc\u9891\u8d2b\u54c1\u8058\u62da\u59d8\u5ad4\u6980\u725d\u98a6',
+  'ping': '\u4e52\u576a\u82f9\u840d\u5e73\u51ed\u74f6\u8bc4\u5c4f\u4fdc\u5a09\u67b0\u9c86',
+  'po': '\u5761\u6cfc\u9887\u5a46\u7834\u9b44\u8feb\u7c95\u53f5\u9131\u6ea5\u73c0\u948b\u94b7\u76a4\u7b38',
+  'pou': '\u5256\u88d2\u8e23',
+  'pu': '\u6251\u94fa\u4ec6\u8386\u8461\u83e9\u84b2\u57d4\u6734\u5703\u666e\u6d66\u8c31\u66dd\u7011\u530d\u5657\u6fee\u749e\u6c06\u9564\u9568\u8e7c',
+  'qi': '\u671f\u6b3a\u6816\u621a\u59bb\u4e03\u51c4\u6f06\u67d2\u6c8f\u5176\u68cb\u5947\u6b67\u7566\u5d0e\u8110\u9f50\u65d7\u7948\u7941\u9a91\u8d77\u5c82\u4e5e\u4f01\u542f\u5951\u780c\u5668\u6c14\u8fc4\u5f03\u6c7d\u6ce3\u8bab\u4e9f\u4e93\u573b\u8291\u840b\u847a\u5601\u5c7a\u5c90\u6c54\u6dc7\u9a90\u7eee\u742a\u7426\u675e\u6864\u69ed\u6b39\u797a\u61a9\u789b\u86f4\u871e\u7da6\u7dae\u8dbf\u8e4a\u9ccd\u9e92',
+  'qia': '\u6390\u6070\u6d3d\u845c',
+  'qian': '\u7275\u6266\u948e\u94c5\u5343\u8fc1\u7b7e\u4edf\u8c26\u4e7e\u9ed4\u94b1\u94b3\u524d\u6f5c\u9063\u6d45\u8c34\u5811\u5d4c\u6b20\u6b49\u4f65\u9621\u828a\u82a1\u8368\u63ae\u5c8d\u60ad\u614a\u9a9e\u6434\u8930\u7f31\u6920\u80b7\u6106\u94a4\u8654\u7b9d',
+  'qiang': '\u67aa\u545b\u8154\u7f8c\u5899\u8537\u5f3a\u62a2\u5af1\u6a2f\u6217\u709d\u9516\u9535\u956a\u8941\u8723\u7f9f\u8deb\u8dc4',
+  'qiao': '\u6a47\u9539\u6572\u6084\u6865\u77a7\u4e54\u4fa8\u5de7\u9798\u64ac\u7fd8\u5ced\u4fcf\u7a8d\u5281\u8bee\u8c2f\u835e\u6100\u6194\u7f32\u6a35\u6bf3\u7857\u8df7\u9792',
+  'qie': '\u5207\u8304\u4e14\u602f\u7a83\u90c4\u553c\u60ec\u59be\u6308\u9532\u7ba7',
+  'qin': '\u94a6\u4fb5\u4eb2\u79e6\u7434\u52e4\u82b9\u64d2\u79bd\u5bdd\u6c81\u82a9\u84c1\u8572\u63ff\u5423\u55ea\u5659\u6eb1\u6a8e\u8793\u887e',
+  'qing': '\u9752\u8f7b\u6c22\u503e\u537f\u6e05\u64ce\u6674\u6c30\u60c5\u9877\u8bf7\u5e86\u5029\u82d8\u570a\u6aa0\u78ec\u873b\u7f44\u7b90\u8b26\u9cad\u9ee5',
+  'qiong': '\u743c\u7a77\u909b\u8315\u7a79\u7b47\u928e',
+  'qiu': '\u79cb\u4e18\u90b1\u7403\u6c42\u56da\u914b\u6cc5\u4fc5\u6c3d\u5def\u827d\u72b0\u6e6b\u9011\u9052\u6978\u8d47\u9e20\u866c\u86af\u8764\u88d8\u7cd7\u9cc5\u9f3d',
+  'qu': '\u8d8b\u533a\u86c6\u66f2\u8eaf\u5c48\u9a71\u6e20\u53d6\u5a36\u9f8b\u8da3\u53bb\u8bce\u52ac\u8556\u8627\u5c96\u8862\u9612\u74a9\u89d1\u6c0d\u795b\u78f2\u766f\u86d0\u883c\u9eb4\u77bf\u9ee2',
+  'quan': '\u5708\u98a7\u6743\u919b\u6cc9\u5168\u75ca\u62f3\u72ac\u5238\u529d\u8be0\u8343\u737e\u609b\u7efb\u8f81\u754e\u94e8\u8737\u7b4c\u9b08',
+  'que': '\u7f3a\u7094\u7638\u5374\u9e4a\u69b7\u786e\u96c0\u9619\u60ab',
+  'qun': '\u88d9\u7fa4\u9021',
+  'ran': '\u7136\u71c3\u5189\u67d3\u82d2\u9aef',
+  'rang': '\u74e4\u58e4\u6518\u56b7\u8ba9\u79b3\u7a70',
+  'rao': '\u9976\u6270\u7ed5\u835b\u5a06\u6861',
+  'ruo': '\u60f9\u82e5\u5f31',
+  're': '\u70ed\u504c',
+  'ren': '\u58ec\u4ec1\u4eba\u5fcd\u97e7\u4efb\u8ba4\u5203\u598a\u7eab\u4ede\u834f\u845a\u996a\u8f6b\u7a14\u887d',
+  'reng': '\u6254\u4ecd',
+  'ri': '\u65e5',
+  'rong': '\u620e\u8338\u84c9\u8363\u878d\u7194\u6eb6\u5bb9\u7ed2\u5197\u5d58\u72e8\u7f1b\u6995\u877e',
+  'rou': '\u63c9\u67d4\u8089\u7cc5\u8e42\u97a3',
+  'ru': '\u8339\u8815\u5112\u5b7a\u5982\u8fb1\u4e73\u6c5d\u5165\u8925\u84d0\u85b7\u5685\u6d33\u6ebd\u6fe1\u94f7\u8966\u98a5',
+  'ruan': '\u8f6f\u962e\u670a',
+  'rui': '\u854a\u745e\u9510\u82ae\u8564\u777f\u868b',
+  'run': '\u95f0\u6da6',
+  'sa': '\u6492\u6d12\u8428\u5345\u4ee8\u6332\u98d2',
+  'sai': '\u816e\u9cc3\u585e\u8d5b\u567b',
+  'san': '\u4e09\u53c1\u4f1e\u6563\u5f61\u9993\u6c35\u6bf5\u7cc1\u9730',
+  'sang': '\u6851\u55d3\u4e27\u6421\u78c9\u98a1',
+  'sao': '\u6414\u9a9a\u626b\u5ac2\u57fd\u81ca\u7619\u9ccb',
+  'se': '\u745f\u8272\u6da9\u556c\u94e9\u94ef\u7a51',
+  'sen': '\u68ee',
+  'seng': '\u50e7',
+  'sha': '\u838e\u7802\u6740\u5239\u6c99\u7eb1\u50bb\u5565\u715e\u810e\u6b43\u75e7\u88df\u970e\u9ca8',
+  'shai': '\u7b5b\u6652\u917e',
+  'shan': '\u73ca\u82eb\u6749\u5c71\u5220\u717d\u886b\u95ea\u9655\u64c5\u8d61\u81b3\u5584\u6c55\u6247\u7f2e\u5261\u8baa\u912f\u57cf\u829f\u6f78\u59d7\u9a9f\u81bb\u9490\u759d\u87ee\u8222\u8dda\u9cdd',
+  'shang': '\u5892\u4f24\u5546\u8d4f\u664c\u4e0a\u5c1a\u88f3\u57a7\u7ef1\u6b87\u71b5\u89de',
+  'shao': '\u68a2\u634e\u7a0d\u70e7\u828d\u52fa\u97f6\u5c11\u54e8\u90b5\u7ecd\u52ad\u82d5\u6f72\u86f8\u7b24\u7b72\u8244',
+  'she': '\u5962\u8d4a\u86c7\u820c\u820d\u8d66\u6444\u5c04\u6151\u6d89\u793e\u8bbe\u538d\u4f58\u731e\u7572\u9e9d',
+  'shen': '\u7837\u7533\u547b\u4f38\u8eab\u6df1\u5a20\u7ec5\u795e\u6c88\u5ba1\u5a76\u751a\u80be\u614e\u6e17\u8bdc\u8c02\u5432\u54c2\u6e16\u6939\u77e7\u8703',
+  'sheng': '\u58f0\u751f\u7525\u7272\u5347\u7ef3\u7701\u76db\u5269\u80dc\u5723\u4e1e\u6e11\u5ab5\u771a\u7b19',
+  'shi': '\u5e08\u5931\u72ee\u65bd\u6e7f\u8bd7\u5c38\u8671\u5341\u77f3\u62fe\u65f6\u4ec0\u98df\u8680\u5b9e\u8bc6\u53f2\u77e2\u4f7f\u5c4e\u9a76\u59cb\u5f0f\u793a\u58eb\u4e16\u67ff\u4e8b\u62ed\u8a93\u901d\u52bf\u662f\u55dc\u566c\u9002\u4ed5\u4f8d\u91ca\u9970\u6c0f\u5e02\u6043\u5ba4\u89c6\u8bd5\u8c25\u57d8\u83b3\u84cd\u5f11\u5511\u9963\u8f7c\u8006\u8d33\u70bb\u793b\u94c8\u94ca\u87ab\u8210\u7b6e\u8c55\u9ca5\u9cba',
+  'shou': '\u6536\u624b\u9996\u5b88\u5bff\u6388\u552e\u53d7\u7626\u517d\u624c\u72e9\u7ef6\u824f',
+  'shu': '\u852c\u67a2\u68b3\u6b8a\u6292\u8f93\u53d4\u8212\u6dd1\u758f\u4e66\u8d4e\u5b70\u719f\u85af\u6691\u66d9\u7f72\u8700\u9ecd\u9f20\u5c5e\u672f\u8ff0\u6811\u675f\u620d\u7ad6\u5885\u5eb6\u6570\u6f31\u6055\u500f\u587e\u83fd\u5fc4\u6cad\u6d91\u6f8d\u59dd\u7ebe\u6bf9\u8167\u6bb3\u956f\u79eb\u9e6c',
+  'shua': '\u5237\u800d\u5530\u6dae',
+  'shuai': '\u6454\u8870\u7529\u5e05\u87c0',
+  'shuan': '\u6813\u62f4\u95e9',
+  'shuang': '\u971c\u53cc\u723d\u5b40',
+  'shui': '\u8c01\u6c34\u7761\u7a0e',
+  'shun': '\u542e\u77ac\u987a\u821c\u6042',
+  'shuo': '\u8bf4\u7855\u6714\u70c1\u84b4\u6420\u55cd\u6fef\u5981\u69ca\u94c4',
+  'si': '\u65af\u6495\u5636\u601d\u79c1\u53f8\u4e1d\u6b7b\u8086\u5bfa\u55e3\u56db\u4f3a\u4f3c\u9972\u5df3\u53ae\u4fdf\u5155\u83e5\u549d\u6c5c\u6cd7\u6f8c\u59d2\u9a77\u7f0c\u7940\u7960\u9536\u9e36\u801c\u86f3\u7b25',
+  'song': '\u677e\u8038\u6002\u9882\u9001\u5b8b\u8bbc\u8bf5\u51c7\u83d8\u5d27\u5d69\u5fea\u609a\u6dde\u7ae6',
+  'sou': '\u641c\u8258\u64de\u55fd\u53df\u55d6\u55fe\u998a\u6eb2\u98d5\u778d\u953c\u878b',
+  'su': '\u82cf\u9165\u4fd7\u7d20\u901f\u7c9f\u50f3\u5851\u6eaf\u5bbf\u8bc9\u8083\u5919\u8c21\u850c\u55c9\u612b\u7c0c\u89eb\u7a23',
+  'suan': '\u9178\u849c\u7b97',
+  'sui': '\u867d\u968b\u968f\u7ee5\u9ad3\u788e\u5c81\u7a57\u9042\u96a7\u795f\u84d1\u51ab\u8c07\u6fc9\u9083\u71e7\u772d\u7762',
+  'sun': '\u5b59\u635f\u7b0b\u836a\u72f2\u98e7\u69ab\u8de3\u96bc',
+  'suo': '\u68ad\u5506\u7f29\u7410\u7d22\u9501\u6240\u5522\u55e6\u5a11\u686b\u7743\u7fa7',
+  'ta': '\u584c\u4ed6\u5b83\u5979\u5854\u736d\u631e\u8e4b\u8e0f\u95fc\u6ebb\u9062\u69bb\u6c93',
+  'tai': '\u80ce\u82d4\u62ac\u53f0\u6cf0\u915e\u592a\u6001\u6c70\u90b0\u85b9\u80bd\u70b1\u949b\u8dc6\u9c90',
+  'tan': '\u574d\u644a\u8d2a\u762b\u6ee9\u575b\u6a80\u75f0\u6f6d\u8c2d\u8c08\u5766\u6bef\u8892\u78b3\u63a2\u53f9\u70ad\u90ef\u8548\u6619\u94bd\u952c\u8983',
+  'tang': '\u6c64\u5858\u642a\u5802\u68e0\u819b\u5510\u7cd6\u50a5\u9967\u6e8f\u746d\u94f4\u9557\u8025\u8797\u87b3\u7fb0\u91a3',
+  'thang': '\u5018\u8eba\u6dcc',
+  'theng': '\u8d9f\u70eb',
+  'tao': '\u638f\u6d9b\u6ed4\u7ee6\u8404\u6843\u9003\u6dd8\u9676\u8ba8\u5957\u6311\u9f17\u5555\u97ec\u9955',
+  'te': '\u7279',
+  'teng': '\u85e4\u817e\u75bc\u8a8a\u6ed5',
+  'ti': '\u68af\u5254\u8e22\u9511\u63d0\u9898\u8e44\u557c\u4f53\u66ff\u568f\u60d5\u6d95\u5243\u5c49\u8351\u608c\u9016\u7ee8\u7f07\u9e48\u88fc\u918d',
+  'tian': '\u5929\u6dfb\u586b\u7530\u751c\u606c\u8214\u8146\u63ad\u5fdd\u9617\u6b84\u754b\u94bf\u86ba',
+  'tiao': '\u6761\u8fe2\u773a\u8df3\u4f7b\u7967\u94eb\u7a95\u9f86\u9ca6',
+  'tie': '\u8d34\u94c1\u5e16\u841c\u992e',
+  'ting': '\u5385\u542c\u70c3\u6c40\u5ef7\u505c\u4ead\u5ead\u633a\u8247\u839b\u8476\u5a77\u6883\u8713\u9706',
+  'tong': '\u901a\u6850\u916e\u77b3\u540c\u94dc\u5f64\u7ae5\u6876\u6345\u7b52\u7edf\u75db\u4f5f\u50ee\u4edd\u833c\u55f5\u6078\u6f7c\u783c',
+  'tou': '\u5077\u6295\u5934\u900f\u4ea0',
+  'tu': '\u51f8\u79c3\u7a81\u56fe\u5f92\u9014\u6d82\u5c60\u571f\u5410\u5154\u580d\u837c\u83df\u948d\u9174',
+  'tuan': '\u6e4d\u56e2\u7583',
+  'tui': '\u63a8\u9893\u817f\u8715\u892a\u9000\u5fd2\u717a',
+  'tun': '\u541e\u5c6f\u81c0\u9968\u66be\u8c5a\u7a80',
+  'tuo': '\u62d6\u6258\u8131\u9e35\u9640\u9a6e\u9a7c\u692d\u59a5\u62d3\u553e\u4e47\u4f57\u5768\u5eb9\u6cb1\u67dd\u7823\u7ba8\u8204\u8dce\u9f0d',
+  'wa': '\u6316\u54c7\u86d9\u6d3c\u5a03\u74e6\u889c\u4f64\u5a32\u817d',
+  'wai': '\u6b6a\u5916',
+  'wan': '\u8c4c\u5f2f\u6e7e\u73a9\u987d\u4e38\u70f7\u5b8c\u7897\u633d\u665a\u7696\u60cb\u5b9b\u5a49\u4e07\u8155\u525c\u8284\u82cb\u83c0\u7ea8\u7efe\u742c\u8118\u7579\u873f\u7ba2',
+  'wang': '\u6c6a\u738b\u4ea1\u6789\u7f51\u5f80\u65fa\u671b\u5fd8\u5984\u7f54\u5c22\u60d8\u8f8b\u9b4d',
+  'wei': '\u5a01\u5dcd\u5fae\u5371\u97e6\u8fdd\u6845\u56f4\u552f\u60df\u4e3a\u6f4d\u7ef4\u82c7\u840e\u59d4\u4f1f\u4f2a\u5c3e\u7eac\u672a\u851a\u5473\u754f\u80c3\u5582\u9b4f\u4f4d\u6e2d\u8c13\u5c09\u6170\u536b\u502d\u504e\u8bff\u9688\u8473\u8587\u5e0f\u5e37\u5d34\u5d6c\u7325\u732c\u95f1\u6ca9\u6d27\u6da0\u9036\u5a13\u73ae\u97ea\u8ece\u709c\u7168\u71a8\u75ff\u8249\u9c94',
+  'wen': '\u761f\u6e29\u868a\u6587\u95fb\u7eb9\u543b\u7a33\u7d0a\u95ee\u520e\u6120\u960c\u6c76\u74ba\u97eb\u6b81\u96ef',
+  'weng': '\u55e1\u7fc1\u74ee\u84ca\u8579',
+  'wo': '\u631d\u8717\u6da1\u7a9d\u6211\u65a1\u5367\u63e1\u6c83\u83b4\u5e44\u6e25\u674c\u809f\u9f8c',
+  'wu': '\u5deb\u545c\u94a8\u4e4c\u6c61\u8bec\u5c4b\u65e0\u829c\u68a7\u543e\u5434\u6bcb\u6b66\u4e94\u6342\u5348\u821e\u4f0d\u4fae\u575e\u620a\u96fe\u6664\u7269\u52ff\u52a1\u609f\u8bef\u5140\u4ef5\u9622\u90ac\u572c\u82b4\u5e91\u6003\u5fe4\u6d6f\u5be4\u8fd5\u59a9\u9a9b\u727e\u7110\u9e49\u9e5c\u8708\u92c8\u9f2f',
+  'xi': '\u6614\u7199\u6790\u897f\u7852\u77fd\u6670\u563b\u5438\u9521\u727a\u7a00\u606f\u5e0c\u6089\u819d\u5915\u60dc\u7184\u70ef\u6eaa\u6c50\u7280\u6a84\u88ad\u5e2d\u4e60\u5ab3\u559c\u94e3\u6d17\u7cfb\u9699\u620f\u7ec6\u50d6\u516e\u96b0\u90d7\u831c\u8478\u84f0\u595a\u550f\u5f99\u9969\u960b\u6d60\u6dc5\u5c63\u5b09\u73ba\u6a28\u66e6\u89cb\u6b37\u71b9\u798a\u79a7\u94b8\u7699\u7a78\u8725\u87cb\u823e\u7fb2\u7c9e\u7fd5\u91af\u9f37',
+  'xia': '\u778e\u867e\u5323\u971e\u8f96\u6687\u5ce1\u4fa0\u72ed\u4e0b\u53a6\u590f\u5413\u6380\u846d\u55c4\u72ce\u9050\u7455\u7856\u7615\u7f45\u9ee0',
+  'xian': '\u9528\u5148\u4ed9\u9c9c\u7ea4\u54b8\u8d24\u8854\u8237\u95f2\u6d8e\u5f26\u5acc\u663e\u9669\u73b0\u732e\u53bf\u817a\u9985\u7fa1\u5baa\u9677\u9650\u7ebf\u51bc\u85d3\u5c98\u7303\u66b9\u5a34\u6c19\u7946\u9e47\u75eb\u86ac\u7b45\u7c7c\u9170\u8df9',
+  'xiang': '\u76f8\u53a2\u9576\u9999\u7bb1\u8944\u6e58\u4e61\u7fd4\u7965\u8be6\u60f3\u54cd\u4eab\u9879\u5df7\u6a61\u50cf\u5411\u8c61\u8297\u8459\u9977\u5ea0\u9aa7\u7f03\u87d3\u9c9e\u98e8',
+  'xiao': '\u8427\u785d\u9704\u524a\u54ee\u56a3\u9500\u6d88\u5bb5\u6dc6\u6653\u5c0f\u5b5d\u6821\u8096\u5578\u7b11\u6548\u54d3\u54bb\u5d24\u6f47\u900d\u9a81\u7ee1\u67ad\u67b5\u7b71\u7bab\u9b48',
+  'xie': '\u6954\u4e9b\u6b47\u874e\u978b\u534f\u631f\u643a\u90aa\u659c\u80c1\u8c10\u5199\u68b0\u5378\u87f9\u61c8\u6cc4\u6cfb\u8c22\u5c51\u5055\u4eb5\u52f0\u71ee\u85a4\u64b7\u5ee8\u7023\u9082\u7ec1\u7f2c\u69ad\u698d\u6b59\u8e9e',
+  'xin': '\u85aa\u82af\u950c\u6b23\u8f9b\u65b0\u5ffb\u5fc3\u4fe1\u8845\u56df\u99a8\u8398\u6b46\u94fd\u946b',
+  'xing': '\u661f\u8165\u7329\u60fa\u5174\u5211\u578b\u5f62\u90a2\u884c\u9192\u5e78\u674f\u6027\u59d3\u9649\u8347\u8365\u64e4\u60bb\u784e',
+  'xiong': '\u5144\u51f6\u80f8\u5308\u6c79\u96c4\u718a\u828e',
+  'xiu': '\u4f11\u4fee\u7f9e\u673d\u55c5\u9508\u79c0\u8896\u7ee3\u83a0\u5cab\u9990\u5ea5\u9e3a\u8c85\u9af9',
+  'xu': '\u589f\u620c\u9700\u865a\u5618\u987b\u5f90\u8bb8\u84c4\u9157\u53d9\u65ed\u5e8f\u755c\u6064\u7d6e\u5a7f\u7eea\u7eed\u8bb4\u8be9\u5729\u84ff\u6035\u6d2b\u6e86\u987c\u6829\u7166\u7809\u76f1\u80e5\u7cc8\u9191',
+  'xuan': '\u8f69\u55a7\u5ba3\u60ac\u65cb\u7384\u9009\u7663\u7729\u7eda\u5107\u8c16\u8431\u63ce\u9994\u6ceb\u6d35\u6e32\u6f29\u7487\u6966\u6684\u70ab\u714a\u78b9\u94c9\u955f\u75c3',
+  'xue': '\u9774\u859b\u5b66\u7a74\u96ea\u8840\u5671\u6cf6\u9cd5',
+  'xun': '\u52cb\u718f\u5faa\u65ec\u8be2\u5bfb\u9a6f\u5de1\u6b89\u6c5b\u8bad\u8baf\u900a\u8fc5\u5dfd\u57d9\u8340\u85b0\u5ccb\u5f87\u6d54\u66db\u7aa8\u91ba\u9c9f',
+  'ya': '\u538b\u62bc\u9e26\u9e2d\u5440\u4e2b\u82bd\u7259\u869c\u5d16\u8859\u6daf\u96c5\u54d1\u4e9a\u8bb6\u4f22\u63e0\u5416\u5c88\u8fd3\u5a05\u740a\u6860\u6c29\u7811\u775a\u75d6',
+  'yan': '\u7109\u54bd\u9609\u70df\u6df9\u76d0\u4e25\u7814\u8712\u5ca9\u5ef6\u8a00\u989c\u960e\u708e\u6cbf\u5944\u63a9\u773c\u884d\u6f14\u8273\u5830\u71d5\u538c\u781a\u96c1\u5501\u5f66\u7130\u5bb4\u8c1a\u9a8c\u53a3\u9765\u8d5d\u4fe8\u5043\u5156\u8ba0\u8c33\u90fe\u9122\u82ab\u83f8\u5d26\u6079\u95eb\u960f\u6d07\u6e6e\u6edf\u598d\u5ae3\u7430\u664f\u80ed\u814c\u7131\u7f68\u7b75\u917d\u9b47\u990d\u9f39',
+  'yang': '\u6b83\u592e\u9e2f\u79e7\u6768\u626c\u4f6f\u75a1\u7f8a\u6d0b\u9633\u6c27\u4ef0\u75d2\u517b\u6837\u6f3e\u5f89\u600f\u6cf1\u7080\u70ca\u6059\u86d8\u9785',
+  'yao': '\u9080\u8170\u5996\u7476\u6447\u5c27\u9065\u7a91\u8c23\u59da\u54ac\u8200\u836f\u8981\u8000\u592d\u723b\u5406\u5d3e\u5fad\u7039\u5e7a\u73e7\u6773\u66dc\u80b4\u9e5e\u7a88\u7e47\u9cd0',
+  'ye': '\u6930\u564e\u8036\u7237\u91ce\u51b6\u4e5f\u9875\u6396\u4e1a\u53f6\u66f3\u814b\u591c\u6db2\u8c12\u90ba\u63f6\u9980\u6654\u70e8\u94d8',
+  'yi': '\u4e00\u58f9\u533b\u63d6\u94f1\u4f9d\u4f0a\u8863\u9890\u5937\u9057\u79fb\u4eea\u80f0\u7591\u6c82\u5b9c\u59e8\u5f5d\u6905\u8681\u501a\u5df2\u4e59\u77e3\u4ee5\u827a\u6291\u6613\u9091\u5c79\u4ebf\u5f79\u81c6\u9038\u8084\u75ab\u4ea6\u88d4\u610f\u6bc5\u5fc6\u4e49\u76ca\u6ea2\u8be3\u8bae\u8c0a\u8bd1\u5f02\u7ffc\u7fcc\u7ece\u5208\u5293\u4f7e\u8bd2\u572a\u572f\u57f8\u61ff\u82e1\u858f\u5f08\u5955\u6339\u5f0b\u5453\u54a6\u54bf\u566b\u5cc4\u5db7\u7317\u9974\u603f\u6021\u6092\u6f2a\u8fe4\u9a7f\u7f22\u6baa\u8d3b\u65d6\u71a0\u9487\u9552\u9571\u75cd\u7617\u7654\u7fca\u8864\u8734\u8223\u7fbf\u7ff3\u914f\u9edf',
+  'yin': '\u8335\u836b\u56e0\u6bb7\u97f3\u9634\u59fb\u541f\u94f6\u6deb\u5bc5\u996e\u5c39\u5f15\u9690\u5370\u80e4\u911e\u5819\u831a\u5591\u72fa\u5924\u6c24\u94df\u763e\u8693\u972a\u9f88',
+  'ying': '\u82f1\u6a31\u5a74\u9e70\u5e94\u7f28\u83b9\u8424\u8425\u8367\u8747\u8fce\u8d62\u76c8\u5f71\u9896\u786c\u6620\u5b34\u90e2\u8314\u83ba\u8426\u6484\u5624\u81ba\u6ee2\u6f46\u701b\u745b\u748e\u6979\u9e66\u763f\u988d\u7f42',
+  'yo': '\u54df\u5537',
+  'yong': '\u62e5\u4f63\u81c3\u75c8\u5eb8\u96cd\u8e0a\u86f9\u548f\u6cf3\u6d8c\u6c38\u607f\u52c7\u7528\u4fd1\u58c5\u5889\u6175\u9095\u955b\u752c\u9cd9\u9954',
+  'you': '\u5e7d\u4f18\u60a0\u5fe7\u5c24\u7531\u90ae\u94c0\u72b9\u6cb9\u6e38\u9149\u6709\u53cb\u53f3\u4f51\u91c9\u8bf1\u53c8\u5e7c\u5363\u6538\u4f91\u83b8\u5466\u56ff\u5ba5\u67da\u7337\u7256\u94d5\u75a3\u8763\u9c7f\u9edd\u9f2c',
+  'yu': '\u8fc2\u6de4\u4e8e\u76c2\u6986\u865e\u611a\u8206\u4f59\u4fde\u903e\u9c7c\u6109\u6e1d\u6e14\u9685\u4e88\u5a31\u96e8\u4e0e\u5c7f\u79b9\u5b87\u8bed\u7fbd\u7389\u57df\u828b\u90c1\u5401\u9047\u55bb\u5cea\u5fa1\u6108\u6b32\u72f1\u80b2\u8a89\u6d74\u5bd3\u88d5\u9884\u8c6b\u9a6d\u79ba\u6bd3\u4f1b\u4fe3\u8c00\u8c15\u8438\u84e3\u63c4\u5581\u5704\u5709\u5d5b\u72f3\u996b\u5ebe\u9608\u59aa\u59a4\u7ea1\u745c\u6631\u89ce\u8174\u6b24\u65bc\u715c\u71e0\u807f\u94b0\u9e46\u7610\u7600\u7ab3\u8753\u7afd\u8201\u96e9\u9f89',
+  'yuan': '\u9e33\u6e0a\u51a4\u5143\u57a3\u8881\u539f\u63f4\u8f95\u56ed\u5458\u5706\u733f\u6e90\u7f18\u8fdc\u82d1\u613f\u6028\u9662\u586c\u6c85\u5a9b\u7457\u6a7c\u7230\u7722\u9e22\u8788\u9f0b',
+  'yue': '\u66f0\u7ea6\u8d8a\u8dc3\u94a5\u5cb3\u7ca4\u6708\u60a6\u9605\u9fa0\u6a3e\u5216\u94ba',
+  'yun': '\u8018\u4e91\u90e7\u5300\u9668\u5141\u8fd0\u8574\u915d\u6655\u97f5\u5b55\u90d3\u82b8\u72c1\u607d\u7ead\u6b92\u6600\u6c32',
+  'za': '\u531d\u7838\u6742\u62f6\u5482',
+  'zai': '\u683d\u54c9\u707e\u5bb0\u8f7d\u518d\u5728\u54b1\u5d3d\u753e',
+  'zan': '\u6512\u6682\u8d5e\u74d2\u661d\u7c2a\u7ccc\u8db1\u933e',
+  'zang': '\u8d43\u810f\u846c\u5958\u6215\u81e7',
+  'zao': '\u906d\u7cdf\u51ff\u85fb\u67a3\u65e9\u6fa1\u86a4\u8e81\u566a\u9020\u7682\u7076\u71e5\u5523\u7f2b',
+  'ze': '\u8d23\u62e9\u5219\u6cfd\u4ec4\u8d5c\u5567\u8fee\u6603\u7b2e\u7ba6\u8234',
+  'zei': '\u8d3c',
+  'zen': '\u600e\u8c2e',
+  'zeng': '\u589e\u618e\u66fe\u8d60\u7f2f\u7511\u7f7e\u9503',
+  'zha': '\u624e\u55b3\u6e23\u672d\u8f67\u94e1\u95f8\u7728\u6805\u69a8\u548b\u4e4d\u70b8\u8bc8\u63f8\u5412\u54a4\u54f3\u600d\u781f\u75c4\u86b1\u9f44',
+  'zhai': '\u6458\u658b\u5b85\u7a84\u503a\u5be8\u7826',
+  'zhan': '\u77bb\u6be1\u8a79\u7c98\u6cbe\u76cf\u65a9\u8f97\u5d2d\u5c55\u8638\u6808\u5360\u6218\u7ad9\u6e5b\u7efd\u8c35\u640c\u65c3',
+  'zhang': '\u6a1f\u7ae0\u5f70\u6f33\u5f20\u638c\u6da8\u6756\u4e08\u5e10\u8d26\u4ed7\u80c0\u7634\u969c\u4ec9\u9123\u5e5b\u5d82\u7350\u5adc\u748b\u87d1',
+  'zhao': '\u62db\u662d\u627e\u6cbc\u8d75\u7167\u7f69\u5146\u8087\u53ec\u722a\u8bcf\u68f9\u948a\u7b0a',
+  'zhe': '\u906e\u6298\u54f2\u86f0\u8f99\u8005\u9517\u8517\u8fd9\u6d59\u8c2a\u966c\u67d8\u8f84\u78d4\u9e67\u891a\u8707\u8d6d',
+  'zhen': '\u73cd\u659f\u771f\u7504\u7827\u81fb\u8d1e\u9488\u4fa6\u6795\u75b9\u8bca\u9707\u632f\u9547\u9635\u7f1c\u6862\u699b\u8f78\u8d48\u80d7\u6715\u796f\u755b\u9e29',
+  'zheng': '\u84b8\u6323\u7741\u5f81\u72f0\u4e89\u6014\u6574\u62ef\u6b63\u653f\u5e27\u75c7\u90d1\u8bc1\u8be4\u5ce5\u94b2\u94ee\u7b5d',
+  'zhi': '\u829d\u679d\u652f\u5431\u8718\u77e5\u80a2\u8102\u6c41\u4e4b\u7ec7\u804c\u76f4\u690d\u6b96\u6267\u503c\u4f84\u5740\u6307\u6b62\u8dbe\u53ea\u65e8\u7eb8\u5fd7\u631a\u63b7\u81f3\u81f4\u7f6e\u5e1c\u5cd9\u5236\u667a\u79e9\u7a1a\u8d28\u7099\u75d4\u6ede\u6cbb\u7a92\u536e\u965f\u90c5\u57f4\u82b7\u646d\u5e19\u5fee\u5f58\u54ab\u9a98\u6809\u67b3\u6800\u684e\u8f75\u8f7e\u6534\u8d3d\u81a3\u7949\u7957\u9ef9\u96c9\u9e37\u75e3\u86ed\u7d77\u916f\u8dd6\u8e2c\u8e2f\u8c78\u89ef',
+  'zhong': '\u4e2d\u76c5\u5fe0\u949f\u8877\u7ec8\u79cd\u80bf\u91cd\u4ef2\u4f17\u51a2\u953a\u87bd\u8202\u822f\u8e35',
+  'zhou': '\u821f\u5468\u5dde\u6d32\u8bcc\u7ca5\u8f74\u8098\u5e1a\u5492\u76b1\u5b99\u663c\u9aa4\u5544\u7740\u501c\u8bf9\u836e\u9b3b\u7ea3\u80c4\u78a1\u7c40\u8233\u914e\u9cb7',
+  'zhu': '\u73e0\u682a\u86db\u6731\u732a\u8bf8\u8bdb\u9010\u7af9\u70db\u716e\u62c4\u77a9\u5631\u4e3b\u8457\u67f1\u52a9\u86c0\u8d2e\u94f8\u7b51\u4f4f\u6ce8\u795d\u9a7b\u4f2b\u4f8f\u90be\u82ce\u8331\u6d19\u6e1a\u6f74\u9a7a\u677c\u69e0\u6a65\u70b7\u94e2\u75b0\u7603\u86b0\u7afa\u7bb8\u7fe5\u8e85\u9e88',
+  'zhua': '\u6293',
+  'zhuai': '\u62fd',
+  'zhuan': '\u4e13\u7816\u8f6c\u64b0\u8d5a\u7bc6\u629f\u556d\u989b',
+  'zhuang': '\u6869\u5e84\u88c5\u5986\u649e\u58ee\u72b6\u4e2c',
+  'zhui': '\u690e\u9525\u8ffd\u8d58\u5760\u7f00\u8411\u9a93\u7f12',
+  'zhun': '\u8c06\u51c6',
+  'zhuo': '\u6349\u62d9\u5353\u684c\u7422\u8301\u914c\u707c\u6d4a\u502c\u8bfc\u5ef4\u855e\u64e2\u555c\u6d5e\u6dbf\u6753\u712f\u799a\u65ab',
+  'zi': '\u5179\u54a8\u8d44\u59ff\u6ecb\u6dc4\u5b5c\u7d2b\u4ed4\u7c7d\u6ed3\u5b50\u81ea\u6e0d\u5b57\u8c18\u5d6b\u59ca\u5b73\u7f01\u6893\u8f8e\u8d40\u6063\u7726\u9531\u79ed\u8014\u7b2b\u7ca2\u89dc\u8a3e\u9cbb\u9aed',
+  'zong': '\u9b03\u68d5\u8e2a\u5b97\u7efc\u603b\u7eb5\u8159\u7cbd',
+  'zou': '\u90b9\u8d70\u594f\u63cd\u9139\u9cb0',
+  'zu': '\u79df\u8db3\u5352\u65cf\u7956\u8bc5\u963b\u7ec4\u4fce\u83f9\u5550\u5f82\u9a75\u8e74',
+  'zuan': '\u94bb\u7e82\u6525\u7f35',
+  'zui': '\u5634\u9189\u6700\u7f6a',
+  'zun': '\u5c0a\u9075\u6499\u6a3d\u9cdf',
+  'zuo': '\u6628\u5de6\u4f50\u67de\u505a\u4f5c\u5750\u5ea7\u961d\u963c\u80d9\u795a\u9162',
+  'cou': '\u85ae\u6971\u8f8f\u8160',
+  'nang': '\u652e\u54dd\u56d4\u9995\u66e9',
+  'o': '\u5594',
+  'dia': '\u55f2',
+  'chuai': '\u562c\u81aa\u8e39',
+  'cen': '\u5c91\u6d94',
+  'diu': '\u94e5',
+  'nou': '\u8028',
+  'fou': '\u7f36',
+  'bia': '\u9adf'
+}

+ 37 - 0
HX-SHOP/common/pinyin/pinyin2.js

@@ -0,0 +1,37 @@
+import { pinyin } from './pinyin.js'
+export default {
+  chineseToPinYin: function (l1) {
+    var l2 = l1.length
+    var I1 = ''
+    var reg = new RegExp('[a-zA-Z0-9]')
+    for (var i = 0; i < l2; i++) {
+      var val = l1.substr(i, 1)
+      var name = this.arraySearch(val, pinyin)
+      if (reg.test(val)) {
+        I1 += val
+      } else if (name !== false) {
+        I1 += name
+      }
+    }
+    I1 = I1.replace(/ /g, '-')
+    while (I1.indexOf('--') > 0) {
+      I1 = I1.replace('--', '-')
+    }
+    return I1
+  },
+  arraySearch: function (l1, l2) {
+    for (var name in pinyin) {
+      if (pinyin[name].indexOf(l1) !== -1) {
+        return this.ucfirst(name)
+      }
+    }
+    return false
+  },
+  ucfirst: function (l1) {
+    if (l1.length > 0) {
+      var first = l1.substr(0, 1).toUpperCase()
+      var spare = l1.substr(1, l1.length)
+      return first + spare
+    }
+  }
+}

+ 57 - 0
HX-SHOP/common/pinyin/pinyin3.js

@@ -0,0 +1,57 @@
+import vPinyin from './pinyin2.js';
+var Letters =  ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U','V', 'W', 'X', 'Y', 'Z', '#'];
+export default {
+	paixu: function(ary) {		
+		var e = []
+		e = ary
+		/*按字母排序分开*/
+		var list = []
+		e.forEach((value,index)=>{
+			var pinyin = vPinyin.chineseToPinYin(value.name)[0]
+			Letters.forEach((value2, index2) => {
+				if (value2 == pinyin) {
+					var contact = {
+						letter: value2,
+						value: {
+							name: value.name,
+							phone: value.phone.replace(/\s*/g,""),
+						}
+					}
+					list = list.concat(contact)
+				}
+			})
+		})		
+		/*获取所有字母字母去掉*/
+		var list2 = []
+		list.forEach((value, index) => {
+			var map = list[index].letter
+			list2 = list2.concat(map)
+		})		
+		/*去掉相同的字母*/
+		var newArr = [];
+		for (var i = 0; i < list2.length - 1; i++) {
+			if (newArr.indexOf(list2[i]) == -1) {
+				newArr.push(list2[i]);
+			}
+		}
+		/*给数组letter赋值字母*/
+		var list3 = []
+		newArr.forEach((value, index) => {
+			var map = {
+				letter: value,
+				contacts: []
+			}
+			list3 = list3.concat(map)
+		})
+		/*得到数组*/
+		list3.forEach((value, index) => {
+			list.forEach((value2, index2) => {
+				if (value.letter == value2.letter) {
+					var map = value2.value
+					value.contacts = value.contacts.concat(map)
+				}
+			})
+		})
+		return list3;
+	}
+}

+ 627 - 0
HX-SHOP/common/testdata.js

@@ -0,0 +1,627 @@
+//商家信息
+const storeData = {
+		//商家唯一标识
+		store_id: '168',
+		//商家名称
+		store_name: '小太阳商店',
+		//头像
+		avatar: '//imgs.1op.cn/i/hxshop/avatar/3.png',
+		//横幅图片
+		banner: '//imgs.1op.cn/i/hxshop/banner/banner.jpg',
+		//详情
+		info: '店内用了本市最好的鲜肉,排骨;配料未本店祖传秘方,吃一次将永不忘。',
+		//商家住址
+		address: '新疆阿克苏是他北路2号',
+		//地标或社区
+		community: '天府名城',
+		//配送时间
+		delivery_time: '11:00~20:30',
+		//联系电话
+		telephone: '18299989916',
+		//商家购物车
+		shopping_cart: [],
+		//配送费
+		shipping_dees: 0,
+		//配送起步价
+		starting_price:30
+	};
+
+//首页门店列表
+const storeList = [
+	{
+		//商户标识
+		store_id: '852',
+		//店名
+		name: '田东日式料理',
+		//门头
+		avatar: '//imgs.1op.cn/i/hxshop/goods/14.jpg',
+		//小区
+		community: '秦阳店',
+		//评分
+		mark: '4.8',
+		//月售
+		monthly_sales: 356,
+		//门店距离,按米计算
+		distance: 500,
+		//起送价
+		starting_price: 3,
+		//配送费
+		shipping_dees: 15,
+		//商品列表
+		goods:[{
+				//id
+				id: '235',
+				//商品名称
+				name: '画画酱酱面',
+				//主图
+				main_pic: '//imgs.1op.cn/i/hxshop/goods/10.jpg',
+				//标签 【招牌,爆款,推荐】等等
+				tag: '招牌',
+				//现价
+				price: 45,
+				//原价
+				old_price: 65,
+			}
+			,{id: '236', name: '白色米', main_pic: '//imgs.1op.cn/i/hxshop/goods/6.jpg', tag: '招牌', price: 45, old_price: 65,}
+			,{id: '237', name: '小羊肉', main_pic: '//imgs.1op.cn/i/hxshop/goods/2.jpg', tag: '爆款', price: 45, old_price: 65,}
+			,{id: '238', name: '烤鸡翅', main_pic: '//imgs.1op.cn/i/hxshop/goods/3.jpg', tag: '爆款', price: 45, old_price: 65,}
+			,{id: '239', name: '爆爆鱼', main_pic: '//imgs.1op.cn/i/hxshop/goods/4.jpg', tag: '推荐', price: 45, old_price: 65,}
+			,{id: '240', name: '生吃肉票', main_pic: '//imgs.1op.cn/i/hxshop/goods/5.jpg', tag: '推荐', price: 45, old_price: 65,}
+			
+		]
+		
+	}
+	,{
+		store_id: '853',
+		name: '十里飘香烧烤',
+		avatar: '//imgs.1op.cn/i/hxshop/goods/2.jpg',
+		community: '',
+		mark: '4.8',
+		monthly_sales: 356,
+		distance: 500,
+		starting_price: 3,
+		shipping_dees: 15,
+		goods:[
+			{id: '236', name: '可乐鸡翅buibui爽', main_pic: '//imgs.1op.cn/i/hxshop/goods/7.jpg', tag: '招牌', price: 45, old_price: 65,}
+			,{id: '237', name: '百富汉堡', main_pic: '//imgs.1op.cn/i/hxshop/goods/8.jpg', tag: '爆款', price: 45, old_price: 65,}
+			,{id: '238', name: '百富汉堡', main_pic: '//imgs.1op.cn/i/hxshop/goods/9.jpg', tag: '爆款', price: 45, old_price: 65,}
+			,{id: '239', name: '百富汉堡', main_pic: '//imgs.1op.cn/i/hxshop/goods/10.jpg', tag: '推荐', price: 45, old_price: 65,}
+			,{id: '240', name: '百富汉堡', main_pic: '//imgs.1op.cn/i/hxshop/goods/11.jpg', tag: '推荐', price: 45, old_price: 65,}
+		]
+		
+	}
+	,{
+		store_id: '853',
+		name: '德克士',
+		avatar: '//imgs.1op.cn/i/hxshop/goods/3.jpg',
+		community: '天府名城',
+		mark: '4.8',
+		monthly_sales: 356,
+		distance: 500,
+		starting_price: 3,
+		shipping_dees: 15,
+		goods:[
+			{id: '236', name: '可乐鸡翅buibui爽', main_pic: '//imgs.1op.cn/i/hxshop/goods/12.jpg', tag: '招牌', price: 45, old_price: 65,}
+			,{id: '237', name: '百富汉堡', main_pic: '//imgs.1op.cn/i/hxshop/goods/13.jpg', tag: '爆款', price: 45, old_price: 65,}
+			,{id: '238', name: '百富汉堡', main_pic: '//imgs.1op.cn/i/hxshop/goods/14.jpg', tag: '爆款', price: 45, old_price: 65,}
+			,{id: '239', name: '百富汉堡', main_pic: '//imgs.1op.cn/i/hxshop/goods/15.jpg', tag: '推荐', price: 45, old_price: 65,}
+			,{id: '240', name: '百富汉堡', main_pic: '//imgs.1op.cn/i/hxshop/goods/16.jpg', tag: '推荐', price: 45, old_price: 65,}
+		]
+		
+	}
+	,{
+		store_id: '854',
+		name: '五点快餐',
+		avatar: '//imgs.1op.cn/i/hxshop/goods/4.jpg',
+		community: '天北花园',
+		mark: '4.8',
+		monthly_sales: 356,
+		distance: 500,
+		starting_price: 3,
+		shipping_dees: 15,
+		goods:[
+			{id: '236', name: '可乐鸡翅buibui爽', main_pic: '//imgs.1op.cn/i/hxshop/goods/17.jpg', tag: '招牌', price: 45, old_price: 65,}
+			,{id: '237', name: '百富汉堡', main_pic: '//imgs.1op.cn/i/hxshop/goods/1.jpg', tag: '爆款', price: 45, old_price: 65,}
+			,{id: '238', name: '百富汉堡', main_pic: '//imgs.1op.cn/i/hxshop/goods/3.jpg', tag: '爆款', price: 45, old_price: 65,}
+			,{id: '239', name: '百富汉堡', main_pic: '//imgs.1op.cn/i/hxshop/goods/5.jpg', tag: '推荐', price: 45, old_price: 65,}
+			,{id: '240', name: '百富汉堡', main_pic: '//imgs.1op.cn/i/hxshop/goods/7.jpg', tag: '推荐', price: 45, old_price: 65,}
+		]
+		
+	}]
+
+//评论数据
+const commentData = [{
+		header_img: "//imgs.1op.cn/i/hxshop/avatar/3.png",
+		user_name: "测试1",
+		rate:5,
+		create_time: "2019.04.12",
+		content: "好评",
+		imgs:[
+			'//imgs.1op.cn/i/hxshop/goods/7.jpg',
+			'//imgs.1op.cn/i/hxshop/goods/1.jpg',
+			'//imgs.1op.cn/i/hxshop/goods/9.jpg',
+			'//imgs.1op.cn/i/hxshop/goods/3.jpg'
+		]
+	},
+	{
+		content: "中评",
+		create_time: "2019.04.12",
+		header_img: "//imgs.1op.cn/i/hxshop/avatar/2.png",
+		user_name: "测试2",
+		rate:4,
+		// imgs:[]
+	},
+	{
+		content: "",
+		create_time: "2019.04.12",
+		header_img: "//imgs.1op.cn/i/hxshop/avatar/2.png",
+		user_name: "测试3",
+		rate:2,
+		// imgs:[]
+	},{
+		content: "好评",
+		create_time: "2019.04.12",
+		header_img: "//imgs.1op.cn/i/hxshop/avatar/3.png",
+		user_name: "小蚂蚁",
+		rate:5,
+		imgs:[
+			'//imgs.1op.cn/i/hxshop/goods/9.jpg',
+			'//imgs.1op.cn/i/hxshop/goods/12.jpg',
+			'//imgs.1op.cn/i/hxshop/goods/16.jpg',
+			'//imgs.1op.cn/i/hxshop/goods/7.jpg'
+		]
+	},
+	{
+		content: "中评",
+		create_time: "2019.04.12",
+		header_img: "//imgs.1op.cn/i/hxshop/avatar/4.png",
+		user_name: "沙漠骆驼",
+		rate:3.5,
+		// imgs:[]
+	},
+	{
+		content: "",
+		create_time: "2019.04.12",
+		header_img: "//imgs.1op.cn/i/hxshop/avatar/5.png",
+		user_name: "莫思",
+		rate:2.3,
+		// imgs:[]
+	}];
+
+//商品数据
+const goodsData= [{   
+		id: 1,
+		type_id:1,
+		name:'白果王水果沙拉',
+		descripe:"脆糯营养,口感好,健康绿色",
+		img:'//imgs.1op.cn/i/hxshop/goods/14.jpg',
+		price:"",
+		oldprice:"",
+		//规格
+		form: {id:1,name:"尺寸"},
+		form_child:[
+			{id:81,pid:1,name:"8寸500g", price:"46", oldprice:"100", select:true},
+			{id:82,pid:1,name:"10寸600g", price:"97", oldprice:"100",select:false},
+			{id:83,pid:1,name:"12寸800g", price:"135", oldprice:"100",select:false},
+			{id:84,pid:1,name:"四川麻辣", price:"12", oldprice:"100",select:false},
+			{id:85,pid:1,name:"香辣", price:"20", oldprice:"100",select:false},
+			{id:86,pid:1,name:"卤香", price:"90", oldprice:"100",select:false},
+			{id:87,pid:1,name:"鲜甜广味", price:"80", oldprice:"100",select:false},
+			{id:88,pid:1,name:"镇店茴香味", price:"100", oldprice:"100",select:false}
+		]
+	},
+	{   
+		id: 2,
+		type_id:2,
+		name:'精品烤山药',
+		descripe:"脆糯营养,口感好,健康绿色",
+		img: '//imgs.1op.cn/i/hxshop/goods/12.jpg',
+		price:"",
+		oldprice:"",
+		//规格
+		form: {id:1,name:"尺寸"},
+		form_child:[
+			{id:81,pid:1,name:"8寸500g", price:"78", oldprice:"100", select:true},
+			{id:82,pid:1,name:"10寸600g", price:"97", oldprice:"100",select:false},
+			{id:83,pid:1,name:"12寸800g", price:"135", oldprice:"100",select:false},
+			{id:84,pid:1,name:"四川麻辣", price:"12", oldprice:"100",select:false},
+			{id:85,pid:1,name:"香辣", price:"20", oldprice:"100",select:false},
+			{id:86,pid:1,name:"卤香", price:"90", oldprice:"100",select:false},
+			{id:87,pid:1,name:"鲜甜广味", price:"80", oldprice:"100",select:false},
+			{id:88,pid:1,name:"镇店茴香味", price:"100", oldprice:"100",select:false}
+		]
+	},
+	{   
+		id: 3,
+		type_id:2,
+		name:'川味毛血旺',
+		descripe:"脆糯营养,口感好,健康绿色",
+		img: '//imgs.1op.cn/i/hxshop/goods/11.jpg',
+		price:"4",
+		oldprice:"",
+		
+	},
+	{   
+		id: 4,
+		type_id:3,
+		name:'吐鲁番烤全羊',
+		descripe:"脆糯营养,口感好,健康绿色",
+		img: '//imgs.1op.cn/i/hxshop/goods/10.jpg',
+		price:"4",
+		oldprice:""
+	},
+	{   
+		id: 5,
+		type_id:3,
+		name:'红烧肉',
+		descripe:"脆糯营养,口感好,健康绿色",
+		img: '//imgs.1op.cn/i/hxshop/goods/9.jpg',
+		price:"4",
+		oldprice:""
+	},
+	{   
+		id: 6,
+		type_id:4,
+		name:'新疆特色辣子鸡',
+		descripe:"脆糯营养,口感好,健康绿色",
+		img: '//imgs.1op.cn/i/hxshop/goods/8.jpg',
+		price:"4",
+		oldprice:""
+	},
+	{
+		id: 106,
+		type_id:4,
+		name:'新疆特色羊排',
+		descripe:"脆糯营养,口感好,健康绿色",
+		img: '//imgs.1op.cn/i/hxshop/goods/9.jpg',
+		price:"4",
+		oldprice:""
+	},
+	{   
+		id: 7,
+		type_id:5,
+		name:'绝味海鲜拼盘',
+		descripe:"脆糯营养,口感好,健康绿色",
+		img: '//imgs.1op.cn/i/hxshop/goods/7.jpg',
+		price:"4",
+		oldprice:""
+	},
+	{   
+		id: 8,
+		type_id:5,
+		name:'金色香糯大粽子',
+		descripe:"脆糯营养,口感好,健康绿色",
+		img: '//imgs.1op.cn/i/hxshop/goods/6.jpg',
+		price:"4",
+		oldprice:""
+	},
+	{   
+		id: 9,
+		type_id:5,
+		name:'马梓林香香鸡',
+		descripe:"脆糯营养,口感好,健康绿色",
+		img: '//imgs.1op.cn/i/hxshop/goods/5.jpg',
+		price:"4",
+		oldprice:""
+	},
+	{   
+		id: 10,
+		type_id:6,
+		name:'草莓味莫普氏蛋糕',
+		descripe:"脆糯营养,口感好,健康绿色",
+		img: '//imgs.1op.cn/i/hxshop/goods/4.jpg',
+		price:"4",
+		oldprice:""
+	},
+	{   
+		id: 23,
+		type_id:6,
+		name:'川味毛血旺',
+		descripe:"脆糯营养,口感好,健康绿色",
+		img: '//imgs.1op.cn/i/hxshop/goods/11.jpg',
+		price:"4",
+		oldprice:"",
+		
+	},
+	{   
+		id: 24,
+		type_id:6,
+		name:'吐鲁番烤全羊',
+		descripe:"脆糯营养,口感好,健康绿色",
+		img: '//imgs.1op.cn/i/hxshop/goods/10.jpg',
+		price:"4",
+		oldprice:""
+	},
+	{   
+		id: 25,
+		type_id:7,
+		name:'红烧肉',
+		descripe:"脆糯营养,口感好,健康绿色",
+		img: '//imgs.1op.cn/i/hxshop/goods/9.jpg',
+		price:"4",
+		oldprice:""
+	},
+	{   
+		id: 26,
+		type_id:7,
+		name:'新疆特色辣子鸡',
+		descripe:"脆糯营养,口感好,健康绿色",
+		img: '//imgs.1op.cn/i/hxshop/goods/8.jpg',
+		price:"4",
+		oldprice:""
+	},
+	{   
+		id: 27,
+		type_id:7,
+		name:'绝味海鲜拼盘',
+		descripe:"脆糯营养,口感好,健康绿色",
+		img: '//imgs.1op.cn/i/hxshop/goods/7.jpg',
+		price:"4",
+		oldprice:""
+	},
+	{id: 28,type_id:8,name:'金色香糯大粽子',descripe:"脆糯营养,口感好,健康绿色",img: '//imgs.1op.cn/i/hxshop/goods/6.jpg',price:"4",oldprice:""},
+	{id: 29,type_id:8,name:'马梓林香香鸡',descripe:"脆糯营养,口感好,健康绿色",img: '//imgs.1op.cn/i/hxshop/goods/5.jpg',price:"4",oldprice:""},
+	{id: 30,type_id:8,name:'草莓味莫普氏蛋糕',descripe:"脆糯营养,口感好,健康绿色",img: '//imgs.1op.cn/i/hxshop/goods/4.jpg',price:"4",oldprice:""},
+	{id: 31,type_id:9,name:'金色香糯大粽子',descripe:"脆糯营养,口感好,健康绿色",img: '//imgs.1op.cn/i/hxshop/goods/16.jpg',price:"4",oldprice:""},
+	{id: 32,type_id:9,name:'马梓林香香鸡',descripe:"脆糯营养,口感好,健康绿色",img: '//imgs.1op.cn/i/hxshop/goods/17.jpg',price:"4",oldprice:""},
+	{id: 33,type_id:9,name:'草莓味莫普氏蛋糕',descripe:"脆糯营养,口感好,健康绿色",img: '//imgs.1op.cn/i/hxshop/goods/15.jpg',price:"4",oldprice:""},
+	{id: 46,type_id:8,name:'金色香糯大粽子',descripe:"脆糯营养,口感好,健康绿色",img: '//imgs.1op.cn/i/hxshop/goods/6.jpg',price:"4",oldprice:""},
+	{id: 34,type_id:10,name:'马梓林香香鸡',descripe:"脆糯营养,口感好,健康绿色",img: '//imgs.1op.cn/i/hxshop/goods/14.jpg',price:"4",oldprice:""},
+	{id: 35,type_id:10,name:'草莓味莫普氏蛋糕',descripe:"脆糯营养,口感好,健康绿色",img: '//imgs.1op.cn/i/hxshop/goods/13.jpg',price:"4",oldprice:""},
+	{id: 45,type_id:8,name:'金色香糯大粽子',descripe:"脆糯营养,口感好,健康绿色",img: '//imgs.1op.cn/i/hxshop/goods/6.jpg',price:"4",oldprice:""},
+	{id: 36,type_id:10,name:'马梓林香香鸡',descripe:"脆糯营养,口感好,健康绿色",img: '//imgs.1op.cn/i/hxshop/goods/12.jpg',price:"4",oldprice:""},
+	{id: 37,type_id:10,name:'草莓味莫普氏蛋糕',descripe:"脆糯营养,口感好,健康绿色",img: '//imgs.1op.cn/i/hxshop/goods/11.jpg',price:"4",oldprice:""},
+	{id: 38,type_id:11,name:'草莓味莫普氏蛋糕',descripe:"脆糯营养,口感好,健康绿色",img: '//imgs.1op.cn/i/hxshop/goods/10.jpg',price:"4",oldprice:""},
+	{id: 44,type_id:8,name:'金色香糯大粽子',descripe:"脆糯营养,口感好,健康绿色",img: '//imgs.1op.cn/i/hxshop/goods/6.jpg',price:"4",oldprice:""},
+	{id: 39,type_id:12,name:'马梓林香香鸡',descripe:"脆糯营养,口感好,健康绿色",img: '//imgs.1op.cn/i/hxshop/goods/9.jpg',price:"4",oldprice:""},
+	{id: 40,type_id:12,name:'草莓味莫普氏蛋糕',descripe:"脆糯营养,口感好,健康绿色",img: '//imgs.1op.cn/i/hxshop/goods/8.jpg',price:"4",oldprice:""},
+	{id: 13,type_id:13,name:'金色香糯大粽子',descripe:"脆糯营养,口感好,健康绿色",img: '//imgs.1op.cn/i/hxshop/goods/6.jpg',price:"4",oldprice:""},
+	{id: 41,type_id:12,name:'马梓林香香鸡',descripe:"脆糯营养,口感好,健康绿色",img: '//imgs.1op.cn/i/hxshop/goods/7.jpg',price:"4",oldprice:""},
+	{id: 42,type_id:13,name:'草莓味莫普氏蛋糕',descripe:"脆糯营养,口感好,健康绿色",img: '//imgs.1op.cn/i/hxshop/goods/1.jpg',price:"4",oldprice:""}
+	];
+	
+//商品种类数据
+const categoryData = [
+		{id: 1,name: '烧烤'},
+		{id: 2,name: '生鲜'},
+		{id: 3,name: '绿蔬'},
+		{id: 4,name: '肉类'},
+		{id: 5,name: '川味'},
+		{id: 6,name: '粤菜'},
+		{id: 7,name: '湘菜'},
+		{id: 8,name: '西餐'},
+		{id: 9,name: '饮料'},
+		{id: 10,name: '糕点'},
+		{id: 11,name: '凉菜'},
+		{id: 12,name: '火锅'},
+		{id: 13,name: '干锅'}
+	];
+
+//商品详细
+const goodsInfo = {
+	//商品id
+	id: 18,
+	//商品类id
+	type_id:1,
+	//商品名称
+	name:'新疆特色辣子鸡排饭',
+	//商品描述-就是掌柜描述,
+	descripe:"口味可以自己选,有香辣、蒜香、葱香、孜然、老麻口味",
+	//主图
+	img:'//imgs.1op.cn/i/hxshop/goods/7.jpg',
+	//滚动图片
+	banner_img:['//imgs.1op.cn/i/hxshop/goods/14.jpg','//imgs.1op.cn/i/hxshop/goods/7.jpg','//imgs.1op.cn/i/hxshop/goods/12.jpg'],
+	//现价
+	price:"23",
+	//原价
+	oldprice:"44",
+	//月销售
+	monthly_sales: "566",
+	//商品标签
+	goods_tag:['约800克','香辣','特色菜','营养美食'],
+	//规格
+	form: {id:1,name:"尺寸"},
+	form_child:[
+		{id:81,pid:1,name:"8寸500g", price:"46", oldprice:"100", select:true},
+		{id:82,pid:1,name:"10寸600g", price:"97", oldprice:"100",select:false},
+		{id:83,pid:1,name:"12寸800g", price:"135", oldprice:"100",select:false},
+		{id:84,pid:1,name:"四川麻辣", price:"12", oldprice:"100",select:false},
+		{id:85,pid:1,name:"香辣", price:"20", oldprice:"100",select:false},
+		{id:86,pid:1,name:"卤香", price:"90", oldprice:"100",select:false},
+		{id:87,pid:1,name:"鲜甜广味", price:"80", oldprice:"100",select:false},
+		{id:88,pid:1,name:"镇店茴香味", price:"100", oldprice:"100",select:false}
+	],
+	//详情
+	detail:[
+		{
+			tit:'掌柜描述',
+			txt:'口味可以自己选,有香辣、蒜香、葱香、孜然、老麻口味',
+		},{
+			tit:'主料',
+			txt:'鸡胸排,大葱',
+		},{
+			tit:'菜系',
+			txt:'新疆特色菜',
+		},{
+			tit:'口味',
+			txt:'香辣',
+		}
+		//......更多
+	],
+	//图文
+	desc: `
+		<view style="width:100%">
+			<image style="width:100%;display:block;" src="//imgs.1op.cn/i/hxshop/goods/14.jpg" />
+			<image style="width:100%;display:block;" src="//imgs.1op.cn/i/hxshop/goods/7.jpg" />
+			<image style="width:100%;display:block;" src="//imgs.1op.cn/i/hxshop/goods/6.jpg" />
+			<image style="width:100%;display:block;" src="//imgs.1op.cn/i/hxshop/goods/3.jpg" />
+			<image style="width:100%;display:block;" src="//imgs.1op.cn/i/hxshop/goods/1.jpg" />
+		</view>
+	`,
+};
+
+//商品评价
+const goodsEva = {
+	//总评价数
+	sum: '386',
+	//好评
+	praise: '306',
+	//差评
+	bad_review: '80',
+	//评价标签
+	eva_tag: {
+		//有图
+		'exist_pic': '62',
+		//赞
+		'appreciate': '96',
+		//踩
+		'oppose': '16',
+		//其他标签
+		'other': ['92%人口味满意','300人希望再次购买']
+	},
+	eva_list: [
+		{
+			//用户名
+			name: '白色的太阳',
+			//头像
+			avatar: '//imgs.1op.cn/i/hxshop/avatar/4.png',
+			//评论时间
+			time: '2020.03.12',
+			//点赞或踩商品,没有投票【0】、赞【1】、踩【2】
+			point: 1,
+			//评价内容
+			content: "味道好极了,家里人超爱吃,希望下次能多放点辣椒,我们家吃辣",
+			//上传的图片
+			pic: ['//imgs.1op.cn/i/hxshop/goods/12.jpg','//imgs.1op.cn/i/hxshop/goods/13.jpg','//imgs.1op.cn/i/hxshop/goods/15.jpg']
+		},
+		{
+			//用户名
+			name: '匿名用户',
+			//头像
+			avatar: '//imgs.1op.cn/i/hxshop/avatar/2.png',
+			//评论时间
+			time: '2020.03.16',
+			//点赞或踩商品,没有投票【0】、赞【1】、踩【2】
+			point: 2,
+			//评价内容
+			content: "",
+			//上传的图片
+			pic: []
+		},
+		{
+			//用户名
+			name: '匿名用户',
+			//头像
+			avatar: '//imgs.1op.cn/i/hxshop/avatar/6.png',
+			//评论时间
+			time: '2020.03.16',
+			//点赞或踩商品,没有投票【0】、赞【1】、踩【2】
+			point: 0,
+			//评价内容
+			content: "一般般",
+			//上传的图片
+			pic: []
+		},
+	]
+}
+
+// 订单
+const ordersData = [
+	{
+		id: 'MS2020041101',
+		store_id: 168,
+		tag:'../../static/img/index/yd.png',
+		store_name: '肯德基',
+		community: '阿克苏友好店',
+		avatar: 'https://imgs.1op.cn/i/hxshop/avatar/2.png',
+		create_time: '2020-4-11 19:51',
+		total: 122.45,
+		//订单状态 [1已取消,2待支付,3待收货,4待评价,5完成,6退款中,7退款完成]
+		status: 3,
+	},
+	{
+		id: 'MS2020041102',
+		store_id: 186,
+		tag:'../../static/img/index/sc.png',
+		store_name: '美食大龙虾*烧烤虾尾',
+		goods_name: '小龙虾+鸡翅+可乐+田螺',
+		community: '',
+		avatar: 'https://imgs.1op.cn/i/hxshop/avatar/5.png',
+		create_time: '2020-4-11 19:51',
+		total: 122.45,
+		//订单状态 [1已取消,2待支付,3待收货,4待评价,5完成,6退款中,7退款完成]
+		status: 2,
+	},
+	{
+		id: 'MS2020041103',
+		store_id: 183,
+		tag:'../../static/img/index/sg.png',
+		store_name: '辣椒小海鲜',
+		community: '',
+		avatar: 'https://imgs.1op.cn/i/hxshop/avatar/9.png',
+		create_time: '2020-4-11 19:51',
+		total: 122.45,
+		//订单状态 [1已取消,2待支付,3待收货,4待评价,5完成,6退款中,7退款完成]
+		status: 1,
+	},
+	{
+		id: 'MS2020041104',
+		store_id: 182,
+		tag:'../../static/img/index/cs.png',
+		store_name: '特色冒菜-四川爆啦',
+		community: '特卖店',
+		avatar: 'https://imgs.1op.cn/i/hxshop/avatar/9.png',
+		create_time: '2020-4-11 19:51',
+		total: 122.45,
+		//订单状态 [1已取消,2待支付,3待收货,4待评价,5完成,6退款中,7退款完成]
+		status: 4,
+	},
+	{
+		id: 'MS2020041105',
+		store_id: 181,
+		tag:'../../static/img/index/yd.png',
+		store_name: '绝味黑鸭脖',
+		community: '',
+		avatar: 'https://imgs.1op.cn/i/hxshop/avatar/9.png',
+		create_time: '2020-4-11 19:51',
+		total: 122.45,
+		//订单状态 [1已取消,2待支付,3待收货,4待评价,5完成,6退款中,7退款完成]
+		status: 5,
+	},
+	{
+		id: 'MS2020041106',
+		store_id: 180,
+		tag:'../../static/img/index/yd.png',
+		store_name: '天天来食府',
+		community: '',
+		avatar: 'https://imgs.1op.cn/i/hxshop/avatar/9.png',
+		create_time: '2020-4-11 19:51',
+		total: 122.45,
+		//订单状态 [1已取消,2待支付,3待收货,4待评价,5完成,6退款中,7退款完成]
+		status: 6,
+	},
+	{
+		id: 'MS2020041107',
+		store_id: 170,
+		tag:'../../static/img/index/yd.png',
+		store_name: '肯德基',
+		community: '兴隆店',
+		avatar: 'https://imgs.1op.cn/i/hxshop/avatar/10.png',
+		create_time: '2020-4-11 19:51',
+		total: 122.45,
+		//订单状态 [1已取消,2待支付,3待收货,4待评价,5完成,6退款中,7退款完成]
+		status: 7,
+	}
+]
+	
+export default {
+	storeData,
+	storeList,
+	commentData,
+	goodsData,
+	categoryData,
+	goodsInfo,
+	goodsEva,
+	ordersData
+}
+	

+ 20 - 0
HX-SHOP/common/vmeitime-http/app.js

@@ -0,0 +1,20 @@
+import http from './interface'
+
+/**
+ * 检查是否有新版本
+ * {version:1}
+ */
+export const upgrade = (data) => {
+    return http.request({
+        url: '/home/v1/app/upgrade',
+		method:'GET',
+        data,
+    })
+}
+
+
+
+export default {
+	upgrade,
+}
+

+ 15 - 0
HX-SHOP/common/vmeitime-http/carpool.js

@@ -0,0 +1,15 @@
+import http from './interface'
+
+
+//用户名登录
+export const carpool = (data) => {
+    return http.request({
+        url: '/home/v1/carpool',
+		method:'POST',
+        data,
+    })
+}
+
+export default {
+	carpool
+}

+ 20 - 0
HX-SHOP/common/vmeitime-http/code.js

@@ -0,0 +1,20 @@
+//所有获取手机验证码的接口
+
+import http from './interface'
+
+
+/**
+ * 获取更新手机号的验证码
+ * phone	手机号
+ */
+export const updatePhone = (data) => {
+    return http.request({
+        url: '/home/v1/code/update_phone',
+		method:'get',
+        data,
+    })
+}
+
+export default {
+	updatePhone
+}

+ 188 - 0
HX-SHOP/common/vmeitime-http/index.js

@@ -0,0 +1,188 @@
+import store from '@/store/index';
+
+import config from '@/config.js'
+
+import http from './interface'
+
+import carpool from './carpool.js'
+
+import user from './user.js'
+
+import code from './code.js'
+
+import app from './app.js'
+/**
+ * 将业务所有接口统一起来便于维护
+ * 如果项目很大可以将 url 独立成文件,接口分成不同的模块
+ * 
+ */
+
+//实例
+/* export const goods = (data) => {
+	//设置请求前拦截器
+	http.interceptor.request = (config) => {
+		config.header = {
+			token: '12345647sdfads'
+		}
+	}
+	//设置请求结束后拦截器
+	http.interceptor.response = (response) => {
+		//判断返回状态 执行相应操作
+		console.log(response)
+		return response;
+	}
+    return http.request({
+		//baseUrl: 'https://unidemo.dcloud.net.cn/',
+        url: '/home/v1/goods',
+		method:'POST',
+		dataType: 'json',
+        data,
+    })
+} */
+
+//------------------------------------------------------------------------------------------
+//---------------------------------------   拦截器  ----------------------------------
+//------------------------------------------------------------------------------------------
+//服务器地址
+http.config.baseUrl = config.server
+
+//设置请求前拦截器
+http.interceptor.request = (config) => {
+    //添加通用参数
+    config.header = {
+        "token": uni.getStorageSync('userData').token
+    }
+	
+}
+
+//设置请求结束后拦截器
+http.interceptor.response = (res) => {
+	
+	console.log("拦截",res);
+	let code = res.statusCode;
+	let err = null;
+	
+	//未连接到网络
+	if(!code){
+		uni.showModal({
+			title: '提示',
+			content: 'APP服务端未响应!',
+			confirmColor: '#3CC51F',
+			showCancel: false,
+			success: function (msg) {
+				if (msg.confirm) {
+					
+				}
+			}
+		});
+		return res;
+	}
+	if(code != 200){
+		//判断网络请求状态 执行相应操作
+		switch(true){
+			case code>=200 && code<300:
+				break;
+			case code>=300 && code<400:
+				break;
+			case code>=400 && code<500:
+				err = "客户端请求错误!"
+				break;
+			case code==504:
+				err = "网络请求超时!"
+				break;
+			case code>=500 && code<600:
+				err = "服务器响应错误!"
+				break;
+		}
+		if(err){
+			uni.showModal({
+				title: '提示',
+				content: err,
+				confirmColor: '#3CC51F',
+				showCancel: false,
+				success: function (msg) {
+					if (msg.confirm) {
+						
+					}
+				}
+			});
+			return res;
+		}
+	}
+	
+	
+	//服务器返回错误的格式
+	if(typeof resData.code == "undefined"){
+		uni.showModal({
+			title: '提示',
+			content: '服务器返回错误',
+			confirmColor: '#3CC51F',
+			showCancel: false,
+			success: function (msg) {
+				if (msg.confirm) {
+					
+				}
+			}
+		});
+		return res;
+	}
+	
+	
+    //判断返回状态 执行相应操作
+	switch(res.data.code){
+		//未登录
+		case -1:
+			let txt = "您还未登录"
+			//如果本地登录状态时true则提示登录信息过期
+			//如果本地登录状态是false则提示登录
+			if(store.state.hasLogin){
+				txt = "登录过期,请重新登录"
+				//取消登录状态
+				store.dispatch("logout");
+			}
+			console.log();
+			uni.showModal({
+				title: '',
+				content: txt,
+				confirmText: "去登录",
+				confirmColor: '#3CC51F',
+				success: function (msg) {
+					if (msg.confirm) {
+						uni.navigateTo({
+							url: '/pages/user/login/login'
+						});
+					} else if (msg.cancel) {
+						
+					}
+				}
+			});
+			break;
+		//异常
+		case 9999:
+			uni.showModal({
+				title: '提示',
+				content: '远程端返回一个错误',
+				confirmColor: '#3CC51F',
+				showCancel: false,
+				success: function (msg) {
+					if (msg.confirm) {
+						
+					}
+				}
+			});
+			break;
+		default:
+			break;
+	}
+	
+    return res;
+}
+
+// 默认全部导出  import api from '@/common/vmeitime-http/'
+export default {
+	user,
+	code,
+	carpool,
+	app
+	
+}

+ 191 - 0
HX-SHOP/common/vmeitime-http/interface.js

@@ -0,0 +1,191 @@
+/**
+ * 通用uni-app网络请求
+ * 基于 Promise 对象实现更简单的 request 使用方式,支持请求和响应拦截
+ */
+
+/*
+// 开放的接口
+import http from './interface'
+
+http.config.baseUrl = "http://localhost:8080/api/"
+
+http.request(url:'user/list',method:'GET').then((res)=>{
+	console.log(JSON.stringify(res))
+})
+http.get('user/list').then((res)=>{
+	console.log(JSON.stringify(res))
+})
+http.get('user/list', {status: 1}).then((res)=>{
+	console.log(JSON.stringify(res))
+})
+http.post('user', {id:1, status: 1}).then((res)=>{
+	console.log(JSON.stringify(res))
+})
+http.put('user/1', {status: 2}).then((res)=>{
+	console.log(JSON.stringify(res))
+})
+http.delete('user/1').then((res)=>{
+	console.log(JSON.stringify(res))
+}) 
+
+*/
+export default {
+	config: {
+		baseUrl: "http://192.168.0.15:666",
+		header: {
+			'Content-Type':'application/json;charset=UTF-8',
+			'Content-Type':'application/x-www-form-urlencoded'
+		},  
+		data: {},
+		method: "GET",
+		dataType: "json",  /* 如设为json,会对返回的数据做一次 JSON.parse */
+		responseType: "text",
+		success() {},
+		fail() {},
+		complete() {}
+	},
+	interceptor: {
+		request: null,
+		response: null
+	},
+	request(options) {
+		if (!options) {
+			options = {}
+		}
+		options.baseUrl = options.baseUrl || this.config.baseUrl
+		options.dataType = options.dataType || this.config.dataType
+		options.url = options.baseUrl + options.url
+		options.data = options.data || {}
+		options.method = options.method || this.config.method
+		//TODO 加密数据
+		
+		//TODO 数据签名
+		/* 
+		_token = {'token': getStorage(STOREKEY_LOGIN).token || 'undefined'},
+		_sign = {'sign': sign(JSON.stringify(options.data))}
+		options.header = Object.assign({}, options.header, _token,_sign) 
+		*/
+	   
+		return new Promise((resolve, reject) => {
+			let _config = null
+			
+			options.complete = (response) => {
+				let statusCode = response.statusCode
+				response.config = _config
+				if (process.env.NODE_ENV === 'development') {
+					if (statusCode === 200) {
+						//console.log("【" + _config.requestId + "】 结果:" + JSON.stringify(response.data))
+					}
+				}
+				if (this.interceptor.response) {
+					let newResponse = this.interceptor.response(response)
+					if (newResponse) {
+						response = newResponse
+					}
+				}
+				// 统一的响应日志记录
+				_reslog(response)
+				if (statusCode === 200) { //成功
+					resolve(response);
+				} else {
+					reject(response)
+				}
+			}
+
+			_config = Object.assign({}, this.config, options)
+			_config.requestId = new Date().getTime()
+
+			if (this.interceptor.request) {
+				this.interceptor.request(_config)
+			}
+			
+			// 统一的请求日志记录
+			_reqlog(_config)
+
+			if (process.env.NODE_ENV === 'development') {
+				//console.log("【" + _config.requestId + "】 地址:" + _config.url)
+				if (_config.data) {
+					//console.log("【" + _config.requestId + "】 参数:" + JSON.stringify(_config.data))
+				}
+			}
+
+			uni.request(_config);
+		});
+	},
+	get(url, data, options) {
+		if (!options) {
+			options = {}
+		}
+		options.url = url
+		options.data = data
+		options.method = 'GET'  
+		return this.request(options)
+	},
+	post(url, data, options) {
+		if (!options) {
+			options = {}
+		}
+		options.url = url
+		options.data = data
+		options.method = 'POST'
+		return this.request(options)
+	},
+	put(url, data, options) {
+		if (!options) {
+			options = {}
+		}
+		options.url = url
+		options.data = data
+		options.method = 'PUT'
+		return this.request(options)
+	},
+	delete(url, data, options) {
+		if (!options) {
+			options = {}
+		}
+		options.url = url
+		options.data = data
+		options.method = 'DELETE'
+		return this.request(options)
+	}
+}
+
+
+/**
+ * 请求接口日志记录
+ */
+function _reqlog(req) {
+	if (process.env.NODE_ENV === 'development') {
+		//console.log("【" + req.requestId + "】 地址:" + req.url)
+		if (req.data) {
+			//console.log("【" + req.requestId + "】 请求参数:" + JSON.stringify(req.data))
+		}
+	}
+	//TODO 调接口异步写入日志数据库
+}
+
+/**
+ * 响应接口日志记录
+ */
+function _reslog(res) {
+	let _statusCode = res.statusCode;
+	if (process.env.NODE_ENV === 'development') {
+		//console.log("【" + res.config.requestId + "】 地址:" + res.config.url)
+		if (res.config.data) {
+			//console.log("【" + res.config.requestId + "】 请求参数:" + JSON.stringify(res.config.data))
+		}
+		//console.log("【" + res.config.requestId + "】 响应结果:" + JSON.stringify(res))
+	}
+	//TODO 除了接口服务错误外,其他日志调接口异步写入日志数据库
+	switch(_statusCode){
+		case 200:
+			break;
+		case 401:
+			break;
+		case 404:
+			break;
+		default:
+			break;
+	}
+}
+

+ 198 - 0
HX-SHOP/common/vmeitime-http/readme.md

@@ -0,0 +1,198 @@
+**插件使用说明**
+
+- 基于 Promise 对象实现更简单的 request 使用方式,支持请求和响应拦截
+- 下载后把 vmeitime-http 文件夹 copy 到项目 common/ 目录下
+
+## 1. 配置 
+
+### 1.1 全局配置修改(修改vmeitime-http/interface.js中config和interceptor)
+``` javascript 
+	config: {
+		baseUrl: "https://api.com/api/",
+		header: {
+			'Content-Type':'application/json;charset=UTF-8',
+			'Content-Type':'application/x-www-form-urlencoded'
+		},    
+		dataType: "json",  
+		responseType: "text"
+	},
+	interceptor: {
+		request: null,
+		response: null
+	}
+```
+	
+### 1.2 具体接口调用时修改(在vmeitime-http/index.js文件中具体业务接口中配置)
+``` javascript
+//设置baseUrl
+http.config.baseUrl = "http://localhost:8080/api/"
+//设置请求前拦截器
+http.interceptor.request = (config) => {
+    //添加通用参数
+    config.header = {
+        "token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+    }
+}
+//设置请求结束后拦截器
+http.interceptor.response = (response) => {
+    //判断返回状态 执行相应操作
+    return response;
+}
+```	
+
+
+## 2. 使用
+
+### 2.1 全局使用(在main.js注册)
+
+``` //  main.js
+  import api from '@/common/vmeitime-http/'
+	
+	// 全局挂载后使用
+	Vue.prototype.$api = api
+```
+
+``` // pages/index/index.vue
+
+<template>
+	<view class="content">
+		
+		<view class="uni-padding-wrap uni-common-mt">
+			<view class="uni-textarea uni-common-mt">
+				<textarea :value="res"></textarea>
+			</view>
+			<view class="uni-btn-v uni-common-mt">
+				<button type="primary" @click="sendRequest" :loading="loading">发起请求</button>
+				<button type="default" @click="sendRequest1" :loading="loading">发起请求(async/await)</button>
+			</view>
+		</view>
+		
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				loading: false,
+				res: ''
+			}
+		},
+		onLoad(option) {
+			//this.sendRequest();
+			//this.sendRequest1();
+		},
+		methods: {
+			// 方式一
+			sendRequest: function() {
+				this.loading = true
+				this.$api.test({noncestr: Date.now()}).then((res)=>{
+					this.loading = false;
+					console.log('request success', res)
+					uni.showToast({
+						title: '请求成功',
+						icon: 'success',
+						mask: true
+					});
+					this.res = '请求结果 : ' + JSON.stringify(res);
+				}).catch((err)=>{
+					this.loading = false;
+					console.log('request fail', err);
+				})
+			},
+			
+			//方式二  https://segmentfault.com/a/1190000013292562?utm_source=channel-newest
+			async sendRequest1() {
+				this.loading = true
+				let res = await this.$api.test({noncestr: Date.now()});
+				this.loading = false;
+				this.res = '请求结果 : ' + JSON.stringify(res);
+			}
+		}
+	}
+</script>
+```
+
+
+### 2.2 局部使用(局部使用,不需要在 main.js 中注册) 
+
+``` // pages/index/index.vue
+
+<template>
+	<view class="content">
+		
+		<view class="uni-padding-wrap uni-common-mt">
+			<view class="uni-textarea uni-common-mt">
+				<textarea :value="res"></textarea>
+			</view>
+			<view class="uni-btn-v uni-common-mt">
+				<button type="primary" @click="sendRequest" :loading="loading">发起请求</button>
+				<button type="default" @click="sendRequest1" :loading="loading">发起请求(async/await)</button>
+			</view>
+		</view>
+		
+	</view>
+</template>
+
+<script>
+    import api from '@/common/vmeitime-http/'
+
+    export default {
+        data() {
+            return {
+				loading: false,
+				res: ''
+			}
+        },
+        onLoad(option) {
+        	//this.sendRequest();
+        	//this.sendRequest1();
+        },
+        methods: {
+        	// 方式一
+        	sendRequest: function() {
+        		this.loading = true
+        		api.test({noncestr: Date.now()}).then((res)=>{
+        			this.loading = false;
+        			console.log('request success', res)
+        			uni.showToast({
+        				title: '请求成功',
+        				icon: 'success',
+        				mask: true
+        			});
+        			this.res = '请求结果 : ' + JSON.stringify(res);
+        		}).catch((err)=>{
+        			this.loading = false;
+        			console.log('request fail', err);
+        		})
+        	},
+        	
+        	//方式二
+        	async sendRequest1() {
+        		this.loading = true
+        		let res = await this.api.test({noncestr: Date.now()});
+        		this.loading = false;
+        		this.res = '请求结果 : ' + JSON.stringify(res);
+        	}
+        }
+    }
+</script>
+
+```
+
+
+## 3. 接口数据加密、接口签名核验
+
+在vmeitime-http/interface.js文件中的request(Object)方法中补充修改相应的代码
+
+## 4. 接口请求/响应日志记录
+
+在vmeitime-http/interface.js文件中的request(Object)方法中补充修改相应的代码
+
+## 5. 业务相关接口编写
+
+在vmeitime-http/index.js文件中的编写具体业务相关的接口,参考test()方法
+
+
+
+	

+ 91 - 0
HX-SHOP/common/vmeitime-http/user.js

@@ -0,0 +1,91 @@
+import http from './interface'
+
+//手机号登录
+export const login = (data) => {
+    return http.request({
+        url: '/home/v1/login',
+		method:'POST',
+        data,
+    })
+}
+
+//退出登录
+export const logout = () => {
+    return http.request({
+        url: '/home/v1/logout',
+		method:'GET',
+    })
+}
+
+//使用手机号注册账户
+export const phoneReg = (data) => {
+    return http.request({
+        url: '/home/v1/reg/phone',
+		method:'POST',
+        data,
+    })
+}
+
+
+/**
+ * 修改密码
+ * oldPwd	原密码
+ * newPwd	新密码
+ */
+export const updatePassword = (data) => {
+    return http.request({
+        url: '/home/v1/password/update',
+		method:'POST',
+        data,
+    })
+}
+
+/**
+ * 密码验证
+ * oldPwd	原密码
+ * newPwd	新密码
+ */
+export const passwordValidation = (data) => {
+    return http.request({
+        url: '/home/v1/password/validation',
+		method:'POST',
+        data,
+    })
+}
+
+/**
+ * 检查是否登录
+ * oldPwd	原密码
+ * newPwd	新密码
+ */
+export const hasLogin = () => {
+    return http.request({
+        url: '/home/v1/user/islogin',
+		method:'GET'
+    })
+}
+
+
+/**
+ * 更新手机号
+ * phone	手机号
+ * code		手机验证码
+ */
+export const updatePhone = (data) =>{
+	return http.request({
+	    url: '/home/v1/user/phone/update',
+		method:'POST',
+	    data,
+	})
+}
+
+export default {
+	login,
+	logout,
+	phoneReg,
+	updatePassword,
+	passwordValidation,
+	updatePhone,
+	hasLogin
+}
+

+ 90 - 0
HX-SHOP/components/flyInCart.vue

@@ -0,0 +1,90 @@
+ <!-- uni兼职开发加qq1844014810  -->
+<template>
+	<view class="relative">
+		<view  class="ball" v-for="(d,i) in balls" :key="i" :style=" d.inited ? 'transition: transform .4s cubic-bezier(.6,-0.63,.94,.71); transform: translate3d(0, ' + offsetY + 'px,0); top: ' + ballY + 'px;' : '' ">
+			<view class="inner arbg" :style="d.inited ? 'transition: transform .4s linear; transform: translate3d( ' + offsetX + 'px,0,0); left: ' + ballX + 'px; opacity: 1;' : '' "></view>
+		</view>
+	</view>
+</template>
+ 
+<script>
+	export default {
+		props:{
+			cartBasketRect:Object,// 购物车篮的rect信息
+		},
+		 data() { 
+		  	return {
+				offsetX: 0,
+				offsetY: 0,
+				ballX: 0,
+				ballY: 0,
+				balls: {},
+				//避免抖动
+				lastEvent:'',
+				lastId:''
+			}
+		  },
+		  created() {
+			  	let balls = [];
+			  	for (let i = 0; i < 5; i++) {
+			  		balls.push({ inited: false });
+			  	}
+				this.balls = balls
+		  },
+		  methods:{
+			  getBalls() {
+			  	return balls;
+			  },
+			  addToCart (e,id) {
+				if(!id){
+				  this.lastId  = ''
+				  return
+				}
+
+				const self = this
+				if(this.lastId == id){
+				  e = this.lastEvent
+				}else{
+				  this.lastId  = id
+				  this.lastEvent = e
+				}
+				//((res.width + that.ballWidth ) / 2  - that.ballWidth);
+				let ballX = e.left
+				let	ballY = e.top
+				this.offsetX = -Math.abs(this.cartBasketRect.left - ballX + 10)
+				this.offsetY = Math.abs(this.cartBasketRect.top - ballY +(this.cartBasketRect.height/1.5))
+				this.ballX = ballX
+				this.ballY = ballY
+					
+				
+				for (let i = 0; i < 5; i++) {
+					if (!this.balls[i].inited) {
+						this.balls[i].inited = true
+							setTimeout(() => {
+								self.balls[i].inited= false
+							}, 500);
+						break;
+					}
+				}
+			  }
+		  }
+		  
+		  
+	}
+</script>
+
+ 
+<style scoped>
+.ball {
+	position: fixed;
+	z-index:99999;
+}
+.ball .inner {
+	background: #ff5722;
+	width: 15px;
+	height: 15px;
+	position: fixed;
+	border-radius: 50%;
+	opacity: 0;
+}
+</style> 

+ 287 - 0
HX-SHOP/components/hx-comment/hx-comment.vue

@@ -0,0 +1,287 @@
+<template>
+	<view class="hx-comment">
+		<view class="hx-comment_basic-info">
+			<view class="hx-comment_basic-info_left">
+				<view class="hx-comment_basic-info_left_top">
+					<text>3.5</text>
+				</view>
+				<view class="hx-comment_basic-info_left_bottom">
+					<text>商家评分</text>
+				</view>
+			</view>
+			<view class="hx-comment_basic-info_center">
+				<view class="hx-comment_basic-info_center_item" style="margin-bottom: 10px;">
+					<view class="hx-comment_basic-info_center_item_left">
+						<text>包装</text>
+					</view>
+					<view class="hx-comment_basic-info_center_item_center">
+						<uni-rate size="14" value="3.6"></uni-rate>
+					</view>
+					<view class="hx-comment_basic-info_center_item_right">
+						<text>3.6</text>
+					</view>
+				</view>
+				<view class="hx-comment_basic-info_center_item">
+					<view class="hx-comment_basic-info_center_item_left">
+						<text>新鲜</text>
+					</view>
+					<view class="hx-comment_basic-info_center_item_center">
+						<uni-rate size="14" value="4.5"></uni-rate>
+					</view>
+					<view class="hx-comment_basic-info_center_item_right">
+						<text>4.5</text>
+					</view>
+				</view>
+			</view>
+			<view class="hx-comment_basic-info_right">
+				
+				<view class="hx-comment_basic-info_right_top">
+					<view class="hx-comment_basic-info_right_top">
+						<text>95%</text>
+					</view>
+					<view class="hx-comment_basic-info_right_bottom">
+						<text>配送满意度</text>
+					</view>
+				</view>
+			</view>
+		</view>
+		<view class="hx-comment_dividing-line15"></view>
+		<view class="hx-comment_main-box">
+			
+			<view class="lists" v-if="listData.length > 0">
+				<block v-for="(item, index_) in listData" :key="index_">
+					<view class="item">
+						<view class="icon"><image :src="item.header_img" mode="widthFix" style="width:100%" /></view>
+						<view class="info">
+							<view class="name-time">
+								<text class="name">{{ item.user_name }}</text>
+								<text class="time">{{ item.create_time }}</text>
+							</view>
+							<view class="stars">
+								<text>评分</text> <uni-rate size="14" value="4.5"></uni-rate>
+							</view>
+							<view class="evaluate-content">
+								<text>{{ item.content || '用户暂未评价' }}</text>
+								<view class="imgs" v-if="item.imgs">
+									<block v-for="(imgurl, index) in item.imgs" :key="index">
+										<view class="imgs-box"><image :src="imgurl" mode="widthFix" style="width: 100%;" @click="previewImgs(imgurl,item.imgs)"></image></view>
+									</block>
+								</view>
+							</view>
+						</view>
+					</view>
+					<view class="hx-bb"></view>
+				</block>
+			</view>
+			<view class="no-lists" v-else>暂无评论</view>
+			
+		</view>
+	</view>
+</template>
+
+<script>
+	import uniRate from '@/components/uni-rate/uni-rate.vue'
+	
+	export default {
+		name: "hx-comment",
+		components: {uniRate},
+		props: {
+			//评价列表数据
+			listData: {
+				type: Array,
+				default: function(){
+					return [];
+				},
+			},
+		},
+		data() {
+			return {
+				
+			};
+		},
+		
+		created() {
+		},
+		methods: {
+			previewImgs(img,imgList){
+				// 预览图片
+				uni.previewImage({
+					current: img,
+					urls: imgList,
+					indicator: "default",
+					// longPressActions: {
+					// 	itemList: ['发送给朋友', '保存图片', '收藏'],
+					// 	success: function(data) {
+					// 		//console.log('选中了第' + (data.tapIndex + 1) + '个按钮,第' + (data.index + 1) + '张图片');
+					// 	},
+					// 	fail: function(err) {
+					// 		//console.log(err.errMsg);
+					// 	}
+					// }
+				});
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	
+	$hx-color-main: #ff9800;
+	$hx-color-gray: #999999;
+	
+	.hx-comment{
+		
+		position: relative;
+		.hx-bb{
+			margin-left: 11px;
+			border-bottom: 1px solid #efefef;
+			
+		}
+		&_dividing-line15{
+			height: 15px;
+			background: #efefef;
+			width: 100%;
+		}
+		&_dividing-line{
+			height: 2px;
+			background: #efefef;
+			width: 100%;
+		}
+		&_basic-info{
+			height: 82px;
+			display: flex;
+			flex-direction: row;
+			align-items: center;
+			text-align: center;
+		
+			&_left{
+				display: flex;
+				flex-direction: column;
+				width: 100px;
+				&_top{
+					font-size: 32px;
+					margin-bottom: 2px;
+					color: $hx-color-main;
+				}
+				&_bottom{
+					font-size: 12px;
+					 color: #555555;
+				}
+			}
+			&_center{
+				flex: 1;
+				display: flex;
+				align-items: center;
+				flex-direction: column;
+				
+				&_item{
+					font-size: 12px;
+					display: flex;
+					flex-direction: row;
+					align-items: center;
+					justify-content : center;
+					&_left{
+						color: #555555;
+					}
+					&_center{
+						margin: 0 6px 0 8px;
+						height: 0;
+					}
+					&_right{
+						color: #FF9800;
+					}
+				}
+			}
+			&_right{
+				width: 100px;
+				display: flex;
+				flex-direction: column;
+				border-left: 1px solid #efefef;
+				&_top{
+					font-size: 26px;
+					margin-bottom: 2px;
+					 color: $hx-color-gray;
+				}
+				&_bottom{
+					font-size: 12px;
+					 color: $hx-color-gray;
+				}
+			}
+		}
+		&_main-box{
+			
+			.lists .item {
+				padding: 20upx;
+				display: flex;
+				font-size: 22upx;
+				color: #999;
+				.icon {
+					width: 60upx;
+					height: 60upx;
+					border-radius: 50%;
+					overflow: hidden;
+					margin-right: 26upx;
+					border: 1px solid #efefef;
+				}
+			}
+			.lists .item .info {
+				flex: 1;
+				font-size: 16px;
+				color: #000;
+				.name-time {
+					display: flex;
+					align-items: center;
+					justify-content: space-between;
+					.name{
+						font-size: 16px;
+						color: #000;
+					}
+					.time{
+						font-size: 12px;
+						color: #999;
+					}
+				}
+				.stars {
+					padding: 6px 0 10px;
+					display: flex;
+					flex-direction: row;
+					align-items: center;
+					position: relative;
+					text{
+						font-size: 12px;
+						color: #999;
+						margin-right: 6px;
+					} 
+					.uni-rate{
+						height: 0;
+					}
+				}
+				.evaluate-content {
+					color: #555555;
+					font-size: 14px;
+					text-align: left;
+					padding-top: 4px;
+					.imgs {
+						display: flex;
+						flex-wrap: wrap;
+						padding-top: 4px;
+						.imgs-box {
+							width: 25%;
+							padding-right: 5px;
+							box-sizing: border-box;
+							image{
+								border-radius: 4px;
+							}
+						}
+					}
+				}
+			}
+			.no-lists {
+				padding: 20upx 0;
+				text-align: center;
+				font-size: 24upx;
+				color: #666;
+			}
+		}
+	}
+</style>

+ 125 - 0
HX-SHOP/components/hx-jump-ball/README.md

@@ -0,0 +1,125 @@
+# hx-jump-ball 用于加入购物车的跳跃效果
+
+特效组件
+
+本组件目前兼容H5、5+APP。
+
+ ![image](https://raw.githubusercontent.com/Asuancaiyu/uniapp/master/components/hx-jump-ball/demo.gif)
+### 使用案例:
+[使用案例:HX商城。模版地址:https://ext.dcloud.net.cn/plugin?id=1352](https://ext.dcloud.net.cn/plugin?id=1352)
+
+### 本组件支持模式:
+1. 主要应用在购物车添加商品时的动态效果  
+
+
+### 使用前提
+
+注意HBuilder X 2.4.7版本以下 H5 是没有效果的,app有;所以赶紧升级编辑器!!!
+
+### 使用方式	
+页面使用需在 ``` script ``` 中引用组件
+``` javascript
+import hxJumpBall from "@/components/hx-jump-ball/hx-jump-ball.vue"
+export default {
+    components: {hxJumpBall}
+}
+```
+
+
+### 属性
+#### 基本属性 
+| 名称                         | 类型            | 默认值                | 描述                                               |
+| ----------------------------|---------------  | ---------------------- | ---------------------------------------------------|
+| element                     | Array           | []                     | `[起跳元素,终点元素]`必填项,可以动态改变起跳元素,使用方式看demo     |
+| start                       | Number          | 1                      | 想要执行一次动画,需要改变该值(每次加一或减一)						|
+| ballWidth                   | Number          | 15                     | 小球宽度                                           |
+| ballHeight                  | Number          | 15                     | 小球高度                                           |
+| backgroundColor             | String          | reg                    | 小球颜色                                           |
+| backgroundImage             | String          | ''                     | 小球图片                                          |
+| index                       | Number          | 1                      | 堆叠顺序(z-index 参数)                                     |
+| bezier                      | String          | cubic-bezier(.6,-0.63,.94,.71)          | 贝塞尔曲线,如果你想调整小球跳跃高度只需调整第二个参数 (-1 ~ 1)                             |
+| speed                       | Number          | 800                    | 下落速度(毫秒)                             |
+
+
+### 事件
+| 名称             | 参数              | 描述                      |
+| -----------------|------------------| --------------------------|
+| @msg             | res              | 执行成功返回{code:0} ,失败返回{code:1,error:'info'}         |
+
+## 使用例子
+
+### html
+``` html
+<template>
+	<view>
+		<jumpBall :start.sync="num" :element.sync="element" @msg="jbMsg" />
+		  
+		<view class="add" @click="anima()" ><button>起跳1</button></view>
+		<view class="add2" @click="anima2()"><button>起跳2</button></view>  
+		<view class="foot"><view class="cart">测试位置</view></view>
+	</view>
+</template>
+```
+
+### javacript
+``` javacript
+<script>
+	import jumpBall from '@/components/hx-jump-ball/hx-jump-ball.vue';
+	export default {
+		components: {
+		  jumpBall
+		},
+		data() {
+			return {
+				num:1,
+				element: [],
+			}
+		},
+		methods: {
+			anima(){
+				this.element = ['.add','.cart'];
+				this.num ++; 
+			},
+			anima2(){
+				this.element = ['.add2','.cart'];
+				this.num ++;
+			}, 
+			jbMsg(res){
+				//执行加入购物车的逻辑
+				console.log("执行回调",res.code);
+			}
+		}
+	}
+</script>
+```
+
+### css
+```
+<style>
+	.add{
+		position: fixed;
+		right:30px;
+		top: 150px;
+	}
+	.add2{
+		position: fixed;
+		right:30px;
+		top: 250px;
+	}
+	.foot{
+		position: fixed;
+		bottom: 0;
+		height: 90upx;
+		background: #e1e1e1;
+		width: 100%;
+	}
+	.foot .cart{
+		width: 180upx;
+		margin-left: 60upx;
+		height: 90upx;
+		background: #999999;
+		line-height: 90upx;
+		text-align: center;
+	}
+</style>
+```

+ 239 - 0
HX-SHOP/components/hx-jump-ball/hx-jump-ball - ╕▒▒╛.vue

@@ -0,0 +1,239 @@
+<template>
+	<view class="hx-jump-ball">
+		<view class="ballBox" :animation="ballBoxAnimationData" :style="{'z-index':index}">
+			<view class="ballOuter" 
+			:animation="ballOuterAnimationData" 
+			:style="{width:ballWidth*2 + 'upx',height:ballHeight*2 + 'upx','background-color':backgroundColor,'background-image': backgroundImage ?`url(${backgroundImage})`: ''}">
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: "hx-jump-ball",
+		data() {
+			return {
+				flag: false,
+				ballBoxAnimation: null,
+				ballOuterAnimation: null,
+				ballBoxAnimationData: {},
+				ballOuterAnimationData: {},
+			};
+		},
+		props: {
+			//小球宽度
+			ballWidth: {
+			    type: Number,
+				default: 15
+			},
+			//小球高度
+			ballHeight: {
+			    type: Number,
+				default: 15
+			},
+			//小球颜色
+			backgroundColor: {
+			    type: String,
+				default: "reg"
+			},
+			//图片
+			backgroundImage: {
+			    type: String,
+				default: ""
+			},
+			//小球的堆叠顺序
+			index: {
+			    type: Number,
+				default: 0
+			},
+			//开始动画
+			start: {
+			    type: Number,
+				default: 1
+			},
+			//html元素class名称,[起点元素,终点元素]
+			element:{
+				type: Array,
+				default(){
+					return []
+				}
+			},
+			//下落速度 ms毫秒
+			speed:{
+				type: Number,
+				default: 800
+			},
+			//贝塞尔曲线
+			bezier:{
+				type: String,
+				default: "cubic-bezier(.6,-0.63,.94,.71)"
+			}
+		},
+		
+		watch:{
+			start(val,oldVal) {
+				var that = this;
+				if(!that.element){
+					return;
+				}
+				if(this.flag){
+					return;
+				}
+				that.flag = !that.flag;
+				that.getElementCoordinate(that.element[0],that.element[1]);
+				
+			}
+		},
+		created() {
+			this.ballBoxAnimation = uni.createAnimation({
+				duration: 0,
+				timingFunction: this.bezier,
+				delay: 0
+			}); 
+			this.ballOuterAnimation = uni.createAnimation({
+				duration: 0,
+				timingFunction: "linear",
+				delay: 0
+			});
+			this.setEnd();
+			//初始化位置
+		},
+		methods:{
+			//获取元素坐标
+			getElementCoordinate(startElement,endElement){
+				let that = this;
+				const query = uni.createSelectorQuery();  
+				let nodesRef = query.select(startElement); 
+				nodesRef.fields({  
+				      id: true,  
+				      rect: true,
+					  size: true
+				}, res => {
+					  if(!res){
+						  that.flag = !that.flag;
+						  that.$emit("msg",{code: 100, error: '未获取到起始元素位置'})
+						  return ;
+					  }
+					  const SLeft = res.left  + ((res.width + that.ballWidth ) / 2  - that.ballWidth);
+					  const STop = res.bottom - ((res.height - that.ballHeight ) / 2  + that.ballHeight);
+					  
+					  let nodesRef2 = uni.createSelectorQuery().select(endElement); 
+					  nodesRef2.fields({  
+					        id: true,  
+					        rect: true,
+					  	  size: true
+					  }, res2 => {  
+					  	  if(!res2){
+							  that.$emit("msg",{code: 101, error: '未获取到结束元素位置'})
+							  return ;
+					  	  }
+						  //计算出元素的中心坐标
+					  	  let ELeft = res2.left + ((res2.width + that.ballWidth ) / 2  - that.ballWidth);
+					  	  let ETop = res2.bottom - ((res2.height - that.ballHeight ) / 2  + that.ballHeight);
+					  	  that.startAnimation(SLeft,STop,ELeft,ETop);
+					  }).exec()  
+					  
+				}).exec()  
+			},
+			
+			
+			//开始动画
+			startAnimation(SLeft,STop,ELeft,ETop){
+				let that = this;
+				
+				let jumpDistance = SLeft - ELeft;
+				
+			
+				
+			
+			//  暂时注释掉,待uniapp修复bug后再调整
+				//根坐标
+			// 	this.ballBoxAnimation.translate3d(ELeft,STop,0).step({duration: 800});
+			// 	this.ballBoxAnimation.translate3d(ELeft,ETop,0).step({duration: 800});
+			// 	this.ballBoxAnimationData = this.ballBoxAnimation.export();
+			
+			// 	console.log('根坐标执行玩');
+			// 	//相对根的坐标
+			// 	this.ballOuterAnimation.translate3d(jumpDistance,0,0).step({duration: 800});
+			// 	this.ballOuterAnimation.translate3d(0,0,0).step({duration: 800});
+			// 	this.ballOuterAnimationData = this.ballOuterAnimation.export();
+			// 	console.log('相对根的坐标');
+			// 	setTimeout(function() {
+			// 		console.log("动画完成");
+			// 		that.flag = !that.flag;
+			// 	}, 800);
+				//初始化位置
+				//that.setStart(SLeft,STop,ELeft,ETop);
+				//因为uniapp  step()有bug,所以必须要延时执行
+				that.ballBoxAnimation = uni.createAnimation({
+					duration: 0,
+					timingFunction: that.bezier,
+					delay: 0
+				}); 
+				that.ballOuterAnimation = uni.createAnimation({
+					duration: 0,
+					timingFunction: "linear",
+					delay: 0
+				});
+				//根坐标
+				that.ballBoxAnimation.translate3d(ELeft,STop,0).opacity(1).step({duration: 0});
+				that.ballBoxAnimation.opacity(1).translate3d(ELeft,ETop,0).step({duration: that.speed});
+				that.ballBoxAnimation.opacity(0).step({duration: 0});
+				that.ballBoxAnimationData = that.ballBoxAnimation.export();
+				
+				//相对根的坐标
+				that.ballOuterAnimation.translate3d(SLeft - ELeft,0,0).opacity(1).step({duration: 0});
+				that.ballOuterAnimation.opacity(1).translate3d(0,0,0).step({duration: that.speed});
+				that.ballOuterAnimation.opacity(0).step({duration: 0});
+				that.ballOuterAnimationData = that.ballOuterAnimation.export();
+				
+				setTimeout(function() {
+					that.flag = !that.flag;
+					that.$emit("msg",{code:0,status:true});
+				},  that.speed);
+				
+				
+			},
+			 //动画开始前初始化小球位置并显示小球
+			setStart(SLeft,STop,ELeft,ETop){
+				this.ballBoxAnimation.translate3d(ELeft,STop,0).opacity(1).step({duration: 0});
+				this.ballBoxAnimationData = this.ballBoxAnimation.export();
+				
+				this.ballOuterAnimation.translate3d(SLeft - ELeft,0,0).opacity(1).step({duration: 0});
+				this.ballOuterAnimationData = this.ballOuterAnimation.export();
+			},
+			
+			//隐藏小球
+			setEnd(){
+				this.ballBoxAnimation.opacity(0).step({duration: 0});
+				this.ballBoxAnimationData = this.ballBoxAnimation.export();
+				
+				this.ballOuterAnimation.opacity(0).step({duration: 0});
+				this.ballOuterAnimationData = this.ballOuterAnimation.export();
+			}
+		}
+	}
+</script>
+
+<style>
+	.ballBox{
+		position: fixed;
+		left: 0;
+		top: 0;
+		z-index: 9;
+		/*  用颜色来演示用原理 */
+		/*background-color: #4CD964*/;
+		height:30rpx;
+		width:30rpx;
+	}
+	.ballOuter {
+	   background:red;
+	   height:100%;
+	   width:100%;
+	   border-radius: 50%;
+	   background-size: 100% 100%;
+	   background-position: center;
+	}
+	
+</style>

+ 266 - 0
HX-SHOP/components/hx-jump-ball/hx-jump-ball.vue

@@ -0,0 +1,266 @@
+<template>
+	<view class="hx-jump-ball">
+		<view class="ballBox"  :style="{transition:'all '+adminTime +'ms' + ' linear','z-index':index,left: ctnBallX+'px',top: ctnBallY+'px',opacity:ctnOpacity}">
+			<view class="ballOuter" 
+			
+			:style="{transition:'all '+adminTime +'ms' + ' linear',left: ballX+'px',top: ballY+'px',opacity:opacity,width:ballWidth + 'px',height:ballHeight + 'px','background-color':backgroundColor,'background-image': backgroundImage ?`url(${backgroundImage})`: ''}">
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: "hx-jump-ball",
+		data() {
+			return {
+				flag: false,
+				ballBoxAnimation: null,
+				ballOuterAnimation: null,
+				ballBoxAnimationData: {},
+				ballOuterAnimationData: {},
+				
+				//小球透明
+				opacity: 1,
+				ballX: 0,
+				ballY: 0,
+				ctnOpacity: 1,
+				ctnBallX: 0,
+				ctnBallY: 0,
+				
+				adminTime: 500,
+			};
+		},
+		props: {
+			//小球宽度
+			ballWidth: {
+			    type: Number,
+				default: 15
+			},
+			//小球高度
+			ballHeight: {
+			    type: Number,
+				default: 15
+			},
+			//小球颜色
+			backgroundColor: {
+			    type: String,
+				default: "reg"
+			},
+			//图片
+			backgroundImage: {
+			    type: String,
+				default: ""
+			},
+			//小球的堆叠顺序
+			index: {
+			    type: Number,
+				default: 0
+			},
+			//开始动画
+			start: {
+			    type: Number,
+				default: 1
+			},
+			//html元素class名称,[起点元素,终点元素]
+			element:{
+				type: Array,
+				default(){
+					return []
+				}
+			},
+			//下落速度 ms毫秒
+			speed:{
+				type: Number,
+				default: 800
+			},
+			//贝塞尔曲线
+			bezier:{
+				type: String,
+				default: "cubic-bezier(.6,-0.63,.94,.71)"
+			}
+		},
+		
+		watch:{
+			start(val,oldVal) {
+				var that = this;
+				if(!that.element){
+					return;
+				}
+				if(this.flag){
+					return;
+				}
+				that.flag = !that.flag;
+				that.getElementCoordinate(that.element[0],that.element[1]);
+				
+			}
+		},
+		created() {
+			this.ballBoxAnimation = uni.createAnimation({
+				duration: 0,
+				timingFunction: this.bezier,
+				delay: 0
+			}); 
+			this.ballOuterAnimation = uni.createAnimation({
+				duration: 0,
+				timingFunction: "linear",
+				delay: 0
+			});
+			//this.setEnd();
+			//初始化位置
+		},
+		methods:{
+			//获取元素坐标
+			getElementCoordinate(startElement,endElement){
+				let that = this;
+				const query = uni.createSelectorQuery();  
+				let nodesRef = query.select(startElement); 
+				nodesRef.fields({  
+				      id: true,  
+				      rect: true,
+					  size: true
+				}, res => {
+					  if(!res){
+						  that.flag = !that.flag;
+						  that.$emit("msg",{code: 100, error: '未获取到起始元素位置'})
+						  return ;
+					  }
+					  const SLeft = res.left  + ((res.width + that.ballWidth ) / 2  - that.ballWidth);
+					  const STop = res.bottom - ((res.height - that.ballHeight ) / 2  + that.ballHeight);
+					  
+					  let nodesRef2 = uni.createSelectorQuery().select(endElement); 
+					  nodesRef2.fields({  
+					        id: true,  
+					        rect: true,
+					  	  size: true
+					  }, res2 => {  
+					  	  if(!res2){
+							  that.$emit("msg",{code: 101, error: '未获取到结束元素位置'})
+							  return ;
+					  	  }
+						  //计算出元素的中心坐标
+					  	  let ELeft = res2.left + ((res2.width + that.ballWidth ) / 2  - that.ballWidth);
+					  	  let ETop = res2.bottom - ((res2.height - that.ballHeight ) / 2  + that.ballHeight);
+					  	  that.startAnimation(SLeft,STop,ELeft,ETop);
+					  }).exec()  
+					  
+				}).exec()  
+			},
+			
+			
+			//开始动画
+			startAnimation(SLeft,STop,ELeft,ETop){
+				let that = this;
+				this.adminTime = 500
+				let jumpDistance = SLeft - ELeft;
+				this.opacity= 1;
+				this.ballX = SLeft - ELeft;
+				this.ballY= 0;
+				this.ctnOpacity= 1;
+				this.ctnBallX= ELeft;
+				this.ctnBallY= STop;
+				setTimeout(function() {
+					this.adminTime = 0;
+					this.opacity= 1;
+					this.ballX = 0;
+					this.ballY= 0;
+					this.ctnOpacity= 1;
+					this.ctnBallX= ELeft;
+					this.ctnBallY= ETop;
+				},  100);
+				
+				
+
+			//  暂时注释掉,待uniapp修复bug后再调整
+				//根坐标
+			// 	this.ballBoxAnimation.translate3d(ELeft,STop,0).opacity(1).step({duration: 800});
+			// 	this.ballBoxAnimation.translate3d(ELeft,ETop,0).step({duration: 800});
+			// 	this.ballBoxAnimationData = this.ballBoxAnimation.export();
+			
+			// 	console.log('根坐标执行玩');
+			// 	//相对根的坐标
+			// 	this.ballOuterAnimation.translate3d(jumpDistance,0,0).opacity(1).step({duration: 800});
+			// 	this.ballOuterAnimation.translate3d(0,0,0).step({duration: 800});
+			// 	this.ballOuterAnimationData = this.ballOuterAnimation.export();
+			// 	console.log('相对根的坐标');
+			// 	setTimeout(function() {
+			// 		console.log("动画完成");
+			// 		that.flag = !that.flag;
+			// 	}, 800);
+				//初始化位置
+				//that.setStart(SLeft,STop,ELeft,ETop);
+				//因为uniapp  step()有bug,所以必须要延时执行
+				// that.ballBoxAnimation = uni.createAnimation({
+				// 	duration: 0,
+				// 	timingFunction: that.bezier,
+				// 	delay: 0
+				// }); 
+				// that.ballOuterAnimation = uni.createAnimation({
+				// 	duration: 0,
+				// 	timingFunction: "linear",
+				// 	delay: 0
+				// });
+				
+				//根坐标
+				//that.ballBoxAnimation.translate3d(ELeft,STop,0).opacity(1).step({duration: 0});
+				//that.ballBoxAnimation.opacity(1).translate3d(ELeft,ETop,0).step({duration: 1500});
+				//that.ballBoxAnimation.opacity(0).step({duration: 0});
+				//that.ballBoxAnimationData = that.ballBoxAnimation.export();
+				
+				//相对根的坐标
+				//that.ballOuterAnimation.translate3d(SLeft - ELeft,0,0).opacity(1).step({duration: 0});
+				//that.ballOuterAnimation.opacity(1).translate3d(0,0,0).step({duration: 1500});
+				//that.ballOuterAnimation.opacity(0).step({duration: 0});
+				//that.ballOuterAnimationData = that.ballOuterAnimation.export();
+				
+				setTimeout(function() {
+					that.flag = !that.flag;
+					that.$emit("msg",{code:0,status:true});
+				},  that.speed);
+				
+			},
+			ballIni(){
+				
+			},
+			 //动画开始前初始化小球位置并显示小球
+			setStart(SLeft,STop,ELeft,ETop){
+				this.ballBoxAnimation.translate3d(ELeft,STop,0).opacity(1).step({duration: 0});
+				this.ballBoxAnimationData = this.ballBoxAnimation.export();
+				
+				this.ballOuterAnimation.translate3d(SLeft - ELeft,0,0).opacity(1).step({duration: 0});
+				this.ballOuterAnimationData = this.ballOuterAnimation.export();
+			},
+			
+			//隐藏小球
+			setEnd(){
+				this.ballBoxAnimation.opacity(0).step({duration: 0});
+				this.ballBoxAnimationData = this.ballBoxAnimation.export();
+				
+				this.ballOuterAnimation.opacity(0).step({duration: 0});
+				this.ballOuterAnimationData = this.ballOuterAnimation.export();
+			}
+		}
+	}
+</script>
+
+<style>
+	.ballBox{
+		position: fixed;
+		left: 0;
+		top: 0;
+		z-index: 9;
+		/*  用颜色来演示用原理 */
+		background-color: #4CD964;
+		height:30rpx;
+		width:30rpx;
+	}
+	.ballOuter {
+	   background:red;
+	   height:100%;
+	   width:100%;
+	   border-radius: 50%;
+	   background-size: 100% 100%;
+	   background-position: center;
+	}
+	
+</style>

+ 86 - 0
HX-SHOP/components/hx-load/hx-load.vue

@@ -0,0 +1,86 @@
+<template>
+	<view class="hx-load">
+		<view class="style1" v-if="style == 1">
+			<view class="">
+				<view class="item bounce1" :style="color ? `background-color: ${color}` : '' "></view>
+				<view class="item bounce2" :style="color ? `background-color: ${color}` : '' "></view>
+				<view class="item bounce3" :style="color ? `background-color: ${color}` : '' "></view>
+			</view>
+			<text>{{txt}}</text>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: 'hx-load',
+		data() {
+			return {
+				
+			};
+		},
+		props:{
+			'color': {
+				type: String,
+				default: '',
+			},
+			'style': {
+				type: Number,
+				default: 1,
+			},
+			'txt': {
+				type: String,
+				default: '正在载入',
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.hx-load{
+		.style1 {
+		  margin: 20px auto;
+		  width: 150px;
+		  text-align: center;
+		  .item {
+		    width: 12px;
+		    height: 12px;
+		    background-color: #ffd11c;
+		    margin: 0 3px;
+		    border-radius: 100%;
+		    display: inline-block;
+		    -webkit-animation: bouncedelay 1.4s infinite ease-in-out;
+		    animation: bouncedelay 1.4s infinite ease-in-out;
+		    -webkit-animation-fill-mode: both;
+		    animation-fill-mode: both;
+		  }
+		  .bounce1 {
+		    -webkit-animation-delay: -0.32s;
+		    animation-delay: -0.32s;
+		  }
+		  .bounce2 {
+		    -webkit-animation-delay: -0.16s;
+		    animation-delay: -0.16s;
+		  }
+		  text{
+			  margin-top: 6px;
+			  font-size: 12px;
+			  color: #cccccc;
+		  }
+		}
+		@-webkit-keyframes bouncedelay {
+		  0%, 80%, 100% { -webkit-transform: scale(0.0) }
+		  40% { -webkit-transform: scale(1.0) }
+		}
+		@keyframes bouncedelay {
+		  0%, 80%, 100% {
+		    transform: scale(0.0);
+		    -webkit-transform: scale(0.0);
+		  } 40% {
+		    transform: scale(1.0);
+		    -webkit-transform: scale(1.0);
+		  }
+		}
+	}
+
+</style>

+ 255 - 0
HX-SHOP/components/hx-navbar/README.md

@@ -0,0 +1,255 @@
+# hx-navbar 适用于 uni-app 项目的头部导航组件
+
+导航栏组件,主要用于头部导航,组件名:hx-navbar
+
+本组件目前兼容微信小程序、H5、5+APP。
+
+## QQ群 954035921 
+如有问题可进群发图讨论
+
+### 本组件支持模式:
+1. 普通固定顶部导航  
+2. 透明导航  
+3. 透明固定顶部导航 
+4. 不固定普通导航
+5. 背景颜色线性渐变
+6. 滑动显示背景
+7. 左、中、右3个插槽;可关闭左右插槽使中间插槽铺满导航,实现高度自定义的导航需求
+
+### 使用前提
+
+需要先安装·uniapp·官方的```uni-icons``` 图标组件,```uni-icons```官方组件下载地址:[https://ext.dcloud.net.cn/plugin?id=28](https://ext.dcloud.net.cn/plugin?id=28)
+
+### 使用方式	
+页面使用需在 ``` script ``` 中引用组件
+``` javascript
+import hxNavbar from "@/components/hx-navbar/hx-navbar.vue"
+export default {
+    components: {hxNavbar}
+}
+```
+
+全局使用需在 ``` main.js ```  中注册组件
+``` javascript
+import hxNavbar from "./components/hx-navbar/hx-navbar.vue"
+Vue.component('hx-navbar',hxNavbar)
+
+```
+
+
+### 属性
+#### 基本属性 
+| 名称                        | 类型            | 默认值                | 描述                                               |
+| ----------------------------|--------------- | ---------------------- | ---------------------------------------------------|
+| back                   	  | Boolean         | true          | 返回上一页,(设置后,```leftIcon```属性,和```click-left```事件将失效|
+| height                   	  | String         | 44px          | 导航栏高度(不包含状态栏高度)|
+| barPlaceholder              | String         | auto          | 导航栏占位符 显示(show),隐藏(hidden),自动(auto:如果头部为固定fixed ,则显示占位符)               |
+| title                       | String         | -             | 导航标题(当设置了标题,中间插槽将失效)                                     |
+| fixed                       | Boolean        | false         | 固定头部											|
+| color                       | String         | #000000       | 导航文字颜色(如果需要屏幕滑动后变色,参数则为数组,例子:`['#000000','#ffffff']`)                                        |
+| backgroundColor             | Array          | [255, 255, 255]          | 导航背景颜色为RGB 编号(单色背景数组为```[255,255,255]```,线性渐变背景```[[236, 0, 140],[103, 57, 182],...]```)                                      |
+| pageScroll				  | Object         | {}             | 屏幕滑动距离顶部的对象```滑动渐变必要参数```                                       |
+| backgroundColorLinearDeg    | String         | 45             | 导航背景线性渐变角度                                       |
+| backgroundImg   			  | String         | -             | 导航背景图片(背景图片优先级高于背景颜色)  |
+| transparent   			  | String         | show             | 背景透明(show 不透明,hidden 透明,auto 自动:滑动逐渐显示背景颜色,当头部固定时生效) 兼容性:头条小程序必须在页面上加 onPageScroll(e){} ,才能滑动显示背景,可参考dome7|
+| shadow                      | Boolean         | false         | 导航栏阴影          |
+| border                      | Boolean         | false         | 导航栏边框                           |
+
+#### 关于状态栏的属性
+| 名称                        | 类型            | 默认值                | 描述                                               |
+| ----------------------------|--------------- | ---------------------- | ---------------------------------------------------|
+| statusBar                   | Boolean         | true       		   | 包含状态栏												|
+| statusBarFontColor          | Array,String   | #000000               | 状态栏字体颜色,只支持```#000000 ```和```#FFFFFF```(如果需要屏幕滑动变色,参数则为数组,例子:```['#000000','#ffffff']```)|
+| statusBarBackground         | String         | -                     | 状态栏背景颜色,如果你想单独设置状态栏颜色,该属性是个不错的选择
+
+#### 关于插槽的属性
+| 名称                        | 类型            | 默认值                | 描述                                               |
+| ----------------------------|--------------- | ---------------------- | ---------------------------------------------------|
+| leftIcon                    | String         | -             | 左插槽图标,必须为 ```uni-icons``` 图标                                       |
+| rightIcon   				  | String         | -             | 右插槽图标,必须为 ```uni-icons``` 图标  |
+| leftSlot                    | Boolean        | true          | 开启左插槽                                        |
+| rightSlot                   | Boolean        | true          | 开启右插槽                                      |
+| leftSlidiSwitch             | Boolean         | false         | 屏幕滑动后 `left`插槽切换为`leftAfter`插槽                       |
+| centerSlidiSwitch           | Boolean         | false         | 屏幕滑动后 `default`插槽切换为`centerAfter`插槽                            |
+| rightSlidiSwitch            | Boolean         | false         | 屏幕滑动后 `right`插槽切换为`rightAfter`插槽                            |
+
+
+#### 返回上一页为空时的处理属性
+| 名称                        | 类型            | 默认值                | 描述                                               |
+| ----------------------------|--------------- | ---------------------- | ---------------------------------------------------|
+| backTabbarUrl               | String         | /pages/index/index     | 返回至指定的tabber页面(返回首页),当上一页为空时生效;全局使用推荐进组件修改`backTabbarUrl`的默认值|
+| defaultBackUrl              | String         | -          			| 返回至指定的普通页面,当上一页为空时生效;`defaultBackUrl`优先级高于`backTabbarUrl`;主要应用在返回失效时|
+
+``` html
+<!-- 使用场景:假如刷新了当前页面,那么返回事件将失效。
+这时用上 `defaultBackUrl` 或 `backTabbarUrl` 则能返回至指定页面-->
+<hx-navbar left-text="关于" defaultBackUrl="/pages/user/setting/setting" />
+```
+
+
+### 插槽
+| 名称                  | 描述                                                               |
+| ----------------------|-------------------------------------------------------------------|   
+| left                  | 左插槽 (可关闭该插槽 ```leftSlot``` 属性)                           |
+| default               | 中间插槽(当设置了标题,中间插槽将失效)                               |
+| right                 | 右插槽 (可关闭该插槽 ```rightSlot``` 属性)                          |
+| leftAfter             | 屏幕滑动后的左插槽 (需要开启`leftSlidiSwitch`属性才生效)                  |
+| centerAfter           | 屏幕滑动后的中插槽 (需要开启`centerSlidiSwitch`属性才生效)                  |
+| rightAfter            | 屏幕滑动后的右插槽 (需要开启`rightSlidiSwitch`属性才生效)                  |
+
+
+``` html
+<hx-navbar>
+    <view>标题栏(中间插槽)</view>
+    <view slot="left">left(左插槽)</view>
+    <view  slot="right">right(右插槽)</view>
+</hx-navbar>
+```
+
+
+### 事件
+| 名称             | 参数              | 描述                      |
+| -----------------|------------------| --------------------------|
+| click-left       | -                | 左侧按钮点击时触发,此事件将覆盖 `返回`          |
+| click-right      | -                | 右侧按钮点击时触发          |
+| scroll           | -                | 监听滚动条,回调参数为滚动距离;固定头部时生效;应用场景:如滚动到多少时触发某些事件          |
+
+## 使用例子
+
+### 简单使用
+``` html
+<hx-navbar title="我爱新疆" left-text="返回" />
+```
+
+### 背景颜色线性渐变、头部固定
+``` html
+<hx-navbar 
+	title="颜色渐变" 
+	:back="false"
+	:fixed="true"
+	color="#ffffff"
+	:background-color="[[28, 187, 180],[141, 198, 63]]">
+</hx-navbar>
+```
+
+### 滑动显示背景
+``` html
+<!-- 该例子取消了导航占位符 -->
+<hx-navbar 
+	title="颜色渐变" 
+	:back="false"
+	:fixed="true"
+	color="#ffffff"
+	barPlaceholder="hidden"
+	transparent="auto"
+	:background-color="[[28, 187, 180],[141, 198, 63]]"
+	:pageScroll.sync="scrollData">
+</hx-navbar>
+
+```
+``` javascript
+data() {
+	return {
+		scrollData: {},
+	}
+},
+//必须在页面加 onPageScroll(e){} ,才能滑动显示背景
+onPageScroll(e){
+	this.scrollData = e;
+},
+```
+
+### 左中插槽演示
+``` html
+<hx-navbar  
+	:back="false" 
+	:fixed="true"
+	right-icon="scan">
+	<block slot="left">
+		<view class="city">
+			<view>新疆</view>
+			<uni-icons type="arrowdown" color="#333333" size="22" />
+		</view>
+	</block>
+	<view class="input-view">
+		<uni-icons type="search" size="22" color="#666666" />
+		<input confirm-type="search" class="input" type="text" placeholder="输入搜索关键词" @confirm="confirm">
+	</view>
+</hx-navbar>
+
+
+/*css 用于演示插槽自定义样式*/
+<style>
+	.city{
+		display: flex;flex-direction: row;
+		align-items: center;
+		justify-content: center;
+		width: 100%;
+		margin-left: 8px;
+		white-space: nowrap;
+	}
+</style>
+```
+
+### 关闭左右插槽演示
+``` html
+<hx-navbar  :back="false" :fixed="true" :leftSlot='false' :rightSlot='false'>
+	<view style="display: flex;">
+		<view class="city">
+			<view>新疆</view>
+			<uni-icons type="arrowdown" size="22" />
+		</view>
+		<view class="input-view" style="width: 100%;">
+			<uni-icons type="search" size="22" color="#666666" />
+			<input confirm-type="search" class="input" type="text" placeholder="输入搜索关键词" @confirm="confirm">
+		</view>
+		<uni-icons type="scan" size="22" style="line-height: 44px;padding-left: 8px;"/>
+	</view>
+</hx-navbar>
+/*css 用于演示插槽自定义样式*/
+<style>
+	.city{
+		display: flex;flex-direction: row;
+		align-items: center;
+		justify-content: center;
+		width: 100%;
+		margin-left: 8px;
+		white-space: nowrap;
+	}
+</style>
+```
+
+### 屏幕滑动切换显示插槽
+``` html
+<!-- 该例子演示中间插槽、右插槽屏幕滑动后的变换 -->
+<hx-navbar  
+:border="true" 
+:centerSlidiSwitch="true"
+:rightSlidiSwitch="true"
+:fixed="true"
+:pageScroll.sync="scrollData">
+	<view style="text-align: center;width: 100%;">
+		<text>帮助反馈</text>
+	</view>
+	<view slot="centerAfter" style="text-align: center;width: 100%;">
+		<text>咨询</text>
+	</view>
+	<block slot="right">
+		<uni-icons type="qq" size="30" ></uni-icons>
+	</block>
+	<block slot="rightAfter">
+		<uni-icons type="chat" size="30" ></uni-icons>
+	</block>
+</hx-navbar>
+```
+``` javascript
+data() {
+	return {
+		scrollData: {},
+	}
+},
+//必须在页面加 onPageScroll(e){} ,才能滑动显示
+onPageScroll(e){
+	this.scrollData = e;
+},
+```

+ 635 - 0
HX-SHOP/components/hx-navbar/hx-navbar.vue

@@ -0,0 +1,635 @@
+<template>
+	
+	<view class="hx-navbar" >
+		
+		<view
+			:class="{'hx-navbar--fixed': fixed,'hx-navbar--shadow':shadow,'hx-navbar--border':border}"
+			:style="{'background': backgroundColorRgba}"
+			class="hx-navbar__content">
+			<block v-if="backgroundImg">
+				<image class="navbgimg" :src="backgroundImg" mode=""></image>
+			</block>
+			
+			<view :style="{ height: statusBarHeight ,'background': statusBarBackground}" class="hx-status-bar" v-if="statusBar" ></view>
+			<view :style="{color:colorInfo,height: height,'line-height':height}" class="hd hx-navbar__header hx-navbar__content_view">
+				<view class="hx-navbar__header-btns hx-navbar__content_view"  @tap="onClickLeft" v-if="leftSlot" :style="{'color': colorInfo}">
+					<block v-if="leftText.length || leftIcon.length || back">
+						<view
+							v-if="leftIcon.length || back"
+							:class="back ? 'left_back' : ''"
+							class="hx-navbar__content_view" >
+							<uni-icons :type="back ? 'arrowleft' : leftIcon" :color="colorInfo" size="28"/>
+						</view>
+						<view
+							v-if="leftText.length"
+							:class="{'hx-navbar-btn-icon-left':!leftIcon.length}"
+							class="hx-navbar-btn-text hx-navbar__content_view">{{ leftText }}</view>
+						
+					</block>
+					<block v-else>
+						<slot name="leftAfter" v-if="leftSlidiSwitch && slotSlidiSwitch == 1" />
+						<slot name="left" v-else/>
+						
+					</block>
+				</view>
+			  
+			  
+				<view class="hx-navbar__header-container hx-navbar__content_view">
+					<view
+					  v-if="title.length"
+					  class="hx-navbar__header-container-inner hx-navbar__content_view">{{ title }}</view>
+					<!-- 标题插槽 -->
+				
+					<block v-else>
+						<slot name="centerAfter" v-if="centerSlidiSwitch && slotSlidiSwitch == 1"/>
+						<slot v-else/>
+						
+					</block>
+				</view>
+				
+				<view :class="title.length?'hx-navbar__header-btns-right':''"
+					class="hx-navbar__header-btns hx-navbar__content_view"
+					@tap="onClickRight"
+					v-if="rightSlot">
+					<!-- 优先显示图标 -->
+					<block v-if="rightIcon.length || rightText.length">
+						<view  class="hx-navbar__content_view" v-if="rightIcon.length">
+							<uni-icons :type="rightIcon" :color="colorInfo" size="28"/>
+						</view>
+						<view v-if="rightText.length" class="hx-navbar-btn-text hx-navbar__content_view">{{ rightText }}</view>
+					</block>
+					<block v-else>
+						<slot name="rightAfter"  v-if="rightSlidiSwitch && slotSlidiSwitch == 1"/>
+						<slot name="right" v-else/>
+					</block>
+					
+					
+				</view>
+			  
+			</view>
+		</view>
+		
+		<view
+		  v-if="placeholder" 
+		  class="hx-navbar__placeholder">
+		  <view :style="{ height: statusBarHeight}" class="hx-status-bar" v-if="statusBar" ></view>
+		 
+		  <view :style="{ height: height}" />
+		</view>
+	</view>
+	
+</template>
+
+<script>
+	import uniIcons from '../uni-icons/uni-icons.vue'
+	//获取系统状态栏高度
+	var statusBarHeight = uni.getSystemInfoSync().statusBarHeight  + 'px';
+	export default {
+		name: "hx-navbar",
+		components: {
+		  uniIcons
+		},
+		data() {
+			return {
+				 statusBarHeight: statusBarHeight,
+				 transparentValue: 0,
+				 navTransparentFixedFontColor: '#fff',
+				 
+				 statusBarFontColorInfo: [],
+				 backgroundColorRgba: 'rgba(255,255,255,1)',
+				 backgroundColorRgb: 'rgb(222,222,222)',
+				 colorInfo: '#000000',
+				 placeholder: false,
+				 colorContainer: null,
+				 slotSlidiSwitch: 0
+				 
+			};
+		},
+		props:{
+			height:{
+				type: String,
+				default: "44px"
+			},
+			//导航栏占位符 显示(show),隐藏(hidden),自动(auto:如果头部为固定fiexd ,则显示占位符)
+			barPlaceholder:{
+				type: String,
+				default: "auto"
+			},
+			//返回上一页
+			back:{
+				type: [Boolean, String],
+				default: true
+			},
+			//标题
+			title: {
+			  type: String,
+			  default: ''
+			},
+			//是否开启左插槽
+			leftSlot:{
+				type: [Boolean, String],
+				default: true
+			},
+			//是否开启右插槽
+			rightSlot:{
+				type: [Boolean, String],
+				default: true
+			},
+		
+			//左边文字
+			leftText: {
+			  type: String,
+			  default: ''
+			},
+			//右插槽文字
+			rightText: {
+			  type: String,
+			  default: ''
+			},
+			//左插槽图标
+			leftIcon: {
+			  type: String,
+			  default: ''
+			},
+			//右插槽图标
+			rightIcon: {
+			  type: String,
+			  default: ''
+			},
+			//是否固定头
+			fixed: {
+			  type: [Boolean, String],
+			  default: false
+			},
+			//文字颜色
+			color: {
+			  type: [Array,String],
+			  default: "#000000"
+			},
+			//导航栏背景颜色
+			backgroundColor: {
+			  type: Array,
+			  default: function(){
+				  return new Array([255,255,255],[255,255,255]);
+			  }
+			},
+			//线性渐变角度
+			backgroundColorLinearDeg: {
+				type: String,
+				default: '45'
+			},
+			//背景图片
+			backgroundImg: {
+				type: String,
+				default: ''
+			},
+			//背景透明(show,hidden,auto)
+			transparent: {
+				type: String,
+				default: 'show'
+			},
+			//状态栏字体颜色,只支持黑(#000000)和白(#FFFFFF)两种颜色。(,)
+			statusBarFontColor:{
+				type: [Array,String],
+				default:function(){
+				  return new Array("#000000","#000000");
+				} 
+			},
+			//是否包含状态栏
+			statusBar: {
+			  type: [Boolean, String],
+			  default: true
+			},
+			//状态栏背景颜色
+			statusBarBackground:{
+				type: String,
+				default: ''
+			},
+			//导航栏阴影
+			shadow: {
+			  type: [String, Boolean],
+			  default: false
+			},
+			//导航栏边框
+			border: {
+			  type: [String, Boolean],
+			  default: false
+			},
+			//跳至普通页面
+			defaultBackUrl: {
+			  type: String,
+			  default: ''
+			},
+			//跳至tabber页面
+			backTabbarUrl: {
+			  type: String,
+			  default: '/pages/index/index'
+			},
+			//滑动后切换左插槽
+			leftSlidiSwitch:{
+				type: [Boolean,String],
+				default: false,
+			},
+			//滑动后切换中间插槽
+			centerSlidiSwitch:{
+				type: [Boolean,String],
+				default: false
+			},
+			//滑动后切换右插槽
+			rightSlidiSwitch:{
+				type: [Boolean,String],
+				default: false
+			},
+			//页面的onPageScroll
+			pageScroll:{
+				type: Object,
+				default:function(){
+				  return {}
+				} 

+			},
+			
+		},
+		created(){
+			var that = this;
+			//是否添加占位符
+			switch (that.barPlaceholder){
+				case 'show':
+					that.placeholder = true;
+					break;
+				case 'hidden':
+					that.placeholder = false;
+					break;
+				case 'auto':
+					if(that.fixed){
+						that.placeholder = true;
+					}
+					break;
+			}
+			
+			//设置状态栏文字颜色
+			that.setStatusBarFontColor();
+
+			//文字颜色
+			that.colorContainer = typeof that.color == 'object' ?  that.color : [that.color,that.color];
+			that.colorInfo = that.colorContainer[0];
+			//导航栏透明设置 及监听滚动
+			switch (that.transparent){
+				case 'show':
+					that.transparentValue = 1;
+					break;
+				case 'hidden':
+					that.transparentValue = 0;
+					break;
+				case 'auto':
+					that.setTVAuto(that.pageScroll)
+					break;
+			}
+			that.setBgColor();
+			
+			//滑动切换
+			if(that.fixed && (that.leftSlidiSwitch || that.centerSlidiSwitch || that.rightSlidiSwitch)){
+				that.doScroll(that.pageScroll);
+			}
+			
+		},
+		watch:{
+			pageScroll(val,oldVal){
+				var that = this;
+				//导航栏透明设置 及监听滚动
+				switch (that.transparent){
+					case 'show':
+						that.transparentValue = 1;
+						break;
+					case 'hidden':
+						that.transparentValue = 0;
+						break;
+					case 'auto':
+						this.setTVAuto(val)
+						break;
+				}
+				//滑动切换
+				if(that.fixed && (that.leftSlidiSwitch || that.centerSlidiSwitch || that.rightSlidiSwitch)){
+					that.doScroll(val);
+				}
+			},
+			//监控透明度变化 
+			transparentValue(val,oldVal) {
+				var that = this;
+				//this.settingColor();
+				
+				//头条小程序不支持setNavigationBarColor方法
+				// #ifndef MP-TOUTIAO || H5
+				if(oldVal > 0.8){
+					uni.setNavigationBarColor({
+						frontColor: that.statusBarFontColorInfo[1],
+						backgroundColor: that.backgroundColorRgb
+					});
+				}else if(oldVal < 0.2){
+					uni.setNavigationBarColor({
+						frontColor: that.statusBarFontColorInfo[0],
+						backgroundColor:  that.backgroundColorRgb
+					});
+				}
+				// #endif
+				
+				// #ifdef MP-TOUTIAO
+				if (tt.setNavigationBarColor) {
+				 if(oldVal > 0.8){
+				 	tt.setNavigationBarColor({
+				 	  frontColor: that.statusBarFontColorInfo[1],
+				 	  backgroundColor: that.backgroundColorRgb,
+				 	  success(res) {},
+				 	  fail(res) {}
+				 	});
+				 }else if(oldVal < 0.2){
+				 	tt.setNavigationBarColor({
+				 	    frontColor: that.statusBarFontColorInfo[0],
+				 	    backgroundColor: that.backgroundColorRgb,
+				 		success(res) {},
+				 		fail(res) {}
+				 	});
+				 }
+				} else {
+				  console.log("hx-navbar 提示:当前客户端版本过低,无法使用状态栏颜色修改功能,请升级(基础库1.40+)。")
+				}
+				// #endif
+			},
+			//监听背景颜色
+			backgroundColor(val,old){
+				var that = this;
+				that.setBgColor()
+			},
+		
+			color(val,old){
+				var that = this;
+				//文字颜色
+				/* that.colorContainer = typeof val == 'object' ?  val : [val,val];
+				that.colorInfo = that.colorContainer[0]; */
+				
+			}
+		},
+		methods: {
+			
+			onClickLeft () {
+				if(this.back){
+					if(getCurrentPages().length>1){
+						uni.navigateBack();
+					}else{
+						// #ifdef H5
+						history.back()
+						// #endif
+						// #ifndef H5
+						if(this.defaultBackUrl){
+							uni.redirectTo({
+								url:this.defaultBackUrl
+							})
+						}else{
+							if(this.backTabbarUrl){
+								uni.reLaunch({
+									url: this.backTabbarUrl
+								});
+							}
+							
+						}
+						// #endif
+					}
+					
+				}else{
+					this.$emit('click-left')
+				}
+		    },
+		    onClickRight () {
+				this.$emit('click-right')
+		    }, 
+			
+			//监听滚动后的操作
+			doScroll(e){
+				let that = this;
+				that.$emit('scroll', e);
+				if (e.scrollTop > 100) {
+					that.slotSlidiSwitch = 1;
+				} else {
+					that.slotSlidiSwitch = 0
+				}
+			},
+			//滑动渐变
+			setTVAuto(e){
+				let that = this;
+				that.$emit('scroll', e);
+				if (e.scrollTop > 100) {
+					that.transparentValue = 1;
+					that.colorInfo = that.colorContainer[1];
+				} else {
+					that.transparentValue = e.scrollTop / 100;
+					that.colorInfo = that.colorContainer[0];
+				}
+				that.setBgColor();
+			},
+			//背景颜色
+			setBgColor(){
+				
+				var that = this;
+				//如果存在背景图片则背景颜色失效
+				// if(that.backgroundImg){
+				// 	that.backgroundColorRgba = "url(" + that.backgroundImg + ")";
+				// 	return;
+				// }
+				
+				//背景颜色
+				if(typeof that.backgroundColor[0] == 'object'){
+					let l = that.backgroundColor.length;
+					if( l >= 2){
+						let rgbStr = "linear-gradient("+ that.backgroundColorLinearDeg +"deg,";
+						let c = null;
+						for(var i in that.backgroundColor){
+							c = that.backgroundColor[i];
+							rgbStr += "rgba("+ c[0] + "," + c[1] + "," + c[2] +"," + that.transparentValue+")";
+							
+							if(l != (i*1)+1){
+								rgbStr += ",";
+							}
+						}
+						rgbStr += ")"; 
+						that.backgroundColorRgba = rgbStr;
+					}
+					
+				}else{
+					let rgbStr = that.backgroundColor[0] + ','+  that.backgroundColor[1] + ','+  that.backgroundColor[2];
+					that.backgroundColorRgb= 'rgb('+ rgbStr + ')';
+					that.backgroundColorRgba = 'rgba('+ rgbStr +',' + that.transparentValue+')';
+				}
+			},
+			setStatusBarFontColor(){
+			  var that = this;
+			  if(typeof that.statusBarFontColor == 'string'){
+				that.statusBarFontColorInfo = [that.statusBarFontColor,that.statusBarFontColor];
+			  }else if(typeof that.statusBarFontColor == 'object'){
+				if (that.statusBarFontColor.length==1){
+					that.statusBarFontColorInfo = [that.statusBarFontColor[0],that.statusBarFontColor[0]];
+				}else if(that.statusBarFontColor.length>=2){
+					that.statusBarFontColorInfo = [that.statusBarFontColor[0],that.statusBarFontColor[1]];
+				}
+			  }
+			  // #ifndef MP-TOUTIAO || H5
+			  uni.setNavigationBarColor({
+				frontColor: that.statusBarFontColorInfo[0],
+				backgroundColor: that.backgroundColorRgb
+			  });
+			   // #endif
+			   
+			  // #ifdef MP-TOUTIAO
+			  if (tt.setNavigationBarColor) {
+			    tt.setNavigationBarColor({
+			      frontColor: that.statusBarFontColorInfo[0],
+			      backgroundColor: that.backgroundColorRgb
+			    });
+			  } else {
+			     console.log("hx-navbar 提示:当前客户端版本过低,无法使用状态栏颜色修改功能,请升级(基础库1.40+)。")
+			  }
+			  // #endif
+			}
+		  
+		},
+		destroyed(){
+			
+		},
+		
+		
+	}
+</script>
+
+<style lang="scss">
+	$nav-height: 44px;
+	
+	.hd{
+		overflow: hidden;
+	}
+	
+	//防止其他ui影响
+	.hx-navbar uni-view,
+	.hx-navbar uni-scroll-view,
+	.hx-navbar uni-swiper,
+	.hx-navbar uni-button,
+	.hx-navbar uni-input,
+	.hx-navbar uni-textarea,
+	.hx-navbar uni-label,
+	.hx-navbar uni-navigator,
+	.hx-navbar uni-image {
+		box-sizing: unset;
+	}
+	.hx-navbar {
+		position: relative;
+		padding-top: 0;
+		overflow: hidden;
+		
+		&__content {
+			display: block;
+			position: relative;
+			width: 100%;
+			/*background-color: $uni-bg-color*/;
+			overflow: hidden;
+			.navbgimg{
+				position: absolute;
+				top: 0;
+				left: 0;
+				z-index: 0;
+				width: 100%;
+			}
+			
+			.hx-navbar__content_view {
+				// line-height: $nav-height;
+				display: flex;
+				align-items: center;
+				
+			}
+			.hx-status-bar {
+				display: block;
+				width: 100%;
+				height: 40px;
+				height: var(--status-bar-height);
+				position: relative;
+				z-index: 1;
+			}
+		}
+	
+		&__header {
+			position: relative;
+			z-index: 1;
+			display: flex;
+			flex-direction: row;
+			width: 100%;
+			height:  $nav-height;
+			line-height: $nav-height;
+			font-size: 36upx;
+			transition: color 0.5s ease 0s;
+			&-btns {
+				display: inline-flex;
+				flex-wrap: nowrap;
+				flex-shrink: 0;
+				min-width: 54px;
+				//padding: 0 6px;
+	
+				&:first-child {
+					padding-left: 0;
+				}
+	
+				&:last-child {
+					min-width: 54px;
+				}
+	
+	    &-right:last-child{
+	     
+	      text-align: right;
+	      flex-direction: row-reverse;
+	    }
+			}
+	
+			&-container {
+				width: 100%;
+				margin: 0 10upx;
+	
+				&-inner {
+					width: 100%;
+					display: flex;
+					justify-content: center;
+					font-size: 36upx;
+					
+					// padding-right: 60upx;
+				}
+			}
+		}
+	
+		&__placeholder {
+			&-view {
+				height: $nav-height;
+			}
+		}
+	
+		&--fixed {
+			position: fixed;
+			top:0;
+			z-index: 998;
+		}
+	
+		&--shadow {
+			box-shadow: 0 2upx 12upx #ccc;
+		}
+	
+		&--border:after {
+			position: absolute;
+			z-index: 3;
+			bottom: 0;
+			left: 0;
+			right: 0;
+			height: 1px;
+			content: '';
+			-webkit-transform: scaleY(.5);
+			transform: scaleY(.5);
+			background-color: #efefef;
+		}
+	}
+	.left_back{
+		padding-left: 12upx;
+		padding-right: 12upx;
+	}
+</style>

+ 215 - 0
HX-SHOP/components/hx-preview-img/hx-preview-img.vue

@@ -0,0 +1,215 @@
+<template>
+	<view class="previewImg"  @touchmove.stop.prevent="mpClear" :animation="formAnimationData">
+		<view class="close" @click="close">
+			<text>关闭</text>
+		</view>
+		<view class="mask" >
+			
+			<swiper @change="changeSwiper"  class="my_swiper" :current="currentIndex" :circular="circular" :indicator-dots="indicatorDots" :autoplay="autoplay" :duration="duration">
+				<swiper-item v-for="(src, y) in picList" :key="y" >
+					<!-- <movable-area class="movable_box" :scale-area="true" >
+						<movable-view class="movable_view"  :scale="false" direction="all"  :scale-min="0.5" :scale-value="1" :scale-max="3" >
+							
+						</movable-view>
+					</movable-area> -->
+					<view  class="bg_img" :style="{ backgroundImage: 'url('+ src +')'}"></view>
+				</swiper-item>
+			</swiper>
+		</view>
+		<view class="pagebox" v-if="picList.length>0">{{ Number(currentIndex) + 1 }} / {{ picList.length }}</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: 'hx-preview-img',
+		props: {
+			current: {
+				type: String,
+				default: ''
+			},
+			list: {
+				type: Array,
+				default: function(){
+					return new Array();
+				}
+			},
+			//开始
+			start: {
+			    type: Number,
+				default: 0
+			},
+			
+		},
+			
+		data() {
+			return {
+				picList: [],
+				indicatorDots: false,
+				autoplay: false,
+				duration: 50,
+				circular: true,
+				currentIndex: 0,
+				isShowSwiper: false,
+				animation:{},
+				formAnimationData: {},
+			};
+		},
+		watch: {
+			list(val) {
+				
+			},
+			current(val){
+				
+			},
+			start(val,oldVal) {
+				var that = this;
+				if(val<=0){
+					this.close()
+				}else{
+					//图片预览器为显示
+					this.$emit("status",true)
+					this.picListInit();
+				}
+				
+			}
+		},
+		created() {
+			
+		},
+		methods: {
+			
+			picListInit() {
+				
+				let that = this
+				if(!this.current || !this.list){
+					return;
+				}
+				for(var i in this.list){
+					if(this.current == this.list[i]){
+						this.currentIndex = i;
+						break;
+					}
+				}
+				this.picList=this.list;
+				that.animation = uni.createAnimation({
+				  //duration: 1000,
+					timingFunction: 'ease',
+				})
+				that.animation.top(0).bottom(0).left(0).right(0).step({ duration: 0 })
+				that.animation.opacity(1).step({ duration: 300 })
+				that.formAnimationData = that.animation.export()
+				
+			},
+			changeSwiper(e) {
+				this.currentIndex = e.target.current;
+			},
+			mpClear(e) {
+				// TODO nvue 取消冒泡
+				e.stopPropagation()
+			},
+			close(){
+				
+				var that = this;
+				//图片预览器为隐藏
+				this.$emit("status",false)
+				this.animation = uni.createAnimation({
+				  //duration: 1000,
+					timingFunction: 'ease',
+				})
+				this.animation.scale(0,0).opacity(0).step({ duration: 300 })
+				this.animation.top(0).bottom(0).left("-100%").right("100%").step({ duration: 0 })
+				this.formAnimationData = this.animation.export()
+				
+			}
+			
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+.previewImg {
+	opacity: 0;
+	position: fixed;
+	top: 0;
+	right: 100%;
+	left: -100%;
+	width: 100%;
+	height: 100%;
+	z-index: 99999999;
+	
+	.close{
+		position: absolute;
+		top: calc(var(--status-bar-height) + 15px);
+		left: 15px;
+		z-index: 6;
+		color: #ffffff;
+		font-size: 14px;
+		background-color: rgba(255, 255, 255, 0.4);
+		padding: 0 9px;
+		border-radius: 4px;
+		text-align: center;
+		display: flex;
+		align-items: center;
+		height: 27px;
+
+	}
+	.pagebox{
+		position: absolute;
+		z-index: 6;
+		color: #fff;
+		bottom: 20rpx;
+		text-align: center;
+		width: 100%;
+	}
+	.mask {
+		position: absolute;
+		top: 0;
+		left: 0;
+		width: 100%;
+		height: 100%;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		background-color: #000;
+		z-index: 5;
+		.my_swiper {
+			width: 100%;
+			height: 60vh;
+			.bg_img {
+				background-size: 100% auto;
+				background-repeat: no-repeat;
+				background-position:center;
+				width: 100%;
+				height: 100%;
+			}
+			.movable_box{
+				width: 100%;
+				height: 60vh;
+				.movable_view{
+					width: 100%;
+					height: 60vh;
+					
+				}
+			
+			}
+			
+		}
+	}
+	
+	.pic_list {
+		display: flex;
+		flex-flow: row wrap;
+		> view {
+			flex: 0 0 33.3vw;
+			height: 33.3vw;
+			padding: 1vw;
+			> image {
+				width: 100%;
+				height: 100%;
+			}
+		}
+	}
+}
+
+</style>

+ 202 - 0
HX-SHOP/components/hx-share/hx-share.vue

@@ -0,0 +1,202 @@
+<template>
+	<view v-if="show" class="mask" @click="toggleMask" @touchmove.stop.prevent="stopPrevent"
+		:style="{backgroundColor: backgroundColor}"
+	>
+		<view 
+			class="mask-content"
+			@click.stop.prevent="stopPrevent"
+			:style="[{
+				height: config.height, 
+				transform: transform
+			}]"
+		>
+			<scroll-view class="view-content" scroll-y>
+				<view class="share-header">
+					分享到
+				</view>
+				<view class="share-list">
+					<view 
+						v-for="(item, index) in shareList" :key="index"
+						class="share-item" 
+						@click="shareToFriend(item.text)"
+					>
+						<image :src="item.icon" mode=""></image>
+						<text>{{item.text}}</text>
+					</view>
+				</view>
+			</scroll-view>
+			<view class="bottom b-t" @click="toggleMask">取消</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				transform: 'translateY(50vh)',
+				timer: 0,
+				backgroundColor: 'rgba(0,0,0,0)',
+				show: false,
+				config: {},
+			};
+		},
+		props:{
+			contentHeight:{
+				type: Number,
+				default: 0
+			},
+			//是否是tabbar页面
+			hasTabbar:{
+				type: Boolean,
+				default: false
+			},
+			shareList:{
+				type: Array,
+				default: function(){
+					return [];
+				}
+			}
+		},
+		created() {
+			const height = uni.upx2px(this.contentHeight) + 'px';
+			this.config = {
+				height: height,
+				transform: `translateY(${height})`,
+				backgroundColor: 'rgba(0,0,0,.4)',
+			}
+			this.transform = this.config.transform;
+		},
+		methods:{
+			toggleMask(){
+				//防止高频点击
+				if(this.timer == 1){
+					return;
+				}
+				this.timer = 1;
+				setTimeout(()=>{
+					this.timer = 0;
+				}, 500)
+				
+				if(this.show){
+					this.transform = this.config.transform;
+					this.backgroundColor = 'rgba(0,0,0,0)';
+					setTimeout(()=>{
+						this.show = false;
+						this.hasTabbar && uni.showTabBar();
+					}, 200)
+					return;
+				}
+				
+				this.show = true;
+				//等待mask重绘完成执行
+				if(this.hasTabbar){
+					uni.hideTabBar({
+						success: () => {
+							setTimeout(()=>{
+								this.backgroundColor = this.config.backgroundColor;
+								this.transform = 'translateY(0px)';
+							}, 10)
+						}
+					});
+				}else{
+					setTimeout(()=>{
+						this.backgroundColor = this.config.backgroundColor;
+						this.transform = 'translateY(0px)';
+					}, 10)
+				}
+			},
+			//防止冒泡和滚动穿透
+			stopPrevent(){},
+			//分享操作
+			shareToFriend(type){
+				this.$api.msg(`分享给${type}`);
+				this.toggleMask();
+			},
+		}
+	}
+</script>
+
+<style lang='scss'>
+	.mask{
+		position:fixed;
+		left: 0;
+		top: 0;
+		right: 0;
+		bottom: 0;
+		display:flex;
+		justify-content: center;
+		align-items: flex-end;
+		z-index: 998;
+		transition: .3s;
+		.bottom{
+			position:absolute;
+			left: 0;
+			bottom: 0;
+			display:flex;
+			justify-content: center;
+			align-items: center;
+			width: 100%;
+			height: 90upx;
+			background: #fff;
+			z-index: 9;
+			font-size: 13px;
+			color: #303133;
+		}
+	}
+	
+	.mask-content{
+		width: 100%;
+		height: 580upx;
+		transition: .3s;
+		background: #fff;
+		&.has-bottom{
+			padding-bottom: 90upx;
+		}
+		.view-content{
+			height: 100%;
+		}
+	}
+	.share-header{
+		height: 110upx;
+		font-size: 13px;
+		color: font-color-dark;
+		display:flex;
+		align-items:center;
+		justify-content: center;
+		padding-top: 10upx;
+		&:before, &:after{
+			content: '';
+			width: 240upx;
+			heighg: 0;
+			border-top: 1px solid #E4E7ED;
+			transform: scaleY(.5);
+			margin-right: 30upx;
+		}
+		 &:after{
+			 margin-left: 30upx;
+			 margin-right: 0;
+		 }
+	}
+	.share-list{
+		display:flex;
+		flex-wrap: wrap;
+	}
+	.share-item{
+		min-width: 33.33%;
+		display:flex;
+		flex-direction: column;
+		justify-content: center;
+		align-items: center;
+		height: 180upx;
+		image{
+			width: 80upx;
+			height: 80upx;
+			margin-bottom: 16upx;
+		}
+		text{
+			font-size: 12px;
+			color: #606266;
+		}
+	}
+</style>

+ 55 - 0
HX-SHOP/components/mescroll-uni/components/mescroll-down.css

@@ -0,0 +1,55 @@
+/* 下拉刷新区域 */
+.mescroll-downwarp {
+	position: absolute;
+	top: -100%;
+	left: 0;
+	width: 100%;
+	height: 100%;
+	text-align: center;
+}
+
+/* 下拉刷新--内容区,定位于区域底部 */
+.mescroll-downwarp .downwarp-content {
+	position: absolute;
+	left: 0;
+	bottom: 0;
+	width: 100%;
+	min-height: 60rpx;
+	padding: 20rpx 0;
+	text-align: center;
+}
+
+/* 下拉刷新--提示文本 */
+.mescroll-downwarp .downwarp-tip {
+	display: inline-block;
+	font-size: 28rpx;
+	vertical-align: middle;
+	margin-left: 16rpx;
+	/* color: gray; 已在style设置color,此处删去*/
+}
+
+/* 下拉刷新--旋转进度条 */
+.mescroll-downwarp .downwarp-progress {
+	display: inline-block;
+	width: 32rpx;
+	height: 32rpx;
+	border-radius: 50%;
+	border: 2rpx solid gray;
+	border-bottom-color: transparent !important; /*已在style设置border-color,此处需加 !important*/
+	vertical-align: middle;
+}
+
+/* 旋转动画 */
+.mescroll-downwarp .mescroll-rotate {
+	animation: mescrollDownRotate 0.6s linear infinite;
+}
+
+@keyframes mescrollDownRotate {
+	0% {
+		transform: rotate(0deg);
+	}
+
+	100% {
+		transform: rotate(360deg);
+	}
+}

+ 47 - 0
HX-SHOP/components/mescroll-uni/components/mescroll-down.vue

@@ -0,0 +1,47 @@
+<!-- 下拉刷新区域 -->
+<template>
+	<view v-if="mOption.use" class="mescroll-downwarp" :style="{'background-color':mescroll.optDown.bgColor,'color':mescroll.optDown.textColor}">
+		<view class="downwarp-content">
+			<view class="downwarp-progress" :class="{'mescroll-rotate': isDownLoading}" :style="{'border-color':mescroll.optDown.textColor, 'transform':downRotate}"></view>
+			<view class="downwarp-tip">{{downText}}</view>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	props: {
+		option: Object , // down的配置项
+		type: Number, // 下拉状态(inOffset:1, outOffset:2, showLoading:3, endDownScroll:4)
+		rate: Number // 下拉比率 (inOffset: rate<1; outOffset: rate>=1)
+	},
+	computed: {
+		// 支付宝小程序需写成计算属性,prop定义default仍报错
+		mOption(){
+			return this.option || {}
+		},
+		// 是否在加载中
+		isDownLoading(){
+			return this.type === 3
+		},
+		// 旋转的角度
+		downRotate(){
+			return 'rotate(' + 360 * this.rate + 'deg)'
+		},
+		// 文本提示
+		downText(){
+			switch (this.type){
+				case 1: return this.mOption.textInOffset;
+				case 2: return this.mOption.textOutOffset;
+				case 3: return this.mOption.textLoading;
+				case 4: return this.mOption.textLoading;
+				default: return this.mOption.textInOffset;
+			}
+		}
+	}
+};
+</script>
+
+<style>
+@import "./mescroll-down.css";
+</style>

+ 90 - 0
HX-SHOP/components/mescroll-uni/components/mescroll-empty.vue

@@ -0,0 +1,90 @@
+<!--空布局
+
+可作为独立的组件, 不使用mescroll的页面也能单独引入, 以便APP全局统一管理:
+import MescrollEmpty from '@/components/mescroll-uni/components/mescroll-empty.vue';
+<mescroll-empty v-if="isShowEmpty" :option="optEmpty" @emptyclick="emptyClick"></mescroll-empty>
+
+-->
+<template>
+	<view class="mescroll-empty" :class="{ 'empty-fixed': option.fixed }" :style="{ 'z-index': option.zIndex, top: option.top }">
+		<image v-if="icon" class="empty-icon" :src="icon" mode="widthFix" />
+		<view v-if="tip" class="empty-tip">{{ tip }}</view>
+		<view v-if="option.btnText" class="empty-btn" @click="emptyClick">{{ option.btnText }}</view>
+	</view>
+</template>
+
+<script>
+// 引入全局配置
+import GlobalOption from './../mescroll-uni-option.js';
+export default {
+	props: {
+		// empty的配置项: 默认为GlobalOption.up.empty
+		option: {
+			type: Object,
+			default() {
+				return {};
+			}
+		}
+	},
+	// 使用computed获取配置,用于支持option的动态配置
+	computed: {
+		// 图标
+		icon() {
+			return this.option.icon == null ? GlobalOption.up.empty.icon : this.option.icon; // 此处不使用短路求值, 用于支持传空串不显示图标
+		},
+		// 文本提示
+		tip() {
+			return this.option.tip == null ? GlobalOption.up.empty.tip : this.option.tip; // 此处不使用短路求值, 用于支持传空串不显示文本提示
+		}
+	},
+	methods: {
+		// 点击按钮
+		emptyClick() {
+			this.$emit('emptyclick');
+		}
+	}
+};
+</script>
+
+<style>
+/* 无任何数据的空布局 */
+.mescroll-empty {
+	box-sizing: border-box;
+	width: 100%;
+	padding: 100rpx 50rpx;
+	text-align: center;
+}
+
+.mescroll-empty.empty-fixed {
+	z-index: 99;
+	position: absolute; /*transform会使fixed失效,最终会降级为absolute */
+	top: 100rpx;
+	left: 0;
+}
+
+.mescroll-empty .empty-icon {
+	width: 280rpx;
+	height: 280rpx;
+}
+
+.mescroll-empty .empty-tip {
+	margin-top: 20rpx;
+	font-size: 24rpx;
+	color: gray;
+}
+
+.mescroll-empty .empty-btn {
+	display: inline-block;
+	margin-top: 40rpx;
+	min-width: 200rpx;
+	padding: 18rpx;
+	font-size: 28rpx;
+	border: 1rpx solid #e04b28;
+	border-radius: 60rpx;
+	color: #e04b28;
+}
+
+.mescroll-empty .empty-btn:active {
+	opacity: 0.75;
+}
+</style>

+ 81 - 0
HX-SHOP/components/mescroll-uni/components/mescroll-top.vue

@@ -0,0 +1,81 @@
+<!-- 回到顶部的按钮 -->
+<template>
+	<image
+		v-if="mOption.src"
+		class="mescroll-totop"
+		:class="[value ? 'mescroll-totop-in' : 'mescroll-totop-out', {'mescroll-safe-bottom': mOption.safearea}]"
+		:style="{'z-index':mOption.zIndex, 'left': left, 'right': right, 'bottom':addUnit(mOption.bottom), 'width':addUnit(mOption.width), 'border-radius':addUnit(mOption.radius)}"
+		:src="mOption.src"
+		mode="widthFix"
+		@click="toTopClick"
+	/>
+</template>
+
+<script>
+export default {
+	props: {
+		// up.toTop的配置项
+		option: Object,
+		// 是否显示
+		value: false
+	},
+	computed: {
+		// 支付宝小程序需写成计算属性,prop定义default仍报错
+		mOption(){
+			return this.option || {}
+		},
+		// 优先显示左边
+		left(){
+			return this.mOption.left ? this.addUnit(this.mOption.left) : 'auto';
+		},
+		// 右边距离 (优先显示左边)
+		right() {
+			return this.mOption.left ? 'auto' : this.addUnit(this.mOption.right);
+		}
+	},
+	methods: {
+		addUnit(num){
+			if(!num) return 0;
+			if(typeof num === 'number') return num + 'rpx';
+			return num
+		},
+		toTopClick() {
+			this.$emit('input', false); // 使v-model生效
+			this.$emit('click'); // 派发点击事件
+		}
+	}
+};
+</script>
+
+<style>
+/* 回到顶部的按钮 */
+.mescroll-totop {
+	z-index: 9990;
+	position: fixed !important; /* 加上important避免编译到H5,在多mescroll中定位失效 */
+	right: 20rpx;
+	bottom: 120rpx;
+	width: 72rpx;
+	height: auto;
+	border-radius: 50%;
+	opacity: 0;
+	transition: opacity 0.5s; /* 过渡 */
+	margin-bottom: var(--window-bottom); /* css变量 */
+}
+
+ /* 适配 iPhoneX */
+.mescroll-safe-bottom{
+	margin-bottom: calc(var(--window-bottom) + constant(safe-area-inset-bottom)); /* window-bottom + 适配 iPhoneX */
+	margin-bottom: calc(var(--window-bottom) + env(safe-area-inset-bottom));
+}
+
+/* 显示 -- 淡入 */
+.mescroll-totop-in {
+	opacity: 1;
+}
+
+/* 隐藏 -- 淡出且不接收事件*/
+.mescroll-totop-out {
+	opacity: 0;
+	pointer-events: none;
+}
+</style>

+ 46 - 0
HX-SHOP/components/mescroll-uni/components/mescroll-up.css

@@ -0,0 +1,46 @@
+/* 上拉加载区域 */
+.mescroll-upwarp {
+	min-height: 60rpx;
+	padding: 30rpx 0;
+	text-align: center;
+	clear: both;
+}
+
+/*提示文本 */
+.mescroll-upwarp .upwarp-tip,
+.mescroll-upwarp .upwarp-nodata {
+	display: inline-block;
+	font-size: 28rpx;
+	vertical-align: middle;
+	/* color: gray; 已在style设置color,此处删去*/
+}
+
+.mescroll-upwarp .upwarp-tip {
+	margin-left: 16rpx;
+}
+
+/*旋转进度条 */
+.mescroll-upwarp .upwarp-progress {
+	display: inline-block;
+	width: 32rpx;
+	height: 32rpx;
+	border-radius: 50%;
+	border: 2rpx solid gray;
+	border-bottom-color: transparent !important; /*已在style设置border-color,此处需加 !important*/
+	vertical-align: middle;
+}
+
+/* 旋转动画 */
+.mescroll-upwarp .mescroll-rotate {
+	animation: mescrollUpRotate 0.6s linear infinite;
+}
+
+@keyframes mescrollUpRotate {
+	0% {
+		transform: rotate(0deg);
+	}
+
+	100% {
+		transform: rotate(360deg);
+	}
+}

+ 39 - 0
HX-SHOP/components/mescroll-uni/components/mescroll-up.vue

@@ -0,0 +1,39 @@
+<!-- 上拉加载区域 -->
+<template>
+	<view class="mescroll-upwarp" :style="{'background-color':mescroll.optUp.bgColor,'color':mescroll.optUp.textColor}">
+		<!-- 加载中 (此处不能用v-if,否则android小程序快速上拉可能会不断触发上拉回调) -->
+		<view v-show="isUpLoading">
+			<view class="upwarp-progress mescroll-rotate" :style="{'border-color':mescroll.optUp.textColor}"></view>
+			<view class="upwarp-tip">{{ mOption.textLoading }}</view>
+		</view>
+		<!-- 无数据 -->
+		<view v-if="isUpNoMore" class="upwarp-nodata">{{ mOption.textNoMore }}</view>
+	</view>
+</template>
+
+<script>
+export default {
+	props: {
+		option: Object, // up的配置项
+		type: Number // 上拉加载的状态:0(loading前),1(loading中),2(没有更多了)
+	},
+	computed: {
+		// 支付宝小程序需写成计算属性,prop定义default仍报错
+		mOption() {
+			return this.option || {};
+		},
+		// 加载中
+		isUpLoading() {
+			return this.type === 1;
+		},
+		// 没有更多了
+		isUpNoMore() {
+			return this.type === 2;
+		}
+	}
+};
+</script>
+
+<style>
+@import './mescroll-up.css';
+</style>

+ 10 - 0
HX-SHOP/components/mescroll-uni/mescroll-body.css

@@ -0,0 +1,10 @@
+page {
+	-webkit-overflow-scrolling: touch; /* 使iOS滚动流畅 */
+}
+
+.mescroll-body {
+	position: relative; /* 下拉刷新区域相对自身定位 */
+	height: auto; /* 不可固定高度,否则overflow: hidden, 可通过设置最小高度使列表不满屏仍可下拉*/
+	overflow: hidden; /* 遮住顶部下拉刷新区域 */
+	box-sizing: border-box; /* 避免设置padding出现双滚动条的问题 */
+}

+ 292 - 0
HX-SHOP/components/mescroll-uni/mescroll-body.vue

@@ -0,0 +1,292 @@
+<template>
+	<view class="mescroll-body" :style="{'minHeight':minHeight, 'padding-top': padTop, 'padding-bottom': padBottom, 'padding-bottom': padBottomConstant, 'padding-bottom': padBottomEnv }" @touchstart="touchstartEvent" @touchmove="touchmoveEvent" @touchend="touchendEvent" @touchcancel="touchendEvent" >
+		<view class="mescroll-body-content" :style="{ transform: translateY, transition: transition }">
+			<!-- 下拉加载区域 (支付宝小程序子组件传参给子子组件仍报单项数据流的异常,暂时不通过mescroll-down组件实现)-->
+			<!-- <mescroll-down :option="mescroll.optDown" :type="downLoadType" :rate="downRate"></mescroll-down> -->
+			<view v-if="mescroll.optDown.use" class="mescroll-downwarp" :style="{'background-color':mescroll.optDown.bgColor,'color':mescroll.optDown.textColor}">
+				<view class="downwarp-content">
+					<view class="downwarp-progress" :class="{'mescroll-rotate': isDownLoading}" :style="{'border-color':mescroll.optDown.textColor, 'transform': downRotate}"></view>
+					<view class="downwarp-tip">{{downText}}</view>
+				</view>
+			</view>
+	
+			<!-- 列表内容 -->
+			<slot></slot>
+
+			<!-- 空布局 -->
+			<mescroll-empty v-if="isShowEmpty" :option="mescroll.optUp.empty" @emptyclick="emptyClick"></mescroll-empty>
+
+			<!-- 上拉加载区域 (下拉刷新时不显示, 支付宝小程序子组件传参给子子组件仍报单项数据流的异常,暂时不通过mescroll-up组件实现)-->
+			<!-- <mescroll-up v-if="mescroll.optUp.use && !isDownLoading" :option="mescroll.optUp" :type="upLoadType"></mescroll-up> -->
+			<view v-if="mescroll.optUp.use && !isDownLoading && (upLoadType === 1 || upLoadType === 2 )" class="mescroll-upwarp" :style="{'background-color':mescroll.optUp.bgColor,'color':mescroll.optUp.textColor}">
+				<!-- 加载中 (此处不能用v-if,否则android小程序快速上拉可能会不断触发上拉回调) -->
+				<view v-show="upLoadType===1">
+					<view class="upwarp-progress mescroll-rotate" :style="{'border-color':mescroll.optUp.textColor}"></view>
+					<view class="upwarp-tip">{{ mescroll.optUp.textLoading }}</view>
+				</view>
+				<!-- 无数据 -->
+				<view v-if="upLoadType===2" class="upwarp-nodata">{{ mescroll.optUp.textNoMore }}</view>
+			</view>
+		</view>
+
+		<!-- 回到顶部按钮 (fixed元素需写在transform外面,防止降级为absolute)-->
+		<mescroll-top v-model="isShowToTop" :option="mescroll.optUp.toTop" @click="toTopClick"></mescroll-top>
+	</view>
+</template>
+
+<script>
+	// 引入mescroll-uni.js,处理核心逻辑
+	import MeScroll from './mescroll-uni.js';
+	// 引入全局配置
+	import GlobalOption from './mescroll-uni-option.js';
+	// 引入空布局组件
+	import MescrollEmpty from './components/mescroll-empty.vue';
+	// 引入回到顶部组件
+	import MescrollTop from './components/mescroll-top.vue';
+	
+	export default {
+		components: {
+			MescrollEmpty,
+			MescrollTop
+		},
+		data() {
+			return {
+				mescroll: {optDown:{},optUp:{}}, // mescroll实例
+				downHight: 0, //下拉刷新: 容器高度
+				downRate: 0, // 下拉比率(inOffset: rate<1; outOffset: rate>=1)
+				downLoadType: 4, // 下拉刷新状态 (inOffset:1, outOffset:2, showLoading:3, endDownScroll:4)
+				upLoadType: 0, // 上拉加载状态:0(loading前),1(loading中),2(没有更多了)
+				isShowEmpty: false, // 是否显示空布局
+				isShowToTop: false, // 是否显示回到顶部按钮
+				windowHeight: 0, // 可使用窗口的高度
+				statusBarHeight: 0, // 状态栏高度
+				isSafearea: false // 支持安全区
+			};
+		},
+		props: {
+			down: Object, // 下拉刷新的参数配置
+			up: Object, // 上拉加载的参数配置
+			top: [String, Number], // 下拉布局往下的偏移量 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx, 百分比则相对于windowHeight)
+			topbar: Boolean, // top的偏移量是否加上状态栏高度, 默认false (使用场景:取消原生导航栏时,配置此项可自动加上状态栏高度的偏移量)
+			bottom: [String, Number], // 上拉布局往上的偏移量 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx, 百分比则相对于windowHeight)
+			safearea: Boolean, // bottom的偏移量是否加上底部安全区的距离, 默认false (需要适配iPhoneX时使用)
+			height: [String, Number] // 指定mescroll最小高度,默认windowHeight,使列表不满屏仍可下拉
+		},
+		computed: {
+			// mescroll最小高度,默认windowHeight,使列表不满屏仍可下拉
+			minHeight(){
+				return this.toPx(this.height || '100%') + 'px'
+			},
+			// 下拉布局往下偏移的距离 (px)
+			numTop() {
+				return this.toPx(this.top) + (this.topbar ? this.statusBarHeight : 0);
+			},
+			padTop() {
+				return this.numTop + 'px';
+			},
+			// 上拉布局往上偏移 (px)
+			numBottom() {
+				return this.toPx(this.bottom);
+			},
+			padBottom() {
+				return this.numBottom + 'px';
+			},
+			padBottomConstant() {
+				return this.isSafearea ? 'calc(' + this.padBottom + ' + constant(safe-area-inset-bottom))' : this.padBottom;
+			},
+			padBottomEnv() {
+				return this.isSafearea ? 'calc(' + this.padBottom + ' + env(safe-area-inset-bottom))' : this.padBottom;
+			},
+			// 是否为重置下拉的状态
+			isDownReset() {
+				return this.downLoadType === 3 || this.downLoadType === 4;
+			},
+			// 过渡
+			transition() {
+				return this.isDownReset ? 'transform 300ms' : this.downTransition;
+			},
+			translateY() {
+				return this.downHight > 0 ? 'translateY(' + this.downHight + 'px)' : ''; // transform会使fixed失效,需注意把fixed元素写在mescroll之外
+			},
+			// 是否在加载中
+			isDownLoading(){
+				return this.downLoadType === 3
+			},
+			// 旋转的角度
+			downRotate(){
+				return 'rotate(' + 360 * this.downRate + 'deg)'
+			},
+			// 文本提示
+			downText(){
+				switch (this.downLoadType){
+					case 1: return this.mescroll.optDown.textInOffset;
+					case 2: return this.mescroll.optDown.textOutOffset;
+					case 3: return this.mescroll.optDown.textLoading;
+					case 4: return this.mescroll.optDown.textLoading;
+					default: return this.mescroll.optDown.textInOffset;
+				}
+			}
+		},
+		methods: {
+			//number,rpx,upx,px,% --> px的数值
+			toPx(num) {
+				if (typeof num === 'string') {
+					if (num.indexOf('px') !== -1) {
+						if (num.indexOf('rpx') !== -1) {
+							// "10rpx"
+							num = num.replace('rpx', '');
+						} else if (num.indexOf('upx') !== -1) {
+							// "10upx"
+							num = num.replace('upx', '');
+						} else {
+							// "10px"
+							return Number(num.replace('px', ''));
+						}
+					} else if (num.indexOf('%') !== -1) {
+						// 传百分比,则相对于windowHeight,传"10%"则等于windowHeight的10%
+						let rate = Number(num.replace('%', '')) / 100;
+						return this.windowHeight * rate;
+					}
+				}
+				return num ? uni.upx2px(Number(num)) : 0;
+			},
+			//注册列表touchstart事件,用于下拉刷新
+			touchstartEvent(e) {
+				this.mescroll.touchstartEvent(e);
+			},
+			//注册列表touchmove事件,用于下拉刷新
+			touchmoveEvent(e) {
+				this.mescroll.touchmoveEvent(e);
+			},
+			//注册列表touchend事件,用于下拉刷新
+			touchendEvent(e) {
+				this.mescroll.touchendEvent(e);
+			},
+			// 点击空布局的按钮回调
+			emptyClick() {
+				this.$emit('emptyclick', this.mescroll);
+			},
+			// 点击回到顶部的按钮回调
+			toTopClick() {
+				this.mescroll.scrollTo(0, this.mescroll.optUp.toTop.duration); // 执行回到顶部
+				this.$emit('topclick', this.mescroll); // 派发点击回到顶部按钮的回调
+			}
+		},
+		// 使用created初始化mescroll对象; 如果用mounted部分css样式编译到H5会失效
+		created() {
+			let vm = this;
+
+			let diyOption = {
+				// 下拉刷新的配置
+				down: {
+					inOffset(mescroll) {
+						vm.downLoadType = 1; // 下拉的距离进入offset范围内那一刻的回调 (自定义mescroll组件时,此行不可删)
+					},
+					outOffset(mescroll) {
+						vm.downLoadType = 2; // 下拉的距离大于offset那一刻的回调 (自定义mescroll组件时,此行不可删)
+					},
+					onMoving(mescroll, rate, downHight) {
+						// 下拉过程中的回调,滑动过程一直在执行;
+						vm.downHight = downHight; // 设置下拉区域的高度 (自定义mescroll组件时,此行不可删)
+						vm.downRate = rate; //下拉比率 (inOffset: rate<1; outOffset: rate>=1)
+					},
+					showLoading(mescroll, downHight) {
+						vm.downLoadType = 3; // 显示下拉刷新进度的回调 (自定义mescroll组件时,此行不可删)
+						vm.downHight = downHight; // 设置下拉区域的高度 (自定义mescroll组件时,此行不可删)
+					},
+					endDownScroll(mescroll) {
+						vm.downLoadType = 4; // 结束下拉 (自定义mescroll组件时,此行不可删)
+						vm.downHight = 0; // 设置下拉区域的高度 (自定义mescroll组件时,此行不可删)
+					},
+					// 派发下拉刷新的回调
+					callback: function(mescroll) {
+						vm.$emit('down', mescroll);
+					}
+				},
+				// 上拉加载的配置
+				up: {
+					// 显示加载中的回调
+					showLoading() {
+						vm.upLoadType = 1;
+					},
+					// 显示无更多数据的回调
+					showNoMore() {
+						vm.upLoadType = 2;
+					},
+					// 隐藏上拉加载的回调
+					hideUpScroll() {
+						vm.upLoadType = 0;
+					},
+					// 空布局
+					empty: {
+						onShow(isShow) {
+							// 显示隐藏的回调
+							vm.isShowEmpty = isShow;
+						}
+					},
+					// 回到顶部
+					toTop: {
+						onShow(isShow) {
+							// 显示隐藏的回调
+							vm.isShowToTop = isShow;
+						}
+					},
+					// 派发上拉加载的回调
+					callback: function(mescroll) {
+						vm.$emit('up', mescroll);
+					}
+				}
+			};
+
+			MeScroll.extend(diyOption, GlobalOption); // 混入全局的配置
+			let myOption = JSON.parse(
+				JSON.stringify({
+					down: vm.down,
+					up: vm.up
+				})
+			); // 深拷贝,避免对props的影响
+			MeScroll.extend(myOption, diyOption); // 混入具体界面的配置
+
+			// 初始化MeScroll对象
+			vm.mescroll = new MeScroll(myOption, true); // 传入true,标记body为滚动区域
+			// init回调mescroll对象
+			vm.$emit('init', vm.mescroll);
+
+			// 设置高度
+			const sys = uni.getSystemInfoSync();
+			if (sys.windowHeight) vm.windowHeight = sys.windowHeight;
+			if (sys.statusBarHeight) vm.statusBarHeight = sys.statusBarHeight;
+			// 使down的bottomOffset生效
+			vm.mescroll.setBodyHeight(sys.windowHeight);
+			// mescroll-body在Android小程序下拉会卡顿,无法像mescroll-uni那样通过设置"disableScroll":true解决,只能用动画过渡缓解
+			// #ifdef MP
+			if(sys.platform == "android") vm.downTransition = 'transform 200ms'
+			// #endif
+
+			// 因为使用的是page的scroll,这里需自定义scrollTo
+			vm.mescroll.resetScrollTo((y, t) => {
+				uni.pageScrollTo({
+					scrollTop: y,
+					duration: t
+				})
+			});
+
+			// 具体的界面如果不配置up.toTop.safearea,则取本vue的safearea值
+			if(sys.platform == "ios"){
+				vm.isSafearea = vm.safearea;
+				if (vm.up && vm.up.toTop && vm.up.toTop.safearea != null) {} else {
+					vm.mescroll.optUp.toTop.safearea = vm.safearea;
+				}
+			}else{
+				vm.isSafearea = false
+				vm.mescroll.optUp.toTop.safearea = false
+			}
+		}
+	};
+</script>
+
+<style>
+	@import "./mescroll-body.css";
+	@import "./components/mescroll-down.css";
+	@import './components/mescroll-up.css';
+</style>

+ 60 - 0
HX-SHOP/components/mescroll-uni/mescroll-mixins.js

@@ -0,0 +1,60 @@
+// mescroll-body 和 mescroll-uni 通用
+
+// import MescrollUni from "./mescroll-uni.vue";
+// import MescrollBody from "./mescroll-body.vue";
+
+const MescrollMixin = {
+	// components: { // 非H5端无法通过mixin注册组件, 只能在main.js中注册全局组件或具体界面中注册
+	// 	MescrollUni,
+	// 	MescrollBody
+	// },
+	data() {
+		return {
+			mescroll: null //mescroll实例对象
+		}
+	},
+	// 注册系统自带的下拉刷新 (配置down.native为true时生效, 还需在pages配置enablePullDownRefresh:true;详请参考mescroll-native的案例)
+	onPullDownRefresh(){
+		this.mescroll && this.mescroll.onPullDownRefresh();
+	},
+	// 注册列表滚动事件,用于判定在顶部可下拉刷新,在指定位置可显示隐藏回到顶部按钮 (此方法为页面生命周期,无法在子组件中触发, 仅在mescroll-body生效)
+	onPageScroll(e) {
+		this.mescroll && this.mescroll.onPageScroll(e);
+	},
+	// 注册滚动到底部的事件,用于上拉加载 (此方法为页面生命周期,无法在子组件中触发, 仅在mescroll-body生效)
+	onReachBottom() {
+		this.mescroll && this.mescroll.onReachBottom();
+	},
+	methods: {
+		// mescroll组件初始化的回调,可获取到mescroll对象
+		mescrollInit(mescroll) {
+			this.mescroll = mescroll;
+			this.mescrollInitByRef(); // 兼容字节跳动小程序
+		},
+		// 以ref的方式初始化mescroll对象 (兼容字节跳动小程序: http://www.mescroll.com/qa.html?v=20200107#q26)
+		mescrollInitByRef() {
+			if(!this.mescroll || !this.mescroll.resetUpScroll){
+				let mescrollRef = this.$refs.mescrollRef;
+				if(mescrollRef) this.mescroll = mescrollRef.mescroll
+			}
+		},
+		// 下拉刷新的回调
+		downCallback() {
+			// mixin默认resetUpScroll
+			this.mescroll.resetUpScroll()
+		},
+		// 上拉加载的回调
+		upCallback() {
+			// mixin默认延时500自动结束加载
+			setTimeout(()=>{
+				this.mescroll.endErr();
+			}, 500)
+		}
+	},
+	mounted() {
+		this.mescrollInitByRef(); // 兼容字节跳动小程序, 避免未设置@init或@init此时未能取到ref的情况
+	}
+	
+}
+
+export default MescrollMixin;

+ 34 - 0
HX-SHOP/components/mescroll-uni/mescroll-uni-option.js

@@ -0,0 +1,34 @@
+// 全局配置
+// mescroll-body 和 mescroll-uni 通用
+const GlobalOption = {
+	down: {
+		// 其他down的配置参数也可以写,这里只展示了常用的配置:
+		textInOffset: '下拉刷新', // 下拉的距离在offset范围内的提示文本
+		textOutOffset: '释放更新', // 下拉的距离大于offset范围的提示文本
+		textLoading: '加载中 ...', // 加载中的提示文本
+		offset: 80, // 在列表顶部,下拉大于80px,松手即可触发下拉刷新的回调
+		native: false // 是否使用系统自带的下拉刷新; 默认false; 仅在mescroll-body生效 (值为true时,还需在pages配置enablePullDownRefresh:true;详请参考mescroll-native的案例)
+	},
+	up: {
+		// 其他up的配置参数也可以写,这里只展示了常用的配置:
+		textLoading: '加载中 ...', // 加载中的提示文本
+		textNoMore: '-- END --', // 没有更多数据的提示文本
+		offset: 80, // 距底部多远时,触发upCallback
+		isBounce: false, // 默认禁止橡皮筋的回弹效果, 必读事项: http://www.mescroll.com/qa.html?v=190725#q25
+		toTop: {
+			// 回到顶部按钮,需配置src才显示
+			src: "http://www.mescroll.com/img/mescroll-totop.png?v=1", // 图片路径 (建议放入static目录, 如 /static/img/mescroll-totop.png )
+			offset: 1000, // 列表滚动多少距离才显示回到顶部按钮,默认1000px
+			right: 20, // 到右边的距离, 默认20 (支持"20rpx", "20px", "20%"格式的值, 纯数字则默认单位rpx)
+			bottom: 120, // 到底部的距离, 默认120 (支持"20rpx", "20px", "20%"格式的值, 纯数字则默认单位rpx)
+			width: 72 // 回到顶部图标的宽度, 默认72 (支持"20rpx", "20px", "20%"格式的值, 纯数字则默认单位rpx)
+		},
+		empty: {
+			use: true, // 是否显示空布局
+			icon: "http://www.mescroll.com/img/mescroll-empty.png?v=1", // 图标路径 (建议放入static目录, 如 /static/img/mescroll-empty.png )
+			tip: '~ 暂无相关数据 ~' // 提示
+		}
+	}
+}
+
+export default GlobalOption

+ 29 - 0
HX-SHOP/components/mescroll-uni/mescroll-uni.css

@@ -0,0 +1,29 @@
+page {
+	height: 100%;
+	box-sizing: border-box; /* 避免设置padding出现双滚动条的问题 */
+}
+
+.mescroll-uni-warp{
+	height: 100%;
+}
+
+.mescroll-uni {
+	position: relative;
+	width: 100%;
+	height: 100%;
+	min-height: 200rpx;
+	overflow-y: auto;
+	box-sizing: border-box; /* 避免设置padding出现双滚动条的问题 */
+}
+
+/* 定位的方式固定高度 */
+.mescroll-uni-fixed{
+	z-index: 1;
+	position: fixed;
+	top: 0;
+	left: 0;
+	right: 0;
+	bottom: 0;
+	width: auto; /* 使right生效 */
+	height: auto; /* 使bottom生效 */
+}

+ 862 - 0
HX-SHOP/components/mescroll-uni/mescroll-uni.js

@@ -0,0 +1,862 @@
+/* mescroll
+ * version 1.2.5
+ * 2020-03-15 wenju
+ * http://www.mescroll.com
+ */
+
+export default function MeScroll(options, isScrollBody) {
+	let me = this;
+	me.version = '1.2.5'; // mescroll版本号
+	me.options = options || {}; // 配置
+	me.isScrollBody = isScrollBody || false; // 滚动区域是否为原生页面滚动; 默认为scroll-view
+
+	me.isDownScrolling = false; // 是否在执行下拉刷新的回调
+	me.isUpScrolling = false; // 是否在执行上拉加载的回调
+	let hasDownCallback = me.options.down && me.options.down.callback; // 是否配置了down的callback
+
+	// 初始化下拉刷新
+	me.initDownScroll();
+	// 初始化上拉加载,则初始化
+	me.initUpScroll();
+
+	// 自动加载
+	setTimeout(function() { // 待主线程执行完毕再执行,避免new MeScroll未初始化,在回调获取不到mescroll的实例
+		// 自动触发下拉刷新 (只有配置了down的callback才自动触发下拉刷新)
+		if (me.optDown.use && me.optDown.auto && hasDownCallback) {
+			if (me.optDown.autoShowLoading) {
+				me.triggerDownScroll(); // 显示下拉进度,执行下拉回调
+			} else {
+				me.optDown.callback && me.optDown.callback(me); // 不显示下拉进度,直接执行下拉回调
+			}
+		}
+		// 自动触发上拉加载
+		setTimeout(function(){ // 延时确保先执行down的callback,再执行up的callback,因为部分小程序emit是异步,会导致isUpAutoLoad判断有误
+			me.optUp.use && me.optUp.auto && !me.isUpAutoLoad && me.triggerUpScroll();
+		},100)
+	}, 30); // 需让me.optDown.inited和me.optUp.inited先执行
+}
+
+/* 配置参数:下拉刷新 */
+MeScroll.prototype.extendDownScroll = function(optDown) {
+	// 下拉刷新的配置
+	MeScroll.extend(optDown, {
+		use: true, // 是否启用下拉刷新; 默认true
+		auto: true, // 是否在初始化完毕之后自动执行下拉刷新的回调; 默认true
+		native: false, // 是否使用系统自带的下拉刷新; 默认false; 仅mescroll-body生效 (值为true时,还需在pages配置enablePullDownRefresh:true;详请参考mescroll-native的案例)
+		autoShowLoading: false, // 如果设置auto=true(在初始化完毕之后自动执行下拉刷新的回调),那么是否显示下拉刷新的进度; 默认false
+		isLock: false, // 是否锁定下拉刷新,默认false;
+		offset: 80, // 在列表顶部,下拉大于80px,松手即可触发下拉刷新的回调
+		startTop: 100, // scroll-view滚动到顶部时,此时的scroll-top不一定为0, 此值用于控制最大的误差
+		fps: 80, // 下拉节流 (值越大每秒刷新频率越高)
+		inOffsetRate: 1, // 在列表顶部,下拉的距离小于offset时,改变下拉区域高度比例;值小于1且越接近0,高度变化越小,表现为越往下越难拉
+		outOffsetRate: 0.2, // 在列表顶部,下拉的距离大于offset时,改变下拉区域高度比例;值小于1且越接近0,高度变化越小,表现为越往下越难拉
+		bottomOffset: 20, // 当手指touchmove位置在距离body底部20px范围内的时候结束上拉刷新,避免Webview嵌套导致touchend事件不执行
+		minAngle: 45, // 向下滑动最少偏移的角度,取值区间  [0,90];默认45度,即向下滑动的角度大于45度则触发下拉;而小于45度,将不触发下拉,避免与左右滑动的轮播等组件冲突;
+		textInOffset: '下拉刷新', // 下拉的距离在offset范围内的提示文本
+		textOutOffset: '释放更新', // 下拉的距离大于offset范围的提示文本
+		textLoading: '加载中 ...', // 加载中的提示文本
+		bgColor: "transparent", // 背景颜色 (建议在pages.json中再设置一下backgroundColorTop)
+		textColor: "gray", // 文本颜色 (当bgColor配置了颜色,而textColor未配置时,则textColor会默认为白色)
+		inited: null, // 下拉刷新初始化完毕的回调
+		inOffset: null, // 下拉的距离进入offset范围内那一刻的回调
+		outOffset: null, // 下拉的距离大于offset那一刻的回调
+		onMoving: null, // 下拉过程中的回调,滑动过程一直在执行; rate下拉区域当前高度与指定距离的比值(inOffset: rate<1; outOffset: rate>=1); downHight当前下拉区域的高度
+		beforeLoading: null, // 准备触发下拉刷新的回调: 如果return true,将不触发showLoading和callback回调; 常用来完全自定义下拉刷新, 参考案例【淘宝 v6.8.0】
+		showLoading: null, // 显示下拉刷新进度的回调
+		afterLoading: null, // 准备结束下拉的回调. 返回结束下拉的延时执行时间,默认0ms; 常用于结束下拉之前再显示另外一小段动画,才去隐藏下拉刷新的场景, 参考案例【dotJump】
+		endDownScroll: null, // 结束下拉刷新的回调
+		callback: function(mescroll) {
+			// 下拉刷新的回调;默认重置上拉加载列表为第一页
+			mescroll.resetUpScroll();
+		}
+	})
+}
+
+/* 配置参数:上拉加载 */
+MeScroll.prototype.extendUpScroll = function(optUp) {
+	// 上拉加载的配置
+	MeScroll.extend(optUp, {
+		use: true, // 是否启用上拉加载; 默认true
+		auto: true, // 是否在初始化完毕之后自动执行上拉加载的回调; 默认true
+		isLock: false, // 是否锁定上拉加载,默认false;
+		isBoth: true, // 上拉加载时,如果滑动到列表顶部是否可以同时触发下拉刷新;默认true,两者可同时触发;
+		isBounce: false, // 默认禁止橡皮筋的回弹效果, 必读事项: http://www.mescroll.com/qa.html?v=190725#q25
+		callback: null, // 上拉加载的回调;function(page,mescroll){ }
+		page: {
+			num: 0, // 当前页码,默认0,回调之前会加1,即callback(page)会从1开始
+			size: 10, // 每页数据的数量
+			time: null // 加载第一页数据服务器返回的时间; 防止用户翻页时,后台新增了数据从而导致下一页数据重复;
+		},
+		noMoreSize: 5, // 如果列表已无数据,可设置列表的总数量要大于等于5条才显示无更多数据;避免列表数据过少(比如只有一条数据),显示无更多数据会不好看
+		offset: 80, // 距底部多远时,触发upCallback
+		textLoading: '加载中 ...', // 加载中的提示文本
+		textNoMore: '-- END --', // 没有更多数据的提示文本
+		bgColor: "transparent", // 背景颜色 (建议在pages.json中再设置一下backgroundColorBottom)
+		textColor: "gray", // 文本颜色 (当bgColor配置了颜色,而textColor未配置时,则textColor会默认为白色)
+		inited: null, // 初始化完毕的回调
+		showLoading: null, // 显示加载中的回调
+		showNoMore: null, // 显示无更多数据的回调
+		hideUpScroll: null, // 隐藏上拉加载的回调
+		errDistance: 60, // endErr的时候需往上滑动一段距离,使其往下滑动时再次触发onReachBottom,仅mescroll-body生效
+		toTop: {
+			// 回到顶部按钮,需配置src才显示
+			src: null, // 图片路径,默认null (绝对路径或网络图)
+			offset: 1000, // 列表滚动多少距离才显示回到顶部按钮,默认1000
+			duration: 300, // 回到顶部的动画时长,默认300ms (当值为0或300则使用系统自带回到顶部,更流畅; 其他值则通过step模拟,部分机型可能不够流畅,所以非特殊情况不建议修改此项)
+			btnClick: null, // 点击按钮的回调
+			onShow: null, // 是否显示的回调
+			zIndex: 9990, // fixed定位z-index值
+			left: null, // 到左边的距离, 默认null. 此项有值时,right不生效. (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx)
+			right: 20, // 到右边的距离, 默认20 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx)
+			bottom: 120, // 到底部的距离, 默认120 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx)
+			safearea: false, // bottom的偏移量是否加上底部安全区的距离, 默认false, 需要适配iPhoneX时使用 (具体的界面如果不配置此项,则取本vue的safearea值)
+			width: 72, // 回到顶部图标的宽度, 默认72 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx)
+			radius: "50%" // 圆角, 默认"50%" (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx)
+		},
+		empty: {
+			use: true, // 是否显示空布局
+			icon: null, // 图标路径
+			tip: '~ 暂无相关数据 ~', // 提示
+			btnText: '', // 按钮
+			btnClick: null, // 点击按钮的回调
+			onShow: null, // 是否显示的回调
+			fixed: false, // 是否使用fixed定位,默认false; 配置fixed为true,以下的top和zIndex才生效 (transform会使fixed失效,最终会降级为absolute)
+			top: "100rpx", // fixed定位的top值 (完整的单位值,如 "10%"; "100rpx")
+			zIndex: 99 // fixed定位z-index值
+		},
+		onScroll: false // 是否监听滚动事件
+	})
+}
+
+/* 配置参数 */
+MeScroll.extend = function(userOption, defaultOption) {
+	if (!userOption) return defaultOption;
+	for (let key in defaultOption) {
+		if (userOption[key] == null) {
+			let def = defaultOption[key];
+			if (def != null && typeof def === 'object') {
+				userOption[key] = MeScroll.extend({}, def); // 深度匹配
+			} else {
+				userOption[key] = def;
+			}
+		} else if (typeof userOption[key] === 'object') {
+			MeScroll.extend(userOption[key], defaultOption[key]); // 深度匹配
+		}
+	}
+	return userOption;
+}
+
+/* 简单判断是否配置了颜色 (非透明,非白色) */
+MeScroll.prototype.hasColor = function(color) {
+	if(!color) return false;
+	let c = color.toLowerCase();
+	return c != "#fff" && c != "#ffffff" && c != "transparent" && c != "white"
+}
+
+/* -------初始化下拉刷新------- */
+MeScroll.prototype.initDownScroll = function() {
+	let me = this;
+	// 配置参数
+	me.optDown = me.options.down || {};
+	if(!me.optDown.textColor && me.hasColor(me.optDown.bgColor)) me.optDown.textColor = "#fff"; // 当bgColor有值且textColor未设置,则textColor默认白色
+	me.extendDownScroll(me.optDown);
+	
+	// 如果是mescroll-body且配置了native,则禁止自定义的下拉刷新
+	if(me.isScrollBody && me.optDown.native){
+		me.optDown.use = false
+	}else{
+		me.optDown.native = false // 仅mescroll-body支持,mescroll-uni不支持
+	}
+	
+	me.downHight = 0; // 下拉区域的高度
+
+	// 在页面中加入下拉布局
+	if (me.optDown.use && me.optDown.inited) {
+		// 初始化完毕的回调
+		setTimeout(function() { // 待主线程执行完毕再执行,避免new MeScroll未初始化,在回调获取不到mescroll的实例
+			me.optDown.inited(me);
+		}, 0)
+	}
+}
+
+/* 列表touchstart事件 */
+MeScroll.prototype.touchstartEvent = function(e) {
+	if (!this.optDown.use) return;
+
+	this.startPoint = this.getPoint(e); // 记录起点
+	this.startTop = this.getScrollTop(); // 记录此时的滚动条位置
+	this.lastPoint = this.startPoint; // 重置上次move的点
+	this.maxTouchmoveY = this.getBodyHeight() - this.optDown.bottomOffset; // 手指触摸的最大范围(写在touchstart避免body获取高度为0的情况)
+	this.inTouchend = false; // 标记不是touchend
+}
+
+/* 列表touchmove事件 */
+MeScroll.prototype.touchmoveEvent = function(e) {
+	// #ifdef H5
+	window.isPreventDefault = false // 标记不需要阻止window事件
+	// #endif
+	
+	if (!this.optDown.use) return;
+	if (!this.startPoint) return;
+	let me = this;
+
+	// 节流
+	let t = new Date().getTime();
+	if (me.moveTime && t - me.moveTime < me.moveTimeDiff) { // 小于节流时间,则不处理
+		return;
+	} else {
+		me.moveTime = t
+		if(!me.moveTimeDiff) me.moveTimeDiff = 1000 / me.optDown.fps
+	}
+
+	let scrollTop = me.getScrollTop(); // 当前滚动条的距离
+	let curPoint = me.getPoint(e); // 当前点
+
+	let moveY = curPoint.y - me.startPoint.y; // 和起点比,移动的距离,大于0向下拉,小于0向上拉
+
+	// 向下拉 && 在顶部
+	// mescroll-body,直接判定在顶部即可
+	// scroll-view在滚动时不会触发touchmove,当触顶/底/左/右时,才会触发touchmove
+	// scroll-view滚动到顶部时,scrollTop不一定为0; 在iOS的APP中scrollTop可能为负数,不一定和startTop相等
+	if (moveY > 0 && (
+			(me.isScrollBody && scrollTop <= 0)
+			||
+			(!me.isScrollBody && (scrollTop <= 0 || (scrollTop <= me.optDown.startTop && scrollTop === me.startTop)) )
+		)) {
+		// 可下拉的条件
+		if (!me.inTouchend && !me.isDownScrolling && !me.optDown.isLock && (!me.isUpScrolling || (me.isUpScrolling &&
+				me.optUp.isBoth))) {
+
+			// 下拉的角度是否在配置的范围内
+			let angle = me.getAngle(me.lastPoint, curPoint); // 两点之间的角度,区间 [0,90]
+			if (angle < me.optDown.minAngle) return; // 如果小于配置的角度,则不往下执行下拉刷新
+
+			// 如果手指的位置超过配置的距离,则提前结束下拉,避免Webview嵌套导致touchend无法触发
+			if (me.maxTouchmoveY > 0 && curPoint.y >= me.maxTouchmoveY) {
+				me.inTouchend = true; // 标记执行touchend
+				me.touchendEvent(); // 提前触发touchend
+				return;
+			}
+			
+			// #ifdef H5
+			window.isPreventDefault = true // 标记阻止window事件
+			// #endif
+			me.preventDefault(e); // 阻止默认事件
+
+			let diff = curPoint.y - me.lastPoint.y; // 和上次比,移动的距离 (大于0向下,小于0向上)
+
+			// 下拉距离  < 指定距离
+			if (me.downHight < me.optDown.offset) {
+				if (me.movetype !== 1) {
+					me.movetype = 1; // 加入标记,保证只执行一次
+					me.optDown.inOffset && me.optDown.inOffset(me); // 进入指定距离范围内那一刻的回调,只执行一次
+					me.isMoveDown = true; // 标记下拉区域高度改变,在touchend重置回来
+				}
+				me.downHight += diff * me.optDown.inOffsetRate; // 越往下,高度变化越小
+
+				// 指定距离  <= 下拉距离
+			} else {
+				if (me.movetype !== 2) {
+					me.movetype = 2; // 加入标记,保证只执行一次
+					me.optDown.outOffset && me.optDown.outOffset(me); // 下拉超过指定距离那一刻的回调,只执行一次
+					me.isMoveDown = true; // 标记下拉区域高度改变,在touchend重置回来
+				}
+				if (diff > 0) { // 向下拉
+					me.downHight += Math.round(diff * me.optDown.outOffsetRate); // 越往下,高度变化越小
+				} else { // 向上收
+					me.downHight += diff; // 向上收回高度,则向上滑多少收多少高度
+				}
+			}
+
+			let rate = me.downHight / me.optDown.offset; // 下拉区域当前高度与指定距离的比值
+			me.optDown.onMoving && me.optDown.onMoving(me, rate, me.downHight); // 下拉过程中的回调,一直在执行
+		}
+	}
+
+	me.lastPoint = curPoint; // 记录本次移动的点
+}
+
+/* 列表touchend事件 */
+MeScroll.prototype.touchendEvent = function(e) {
+	if (!this.optDown.use) return;
+	// 如果下拉区域高度已改变,则需重置回来
+	if (this.isMoveDown) {
+		if (this.downHight >= this.optDown.offset) {
+			// 符合触发刷新的条件
+			this.triggerDownScroll();
+		} else {
+			// 不符合的话 则重置
+			this.downHight = 0;
+			this.optDown.endDownScroll && this.optDown.endDownScroll(this);
+		}
+		this.movetype = 0;
+		this.isMoveDown = false;
+	} else if (!this.isScrollBody && this.getScrollTop() === this.startTop) { // scroll-view到顶/左/右/底的滑动事件
+		let isScrollUp = this.getPoint(e).y - this.startPoint.y < 0; // 和起点比,移动的距离,大于0向下拉,小于0向上拉
+		// 上滑
+		if (isScrollUp) {
+			// 需检查滑动的角度
+			let angle = this.getAngle(this.getPoint(e), this.startPoint); // 两点之间的角度,区间 [0,90]
+			if (angle > 80) {
+				// 检查并触发上拉
+				this.triggerUpScroll(true);
+			}
+		}
+	}
+}
+
+/* 根据点击滑动事件获取第一个手指的坐标 */
+MeScroll.prototype.getPoint = function(e) {
+	if (!e) {
+		return {
+			x: 0,
+			y: 0
+		}
+	}
+	if (e.touches && e.touches[0]) {
+		return {
+			x: e.touches[0].pageX,
+			y: e.touches[0].pageY
+		}
+	} else if (e.changedTouches && e.changedTouches[0]) {
+		return {
+			x: e.changedTouches[0].pageX,
+			y: e.changedTouches[0].pageY
+		}
+	} else {
+		return {
+			x: e.clientX,
+			y: e.clientY
+		}
+	}
+}
+
+/* 计算两点之间的角度: 区间 [0,90]*/
+MeScroll.prototype.getAngle = function(p1, p2) {
+	let x = Math.abs(p1.x - p2.x);
+	let y = Math.abs(p1.y - p2.y);
+	let z = Math.sqrt(x * x + y * y);
+	let angle = 0;
+	if (z !== 0) {
+		angle = Math.asin(y / z) / Math.PI * 180;
+	}
+	return angle
+}
+
+/* 触发下拉刷新 */
+MeScroll.prototype.triggerDownScroll = function() {
+	if (this.optDown.beforeLoading && this.optDown.beforeLoading(this)) {
+		//return true则处于完全自定义状态
+	} else {
+		this.showDownScroll(); // 下拉刷新中...
+		this.optDown.callback && this.optDown.callback(this); // 执行回调,联网加载数据
+	}
+}
+
+/* 显示下拉进度布局 */
+MeScroll.prototype.showDownScroll = function() {
+	this.isDownScrolling = true; // 标记下拉中
+	if (this.optDown.native) {
+		uni.startPullDownRefresh(); // 系统自带的下拉刷新
+		this.optDown.showLoading && this.optDown.showLoading(this, 0); // 仍触发showLoading,因为上拉加载用到
+	} else{
+		this.downHight = this.optDown.offset; // 更新下拉区域高度
+		this.optDown.showLoading && this.optDown.showLoading(this, this.downHight); // 下拉刷新中...
+	}
+}
+
+/* 显示系统自带的下拉刷新时需要处理的业务 */
+MeScroll.prototype.onPullDownRefresh = function() {
+	this.isDownScrolling = true; // 标记下拉中
+	this.optDown.showLoading && this.optDown.showLoading(this, 0); // 仍触发showLoading,因为上拉加载用到
+	this.optDown.callback && this.optDown.callback(this); // 执行回调,联网加载数据
+}
+
+/* 结束下拉刷新 */
+MeScroll.prototype.endDownScroll = function() {
+	if (this.optDown.native) { // 结束原生下拉刷新
+		this.isDownScrolling = false;
+		this.optDown.endDownScroll && this.optDown.endDownScroll(this);
+		uni.stopPullDownRefresh();
+		return
+	}
+	let me = this;
+	// 结束下拉刷新的方法
+	let endScroll = function() {
+		me.downHight = 0;
+		me.isDownScrolling = false;
+		me.optDown.endDownScroll && me.optDown.endDownScroll(me);
+		!me.isScrollBody && me.setScrollHeight(0) // scroll-view重置滚动区域,使数据不满屏时仍可检查触发翻页
+	}
+	// 结束下拉刷新时的回调
+	let delay = 0;
+	if (me.optDown.afterLoading) delay = me.optDown.afterLoading(me); // 结束下拉刷新的延时,单位ms
+	if (typeof delay === 'number' && delay > 0) {
+		setTimeout(endScroll, delay);
+	} else {
+		endScroll();
+	}
+}
+
+/* 锁定下拉刷新:isLock=ture,null锁定;isLock=false解锁 */
+MeScroll.prototype.lockDownScroll = function(isLock) {
+	if (isLock == null) isLock = true;
+	this.optDown.isLock = isLock;
+}
+
+/* 锁定上拉加载:isLock=ture,null锁定;isLock=false解锁 */
+MeScroll.prototype.lockUpScroll = function(isLock) {
+	if (isLock == null) isLock = true;
+	this.optUp.isLock = isLock;
+}
+
+/* -------初始化上拉加载------- */
+MeScroll.prototype.initUpScroll = function() {
+	let me = this;
+	// 配置参数
+	me.optUp = me.options.up || {use: false}
+	if(!me.optUp.textColor && me.hasColor(me.optUp.bgColor)) me.optUp.textColor = "#fff"; // 当bgColor有值且textColor未设置,则textColor默认白色
+	me.extendUpScroll(me.optUp);
+
+	if (!me.optUp.isBounce) me.setBounce(false); // 不允许bounce时,需禁止window的touchmove事件
+
+	if (me.optUp.use === false) return; // 配置不使用上拉加载时,则不初始化上拉布局
+	me.optUp.hasNext = true; // 如果使用上拉,则默认有下一页
+	me.startNum = me.optUp.page.num + 1; // 记录page开始的页码
+
+	// 初始化完毕的回调
+	if (me.optUp.inited) {
+		setTimeout(function() { // 待主线程执行完毕再执行,避免new MeScroll未初始化,在回调获取不到mescroll的实例
+			me.optUp.inited(me);
+		}, 0)
+	}
+}
+
+/*滚动到底部的事件 (仅mescroll-body生效)*/
+MeScroll.prototype.onReachBottom = function() {
+	if (this.isScrollBody && !this.isUpScrolling) { // 只能支持下拉刷新的时候同时可以触发上拉加载,否则滚动到底部就需要上滑一点才能触发onReachBottom
+		if (!this.optUp.isLock && this.optUp.hasNext) {
+			this.triggerUpScroll();
+		}
+	}
+}
+
+/*列表滚动事件 (仅mescroll-body生效)*/
+MeScroll.prototype.onPageScroll = function(e) {
+	if (!this.isScrollBody) return;
+	
+	// 更新滚动条的位置 (主要用于判断下拉刷新时,滚动条是否在顶部)
+	this.setScrollTop(e.scrollTop);
+
+	// 顶部按钮的显示隐藏
+	if (e.scrollTop >= this.optUp.toTop.offset) {
+		this.showTopBtn();
+	} else {
+		this.hideTopBtn();
+	}
+}
+
+/*列表滚动事件*/
+MeScroll.prototype.scroll = function(e, onScroll) {
+	// 更新滚动条的位置
+	this.setScrollTop(e.scrollTop);
+	// 更新滚动内容高度
+	this.setScrollHeight(e.scrollHeight);
+
+	// 向上滑还是向下滑动
+	if (this.preScrollY == null) this.preScrollY = 0;
+	this.isScrollUp = e.scrollTop - this.preScrollY > 0;
+	this.preScrollY = e.scrollTop;
+
+	// 上滑 && 检查并触发上拉
+	this.isScrollUp && this.triggerUpScroll(true);
+
+	// 顶部按钮的显示隐藏
+	if (e.scrollTop >= this.optUp.toTop.offset) {
+		this.showTopBtn();
+	} else {
+		this.hideTopBtn();
+	}
+
+	// 滑动监听
+	this.optUp.onScroll && onScroll && onScroll()
+}
+
+/* 触发上拉加载 */
+MeScroll.prototype.triggerUpScroll = function(isCheck) {
+	if (!this.isUpScrolling && this.optUp.use && this.optUp.callback) {
+		// 是否校验在底部; 默认不校验
+		if (isCheck === true) {
+			let canUp = false;
+			// 还有下一页 && 没有锁定 && 不在下拉中
+			if (this.optUp.hasNext && !this.optUp.isLock && !this.isDownScrolling) {
+				if (this.getScrollBottom() <= this.optUp.offset) { // 到底部
+					canUp = true; // 标记可上拉
+				}
+			}
+			if (canUp === false) return;
+		}
+		this.showUpScroll(); // 上拉加载中...
+		this.optUp.page.num++; // 预先加一页,如果失败则减回
+		this.isUpAutoLoad = true; // 标记上拉已经自动执行过,避免初始化时多次触发上拉回调
+		this.num = this.optUp.page.num; // 把最新的页数赋值在mescroll上,避免对page的影响
+		this.size = this.optUp.page.size; // 把最新的页码赋值在mescroll上,避免对page的影响
+		this.time = this.optUp.page.time; // 把最新的页码赋值在mescroll上,避免对page的影响
+		this.optUp.callback(this); // 执行回调,联网加载数据
+	}
+}
+
+/* 显示上拉加载中 */
+MeScroll.prototype.showUpScroll = function() {
+	this.isUpScrolling = true; // 标记上拉加载中
+	this.optUp.showLoading && this.optUp.showLoading(this); // 回调
+}
+
+/* 显示上拉无更多数据 */
+MeScroll.prototype.showNoMore = function() {
+	this.optUp.hasNext = false; // 标记无更多数据
+	this.optUp.showNoMore && this.optUp.showNoMore(this); // 回调
+}
+
+/* 隐藏上拉区域**/
+MeScroll.prototype.hideUpScroll = function() {
+	this.optUp.hideUpScroll && this.optUp.hideUpScroll(this); // 回调
+}
+
+/* 结束上拉加载 */
+MeScroll.prototype.endUpScroll = function(isShowNoMore) {
+	if (isShowNoMore != null) { // isShowNoMore=null,不处理下拉状态,下拉刷新的时候调用
+		if (isShowNoMore) {
+			this.showNoMore(); // isShowNoMore=true,显示无更多数据
+		} else {
+			this.hideUpScroll(); // isShowNoMore=false,隐藏上拉加载
+		}
+	}
+	this.isUpScrolling = false; // 标记结束上拉加载
+}
+
+/* 重置上拉加载列表为第一页
+ *isShowLoading 是否显示进度布局;
+ * 1.默认null,不传参,则显示上拉加载的进度布局
+ * 2.传参true, 则显示下拉刷新的进度布局
+ * 3.传参false,则不显示上拉和下拉的进度 (常用于静默更新列表数据)
+ */
+MeScroll.prototype.resetUpScroll = function(isShowLoading) {
+	if (this.optUp && this.optUp.use) {
+		let page = this.optUp.page;
+		this.prePageNum = page.num; // 缓存重置前的页码,加载失败可退回
+		this.prePageTime = page.time; // 缓存重置前的时间,加载失败可退回
+		page.num = this.startNum; // 重置为第一页
+		page.time = null; // 重置时间为空
+		if (!this.isDownScrolling && isShowLoading !== false) { // 如果不是下拉刷新触发的resetUpScroll并且不配置列表静默更新,则显示进度;
+			if (isShowLoading == null) {
+				this.removeEmpty(); // 移除空布局
+				this.showUpScroll(); // 不传参,默认显示上拉加载的进度布局
+			} else {
+				this.showDownScroll(); // 传true,显示下拉刷新的进度布局,不清空列表
+			}
+		}
+		this.isUpAutoLoad = true; // 标记上拉已经自动执行过,避免初始化时多次触发上拉回调
+		this.num = page.num; // 把最新的页数赋值在mescroll上,避免对page的影响
+		this.size = page.size; // 把最新的页码赋值在mescroll上,避免对page的影响
+		this.time = page.time; // 把最新的页码赋值在mescroll上,避免对page的影响
+		this.optUp.callback && this.optUp.callback(this); // 执行上拉回调
+	}
+}
+
+/* 设置page.num的值 */
+MeScroll.prototype.setPageNum = function(num) {
+	this.optUp.page.num = num - 1;
+}
+
+/* 设置page.size的值 */
+MeScroll.prototype.setPageSize = function(size) {
+	this.optUp.page.size = size;
+}
+
+/* 联网回调成功,结束下拉刷新和上拉加载
+ * dataSize: 当前页的数据量(必传)
+ * totalPage: 总页数(必传)
+ * systime: 服务器时间 (可空)
+ */
+MeScroll.prototype.endByPage = function(dataSize, totalPage, systime) {
+	let hasNext;
+	if (this.optUp.use && totalPage != null) hasNext = this.optUp.page.num < totalPage; // 是否还有下一页
+	this.endSuccess(dataSize, hasNext, systime);
+}
+
+/* 联网回调成功,结束下拉刷新和上拉加载
+ * dataSize: 当前页的数据量(必传)
+ * totalSize: 列表所有数据总数量(必传)
+ * systime: 服务器时间 (可空)
+ */
+MeScroll.prototype.endBySize = function(dataSize, totalSize, systime) {
+	let hasNext;
+	if (this.optUp.use && totalSize != null) {
+		let loadSize = (this.optUp.page.num - 1) * this.optUp.page.size + dataSize; // 已加载的数据总数
+		hasNext = loadSize < totalSize; // 是否还有下一页
+	}
+	this.endSuccess(dataSize, hasNext, systime);
+}
+
+/* 联网回调成功,结束下拉刷新和上拉加载
+ * dataSize: 当前页的数据个数(不是所有页的数据总和),用于上拉加载判断是否还有下一页.如果不传,则会判断还有下一页
+ * hasNext: 是否还有下一页,布尔类型;用来解决这个小问题:比如列表共有20条数据,每页加载10条,共2页.如果只根据dataSize判断,则需翻到第三页才会知道无更多数据,如果传了hasNext,则翻到第二页即可显示无更多数据.
+ * systime: 服务器时间(可空);用来解决这个小问题:当准备翻下一页时,数据库新增了几条记录,此时翻下一页,前面的几条数据会和上一页的重复;这里传入了systime,那么upCallback的page.time就会有值,把page.time传给服务器,让后台过滤新加入的那几条记录
+ */
+MeScroll.prototype.endSuccess = function(dataSize, hasNext, systime) {
+	let me = this;
+	// 结束下拉刷新
+	if (me.isDownScrolling) me.endDownScroll();
+
+	// 结束上拉加载
+	if (me.optUp.use) {
+		let isShowNoMore; // 是否已无更多数据
+		if (dataSize != null) {
+			let pageNum = me.optUp.page.num; // 当前页码
+			let pageSize = me.optUp.page.size; // 每页长度
+			// 如果是第一页
+			if (pageNum === 1) {
+				if (systime) me.optUp.page.time = systime; // 设置加载列表数据第一页的时间
+			}
+			if (dataSize < pageSize || hasNext === false) {
+				// 返回的数据不满一页时,则说明已无更多数据
+				me.optUp.hasNext = false;
+				if (dataSize === 0 && pageNum === 1) {
+					// 如果第一页无任何数据且配置了空布局
+					isShowNoMore = false;
+					me.showEmpty();
+				} else {
+					// 总列表数少于配置的数量,则不显示无更多数据
+					let allDataSize = (pageNum - 1) * pageSize + dataSize;
+					if (allDataSize < me.optUp.noMoreSize) {
+						isShowNoMore = false;
+					} else {
+						isShowNoMore = true;
+					}
+					me.removeEmpty(); // 移除空布局
+				}
+			} else {
+				// 还有下一页
+				isShowNoMore = false;
+				me.optUp.hasNext = true;
+				me.removeEmpty(); // 移除空布局
+			}
+		}
+
+		// 隐藏上拉
+		me.endUpScroll(isShowNoMore);
+	}
+}
+
+/* 回调失败,结束下拉刷新和上拉加载 */
+MeScroll.prototype.endErr = function(errDistance) {
+	// 结束下拉,回调失败重置回原来的页码和时间
+	if (this.isDownScrolling) {
+		let page = this.optUp.page;
+		if (page && this.prePageNum) {
+			page.num = this.prePageNum;
+			page.time = this.prePageTime;
+		}
+		this.endDownScroll();
+	}
+	// 结束上拉,回调失败重置回原来的页码
+	if (this.isUpScrolling) {
+		this.optUp.page.num--;
+		this.endUpScroll(false);
+		// 如果是mescroll-body,则需往回滚一定距离
+		if(this.isScrollBody && errDistance !== 0){ // 不处理0
+			if(!errDistance) errDistance = this.optUp.errDistance; // 不传,则取默认
+			this.scrollTo(this.getScrollTop() - errDistance, 0) // 往上回滚的距离
+		}
+	}
+}
+
+/* 显示空布局 */
+MeScroll.prototype.showEmpty = function() {
+	this.optUp.empty.use && this.optUp.empty.onShow && this.optUp.empty.onShow(true)
+}
+
+/* 移除空布局 */
+MeScroll.prototype.removeEmpty = function() {
+	this.optUp.empty.use && this.optUp.empty.onShow && this.optUp.empty.onShow(false)
+}
+
+/* 显示回到顶部的按钮 */
+MeScroll.prototype.showTopBtn = function() {
+	if (!this.topBtnShow) {
+		this.topBtnShow = true;
+		this.optUp.toTop.onShow && this.optUp.toTop.onShow(true);
+	}
+}
+
+/* 隐藏回到顶部的按钮 */
+MeScroll.prototype.hideTopBtn = function() {
+	if (this.topBtnShow) {
+		this.topBtnShow = false;
+		this.optUp.toTop.onShow && this.optUp.toTop.onShow(false);
+	}
+}
+
+/* 获取滚动条的位置 */
+MeScroll.prototype.getScrollTop = function() {
+	return this.scrollTop || 0
+}
+
+/* 记录滚动条的位置 */
+MeScroll.prototype.setScrollTop = function(y) {
+	this.scrollTop = y;
+}
+
+/* 滚动到指定位置 */
+MeScroll.prototype.scrollTo = function(y, t) {
+	this.myScrollTo && this.myScrollTo(y, t) // scrollview需自定义回到顶部方法
+}
+
+/* 自定义scrollTo */
+MeScroll.prototype.resetScrollTo = function(myScrollTo) {
+	this.myScrollTo = myScrollTo
+}
+
+/* 滚动条到底部的距离 */
+MeScroll.prototype.getScrollBottom = function() {
+	return this.getScrollHeight() - this.getClientHeight() - this.getScrollTop()
+}
+
+/* 计步器
+ star: 开始值
+ end: 结束值
+ callback(step,timer): 回调step值,计步器timer,可自行通过window.clearInterval(timer)结束计步器;
+ t: 计步时长,传0则直接回调end值;不传则默认300ms
+ rate: 周期;不传则默认30ms计步一次
+ * */
+MeScroll.prototype.getStep = function(star, end, callback, t, rate) {
+	let diff = end - star; // 差值
+	if (t === 0 || diff === 0) {
+		callback && callback(end);
+		return;
+	}
+	t = t || 300; // 时长 300ms
+	rate = rate || 30; // 周期 30ms
+	let count = t / rate; // 次数
+	let step = diff / count; // 步长
+	let i = 0; // 计数
+	let timer = setInterval(function() {
+		if (i < count - 1) {
+			star += step;
+			callback && callback(star, timer);
+			i++;
+		} else {
+			callback && callback(end, timer); // 最后一次直接设置end,避免计算误差
+			clearInterval(timer);
+		}
+	}, rate);
+}
+
+/* 滚动容器的高度 */
+MeScroll.prototype.getClientHeight = function(isReal) {
+	let h = this.clientHeight || 0
+	if (h === 0 && isReal !== true) { // 未获取到容器的高度,可临时取body的高度 (可能会有误差)
+		h = this.getBodyHeight()
+	}
+	return h
+}
+MeScroll.prototype.setClientHeight = function(h) {
+	this.clientHeight = h;
+}
+
+/* 滚动内容的高度 */
+MeScroll.prototype.getScrollHeight = function() {
+	return this.scrollHeight || 0;
+}
+MeScroll.prototype.setScrollHeight = function(h) {
+	this.scrollHeight = h;
+}
+
+/* body的高度 */
+MeScroll.prototype.getBodyHeight = function() {
+	return this.bodyHeight || 0;
+}
+MeScroll.prototype.setBodyHeight = function(h) {
+	this.bodyHeight = h;
+}
+
+/* 阻止浏览器默认滚动事件 */
+MeScroll.prototype.preventDefault = function(e) {
+	// 小程序不支持e.preventDefault
+	// app的bounce只能通过配置pages.json的style.app-plus.bounce为"none"来禁止
+	// cancelable:是否可以被禁用; defaultPrevented:是否已经被禁用
+	if (e && e.cancelable && !e.defaultPrevented) e.preventDefault()
+}
+
+/* 是否允许下拉回弹(橡皮筋效果); true或null为允许; false禁止bounce */
+MeScroll.prototype.setBounce = function(isBounce) {
+	// #ifdef H5
+	if (isBounce === false) {
+		this.optUp.isBounce = false; // 禁止
+		// 标记当前页使用了mescroll (需延时,确保page已切换)
+		setTimeout(function() {
+			let uniPageDom = document.getElementsByTagName('uni-page')[0];
+			uniPageDom && uniPageDom.setAttribute('use_mescroll', true)
+		}, 30);
+		// 避免重复添加事件
+		if (window.isSetBounce) return;
+		window.isSetBounce = true;
+		// 需禁止window的touchmove事件才能有效的阻止bounce
+		window.bounceTouchmove = function(e) {
+			if(!window.isPreventDefault) return; // 根据标记判断是否阻止
+			
+			let el = e.target;
+			// 当前touch的元素及父元素是否要拦截touchmove事件
+			let isPrevent = true;
+			while (el !== document.body && el !== document) {
+				if (el.tagName === 'UNI-PAGE') { // 只扫描当前页
+					if (!el.getAttribute('use_mescroll')) {
+						isPrevent = false; // 如果当前页没有使用mescroll,则不阻止
+					}
+					break;
+				}
+				let cls = el.classList;
+				if (cls) {
+					if (cls.contains('mescroll-touch')) { // 采用scroll-view 此处不能过滤mescroll-uni,否则下拉仍然有回弹
+						isPrevent = false; // mescroll-touch无需拦截touchmove事件
+						break;
+					} else if (cls.contains('mescroll-touch-x') || cls.contains('mescroll-touch-y')) {
+						// 如果配置了水平或者垂直滑动
+						let curX = e.touches ? e.touches[0].pageX : e.clientX; // 当前第一个手指距离列表顶部的距离x
+						let curY = e.touches ? e.touches[0].pageY : e.clientY; // 当前第一个手指距离列表顶部的距离y
+						if (!this.preWinX) this.preWinX = curX; // 设置上次移动的距离x
+						if (!this.preWinY) this.preWinY = curY; // 设置上次移动的距离y
+						// 计算两点之间的角度
+						let x = Math.abs(this.preWinX - curX);
+						let y = Math.abs(this.preWinY - curY);
+						let z = Math.sqrt(x * x + y * y);
+						this.preWinX = curX; // 记录本次curX的值
+						this.preWinY = curY; // 记录本次curY的值
+						if (z !== 0) {
+							let angle = Math.asin(y / z) / Math.PI * 180; // 角度区间 [0,90]
+							if ((angle <= 45 && cls.contains('mescroll-touch-x')) || (angle > 45 && cls.contains('mescroll-touch-y'))) {
+								isPrevent = false; // 水平滑动或者垂直滑动,不拦截touchmove事件
+								break;
+							}
+						}
+					}
+				}
+				el = el.parentNode; // 继续检查其父元素
+			}
+			// 拦截touchmove事件:是否可以被禁用&&是否已经被禁用 (这里不使用me.preventDefault(e)的方法,因为某些情况下会报找不到方法的异常)
+			if (isPrevent && e.cancelable && !e.defaultPrevented && typeof e.preventDefault === "function") e.preventDefault();
+		}
+		window.addEventListener('touchmove', window.bounceTouchmove, {
+			passive: false
+		});
+	} else {
+		this.optUp.isBounce = true; // 允许
+		if (window.bounceTouchmove) {
+			window.removeEventListener('touchmove', window.bounceTouchmove);
+			window.bounceTouchmove = null;
+			window.isSetBounce = false;
+		}
+	}
+	// #endif
+}

+ 364 - 0
HX-SHOP/components/mescroll-uni/mescroll-uni.vue

@@ -0,0 +1,364 @@
+<template>
+	<view class="mescroll-uni-warp">
+		<scroll-view :id="viewId" class="mescroll-uni" :class="{'mescroll-uni-fixed':isFixed}" :style="{'height':scrollHeight,'padding-top':padTop,'padding-bottom':padBottom,'padding-bottom':padBottomConstant,'padding-bottom':padBottomEnv,'top':fixedTop,'bottom':fixedBottom,'bottom':fixedBottomConstant,'bottom':fixedBottomEnv}" :scroll-top="scrollTop" :scroll-into-view="scrollToViewId" :scroll-with-animation="scrollAnim" @scroll="scroll" @touchstart="touchstartEvent" @touchmove="touchmoveEvent" @touchend="touchendEvent" @touchcancel="touchendEvent" :scroll-y='isDownReset' :enable-back-to-top="true">
+			<view class="mescroll-uni-content" :style="{'transform': translateY, 'transition': transition}">
+				<!-- 下拉加载区域 (支付宝小程序子组件传参给子子组件仍报单项数据流的异常,暂时不通过mescroll-down组件实现)-->
+				<!-- <mescroll-down :option="mescroll.optDown" :type="downLoadType" :rate="downRate"></mescroll-down> -->
+				<view v-if="mescroll.optDown.use" class="mescroll-downwarp" :style="{'background-color':mescroll.optDown.bgColor,'color':mescroll.optDown.textColor}">
+					<view class="downwarp-content">
+						<view class="downwarp-progress" :class="{'mescroll-rotate': isDownLoading}" :style="{'border-color':mescroll.optDown.textColor, 'transform': downRotate}"></view>
+						<view class="downwarp-tip">{{downText}}</view>
+					</view>
+				</view>
+
+				<!-- 列表内容 -->
+				<slot></slot>
+
+				<!-- 空布局 -->
+				<mescroll-empty v-if="isShowEmpty" :option="mescroll.optUp.empty" @emptyclick="emptyClick"></mescroll-empty>
+
+				<!-- 上拉加载区域 (下拉刷新时不显示, 支付宝小程序子组件传参给子子组件仍报单项数据流的异常,暂时不通过mescroll-up组件实现)-->
+				<!-- <mescroll-up v-if="mescroll.optUp.use && !isDownLoading" :option="mescroll.optUp" :type="upLoadType"></mescroll-up> -->
+				<view v-if="mescroll.optUp.use && !isDownLoading" class="mescroll-upwarp" :style="{'background-color':mescroll.optUp.bgColor,'color':mescroll.optUp.textColor}">
+					<!-- 加载中 (此处不能用v-if,否则android小程序快速上拉可能会不断触发上拉回调) -->
+					<view v-show="upLoadType===1">
+						<view class="upwarp-progress mescroll-rotate" :style="{'border-color':mescroll.optUp.textColor}"></view>
+						<view class="upwarp-tip">{{ mescroll.optUp.textLoading }}</view>
+					</view>
+					<!-- 无数据 -->
+					<view v-if="upLoadType===2" class="upwarp-nodata">{{ mescroll.optUp.textNoMore }}</view>
+				</view>
+			</view>
+		</scroll-view>
+
+		<!-- 回到顶部按钮 (fixed元素,需写在scroll-view外面,防止滚动的时候抖动)-->
+		<mescroll-top v-model="isShowToTop" :option="mescroll.optUp.toTop" @click="toTopClick"></mescroll-top>
+	</view>
+</template>
+
+<script>
+	// 引入mescroll-uni.js,处理核心逻辑
+	import MeScroll from './mescroll-uni.js';
+	// 引入全局配置
+	import GlobalOption from './mescroll-uni-option.js';
+	// 引入空布局组件
+	import MescrollEmpty from './components/mescroll-empty.vue';
+	// 引入回到顶部组件
+	import MescrollTop from './components/mescroll-top.vue';
+
+	export default {
+		components: {
+			MescrollEmpty,
+			MescrollTop
+		},
+		data() {
+			return {
+				mescroll: {optDown:{},optUp:{}}, // mescroll实例
+				viewId: 'id_' + Math.random().toString(36).substr(2), // 随机生成mescroll的id(不能数字开头,否则找不到元素)
+				downHight: 0, //下拉刷新: 容器高度
+				downRate: 0, // 下拉比率(inOffset: rate<1; outOffset: rate>=1)
+				downLoadType: 4, // 下拉刷新状态 (inOffset:1, outOffset:2, showLoading:3, endDownScroll:4)
+				upLoadType: 0, // 上拉加载状态:0(loading前),1(loading中),2(没有更多了)
+				isShowEmpty: false, // 是否显示空布局
+				isShowToTop: false, // 是否显示回到顶部按钮
+				scrollTop: 0, // 滚动条的位置
+				scrollAnim: false, // 是否开启滚动动画
+				windowTop: 0, // 可使用窗口的顶部位置
+				windowBottom: 0, // 可使用窗口的底部位置
+				windowHeight: 0, // 可使用窗口的高度
+				statusBarHeight: 0, // 状态栏高度
+				isSafearea: false, // 支持安全区
+				scrollToViewId: '' // 滚动到指定view的id
+			}
+		},
+		props: {
+			down: Object, // 下拉刷新的参数配置
+			up: Object, // 上拉加载的参数配置
+			top: [String, Number], // 下拉布局往下的偏移量 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx, 百分比则相对于windowHeight)
+			topbar: Boolean, // top的偏移量是否加上状态栏高度, 默认false (使用场景:取消原生导航栏时,配置此项可自动加上状态栏高度的偏移量)
+			bottom: [String, Number], // 上拉布局往上的偏移量 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx, 百分比则相对于windowHeight)
+			safearea: Boolean, // bottom的偏移量是否加上底部安全区的距离, 默认false (需要适配iPhoneX时使用)
+			fixed: { // 是否通过fixed固定mescroll的高度, 默认true
+				type: Boolean,
+				default () {
+					return true
+				}
+			},
+			height: [String, Number] // 指定mescroll的高度, 此项有值,则不使用fixed. (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx, 百分比则相对于windowHeight)
+		},
+		computed: {
+			// 是否使用fixed定位 (当height有值,则不使用)
+			isFixed(){
+				return !this.height && this.fixed
+			},
+			// mescroll的高度
+			scrollHeight(){
+				if (this.isFixed) {
+					return "auto"
+				} else if(this.height){
+					return this.toPx(this.height) + 'px'
+				}else{
+					return "100%"
+				}
+			},
+			// 下拉布局往下偏移的距离 (px)
+			numTop() {
+				return this.toPx(this.top) + (this.topbar ? this.statusBarHeight : 0)
+			},
+			fixedTop() {
+				return this.isFixed ? (this.numTop + this.windowTop) + 'px' : 0
+			},
+			padTop() {
+				return !this.isFixed ? this.numTop + 'px' : 0
+			},
+			// 上拉布局往上偏移 (px)
+			numBottom() {
+				return this.toPx(this.bottom)
+			},
+			fixedBottom() {
+				return this.isFixed ? (this.numBottom + this.windowBottom) + 'px' : 0
+			},
+			fixedBottomConstant(){
+				return this.isSafearea ? "calc("+this.fixedBottom+" + constant(safe-area-inset-bottom))" : this.fixedBottom
+			},
+			fixedBottomEnv(){
+				return this.isSafearea ? "calc("+this.fixedBottom+" + env(safe-area-inset-bottom))" : this.fixedBottom
+			},
+			padBottom() {
+				return !this.isFixed ? this.numBottom + 'px' : 0
+			},
+			padBottomConstant(){
+				return this.isSafearea ? "calc("+this.padBottom+" + constant(safe-area-inset-bottom))" : this.padBottom
+			},
+			padBottomEnv(){
+				return this.isSafearea ? "calc("+this.padBottom+" + env(safe-area-inset-bottom))" : this.padBottom
+			},
+			// 是否为重置下拉的状态
+			isDownReset(){
+				return this.downLoadType===3 || this.downLoadType===4
+			},
+			// 过渡
+			transition() {
+				return this.isDownReset ? 'transform 300ms' : '';
+			},
+			translateY() {
+				return this.downHight > 0 ? 'translateY(' + this.downHight + 'px)' : ''; // transform会使fixed失效,需注意把fixed元素写在mescroll之外
+			},
+			// 是否在加载中
+			isDownLoading(){
+				return this.downLoadType === 3
+			},
+			// 旋转的角度
+			downRotate(){
+				return 'rotate(' + 360 * this.downRate + 'deg)'
+			},
+			// 文本提示
+			downText(){
+				switch (this.downLoadType){
+					case 1: return this.mescroll.optDown.textInOffset;
+					case 2: return this.mescroll.optDown.textOutOffset;
+					case 3: return this.mescroll.optDown.textLoading;
+					case 4: return this.mescroll.optDown.textLoading;
+					default: return this.mescroll.optDown.textInOffset;
+				}
+			}
+		},
+		methods: {
+			//number,rpx,upx,px,% --> px的数值
+			toPx(num){
+				if(typeof num === "string"){
+					if (num.indexOf('px') !== -1) {
+						if(num.indexOf('rpx') !== -1) { // "10rpx"
+							num = num.replace('rpx', '');
+						} else if(num.indexOf('upx') !== -1) { // "10upx"
+							num = num.replace('upx', '');
+						} else { // "10px"
+							return Number(num.replace('px', ''))
+						}
+					}else if (num.indexOf('%') !== -1){
+						// 传百分比,则相对于windowHeight,传"10%"则等于windowHeight的10%
+						let rate = Number(num.replace("%","")) / 100
+						return this.windowHeight * rate
+					}
+				}
+				return num ? uni.upx2px(Number(num)) : 0
+			},
+			//注册列表滚动事件,用于下拉刷新和上拉加载
+			scroll(e) {
+				this.mescroll.scroll(e.detail, () => {
+					this.$emit('scroll', this.mescroll) // 此时可直接通过 this.mescroll.scrollTop获取滚动条位置; this.mescroll.isScrollUp获取是否向上滑动
+				})
+			},
+			//注册列表touchstart事件,用于下拉刷新
+			touchstartEvent(e) {
+				this.mescroll.touchstartEvent(e);
+			},
+			//注册列表touchmove事件,用于下拉刷新
+			touchmoveEvent(e) {
+				this.mescroll.touchmoveEvent(e);
+			},
+			//注册列表touchend事件,用于下拉刷新
+			touchendEvent(e) {
+				this.mescroll.touchendEvent(e);
+			},
+			// 点击空布局的按钮回调
+			emptyClick() {
+				this.$emit('emptyclick', this.mescroll)
+			},
+			// 点击回到顶部的按钮回调
+			toTopClick() {
+				this.mescroll.scrollTo(0, this.mescroll.optUp.toTop.duration); // 执行回到顶部
+				this.$emit('topclick', this.mescroll); // 派发点击回到顶部按钮的回调
+			},
+			// 更新滚动区域的高度 (使内容不满屏和到底,都可继续翻页)
+			setClientHeight() {
+				if (this.mescroll.getClientHeight(true) === 0 && !this.isExec) {
+					this.isExec = true; // 避免多次获取
+					this.$nextTick(() => { // 确保dom已渲染
+						let view = uni.createSelectorQuery().in(this).select('#' + this.viewId);
+						view.boundingClientRect(data => {
+							this.isExec = false;
+							if (data) {
+								this.mescroll.setClientHeight(data.height);
+							} else if (this.clientNum != 3) { // 极少部分情况,可能dom还未渲染完毕,递归获取,最多重试3次
+								this.clientNum = this.clientNum == null ? 1 : this.clientNum + 1;
+								setTimeout(() => {
+									this.setClientHeight()
+								}, this.clientNum * 100)
+							}
+						}).exec();
+					})
+				}
+			}
+		},
+		// 使用created初始化mescroll对象; 如果用mounted部分css样式编译到H5会失效
+		created() {
+			let vm = this;
+
+			let diyOption = {
+				// 下拉刷新的配置
+				down: {
+					inOffset(mescroll) {
+						vm.downLoadType = 1; // 下拉的距离进入offset范围内那一刻的回调 (自定义mescroll组件时,此行不可删)
+					},
+					outOffset(mescroll) {
+						vm.downLoadType = 2; // 下拉的距离大于offset那一刻的回调 (自定义mescroll组件时,此行不可删)
+					},
+					onMoving(mescroll, rate, downHight) {
+						// 下拉过程中的回调,滑动过程一直在执行;
+						vm.downHight = downHight; // 设置下拉区域的高度 (自定义mescroll组件时,此行不可删)
+						vm.downRate = rate; //下拉比率 (inOffset: rate<1; outOffset: rate>=1)
+					},
+					showLoading(mescroll, downHight) {
+						vm.downLoadType = 3; // 显示下拉刷新进度的回调 (自定义mescroll组件时,此行不可删)
+						vm.downHight = downHight; // 设置下拉区域的高度 (自定义mescroll组件时,此行不可删)
+					},
+					endDownScroll(mescroll) {
+						vm.downLoadType = 4; // 结束下拉 (自定义mescroll组件时,此行不可删)
+						vm.downHight = 0; // 设置下拉区域的高度 (自定义mescroll组件时,此行不可删)
+					},
+					// 派发下拉刷新的回调
+					callback: function(mescroll) {
+						vm.$emit('down', mescroll)
+					}
+				},
+				// 上拉加载的配置
+				up: {
+					// 显示加载中的回调
+					showLoading() {
+						vm.upLoadType = 1;
+					},
+					// 显示无更多数据的回调
+					showNoMore() {
+						vm.upLoadType = 2;
+					},
+					// 隐藏上拉加载的回调
+					hideUpScroll() {
+						vm.upLoadType = 0;
+					},
+					// 空布局
+					empty: {
+						onShow(isShow) { // 显示隐藏的回调
+							vm.isShowEmpty = isShow;
+						}
+					},
+					// 回到顶部
+					toTop: {
+						onShow(isShow) { // 显示隐藏的回调
+							vm.isShowToTop = isShow;
+						}
+					},
+					// 派发上拉加载的回调
+					callback: function(mescroll) {
+						vm.$emit('up', mescroll);
+						// 更新容器的高度 (多mescroll的情况)
+						vm.setClientHeight()
+					}
+				}
+			}
+
+			MeScroll.extend(diyOption, GlobalOption); // 混入全局的配置
+			let myOption = JSON.parse(JSON.stringify({
+				'down': vm.down,
+				'up': vm.up
+			})) // 深拷贝,避免对props的影响
+			MeScroll.extend(myOption, diyOption); // 混入具体界面的配置
+
+			// 初始化MeScroll对象
+			vm.mescroll = new MeScroll(myOption);
+			vm.mescroll.viewId = vm.viewId; // 附带id
+			// init回调mescroll对象
+			vm.$emit('init', vm.mescroll);
+			
+			// 设置高度
+			const sys = uni.getSystemInfoSync();
+			if(sys.windowTop) vm.windowTop = sys.windowTop;
+			if(sys.windowBottom) vm.windowBottom = sys.windowBottom;
+			if(sys.windowHeight) vm.windowHeight = sys.windowHeight;
+			if(sys.statusBarHeight) vm.statusBarHeight = sys.statusBarHeight;
+			// 使down的bottomOffset生效
+			vm.mescroll.setBodyHeight(sys.windowHeight);
+
+			// 因为使用的是scrollview,这里需自定义scrollTo
+			vm.mescroll.resetScrollTo((y, t) => {
+				vm.scrollAnim = (t !== 0); // t为0,则不使用动画过渡
+				if(typeof y === 'string'){ // 第一个参数如果为字符串,则使用scroll-into-view
+					vm.scrollToViewId = y;
+					return;
+				}
+				let curY = vm.mescroll.getScrollTop()
+				if (t === 0 || t === 300) { // 当t使用默认配置的300时,则使用系统自带的动画过渡
+					vm.scrollTop = curY;
+					vm.$nextTick(function() {
+						vm.scrollTop = y
+					})
+				} else {
+					vm.mescroll.getStep(curY, y, step => { // 此写法可支持配置t
+						vm.scrollTop = step
+					}, t)
+				}
+			})
+			
+			// 具体的界面如果不配置up.toTop.safearea,则取本vue的safearea值
+			if(sys.platform == "ios"){
+				vm.isSafearea = vm.safearea;
+				if (vm.up && vm.up.toTop && vm.up.toTop.safearea != null) {} else {
+					vm.mescroll.optUp.toTop.safearea = vm.safearea;
+				}
+			}else{
+				vm.isSafearea = false
+				vm.mescroll.optUp.toTop.safearea = false
+			}
+		},
+		mounted() {
+			// 设置容器的高度
+			this.setClientHeight()
+		}
+	}
+</script>
+
+<style>
+	@import "./mescroll-uni.css";
+	@import "./components/mescroll-down.css";
+	@import './components/mescroll-up.css';
+</style>

+ 23 - 0
HX-SHOP/components/mescroll-uni/mixins/mescroll-comp.js

@@ -0,0 +1,23 @@
+/**
+ * mescroll-body写在子组件时,需通过mescroll的mixins补充子组件缺少的生命周期:
+ * 当一个页面只有一个mescroll-body写在子组件时, 则使用mescroll-comp.js (参考 mescroll-comp 案例)
+ * 当一个页面有多个mescroll-body写在子组件时, 则使用mescroll-more.js (参考 mescroll-more 案例)
+ */
+const MescrollCompMixin = {
+	// 因为子组件无onPageScroll和onReachBottom的页面生命周期,需在页面传递进到子组件
+	onPageScroll(e) {
+		let item = this.$refs["mescrollItem"];
+		if(item && item.mescroll) item.mescroll.onPageScroll(e);
+	},
+	onReachBottom() {
+		let item = this.$refs["mescrollItem"];
+		if(item && item.mescroll) item.mescroll.onReachBottom();
+	},
+	// 当down的native: true时, 还需传递此方法进到子组件
+	onPullDownRefresh(){
+		let item = this.$refs["mescrollItem"];
+		if(item && item.mescroll) item.mescroll.onPullDownRefresh();
+	}
+}
+
+export default MescrollCompMixin;

+ 48 - 0
HX-SHOP/components/mescroll-uni/mixins/mescroll-more-item.js

@@ -0,0 +1,48 @@
+/**
+ * mescroll-more-item的mixins, 仅在多个 mescroll-body 写在子组件时使用 (参考 mescroll-more 案例)
+ */
+const MescrollMoreItemMixin = {
+	props:{
+		i: Number, // 每个tab页的专属下标
+		index: { // 当前tab的下标
+			type: Number,
+			default(){
+				return 0
+			}
+		}
+	},
+	data() {
+		return {
+			downOption:{
+				auto:false // 不自动加载
+			},
+			upOption:{
+				auto:false // 不自动加载
+			},
+			isInit: false // 当前tab是否已初始化
+		}
+	},
+	watch:{
+		// 监听下标的变化
+		index(val){
+			if (this.i === val && !this.isInit) {
+				this.isInit = true; // 标记为true
+				this.mescroll && this.mescroll.triggerDownScroll();
+			}
+		}
+	},
+	methods: {
+		// mescroll组件初始化的回调,可获取到mescroll对象
+		mescrollInit(mescroll) {
+			this.mescroll = mescroll;
+			this.mescrollInitByRef && this.mescrollInitByRef(); // 兼容字节跳动小程序 (mescroll-mixins.js)
+			// 自动加载当前tab的数据
+			if(this.i === this.index){
+				this.isInit = true; // 标记为true
+				this.mescroll.triggerDownScroll();
+			}
+		},
+	}
+}
+
+export default MescrollMoreItemMixin;

+ 56 - 0
HX-SHOP/components/mescroll-uni/mixins/mescroll-more.js

@@ -0,0 +1,56 @@
+/**
+ * mescroll-body写在子组件时,需通过mescroll的mixins补充子组件缺少的生命周期:
+ * 当一个页面只有一个mescroll-body写在子组件时, 则使用mescroll-comp.js (参考 mescroll-comp 案例)
+ * 当一个页面有多个mescroll-body写在子组件时, 则使用mescroll-more.js (参考 mescroll-more 案例)
+ */
+const MescrollMoreMixin = {
+	data() {
+		return {
+			tabIndex: 0 // 当前tab下标
+		}
+	},
+	// 因为子组件无onPageScroll和onReachBottom的页面生命周期,需在页面传递进到子组件
+	onPageScroll(e) {
+		let mescroll = this.getMescroll(this.tabIndex);
+		mescroll && mescroll.onPageScroll(e);
+	},
+	onReachBottom() {
+		let mescroll = this.getMescroll(this.tabIndex);
+		mescroll && mescroll.onReachBottom();
+	},
+	// 当down的native: true时, 还需传递此方法进到子组件
+	onPullDownRefresh(){
+		let mescroll = this.getMescroll(this.tabIndex);
+		mescroll && mescroll.onPullDownRefresh();
+	},
+	methods:{
+		// 根据下标获取对应子组件的mescroll
+		getMescroll(i){
+			if(!this.mescrollItems) this.mescrollItems = [];
+			if(!this.mescrollItems[i]) {
+				// v-for中的refs
+				let vForItem = this.$refs["mescrollItem"];
+				if(vForItem){
+					this.mescrollItems[i] = vForItem[i]
+				}else{
+					// 普通的refs,不可重复
+					this.mescrollItems[i] = this.$refs["mescrollItem"+i];
+				}
+			}
+			let item = this.mescrollItems[i]
+			return item ? item.mescroll : null
+		},
+		// 切换tab,恢复滚动条位置
+		tabChange(i){
+			let mescroll = this.getMescroll(i);
+			if(mescroll){
+				// 延时(比$nextTick靠谱一些),确保元素已渲染
+				setTimeout(()=>{
+					mescroll.scrollTo(mescroll.getScrollTop(),0)
+				},30)
+			}
+		}
+	}
+}
+
+export default MescrollMoreMixin;

+ 119 - 0
HX-SHOP/components/mix-list-cell.vue

@@ -0,0 +1,119 @@
+<template>
+	<view class="content">
+		
+		<view class="mix-list-cell" :class="border" @click="eventClick" hover-class="cell-hover"  :hover-stay-time="50">
+			<text
+				v-if="icon"
+				class="cell-icon hxicon"
+				:style="[{
+					color: iconColor,
+				}]"
+				:class="icon"
+			></text>
+			<text class="cell-tit clamp">{{title}}</text>
+			<text v-if="tips" class="cell-tip">{{tips}}</text>
+			<text class="cell-more hxicon"
+				:class="typeList[navigateType]"
+			></text>
+		</view>
+
+	</view>
+</template>
+ 
+<script>
+	/**
+	 *  简单封装了下, 应用范围比较狭窄,可以在此基础上进行扩展使用
+	 *  比如加入image, iconSize可控等
+	 */
+	export default {
+		data() {
+			return {
+				typeList: {
+					left: 'icon-zuo',
+					right: 'icon-you',
+					up: 'icon-shang',
+					down: 'icon-xia'
+				},
+			}
+		},
+		props: {
+			icon: {
+				type: String,
+				default: ''
+			},
+			title: {
+				type: String,
+				default: '标题'
+			},
+			tips: {
+				type: String,
+				default: ''
+			},
+			navigateType: {
+				type: String,
+				default: 'right'
+			},
+			border: {
+				type: String,
+				default: 'b-b'
+			},
+			hoverClass: {
+				type: String,
+				default: 'cell-hover'
+			},
+			iconColor: {
+				type: String,
+				default: '#333'
+			}
+		},
+		methods: {
+			eventClick(){
+				this.$emit('eventClick');
+			}
+		},
+	}
+</script>
+
+<style lang='scss'>
+
+	.icon .mix-list-cell.b-b:after{
+		left: 90upx;
+	}
+	.mix-list-cell{
+		display:flex;
+		align-items:baseline;
+		padding: 20upx $page-row-spacing;
+		line-height:60upx;
+		position:relative;
+		
+		&.cell-hover{
+			background:#fafafa;
+		}
+		&.b-b:after{
+			left: 30upx;
+		}
+
+		.cell-icon{
+			align-self:center;
+			width:56upx;
+			max-height:60upx;
+			font-size:38upx;
+		}
+		.cell-more{
+			align-self: center;
+			font-size:30upx;
+			color:$font-color-base;
+			margin-left:$uni-spacing-row-sm;
+		}
+		.cell-tit{
+			flex: 1;
+			font-size: $font-base;
+			color: $font-color-dark;
+			margin-right:10upx;
+		}
+		.cell-tip{
+			font-size: $font-sm+2upx;
+			color: $font-color-light;
+		}
+	}
+</style>

+ 96 - 0
HX-SHOP/components/uni-icons/icons.js

@@ -0,0 +1,96 @@
+export default {
+	'contact': '\ue100',
+	'person': '\ue101',
+	'personadd': '\ue102',
+	'contact-filled': '\ue130',
+	'person-filled': '\ue131',
+	'personadd-filled': '\ue132',
+	'phone': '\ue200',
+	'email': '\ue201',
+	'chatbubble': '\ue202',
+	'chatboxes': '\ue203',
+	'phone-filled': '\ue230',
+	'email-filled': '\ue231',
+	'chatbubble-filled': '\ue232',
+	'chatboxes-filled': '\ue233',
+	'weibo': '\ue260',
+	'weixin': '\ue261',
+	'pengyouquan': '\ue262',
+	'chat': '\ue263',
+	'qq': '\ue264',
+	'videocam': '\ue300',
+	'camera': '\ue301',
+	'mic': '\ue302',
+	'location': '\ue303',
+	'mic-filled': '\ue332',
+	'speech': '\ue332',
+	'location-filled': '\ue333',
+	'micoff': '\ue360',
+	'image': '\ue363',
+	'map': '\ue364',
+	'compose': '\ue400',
+	'trash': '\ue401',
+	'upload': '\ue402',
+	'download': '\ue403',
+	'close': '\ue404',
+	'redo': '\ue405',
+	'undo': '\ue406',
+	'refresh': '\ue407',
+	'star': '\ue408',
+	'plus': '\ue409',
+	'minus': '\ue410',
+	'circle': '\ue411',
+	'checkbox': '\ue411',
+	'close-filled': '\ue434',
+	'clear': '\ue434',
+	'refresh-filled': '\ue437',
+	'star-filled': '\ue438',
+	'plus-filled': '\ue439',
+	'minus-filled': '\ue440',
+	'circle-filled': '\ue441',
+	'checkbox-filled': '\ue442',
+	'closeempty': '\ue460',
+	'refreshempty': '\ue461',
+	'reload': '\ue462',
+	'starhalf': '\ue463',
+	'spinner': '\ue464',
+	'spinner-cycle': '\ue465',
+	'search': '\ue466',
+	'plusempty': '\ue468',
+	'forward': '\ue470',
+	'back': '\ue471',
+	'left-nav': '\ue471',
+	'checkmarkempty': '\ue472',
+	'home': '\ue500',
+	'navigate': '\ue501',
+	'gear': '\ue502',
+	'paperplane': '\ue503',
+	'info': '\ue504',
+	'help': '\ue505',
+	'locked': '\ue506',
+	'more': '\ue507',
+	'flag': '\ue508',
+	'home-filled': '\ue530',
+	'gear-filled': '\ue532',
+	'info-filled': '\ue534',
+	'help-filled': '\ue535',
+	'more-filled': '\ue537',
+	'settings': '\ue560',
+	'list': '\ue562',
+	'bars': '\ue563',
+	'loop': '\ue565',
+	'paperclip': '\ue567',
+	'eye': '\ue568',
+	'arrowup': '\ue580',
+	'arrowdown': '\ue581',
+	'arrowleft': '\ue582',
+	'arrowright': '\ue583',
+	'arrowthinup': '\ue584',
+	'arrowthindown': '\ue585',
+	'arrowthinleft': '\ue586',
+	'arrowthinright': '\ue587',
+	'pulldown': '\ue588',
+	'closefill': '\ue589',
+	'sound': '\ue590',
+	'scan': '\ue612'
+}

File diff ditekan karena terlalu besar
+ 10 - 0
HX-SHOP/components/uni-icons/uni-icons.vue


+ 209 - 0
HX-SHOP/components/uni-number-box/uni-number-box.vue

@@ -0,0 +1,209 @@
+<template>
+	<view class="hx-numbox">
+		<view @click="_calcValue('minus')" class="hx-numbox__minus" v-if="inputValue>0">
+			<text class="hx-numbox--text" :class="{ 'hx-numbox--disabled': inputValue <= min || disabled }">-</text>
+		</view>
+		<input :disabled="true" @blur="_onBlur" class="hx-numbox__value" type="number" v-model="inputValue" v-if="inputValue>0"/>
+		
+		<view @click="_calcValue('plus')" class="hx-numbox__plus" >
+			<text class="hx-numbox--text" :class="{ 'hx-numbox--disabled': inputValue >= max || disabled }">+</text>
+		</view>
+	</view>
+</template>
+<script>
+	export default {
+		name: "hxNumberBox",
+		props: {
+			value: {
+				type: [Number, String],
+				default: 0
+			},
+			min: {
+				type: Number,
+				default: 0
+			},
+			max: {
+				type: Number,
+				default: 100
+			},
+			step: {
+				type: Number,
+				default: 1
+			},
+			disabled: {
+				type: Boolean,
+				default: false
+			},
+			rowData: {
+				type: Object,
+				default: ()=>{
+					return {}
+				}
+			},
+			clickTime: {
+				type: Number,
+				default: 0
+			}
+			
+		},
+		data() {
+			return {
+				inputValue: 0,
+				addStaus: true,
+			};
+		},
+		watch: {
+			value(val) {
+				this.inputValue = +val;
+			},
+			inputValue(newVal, oldVal) {
+				if (+newVal !== +oldVal) {
+					//this.$emit("change", newVal,this.rowData);
+				}
+				/* if(+newVal > +oldVal){
+					
+				} */
+			}
+		},
+		created() {
+			this.inputValue = +this.value;
+		},
+		methods: {
+			_calcValue(type) {
+				let that = this;
+				if (this.disabled) {
+					return;
+				}
+			
+				const scale = this._getDecimalScale();
+				let value = this.inputValue * scale;
+				let step = this.step * scale;
+				
+				
+				if (type === "minus") {
+					this.$emit("lessChange", this.inputValue,this.rowData);
+					value -= step;
+					if (value < this.min) {
+						return;
+					}
+					if(value > this.max){
+						value = this.max
+					}
+				} else if (type === "plus") {
+					this.$emit("addChange", this.inputValue,this.rowData);
+					if(that.clickTime > 0){
+						if(!this.addStaus){
+							return;
+						}else{
+							this.addStaus = false;
+							setTimeout(()=>{
+								that.addStaus = true;
+							},that.clickTime)
+						}
+					}
+					value += step;
+					if (value > this.max) {
+						return;
+					}
+					if(value < this.min){
+						value = this.min
+					}
+				}
+
+				this.inputValue = String(value / scale);
+				this.$emit("change", this.inputValue,this.rowData);
+			},
+			_getDecimalScale() {
+				let scale = 1;
+				// 浮点型
+				if (~~this.step !== this.step) {
+					scale = Math.pow(10, (this.step + "").split(".")[1].length);
+				}
+				return scale;
+			},
+			_onBlur(event) {
+				let value = event.detail.value;
+				if (!value) {
+					// this.inputValue = 0;
+					return;
+				}
+				value = +value;
+				if (value > this.max) {
+					value = this.max;
+				} else if (value < this.min) {
+					value = this.min;
+				}
+				this.inputValue = value;
+			}
+		}
+	};
+</script>
+<style lang="scss" scoped>
+	$box-height: 28px;
+	
+	$box-line-height: 22px;
+	$box-width: 28px;
+
+	.hx-numbox {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		height: $box-height;
+		line-height: $box-height;
+		width: 85px;
+		justify-content: flex-end;
+	}
+
+	.hx-numbox__value {
+		
+		width: 28px;
+		height: $box-height;
+		text-align: center;
+		font-size: $uni-font-size-lg;
+		color: #222222;
+	}
+
+	.hx-numbox__minus {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+		justify-content: center;
+		width: $box-width - 1;
+		height: $box-height - 1;
+		
+		font-size: 30px;
+		color: $uni-text-color;
+		
+		background-color: #f8f8f8;
+		border-radius: 50%;
+		border: 1px solid #d8d8d8;
+		color: #868686;
+		
+	}
+
+	.hx-numbox__plus {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+		justify-content: center;
+		width: $box-width;
+		height: $box-height;
+		background: linear-gradient(100deg, #FFEB3B, #FFC107);
+		font-size: 22px;
+		border-radius: 50%;
+	}
+
+	.hx-numbox--text {
+		font-size: 40rpx;
+		color: $uni-text-color;
+	}
+
+	.hx-numbox--disabled {
+		color: $uni-text-color-disable;
+	}
+</style>

+ 263 - 0
HX-SHOP/components/uni-popup/uni-popup.vue

@@ -0,0 +1,263 @@
+<template>
+	<view v-if="showPopup" class="uni-popup" @touchmove.stop.prevent="clear">
+		<uni-transition :mode-class="['fade']" :styles="maskClass" :duration="duration" :show="showTrans" @click="onTap" />
+		<uni-transition :mode-class="ani" :styles="transClass" :duration="duration" :show="showTrans" @click="onTap">
+			<view class="uni-popup__wrapper-box" @click.stop="clear">
+				<slot />
+			</view>
+		</uni-transition>
+	</view>
+</template>
+
+<script>
+	import uniTransition from '../uni-transition/uni-transition.vue'
+
+	/**
+	 * PopUp 弹出层
+	 * @description 弹出层组件,为了解决遮罩弹层的问题
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=329
+	 * @property {String} type = [top|center|bottom] 弹出方式
+	 * 	@value top 顶部弹出
+	 * 	@value center 中间弹出
+	 * 	@value bottom 底部弹出
+	 * @property {Boolean} animation = [ture|false] 是否开启动画
+	 * @property {Boolean} maskClick = [ture|false] 蒙版点击是否关闭弹窗
+	 * @event {Function} change 打开关闭弹窗触发,e={show: false}
+	 */
+
+	export default {
+		name: 'UniPopup',
+		components: {
+			uniTransition
+		},
+		props: {
+			// 开启动画
+			animation: {
+				type: Boolean,
+				default: true
+			},
+			// 弹出层类型,可选值,top: 顶部弹出层;bottom:底部弹出层;center:全屏弹出层
+			type: {
+				type: String,
+				default: 'center'
+			},
+			// maskClick
+			maskClick: {
+				type: Boolean,
+				default: true
+			}
+		},
+		data() {
+			return {
+				duration: 300,
+				ani: [],
+				showPopup: false,
+				showTrans: false,
+				maskClass: {
+					'position': 'fixed',
+					'bottom': 0,
+					'top': 0,
+					'left': 0,
+					'right': 0,
+					'backgroundColor': 'rgba(0, 0, 0, 0.4)'
+				},
+				transClass: {
+					'position': 'fixed',
+					'left': 0,
+					'right': 0,
+				}
+			}
+		},
+		watch: {
+			type: {
+				handler: function(newVal) {
+					switch (this.type) {
+						case 'top':
+							this.ani = ['slide-top']
+							this.transClass = {
+								'position': 'fixed',
+								'left': 0,
+								'right': 0,
+							}
+							break
+						case 'bottom':
+							this.ani = ['slide-bottom']
+							this.transClass = {
+								'position': 'fixed',
+								'left': 0,
+								'right': 0,
+								'bottom': 0
+							}
+							break
+						case 'center':
+							this.ani = ['zoom-out', 'fade']
+							this.transClass = {
+								'position': 'fixed',
+								/* #ifndef APP-NVUE */
+								'display': 'flex',
+								'flexDirection': 'column',
+								/* #endif */
+								'bottom': 0,
+								'left': 0,
+								'right': 0,
+								'top': 0,
+								'justifyContent': 'center',
+								'alignItems': 'center'
+							}
+
+							break
+					}
+				},
+				immediate: true
+			}
+		},
+		created() {
+			if (this.animation) {
+				this.duration = 300
+			} else {
+				this.duration = 0
+			}
+		},
+		methods: {
+			clear(e) {
+				// TODO nvue 取消冒泡
+				e.stopPropagation()
+			},
+			open() {
+				this.showPopup = true
+				this.$nextTick(() => {
+					clearTimeout(this.timer)
+					this.timer = setTimeout(() => {
+						this.showTrans = true
+					}, 50);
+				})
+				this.$emit('change', {
+					show: true
+				})
+			},
+			close(type) {
+				this.showTrans = false
+				this.$nextTick(() => {
+					clearTimeout(this.timer)
+					this.timer = setTimeout(() => {
+						this.$emit('change', {
+							show: false
+						})
+						this.showPopup = false
+					}, 300)
+				})
+			},
+			onTap() {
+				if (!this.maskClick) return
+				this.close()
+			}
+		}
+	}
+</script>
+<style lang="scss" scoped>
+	.uni-popup {
+		position: fixed;
+		/* #ifdef H5 */
+		top: var(--window-top);
+		/* #endif */
+		/* #ifndef H5 */
+		top: 0;
+		/* #endif */
+		bottom: 0;
+		left: 0;
+		right: 0;
+		/* #ifndef APP-NVUE */
+		z-index: 99;
+		/* #endif */
+	}
+
+	.uni-popup__mask {
+		position: absolute;
+		top: 0;
+		bottom: 0;
+		left: 0;
+		right: 0;
+		background-color: $uni-bg-color-mask;
+		opacity: 0;
+	}
+
+	.mask-ani {
+		transition-property: opacity;
+		transition-duration: 0.2s;
+	}
+
+	.uni-top-mask {
+		opacity: 1;
+	}
+
+	.uni-bottom-mask {
+		opacity: 1;
+	}
+
+	.uni-center-mask {
+		opacity: 1;
+	}
+
+	.uni-popup__wrapper {
+		/* #ifndef APP-NVUE */
+		display: block;
+		/* #endif */
+		position: absolute;
+	}
+
+	.top {
+		top: 0;
+		left: 0;
+		right: 0;
+		transform: translateY(-500px);
+	}
+
+	.bottom {
+		bottom: 0;
+		left: 0;
+		right: 0;
+		transform: translateY(500px);
+	}
+
+	.center {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		flex-direction: column;
+		/* #endif */
+		bottom: 0;
+		left: 0;
+		right: 0;
+		top: 0;
+		justify-content: center;
+		align-items: center;
+		transform: scale(1.2);
+		opacity: 0;
+	}
+
+	.uni-popup__wrapper-box {
+		/* #ifndef APP-NVUE */
+		display: block;
+		/* #endif */
+		position: relative;
+	}
+
+	.content-ani {
+		// transition: transform 0.3s;
+		transition-property: transform, opacity;
+		transition-duration: 0.2s;
+	}
+
+
+	.uni-top-content {
+		transform: translateY(0);
+	}
+
+	.uni-bottom-content {
+		transform: translateY(0);
+	}
+
+	.uni-center-content {
+		transform: scale(1);
+		opacity: 1;
+	}
+</style>

+ 141 - 0
HX-SHOP/components/uni-rate/uni-rate.vue

@@ -0,0 +1,141 @@
+<template>
+	<view class="uni-rate">
+		<view :key="index" :style="{ marginLeft: margin + 'px' }" @click="_onClick(index)" class="uni-rate__icon" v-for="(star, index) in stars">
+			<uni-icons :color="color" :size="size" :type="isFill ? 'star-filled' : 'star'" />
+			<!-- #ifdef APP-NVUE -->
+			<view :style="{ width: star.activeWitch.replace('%','')*size/100+'px'}" class="uni-rate__icon-on">
+				<uni-icons style="text-align: left;" :color="activeColor" :size="size" type="star-filled" />
+			</view>
+			<!-- #endif -->
+			<!-- #ifndef APP-NVUE -->
+			<view :style="{ width: star.activeWitch,top:-size/2+'px'}" class="uni-rate__icon-on">
+				<uni-icons :color="activeColor" :size="size" type="star-filled" />
+			</view>
+			<!-- #endif -->
+		</view>
+	</view>
+</template>
+
+<script>
+	import uniIcons from "../uni-icons/uni-icons.vue";
+	export default {
+		name: "UniRate",
+		components: {
+			uniIcons
+		},
+		props: {
+			isFill: {
+				// 星星的类型,是否镂空
+				type: [Boolean, String],
+				default: true
+			},
+			color: {
+				// 星星的颜色
+				type: String,
+				default: "#ececec"
+			},
+			activeColor: {
+				// 星星选中状态颜色
+				type: String,
+				default: "#ffca3e"
+			},
+			size: {
+				// 星星的大小
+				type: [Number, String],
+				default: 24
+			},
+			value: {
+				// 当前评分
+				type: [Number, String],
+				default: 0
+			},
+			max: {
+				// 最大评分
+				type: [Number, String],
+				default: 5
+			},
+			margin: {
+				// 星星的间距
+				type: [Number, String],
+				default: 0
+			},
+			disabled: {
+				// 是否可点击
+				type: [Boolean, String],
+				default: false
+			}
+		},
+		data() {
+			return {
+				valueSync: ""
+			};
+		},
+		computed: {
+			stars() {
+				const value = this.valueSync ? this.valueSync : 0;
+				const starList = [];
+				const floorValue = Math.floor(value);
+				const ceilValue = Math.ceil(value);
+				// console.log("ceilValue: " + ceilValue);
+				// console.log("floorValue: " + floorValue);
+				for (let i = 0; i < this.max; i++) {
+					if (floorValue > i) {
+						starList.push({
+							activeWitch: "100%"
+						});
+					} else if (ceilValue - 1 === i) {
+						starList.push({
+							activeWitch: (value - floorValue) * 100 + "%"
+						});
+					} else {
+						starList.push({
+							activeWitch: "0"
+						});
+					}
+				}
+				//console.log("starList[4]: " + starList[4].activeWitch);
+				return starList;
+			}
+		},
+		created() {
+			this.valueSync = Number(this.value);
+		},
+		methods: {
+			_onClick(index) {
+				if (this.disabled) {
+					return;
+				}
+				this.valueSync = index + 1;
+				this.$emit("change", {
+					value: this.valueSync
+				});
+			}
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	.uni-rate {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		line-height: 0;
+		font-size: 0;
+		flex-direction: row;
+	}
+
+	.uni-rate__icon {
+		position: relative;
+		line-height: 0;
+		font-size: 0;
+	}
+
+	.uni-rate__icon-on {
+		overflow: hidden;
+		position: absolute;
+		top: 0;
+		left: 0;
+		line-height: 1;
+		text-align: left;
+	}
+</style>

+ 279 - 0
HX-SHOP/components/uni-transition/uni-transition.vue

@@ -0,0 +1,279 @@
+<template>
+	<view v-if="isShow" ref="ani" class="uni-transition" :class="[ani.in]" :style="'transform:' +transform+';'+stylesObject"
+	 @click="change">
+		 <slot></slot>
+	</view>
+</template>
+
+<script>
+	// #ifdef APP-NVUE
+	const animation = uni.requireNativePlugin('animation');
+	// #endif
+	/**
+	 * Transition 过渡动画
+	 * @description 简单过渡动画组件
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=985
+	 * @property {Boolean} show = [false|true] 控制组件显示或隐藏
+     * @property {Array} modeClass = [fade|slide-top|slide-right|slide-bottom|slide-left|zoom-in|zoom-out] 过渡动画类型
+     *  @value fade 渐隐渐出过渡
+     *  @value slide-top 由上至下过渡
+     *  @value slide-right 由右至左过渡
+     *  @value slide-bottom 由下至上过渡
+     *  @value slide-left 由左至右过渡
+     *  @value zoom-in 由小到大过渡
+     *  @value zoom-out 由大到小过渡
+	 * @property {Number} duration 过渡动画持续时间
+	 * @property {Object} styles 组件样式,同 css 样式,注意带’-‘连接符的属性需要使用小驼峰写法如:`backgroundColor:red`
+	 */
+	export default {
+		name: 'uniTransition',
+		props: {
+			show: {
+				type: Boolean,
+				default: false
+			},
+			modeClass: {
+				type: Array,
+				default () {
+					return []
+				}
+			},
+			duration: {
+				type: Number,
+				default: 300
+			},
+			styles: {
+				type: Object,
+				default () {
+					return {}
+				}
+			}
+		},
+		data() {
+			return {
+				isShow: false,
+				transform: '',
+				ani: { in: '',
+					active: ''
+				}
+			};
+		},
+		watch: {
+			show: {
+				handler(newVal) {
+					if (newVal) {
+						this.open()
+					} else {
+						this.close()
+					}
+				},
+				immediate: true
+			}
+		},
+		computed: {
+			stylesObject() {
+				let styles = {
+					...this.styles,
+					'transition-duration': this.duration / 1000 + 's'
+				}
+				let transfrom = ''
+				for (let i in styles) {
+					let line = this.toLine(i)
+					transfrom += line + ':' + styles[i] + ';'
+				}
+				return transfrom
+			}
+		},
+		created() {
+			// this.timer = null
+			// this.nextTick = (time = 50) => new Promise(resolve => {
+			// 	clearTimeout(this.timer)
+			// 	this.timer = setTimeout(resolve, time)
+			// 	return this.timer
+			// });
+		},
+		methods: {
+			change() {
+				this.$emit('click', {
+					detail: this.isShow
+				})
+			},
+			open() {
+				clearTimeout(this.timer)
+				this.isShow = true
+				this.transform = ''
+				this.ani.in = ''
+				for (let i in this.getTranfrom(false)) {
+					if (i === 'opacity') {
+						this.ani.in = 'fade-in'
+					} else {
+						this.transform += `${this.getTranfrom(false)[i]} `
+					}
+				}
+				this.$nextTick(() => {
+					setTimeout(() => {
+						this._animation(true)
+					}, 50)
+				})
+
+			},
+			close(type) {
+				clearTimeout(this.timer)
+				this._animation(false)
+			},
+			_animation(type) {
+				let styles = this.getTranfrom(type)
+				// #ifdef APP-NVUE
+				if(!this.$refs['ani']) return
+				animation.transition(this.$refs['ani'].ref, {
+					styles,
+					duration: this.duration, //ms
+					timingFunction: 'ease',
+					needLayout: false,
+					delay: 0 //ms
+				}, () => {
+					if (!type) {
+						this.isShow = false
+					}
+					this.$emit('change', {
+						detail: this.isShow
+					})
+				})
+				// #endif
+				// #ifndef APP-NVUE
+				this.transform = ''
+				for (let i in styles) {
+					if (i === 'opacity') {
+						this.ani.in = `fade-${type?'out':'in'}`
+					} else {
+						this.transform += `${styles[i]} `
+					}
+				}
+				this.timer = setTimeout(() => {
+					if (!type) {
+						this.isShow = false
+					}
+					this.$emit('change', {
+						detail: this.isShow
+					})
+
+				}, this.duration)
+				// #endif
+
+			},
+			getTranfrom(type) {
+				let styles = {
+					transform: ''
+				}
+				this.modeClass.forEach((mode) => {
+					switch (mode) {
+						case 'fade':
+							styles.opacity = type ? 1 : 0
+							break;
+						case 'slide-top':
+							styles.transform += `translateY(${type?'0':'-100%'}) `
+							break;
+						case 'slide-right':
+							styles.transform += `translateX(${type?'0':'100%'}) `
+							break;
+						case 'slide-bottom':
+							styles.transform += `translateY(${type?'0':'100%'}) `
+							break;
+						case 'slide-left':
+							styles.transform += `translateX(${type?'0':'-100%'}) `
+							break;
+						case 'zoom-in':
+							styles.transform += `scale(${type?1:0.8}) `
+							break;
+						case 'zoom-out':
+							styles.transform += `scale(${type?1:1.2}) `
+							break;
+					}
+				})
+				return styles
+			},
+			_modeClassArr(type) {
+				let mode = this.modeClass
+				if (typeof(mode) !== "string") {
+					let modestr = ''
+					mode.forEach((item) => {
+						modestr += (item + '-' + type + ',')
+					})
+					return modestr.substr(0, modestr.length - 1)
+				} else {
+					return mode + '-' + type
+				}
+			},
+			// getEl(el) {
+			// 	console.log(el || el.ref || null);
+			// 	return el || el.ref || null
+			// },
+			toLine(name) {
+				return name.replace(/([A-Z])/g, "-$1").toLowerCase();
+			}
+		}
+	}
+</script>
+
+<style>
+	.uni-transition {
+		transition-timing-function: ease;
+		transition-duration: 0.3s;
+		transition-property: transform, opacity;
+	}
+
+	.fade-in {
+		opacity: 0;
+	}
+
+	.fade-active {
+		opacity: 1;
+	}
+
+	.slide-top-in {
+		/* transition-property: transform, opacity; */
+		transform: translateY(-100%);
+	}
+
+	.slide-top-active {
+		transform: translateY(0);
+		/* opacity: 1; */
+	}
+
+	.slide-right-in {
+		transform: translateX(100%);
+	}
+
+	.slide-right-active {
+		transform: translateX(0);
+	}
+
+	.slide-bottom-in {
+		transform: translateY(100%);
+	}
+
+	.slide-bottom-active {
+		transform: translateY(0);
+	}
+
+	.slide-left-in {
+		transform: translateX(-100%);
+	}
+
+	.slide-left-active {
+		transform: translateX(0);
+		opacity: 1;
+	}
+
+	.zoom-in-in {
+		transform: scale(0.8);
+	}
+
+	.zoom-out-active {
+		transform: scale(1);
+	}
+
+	.zoom-out-in {
+		transform: scale(1.2);
+	}
+</style>

File diff ditekan karena terlalu besar
+ 36 - 0
HX-SHOP/components/watch-login/css/icon.css


+ 109 - 0
HX-SHOP/components/watch-login/watch-button.vue

@@ -0,0 +1,109 @@
+<template>
+	<view>
+		<!-- 按钮 -->
+		<button :class="['buttonBorder',!_rotate?'dlbutton':'dlbutton_loading']" :style="{'background':bgColor, 'color': fontColor}">
+			<view :class="_rotate?'rotate_loop':''">
+				<text v-if="_rotate" class="cuIcon cuIcon-loading1 "></text>
+				<text v-if="!_rotate">{{ text }}</text>
+			</view>
+		</button>
+	</view>
+</template>
+
+<script>
+	export default{
+		props:{
+			text: String, //显示文本
+			rotate:{
+				//是否启动加载
+				type: [Boolean,String],
+				default: false,
+			}, 
+			bgColor:{
+				//按钮背景颜色
+				type: String,
+				default: "linear-gradient(to right, rgba(255, 231, 21, 0.8), rgba(255, 193, 7, 0.8))",
+			},
+			fontColor:{
+				//按钮字体颜色
+				type: String,
+				default: "#FFFFFF",
+			},
+		},
+		computed:{
+			_rotate() {
+				//处理值
+				return String(this.rotate) !== 'false'
+			},
+		}
+	}
+</script>
+
+<style>
+	@import url("./css/icon.css");
+	
+	.dlbutton {
+		color: #FFFFFF;
+		font-size: 30upx;
+		width:601upx;
+		height:100upx;
+		background:linear-gradient(to right, rgba(0,0,0,0.7), rgba(0,0,0,0.6));
+		box-shadow:0upx 0upx 13upx 0upx rgba(164,217,228,0.4);
+		border-radius:2.5rem;
+		line-height: 100upx;
+		text-align: center;
+		margin-left: auto;
+		margin-right: auto;
+		margin-top: 96upx;
+	}
+	.dlbutton_loading {
+		color: #FFFFFF;
+		font-size: 30upx;
+		width:100upx;
+		height:100upx;
+		background:linear-gradient(to right, rgba(0,0,0,0.7), rgba(0,0,0,0.6));
+		box-shadow:0upx 0upx 13upx 0upx rgba(164,217,228,0.4);
+		border-radius:2.5rem;
+		line-height: 100upx;
+		text-align: center;
+		margin-left: auto;
+		margin-right: auto;
+		margin-top: 96upx;
+	}
+	.buttonBorder{
+	    border: none ;
+	    border-radius: 2.5rem ;
+	    -webkit-box-shadow: 0 0 60upx 0 rgba(57, 181, 74, 0.2);
+	    box-shadow: 0 0 60upx 0 rgba(57, 181, 74, 0.2);
+	    -webkit-transition: all 0.4s cubic-bezier(.57,.19,.51,.95);
+	    -moz-transition: all 0.4s cubic-bezier(.57,.19,.51,.95);
+	    -ms-transition: all 0.4s cubic-bezier(.57,.19,.51,.95);
+	    -o-transition: all 0.4s cubic-bezier(.57,.19,.51,.95);
+	    transition: all 0.4s cubic-bezier(.57,.19,.51,.95);
+	}
+	
+	/* 旋转动画 */
+	.rotate_loop{
+		-webkit-transition-property: -webkit-transform;
+	    -webkit-transition-duration: 1s;
+	    -moz-transition-property: -moz-transform;
+	    -moz-transition-duration: 1s;
+	    -webkit-animation: rotate 1s linear infinite;
+	    -moz-animation: rotate 1s linear infinite;
+	    -o-animation: rotate 1s linear infinite;
+	    animation: rotate 1s linear infinite;
+	}
+	@-webkit-keyframes rotate{from{-webkit-transform: rotate(0deg)}
+	    to{-webkit-transform: rotate(360deg)}
+	}
+	@-moz-keyframes rotate{from{-moz-transform: rotate(0deg)}
+	    to{-moz-transform: rotate(359deg)}
+	}
+	@-o-keyframes rotate{from{-o-transform: rotate(0deg)}
+	    to{-o-transform: rotate(359deg)}
+	}
+	@keyframes rotate{from{transform: rotate(0deg)}
+	    to{transform: rotate(359deg)}
+	}
+	button::after{ border: none;} 
+</style>

+ 208 - 0
HX-SHOP/components/watch-login/watch-input.vue

@@ -0,0 +1,208 @@
+<template>
+	<view class="main-list oBorder">
+		<!-- 文本框 -->
+		<input 
+			class="main-input" 
+			:value="value" 
+			:type="_type" 
+			:maxlength="maxlength" 
+			:placeholder="placeholder" 
+			:password="type==='password'&&!showPassword" 
+			@input="onInput"
+		/>
+		<!-- 是否可见密码 -->
+		<image 
+			v-if="_isShowPass&&type==='password'&&!_isShowCode"
+			class="img cuIcon" 
+			:class="showPassword?'cuIcon-attention':'cuIcon-attentionforbid'" 
+			@tap="showPass"
+		></image>
+		<!-- 倒计时 -->
+		<view 
+			v-if="_isShowCode&&!_isShowPass"
+			:class="['vercode',{'vercode-run': second>0}]" 
+			@click="setCode"
+		>{{ getVerCodeSecond }}</view>
+		
+	</view>
+</template>
+
+<script>
+	var _this, countDown;
+	export default{
+		data(){
+			return{
+				showPassword: false, //是否显示明文
+				second: 0, //倒计时
+				isRunCode: false, //是否开始倒计时
+			}
+		},
+		props:{
+			type: String, //类型
+			value: String, //值
+			placeholder: String, //框内提示
+			maxlength: {
+				//最大长度
+				type: [Number,String],
+				default: 20,
+			},
+			isShowPass:{
+				//是否显示密码图标(二选一)
+				type: [Boolean,String],
+				default: false,
+			},
+			isShowCode:{
+				//是否显示获取验证码(二选一)
+				type: [Boolean,String],
+				default: false,
+			},
+			codeText:{
+				type: String,
+				default: "获取验证码",
+			},
+			setTime:{
+				//倒计时时间设置
+				type: [Number,String],
+				default: 60,
+			}
+		},
+		model: {
+			prop: 'value',
+			event: 'input'
+		},
+		mounted() {
+			_this=this
+			//准备触发
+			this.$on('runCode',(val)=>{
+                this.runCode(val);
+            });
+			clearInterval(countDown);//先清理一次循环,避免缓存
+		},
+		methods:{
+			showPass(){
+				//是否显示密码
+				this.showPassword = !this.showPassword
+			},
+			onInput(e) {
+				//传出值
+				this.$emit('input', e.target.value)
+			},
+			setCode(){
+				//设置获取验证码的事件
+				if(this.isRunCode){
+					//判断是否开始倒计时,避免重复点击
+					return false;
+				}
+				this.$emit('setCode')
+			},
+			runCode(val){
+				//开始倒计时
+				if(String(val)=="0"){
+					
+					//判断是否需要终止循环
+					this.second = 0; //初始倒计时
+					clearInterval(countDown);//清理循环
+					this.isRunCode= false; //关闭循环状态
+					return false;
+				}
+				if(this.isRunCode){
+					//判断是否开始倒计时,避免重复点击
+					return false;
+				}
+				this.isRunCode= true
+				this.second = this._setTime //倒数秒数
+				
+				let _this=this;
+				countDown = setInterval(function(){
+					_this.second--
+					if(_this.second==0){
+						_this.isRunCode= false
+						clearInterval(countDown)
+					}
+				},1000)
+			}
+			
+			
+		},
+		computed:{
+			_type(){
+				//处理值
+				const type = this.type
+				return type == 'password' ? 'text' : type
+			},
+			_isShowPass() {
+				//处理值
+				return String(this.isShowPass) !== 'false'
+			},
+			_isShowCode() {
+				//处理值
+				return String(this.isShowCode) !== 'false'
+			},
+			_setTime() {
+				//处理值
+				const setTime = Number(this.setTime)
+				return setTime>0 ? setTime : 60
+			},
+			getVerCodeSecond(){
+				//验证码倒计时计算
+				if(this.second<=0){
+					return this.codeText;
+				}else{
+					if(this.second<10){
+						return '0'+this.second;
+					}else{
+						return this.second;
+					}
+				}
+				
+			}
+		}
+	}
+</script>
+
+<style>
+	@import url("./css/icon.css");
+	
+	.main-list{
+		display: flex;
+		flex-direction: row;
+		justify-content: space-between;
+		align-items: center;
+		height: 36upx;   /* Input 高度 */
+		color: #333333;
+		padding: 32upx;
+		margin-top:24upx;
+		margin-bottom: 24upx;
+		    
+	}
+	.img{
+		width: 32upx;
+		height: 32upx;
+		font-size: 32upx;
+	}
+	.main-input{
+		flex: 1;
+		text-align: left;
+		font-size: 28upx;
+		/* line-height: 100upx; */
+		padding-right: 10upx;
+		margin-left: 20upx;
+	}
+	.vercode {
+		color: rgba(0,0,0,0.7);
+		font-size: 24upx;
+		line-height: 100upx;
+	}
+	.vercode-run {
+		color: rgba(0,0,0,0.4) !important;
+	}
+	.oBorder{
+	    border: none;
+	    border-radius: 2.5rem ;
+	    /* -webkit-box-shadow: 0 0 60upx 0 rgba(43,86,112,.1) ;
+	    box-shadow: 0 0 60upx 0 rgba(43,86,112,.1) ; */
+		background: #fff;
+		height: 40px;
+	}
+	
+</style>

+ 18 - 0
HX-SHOP/config.js

@@ -0,0 +1,18 @@
+
+export default {
+	server: "http://192.168.0.15:666",
+	appName: "云同城",
+	
+	
+	// #ifdef APP-PLUS
+	version: plus.runtime.version,
+	varsionCode: plus.runtime.versionCode,
+	// #endif
+	// #ifndef APP-PLUS
+	version: '1.0.0',
+	// #endif
+	author: "吃酸菜的鱼",
+	company: "汇贤网络技术有限公司",
+	companyEN: "HuiXian"
+}
+

+ 37 - 0
HX-SHOP/main.js

@@ -0,0 +1,37 @@
+import Vue from 'vue'
+import App from './App'
+
+import store from './store/index';
+Vue.prototype.$store = store;
+
+//配置
+import config from './config.js'
+Vue.prototype.$conf = config
+
+Vue.prototype.$msg = (title, duration=1500, mask=false, icon='none')=>{
+	//统一提示方便全局修改
+	if(Boolean(title) === false){
+		return;
+	}
+	uni.showToast({
+		title,
+		duration,
+		mask,
+		icon
+	});
+}
+
+import api from './common/vmeitime-http/index.js'
+Vue.prototype.$api = api
+
+import appupgrade from './common/appupgrade.js'
+Vue.prototype.$appUpgrade = appupgrade
+
+Vue.config.productionTip = false
+
+App.mpType = 'app'
+
+const app = new Vue({
+    ...App
+})
+app.$mount()

+ 81 - 0
HX-SHOP/manifest.json

@@ -0,0 +1,81 @@
+{
+    "name" : "HX-SHOP",
+    "appid" : "",
+    "description" : "",
+    "versionName" : "1.0.0",
+    "versionCode" : "100",
+    "transformPx" : false,
+    "app-plus" : {
+        /* 5+App特有相关 */
+        "splashscreen" : {
+            "alwaysShowBeforeRender" : true,
+            "waiting" : true,
+            "autoclose" : true,
+            "delay" : 0
+        },
+        "modules" : {
+            "Maps" : {},
+            "Payment" : {}
+        },
+        /* 模块配置 */
+        "distribute" : {
+            /* 应用发布信息 */
+            "android" : {
+                /* android打包配置 */
+                "permissions" : [
+                    "<uses-feature android:name=\"android.hardware.camera\"/>",
+                    "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CALL_PHONE\"/>",
+                    "<uses-permission android:name=\"android.permission.CAMERA\"/>",
+                    "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
+                    "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
+                    "<uses-permission android:name=\"android.permission.INTERNET\"/>",
+                    "<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
+                    "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_CONTACTS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
+                    "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
+                    "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
+                    "<uses-permission android:name=\"android.permission.WRITE_CONTACTS\"/>",
+                    "<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"/>",
+                    "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
+                ]
+            },
+            "ios" : {},
+            /* ios打包配置 */
+            "sdkConfigs" : {
+                "ad" : {},
+                "payment" : {
+                    "alipay" : {}
+                },
+                "maps" : {
+                    "amap" : {
+                        "appkey_ios" : "00b5200c6368e8c26632edbfc7197df8",
+                        "appkey_android" : "00b5200c6368e8c26632edbfc7197df8"
+                    }
+                }
+            }
+        },
+        "compilerVersion" : 3
+    },
+    /* SDK配置 */
+    "quickapp" : {},
+    /* 快应用特有相关 */
+    "mp-weixin" : {
+        "appid" : "",
+        "setting" : {
+            "urlCheck" : true,
+            "es6" : true,
+            "minified" : true
+        }
+    },
+    "vueVersion" : "2"
+}

+ 11 - 0
HX-SHOP/package-lock.json

@@ -0,0 +1,11 @@
+{
+  "requires": true,
+  "lockfileVersion": 1,
+  "dependencies": {
+    "crypto-js": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.0.0.tgz",
+      "integrity": "sha512-bzHZN8Pn+gS7DQA6n+iUmBfl0hO5DJq++QP3U6uTucDtk/0iGpXd/Gg7CGR0p8tJhofJyaKoWBuJI4eAO00BBg=="
+    }
+  }
+}

+ 222 - 0
HX-SHOP/pages.json

@@ -0,0 +1,222 @@
+{
+	"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
+		{
+			"path": "pages/index/index",
+			"style": {
+				"navigationBarTitleText": "超市",
+				"app-plus": {
+					"scrollIndicator": "none"
+					//"enablePullDownRefresh": true
+				}
+			}
+		}, {
+			"path": "pages/store/index",
+			"style": {
+				"app-plus": {
+					"scrollIndicator": "none"
+				}
+			}
+		}
+
+		, {
+			"path": "pages/product/product",
+			"style": {
+				"app-plus": {
+					"animationType": "zoom-out",
+					"animationDuration": 300
+				}
+			}
+		}
+
+		, {
+			"path": "pages/user/login/login",
+			"style": {
+				"app-plus": {
+					"scrollIndicator": "none"
+				}
+			}
+		}, {
+			"path": "pages/user/register/register",
+			"style": {
+				"app-plus": {
+					"scrollIndicator": "none"
+				}
+			}
+		}, {
+			"path": "pages/user/forget/forget",
+			"style": {
+				"app-plus": {
+					"scrollIndicator": "none"
+				}
+			}
+		}, {
+			"path": "pages/user/center/center",
+			"style": {
+				"app-plus": {
+					"scrollIndicator": "none"
+				}
+			}
+		}, {
+			"path": "pages/user/setting/setting",
+			"style": {}
+		}, {
+			"path": "pages/user/bash/bash",
+			"style": {
+				"app-plus": {
+					"scrollIndicator": "none"
+				}
+			}
+		}
+
+		, {
+			"path": "pages/user/account_security/security",
+			"style": {}
+		}, {
+			"path": "pages/user/account_security/phone",
+			"style": {}
+		}, {
+			"path": "pages/user/account_security/update_password",
+			"style": {}
+		}, {
+			"path": "pages/user/account_security/address_book",
+			"style": {}
+		}, {
+			"path": "pages/user/account_security/update_phone",
+			"style": {}
+		}, {
+			"path": "pages/user/account_security/bind_phone",
+			"style": {}
+		}, {
+			"path": "pages/base/protocol/protocol",
+			"style": {}
+		}, {
+			"path": "pages/base/about",
+			"style": {}
+		}, {
+			"path": "pages/base/features",
+			"style": {}
+		}, {
+			"path": "pages/base/release_notes",
+			"style": {}
+		}, {
+			"path": "pages/base/help_feedback",
+			"style": {}
+		}, {
+			"path": "pages/base/help_problem",
+			"style": {}
+		}, {
+			"path": "pages/user/account_security/forget_password",
+			"style": {}
+		}, {
+			"path": "pages/user/account_security/verification_phone",
+			"style": {}
+		}
+
+		, {
+			"path": "pages/user/address/address",
+			"style": {}
+		}, {
+			"path": "pages/user/address/addressManage",
+			"style": {}
+		}
+
+		, {
+			"path": "pages/order/order",
+			"style": {}
+		}, {
+			"path": "pages/order/preview",
+			"style": {
+				"app-plus": {
+					"scrollIndicator": "none"
+				}
+			}
+		}, {
+			"path": "pages/order/pay",
+			"style": {
+				"app-plus": {
+					"scrollIndicator": "none"
+				}
+			}
+		}, {
+			"path": "pages/search/search",
+			"style": {}
+		}, {
+			"path": "pages/user/coupon/coupon",
+			"style": {}
+		}, {
+			"path": "pages/map/location",
+			"style": {
+
+			}
+		},
+		{
+			"path": "pages/index/detail",
+			"style": {
+
+			}
+		}, {
+			"path": "pages/market/market",
+			"style": {
+				"navigationBarTitleText": "",
+				"enablePullDownRefresh": false
+			}
+
+		}
+	],
+	"globalStyle": {
+		"navigationBarTextStyle": "black",
+		"navigationBarTitleText": "uni-app",
+		"navigationBarBackgroundColor": "#F8F8F8",
+		"navigationStyle": "custom",
+		"backgroundColor": "#F8F8F8"
+	},
+	"tabBar": {
+		"color": "#C0C4CC",
+		"selectedColor": "#ffc107",
+		"borderStyle": "black",
+		"backgroundColor": "#ffffff",
+		"fontSize": "11px",
+		"spacing": "5px",
+		"list": [{
+				"pagePath": "pages/index/index",
+				"iconPath": "static/tabbar/tab-home.png",
+				"selectedIconPath": "static/tabbar/tab-home-current.png",
+
+				"text": "首页"
+			},
+			{
+				"pagePath": "pages/market/market",
+				"iconPath": "static/tabbar/tab-cart.png",
+				"selectedIconPath": "static/tabbar/tab-cart-current.png",
+				"text": "超市"
+			},
+			// {
+			// 	"pagePath": "pages/user/address/address",
+			// 	"iconPath": "static/tabbar/tab-cart.png",
+			// 	"selectedIconPath": "static/tabbar/tab-cart-current.png",
+			// 	"text": "购物车"
+			// },
+
+			// {
+			// 	"pagePath": "pages/order/order",
+			// 	"iconPath": "static/tabbar/order.png",
+			// 	"selectedIconPath": "static/tabbar/order-current.png",
+			// 	"text": "订单"
+			// },
+			{
+				"pagePath": "pages/user/center/center",
+				"iconPath": "static/tabbar/tab-my.png",
+				"selectedIconPath": "static/tabbar/tab-my-current.png",
+				"text": "我的"
+			}
+		]
+	},
+	"condition": { //模式配置,仅开发期间生效
+		"current": 0, //当前激活的模式(list 的索引项)
+		"list": [{
+			"name": "test", //模式名称
+			"path": "pages/store/index", //启动页面,必选
+			"query": "" //启动参数,在页面的onLoad函数里面得到
+		}]
+	}
+}

+ 193 - 0
HX-SHOP/pages/base/about.vue

@@ -0,0 +1,193 @@
+<template>
+	<view>
+		<hx-navbar left-text="关于" defaultBackUrl="/pages/user/setting/setting"></hx-navbar>
+		
+		<view class="container">
+			<image src="../../static/img/logo96x96.png" mode=""></image>
+			<view class="title margin-top">
+				<text>{{appName}}</text>
+			</view>
+			<text class="vsersion">版本号 {{version}}</text>
+		</view>
+	
+		<view class="cu-list menu sm-border">
+			
+			<navigator class="cu-item arrow " url="features" open-type="navigate">
+				<view class="content">
+					<text class="text-black">功能介绍</text>
+				</view>
+				<view class="action">
+					<text class="text-grey text-sm"></text>
+				</view>
+			</navigator>
+			<!-- #ifdef APP-PLUS -->
+			<view class="cu-item arrow " @click="upgrade">
+				<view class="content">
+					<text class="text-black">检测更新</text>
+				</view>
+				<view class="action">
+					<text class="text-grey text-sm"></text>
+				</view>
+			</view>
+			<!-- #endif -->
+			<navigator class="cu-item arrow " url="protocol/protocol" open-type="navigate">
+				<view class="content">
+					<text class="text-black">服务协议</text>
+				</view>
+				<view class="action">
+					<text class="text-grey text-sm"></text>
+				</view>
+			</navigator>
+		</view>
+		<view class="foot">
+			<view class="solid-bottom text-xs padding justify-center">
+				<text class="text-gray">{{company}} 版权所有</text>
+				<view></view>
+				<text class="text-gray">Copyright © 2019-{{nowYear}} {{companyEN}}</text>
+				<view></view>
+				<text class="text-gray">All Rights Reserved</text>
+				
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	var that;
+	export default {
+		data() {
+			return {
+				appName: this.$conf.appName,
+				version: this.$conf.version,
+				company: this.$conf.company,
+				companyEN: this.$conf.companyEN,
+				nowYear: 2019,
+				server: this.$conf.server
+			}
+		},
+		onLoad(){
+			
+		},
+		mounted() {
+			that= this;
+			var myDate = new Date();
+			that.nowYear = myDate.getFullYear();
+		},
+		methods: {
+			// #ifdef APP-PLUS
+			upgrade(){
+				let that = this;
+				 plus.runtime.getProperty(plus.runtime.appid,function(inf){ 
+				        that.$appUpgrade.checkUpgrade( inf.version); 
+				        //sessionStorage.setItem('upgrade','1');
+				 });  
+				/* uni.showLoading({
+				    title: '获取最新版本中'
+				});
+				setTimeout(function () {
+				    uni.hideLoading();
+					uni.showToast({
+					    title: '已是最新版本',
+						position: 'center',
+					});
+				}, 2000); */
+			},
+			
+			//检查更新
+			checkUpgrade(wgtVer){
+				let that = this;
+				plus.nativeUI.showWaiting("检测更新...");
+				that.$api.app.upgrade({version:wgtVer}).then((res)=>{
+					plus.nativeUI.closeWaiting();
+					let resData = res.data;
+					if( parseInt(resData.code) ==1 ){                           
+						//可以升级
+						plus.nativeUI.confirm("检查到当前版本有最新更新,下载升级?",
+							function(event){
+								if(event.index ==0){
+									console.log('下载地址:'+ server + resData.url)
+									downWgt(server + resData.url); //下载更新版的地址
+								}                        
+							} ,'系统消息',['马上升级','下次再说']);                
+					} else{  
+						plus.nativeUI.toast("无新版本可更新!");
+					}
+				}).catch((e)=>{
+					plus.nativeUI.closeWaiting();
+					 plus.nativeUI.toast('检测更新失败!') ;
+				})
+			},
+			// 下载wgt文件
+			downWgt(wgtUrl){
+			    plus.nativeUI.showWaiting("下载更新文件...");
+			    plus.downloader.createDownload( wgtUrl, {filename:"_doc/update/"}, function(d,status){
+			        if ( status == 200 ) { 
+			            //console.log("下载wgt成功:"+d.filename);
+			            installWgt(d.filename); // 安装wgt包
+			        } else {
+			            //console.log("下载wgt失败!");
+			            plus.nativeUI.alert("下载更新失败!");
+			        }
+			        plus.nativeUI.closeWaiting();
+			    }).start();
+			},
+			
+			// 更新应用资源  
+			installWgt(path){
+			    plus.nativeUI.showWaiting("正在安装更新文件...");
+			    plus.runtime.install(path,{},function(){
+			        plus.nativeUI.closeWaiting();        
+			        plus.nativeUI.alert("应用资源更新完成!",function(){
+			            plus.runtime.restart();
+			        });
+			    },function(e){
+			        plus.nativeUI.closeWaiting();        
+			        plus.nativeUI.alert("安装更新文件失败["+e.code+"]:"+e.message);
+			    });
+			}
+			
+			// #endif
+		}
+	}
+</script>
+
+<style>
+	page{
+		background: #ffffff;
+	}
+	.cu-list.menu {
+	    margin-left:24upx;
+		margin-right:24upx;
+		border-top: 2upx solid #f1f1f1;
+	    border-bottom: 2upx solid #f1f1f1;
+	}
+	.text-grey{
+		color: #555555;
+	}
+	.container{
+		margin-top: 60upx;
+		margin-bottom: 60upx;
+		text-align: center;
+	}
+	.container image{
+		width: 192upx;
+		height: 192upx;
+	}
+	.title{
+		font-size: 40upx;
+		font-weight: bold;
+		color: #333333;
+		text-align: center;
+		margin-bottom: 8upx;
+	}
+	.version{
+		font-size: 32upx;
+		color: #333333;
+	}
+	.foot{
+		position: absolute;
+		bottom: 10upx;
+		text-align: center;
+		width: 100%;
+	}
+</style>

+ 45 - 0
HX-SHOP/pages/base/features.vue

@@ -0,0 +1,45 @@
+<template>
+	<view>
+		<hx-navbar left-text="功能介绍" :border="true" defaultBackUrl="about"></hx-navbar>
+		<view class="cu-list menu sm-border">
+			
+			<navigator class="cu-item arrow " url="release_notes?v=202" open-type="navigate">
+				<view class="content">
+					<text class="text-black">1.0.1主要更新</text>
+				</view>
+				<view class="action">
+					<text class="text-black text-sm">11月11日</text>
+				</view>
+			</navigator>
+			<navigator class="cu-item arrow " url="release_notes?v=201" open-type="navigate">
+				<view class="content">
+					<text class="text-black">1.0.0主要更新</text>
+				</view>
+				<view class="action">
+					<text class="text-black text-sm">10月8日</text>
+				</view>
+			</navigator>
+			
+			
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				
+			}
+		},
+		methods: {
+			
+		}
+	}
+</script>
+
+<style>
+page{
+	background: #fff;
+}
+</style>

+ 65 - 0
HX-SHOP/pages/base/help_feedback.vue

@@ -0,0 +1,65 @@
+<template>
+	<view>
+		<hx-navbar left-text="帮助与反馈" defaultBackUrl="/pages/user/setting/setting" :background-color="[245,245,245]"></hx-navbar>
+		
+		<view class="flex-sub ">
+			<view class="solid-bottom text-df padding">
+				<text class="text-gray">热点问题</text>
+			</view>
+		</view>
+		<view class="cu-list menu sm-border">
+			<navigator class="cu-item arrow " url="help_problem?v=202" open-type="navigate">
+				<view class="content">
+					<text class="text-black">如何使用用户帮助功能?</text>
+				</view>
+			</navigator>
+			<navigator class="cu-item arrow " url="help_problem?v=201" open-type="navigate">
+				<view class="content">
+					<text class="text-black">该app能不能推荐给我的朋友,或者网友呢?</text>
+				</view>
+			</navigator>
+			<navigator class="cu-item arrow " url="help_problem?v=201" open-type="navigate">
+				<view class="content">
+					<text class="text-black">该app能不能推荐给我的朋友,或者网友呢?</text>
+				</view>
+			</navigator>
+			<navigator class="cu-item arrow " url="help_problem?v=201" open-type="navigate">
+				<view class="content">
+					<text class="text-black">该app能不能推荐给我的朋友,或者网友呢?</text>
+				</view>
+			</navigator>
+			<navigator class="cu-item arrow " url="help_problem?v=201" open-type="navigate">
+				<view class="content">
+					<text class="text-black">该app能不能推荐给我的朋友,或者网友呢?</text>
+				</view>
+			</navigator>
+			<navigator class="cu-item arrow " url="help_problem?v=201" open-type="navigate">
+				<view class="content">
+					<text class="text-black">该app能不能推荐给我的朋友,或者网友呢?</text>
+				</view>
+			</navigator>
+		</view> 
+		
+		<view class="cu-bar flex foot">
+			<button class="cu-btn lg text-grey" style="width: 100%;"><uni-icons style="chat" size="30"></uni-icons>意见反馈</button>
+			
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				
+			}
+		},
+		methods: {
+			
+		}
+	}
+</script>
+
+<style>
+
+</style>

+ 23 - 0
HX-SHOP/pages/base/help_problem.vue

@@ -0,0 +1,23 @@
+<template>
+	<view>
+		<hx-navbar left-text="帮助" defaultBackUrl="help_feedback" :background-color="[245,245,245]"></hx-navbar>
+		
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				
+			}
+		},
+		methods: {
+			
+		}
+	}
+</script>
+
+<style>
+
+</style>

+ 288 - 0
HX-SHOP/pages/base/protocol/protocol.vue

@@ -0,0 +1,288 @@
+<template>
+	<view>
+		<hx-navbar
+			:status-bar="true"
+			:fixed="true"
+			transparent="show"
+			title="用户协议"
+			:border="true"
+			defaultBackUrl="../about">
+		</hx-navbar>
+		<view class="main">
+			<text>
+				欢迎您使用 ZSD 同城的服务!
+				为使用 ZSD 同城的服务,您应当阅读并遵守《ZSD 同城使用协议》和《ZSD 同城隐私权条款》。本协议
+				是用户与 ZSD 同城之间的法律协议,是用户注册 ZSD 同城平台账号和/或使用 ZSD 同城服务时使用的通用条
+				款。请您务必审慎阅读、充分理解各条款内容,特别是免除或者限制责任的条款、管辖与法律适用条
+				款。限制、免责条款可能以黑体加粗或加下划线的形式提示您重点注意。您不应当以 ZSD 同城未对本协议
+				以合理方式提醒用户注意或未根据用户要求尽到说明义务为理由而声称或要求法院或其它任何第三方确
+				认相关条款非法或无效。除非您已阅读并接受本协议所有条款,否则您无权使用 ZSD 同城提供的服务。您
+				使用 ZSD 同城的服务即视为您已阅读并同意上述协议的约束。
+				一、定义
+				ZSD 同城平台,是指北京五八信息技术有限公司旗下运营之 ZSD 同城网站(www.ZSD.com)、ZSD 同城无
+				线站点(包括 wap.ZSD.com,m.ZSD.com)及 ZSD 同城移动应用软件(APP)。
+				用户,包含注册用户和非注册用户,以下亦称为“您”。注册用户是指通过 ZSD 同城平台完成全部注册
+				程序后,使用 ZSD 同城平台服务或 ZSD 同城网站资料的用户。非注册用户是指未进行注册、直接登录 ZSD 同
+				城平台或通过其他网站进入 ZSD 同城平台直接或间接地使用 ZSD 同城平台服务或 ZSD 同城网站资料的用户。
+				协议方,本协议中协议双方合称“协议方”。北京五八信息技术有限公司及其相关服务可能存在的运营
+				关联单位、ZSD 同城平台在协议中统称为"ZSD 同城"。
+				二、协议的效力
+				1、在您按照注册页面提示填写信息、阅读并同意本协议并完成全部注册程序后或以其他 ZSD 同城允
+				许的方式实际使用 ZSD 同城平台服务时,您即受本协议的约束。
+				2、本协议内容包括本协议正文、《ZSD 同城隐私权条款》(如需进一步了解,请点击
+				https://about.ZSD.com/395.html),且您在使用 ZSD 同城某一特定服务时,该服务可能会另有单独的协
+				议、相关业务规则等(以下统称为“规则”)。所有 ZSD 同城已经发布的或将来可能发布的规则为本协议不
+				可分割的组成部分,与本协议具有同等法律效力。除另行明确声明外,任何 ZSD 同城及其关联公司提供的
+				服务(以下称为“ZSD 同城平台服务”)均受本协议约束。您承诺接受并遵守本协议的约定。如果您不同意
+				本协议的约定,您应立即停止注册程序或停止使用 ZSD 同城平台服务;如您继续访问和使用 ZSD 同城平台
+				服务,即视为您已确知并完全同意本协议各项内容。
+				3、ZSD 同城有权根据国家法律法规的更新、产品和服务规则的调整需要不时地制订、修改本协议及/
+				或各类规则,并提前以网站公示的方式进行公示。如您继续使用 ZSD 同城平台服务的,即表示您接受经修
+				订的协议和规则。如发生有关争议时,以 ZSD 同城最新的相关协议和规则为准。
+				三、注册
+				1、您确认,在您完成注册程序或以其他 ZSD 同城允许的方式实际使用 ZSD 同城平台服务时,您应当是
+				具备相应民事行为能力的自然人(十六周岁以上的未成年人,以自己的劳动收入为主要生活来源的,视为
+				完全民事行为能力人)、法人或其他组织。若您不具备前述主体资格,则您及您的家长或法定监护人(以
+				下统称"监护人")应承担因此而导致的一切后果,且 ZSD 同城有权注销您的账户,并向您及您的监护人索
+				偿。
+				2、ZSD 同城非常重视对青少年个人信息搜集和使用的安全性的保护。ZSD 同城建议,任何未满 18 周岁
+				的未成年人参加网上活动应事先取得其监护人可经查证的同意并遵守《全国青少年网络文明公约》。监护
+				人应承担未成年人网络活动风险及保护未成年人相关网络隐私的首要责任。
+				3、在您签署本协议,完成注册程序时,ZSD 同城会向您提供唯一编号的 ZSD 同城账户。您应对您的用
+				户账户、登录密码、支付密码(如有)、验证码的安全,以及对通过您的账户和密码实施的行为负责;
+				因此所衍生的任何损失或损害,ZSD 同城无法也不承担任何责任。除非有法律规定或行政司法机关的指
+				令,且征得 ZSD 同城的同意,否则您的用户账户、登录密码、支付密码(如有)和验证码不得以任何方式
+				。否则,
+				由此给您(或 ZSD 同城、任何第三方)造成的一切损失,概由您自行承担(或者负责赔偿)。
+				4、ZSD 同城承诺非经法定原因、本协议的约定或您的事先许可,ZSD 同城不会向任何第三方透露您的
+				注册账号、手机号码等非公开信息。如果发现任何人不当使用您的账户或有任何其他可能危及您的账户安
+				全的情形时,您应当立即以有效方式通知 ZSD 同城,要求 ZSD 同城暂停相关服务。您理解 ZSD 同城对您的请
+				求采取行动需要合理时间,ZSD 同城对在采取行动前已经产生的后果(包括但不限于您的任何损失)不承
+				担任何责任。
+				5、您在注册帐号或使用 ZSD 同城平台服务的过程中,应提供合法、真实、准确的个人资料,您填写
+				的个人资料有变动的,应及时进行更新。如果因您提供的个人资料不合法、不真实、不准确的,您需承担
+				因此引起的相应责任及后果,并且 ZSD 同城保留终止您使用 ZSD 同城各项服务的权利。
+				6、您了解并同意,如您符合并且遵守本协议条款,在通过 ZSD 同城平台完成注册程序之后,即可成
+				为 ZSD 同城平台注册用户。对于您主动提交的相关信息,您授权 ZSD 同城及/或 ZSD 同城网站运营者及关联服
+				务提供方委托的第三方通过合法渠道(包括但不限于征信机构等)了解、咨询、审查您的个人市场交易风
+				险的真实情况,并据此判断您的风险状况。
+				7、您不得通过任何手段恶意注册 ZSD 同城网站帐号,包括但不限于以牟利、炒作、套现等为目的多
+				个账号注册。您亦不得盗用其他用户帐号。
+				8、您了解并同意,一经注册用户账号,即视为您同意 ZSD 同城及/或其关联公司可以通过拨打电话、
+				发送短信或者电子邮件等方式向您注册时填写的手机号码、电子邮箱等发送、告知相应的产品服务广告信
+				息、促销优惠等营销信息;您如果不同意接收相关信息,您可以通过相应的退订功能或相关提示进行退
+				订。
+				四、ZSD 同城平台服务使用规范
+				1、通过 ZSD 同城平台,您可以按照 ZSD 同城的规则发布各种生活信息。但所发布之信息不得含有如下
+				内容:
+				1) 反对宪法所确定的基本原则,煽动抗拒、破坏宪法和法律、行政法规实施的;
+				2)煽动危害国家安全、泄露国家秘密、颠覆国家政权,推翻社会主义制度的;
+				3)煽动分裂国家、破坏国家统一、损害国家荣誉和民族利益的;
+				4)煽动民族仇恨、民族歧视,破坏民族团结的;
+				5)捏造或者歪曲事实,散布谣言,扰乱社会秩序的;
+				6)进行政治宣传或破坏国家宗教政策、宣扬封建迷信、淫秽、色情、赌博、暴力、凶杀、恐怖、教唆
+				犯罪的;
+				7)公然侮辱他人或者捏造事实诽谤他人的,或者进行其他恶意攻击的;
+				8)损害国家机关信誉的;
+				9)其他违反宪法和法律法规的;
+				2、在接受 ZSD 同城服务的过程中,您不得从事下列行为:
+				1)发表、传送、传播、储存侵害他人知识产权、商业秘密权等合法权利的内容,包含病毒、木马、
+				定时炸弹等可能对 ZSD 同城系统造成伤害或影响其稳定性的内容制造虚假身份以误导、欺骗他人;
+				2)传送或散布以其他方式实现传送的含有受到知识产权法律保护的图像、相片、软件或其他资料的
+				文件,作为举例(但不限于此):包括版权或商标法(或隐私权或公开权),除非用户拥有或控制着相应
+				的权利或已得到所有必要的认可;
+				3)使用任何包含有通过侵犯商标、版权、专利、商业机密或任何一方的其他专有权利的方式利用本
+				“软件”获得的图像或相片的资料或信息;
+				4)进行危害计算机网络安全的行为,包括但不限于:使用未经许可的数据或进入未经许可的服务器/
+				帐号;未经允许进入公众计算机网络或者他人计算机系统并删除、修改、增加存储信息;未经许可,企图
+				探查、扫描、测试本平台系统或网络的弱点或其它实施破坏网络安全的行为;企图干涉、破坏本平台系统
+				或网站的正常运行,故意传播恶意程序或病毒以及其他破坏干扰正常网络信息服务的行为;伪造 TCP/IP
+				数据包名称或部分名称;
+				5)修改或伪造软件作品运行中的指令、数据、数据包,增加、删减、变动软件 的功能或运行效果,
+				不得将用于上述用途的软件通过信息网络向公众传播或者运营;
+				6)在未经 ZSD 同城书面明确授权前提下,出售、出租、出借、散布、转移或转授权软件和服务或相
+				关的链接或从使用软件和服务或软件和服务的条款中获利,无论以上使用是否为直接经济或金钱收益;
+				7) 违背 ZSD 同城页面公布之活动规则,包括但不限于发布虚假信息、作弊或通过其他手段进行虚假
+				交易。
+				3、您了解并同意,ZSD 同城有权应政府部门(包括司法及行政部门)的要求,向其提供您在 ZSD 同城
+				平台填写的注册信息和发布纪录等必要信息,且无须征得您的同意或提前通知于您。
+				4、在 ZSD 同城平台上使用 ZSD 同城服务过程中,您承诺遵守以下约定:
+				1)在使用 ZSD 同城平台服务过程中实施的所有行为均遵守国家法律、法规等规范文件及 ZSD 同城平台各
+				项规则的规定和要求,不违背社会公共利益或公共道德,不损害他人的合法权益,不违反本协议及相关规
+				则。您如果违反前述承诺,产生任何法律后果的,您应以自己的名义独立承担所有的法律责任,并确保
+				ZSD 同城免于因此产生任何损失或增加费用。
+				2)不发布国家禁止发布的信息(除非取得合法且足够的许可),不发布涉嫌侵犯他人知识产权或其它
+				合法权益的信息,不发布违背社会公共利益或公共道德、公序良俗的信息,不发布其它涉嫌违法或违反本
+				协议及各类规则的信息。
+				3)不对 ZSD 同城平台上的任何数据作商业性利用,包括但不限于在未经 ZSD 同城事先书面同意的情况
+				下,以复制、传播等任何方式使用 ZSD 同城平台站上展示的资料。
+				4)不使用任何装置、软件或例行程序干预或试图干预 ZSD 同城平台的正常运作或正在 ZSD 同城平台上进
+				行的任何活动。您不得采取任何将导致不合理的庞大数据负载加诸 ZSD 同城平台网络设备的行动。
+				5、您了解并同意:
+				1)您违反上述承诺时,ZSD 同城有权依据本协议的约定,做出相应处理或终止向您提供服务,且无须
+				征得您的同意或提前通知于您。
+				2)根据相关法令的指定或者 ZSD 同城服务规则的判断,您的行为涉嫌违反法律法规的规定或违反本协
+				议和/或规则的条款的,ZSD 同城有权采取相应措施,包括但不限于直接屏蔽、删除侵权信息、降低您的信
+				用值或直接停止提供服务。如因此使 ZSD 同城遭受损失,或受到任何第三方的索赔,或受到任何行政管理
+				部门的处罚,您应当赔偿 ZSD 同城因此造成的损失及(或)发生的费用,包括合理的律师费用。
+				3)对于您在 ZSD 同城平台上实施的行为,包括您未在 ZSD 同城平台上实施但已经对 ZSD 同城平台及其用
+				户产生影响的行为,ZSD 同城有权单方认定您行为的性质及是否构成对本协议和/或规则的违反,并据此采
+				取相应的处理措施。您应自行保存与您行为有关的全部证据,并应对无法提供充要证据承担不利后果。
+				4)对于您涉嫌违反承诺的行为对任意第三方造成损害的,您均应当以自己的名义独立承担所有的法律
+				责任,并应确保 ZSD 同城免于承担因此产生的损失或增加的费用。
+				五、责任范围和责任限制
+				1、ZSD 同城负责向您提供 ZSD 同城平台服务。但 ZSD 同城对 ZSD 同城平台服务不作任何明示或暗示的保
+				证,包括但不限于 ZSD 同城平台服务的适用性、没有错误或疏漏、持续性、准确性、可靠性、适用于某一
+				特定用途。同时,ZSD 同城也不对 ZSD 同城平台服务所涉及的技术及信息的有效性、准确性、正确性、可
+				靠性、稳定性、完整性和及时性作出任何承诺和保证。
+				2、ZSD 同城仅向您提供 ZSD 同城平台服务,您了解 ZSD 同城平台上的信息系用户自行发布,由于海量
+				信息的存在,且 ZSD 同城平台无法杜绝可能存在风险和瑕疵。您应谨慎判断确定相关信息的真实性、合法
+				性和有效性,并注意保留相应的证据以利于维权,如可能,尽量采用网站建议的交易方式进行。
+				3、ZSD 同城平台与其他的在线使用的互联网网站一样,也会受到各种不良信息、网络安全和网络故障
+				问题的困扰,包括但不限于:
+				1)其他用户可能会发布诈骗或虚假信息,或者发表有谩骂、诅咒、诋毁、攻击内容的,或者含有淫
+				秽、色情、下流、反动、煽动民族仇恨等让人反感、厌恶的内容的非法言论;
+				2)其他用户可能会发布一些侵犯您或者其他第三方知识产权、肖像权、姓名权、名誉权、隐私权和/
+				或其他合法权益的图片、照片、文字等资料;
+				3)面临着诸如黑客攻击、计算机病毒困扰、系统崩溃、网络掉线、网速缓慢、程序漏洞等问题的困
+				扰和威胁。
+				您充分了解并同意:上述的各种不良信息、网络安全和网络故障问题,并不是 ZSD 同城或者 ZSD 同城
+				平台所导致的问题,由此可能会造成您感到反感、恶心、呕吐等精神损害,或者给您造成其他的损失,
+				概由您自行承担,ZSD 同城无须向您承担任何责任。
+				4、您同意,在发现本网站任何内容不符合法律规定,或不符合本用户协议规定的,您有义务及时通
+				知 ZSD 同城。如果您发现您的个人信息被盗用、您的版权或者其他权利被侵害,请将此情况告知 ZSD 同城
+				并同时提供如下信息和材料:
+				1)侵犯您权利的信息的网址,编号或其他可以找到该信息的细节;
+				2)您是所述的版权或者其他权利的合法拥有者的权利证明;
+				3)您的联系方式,包括联系人姓名,地址,电话号码和电子邮件;
+				4)您的身份证复印件、营业执照等其他相关资料。
+				经审查得到证实的,我们将及时删除相关信息。我们仅接受邮寄、电子邮件或传真方式的书面侵权通
+				知。情况紧急的,您可以通过客服电话先行告知,我们会视情况采取相应措施。
+				5、您了解并同意,ZSD 同城不对因下述任一情况而导致您的任何损害赔偿承担责任,包括但不限于利
+				润、商誉、使用、数据等方面的损失或其它无形损失的损害赔偿:
+				1) 使用或未能使用 ZSD 同城平台服务;
+				2) 第三方未经批准地使用您的账户或更改您的数据;
+				3) 通过 ZSD 同城平台服务购买或获取任何商品、样品、数据、信息等行为或替代行为产生的费用及损
+				失;
+				4) 您对 ZSD 同城平台服务的误解;
+				5) 任何非因 ZSD 同城的原因而引起的与 ZSD 同城平台服务有关的其它损失。
+				6、您在 ZSD 同城上使用第三方提供的产品或服务时,除遵守本协议约定外,还应遵守第三方的用户
+				协议。ZSD 同城和第三方对可能出现的纠纷在法律规定和约定的范围内各自承担责任。
+				7、您同意在使用 ZSD 同城平台服务过程中显示 ZSD 同城自行或由第三方服务商向您发送的推广或宣传
+				信息(包括商业与非商业信息),其方式和范围可不经向您特别通知而变更。除法律法规明确规定外,
+				您应自行对依该推广信息进行的交易负责,对用户因依该推广信息进行的交易或前述第三方服务商提供
+				的内容而遭受的损失或损害,ZSD 同城不承担任何责任。
+				8、ZSD 同城对下列不可抗力行为免责:信息网络正常的设备维护,信息网络连接故障,电脑、通讯或
+				其他系统的故障,电力故障,罢工,劳动争议,暴乱,起义,骚乱,生产力或生产资料不足,火灾,洪
+				水,风暴,爆炸,战争,政府行为,司法行政机关的命令或第三方的不作为而造成的不能服务或延迟服
+				务。
+				9、您应当严格遵守本协议及 ZSD 同城发布的其他协议、活动规则,因您违反协议或规则的行为给第
+				三方或 ZSD 同城造成损失的,您应当承担全部责任。
+				10、ZSD 同城保留在中华人民共和国大陆地区法施行之法律允许的范围内独立决定拒绝服务、关闭用
+				户账户、清除或编辑内容或取消订单的权利。
+				六、协议终止
+				1、您同意,ZSD 同城基于平台服务的安全性,有权中止向您提供部分或全部 ZSD 同城平台服务,暂时
+				冻结您的账户,待安全问题解决后及时恢复,并对中止、冻结及恢复的事实及时通知。如果网站的安全问
+				题是由于您的违法行为引起,ZSD 同城有权终止向您提供部分或全部 ZSD 同城平台服务,永久冻结(注销)
+				您的帐户,并有权向您对损失进行索赔。
+				2、如您对本协议的修改有异议,或对 ZSD 同城的服务不满,可以行使如下权利:
+				1)停止使用 ZSD 同城的网络服务;
+				2)通过客服等渠道告知 ZSD 同城停止对其服务。结束服务后,您使用 ZSD 同城服务的权利立即终止。
+				在此情况下,ZSD 同城没有义务传送任何未处理的信息或未完成的服务给您或任何无直接关系的第三方。
+				3、您同意,您与 ZSD 同城的协议关系终止后,ZSD 同城仍享有下列权利:
+				1) 继续保存您未及时删除的注册信息及您使用 ZSD 同城平台服务期间发布的所有信息至法律规定的记
+				录保存期满。
+				2)您在使用 ZSD 同城平台服务期间存在违法行为或违反本协议和/或规则的行为的,ZSD 同城仍可依据
+				本协议向您主张权利、追究责任。
+				七、隐私权政策
+				1、ZSD 同城将在 ZSD 同城平台公布并不时修订隐私权条款,隐私权条款构成本协议的有效组成部分。
+				2、您知悉并承诺在使用 ZSD 同城的服务过程中,遵守《ZSD 同城隐私权条款》(网址:
+				https://about.ZSD.com/395.html)。
+				3、ZSD 同城要求各搜索引擎遵循行业规范,即“拒绝 Robots 访问标准”(Robots Exclusion
+				Standard),否则将视你的抓取行为是对我网站财产权利和知识产权的侵犯,有权通过法律诉讼维护网站
+				利益。
+				八、知识产权声明
+				1、“ZSD 同城” 、 “五八同城 ” 、“ 网邻通 ”、 “ 五八帮帮”等为 ZSD 同城所在公司及其关联公司的商
+				标,受法律保护,任何人不得擅自使用。凡侵犯本公司版权等知识产权的,ZSD 同城将依法追究其相关法
+				律责任。
+				2、ZSD 同城平台所刊登的资料信息(包括但不限于编码、文字、图表、标识、按钮图标、图像、声音
+				文件片段、数字下载、数据编辑和软件),均是 ZSD 同城或其内容提供者的财产,受中国和国际版权法的
+				保护。本平台上所有内容的汇编是 ZSD 同城的排他财产,受中国和国际版权法的保护。本平台上所有软件
+				都是 ZSD 同城或其关联公司或其软件供应商的财产,受中国和国际版权法的保护。未经 ZSD 同城的明确书
+				面许可,任何第三方不得为任何非私人或商业目的获取或使用 ZSD 同城网站的任何部分或通过 ZSD 同城网
+				站可直接或间接获得的任何内容、服务或资料。任何第三方违反本协议的规定以任何方式,和/或以任何
+				文字对 ZSD 同城网站的任何部分进行发表、复制、转载、更改、引用、链接、下载或以其他方式进行使
+				用,或向任何其他第三方提供获取 ZSD 同城网站任何内容的渠道,则对 ZSD 同城网站的使用权将立即终
+				止,且任何第三方必须按照 ZSD 同城的要求,归还或销毁使用 ZSD 同城网站任何部分的内容所创建的资料
+				的任何副本。
+				3、用户一旦接受本协议,即表明该用户主动将其在任何时间段在本平台发表的任何形式的信息内容
+				(包括但不限于用户评价、用户咨询、各类话题文章等信息内容)的财产性权利等任何可转让的权利,如
+				著作权财产权(包括并不限于:复制权、发行权、出租权、展览权、表演权、放映权、广播权、信息网络
+				传播权、摄制权、改编权、翻译权、汇编权以及应当由著作权人享有的其他可转让权利),全部独家且不
+				可撤销地转让给 ZSD 同城所有,用户同意 ZSD 同城有权就任何主体侵权而单独提起诉讼。
+				4、本协议已经构成《中华人民共和国著作权法》第二十五条(条文序号依照 2010 年版著作权法确
+				定)及相关法律规定的著作财产权等权利转让的书面协议,其效力及于用户在 ZSD 同城平台上发布的任何
+				受著作权法保护的作品内容,无论该等内容形成于本协议订立前还是本协议订立后。
+				5、用户同意并已充分了解本协议的条款,承诺不将已发表于本站的信息,以任何形式发布或授权其
+				它主体以任何方式使用(包括但不限于在各类网站、媒体上使用)。
+				6、用户通过 ZSD 同城平台发布的信息或内容,并不代表 ZSD 同城之意见及观点,也不意味着 ZSD 同城
+				赞同其观点或证实其内容的真实性。ZSD 同城有权删除网站内各类不符合法律或本协议规定的信息或内
+				容,而保留不通知用户的权利。
+				7、用户通过 ZSD 同城平台发布的信息、文字、图片等资料均由 ZSD 同城用户提供,其真实性、准确性
+				和合法性由信息发布人负责。ZSD 同城不提供任何保证,并不承担任何法律责任。如果以上资料侵犯了第
+				三方的知识产权或其他权利,责任由信息发布者本人承担,ZSD 同城对此不承担责任。
+				8、除法律另有强制性规定外,未经 ZSD 同城明确的特别书面许可,任何单位或个人不得以任何方式
+				非法地全部或部分复制、传播、展示、镜像、上载、下载、转载、引用、链接、抓取或以其他方式使用本
+				站的信息内容,否则,ZSD 同城有权追究其法律责任。
+				9、ZSD 同城平台以下内容不可任意转载:
+				1)本平台内发布的所有信息;
+				2)已作出不得转载或未经许可不得转载声明的内容;
+				3)本平台中特有的图形、标志、页面风格、编排方式、程序等;
+				4)本平台中必须具有特别授权或具有注册用户资格方可知晓的内容;
+				5)其他法律不允许或本平台认为不适合转载的内容。
+				10、对于不当引用 ZSD 同城网站内容而引起的纷争等或因纠纷等造成的任何损失,ZSD 同城不承担相关
+				法律责任。对不遵守本声明的用户或其他违法、恶意使用 ZSD 同城网站内容者,ZSD 同城保留追究其法律责
+				任的权利。
+				11、ZSD 同城平台相关声明版权及其修改权、更新权和法律允许范围内的解释权均属 ZSD 同城所有。
+				九、法律适用、管辖与其他
+				1、本协议之订立、生效、解释、修订、补充、终止、执行与争议解决均适用中华人民共和国法律,
+				如法律无相关规定的,则应参照通用国际商业惯例和(或)行业惯例。
+				2、本协议任一条款被视为废止、无效或不可执行,该条应视为可分的且并不影响本协议其余条款的
+				有效性及可执行性。
+				3、因本协议产生之争议、纠纷,应由 ZSD 同城与您友好协商解决;协商不成的,应依照中华人民共
+				和国法律予以处理,并以北京市朝阳区人民法院为第一审管辖法院,按照中华人民共和国法律,因级别
+				管辖的规定,北京市朝阳区人民法院无权管辖的,以其上级法院作为第一审管辖法院。
+				为维护网民和相关权利人利益,北京五八信息技术有限公司已经以公示的方式,为用户及相关权利
+				人提供了丰富、便捷的线上线下投诉渠道(包括但不限于通过您的专属客服、ZSD 同城网站首页下方的违
+				法信息举报电话或者通过 ZSD 同城网站的帮助中心页面(网址:
+				https://about.ZSD.com/customerservice.html)等渠道与 ZSD 同城取得联系)。基于网络用户间的公平考
+				量,同时也为了使网络用户的投诉能够及时得到处理,避免被当做垃圾邮件屏蔽,北京五八信息技术有
+				限公司拒绝接收和处理所有以电子邮件形式发送给本公司员工个人的网络侵权通知,更不承诺对发送给
+				本公司员工个人的电子邮件侵权通知进行优先处理,特此告知。
+			</text>
+		</view>
+		
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				
+			}
+		},
+		methods: {
+			
+		}
+	}
+</script>
+
+<style>
+	page{
+		background: #ffffff;
+	}
+	.main{
+		padding: 24upx;
+	}
+</style>

+ 36 - 0
HX-SHOP/pages/base/release_notes.vue

@@ -0,0 +1,36 @@
+<template>
+	<view>
+		<hx-navbar left-text="功能介绍" :border="true" defaultBackUrl="features"></hx-navbar>
+		<view class="content">
+			{{content}} 
+		</view>
+	</view>
+	
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				content: '',
+			}
+		},
+		onLoad(option) {
+			this.getUpdateInfo(option)
+		},
+		methods: {
+			getUpdateInfo(option){
+				this.content = option.v + "的更新内容"
+			}
+		}
+	}
+</script>
+
+<style>
+	page{
+		background: #fff;
+	}
+	.content{
+		margin: 24upx;
+	}
+</style>

+ 15 - 0
HX-SHOP/pages/index/detail.vue

@@ -0,0 +1,15 @@
+<template>
+	<view>
+		123
+
+	</view>
+
+</template>
+
+<script>
+
+</script>
+
+<style lang="scss">
+
+</style>

+ 812 - 0
HX-SHOP/pages/index/index.vue

@@ -0,0 +1,812 @@
+<template>
+	<view>
+		<view class="head-box">
+			<view class="navbar"></view>
+			<view class="container">
+				<view class="left">
+					<view class="logo">
+						<image src="../../static/img/logo96x96.png" mode="aspectFit"></image>
+					</view>
+					<view class="">
+						byqMarket
+					</view>
+				</view>
+				<!-- 		<view class="right" :style="'padding-right: ' + MPPR + 'px'">
+					<view class="address-box">
+						<i class="hxicon-locationfill"></i>
+						<text>幸福花园</text>
+						<i class="hxicon-right"></i>
+					</view>
+					<view class="notice">
+						<i class="hxicon-notice"></i>
+					</view>
+				</view> -->
+
+			</view>
+		</view>
+		<view class=" bannerimg-box">
+			<swiper circular duration="400" interval="10000" autoplay>
+				<swiper-item class="swiper-item bannerImg" v-for="(item,index) in bannerData" :key="index">
+					图片尺寸为 750*250
+					<!-- <image :src="item.src" class="loaded" mode="widthFix"></image> -->
+				</swiper-item>
+			</swiper>
+		</view>
+
+		<!-- 		<view class="search-box" :class="{'QZBG':GDHEAD}" :style="GDHEAD ? 'padding-right: ' + MPPR + 'px' : ''">
+			<view class="navbar" ></view>
+			<view class="ctn">
+				<view class="hx-search-box" @click="goSearch">
+					<uni-icons type="search" size="22" color="#666666" />
+					<text>输入搜索关键词</text>
+				</view>
+			</view>
+		</view> -->
+		<!-- 		<view class="container">
+			<view class="hot-box">
+				<text class="item" v-for="(item,i) in hos_list" :key="i">{{item}}</text>
+			</view>
+		</view> -->
+		<mescroll-body ref="mescrollRef" :down="downOption" @down="downCallback" @up="upCallback">
+			<!-- 
+			<view class="container menu-box">
+				<view class="item-box" v-for="(item,i) in menuList" :key="i">
+					<image :src="item.img" mode=""></image>
+					<view class="tit">
+						<text>{{item.tit}}</text>
+					</view>
+				</view>
+			</view> -->
+			<view class="container gg-box">
+				<view class="item-ggbox" v-for="(item,i) in menuList" :key="i" @click="toGGdetail">
+					<image :src="item.img" mode=""></image>
+					<view class="tit">
+						<view class="title">{{item.tit}}</view>
+						<view class="date">2022-01-01</view>
+					</view>
+				</view>
+			</view>
+
+			<!-- 			<view class="container margin-top sort-box">
+				<view class="item-box" v-for="(item,i) in sortList" :key="i">
+					<view class="tit" :class="{'active': sortIndex == i}">
+						<text>{{item.tit}}</text>
+					</view>
+				</view>
+			</view>
+			<view class=" store-box" v-if="storeList">
+				<view class=" item-box" v-for="(store,i) in storeList" :key="i">
+					<view class="container top-box">
+						<view class="left" @click="toStore(store,null)">
+							<image :src="store.avatar" mode="aspectFill"></image>
+						</view>
+						<view class="right" @click="toStore(store,null)">
+
+							<text class="tit">{{store.name}}({{store.community}})</text>
+							<view class="row justify-content">
+								<view class="row-left">
+									<i class="hxicon-favorfill "></i>
+									<text class="t1">{{store.mark}}</text>
+									<text class="t2">月售{{store.monthly_sales}}</text>
+								</view>
+								<view class="row-right">
+									<i class="hxicon-locationfill"></i>
+									<text>{{store.distance}}</text>
+								</view>
+							</view>
+							<view class="row">
+								<text>起送¥{{store.starting_price}}</text>
+								<text class="t2" v-if="store.shipping_dees > 0">配送¥{{store.shipping_dees}} </text>
+								<text class="t2" v-else>免费配送</text>
+							</view>
+						
+						</view>
+					</view>
+					<scroll-view scroll-x class="bottom-box">
+						<view class="bottom-box-container">
+							<view class="goods-box" v-for="(goods,j) in store.goods" :key="j"
+								@click="toStore(store,goods.id)">
+								<view class="img-box">
+									<image :src="goods.main_pic" mode="aspectFit"></image>
+									<view class="tag">
+										{{goods.tag}}
+									</view>
+								</view>
+								<view class="tit">
+									{{goods.name}}
+								</view>
+								<view class="price-box">
+									<text class="txt1">¥</text>
+									<text class="txt2">{{goods.price}}</text>
+									<text class="txt3">¥{{goods.old_price}}</text>
+								</view>
+							</view>
+						</view>
+
+					</scroll-view>
+				</view>
+			</view> -->
+		</mescroll-body>
+		<view class="footzw"></view>
+	</view>
+
+</template>
+
+<script>
+	import MescrollBody from "@/components/mescroll-uni/mescroll-body.vue"
+	import MescrollUni from "@/components/mescroll-uni/mescroll-uni.vue"
+	import MescrollMixin from "@/components/mescroll-uni/mescroll-mixins.js";
+
+	//引入测试数据
+	import testData from "@/common/testdata.js";
+	const screenHeight = uni.getSystemInfoSync().screenHeight;
+	export default {
+		mixins: [MescrollMixin],
+		components: {
+			MescrollBody
+		},
+		// onPageScroll(e) {
+		// 	let that = this;
+		// 	if (e.scrollTop > 10) {
+		// 		let view = uni.createSelectorQuery().select(".search-box");
+		// 		view.fields({
+		// 			rect: true
+		// 		}, res => {
+		// 			if (res.top == 0) {
+		// 				that.GDHEAD = 1;
+		// 			} else {
+		// 				that.GDHEAD = 0;
+		// 			}
+
+		// 		}).exec();
+		// 	}
+
+		// },
+		data() {
+			return {
+				MPPR: 0,
+				GDHEAD: 0,
+				//显示没有更多商户
+				showFoot: 0,
+				downOption: {
+					auto: false //是否在初始化后,自动执行downCallback; 默认true
+				},
+				menuList: [
+
+					{
+						img: '/static/img/index/cs.png',
+						tit: '超市百货'
+					},
+					{
+						img: '/static/img/index/sc.png',
+						tit: '绿色果蔬'
+					},
+					{
+						img: '/static/img/index/sg.png',
+						tit: '生鲜鱼肉'
+					},
+					{
+						img: '/static/img/index/xh.png',
+						tit: '鲜花礼品'
+					},
+					{
+						img: '/static/img/index/yd.png',
+						tit: '送药到家'
+					}
+				],
+				sortIndex: 0,
+				sortList: [{
+					tit: '附近商户'
+				}, {
+					tit: '销量'
+				}, {
+					tit: '速度'
+				}, {
+					tit: '配送费'
+				}],
+				//filterTagList: [{tit:'支持预定'}, {tit:'销量'}, {tit:'速度'}, {tit:'配送费'}] 
+				storeList: [],
+				bannerData: [{
+						page: '/pages/product/product?id=457',
+						src: '@/static/img/coupon_dq.png'
+					},
+					{
+						page: '/pages/product/product?id=57',
+						src: '//imgs.1op.cn/i/hxshop/banner/banner.jpg'
+					},
+					{
+						page: '/pages/product/product?id=95',
+						src: '//imgs.1op.cn/i/hxshop/banner/banner.jpg'
+					},
+					{
+						page: '/pages/product/product?id=45',
+						src: '//imgs.1op.cn/i/hxshop/banner/banner.jpg'
+					}
+				],
+				hos_list: [
+					'红烧排骨',
+					'飞过肉',
+					'野生大菠萝',
+					'红烧排骨',
+					'西红柿蛋汤'
+				]
+
+			}
+		},
+		onLoad() {
+			let that = this;
+			// #ifdef MP
+			//小程序下空出胶囊距离
+			let m = uni.getMenuButtonBoundingClientRect();
+			that.MPPR = m.width + 8
+
+			// #endif
+		},
+		mounted() {
+			let that = this;
+
+		},
+		methods: {
+			toGGdetail(id) {
+				uni.navigateTo({
+					url: "/pages/index/detail"
+				})
+			},
+			/*下拉刷新的回调 */
+			downCallback() {
+				// that.$request.baseRequest('post', '/evaluateInfo/api/addEvaluateInfo', _data).then(res => {
+				// 	if (res.code==200) {
+				// 		this.$refs.uToast.show({
+				// 			type: 'success',
+				// 			message: "评价成功",
+				// 			complete() {
+				// 				uni.navigateTo({
+				// 					url: '/pages/order/index'
+				// 				})
+				// 			}
+				// 		})
+				// 	}else{
+				// 		this.$refs.uToast.show({
+				// 			type: 'error',
+				// 			message: "评价失败",
+				// 		})
+				// 	}
+				// })
+				let that = this;
+				//联网成功的回调,隐藏下拉刷新的状态
+				that.mescroll.endSuccess();
+				// setTimeout(()=>{
+				// 	that.mescroll.endSuccess();
+				// },1500)
+				//联网失败的回调,隐藏下拉刷新的状态
+				//this.mescroll.endErr();
+
+			},
+			upCallback(page) {
+				let that = this;
+				//加载门店数据
+				that.storeList = testData.storeList;
+				//无更多商家
+				that.showFoot = true;
+				//隐藏加载
+				that.mescroll.endSuccess(10);
+				// setTimeout(()=>{
+				// 	//加载门店数据
+				// 	that.storeList = testData.storeList;
+				// 	//无更多商家
+				// 	that.showFoot = true;
+				// 	//隐藏加载
+				// 	that.mescroll.endSuccess(10);
+				// },1500)
+			},
+			toStore(store, goodsID) {
+				let store_id = store.store_id
+				let parameter = `?sid=${store_id}`
+
+				if (goodsID != null) {
+					parameter += `&gid=${goodsID}`
+				}
+				uni.navigateTo({
+					url: '/pages/store/index' + parameter
+				})
+			},
+			//搜索
+			goSearch() {
+				uni.navigateTo({
+					url: '/pages/search/search?type=home'
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.gg-box {
+		.item-ggbox {
+			margin-bottom: 20rpx;
+			background: white;
+			border-radius: 20rpx;
+
+			.tit {
+				padding: 20rpx;
+				box-sizing: border-box;
+
+				.title {
+					font-weight: 700;
+					font-size: 32rpx;
+					margin-bottom: 20rpx;
+				}
+			}
+
+		}
+
+	}
+
+	.b-b {
+		position: relative;
+	}
+
+	.b-b:after,
+	.b-t:after {
+		position: absolute;
+		z-index: 3;
+		left: 0;
+		right: 0;
+		height: 0;
+		content: '';
+		transform: scaleY(.5);
+		border-bottom: 1px solid #E4E7ED;
+	}
+
+	.b-b:after {
+		bottom: 0;
+	}
+
+	.b-t:after {
+		top: 0;
+	}
+
+	.container {
+		margin: 0 15px;
+	}
+
+	.margin-top {
+		margin-top: 12px;
+	}
+
+	.head-box {
+		padding: 14px 0;
+		/* #ifdef MP */
+		padding-top: 2px;
+		/* #endif */
+		background: linear-gradient(100deg, #FFEB3B, #FFC107);
+		position: relative;
+		z-index: 3;
+
+		.navbar {
+			position: sticky;
+			top: 0;
+			height: var(--status-bar-height);
+		}
+
+		.container {
+			display: flex;
+			flex-direction: row;
+			justify-content: space-between;
+			height: 32px;
+			align-items: center;
+
+			.left {
+				display: flex;
+				align-items: center;
+
+				.logo {
+					width: 32px;
+					height: 32px;
+					margin-right: 20rpx;
+
+					image {
+						width: 32px;
+						height: 32px;
+						border-radius: 50%;
+					}
+				}
+			}
+
+			.right {
+				display: flex;
+				flex-direction: row;
+				color: #333333;
+				align-items: center;
+
+				.address-box {
+					font-size: 14px;
+					margin-right: 16px;
+					display: flex;
+					flex-direction: row;
+					align-items: center;
+
+					text {
+						margin-left: 2px;
+						margin-right: 4px;
+					}
+
+					.icon-right {
+						position: relative;
+						top: 2px;
+					}
+				}
+
+				.notice {
+					font-weight: bold;
+					font-size: 18px;
+				}
+			}
+
+		}
+
+	}
+
+	.search-box {
+		position: sticky;
+		top: 0;
+		z-index: 2;
+		background: linear-gradient(100deg, #FFEB3B, #FFC107);
+		padding-top: var(--status-bar-height);
+		margin-top: calc(var(--status-bar-height) * -1);
+
+		.ctn {
+			border-top-left-radius: 50upx;
+			border-top-right-radius: 50upx;
+			background: #f8f8f8;
+			padding: 15px 15px 12px;
+
+			.hx-search-box {
+				border-radius: 40px;
+				padding: 0 15px;
+				height: 34px;
+				display: flex;
+				align-items: center;
+				line-height: 44rpx;
+				background-color: #eeeeee;
+				flex: 1;
+				color: #888888;
+				font-size: 14px;
+			}
+		}
+	}
+
+	.loaded {
+		background: red;
+	}
+
+	.QZBG {
+		background: #ffffff;
+		box-shadow: 0 1px 6px #ccc;
+
+		.navbar {
+			height: var(--status-bar-height);
+		}
+
+		.ctn {
+			background: #ffffff;
+			/* #ifdef MP */
+			padding-top: 0px;
+			/* #endif */
+		}
+	}
+
+	.hot-box {
+
+		display: flex;
+		flex-direction: row;
+		flex-wrap: wrap;
+		justify-content: flex-start;
+
+		.item {
+			margin-right: 12px;
+			background-color: #EEEEEE;
+			color: #666666;
+			font-size: 12px;
+			border-radius: 20px;
+			padding: 2px 6px;
+			margin-bottom: 8px;
+		}
+
+		.item:last-child {
+			margin-right: 0;
+		}
+	}
+
+	.bannerimg-box {
+		border-bottom-left-radius: 10upx;
+		border-bottom-right-radius: 10upx;
+		padding: 24rpx;
+
+		swiper {
+			height: 233rpx;
+			width: 699rpx;
+		}
+
+		.swiper-item {
+			background: red;
+			display: flex;
+			justify-content: center;
+			align-content: center;
+			overflow: hidden;
+
+			width: 100%;
+			height: 100%;
+
+			image {
+				border-radius: 8px;
+				width: 100%;
+
+			}
+		}
+
+	}
+
+	.menu-box {
+
+		display: flex;
+		flex-direction: row;
+		justify-content: space-between;
+		margin-top: 12px;
+		border-radius: 8px;
+		background: #ffffff;
+		padding: 12px 8px;
+
+		.item-box {
+			display: flex;
+			flex-direction: column;
+			justify-content: center;
+			align-items: center;
+
+			image {
+				width: 40px;
+				height: 40px;
+			}
+
+			.tit {
+				display: flex;
+				justify-content: center;
+				align-items: center;
+				font-size: 12px;
+				margin-top: 6px;
+				color: #333333;
+				padding: 2px 0;
+				white-space: nowrap;
+				overflow: hidden;
+				text-overflow: ellipsis;
+			}
+
+			.active {
+				color: #ffffff;
+				background-color: #999999;
+				border-radius: 60px;
+			}
+		}
+	}
+
+	.sort-box {
+		display: flex;
+		flex-direction: row;
+		margin-top: 12px;
+
+		.item-box {
+
+			margin-right: 16px;
+
+			.tit {
+				display: flex;
+				justify-content: center;
+				align-items: center;
+				font-size: 12px;
+				color: #333333;
+				white-space: nowrap;
+				overflow: hidden;
+				text-overflow: ellipsis;
+			}
+
+			.active {
+				//color: #111111;
+				font-weight: bold;
+			}
+		}
+	}
+
+	.store-box {
+		margin-top: 20px;
+
+		.item-box {
+			display: flex;
+			flex-direction: column;
+			margin-bottom: 14px;
+			padding-bottom: 18px;
+			padding-top: 18px;
+			background-color: #ffffff;
+
+			.top-box {
+				display: flex;
+				flex-direction: row;
+
+				.left {
+					margin-right: 10px;
+
+
+					image {
+						width: 72px;
+						height: 54px;
+						border-radius: 6px;
+					}
+				}
+
+				.right {
+					flex: 1;
+
+					.tit {
+						font-size: 16px;
+						font-weight: bold;
+						color: #333333;
+						white-space: nowrap;
+						overflow: hidden;
+						text-overflow: ellipsis;
+					}
+
+					.justify-content {
+						display: flex;
+						flex-direction: row;
+						justify-content: space-between;
+					}
+
+					.row {
+						font-size: 12px;
+						color: #999999;
+						margin-top: 4px;
+
+						.row-left {
+							display: flex;
+							flex-direction: row;
+
+							.t1,
+							i {
+								color: #ffca3e;
+							}
+
+						}
+
+						.t2 {
+							margin-left: 12px;
+						}
+
+						.row-right {
+							display: flex;
+							flex-direction: row;
+
+							i {
+								margin-right: 4px;
+							}
+						}
+
+					}
+				}
+			}
+
+			.bottom-box {
+				&-container {
+					margin: 12px 0 0;
+					padding-left: 82px;
+
+					white-space: nowrap;
+
+					.goods-box {
+						width: 80px;
+						margin-left: 12px;
+						display: inline-block;
+
+						.img-box {
+							position: relative;
+							width: 80px;
+							height: 60px;
+							background-color: #f1f1f1;
+							border-radius: 4px;
+
+							image {
+								width: 100%;
+								height: 60px;
+							}
+
+							.tag {
+								position: absolute;
+								bottom: 0;
+								left: 0;
+								background-color: #FF5722;
+								color: #ffffff;
+								padding: 2px 4px;
+								font-size: 12px;
+								border-radius: 4px;
+							}
+						}
+
+						.tit {
+							font-size: 14px;
+							margin-top: 4px;
+							white-space: nowrap;
+							overflow: hidden;
+							text-overflow: ellipsis;
+						}
+
+						.price-box {
+							margin-top: 4px;
+
+							.txt1 {
+								font-size: 10px;
+								color: #FF5722;
+							}
+
+							.txt2 {
+								font-size: 16px;
+								color: #FF5722;
+							}
+
+							.txt3 {
+								margin-left: 6px;
+								font-size: 10px;
+								color: #bbbbbb;
+								text-decoration: line-through;
+							}
+						}
+					}
+
+					.goods-box:last-child {
+						margin-right: 12px;
+					}
+
+				}
+
+			}
+		}
+
+		.item-box:last-child {
+			border-bottom: 0;
+		}
+	}
+
+	.foot {
+		position: relative;
+		display: flex;
+		justify-content: center;
+		margin-top: 36px;
+		margin-bottom: 50px;
+
+		text {
+			font-size: 14px;
+			position: relative;
+			z-index: 2;
+			height: 20px;
+			line-height: 20px;
+			background-color: #f8f8f8;
+			color: #cccccc;
+			padding: 0 12px;
+		}
+	}
+
+	.foot::before {
+		content: "";
+		z-index: 1;
+		display: block;
+		position: absolute;
+		top: 50%;
+		height: 0;
+		width: 100%;
+		transform: scaleY(0.5);
+		border-bottom: 1px solid #E4E7ED;
+	}
+
+	.footzw {
+		/* #ifdef H5*/
+		height: 50px;
+		/* #endif */
+	}
+</style>

+ 1568 - 0
HX-SHOP/pages/index/index3.vue

@@ -0,0 +1,1568 @@
+<template>
+	<view class="hx-store" @touchstart="touchStart" @touchend="touchEnd">
+		<hx-navbar 
+		    :fixed="true"
+		    :color="['#ffffff','#888888']"
+		    barPlaceholder="hidden"
+		    transparent="auto"
+			:back="false" 
+			:rightSlot="false"
+		    :background-color="[245,245,245]"
+			@scroll="navbarScroll">
+			<block slot="left">
+				<view class="" style="margin-left: 6px; font-size: 22px;">
+					<!-- <uni-icons type="arrowleft" :color="navSearchColor" size="24" weight="bold"/> -->
+					<i class="hxicon-back"></i>
+				</view>
+				 
+			</block>
+			<view class="ctn">
+				<view class="searchCtn" :style="{'width':navSearchWidth + '%','background-color':'rgba(230,230,230,'+ navSearchBgOpacity +')'}">
+					<!-- <uni-icons type="search" size="22" :color="navSearchColor" weight="bold"/> -->
+					<i class="hxicon-search"></i>
+					<input confirm-type="search" class="input" type="text" placeholder="输入搜索关键词" @confirm="confirm" style="font-size: 14px;" :style="{'opacity':navSearchBgOpacity ,'color':navSearchColor}">
+				</view> 
+				<view class="leftBox" style="font-size: 22px;">
+					<i class="hxicon-favor"></i>
+					<i class="hxicon-more"></i>
+					<!-- <uni-icons type="star" size="22" weight="bold" :color="navSearchColor"/>
+					<uni-icons type="more-filled" weight="bold" size="22" :color="navSearchColor"/> -->
+				</view>
+				<view class="jrNull"></view>
+			</view>
+			<!-- <block slot="right">
+				<view class="" style="display: flex;width: 100%;justify-content: space-between;">
+					<uni-icons type="star" size="22" weight="bold" :color="navSearchColor"/>
+					<uni-icons type="more-filled" weight="bold" size="22" :color="navSearchColor"/>
+				</view>
+			</block> -->
+		</hx-navbar>
+		
+		<jumpBall  :start.sync="num" :element.sync="element" @msg="jbMsg" :speed="animaTime" :index="9999"/>
+	
+		
+		<!-- 头部 -->
+		<view class="header">
+			<image class="header-bg" :src="storeData.banner" mode=""></image>
+			<view :class="showStoreBox ? 'header-bg-gray' : 'header-bg-black'"></view>
+			<view class="header-top-Placeholder" ></view>
+			<view class="container storeInfo hx-shadow" :style="{height:storeInfoBoxHeight + 'px'}">
+				<image class="storeAvatar hx-shadow" :src="storeData.avatar" mode=""></image>
+				<view class="hx-txt-18 hx-color-black hx-txt-weigth hx-mb-10 ">
+					十里桃花
+				</view>
+				<view class="hx-txt-14 hx-color-black ">
+					店家说明,本店放心吃,地方名才
+				</view>
+				<!-- <view class="">
+					后续再扩展优惠券,满减,折扣,活动等功能
+				</view> -->
+				<view class="shrink-box">
+					<i class="hxicon" :class="showStoreBox ? 'icon-fold' : 'icon-unfold'" @click="showStoreBox = !showStoreBox"></i>
+				</view>
+			</view>
+		</view>
+		
+		
+		
+		<!-- 主体 -->
+		<view class="main" :style="{height: mainHeight}" >
+			<!-- <view class="" :style="{display:showZz}" style="position: absolute;top: 0;bottom: 0;left: 0;width: 100%; background: #3F536E;z-index: 999;opacity: 0.5;">
+				遮罩
+			</view> -->
+			<view class="QS-tabs-box" :style="{'top': 'calc(44px + ' + statusBarHeight + 'px)','background-color':'rgba(245,245,245,'+ navSearchBgOpacity +')'}">
+				<view class="" style="width: 210px;height: 100%;">
+						
+					<view class="hx-tabs">
+						<view class="hx-tabs-item" v-for="(item,i) in tabs" :key="i" :class="{'hx-tabs-active': swiperCurrent == i}" @click="swiperChange(i)" :style="{transition: transtionTime + 'ms'}">
+							<text>{{item.name}}</text>
+						</view>
+						<view class="hx-tabs-slider-box" :style="{transition: transtionTime + 'ms',left:swiperCurrentSliderLeft + 'px'}">
+							<view class="hx-tabs-slider"></view>
+						</view>
+					</view>
+				</view>
+			</view>
+			<swiper 
+			id="mainSwiper"
+			style="height: 100%;"
+			:current="swiperCurrent" 
+			:duration="transtionTime"
+			@transition="transition"
+			@animationfinish="animationfinish">
+				<!-- 购物 -->
+				<swiper-item class="swiper-item" >
+					
+						<view class="scroll-items">
+							
+							<view class="category-list">
+								<!-- 左侧分类导航 -->
+								<scroll-view  :scroll-y="true" class="left" >
+							       
+									<view v-for="item in categoryList" :key="item.id" class="row" :class="{active: item.id == currentId}" @click="showCategory(item)">
+										<view class="text">
+											{{item.name}}
+										</view>
+										<view class="row-number" v-if="item.number">
+											{{item.number}}
+										</view>
+									</view>
+							    </scroll-view>
+								<!-- 右侧子导航 -->
+								<scroll-view scroll-with-animation :scroll-y="true" class="right"  @scroll="asideScroll" :scroll-top="tabScrollTop" >
+									<view class="goodsListBox">
+										
+									
+										<view class="category" v-for="item in categoryList" :key="item.id" :id="'goodsBox'+item.id" >
+											<view class="s-item">{{item.name}}</view>
+											<view class="list"  >
+												<view class="box" v-for="(rowData,i) in goodsList" :key="rowData.id" v-if="item.id == rowData.type_id">
+													<!-- 商品列表 -->
+													<!-- <m-store-pro @touchOnGoods="touchOnGoods" :rowData="box"></m-store-pro>
+													 -->
+													<!-- 商品列表 -->
+													<view class="m-store-item">
+														<view class="m-img" @click="hrefGoodsInfo(rowData.id)">
+															<image style="width: 100%;height: 100%;" :src="rowData.img" mode="aspectFit"></image>
+														</view>
+														<view class="m-text">
+															<view class="m-title" @click="hrefGoodsInfo(rowData.id)">
+																{{rowData.name}}
+															</view>
+															<view class="m-descripe">
+																{{rowData.descripe}}
+															</view>
+															<view class="m-price-box">
+																<view class="symbol">¥</view>
+																<view class="m-price">{{rowData.price}}</view>
+																<view class="m-old-price" v-if="rowData.oldprice">
+																	<text>¥{{rowData.oldprice}}</text>
+																</view>
+															</view>
+															<view class="m-distance" >
+																<view :class="'addEle_' + i" class="jumpPosition">
+																</view>
+																<hx-number-box @change="addGoodsChange" :value="rowData.number" :rowData="rowData" :clickTime="animaTime + 100" @addChange="touchOnAddGoods('.addEle_' + i,rowData)"></hx-number-box>
+																
+																<!-- <image @click="touchOnAddGoods('.addEle_' + i,rowData)" style="width:20px;height: 20px;" src="../../static/img/icon/shop_icon_buy.png" mode="aspectFit"></image>
+															 -->
+															</view>
+														</view>
+														
+													</view>
+												</view>
+											</view>
+										</view>
+									</view>
+								</scroll-view>
+							</view>		
+						</view>
+					
+				</swiper-item>
+				
+				<!-- 评价 -->
+				<swiper-item class="swiper-item" >
+					<scroll-view scroll-y style="height: 100%;width: 100%;background-color: #ffffff;" @scroll="asideScroll">
+						<view class="scroll-items evaluate-box" >
+							<view class="evaluate-box-header">
+								
+							</view>
+							<view class="evaluate-box-body">
+								
+							</view>
+							<hx-comment :listData="commentList"></hx-comment>
+						</view>
+					</scroll-view>
+				</swiper-item>
+				
+				<!-- 商家 -->
+				<swiper-item class="swiper-item" >
+					<view class="scroll-items business-box">
+						<view class="info-list hx-mt-15">
+							<view class="info-list-container">
+								<i class="hxicon-location"></i>
+								<text>{{ storeData.address }}</text>
+							</view>
+						</view>
+						
+						<view class="info-list hx-mt-15 ">
+							<view class="info-list-container hx-bb">
+								<i class="hxicon-time"></i>
+								<text>配送时间:{{ storeData.delivery_time }}</text>
+							</view>
+						</view>
+						<view class=" info-list">
+							<view class="info-list-container" @click="goCall(storeData.telephone)">
+								<i class="hxicon-phone"></i>
+								<text style="flex: 1;">商家电话:{{ storeData.telephone }}</text>
+								<view class="right">
+									<text>拨打</text><i class="hxicon-right"></i>
+								</view>
+							</view>
+						</view>
+						<view class="info-list hx-mt-15">
+							<view class="info-list-container" @click="showStoreBoxFunc">
+								<i class="hxicon-new" style="color:#ff3333"></i>
+								<text style="flex: 1;">商家当前热门活动</text>
+								<view class="right">
+									<text>查看</text><i class="hxicon-right"></i>
+								</view>
+							</view>
+						</view>
+					</view>
+				</swiper-item>
+			</swiper>
+		</view>
+		
+		<!-- 购物车 -->
+		<view class="foot"  @touchmove.stop.prevent="mpClear" :style="{height: footHeight}" v-if="showFoot">
+			<view class="zz" @click="hideShoppingCar"></view>
+			<view class="btn-box">
+				<view class="btn-box-left" @click="contact">
+					<view class="imgBox">
+						<image src="../../static/store/contact.png" mode=""></image>
+					</view>
+					<text>联系商家</text>
+				</view>
+				<view class="btn-box-line"></view>
+				<view class="btn-box-center" @click="showShoppingCar">
+					<view class="cart" :animation="cartAnimationData">
+						<view class="tag cartNum" v-if="goodsTotalNumber>0">{{goodsTotalNumber}}</view>
+						<image :src="goodsTotalNumber ? '/static/store/cart.png' : '/static/store/cart2.png'" mode=""></image>
+					</view>
+					<view class="priceBox">
+						<view class="hx-txt-18 hx-color-white" v-if="goodsTotalPrice>0">
+							¥{{goodsTotalPrice}}
+						</view>
+						<view class="hx-txt-10 hx-color-gray">
+							另需配送费¥{{shippingDees}}
+						</view>
+					</view>
+				</view>
+				<view class="btn-box-right">
+					<view class="jiesuan"  v-if="goodsTotalPrice>0 && goodsTotalPrice >= startingPrice" @click="jiesuan">
+						去结算
+					</view>
+					<view class="pscj hx-txt-10 hx-color-gray" v-else>
+						<text v-if="startingPrice>0">差¥{{-(goodsTotalPrice-startingPrice)}}起送</text>
+					</view>
+					
+				</view>
+			</view>
+			<view class="cart-box" :style="{display: showCar ? 'flex' : 'none'}">
+				<view class="box-container rebate-box" v-if="showDiscount">
+					<text>已享100减25</text>
+				</view>
+				<view class="box-container operating-box">
+					<view class="operating-box_right">
+						
+					</view>
+					<view class="operating-box_left clear" @click="clearShoppingCart">
+						<i class="hxicon-delete"></i>
+						<text>清空购物车</text>
+					</view>
+				</view>
+				<view class=" goods-box">
+					<view class="" style="flex: 1;">
+						<scroll-view scroll-y="true" class="goods-list-scroll" :scroll-top="carGoodsScrollTop">
+							<view class="goods-list">
+								<view class="box" v-for="(rowData,i) in shoppCart" :key="i" v-if="rowData.number>0">
+									
+									<view class="m-store-item">
+										<view class="m-img">
+											<image style="width: 100%;height: 100%;" :src="rowData.img" mode="aspectFit"></image>
+										</view>
+										<view class="m-text">
+											<view class="m-title">
+												{{rowData.name}}
+											</view>
+											<view class="m-descripe">
+												{{rowData.descripe}}
+											</view>
+											<view class="m-price-box" >
+												<view class="symbol">¥</view>
+												<view class="m-price">{{rowData.price}}</view>
+												<view class="m-old-price" v-if="rowData.oldprice">
+													<text>¥{{rowData.oldprice}}</text>
+												</view>
+											</view>
+											<view class="m-distance" > 
+											<view :class="'addEle2_' + i" class="jumpPosition">
+											</view>
+												<hx-number-box @change="addGoodsChange" :value="rowData.number" :rowData="rowData" :clickTime="animaTime + 100" @addChange="touchOnAddGoods('.addEle2_' + i,rowData)"></hx-number-box>
+												
+											</view>
+										</view>
+										
+									</view>
+								</view>
+							</view>
+						</scroll-view>
+					</view>
+					
+				</view>
+			</view>
+			
+		</view>
+		
+	</view>
+</template> 
+
+<script>
+	import uniIcons from '@/components/uni-icons/uni-icons.vue';
+	import hxNavbar from '@/components/hx-navbar/hx-navbar.vue';
+	import jumpBall from '@/components/hx-jump-ball/hx-jump-ball.vue';
+	import hxNumberBox from "@/components/uni-number-box/uni-number-box.vue";
+	import hxComment from "@/components/hx-comment/hx-comment.vue";
+	//引入测试数据
+	import testData from "@/common/testdata.js";
+	
+	var statusBarHeight = uni.getSystemInfoSync().statusBarHeight;
+	
+	export default {
+		components: {
+			jumpBall,
+			hxNavbar,
+			uniIcons,
+			hxNumberBox,
+			hxComment
+		},
+		data() {
+			return {
+				//商家信息
+				storeData: [],
+				//商品列表
+				goodsList: [],
+				//商品分类信息列表
+				categoryList: [],
+				//评论列表
+				commentList: [],
+				
+				navSearchWidth: 10,
+				navSearchBgOpacity: 0,
+				navSearchColor: '#ffffff',
+				navHeadHeight: 44,
+				//默认禁止商品栏滚动
+				goodsBoxScroll: false,
+				statusBarHeight,
+				//动画时间
+				animaTime: 300,
+				//商家盒子高度
+				storeInfoBoxHeight: 100,
+				//展开门店信息容器
+				showStoreBox: false,
+				
+				num:1,
+				element: [],				
+				cartAnimation: {},
+				cartAnimationData: {},
+				
+				//tabs
+				tabs: [
+					{name:'购物'},
+					{name:'评价'},
+					{name:'商家'},
+				],
+				swiperCurrent: 0,
+				dx: 0,
+				swiperCurrentSliderLeft: 0,
+				transtionTime:100,
+				
+				//购物车
+				shoppingCartAll:[],
+				//显示购物车
+				showFoot:true,
+				
+				//配送费
+				shippingDees: 0,
+				//配送起步价
+				startingPrice:0,
+				
+				//购物车商品价格合计
+				goodsTotalPrice: 0,
+				//购物车商品数量合计
+				goodsTotalNumber: 0,
+				//购物车
+				shoppCart: [],
+				//foot 高度
+				footHeight: '0',
+				//显示购物车
+				showCar: false,
+				//购物车中商品滚动条位置
+				carGoodsScrollTop: 0,
+				//购物车缓存 Storage 名称
+				shoppingCartStorageName: 'shopping_cart',
+				
+				sizeCalcState: false,
+				tabScrollTop: 0,
+				
+				mainHeight: 0,
+				currentId:1,
+				
+				
+				//购物车显示折扣
+				showDiscount:true,
+				//手指触摸滑动
+				touchData:{},
+				//页面滚动条距离顶部的距离
+				pageScrollTop: 0
+			}
+		},
+		onLoad() {
+			this.cartAnimation = uni.createAnimation({
+				duration: 800,
+				timingFunction: "ease",
+				delay: 0
+			}); 
+			let sysInfo = uni.getSystemInfoSync();
+			//屏幕高度 - 头部导航高度 - 状态栏高度 - 分页高度
+			this.mainHeight = sysInfo.screenHeight - 43 - statusBarHeight - 40  + 'px';
+		
+		},
+		mounted() {
+			let that = this
+			uni.showLoading({
+			    title: '加载中'
+			});
+			//模拟请求数据
+			setTimeout(()=>{
+				//商家信息
+				that.storeData = testData.storeData,
+				//商品列表
+				that.goodsList = testData.goodsData;
+				//商品分类信息列表
+				that.categoryList = testData.categoryData;
+				//评论列表
+				that.commentList = testData.commentData,
+				setTimeout(()=>{
+					that.init();
+					uni.hideLoading();
+				},500)
+			},1000)
+		},
+		watch:{
+			showStoreBox(val,oldVal){
+				if(val == true){
+					
+					this.showStoreBoxFunc();
+				}else{
+					this.hiddenStoreBoxFunc();
+				}
+			}
+		},
+		onPageScroll(e) {
+			let that = this
+		},
+		methods: {
+			
+		
+			init(){
+				let that = this;
+				//假设这是从后台获取的商品数据
+				let goods = this.goodsList;
+				//商品初始化
+				
+				for(let i in goods){
+					
+					goods[i].purchases = 3
+				}
+				
+				let carts = uni.getStorageSync(that.shoppingCartStorageName) || [];
+				//根据缓存数据 获取购物车中属于本商店的商品
+				for(let i in carts){
+					if(carts[i].store_id == that.storeData.store_id){
+						that.shoppCart = carts[i].shopping_cart;
+						break;
+					}
+				}
+				
+				for(let i in that.shoppCart){
+					for(let j in goods){
+						if(goods[j].id == that.shoppCart[i].id){
+							goods[j].number = that.shoppCart[i].number
+						}
+					}
+					//计算商品总价
+					that.goodsTotalPrice += that.shoppCart[i].total
+					//商品总数量
+					that.goodsTotalNumber += that.shoppCart[i].number
+				}
+				//初始化商品列表
+				that.goodsList = goods;
+				
+				//初始化起步价和配送费
+				that.starting_price = that.storeData.starting_price;
+				that.shipping_dees = that.storeData.shipping_dees;
+				
+				that.setLabelNumber();
+				this.calcSize();
+			},
+			//导航栏滑动时的操作
+			navbarScroll(scroll){
+				let top = scroll.scrollTop
+				let that = this
+				this.pageScrollTop = scroll.scrollTop
+				if(top < 120){
+					if(this.navSearchWidth >= 3){
+						if(top<3){
+							this.navSearchWidth = 3
+							this.navSearchBgOpacity = 0
+							this.navSearchColor = '#ffffff'
+						}else{
+							let n = top * (120/100)
+							if(n > 100){
+								n = 100
+							}
+							this.navSearchWidth = n
+							this.navSearchBgOpacity = top * (1/100)
+							this.navSearchColor = '#888888'
+						}
+						
+					}
+					
+				}else{
+					this.navSearchWidth = 100
+					this.navSearchBgOpacity = 1
+					this.navSearchColor = '#888888'
+				}
+				
+				
+			},
+			jbMsg(res){
+				let that = this;
+				
+				that.cartAnimation.matrix(1, 0, 0, 0.7, 0, 7).step({duration: 100})
+				that.cartAnimationData = that.cartAnimation.export();
+				//动画在app端有bug,所以必须写延迟才能解决
+				setTimeout(function() {
+					that.cartAnimation.matrix(1, 0, 0, 1, 0, 0).step({duration: 150});
+					that.cartAnimationData = that.cartAnimation.export();
+				},100);
+			},
+			
+			swiperChange(index) {
+				this.swiperCurrent = index;
+				this.swiperCurrentSliderLeft= 70 * index;
+			},
+			transition({ detail: { dx } }) {
+				// this.$refs.tabs.setDx(dx);
+			},
+			animationfinish({detail: { current }}) {
+				/* this.$refs.tabs.setFinishCurrent(current); */
+				this.swiperCurrent = current;
+				this.current = current;
+				this.swiperChange(current);
+				this.showFoot = current == 0 && this.showStoreBox != true ? true : false;
+				
+			},
+			
+		
+			//一级分类点击
+			showCategory(item){
+				this.calcSize();
+				this.currentId = item.id;
+				let index = this.categoryList.findIndex(sitem=>sitem.id === item.id);
+				this.tabScrollTop = this.categoryList[index].top;
+				
+			},
+			//右侧栏滚动
+			asideScroll(e){
+				let that = this;
+				this.calcSize();
+				let scrollTop = Math.round(e.detail.scrollTop);
+				let tabs = this.categoryList.filter(item=>item.top <= scrollTop).reverse();
+				if(tabs.length > 0){
+					this.currentId = tabs[0].id;
+				}
+				
+				if(scrollTop > 0){
+					uni.createSelectorQuery().select(".main").fields({
+						scrollOffset: true,
+						rect: true,
+					},(res)=>{
+						
+						res.top = Math.round(res.top)
+						if(res.top > 111){
+							that.navbarScroll({scroll:150})
+							uni.pageScrollTo({
+								duration:0,
+								scrollTop:res.top
+							})
+							
+						}
+						
+					}).exec()
+				}
+			},
+			//计算右侧栏每个tab的高度等信息
+			calcSize(event){
+				let h = 0;
+				this.categoryList.forEach(item=>{
+					let view = uni.createSelectorQuery().select("#goodsBox" + item.id);
+					view.fields({
+						size: true
+					}, data => {
+						item.top = h;
+						h += Math.round(data.height);
+						item.bottom = h;
+					}).exec();
+				})
+				this.sizeCalcState = true;
+			},
+			
+			//小球跳跃动画
+			touchOnAddGoods(ele,data){
+				this.element = [ele,'.cart'];
+				this.num ++; 
+			},
+			//新增商品计算价格
+			addGoodsChange(number,rowData){
+				number = Number(number)
+				var that = this;
+				
+				let shoppCart = this.shoppCart;
+				let totalPrice = 0;
+				let totalNumber = 0;
+				let existedGoods = false;
+				//检查该商品是否为第一次添加,如果为第二次添加,则直接修改商品数量,并计算出合计
+				for(var i in shoppCart){
+					//非第一次添加
+					if(shoppCart[i].id == rowData.id){
+						shoppCart[i].number = rowData.number = number;
+						shoppCart[i].total = number * shoppCart[i].price
+						existedGoods = true;
+						break;
+					}
+				}
+				//第一次添加
+				if(!existedGoods){
+					rowData.number = number;
+					rowData.total = number * rowData.price
+					shoppCart.push(rowData);
+				}
+				//计算总商品数量和总价
+				for(var i in shoppCart){
+					//总价
+					totalPrice += shoppCart[i].total
+					totalNumber += shoppCart[i].number
+					
+				}
+				//更改商品列表中的已购买数量
+				for(let i in that.goodsList){
+					if(that.goodsList[i].id == rowData.id){
+						that.goodsList[i] = rowData
+						break;
+					}
+				}
+				
+				that.shoppCart = shoppCart;
+				if(that.goodsTotalPrice < totalPrice){
+					//更具小球动画延时更改数据
+					setTimeout(function(){
+						that.goodsTotalPrice = totalPrice
+						that.goodsTotalNumber = totalNumber
+					},that.animaTime + 150);
+				}else{
+					that.goodsTotalPrice = totalPrice
+					that.goodsTotalNumber = totalNumber
+				}
+				
+				//门店第一次添加该商品
+				let isFirstAddGoods = true;
+				that.storeData.shopping_cart = that.shoppCart;
+				
+				for(let i in that.shoppingCartAll){
+					if(that.shoppingCartAll[i].store_id == that.storeData.store_id){
+						that.shoppingCartAll[i] = that.storeData
+						isFirstAddGoods = false
+					}
+				}
+				
+				that.setLabelNumber();
+				if(isFirstAddGoods === true){
+					that.shoppingCartAll.push(that.storeData)
+				}
+				if(that.goodsTotalNumber == 0){
+					that.hideShoppingCar();
+				}
+				
+				//购物车商品数据缓存至本地
+				uni.setStorageSync(that.shoppingCartStorageName,that.shoppingCartAll);
+			},
+			
+			//计算每类商品购买的总数
+			setLabelNumber(){
+				let that = this;
+				//计算每一类购买商品的总数量
+				for(let j in that.categoryList){
+					let n = 0;
+					for(var i in that.shoppCart){
+						if(that.shoppCart[i].type_id ==  that.categoryList[j].id){
+							n += that.shoppCart[i].number;
+						}
+					}
+					that.categoryList[j].number = n;
+				}
+			},
+			
+			//去结算
+			jiesuan(){
+				uni.showModal({
+					title:"",
+					content:"去结算"
+				})
+			},
+			//联系商家
+			contact(){
+				uni.showModal({
+					title:"",
+					content:"联系商家"
+				})
+			},
+			
+			showStoreBoxFunc(){
+				this.storeInfoBoxHeight = uni.getSystemInfoSync().screenHeight-136;
+				this.$set(this.$data,'showFoot',false);
+				this.showStoreBox = true;
+				uni.pageScrollTo({
+					duration:0,
+					scrollTop:0
+				})
+			},
+			hiddenStoreBoxFunc(){
+				this.storeInfoBoxHeight = 100;
+				this.showStoreBox = false;
+				if(this.swiperCurrent == 0){
+					this.$set(this.$data,'showFoot',true);
+				}
+			},
+			
+			mpClear(e) {
+				// TODO nvue 取消冒泡
+				e.stopPropagation()
+			},
+			
+			//显示购物车
+			showShoppingCar(){
+				if(this.goodsTotalNumber == 0){
+					return;
+				}
+				this.footHeight = '100%';
+				this.showCar = true;
+				this.carGoodsScrollTop = 0;
+			},
+			//隐藏购物车
+			hideShoppingCar(){
+				this.footHeight = '0';
+				this.showCar = false;
+			},
+			//清空该门店的购物车
+			clearShoppingCart(){
+				let that = this;
+				that.shoppCart = [];
+				that.storeData.shopping_cart = [];
+				for(let i in that.shoppingCartAll){
+					if(that.shoppingCartAll[i].store_id == that.storeData.store_id){
+						that.shoppingCartAll[i] = that.storeData
+					}
+				}
+				uni.setStorageSync(that.shoppingCartStorageName,that.shoppingCartAll);
+				
+				for(let i in that.goodsList){
+					that.goodsList[i].number = 0;
+				}
+				for(let i in that.categoryList){
+					that.categoryList[i].number = 0;
+				}
+				//购物车商品价格合计
+				that.goodsTotalPrice = 0;
+				//购物车商品数量合计
+				that.goodsTotalNumber = 0;
+				that.hideShoppingCar();
+			},
+			hrefGoodsInfo(id){
+				uni.navigateTo({
+				    url: '/pages/product/product?id=' + id
+				});
+			},
+			//拨打电话
+			goCall(phone){
+				if(!phone){
+					return;
+				}
+				uni.makePhoneCall({
+				    phoneNumber: phone //仅为示例
+				});
+			},
+			
+			touchStart(e){
+			                    
+			    this.touchData.clientX=e.changedTouches[0].clientX;
+			                 
+			    this.touchData.clientY=e.changedTouches[0].clientY;
+			},
+			touchEnd(e){
+			   
+			    const subX=e.changedTouches[0].clientX-this.touchData.clientX;
+			    const subY=e.changedTouches[0].clientY - this.touchData.clientY;
+			    if(subY>50 || subY<-50){
+					if(subY>50){
+					    //console.log('下滑')
+						if(this.pageScrollTop == 0){
+							//this.showStoreBox=true;
+							
+						}
+					}else if(subY<-50){
+					    //console.log('上滑')
+						this.showStoreBox= false;
+					}else{
+					    //console.log('上下滑无效')
+					}
+					
+			    }else{
+			        if(subX>100){
+			            //console.log('右滑')
+			        }else if(subX<-100){
+			            //console.log('左滑')
+			        }else{
+			            //console.log('左右滑无效')
+			        }
+			    }
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	//主题颜色
+	$hx-theme-color: #FFC107;
+	$hx-theme-color-light: #FFEB3B;
+	
+	.add{
+		position: fixed;
+		right: 60upx;
+		top: 300upx;
+		z-index: 999;
+	}
+	.ctn{
+		
+		/* border: 1px solid #e3e3e3; */
+		width: 100%;
+		display: flex;
+		justify-content: flex-end;
+		overflow: hidden;
+		align-items: center;
+		.searchCtn{
+			display: flex;
+			border-radius: 80upx;
+			padding: 8upx 12upx;
+			line-height: 44upx;
+			background: #e0e0e0;
+			overflow: hidden;
+			align-items: center;
+			min-width: 22px;
+		}
+		.leftBox{
+			display: flex;
+			width: 53px;
+			justify-content: space-between;
+			flex: none;
+			margin: 0 8px;
+		}
+		.jrNull{
+			/* #ifdef MP */
+			width: 95px;
+			flex: none;
+			/* #endif */
+		}
+	}
+	
+	
+	page{
+		background: #ffffff;
+	}
+	.hx-bb{
+		border-bottom: 1px solid $uni-border-color;
+	}
+	.hx-txt-10{
+		font-size: 10px;
+	}
+	.hx-txt-12{
+		font-size: 12px;
+	}
+	.hx-txt-14{
+		font-size: 14px;
+	}
+	.hx-txt-16{
+		font-size: 16px;
+	}
+	.hx-txt-18{
+		font-size: 18px;
+	}
+	.hx-txt-22{
+		font-size: 22px;
+	}
+	.hx-color-gray{
+		color: #bbbbbb;
+	}
+	.hx-color-white{
+		color: #FFFFFF;
+	}
+	.hx-color-black{
+		color: #333333;
+	}
+	.hx-txt-weigth{
+		font-weight: bold;
+	}
+	.hx-mb-10{
+		margin-bottom: 10px;
+	}
+	.hx-mt-15{
+		margin-top: 15px;
+	}
+	.hx-shadow{
+		box-shadow: 0px 6upx 16upx rgba(173, 173, 173, 0.2);
+	}
+	
+	.hx-store{
+		.header{
+			position: relative;
+			min-height: 230px;
+			&-bg{
+				position: absolute;
+				left: 0;
+				top: 0;
+				z-index: 2;
+				width: 100%;
+				height: 142px;
+			}
+			&-bg-black{
+				position: absolute;
+				left: 0;
+				top: 142px;
+				bottom: 0;
+				z-index: 1;
+				background-color: #ffffff;
+				width: 100%;
+				transition: background-color 0.2s;
+			}
+			&-bg-gray{
+				position: absolute;
+				left: 0;
+				top: 142px;
+				bottom: -16px;
+				z-index: 1;
+				background-color: #afafaf;
+				width: 100%;
+				transition: background-color 0.2s;
+			}
+			&-top-Placeholder{
+				height: 105px;
+			}
+			.storeInfo{
+				position: relative;
+				z-index: 2;
+				background: #ffffff;
+				height: 100px;
+				border-radius: 6px;
+				padding: 12px;
+				margin-bottom: 4px;
+				transition: all 0.2s;
+				.shrink-box{
+					position: absolute;
+					bottom: 0;
+					left: 0;
+					right: 0;
+					text-align: center;
+					font-size: 20px;
+					color: #a2a8ab;
+				}
+				.storeAvatar{
+					position: absolute;
+					width: 50px;
+					height: 50px;
+					right: 16px;
+					top: -25px;
+					background: #ffffff;
+					border-radius: 4px;
+					
+				}
+			}
+		}
+		.container{
+			margin: 0 32upx;
+		}
+		.QS-tabs-box{
+			width: 100%;
+			position: sticky;
+			top: calc(44px + var(--status-bar-height));
+			z-index: 10;
+			background-color: white;
+			border-bottom: 1px solid #efefef;
+			height: 40px;
+			
+			.hx-tabs{
+				position: relative;
+				display: flex;
+				height:100%;
+				&-item{
+					display: flex;
+					flex-direction: row;
+					justify-content: center;
+					align-items: center;
+					width: 70px;
+					color:#666666;
+					text{
+						font-size: 16px;
+					}
+					
+				}
+				&-active{
+					color:#333333;
+					font-weight: bold;
+				}
+				&-slider-box{
+					position: absolute;
+					display: flex;
+					justify-content: center;
+					bottom: 0;
+					width: 70px;
+				}
+				&-slider{
+					display: flex;
+					background: #f6d200;
+					width: 30px;
+					height: 3px;
+				}
+			}
+		}
+		.main{
+			position: relative;
+			background-color: #ffffff;
+			
+			#mainSwiper{
+				background-color: #eeeeee;
+				position: sticky;
+				top: calc(40px + 44px + var(--status-bar-height));
+				.scroll-items{
+					// 商品列表样式
+					.category-list{
+						width: 100%;
+						background-color: #fff;
+						display: flex;
+						padding-bottom: 50px;
+						
+						.left,.right{
+							background: #fff;
+							position: absolute;
+							top:0;
+							bottom: 0upx;
+						}
+						.left{
+							width: 24%;
+							left: 0upx;
+							background-color: #f6f3f3;
+							
+							.row{
+								width: 100%;
+								height: 45px;
+								display: flex;
+								align-items: center;
+								overflow: hidden;
+								position: relative;
+								.text{
+									width: 100%;
+									font-size: 14px;
+									color:#999999;
+									overflow: hidden;
+									text-overflow: ellipsis;
+									display: -webkit-box;
+									-webkit-box-orient: vertical;
+									-webkit-line-clamp: 2;
+									text-align: center;
+									padding: 0 16px;
+								}
+								&-number{
+									position: absolute;
+									width: 18px;
+									height: 18px;
+									right: 4px;
+									top: 4px;
+									background: #ff5722;
+									border-radius: 50%;
+									line-height: 18px;
+									text-align: center;
+									font-size: 10px;
+									color: #ffffff;
+								}
+								&.active{
+									height: 45px;
+									background-color: #fff;
+									.text{
+										font-size: 14px;
+										
+									}
+								}
+							}
+							.row:last-child{
+								margin-bottom: 200upx;
+							}
+						}
+						.right{
+						   width: 76%;
+							left: 24%;
+							.goodsListBox{
+								padding-bottom: 100px;
+								.category{
+					// 				width: 94%;
+									padding: 0 15px 10px 15px;
+									.s-item{
+										height: 45px;
+										line-height: 45px;
+										font-size: 16px;
+										background: #ffffff;
+										color: #555555;
+										position: sticky;
+										top: 0;
+										z-index: 18;
+									}
+									.list:last-child{
+										margin-bottom: 0;
+									}
+									.list{
+										margin-bottom: 20px;
+										width: 100%;
+										display: flex;
+										flex-wrap: wrap;
+										.box:first-child{
+											.m-store-item{
+												margin-top: 0;
+											}
+										}
+										.box{
+											width: 100%;
+											
+											.m-store-item{
+												display: flex;
+												flex-direction: row;
+												width: 100%;
+												justify-content: space-between;
+												align-items: flex-end;
+												margin-top: 15px;
+												margin-bottom: 15px;
+												.m-img{
+													flex: 0 0 85px;
+													height: 85px;
+													background: #eee;
+													border-radius: 4px;
+												}
+												.m-text{
+													flex: 1;
+													position: relative;
+													height: 85px;
+													padding: 0 6px;
+													display: flex;
+													align-content: space-between;
+													flex-direction: column;
+													.m-title{
+														font-size: 16px;
+														color:#555555;
+														height: 21px;
+														font-weight: bold;
+													}
+													.m-descripe{
+														font-size: 12px;
+														color:#999999;
+														margin-top: 5px;
+														height: 35px;
+													}
+													.m-price-box{
+														height: 24px;
+														font-weight: bold;
+														display: flex;
+														flex-direction: row;
+														align-items: flex-end;
+														.symbol{
+															color:#ff582b;
+															font-size: 12px;
+														}
+														.m-price{
+															position: relative;
+															top: 2px;
+															font-size: 18px;
+															color:#ff582b;
+														}
+														.m-old-price{
+															margin-left: 3px;
+															display: flex;
+															flex-direction: row;
+															font-size: 10px;
+															color:#999999;
+															margin-top: 5upx;
+															text-decoration: line-through;
+															font-weight: normal;
+														}
+													}
+													.m-distance{
+														position: absolute;
+														right: 0;
+														bottom: -4px;
+														z-index: 16;
+														color:#b2b2b2;
+														font-size: 20upx;
+														text-align: right;
+														.jumpPosition{
+															position: absolute; 
+															bottom: 23px;
+															right: 0;
+															z-index: 2;
+															width: 28px;
+															height: 28px;
+														}
+													}
+													
+												}
+												
+											}
+										}
+									}
+								}
+							}
+						}
+					}
+				}
+				.evaluate-box{
+					
+				}
+				.business-box{
+					
+					.info-list{
+						background: #ffffff;
+						padding: 0 15px;
+						&-container{
+							line-height: 46px;
+							height: 46px;
+							display: flex;
+							flex-direction: row;
+							[class*="hxicon-"]="hxicon-"]{
+								color: #a2a2a2;
+								margin-right: 8px;
+							}
+							text{
+								font-size: 14px;
+							}
+							.right{
+								
+								float: right;
+								color: #dddddd;
+								display: flex;
+								flex-direction: row;
+								align-items:center;
+								[class*="hxicon-"]{
+									color: #dddddd;
+									margin-right: 0;
+									font-size: 16px;
+								}
+							}
+						}
+						
+					}
+				}
+			}
+			
+		}
+		.foot{
+			position: fixed;
+			display: flex;
+			z-index: 999;
+			
+			justify-content:center;
+			align-items : center; 
+			bottom: 0;
+			height: 100%;
+			width: 100%;
+			
+			/*width: calc(100% - 32px);*/
+			.btn-box{
+				position:absolute;
+				display: flex;
+				bottom: 6px;
+				justify-content:center;
+				align-items : center; 
+				margin:0;
+				height: 45px;
+				width: calc(100% - 32px);
+				z-index: 9;
+				&-left{
+					background: #222222;
+					border-top-left-radius:50px;
+					border-top-right-radius:9px;
+					border-bottom-left-radius:50px;
+					border-bottom-right-radius:9px;
+					padding-left: 6upx;
+					display: flex;
+					flex-direction:column;
+					justify-content:center;
+					align-self: center;
+					width: 70px;
+					height: 100%;
+					color: #f6d200;
+					text-align: center;
+					.imgBox{
+						display: flex;
+						text-align: center;
+						justify-content:center;
+						image{
+							width: 20px;
+							height: 20px;
+						}
+					}
+					text{
+						font-size: 20upx;
+					}
+				}
+				&-line{
+					background: #ffffff;
+					width: 2px;
+					height: 100%;
+				}
+				&-center{
+					height: 100%;
+					flex: auto;
+					display: flex;
+					justify-content:flex-start;
+					align-self: center;
+					align-items: center;
+					background: #222222;
+					border-top-left-radius:8upx;
+					border-bottom-left-radius:8upx;
+					padding-left: 10upx;
+					.cart{
+						position: relative;
+						width: 36px;
+						height: 36px;
+						image{
+							width: 100%;
+							height: 100%;
+						}
+						.tag{
+							position: absolute;
+							right: 12upx;
+							top: 16upx;
+							height: 18px;
+							width: 18px;
+							background-color: #ff4000;
+							color: #ffffff;
+							border-radius: 50%;
+							z-index: 1;
+							font-size: 10px;
+							text-align: center;
+							line-height: 18px;
+						}
+					}
+					.priceBox{
+						flex: auto;
+					}
+					
+				}
+				&-right{
+					width: 70px;
+					height: 100%;
+					position: relative;
+					display: flex;
+					justify-content:flex-start;
+					align-self: center;
+					align-items: center;
+					
+					
+					.pscj{
+						width: 100%;
+						height: 100%;
+						border-top-right-radius:100upx;
+						border-bottom-right-radius:100upx;
+						background: #222222;
+						text-align: center;
+						display: flex;
+						justify-content:center;
+						align-self: center;
+						align-items: center;  
+					}
+					.jiesuan{
+						width: 100%;
+						height: 100%;
+						font-size: 28upx;
+						border-top-right-radius:100upx;
+						border-bottom-right-radius:100upx;
+						text-align: center;
+						display: flex;
+						justify-content:center;
+						align-self: center;
+						align-items: center;    
+						background: linear-gradient(45deg, $hx-theme-color-light, $hx-theme-color); 
+						font-weight: bold;
+						color: #222222;
+					}
+				}
+			}
+			.zz{
+				position: absolute;
+				top: 0;
+				left: 0;
+				right: 0;
+				bottom: 0;
+				background-color: rgba(0,0,0,.7);
+				z-index: 1;
+			}
+			.cart-box{
+				display: flex;
+				justify-content: flex-start;
+				flex-flow: column;
+				background: #ffffff;
+				position: absolute;
+				bottom: 0; 
+				z-index: 2;
+				max-height: 66%;
+				
+				padding-bottom: 62px;
+				border-top-left-radius: 16px;
+				border-top-right-radius: 16px;
+				overflow: hidden;
+				width: 100%;
+				.rebate-box{
+					height: 30px;
+					background: #FFC107;
+					color: #FF9900;
+					text-align: center;
+					line-height: 30px;
+					font-size: 14px;
+				}
+				.box-container{
+					box-sizing: border-box;
+					padding:0 16px;
+				}
+				.operating-box{
+					font-size: 12px;
+					line-height: 40px;
+					height: 40px;
+					border-bottom: 1px solid #f6f6f6;
+					color: #666666;
+					display: flex;
+					flex-direction: row;
+					&_right{
+						flex: 1;
+					}
+					&_left{
+						display: flex;
+						flex-direction: row;
+					}
+					
+				}
+				.goods-box{
+					height: 100%;
+				    overflow: hidden;
+					flex: 1;
+					display: flex;
+					.goods-list-scroll{
+						height: 100%;
+						
+						.goods-list{
+							
+							width: 100%;
+							display: flex;
+							flex-wrap: wrap;
+							
+							.box{
+								width: 100%;
+								border-bottom: 1px solid #f6f6f6;
+								box-sizing: border-box;
+								padding: 0 16px;
+								.m-store-item{
+									display: flex;
+									flex-direction: row;
+									width: 100%;
+									justify-content: space-between;
+									align-items: flex-end;
+									padding-top: 15px;
+									padding-bottom: 15px;
+									.m-img{
+										flex: 0 0 85px;
+										height: 85px;
+										background: #eee;
+										border-radius: 4px;
+									}
+									.m-text{
+										flex: 1;
+										position: relative;
+										height: 85px;
+										padding: 0 6px;
+										display: flex;
+										align-content: space-between;
+										flex-direction: column;
+										.m-title{
+											font-size: 16px;
+											color:#555555;
+											height: 21px;
+											font-weight: bold;
+										}
+										.m-descripe{
+											font-size: 12px;
+											color:#999999;
+											margin-top: 5px;
+											height: 35px;
+										}
+										.m-price-box{
+											height: 24px;
+											font-weight: bold;
+											display: flex;
+											flex-direction: row;
+											align-items: flex-end;
+											.symbol{
+												color:#ff582b;
+												font-size: 12px;
+											}
+											.m-price{
+												position: relative;
+												top: 2px;
+												font-size: 18px;
+												color:#ff582b;
+											}
+											.m-old-price{
+												margin-left: 3px;
+												display: flex;
+												flex-direction: row;
+												font-size: 10px;
+												color:#999999;
+												margin-top: 5upx;
+												text-decoration: line-through;
+												font-weight: normal;
+											}
+										}
+										.m-distance{
+											position: absolute;
+											right: 0;
+											bottom: -4px;
+											z-index: 16;
+											color:#b2b2b2;
+											font-size: 20upx;
+											text-align: right;
+											.jumpPosition{
+												position: absolute; 
+												bottom: 23px;
+												right: 0;
+												z-index: 2;
+												width: 28px;
+												height: 28px;
+											}
+										}
+										
+									}
+									
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+</style>

+ 342 - 0
HX-SHOP/pages/map/location.nvue

@@ -0,0 +1,342 @@
+<template>
+	<view>
+		<map :style="{width: '750rpx',height: mapHeight + 'px'}" class="map" 
+		:latitude="mapCenter.latitude" 
+		:longitude="mapCenter.longitude" 
+		:markers="markers" 
+		:polyline="polyline"></map>
+		 
+		 <view class="main">
+			<view class="main-top">
+		 		<view class="main-top-left">
+		 		 	<view class="main-top-left-txt ">
+		 		 		<text class="tit">骑手正在送货</text>
+		 		 	</view>
+		 		 	<view class="main-top-left-bottom mt8">
+		 		 		<text class="hxicon txt14 color-dark-gray">&#xe65e;</text>
+		 		 		<text class="txt14 ml6">预计送达</text>
+		 		 		<text class="txt14 ml6 color-blue">19:30</text>
+		 		 	</view>
+		 		</view>
+		 	 	<button style="width: 100px;" size="mini" class="btn" hover-class="bg-active" type="primary" @click="submit">确认收货</button>
+		 	</view>
+		 	<view class="main-bottom">
+		 		<image class="main-bottom-row1" :src="riderInfo.avatar" mode=""></image>
+		 		<view class="main-bottom-row2">
+		 			<text class="main-bottom-row2-txt1">{{riderInfo.name}}</text>
+		 			<text class="main-bottom-row2-txt2 mt2">满意度:{{praise}}%</text>
+		 		</view>
+		 		<text class="hxicon main-bottom-txt">&#xe779;</text>
+		 		<text class="hxicon main-bottom-txt" @click="call">&#xe652;</text>
+		 	</view>
+		 </view>
+		
+	</view>
+</template>
+
+<script>
+	// #ifdef APP-PLUS-NVUE
+	var domModule = weex.requireModule('dom');
+	domModule.addRule('fontFace', {
+	  'fontFamily': "iconfont",
+	  'src': "url('https://at.alicdn.com/t/font_1380649_u1j4yykb94h.ttf')"
+	})
+	// #endif
+	var sysInfo = uni.getSystemInfoSync();
+	export default {
+		data() {
+			return {
+				orderId: null,
+				markers: [],
+				polyline: [],
+				mapHeight: sysInfo.screenHeight,
+				// 用户经纬度
+				userAddress: {
+					// 经度
+					longitude: 41.173098,
+					// 纬度
+					latitude: 80.2632808
+				},
+				// 地图中心点
+				mapCenter: {
+					// 经度
+					longitude: null,
+					// 纬度
+					latitude: null
+				},
+				// 骑手经纬度
+				riderAddress: {
+					// 经度
+					longitude: 41.1730980,
+					// 纬度
+					latitude: 80.2632808
+				},
+				riderInfo: {
+					id: null,
+					name: null,
+					praise: 30,
+					dislike: 2,
+					phone: null,
+					avatar: 'https://imgs.1op.cn/i/hxshop/avatar/3.png'
+				},
+				praise: 100
+			};
+		},
+		onLoad(option) {
+			
+			if(option.id){
+				this.orderId = option.id
+			}
+			this.init()
+		},
+		mounted() {
+			
+		},
+		methods:{
+			// 获取用户收件地址
+			init(){
+				let that = this
+				new Promise((resolve, reject) =>{
+					// 你的请求逻辑
+					// ......
+					// 这里方便测试,我使用手机当前位置 代替 用户收件地址位置;上线则以用户填写的收件地址为准
+					// 假如请求成功拿到用户地址
+					uni.getLocation({
+						type: 'gcj02',
+						success: function (res) {
+							resolve(res)
+						},
+						fail:function(res) {
+							reject(res)
+						}
+					});
+				}).then((res) => {
+					//设置用户经纬度
+					that.userAddress = {
+						longitude: res.longitude,
+						latitude: res.latitude
+					}
+					// 接下来去拿取骑手信息
+					
+					// 假如通过请求拿到骑手信息
+					that.riderInfo = {
+						id: 863,
+						name: "闪电骑手",
+						praise: 81,
+						dislike: 3,
+						phone: '18299989999',
+						avatar: 'https://imgs.1op.cn/i/hxshop/avatar/3.png'
+					},
+					//计算好评
+					that.praise= parseInt(that.riderInfo.praise/(that.riderInfo.praise + that.riderInfo.dislike) * 100)
+					
+					// 接下来去拿取骑手地址去更新地图,并且每3秒获取一次
+					that.getRiderAddress()
+					setInterval(()=>{
+						that.getRiderAddress()
+					},3000)
+				},(err) => {
+					console.log("获取失败")
+				})
+			},
+			
+			getRiderAddress(){
+				let that = this
+				// 获取骑手位置
+				// ----------------------
+				// 假如通过请求获取到了骑手位置
+				// 伪造一个随机数,好像骑手在移动一样
+				var num = Math.floor(Math.random() * 25 + 3) /10000 + 0.015;
+				var num2 = Math.floor(Math.random() * 25 + 3) /10000 + 0.015;
+				that.riderAddress={
+					latitude: that.userAddress.latitude + num,
+					longitude: that.userAddress.longitude + num2
+				}
+				
+				// 地图标标记
+				that.markers = [
+					//用户标记
+					{
+						id: 1,
+						callout: {
+							content:'收件地址',
+							color:'#ff9900',
+							padding:'6',
+							borderRadius:'50',
+							textAlign:'left',
+							fontSize:'14',
+							display:'BYCLICK'
+						},
+						latitude: that.userAddress.latitude,
+						longitude: that.userAddress.longitude,
+						iconPath: '/static/img/map_home.png',
+						width: '64',
+						height: '64'
+					},
+					//骑手标记
+					{
+						id: 9999,
+						callout: {
+							content:'骑手',
+							color:'#ff9900',
+							padding:'6',
+							borderRadius:'50',
+							textAlign:'left',
+							fontSize:'14',
+							display:'ALWAYS'
+						},
+						latitude: that.riderAddress.latitude,
+						longitude: that.riderAddress.longitude,
+						iconPath: '/static/img/map_qs.png',
+						width:'64',
+						height:'64'
+					},
+				];
+				//线
+				that.polyline = [{
+					points: [that.userAddress,that.riderAddress],
+					color: "#ff9900",
+					width: 10
+				}];
+				
+					that.mapCenter={
+						latitude: that.riderAddress.latitude,
+						longitude: that.riderAddress.longitude
+					}
+				
+				
+			},
+			//打电话
+			call(){
+				if(this.riderInfo.phone){
+					uni.makePhoneCall({
+					    phoneNumber: ''+this.riderInfo.phone,
+						fail: (res)=>{
+							uni.showModal({
+								title: '提示',
+								content: "自动拨号失败!请手动拨打电话:" + this.riderInfo.phone,
+								showCancel: false,
+								cancelText: '',
+								confirmText: '确认',
+							});
+						}
+					});
+				}
+				
+			},
+			//确认收货
+			submit(){
+				//确认收货
+				
+				uni.showModal({
+					title: '提示',
+					content: '已确认收货'+this.orderId,
+					showCancel: false,
+					cancelText: '',
+					confirmText: '确认',
+					success: res => {},
+					fail: () => {},
+					complete: () => {}
+				});
+			}
+			
+		}
+	}
+</script>
+
+<style>
+
+.txt14{
+	font-size: 14px;
+}
+.mt8{
+	margin-top: 8px;
+}
+.mt2{
+	margin-top: 2px;
+}
+.ml6{
+	margin-left: 6px;
+}
+.color-blue{
+	color: #2196f3;
+}
+.color-dark-gray{
+	color: #888;
+}
+.main{
+	position: fixed;
+	z-index: 999;
+	bottom: 30px;
+	left: 15px;
+	right: 15px;
+	background-color: #fff;
+	border-radius: 10px;
+	padding: 15px 18px;
+	box-shadow: 0px 0px 10px #b7b7b7;
+	flex-direction: column;
+}
+.main-top{
+	flex-direction: row;
+	align-items: center;
+	padding-bottom: 15px;
+	border-bottom-width: 1px;
+	border-bottom-style: solid;
+	border-bottom-color: #eef1f4;
+}
+.main-top-left{
+	flex-direction: column;
+	flex: 1;
+}
+.main-top-left-txt{
+	font-size: 20px;
+	color: #333;
+}
+.main-top-left-bottom{
+	flex-direction: row;
+	align-items: center;
+}
+
+.hxicon-timefill{
+	font-size: 14px;
+}
+.main-bottom{
+	margin-top: 15px;
+	flex-direction: row;
+	align-items: center;
+}
+.main-bottom-row1{
+	width: 44px;
+	height: 44px;
+	border-radius: 50%;
+}
+.main-bottom-row2{
+	flex-direction: column;
+	flex: 1;
+	margin-left: 12px;
+}
+.main-bottom-row2-txt1{
+	font-size: 18px;
+	color: #333;
+}
+.main-bottom-row2-txt2{
+	font-size: 14px;
+	color: #333;
+}
+.main-bottom-txt{
+	font-size: 26px;
+	color: #666;
+	padding: 5px;
+	margin-left: 12px;
+}
+.bg-active{
+	background-image: linear-gradient(100deg, #e8d536, #dda809);
+}
+.btn{
+	background-image: linear-gradient(100deg, #FFEB3B, #FFC107);
+	border-width: 0;
+	padding: 6px 0;
+	color: #333333;
+}
+
+</style>

+ 153 - 0
HX-SHOP/pages/market/market.vue

@@ -0,0 +1,153 @@
+<template>
+	<view class="content">
+		<view class="head">
+			<view class="status"></view>
+			<view class="search" @click="goSearch">
+				<i class="hxicon-search"></i>
+				<text class="tit">搜索店铺</text>
+			</view>
+		</view>
+		<view class="tabs-box">
+			<view class="hx-tabs">
+				<view class="hx-tabs-item" v-for="(item,i) in tabs" :key="i"
+					:class="{'hx-tabs-active': swiperCurrent == i}" @click="swiperChange(i)"
+					:style="{transition: transtionTime + 'ms'}">
+					<text>{{item.name}}</text>
+				</view>
+				<view class="hx-tabs-slider-box"
+					:style="{width: (100/tabs.length) + '%',transition: transtionTime + 'ms',left:swiperCurrentSliderLeft + '%'}">
+					<view class="hx-tabs-slider"></view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				swiperCurrent: 0,
+				transtionTime: 100,
+				swiperCurrentSliderLeft: 0,
+				tabs: [{
+						name: '综合推荐',
+						data: [],
+						api: '',
+						load: false
+					},
+					{
+						name: '距离优先',
+						data: [],
+						api: '',
+						load: false
+					},
+				],
+			}
+		},
+		methods: {
+			swiperChange(index) {
+				this.swiperCurrent = index;
+				this.swiperCurrentSliderLeft = (100 / this.tabs.length) * index;
+				let url = this.tabs[index].api;
+
+				// index 0全部,1待支付,2待收货,3待评价,4退款
+				// 假如滑动了tab则 去获取对应的数据
+				if (this.tabs[index].data.length == 0) {
+					// 只获取一次数据
+					// this.getOrderData(index)
+				}
+			},
+		}
+	}
+</script>
+
+<style scoped lang="scss">
+	.head {
+
+		background: linear-gradient(100deg, #FFEB3B, #FFC107);
+		padding-bottom: 10px;
+		padding-top: 10px;
+
+		.status {
+			height: var(--status-bar-height);
+		}
+
+		.search {
+			height: 40px;
+			background-color: #fff;
+			border-radius: 10px;
+			margin: 0 15px;
+			display: flex;
+			align-items: center;
+			padding: 0 15px;
+			font-size: 14px;
+			color: #888;
+
+			i {
+				font-weight: bold;
+				font-size: 16px;
+			}
+
+			.tit {
+				margin-left: 6px;
+			}
+		}
+	}
+
+	.tabs-box {
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		width: 100%;
+		position: sticky;
+		top: calc(44px + var(--status-bar-height));
+		z-index: 10;
+		background-color: white;
+		height: 50px;
+		padding-bottom: 10px;
+
+		.hx-tabs {
+			position: relative;
+			display: flex;
+			height: 100%;
+			width: 100%;
+			justify-content: space-evenly;
+
+			&-item {
+				display: flex;
+				flex: 1;
+				flex-direction: row;
+				justify-content: center;
+				align-items: center;
+				width: 70px;
+				color: #666666;
+
+				text {
+					font-size: 16px;
+				}
+
+			}
+
+			&-active {
+				color: #333333;
+				font-weight: bold;
+			}
+
+			&-slider-box {
+				position: absolute;
+				display: flex;
+				justify-content: center;
+				bottom: 0;
+				width: 20%;
+			}
+
+			&-slider {
+				display: flex;
+				background: #f6d200;
+				width: 30px;
+				height: 3px;
+			}
+		}
+	}
+</style>

+ 733 - 0
HX-SHOP/pages/order/order.vue

@@ -0,0 +1,733 @@
+<template>
+	<view>
+		<view class="head">
+			<view class="status"></view>
+			<view class="search" @click="goSearch">
+				<i class="hxicon-search"></i>
+				<text class="tit">搜索我的订单</text>
+			</view>
+		</view>
+		<view class="tabs-box">
+			<view class="hx-tabs">
+				<view class="hx-tabs-item" v-for="(item,i) in tabs" :key="i" :class="{'hx-tabs-active': swiperCurrent == i}" @click="swiperChange(i)" :style="{transition: transtionTime + 'ms'}">
+					<text>{{item.name}}</text>
+				</view>
+				<view class="hx-tabs-slider-box" :style="{width: (100/tabs.length) + '%',transition: transtionTime + 'ms',left:swiperCurrentSliderLeft + '%'}">
+					<view class="hx-tabs-slider"></view>
+				</view>
+			</view>
+		</view>
+		
+		<view class="main" :style="{height: mainHeight}" >
+			<swiper 
+			id="mainSwiper"
+			style="height: 100%;"
+			:current="swiperCurrent" 
+			:duration="transtionTime"
+			@animationfinish="animationfinish">
+				
+				<swiper-item class="swiper-item" >
+					<view class="scroll-items">
+							<scroll-view 
+							style="height: 100%;width: 100%;"
+							scroll-with-animation 
+							:scroll-y="true" 
+							refresher-background="#eee" 
+							:refresher-enabled="reloadDown"  
+							:refresher-triggered="triggered"
+							:refresher-threshold="100" 
+							@refresherrefresh="onRefresh" 
+							@refresherrestore="onRestore" >
+								<!-- 标签为全部时,有推广图 -->
+								<view class=" bannerimg-box">
+									<swiper  circular duration="400" interval="10000" autoplay >
+										<swiper-item class="swiper-item bannerImg" v-for="(banner,k) in bannerData" :key="k" v-if="banner">
+											<!-- 图片尺寸为 750*250 -->
+											<image :src="banner.src" class="loaded" mode="widthFix"></image>
+										</swiper-item>
+									</swiper>
+								</view>
+								<view class="nullOrder" v-if="tabs[0].data && tabs[0].data.length == 0 && tabs[4].hide_load">
+									<image src="../../static/img/order_icon.png" mode=""></image>
+									<text class="tit">暂无订单</text>
+								</view>
+								<block v-for="(order,j) in tabs[0].data" :key="j" v-else>
+									
+								<view class="order-item" v-if="order">
+									<view class="item-top">
+										<image :src="order.tag" mode=""></image>
+										<view class="tit">
+											<text>{{order.store_name}}</text>
+											<text v-if="order.community">({{order.community}})</text>
+											<i class="hxicon-right"></i>
+										</view>
+										<view class="right" v-if="order.status == 1"><text>已取消</text></view>
+										<view class="right" v-else-if="order.status == 2"><text>待支付</text></view>
+										<view class="right" v-else-if="order.status == 3"><text>待收取</text></view>
+										<view class="right" v-else-if="order.status == 4"><text>待评价</text></view>
+										<view class="right" v-else-if="order.status == 5"><text>已完成</text></view>
+										<view class="right" v-else-if="order.status == 6"><text>退款中</text></view>
+										<view class="right" v-else-if="order.status == 7"><text>退款成功</text></view>
+									</view>
+									<view class="item-center">
+										<image :src="order.avatar" mode=""></image>
+										<view class="right">
+											<view class="row" v-if="order.goods_name">
+												<text>{{order.goods_name}}</text>
+											</view>
+											<view class="row">
+												<text>下单时间:{{order.create_time}}</text>
+											</view>
+											<view class="row">
+												<text>总价:¥{{order.total}}</text>
+											</view>
+										</view>
+									</view>
+									<view class="item-bottom">
+										<view class="left"></view>
+										<view class="btn" v-if="order.status == 1 || order.status == 5" @click="goStore(order.id)">再来一单</view>
+										<view class="btn bg-yellow" v-else-if="order.status == 2" @click="goPay(order.id)">去支付</view>
+										<view class="btn" v-else-if="order.status == 3" @click="goOrderInfo(order.id)">查看</view>
+										<view class="btn bg-yellow" v-else-if="order.status == 4" @click="goComment(order.id)">去评价</view>
+										<view class="btn" v-else-if="order.status == 6 || order.status == 7" @click="goRefund(order.id)">退款进度</view>
+									</view>
+								</view>
+								</block>
+							</scroll-view>
+					</view>
+				</swiper-item>
+				
+				
+				<swiper-item class="swiper-item" >
+					<view class="scroll-items">
+							<scroll-view 
+							style="height: 100%;width: 100%;"
+							scroll-with-animation 
+							:scroll-y="true" 
+							refresher-background="#eee" 
+							:refresher-enabled="reloadDown"  
+							:refresher-triggered="triggered"
+							:refresher-threshold="100" 
+							@refresherrefresh="onRefresh" 
+							@refresherrestore="onRestore" >
+								
+								<view class="nullOrder" v-if="tabs[1].data && tabs[1].data.length == 0 && tabs[4].hide_load">
+									<image src="../../static/img/order_icon.png" mode=""></image>
+									<text class="tit">暂无订单</text>
+								</view>
+								<block v-for="(order,j) in tabs[1].data" :key="j" v-else>
+									
+								<view class="order-item" v-if="order">
+									<view class="item-top">
+										<image :src="order.tag" mode=""></image>
+										<view class="tit">
+											<text>{{order.store_name}}</text>
+											<text v-if="order.community">({{order.community}})</text>
+											<i class="hxicon-right"></i>
+										</view>
+										<view class="right" v-if="order.status == 1"><text>已取消</text></view>
+										<view class="right" v-else-if="order.status == 2"><text>待支付</text></view>
+										<view class="right" v-else-if="order.status == 3"><text>待收取</text></view>
+										<view class="right" v-else-if="order.status == 4"><text>待评价</text></view>
+										<view class="right" v-else-if="order.status == 5"><text>已完成</text></view>
+										<view class="right" v-else-if="order.status == 6"><text>退款中</text></view>
+										<view class="right" v-else-if="order.status == 7"><text>退款成功</text></view>
+									</view>
+									<view class="item-center">
+										<image :src="order.avatar" mode=""></image>
+										<view class="right">
+											<view class="row" v-if="order.goods_name">
+												<text>{{order.goods_name}}</text>
+											</view>
+											<view class="row">
+												<text>下单时间:{{order.create_time}}</text>
+											</view>
+											<view class="row">
+												<text>总价:¥{{order.total}}</text>
+											</view>
+										</view>
+									</view>
+									<view class="item-bottom">
+										<view class="left"></view>
+										<view class="btn" v-if="order.status == 1 || order.status == 5" @click="goStore(order.store_id,order.id)">再来一单</view>
+										<view class="btn bg-yellow" v-else-if="order.status == 2" @click="goPay(order.id)">去支付</view>
+										<view class="btn" v-else-if="order.status == 3" @click="goOrderInfo(order.id)">查看</view>
+										<view class="btn bg-yellow" v-else-if="order.status == 4" @click="goComment(order.id)">去评价</view>
+										<view class="btn" v-else-if="order.status == 6 || order.status == 7" @click="goRefund(order.id)">退款进度</view>
+									</view>
+								</view>
+								</block>
+							</scroll-view>
+					</view>
+				</swiper-item>
+				
+				
+				<swiper-item class="swiper-item" >
+					<view class="scroll-items">
+							<scroll-view 
+							style="height: 100%;width: 100%;"
+							scroll-with-animation 
+							:scroll-y="true" 
+							refresher-background="#eee" 
+							:refresher-enabled="reloadDown"  
+							:refresher-triggered="triggered"
+							:refresher-threshold="100" 
+							@refresherrefresh="onRefresh" 
+							@refresherrestore="onRestore" >
+								
+								<view class="nullOrder" v-if="tabs[2].data && tabs[2].data.length == 0 && tabs[4].hide_load">
+									<image src="../../static/img/order_icon.png" mode=""></image>
+									<text class="tit">暂无订单</text>
+								</view>
+								<block v-for="(order,j) in tabs[2].data" :key="j" v-else>
+									
+								<view class="order-item" v-if="order">
+									<view class="item-top">
+										<image :src="order.tag" mode=""></image>
+										<view class="tit">
+											<text>{{order.store_name}}</text>
+											<text v-if="order.community">({{order.community}})</text>
+											<i class="hxicon-right"></i>
+										</view>
+										<view class="right" v-if="order.status == 1"><text>已取消</text></view>
+										<view class="right" v-else-if="order.status == 2"><text>待支付</text></view>
+										<view class="right" v-else-if="order.status == 3"><text>待收取</text></view>
+										<view class="right" v-else-if="order.status == 4"><text>待评价</text></view>
+										<view class="right" v-else-if="order.status == 5"><text>已完成</text></view>
+										<view class="right" v-else-if="order.status == 6"><text>退款中</text></view>
+										<view class="right" v-else-if="order.status == 7"><text>退款成功</text></view>
+									</view>
+									<view class="item-center">
+										<image :src="order.avatar" mode=""></image>
+										<view class="right">
+											<view class="row" v-if="order.goods_name">
+												<text>{{order.goods_name}}</text>
+											</view>
+											<view class="row">
+												<text>下单时间:{{order.create_time}}</text>
+											</view>
+											<view class="row">
+												<text>总价:¥{{order.total}}</text>
+											</view>
+										</view>
+									</view>
+									<view class="item-bottom">
+										<view class="left"></view>
+										<view class="btn" v-if="order.status == 1 || order.status == 5" @click="goStore(order.id)">再来一单</view>
+										<view class="btn bg-yellow" v-else-if="order.status == 2" @click="goPay(order.id)">去支付</view>
+										<view class="btn" v-else-if="order.status == 3" @click="goOrderInfo(order.id)">查看</view>
+										<view class="btn bg-yellow" v-else-if="order.status == 4" @click="goComment(order.id)">去评价</view>
+										<view class="btn" v-else-if="order.status == 6 || order.status == 7" @click="goRefund(order.id)">退款进度</view>
+									</view>
+								</view>
+								</block>
+							</scroll-view>
+					</view>
+				</swiper-item>
+				
+				
+				<swiper-item class="swiper-item" >
+					<view class="scroll-items">
+							<scroll-view 
+							style="height: 100%;width: 100%;"
+							scroll-with-animation 
+							:scroll-y="true" 
+							refresher-background="#eee" 
+							:refresher-enabled="reloadDown"  
+							:refresher-triggered="triggered"
+							:refresher-threshold="100" 
+							@refresherrefresh="onRefresh" 
+							@refresherrestore="onRestore" >
+								
+								<view class="nullOrder" v-if="tabs[3].data && tabs[3].data.length == 0 && tabs[4].hide_load">
+									<image src="../../static/img/order_icon.png" mode=""></image>
+									<text class="tit">暂无订单</text>
+								</view>
+								<block v-for="(order,j) in tabs[3].data" :key="j" v-else>
+									
+								<view class="order-item" v-if="order">
+									<view class="item-top">
+										<image :src="order.tag" mode=""></image>
+										<view class="tit">
+											<text>{{order.store_name}}</text>
+											<text v-if="order.community">({{order.community}})</text>
+											<i class="hxicon-right"></i>
+										</view>
+										<view class="right" v-if="order.status == 1"><text>已取消</text></view>
+										<view class="right" v-else-if="order.status == 2"><text>待支付</text></view>
+										<view class="right" v-else-if="order.status == 3"><text>待收取</text></view>
+										<view class="right" v-else-if="order.status == 4"><text>待评价</text></view>
+										<view class="right" v-else-if="order.status == 5"><text>已完成</text></view>
+										<view class="right" v-else-if="order.status == 6"><text>退款中</text></view>
+										<view class="right" v-else-if="order.status == 7"><text>退款成功</text></view>
+									</view>
+									<view class="item-center">
+										<image :src="order.avatar" mode=""></image>
+										<view class="right">
+											<view class="row" v-if="order.goods_name">
+												<text>{{order.goods_name}}</text>
+											</view>
+											<view class="row">
+												<text>下单时间:{{order.create_time}}</text>
+											</view>
+											<view class="row">
+												<text>总价:¥{{order.total}}</text>
+											</view>
+										</view>
+									</view>
+									<view class="item-bottom">
+										<view class="left"></view>
+										<view class="btn" v-if="order.status == 1 || order.status == 5" @click="goStore(order.id)">再来一单</view>
+										<view class="btn bg-yellow" v-else-if="order.status == 2" @click="goPay(order.id)">去支付</view>
+										<view class="btn" v-else-if="order.status == 3" @click="goOrderInfo(order.id)">查看</view>
+										<view class="btn bg-yellow" v-else-if="order.status == 4" @click="goComment(order.id)">去评价</view>
+										<view class="btn" v-else-if="order.status == 6 || order.status == 7" @click="goRefund(order.id)">退款进度</view>
+									</view>
+								</view>
+								</block>
+							</scroll-view>
+					</view>
+				</swiper-item>
+				
+				
+				<swiper-item class="swiper-item" >
+					<view class="scroll-items">
+							<scroll-view 
+							style="height: 100%;width: 100%;"
+							scroll-with-animation 
+							:scroll-y="true" 
+							refresher-background="#eee" 
+							:refresher-enabled="reloadDown"  
+							:refresher-triggered="triggered"
+							:refresher-threshold="100" 
+							@refresherrefresh="onRefresh" 
+							@refresherrestore="onRestore" >
+								
+								<view class="nullOrder" v-if="tabs[4].data && tabs[4].data.length == 0 && tabs[4].hide_load">
+									<image src="/static/img/order_icon.png" mode=""></image>
+									<text class="tit">暂无订单</text>
+								</view>
+								<block v-for="(order,j) in tabs[4].data" :key="j" v-else>
+									
+								<view class="order-item" v-if="order">
+									<view class="item-top">
+										<image :src="order.tag" mode=""></image>
+										<view class="tit">
+											<text>{{order.store_name}}</text>
+											<text v-if="order.community">({{order.community}})</text>
+											<i class="hxicon-right"></i>
+										</view>
+										<view class="right" v-if="order.status == 1"><text>已取消</text></view>
+										<view class="right" v-else-if="order.status == 2"><text>待支付</text></view>
+										<view class="right" v-else-if="order.status == 3"><text>待收取</text></view>
+										<view class="right" v-else-if="order.status == 4"><text>待评价</text></view>
+										<view class="right" v-else-if="order.status == 5"><text>已完成</text></view>
+										<view class="right" v-else-if="order.status == 6"><text>退款中</text></view>
+										<view class="right" v-else-if="order.status == 7"><text>退款成功</text></view>
+									</view>
+									<view class="item-center">
+										<image :src="order.avatar" mode=""></image>
+										<view class="right">
+											<view class="row" v-if="order.goods_name">
+												<text>{{order.goods_name}}</text>
+											</view>
+											<view class="row">
+												<text>下单时间:{{order.create_time}}</text>
+											</view>
+											<view class="row">
+												<text>总价:¥{{order.total}}</text>
+											</view>
+										</view>
+									</view>
+									<view class="item-bottom">
+										<view class="left"></view>
+										<view class="btn" v-if="order.status == 1 || order.status == 5">再来一单</view>
+										<view class="btn bg-yellow" v-else-if="order.status == 2">去支付</view>
+										<view class="btn" v-else-if="order.status == 3">查看</view>
+										<view class="btn bg-yellow" v-else-if="order.status == 4">去评价</view>
+										<view class="btn" v-else-if="order.status == 6 || order.status == 7">退款进度</view>
+									</view>
+								</view>
+								</block>
+							</scroll-view>
+					</view>
+				</swiper-item>
+			</swiper>
+		</view>
+		
+	</view>
+</template>
+
+<script>
+	var sysInfo = uni.getSystemInfoSync();
+	var statusBarHeight = uni.getSystemInfoSync().statusBarHeight;
+	//引入测试数据
+	import testData from "@/common/testdata.js";
+	export default {
+		data() {
+			return {
+				mainHeight: 0,
+				statusBarHeight,
+				tabs: [
+					{name:'全部', data:[], api:'',load: false},
+					{name:'待付款', data:[], api:'', load: false},
+					{name:'待使用', data:[], api:'', load: false},
+					{name:'待评价', data:[], api:'', load: false},
+					{name:'退款', data:[], api:'', load: false},
+				],
+				bannerData:[
+					{page: '/pages/product/product?id=457', src: '//imgs.1op.cn/i/hxshop/banner/banner.jpg'},
+					{page: '/pages/product/product?id=57', src:'//imgs.1op.cn/i/hxshop/banner/banner.jpg'},
+					{page: '/pages/product/product?id=95', src:'//imgs.1op.cn/i/hxshop/banner/banner.jpg'},
+					{page: '/pages/product/product?id=45', src:'//imgs.1op.cn/i/hxshop/banner/banner.jpg'}
+				],
+				
+				swiperCurrent: 0,
+				transtionTime:100,
+				swiperCurrentSliderLeft: 0,
+				orderData: [
+					//1,2,3,4,5,6,7,8,9,10
+				],
+				triggered: true,
+				//下拉刷新
+				reloadDown: false,
+				
+			}
+		},
+		onLoad(option) {
+			
+			this.mainHeight = sysInfo.screenHeight - statusBarHeight - 50 - 60 - 50 + 'px';
+			this._freshing = false;
+			if(option.state){
+				this.swiperChange(option.state) 
+				console.log(option.state);
+			}else{
+				// 全部订单 index为0
+				this.tabs[0].data= testData.ordersData
+			}
+		},
+		mounted() {
+			
+		},
+		methods: {
+			animationfinish({detail: { current }}) {
+				/* this.$refs.tabs.setFinishCurrent(current); */
+				this.swiperCurrent = current;
+				this.current = current;
+				this.swiperChange(current);
+			},
+			swiperChange(index) {
+				this.swiperCurrent = index;
+				this.swiperCurrentSliderLeft= (100/this.tabs.length) * index;
+				let url = this.tabs[index].api;
+				
+				// index 0全部,1待支付,2待收货,3待评价,4退款
+				// 假如滑动了tab则 去获取对应的数据
+				if(this.tabs[index].data.length == 0){
+					// 只获取一次数据
+					this.getOrderData(index)
+				}
+			},
+			getOrderData(index){
+				var orderData = []
+				//------------------------------------------
+				//--------------------------------------------
+				// 假如这为请求
+				for(let i in testData.ordersData){
+					if(!testData.ordersData[i]){
+						console.log("不存在:"+i)
+					}
+					if(index == 1 && testData.ordersData[i].status == 2){
+						orderData.push(testData.ordersData[i]);
+					}else if(index == 2 && testData.ordersData[i].status == 3){
+						orderData.push(testData.ordersData[i]);
+					}else if(index == 3 && testData.ordersData[i].status == 4){
+						orderData.push(testData.ordersData[i]);
+					}else if(index == 4 && (testData.ordersData[i].status == 6 || testData.ordersData[i].status == 7)){
+						orderData.push(testData.ordersData[i]);
+					}
+				}
+				//--------------------------------------------
+				//--------------------------------------------
+				uni.showLoading()
+				// 假如 orderData 为返回的数据,我们吧数据赋给对应的index 即可
+				setTimeout(()=>{
+					this.tabs[index].data= orderData
+					this.tabs[index].hide_load = true
+					uni.hideLoading()
+				},1000)
+			},
+			// 下拉刷新
+			onRefresh() {
+				if (this._freshing) return;
+				this._freshing = true;
+				setTimeout(() => {
+					this.triggered = false;
+					this._freshing = false;
+				}, 1500)
+			},
+			onRestore() {
+				this.triggered = 'restore'; // 需要重置
+				console.log("重置刷新");
+			},
+			//去支付
+			goPay(orderId){
+				uni.redirectTo({
+				    url: '/pages/order/pay?id=' + orderId
+				});
+			},
+			//去门店
+			goStore(storeId,orderId){
+				uni.redirectTo({
+				    url: '/pages/store/index?sid=' + storeId + '&oid=' + orderId
+				});
+			},
+			//去订单详情
+			goOrderInfo(orderId){
+				uni.redirectTo({
+				    url: '/pages/map/location?id=' + orderId
+				});
+			},
+			//去评论
+			goComment(orderId){
+				// uni.redirectTo({
+				//     url: '/pages/order/pay?id=' + orderId
+				// });
+			},
+			//查看退款详情
+			goRefund(orderId){
+				// uni.redirectTo({
+				//     url: '/pages/order/pay?id=' + orderId
+				// });
+			},
+			//搜索
+			goSearch(){
+				uni.navigateTo({
+					url: '/pages/search/search?type=order'
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+.head{
+	
+	background: linear-gradient(100deg, #FFEB3B, #FFC107);
+	padding-bottom: 10px;
+	padding-top: 10px;
+	.status{
+		height: var(--status-bar-height);
+	}
+	.search{
+		height: 40px;
+		background-color: #fff;
+		border-radius: 10px;
+		margin: 0 15px;
+		display: flex;
+		align-items: center;
+		padding: 0 15px;
+		font-size: 14px;
+		color: #888;
+		i{
+			font-weight: bold;
+			font-size: 16px;
+		}
+		.tit{
+			margin-left: 6px;
+		}
+	}
+}
+.tabs-box{
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	width: 100%;
+	position: sticky;
+	top: calc(44px + var(--status-bar-height));
+	z-index: 10;
+	background-color: white;
+	height: 50px;
+	padding-bottom: 10px;
+	
+	.hx-tabs{
+		position: relative;
+		display: flex;
+		height:100%;
+		width: 100%;
+		justify-content: space-evenly;
+		&-item{
+			display: flex;
+			flex: 1;
+			flex-direction: row;
+			justify-content: center;
+			align-items: center;
+			width: 70px;
+			color:#666666;
+			text{
+				font-size: 16px;
+			}
+			
+		}
+		&-active{
+			color:#333333;
+			font-weight: bold;
+		}
+		&-slider-box{
+			position: absolute;
+			display: flex;
+			justify-content: center;
+			bottom: 0;
+			width: 20%;
+		}
+		&-slider{
+			display: flex;
+			background: #f6d200;
+			width: 30px;
+			height: 3px;
+		}
+	}
+}
+.main{
+	position: relative;
+	background-color: #ffffff;
+	#mainSwiper{
+		background-color: #eeeeee;
+		height: 100%;
+		width: 100%;
+		.bannerimg-box{
+			border-bottom-left-radius:10upx;
+			border-bottom-right-radius:10upx;
+			padding: 15px 24rpx 7px;
+			swiper{
+				height: 233rpx;
+				width: 699rpx;
+			}
+			.swiper-item {
+				
+				display: flex;
+				justify-content: center;
+				align-content: center;
+				overflow: hidden;
+				
+				width: 100%;
+				height: 100%;
+				image {
+					border-radius: 8px;
+					width: 100%;
+				}
+			}
+		}
+		.nullOrder{
+			display: flex;
+			flex-direction: column;
+			justify-content: center;
+			align-items: center;
+			margin: 40px auto;
+			image{
+				width: 283px;
+				height: 200px;
+			}
+			.tit{
+				display: flex;
+				flex-direction: column;
+				font-size: 16px;
+				font-weight: bold;
+				color: #555;
+				margin-top: 6px;
+				
+			}
+		}
+		.scroll-items{
+			height: 100%;
+			.order-item{
+				display: flex;
+				flex-direction: column;
+				background-color: #fff;
+				margin: 8px 15px;
+				border-radius: 10px;
+				padding: 0 15px;
+				.item-top{
+					display: flex;
+					flex-direction: row;
+					align-items: center;
+					padding: 12px 0;
+					border-bottom: 1px solid #f5f5f5;
+					image{
+						border-radius: 50%;
+						width: 24px;
+						height: 24px;
+					}
+					.tit{
+						flex: 1;
+						margin-left: 6px;
+						font-size: 16px;
+						font-weight: bold;
+						color: #333;
+						padding-right: 40px;
+						display: flex;
+						align-items: center;
+						flex-wrap: wrap;
+						flex-direction: row;
+
+					}
+					.right{
+						font-size: 14px;
+						color: #666;
+					}
+				}
+				.item-center{
+					display: flex;
+					flex-direction: row;
+					margin-top: 12px;
+					color: #666;
+					font-size: 14px;
+					image{
+						border-radius: 6px;
+						height: 60px;
+						width: 60px;
+					}
+					.right{
+						flex: 1;
+						margin-left: 10px;
+					}
+				}
+				.item-bottom{
+					display: flex;
+					flex-direction: row;
+					margin-top: 12px;
+					margin-bottom: 15px;
+					.left{
+						flex: 1;
+					}
+					.btn{
+						padding: 7px 14px;
+						border: 1px solid #cdcdcd;
+						font-size: 14px;
+						color: #555;
+						border-radius: 10px;
+						transition: all 0.2s;
+						background: #fff;
+					}
+					.btn:active{
+						color: #888;
+						background: #f1f1f1;
+					}
+					.bg-yellow{
+						background: linear-gradient(100deg, #FFEB3B, #FFC107);
+						border-color: #ffe635;
+						font-weight: bold;
+					}
+					.bg-yellow:active{
+						background: linear-gradient(100deg, #e8d536, #dda809);
+					}
+				}
+			}
+		}
+		// position: sticky;
+		//top: calc(50px + 44px + var(--status-bar-height));
+		
+	}
+	
+}
+</style>

+ 336 - 0
HX-SHOP/pages/order/pay.vue

@@ -0,0 +1,336 @@
+<template>
+	<view>
+		<hx-navbar title="支付订单" :backgroundColor="[241,241,241]"></hx-navbar>
+		<view class="head">
+			<view class="row" >
+				<text v-if="countdownStr">支付剩余时间 {{countdownStr}}</text>
+				<text v-else>重新提交订单</text>
+			</view>
+			<view class="row pricebox pt-8">
+				<text class="fh">¥</text>
+				<text class="txt1">{{orderInfo.money}}</text>
+			</view>
+			<view class="row pt-4" @click="doOrder">
+				<text>{{orderInfo.store_name}}</text>
+				<text v-if="orderInfo.store_community">({{orderInfo.store_community}})</text>
+				<text>订单详情</text>
+				<i class="hxicon-right"></i>
+			</view>
+		</view>
+		<view class="container">
+			<radio-group @change="payChange" class="list-box">
+			<block v-for="(item,i) in payData" :key="i">
+				<view class="flex-rl list-item">
+					<view class="left">
+						<view class="iconbox" :style="'background-color:' + item.icon_color">
+							<i :class="item.icon" ></i>
+						</view>
+						
+					</view>
+					<view class="b-b right">
+						<view class="tit-box">
+							<text class="tit">{{item.name}}</text>
+						</view>
+						<radio :value="item.id" color="#ffc107" :checked="item.default == 1" />
+					</view>
+				</view>
+			</block>
+			</radio-group>
+		</view>
+		<view class="btn" @click="submitPay">
+			<text>确认支付</text>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		onLoad(option) {
+			let that = this
+			//获取订单id
+			if(option.id){
+				
+			}
+		},
+		onReady(){
+			let that = this
+			that.orderInfo = {
+				//订单id
+				order_id: "LQL20200410134",
+				//金额
+				money: 206.2,
+				//门店名称
+				store_name: "小太阳红旗商店",
+				//门店地标
+				store_community: "玫瑰园店",
+				//订单创建时间
+				create_date: "2020-04-10 18:08:56",
+				//订单有效期
+				expiration_date: "2021-04-12 20:06:56"
+			}
+			that.countdown();
+			
+			for (let i in this.payData){
+				if(this.payData[i].default == 1){
+					this.payType = this.payData[i].id
+				}
+			}
+		},
+		data() {
+			return {
+				countdownStr: "00:00",
+				//订单信息
+				orderInfo:{},
+				//默认支付方式
+				payType:"wxpay",
+				// 支付方式
+				payData: [{
+						id: "wxpay",
+						name: "微信支付",
+						icon: "hxicon-weixinzhifu",
+						icon_color: "#09bb07",
+						default: 0,
+					},
+					{
+						id: "alipay",
+						name: "支付宝支付",
+						icon: "hxicon-zhifubaozhifu",
+						icon_color: "#08a0e9",
+						default: 1
+					}],
+
+			}
+		},
+		methods: {
+			
+			payChange(event){
+				
+				this.payType = event.target.value
+			},
+			doOrder(){
+				//查看订单
+				uni.showModal({
+				    content: '这是查看订单的事件',
+					showCancel: false,
+					confirmColor: "#999",
+				    success: function (res) {
+				       
+				    }
+				});
+			},
+			
+			//倒计时
+			countdown(){
+				var go_time=new Date((this.orderInfo.expiration_date).replace(/-/g, '/'));
+				var now_time=new Date();
+				if(!go_time.getTime()){
+					return
+				}
+				var alltime =go_time.getTime() -now_time.getTime ();  //剩余的时间(毫秒)
+				if(alltime <= 0){
+					this.countdownStr = ""
+					this.showPrompt()
+					return
+				}
+				 var haoscend =alltime%1000;  //毫秒
+				//console.log(haoscend);
+				var scend = parseInt ((alltime/1000)%60  )
+				//console.log(scend);
+				var minute =parseInt((alltime/1000/60)%60  )
+			   // console.log(minute);
+				var hour =parseInt((alltime/1000/60/60)%24 )
+				if(scend<10){
+					scend = "0" + scend
+				}
+				if(minute<10){
+					minute = "0" + minute
+				}
+				let str = minute +":"+scend;
+				if(hour>0){
+					str = hour + ':' + str
+				}
+				this.countdownStr = str
+				setTimeout (this.countdown ,1000); 
+			},
+			//显示弹窗
+			showPrompt(){
+				uni.showModal({
+				    content: '支付超时,请重新下单',
+					showCancel: false,
+					confirmText: "重新下单",
+					confirmColor: "#999",
+				    success: function (res) {
+				        if (res.confirm) {
+				           
+				        }
+				    }
+				});
+			},
+			//确认支付
+			submitPay(){
+				if(this.countdownStr == ''){
+					this.showPrompt()
+					return
+				}
+				// #ifdef APP-PLUS
+					
+					uni.requestPayment({
+					    provider: this.payType,
+					    orderInfo: 'orderInfo', //微信、支付宝订单数据
+					    success: function (res) {
+					        console.log('success:' + JSON.stringify(res));
+					    },
+					    fail: function (err) {
+					        console.log('fail:' + JSON.stringify(err));
+					    }
+					});
+				//#endif
+			
+				// #ifdef MP-WEIXIN
+				//微信小程序
+				uni.requestPayment({
+					provider: 'wxpay',
+					timeStamp: String(Date.now()),
+					nonceStr: 'A1B2C3D4E5',
+					package: 'prepay_id=wx20180101abcdefg',
+					signType: 'MD5',
+					paySign: '',
+					success: function (res) {
+						console.log('success:' + JSON.stringify(res));
+					},
+					fail: function (err) {
+						console.log('fail:' + JSON.stringify(err));
+					}
+				});
+				// #endif
+				
+			}
+		   
+		}
+	}
+</script>
+
+<style lang="scss">
+	page{
+		background-color: #f1f1f1;
+	}
+	.pt-8{
+		margin-top: 8px;
+	}
+	.pt-4{
+		margin-top: 4px;
+	}
+	.flex-rl{
+		display: flex;
+		flex-direction: row;
+		justify-content: space-between;
+	}
+	.head{
+		display: flex;
+		flex-direction: column;
+		justify-content: center;
+		padding: 30px 15px;
+		.row{
+			display: flex;
+			flex-direction: row;
+			justify-content: center;
+			font-size: 12px;
+			color: #888;
+			.fh{
+				font-size: 16px;
+				font-weight: bold;
+				color: #000;
+			}
+			.txt1{
+				font-size: 34px;
+				font-weight: bold;
+				color: #000;
+			}
+			[class*="hxicon-"]{
+				position: relative;
+				top: 3px;
+				margin-left: 3px;
+			}
+		}
+		.pricebox{
+			display: flex;
+			flex-direction: row;
+			align-items: baseline;
+		}
+		
+	}
+	.container{
+		margin: 15px;
+		border-radius: 10px;
+		background-color: #fff;
+		overflow: hidden;
+		padding: 0 8px 0 14px;
+		.list-box{
+			display: flex;
+			flex-direction: column;
+			.list-item{
+				display: flex;
+				flex-direction: row;
+				
+				align-items: center;
+				height: 50px;
+				
+				
+				.left{
+					display: flex;
+					flex-direction: row;
+					align-items: center;
+					.iconbox{
+						display: flex;
+						flex-direction: row;
+						justify-content: center;
+						align-items: center;
+						height: 24px;
+						width: 24px;
+						border-radius: 4px;
+						[class*="hxicon-"]{
+							font-size: 22px;
+							color: #fff;
+						}
+						
+					}
+					
+					
+				}
+				.right{
+					display: flex;
+					flex-direction: row;
+					align-items: center;
+					flex: 1;
+					height: 100%;
+					.tit-box{
+						flex: 1;
+						.tit{
+							font-size: 16px;
+							color: #333;
+							margin-left: 6px;
+						}
+					}
+					
+				}
+			}
+		}
+	}
+	.btn{
+		position: fixed;
+		display: flex;
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+		border-radius: 10px;
+		overflow: hidden;
+		bottom: 15px;
+		left: 15px;
+		right: 15px;
+		height: 45px;
+		font-size: 16px;
+		font-weight: bold;
+		color: #333;
+		background: linear-gradient(45deg, #ffd900, #ffc107);		
+	}
+</style>

+ 869 - 0
HX-SHOP/pages/order/preview.vue

@@ -0,0 +1,869 @@
+<template>
+	<view>
+		<hx-navbar  
+		:border="false" 
+		:centerSlidiSwitch="true"
+		:rightSlidiSwitch="false"
+		:fixed="true"
+		:backgroundColor="[255,193,7]"
+		:pageScroll.sync="scrollData">
+		    <view style="text-align: center;width: 100%;">
+		        <text>提交订单</text>
+		    </view>
+		    <view slot="centerAfter" style="text-align: center;width: 100%;">
+		        <text>选择收获地址 ></text>
+		    </view>
+		</hx-navbar>
+		<view class="head tab-right-active">
+		
+			<view class="tab-box" v-if="tabIndex>0">
+				<view class="item left" :class="{'active':tabIndex == 1}"  @click="tabIndex = 1">
+					<view class="tit-box">
+						<text>配送</text>
+					</view>
+				</view>
+				<view class="item right" :class="{'active':tabIndex == 2}"  @click="tabIndex=2">
+					<view class="tit-box">
+						<text>到店自取</text>
+					</view>
+				</view>
+			</view>
+			<view class="container head-bottom" :class="{'selectOne': tabIndex == 1,'selectTow':tabIndex == 2}">
+				<view class="tab" v-if="tabIndex == 2">
+					2
+				</view>
+				<view class="tab" v-else>
+					<view class="t-top">
+						<view class="t-top-box">
+							<block  v-if="!addressData">
+								<text class="txt1">选择收货地址</text>
+								<i class="hxicon-right icon1"></i>
+							</block>
+							<block v-else>
+								
+							</block>
+						</view>
+					</view>
+					<view class="t-bb"></view>
+					<view class="t-bottom">
+						<view class="row1">
+							<view class="left">
+								<text>送达时间</text>
+							</view>
+							<view class="right">
+								<text>未选择(必选)</text>
+								<i class="hxicon-right"></i>
+							</view>
+						</view>
+						<view class="row2">
+							<text>为减少接触,封闭管理时,请在地址中更新具体去餐点</text>
+						</view>
+					</view>
+				</view>
+			</view>
+		</view>
+		<view class="b-r m-t container p12">
+			<view class="store">
+				<view class="name ">
+					<text>{{storeData.store_name}}</text>
+					<!-- 标志性位置 ,社区  如:白羊区店,玫瑰园小区 -->
+					<text v-if="storeData.community">({{storeData.community}})</text>
+				</view>
+				<view class="p-bb b-b"></view>
+				<view class="goods-box" >
+					<block v-for="(goods,i) in storeData.shopping_cart" :key="i" v-if="storeData.shopping_cart">
+					<view class="goods-item" >
+						<view class="left">
+							<image :src="goods.img" mode="aspectFit"></image>
+						</view>
+						<view class="right">
+							<view class="row1">
+								<view class="tit">
+									<text class="zk" v-if="goods.oldprice && Number(goods.price) < Number(goods.oldprice)">折</text>
+									<text>{{goods.name}}</text>
+									
+								</view>
+								<view class="old-price" v-if="goods.oldprice">
+									<text class="fh">¥</text><text class="lt">{{goods.oldprice}}</text>
+								</view>
+								<view class="price">
+									<text class="fh">¥</text><text>{{goods.price}}</text>
+								</view>
+							</view>
+							<view class="row2">
+								<text>{{goods.descripe}}</text>
+							</view>
+							<view class="row3">
+								x<text>{{goods.number}}</text>
+							</view>
+						</view>
+					</view>
+					</block>
+				</view>
+				<view class="p-bb b-b"></view>
+				<view class="flex-rl peisong">
+					<view class="right">
+						<text>配送费</text>
+					</view>
+					<view class="left">
+						<text class="fh">¥</text><text>{{storeData.shipping_dees}}</text>
+					</view>
+				</view>
+				<view class="p-bb b-b"></view>
+				<view class="zhekou-box">
+					<block v-for="(item,i) in couponData" :key="i">
+						<view class="zhekou">
+							<view class="flex-rl  row1">
+								<view class="left">
+									<i class="hxicon" :class="item.icon"></i>
+									<text class="tit">{{item.tit}}</text>
+								</view>
+								<view class="right">
+									<view class="tag1">
+										<text>{{item.content}}</text>
+									</view>
+								</view>
+							</view>
+							<!-- 备注 -->
+							<view class="row2" v-if="item.remark">
+								{{item.remark}}
+							</view>
+						</view>
+					</block>
+				</view>
+				<view class="p-bb b-b"></view>
+				<view class="flex-rl totalbox" >
+					<view class="left">
+						<text>优惠规则</text>
+						<i class="hxicon-question"></i>
+					</view>
+					<view class="right">
+						<view class="yh">
+							<text class="txt">已优惠</text>
+							<text class="fh">¥</text>
+							<text class="num">{{totalYhPrice}}</text>
+						</view>
+						<view class="total">
+							<text class="txt">小计</text>
+							<text class="fh">¥</text>
+							<text class="num">{{totalPrice}}</text>
+						</view>
+					</view>
+				</view>
+				
+			</view>
+		</view>
+		<view class="b-r m-t container p12">
+			<view class="privacy">
+				<view class="flex-rl row1 ">
+					<view class="left">
+						<i class=" hxicon-cardboardfill icon1"></i>
+						<text class="txt">号码保护</text>
+						<i class=" hxicon-question icon2"></i>
+					</view>
+					<view class="right">
+						<switch :checked="ysStatus" @change="privacyStatusChange" color="#ffc107"/>
+					</view>
+				</view>
+				<view class="row2">
+					对商家,骑手隐藏您的真实手机号,保护您的隐私
+				</view>
+				<view class="row3" v-if="ysStatus">
+					为保障服务质量,开启号码保护的订单通话可能会被录音
+				</view>
+			</view>
+		</view>
+		<view class="b-r m-t container p12 other-box">
+			<view class="flex-rl row">
+				<view class="left">
+					<text>备注</text>
+				</view>
+				<view class="right">
+					<text v-if="remark">{{remark}}</text>
+					<text v-if="!remark">点击可填写备注</text>
+					<i class="hxicon-right"></i>
+				</view>
+			</view>
+		</view>
+		<view class="body-end"></view>
+		
+		<view class="foot">
+			<view class="left">
+				<view class="price">
+					<text class="fh">¥</text>
+					<text class="txt">{{totalPrice}}</text>
+				</view>
+				<view class="discount" v-if="totalYhPrice">
+					<text>已优惠¥{{totalYhPrice}}</text>
+				</view>
+			</view>
+			<view class="center">
+				<text>找人付</text>
+			</view>
+			<view class="right" @click="submit">
+				<text>提交订单</text>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+		    return {
+		        scrollData: {},
+				//购物车缓存 Storage 名称
+				shoppingCartStorageName: 'shopping_cart',
+				//门店信息
+				storeData:{},
+				//购物车
+				shoppCart:[],
+				//头部选项卡 参数为 0不显示选项卡,1,2
+				tabIndex:1,
+				//收获地址
+				addressData: null,
+				//手机隐私
+				ysStatus: true,
+				
+				//优惠券
+				couponData: [{
+					id:"ASD2020410003",
+					icon: "icon-ticket_money_fill",
+					//标题
+					tit: "门店新客立减",
+					//说明
+					content: "15元商家券",
+					//备注
+					remark: "满减券和商品折扣可同享",
+					//面额
+					value: 15
+				},{
+					id:"ASD2020410001",
+					icon: "icon-ticket_money_fill",
+					tit: "商家抵用立减",
+					content: "-¥50",
+					//面额
+					value: 50
+				}],
+				
+				//结算价
+				totalPrice: 0,
+				//已优惠价
+				totalYhPrice: 0,
+				//商品数量
+				totalNumber: 0,
+				
+				remark: ""
+		    }
+		},
+		onLoad(option){
+			let that = this
+			let totalPrice = 0
+			let totalNumber = 0
+			let totalOldPrice = 0
+			if(option.sid){
+				let carts = uni.getStorageSync(that.shoppingCartStorageName) || []
+				if(carts){
+					//根据缓存数据 获取购物车中属于本商店的商品
+					for(let i in carts){
+						if(carts[i].store_id == option.sid){
+							that.shoppCart = carts[i].shopping_cart;
+							that.storeData = carts[i]
+							break;
+						}
+					}
+				}
+				let cj = 0
+				let op = 0
+				let p = 0
+				let num = 0
+				//计算总商品数量和总价
+				for(var i in that.shoppCart){
+					p = Number(that.shoppCart[i].price);
+					op = Number(that.shoppCart[i].oldprice);
+					num = Number(that.shoppCart[i].number)
+					totalNumber += num
+					totalPrice += p * num
+					if(op > p){
+						cj +=  (op - p) * num
+					}
+				}
+				that.totalPrice = totalPrice
+				that.totalYhPrice = cj
+			}
+			
+		},
+		onPageScroll(e){
+		    this.scrollData = e;
+		},
+		methods: {
+			privacyStatusChange(e){
+				this.ysStatus = e.target.value
+			},
+			
+			//提交订单
+			submit(){
+				let that = this
+				let goodsID = []
+				for (var i in that.shoppCart){
+					goodsID.push(that.shoppCart[i].id)
+				}
+				let data = {
+					//商品id
+					goods : goodsID,
+					//使用的优惠券 id
+					coupon: [],
+					//手机隐私
+					privacy_status: that.ysStatus ? 1 : 0
+				}
+				
+				//向后台发送 data 进行真实合计,生成订单,并返回订单信息
+				//模拟请求数据
+				uni.showLoading({
+				    title: '正在生成订单'
+				});
+				setTimeout(()=>{
+					uni.hideLoading()
+				},1000)
+				//假设返回了订单信息,跳转至支付页面
+				let orderId="DGSD2020041035"
+				uni.redirectTo({
+				    url: '/pages/order/pay?id=' + orderId
+				});
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+
+.b-r{
+	border-radius: 6px;
+}
+.m-t{
+	margin-top: 6px;
+}
+
+.p-bb{
+	margin: 16px 0;
+	height: 1px;
+	//background:  #E4E7ED;
+}
+.flex-rl{
+	display: flex;
+	flex-direction: row;
+	justify-content: space-between;
+}
+.container{
+	margin-left: 12px;
+	margin-right: 12px;
+	background-color: #ffffff;
+}
+.p12{
+	padding: 12px;
+}
+.head{
+	background: linear-gradient(to bottom, #ffc107, #f1f1f1);
+	
+	padding-top: 20px;
+	
+	.tab-box{
+		position: relative;
+		height: 40px;
+		margin: 0 12px;
+		.item{
+			position: absolute;
+			top: 0;
+			bottom: 0;
+			height: 40px;
+			text-align: center;
+			font-size: 14px;
+			
+			width: 50%;
+			.tit-box{
+				position: relative;
+				height: 36px;
+				line-height: 36px;
+				border-top-left-radius: 6px;
+				border-top-right-radius: 6px;
+				background-color: rgba(#ffffff, .6);
+				width: 100%;
+			}
+		}
+		.item:first-child{
+			display: flex;
+			flex-direction: row;
+			justify-content: flex-start;
+			align-items: flex-end;
+			left: 0;
+		}
+		.item:last-child{
+			display: flex;
+			flex-direction: row;
+			justify-content: flex-end;
+			align-items: flex-end;
+			right: 0;
+		}
+		.active{
+			height: 40px;
+			width: 51%;
+			font-weight: bold;
+			.tit-box{
+				height: 40px;
+				line-height: 40px;
+				background-color:rgba(#ffffff, 1);
+			}
+			
+		}
+		.left .tit-box{
+			margin-left: 12px;
+			margin-right: -12px;
+			padding-right: 12px;
+		}
+		.right .tit-box{
+			margin-right: 12px;
+			margin-left: -12px;
+			padding-left: 12px;
+		}
+		.left.active .tit-box{
+			margin: 0;
+		}
+		.right.active .tit-box{
+			margin: 0;
+		}
+		.left.active .tit-box:after{
+			content: '';
+			position: absolute;
+			right: -12px;
+			bottom: 0;
+			border-top: 12px solid transparent;
+			border-right: 12px solid transparent;
+			border-bottom: 36px solid #ffffff;
+		}
+		.right.active .tit-box:after{
+			content: '';
+			position: absolute;
+			left: -12px;
+			bottom: 0;
+			border-top: 12px solid transparent;
+			border-left: 12px solid transparent;
+			border-bottom: 36px solid #ffffff;
+		}
+	}
+	.head-bottom{
+		overflow: hidden;
+		background: #ffffff;
+		border-top-left-radius: 6px;
+		border-top-right-radius: 6px;
+		border-bottom-left-radius: 6px;
+		border-bottom-right-radius: 6px;
+		
+		.tab{
+			
+			.t-top{
+				
+				&-box{
+					margin: 0;
+					padding: 12px;
+					.txt1{
+						font-size: 18px;
+						color: #888;
+					}
+					.icon1{
+						margin-left: 8px;
+						color: #bbb;
+					}
+				}
+				&-box:active{
+					background-color: #f5f5f5;
+				}
+			}
+			.t-bb{
+				margin: 0 12px;
+				height: 0.5px;
+				background-color:  #E4E7ED;
+			}
+			.t-bottom{
+				padding: 12px;
+				.row1{
+					display: flex;
+					flex-direction: row;
+					justify-content: space-between;
+					
+					//padding: 12px 0 0;
+					.left{
+						font-size: 14px;
+						font-weight: bold;
+					}
+					.right{
+						font-size: 14px;
+						color: #ff9800;
+						i{
+							margin-left: 8px;
+							color: #bbb;
+						}
+					}
+				}
+				.row2{
+					margin-top: 6px;
+					font-size: 12px;
+					color: #ff9800;
+				}
+			}
+		}
+	}
+	.head-bottom.selectOne{
+		border-top-left-radius: 0;
+		border-top-right-radius: px;
+	}
+	.head-bottom.selectTow{
+		border-top-left-radius: 6px;
+		border-top-right-radius: 0;
+	}
+}
+
+.store{
+	display: flex;
+	flex-direction: column;
+	
+	.name{
+		padding: 4px 0 0px;
+		font-size: 14px;
+	}
+	.goods-box{
+		.goods-item{
+			margin-top: 20px;
+			display: flex;
+			flex-direction: row;
+			.left{
+				width: 60px;
+				height: 60px;
+				image{
+					border-radius: 4px;
+					overflow: hidden;
+					width: 100%;
+					height: 100%;
+					background-color: #f1f1f1;
+				}
+			}
+			.right{
+				display: flex;
+				flex-direction: column;
+				justify-content: space-between;
+				flex: 1;
+				padding-left: 14px;
+				.row1{
+					display: flex;
+					flex-direction: row;
+					justify-content: space-between;
+					.tit{
+						font-size: 14px;
+						color: #333333;
+						font-weight: bold;
+						flex: 1;
+						flex-wrap: wrap;
+						.zk{
+							padding: 1px 3px;
+							font-size: 10px;
+							margin-right: 8px;
+							border-radius: 4px;
+							background-color: #F9221D;
+							color: #ffffff;
+						}
+					}
+					.old-price{
+						padding-left: 12px;
+						font-size: 14px;
+						color: #888888;
+						font-weight: bold;
+						.lt{
+							 text-decoration: line-through;
+						}
+						.fh{
+							font-size: 10px;
+						}
+					}
+					.price{
+						font-size: 16px;
+						padding-left: 12px;
+						color: #333333;
+						font-weight: bold;
+						.fh{
+							font-size: 10px;
+						}
+					}
+				}
+				.row2{
+					
+				}
+				.row3{
+					font-size: 10px;
+					color: #888888;
+				}
+			}
+		}
+		.goods-item:first-child{
+			margin: 0;
+		}
+	}
+	.peisong{
+		.right{
+			font-size: 14px;
+			font-weight: bold;
+		}
+		.left{
+			font-size: 16px;
+			font-weight: bold;
+			.fh{
+				font-size: 10px;
+			}
+		}
+	}
+	.zhekou-box{
+		.zhekou{
+			display: flex;
+			flex-direction: column;
+			margin-top: 12px;
+			.row1{
+				align-items: center;
+				.left{
+					display: flex;
+					flex-direction: row;
+					align-items: center;
+					height: 20px;
+					line-height: 20px;
+					i{
+						font-size: 16px;
+						color: #ff5722;
+					}
+					.tit{
+						font-weight: bold;
+						margin-left: 6px;
+						font-size: 14px;
+						color: #333;
+					}
+				}
+				.right{
+					.tag1{
+						font-weight: bold;
+						font-size: 14px;
+						color: #ff5722;
+					}
+				}
+			}
+			.row2{
+				
+				height: 20px;
+				line-height: 20px;
+				font-size: 12px;
+				color: #888;
+			}
+			
+		}
+		.zhekou:first-child{
+			margin: 0;
+		}
+	}
+	
+	.totalbox{
+		align-items: flex-end;
+		.left{
+			display: flex;
+			flex-direction: row;
+			align-items: center;
+			font-size: 14px;
+			color: #888;
+			[class*="hxicon-"]{
+				color: #aaa;
+				margin-left: 4px;
+				font-size: 16px;
+			}
+		}
+		.right{
+			display: flex;
+			flex-direction: row;
+			align-items: flex-end;
+			.yh{
+				color: #ff5722;
+				.txt{
+					
+					color: #000;
+					font-size: 15px;
+				}
+				.fh{
+					font-weight: bold;
+					margin-left: 3px;
+					font-size: 13px;
+				}
+				.num{
+					font-weight: bold;
+					font-size: 18px;
+				}
+			}
+			.total{
+				margin-left: 16px;
+				color: #333;
+				.txt{
+					font-size: 15px;
+				}
+				.fh{
+					margin-left: 3px;
+					font-size: 12px;
+					font-weight: bold;
+				}
+				.num{
+					font-weight: 900;
+					font-size: 22px;
+				}
+			}
+		}
+	}
+}
+
+.privacy{
+	display: flex;
+	flex-direction: column;
+	
+	.row1{
+		align-items: flex-end;
+		.left{
+			display: flex;
+			flex-direction: row;
+			align-items: center;
+			.icon1{
+				color: #444;
+				font-size: 24px;
+			}
+			.icon2{
+				color: #aaa;
+				margin-left: 6px;
+				font-size: 16px;
+			}
+			.txt{
+				color: #333;
+				margin-left: 6px;
+				font-weight: bold;
+				font-size: 14px;
+			}
+		}
+		.right{
+			
+		}
+	}
+	.row2{
+		margin-top: 4px;
+		color: #888;
+		font-size: 12px;
+	}
+	.row3{
+		margin-top: 8px;
+		font-size: 12px;
+		color: #ff9800;
+	}
+}
+.other-box{
+	display: flex;
+	flex-direction: column;
+	.row{
+		align-items: center;
+		.left{
+			font-size: 14px;
+			color: #333;
+			font-weight: bold;
+			flex: 1;
+		}
+		.right{
+			display: flex;
+			flex-direction: column;
+			justify-content: flex-end;
+			align-items: center;
+			flex-wrap: wrap;
+			width: 60%;
+			font-size: 14px;
+			display: flex;
+			flex-direction: row;
+			color: #aaa;
+			[class*="hxicon-"]{
+				position: relative;
+				top: 2px;
+				font-size: 14px;
+			}
+		}
+	}
+}
+.body-end{
+	height: 100px;
+}
+.foot{
+	z-index: 11;
+	position: fixed;
+	display: flex;
+	flex-direction: row;
+	border-radius: 50px;
+	overflow: hidden;
+	bottom: 12px;
+	left: 12px;
+	right: 12px;
+	height: 50px;
+	
+	.left{
+		padding: 0 12px;
+		display: flex;
+		flex-direction: column;
+		justify-content: center;
+		background-color: #222222;
+		flex: 1;
+		
+		.price{
+			display: flex;
+			flex-direction: row;
+			align-items: baseline;
+			color: #fff;
+			height: 25px;
+			line-height: 25px;
+			.fh{
+				font-weight: bold;
+				font-size: 12px;
+			}
+			.txt{
+				
+				font-size: 22px;
+				font-weight: bold;
+			}
+		}
+		.discount{
+			margin-left: 2px;
+			font-size: 10px;
+			color: #bbb;
+		}
+	}
+	.center{
+		display: flex;
+		align-items: center;
+		background-color: #444;
+		color: #FFC107;
+		font-weight: bold;
+		font-size: 16px;
+		padding-left: 15px;
+		padding-right: 15px;
+		transition: all 0.3s;
+	}
+	.center:active{
+		background-color: #666;
+	}
+	.right{
+		display: flex;
+		align-items: center;
+		color: #222;
+		font-weight: bold;
+		font-size: 16px;
+		padding-left: 15px;
+		padding-right: 15px;
+		transition: all 0.3s;
+		background: linear-gradient(45deg, #FFEB3B, #FFC107);
+	}
+	.right:active{
+		background: linear-gradient(45deg, #e0ce31, #e4ad06);
+	}
+}
+</style>

+ 2413 - 0
HX-SHOP/pages/product/product.vue

@@ -0,0 +1,2413 @@
+<template>
+	<view class="container" id="productPage">
+		
+		<hx-navbar
+		    :fixed="true"
+		    :color="['#ffffff','#888888']"
+		    barPlaceholder="hidden"
+		    transparent="auto"
+			:back="false" 
+			:rightSlot="false"
+		    :background-color="[255,255,255]"
+			:pageScroll.sync="pageScroll">
+			<block slot="left">
+				<view class="ring" style="margin-left: 6px;font-weight: bold;" :style="showRing ? '' : 'background-color:#ffffff'" @click="backPage">
+					<i class="hxicon-unfold"></i>
+				</view>
+				 
+			</block>
+			<view class="ctn">
+				<view class="tabs-box" style="background: none; width: auto;" :style="!showRing ? '' : 'display:none;'">
+					<view class="" style="width: 210px;height: 100%;">
+						<view class="hx-tabs">
+							<view class="hx-tabs-item" v-for="(item,i) in tabs" :key="i" :class="{'hx-tabs-active': swiperCurrent == i}" @click="swiperChange(i,item.id)" >
+								<text>{{item.name}}</text>
+							</view>
+							<view class="hx-tabs-slider-box" :style="{left:swiperCurrentSliderLeft + 'px'}">
+								<view class="hx-tabs-slider"></view>
+							</view>
+						</view>
+					</view>
+				</view>
+				
+				<view class="leftBox">
+					<view class="ring" :style="showRing ? '' : 'background-color:#ffffff'">
+						<i class="hxicon-cart_fill_light"></i>
+					</view>
+					<view class="ring" :style="showRing ? '' : 'background-color:#ffffff'" @click="share">
+						<i class="hxicon-more"></i>
+					</view>
+					
+				</view>
+				<view class="jrNull"></view>
+			</view>
+		</hx-navbar>
+		
+		<!-- 滑动图片 -->
+		<view class="carousel">
+			<swiper indicator-dots circular=true duration="400">
+				<swiper-item class="swiper-item" v-for="(item,index) in goodsInfoData.banner_img" :key="index" @click="previewImg(item,goodsInfoData.banner_img)">
+					<view class="image-wrapper">
+						<image
+							:src="item" 
+							class="loaded" 
+							mode="aspectFill"
+						></image>
+					</view>
+				</swiper-item>
+			</swiper>
+		</view>
+		<!-- 只需要绑定购物车位置即可 -->
+		<flyInCart ref="inCart" :cartBasketRect="cartBasketRect"></flyInCart>
+		<view class="container-box introduce-section" >
+			<text class="title">{{ goodsInfoData.name }}</text>
+			<view class="tag-box">
+				<block v-for="(item,i) in goodsInfoData.goods_tag" :key="i">
+					<text class="tag-item" >{{item}}</text>
+				</block>
+				
+				<!-- <text class="tag-item">香辣</text>
+				<text class="tag-item">好吃</text> -->
+			</view>
+			<view class="bot-row">
+				<text>月售{{ goodsInfoData.monthly_sales ? goodsInfoData.monthly_sales : 0 }}</text>
+				<!-- <text>库存: 4690</text>
+				<text>浏览量: 768</text> -->
+			</view>
+			
+		</view>
+		<view class="container-box shopping-cart" :class="{'barBorder':showBorder}">
+			<view class="price-box" >
+				<text class="price-tip">¥</text>
+				<text class="price">{{ goodsInfoData.price }}</text>
+				<block v-if="goodsInfoData.oldprice != 0 && goodsInfoData.oldprice > goodsInfoData.price">
+					<text class="m-price" >¥{{ goodsInfoData.oldprice }}</text>
+					<text class="coupon-tip" >{{(goodsInfoData.price/goodsInfoData.oldprice * 10).toFixed(1)}}折</text>
+				</block>
+			</view>
+			
+			<block v-if="goodsInfoData.form">
+				<view class="add-btn" @click="showForm(goodsInfoData)">
+					<i class="hxicon-add" id="eleAdd"></i>
+					<text>选规格</text>
+					
+					<!-- #ifdef APP-PLUS || H5 -->
+						<view class="num"  v-if="getCartGoodsNum(currentGoodsData)">{{getCartGoodsNum(currentGoodsData)}}</view>
+					<!-- #endif -->
+					
+				</view>
+			</block>
+			<block v-else>
+				
+				<block v-if="!currentGoodsData.number">
+					<view class="add-btn" @click="formFirstAddGoods()">
+						<i class="hxicon-add" id="eleAdd"></i>
+						<text>加入购物车</text>
+					</view>
+				</block>
+				<block v-else>
+					<view class="btn-box">
+						<view id="eleAdd" class="addEle_gg jumpPosition"></view>
+						<hx-number-box @change="formAddGoodsChange" :value="currentGoodsData.number" :rowData="currentGoodsData" :clickTime="animaTime" @addChange="touchOnAddGoods('#eleAdd',currentGoodsData)"></hx-number-box>
+					</view>
+				</block>
+			</block>
+		</view>
+		<view class="line-weight"></view>
+		
+		<!--  分享 -->
+		<view class="share-section" @click="share">
+			<view class="share-icon">
+				<text class="hxicon-favor_fill_light"></text>返
+			</view>
+			<text class="tit">该商品分享可领49减10红包</text>
+			<text class="hxicon-mark"></text>
+			<view class="share-btn">
+				立即分享
+				<text class="hxicon-right"></text>
+			</view>
+		</view> 
+		<!-- <view class="c-list">
+			<view class="c-row b-b" @click="toggleSpec">
+				<text class="tit">购买类型</text>
+				<view class="con">
+					<text class="selected-text" v-for="(sItem, sIndex) in specSelected" :key="sIndex">
+						{{sItem.name}}
+					</text>
+				</view>
+				<text class="hxicon-right"></text>
+			</view>
+			
+		</view>
+		<view class="line-weight"></view> -->
+		
+		<!-- 详情 -->
+		<view class="container-box">
+			<view class="tabs-box" >
+				<view class="" style="width: 210px;height: 100%;">
+						
+					<view class="hx-tabs">
+						<view class="hx-tabs-item" v-for="(item,i) in tabs" :key="i" :class="{'hx-tabs-active': swiperCurrent == i}" @click="swiperChange(i,item.id)" >
+							<text>{{item.name}}</text>
+						</view>
+						<view class="hx-tabs-slider-box" :style="{left:swiperCurrentSliderLeft + 'px'}">
+							<view class="hx-tabs-slider"></view>
+						</view>
+					</view>
+				</view>
+			</view>
+			<view class="info-box" id="detail">
+				<view class="info-item" v-for="(item,i) in goodsInfoData.detail" :key="i">
+					<text class="left">{{item.tit}}:</text>
+					<text class="right">{{item.txt}}</text>
+				</view>
+			</view>
+			
+		</view>
+		<view class="line-weight"></view>
+		
+		<!-- 评价 -->
+		<view class="container-box eva-section" id="eva">
+			<view class="e-header">
+				<text class="tit">评价</text>
+				<text class="hpd" v-if="goodsEvaData.praise/goodsEvaData.sum * 100 > 0">({{Math.round(goodsEvaData.praise/goodsEvaData.sum * 100)}}%好评度)</text>
+				<text class="tip">{{goodsEvaData.sum ? goodsEvaData.sum : 0}}条评论</text>
+				<text class="hxicon-right"></text>
+			</view> 
+			<view class="eva-tag-box" v-if="goodsEvaData.eva_tag">
+				<!-- 标签自定义 ;“有图 ,赞,踩” 三种标签一般评价都有-->
+				<view class="tag-item" v-if="goodsEvaData.eva_tag.exist_pic > 0">有图 <text class="num">{{goodsEvaData.eva_tag.exist_pic}}</text></view>
+				<view class="tag-item" v-if="goodsEvaData.eva_tag.appreciate > 0"><i class="hxicon-appreciate_fill_light"></i> <text class="num">{{goodsEvaData.eva_tag.appreciate}}</text></view>
+				<view class="tag-item tread-bg" v-if="goodsEvaData.eva_tag.oppose > 0"><i class="hxicon-oppose_fill_light tread"></i> <text class="num">{{goodsEvaData.eva_tag.oppose}}</text></view>
+				<view class="tag-item" v-for="(item,i) in goodsEvaData.eva_tag.other" :key="i">{{item}}</view>
+				
+			</view>
+			<!-- 最好不要超过两条评价 -->
+			<view class="eva-box" v-for="(item, i) in goodsEvaData.eva_list" :key="i">
+				<image class="portrait" :src="item.avatar" mode="aspectFill"></image>
+				<view class="right">
+					<view class="bot">
+						<text class="attr">{{item.name}}</text>
+						<text class="time">{{item.time}}</text>
+					</view>
+					<view class="praise-box" v-if="item.point == 1">
+						<i class="hxicon-appreciate_fill_light" ></i>
+						<text class="praise-txt">攒了该商品</text>
+					</view>
+					<view class="praise-box" v-else-if="item.point == 2">
+						<i class="hxicon-oppose_fill_light " :class="{tread:true}"></i>
+						<text class="praise-txt">踩了该商品</text>
+					</view>
+					<text class="con">{{item.content}}</text>
+					<view class="imgs" v-if="item.pic">
+						<block v-for="(imgurl, index) in item.pic" :key="index">
+							<view class="imgs-box"><image :src="imgurl" mode="widthFix" style="width: 100%;" @click="previewImg(imgurl,item.pic)"></image></view>
+						</block>
+					</view>
+				</view>
+				
+			</view>
+			
+			
+			<view class="eva-btn">
+				<view class="avatar-box">
+					<view class="avatar-item" v-for="(item, i) in goodsEvaData.eva_list" :key="i">
+						<image :src="item.avatar" mode=""></image>
+					</view>
+					
+					<view class="avatar-item">
+						<i class="hxicon-more"></i>
+					</view>
+				</view>
+				<text>{{goodsEvaData.sum}}条评价</text>
+				<i class="hxicon-right"></i>
+			</view>
+		</view>
+		<view class="line-weight"></view>
+		<view class="detail-desc" id="coll">
+			<view class="d-header">
+				<text>图文详情</text>
+			</view>
+			<rich-text :nodes="goodsInfoData.desc"></rich-text>
+		</view>
+		
+		<!-- 底部操作菜单 -->
+		<!-- <view class="page-bottom">
+			<navigator url="/pages/index/index" open-type="switchTab" class="p-b-btn">
+				<text class="hxicon-home_fill_light"></text>
+				<text>首页</text>
+			</navigator>
+			<navigator url="/pages/cart/cart" open-type="switchTab" class="p-b-btn">
+				<text class="hxicon-cartfill"></text>
+				<text>购物车</text>
+			</navigator>
+			<view class="p-b-btn" :class="{active: favorite}" @click="toFavorite">
+				<text class="hxicon-likefill"></text>
+				<text>收藏</text>
+			</view>
+			
+			<view class="action-btn-group">
+				<button type="primary" class=" action-btn no-border buy-now-btn" @click="buy">立即购买</button>
+				<button type="primary" class=" action-btn no-border add-cart-btn">加入购物车</button>
+			</view>
+		</view> -->
+		
+		<!-- 购物车 -->
+		<view class="foot"  @touchmove.stop.prevent="mpClear" :style="{height: footHeight}" v-if="showFoot">
+			<view class="zz" @click="hideShoppingCar"></view>
+			<view class="btn-box">
+				<view class="btn-box-left" @click="contact">
+					<view class="imgBox">
+						<image src="../../static/store/contact.png" mode=""></image>
+					</view>
+					<text>联系商家</text>
+				</view>
+				<view class="btn-box-line"></view>
+				<view class="btn-box-center" @click="showShoppingCar">
+					<view class="cart" :animation="cartAnimationData">
+						<view class="tag cartNum" v-if="goodsTotalNumber>0">{{goodsTotalNumber}}</view>
+						<image :src="goodsTotalNumber ? '/static/store/cart.png' : '/static/store/cart2.png'" mode=""></image>
+					</view>
+					<view class="priceBox">
+						<view class="hx-txt-18 hx-color-white" v-if="goodsTotalPrice>0">
+							¥{{goodsTotalPrice}}
+						</view>
+						<view class="hx-txt-10 hx-color-gray">
+							另需配送费¥{{shippingDees}}
+						</view>
+					</view>
+				</view>
+				<view class="btn-box-right">
+					<view class="jiesuan"  v-if="goodsTotalPrice>0 && goodsTotalPrice >= startingPrice" @click="jiesuan">
+						去结算
+					</view>
+					<view class="pscj hx-txt-10 hx-color-gray" v-else>
+						<text v-if="startingPrice>0">差¥{{-(goodsTotalPrice-startingPrice)}}起送</text>
+					</view>
+					
+				</view>
+			</view>
+			<view class="cart-box" :style="{display: showCar ? 'flex' : 'none'}">
+				<view class="box-container rebate-box" v-if="showDiscount">
+					<text>已享100减25</text>
+				</view>
+				<view class="box-container operating-box">
+					<view class="operating-box_right">
+						
+					</view>
+					<view class="operating-box_left clear" @click="clearShoppingCart">
+						<i class="hxicon-delete"></i>
+						<text>清空购物车</text>
+					</view>
+				</view>
+				<view class=" goods-box">
+					<view class="" style="flex: 1;">
+						<scroll-view scroll-y="true" class="goods-list-scroll" :scroll-top="carGoodsScrollTop">
+							<view class="goods-list">
+								<view class="box" v-for="rowData in shoppCart" :key="rowData.id" v-if="rowData.number>0">
+									
+									<view class="m-store-item">
+										<view class="m-img">
+											<image style="width: 100%;height: 100%;" :src="rowData.img" mode="aspectFit"></image>
+										</view>
+										<view class="m-text">
+											<view class="m-title">
+												{{rowData.name}}
+											</view>
+											<view class="m-descripe">
+												
+												{{rowData.current_form ? rowData.form.name + ":" + rowData.current_form.name : rowData.descripe}}
+												
+											</view>
+											<view class="m-price-box" >
+												<view class="symbol">¥</view>
+												<view class="m-price">{{rowData.price}}</view>
+												<view class="m-old-price" v-if="rowData.oldprice">
+													<text>¥{{rowData.oldprice}}</text>
+												</view>
+											</view>
+											<view class="m-distance" > 
+											<view :class="'addEle2_' + rowData.id" class="jumpPosition">
+											</view>
+												<hx-number-box @change="addGoodsChange" :value="rowData.number" :rowData="rowData" :clickTime="400" @addChange="touchOnAddGoods('.addEle2_' + rowData.id,rowData)"></hx-number-box>
+												
+											</view>
+										</view>
+										
+									</view>
+								</view>
+							</view>
+						</scroll-view>
+					</view>
+					
+				</view>
+			</view>
+			
+		</view>
+		
+
+		<!-- 多规格 -->
+		<uni-popup ref="popup" type="center" @change="popupChange">
+			<view class="form-main" v-if="currentGoodsData.name">
+				<view class="form-main_ctn" @click.stop.prevent="mpClear" >
+					<view class="godos_tit"><text>{{currentGoodsData.name}}</text></view>
+					
+					<view class="gg_tit">
+						<text>{{currentGoodsData.form.name}}</text>
+					</view>
+					<view class="gg_box">
+						<block v-for="(form_child,j) in currentGoodsData.form_child" :key="j" v-if="form_child.pid == currentGoodsData.form.id">
+							<view class="item" :class="{'active': form_child.select}" @click="selectGoodsForm(currentGoodsData,form_child)">{{form_child.name}}</view>
+						</block>
+					</view>
+					
+					<view class="select_gg">
+						<text class="lable">已选规格:</text>
+						<view class="select_gg_box">
+							<block v-for="(form_child,j) in currentGoodsData.form_child" :key="j" v-if="form_child.select == true">
+								<view class="gg-item">
+									<text>{{form_child.name}} </text>
+									<text class="gg-item-cut">,</text>
+								</view>
+							</block>
+						</view>
+					</view>
+					
+					<view class="bottom">
+						<view class="price_box">
+							<text>¥</text>
+							<block v-for="(form_child,j) in currentGoodsData.form_child" :key="j" v-if="form_child.select == true">
+								<text class="price">{{form_child.price}}</text>
+							</block>
+						</view>
+						<view class="form-btn-box">
+							<block v-if="!currentGoodsData.number">
+								<view id="ggAddBtn" class="add-btn" @click="formFirstAddGoods()">
+									<i class="hxicon-add" id="eleAdd"></i>
+									<text>加入购物车</text>
+								</view>
+							</block>
+							<block v-else>
+								<view class="addEle_gg jumpPosition"></view>
+								<hx-number-box @change="formAddGoodsChange" :value="currentGoodsData.number" :rowData="currentGoodsData" :clickTime="animaTime + 200" @addChange="touchOnAddGoods('.addEle_gg',currentGoodsData)"></hx-number-box>
+							</block>
+						</view>
+						
+					</view>
+				</view>
+				<view class="close" @click="hiddenForm()">
+					<i class="hxicon-close"></i> 
+				</view>
+			</view>
+			
+		</uni-popup>
+		<!-- 分享 -->
+		<share 
+			ref="share" 
+			:contentHeight="580"
+			:shareList="shareList"
+		></share>
+		
+	</view>
+</template>
+
+<script>
+	import share from '@/components/hx-share/hx-share';
+	import hxNavbar from '@/components/hx-navbar/hx-navbar.vue';
+	import jumpBall from '@/components/hx-jump-ball/hx-jump-ball.vue';
+	import hxNumberBox from "@/components/uni-number-box/uni-number-box.vue";
+	//  加入购物车动画组件
+	import flyInCart from '@/components/flyInCart.vue'
+	//引入测试数据
+	import testData from "@/common/testdata.js";
+	
+	var statusBarHeight = uni.getSystemInfoSync().statusBarHeight;
+	export default{
+		components: {
+			share,
+			hxNumberBox,
+			flyInCart,
+			hxNavbar
+		},
+		data() {
+			return {
+				pageScroll: {},
+				
+				specClass: 'none',
+				specSelected:[],
+				
+				//tabs
+				tabs: [
+					{name:'详情',id: 'detail'},
+					{name:'评价',id: 'eva'},
+					{name:'图文',id: 'coll'},
+				],
+				swiperCurrent: 0,
+				swiperCurrentSliderLeft: 0,
+				showRing: true,
+				showTabs: true,
+				showBorder: false,
+				
+				favorite: true,
+				
+				//小球动画
+				num:1,
+				element: [],
+				animaTime: 300,
+				cartAnimation: {},
+				cartAnimationData: {},
+				
+				//购物车
+				shoppingCartAll:[],
+				//商家信息
+				storeData: [],
+				//显示购物车
+				showFoot:true,
+				//配送费
+				shippingDees: 0,
+				//配送起步价
+				startingPrice:10,
+				//购物车商品价格合计
+				goodsTotalPrice: 0,
+				//购物车商品数量合计
+				goodsTotalNumber: 0,
+				//购物车
+				shoppCart: [],
+				//foot 高度
+				footHeight: '0',
+				//显示购物车
+				showCar: false,
+				//购物车中商品滚动条位置
+				carGoodsScrollTop: 0,
+				//购物车缓存 Storage 名称
+				shoppingCartStorageName: 'shopping_cart',
+				//购物车显示折扣
+				showDiscount:true,
+				
+				//商品信息
+				goodsInfoData: {},
+				//商品评价
+				goodsEvaData: {},
+				
+				
+			
+				//多规格当前产品
+				currentGoodsData: {},
+				//显示规格容器
+				showFormBox: false,
+				//显示规格动画
+				formAnimationData:{},
+			
+				isBack: true,
+				//购物车位置数据
+				cartBasketRect:{},
+				
+				//分享
+				shareList: [{
+					type: 1,
+					icon: '/static/shop/share_wechat.png',
+					text: '微信好友'
+				},
+				{
+					type: 2,
+					icon: '/static/shop/share_moment.png',
+					text: '朋友圈'
+				},
+				{
+					type: 3,
+					icon: '/static/shop/share_qq.png',
+					text: 'QQ好友'
+				},
+				{
+					type: 4,
+					icon: '/static/shop/share_qqzone.png',
+					text: 'QQ空间'
+				}],
+				
+			
+			};
+		},
+		async onLoad(options){
+			let that = this;
+			//接收传值,id里面放的是商品id
+			let id = options.id;
+			if(id){
+			
+			}
+			
+			//模拟请求数据
+			uni.showLoading({
+			    title: '加载中'
+			});
+			setTimeout(()=>{
+				//商家信息
+				that.storeData = testData.storeData
+				//商品信息
+				that.goodsInfoData = testData.goodsInfo
+				that.currentGoodsData = testData.goodsInfo
+				let cartGoods = that.getStoreCart()
+				//普通商品直接可以显示数量
+				if(!that.currentGoodsData.form){
+					for(let i in cartGoods){
+						if(cartGoods[i].id == that.currentGoodsData.id){
+							that.currentGoodsData.number = cartGoods[i].number
+							break
+						}
+					}
+				}
+				//商品评价
+				that.goodsEvaData = testData.goodsEva
+				setTimeout(()=>{
+					
+					uni.hideLoading();
+				},500)
+			},1000)
+			
+			
+			this.cartAnimation = uni.createAnimation({
+				duration: 800,
+				timingFunction: "ease",
+				delay: 0
+			}); 
+			
+		
+		},
+		onReady() {
+			const that = this
+			
+			let q = uni.createSelectorQuery()
+			setTimeout(function(){
+				q.select('.cart').boundingClientRect(data => {
+				 that.cartBasketRect = data
+				}).exec();
+			},100)
+		},
+		onShow() {
+			this.init();
+		},
+		//监听返回
+		onBackPress(event) {
+			
+			if(!this.isBack){
+				this.$refs.popup.close()
+				return true
+			}
+		},
+		//导航栏滑动时的操作
+		onPageScroll(e) {
+			let top = e.scrollTop
+			let that = this
+			that.pageScroll =e
+			let view = uni.createSelectorQuery().select(".shopping-cart");
+			view.fields({
+				rect: true
+			}, data => {
+				if(data.top - statusBarHeight<= 44){
+					that.showBorder = true;
+				}else{
+					that.showBorder = false;
+				}
+			}).exec();
+			if(top < 120){
+				that.showRing = true;
+			}else{
+				that.showRing = false;
+				this.navSearchBgOpacity = 1
+				this.navSearchColor = '#888888'
+			}
+		},
+		methods:{
+			init(){
+				let that = this;
+				let carts = uni.getStorageSync(that.shoppingCartStorageName) || [];
+				//根据缓存数据 获取购物车中属于本商店的商品
+				for(let i in carts){
+					if(carts[i].store_idd == that.storeDatastore_idid){
+						that.shoppCart = carts[i].shopping_cart;
+						break;
+					}
+				}
+				that.goodsTotalPrice = 0;
+				that.goodsTotalNumber = 0;
+				for(let i in that.shoppCart){
+					//计算商品总价
+					that.goodsTotalPrice += that.shoppCart[i].total
+					//商品总数量
+					that.goodsTotalNumber += that.shoppCart[i].number
+				}
+				//初始化起步价和配送费
+				that.starting_price = that.storeData.starting_price;
+				that.shipping_dees = that.storeData.shipping_dees;
+				
+				that.setLabelNumber();
+			},
+			
+			popupChange(e){
+				this.isBack = !e.show
+			},
+			//返回
+			backPage(){
+				var pages = getCurrentPages().length;
+				console.log(pages);
+				if(pages == 1){
+					// uni.switchTab({
+					//     url: '/pages/index/index'
+					// });
+					uni.redirectTo({
+					   url: '/pages/index/index'
+					});
+				}else{
+					uni.navigateBack({
+						animationType:"zoom-in"
+					});
+				}
+			},
+			//tab 事件
+			swiperChange(index,idName) {
+				this.swiperCurrent = index;
+				this.swiperCurrentSliderLeft= 70 * index;
+				
+				//滚动至指定位置
+				//最终位置 = 目标节点坐标 - 目标节点坐标 - 状态栏高度 - 导航栏高度44 - 价格栏高度
+				let view = uni.createSelectorQuery().select("#productPage");
+				view.boundingClientRect(data => {
+					let view2 = uni.createSelectorQuery().select("#" + idName);
+					view2.boundingClientRect(data2 => {
+						let view3 = uni.createSelectorQuery().select(".shopping-cart");
+						view3.fields({
+							size: true
+						}, res => {
+							uni.pageScrollTo({
+								duration:300,
+								scrollTop:data2.top - data.top - statusBarHeight - 44 - res.height
+							})
+							
+						}).exec();
+						
+						
+					}).exec();
+					
+				}).exec();
+			},
+		
+			mpClear(e) {
+				// TODO nvue 取消冒泡
+				e.stopPropagation()
+			},
+			//显示购物车
+			showShoppingCar(){
+				if(this.goodsTotalNumber == 0){
+					return;
+				}
+				this.footHeight = '100%';
+				this.showCar = true;
+				this.carGoodsScrollTop = 0;
+			},
+			//隐藏购物车
+			hideShoppingCar(){
+				this.footHeight = '0';
+				this.showCar = false;
+			},
+			//清空该门店的购物车
+			clearShoppingCart(){
+				let that = this;
+				that.shoppCart = [];
+				that.storeData.shopping_cart = [];
+				for(let i in that.shoppingCartAll){
+					if(that.shoppingCartAll[i].store_idd == that.storeDatastore_idid){
+						that.shoppingCartAll[i] = that.storeData
+					}
+				}
+				uni.setStorageSync(that.shoppingCartStorageName,that.shoppingCartAll);
+				
+				for(let i in that.goodsList){
+					that.goodsList[i].number = 0;
+				}
+				for(let i in that.categoryList){
+					that.categoryList[i].number = 0;
+				}
+				//购物车商品价格合计
+				that.goodsTotalPrice = 0;
+				//购物车商品数量合计
+				that.goodsTotalNumber = 0;
+				that.hideShoppingCar();
+			},
+			//增加商品后的回调事件
+			touchOnAddGoods(ele,data){
+				
+				// this.element = [ele,'.cart'];
+				// this.num ++; 
+				const that = this;
+				let q = uni.createSelectorQuery()
+				q.select(ele).boundingClientRect(res => {
+					console.log(res);
+					that.$refs.inCart.addToCart(res,data.id);
+				}).exec();
+			},
+			
+			//新增商品
+			storeAddGoods(number,rowData){
+				var that = this;
+				let shoppCart = [];
+				let totalPrice = 0;
+				let totalNumber = 0;
+				let existedGoods = false;
+				number = Number(number)
+				
+				let carts = uni.getStorageSync(that.shoppingCartStorageName) || [];
+				
+				//根据缓存数据 获取购物车中属于本商店的商品
+				for(let i in carts){
+					if(carts[i].store_id == that.storeData.store_id){
+						shoppCart = carts[i].shopping_cart;
+						break;
+					}
+				}
+				
+				//是否为有规格的商品
+				let isFormGoods = false
+				if(rowData.current_form){
+					isFormGoods = true
+				}
+				let deleteGoods = null
+				//检查该商品是否为第一次添加,
+				for(var i in shoppCart){
+					if(shoppCart[i].id == rowData.id){
+						if(isFormGoods){
+							//相同商品比较规格是否也相同
+							if(shoppCart[i].current_form.id == rowData.current_form.id){
+								existedGoods = true;
+							}
+						}else{
+							existedGoods = true;
+						}
+						if(existedGoods){
+							//在购物车中移除该商品
+							if(number <= 0){
+								deleteGoods = shoppCart[i];
+								break;
+							}
+							if(isFormGoods){
+								shoppCart[i].price = rowData.current_form.price
+								shoppCart[i].oldprice = rowData.current_form.oldprice
+								shoppCart[i].total = number *  rowData.current_form.price
+							}else{
+								shoppCart[i].price = rowData.price
+								shoppCart[i].total = number *  rowData.price
+								shoppCart[i].oldprice = rowData.oldprice
+							}
+							//非第一次添加,直接修改商品数量,并计算出单品合计
+							
+							shoppCart[i].number = rowData.number = number
+							break;
+						}
+					}
+				}
+				//在购物车中移除该商品
+				if(deleteGoods != null){
+					
+					if(!carts){
+						return [];
+					}
+					//根据缓存数据 获取购物车中属于本商店的商品
+					for(let i in carts){
+						if(carts[i].store_id == that.storeData.store_id){
+							var index = shoppCart.indexOf(deleteGoods);
+						
+							if (index > -1) { 
+								shoppCart.splice(index, 1); 
+							} 
+							carts[i].shopping_cart = shoppCart
+							
+							//计算总商品数量和总价
+							for(var j in shoppCart){
+								//总价
+								totalPrice += shoppCart[j].total
+								totalNumber += shoppCart[j].number
+							}
+							//更改商品列表中的已购买数量
+							for(let j in that.goodsList){
+								if(that.goodsList[j].id == rowData.id){
+									that.goodsList[j] = rowData
+									break;
+								}
+							}
+							break;
+						}
+					}
+					
+				}else{
+					//第一次添加
+					if(!existedGoods){
+						if(rowData.form){
+							rowData.price = rowData.current_form.price
+							rowData.oldprice = rowData.current_form.oldprice
+							rowData.total = number *  rowData.current_form.price
+						}else{
+							rowData.total = number *  rowData.price
+						}
+						rowData.number = number;
+						shoppCart.push(rowData);
+					}
+					
+					//计算总商品数量和总价
+					for(var i in shoppCart){
+						//总价
+						totalPrice += shoppCart[i].total
+						totalNumber += shoppCart[i].number
+					}
+					
+					that.storeData.shopping_cart = shoppCart;
+					//门店第一次添加商品
+					let isFirstAddGoods = true;
+					for(let i in carts){
+						if(carts[i].store_id == that.storeData.store_id){
+							carts[i] = that.storeData
+							isFirstAddGoods = false
+						}
+					}
+					if(isFirstAddGoods === true){
+						carts.push(that.storeData)
+					}
+				}
+				that.shoppCart = shoppCart
+				that.shoppingCartAll = carts
+				that.currentGoodsData.number = number
+				//购物车商品数据缓存至本地
+				uni.setStorageSync(that.shoppingCartStorageName,carts);
+				return {
+					shoppCart: shoppCart,
+					totalPrice: totalPrice,
+					totalNumber: totalNumber
+				}
+			},
+			
+			//新增商品计算价格
+			addGoodsChange(number,dataArr){
+				number = Number(number)
+				var that = this;
+				let rowData = {
+					id: dataArr.id,
+					type_id: dataArr.type_id,
+					name: dataArr.name,
+					descripe: dataArr.descripe,
+					img: dataArr.img,
+					price: dataArr.price,
+					oldprice: dataArr.oldprice,
+					number: number
+				}
+				if(dataArr.form){
+					rowData.form = dataArr.form
+					rowData.form_child = dataArr.form_child
+					rowData.current_form =  dataArr.current_form
+				}
+				
+				let res = that.storeAddGoods(number,rowData)
+				console.log(res.totalPrice)
+				if(res.totalPrice){
+					that.goodsTotalPrice = res.totalPrice
+					that.goodsTotalNumber = res.totalNumber
+					if(that.goodsTotalNumber == 0){
+						that.hideShoppingCar();
+					}
+					
+				}
+				
+				return 
+				let shoppCart = this.shoppCart;
+				let totalPrice = 0;
+				let totalNumber = 0;
+				let existedGoods = false;
+				
+				
+				// //点击添加购物车时生效
+				// if(status){
+				// 	that.element = ['#eleAdd','.cart'];
+				// 	that.num ++; 
+				// }
+				//检查该商品是否为第一次添加,如果为第二次添加,则直接修改商品数量,并计算出合计
+				for(var i in shoppCart){
+					//非第一次添加
+					if(shoppCart[i].id == rowData.id){
+						//如果为加入购物车则为叠加
+						if(status){
+							number = shoppCart[i].number + number
+						}
+						shoppCart[i].number = rowData.number = number;
+						shoppCart[i].total = number * shoppCart[i].price
+						existedGoods = true;
+						break;
+					}
+				}
+				//第一次添加
+				if(!existedGoods){
+					rowData.number = number;
+					rowData.total = number * rowData.price
+					shoppCart.push(rowData);
+				}
+				
+				//计算总商品数量和总价
+				for(var i in shoppCart){
+					//总价
+					totalPrice += shoppCart[i].total
+					totalNumber += shoppCart[i].number
+					
+				}
+				//更改商品列表中的已购买数量
+				for(let i in that.goodsList){
+					if(that.goodsList[i].id == rowData.id){
+						that.goodsList[i] = rowData
+						break;
+					}
+				}
+				
+				that.shoppCart = shoppCart;
+				
+				that.goodsTotalPrice = totalPrice
+				that.goodsTotalNumber = totalNumber
+				
+				//门店第一次添加该商品
+				let isFirstAddGoods = true;
+				that.storeData.shopping_cart = that.shoppCart;
+				
+				for(let i in that.shoppingCartAll){
+					if(that.shoppingCartAll[i].store_id == that.storeData.store_id){
+						that.shoppingCartAll[i] = that.storeData
+						isFirstAddGoods = false
+					}
+				}
+				
+				that.setLabelNumber();
+				if(isFirstAddGoods === true){
+					that.shoppingCartAll.push(that.storeData)
+				}
+				if(that.goodsTotalNumber == 0){
+					that.hideShoppingCar();
+				}
+				
+				//购物车商品数据缓存至本地
+				uni.setStorageSync(that.shoppingCartStorageName,that.shoppingCartAll);
+			},
+			//计算每类商品购买的总数
+			setLabelNumber(){
+				let that = this;
+				//计算每一类购买商品的总数量
+				for(let j in that.categoryList){
+					let n = 0;
+					for(var i in that.shoppCart){
+						if(that.shoppCart[i].type_id ==  that.categoryList[j].id){
+							n += that.shoppCart[i].number;
+						}
+					}
+					that.categoryList[j].number = n;
+				}
+			},
+			
+			//去结算
+			jiesuan(){
+				this.navTo("/pages/order/preview?sid=" + this.storeData.store_id)
+			},
+			//联系商家
+			contact(){
+				uni.showModal({
+					title:"",
+					content:"联系商家"
+				})
+			},
+			
+			//预览图片
+			previewImg(img,imgList){
+				
+				// 预览图片
+				uni.previewImage({
+					current: img,
+					urls: imgList,
+					indicator: "default",
+					// longPressActions: {
+					// 	itemList: ['发送给朋友', '保存图片', '收藏'],
+					// 	success: function(data) {
+					// 		//console.log('选中了第' + (data.tapIndex + 1) + '个按钮,第' + (data.index + 1) + '张图片');
+					// 	},
+					// 	fail: function(err) {
+					// 		//console.log(err.errMsg);
+					// 	}
+					// }
+				});
+			},
+			
+			//-----------------------------------------------------------------------------------
+			//显示 规格
+			showForm(goods){
+				var that = this;
+				let goodsCart = that.getStoreCart();
+			
+				if(goodsCart){
+					let currentGoods = null
+					for(let i in goodsCart){
+						if(goodsCart[i].id == goods.id){
+							currentGoods = goodsCart[i]
+							break
+						}
+					}
+					if(currentGoods){
+						let selectStatus = false
+						for (let i in goods.form_child){
+							if(goods.form_child[i].id == currentGoods.current_form.id){
+								if(!selectStatus){
+									goods.form_child[i].select = true
+									goods.number = currentGoods.number
+									selectStatus = true
+								}else{
+									goods.form_child[i].select = false
+								}
+							}else{
+								goods.form_child[i].select = false
+							}
+						}
+					}
+					
+				}
+				that.currentGoodsData = goods
+				that.$refs.popup.open()
+			},
+			//隐藏规格
+			hiddenForm(){
+				this.$refs.popup.close();
+			},
+			formFirstAddGoods(){
+				let that = this
+				that.formAddGoodsChange(1,that.currentGoodsData)
+				that.touchOnAddGoods('#eleAdd',that.currentGoodsData)
+			},
+			//加入购物车
+			formAddGoodsChange(number,goodsData){
+				let that = this;
+				if(number == 1){
+					for(let i in goodsData.form_child){
+						if(goodsData.form_child[i].select == true ){
+							that.currentGoodsData.current_form = goodsData.form_child[i]
+							break
+						}
+					}
+				}
+				that.addGoodsChange(number,that.currentGoodsData)
+				
+				
+			},
+			//选择规格
+			selectGoodsForm(goods,formChild){
+				let that = this
+				let data = goods.form_child
+				let n = 0
+				for (var i in data){
+					if(data[i].id == formChild.id){
+						data[i].select = true
+					}else{
+						data[i].select = false
+					}
+				}
+				let goodsCart = that.getStoreCart();	
+				if(goodsCart){
+					for(let i in goodsCart){
+						if(goodsCart[i].id == goods.id && goodsCart[i].current_form.id == formChild.id){
+							n = goodsCart[i].number
+							break;
+						}
+					}
+				}
+				
+				goods.number = n
+				this.currentGoodsData = goods
+				
+			},
+			
+			//获取该商品在购物车的数量
+			getCartGoodsNum(goods){
+				let cart = this.getStoreCart()
+				let n = 0
+				if(cart){
+					for(let i in cart){
+						if(cart[i].id == goods.id){
+							n += cart[i].number
+						}
+					}
+				}
+				return n
+			},
+			//-----------------------------------------------------------------------------------
+			//获取门店购物车
+			getStoreCart(){
+				let that = this
+				let shoppCart = {}
+				let carts = uni.getStorageSync(that.shoppingCartStorageName) || [];
+				
+				if(carts){
+					//根据缓存数据 获取购物车中属于本商店的商品
+					for(let i in carts){
+						if(carts[i].store_id == that.storeData.store_id){
+							shoppCart = carts[i].shopping_cart;
+							break;
+						}
+					}
+				}else{
+					that.storeData.shopping_cart = []
+					uni.setStorageSync(that.shoppingCartStorageName,that.storeData);
+				}
+				return shoppCart
+			},
+			
+			
+			
+			//分享
+			share(){
+				this.$refs.share.toggleMask();	
+			},
+			//收藏
+			toFavorite(){
+				this.favorite = !this.favorite;
+			},
+			buy(){
+				uni.navigateTo({
+					url: `/pages/shop/order/createOrder`
+				})
+			},
+			stopPrevent(){}
+		},
+
+	}
+</script>
+
+<style lang='scss'>
+	//主题颜色
+	$hx-theme-color: #FFC107;
+	$hx-theme-color-light: #FFEB3B;
+	page{
+		background: #ffffff;
+		padding-bottom: 160upx;
+	}
+	/*边框*/
+	.b-b:after,
+	.b-t:after {
+		position: absolute;
+		z-index: 3;
+		left: 0;
+		right: 0;
+		height: 0;
+		content: '';
+		transform: scaleY(.5);
+		border-bottom: 1px solid #E4E7ED;
+	}
+	
+	.b-b:after {
+		bottom: 0;
+	}
+	
+	.b-t:after {
+		top: 0;
+	}
+	.hx-txt-10{
+		font-size: 10px;
+	}
+	.hx-txt-12{
+		font-size: 12px;
+	}
+	.hx-txt-14{
+		font-size: 14px;
+	}
+	.hx-txt-16{
+		font-size: 16px;
+	}
+	.hx-txt-18{
+		font-size: 18px;
+	}
+	.hx-txt-22{
+		font-size: 22px;
+	}
+	.hx-color-gray{
+		color: #bbbbbb;
+	}
+	.hx-color-white{
+		color: #FFFFFF;
+	}
+	.hx-color-black{
+		color: #333333;
+	}
+	.hx-txt-weigth{
+		font-weight: bold;
+	}
+	.hx-mb-10{
+		margin-bottom: 10px;
+	}
+	.hx-mt-15{
+		margin-top: 15px;
+	}
+	.hx-shadow{
+		box-shadow: 0px 6upx 16upx rgba(173, 173, 173, 0.2);
+	}
+	.ring{
+		background-color: rgba(0, 0, 0, 0.3);
+		width: 28px;
+		height: 28px;
+		border-radius: 100%;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		font-size: 16px;
+	}
+	.ctn{
+		
+		/* border: 1px solid #e3e3e3; */
+		width: 100%;
+		display: flex;
+		justify-content: flex-end;
+		overflow: hidden;
+		align-items: center;
+		.leftBox{
+			display: flex;
+			width: 60px;
+			justify-content: space-between;
+			flex: none;
+			margin: 0 8px;
+			align-items: center;
+		}
+		.jrNull{
+			/* #ifdef MP */
+			width: 95px;
+			flex: none;
+			/* #endif */
+		}
+	}
+	.barBorder{
+		box-shadow: 0 1px 6px #ccc;
+		border-top: 1px solid #f1f1f1;
+	}
+	.icon-right{
+		font-size: 16px;
+		color: #888;
+	}
+	.carousel {
+		height: 722upx;
+		position:relative;
+		swiper{
+			height: 100%;
+		}
+		.image-wrapper{
+			width: 100%;
+			height: 100%;
+		}
+		.swiper-item {
+			display: flex;
+			justify-content: center;
+			align-content: center;
+			height: 750upx;
+			overflow: hidden;
+			image {
+				width: 100%;
+				height: 100%;
+			}
+		}
+		
+	}
+	.line-weight{
+		background-color: #efefef;
+		height: 10px;
+	}
+	.container-box{
+		background: #fff;
+		padding: 10px 15px;
+	}
+	/* 标题简介 */
+	.introduce-section{
+		padding-bottom: 0;
+		.title{
+			font-size: 32upx;
+			color: #303133;
+			height: 50upx;
+			line-height: 50upx;
+			font-weight: bold;
+		}
+		.tag-box{
+			display: flex;
+			align-items:baseline;
+			margin: 6px 0 4px;
+			flex-wrap: wrap;
+			.tag-item{
+				align-items: center;
+				padding: 2px 5px;
+				background: #efefef;
+				margin-bottom: 8px;
+				font-size: 10px;
+				margin-right: 10px;
+				border-radius: 3px;
+				color: #555555;
+			}
+		}
+		.bot-row{
+			display:flex;
+			align-items:center;
+			height: 20px;
+			font-size: 12px;
+			color: #909399;
+			text{
+				flex: 1;
+			}
+		}
+	}
+	/* 价格 */
+	.shopping-cart{
+		
+		position: sticky;
+		top: calc(44px + var(--status-bar-height));
+		padding-top: 10px;
+		display: flex;
+		justify-content: space-between;
+		background: #ffffff;
+		
+		z-index: 10;
+		.price-box{
+			display:flex;
+			align-items:baseline;
+			font-size: 12px;
+			color:#ff582b;
+			flex: 1;
+			.price{
+				font-size: 20px;
+			}
+			.m-price{
+				margin:0 6px;
+				color: #909399;
+				text-decoration: line-through;
+				font-size: 12px;
+			}
+			.coupon-tip{
+				align-items: center;
+				padding: 4upx 10upx;
+				background: #FF5722;
+				font-size: 12px;
+				color: #fff;
+				border-radius: 3px;
+				line-height: 1;
+				transform: translateY(-4upx); 
+			}
+		}
+		.add-btn{
+			position: relative;
+			border-radius: 50px;
+			background-color: #ffce3c; 
+			padding: 3px 10px;
+			display: flex;
+			height: 30px;
+			align-items: center;
+			i{
+				font-weight: bold;
+				margin-left: -4px;
+				margin-right: 3px;
+			}
+			text{
+				
+				font-size: 14px;
+				font-weight: bold;
+				color: #363636;
+			}
+			.jumpPosition{
+				position: absolute;
+				right: 6px;
+				top: 11px;
+			}
+			.num{
+				position: absolute;
+				right: 0;
+				top: -10px;
+				width: 18px;
+				height: 18px;
+				line-height: 18px;
+				font-size: 10px;
+				color: #fff;
+				background-color: #ff5722;
+				text-align: center;
+				border-radius: 50%;
+				
+			}
+		}
+		.btn-box{
+			position: relative;
+			border-radius: 50px;
+			padding: 3px 10px;
+			display: flex;
+			height: 30px;
+			align-items: center;
+			.jumpPosition{
+				position: absolute;
+				right: 16px;
+				top: 11px;
+			}
+		}
+		
+	}
+	
+	/* 分享 */
+	.share-section{
+		display:flex;
+		align-items:center;
+		color: #606266;
+		background: linear-gradient(to right, #fff8c3, #ffcc33);
+		padding: 12upx 30upx;
+		.share-icon{
+			display:flex;
+			align-items: center;
+			width: 38px;
+			height: 16px;
+			line-height: 1;
+			border: 1px solid #FF9800;
+			border-radius: 2px;
+			position: relative;
+			overflow: hidden;
+			font-size: 12px;
+			color: #FF5722;
+			&:after{
+				content: '';
+				width: 50upx;
+				height: 50upx;
+				border-radius: 50%;
+				left: -20upx;
+				top: -12upx;
+				position:absolute;
+				background: #FF9800;
+			}
+		}
+		.icon-favor_fill_light{
+			position:relative;
+			z-index: 1;
+			font-size: 24upx;
+			margin-left: 2upx;
+			margin-right: 10upx;
+			color: #fff;
+			line-height: 1;
+		}
+		.tit{
+			font-size: 14px;
+			margin-left:10upx;
+		}
+		.icon-mark{
+			padding: 10upx;
+			font-size: 30upx;
+			line-height: 1;
+		}
+		.share-btn{
+			flex: 1;
+			text-align: right;
+			font-size: 12px;
+			color: #FF5722;
+		}
+		.icon-right{
+			font-size: 12px;
+			margin-left: 4upx;
+			color: #fa436a;
+			
+		}
+	}
+	
+	.tabs-box{
+		width: 100%;
+		z-index: 10;
+		background-color: white;
+		height: 40px;
+		.hx-tabs{
+			position: relative;
+			display: flex;
+			height:100%;
+			&-item{
+				display: flex;
+				flex-direction: row;
+				justify-content: left;
+				align-items: center;
+				width: 70px;
+				color:#666666;
+				text{
+					font-size: 16px;
+				}
+				
+			}
+			&-active{
+				color:#333333;
+				font-weight: bold;
+			}
+			&-slider-box{
+				position: absolute;
+				display: flex;
+				justify-content: left;
+				bottom: 0;
+				width: 70px;
+			}
+			&-slider{
+				display: flex;
+				background: #FFC107;
+				width: 20px;
+				height: 2px;
+				margin-left: 6px;
+			}
+		}
+	}
+	/* 详情 */
+	.info-box{
+		display: flex;
+		flex-direction: column;
+		padding-top: 12px;
+		.info-item{
+			display: flex;
+			flex-direction: row;
+			align-items: flex-start;
+			font-size: 14px;
+			margin-bottom: 6px;
+			.left{
+				color: #909399;
+				width: 84px;
+			}
+			.right{
+				color: #000000;
+				flex: 1;
+			}
+		}
+	}
+	
+	.c-list{
+		font-size: 13px;
+		color: #606266;
+		background: #fff;
+		.c-row{
+			display:flex;
+			align-items:center;
+			padding: 20upx 30upx;
+			position:relative;
+		}
+		.tit{
+			width: 140upx;
+		}
+		.con{
+			flex: 1;
+			color: #303133;
+			.selected-text{
+				margin-right: 10upx;
+			}
+		}
+		.bz-list{
+			height: 40upx;
+			font-size: 13px;
+			color: #303133;
+			text{
+				display: inline-block;
+				margin-right: 30upx;
+			}
+		}
+		.con-list{
+			flex: 1;
+			display:flex;
+			flex-direction: column;
+			color: #303133;
+			line-height: 40upx; 
+		}
+		.red{
+			color: #fa436a;
+		}
+	}
+	
+	/* 评价 */
+	.eva-section{
+		display: flex;
+		flex-direction: column;
+		
+		.e-header{
+			display: flex;
+			align-items: center;
+			height: 70upx;
+			font-size: 13px ;
+			color: #909399;
+			.tit{
+				font-size: 16px;
+				color: #303133;
+				margin-right: 6px;
+				font-weight: bold;
+			}
+			.hpd{
+				font-size: 12px;
+				transform: translateY(2px);
+			}
+			.tip{
+				flex: 1;
+				text-align: right;
+			}
+			.icon-right{
+				margin-left: 10upx;
+			}
+			
+		}
+		.eva-tag-box{
+			display: flex;
+			align-items:baseline;
+			margin: 6px 0 6px;
+			flex-wrap: wrap;
+			.tag-item{
+				align-items: center;
+				padding: 4px 8px;
+				background: #fae196;
+				font-size: 10px;
+				margin-right: 10px;
+				margin-bottom: 10px;
+				border-radius: 3px;
+				color: #555555;
+				display: flex;
+				flex-direction: row;
+				i{
+					color: #F0AD4E;
+					font-size: 12px;
+				}
+				.tread{
+					color: #909399
+				}
+				
+				.num{
+					margin-left: 6px;
+				}
+			}
+			.tread-bg{
+				background-color: #eeeeee !important;
+			}
+		}
+		.eva-btn{
+			margin:16px 0 6px;
+			background: #f6f6f6;
+			border-radius: 4px;
+			display: flex;
+			height: 36px;
+			justify-content: center;
+			align-items: center;
+			flex-direction: row;
+			font-size: 14px;
+			text{
+				margin-left: 10px;
+				margin-right: 6px;
+			}
+			.avatar-box{
+				display: flex;
+				flex-direction: row;
+				.avatar-item{
+					width: 20px;
+					height: 20px;
+					overflow: hidden;
+					border-radius: 100%;
+					background-color:#cfcfcf;
+					border: 0.5px solid #cccccc;
+					display: flex;
+					justify-content: center;
+					align-items: center;
+					margin-left: -5px;
+					z-index: 1;
+					image{
+						width: 20px;
+						height: 20px;
+						
+					}
+					i{
+						color: #ffffff;
+					}
+				}
+			}
+		}
+	}
+	.eva-box{
+		display: flex;
+		padding: 10px 0;
+		border-bottom: 1px solid #f5f5f5;
+		.portrait{
+			flex-shrink: 0;
+			width: 80upx;
+			height: 80upx;
+			border-radius: 100px;
+		}
+		.right{
+			flex: 1;
+			display: flex;
+			flex-direction: column;
+			font-size: 14px;
+			color: #606266;
+			padding-left: 26upx;
+			.con{
+				font-size: 14px;
+				color: #303133;
+				padding: 10px 0 6px;
+			}
+			.bot{
+				display: flex;
+				justify-content: space-between;
+				font-size: 12px;
+				color:#909399;
+			}
+			.praise-box{
+				margin-top: 4px;
+				display: flex;
+				flex-direction: row;
+				[class*="hxicon-"]{
+					color: #F0AD4E;
+					margin-right: 6px;
+				}
+				.tread{
+					color: #909399;
+				}
+				
+				.praise-txt{
+					color:#909399;
+					font-size: 12px;
+				}
+			}
+			.imgs {
+				display: flex;
+				flex-wrap: wrap;
+				padding-top: 4px;
+				.imgs-box {
+					width: 25%;
+					padding-right: 5px;
+					box-sizing: border-box;
+					image{
+						border-radius: 4px;
+					}
+				}
+			}
+		}
+	}
+	/*  详情 */
+	.detail-desc{
+		background: #fff;
+		margin-top: 16upx;
+		.d-header{
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			height: 80upx;
+			font-size: 15px;
+			color: #303133;
+			position: relative;
+				
+			text{
+				padding: 0 20upx;
+				background: #fff;
+				position: relative;
+				z-index: 1;
+			}
+			&:after{
+				position: absolute;
+				left: 50%;
+				top: 50%;
+				transform: translateX(-50%);
+				width: 300upx;
+				height: 0;
+				content: '';
+				border-bottom: 1px solid #ccc; 
+			}
+		}
+	}
+	
+	
+	
+	/*  弹出层 */
+	.popup {
+		position: fixed;
+		left: 0;
+		top: 0;
+		right: 0;
+		bottom: 0;
+		z-index: 99;
+		
+		&.show {
+			display: block;
+			.mask{
+				animation: showPopup 0.2s linear both;
+			}
+			.layer {
+				animation: showLayer 0.2s linear both;
+			}
+		}
+		&.hide {
+			.mask{
+				animation: hidePopup 0.2s linear both;
+			}
+			.layer {
+				animation: hideLayer 0.2s linear both;
+			}
+		}
+		&.none {
+			display: none;
+		}
+		.mask{
+			position: fixed;
+			top: 0;
+			width: 100%;
+			height: 100%;
+			z-index: 1;
+			background-color: rgba(0, 0, 0, 0.4);
+		}
+		.layer {
+			position: fixed;
+			z-index: 99;
+			bottom: 0;
+			width: 100%;
+			min-height: 40vh;
+			border-radius: 10upx 10upx 0 0;
+			background-color: #fff;
+			.btn{
+				height: 66upx;
+				line-height: 66upx;
+				border-radius: 100upx;
+				background: #fa436a;
+				font-size: 15px;
+				color: #fff;
+				margin: 30upx auto 20upx;
+			}
+		}
+		@keyframes showPopup {
+			0% {
+				opacity: 0;
+			}
+			100% {
+				opacity: 1;
+			}
+		}
+		@keyframes hidePopup {
+			0% {
+				opacity: 1;
+			}
+			100% {
+				opacity: 0;
+			}
+		}
+		@keyframes showLayer {
+			0% {
+				transform: translateY(120%);
+			}
+			100% {
+				transform: translateY(0%);
+			}
+		}
+		@keyframes hideLayer {
+			0% {
+				transform: translateY(0);
+			}
+			100% {
+				transform: translateY(120%);
+			}
+		}
+	}
+	
+	/* 底部操作菜单 */
+	.page-bottom{
+		position:fixed;
+		left: 30upx;
+		bottom:30upx;
+		z-index: 95;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		width: 690upx;
+		height: 100upx;
+		background: rgba(255,255,255,.9);
+		box-shadow: 0 0 20upx 0 rgba(0,0,0,.5);
+		border-radius: 16upx;
+		
+		.p-b-btn{
+			display:flex;
+			flex-direction: column;
+			align-items: center;
+			justify-content: center;
+			font-size: 12px;
+			color: #606266;
+			width: 96upx;
+			height: 80upx;
+			[class*="hxicon-"]{
+				font-size: 40upx;
+				line-height: 48upx;
+				color: #909399;
+			}
+			&.active, &.active [class*="hxicon-"]{
+				color: #fa436a;
+			}
+			.icon-fenxiang2{
+				font-size: 42upx;
+				transform: translateY(-2upx);
+			}
+			.icon-likefill{
+				font-size: 46upx;
+			}
+		}
+		.action-btn-group{
+			display: flex;
+			height: 76upx;
+			border-radius: 100px;
+			overflow: hidden;
+			box-shadow: 0 20upx 40upx -16upx #fa436a;
+			box-shadow: 1px 2px 5px rgba(219, 63, 96, 0.4);
+			background: linear-gradient(to right, #ffac30,#fa436a,#F56C6C);
+			margin-left: 20upx;
+			position:relative;
+			&:after{
+				content: '';
+				position:absolute;
+				top: 50%;
+				right: 50%;
+				transform: translateY(-50%);
+				height: 28upx;
+				width: 0;
+				border-right: 1px solid rgba(255,255,255,.5);
+			}
+			.action-btn{
+				display:flex;
+				align-items: center;
+				justify-content: center;
+				width: 180upx;
+				height: 100%;
+				font-size: 14px ;
+				padding: 0;
+				border-radius: 0;
+				background: transparent;
+			}
+		}
+	}
+	
+	/* foot */
+	.foot{
+		position: fixed;
+		display: flex;
+		z-index: 12;
+		
+		justify-content:center;
+		align-items : center; 
+		bottom: 0;
+		height: 100%;
+		width: 100%;
+		
+		/*width: calc(100% - 32px);*/
+		.btn-box{
+			position:absolute;
+			display: flex;
+			bottom: 15px;
+			justify-content:center;
+			align-items : center; 
+			margin:0;
+			height: 50px;
+			width: calc(100% - 32px);
+			z-index: 9;
+			&-left{
+				background: #222222;
+				border-top-left-radius:50px;
+				border-top-right-radius:9px;
+				border-bottom-left-radius:50px;
+				border-bottom-right-radius:9px;
+				padding-left: 6upx;
+				display: flex;
+				flex-direction:column;
+				justify-content:center;
+				align-self: center;
+				width: 70px;
+				height: 100%;
+				color: #f6d200;
+				text-align: center;
+				.imgBox{
+					display: flex;
+					text-align: center;
+					justify-content:center;
+					image{
+						width: 20px;
+						height: 20px;
+					}
+				}
+				text{
+					font-size: 20upx;
+				}
+			}
+			&-line{
+				background: #ffffff;
+				width: 2px;
+				height: 100%;
+			}
+			&-center{
+				height: 100%;
+				flex: auto;
+				display: flex;
+				justify-content:flex-start;
+				align-self: center;
+				align-items: center;
+				background: #222222;
+				border-top-left-radius:8upx;
+				border-bottom-left-radius:8upx;
+				padding-left: 10upx;
+				.cart{
+					position: relative;
+					width: 36px;
+					height: 36px;
+					image{
+						width: 100%;
+						height: 100%;
+					}
+					.tag{
+						position: absolute;
+						right: 12upx;
+						top: 16upx;
+						height: 18px;
+						width: 18px;
+						background-color: #ff4000;
+						color: #ffffff;
+						border-radius: 50%;
+						z-index: 1;
+						font-size: 10px;
+						text-align: center;
+						line-height: 18px;
+					}
+				}
+				.priceBox{
+					flex: auto;
+				}
+				
+			}
+			&-right{
+				width: 70px;
+				height: 100%;
+				position: relative;
+				display: flex;
+				justify-content:flex-start;
+				align-self: center;
+				align-items: center;
+				
+				
+				.pscj{
+					width: 100%;
+					height: 100%;
+					border-top-right-radius:100upx;
+					border-bottom-right-radius:100upx;
+					background: #222222;
+					text-align: center;
+					display: flex;
+					justify-content:center;
+					align-self: center;
+					align-items: center;  
+				}
+				.jiesuan{
+					width: 100%;
+					height: 100%;
+					font-size: 28upx;
+					border-top-right-radius:100upx;
+					border-bottom-right-radius:100upx;
+					text-align: center;
+					display: flex;
+					justify-content:center;
+					align-self: center;
+					align-items: center;    
+					background: linear-gradient(45deg, $hx-theme-color-light, $hx-theme-color); 
+					font-weight: bold;
+					color: #222222;
+				}
+			}
+		}
+		.zz{
+			position: absolute;
+			top: 0;
+			left: 0;
+			right: 0;
+			bottom: 0;
+			background-color: rgba(0,0,0,.7);
+			z-index: 1;
+		}
+		.cart-box{
+			display: flex;
+			justify-content: flex-start;
+			flex-flow: column;
+			background: #ffffff;
+			position: absolute;
+			bottom: 0; 
+			z-index: 2;
+			max-height: 66%;
+			
+			padding-bottom: 62px;
+			border-top-left-radius: 16px;
+			border-top-right-radius: 16px;
+			overflow: hidden;
+			width: 100%;
+			.rebate-box{
+				height: 30px;
+				background: #FFC107;
+				color: #FF9900;
+				text-align: center;
+				line-height: 30px;
+				font-size: 14px;
+			}
+			.box-container{
+				box-sizing: border-box;
+				padding:0 16px;
+			}
+			.operating-box{
+				font-size: 12px;
+				line-height: 40px;
+				height: 40px;
+				border-bottom: 1px solid #f6f6f6;
+				color: #666666;
+				display: flex;
+				flex-direction: row;
+				&_right{
+					flex: 1;
+				}
+				&_left{
+					display: flex;
+					flex-direction: row;
+				}
+				
+			}
+			.goods-box{
+				height: 100%;
+			    overflow: hidden;
+				flex: 1;
+				display: flex;
+				.goods-list-scroll{
+					height: 100%;
+					
+					.goods-list{
+						
+						width: 100%;
+						display: flex;
+						flex-wrap: wrap;
+						
+						.box{
+							width: 100%;
+							border-bottom: 1px solid #f6f6f6;
+							box-sizing: border-box;
+							padding: 0 16px;
+							.m-store-item{
+								display: flex;
+								flex-direction: row;
+								width: 100%;
+								justify-content: space-between;
+								align-items: flex-end;
+								padding-top: 15px;
+								padding-bottom: 15px;
+								.m-img{
+									flex: 0 0 85px;
+									height: 85px;
+									background: #eee;
+									border-radius: 4px;
+								}
+								.m-text{
+									flex: 1;
+									position: relative;
+									height: 85px;
+									padding: 0 6px;
+									display: flex;
+									align-content: space-between;
+									flex-direction: column;
+									.m-title{
+										font-size: 16px;
+										color:#555555;
+										height: 21px;
+										font-weight: bold;
+									}
+									.m-descripe{
+										font-size: 12px;
+										color:#999999;
+										margin-top: 5px;
+										height: 35px;
+									}
+									.m-price-box{
+										height: 24px;
+										font-weight: bold;
+										display: flex;
+										flex-direction: row;
+										align-items: flex-end;
+										.symbol{
+											color:#ff582b;
+											font-size: 12px;
+										}
+										.m-price{
+											position: relative;
+											top: 2px;
+											font-size: 18px;
+											color:#ff582b;
+										}
+										.m-old-price{
+											margin-left: 3px;
+											display: flex;
+											flex-direction: row;
+											font-size: 10px;
+											color:#999999;
+											margin-top: 5upx;
+											text-decoration: line-through;
+											font-weight: normal;
+										}
+									}
+									.m-distance{
+										position: absolute;
+										right: 0;
+										bottom: -4px;
+										z-index: 16;
+										color:#b2b2b2;
+										font-size: 20upx;
+										text-align: right;
+										.jumpPosition{
+											position: absolute; 
+											bottom: 23px;
+											right: 0;
+											z-index: 2;
+											width: 28px;
+											height: 28px;
+										}
+									}
+									
+								}
+								
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+	.form-main{
+		
+		display: flex;
+		flex-direction: column;
+		justify-content: left;
+		padding: 15px;
+		
+		.form-main_ctn{
+			display: flex;
+			flex-direction: column;
+			justify-content: left;
+			padding: 23px 22px 22px 22px;
+			background-color: #fff;
+			border-radius: 8px;
+			.godos_tit{
+				margin-top: 4px;
+				margin-bottom: 6px;
+				font-size: 18px;
+				font-weight: bold;
+				color: #333; 
+			}
+			.gg_tit{
+				margin-top: 8px;
+				font-size: 14px;
+				font-weight: bold;
+				color: #555;
+			}
+			.gg_box{
+				margin-top: 8px;
+				display: flex;
+				flex-direction: row;
+				flex-wrap: wrap;
+				font-size: 12;
+				color: #333;
+				.item{
+					margin-right: 14px;
+					margin-bottom: 14px;
+					border: 1px solid #f1f1f1;
+					border-radius: 4px;
+					padding: 4px 6px;
+				}
+				.item.active{
+					border-color: #ffe081;
+					background-color: #fff0b7;
+				}
+				
+			}
+			.select_gg{
+				margin: 26px -12px 0;
+				padding: 6px 12px;
+				color: #999;
+				background-color: #f9f9f9;
+				display: flex;
+				flex-direction: row;
+				.lable{
+					
+				}
+				.select_gg_box{
+					flex: 1;
+					display: flex;
+					flex-direction: row;
+					flex-wrap: wrap;
+					.gg-item{
+						color: #333;
+						.gg-item-cut{
+							margin-left: 3px;
+							margin-right: 3px;
+						}
+					}
+					.gg-item:last-child{
+						.gg-item-cut{
+							display: none;
+						}
+					}
+				}
+				
+			}
+			.bottom{
+				position: relative;
+				display: flex;
+				flex-direction: row;
+				margin-top: 12px;
+				.price_box{
+					flex: 1;
+					lign-items: baseline;
+					color: #ff582b;
+					font-size: 14px;
+					position: relative;
+					top: 4px;
+					.price{
+						font-size:  24px;
+					}
+				}
+				.jumpPosition{
+					position: absolute;
+					right: 16px;
+					top: 2px;
+				}
+				.form-btn-box{
+					height: 30px;
+					line-height: 30px;
+					.add-btn{
+						border-radius: 50px;
+						background-color: #ffce3c; 
+						padding: 0 12px;
+						display: flex;
+						height: 30px;
+						line-height: 30px;
+						align-items: center;
+						i{
+							font-weight: bold;
+							font-size: 18px;
+							margin-right: 3px;
+							margin-left: -4px;
+						}
+						text{
+							
+							font-size: 14px;
+							font-weight: bold;
+							color: #363636;
+						}
+					}
+				}
+			}
+			
+		}
+		
+		.close{
+			position: absolute;
+			left: 50%;
+			margin-left: -20px;
+			bottom: -70px;
+			border-radius: 50%;
+			height: 40px;
+			width: 40px;
+			background-color: #fff;
+			opacity: 0.7;
+			text-align: center;
+			line-height: 43px;
+			i{
+				font-weight: bold;
+				font-size: 22px;
+			}
+		}
+	}
+</style>

+ 49 - 0
HX-SHOP/pages/search/search.vue

@@ -0,0 +1,49 @@
+<template>
+	<view>
+		<hx-navbar title="搜索页面"></hx-navbar>
+		<view class="contianer">
+			<text class="txt">{{dataType}}</text>
+		</view>
+		<view class="contianer">
+			<text class="txt">待开发</text>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				dataType: null
+			}
+		},
+		onLoad(option){
+			if(option.type){
+				switch(option.type){
+					case 'home':
+						this.dataType = "来自首页的搜索";
+						break
+					case 'store':
+						this.dataType = "来自商户页的搜索"
+						break
+					case 'order':
+						this.dataType = "来自订单页的搜索"
+						break
+				}
+			}
+		},
+		methods: {
+			
+		}
+	}
+</script>
+
+<style>
+.contianer{
+	margin: 15px;
+}
+.txt{
+	font-size: 16px;
+	color: #888888;
+}
+</style>

+ 1762 - 0
HX-SHOP/pages/store/index - ╕▒▒╛ (2).vue

@@ -0,0 +1,1762 @@
+<template>
+	<view>
+		<hx-navbar
+			:fixed="true"
+			:color="['#ffffff','#888888']"
+			barPlaceholder="hidden"
+			transparent="auto"
+			title="商户中心"
+			:backgroundColor="[[245,245,245],[255,193,7]]"
+			:pageScroll.sync="scrollData">
+		</hx-navbar>
+		<!-- 头部 -->
+		<view class="header">
+			<image class="bg header-banner " :src="storeData.banner" mode=""></image>
+			<view class="header-bottom">
+				<view class="flex-row justify-between storeInfo hx-shadow">
+					<view class="left flex1 hx-pr15">
+						<view class="hx-txt-18 hx-color-black hx-txt-weigth hx-mb-10 flex-wrap ">
+							{{storeData.store_name}}
+						</view>
+						<view class="hx-txt-14 flex-wrap" style="color: #888;">
+							{{storeData.info}}
+						</view>
+					</view>
+					<view class="right">
+						<image class="storeAvatar hx-shadow" :src="storeData.avatar" mode=""></image>
+					</view>
+					
+				</view>
+			</view>
+		</view>
+		
+		<!-- tab -->
+		<view class="tabs-box hx-bb">
+			<view class="hx-tabs">
+				<view class="hx-tabs-item" v-for="(item,i) in tabs" :key="i" :class="{'hx-tabs-active': swiperCurrent == i}" @click="swiperChange(i)" :style="{transition: transtionTime + 'ms'}">
+					<text>{{item.name}}</text>
+				</view>
+				<view class="" style="width: 40%;"></view>
+				<view class="hx-tabs-slider-box" :style="{width: (60/tabs.length) + '%',transition: transtionTime + 'ms',left:swiperCurrentSliderLeft + '%'}">
+					<view class="hx-tabs-slider"></view>
+				</view>
+			</view>
+		</view>
+		
+		<view class="main" :style="{height: mainHeight}" >
+			<swiper 
+			id="mainSwiper"
+			style="height: 100%;"
+			:current="swiperCurrent" 
+			:duration="transtionTime"
+			@animationfinish="animationfinish">
+				
+				<swiper-item class="swiper-item" >
+					<view class="scroll-items">
+						<view class="category-list">
+							<!-- 左侧分类导航 -->
+							<scroll-view  :scroll-y="isBoxScroll" class="left" :scroll-top="menuScrollTop" >
+								<view class="scroll-items">
+									<view  v-for="(item,i) in categoryList" :key="i" class="row" :class="{active: item.id == menuCurrentId}" @click="showCategory(item)">
+										<view class="text">
+											{{item.name}}
+										</view>
+										<view class="row-number" v-if="item.number">
+											{{item.number}}
+										</view>
+									</view>
+								</view>
+							</scroll-view>
+							<!-- 右侧子导航 -->
+							<scroll-view scroll-with-animation :scroll-y="isBoxScroll" class="right"  @scroll="asideScroll" :scroll-top="tabScrollTop" >
+								<view class="goodsListBox">
+									
+									<view class="category" v-for="item in categoryList" :key="item.id" :id="'goodsBox'+item.id" >
+										<view class="s-item">{{item.name}}</view>
+										<view class="list"  >
+											<view class="box" v-for="(rowData,i) in goodsList" :key="rowData.id" v-if="item.id == rowData.type_id">
+												<!-- 商品列表 -->
+												<view class="m-store-item">
+													<view class="m-img" @click="hrefGoodsInfo(rowData.id)">
+														<image style="width: 100%;height: 100%;" :src="rowData.img" mode="aspectFit"></image>
+													</view>
+													<view class="m-text">
+														<view class="m-title" @click="hrefGoodsInfo(rowData.id)">
+															{{rowData.name}}
+														</view>
+														
+														<view class="m-descripe">
+															
+															{{rowData.descripe}}
+															
+														</view>
+													
+														<block v-if="rowData.form">
+															<view class="m-price-box">
+																<view class="symbol">¥</view>
+																<view class="m-price">{{rowData.form_child[0].price}}</view>
+																<view class="m-old-price" v-if="rowData.form_child[0].oldprice">
+																	<text>¥{{rowData.form_child[0].oldprice}}</text>
+																</view>
+															</view>
+														</block>
+														<block v-else>
+														<view class="m-price-box">
+															<view class="symbol">¥</view>
+															<view class="m-price">{{rowData.price}}</view>
+															<view class="m-old-price" v-if="rowData.oldprice">
+																<text>¥{{rowData.oldprice}}</text>
+															</view>
+														</view>
+														</block>
+														<view class="m-distance" >
+															<block v-if="rowData.form">
+																<view class="miniBtn" @click="showForm(rowData)">
+																	<text>选规格</text>
+																	<view class="num" ></view>
+																</view>
+															</block>
+															<block v-else>
+																<view :class="'addEle_' + i" class="jumpPosition"></view>
+																<hx-number-box @change="addGoodsChange" :value="rowData.number" :rowData="rowData" :clickTime="animaTime + 200" @addChange="touchOnAddGoods('.addEle_' + i,rowData)"></hx-number-box>
+															</block>
+														</view>
+													</view>
+													
+												</view>
+											</view>
+										</view>
+									</view>
+								</view>
+							</scroll-view>
+							
+						</view>
+					</view>
+				</swiper-item>
+				
+				
+				<swiper-item class="swiper-item" >
+					<view class="scroll-items">
+						<scroll-view  scroll-y style="height: 100%;width: 100%;background-color: #ffffff;"  :scroll-y="isBoxScroll" >
+							<view class="scroll-items evaluate-box" >
+								<view class="evaluate-box-header">
+									
+								</view>
+								<view class="evaluate-box-body">
+									
+								</view>
+								<hx-comment :listData="commentList" @previewImg="commentPreviewImg"></hx-comment>
+							</view>
+						</scroll-view>
+					</view>
+					
+				</swiper-item>
+				
+				
+				<swiper-item class="swiper-item" >
+					<view class="scroll-items">
+						<view class="business-box">
+							<view class="info-list hx-mt-15">
+								<view class="info-list-container">
+									<i class="hxicon-location"></i>
+									<text>{{ storeData.address }}</text>
+								</view>
+							</view>
+							
+							<view class="info-list hx-mt-15 ">
+								<view class="info-list-container hx-bb">
+									<i class="hxicon-time"></i>
+									<text>配送时间:{{ storeData.delivery_time }}</text>
+								</view>
+							</view>
+							<view class=" info-list">
+								<view class="info-list-container" @click="goCall(storeData.telephone)">
+									<i class="hxicon-phone"></i>
+									<text style="flex: 1;">商家电话:{{ storeData.telephone }}</text>
+									<view class="right">
+										<text>拨打</text><i class="hxicon-right"></i>
+									</view>
+								</view>
+							</view>
+							<view class="info-list hx-mt-15">
+								<view class="info-list-container">
+									<i class="hxicon-new" style="color:#ff3333"></i>
+									<text style="flex: 1;">商家当前热门活动</text>
+									<view class="right">
+										<text>查看</text><i class="hxicon-right"></i>
+									</view>
+								</view>
+							</view>
+						</view>
+					</view>
+				</swiper-item>
+			</swiper>
+		</view>
+		
+		<!-- 多规格 -->
+		<uni-popup ref="popup" type="center" @change="popupChange">
+			<view class="form-main" v-if="currentGoodsData">
+				<view class="form-main_ctn" @click.stop.prevent="mpClear" >
+					<view class="godos_tit"><text>{{currentGoodsData.name}}</text></view>
+					
+					<view class="gg_tit">
+						<text>{{currentGoodsData.form.name}}</text>
+					</view>
+					<view class="gg_box">
+						<block v-for="(form_child,j) in currentGoodsData.form_child" :key="j" v-if="form_child.pid == currentGoodsData.form.id">
+							<view class="item" :class="{'active': form_child.select}" @click="selectGoodsForm(currentGoodsData,form_child)">{{form_child.name}}</view>
+						</block>
+					</view>
+					
+					<view class="select_gg">
+						<text class="lable">已选规格:</text>
+						<view class="select_gg_box">
+							<block v-for="(form_child,j) in currentGoodsData.form_child" :key="j" v-if="form_child.select == true">
+								<view class="gg-item">
+									<text>{{form_child.name}} </text>
+									<text class="gg-item-cut">,</text>
+								</view>
+							</block>
+						</view>
+					</view>
+					
+					<view class="bottom">
+						<view class="price_box">
+							<text>¥</text>
+							<block v-for="(form_child,j) in currentGoodsData.form_child" :key="j" v-if="form_child.select == true">
+								<text class="price">{{form_child.price}}</text>
+							</block>
+						</view>
+						<view class="form-btn-box">
+							<block v-if="!currentGoodsData.number">
+								<view id="ggAddBtn" class="add-btn" @click="formFirstAddGoods()">
+									<i class="hxicon-add" id="eleAdd"></i>
+									<text>加入购物车</text>
+								</view>
+							</block>
+							<block v-else>
+								<view class="addEle_gg jumpPosition"></view>
+								<hx-number-box @change="formAddGoodsChange" :value="currentGoodsData.number" :rowData="currentGoodsData" :clickTime="animaTime + 200" @addChange="touchOnAddGoods('.addEle_gg',currentGoodsData)"></hx-number-box>
+							</block>
+						</view>
+						
+					</view>
+				</view>
+				<view class="close" @click="hiddenForm()">
+					<i class="hxicon-close"></i> 
+				</view>
+			</view>
+			
+		</uni-popup>
+		
+		<!-- 购物车 -->
+		<view class="foot"  @touchmove.stop.prevent="mpClear" :style="{height: footHeight}" v-if="showFoot">
+			<view class="zz" @click="hideShoppingCar"></view>
+			<view class="btn-box">
+				<view class="btn-box-left" @click="contact">
+					<view class="imgBox">
+						<image src="../../static/store/contact.png" mode=""></image>
+					</view>
+					<text>联系商家</text>
+				</view>
+				<view class="btn-box-line"></view>
+				<view class="btn-box-center" @click="showShoppingCar">
+					<view class="cart">
+						<view class="tag cartNum" v-if="goodsTotalNumber>0">{{goodsTotalNumber}}</view>
+						<image :src="goodsTotalNumber ? '/static/store/cart.png' : '/static/store/cart2.png'" mode=""></image>
+					</view>
+					<view class="priceBox">
+						<view class="hx-txt-18 hx-color-white" v-if="goodsTotalPrice>0">
+							¥{{goodsTotalPrice}}
+						</view>
+						<view class="hx-txt-10 hx-color-gray">
+							另需配送费¥{{shippingDees}}
+						</view>
+					</view>
+				</view>
+				<view class="btn-box-right">
+					<view class="jiesuan"  v-if="goodsTotalPrice>0 && goodsTotalPrice >= startingPrice" @click="jiesuan">
+						去结算
+					</view>
+					<view class="pscj hx-txt-10 hx-color-gray" v-else>
+						<text v-if="startingPrice>0">差¥{{-(goodsTotalPrice-startingPrice)}}起送</text>
+					</view>
+					
+				</view>
+			</view>
+			<view class="cart-box" :style="{display: showCar ? 'flex' : 'none'}">
+				<!-- <view class="box-container rebate-box" v-if="showDiscount">
+					<text>已享100减25</text>
+				</view> -->
+				<view class="box-container operating-box">
+					<view class="operating-box_right">
+						
+					</view>
+					<view class="operating-box_left clear" @click="clearShoppingCart">
+						<i class="hxicon-delete"></i>
+						<text>清空购物车</text>
+					</view>
+				</view>
+				<view class=" goods-box">
+					<view class="" style="flex: 1;">
+						<scroll-view scroll-y="true" class="goods-list-scroll" :scroll-top="carGoodsScrollTop">
+							<view class="goods-list">
+								<view class="box" v-for="(rowData,i) in shoppCart" :key="i" v-if="rowData.number>0">
+									
+									<view class="m-store-item">
+										<view class="m-img">
+											<image style="width: 100%;height: 100%;" :src="rowData.img" mode="aspectFit"></image>
+										</view>
+										<view class="m-text">
+											<view class="m-title">
+												{{rowData.name}}
+											</view>
+											<view class="m-descripe">
+												
+												{{rowData.current_form ? rowData.form.name + ":" + rowData.current_form.name : rowData.descripe}}
+											</view>
+											<view class="m-price-box" >
+												<view class="symbol">¥</view>
+												<view class="m-price">{{rowData.price}}</view>
+												<view class="m-old-price" v-if="rowData.oldprice">
+													<text>¥{{rowData.oldprice}}</text>
+												</view>
+											</view>
+											<view class="m-distance" > 
+											<view :class="'addEle2_' + i" class="jumpPosition">
+											</view>
+												<hx-number-box @change="addGoodsChange" :value="rowData.number" :rowData="rowData" :clickTime="animaTime + 200" @addChange="touchOnAddGoods('.addEle2_' + i,rowData)"></hx-number-box>
+												
+											</view>
+										</view>
+										
+									</view>
+								</view>
+							</view>
+						</scroll-view>
+					</view>
+					
+				</view>
+			</view>
+			
+		</view>
+	</view>
+</template>
+<script>
+	import hxComment from "@/components/hx-comment/hx-comment.vue";
+	import hxNumberBox from "@/components/uni-number-box/uni-number-box.vue";
+	//引入测试数据
+	import testData from "@/common/testdata.js";
+	
+	var statusBarHeight = uni.getSystemInfoSync().statusBarHeight;
+	
+	export default {
+		components: {
+			hxComment,
+			hxNumberBox
+		},
+		data() {
+			return {
+				scrollData:{},
+				
+				// 门店信息
+				storeData:{},
+				
+				// 显示页尾显示购物车
+				showFoot: true,
+				//显示购物车里的商品
+				showCar: false,
+				//所有门店购物车
+				shoppingCartAll:[],
+				//配送费
+				shippingDees: 0,
+				//配送起步价
+				startingPrice:0,
+				//购物车商品价格合计
+				goodsTotalPrice: 0,
+				//购物车商品数量合计
+				goodsTotalNumber: 0,
+				//当前门店购物车
+				shoppCart: [],
+				//foot 高度
+				footHeight: '0',
+				//购物车中商品滚动条位置
+				carGoodsScrollTop: 0,
+				//购物车缓存 Storage 名称
+				shoppingCartStorageName: 'shopping_cart',
+				
+				//tabs
+				tabs: [
+					{name:'购物'},
+					{name:'评价'},
+					{name:'商家'},
+				],
+				// swiper当前索引
+				swiperCurrent:0,
+				swiperCurrentSliderLeft: 0,
+				// swiper滑动时间
+				transtionTime:100,
+				
+				//head容器的高度
+				headHeight: 0,
+				// main容器的高度
+				mainHeight:0,
+				
+				//评论列表
+				commentList: [],
+				
+				
+				// 是否可以滚动
+				isBoxScroll: false,
+				
+				// 菜单索引
+				menuCurrentId: 1,
+				// 菜单滚动距离
+				tabScrollTop: 0,
+				// 菜单分类滚动距离
+				menuScrollTop:0,
+				// 分类列表
+				categoryList:[],
+				// 商品数据
+				goodsList:[],
+				// 是否计算了每个分类容器的高度
+				sizeCalcState: false,
+				
+				//图片预览
+				currentImg: '',
+				previewImgList: [],
+				previewImgStatus: true,
+				PINum: 0,
+				
+				// 是否
+				isBack: true,
+				
+				currentGoodsData: null,
+				
+				//动画时间
+				animaTime: 300,
+			}
+		},
+		onLoad(option) {
+			const that = this; 
+			
+			
+			
+			//商家信息
+			that.storeData = testData.storeData,
+			//商品列表
+			that.goodsList = testData.goodsData;
+			//商品分类信息列表
+			that.categoryList = testData.categoryData;
+			//评论列表
+			that.commentList = testData.commentData;
+			
+			const carts = uni.getStorageSync(that.shoppingCartStorageName) || [];
+			that.shoppingCartAll = carts
+			if(carts){
+				//根据缓存数据 获取购物车中属于本商店的商品
+				for(let i in carts){
+					if(carts[i].store_id == that.storeData.store_id){
+						that.shoppCart = carts[i].shopping_cart  ? carts[i].shopping_cart : [];
+						break;
+					}
+				}
+			}
+		},
+		onPageScroll(e){
+			const that = this
+		    that.scrollData = e;
+			let view = uni.createSelectorQuery().select(".main");
+			view.fields({
+				rect: true
+			}, data => {
+				if(data != null){
+					// 状态栏 + nav + tab
+					if(data.top <= statusBarHeight+89){
+						that.isBoxScroll = true
+					}else{
+						that.isBoxScroll = false
+					}
+				}
+				
+			}).exec();
+		},
+		onReady() {
+			const that = this
+			const sysInfo = uni.getSystemInfoSync();
+			const view = uni.createSelectorQuery().select(".head");
+			//屏幕高度 - 头部导航高度 - 状态栏高度 - tab高度
+			that.mainHeight = sysInfo.screenHeight - statusBarHeight - 44 - 44 + 'px';
+			view.fields({
+				size: true
+			}, data => {
+				if(data != null){
+					that.headHeight = data.height
+				}
+			}).exec();
+			that.calcSize();
+		},
+		onBackPress(event) {
+			
+			// if(this.showFormBox){
+			// 	this.hiddenForm()
+			// 	return true
+			// }
+			if(!this.isBack){
+				this.$refs.popup.close()
+				return true
+			}
+			if(this.previewImgStatus){
+				this.PINum = 0
+				return true
+			}
+		},
+		methods:{
+			mpClear(e) {
+				// TODO nvue 取消冒泡
+				e.stopPropagation()
+			},
+			//显示购物车
+			showShoppingCar(){
+				if(this.goodsTotalNumber == 0){
+					return;
+				}
+				this.showCar = true;
+			},
+			//隐藏购物车
+			hideShoppingCar(){
+				this.showCar = false;
+			},
+			
+			// 切换tab
+			swiperChange(index) {
+				this.swiperCurrent = index;
+				this.swiperCurrentSliderLeft= (60/this.tabs.length) * index;
+			},
+			animationfinish({detail: { current }}) {
+				/* this.$refs.tabs.setFinishCurrent(current); */
+				this.swiperCurrent = current;
+				this.current = current;
+				this.swiperChange(current);
+			},
+			
+			//拨打电话
+			goCall(phone){
+				if(!phone){return;}
+				uni.makePhoneCall({phoneNumber: phone});
+			},
+			
+			//点击一级分类
+			showCategory(item){
+				const that = this
+				that.isBoxScroll = true;
+				that.menuCurrentId = item.id;
+				setTimeout(()=>{
+					let index = that.categoryList.findIndex(sitem=>sitem.id === item.id);
+					that.tabScrollTop = that.categoryList[index].top;
+					that.isBoxScroll = false
+				},100)
+				
+				
+			},
+			//右侧栏滚动
+			asideScroll(e){
+				const that = this;
+				const scrollTop = Math.round(e.detail.scrollTop);
+				
+				const tabs = that.categoryList.filter(item=>item.top <= scrollTop).reverse();
+				
+				if(tabs.length > 0){
+					that.menuCurrentId = tabs[0].id;
+				}
+				const menuNum = that.categoryList.length
+				const cNum = tabs.length
+				// 定位在第4个分类,当分类滑动到第4格时将不再变换位置。
+				const n = 4
+				if(cNum>n){
+					that.menuScrollTop = (cNum - n) * 45
+				}
+			},
+			//计算右侧栏每个tab的高度等信息
+			calcSize(event){
+				let h = 0;
+				if(this.sizeCalcState){
+					return false
+				}
+				this.categoryList.forEach(item=>{
+					let view = uni.createSelectorQuery().select("#goodsBox" + item.id);
+					view.fields({
+						size: true
+					}, data => {
+						if(data != null){
+							item.top = h;
+							h += Math.round(data.height);
+							item.bottom = h;
+						}
+						
+					}).exec();
+				})
+				this.sizeCalcState = true;
+			},
+			
+			//获取该商品在购物车的数量
+			getCartGoodsNum(goods){
+				const that = this
+				const cart = that.shoppCart
+				var n = 0
+				if(cart){
+					for(let i in cart){
+						if(cart[i].id == goods.id){
+							n += cart[i].number
+						}
+					}
+				}
+				return n
+			},
+			
+			//小球跳跃动画
+			touchOnAddGoods(ele,data){
+				// this.element = [ele,'.cart'];
+				// this.num ++; 
+			},
+			// --------------------------------------------------------------------------------------------
+			//------------------------------------------------------------------------------------------------
+			//获取门店购物车
+			getStoreCart(){
+				// let that = this
+				// let shoppCart = {}
+				// let carts = uni.getStorageSync(that.shoppingCartStorageName) || [];
+				// if(carts){
+				// 	//根据缓存数据 获取购物车中属于本商店的商品
+				// 	for(let i in carts){
+				// 		if(carts[i].store_id == that.storeData.store_id){
+				// 			shoppCart = carts[i].shopping_cart  ? carts[i].shopping_cart : [];
+				// 			break;
+				// 		}
+				// 	}
+				// }
+				// }else{
+				// 	that.storeData.shopping_cart = []
+				// 	uni.setStorageSync(that.shoppingCartStorageName,that.storeData);
+				// }
+				//return shoppCart
+			},
+			popupChange(e){
+				this.isBack = !e.show
+			},
+			//显示 规格
+			showForm(goods){
+				var that = this;
+				let goodsCart = that.shoppCart;
+				if(goodsCart){
+					let currentGoods = null
+					for(let i in goodsCart){
+						if(goodsCart[i].id == goods.id){
+							currentGoods = goodsCart[i]
+							break
+						}
+					}
+					if(currentGoods){
+						let selectStatus = false
+						for (let i in goods.form_child){
+							if(goods.form_child[i].id == currentGoods.current_form.id){
+								if(!selectStatus){
+									goods.form_child[i].select = true
+									goods.number = currentGoods.number
+									selectStatus = true
+								}else{
+									goods.form_child[i].select = false
+								}
+							}else{
+								goods.form_child[i].select = false
+							}
+						}
+					}
+					
+				}
+				that.currentGoodsData = goods
+				that.$refs.popup.open()
+				
+			},
+			//加入购物车
+			formAddGoodsChange(number,goodsData){
+				let that = this;
+				if(number >= 1){
+					for(let i in goodsData.form_child){
+						if(goodsData.form_child[i].select == true ){
+							that.currentGoodsData.current_form = goodsData.form_child[i]
+							break
+						}
+					}
+				}
+				that.addGoodsChange(number,that.currentGoodsData)
+			},
+			formFirstAddGoods(){
+				const that = this
+					
+				that.formAddGoodsChange(1,that.currentGoodsData)
+				that.touchOnAddGoods('#ggAddBtn',that.currentGoodsData)
+			},
+			//隐藏规格
+			hiddenForm(){
+				this.$refs.popup.close();
+			},
+			//选择规格
+			selectGoodsForm(goods,formChild){
+				const that = this
+				const data = goods.form_child
+				var n = 0
+				for (var i in data){
+					if(data[i].id == formChild.id){
+						data[i].select = true
+					}else{
+						data[i].select = false
+					}
+				}
+				const goodsCart = that.shoppCart;	
+				if(goodsCart){
+					for(let i in goodsCart){
+						if(goodsCart[i].id == goods.id && goodsCart[i].current_form.id == formChild.id){
+							n = goodsCart[i].number
+							break;
+						}
+					}
+				}
+				goods.number = n
+				this.currentGoodsData = goods
+			},
+			//计算每类商品购买的总数
+			setLabelNumber(){
+				const that = this;
+				//计算每一类购买商品的总数量
+				for(let j in that.categoryList){
+					const n = 0;
+					for(var i in that.shoppCart){
+						if(that.shoppCart[i].type_id ==  that.categoryList[j].id){
+							n += that.shoppCart[i].number;
+						}
+					}
+					that.categoryList[j].number = n;
+				}
+			},
+			//新增商品计算价格
+			addGoodsChange(number,rowData){
+				
+				number = Number(number)
+				var that = this;
+				
+				let shoppCart = [];
+				let totalPrice = 0;
+				let totalNumber = 0;
+				let existedGoods = false;
+				//门店第一次添加商品
+				let isFirstAddGoods = true;
+				//是否为有规格的商品
+				let isFormGoods = false
+				if(rowData.current_form){
+					isFormGoods = true
+				}
+				let deleteGoods = null
+				let carts = uni.getStorageSync(that.shoppingCartStorageName) || [];
+			
+				if(carts.length != 0){
+					isFirstAddGoods = false
+					//根据缓存数据 获取购物车中属于本商店的商品
+					for(let i in carts){
+						if(carts[i].store_id == that.storeData.store_id){
+							shoppCart = carts[i].shopping_cart ? carts[i].shopping_cart : [];
+							break;
+						}
+					}
+					//检查该商品是否为第一次添加,
+					for(var i in shoppCart){
+						if(shoppCart[i].id == rowData.id){
+							if(isFormGoods){
+								//相同商品比较规格是否也相同
+								if(shoppCart[i].current_form.id == rowData.current_form.id){
+									existedGoods = true;
+								}
+							}else{
+								existedGoods = true;
+							}
+							if(existedGoods){
+								//在购物车中移除该商品
+								if(number <= 0){
+									deleteGoods = shoppCart[i];
+									break;
+								}
+								//非第一次添加,直接修改商品数量,并计算出单品合计
+								if(isFormGoods){
+									shoppCart[i].price = rowData.current_form.price
+									shoppCart[i].oldprice = rowData.current_form.oldprice
+									shoppCart[i].total = number *  rowData.current_form.price
+								}else{
+									shoppCart[i].price = rowData.price
+									shoppCart[i].total = number *  rowData.price
+									shoppCart[i].oldprice = rowData.oldprice
+								}
+								shoppCart[i].number = rowData.number = number
+								break;
+							}
+						}
+					}
+				}
+				//在购物车中移除该商品
+				if(deleteGoods != null){
+					if(carts){
+						//根据缓存数据 获取购物车中属于本商店的商品
+						for(let i in carts){
+							if(carts[i].store_id == that.storeData.store_id){
+								var index = shoppCart.indexOf(deleteGoods);
+							
+								if (index > -1) { 
+									shoppCart.splice(index, 1); 
+								} 
+								carts[i].shopping_cart = shoppCart
+								
+								//计算总商品数量和总价
+								for(var j in shoppCart){
+									//总价
+									totalPrice += shoppCart[j].total
+									totalNumber += shoppCart[j].number
+								}
+								//更改商品列表中的已购买数量
+								for(let j in that.goodsList){
+									if(that.goodsList[j].id == rowData.id){
+										that.goodsList[j] = rowData
+										break;
+									}
+								}
+								that.goodsTotalPrice = totalPrice
+								that.goodsTotalNumber = totalNumber
+								that.shoppCart = shoppCart
+								that.shoppingCartAll = carts
+								that.setLabelNumber()
+								uni.setStorageSync(that.shoppingCartStorageName,carts);
+								break;
+							}
+						}
+					}else{
+						that.storeData.shopping_cart = []
+						uni.setStorageSync(that.shoppingCartStorageName,that.storeData);
+					}
+					return 
+				}
+					
+				//第一次添加
+				if(!existedGoods){
+					if(rowData.form){
+						rowData.price = rowData.current_form.price
+						rowData.oldprice = rowData.current_form.oldprice
+						rowData.total = number *  rowData.current_form.price
+					}else{
+						rowData.total = number *  rowData.price
+					}
+					rowData.number = number;
+					shoppCart.push(rowData);
+				}
+				
+				//计算总商品数量和总价
+				for(var i in shoppCart){
+					//总价
+					totalPrice += shoppCart[i].total
+					totalNumber += shoppCart[i].number
+				}
+				//更改商品列表中的已购买数量
+				for(let i in that.goodsList){
+					if(that.goodsList[i].id == rowData.id){
+						that.goodsList[i] = rowData
+						break;
+					}
+				}
+				if(that.goodsTotalPrice < totalPrice){
+					//更具小球动画延时更改数据
+					that.goodsTotalPrice = totalPrice
+					that.goodsTotalNumber = totalNumber
+					
+				}else{
+					that.goodsTotalPrice = totalPrice
+					that.goodsTotalNumber = totalNumber
+				}
+				
+				that.shoppCart = shoppCart; 
+				that.storeData.shopping_cart = shoppCart;
+				
+				that.setLabelNumber();
+				if(isFirstAddGoods){
+					carts.push(that.storeData)
+				}
+				if(that.goodsTotalNumber == 0){
+					that.hideShoppingCar();
+				}
+				//购物车商品数据缓存至本地
+				uni.setStorageSync(that.shoppingCartStorageName,carts);
+			},
+		}
+	}
+</script>
+<style lang="scss">
+	//主题颜色
+	$hx-theme-color: #FFC107;
+	$hx-theme-color-light: #FFEB3B;
+	page{
+		background-color: #e1e1e1;
+	}
+	.flex-row{
+		display: flex;
+		flex-direction: row;
+	}
+	.flex-column{
+		display: flex;
+		flex-direction: column;
+	}
+	.flex-wrap{
+		flex-wrap: wrap;
+	}
+	.flex1{
+		flex: 1;
+	}
+	.align-center{
+		align-items: center;
+		
+	}
+	.justify-center{
+		justify-content: center;
+	}
+	.justify-between{
+		justify-content: space-between;
+	}
+	.hx-shadow{
+		box-shadow: 0px 4px 9px rgba(173, 173, 173, 0.2);
+	}
+	.hx-bb{
+		border-bottom: 1px solid $uni-border-color;
+	}
+	.hx-txt-10{
+		font-size: 10px;
+	}
+	.hx-txt-12{
+		font-size: 12px;
+	}
+	.hx-txt-14{
+		font-size: 14px;
+	}
+	.hx-txt-16{
+		font-size: 16px;
+	}
+	.hx-txt-18{
+		font-size: 18px;
+	}
+	.hx-txt-22{
+		font-size: 22px;
+	}
+	.hx-color-gray{
+		color: #bbbbbb;
+	}
+	.hx-color-white{
+		color: #FFFFFF;
+	}
+	.hx-color-black{
+		color: #333333;
+	}
+	.hx-txt-weigth{
+		font-weight: bold;
+	}
+	.hx-mb-10{
+		margin-bottom: 10px;
+	}
+	.hx-mt-15{
+		margin-top: 15px;
+	}
+	.hx-pr15{
+		padding-right: 15px;
+	}
+	.bg{
+		background: linear-gradient(100deg, #FFEB3B, #FFC107);
+	}
+	.miniBtn{
+		position: relative;
+		padding: 0 12px;
+		border-radius: 20px;
+		height: 24px;
+		line-height: 24px;
+		text-align: center;
+		background: linear-gradient(100deg, #FFEB3B, #FFC107);
+		font-size: 10px;
+		color: #333;
+		.num{
+			position: absolute;
+			right: 0;
+			top: -10px;
+			width: 18px;
+			height: 18px;
+			line-height: 18px;
+			font-size: 10px;
+			color: #fff;
+			background-color: #ff5722;
+			text-align: center;
+			border-radius: 50%;
+			
+		}
+	}
+	.header{
+		
+		background-color: #fff;
+		&-banner{
+			width: 100%;
+			height: 142px;
+		}
+		&-bottom{
+			position: relative;
+			z-index: 1;
+			margin-top: -40px;
+			padding: 0 15px 10px;
+			.storeInfo{
+				z-index: 2;
+				background: #ffffff;
+				
+				border-radius: 6px;
+				padding: 20px 15px;
+				margin-bottom: 4px;
+				transition: all 0.2s;
+				.storeAvatar{
+					width: 50px;
+					height: 50px;
+					background: #e1e1e1;
+					border-radius: 4px;
+					
+				}
+			}
+		}
+	}
+	
+	.tabs-box{
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		width: 100%;
+		position: sticky;
+		top: calc(44px + var(--status-bar-height));
+		z-index: 10;
+		background-color: white;
+		height: 44px;
+		
+		
+		.hx-tabs{
+			position: relative;
+			display: flex;
+			height:100%;
+			width: 100%;
+			justify-content: space-evenly;
+			&-item{
+				display: flex;
+				flex: 1;
+				flex-direction: row;
+				justify-content: center;
+				align-items: center;
+				width: 70px;
+				color:#666666;
+				text{
+					font-size: 16px;
+				}
+				
+			}
+			&-active{
+				color:#333333;
+				font-weight: bold;
+			}
+			&-slider-box{
+				position: absolute;
+				display: flex;
+				justify-content: center;
+				bottom: 0;
+				width: 20%;
+			}
+			&-slider{
+				display: flex;
+				background: #f6d200;
+				width: 30px;
+				height: 3px;
+				border-radius: 20px;
+			}
+		}
+	}
+	
+	.foot{
+		position: fixed;
+		display: flex;
+		z-index: 20;
+		justify-content:center;
+		align-items : center; 
+		bottom: 0;
+		height: 100%;
+		width: 100%;
+		.btn-box{
+			position:absolute;
+			display: flex;
+			bottom: 15px;
+			justify-content:center;
+			align-items : center; 
+			margin:0;
+			height: 50px;
+			width: calc(100% - 32px);
+			z-index: 9;
+			&-left{
+				background: #222222;
+				border-top-left-radius:50px;
+				border-top-right-radius:9px;
+				border-bottom-left-radius:50px;
+				border-bottom-right-radius:9px;
+				padding-left: 6upx;
+				display: flex;
+				flex-direction:column;
+				justify-content:center;
+				align-self: center;
+				width: 70px;
+				height: 100%;
+				color: #f6d200;
+				text-align: center;
+				.imgBox{
+					display: flex;
+					text-align: center;
+					justify-content:center;
+					image{
+						width: 20px;
+						height: 20px;
+					}
+				}
+				text{
+					font-size: 20upx;
+				}
+			}
+			&-line{
+				background: #ffffff;
+				width: 2px;
+				height: 100%;
+			}
+			&-center{
+				height: 100%;
+				flex: auto;
+				display: flex;
+				justify-content:flex-start;
+				align-self: center;
+				align-items: center;
+				background: #222222;
+				border-top-left-radius:8upx;
+				border-bottom-left-radius:8upx;
+				padding-left: 10upx;
+				.cart{
+					position: relative;
+					width: 36px;
+					height: 36px;
+					image{
+						width: 100%;
+						height: 100%;
+					}
+					.tag{
+						position: absolute;
+						right: 12upx;
+						top: 16upx;
+						height: 18px;
+						width: 18px;
+						background-color: #ff4000;
+						color: #ffffff;
+						border-radius: 50%;
+						z-index: 1;
+						font-size: 10px;
+						text-align: center;
+						line-height: 18px;
+					}
+				}
+				.priceBox{
+					flex: auto;
+				}
+				
+			}
+			&-right{
+				width: 70px;
+				height: 100%;
+				position: relative;
+				display: flex;
+				justify-content:flex-start;
+				align-self: center;
+				align-items: center;
+				
+				
+				.pscj{
+					width: 100%;
+					height: 100%;
+					border-top-right-radius:100upx;
+					border-bottom-right-radius:100upx;
+					background: #222222;
+					text-align: center;
+					display: flex;
+					justify-content:center;
+					align-self: center;
+					align-items: center;  
+				}
+				.jiesuan{
+					width: 100%;
+					height: 100%;
+					font-size: 28upx;
+					border-top-right-radius:100upx;
+					border-bottom-right-radius:100upx;
+					text-align: center;
+					display: flex;
+					justify-content:center;
+					align-self: center;
+					align-items: center;    
+					background: linear-gradient(45deg, $hx-theme-color-light, $hx-theme-color); 
+					font-weight: bold;
+					color: #222222;
+				}
+			}
+		}
+		.zz{
+			position: absolute;
+			top: 0;
+			left: 0;
+			right: 0;
+			bottom: 0;
+			background-color: rgba(0,0,0,.7);
+			z-index: 1;
+		}
+		.cart-box{
+			display: flex;
+			justify-content: flex-start;
+			flex-flow: column;
+			background: #ffffff;
+			position: absolute;
+			bottom: 0; 
+			z-index: 2;
+			max-height: 66%;
+			
+			padding-bottom: 62px;
+			border-top-left-radius: 16px;
+			border-top-right-radius: 16px;
+			overflow: hidden;
+			width: 100%;
+			.rebate-box{
+				height: 30px;
+				background: #FFC107;
+				color: #FF9900;
+				text-align: center;
+				line-height: 30px;
+				font-size: 14px;
+			}
+			.box-container{
+				box-sizing: border-box;
+				padding:0 16px;
+			}
+			.operating-box{
+				font-size: 12px;
+				line-height: 40px;
+				height: 40px;
+				border-bottom: 1px solid #f6f6f6;
+				color: #666666;
+				display: flex;
+				flex-direction: row;
+				&_right{
+					flex: 1;
+				}
+				&_left{
+					display: flex;
+					flex-direction: row;
+				}
+				
+			}
+			.goods-box{
+				height: 100%;
+			    overflow: hidden;
+				flex: 1;
+				display: flex;
+				.goods-list-scroll{
+					height: 100%;
+					
+					.goods-list{
+						
+						width: 100%;
+						display: flex;
+						flex-wrap: wrap;
+						
+						.box{
+							width: 100%;
+							border-bottom: 1px solid #f6f6f6;
+							box-sizing: border-box;
+							padding: 0 16px;
+							.m-store-item{
+								display: flex;
+								flex-direction: row;
+								width: 100%;
+								justify-content: space-between;
+								align-items: flex-end;
+								padding-top: 15px;
+								padding-bottom: 15px;
+								.m-img{
+									flex: 0 0 85px;
+									height: 85px;
+									background: #eee;
+									border-radius: 4px;
+								}
+								.m-text{
+									flex: 1;
+									position: relative;
+									height: 85px;
+									padding: 0 6px;
+									display: flex;
+									align-content: space-between;
+									flex-direction: column;
+									.m-title{
+										font-size: 16px;
+										color:#555555;
+										height: 21px;
+										font-weight: bold;
+									}
+									.m-descripe{
+										font-size: 12px;
+										color:#999999;
+										margin-top: 5px;
+										height: 35px;
+									}
+									.m-price-box{
+										height: 24px;
+										font-weight: bold;
+										display: flex;
+										flex-direction: row;
+										align-items: flex-end;
+										.symbol{
+											color:#ff582b;
+											font-size: 12px;
+										}
+										.m-price{
+											position: relative;
+											top: 2px;
+											font-size: 18px;
+											color:#ff582b;
+										}
+										.m-old-price{
+											margin-left: 3px;
+											display: flex;
+											flex-direction: row;
+											font-size: 10px;
+											color:#999999;
+											margin-top: 5upx;
+											text-decoration: line-through;
+											font-weight: normal;
+										}
+									}
+									.m-distance{
+										position: absolute;
+										right: 0;
+										bottom: -4px;
+										z-index: 16;
+										color:#b2b2b2;
+										font-size: 20upx;
+										text-align: right;
+										.jumpPosition{
+											position: absolute; 
+											bottom: 23px;
+											right: 0;
+											z-index: 2;
+											width: 28px;
+											height: 28px;
+										}
+									}
+									
+								}
+								
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+	
+	.main{
+		position: sticky;
+		top: calc(88px + 0px);
+		background-color: #ffffff;
+		#mainSwiper{
+			background-color: #eeeeee;
+			height: 100%;
+			width: 100%;
+			.scroll-items{
+				height: 100%;
+				// 商品列表样式
+				.category-list{
+					width: 100%;
+					background-color: #fff;
+					display: flex;
+					padding-bottom: 50px;
+					
+					.left,.right{
+						background: #fff;
+						position: absolute;
+						top:0;
+						bottom: 0upx;
+					}
+					.left{
+						width: 24%;
+						left: 0upx;
+						background-color: #f6f3f3;
+						
+						.row{
+							width: 100%;
+							height: 45px;
+							display: flex;
+							align-items: center;
+							overflow: hidden;
+							position: relative;
+							.text{
+								width: 100%;
+								font-size: 14px;
+								color:#999999;
+								overflow: hidden;
+								text-overflow: ellipsis;
+								display: -webkit-box;
+								-webkit-box-orient: vertical;
+								-webkit-line-clamp: 2;
+								text-align: center;
+								padding: 0 16px;
+							}
+							&-number{
+								position: absolute;
+								width: 18px;
+								height: 18px;
+								right: 4px;
+								top: 4px;
+								background: #ff5722;
+								border-radius: 50%;
+								line-height: 18px;
+								text-align: center;
+								font-size: 10px;
+								color: #ffffff;
+							}
+							&.active{
+								height: 45px;
+								background-color: #fff;
+								position: sticky;
+								z-index: 1;
+								top: 0;
+								.text{
+									font-size: 14px;
+									
+								}
+							}
+						}
+						.row:last-child{
+							margin-bottom: 200upx;
+						}
+					}
+					.right{
+					   width: 76%;
+						left: 24%;
+						.goodsListBox{
+							padding-bottom: 100px;
+							.category{
+				// 				width: 94%;
+								padding: 0 15px 10px 15px;
+								.s-item{
+									height: 45px;
+									line-height: 45px;
+									font-size: 16px;
+									background: #ffffff;
+									color: #555555;
+									position: sticky;
+									top: 0;
+									z-index: 18;
+								}
+								.list:last-child{
+									margin-bottom: 0;
+								}
+								.list{
+									margin-bottom: 20px;
+									width: 100%;
+									display: flex;
+									flex-wrap: wrap;
+									.box:first-child{
+										.m-store-item{
+											margin-top: 0;
+										}
+									}
+									.box{
+										width: 100%;
+										
+										.m-store-item{
+											display: flex;
+											flex-direction: row;
+											width: 100%;
+											justify-content: space-between;
+											align-items: flex-end;
+											margin-top: 15px;
+											margin-bottom: 15px;
+											.m-img{
+												flex: 0 0 85px;
+												height: 85px;
+												background: #eee;
+												border-radius: 4px;
+											}
+											.m-text{
+												flex: 1;
+												position: relative;
+												height: 85px;
+												padding: 0 6px;
+												display: flex;
+												align-content: space-between;
+												flex-direction: column;
+												.m-title{
+													font-size: 16px;
+													color:#555555;
+													height: 21px;
+													font-weight: bold;
+												}
+												.m-descripe{
+													font-size: 12px;
+													color:#999999;
+													margin-top: 5px;
+													height: 35px;
+												}
+												.m-price-box{
+													height: 24px;
+													font-weight: bold;
+													display: flex;
+													flex-direction: row;
+													align-items: flex-end;
+													.symbol{
+														color:#ff582b;
+														font-size: 12px;
+													}
+													.m-price{
+														position: relative;
+														top: 2px;
+														font-size: 18px;
+														color:#ff582b;
+													}
+													.m-old-price{
+														margin-left: 3px;
+														display: flex;
+														flex-direction: row;
+														font-size: 10px;
+														color:#999999;
+														margin-top: 5upx;
+														text-decoration: line-through;
+														font-weight: normal;
+													}
+												}
+												.m-distance{
+													position: absolute;
+													right: 0;
+													bottom: -4px;
+													z-index: 16;
+													color:#b2b2b2;
+													font-size: 20upx;
+													text-align: right;
+													.jumpPosition{
+														position: absolute; 
+														bottom: 23px;
+														right: 0;
+														z-index: 2;
+														width: 28px;
+														height: 28px;
+													}
+												}
+												
+											}
+											
+										}
+									}
+								}
+							}
+						}
+					}
+				}
+				.evaluate-box{
+					padding-bottom: 80px;
+				}
+				.business-box{
+					
+					.info-list{
+						background: #ffffff;
+						padding: 0 15px;
+						&-container{
+							line-height: 46px;
+							height: 46px;
+							display: flex;
+							flex-direction: row;
+							[class*="hxicon-"]{
+								color: #a2a2a2;
+								margin-right: 8px;
+							}
+							text{
+								font-size: 14px;
+							}
+							.right{
+								
+								float: right;
+								color: #dddddd;
+								display: flex;
+								flex-direction: row;
+								align-items:center;
+								[class*="hxicon-"]{
+									color: #dddddd;
+									margin-right: 0;
+									font-size: 16px;
+								}
+							}
+						}
+						
+					}
+				}
+			}
+		
+		}
+		
+	}
+	.form-main{
+		
+		display: flex;
+		flex-direction: column;
+		justify-content: left;
+		padding: 15px;
+		
+		.form-main_ctn{
+			display: flex;
+			flex-direction: column;
+			justify-content: left;
+			padding: 23px 22px 22px 22px;
+			background-color: #fff;
+			border-radius: 8px;
+			.godos_tit{
+				margin-top: 4px;
+				margin-bottom: 6px;
+				font-size: 18px;
+				font-weight: bold;
+				color: #333; 
+			}
+			.gg_tit{
+				margin-top: 8px;
+				font-size: 14px;
+				font-weight: bold;
+				color: #555;
+			}
+			.gg_box{
+				margin-top: 8px;
+				display: flex;
+				flex-direction: row;
+				flex-wrap: wrap;
+				font-size: 12;
+				color: #333;
+				.item{
+					margin-right: 14px;
+					margin-bottom: 14px;
+					border: 1px solid #f1f1f1;
+					border-radius: 4px;
+					padding: 4px 6px;
+				}
+				.item.active{
+					border-color: #ffe081;
+					background-color: #fff0b7;
+				}
+				
+			}
+			.select_gg{
+				margin: 26px -12px 0;
+				padding: 6px 12px;
+				color: #999;
+				background-color: #f9f9f9;
+				display: flex;
+				flex-direction: row;
+				.lable{
+					
+				}
+				.select_gg_box{
+					flex: 1;
+					display: flex;
+					flex-direction: row;
+					flex-wrap: wrap;
+					.gg-item{
+						color: #333;
+						.gg-item-cut{
+							margin-left: 3px;
+							margin-right: 3px;
+						}
+					}
+					.gg-item:last-child{
+						.gg-item-cut{
+							display: none;
+						}
+					}
+				}
+				
+			}
+			.bottom{
+				position: relative;
+				display: flex;
+				flex-direction: row;
+				margin-top: 12px;
+				.price_box{
+					flex: 1;
+					lign-items: baseline;
+					color: #ff582b;
+					font-size: 14px;
+					position: relative;
+					top: 4px;
+					.price{
+						font-size:  24px;
+					}
+				}
+				.jumpPosition{
+					position: absolute;
+					right: 16px;
+					top: 2px;
+				}
+				.form-btn-box{
+					height: 30px;
+					line-height: 30px;
+					.add-btn{
+						border-radius: 50px;
+						background-color: #ffce3c; 
+						padding: 0 12px;
+						display: flex;
+						height: 30px;
+						line-height: 30px;
+						align-items: center;
+						i{
+							font-weight: bold;
+							font-size: 18px;
+							margin-right: 3px;
+							margin-left: -4px;
+						}
+						text{
+							
+							font-size: 14px;
+							font-weight: bold;
+							color: #363636;
+						}
+					}
+				}
+			}
+			
+		}
+		
+		.close{
+			position: absolute;
+			left: 50%;
+			margin-left: -20px;
+			bottom: -70px;
+			border-radius: 50%;
+			height: 40px;
+			width: 40px;
+			background-color: #fff;
+			opacity: 0.7;
+			text-align: center;
+			line-height: 43px;
+			i{
+				font-weight: bold;
+				font-size: 22px;
+			}
+		}
+	}
+	
+</style>

+ 2047 - 0
HX-SHOP/pages/store/index.vue

@@ -0,0 +1,2047 @@
+<template>
+	<view class="hx-store" @touchstart="touchStart">
+		<hx-navbar 
+		    :fixed="true"
+		    :color="['#ffffff','#888888']"
+		    barPlaceholder="hidden"
+		    transparent="auto"
+			:back="false" 
+			:rightSlot="false"
+		    :background-color="[245,245,245]"
+			:pageScroll.sync="pageScroll">
+			<block slot="left">
+				<view class="" style="margin-left: 6px; font-size: 22px;" @click="navBack">
+					<i class="hxicon-back"></i>
+				</view>
+				 
+			</block>
+			<view class="ctn">
+			
+				<view class="searchCtn" :style="{'width':navSearchWidth + '%','background-color':'rgba(230,230,230,'+ navSearchBgOpacity +')'}">
+				
+					<i class="hxicon-search"></i>
+					<input confirm-type="search" class="input" type="text" placeholder="输入搜索关键词"  style="font-size: 14px;" :style="{'opacity':navSearchBgOpacity ,'color':navSearchColor}">
+				</view> 
+				<view class="leftBox" style="font-size: 22px;">
+					<i class="hxicon-favor"></i>
+					<i class="hxicon-more"></i>
+					
+				</view>
+				<view class="jrNull"></view>
+			</view>
+		</hx-navbar>
+		
+		
+	
+		<!-- 只需要绑定购物车位置即可 -->
+		<flyInCart ref="inCart" :cartBasketRect="cartBasketRect"></flyInCart>
+		<!-- 头部 -->
+		<view class="header">
+			<image class="header-bg" :src="storeData.banner" mode=""></image>
+			<view :class="showStoreBox ? 'header-bg-gray' : 'header-bg-black'"></view>
+			<view class="header-top-Placeholder" ></view>
+			<view class="container storeInfo hx-shadow" :style="{height:storeInfoBoxHeight + 'px'}">
+				<image class="storeAvatar hx-shadow" :src="storeData.avatar" mode=""></image>
+				<view class="hx-txt-18 hx-color-black hx-txt-weigth hx-mb-10 ">
+					十里桃花
+				</view>
+				<view class="hx-txt-14 hx-color-black ">
+					店家说明,本店放心吃,地方名才
+				</view>
+				<!-- <view class="">
+					后续再扩展优惠券,满减,折扣,活动等功能
+				</view> -->
+				<view class="shrink-box">
+					<i class="hxicon" :class="showStoreBox ? 'icon-fold' : 'icon-unfold'" @click="showStoreBox = !showStoreBox"></i>
+				</view>
+			</view>
+		</view>
+		
+		
+		
+		<!-- 主体 -->
+		<view class="main" :style="{height: mainHeight}" >
+			<!-- <view class="" :style="{display:showZz}" style="position: absolute;top: 0;bottom: 0;left: 0;width: 100%; background: #3F536E;z-index: 999;opacity: 0.5;">
+				遮罩
+			</view> -->
+			<view class="tabs-box" :style="{'top': 'calc(44px + ' + statusBarHeight + 'px)','background-color':'rgba(245,245,245,'+ navSearchBgOpacity +')'}">
+				<view class="" style="width: 210px; height: 100%;">
+						
+					<view class="hx-tabs">
+						<view class="hx-tabs-item" v-for="(item,i) in tabs" :key="i" :class="{'hx-tabs-active': swiperCurrent == i}" @click="swiperChange(i)" :style="{transition: transtionTime + 'ms'}">
+							<text>{{item.name}}</text>
+						</view>
+						<view class="hx-tabs-slider-box" :style="{transition: transtionTime + 'ms',left:swiperCurrentSliderLeft + 'px'}">
+							<view class="hx-tabs-slider"></view>
+						</view>
+					</view>
+				</view>
+			</view>
+			<swiper 
+			id="mainSwiper"
+			style="height: 100%;"
+			:current="swiperCurrent" 
+			:duration="transtionTime"
+			@transition="transition"
+			@animationfinish="animationfinish">
+				<!-- 购物 -->
+				<swiper-item class="swiper-item" >
+					
+						<view class="scroll-items">
+							
+							<view class="category-list">
+								<!-- 左侧分类导航 -->
+								<scroll-view  :scroll-top="menuScrollTop" :scroll-y="goodsBoxScroll" class="left" >
+							       
+									<view v-for="item in categoryList" :key="item.id" class="row" :class="{active: item.id == menuCurrentId}" @click="showCategory(item)">
+										<view class="text">
+											{{item.name}}
+										</view>
+										<view class="row-number" v-if="item.number">
+											{{item.number}}
+										</view>
+									</view>
+							    </scroll-view>
+								<!-- 右侧子导航 -->
+								<scroll-view scroll-with-animation :scroll-y="goodsBoxScroll" class="right"  @scroll="asideScroll" :scroll-top="tabScrollTop" >
+									<view class="goodsListBox">
+										
+									
+										<view class="category" v-for="item in categoryList" :key="item.id" :id="'goodsBox'+item.id" >
+											<view class="s-item">{{item.name}}</view>
+											<view class="list"  >
+												<view class="box" v-for="(rowData,i) in goodsList" :key="rowData.id" v-if="item.id == rowData.type_id">
+													<!-- 商品列表 -->
+													<!-- <m-store-pro @touchOnGoods="touchOnGoods" :rowData="box"></m-store-pro>
+													 -->
+													<!-- 商品列表 -->
+													<view class="m-store-item">
+														<view class="m-img" @click="hrefGoodsInfo(rowData.id)">
+															<image style="width: 100%;height: 100%;" :src="rowData.img" mode="aspectFit"></image>
+														</view>
+														<view class="m-text">
+															<view class="m-title" @click="hrefGoodsInfo(rowData.id)">
+																{{rowData.name}}
+															</view>
+															
+															<view class="m-descripe">
+																
+																{{rowData.descripe}}
+																
+															</view>
+														
+															<block v-if="rowData.form">
+																<view class="m-price-box">
+																	<view class="symbol">¥</view>
+																	<view class="m-price">{{rowData.form_child[0].price}}</view>
+																	<view class="m-old-price" v-if="rowData.form_child[0].oldprice">
+																		<text>¥{{rowData.form_child[0].oldprice}}</text>
+																	</view>
+																</view>
+															</block>
+															<block v-else>
+															<view class="m-price-box">
+																<view class="symbol">¥</view>
+																<view class="m-price">{{rowData.price}}</view>
+																<view class="m-old-price" v-if="rowData.oldprice">
+																	<text>¥{{rowData.oldprice}}</text>
+																</view>
+															</view>
+															</block>
+															<view class="m-distance" >
+																
+																<block v-if="rowData.form">
+																	<view class="miniBtn" @click="showForm(rowData)">
+																		<text>选规格</text>
+																		<!-- #ifdef APP-PLUS || H5 -->
+																		<view class="num" v-if="getCartGoodsNum(rowData)">{{getCartGoodsNum(rowData)}}</view>
+																		<!-- #endif -->
+																	
+																	</view>
+																</block>
+																<block v-else>
+																	<view :class="'addEle_' + i" class="jumpPosition"></view>
+																	<hx-number-box @change="addGoodsChange" :value="rowData.number" :rowData="rowData" :clickTime="animaTime" @addChange="touchOnAddGoods('.addEle_' + i,rowData)"></hx-number-box>
+																</block>
+																<!-- <image @click="touchOnAddGoods('.addEle_' + i,rowData)" style="width:20px;height: 20px;" src="../../static/img/icon/shop_icon_buy.png" mode="aspectFit"></image>
+															 -->
+															</view>
+														</view>
+														
+													</view>
+												</view>
+											</view>
+										</view>
+									</view>
+								</scroll-view>
+							</view>		
+						</view>
+					
+				</swiper-item>
+				
+				<!-- 评价 -->
+				<swiper-item class="swiper-item" >
+					<scroll-view scroll-y style="height: 100%;width: 100%;background-color: #ffffff;" @scroll="asideScroll" :scroll-y="goodsBoxScroll" >
+						<view class="scroll-items evaluate-box" >
+							<view class="evaluate-box-header">
+								
+							</view>
+							<view class="evaluate-box-body">
+								
+							</view>
+							<hx-comment :listData="commentList"></hx-comment>
+						</view>
+					</scroll-view>
+				</swiper-item>
+				
+				<!-- 商家 -->
+				<swiper-item class="swiper-item" >
+					<view class="scroll-items business-box">
+						<view class="info-list hx-mt-15">
+							<view class="info-list-container">
+								<i class="hxicon-location"></i>
+								<text>{{ storeData.address }}</text>
+							</view>
+						</view>
+						
+						<view class="info-list hx-mt-15 ">
+							<view class="info-list-container hx-bb">
+								<i class="hxicon-time"></i>
+								<text>配送时间:{{ storeData.delivery_time }}</text>
+							</view>
+						</view>
+						<view class=" info-list">
+							<view class="info-list-container" @click="goCall(storeData.telephone)">
+								<i class="hxicon-phone"></i>
+								<text style="flex: 1;">商家电话:{{ storeData.telephone }}</text>
+								<view class="right">
+									<text>拨打</text><i class="hxicon-right"></i>
+								</view>
+							</view>
+						</view>
+						<view class="info-list hx-mt-15">
+							<view class="info-list-container" @click="showStoreBoxFunc">
+								<i class="hxicon-new" style="color:#ff3333"></i>
+								<text style="flex: 1;">商家当前热门活动</text>
+								<view class="right">
+									<text>查看</text><i class="hxicon-right"></i>
+								</view>
+							</view>
+						</view>
+					</view>
+				</swiper-item>
+			</swiper>
+		</view>
+		
+		<!-- 购物车 -->
+		<view class="foot"  @touchmove.stop.prevent="mpClear" :style="{height: footHeight}" v-if="showFoot">
+			<view class="zz" @click="hideShoppingCar"></view>
+			<view class="btn-box">
+				<view class="btn-box-left" @click="contact">
+					<view class="imgBox">
+						<image src="../../static/store/contact.png" mode=""></image>
+					</view>
+					<text>联系商家</text>
+				</view>
+				<view class="btn-box-line"></view>
+				<view class="btn-box-center" @click="showShoppingCar">
+					<view class="cart" :animation="cartAnimationData">
+						<view class="tag cartNum" v-if="goodsTotalNumber>0">{{goodsTotalNumber}}</view>
+						<image :src="goodsTotalNumber ? '/static/store/cart.png' : '/static/store/cart2.png'" mode=""></image>
+					</view>
+					<view class="priceBox">
+						<view class="hx-txt-18 hx-color-white" v-if="goodsTotalPrice>0">
+							¥{{goodsTotalPrice}}
+						</view>
+						<view class="hx-txt-10 hx-color-gray">
+							另需配送费¥{{shippingDees}}
+						</view>
+					</view>
+				</view>
+				<view class="btn-box-right">
+					<view class="jiesuan"  v-if="goodsTotalPrice>0 && goodsTotalPrice >= startingPrice" @click="jiesuan">
+						去结算
+					</view>
+					<view class="pscj hx-txt-10 hx-color-gray" v-else>
+						<text v-if="startingPrice>0">差¥{{-(goodsTotalPrice-startingPrice)}}起送</text>
+					</view>
+					
+				</view>
+			</view>
+			<view class="cart-box" :style="{display: showCar ? 'flex' : 'none'}">
+				<view class="box-container rebate-box" v-if="showDiscount">
+					<text>已享100减25</text>
+				</view>
+				<view class="box-container operating-box">
+					<view class="operating-box_right">
+						
+					</view>
+					<view class="operating-box_left clear" @click="clearShoppingCart">
+						<i class="hxicon-delete"></i>
+						<text>清空购物车</text>
+					</view>
+				</view>
+				<view class=" goods-box">
+					<view class="" style="flex: 1;">
+						<scroll-view scroll-y="true" class="goods-list-scroll" :scroll-top="carGoodsScrollTop">
+							<view class="goods-list">
+								<view class="box" v-for="(rowData,i) in shoppCart" :key="rowData.id" v-if="rowData.number>0">
+									
+									<view class="m-store-item">
+										<view class="m-img">
+											<image style="width: 100%;height: 100%;" :src="rowData.img" mode="aspectFit"></image>
+										</view>
+										<view class="m-text">
+											<view class="m-title">
+												{{rowData.name}}
+											</view>
+											<view class="m-descripe">
+												
+												{{rowData.current_form ? rowData.form.name + ":" + rowData.current_form.name : rowData.descripe}}
+											</view>
+											<view class="m-price-box" >
+												<view class="symbol">¥</view>
+												<view class="m-price">{{rowData.price}}</view>
+												<view class="m-old-price" v-if="rowData.oldprice">
+													<text>¥{{rowData.oldprice}}</text>
+												</view>
+											</view>
+											<view class="m-distance" > 
+											<view :class="'addEle2_' + rowData.id" class="jumpPosition">
+											</view>
+												<hx-number-box @change="addGoodsChange" :value="rowData.number" :rowData="rowData" :clickTime="animaTime" @addChange="touchOnAddGoods('.addEle2_' + rowData.id,rowData)"></hx-number-box>
+												
+											</view>
+										</view>
+										
+									</view>
+								</view>
+							</view>
+						</scroll-view>
+					</view>
+					
+				</view>
+			</view>
+			
+		</view>
+		 <!-- v-if="showFormBox" -->
+		
+		<!-- 多规格 -->
+		<uni-popup ref="popup" type="center" @change="popupChange">
+			<view class="form-main" v-if="currentGoodsData.name">
+				<view class="form-main_ctn" @click.stop.prevent="mpClear" >
+					<view class="godos_tit"><text>{{currentGoodsData.name}}</text></view>
+					
+					<view class="gg_tit">
+						<text>{{currentGoodsData.form.name}}</text>
+					</view>
+					<view class="gg_box">
+						<block v-for="form_child in currentGoodsData.form_child" :key="form_child.id" v-if="form_child.pid == currentGoodsData.form.id">
+							<view class="item" :class="{'active': form_child.select}" @click="selectGoodsForm(currentGoodsData,form_child)">{{form_child.name}}</view>
+						</block>
+					</view>
+					
+					<view class="select_gg">
+						<text class="lable">已选规格:</text>
+						<view class="select_gg_box">
+							<block v-for="form_child in currentGoodsData.form_child" :key="form_child.id" v-if="form_child.select == true">
+								<view class="gg-item">
+									<text>{{form_child.name}} </text>
+									<text class="gg-item-cut">,</text>
+								</view>
+							</block>
+						</view>
+					</view>
+					
+					<view class="bottom">
+						<view class="price_box">
+							<text>¥</text>
+							<block v-for="(form_child,i) in currentGoodsData.form_child" :key="i" v-if="form_child.select == true">
+								<text class="price">{{form_child.price}}</text>
+							</block>
+						</view>
+						<view class="form-btn-box">
+							<block v-if="!currentGoodsData.number">
+								<view id="ggAddBtn" class="add-btn" @click="formFirstAddGoods()">
+									<i class="hxicon-add" id="eleAdd"></i>
+									<text>加入购物车</text>
+								</view>
+							</block>
+							<block v-else>
+								<view class="addEle_gg jumpPosition"></view>
+								<hx-number-box @change="formAddGoodsChange" :value="currentGoodsData.number" :rowData="currentGoodsData" :clickTime="animaTime + 200" @addChange="touchOnAddGoods('.addEle_gg',currentGoodsData)"></hx-number-box>
+							</block>
+						</view>
+						
+					</view>
+				</view>
+				<view class="close" @click="hiddenForm()">
+					<i class="hxicon-close"></i> 
+				</view>
+			</view>
+			
+		</uni-popup>
+		
+	</view>
+</template> 
+
+<script>
+	import uniIcons from '@/components/uni-icons/uni-icons.vue';
+	import hxNavbar from '@/components/hx-navbar/hx-navbar.vue';
+	import jumpBall from '@/components/hx-jump-ball/hx-jump-ball.vue';
+	import hxNumberBox from "@/components/uni-number-box/uni-number-box.vue";
+	import hxComment from "@/components/hx-comment/hx-comment.vue";
+	//  加入购物车动画组件
+	import flyInCart from '@/components/flyInCart.vue'
+	//引入测试数据
+	import testData from "@/common/testdata.js";
+	
+	var statusBarHeight = uni.getSystemInfoSync().statusBarHeight;
+	
+	export default {
+		components: {
+			jumpBall,
+			hxNavbar,
+			uniIcons,
+			hxNumberBox,
+			hxComment,
+			flyInCart
+		},
+		data() {
+			return {
+				pageScroll:{},
+				//商家信息
+				storeData: [],
+				//商品列表
+				goodsList: [],
+				//商品分类信息列表
+				categoryList: [],
+				//评论列表
+				commentList: [],
+				
+				navSearchWidth: 3,
+				navSearchBgOpacity: 0,
+				navSearchColor: '#ffffff',
+				navHeadHeight: 44,
+				//默认禁止商品栏滚动
+				goodsBoxScroll: false,
+				statusBarHeight,
+				//动画时间
+				animaTime: 300,
+				//商家盒子高度
+				storeInfoBoxHeight: 100,
+				//展开门店信息容器
+				showStoreBox: false,
+				
+				num:1,
+				element: [],				
+				cartAnimation: {},
+				cartAnimationData: {},
+				
+				//tabs
+				tabs: [
+					{name:'购物'},
+					{name:'评价'},
+					{name:'商家'},
+				],
+				swiperCurrent: 0,
+				dx: 0,
+				swiperCurrentSliderLeft: 0,
+				transtionTime:100,
+				
+				//所有购物车
+				shoppingCartAll:[],
+				//显示购物车
+				showFoot:true,
+				
+				//配送费
+				shippingDees: 0,
+				//配送起步价
+				startingPrice:0,
+				
+				//购物车商品价格合计
+				goodsTotalPrice: 0,
+				//购物车商品数量合计
+				goodsTotalNumber: 0,
+				//当前门店购物车
+				shoppCart: [],
+				//foot 高度
+				footHeight: '0',
+				//显示购物车
+				showCar: false,
+				//购物车中商品滚动条位置
+				carGoodsScrollTop: 0,
+				//购物车缓存 Storage 名称
+				shoppingCartStorageName: 'shopping_cart',
+				
+				sizeCalcState: false,
+				tabScrollTop: 0,
+				
+				mainHeight: 0,
+				menuCurrentId:1,
+				
+				
+				//购物车显示折扣
+				showDiscount:true,
+				//手指触摸滑动
+				touchData:{},
+				//页面滚动条距离顶部的距离
+				pageScrollTop: 0,
+				
+				menuScrollTop: 0,
+				
+				//多规格当前产品
+				currentGoodsData: {},
+				//显示规格容器
+				showFormBox: false,
+				//显示规格动画
+				formAnimationData:{},
+				
+				//购物车位置数据
+				cartBasketRect:{},
+			
+				navStatus: true,
+				isBack:true,
+			}
+		},
+		async onLoad(option) {
+			const that = this
+			uni.showLoading({
+			    title: '加载中'
+			});
+			
+			
+			//模拟请求数据
+			setTimeout(()=>{
+				//商家信息
+				that.storeData = testData.storeData,
+				//商品列表
+				that.goodsList = testData.goodsData;
+				//商品分类信息列表
+				that.categoryList = testData.categoryData;
+				//评论列表
+				that.commentList = testData.commentData,
+				
+				setTimeout(()=>{
+					this.init();
+					uni.hideLoading();
+				},200)
+			},500)
+			
+		},
+		onReady() {
+			const that = this
+			let sysInfo = uni.getSystemInfoSync();
+			//屏幕高度 - 头部导航高度 - 状态栏高度 - 分页高度
+			this.mainHeight = sysInfo.screenHeight - 43 - statusBarHeight - 40  + 'px';
+			
+			let q = uni.createSelectorQuery()
+			setTimeout(function(){
+				q.select('.cart').boundingClientRect(data => {
+				 that.cartBasketRect = data
+				}).exec();
+			},100)
+			that.calcSize();
+		},
+		onBackPress(event) {
+			
+			if(this.showFormBox){
+				this.hiddenForm()
+				return true
+			}
+			if(!this.isBack){
+				this.$refs.popup.close()
+				return true
+			}
+			
+		},
+		onShow() {
+			this.init();
+		},
+		mounted() {
+			let that = this
+			
+		},
+		watch:{
+			showStoreBox(val,oldVal){
+				if(val == true){
+					
+					this.showStoreBoxFunc();
+				}else{
+					this.hiddenStoreBoxFunc();
+				}
+			}
+		},
+		
+		onPageScroll(e) {
+			let that = this
+			let top = e.scrollTop
+			that.pageScrollTop = e.scrollTop
+			that.pageScroll = e
+			
+			if(top < 120){
+				if(that.navSearchWidth >= 3){
+					if(top<3){
+						that.navSearchWidth = 3
+						that.navSearchBgOpacity = 0
+						that.navSearchColor = '#ffffff'
+					}else{
+						let n = top * (120/100)
+						if(n > 100){
+							n = 100
+						}
+						that.navSearchWidth = n
+						//that.navSearchBgOpacity =1
+						that.navSearchBgOpacity = top * (1/100)
+						that.navSearchColor = '#888888'
+					}
+				}
+			}else{
+				that.navSearchWidth = 100
+				that.navSearchBgOpacity = 1
+				that.navSearchColor = '#888888'
+			}
+			
+			let view = uni.createSelectorQuery().select(".main");
+			view.fields({
+				rect: true
+			}, data => {
+				if(data != null){
+					if(data.top <= statusBarHeight+44){
+						that.goodsBoxScroll = true
+					}else{
+						that.goodsBoxScroll = false
+					}
+				}
+				
+			}).exec();
+		},
+		methods: {
+			
+			init(){
+				let that = this;
+				//假设这是从后台获取的商品数据
+				let goods = this.goodsList;
+				//商品初始化
+				// for(let i in goods){
+				// 	goods[i].purchases = 3
+				// }
+				that.shoppCart = []
+				let carts = uni.getStorageSync(that.shoppingCartStorageName) || [];
+				console.log(carts);
+				//根据缓存数据 获取购物车中属于本商店的商品
+				for(let i in carts){
+					if(carts[i].store_id == that.storeData.store_id){
+						that.shoppCart = carts[i].shopping_cart  ? carts[i].shopping_cart : [];
+						break;
+					}
+				}
+				that.goodsTotalPrice = 0;
+				that.goodsTotalNumber = 0;
+				for(let i in that.shoppCart){
+					for(let j in goods){
+						if(goods[j].id == that.shoppCart[i].id){
+							goods[j].number = that.shoppCart[i].number
+						}
+					}
+					//计算商品总价
+					that.goodsTotalPrice += that.shoppCart[i].total
+					//商品总数量
+					that.goodsTotalNumber += that.shoppCart[i].number
+				}
+				//初始化商品列表
+				that.goodsList = goods;
+				
+				//初始化起步价和配送费
+				that.starting_price = that.storeData.starting_price;
+				that.shipping_dees = that.storeData.shipping_dees;
+				
+				that.setLabelNumber();
+			},
+			navBack(){
+				if(getCurrentPages().length>1){
+					uni.navigateBack();
+				}else{
+					// #ifdef H5
+					history.back()
+					// #endif
+					// #ifndef H5
+					uni.reLaunch({
+						url: '/pages/index/index'
+					});
+					// #endif
+				}
+			},
+			popupChange(e){
+				this.isBack = !e.show
+			},
+			//-----------------------------------------------------------------------------------
+			//显示 规格
+			showForm(goods){
+				var that = this;
+				let goodsCart = that.getStoreCart();
+			
+				if(goodsCart){
+					let currentGoods = null
+					for(let i in goodsCart){
+						if(goodsCart[i].id == goods.id){
+							currentGoods = goodsCart[i]
+							break
+						}
+					}
+					if(currentGoods){
+						let selectStatus = false
+						for (let i in goods.form_child){
+							if(goods.form_child[i].id == currentGoods.current_form.id){
+								if(!selectStatus){
+									goods.form_child[i].select = true
+									goods.number = currentGoods.number
+									selectStatus = true
+								}else{
+									goods.form_child[i].select = false
+								}
+							}else{
+								goods.form_child[i].select = false
+							}
+						}
+					}
+					
+				}
+				that.currentGoodsData = goods
+				that.$refs.popup.open()
+			},
+			//隐藏规格
+			hiddenForm(){
+				this.$refs.popup.close();
+			},
+			formFirstAddGoods(){
+				let that = this
+		
+				that.formAddGoodsChange(1,that.currentGoodsData)
+				that.touchOnAddGoods('#ggAddBtn',that.currentGoodsData)
+			},
+			//加入购物车
+			formAddGoodsChange(number,goodsData){
+				let that = this;
+				if(number >= 1){
+					for(let i in goodsData.form_child){
+						if(goodsData.form_child[i].select == true ){
+							that.currentGoodsData.current_form = goodsData.form_child[i]
+							break
+						}
+					}
+				}
+				that.addGoodsChange(number,that.currentGoodsData)
+				
+			},
+			//选择规格
+			selectGoodsForm(goods,formChild){
+				let that = this
+				let data = goods.form_child
+				let n = 0
+				for (var i in data){
+					if(data[i].id == formChild.id){
+						data[i].select = true
+					}else{
+						data[i].select = false
+					}
+				}
+				let goodsCart = that.getStoreCart();	
+				if(goodsCart){
+					for(let i in goodsCart){
+						if(goodsCart[i].id == goods.id && goodsCart[i].current_form.id == formChild.id){
+							n = goodsCart[i].number
+							break;
+						}
+					}
+				}
+				
+				goods.number = n
+				this.currentGoodsData = goods
+			},
+			
+			//获取该商品在购物车的数量
+			getCartGoodsNum(goods){
+				let cart = this.getStoreCart()
+				let n = 0
+				if(cart){
+					for(let i in cart){
+						if(cart[i].id == goods.id){
+							n += cart[i].number
+						}
+					}
+				}
+				return n
+			},
+			//-----------------------------------------------------------------------------------
+			//获取门店购物车
+			getStoreCart(){
+				const that = this
+				return that.shoppCart
+			},
+			
+			
+			//---------------------------------------------------------------------------------
+	
+			
+			swiperChange(index) {
+				this.swiperCurrent = index;
+				this.swiperCurrentSliderLeft= 70 * index;
+			},
+			transition({ detail: { dx } }) {
+				// this.$refs.tabs.setDx(dx);
+			},
+			animationfinish({detail: { current }}) {
+				/* this.$refs.tabs.setFinishCurrent(current); */
+				this.swiperCurrent = current;
+				this.current = current;
+				this.swiperChange(current);
+				this.showFoot = current == 0 && this.showStoreBox != true ? true : false;
+				
+			},
+			
+			//一级分类点击
+			showCategory(item){
+				
+				const that = this
+				that.isBoxScroll = true;
+				that.menuCurrentId = item.id;
+				setTimeout(()=>{
+					let index = that.categoryList.findIndex(sitem=>sitem.id === item.id);
+					that.tabScrollTop = that.categoryList[index].top;
+					that.isBoxScroll = false
+				},100)
+				
+			},
+			//右侧栏滚动
+			asideScroll(e){
+				const that = this;
+				const scrollTop = Math.round(e.detail.scrollTop);
+				that.calcSize()
+				const tabs = that.categoryList.filter(item=>item.top <= scrollTop).reverse();
+				
+				if(tabs.length > 0){
+					that.menuCurrentId = tabs[0].id;
+				}
+				const menuNum = that.categoryList.length
+				const cNum = tabs.length
+				// 定位在第4个分类,当分类滑动到第4格时将不再变换位置。
+				const n = 4
+				if(cNum>n){
+					that.menuScrollTop = (cNum - n) * 45
+				}else{
+					that.menuScrollTop = 0
+				}
+			},
+			//计算右侧栏每个tab的高度等信息
+			calcSize(event){
+				let h = 0;
+				// if(this.sizeCalcState){
+				// 	return false
+				// }
+				this.categoryList.forEach(item=>{
+					let view = uni.createSelectorQuery().select("#goodsBox" + item.id);
+					view.fields({
+						size: true
+					}, data => {
+						if(data != null){
+							item.top = h;
+							h += Math.round(data.height);
+							item.bottom = h;
+						}
+						
+					}).exec();
+				})
+				this.sizeCalcState = true;
+			},
+			
+			//小球跳跃动画
+			touchOnAddGoods(ele,data){
+				const that = this;
+				let q = uni.createSelectorQuery()
+				q.select(ele).boundingClientRect(res => {
+					that.$refs.inCart.addToCart(res,data.id);
+				}).exec();
+				
+			},
+			//新增商品计算价格
+			addGoodsChange(number,rowData){
+				
+				number = Number(number)
+				var that = this;
+				
+				let shoppCart = [];
+				let totalPrice = 0;
+				let totalNumber = 0;
+				let existedGoods = false;
+				//门店第一次添加商品
+				let isFirstAddGoods = true;
+				//是否为有规格的商品
+				let isFormGoods = false
+				if(rowData.current_form){
+					isFormGoods = true
+				}
+				let deleteGoods = null
+				let carts = uni.getStorageSync(that.shoppingCartStorageName) || [];
+			
+				if(carts.length != 0){
+					isFirstAddGoods = false
+					//根据缓存数据 获取购物车中属于本商店的商品
+					for(let i in carts){
+						if(carts[i].store_id == that.storeData.store_id){
+							shoppCart = carts[i].shopping_cart ? carts[i].shopping_cart : [];
+							break;
+						}
+					}
+					//检查该商品是否为第一次添加,
+					for(var i in shoppCart){
+						// if(shoppCart[i].id == rowData.id){
+						// 	// 是多规格商品
+						// 	if(isFormGoods){
+						// 		//规格相同
+						// 		if(shoppCart[i].current_form.id == rowData.current_form.id){
+						// 			//数量为0,在购物车中移除该商品
+						// 			if(number <= 0){
+						// 				deleteGoods = shoppCart[i];
+						// 				break;
+						// 			}else{
+						// 				// 直接修改商品数量,并计算出单品合计
+						// 				shoppCart[i].price = rowData.current_form.price
+						// 				shoppCart[i].oldprice = rowData.current_form.oldprice
+						// 				shoppCart[i].total = number *  rowData.current_form.price
+						// 			}
+									
+						// 		}
+						// 	}else{
+						// 		// 不是多规格商品
+						// 	}
+						// }
+						if(shoppCart[i].id == rowData.id){
+							if(isFormGoods){
+								//相同商品比较规格是否也相同
+								if(shoppCart[i].current_form.id == rowData.current_form.id){
+									existedGoods = true;
+								}
+							}else{
+								existedGoods = true;
+							}
+							if(existedGoods){
+								//在购物车中移除该商品
+								if(number <= 0){
+									deleteGoods = shoppCart[i];
+									break;
+								}
+								//非第一次添加,直接修改商品数量,并计算出单品合计
+								if(isFormGoods){
+									shoppCart[i].price = rowData.current_form.price
+									shoppCart[i].oldprice = rowData.current_form.oldprice
+									shoppCart[i].total = number *  rowData.current_form.price
+								}else{
+									shoppCart[i].price = rowData.price
+									shoppCart[i].total = number *  rowData.price
+									shoppCart[i].oldprice = rowData.oldprice
+								}
+								shoppCart[i].number = rowData.number = number
+								break;
+							}
+						}
+					}
+				}
+				//在购物车中移除该商品
+				if(deleteGoods != null){
+					if(carts){
+						//根据缓存数据 获取购物车中属于本商店的商品
+						for(let i in carts){
+							if(carts[i].store_id == that.storeData.store_id){
+								var index = shoppCart.indexOf(deleteGoods);
+							
+								if (index > -1) { 
+									shoppCart.splice(index, 1); 
+								} 
+								carts[i].shopping_cart = shoppCart
+								uni.setStorageSync(that.shoppingCartStorageName,carts);
+								break;
+							}
+						}
+						setTimeout(()=>{
+							this.init();
+						},100)
+					}else{
+						that.storeData.shopping_cart = []
+						uni.setStorageSync(that.shoppingCartStorageName,that.storeData);
+					}
+					
+					return 
+				}
+					
+				//第一次添加
+				if(!existedGoods){
+					if(rowData.form){
+						rowData.price = rowData.current_form.price
+						rowData.oldprice = rowData.current_form.oldprice
+						rowData.total = number *  rowData.current_form.price
+					}else{
+						rowData.total = number *  rowData.price
+					}
+					rowData.number = number;
+					shoppCart.push(rowData);
+				}
+				
+				//计算总商品数量和总价
+				for(var i in shoppCart){
+					//总价
+					totalPrice += shoppCart[i].total
+					totalNumber += shoppCart[i].number
+				}
+				//更改商品列表中的已购买数量
+				for(let i in that.goodsList){
+					if(that.goodsList[i].id == rowData.id){
+						that.goodsList[i] = rowData
+						break;
+					}
+				}
+				
+				that.goodsTotalPrice = totalPrice
+				that.goodsTotalNumber = totalNumber
+				
+				that.shoppCart = shoppCart; 
+				that.storeData.shopping_cart = shoppCart;
+				
+				that.setLabelNumber();
+				if(isFirstAddGoods){
+					carts.push(that.storeData)
+				}
+				if(that.goodsTotalNumber == 0){
+					that.hideShoppingCar();
+				}
+				//购物车商品数据缓存至本地
+				uni.setStorageSync(that.shoppingCartStorageName,carts);
+			},
+			
+			//计算每类商品购买的总数
+			setLabelNumber(){
+				let that = this;
+				//计算每一类购买商品的总数量
+				for(let j in that.categoryList){
+					let n = 0;
+					for(var i in that.shoppCart){
+						if(that.shoppCart[i].type_id ==  that.categoryList[j].id){
+							n += that.shoppCart[i].number;
+						}
+					}
+					that.categoryList[j].number = n;
+				}
+			},
+			
+			//去结算
+			jiesuan(){
+				
+				this.navTo("/pages/order/preview?sid=" + this.storeData.store_id)
+				
+			},
+			navTo(url){
+				let that = this;
+				if(that.navStatus){
+					that.navStatus = false
+					uni.navigateTo({
+						url: url,
+						complete:function(){
+							that.navStatus = true
+						}
+					})
+				}
+			},
+			//联系商家
+			contact(){
+				uni.showModal({
+					title:"",
+					content:"联系商家"
+				})
+			},
+			
+			showStoreBoxFunc(){
+				this.storeInfoBoxHeight = uni.getSystemInfoSync().screenHeight-136;
+				this.$set(this.$data,'showFoot',false);
+				this.showStoreBox = true;
+				uni.pageScrollTo({
+					duration:0,
+					scrollTop:0
+				})
+			},
+			hiddenStoreBoxFunc(){
+				this.storeInfoBoxHeight = 100;
+				this.showStoreBox = false;
+				if(this.swiperCurrent == 0){
+					this.$set(this.$data,'showFoot',true);
+				}
+			},
+			
+			mpClear(e) {
+				// TODO nvue 取消冒泡
+				e.stopPropagation()
+			},
+			
+			//显示购物车
+			showShoppingCar(){
+				if(this.goodsTotalNumber == 0){
+					return;
+				}
+				this.footHeight = '100%';
+				this.showCar = true;
+				this.carGoodsScrollTop = 0;
+			},
+			//隐藏购物车
+			hideShoppingCar(){
+				this.footHeight = '0';
+				this.showCar = false;
+			},
+			//清空该门店的购物车
+			clearShoppingCart(){
+				let that = this;
+				that.shoppCart = [];
+				that.storeData.shopping_cart = [];
+				for(let i in that.shoppingCartAll){
+					if(that.shoppingCartAll[i].store_id == that.storeData.store_id){
+						that.shoppingCartAll[i] = that.storeData
+					}
+				}
+				uni.setStorageSync(that.shoppingCartStorageName,that.shoppingCartAll);
+				
+				for(let i in that.goodsList){
+					that.goodsList[i].number = 0;
+				}
+				for(let i in that.categoryList){
+					that.categoryList[i].number = 0;
+				}
+				//购物车商品价格合计
+				that.goodsTotalPrice = 0;
+				//购物车商品数量合计
+				that.goodsTotalNumber = 0;
+				that.hideShoppingCar();
+			},
+			hrefGoodsInfo(id){
+				
+				this.navTo('/pages/product/product?id=' + id)
+			},
+			//拨打电话
+			goCall(phone){
+				if(!phone){
+					return;
+				}
+				uni.makePhoneCall({
+				    phoneNumber: phone //仅为示例
+				});
+			},
+			
+			touchStart(e){
+			                    
+			    this.touchData.clientX=e.changedTouches[0].clientX;
+			                 
+			    this.touchData.clientY=e.changedTouches[0].clientY;
+			},
+		}
+	}
+</script>
+
+<style lang="scss">
+	//主题颜色
+	$hx-theme-color: #FFC107;
+	$hx-theme-color-light: #FFEB3B;
+	
+	.add{
+		position: fixed;
+		right: 60upx;
+		top: 300upx;
+		z-index: 999;
+	}
+	.ctn{
+		
+		/* border: 1px solid #e3e3e3; */
+		width: 100%;
+		display: flex;
+		justify-content: flex-end;
+		overflow: hidden;
+		align-items: center;
+		.searchCtn{
+			display: flex;
+			border-radius: 80upx;
+			padding: 8upx 12upx;
+			line-height: 44upx;
+			background: #e0e0e0;
+			overflow: hidden;
+			align-items: center;
+			min-width: 22px;
+		}
+		.leftBox{
+			display: flex;
+			width: 53px;
+			justify-content: space-between;
+			flex: none;
+			margin: 0 8px;
+		}
+		.jrNull{
+			/* #ifdef MP */
+			width: 95px;
+			flex: none;
+			/* #endif */
+		}
+	}
+	
+	
+	page{
+		background: #ffffff;
+	}
+	.hx-bb{
+		border-bottom: 1px solid $uni-border-color;
+	}
+	.hx-txt-10{
+		font-size: 10px;
+	}
+	.hx-txt-12{
+		font-size: 12px;
+	}
+	.hx-txt-14{
+		font-size: 14px;
+	}
+	.hx-txt-16{
+		font-size: 16px;
+	}
+	.hx-txt-18{
+		font-size: 18px;
+	}
+	.hx-txt-22{
+		font-size: 22px;
+	}
+	.hx-color-gray{
+		color: #bbbbbb;
+	}
+	.hx-color-white{
+		color: #FFFFFF;
+	}
+	.hx-color-black{
+		color: #333333;
+	}
+	.hx-txt-weigth{
+		font-weight: bold;
+	}
+	.hx-mb-10{
+		margin-bottom: 10px;
+	}
+	.hx-mt-15{
+		margin-top: 15px;
+	}
+	.hx-shadow{
+		box-shadow: 0px 6upx 16upx rgba(173, 173, 173, 0.2);
+	}
+	.miniBtn{
+		position: relative;
+		padding: 0 12px;
+		border-radius: 20px;
+		height: 24px;
+		line-height: 24px;
+		text-align: center;
+		background: linear-gradient(100deg, #FFEB3B, #FFC107);
+		font-size: 10px;
+		color: #333;
+		.num{
+			position: absolute;
+			right: 0;
+			top: -10px;
+			width: 18px;
+			height: 18px;
+			line-height: 18px;
+			font-size: 10px;
+			color: #fff;
+			background-color: #ff5722;
+			text-align: center;
+			border-radius: 50%;
+			
+		}
+	}
+	.hx-store{
+		.header{
+			position: relative;
+			min-height: 230px;
+			&-bg{
+				position: absolute;
+				left: 0;
+				top: 0;
+				z-index: 2;
+				width: 100%;
+				height: 142px;
+			}
+			&-bg-black{
+				position: absolute;
+				left: 0;
+				top: 142px;
+				bottom: 0;
+				z-index: 1;
+				background-color: #ffffff;
+				width: 100%;
+				transition: background-color 0.2s;
+			}
+			&-bg-gray{
+				position: absolute;
+				left: 0;
+				top: 142px;
+				bottom: -16px;
+				z-index: 1;
+				background-color: #afafaf;
+				width: 100%;
+				transition: background-color 0.2s;
+			}
+			&-top-Placeholder{
+				height: 105px;
+			}
+			.storeInfo{
+				position: relative;
+				z-index: 2;
+				background: #ffffff;
+				height: 100px;
+				border-radius: 6px;
+				padding: 12px;
+				margin-bottom: 4px;
+				transition: all 0.2s;
+				.shrink-box{
+					position: absolute;
+					bottom: 0;
+					left: 0;
+					right: 0;
+					text-align: center;
+					font-size: 20px;
+					color: #a2a8ab;
+				}
+				.storeAvatar{
+					position: absolute;
+					width: 50px;
+					height: 50px;
+					right: 16px;
+					top: -25px;
+					background: #ffffff;
+					border-radius: 4px;
+					
+				}
+			}
+		}
+		.container{
+			margin: 0 32upx;
+		}
+		.tabs-box{
+			width: 100%;
+			position: sticky;
+			top: calc(44px + var(--status-bar-height));
+			z-index: 10;
+			background-color: white;
+			border-bottom: 1px solid #efefef;
+			height: 40px;
+			
+			.hx-tabs{
+				position: relative;
+				display: flex;
+				height:100%;
+				&-item{
+					display: flex;
+					flex-direction: row;
+					justify-content: center;
+					align-items: center;
+					width: 70px;
+					color:#666666;
+					text{
+						font-size: 16px;
+					}
+					
+				}
+				&-active{
+					color:#333333;
+					font-weight: bold;
+				}
+				&-slider-box{
+					position: absolute;
+					display: flex;
+					justify-content: center;
+					bottom: 0;
+					width: 70px;
+				}
+				&-slider{
+					display: flex;
+					background: #f6d200;
+					width: 30px;
+					height: 3px;
+				}
+			}
+		}
+		.main{
+			position: relative;
+			background-color: #ffffff;
+			
+			#mainSwiper{
+				background-color: #eeeeee;
+				position: sticky;
+				top: calc(40px + 44px + var(--status-bar-height));
+				.scroll-items{
+					// 商品列表样式
+					.category-list{
+						width: 100%;
+						background-color: #fff;
+						display: flex;
+						padding-bottom: 50px;
+						
+						.left,.right{
+							background: #fff;
+							position: absolute;
+							top:0;
+							bottom: 0upx;
+						}
+						.left{
+							width: 24%;
+							left: 0upx;
+							background-color: #f6f3f3;
+							
+							.row{
+								width: 100%;
+								height: 45px;
+								display: flex;
+								align-items: center;
+								overflow: hidden;
+								position: relative;
+								.text{
+									width: 100%;
+									font-size: 14px;
+									color:#999999;
+									overflow: hidden;
+									text-overflow: ellipsis;
+									display: -webkit-box;
+									-webkit-box-orient: vertical;
+									-webkit-line-clamp: 2;
+									text-align: center;
+									padding: 0 16px;
+								}
+								&-number{
+									position: absolute;
+									width: 18px;
+									height: 18px;
+									right: 4px;
+									top: 4px;
+									background: #ff5722;
+									border-radius: 50%;
+									line-height: 18px;
+									text-align: center;
+									font-size: 10px;
+									color: #ffffff;
+								}
+								&.active{
+									height: 45px;
+									background-color: #fff;
+									.text{
+										font-size: 14px;
+										
+									}
+								}
+							}
+							.row:last-child{
+								margin-bottom: 200upx;
+							}
+						}
+						.right{
+						   width: 76%;
+							left: 24%;
+							.goodsListBox{
+								padding-bottom: 100px;
+								.category{
+					// 				width: 94%;
+									padding: 0 15px 10px 15px;
+									.s-item{
+										height: 45px;
+										line-height: 45px;
+										font-size: 16px;
+										background: #ffffff;
+										color: #555555;
+										position: sticky;
+										top: 0;
+										z-index: 18;
+									}
+									.list:last-child{
+										margin-bottom: 0;
+									}
+									.list{
+										margin-bottom: 20px;
+										width: 100%;
+										display: flex;
+										flex-wrap: wrap;
+										.box:first-child{
+											.m-store-item{
+												margin-top: 0;
+											}
+										}
+										.box{
+											width: 100%;
+											
+											.m-store-item{
+												display: flex;
+												flex-direction: row;
+												width: 100%;
+												justify-content: space-between;
+												align-items: flex-end;
+												margin-top: 15px;
+												margin-bottom: 15px;
+												.m-img{
+													flex: 0 0 85px;
+													height: 85px;
+													background: #eee;
+													border-radius: 4px;
+												}
+												.m-text{
+													flex: 1;
+													position: relative;
+													height: 85px;
+													padding: 0 6px;
+													display: flex;
+													align-content: space-between;
+													flex-direction: column;
+													.m-title{
+														font-size: 16px;
+														color:#555555;
+														height: 21px;
+														font-weight: bold;
+													}
+													.m-descripe{
+														font-size: 12px;
+														color:#999999;
+														margin-top: 5px;
+														height: 35px;
+													}
+													.m-price-box{
+														height: 24px;
+														font-weight: bold;
+														display: flex;
+														flex-direction: row;
+														align-items: flex-end;
+														.symbol{
+															color:#ff582b;
+															font-size: 12px;
+														}
+														.m-price{
+															position: relative;
+															top: 2px;
+															font-size: 18px;
+															color:#ff582b;
+														}
+														.m-old-price{
+															margin-left: 3px;
+															display: flex;
+															flex-direction: row;
+															font-size: 10px;
+															color:#999999;
+															margin-top: 5upx;
+															text-decoration: line-through;
+															font-weight: normal;
+														}
+													}
+													.m-distance{
+														position: absolute;
+														right: 0;
+														bottom: -4px;
+														z-index: 16;
+														color:#b2b2b2;
+														font-size: 20upx;
+														text-align: right;
+														.jumpPosition{
+															position: absolute; 
+															bottom: 23px;
+															right: 0;
+															z-index: 2;
+															width: 28px;
+															height: 28px;
+														}
+													}
+													
+												}
+												
+											}
+										}
+									}
+								}
+							}
+						}
+					}
+				}
+				.evaluate-box{
+					
+				}
+				.business-box{
+					
+					.info-list{
+						background: #ffffff;
+						padding: 0 15px;
+						&-container{
+							line-height: 46px;
+							height: 46px;
+							display: flex;
+							flex-direction: row;
+							[class*="hxicon-"]{
+								color: #a2a2a2;
+								margin-right: 8px;
+							}
+							text{
+								font-size: 14px;
+							}
+							.right{
+								
+								float: right;
+								color: #dddddd;
+								display: flex;
+								flex-direction: row;
+								align-items:center;
+								[class*="hxicon-"]{
+									color: #dddddd;
+									margin-right: 0;
+									font-size: 16px;
+								}
+							}
+						}
+						
+					}
+				}
+			}
+			
+		}
+		.foot{
+			position: fixed;
+			display: flex;
+			z-index: 999;
+			
+			justify-content:center;
+			align-items : center; 
+			bottom: 0;
+			height: 100%;
+			width: 100%;
+			
+			/*width: calc(100% - 32px);*/
+			.btn-box{
+				position:absolute;
+				display: flex;
+				bottom: 15px;
+				justify-content:center;
+				align-items : center; 
+				margin:0;
+				height: 50px;
+				width: calc(100% - 32px);
+				z-index: 9;
+				&-left{
+					background: #222222;
+					border-top-left-radius:50px;
+					border-top-right-radius:9px;
+					border-bottom-left-radius:50px;
+					border-bottom-right-radius:9px;
+					padding-left: 6upx;
+					display: flex;
+					flex-direction:column;
+					justify-content:center;
+					align-self: center;
+					width: 70px;
+					height: 100%;
+					color: #f6d200;
+					text-align: center;
+					.imgBox{
+						display: flex;
+						text-align: center;
+						justify-content:center;
+						image{
+							width: 20px;
+							height: 20px;
+						}
+					}
+					text{
+						font-size: 20upx;
+					}
+				}
+				&-line{
+					background: #ffffff;
+					width: 2px;
+					height: 100%;
+				}
+				&-center{
+					height: 100%;
+					flex: auto;
+					display: flex;
+					justify-content:flex-start;
+					align-self: center;
+					align-items: center;
+					background: #222222;
+					border-top-left-radius:8upx;
+					border-bottom-left-radius:8upx;
+					padding-left: 10upx;
+					.cart{
+						position: relative;
+						width: 36px;
+						height: 36px;
+						image{
+							width: 100%;
+							height: 100%;
+						}
+						.tag{
+							position: absolute;
+							right: 12upx;
+							top: 16upx;
+							height: 18px;
+							width: 18px;
+							background-color: #ff4000;
+							color: #ffffff;
+							border-radius: 50%;
+							z-index: 1;
+							font-size: 10px;
+							text-align: center;
+							line-height: 18px;
+						}
+					}
+					.priceBox{
+						flex: auto;
+					}
+					
+				}
+				&-right{
+					width: 70px;
+					height: 100%;
+					position: relative;
+					display: flex;
+					justify-content:flex-start;
+					align-self: center;
+					align-items: center;
+					
+					
+					.pscj{
+						width: 100%;
+						height: 100%;
+						border-top-right-radius:100upx;
+						border-bottom-right-radius:100upx;
+						background: #222222;
+						text-align: center;
+						display: flex;
+						justify-content:center;
+						align-self: center;
+						align-items: center;  
+					}
+					.jiesuan{
+						width: 100%;
+						height: 100%;
+						font-size: 28upx;
+						border-top-right-radius:100upx;
+						border-bottom-right-radius:100upx;
+						text-align: center;
+						display: flex;
+						justify-content:center;
+						align-self: center;
+						align-items: center;    
+						background: linear-gradient(45deg, $hx-theme-color-light, $hx-theme-color); 
+						font-weight: bold;
+						color: #222222;
+					}
+				}
+			}
+			.zz{
+				position: absolute;
+				top: 0;
+				left: 0;
+				right: 0;
+				bottom: 0;
+				background-color: rgba(0,0,0,.7);
+				z-index: 1;
+			}
+			.cart-box{
+				display: flex;
+				justify-content: flex-start;
+				flex-flow: column;
+				background: #ffffff;
+				position: absolute;
+				bottom: 0; 
+				z-index: 2;
+				max-height: 66%;
+				
+				padding-bottom: 62px;
+				border-top-left-radius: 16px;
+				border-top-right-radius: 16px;
+				overflow: hidden;
+				width: 100%;
+				.rebate-box{
+					height: 30px;
+					background: #FFC107;
+					color: #FF9900;
+					text-align: center;
+					line-height: 30px;
+					font-size: 14px;
+				}
+				.box-container{
+					box-sizing: border-box;
+					padding:0 16px;
+				}
+				.operating-box{
+					font-size: 12px;
+					line-height: 40px;
+					height: 40px;
+					border-bottom: 1px solid #f6f6f6;
+					color: #666666;
+					display: flex;
+					flex-direction: row;
+					&_right{
+						flex: 1;
+					}
+					&_left{
+						display: flex;
+						flex-direction: row;
+					}
+					
+				}
+				.goods-box{
+					height: 100%;
+				    overflow: hidden;
+					flex: 1;
+					display: flex;
+					.goods-list-scroll{
+						height: 100%;
+						
+						.goods-list{
+							
+							width: 100%;
+							display: flex;
+							flex-wrap: wrap;
+							
+							.box{
+								width: 100%;
+								border-bottom: 1px solid #f6f6f6;
+								box-sizing: border-box;
+								padding: 0 16px;
+								.m-store-item{
+									display: flex;
+									flex-direction: row;
+									width: 100%;
+									justify-content: space-between;
+									align-items: flex-end;
+									padding-top: 15px;
+									padding-bottom: 15px;
+									.m-img{
+										flex: 0 0 85px;
+										height: 85px;
+										background: #eee;
+										border-radius: 4px;
+									}
+									.m-text{
+										flex: 1;
+										position: relative;
+										height: 85px;
+										padding: 0 6px;
+										display: flex;
+										align-content: space-between;
+										flex-direction: column;
+										.m-title{
+											font-size: 16px;
+											color:#555555;
+											height: 21px;
+											font-weight: bold;
+										}
+										.m-descripe{
+											font-size: 12px;
+											color:#999999;
+											margin-top: 5px;
+											height: 35px;
+										}
+										.m-price-box{
+											height: 24px;
+											font-weight: bold;
+											display: flex;
+											flex-direction: row;
+											align-items: flex-end;
+											.symbol{
+												color:#ff582b;
+												font-size: 12px;
+											}
+											.m-price{
+												position: relative;
+												top: 2px;
+												font-size: 18px;
+												color:#ff582b;
+											}
+											.m-old-price{
+												margin-left: 3px;
+												display: flex;
+												flex-direction: row;
+												font-size: 10px;
+												color:#999999;
+												margin-top: 5upx;
+												text-decoration: line-through;
+												font-weight: normal;
+											}
+										}
+										.m-distance{
+											position: absolute;
+											right: 0;
+											bottom: -4px;
+											z-index: 16;
+											color:#b2b2b2;
+											font-size: 20upx;
+											text-align: right;
+											.jumpPosition{
+												position: absolute; 
+												bottom: 23px;
+												right: 0;
+												z-index: 2;
+												width: 28px;
+												height: 28px;
+											}
+										}
+										
+									}
+									
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+	.form-main{
+		
+		display: flex;
+		flex-direction: column;
+		justify-content: left;
+		padding: 15px;
+		
+		.form-main_ctn{
+			display: flex;
+			flex-direction: column;
+			justify-content: left;
+			padding: 23px 22px 22px 22px;
+			background-color: #fff;
+			border-radius: 8px;
+			.godos_tit{
+				margin-top: 4px;
+				margin-bottom: 6px;
+				font-size: 18px;
+				font-weight: bold;
+				color: #333; 
+			}
+			.gg_tit{
+				margin-top: 8px;
+				font-size: 14px;
+				font-weight: bold;
+				color: #555;
+			}
+			.gg_box{
+				margin-top: 8px;
+				display: flex;
+				flex-direction: row;
+				flex-wrap: wrap;
+				font-size: 12;
+				color: #333;
+				.item{
+					margin-right: 14px;
+					margin-bottom: 14px;
+					border: 1px solid #f1f1f1;
+					border-radius: 4px;
+					padding: 4px 6px;
+				}
+				.item.active{
+					border-color: #ffe081;
+					background-color: #fff0b7;
+				}
+				
+			}
+			.select_gg{
+				margin: 26px -12px 0;
+				padding: 6px 12px;
+				color: #999;
+				background-color: #f9f9f9;
+				display: flex;
+				flex-direction: row;
+				.lable{
+					
+				}
+				.select_gg_box{
+					flex: 1;
+					display: flex;
+					flex-direction: row;
+					flex-wrap: wrap;
+					.gg-item{
+						color: #333;
+						.gg-item-cut{
+							margin-left: 3px;
+							margin-right: 3px;
+						}
+					}
+					.gg-item:last-child{
+						.gg-item-cut{
+							display: none;
+						}
+					}
+				}
+				
+			}
+			.bottom{
+				position: relative;
+				display: flex;
+				flex-direction: row;
+				margin-top: 12px;
+				.price_box{
+					flex: 1;
+					lign-items: baseline;
+					color: #ff582b;
+					font-size: 14px;
+					position: relative;
+					top: 4px;
+					.price{
+						font-size:  24px;
+					}
+				}
+				.jumpPosition{
+					position: absolute;
+					right: 16px;
+					top: 2px;
+				}
+				.form-btn-box{
+					height: 30px;
+					line-height: 30px;
+					.add-btn{
+						border-radius: 50px;
+						background-color: #ffce3c; 
+						padding: 0 12px;
+						display: flex;
+						height: 30px;
+						line-height: 30px;
+						align-items: center;
+						i{
+							font-weight: bold;
+							font-size: 18px;
+							margin-right: 3px;
+							margin-left: -4px;
+						}
+						text{
+							
+							font-size: 14px;
+							font-weight: bold;
+							color: #363636;
+						}
+					}
+				}
+			}
+			
+		}
+		
+		.close{
+			position: absolute;
+			left: 50%;
+			margin-left: -20px;
+			bottom: -70px;
+			border-radius: 50%;
+			height: 40px;
+			width: 40px;
+			background-color: #fff;
+			opacity: 0.7;
+			text-align: center;
+			line-height: 43px;
+			i{
+				font-weight: bold;
+				font-size: 22px;
+			}
+		}
+	}
+</style>

+ 404 - 0
HX-SHOP/pages/user/account_security/address_book.vue

@@ -0,0 +1,404 @@
+<template>
+	<view class="">
+		<hx-navbar leftText="查看手机通讯录" defaultBackUrl="phone" :fixed="true" >
+		</hx-navbar>
+		<view class="content">
+			<input v-if="contacts.length>0 || isSearch" class="search" type="text" placeholder="搜索联系人" @input="onSearchInput" />
+			<view v-if="contacts.length>0">
+				<scroll-view class="contact-scroll" scroll-y :scroll-into-view="scrollViewId">
+					<view class="box" v-for="(item,key) in contacts" :key="key">
+						<view class="divider" :id="item.letter">
+							<text class="divider-text">{{item.letter}}</text>
+						</view>
+						<view class="item" hover-class="hover" hover-start-time="20" v-for="(contact,index) in item.contacts" :key="index" @click='onSelectClick(contact)'>
+							<image class="portrait" src="/static/img/missing-face.png" mode="aspectFill"></image>
+							<view class="item-content">
+								<view class="text-black"><text class="">{{contact.name}}</text></view>
+								<view class="text-gray text-sm">
+									{{appName}}:{{contact.name}}
+								</view>
+							</view>
+						</view>
+					</view>
+				</scroll-view>
+				<view class="indexBar-bg">
+					<view class="indexBar" >
+						<view class="indexBar-box" @touchstart="tStart" @touchend="tEnd" @touchmove="tMove">
+							<view class="indexBar-item" v-for="(item,index) in contacts" :key="index" :id="item.letter" @touchstart="getCur"
+							 @touchend="setCur">
+								{{item.letter}}
+							</view>
+						</view>
+					</view> 
+				</view>
+				<view v-show="!hidden" class="indexToast">{{letter}}</view>
+			</view>
+			<text v-else class="no-contact">通讯录暂无联系人</text>
+		</view>
+	</view>
+	
+</template>
+
+<script>
+	import pinyin from '@/common/pinyin/pinyin3.js'
+	var platform = uni.getSystemInfoSync().platform
+
+	export default {
+		data() {
+			return {
+				/* 侧边栏选择器 */
+				scrollViewId: "wo",
+				letter: "",
+				boxTop: 0,
+				barHeight: 0,
+				minHeight: 0,
+				hidden: true,
+				/* 联系人 */
+				contacts: [],
+				contactItems: [],
+				isSearch: false,
+				isShow: false,
+				appName: ''
+			}
+		},
+		onLoad() {
+			const res = uni.getSystemInfoSync();
+			this.barHeight = res.windowHeight / 27;
+			//初始通讯录
+			this.initContacts();
+			this.appName = this.$conf.appName
+		},
+		methods: {
+			/*
+			 * 滑动的侧边选择器
+			 */
+			getCur(e) {
+				console.log("显示");
+				this.hidden = false
+				this.letter = e.target.id
+			},
+			setCur(e) {
+				console.log("隐藏");
+				this.hidden = true;
+				this.letter = e.target.id
+			},
+			tMove(e) {
+				 
+				var y = e.touches[0].clientY
+				var offsettop = this.boxTop
+				console.log(offsettop)
+				//判断选择区域,只有在选择区才会生效
+				if (y > offsettop) {
+					var num = Math.floor((y - offsettop) / this.barHeight);
+					if (num < this.contacts.length) {
+						this.letter = this.contacts[num].letter
+						this.scrollViewId = this.letter
+					}
+				}
+			},
+			tStart() {
+				this.hidden = false;
+				let that =this;
+				const query = uni.createSelectorQuery().in(this);
+				query.select('.indexBar-box').boundingClientRect(data => {
+					if (data != null) {
+						that.boxTop = data.top
+					}
+				}).exec();
+			},
+			tEnd() {
+				this.hidden = true;
+				
+			},
+			/* 
+			 * 初始化通讯录
+			 */
+			initContacts: function() {
+				//获取手机通讯录
+				plus.contacts.getAddressBook(plus.contacts.ADDRESSBOOK_PHONE, (addressbook) => {
+					// 可通过addressbook进行通讯录操作
+					addressbook.find(["displayName", "phoneNumbers"], (contacts) => {
+						var items = [];
+						for (var i = 0; i < contacts.length; i++) {
+							if (contacts[i].phoneNumbers.length > 0) {
+								var contact = {
+									'name': contacts[i].displayName,
+									'phone': contacts[i].phoneNumbers[0].value
+								};
+								items.push(contact);
+							}
+						}
+						this.contacts = pinyin.paixu(items)
+						this.contacts.sort(function(o1, o2) {
+							return o1.letter.charCodeAt(0) - o2.letter.charCodeAt(0)
+						})
+						this.contactItems = JSON.parse(JSON.stringify(this.contacts))
+					}, (e) => {
+						this.onAddressBookSetting()
+					});
+				}, (e) => {
+					this.onAddressBookSetting()
+				});
+			},
+			/*
+			 * 权限设置
+			 */
+			onAddressBookSetting: function() {
+				if (this.isShow) {
+					return
+				}
+				this.isShow = true
+				uni.showModal({
+					title: '提示',
+					content: 'APP通讯录权限没有开启,是否开启?',
+					success(res) {
+						if (res.confirm) {
+							if (platform == 'ios') {
+								var UIApplication = plus.ios.import("UIApplication");
+								var NSURL2 = plus.ios.import("NSURL");
+								var setting2 = NSURL2.URLWithString("app-settings:");
+								var application2 = UIApplication.sharedApplication();
+								application2.openURL(setting2);
+								plus.ios.deleteObject(setting2);
+								plus.ios.deleteObject(NSURL2);
+								plus.ios.deleteObject(application2);
+							} else {
+								var main = plus.android.runtimeMainActivity();
+								var bulid = plus.android.importClass("android.os.Build");
+								var Intent = plus.android.importClass('android.content.Intent');
+								if (bulid.VERSION.SDK_INT >= 9) {
+									var intent = new Intent('android.settings.APPLICATION_DETAILS_SETTINGS');
+									var Uri = plus.android.importClass('android.net.Uri');
+									var uri = Uri.fromParts("package", main.getPackageName(), null)
+									intent.setData(uri);
+									intent.putExtra('android.content.Intent.setFlags', Intent.FLAG_ACTIVITY_NEW_TASK);
+								} else if (bulid.VERSION.SDK_INT <= 8) {
+									var intent = new Intent(Intent.ACTION_VIEW);
+									intent.setClassName("com.android.settings", "com.android.settings.InstalledAppDetails");
+									intent.putExtra("com.android.settings.ApplicationPkgName", main.getPackageName());
+									intent.putExtra('android.content.Intent.setFlags', Intent.FLAG_ACTIVITY_NEW_TASK);
+								}
+								main.startActivity(intent);
+								this.isShow = false
+							}
+						} else {
+							uni.navigateBack({
+								delta: 1
+							})
+						}
+					}
+				})
+			},
+			/* 
+			 * 点击联系人
+			 */
+			onSelectClick: function(contact) {
+				uni.showActionSheet({
+					itemList: ['电话联系'],
+					success: (e) => {
+						if (e.tapIndex == 0) {
+							uni.makePhoneCall({
+								phoneNumber: contact.phone
+							});
+						}
+					}
+				})
+			},
+			/* 
+			 * 搜索
+			 */
+			onSearchInput: function(e) {
+				var searchVal = e.detail.value
+				this.isSearch = true
+				if (searchVal == '') {
+					this.contacts = JSON.parse(JSON.stringify(this.contactItems))
+					this.isSearch = false
+				} else {
+					var showList = []
+					var list = []
+					list = JSON.parse(JSON.stringify(this.contactItems))
+					list.forEach((item, index1) => {
+						var contacts = []
+						item.contacts.forEach((contact, index2) => {
+							for (var i = 0; i < searchVal.length; i++) {
+								if (contact.name.indexOf(searchVal[i]) != -1) {
+									var contain = false;
+									contacts.find(function(val) {
+										if (val.phone == contact.phone) {
+											contain = true;
+										}
+									});
+									if (!contain) {
+										contacts.push(contact);
+									}
+								}
+							}
+						})
+						if (contacts.length > 0) {
+							var contacts = {
+								letter: item.letter,
+								contacts: contacts
+							}
+							showList = showList.concat(contacts)
+						}
+					})
+					setTimeout(() => {
+						this.contacts = JSON.parse(JSON.stringify(showList))
+					}, 200)
+				}
+			}
+		}
+	}
+</script>
+
+<style>
+	page{
+		background: #ffffff;
+	}
+	.content {
+		display: flex;
+		flex-direction: column;
+		justify-content: flex-start;
+		align-items: center;
+		width: 100%;
+		height: 100%;
+	}
+
+	.search {
+		width: 80%;
+		height: 70upx;
+		display: flex;
+		flex-flow: row nowrap;
+		justify-content: center;
+		align-content: center;
+		text-align: center;
+		font-size: 30upx;
+		background-color: #f0f0f0;
+		border-radius: 15upx;
+		margin-top: 10upx;
+		margin-bottom: 10upx;
+	}
+
+	.contact-scroll {
+		display: flex;
+		flex-direction: column;
+		justify-content: flex-start;
+		align-items: center;
+		width: 100vw;
+		height: calc(100vh - 90upx - var(--status-bar-height) - 88upx);
+	}
+
+	.box {
+		display: flex;
+		flex-direction: column;
+		justify-content: flex-start;
+		align-items: center;
+		width: 100%;
+	}
+
+	.divider {
+		width: 100%;
+		background-color: #F0F0F0;
+		padding: 30upx;
+		color: #000;
+	}
+	
+	.divider-text {
+		margin-left: 20upx;
+	}
+
+	.item {
+		display: flex;
+		flex-direction: row;
+		flex-wrap: nowrap;
+		justify-content: flex-start;
+		align-items: center;
+		width: 100%;
+		/*border-bottom: 1px solid #f0f0f0;*/
+		padding: 16upx 12upx;
+		
+	}
+	.item-content{
+		
+	}
+	.portrait {
+		width: 96upx;
+		height: 96upx;
+		padding: 15upx;
+	}
+
+	.name {
+		font-size: 35upx;
+	}
+
+	.hover {
+		background-color: #e7e7e7;
+	}
+
+	.indexBar-bg {
+		height: 100vh;
+		width: 60px;
+		position: fixed;
+		right: 0;
+		top: 0;
+		z-index: 1000;
+	}
+
+	.indexBar {
+		position: absolute;
+		left: 50%;
+		top: 50%;
+		transform: translate(0, -50%);
+		display: flex;
+		align-items: center;
+		z-index: 1003;
+	}
+
+	.indexBar .indexBar-box {
+		width: 60upx;
+		height: auto;
+		background: #fff;
+		display: flex;
+		flex-direction: column;
+		box-shadow: 0 0 20upx rgba(0, 0, 0, 0.1);
+		border-radius: 10upx;
+		z-index: 1004;
+	}
+
+	.indexBar-item {
+		flex: 1;
+		width: 60upx;
+		height: 60upx;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		font-size: 24upx;
+		color: #888;
+		z-index: 1005;
+	}
+
+	.indexToast {
+		position: fixed;
+		top: 0;
+		right: 80upx;
+		bottom: 0;
+		background: rgba(0, 0, 0, 0.5);
+		width: 100upx;
+		height: 100upx;
+		border-radius: 10upx;
+		margin: auto;
+		color: #fff;
+		line-height: 100upx;
+		text-align: center;
+		font-size: 48upx;
+	}
+
+	.no-contact {
+		position: fixed;
+		width: 100%;
+		margin-top: 300upx;
+		font-size: 35upx;
+		color: #666666;
+		text-align: center;
+	}
+</style>

+ 89 - 0
HX-SHOP/pages/user/account_security/bind_phone.vue

@@ -0,0 +1,89 @@
+<template>
+    <view>
+        <hx-navbar :status-bar="true" defaultBackUrl="phone" :fixed="true" left-icon="back" left-text="验证手机号" right-text="下一步"></hx-navbar>
+        <view class=" msgBox mRL">
+        	<text class="text-gray ">
+        		验证你的手机号码,{{appName}}会向你发送一条验证短信,并且会自动完成验证,整个过程你只需要耐心等待。{{appName}}不会公开你的手机号码给其他用户。
+        	</text>
+        </view>
+		<view class="content mRL">
+			<view class="areaCodeBox ">
+				<text class="areaCode">+86</text>
+				<text class="areaText">中国大陆</text>
+			</view>
+			<view class="phoneBox">
+				<input type="text" :value="phone" placeholder="你本人手机号"/>
+			</view>
+		</view>
+    </view>
+</template>
+
+<script>
+    import {
+        mapState 
+    } from 'vuex';
+    export default {
+        data() {
+            return {
+				phone: '',
+				appName: '',
+            }
+        },
+		onLoad() {
+			this.appName = this.$conf.appName;
+		},
+		computed:{
+			...mapState(['userData'])
+		},
+        methods: {
+
+        },
+        
+    }
+</script>
+
+<style lang="scss">
+	
+   page{
+	  
+   }
+	.content{
+		display: flex;
+		flex-direction:row;
+		justify-content: center;
+		align-items: flex-end;
+		height: 116upx;
+		margin-top: 50upx;
+	}
+	.areaCodeBox{
+		width: 160upx;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		flex-direction:column;
+		border-bottom: 1px solid #e1e1e1;
+		padding: 8upx 0;
+		margin-right: 24upx;
+	}
+	.mRL{
+		margin-left: 40upx;
+		margin-right: 40upx;
+	}
+	.msgBox{
+		margin-top: 56upx;
+	}
+	.areaCode{
+		font-size: 30upx;
+		color: #333333;
+	}
+	.areaText{
+		font-size: 16upx;
+		color: #444444;
+	}
+	.phoneBox{
+		width: 100%;
+		border-bottom: 1px solid $base-color;
+		font-size: 38upx;
+		padding: 0  12upx 16upx  12upx;
+	}
+</style>

+ 52 - 0
HX-SHOP/pages/user/account_security/forget_password.vue

@@ -0,0 +1,52 @@
+<template>
+	<view>
+		<hx-navbar :status-bar="true" :fixed="true" defaultBackUrl="security" left-text="设置密码">
+			
+		</hx-navbar>
+		<view class="" style="margin-top: 200upx;">
+			
+		</view>
+		<input type="text" value="asdfaf" @blur="test" @confirm="suc"/>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				
+			}
+		},
+		onLoad() {
+			try{
+				var powered = false;
+				chrome.bluetooth.getAdapterState(function(adapter) {
+				  powered = adapter.powered;
+				});
+				
+				chrome.bluetooth.onAdapterStateChanged.addListener(
+				  function(adapter) {
+				    if (adapter.powered != powered) {
+				      powered = adapter.powered;
+				      if (powered) {
+				        console.log("Adapter radio is on");
+				      } else {
+				        console.log("Adapter radio is off");
+				      }
+				    }
+				  });
+			}catch(e){
+				//TODO handle the exception
+				console.log(e)
+			}
+			
+		},
+		methods: {
+			
+		}
+	}
+</script>
+
+<style>
+
+</style>

+ 96 - 0
HX-SHOP/pages/user/account_security/phone.vue

@@ -0,0 +1,96 @@
+<template>
+	<view>
+		<hx-navbar left-text="绑定手机号" defaultBackUrl="security"></hx-navbar>
+		
+		<view class="content margin-top" v-if="currentPhone.length">
+			
+			<view class="flex justify-center">
+				<image class="" src="/static/img/user/phone2.png" mode=""></image>
+			</view>
+			
+			<view class="margin-top">
+				<text class="text-black">
+					绑定的手机号:{{currentPhone}}
+				</text>
+			</view>
+			<!-- #ifdef APP-PLUS -->
+			<view class="margin-top">				<text class="text-gray ">
+					已启用手机通讯录匹配,点击下方按钮可查看手机通讯录中哪些朋友注册了{{appName}}
+				</text>
+			</view>
+			<button class="cu-btn lg bg-green text-white margin-top" style="width: 100%;" @click="hrefTo('address_book')">查看手机通讯录</button>
+			<!-- #endif -->
+			
+			<button class="cu-btn bg-white lg text-green margin-top" style="width: 100%;"  @click="hrefTo('update_phone')">更换手机号</button>
+			
+		</view>
+		
+		<view class="content margin-top" v-else>
+			<view class="flex justify-center">
+				<image class="" src="/static/img/user/phone.png" mode=""></image>
+			</view>
+			<view class="margin-top">
+				<text class="text-black">
+					你还没有绑定手机
+				</text>
+			</view>
+			<!-- #ifdef APP-PLUS -->
+			<view class="margin-top">				<text class="text-gray ">
+					已启用手机通讯录匹配,点击下方按钮可查看手机通讯录中哪些朋友注册了{{appName}}
+				</text>
+			</view>
+			<button class="cu-btn lg bg-yellow text-white margin-top" style="width: 100%;" @click="hrefTo('address_book')">查看手机通讯录</button>
+			<!-- #endif -->
+			<button class="cu-btn bg-yellow lg text-white margin-top" style="width: 100%;" @click="hrefTo('bind_phone')">绑定手机号</button>
+			
+			
+		</view>
+		
+	</view>
+</template>
+
+<script>
+	import {
+	    mapState 
+	} from 'vuex';
+	export default {
+		data() {
+			return {
+				appName: '',
+				currentPhone: '',
+			}
+		},
+		onLoad(){
+			let that = this;
+			that.appName = that.$conf.appName;
+			that.currentPhone = this.userData.member.mobile
+		},
+		computed:{
+			...mapState(['userData'])
+		},
+		methods: {
+			hrefTo(url){
+				if(url.length>0){
+					uni.navigateTo({
+						url: url
+					});	
+				}
+				
+			}
+		}
+	}
+</script>
+
+<style>
+	.content{
+		padding: 24upx; 
+		text-align: center;
+	}
+	.content image{
+		text-align: center;
+		width: 240upx;
+		height: 240upx;
+		margin-top: 30upx;
+		margin-bottom: 30upx;
+	}
+</style>

+ 62 - 0
HX-SHOP/pages/user/account_security/security.vue

@@ -0,0 +1,62 @@
+<template>
+	<view>
+		<hx-navbar left-text="安全设置" defaultBackUrl="/pages/user/setting/setting"></hx-navbar>
+	
+		<view class="cu-list menu sm-border margin-top">
+			
+			<navigator class="cu-item arrow " url="phone" open-type="navigate">
+				<view class="content">
+					<text class="text-black">手机号</text>
+				</view>
+				<view class="action">
+					<text class="text-grey text-sm">{{mobile}}</text>
+				</view>
+			</navigator>
+			<navigator class="cu-item arrow " url="update_password" open-type="navigate">
+				<view class="content">
+					<text class="text-black">密码设置</text>
+				</view>
+				<view class="action">
+					<text class="text-grey text-sm"></text>
+				</view>
+			</navigator>
+			
+			
+		</view>
+	</view>
+	
+</template>
+
+<script>
+	import {
+	    mapState 
+	} from 'vuex';
+	export default {
+		data() {
+			return {
+				mobile: '',
+			}
+		},
+		onReady() {
+			
+		},
+		computed:{
+			...mapState(['userData'])
+		},
+		mounted() {
+			
+			if(Object.keys(this.userData).length != 0){
+				let str =this.userData.member.mobile;
+				this.mobile = str.replace(/(\d{3})(\d{6})(\d{2})/g,'$1******$3');
+			}
+			
+		},
+		methods: {
+			
+		}
+	}
+</script>
+
+<style>
+
+</style>

+ 332 - 0
HX-SHOP/pages/user/account_security/update_password.vue

@@ -0,0 +1,332 @@
+<template>
+    <view>
+        <hx-navbar :status-bar="true" :fixed="true" defaultBackUrl="security" left-text="设置密码">
+			<view slot="right" class="navRight">
+				<button class="nextBtn" size="mini" @click="formSubmit">完成</button>
+			</view>
+		</hx-navbar>
+        
+		<view class="content mRL">
+			<view class="mt">
+				<text class="text-gray ">
+					请设置{{appName}}密码,你可以用{{appName}}绑定的账号+{{appName}}密码登录,比如使用手机号+{{appName}}密码登录{{appName}},更快捷。
+				</text>
+			</view>
+			<view class="pwsBox">
+				<view class="listItem">
+					<view class="listItem-left">
+						原密码
+					</view>
+					<view class="listItem-right" :class="[setActive1 && 'active']">
+						<input type="text" :password="true" placeholder-style="color:#b5b5b5;" value="" 
+						:v-model="oldPwd"
+						:focus="setActive1" 
+						placeholder="填写原密码"  
+						@focus="setActive1 = true" 
+						@blur="setActive1 = false"
+						@input="setOldPwd"
+						@confirm="formNext1"
+						confirm-type="next"/>
+					</view>
+				</view>
+				<view class="listItem">
+					<view class="listItem-left">
+						新密码
+					</view>
+					<view class="listItem-right" :class="[setActive2 && 'active']">
+						<input type="text" :password="true" placeholder-style="color:#b5b5b5;" 
+						value="" 
+						:focus="setActive2" 
+						placeholder="填写新密码" 
+						@focus="setActive2 = true" 
+						@blur="setActive2 = false"
+						@input="setNewPwd"
+						@confirm="formNext2"
+						confirm-type="next"/>
+					</view>
+				</view>
+				<view class="listItem">
+					<view class="listItem-left">
+						确认密码
+					</view>
+					<view class="listItem-right" :class="[setActive3 && 'active']">
+						<input type="text" :password="true" placeholder-style="color:#b5b5b5;" value=""  
+						placeholder="再次填写确认" 
+						:focus="setActive3" 
+						@focus="setActive3 = true" 
+						@blur="setActive3 = false"
+						@input="setReNewPwd"
+						@confirm="formNext3"
+						confirm-type="done"/>
+					</view>
+				</view>
+			</view>
+			<view class="margin-top caption">
+				密码必须是8-16位的数字、字母组合(不能是纯数字)
+			</view>
+			<navigator url="forget_password" class="forget">
+				忘记原密码?
+			</navigator>
+		</view>
+    </view>
+</template>
+
+<script>
+    
+    export default {
+        data() {
+            return {
+				currentPhone: '',
+				appName: this.$conf.appName,
+				
+				setActive1: true,
+				setActive2: false,
+				setActive3: false,
+				
+				oldPwd: '',
+				newPwd: '',
+				reNewPwd: '',
+				
+            }
+        },
+        methods: {
+			setOldPwd(event){
+				this.oldPwd = event.target.value;
+			},
+			setNewPwd(event){
+				this.newPwd = event.target.value;
+			},
+			setReNewPwd(event){
+				this.reNewPwd = event.target.value;
+			},
+			formNext1(value){
+				this.oldPwd = value;
+				setActive2 = true;
+			},
+			formNext2(value){
+				this.newPwd = value;
+				setActive3 = true;
+			},
+			formNext3(value){
+				this.reNewPwd = value,
+				this.formSubmit();
+			},
+			formSubmit(){
+				let that = this;
+				if(!this.oldPwd){
+					uni.showModal({
+					    title: '提示',
+					    content: '请先填写原密码',
+						confirmColor: '#3CC51F',
+						showCancel: false,
+					    success: function (res) {
+					        if (res.confirm) {
+					            that.setActive1 = true
+					        }
+					    }
+					});
+					return;
+				}
+				if(that.oldPwd.length<6){
+					uni.showToast({
+						icon: 'none',
+						position: 'bottom',
+						title: '原密码不正确!'
+					});
+					return;
+				}
+				
+				
+				
+				uni.showLoading({mask:true});
+				//验证原密码
+				that.$api.user.passwordValidation({
+					'str': that.$strEncode({
+						oldPwd: that.oldPwd
+					})
+				}).then((res) => {
+					
+					let code = res.data.code;
+					if(res.data.code != '0'){
+						uni.showToast({
+							icon: 'none',
+							position: 'bottom',
+							title: '原密码不正确!'
+						});
+						uni.hideLoading();
+						that.setActive1 = true;
+						return;
+					}else{
+						
+						if(!this.newPwd || !this.reNewPwd || this.newPwd != this.reNewPwd){
+							uni.showModal({
+							    title: '提示',
+							    content: '两次填写的密码不一致',
+								confirmColor: '#3CC51F',
+								showCancel: false,
+							    success: function (res) {
+							        if (res.confirm) {
+										if(!that.newPwd){
+											 that.setActive2 = true
+										}else{
+											 that.setActive3 = true
+										}
+							           
+							        }
+							    }
+							});
+							uni.hideLoading();
+							return;
+						}
+						var patrn=/^[0-9]{1,20}$/;
+						if (patrn.exec(this.newPwd)){
+							uni.showToast({
+								icon: 'none',
+								position: 'bottom',
+								title: '密码不能为纯数字!'
+							});
+							return;
+						}
+						if(this.newPwd.length<8){
+							uni.showToast({
+								icon: 'none',
+								position: 'bottom',
+								title: '密码长度为8-20位!'
+							});
+							return;
+						}
+						
+						//新密码不能和旧密码相同
+						if(this.newPwd == this.oldPwd){
+							uni.showModal({
+							    title: '提示',
+							    content: '新密码不能和原密码相同',
+								confirmColor: '#3CC51F',
+								showCancel: false,
+							    success: function (res) {
+							        if (res.confirm) {
+							            that.setActive1 = true
+							        }
+							    }
+							});
+							uni.hideLoading();
+							return;
+						}
+						
+						that.$api.user.updatePassword({
+							'str': that.$strEncode({
+								oldPwd: that.oldPwd,
+								newPwd: that.newPwd
+							})
+						}).then((res) => {
+							uni.hideLoading();
+							let code = res.data.code;
+							if(code != '0'){
+								uni.showToast({
+									icon: 'none',
+									position: 'bottom',
+									title: res.data.msg
+								});
+								return;
+							}
+							uni.showToast({
+							    title: '完成',
+								icon: 'success',
+							    duration: 2000,
+								success:function (res){
+									//修改成功后返回上一级
+									setTimeout(function() {
+										if(getCurrentPages().length>1){
+											uni.navigateBack();
+										}else{
+											uni.redirectTo({
+												url:'security'
+											});
+										}
+									}, 2000);
+								}
+							});
+						}).catch((err) =>{
+							uni.hideLoading();
+						})
+						
+					}
+				}).catch((err)=>{
+					uni.hideLoading();
+				});
+				
+				
+			},
+        },
+        
+    }
+</script>
+
+<style lang="scss">
+	.navRight{
+		height: 100%;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		margin-right: 10upx;
+	}
+	.content{
+		margin-left: 40upx;
+		margin-right: 40upx;
+	}
+	.mt{
+		margin-top: 56upx;
+	}
+	.pwsBox{
+		display: flex;
+		flex-direction:column;
+		justify-content: center;
+		margin-top: 40upx;
+	}
+	.listItem{
+		display: flex;
+		flex-direction:row;
+		justify-content: center;
+		align-items: flex-end;
+		height: 90upx;
+		
+	}
+	.listItem-left{
+		
+		margin-right: 20upx;
+		width: 74px;
+		padding-bottom: 14upx;
+		padding-top: 12upx;
+		font-size: 34upx;
+		height: 72upx;
+	}
+	.listItem-right{
+		border-bottom: 1upx solid #d6d6d6;
+		padding: 12upx;
+		font-size: 34upx;
+		flex: 1;
+		height: 72upx;
+	}
+	.listItem-right.active{
+		border-bottom-color: $base-color;
+	}
+	.forget{
+		color: #0077AA;
+		font-size: 26upx;
+		display: inline;
+		
+	}
+	.caption{
+		font-size: 26upx;
+		color: #666666;
+		margin-bottom: 8upx;
+	}
+	.nextBtn{
+		background:  $base-color;
+		color: #ffffff;
+		border-color:  $base-color;
+	}
+	.nextBtn:after{
+		border-color:  $base-color;
+	}
+</style>

+ 125 - 0
HX-SHOP/pages/user/account_security/update_phone.vue

@@ -0,0 +1,125 @@
+
+
+<template>
+    <view>
+        <hx-navbar :status-bar="true" defaultBackUrl="phone" :fixed="true" left-icon="back" left-text="验证手机号" @click-right="next" right-text="下一步"></hx-navbar>
+        <view class=" msgBox mRL">
+        	<text class="text-gray ">
+        		更换手机号后,下次登录可使用新手机号登录。当前手机号:{{mobile}}
+        	</text>
+        </view>
+		<view class="content mRL">
+			<view class="areaCodeBox ">
+				<text class="areaCode">+86</text>
+				<text class="areaText">中国大陆</text>
+			</view>
+			<view class="phoneBox">
+				<input type="number" placeholder="你本人手机号" maxlength="11" @blur="inputBlur" @confirm="submit"/>
+			</view>
+		</view>
+    </view>
+</template>
+
+<script>
+    import {
+        mapState 
+    } from 'vuex';
+    export default {
+        data() {
+            return {
+				mobile: '',
+				newMobile: '',
+				appName: '',
+				
+			
+            }
+        },
+		onLoad() {
+			this.appName = this.$conf.appName;
+			this.mobile = this.userData.member.mobile;
+		},
+		
+		computed: { 
+			...mapState(['hasLogin','userData'])
+		},
+        methods: {
+			submit(even){
+				this.newMobile = even.detail.value;
+				this.next();
+			},
+			inputBlur(even){
+				this.newMobile = even.detail.value;
+			},
+			next(){
+				let that = this;
+				let reg =/^1[3-9]\d{9}$/; 
+				if(!reg.exec(that.newMobile)){
+					uni.showToast({
+						icon:'none',
+						title: '手机号格式不正确!',
+						duration: 2000
+					})
+					return;
+				}
+				if(that.newMobile ==  that.mobile){
+					uni.showToast({
+						icon:'none',
+						title: '不能重复绑定该手机号!',
+						duration: 2000
+					})
+					return;
+				}
+				uni.navigateTo({
+					url: 'verification_phone?mobile=' + that.newMobile
+				});
+			}
+        },
+        
+    }
+</script>
+
+<style>
+	
+   page{
+	  
+   }
+	.content{
+		display: flex;
+		flex-direction:row;
+		justify-content: center;
+		align-items: flex-end;
+		height: 116upx;
+		margin-top: 50upx;
+	}
+	.areaCodeBox{
+		width: 160upx;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		flex-direction:column;
+		border-bottom: 1px solid #e1e1e1;
+		padding: 8upx 0;
+		margin-right: 24upx;
+	}
+	.mRL{
+		margin-left: 40upx;
+		margin-right: 40upx;
+	}
+	.msgBox{
+		margin-top: 56upx;
+	}
+	.areaCode{
+		font-size: 30upx;
+		color: #333333;
+	}
+	.areaText{
+		font-size: 16upx;
+		color: #444444;
+	}
+	.phoneBox{
+		width: 100%;
+		border-bottom: 1px solid #1AAD19;
+		font-size: 38upx;
+		padding: 0  12upx 16upx  12upx;
+	}
+</style>

+ 322 - 0
HX-SHOP/pages/user/account_security/verification_phone.vue

@@ -0,0 +1,322 @@
+<template>
+    <view class="code-box">
+		<hx-navbar left-text="" defaultBackUrl="update_phone" transparent="hidden" >
+			<view slot="right" class="navRight">
+				<button class="nextBtn" size="mini" @click="formSubmit">完成</button>
+			</view>
+		</hx-navbar>
+		<view class="mRL">
+			<view class="title">
+				输入短信验证码
+			</view>
+			<view class="content">
+				验证码已发送至{{mobile}},请在下方输入框内输入4位数字验证码。
+			</view>
+			
+			<view class="flex-box margin-top">
+			    <input
+			        type="number"
+			        focus="true"
+			        :maxlength="maxlength"
+			        class="hide-input"
+			        @input="getVal"
+			    />
+			    <block v-for="(item, index) in ranges" :key="index">
+			        <view :class="['item', { active: codeIndex === item, middle: type === 'middle', bottom: type === 'bottom', box: type === 'box' }]">
+			            <view class="line" v-if="type !== 'middle'"></view>
+			            <view v-if="type === 'middle' && codeIndex <= item" class="bottom-line"></view>
+			            <block v-if="isPwd && codeArr.length >= item">
+			                <text class="dot">.</text>
+			            </block>
+			            <block v-else>  {{ codeArr[index] ? codeArr[index] : ''}}</block>
+			        </view>
+			    </block>
+				
+			</view>
+			
+			<view class="timing-box margin-top">
+				
+				
+				<block v-if="timing>0">
+					<block v-if="postStatus"><text>正在发送短信验证...</text></block>
+					<block v-else><text>{{timing}}秒后重新发送</text></block>
+				</block>
+				<block v-else>
+					<view class="color-green" @click="resend">
+						重新发送
+					</view>
+				</block>
+				
+				
+			</view>
+			
+		</view>
+        
+    </view>
+</template>
+
+<script>
+	export default {
+		
+	    watch: {
+	        maxlength: {
+	            immediate: true,
+	            handler: function(newV) {
+	                if (newV === 6) {
+	                    this.ranges = [1, 2, 3, 4, 5, 6]
+	                } else {
+	                    this.ranges = [1, 2, 3, 4]
+	                }
+	            }
+	        }
+	    },
+	    data() {
+	        return {
+	            codeIndex: 1,
+				mobile: '',
+	            codeArr: [],
+	            ranges: [1, 2, 3, 4],
+				maxlength:4,
+				isPwd: false,
+				type: "bottom",
+				timing: 0,
+				tNumber: 90,
+				postStatus: false
+	        }
+	    },
+		onLoad(option) {
+			let reg =/^1[3-9]\d{9}$/;
+			let that = this;
+			
+			if(!reg.exec(option.mobile)){
+				uni.showToast({
+					icon:'none',
+					title: '手机号格式不正确!',
+					duration: 2000
+				})
+			}else{
+				this.mobile = option.mobile;
+				that.resend();
+			}
+			
+			
+		},
+	    methods: {
+	        getVal(e) {
+	            let { value } = e.detail
+	            let arr = value.split('')
+	            this.codeIndex = arr.length + 1
+	            this.codeArr = arr
+	            if (this.codeIndex > Number(this.maxlength)) {
+					//验证码输入完成以后的操作
+					let code =this.codeArr.join('');
+	                console.log(code);
+					this.updatePhone(code);
+	            }
+	        },
+			//验证手机号
+			updatePhone(c){
+				let that = this;
+				uni.showLoading({mask:true});
+				
+				this.$api.user.updatePhone({
+					phone: that.mobile,
+					code: c
+				}).then((res)=>{
+					uni.hideLoading();
+					if(res.data.code == '0'){
+						uni.showToast({
+						    title: '完成!',
+							icon: 'success',
+						    duration: 2000,
+							success:function(){
+								//完成后返回至安全设置
+								if(getCurrentPages() >= 3){
+									uni.navigateBack({
+									    delta: 3
+									});
+								}else{
+									uni.reLaunch({
+									    url: 'security'
+									});
+								}
+								
+							}
+						});
+					}
+				}).catch((err)=>{
+					uni.hideLoading();
+				})
+			},
+			
+			
+			//重新发送验证码
+			resend(){
+				let that = this;
+				if(!that.mobile){
+					uni.showToast({
+						icon:'none',
+						title: '手机号格式不正确!',
+						duration: 2000
+					})
+					return;
+				}
+				uni.showLoading({mask:true});
+				this.postStatus = true
+				this.$api.code.updatePhone({
+					phone: that.mobile
+				}).then((res)=>{
+					uni.hideLoading();
+					that.postStatus = false;
+					if(res.data.code != '0'){
+						uni.showToast({
+						    title: '获取验证码失败!',
+						    duration: 2000
+						});
+					}
+				}).catch((e)=>{ 
+					that.postStatus = false
+					uni.hideLoading();
+					that.timing = 0
+					console.log("catch",e);
+				})
+				that.timing = that.tNumber;
+				let t = setInterval(function(){
+					that.timing = that.timing - 1
+					if(that.timing <= 0){
+						clearTimeout(t);
+					}
+				},1000)
+			}
+		
+	    }
+	}
+</script>
+
+
+<style scoped>
+    @keyframes twinkling {
+        0% {
+            opacity: 0.2;
+        }
+        50% {
+            opacity: 0.5;
+        }
+        100% {
+            opacity: 0.2;
+        }
+    }
+	.navRight{
+		height: 100%;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		margin-right: 10upx;
+	}
+	.nextBtn{
+		background: #07c160;
+		color: #ffffff;
+		border-color: #07c160;
+	}
+	.nextBtn:after{
+		border-color: #07c160;
+	}
+	.color-green{
+		 color: #00C777;
+	}
+	.mRL{
+		margin: 30upx;
+	}
+	.margin-top{
+		margin-top: 30upx;
+	}
+	.title {
+		font-size: 50upx;
+		color: #555555;
+		margin-bottom: 24upx;
+	}
+	.content {
+		font-size: 32upx;
+		
+		color: #999999;
+	}
+	.timing-box{
+		color: #aaaaaa;
+		text-align: center;
+	}
+    .code-box {
+        text-align: left;
+    }
+    .flex-box {
+        display: flex;
+        justify-content: center;
+        flex-wrap: wrap;
+        position: relative;
+		 text-align: center;
+    }
+    .flex-box .hide-input {
+        position: absolute;
+        top: 0;
+        left: -100%;
+        width: 200%;
+        height: 100%;
+        text-align: left;
+        z-index: 9;
+        opacity: 1;
+    }
+    .flex-box .item {
+        position: relative;
+        width: 100upx;
+        height: 100upx;
+        margin-right: 18upx;
+        font-size: 70upx;
+        color: #555555;
+        line-height: 100upx;
+    }
+    .flex-box .item:last-child {
+        margin-right: 0;
+    }
+    .flex-box .middle {
+        border: none;
+    }
+    .flex-box .box {
+        box-sizing: border-box;
+        border: 2upx solid #cccccc;
+        border-radius: 6upx;
+    }
+    .flex-box .bottom {
+        box-sizing: border-box;
+        border-bottom: 4upx solid #d2d2d2;
+    }
+    .flex-box .active {
+        border-color: #00C777;
+    }
+    .flex-box .active .line {
+        display: block;
+    }
+    .flex-box .line {
+        display: none;
+        position: absolute;
+        left: 50%;
+        top: 50%;
+        transform: translate(-50%, -50%);
+        width: 2upx;
+        height: 40upx;
+        background: #333333;
+        animation: twinkling 1s infinite ease;
+    }
+    .flex-box .dot{
+        font-size: 80upx;
+        line-height: 40upx;
+    }
+    .flex-box .bottom-line {
+        height: 4px;
+        background: #000000;
+        width: 80%;
+        position: absolute;
+        border-radius: 2px;
+        top: 50%;
+        left: 50%;
+        transform: translate(-50%, -50%);
+    }
+</style>

+ 161 - 0
HX-SHOP/pages/user/address/address.vue

@@ -0,0 +1,161 @@
+<template>
+	<view class="content b-t">
+		<hx-navbar left-text="收货地址" backTabbarUrl="/pages/user/center/center" :backgroundColor="[241,241,241]"></hx-navbar>
+		<view class="bb15">
+			
+		</view>
+		<view class="list-box">
+			<view class="list b-b" v-for="(item, index) in addressList" :key="index" @click="checkAddress(item)">
+				<view class="wrapper">
+					<view class="address-box">
+						<text v-if="item.default" class="tag">默认</text>
+						<text class="address">{{item.addressName}} {{item.area}}</text>
+					</view>
+					<view class="u-box">
+						<text class="name">{{item.name}}</text>
+						<text class="mobile">{{item.mobile}}</text>
+					</view>
+				</view>
+				<text class="hxicon-edit" @click.stop="addAddress('edit', item)"></text>
+			</view>
+		</view>
+		
+		<view class="add-btn" @click="addAddress('add')">
+			<text>新增地址</text>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				source: 0,
+				addressList: [
+					{
+						name: '刘晓晓',
+						mobile: '18666666666',
+						addressName: '贵族皇仕牛排(东城店)',
+						address: '北京市东城区',
+						area: 'B区',
+						default: true
+					},{
+						name: '刘大大',
+						mobile: '18667766666',
+						addressName: '龙回1区12号楼',
+						address: '山东省济南市历城区',
+						area: '西单元302',
+						default: false,
+					}
+				]
+			}
+		},
+		onLoad(option){
+			console.log(option.source);
+			this.source = option.source;
+		},
+		methods: {
+			//选择地址
+			checkAddress(item){
+				if(this.source == 1){
+					//this.$api.prePage()获取上一页实例,在App.vue定义
+					this.$api.prePage().addressData = item;
+					uni.navigateBack()
+				}
+			},
+			addAddress(type, item){
+				uni.navigateTo({
+					url: `/pages/user/address/addressManage?type=${type}&data=${JSON.stringify(item)}`
+				})
+			},
+			//添加或修改成功之后回调
+			refreshList(data, type){
+				//添加或修改后事件,这里直接在最前面添加了一条数据,实际应用中直接刷新地址列表即可
+				this.addressList.unshift(data);
+				
+				console.log(data, type);
+			}
+		}
+	}
+</script>
+
+<style lang='scss'>
+	.bb15{
+		padding-bottom: 30upx;
+	}
+	.content{
+		position: relative;
+	}
+	.list-box{
+		display: flex;
+		flex-direction: column;
+		background-color: #fff;
+		border-radius: 10px;
+		overflow: hidden;
+		margin: 0 15px;
+	}
+	.list{
+		display: flex;
+		align-items: center;
+		padding: 14px 15px;
+		background: #fff;
+		position: relative;
+	}
+	.wrapper{
+		display: flex;
+		flex-direction: column;
+		flex: 1;
+	}
+	.address-box{
+		display: flex;
+		align-items: center;
+		.tag{
+			font-size: 24upx;
+			color: $base-color;
+			margin-right: 10upx;
+			background: #fffafb;
+			border: 1px solid #ffc107;
+			border-radius: 4upx;
+			padding: 4upx 10upx;
+			line-height: 1;
+		}
+		.address{
+			font-size: 30upx;
+			color: $font-color-dark;
+		}
+	}
+	.u-box{
+		font-size: 28upx;
+		color: $font-color-light;
+		margin-top: 16upx;
+		.name{
+			margin-right: 30upx;
+		}
+	}
+	.icon-edit{
+		display: flex;
+		align-items: center;
+		height: 80upx;
+		font-size: 40upx;
+		color: $font-color-light;
+		padding-left: 30upx;
+	}
+	
+	.add-btn{
+		position: fixed;
+		display: flex;
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+		border-radius: 10px;
+		overflow: hidden;
+		bottom: 15px;
+		left: 15px;
+		right: 15px;
+		height: 45px;
+		font-size: 16px;
+		font-weight: bold;
+		color: #333;
+		background: linear-gradient(45deg, #ffd900, #ffc107);		
+	}
+</style>

+ 174 - 0
HX-SHOP/pages/user/address/addressManage.vue

@@ -0,0 +1,174 @@
+<template>
+	<view class="content">
+		<hx-navbar title="收货地址" backTabbarUrl="/pages/user/center/center" :backgroundColor="[241,241,241]"></hx-navbar>
+		<view class="bb15">
+			
+		</view>
+		<view class="list-box">
+			<view class="row b-b">
+				<text class="tit">联系人</text>
+				<input class="input" type="text" v-model="addressData.name" placeholder="收货人姓名" placeholder-class="placeholder" />
+			</view>
+			<view class="row b-b">
+				<text class="tit">手机号</text>
+				<input class="input" type="number" v-model="addressData.mobile" placeholder="收货人手机号码" placeholder-class="placeholder" />
+			</view>
+			<view class="row b-b">
+				<text class="tit">地址</text>
+				<text @click="chooseLocation" class="input">
+					{{addressData.addressName}}
+				</text>
+				<text class="hxicon-locationfill"></text>
+			</view>
+			<view class="row b-b"> 
+				<text class="tit">门牌号</text>
+				<input class="input" type="text" v-model="addressData.area" placeholder="楼号、门牌" placeholder-class="placeholder" />
+			</view>
+			
+			<view class="row default-row">
+				<text class="tit">设为默认</text>
+				<switch :checked="addressData.defaule" color="#ffc107" @change="switchChange" />
+			</view>
+			</view>
+		<view class="add-btn" @click="confirm">
+			<text>提交</text>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				addressData: {
+					name: '',
+					mobile: '',
+					addressName: '在地图选择',
+					address: '',
+					area: '',
+					default: false
+				}
+			}
+		},
+		onLoad(option){
+			let title = '新增收货地址';
+			if(option.type==='edit'){
+				title = '编辑收货地址'
+				
+				this.addressData = JSON.parse(option.data)
+			}
+			this.manageType = option.type;
+			uni.setNavigationBarTitle({
+				title
+			})
+		},
+		methods: {
+			switchChange(e){
+				this.addressData.default = e.detail;
+			},
+			
+			//地图选择地址
+			chooseLocation(){
+				uni.chooseLocation({
+					success: (data)=> {
+						this.addressData.addressName = data.name;
+						this.addressData.address = data.name;
+					}
+				})
+			},
+			
+			//提交
+			confirm(){
+				let data = this.addressData;
+				if(!data.name){
+					this.$api.msg('请填写收货人姓名');
+					return;
+				}
+				if(!/(^1[3|4|5|7|8][0-9]{9}$)/.test(data.mobile)){
+					this.$api.msg('请输入正确的手机号码');
+					return;
+				}
+				if(!data.address){
+					this.$api.msg('请在地图选择所在位置');
+					return;
+				}
+				if(!data.area){
+					this.$api.msg('请填写门牌号信息');
+					return;
+				}
+				
+				//this.$api.prePage()获取上一页实例,可直接调用上页所有数据和方法,在App.vue定义
+				this.$api.prePage().refreshList(data, this.manageType);
+				this.$api.msg(`地址${this.manageType=='edit' ? '修改': '添加'}成功`);
+				setTimeout(()=>{
+					uni.navigateBack()
+				}, 800)
+			},
+		}
+	}
+</script>
+
+<style lang="scss">
+	.bb15{
+		background: #f1f1f1;
+		padding-top: 40upx;
+	}
+	.list-box{
+		display: flex;
+		flex-direction: column;
+		background-color: #fff;
+		border-radius: 10px;
+		overflow: hidden;
+		margin: 0 15px;
+	}
+	.row{
+		display: flex;
+		align-items: center;
+		position: relative;
+		padding:0 30upx;
+		height: 110upx;
+		background: #fff;
+		
+		.tit{
+			flex-shrink: 0;
+			width: 120upx;
+			font-size: 30upx;
+			color: $font-color-dark;
+		}
+		.input{
+			flex: 1;
+			font-size: 30upx;
+			color: $font-color-dark;
+		}
+		.icon-locationfill{
+			font-size: 36upx;
+			color: $font-color-light;
+		}
+	}
+	.default-row{
+		margin-top: 16upx;
+		.tit{
+			flex: 1;
+		}
+		switch{
+			transform: translateX(16upx) scale(.9);
+		}
+	}
+	.add-btn{
+		position: fixed;
+		display: flex;
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+		border-radius: 10px;
+		overflow: hidden;
+		bottom: 15px;
+		left: 15px;
+		right: 15px;
+		height: 45px;
+		font-size: 16px;
+		font-weight: bold;
+		color: #333;
+		background: linear-gradient(45deg, #ffd900, #ffc107);		
+	}
+</style>

+ 26 - 0
HX-SHOP/pages/user/bash/bash.vue

@@ -0,0 +1,26 @@
+<template>
+	<view>
+		<hx-navbar title="个人信息" transparent="hidden"></hx-navbar>
+		
+		<text>
+			热更新
+		</text>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				
+			}
+		},
+		methods: {
+			
+		}
+	}
+</script>
+
+<style>
+
+</style>

+ 458 - 0
HX-SHOP/pages/user/center/center.vue

@@ -0,0 +1,458 @@
+<template>
+	<view class="container">
+		<hx-navbar :status-bar="true" :back="false" barPlaceholder="hidden" :fixed="true" :title.sync="pageTitle"
+			:color="['#ffffff','#666666']" transparent="auto" :background-color="[255,255,255]"
+			@click-left="navTo(userSettingUrl)">
+			<!-- 			<view slot="left">
+				<view style="margin-left: 26upx;font-size: 22px;">
+					<i class="hxicon-settings"></i>
+				</view>
+			</view>
+			<view slot="right">
+				<view style="margin-right: 16upx;font-size: 22px;">
+					<i class="hxicon-mark"></i>
+				</view>
+			</view> -->
+		</hx-navbar>
+
+		<view class="user-section ">
+			<image class="bg" src="/static/img/user/user-bg.jpg"></image>
+			<view class="user-info-box">
+				<view class="portrait-box" @click="userBash">
+					<image class="portrait" :src="memberInfo.face || defaultFace"></image>
+				</view>
+				<view class="info-box" @click="userBash">
+					<text class="username">{{memberInfo.nickname || '登录/注册'}}</text>
+				</view>
+			</view>
+			<!-- <view class="vip-card-box">
+				<image class="card-bg" src="/static/img/user/vip-card-bg.png" mode=""></image>
+				<view class="b-btn">
+					立即开通
+				</view>
+				<view class="tit">
+					<text class="hxicon-iLinkapp-"></text>
+					DCloud会员
+				</view>
+				<text class="e-m">DCloud Union</text>
+				<text class="e-b">开通会员开发无bug 一测就上线</text>
+			</view> -->
+		</view>
+
+		<view class="cover-container" :style="[{
+				transform: coverTransform,
+				transition: coverTransition
+			}]" @touchstart="coverTouchstart" @touchmove="coverTouchmove" @touchend="coverTouchend">
+			<image class="arc" src="/static/img/user/arc.png"></image>
+
+			<!-- <view class="tj-sction">
+				<view class="tj-item">
+					<text class="num">128.8</text>
+					<text>余额</text>
+				</view>
+				<view class="tj-item" @click="navTo('/pages/user/coupon/coupon')">
+					<text class="num">0</text>
+					<text>优惠券</text>
+				</view>
+				<view class="tj-item">
+					<text class="num">20</text>
+					<text>积分</text>
+				</view>
+			</view> -->
+			<!-- 订单 -->
+			<!-- 	<view class="order-section">
+				<navigator class="order-item" url="/pages/order/order?state=1" open-type="switchTab"
+					hover-class="common-hover" :hover-stay-time="50">
+					<text class="hxicon-pay"></text>
+					<text>待付款</text>
+				</navigator>
+				<navigator class="order-item" url="/pages/order/order?state=2" open-type="switchTab"
+					hover-class="common-hover" :hover-stay-time="50">
+					<text class="hxicon-deliver"></text>
+					<text>待收货</text>
+				</navigator>
+				<navigator class="order-item" url="/pages/order/order?state=3" open-type="switchTab"
+					hover-class="common-hover" :hover-stay-time="50">
+					<text class="hxicon-comment"></text>
+					<text>待评价</text>
+				</navigator>
+				<navigator class="order-item" url="/pages/order/order?state=4" open-type="switchTab"
+					hover-class="common-hover" :hover-stay-time="50">
+					<text class="hxicon-refund"></text>
+					<text>退款/售后</text>
+				</navigator>
+				<navigator class="order-item" url="/pages/order/order?state=0" open-type="switchTab"
+					hover-class="common-hover" :hover-stay-time="50">
+					<text class="hxicon-form"></text>
+					<text>全部订单</text>
+				</navigator>
+			</view> -->
+			<!-- 浏览历史 -->
+			<view class="history-section icon">
+				<!-- <view class="sec-header">
+					<text class="hxicon-lishijilu"></text>
+					<text>浏览历史</text>
+				</view> -->
+				<!-- <scroll-view scroll-x class="h-list">
+					<image @click="navTo('/pages/product/product')" src="//imgs.1op.cn/i/hxshop/goods/8.jpg"
+						mode="aspectFill"></image>
+					<image @click="navTo('/pages/product/product')" src="//imgs.1op.cn/i/hxshop/goods/9.jpg"
+						mode="aspectFill"></image>
+					<image @click="navTo('/pages/product/product')" src="//imgs.1op.cn/i/hxshop/goods/10.jpg"></image>
+					<image @click="navTo('/pages/product/product')" src="//imgs.1op.cn/i/hxshop/goods/11.jpg"
+						mode="aspectFill"></image>
+					<image @click="navTo('/pages/product/product')" src="//imgs.1op.cn/i/hxshop/goods/12.jpg"></image>
+					<image @click="navTo('/pages/product/product')" src="//imgs.1op.cn/i/hxshop/goods/13.jpg"
+						mode="aspectFill"></image>
+				</scroll-view> -->
+				<list-cell icon="hxicon-moneybagfill" iconColor="#e07472" title="我的钱包"></list-cell>
+				<list-cell icon="hxicon-locationfill" iconColor="#5fcda2" title="地址管理"
+					@eventClick="navTo('/pages/user/address/address')"></list-cell>
+				<!-- <list-cell icon="hxicon-round_pay_fill" iconColor="#9789f7" title="分享" tips="邀请好友赢10万大礼"></list-cell> -->
+				<!-- <list-cell icon="hxicon-message_fill_light" iconColor="#ee883b" title="晒单" tips="晒单抢红包"></list-cell> -->
+				<!-- <list-cell icon="hxicon-round_favor_fill" iconColor="#54b4ef" title="我的收藏"></list-cell> -->
+				<list-cell icon="hxicon-settings" iconColor="#e07472" title="设置" border=""
+					@eventClick="navTo('/pages/user/setting/setting')"></list-cell>
+			</view>
+		</view>
+
+
+	</view>
+</template>
+<script>
+	import hxNavbar from "@/components/hx-navbar/hx-navbar.vue"
+
+	import listCell from '@/components/mix-list-cell';
+	import {
+		mapState
+	} from 'vuex';
+	let startY = 0,
+		moveY = 0,
+		pageAtTop = true;
+	export default {
+		components: {
+			listCell,
+			hxNavbar
+		},
+		data() {
+			return {
+				pageTitle: "我的",
+				coverTransform: 'translateY(0px)',
+				coverTransition: '0s',
+				moving: false,
+				defaultFace: '/static/img/user/missing-face.png',
+				userSettingUrl: '/pages/user/setting/setting',
+
+				memberInfo: {
+					face: '',
+					nickname: "",
+				}
+			}
+		},
+		onLoad() {
+
+
+		},
+		onReady() {
+
+		},
+		onShow() {
+			let member = this.userData.member;
+			if (member) {
+				this.memberInfo = {
+					face: member.facke,
+					nickname: member.nickname
+				}
+			} else {
+				this.memberInfo = {
+					face: '',
+					nickname: ''
+				}
+			}
+
+		},
+		// #ifndef MP
+		onNavigationBarButtonTap(e) {
+			const index = e.index;
+			if (index === 0) {
+				this.navTo('/pages/user/setting/setting');
+			} else if (index === 1) {
+				// #ifdef APP-PLUS
+				const pages = getCurrentPages();
+				const page = pages[pages.length - 1];
+				const currentWebview = page.$getAppWebview();
+				currentWebview.hideTitleNViewButtonRedDot({
+					index
+				});
+				// #endif
+				uni.navigateTo({
+					url: '/pages/notice/notice'
+				})
+			}
+		},
+		// #endif
+		computed: {
+			...mapState(['hasLogin', 'userData'])
+		},
+		methods: {
+			//个人信息
+			userBash() {
+				if (this.userData) {
+					this.navTo('/pages/user/bash/bash')
+
+				} else {
+					uni.navigateTo({
+						url: '/pages/user/login/login'
+					});
+				}
+			},
+
+
+			/**
+			 *  会员卡下拉和回弹
+			 *  1.关闭bounce避免ios端下拉冲突
+			 *  2.由于touchmove事件的缺陷(以前做小程序就遇到,比如20跳到40,h5反而好很多),下拉的时候会有掉帧的感觉
+			 *    transition设置0.1秒延迟,让css来过渡这段空窗期
+			 *  3.回弹效果可修改曲线值来调整效果,推荐一个好用的bezier生成工具 http://cubic-bezier.com/
+			 */
+			coverTouchstart(e) {
+				if (pageAtTop === false) {
+					return;
+				}
+				this.coverTransition = 'transform .1s linear';
+				startY = e.touches[0].clientY;
+			},
+			coverTouchmove(e) {
+				moveY = e.touches[0].clientY;
+				let moveDistance = moveY - startY;
+				if (moveDistance < 0) {
+					this.moving = false;
+					return;
+				}
+				this.moving = true;
+				if (moveDistance >= 80 && moveDistance < 100) {
+					moveDistance = 80;
+				}
+
+				if (moveDistance > 0 && moveDistance <= 80) {
+					this.coverTransform = `translateY(${moveDistance}px)`;
+				}
+			},
+			coverTouchend() {
+				if (this.moving === false) {
+					return;
+				}
+				this.moving = false;
+				this.coverTransition = 'transform 0.3s cubic-bezier(.21,1.93,.53,.64)';
+				this.coverTransform = 'translateY(0px)';
+			},
+
+
+		}
+	}
+</script>
+<style lang='scss'>
+	%flex-center {
+		display: flex;
+		flex-direction: column;
+		justify-content: center;
+		align-items: center;
+	}
+
+	%section {
+		display: flex;
+		justify-content: space-around;
+		align-content: center;
+		background: #fff;
+		border-radius: 10upx;
+	}
+
+	.user-section {
+		height: 520upx;
+		padding: 100upx 30upx 0;
+		position: relative;
+
+		.bg {
+			position: absolute;
+			left: 0;
+			top: 0;
+			width: 100%;
+			height: 100%;
+			filter: blur(1px);
+
+
+		}
+	}
+
+	.user-info-box {
+		height: 180upx;
+		display: flex;
+		align-items: center;
+		position: relative;
+		z-index: 1;
+
+		.portrait {
+			width: 128upx;
+			height: 128upx;
+			/* border:5upx solid #fff; */
+			border-radius: 50%;
+			box-shadow: 0 0px 12px #848484;
+		}
+
+		.username {
+			font-size: $font-lg + 4upx;
+			color: $font-color-dark;
+			margin-left: 20upx;
+			font-weight: bold;
+		}
+	}
+
+	.vip-card-box {
+
+		display: none;
+		flex-direction: column;
+		color: #f7d680;
+		height: 240upx;
+		background: linear-gradient(to right, rgba(0, 0, 0, .7), rgba(0, 0, 0, .8));
+		border-radius: 16upx 16upx 0 0;
+		overflow: hidden;
+		position: relative;
+		padding: 20upx 24upx;
+
+		.card-bg {
+			position: absolute;
+			top: 20upx;
+			right: 0;
+			width: 380upx;
+			height: 260upx;
+		}
+
+		.b-btn {
+			position: absolute;
+			right: 20upx;
+			top: 16upx;
+			width: 132upx;
+			height: 40upx;
+			text-align: center;
+			line-height: 40upx;
+			font-size: 22upx;
+			color: #36343c;
+			border-radius: 20px;
+			background: linear-gradient(to right, #f9e6af, #ffd465);
+			z-index: 1;
+		}
+
+		.tit {
+			font-size: $font-base+2upx;
+			color: #f7d680;
+			margin-bottom: 28upx;
+
+			[class*="hxicon-"] {
+				color: #f6e5a3;
+				margin-right: 16upx;
+			}
+		}
+
+		.e-b {
+			font-size: $font-sm;
+			color: #d8cba9;
+			margin-top: 10upx;
+		}
+	}
+
+	.cover-container {
+		background: $page-color-base;
+		margin-top: -150upx;
+		padding: 0 30upx;
+		position: relative;
+		background: #f5f5f5;
+		padding-bottom: 20upx;
+
+		.arc {
+			position: absolute;
+			left: 0;
+			top: -34upx;
+			width: 100%;
+			height: 36upx;
+		}
+	}
+
+	.tj-sction {
+		@extend %section;
+
+		.tj-item {
+			@extend %flex-center;
+			flex-direction: column;
+			height: 140upx;
+			font-size: $font-sm;
+			color: #75787d;
+		}
+
+		.num {
+			font-size: $font-lg;
+			color: $font-color-dark;
+			margin-bottom: 8upx;
+		}
+	}
+
+	.order-section {
+		@extend %section;
+		padding: 28upx 0;
+		margin-top: 20upx;
+
+		.order-item {
+			@extend %flex-center;
+			width: 120upx;
+			height: 120upx;
+			border-radius: 10upx;
+			font-size: $font-sm;
+			color: $font-color-dark;
+		}
+
+		[class*="hxicon-"] {
+			font-size: 48upx;
+			margin-bottom: 18upx;
+			color: #ffd21c;
+		}
+
+		.icon-shouhoutuikuan {
+			font-size: 44upx;
+		}
+	}
+
+	.history-section {
+		padding: 30upx 0 0;
+		margin-top: 20upx;
+		background: #fff;
+		border-radius: 10upx;
+
+		.sec-header {
+			display: flex;
+			align-items: center;
+			font-size: $font-base;
+			color: $font-color-dark;
+			line-height: 40upx;
+			margin-left: 30upx;
+
+			[class*="hxicon-"] {
+				font-size: 44upx;
+				color: #5eba8f;
+				margin-right: 16upx;
+				line-height: 40upx;
+			}
+		}
+
+		.h-list {
+			white-space: nowrap;
+			padding: 30upx 30upx 0;
+
+			image {
+				display: inline-block;
+				width: 160upx;
+				height: 160upx;
+				margin-right: 20upx;
+				border-radius: 10upx;
+			}
+		}
+	}
+</style>

+ 446 - 0
HX-SHOP/pages/user/coupon/coupon.vue

@@ -0,0 +1,446 @@
+<template>
+	<view>
+		<hx-navbar title="红包卡券" :fixed="true" :backgroundColor="[[255,235,59],[255,193,7]]"></hx-navbar>
+		<view class="head">
+			<!-- <view class="item" v-for="(item,i) in navData" :key="i" v-if="item">
+				<image :src="item.img" mode=""></image>
+				<text class="txt">{{item.name}}</text>
+			</view> -->
+			<view class="item">
+				<image src="/static/img/coupon_lq.png" mode=""></image>
+				<text class="txt">免费领券</text>
+			</view>
+			<view class="item">
+				<image src="/static/img/coupon_gq.png" mode=""></image>
+				<text class="txt">特惠购券</text>
+			</view>
+			<view class="item" @click="duihuan">
+				<image src="/static/img/coupon_dq.png" mode=""></image>
+				<text class="txt">快捷兑券</text>
+			</view>
+		</view>
+		
+		<view class="main">
+			<view class="list-box">
+				<view class="left">
+					<text>红包/抵用券</text>
+				</view>
+				<view class="right">
+					<text>查看全部</text>
+					<i class="hxicon-right"></i>
+				</view>
+			</view>
+			<view class="coupon-box">
+				<view class="row" v-for="(item,i) in couponData" :key="i" v-if="item">
+					<view class="row-top">
+						<view class="left">
+							<view class="top" v-if="item.type==2">
+								<text class="txt2">{{item.value}}</text>
+								<text class="txt1">折</text>
+							</view>
+							<view class="top" v-else>
+								<text class="txt1">¥</text>
+								<text class="txt2">{{item.value}}</text>
+							</view>
+							<view class="bottom">
+								<view class="txt1">
+									{{item.type_name}}
+								</view>
+							</view>
+						</view>
+						<view class="center">
+							<view class="center-row">
+								<text class="txt4">{{item.type_name}}</text>
+							</view>
+							<view class="center-row">
+								<text class="txt1">{{timeGs(item.end_time)}}</text>
+							</view>
+							<view class="center-row" @click="item.hide_rule = !item.hide_rule">
+								<text class="txt3" >使用规则</text>
+								<i class="txt3 hxicon" :class="item.hide_rule ? 'icon-unfold' : 'icon-fold'"></i>
+							</view>
+							
+						</view>
+						<view class="right">
+							<view class="btn" @click="goStroe(item)">立即使用</view>
+						</view>
+					</view>
+					
+					<view class="beyond" v-if="item.hide_rule == false">
+						<view class="beyond-q beyond-ql"></view>
+						<view class="beyond-q beyond-qr"></view>
+						<text class="txt3">满{{item.beyond}}元可使用,{{item.docs}}</text>
+					</view>
+				</view>
+				
+			</view>
+			<!-- 暂时未规划卡包 -->
+			<!-- <view class="list-box mt">
+				<view class="left">
+					<text>卡包</text>
+				</view>
+				<view class="right">
+					<i class="hxicon-right"></i>
+				</view>
+			</view> -->
+		</view>
+		<view class="foot">
+			
+		</view>
+		
+		<uni-popup ref="popup" type="center" @change="popupChange">
+			<view class="dh-box">
+				<view class="title">
+					<text>快捷兑券</text>
+				</view>
+				<view class="row">
+					<input type="text" value="" v-model="qCode" placeholder="填入券码"/>
+				</view>
+				<view class="btn" @click="submitCode">确认兑券</view>
+			</view>
+		</uni-popup>
+	</view>
+</template>
+
+<script>
+	import uniPopup from "@/components/uni-popup/uni-popup.vue"
+	export default {
+	    components: {uniPopup},
+		data() {
+			return {
+				navData:[
+					{
+						img: '/static/img/coupon_lq.png',
+						name: '免费领券'
+					},
+					{
+						img: '/static/img/coupon_gq.png',
+						name: '特惠购券'
+					},
+					{
+						img: '/static/img/coupon_dq.png',
+						name: '快捷兑券'
+					}
+				],
+				qCode:'',
+				isBack: true,
+				couponData: [
+					{
+						id: 'MS68941',
+						// 类型 1优惠券,2折扣券,3抵扣券
+						type: 1,
+						type_name: '优惠券',
+						store_id: '123',
+						title: '外卖美食红包',
+						value: 20,
+						// 满足条件,满xx减xx
+						beyond: 100,
+						create_time: '2020-04-17 20:30:11',
+						end_time: '2021-04-17 20:30:11',
+						docs: '不可与满减,折扣商品,第二份半价,津贴活动同时享有。在线支付专享。',
+						hide_rule: true
+					},
+					{
+						id: 'MS68941',
+						// 类型 1优惠券,2折扣券,3抵扣券
+						type: 2,
+						type_name: '折扣券',
+						title: '外卖美食红包',
+						store_id: '123',
+						value: 7.4,
+						// 满足条件,满xx减xx
+						beyond: 150,
+						create_time: '2020-04-17 20:30:11',
+						end_time: '2021-04-17 20:30:11',
+						docs: '不可与满减,折扣商品,第二份半价,津贴活动同时享有。在线支付专享。',
+						hide_rule: true
+					},
+					{
+						id: 'MS68941',
+						// 类型 1优惠券,2折扣券,3抵扣券
+						type: 3,
+						type_name: '抵扣券',
+						title: '外卖美食红包',
+						store_id: '123',
+						value: 66,
+						// 满足条件,满xx减xx
+						beyond: 200,
+						create_time: '2020-04-17 20:30:11',
+						end_time: '2020-04-19 12:55:11',
+						docs: '不可与满减,折扣商品,第二份半价,津贴活动同时享有。在线支付专享。',
+						hide_rule: true
+					},
+					{
+						id: 'MS68941',
+						// 类型 1优惠券,2折扣券,3抵扣券
+						type: 1,
+						type_name: '优惠券',
+						title: '外卖美食红包',
+						store_id: '123',
+						value: 20,
+						// 满足条件,满xx减xx
+						beyond: 100,
+						create_time: '2020-04-17 20:30:11',
+						end_time: '2020-04-18 23:30:11',
+						docs: '不可与满减,折扣商品,第二份半价,津贴活动同时享有。在线支付专享。',
+						hide_rule: true
+					}
+				]
+			}
+		},
+		onBackPress() {
+			if(!this.isBack){
+				this.$refs.popup.close()
+				return true
+			}
+		},
+		methods: {
+			duihuan(){
+				this.$refs.popup.open()
+			},
+			popupChange(e){
+				this.isBack = !e.show
+			},
+			submitCode(){
+				if(this.qCode == ''){
+					return
+				}
+				this.$refs.popup.close()
+				uni.showModal({
+					showCancel: false,
+					content: '提交事件,券码为:'+ this.qCode
+				})
+			},
+			goStroe(row){
+				uni.navigateTo({
+					url:'/pages/store/index?sid=' + row.store_id
+				})
+			},
+			timeGs(cDate){
+				var go_time=new Date(cDate.replace(/-/g, '/'));
+				var now_time=new Date();
+				if(!go_time.getTime()){
+					return '已失效'
+				}
+				let str = ''
+				var alltime =go_time.getTime() -now_time.getTime ();  //剩余的时间(毫秒)
+				if(alltime <= 0){
+					str = "已过期"
+					return str
+				}
+				
+				
+				if(go_time.getYear() == now_time.getYear() && go_time.getMonth() == now_time.getMonth() && go_time.getDay() == now_time.getDay()){
+					str = "今日" + go_time.getHours() + ':' + go_time.getMinutes() + "到期"
+				}else{
+					let day = parseInt(alltime/86400000);
+					if(day > 1){
+						str = "还剩" + day + '天到期'
+					}else{
+						str = "明日" + go_time.getHours() + ':' + go_time.getMinutes() + "到期"
+					}
+				}
+				return str
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+page{
+	background-color: #f7f8fc;
+}
+.mt{
+	margin-top: 15px;
+}
+.head{
+	display: flex;
+	flex-direction: row;
+	justify-content: center;
+	align-items: center;
+	.item{
+		display: flex;
+		flex-direction: column;
+		justify-content: center;
+		align-items: center;
+		margin-top: 10px;
+		padding: 12px 30px;
+		image{
+			width: 40px;
+			height: 40px;
+		}
+		.txt{
+			font-size: 12px;
+			color: #444;
+			margin-top: 6px;
+		}
+	}
+}
+.main{
+	display: flex;
+	flex-direction: column;
+	margin: 20px 15px 0;
+		
+	.list-box{
+		display: flex;
+		flex-direction: row;
+		align-items: center;
+		justify-content: space-between;
+		.left{
+			font-size: 16px;
+			font-weight: bold;
+			color: #333;
+			flex: 1;
+		}
+		.right{
+			font-size: 12px;
+			color: #555;
+		}
+		
+	}
+	.coupon-box{
+		
+		display: flex;
+		flex-direction: column;
+		.row{
+			display: flex;
+			flex-direction: column;
+			padding: 15px;
+			background: #fff;
+			border-radius: 10px;
+			margin-top: 15px;
+			.row-top{
+				display: flex;
+				flex-direction: row;
+				.txt1{
+					font-size: 14px;
+					color: #FF9800;
+				}
+				.txt2{
+					font-size: 30px;
+					color: #FF5722;
+				}
+				.txt3{
+					font-size: 12px;
+					color: #999;
+				}
+				.txt4{
+					font-size: 14px;
+					color: #333;
+				}
+				.left{
+					padding: 0 20px;
+					margin-left: -15px;
+					display: flex;
+					flex-direction: column;
+					justify-content: center;
+					align-items: center;
+					
+				}
+				.center{
+					display: flex;
+					flex-direction: column;
+					flex: 1;
+					.center-row{
+						display: flex;
+						flex-wrap: wrap;
+						margin-bottom: 6px;
+						align-items: center;
+						[class*="hxicon-"]{
+							margin-left: 6px;
+						}
+					}
+					
+					.center-row:last-child{
+						margin-bottom: 0;
+					}
+				}
+				.right{
+					display: flex;
+					justify-content: center;
+					align-items: center;
+					.btn{
+						padding: 5px 12px;
+						border-radius: 40px;
+						background: linear-gradient(100deg, #FF9800, #FF5722);
+						color: #fff;
+						font-size: 12px;
+					}
+				}
+			}
+			.beyond{
+				position: relative;
+				margin: 12px -15px -15px;
+				padding: 12px 15px 12px;
+				background-color: #f5f5f5;
+				border-radius: 10px;
+				border-top: 1px dashed #d9d9d9;
+				
+				.beyond-q{
+					position: absolute;
+					width: 20px;
+					height: 20px;
+					border-radius: 100%;
+					background-color: #f7f8fc;
+					top: -10px;
+				}
+				.beyond-ql{
+					left: -10px;
+				}
+				.beyond-qr{
+					right: -10px;
+				}
+				.txt3{
+					font-size: 12px;
+					color: #999;
+				}
+			}
+		}
+	}
+}
+.foot{
+	height: 50px;
+}
+.dh-box{
+	
+	padding: 15px;
+	border-radius: 10px;
+	background: #fff;
+	display: flex;
+	flex-direction: column;
+	justify-content: right;
+	align-items: center;
+	.title{
+		font-size: 14px;
+		font-weight: bold;
+		color: #555;
+	}
+	.row{
+		margin-top: 12px;
+		height: 40px;
+		border: 1px solid #eee;
+		background: #eee;
+		border-radius: 6px;
+		
+		input{
+			padding: 0 6px;
+			background: #eee;
+			height: 100%;
+			width: 100%;
+		}
+	}
+	.btn{
+		margin-top: 10px;
+		padding: 10px 20px;
+		border-radius: 6px;
+		background: linear-gradient(100deg, #FF9800, #FF5722);
+		color: #fff;
+		font-size: 12px;
+	}
+	.btn:active{
+		
+		background: linear-gradient(100deg, #da8302, #e04d1e);
+		color: #f8f8f8;
+	}
+}
+</style>

+ 239 - 0
HX-SHOP/pages/user/forget/forget.vue

@@ -0,0 +1,239 @@
+<template>
+	<view class="forget">
+		<uni-nav-bar
+			:status-bar="true"
+			:shadow="false"
+			:border="false"
+			background-color="#f1f1f1">
+		  
+		    <view slot="left">
+				<view class="cu-bar">
+					<view class="action">
+						<text class="cuIcon-close" @click="closePage"></text> 
+					</view>
+					<view class="content text-bold">
+						
+					</view>
+				</view> 
+			</view>
+		</uni-nav-bar>
+		
+		<view class="content">
+			<!-- 主体 -->
+			<view class="main">
+				<view class="tips">若你忘记了密码,可在此重置新密码。</view>
+				<wInput
+					v-model="phoneData"
+					type="text"
+					maxlength="11"
+					placeholder="请输入手机号码"
+				></wInput>
+				<wInput
+					v-model="passData"
+					type="password"
+					maxlength="11"
+					placeholder="请输入新密码"
+					isShowPass
+				></wInput>
+				
+				<wInput
+					v-model="verCode"
+					type="number"
+					maxlength="4"
+					placeholder="验证码"
+					
+					isShowCode
+					codeText="获取重置码"
+					setTime="30"
+					ref="runCode"
+					@setCode="getVerCode()"
+				></wInput>
+			</view>
+			
+			<wButton 
+				text="重置密码"
+				:rotate="isRotate" 
+				@click.native="startRePass()"
+			></wButton>
+
+		</view>
+	</view>
+</template>
+
+<script>
+	var _this;
+	import wInput from '@/components/watch-login/watch-input.vue' //input
+	import wButton from '@/components/watch-login/watch-button.vue' //button
+	export default {
+		data() {
+			return {
+				phoneData: "", //电话
+				passData: "", //密码
+				verCode:"", //验证码
+				isRotate: false, //是否加载旋转
+			}
+		},
+		components:{
+			wInput,
+			wButton
+		},
+		mounted() {
+			_this= this;
+			console.log('hello');
+		},
+		methods: {
+			getVerCode(){
+				//获取验证码
+				if (_this.phoneData.length != 11) {
+				     uni.showToast({
+				        icon: 'none',
+						position: 'bottom',
+				        title: '手机号不正确'
+				    });
+				    return false;
+				}
+				console.log("获取验证码")
+				this.$refs.runCode.$emit('runCode'); //触发倒计时(一般用于请求成功验证码后调用)
+				uni.showToast({
+				    icon: 'none',
+					position: 'bottom',
+				    title: '模拟倒计时触发'
+				});
+				
+				setTimeout(function(){
+					_this.$refs.runCode.$emit('runCode',0); //假装模拟下需要 终止倒计时
+					uni.showToast({
+					    icon: 'none',
+						position: 'bottom',
+					    title: '模拟倒计时终止'
+					});
+				},3000)
+			},
+			startRePass() {
+				//重置密码
+				if(this.isRotate){
+					//判断是否加载中,避免重复点击请求
+					return false;
+				}
+				if (this.phoneData.length != 11) {
+				    uni.showToast({
+				        icon: 'none',
+						position: 'bottom',
+				        title: '手机号不正确'
+				    });
+				    return false;
+				}
+			    if (this.passData.length < 6) {
+			        uni.showToast({
+			            icon: 'none',
+						position: 'bottom',
+			            title: '密码不正确'
+			        });
+			        return false;
+			    }
+				if (this.verCode.length != 4) {
+				    uni.showToast({
+				        icon: 'none',
+						position: 'bottom',
+				        title: '验证码不正确'
+				    });
+				    return false;
+				}
+				console.log("重置密码成功")
+				_this.isRotate=true
+				setTimeout(function(){
+					_this.isRotate=false
+				},3000)
+				
+				
+			}
+		}
+	}
+</script>
+
+<style>
+	
+	.content {
+		display: flex;
+		flex-direction: column;
+		justify-content:center;
+		/* margin-top: 128upx; */
+	}
+	
+	/* 头部 logo */
+	.header {
+		width:161upx;
+		height:161upx;
+		box-shadow:0upx 0upx 60upx 0upx rgba(0,0,0,0.1);
+		border-radius:50%;
+		background-color: #000000; 
+		margin-top: 128upx;
+		margin-bottom: 72upx;
+		margin-left: auto;
+		margin-right: auto;
+	}
+	.header image{
+		width:161upx;
+		height:161upx;
+		border-radius:50%;
+	}
+	
+	/* 主体 */
+	.main {
+		display: flex;
+		flex-direction: column;
+		padding-left: 70upx;
+		padding-right: 70upx;
+	}
+	.tips {
+		color: #999999;
+		font-size: 28upx;
+		margin-top: 64upx;
+		margin-left: 48upx;
+	}
+	
+	/* 其他登录方式 */
+	.other_login{
+		display: flex;
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+		margin-top: 256upx;
+		text-align: center;
+	}
+	.login_icon{
+		border: none;
+		font-size: 64upx;
+		margin: 0 64upx 0 64upx;
+		color: rgba(0,0,0,0.7)
+	}
+	.wechat_color{
+		color: #83DC42;
+	}
+	.weibo_color{
+		color: #F9221D;
+	}
+	.github_color{
+		color: #24292E;
+	}
+	
+	/* 底部 */
+	.footer{
+		display: flex;
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+		font-size: 28upx;
+		margin-top: 64upx;
+		color: rgba(0,0,0,0.7);
+		text-align: center;
+		height: 40upx;
+		line-height: 40upx;
+	}
+	.footer text{
+		font-size: 24upx;
+		margin-left: 15upx;
+		margin-right: 15upx;
+	}
+</style>
+

File diff ditekan karena terlalu besar
+ 81 - 0
HX-SHOP/pages/user/login/login.vue


File diff ditekan karena terlalu besar
+ 70 - 0
HX-SHOP/pages/user/register/register.vue


+ 95 - 0
HX-SHOP/pages/user/setting/setting.vue

@@ -0,0 +1,95 @@
+<template>
+	<view>
+		<hx-navbar left-text="设置" backTabbarUrl="/pages/user/center/center"></hx-navbar>
+		
+		<view class="cu-list menu sm-border margin-top">
+			
+			<navigator class="cu-item arrow " url="../account_security/security" open-type="navigate">
+				<view class="content">
+					<text class="text-black">安全设置</text>
+				</view>
+				<view class="action">
+					<text class="text-grey text-sm">手机号、密码</text>
+				</view>
+			</navigator>
+			<view class="cu-item arrow">
+				<view class="content">
+					<text class="text-black">通用</text>
+				</view>
+				<view class="action">
+					<text class="text-grey text-sm"></text>
+				</view>
+			</view>
+			<view class="cu-item arrow">
+				<view class="content">
+					<text class="text-black">隐私</text>
+				</view>
+				<view class="action">
+					<text class="text-grey text-sm"></text>
+				</view>
+			</view>
+			
+			<navigator class="cu-item arrow margin-top" url="../../base/about" open-type="navigate">
+				<view class="content">
+					<text class="text-black">关于</text>
+				</view>
+				<view class="action">
+					<text class="text-grey text-sm">版本号 {{version}}</text>
+				</view>
+			</navigator>
+			<navigator class="cu-item arrow" url="../../base/help_feedback" open-type="navigate">
+				<view class="content">
+					<text class="text-black">帮助与反馈</text>
+				</view>
+				<view class="action">
+					<text class="text-grey text-sm"></text>
+				</view>
+			</navigator>
+			
+			<!-- <view class="cu-item margin-top">
+				<view class="content" style="text-align: center;">
+					<text class="text-black">切换账号</text>
+				</view>
+			</view> -->
+			<view class="cu-item margin-top" @click="logOut">
+				<view class="content" style="text-align: center;">
+					<text class="text-grey" style="color: #ffc107">退出登录</text>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	var that;
+	export default {
+		data() {
+			return {
+				version: this.$conf.version
+			}
+		},
+		onLoad(){
+			var that = this;
+		},
+		mounted() {
+			that= this;
+		},
+		methods: {
+			logOut(){
+				that.$store.dispatch("logout");
+				that.$api.user.logout();
+				
+				that.back();
+			},
+			back(){
+				uni.redirectTo({
+				    url: '/pages/user/login/login'
+				});
+			}
+		}
+	}
+</script>
+
+<style>
+
+</style>

TEMPAT SAMPAH
HX-SHOP/static/img/coupon_dq.png


TEMPAT SAMPAH
HX-SHOP/static/img/coupon_gq.png


TEMPAT SAMPAH
HX-SHOP/static/img/coupon_lq.png


TEMPAT SAMPAH
HX-SHOP/static/img/index/cs.png


Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini