kevin_zhangl 2 years ago
commit
dcb00ac5ae
100 changed files with 11228 additions and 0 deletions
  1. 203 0
      App.vue
  2. 27 0
      androidPrivacy.json
  3. 16 0
      common/directive.js
  4. 81 0
      common/gotopage.js
  5. 2 0
      common/iconfont.css
  6. 152 0
      common/mixin.scss
  7. 2 0
      common/myIcon.css
  8. 98 0
      common/onfire.js
  9. 135 0
      common/pay.js
  10. 41 0
      common/specSelect.js
  11. 1602 0
      common/style.css
  12. 1458 0
      common/uni.css
  13. 171 0
      common/utils.js
  14. 203 0
      components/app-share.vue
  15. 180 0
      components/countdown/countdown.vue
  16. 94 0
      components/diy/article/article.vue
  17. 204 0
      components/diy/assembleProduct/assembleProduct.vue
  18. 161 0
      components/diy/banner/banner.vue
  19. 189 0
      components/diy/bargainProduct/bargainProduct.vue
  20. 18 0
      components/diy/blank/blank.vue
  21. 221 0
      components/diy/coupon/coupon.vue
  22. 174 0
      components/diy/diy.vue
  23. 19 0
      components/diy/guide/guide.vue
  24. 44 0
      components/diy/imagesingle/imagesingle.vue
  25. 71 0
      components/diy/navBar/navBar.vue
  26. 66 0
      components/diy/notice/notice.vue
  27. 277 0
      components/diy/product/product.vue
  28. 30 0
      components/diy/richText/richText.vue
  29. 55 0
      components/diy/search/search.vue
  30. 196 0
      components/diy/seckillProduct/seckillProduct.vue
  31. 36 0
      components/diy/service/service.vue
  32. 142 0
      components/diy/special/special.vue
  33. 64 0
      components/diy/store/store.vue
  34. 73 0
      components/diy/title/title.vue
  35. 29 0
      components/diy/videos/videos.vue
  36. 135 0
      components/diy/window/window.vue
  37. 170 0
      components/diy/wxlive/wxlive.vue
  38. 30 0
      components/header.vue
  39. 114 0
      components/mp-share.vue
  40. 90 0
      components/mpservice/Mpservice.vue
  41. 239 0
      components/mpvue-citypicker/mpvueCityPicker.vue
  42. 463 0
      components/mpvue-picker/mpvuePicker.vue
  43. 100 0
      components/navBar/navBar.vue
  44. 137 0
      components/navBar/scroll-navbar.vue
  45. 38 0
      components/page-foot.vue
  46. 179 0
      components/recommendProduct/recommendProduct.vue
  47. 193 0
      components/searchProduct.vue
  48. 127 0
      components/uni-icon/readme.md
  49. 39 0
      components/uni-icon/uni-icon.vue
  50. 192 0
      components/uni-load-more.vue
  51. 173 0
      components/uni-number-box.vue
  52. 112 0
      components/uni-popup.vue
  53. 134 0
      components/uni-segmented-control.vue
  54. 50 0
      components/uni-steps/readme.md
  55. 257 0
      components/uni-steps/uni-steps.vue
  56. 80 0
      components/upload/upload.vue
  57. 116 0
      components/zz-prompt.vue
  58. 24 0
      config.js
  59. 30 0
      jweixin-module/README.md
  60. 0 0
      jweixin-module/out/index.js
  61. 60 0
      jweixin-module/package.json
  62. 393 0
      main.js
  63. 165 0
      manifest.json
  64. 22 0
      node_modules/@babel/runtime/LICENSE
  65. 19 0
      node_modules/@babel/runtime/README.md
  66. 64 0
      node_modules/@babel/runtime/helpers/AsyncGenerator.js
  67. 4 0
      node_modules/@babel/runtime/helpers/AwaitValue.js
  68. 4 0
      node_modules/@babel/runtime/helpers/OverloadYield.js
  69. 24 0
      node_modules/@babel/runtime/helpers/applyDecoratedDescriptor.js
  70. 242 0
      node_modules/@babel/runtime/helpers/applyDecs.js
  71. 190 0
      node_modules/@babel/runtime/helpers/applyDecs2203.js
  72. 8 0
      node_modules/@babel/runtime/helpers/arrayLikeToArray.js
  73. 4 0
      node_modules/@babel/runtime/helpers/arrayWithHoles.js
  74. 5 0
      node_modules/@babel/runtime/helpers/arrayWithoutHoles.js
  75. 7 0
      node_modules/@babel/runtime/helpers/assertThisInitialized.js
  76. 24 0
      node_modules/@babel/runtime/helpers/asyncGeneratorDelegate.js
  77. 45 0
      node_modules/@babel/runtime/helpers/asyncIterator.js
  78. 31 0
      node_modules/@babel/runtime/helpers/asyncToGenerator.js
  79. 5 0
      node_modules/@babel/runtime/helpers/awaitAsyncGenerator.js
  80. 6 0
      node_modules/@babel/runtime/helpers/checkPrivateRedeclaration.js
  81. 18 0
      node_modules/@babel/runtime/helpers/classApplyDescriptorDestructureSet.js
  82. 7 0
      node_modules/@babel/runtime/helpers/classApplyDescriptorGet.js
  83. 11 0
      node_modules/@babel/runtime/helpers/classApplyDescriptorSet.js
  84. 6 0
      node_modules/@babel/runtime/helpers/classCallCheck.js
  85. 6 0
      node_modules/@babel/runtime/helpers/classCheckPrivateStaticAccess.js
  86. 6 0
      node_modules/@babel/runtime/helpers/classCheckPrivateStaticFieldDescriptor.js
  87. 7 0
      node_modules/@babel/runtime/helpers/classExtractFieldDescriptor.js
  88. 4 0
      node_modules/@babel/runtime/helpers/classNameTDZError.js
  89. 7 0
      node_modules/@babel/runtime/helpers/classPrivateFieldDestructureSet.js
  90. 7 0
      node_modules/@babel/runtime/helpers/classPrivateFieldGet.js
  91. 6 0
      node_modules/@babel/runtime/helpers/classPrivateFieldInitSpec.js
  92. 7 0
      node_modules/@babel/runtime/helpers/classPrivateFieldLooseBase.js
  93. 5 0
      node_modules/@babel/runtime/helpers/classPrivateFieldLooseKey.js
  94. 8 0
      node_modules/@babel/runtime/helpers/classPrivateFieldSet.js
  95. 7 0
      node_modules/@babel/runtime/helpers/classPrivateMethodGet.js
  96. 6 0
      node_modules/@babel/runtime/helpers/classPrivateMethodInitSpec.js
  97. 4 0
      node_modules/@babel/runtime/helpers/classPrivateMethodSet.js
  98. 9 0
      node_modules/@babel/runtime/helpers/classStaticPrivateFieldDestructureSet.js
  99. 9 0
      node_modules/@babel/runtime/helpers/classStaticPrivateFieldSpecGet.js
  100. 10 0
      node_modules/@babel/runtime/helpers/classStaticPrivateFieldSpecSet.js

+ 203 - 0
App.vue

@@ -0,0 +1,203 @@
+<script>
+	import utils from './common/utils.js'
+	import config from './config.js'
+	export default {
+		onLaunch: function(e) {
+			// 隐私政策
+			// #ifdef APP-PLUS
+			this.isFirstEnter();
+			// #endif
+			console.log('App Launch');
+			//#ifdef MP-WEIXIN	
+			//检查更新
+			this.updateManager();
+			//#endif
+			// #ifdef APP-PLUS
+			plus.runtime.getProperty(plus.runtime.appid, function(widgetInfo) {
+				uni.request({
+					url: config.app_url + '/index.php/api/index/update',
+					data: {
+						version: widgetInfo.version,
+						name: widgetInfo.name,
+						app_id: config.app_id,
+						platform: uni.getSystemInfoSync().platform
+					},
+					success: (result) => {
+						console.log(result);
+						var data = result.data.data.result;
+						if (data.update && data.wgtUrl) {
+							uni.downloadFile({
+								url: data.wgtUrl,
+								success: (downloadResult) => {
+									if (downloadResult.statusCode === 200) {
+										plus.runtime.install(downloadResult
+											.tempFilePath, {
+												force: true
+											},
+											function() {
+												console.log('install success...');
+												plus.nativeUI.alert(
+													"已更新至最新版本,确定后将重启应用",
+													function() {
+														plus.runtime.restart();
+													}, "更新提示", "确定");
+											},
+											function(e) {
+												console.error('install fail...');
+											});
+									}
+								}
+							});
+						}
+						if (data.update && data.pkgUrl) {
+							plus.nativeUI.confirm("有新版本更新,请点击确认更新到最新版本,以免影响使用", function(e) {
+								if (e.index == 0) {
+									plus.runtime.openURL(data.pkgUrl);
+								}
+							}, {
+								"title": "更新提示",
+								"buttons": ["确定", "取消"],
+								"verticalAlign": "center"
+							});
+						}
+					},
+					error: (error) => {
+						console.log('----------------error');
+						console.log(error);
+					}
+				});
+			});
+			// #endif
+			//应用启动参数
+			this.onStartupScene(e.query);
+			// #ifndef APP-PLUS
+			this.getTabBarLinks();
+			//#endif
+		},
+		onShow: function() {
+
+
+			//console.log('App Show')
+		},
+		onHide: function() {
+			//console.log('App Hide')
+		},
+		methods: {
+			isFirstEnter() {
+				var firstEnter = uni.getStorageSync('firstEnter'); //同步获取缓存中是否有首次进入字段
+				let self = this;
+				uni.getSystemInfo({
+					success(data) {
+						console.log('firstEnter='+ firstEnter);
+						// 如果是ios并且没有firstEnter缓存则弹出模态框
+						if (data.platform == 'ios' && !firstEnter) {
+							console.log('---------------');
+							uni.navigateTo({
+								url: '/pages/privacy/privacy'
+							})
+						} 
+					}
+				})
+			},
+			updateManager: function() {
+				const updateManager = uni.getUpdateManager();
+				updateManager.onCheckForUpdate(function(res) {
+					// 请求完新版本信息的回调
+					if (res.hasUpdate) {
+						updateManager.onUpdateReady(function(res2) {
+							uni.showModal({
+								title: '更新提示',
+								content: '新版本已经准备好,即将重启应用',
+								showCancel: false,
+								success(res2) {
+									if (res2.confirm) {
+										// 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
+										updateManager.applyUpdate();
+									}
+								}
+							});
+						});
+					}
+				});
+
+				updateManager.onUpdateFailed(function(res) {
+					// 新的版本下载失败
+					uni.showModal({
+						title: '更新提示',
+						content: '检查到有新版本,但下载失败,请检查网络设置',
+						showCancel: false
+					});
+				});
+			},
+			/**
+			 * 小程序启动场景
+			 */
+			onStartupScene(query) {
+				// 获取场景值
+				let scene = utils.getSceneData(query);
+				// 记录推荐人id
+				let refereeId = query.referee_id;
+				if (refereeId > 0) {
+					if (!uni.getStorageSync('referee_id')) {
+						uni.setStorageSync('referee_id', refereeId);
+					}
+				}
+				// 记录分销人id
+				let uid = scene.uid;
+				if (uid > 0) {
+					uni.setStorageSync('referee_id', uid);
+				}
+				// 邀请有礼id
+				let invitation_id = query.invitation_id;
+				if (invitation_id > 0) {
+					uni.setStorageSync('invitation_id', invitation_id);
+				}
+				let invitid = scene.invitid;
+				if (invitid > 0) {
+					uni.setStorageSync('invitation_id', invitid);
+				}
+				// 如果是h5,设置app_id
+				// #ifdef  H5
+				let appId = query.app_id;
+				if (appId > 0) {
+					uni.setStorageSync('app_id', appId);
+				}
+				if (uni.getStorageSync('app_id')) {
+					this.config.app_id = uni.getStorageSync('app_id');
+				}
+				// #endif
+			},
+			getTabBarLinks() {
+				uni.request({
+					url: this.config.app_url + '/index.php/api/index/nav',
+					data: {
+						app_id: this.config.app_id
+					},
+					success: (result) => {
+						let vars = result.data.data.vars;
+						uni.setStorageSync('TabBar', vars);
+						uni.setTabBarStyle({
+							color: vars.no_color,
+							selectedColor: vars.color,
+						})
+						vars.menus.forEach((item, index) => {
+							uni.setTabBarItem({
+								index: index,
+								text: item.text,
+								iconPath: item.iconPath,
+								selectedIconPath: item.selectedIconPath
+							})
+						})
+					}
+				});
+			}
+		}
+	}
+</script>
+
+<style>
+	@import './common/iconfont.css';
+	@import './common/myIcon.css';
+	/*每个页面公共css */
+	@import './common/style.css';
+</style>

+ 27 - 0
androidPrivacy.json

@@ -0,0 +1,27 @@
+{  
+  "version": "1",    
+  "prompt": "template",  
+  "title": "服务协议和隐私政策",  
+  "message": "  请你务必审慎阅读、充分理解“服务协议”和“隐私政策”各条款,包括但不限于:为了更好的向你提供服务,我们需要收集你的设备标识、操作日志等信息用于分析、优化应用性能。<br/>  你可阅读<a href=\"https://business.jjjshop.net/service.html\">《服务协议》</a>和<a href=\"https://business.jjjshop.net/privacy.html\">《隐私政策》</a>了解详细信息。如果你同意,请点击下面按钮开始接受我们的服务。",  
+  "buttonAccept": "同意并接受",  
+  "buttonRefuse": "暂不同意",  
+  "second": {  
+    "title": "确认提示",  
+    "message": "  进入应用前,你需先同意<a href=\"https://business.jjjshop.net/service.html\">《服务协议》</a>和<a href=\"https://business.jjjshop.net/privacy.html\">《隐私政策》</a>,否则将退出应用。",  
+    "buttonAccept": "同意并继续",  
+    "buttonRefuse": "退出应用"  
+  },  
+  "styles": {  
+    "backgroundColor": "#FFFFFF",  
+    "borderRadius":"5px",  
+    "title": {  
+      "color": "#ff00ff"  
+    },  
+    "buttonAccept": {  
+      "color": "#000000"  
+    },  
+    "buttonRefuse": {  
+      "color": "#00ffff"  
+    }  
+  }  
+}

+ 16 - 0
common/directive.js

@@ -0,0 +1,16 @@
+import Vue from 'vue'
+let defaultImg=require("@/static/default.png");
+
+/*指令测试*/
+Vue.directive('demo', {
+  bind: function (el, binding, vnode) {
+    var s = JSON.stringify
+    el.innerHTML =
+      'name: '       + s(binding.name) + '<br>' +
+      'value: '      + s(binding.value) + '<br>' +
+      'expression: ' + s(binding.expression) + '<br>' +
+      'argument: '   + s(binding.arg) + '<br>' +
+      'modifiers: '  + s(binding.modifiers) + '<br>' +
+      'vnode keys: ' + Object.keys(vnode).join(', ')
+  }
+})

+ 81 - 0
common/gotopage.js

@@ -0,0 +1,81 @@
+import config from '../config.js'
+/*导航菜单白名单*/
+const tabBarLinks = [
+	'/pages/index/index',
+	'/pages/product/category',
+	'/pages/cart/cart',
+	'/pages/user/index/index'
+];
+
+/*分享页面白名单*/
+const shareLinks = [
+	'/pages/plus/assemble/fight-group-detail/fight-group-detail',
+	'/pages/plus/bargain/haggle/haggle',
+	'/pages/user/invite/invite',
+	'/pages/product/detail/detail',
+	'/pages/plus/seckill/detail/detail',
+	'/pages/plus/assemble/detail/detail',
+	'/pages/plus/bargain/detail/detail',
+	'/pages/plus/points/detail/detail'
+]
+
+/*
+ * 跳转页面
+ */
+export const gotopage = (url, type) => {
+	if (!url || url.length == 0) {
+		return false;
+	}
+	
+	if(url.substr(0,1)!=='/'){
+		url='/' + url;
+	}
+	let p = url;
+	if(url.indexOf('?') != -1){
+		p = url.substr(0, url.indexOf('?'));
+		// #ifdef  H5
+		if(url.search("app_id") == -1){
+			url = url + '&app_id='+config.app_id;
+		}
+		// #endif
+	}else{
+		// #ifdef  H5
+		if(url.search("app_id") == -1){
+			url = url + '?app_id='+config.app_id;
+		}
+		// #endif
+	}
+	// tabBar页面
+	if (tabBarLinks.indexOf(p) > -1) {
+		uni.reLaunch({
+			url: url
+		});
+	} else {
+		if(process.env.NODE_ENV === 'production'){
+		    //判断是否分享页面
+		    if (shareLinks.indexOf(p) > -1) {
+		    	//公众号
+		    	// #ifdef  H5
+		    	window.location.href = config.app_url + config.h5_addr + url;
+		    	return;
+		    	// #endif
+		    } 
+		}
+		if(type == 'redirect'){
+			uni.redirectTo({
+				url: url
+			});
+			return
+		}
+		if(type == 'reLaunch'){
+			uni.reLaunch({
+				url: url
+			});
+			return
+		}
+		// 普通页面
+		uni.navigateTo({
+			url:  url
+		});
+	}
+}

File diff suppressed because it is too large
+ 2 - 0
common/iconfont.css


+ 152 - 0
common/mixin.scss

@@ -0,0 +1,152 @@
+/*圆角*/
+@mixin border-radius($radius...) {
+    -webkit-border-radius: $radius;
+    -moz-border-radius: $radius;
+    -o-border-radius: $radius;
+    border-radius: $radius;
+}
+
+/*阴影*/
+@mixin box-shadow($shadows...) { 
+    -moz-box-shadow: $shadows;
+    -webkit-box-shadow: $shadows;
+    box-shadow: $shadows;
+}
+
+/*文字阴影*/
+@mixin text-shadow($shadows...){
+    text-shadow:$shadows;
+}
+
+/*线性渐变*/
+@mixin linear-gradient($val...){
+  background: -webkit-linear-gradient($val); /* Safari 5.1 - 6.0 */
+  background: -o-linear-gradient($val); /* Opera 11.1 - 12.0 */
+  background: -moz-linear-gradient($val); /* Firefox 3.6 - 15 */
+  background: linear-gradient($val); /* 标准的语法 */
+}
+
+
+/*垂直居中*/
+@mixin vertical-center() {
+    display: -webkit-flex;
+    display: flex;
+    -webkit-align-items: center;
+    align-items: center;
+    -webkit-justify-content: center;
+    justify-content: center;
+}
+
+
+/*去除padding 宽度*/
+@mixin box-sizing-border() {
+    box-sizing: border-box;
+    -moz-box-sizing: border-box;
+    /* Firefox */
+    -webkit-box-sizing: border-box;
+    /* Safari */
+}
+
+
+/*css3盒子
+ * flex-direction: row  row-reverse column  column-reverse
+ * flex-wrap: nowrap wrap wrap-reverse
+ * justify-content: flex-start flex-end center space-between space-around
+ * align-items: stretch flex-start flex-end center beseline
+ * align-content: stretch flex-start flex-end center space-between space-around
+ * */
+
+@mixin display-flex() {
+    display: -webkit-flex;
+    display: flex;
+}
+
+@mixin flex-direction($value) {
+    @include display-flex();
+    -webkit-flex-direction: $value;
+    flex-direction: $value;
+}
+
+@mixin flex-wrap($value) {
+    @include display-flex();
+    -webkit-flex-wrap: $value;
+    flex-wrap: $value;
+}
+
+@mixin justify-content($value) {
+    @include display-flex();
+    -webkit-justify-content: $value;
+    justify-content: $value;
+}
+
+@mixin align-items($value) {
+    @include display-flex();
+    -webkit-align-items: $value;
+    align-items: $value;
+}
+
+@mixin align-content($value) {
+    @include display-flex();
+    -webkit-align-content: $value;
+    align-content: $value;
+}
+
+/*设置flex*/
+@mixin flex-num($num) {
+    -webkit-box-flex: $num;
+    -ms-flex: $num;
+    flex: $num;
+}
+
+
+/*一行截取*/
+@mixin ellipsis() {
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+}
+
+
+/*多行截取*/
+@mixin ellipsis-clamp($num) {
+    text-overflow: ellipsis;
+    overflow: hidden;
+    display: -webkit-box;
+    -webkit-line-clamp: $num;
+    -webkit-box-orient: vertical;
+    word-break: break-all;
+}
+
+
+/*旋转角度,x,y位移*/
+@mixin rotate-origin($num, $x, $y) {
+    transform: rotate($num);
+    transform-origin: $x $y;
+    -ms-transform: rotate($num);
+    /* IE 9 */
+    -ms-transform-origin: $x $y;
+    /* IE 9 */
+    -webkit-transform: rotate($num);
+    /* Safari and Chrome */
+    -webkit-transform-origin: $x $y;
+    /* Safari and Chrome */
+}
+
+/*旋转*/
+@mixin transform-rotate($deg){
+    transform: rotate($deg);
+    -ms-transform: rotate($deg); /* IE 9 */
+    -webkit-transform: rotate($deg); /* Safari and Chrome */
+}
+
+/*过度*/
+@mixin transition($val...){
+    transition: $val;
+    -webkit-transition: $val; /* Safari */
+}
+
+/*模糊*/
+@mixin filter($val...){
+    -webkit-filter: blur($val);
+   filter:progid:DXImageTransform.Microsoft.Blur(PixelRadius='1');
+}

+ 2 - 0
common/myIcon.css

@@ -0,0 +1,2 @@
+/*自定义iconfont文件,请将你的iconfont.css内容复制拷贝到这里就可以直接在项目里直接引用*/
+/*参考上面的iconfont.css内容和使用方法*/

+ 98 - 0
common/onfire.js

@@ -0,0 +1,98 @@
+"use strict";
+/**
+ * mini (~300 b) version for event-emitter.
+ */
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+/**
+ * const ee = new OnFire();
+ *
+ * ee.on('click', () => {});
+ *
+ * ee.on('mouseover', () => {});
+ *
+ * ee.emit('click', 1, 2, 3);
+ * ee.fire('mouseover', {}); // same with emit
+ *
+ * ee.off();
+ */
+
+var OnFire =
+/** @class */
+function () {
+  function OnFire() {
+    // 所有事件的监听器
+    this.es = {}; // cname of fire
+
+    this.emit = this.fire;
+  }
+
+  OnFire.prototype.on = function (eventName, cb, once) {
+    if (once === void 0) {
+      once = false;
+    }
+
+    if (!this.es[eventName]) {
+      this.es[eventName] = [];
+    }
+
+    this.es[eventName].push({
+      cb: cb,
+      once: once
+    });
+  };
+
+  OnFire.prototype.once = function (eventName, cb) {
+    this.on(eventName, cb, true);
+  };
+
+  OnFire.prototype.fire = function (eventName) {
+    var params = [];
+
+    for (var _i = 1; _i < arguments.length; _i++) {
+      params[_i - 1] = arguments[_i];
+    }
+
+    var listeners = this.es[eventName] || [];
+
+    for (var i = 0; i < listeners.length; i++) {
+      var _a = listeners[i],
+          cb = _a.cb,
+          once = _a.once;
+      cb.apply(this, params);
+
+      if (once) {
+        listeners.splice(i, 1);
+        i--;
+      }
+    }
+  };
+
+  OnFire.prototype.off = function (eventName, cb) {
+    // clean all
+    if (eventName === undefined) {
+      this.es = {};
+    } else {
+      if (cb === undefined) {
+        // clean the eventName's listeners
+        delete this.es[eventName];
+      } else {
+        var listeners = this.es[eventName] || []; // clean the event and listener
+
+        for (var i = 0; i < listeners.length; i++) {
+          if (listeners[i].cb === cb) {
+            listeners.splice(i, 1);
+            i--;
+          }
+        }
+      }
+    }
+  };
+
+  OnFire.ver = "2.0.0";
+  return OnFire;
+}();
+
+exports.default = OnFire;

+ 135 - 0
common/pay.js

@@ -0,0 +1,135 @@
+/*
+ * 支付
+ */
+export const pay = (result, self, success, fail) => {
+	if (result.code === -10) {
+		self.showError(result.msg);
+		return false;
+	}
+
+	// 发起微信支付
+	if (result.data.pay_type == 20) {
+		//小程序支付
+		// #ifdef  MP-WEIXIN	
+		uni.requestPayment({
+			provider: 'wxpay',
+			timeStamp: result.data.payment.timeStamp,
+			nonceStr: result.data.payment.nonceStr,
+			package: 'prepay_id=' + result.data.payment.prepay_id,
+			signType: 'MD5',
+			paySign: result.data.payment.paySign,
+			success: res => {
+				paySuccess(result, self, success);
+			},
+			fail: res => {
+				self.showError('订单未支付成功', () => {
+					payError(result, fail, self);
+				});
+			},
+		});
+		// #endif
+		//公众号支付
+		// #ifdef  H5
+		if(self.isWeixin()){
+			WeixinJSBridge.invoke('getBrandWCPayRequest', JSON.parse(result.data.payment),
+				function(res) {
+					if (res.err_msg == "get_brand_wcpay_request:ok") {
+						paySuccess(result, self, success);
+					} else if (res.err_msg == "get_brand_wcpay_request:cancel") {
+						self.showSuccess('支付取消', () => {
+							payError(result, fail, self);
+						});
+					} else {
+						self.showError('订单未支付成功', () => {
+							payError(result, fail, self);
+						});
+					}
+				}
+			);
+		}else{
+			//h5支付
+			self.gotoPage('/pages/order/pay-h5/pay-h5?order_id='+result.data.order_id+'&order_type='+result.data.order_type);
+			return ;
+		}
+		// #endif
+		// #ifdef  APP-PLUS
+		//微信支付
+		wxAppPay(result, self,success, fail);
+		// #endif
+	}
+	// 余额支付
+	if (result.data.pay_type == 10) {
+		paySuccess(result, self, success);
+	}
+	// 支付宝支付
+	if (result.data.pay_type == 30) {
+		// #ifdef  APP-PLUS
+		aliAppPay(result, self,success, fail);
+		// #endif
+		// #ifdef  H5
+		self.gotoPage('/pages/order/alipay-h5/alipay-h5?order_id='+result.data.order_id+'&order_type='+result.data.order_type);
+		// #endif
+	}
+}
+
+/*跳到支付成功页*/
+function paySuccess(result, self, success) {
+	if(success){
+		success(result);
+		return;
+	}
+	gotoSuccess(result, self);
+}
+/*跳到支付成功页*/
+function gotoSuccess(result, self) {
+	self.gotoPage('/pages/order/pay-success/pay-success?order_id=' + result.data.order_id, 'reLaunch');
+}
+
+/*支付失败跳订单详情*/
+function payError(result, fail, self) {
+	if(fail){
+		fail(result);
+		return;
+	}
+	self.gotoPage('/pages/order/order-detail?order_id=' + result.data.order_id, 'redirect');
+}
+
+function wxAppPay(result, self,success, fail){
+	// 获取支付通道  
+	plus.payment.getChannels(function(channels) {
+		self.channel = channels[0];
+		console.log(self.channel);
+		uni.requestPayment({
+			provider: 'wxpay',
+			orderInfo: result.data.payment,
+			success(res) {
+				paySuccess(result, self, success);
+			},
+			fail(error) {
+				console.log(error);
+				self.showError('订单未支付成功', () => {
+					payError(result, fail);
+				});
+			},
+		});
+	}, function(e) {
+		console.log("获取支付通道失败:" + e.message);
+	});
+}
+
+function aliAppPay(result, self,success, fail){
+	console.log(result.data.payment);
+	uni.requestPayment({
+		provider: 'alipay',
+		orderInfo: result.data.payment,
+		success(res) {
+			paySuccess(result, self, success);
+		},
+		fail(error) {
+			console.log(error);
+			self.showError('订单未支付成功', () => {
+				payError(result, fail, self);
+			});
+		},
+	});
+}

+ 41 - 0
common/specSelect.js

@@ -0,0 +1,41 @@
+/*判断哪些规格可以选*/
+export const judgeSelect = (list,_index,productSpecArr,productSku) => {
+	
+	/*大类*/
+	for (let i = 0, count = list.length; i < count; i++) {
+		/*小类*/
+		for (let j = 0; j < list[i].spec_items.length; j++) {
+			let item = list[i].spec_items[j];
+			if(i!=_index){
+				item.disabled = hasSpecId(i,item.item_id,productSpecArr,productSku);
+			}
+		}
+	}
+}
+
+/*判断有没有规格ID*/
+function hasSpecId(index,id,productSpecArr,productSku){
+	let disabled=false;
+	let reg='';
+	for(let p=0;p<productSpecArr.length;p++){
+		if(p!=index){
+			if(productSpecArr[p]!=null){
+				reg+=productSpecArr[p]+'_';
+			}else{
+				reg+='[0-9]*_';
+			}
+		}else{
+			reg+=id+'_';
+		}
+	}
+	reg=reg.substr(0,reg.length-1);
+	let re=new RegExp(reg,'g');
+	for (let s = 0; s < productSku.length; s++) {
+		let ids=productSku[s].join('_');
+		disabled=re.test(ids);
+		if(disabled){
+			break;
+		}
+	}
+	return !disabled;
+}

+ 1602 - 0
common/style.css

@@ -0,0 +1,1602 @@
+body {
+	background: #f6f6f6;
+	font-size: 24rpx;
+	overflow-x:hidden;
+}
+
+/* #ifdef MP-WEIXIN || APP-PLUS */
+
+::-webkit-scrollbar{
+
+    display: none;
+
+}
+
+/* #endif */
+
+.container {
+	padding: 20rpx;
+}
+
+/*color*/
+.color-57{
+	color: #575757;
+}
+.gray {
+	color: #CCCCCC;
+}
+
+.gray9 {
+	color: #999999;
+}
+
+.gray6 {
+	color: #666666;
+}
+
+.gray3 {
+	color: #333333;
+}
+
+.white {
+	color: #FFFFFF;
+}
+
+.red {
+	color: #f6220c;
+}
+
+.redEe {
+	color: #EE1414;
+}
+
+.redF6 {
+	color: #F6220C;
+}
+
+.blue {
+	color: #28a5ff;
+}
+
+.violet {
+	color: #a824e4;
+}
+
+.yellow {
+	color: #ffd127;
+}
+
+.orange {
+	color: #ff8a00;
+}
+
+.green {
+	color: #32d500;
+}
+
+.brown {
+	color: #4f3a1e;
+}
+
+.golden {
+	color: rgba(168, 112, 13, 1);
+}
+
+/*button*/
+button {
+	margin: 0;
+	font-size: 28rpx;
+}
+
+button.btn-gcred {
+	background: linear-gradient(90deg, #FF6B6B 4%, #F6220C 100%);
+	border: none;
+	color: #FFFFFF;
+}
+
+button.btn-red {
+	border: 1px solid #f6220c;
+	background: #f6220c;
+	color: #FFFFFF;
+}
+
+button.btn-blue {
+	background: #28a5ff;
+	color: #FFFFFF;
+}
+
+button.btn-violet {
+	background: #a824e4;
+	color: #FFFFFF;
+}
+
+button.btn-yellow {
+	background: #ffd127;
+	color: #FFFFFF;
+}
+
+button.btn-gray {
+	background: #CCCCCC;
+	color: #FFFFFF;
+}
+
+button.btn-red-border {
+	background: #FFFFFF;
+	border: 1px solid #f6220c;
+	color: #f6220c;
+}
+
+button.btn-gray-border {
+	background: #FFFFFF;
+	border: 1px solid #CCCCCC;
+	color: #333333;
+}
+
+button.btn-green {
+	background: #44B549;
+	color: #FFFFFF;
+}
+
+button::after {
+	border: none;
+}
+
+button.btn-red[disabled][type=primary],
+button.btn-gray-border[disabled][type=primary] {
+	background-color: #BBBBBB;
+	color: rgba(255, 255, 255, .6);
+}
+
+/*backgroud*/
+.bg-white {
+	background: #FFFFFF;
+}
+
+/*border*/
+.br12{
+	border-radius: 12rpx;
+}
+.border {
+	border: 1rpx solid #DDDDDD;
+}
+
+.border-t {
+	border-top: 1rpx solid #DDDDDD;
+}
+.border-t-d9 {
+	border-top: 1rpx solid #D9D9D9;
+}
+.border-b {
+	border-bottom: 1rpx solid #DDDDDD;
+}
+
+.border-b-d9 {
+	border-bottom: 1rpx solid #D9D9D9;
+}
+
+.border-b-e {
+	border-bottom: 1rpx solid #EEEEEE;
+}
+
+.border-b-d {
+	border-bottom: 1rpx solid #D9D9D9;
+}
+
+.border-red {
+	border: 1rpx solid #f6220c;
+}
+
+/*position*/
+.pr {
+	position: relative;
+}
+
+.pa {
+	position: absolute;
+}
+
+/**/
+.top0 {
+	top: 0;
+}
+
+.right0 {
+	right: 0;
+}
+
+.bottom0 {
+	bottom: 0;
+}
+
+.left0 {
+	left: 0;
+}
+
+/*font*/
+.f20 {
+	font-size: 20rpx;
+}
+
+.f22 {
+	font-size: 22rpx;
+}
+
+.f24 {
+	font-size: 24rpx;
+}
+
+.f26 {
+	font-size: 26rpx;
+}
+
+.f28 {
+	font-size: 28rpx;
+}
+
+.f30 {
+	font-size: 30rpx;
+}
+
+.f32 {
+	font-size: 32rpx;
+}
+
+.f34 {
+	font-size: 34rpx;
+}
+
+.f36 {
+	font-size: 36rpx;
+}
+.f38{
+	font-size: 36rpx;
+}
+
+.f40 {
+	font-size: 40rpx;
+}
+
+.f50 {
+	font-size: 50rpx;
+}
+
+.f60 {
+	font-size: 60rpx;
+}
+
+.fb {
+	font-weight: bold;
+}
+
+/*text align*/
+.tc {
+	text-align: center;
+}
+
+.tr {
+	text-align: right;
+}
+
+/*overflow*/
+.o-h {
+	overflow: hidden;
+}
+
+/*word*/
+.w-b {
+	word-wrap: break-word
+}
+
+/*flex*/
+.flex-1 {
+	flex: 1;
+}
+
+/*icon*/
+.svg-icon {
+	width: 1em;
+	height: 1em;
+	vertical-align: -0.15em;
+	fill: currentColor;
+	overflow: hidden;
+}
+
+.svg-icon {
+	width: 32rpx;
+	height: 32rpx;
+	color: #CCCCCC;
+}
+
+.icon-box {
+	display: flex;
+	justify-content: center;
+	align-items: center;
+}
+
+.iconfont {
+	color: #CCCCCC;
+}
+
+.box-s-b {
+	box-sizing: border-box;
+}
+
+/*width*/
+.ww100 {
+	width: 100%;
+}
+
+.ww50 {
+	width: 50%;
+}
+
+.ww33 {
+	width: 33.33333333%;
+}
+
+.ww25 {
+	width: 25%;
+}
+
+.ww20 {
+	width: 20%;
+}
+
+.hh100 {
+	height: 100%;
+}
+
+/*padding*/
+.p10 {
+	padding: 10rpx;
+}
+
+.p20 {
+	padding: 20rpx;
+}
+
+.p30 {
+	padding: 30rpx;
+}
+
+.p-10-0 {
+	padding: 10rpx 0;
+}
+
+.p-20-0 {
+	padding: 20rpx 0;
+}
+
+.p-30-0 {
+	padding: 30rpx 0;
+}
+
+.p-40-0 {
+	padding: 40rpx 0;
+}
+
+.p-0-10 {
+	padding: 0 10rpx;
+}
+
+.p-0-20 {
+	padding: 0 20rpx;
+}
+
+.p-0-30 {
+	padding: 0 30rpx;
+}
+
+.pt10 {
+	padding-top: 10rpx;
+}
+
+.pt16 {
+	padding-top: 16rpx;
+}
+
+.pt20 {
+	padding-top: 20rpx;
+}
+
+.pt30 {
+	padding-top: 30rpx;
+}
+
+.pt40 {
+	padding-top: 40rpx;
+}
+
+.pt60 {
+	padding-top: 60rpx;
+}
+.pl30 {
+	padding-left: 30rpx;
+}
+.pr20 {
+	padding-right: 20rpx;
+}
+
+.pr100 {
+	padding-right: 100rpx;
+}
+
+.pb0 {
+	padding-bottom: 0;
+}
+
+.pb10 {
+	padding-bottom: 10rpx;
+}
+
+.pb20 {
+	padding-bottom: 20rpx;
+}
+
+.pb30 {
+	padding-bottom: 30rpx;
+}
+
+.pb60 {
+	padding-bottom: 60rpx;
+}
+
+.pb38 {
+	padding-bottom: 38rpx;
+}
+
+.pb100 {
+	padding-bottom: 100rpx;
+}
+
+/*margin*/
+.m20{
+	margin: 20rpx;
+}
+.m-0-20 {
+	margin: 0 20rpx;
+}
+
+.mt10 {
+	margin-top: 10rpx;
+}
+
+.mt20 {
+	margin-top: 20rpx;
+}
+
+.mt30 {
+	margin-top: 30rpx;
+}
+.mt36 {
+	margin-top: 36rpx;
+}
+.mt50 {
+	margin-top: 50rpx;
+}
+
+.mt60 {
+	margin-top: 60rpx;
+}
+
+.mr10 {
+	margin-right: 10rpx;
+}
+
+.mr20 {
+	margin-right: 20rpx;
+}
+
+.mr30 {
+	margin-right: 30rpx;
+}
+
+.mr40 {
+	margin-right: 40rpx;
+}
+
+.mb10 {
+	margin-bottom: 10rpx;
+}
+.mb16 {
+	margin-bottom: 16rpx;
+}
+.mb20 {
+	margin-bottom: 20rpx;
+}
+
+.mb23 {
+	margin-bottom: 23rpx;
+}
+
+.mb30 {
+	margin-bottom: 30rpx;
+}
+
+.ml10 {
+	margin-left: 10rpx;
+}
+
+.ml20 {
+	margin-left: 20rpx;
+}
+
+.ml26 {
+	margin-left: 26rpx;
+}
+
+.ml30 {
+	margin-left: 30rpx;
+}
+
+.ml80 {
+	margin-left: 80rpx;
+}
+
+/*display*/
+.d-f {
+	display: flex;
+}
+
+.d-c-c {
+	display: flex;
+	justify-content: center;
+	align-items: center;
+}
+.d-c-e {
+	display: flex;
+	justify-content: center;
+	align-items: flex-end;
+}
+
+.d-s-c {
+	display: flex;
+	justify-content: flex-start;
+	align-items: center;
+}
+.d-s-e {
+	display: flex;
+	justify-content: flex-start;
+	align-items: flex-end;
+}
+.d-s-s {
+	display: flex;
+	justify-content: flex-start;
+	align-items: flex-start;
+}
+
+.d-e-c {
+	display: flex;
+	justify-content: flex-end;
+	align-items: center;
+}
+
+.d-b-c {
+	display: flex;
+	justify-content: space-between;
+	align-items: center;
+}
+
+.d-b-s {
+	display: flex;
+	justify-content: space-between;
+	align-items: flex-start;
+}
+
+.d-a-c {
+	display: flex;
+	justify-content: space-around;
+	align-items: center;
+}
+
+.d-c {
+	flex-direction: column;
+}
+
+.d-r {
+	flex-direction: row;
+}
+
+.d-stretch {
+	align-items: stretch;
+	align-content: stretch;
+}
+
+.f-w {
+	flex-wrap: wrap;
+}
+
+.w-s-n {
+	white-space: nowrap;
+}
+
+.text-l-t {
+	text-decoration: line-through;
+}
+
+.lh100 {
+	line-height: 100%;
+}
+
+.lh150 {
+	line-height: 150%;
+}
+
+.lh200 {
+	line-height: 200%;
+}
+
+.radius {
+	border-radius: 50%;
+}
+
+.radius8 {
+	border-radius: 8rpx;
+}
+
+/*ellipsis*/
+.text-ellipsis {
+	display: -webkit-box;
+	word-break: break-all;
+	text-overflow: ellipsis;
+	overflow: hidden;
+	-webkit-box-orient: vertical;
+	-webkit-line-clamp: 1;
+}
+
+.text-ellipsis-2 {
+	display: -webkit-box;
+	word-break: break-all;
+	text-overflow: ellipsis;
+	overflow: hidden;
+	-webkit-box-orient: vertical;
+	-webkit-line-clamp: 2;
+}
+
+/*btn*/
+uni-button:after {
+	border: 0;
+}
+
+.text-d-line {
+	text-decoration: line-through;
+}
+
+
+image {
+	display: block;
+	vertical-align: top;
+	vertical-align: text-top;
+	vertical-align: bottom;
+	vertical-align: text-bottom;
+	font-size: 0;
+}
+
+/* image{ background: url(./static/default.png)  center center no-repeat; background-size:100% 100%;} */
+
+/**/
+.none-data-box {
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	flex-direction: column;
+	padding: 80rpx 30rpx;
+}
+
+.none-data-box image {
+	background: none;
+	width: 200rpx;
+}
+
+.none-data-box text {
+	padding-top: 30rpx;
+	font-size: 30rpx;
+	color: #999999;
+}
+
+/*search*/
+/*search*/
+
+
+.index-search-box {
+	background: #efefef;
+	padding: 16rpx 20rpx 18rpx 20rpx;
+	border-bottom: 1px solid #d8d8d8;
+}
+
+.index-search-box-cate {
+	background: $dominant-color;
+	padding: 20rpx;
+	padding-bottom: 60rpx;
+	/* border-bottom: 1px solid #d8d8d8; */
+}
+
+.index-search {
+	display: flex;
+	justify-content: flex-start;
+	align-items: center;
+	padding: 0 20rpx;
+	height: 80rpx;
+	line-height: 80rpx;
+	background: #FFFFFF;
+	border-radius: 16rpx;
+	border: 1px solid #d7d7d7;
+	overflow: hidden;
+	font-size: 30rpx;
+	color: #999;
+	box-sizing: border-box;
+}
+
+.index-search-cate {
+	display: flex;
+	justify-content: flex-start;
+	align-items: center;
+	padding: 0 30rpx;
+	height: 60rpx;
+	line-height: 60rpx;
+	background: #f2f2f2;
+	border-radius: 30rpx;
+	border: 1px solid #d7d7d7;
+	overflow: hidden;
+	font-size: 26rpx;
+	color: #999;
+	box-sizing: border-box;
+}
+
+.index-search-box_re {
+	background: #ffffff;
+	padding: 14rpx 20rpx 18rpx 20rpx;
+	border-bottom: none;
+}
+
+.index-search_re {
+	display: flex;
+	justify-content: flex-start;
+	align-items: center;
+	padding: 0 20rpx;
+	height: 60rpx;
+	line-height: 60rpx;
+	background: #F2F2F2;
+	border-radius: 30rpx;
+	border: none;
+	overflow: hidden;
+	font-size: 26rpx;
+	color: #999;
+	box-sizing: border-box;
+}
+
+.index-search .svg-icon {
+	margin-right: 10rpx;
+}
+
+/*group*/
+.group {
+	margin-top: 20rpx;
+	padding: 10rpx 30rpx;
+}
+
+.group-white {
+	margin-top: 30rpx;
+	padding: 10rpx 30rpx;
+	border-radius: 16rpx;
+	background: #FFFFFF;
+}
+
+.group-hd {
+	display: flex;
+	justify-content: space-between;
+	height: 90rpx;
+}
+
+.group-hd .left,
+.group-hd .right {
+	display: flex;
+	justify-content: flex-start;
+	align-items: center;
+}
+
+.group-hd .left .name {
+	margin-right: 10rpx;
+	font-size: 36rpx;
+	font-weight: bold;
+	line-height: 90rpx;
+}
+
+.group-hd .left .min-name {
+	margin-right: 10rpx;
+	font-size: 30rpx;
+	line-height: 90rpx;
+}
+
+.group-hd .left .svg-icon {
+	margin-right: 10rpx;
+}
+
+.group-hd .left .num {
+	font-size: 30rpx;
+}
+
+.group-hd .right .more {
+	font-size: 28rpx;
+	color: #999999;
+	line-height: 90rpx;
+}
+
+.group-hd .right .svg-icon {
+	margin-left: 10rpx;
+}
+
+.group-bd .list {
+	display: flex;
+	flex-wrap: wrap;
+	flex: 1;
+	justify-content: space-between;
+}
+
+/*product*/
+.product-list {
+	display: flex;
+	justify-content: space-between;
+	flex-wrap: wrap;
+}
+
+.product-list .item {
+	width: 340rpx;
+	background: #FFFFFF;
+	margin-top: 30rpx;
+	border-radius: 8rpx;
+}
+
+.product-list .item image {
+	width: 340rpx;
+	height: 340rpx;
+}
+
+.product-list .item .info {
+	padding: 0 20rpx;
+}
+
+.product-list .item .name {
+	height: 80rpx;
+	line-height: 40rpx;
+}
+
+.product-list .item .price {
+	height: 80rpx;
+	line-height: 80rpx;
+	color: #F6220C;
+}
+
+.product-list .item .unit {
+	font-size: 22rpx;
+}
+
+.product-list .item .num {
+	font-size: 44rpx;
+}
+
+/*comment*/
+.product-comment .group-hd,
+.product-content .group-hd {
+	padding: 0 30rpx;
+}
+
+.comment-list {
+	padding: 0 30rpx;
+}
+
+.comment-list .item {
+	padding: 20rpx 0;
+	border-top: 1px solid #DDDDDD;
+}
+
+.comment-list .cmt-user {
+	display: flex;
+	justify-content: space-between;
+	align-items: center;
+}
+
+.comment-list .cmt-user .left {
+	display: flex;
+	justify-content: flex-start;
+	align-items: center;
+}
+
+.comment-list .cmt-user .photo {
+	width: 80rpx;
+	height: 80rpx;
+	margin-right: 20rpx;
+	border-radius: 40rpx;
+	background: #EEEEEE;
+}
+
+.comment-list .cmt-user .name {
+	font-size: 24rpx;
+}
+
+.comment-list .cmt-user .datetime {
+	font-size: 24rpx;
+	color: #CCCCCC;
+}
+
+
+/**/
+.one-product .cover,
+.one-product .cover image {
+	width: 160rpx;
+	height: 160rpx;
+}
+
+.one-product .pro-info {
+	padding: 0 30rpx;
+	display: -webkit-box;
+	overflow: hidden;
+	-webkit-line-clamp: 2;
+	-webkit-box-orient: vertical;
+	font-size: 28rpx;
+	color: #666666;
+}
+
+.one-product .price {
+	color: #e2231a;
+}
+
+/*order state*/
+.order-state {
+	position: relative;
+	padding: 30rpx;
+	background: #e2231a;
+	color: #ffffff;
+	opacity: 0.8;
+}
+
+.order-state .icon-box .iconfont {
+	font-size: 50rpx;
+	color: #ffffff;
+}
+
+.order-state .state-cont {
+	margin-left: 20rpx;
+	font-size: 24rpx;
+}
+
+.order-state .dot-bg {
+	width: 60rpx;
+	height: 40rpx;
+	right: 200rpx;
+	top: 0;
+	border-radius: 0 0 50% 50%/50%;
+}
+
+.order-state .dot-bg,
+.order-state::after {
+	content: '';
+	position: absolute;
+	background-image: -webkit-linear-gradient(53deg, rgba(255, 255, 255, 0) 8%, rgba(255, 255, 255, 0.1) 78%);
+	background-image: linear-gradient(37deg, rgba(255, 255, 255, 0) 8%, rgba(255, 255, 255, 0.1) 78%);
+}
+
+.order-state:before {
+	content: '';
+	position: absolute;
+	width: 50px;
+	height: 20px;
+	left: 0;
+	bottom: 0;
+	border-radius: 0 100% 0 0;
+	background-image: -webkit-linear-gradient(60deg, rgba(255, 255, 255, 0) 32%, rgba(255, 255, 255, 0.1) 69%);
+	background-image: linear-gradient(30deg, rgba(255, 255, 255, 0) 32%, rgba(255, 255, 255, 0.1) 69%);
+}
+
+.order-state::after {
+	width: 50rpx;
+	height: 90rpx;
+	right: 0;
+	bottom: 0;
+	border-radius: 100% 0 0 100%/50%;
+}
+
+/*confirm order*/
+.add-address {
+	padding: 20rpx;
+}
+
+.address-defalut-wrap {
+	padding: 20rpx 30rpx;
+	background: #FFFFFF;
+}
+
+.address-defalut-wrap .info {
+	display: flex;
+	font-size: 24rpx;
+}
+
+.address-defalut-wrap .info .state,
+.address-defalut-wrap .info .type {
+	padding: 2rpx 10rpx;
+	margin-right: 10rpx;
+	background: #f6220c;
+	color: #FFFFFF;
+	border-radius: 8rpx;
+	font-size: 22rpx;
+}
+
+.address-defalut-wrap .info .type {
+	background: #007AFF;
+}
+
+.address-defalut-wrap .info .province-c-a {
+	color: #666666;
+	line-height: 1.2;
+}
+
+.address-defalut-wrap .address {
+	margin-top: 16rpx;
+	display: flex;
+	justify-content: space-between;
+	align-items: center;
+}
+
+.address-defalut-wrap .address text {
+	flex: 1;
+	font-size: 32rpx;
+}
+
+.address-defalut-wrap .address .icon-box {
+	display: flex;
+	justify-content: flex-end;
+	align-items: center;
+	width: 60rpx;
+	height: 60rpx;
+}
+
+.address-defalut-wrap .user {
+	margin-top: 16rpx;
+	font-size: 24rpx;
+}
+
+.address-defalut-wrap .user .name {
+	margin-right: 10rpx;
+}
+
+.addree-bottom {
+	width: 750rpx;
+	height: 16rpx;
+	background: #F2F2F2;
+	display: flex;
+	overflow: hidden;
+}
+
+.addree-bottom .stripe {
+	flex: 1;
+	display: flex;
+}
+
+.addree-bottom .stripe text {
+	display: block;
+	height: 10rpx;
+	transform: skew(-45deg);
+}
+
+.addree-bottom .stripe .red {
+	flex: 4;
+	background: #f6220c;
+}
+
+.addree-bottom .stripe .white {
+	flex: 1;
+	background: #FFFFFF;
+}
+
+.addree-bottom .stripe .blue {
+	flex: 4;
+	background: #8bb5e8;
+}
+
+.vender,
+.wrap .buy-checkout,
+.buyer-message {
+	margin-top: 20rpx;
+	background: #FFFFFF;
+}
+
+.vender .group-hd {
+	padding: 0 30rpx;
+	border-bottom: 1px solid #EEEEEE;
+}
+
+.vender .list .item {
+	/* display: flex; */
+	padding: 20rpx 30rpx;
+	border-bottom: 1px solid #EEEEEE;
+}
+
+.vender .list .cover {
+	width: 150rpx;
+	height: 150rpx;
+}
+
+.vender .list .cover image {
+	width: 100%;
+	height: 100%;
+}
+
+.vender .list .info {
+	flex: 1;
+	padding-left: 20rpx;
+	box-sizing: border-box;
+	overflow: hidden;
+}
+
+.vender .list .title,
+.vender .list .describe {
+	width: 340rpx;
+	word-break: break-all;
+	text-overflow: ellipsis;
+	display: -webkit-box;
+	-webkit-box-orient: vertical;
+	-webkit-line-clamp: 2;
+	overflow: hidden;
+}
+
+.vender .list .describe {
+	font-size: 24rpx;
+	color: #999999;
+}
+
+.vender .list .price {
+	color: #333333;
+	font-size: 20rpx;
+}
+
+.vender .list .price .num {
+	padding: 0 4rpx;
+	font-size: 32rpx;
+}
+
+.vender .level-box {
+	display: flex;
+	justify-content: space-between;
+	align-items: center;
+}
+
+.vender .level-box .key {
+	font-size: 24rpx;
+	color: #999999;
+}
+
+.vender .level-box .num-wrap {
+	display: flex;
+	justify-content: flex-end;
+	align-items: center;
+}
+
+.vender .level-box .icon-box {
+	width: 60rpx;
+	height: 60rpx;
+	border: 1px solid #DDDDDD;
+	background: #f7f7f7;
+}
+
+.vender .level-box .text-wrap {
+	margin: 0 4rpx;
+	height: 60rpx;
+	line-height: 0;
+	border: 1px solid #DDDDDD;
+	background: #f7f7f7;
+}
+
+.vender .level-box .text-wrap input {
+	padding: 0 10rpx;
+	height: 60rpx;
+	line-height: 0;
+	text-align: center;
+	width: 80rpx;
+	font-size: 24rpx;
+}
+
+
+.vender .total-box {
+	display: flex;
+	justify-content: space-between;
+	padding: 0 30rpx;
+	height: 80rpx;
+	line-height: 80rpx;
+}
+
+.buy-checkout .item {
+	min-height: 50rpx;
+	line-height: 50rpx;
+	padding: 30rpx;
+	display: flex;
+	justify-content: space-between;
+	border-bottom: 1px solid #EEEEEE;
+	font-size: 26rpx;
+}
+
+.buyer-message {
+	padding: 20rpx;
+	font-size: 28rpx;
+}
+
+.buyer-message .textarea {
+	width: 100%;
+	height: 60rpx;
+	line-height: 60rpx;
+	padding: 10rpx;
+	box-sizing: border-box;
+	font-size: 28rpx;
+	background: #EEEEEE;
+}
+
+.foot-pay-btns {
+	position: fixed;
+	padding: 0 20rpx;
+	display: flex;
+	justify-content: space-between;
+	align-items: center;
+	right: 0;
+	bottom: 0;
+	left: 0;
+	height: 120rpx;
+	background: #FFFFFF;
+	border-top: 1rpx solid #EEEEEE;
+	z-index: 99;
+}
+
+.foot-pay-btns .price,
+.vender .total-box .price,
+.buy-checkout .price {
+	color: #f6220c;
+}
+
+.foot-pay-btns .price .num {
+	font-size: 44rpx;
+	font-weight: bold;
+}
+
+.foot-pay-btns button {
+	margin: 0;
+	padding: 0 40rpx;
+	height: 60rpx;
+	line-height: 60rpx;
+	border-radius: 30rpx;
+	font-size: 32rpx;
+	background: #f6220c;
+}
+
+.buy-checkout .iconfont.icon-weixin {
+	color: #04BE01;
+	font-size: 50rpx;
+}
+
+.buy-checkout .iconfont.icon-yue {
+	color: #f0de7c;
+	font-size: 50rpx;
+}
+
+.buy-checkout .item.active .iconfont.icon-xuanze {
+	color: #F6220C;
+}
+.buy-checkout .iconfont.icon-jiantou {
+	color: #999999;
+	font-size: 24rpx;
+}
+/*more upload img*/
+.upload-list {
+	flex-wrap: wrap;
+}
+
+.upload-list .item {
+	width: 220rpx;
+	height: 220rpx;
+	margin-top: 20rpx;
+	margin-right: 16rpx;
+	border: 1px solid #DDDDDD;
+}
+
+.upload-list .item:nth-child(3n),
+.upload-list .item.upload-btn {
+	margin-right: 0;
+}
+
+.upload-list .item,
+.upload-list .item image {
+	width: 214rpx;
+	height: 214rpx;
+}
+
+.upload-list .upload-btn .iconfont {
+	font-size: 60rpx;
+}
+
+/*coupon*/
+.coupon-item {
+	position: relative;
+	display: flex;
+	justify-content: flex-start;
+	align-items: center;
+	height: 200rpx;
+	color: #FFFFFF;
+}
+
+.coupon-item .circles {
+	position: absolute;
+	top: 0;
+	bottom: 0;
+	left: 0;
+	display: flex;
+	flex-direction: column;
+	justify-content: space-around;
+	align-items: stretch;
+	z-index: 30;
+}
+
+.coupon-item .circles text {
+	display: block;
+	width: 10rpx;
+	height: 20rpx;
+	background: #FFFFFF;
+	border-radius: 0 10rpx 10rpx 0
+}
+
+.coupon-item .info {
+	position: relative;
+	padding: 0 30rpx 0 40rpx;
+	width: 40rpx;
+	height: 100%;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	font-size: 40rpx;
+	line-height: 40rpx;
+	border-right: 4rpx dashed rgba(255, 255, 255, .4);
+}
+
+.coupon-item .info::before,
+.coupon-item .info::after {
+	position: absolute;
+	display: block;
+	content: '';
+	width: 30rpx;
+	height: 15rpx;
+	background: #FFFFFF;
+	z-index: 10;
+}
+
+.coupon-item .info::before {
+	top: 0;
+	right: -16rpx;
+	border-radius: 0 0 15rpx 15rpx;
+}
+
+.coupon-item .info::after {
+	bottom: 0;
+	right: -16rpx;
+	border-radius: 15rpx 15rpx 0 0;
+}
+
+.coupon-item-red {
+	background: #e62423;
+	/* linear-gradient(-128deg, #ff6d6d, #ff3636); */
+}
+
+.coupon-item-blue {
+	background: #178ed9;
+	/* linear-gradient(-128deg, #1fd6ff, #3661ff); */
+}
+
+.coupon-item-violet {
+	background: #ab0bf6;
+	/* linear-gradient(-128deg, #d63efc, #6600c3); */
+}
+
+.coupon-item-yellow {
+	background: #f4a50b;
+	/* linear-gradient(-128deg, #ffe31f, #ffaf36); */
+}
+
+.coupon-item-gray {
+	background: #999999;
+	/* linear-gradient(-128deg, #888888, #999999); */
+}
+
+.coupon-item .operation {
+	position: relative;
+	height: 100%;
+	padding-left: 28rpx;
+	flex: 1;
+	overflow: hidden;
+	box-sizing: border-box;
+}
+
+.coupon-item .operation .coupon-content {
+	height: 100%;
+	padding: 20rpx;
+	box-sizing: border-box;
+	display: flex;
+	justify-content: space-around;
+	align-items: flex-start;
+	flex-direction: column;
+}
+
+.coupon-item .btns {
+	padding: 0 30rpx;
+	width: 30rpx;
+	height: 100%;
+	background: rgba(0, 0, 0, .2);
+}
+
+.coupon-item .right-box {
+	padding-right: 30rpx;
+}
+
+.coupon-item .btns button {
+	text-align: 0;
+	padding: 0;
+	width: 30rpx;
+	border-radius: 0;
+	font-size: 30rpx;
+	line-height: 36rpx;
+	background: none;
+}
+
+.rule-wrap {
+	overflow: hidden;
+	height: 0;
+}
+
+.rule-wrap.rule-wrap-auto {
+	height: auto;
+}
+
+.item-wrap .rule {
+	padding: 30rpx;
+	box-sizing: border-box;
+	border-top: dashed 1px #CCCCCC;
+	background: #FFFFFF;
+}
+
+
+/*top-tab*/
+.top-tabbar {
+	height: 96rpx;
+	line-height: 96rpx;
+	display: flex;
+	justify-content: space-between;
+	align-items: center;
+	padding: 0 20rpx;
+	box-sizing: border-box;
+	background: #FFFFFF;
+	border-bottom: 1px solid #f2f2f2;
+}
+
+.tab-item {
+	flex: 1;
+	height: 96rpx;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	font-size: 30rpx;
+	color: #999999;
+}
+
+.tab-item.active {
+	/* border-bottom: 2px solid #f6220c; */
+	margin-bottom: -2px;
+	color: #333333;
+	font-size: 32rpx;
+	font-family: PingFang SC;
+	font-weight: bold;
+	position: relative;
+}
+
+.tab-item.active::after {
+	content: '';
+	width: 72rpx;
+	height: 4rpx;
+	background: #EE1414;
+	border-radius: 2rpx;
+	position: absolute;
+	bottom: 16rpx;
+}
+
+.active-top-tab {
+	/* position: absolute; */
+	/* bottom: 125rpx; */
+	/* z-index: 22; */
+	/* width: 100%; */
+}
+
+/*列表刷新*/
+.top-refresh {
+	overflow: hidden;
+	height: 0;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	transition: height .5s;
+}
+
+.top-refresh.open {
+	height: 96rpx;
+}
+
+.top-refresh .circle {
+	width: 30rpx;
+	height: 30rpx;
+	margin: 0 10rpx;
+	background: #CCCCCC;
+	border-radius: 50%;
+	transform: scale(0);
+	animation: bulge 2s infinite ease-in-out;
+}
+
+@keyframes bulge {
+	50% {
+		transform: scale(1);
+	}
+}
+
+.top-refresh .circle:nth-child(1) {
+	animation-delay: 0s;
+}
+
+.top-refresh .circle:nth-child(2) {
+	animation-delay: .25s;
+}
+
+.top-refresh .circle:nth-child(3) {
+	animation-delay: .50s;
+}
+
+/*foot-btns*/
+.foot-btns {
+	position: fixed;
+	right: 0;
+	bottom: 0;
+	left: 0;
+	height: 90rpx;
+	padding: 0 30rpx;
+	display: flex;
+	justify-content: flex-end;
+	align-items: center;
+	z-index: 99;
+	background: #FFFFFF;
+	box-shadow: 0 -2rpx 8rpx 0 rgba(0, 0, 0, .1);
+}
+
+/*cover*/
+uni-image {
+	width: 100%;
+	height: 100%;
+}
+
+
+.status_bar {
+	height: var(--status-bar-height);
+	width: 100%;
+	background-color: #f6220c;
+}
+
+.top_view {
+	height: var(--status-bar-height);
+	width: 100%;
+	position: fixed;
+	background-color: #f6220c;
+	top: 0;
+	z-index: 9999;
+}
+
+/*  */
+.select_spec {
+	overflow: hidden;
+	text-overflow: ellipsis;
+	white-space: nowrap;
+	font-size: 26rpx;
+	color: #333333;
+}
+.state_top{
+	width: 100%;
+	height: 50rpx;
+}

+ 1458 - 0
common/uni.css

@@ -0,0 +1,1458 @@
+@font-face {
+	font-family: uniicons;
+	font-weight: normal;
+	font-style: normal;
+	src: url('https://img-cdn-qiniu.dcloud.net.cn/fonts/uni.ttf') format('truetype');
+}
+
+/*通用 */
+view{
+	font-size:28upx; 
+	line-height:1.8;
+}
+progress, checkbox-group{
+	width: 100%;
+}
+form {
+	width: 100%;
+}
+.uni-flex {
+	display: flex;
+	flex-direction: row;
+}
+.uni-flex-item {
+	flex: 1;
+}
+.uni-row {
+	flex-direction: row;
+}
+.uni-column {
+	flex-direction: column;
+}
+.uni-link{
+	color:#576B95;
+	font-size:26upx;
+}
+.uni-center{
+	text-align:center;
+}
+.uni-inline-item{
+	display: flex;
+	flex-direction: row;
+	align-items:center;
+}
+.uni-inline-item text{
+	margin-right: 20upx;
+}
+.uni-inline-item text:last-child{
+	margin-right: 0upx;
+	margin-left: 20upx;
+}
+
+/* page */
+.uni-page-head{
+	padding:35upx; 
+	text-align: center;
+}
+.uni-page-head-title {
+	display: inline-block;
+	padding: 0 40upx;
+	font-size: 30upx;
+	height: 88upx;
+	line-height: 88upx;
+	color: #BEBEBE;
+	box-sizing: border-box;
+	border-bottom: 2upx solid #D8D8D8;
+}
+.uni-page-body {
+	width: 100%;
+	flex-grow: 1;
+	overflow-x: hidden;
+}
+.uni-padding-wrap{
+	width:690upx;
+	padding:0 30upx;
+}
+.uni-word {
+	text-align: center;
+	padding:200upx 100upx;
+}
+.uni-title {
+	font-size:30upx;
+	font-weight:500;
+	padding:20upx 0;
+	line-height:1.5;
+}
+.uni-text{
+	font-size:28upx;
+}
+.uni-title text{
+	font-size:24upx; 
+	color:#888;
+}
+
+.uni-text-gray{
+	color: #ccc;
+}
+.uni-text-small {
+	font-size:24upx;
+}
+.uni-common-mb{
+	margin-bottom:30upx;
+}
+.uni-common-pb{
+	padding-bottom:30upx;
+}
+.uni-common-pl{
+	padding-left:30upx;
+}
+.uni-common-mt{
+	margin-top:30upx;
+}
+/* 背景色 */
+.uni-bg-red{
+	background:#F76260; color:#FFF;
+}
+.uni-bg-green{
+	background:#09BB07; color:#FFF;
+}
+.uni-bg-blue{
+	background:#007AFF; color:#FFF;
+}
+/* 标题 */
+.uni-h1 {font-size: 80upx; font-weight:700;}
+.uni-h2 {font-size: 60upx; font-weight:700;}
+.uni-h3 {font-size: 48upx; font-weight:700;}
+.uni-h4 {font-size: 36upx; font-weight:700;}
+.uni-h5 {font-size: 28upx; color: #8f8f94;}
+.uni-h6 {font-size: 24upx; color: #8f8f94;}
+.uni-bold{font-weight:bold;}
+
+/* 文本溢出隐藏 */
+.uni-ellipsis {overflow: hidden; white-space: nowrap; text-overflow: ellipsis;}
+
+/* 竖向百分百按钮 */
+.uni-btn-v{
+	padding:10upx 0;
+}
+.uni-btn-v button{margin:20upx 0;}
+
+/* 表单 */
+.uni-form-item{
+	display:flex;
+	width:100%;
+	padding:10upx 0;
+}
+.uni-form-item .title{
+	padding:10upx 25upx;
+}
+.uni-label {
+	width: 210upx;
+	word-wrap: break-word;
+	word-break: break-all;
+	text-indent:20upx;
+}
+.uni-input {
+	height: 50upx;
+	padding: 15upx 25upx;
+	line-height:50upx;
+	font-size:28upx;
+	background:#FFF;
+	flex: 1;
+}
+radio-group, checkbox-group{
+	width:100%;
+}
+radio-group label, checkbox-group label{
+	padding-right:20upx;
+}
+.uni-form-item .with-fun{
+	display:flex; 
+	flex-wrap:nowrap; 
+	background:#FFFFFF;
+}
+.uni-form-item .with-fun .uni-icon{
+	width:40px; 
+	height:80upx; 
+	line-height:80upx; 
+	flex-shrink:0;
+}
+
+/* loadmore */
+.uni-loadmore{
+	height:80upx;
+	line-height:80upx;
+	text-align:center;
+	padding-bottom:30upx;
+}
+/*数字角标*/
+.uni-badge,
+.uni-badge-default {
+	font-family: 'Helvetica Neue', Helvetica, sans-serif;
+	font-size: 12px;
+	line-height: 1;
+	display: inline-block;
+	padding: 3px 6px;
+	color: #333;
+	border-radius: 100px;
+	background-color: rgba(0, 0, 0, .15);
+}
+.uni-badge.uni-badge-inverted {
+	padding: 0 5px 0 0;
+	color: #929292;
+	background-color: transparent
+}
+.uni-badge-primary {
+	color: #fff;
+	background-color: #007aff
+}
+.uni-badge-blue.uni-badge-inverted,
+.uni-badge-primary.uni-badge-inverted {
+	color: #007aff;
+	background-color: transparent
+}
+.uni-badge-green,
+.uni-badge-success {
+	color: #fff;
+	background-color: #4cd964;
+}
+.uni-badge-green.uni-badge-inverted,
+.uni-badge-success.uni-badge-inverted {
+	color: #4cd964;
+	background-color: transparent
+}
+.uni-badge-warning,
+.uni-badge-yellow {
+	color: #fff;
+	background-color: #f0ad4e
+}
+.uni-badge-warning.uni-badge-inverted,
+.uni-badge-yellow.uni-badge-inverted {
+	color: #f0ad4e;
+	background-color: transparent
+}
+.uni-badge-danger,
+.uni-badge-red {
+	color: #fff;
+	background-color: #dd524d
+}
+.uni-badge-danger.uni-badge-inverted,
+.uni-badge-red.uni-badge-inverted {
+	color: #dd524d;
+	background-color: transparent
+}
+.uni-badge-purple,
+.uni-badge-royal {
+	color: #fff;
+	background-color: #8a6de9
+}
+.uni-badge-purple.uni-badge-inverted,
+.uni-badge-royal.uni-badge-inverted {
+	color: #8a6de9;
+	background-color: transparent
+}
+
+/*折叠面板 */
+.uni-collapse-content {
+	height: 0;
+	width: 100%;
+	overflow: hidden;
+}
+.uni-collapse-content.uni-active {
+	height: auto;
+}
+
+/*卡片视图 */
+.uni-card {
+	background: #fff;
+	border-radius: 8upx;
+	margin:20upx 0;
+	position: relative;
+	box-shadow: 0 2upx 4upx rgba(0, 0, 0, .3);
+}
+.uni-card-content {
+	font-size: 30upx;
+}
+.uni-card-content.image-view{
+    width: 100%;
+    margin: 0;
+}
+.uni-card-content-inner {
+	position: relative;
+	padding: 30upx;
+}
+.uni-card-footer,
+.uni-card-header {
+	position: relative;
+	display: flex;
+	min-height: 50upx;
+	padding: 20upx 30upx;
+	justify-content: space-between;
+	align-items: center;
+}
+.uni-card-header {
+	font-size: 36upx;
+}
+.uni-card-footer {
+	color: #6d6d72;
+}
+.uni-card-footer:before,
+.uni-card-header:after {
+	position: absolute;
+	top: 0;
+	right: 0;
+	left: 0;
+	height: 2upx;
+	content: '';
+	-webkit-transform: scaleY(.5);
+	transform: scaleY(.5);
+	background-color: #c8c7cc;
+}
+.uni-card-header:after {
+	top: auto;
+	bottom: 0;
+}
+.uni-card-media {
+	justify-content: flex-start;
+}
+.uni-card-media-logo {
+	height: 84upx;
+	width: 84upx;
+	margin-right: 20upx;
+}
+.uni-card-media-body {
+	height: 84upx;
+	display: flex;
+	flex-direction: column;
+	justify-content: space-between;
+	align-items: flex-start;
+}
+.uni-card-media-text-top {
+	line-height: 36upx;
+	font-size: 34upx;
+}
+.uni-card-media-text-bottom {
+	line-height: 30upx;
+	font-size: 28upx;
+	color: #8f8f94;
+}
+.uni-card-link {
+	color: #007AFF;
+}
+
+/* 列表 */
+.uni-list {
+	background-color: #FFFFFF;
+	position: relative;
+	width: 100%;
+	display: flex;
+	flex-direction: column;
+}
+.uni-list:after {
+	position: absolute;
+	z-index: 10;
+	right: 0;
+	bottom: 0;
+	left: 0;
+	height: 1px;
+	content: '';
+	-webkit-transform: scaleY(.5);
+	transform: scaleY(.5);
+	background-color: #c8c7cc;
+}
+.uni-list::before {
+	position: absolute;
+	z-index: 10;
+	right: 0;
+	top: 0;
+	left: 0;
+	height: 1px;
+	content: '';
+	-webkit-transform: scaleY(.5);
+	transform: scaleY(.5);
+	background-color: #c8c7cc;
+}
+.uni-list-cell {
+	position: relative;
+	display: flex;
+	flex-direction: row;
+	justify-content: space-between;
+	align-items: center;
+}
+.uni-list-cell-hover {
+	background-color: #eee;
+}
+.uni-list-cell-pd {
+	padding: 22upx 30upx;
+}
+.uni-list-cell-left {
+	font-size:28upx;
+	padding: 0 30upx;
+}
+.uni-list-cell-db,
+.uni-list-cell-right {
+	flex: 1;
+}
+.uni-list-cell::after {
+	position: absolute;
+  z-index: 3;
+	right: 0;
+	bottom: 0;
+	left: 30upx;
+	height: 1px;
+	content: '';
+	-webkit-transform: scaleY(.5);
+	transform: scaleY(.5);
+	background-color: #c8c7cc;
+}
+.uni-list .uni-list-cell:last-child::after {
+	height: 0upx;
+}
+.uni-list-cell-last.uni-list-cell::after {
+	height: 0upx;
+}
+.uni-list-cell-divider {
+	position: relative;
+	display: flex;
+	color: #999;
+	background-color: #f7f7f7;
+	padding:15upx 20upx;
+}
+.uni-list-cell-divider::before {
+	position: absolute;
+	right: 0;
+	top: 0;
+	left: 0;
+	height: 1px;
+	content: '';
+	-webkit-transform: scaleY(.5);
+	transform: scaleY(.5);
+	background-color: #c8c7cc;
+}
+.uni-list-cell-divider::after {
+	position: absolute;
+	right: 0;
+	bottom: 0;
+	left: 0upx;
+	height: 1px;
+	content: '';
+	-webkit-transform: scaleY(.5);
+	transform: scaleY(.5);
+	background-color: #c8c7cc;
+}
+.uni-list-cell-navigate {
+	font-size:30upx;
+	padding: 22upx 30upx;
+	line-height: 48upx;
+	position: relative;
+	display: flex;
+	box-sizing: border-box;
+	width: 100%;
+	flex: 1;
+	justify-content: space-between;
+	align-items: center;
+}
+.uni-list-cell-navigate {
+	padding-right: 36upx;
+}
+.uni-navigate-badge {
+	padding-right: 50upx;
+}
+.uni-list-cell-navigate.uni-navigate-right:after {
+	font-family: uniicons;
+	content: '\e583';
+	position: absolute;
+	right: 24upx;
+	top: 50%;
+	color: #bbb;
+	-webkit-transform: translateY(-50%);
+	transform: translateY(-50%);
+}
+.uni-list-cell-navigate.uni-navigate-bottom:after {
+	font-family: uniicons;
+	content: '\e581';
+	position: absolute;
+	right: 24upx;
+	top: 50%;
+	color: #bbb;
+	-webkit-transform: translateY(-50%);
+	transform: translateY(-50%);
+}
+.uni-list-cell-navigate.uni-navigate-bottom.uni-active::after {
+	font-family: uniicons;
+	content: '\e580';
+	position: absolute;
+	right: 24upx;
+	top: 50%;
+	color: #bbb;
+	-webkit-transform: translateY(-50%);
+	transform: translateY(-50%);
+}
+.uni-collapse.uni-list-cell {
+	flex-direction: column;
+}
+.uni-list-cell-navigate.uni-active {
+	background: #eee;
+}
+.uni-list.uni-collapse {
+	box-sizing: border-box;
+	height: 0;
+	overflow: hidden;
+}
+.uni-collapse .uni-list-cell {
+	padding-left: 20upx;
+}
+.uni-collapse .uni-list-cell::after {
+	left: 52upx;
+}
+.uni-list.uni-active {
+	height: auto;
+}
+
+/* 三行列表 */
+.uni-triplex-row {
+	display: flex;
+	flex: 1;
+	width: 100%;
+	box-sizing: border-box;
+	flex-direction: row;
+	padding: 22upx 30upx;
+}
+.uni-triplex-right,
+.uni-triplex-left {
+	display: flex;
+	flex-direction: column;
+}
+.uni-triplex-left {
+	width: 84%;
+}
+.uni-triplex-left .uni-title{
+	padding:8upx 0;
+}
+.uni-triplex-left .uni-text, .uni-triplex-left .uni-text-small{color:#999999;}
+.uni-triplex-right {
+	width: 16%;
+	text-align: right;
+}
+
+/* 图文列表 */
+.uni-media-list {
+	padding: 22upx 30upx;
+	box-sizing: border-box;
+	display: flex;
+	width: 100%;
+	flex-direction: row;
+}
+.uni-navigate-right.uni-media-list {
+	padding-right: 74upx;
+}
+.uni-pull-right {
+	flex-direction: row-reverse;
+}
+.uni-pull-right>.uni-media-list-logo {
+	margin-right: 0upx;
+	margin-left: 20upx;
+}
+.uni-media-list-logo {
+	height: 84upx;
+	width: 84upx;
+	margin-right: 20upx;
+}
+.uni-media-list-logo image {
+	height: 100%;
+	width: 100%;
+}
+.uni-media-list-body {
+	height: 84upx;
+	display: flex;
+	flex: 1;
+	flex-direction: column;
+	justify-content: space-between;
+	align-items: flex-start;
+	overflow: hidden;
+}
+.uni-media-list-text-top {
+	width: 100%;
+	line-height: 36upx;
+	font-size: 30upx;
+}
+.uni-media-list-text-bottom {
+	width: 100%;
+	line-height: 30upx;
+	font-size: 26upx;
+	color: #8f8f94;
+}
+
+/* 九宫格 */
+.uni-grid-9 {
+	background: #f2f2f2;
+	width: 750upx;
+	display: flex;
+	flex-direction: row;
+	flex-wrap: wrap;
+	border-top: 2upx solid #eee;
+}
+.uni-grid-9-item {
+	width: 250upx;
+	height: 200upx;
+	display: flex;
+	flex-direction: column;
+	align-items: center;
+	justify-content: center;
+	border-bottom: 2upx solid;
+	border-right: 2upx solid;
+	border-color: #eee;
+	box-sizing: border-box;
+}
+.no-border-right {
+	border-right: none;
+}
+.uni-grid-9-image {
+	width: 100upx;
+	height: 100upx;
+}
+.uni-grid-9-text {
+	width: 250upx;
+	line-height: 4upx;
+	height: 40upx;
+	text-align: center;
+	font-size: 30upx;
+}
+.uni-grid-9-item-hover {
+	background: rgba(0, 0, 0, 0.1);
+}
+
+/* 上传 */
+.uni-uploader {
+	flex: 1;
+	flex-direction: column;
+}
+.uni-uploader-head {
+	display: flex;
+	flex-direction: row;
+	justify-content: space-between;
+}
+.uni-uploader-info {
+	color: #B2B2B2;
+}
+.uni-uploader-body {
+	margin-top: 16upx;
+}
+.uni-uploader__files {
+	display: flex;
+	flex-direction: row;
+	flex-wrap: wrap;
+}
+.uni-uploader__file {
+	margin: 10upx;
+	width: 210upx;
+	height: 210upx;
+}
+.uni-uploader__img {
+	display: block;
+	width: 210upx;
+	height: 210upx;
+}
+.uni-uploader__input-box {
+	position: relative;
+	margin:10upx;
+	width: 208upx;
+	height: 208upx;
+	border: 2upx solid #D9D9D9;
+}
+.uni-uploader__input-box:before,
+.uni-uploader__input-box:after {
+	content: " ";
+	position: absolute;
+	top: 50%;
+	left: 50%;
+	-webkit-transform: translate(-50%, -50%);
+	transform: translate(-50%, -50%);
+	background-color: #D9D9D9;
+}
+.uni-uploader__input-box:before {
+	width: 4upx;
+	height: 79upx;
+}
+.uni-uploader__input-box:after {
+	width: 79upx;
+	height: 4upx;
+}
+.uni-uploader__input-box:active {
+	border-color: #999999;
+}
+.uni-uploader__input-box:active:before,
+.uni-uploader__input-box:active:after {
+	background-color: #999999;
+}
+.uni-uploader__input {
+	position: absolute;
+	z-index: 1;
+	top: 0;
+	left: 0;
+	width: 100%;
+	height: 100%;
+	opacity: 0;
+}
+
+/*问题反馈*/
+.feedback-title {
+	display: flex;
+	flex-direction: row;
+	justify-content: space-between;
+	align-items: center;
+	padding: 20upx;
+	color: #8f8f94;
+	font-size: 28upx;
+}
+.feedback-star-view.feedback-title {
+	justify-content: flex-start;
+	margin: 0;
+}
+.feedback-quick {
+	position: relative;
+	padding-right: 40upx;
+}
+.feedback-quick:after {
+	font-family: uniicons;
+	font-size: 40upx;
+	content: '\e581';
+	position: absolute;
+	right: 0;
+	top: 50%;
+	color: #bbb;
+	-webkit-transform: translateY(-50%);
+	transform: translateY(-50%);
+}
+.feedback-body {
+	background: #fff;
+}
+.feedback-textare {
+	height: 200upx;
+	font-size: 34upx;
+	line-height: 50upx;
+	width: 100%;
+	box-sizing: border-box;
+	padding: 20upx 30upx 0;
+}
+.feedback-input {
+	font-size: 34upx;
+	height: 50upx;
+	min-height: 50upx;
+	padding: 15upx 20upx;
+	line-height: 50upx;
+}
+.feedback-uploader {
+	padding: 22upx 20upx;
+}
+.feedback-star {
+	font-family: uniicons;
+	font-size: 40upx;
+	margin-left: 6upx;
+}
+.feedback-star-view {
+	margin-left: 20upx;
+}
+.feedback-star:after {
+	content: '\e408';
+}
+.feedback-star.active {
+	color: #FFB400;
+}
+.feedback-star.active:after {
+	content: '\e438';
+}
+.feedback-submit {
+	background: #007AFF;
+	color: #FFFFFF;
+	margin: 20upx;
+}
+
+/* input group */
+.uni-input-group {
+	position: relative;
+	padding: 0;
+	border: 0;
+	background-color: #fff;
+}
+
+.uni-input-group:before {
+	position: absolute;
+	top: 0;
+	right: 0;
+	left: 0;
+	height: 2upx;
+	content: '';
+	transform: scaleY(.5);
+	background-color: #c8c7cc;
+}
+
+.uni-input-group:after {
+	position: absolute;
+	right: 0;
+	bottom: 0;
+	left: 0;
+	height: 2upx;
+	content: '';
+	transform: scaleY(.5);
+	background-color: #c8c7cc;
+}
+
+.uni-input-row {
+	position: relative;
+	display: flex;
+	flex-direction: row;
+	font-size:28upx;
+	padding: 22upx 30upx;
+	justify-content: space-between;
+}
+
+.uni-input-group .uni-input-row:after {
+	position: absolute;
+	right: 0;
+	bottom: 0;
+	left: 30upx;
+	height: 2upx;
+	content: '';
+	transform: scaleY(.5);
+	background-color: #c8c7cc;
+}
+
+.uni-input-row label {
+	line-height: 70upx;
+}
+
+/* textarea */
+.uni-textarea{
+	width:100%;
+	background:#FFF;
+}
+.uni-textarea textarea{
+	width:96%;
+	padding:18upx 2%;
+	line-height:1.6;
+	font-size:28upx;
+	height:150upx;
+}
+
+/* tab bar */
+.uni-tab-bar {
+	display: flex;
+	flex: 1;
+	flex-direction: column;
+	overflow: hidden;
+	height: 100%;
+}
+
+.uni-tab-bar .list {
+	width: 750upx;
+	height: 100%;
+}
+
+.uni-swiper-tab {
+	width: 100%;
+	white-space: nowrap;
+	line-height: 100upx;
+	height: 100upx;
+	border-bottom: 1px solid #c8c7cc;
+}
+
+.swiper-tab-list {
+	font-size: 30upx;
+	width: 150upx;
+	display: inline-block;
+	text-align: center;
+	color: #555;
+}
+
+.uni-tab-bar .active {
+	color: #007AFF;
+}
+
+.uni-tab-bar .swiper-box {
+	flex: 1;
+	width: 100%;
+	height: calc(100% - 100upx);
+}
+
+.uni-tab-bar-loading{
+	padding:20upx 0;
+}
+
+/* steps */
+.uni-steps{padding:20upx 30upx; flex-grow: 1; display:flex; flex-wrap:wrap;}
+.uni-steps view{display:flex; flex-wrap:wrap; float:none;}
+.uni-steps .step{width:31.3%; margin:0 1%; flex-wrap:nowrap;}
+.uni-steps .step-circle{width:50upx; height:50upx; border-radius:50upx; background:#F1F1F3; justify-content:center; line-height:50upx; flex-shrink:0; margin-right:15upx; color:#666; font-size:28upx;}
+.uni-steps .step-content{width:100%; height:22upx; border-bottom:1px solid #F1F2F3;}
+.uni-steps .step-title{line-height:50upx; height:50upx; background:#FFFFFF; width:auto; overflow:hidden; padding-right:8upx;}
+.uni-steps .current .step-circle{background:#00B26A; color:#FFFFFF;}
+.uni-steps .current .step-content{border-color:#00B26A;}
+.uni-steps .current .step-title{color:#00B26A;}
+
+/* comment */
+.uni-comment{padding:5rpx 0; display: flex; flex-grow:1; flex-direction: column;}
+.uni-comment-list{flex-wrap:nowrap; padding:10rpx 0; margin:10rpx 0; width:100%; display: flex;}
+.uni-comment-face{width:70upx; height:70upx; border-radius:100%; margin-right:20upx; flex-shrink:0; overflow:hidden;}
+.uni-comment-face image{width:100%; border-radius:100%;}
+.uni-comment-body{width:100%;}
+.uni-comment-top{line-height:1.5em; justify-content:space-between;}
+.uni-comment-top text{color:#0A98D5; font-size:24upx;}
+.uni-comment-date{line-height:38upx; flex-direction:row; justify-content:space-between; display:flex !important; flex-grow:1;}
+.uni-comment-date view{color:#666666; font-size:24upx; line-height:38upx;}
+.uni-comment-content{line-height:1.6em; font-size:28upx; padding:8rpx 0;}
+.uni-comment-replay-btn{background:#FFF; font-size:24upx; line-height:28upx; padding:5rpx 20upx; border-radius:30upx; color:#333 !important; margin:0 10upx;}
+
+/* swiper msg */
+.uni-swiper-msg{width:100%; padding:12rpx 0; flex-wrap:nowrap; display:flex;}
+.uni-swiper-msg-icon{width:50upx; margin-right:20upx;}
+.uni-swiper-msg-icon image{width:100%; flex-shrink:0;}
+.uni-swiper-msg swiper{width:100%; height:50upx;}
+.uni-swiper-msg swiper-item{line-height:50upx;}
+
+/* product */
+.uni-product-list {
+    display: flex;
+    width: 100%;
+    flex-wrap: wrap;
+    flex-direction: row;
+}
+
+.uni-product {
+    padding: 20upx;
+    display: flex;
+    flex-direction: column;
+}
+
+.image-view {
+    height: 330upx;
+    width: 330upx;
+	margin:12upx 0;
+}
+
+.uni-product-image {
+    height: 330upx;
+    width: 330upx;
+}
+
+.uni-product-title {
+    width: 300upx;
+    word-break: break-all;
+    display: -webkit-box;
+    overflow: hidden;
+	line-height:1.5;
+    text-overflow: ellipsis;
+    -webkit-box-orient: vertical;
+    -webkit-line-clamp: 2;
+}
+
+.uni-product-price {
+	margin-top:10upx;
+    font-size: 28upx;
+	line-height:1.5;
+    position: relative;
+}
+
+.uni-product-price-original {
+    color: #e80080;
+}
+
+.uni-product-price-favour {
+    color: #888888;
+    text-decoration: line-through;
+    margin-left: 10upx;
+}
+
+.uni-product-tip {
+    position: absolute;
+    right: 10upx;
+    background-color: #ff3333;
+    color: #ffffff;
+    padding: 0 10upx;
+    border-radius: 5upx;
+}
+
+/* timeline */
+.uni-timeline {
+		margin: 35upx 0;
+		display: flex;
+		flex-direction: column;
+		position: relative;
+	}
+
+
+	.uni-timeline-item {
+		display: flex;
+		flex-direction: row;
+		position: relative;
+		padding-bottom: 20upx;
+		box-sizing: border-box;
+		overflow: hidden;
+
+	}
+
+	.uni-timeline-item .uni-timeline-item-keynode {
+		width: 160upx;
+		flex-shrink: 0;
+		box-sizing: border-box;
+		padding-right: 20upx;
+		text-align: right;
+		line-height: 65upx;
+	}
+
+	.uni-timeline-item .uni-timeline-item-divider {
+		flex-shrink: 0;
+		position: relative;
+		width: 30upx;
+		height: 30upx;
+		top: 15upx;
+		border-radius: 50%;
+		background-color: #bbb;
+	}
+
+
+
+	.uni-timeline-item-divider::before,
+	.uni-timeline-item-divider::after {
+		position: absolute;
+		left: 15upx;
+		width: 1upx;
+		height: 100vh;
+		content: '';
+		background: inherit;
+	}
+
+	.uni-timeline-item-divider::before {
+		bottom: 100%;
+	}
+
+	.uni-timeline-item-divider::after {
+		top: 100%;
+	}
+
+
+	.uni-timeline-last-item .uni-timeline-item-divider:after {
+		display: none;
+	}
+
+	.uni-timeline-first-item .uni-timeline-item-divider:before {
+		display: none;
+	}
+
+	.uni-timeline-item .uni-timeline-item-content {
+		padding-left: 20upx;
+	}
+	
+	.uni-timeline-last-item .bottom-border::after{
+		display: none;
+	}
+	
+	.uni-timeline-item-content .datetime{
+		color: #CCCCCC;
+	}
+	
+	/* 自定义节点颜色 */
+	.uni-timeline-last-item .uni-timeline-item-divider{
+		background-color: #1AAD19;
+	}
+  
+  
+/* uni-icon */
+
+.uni-icon {
+	font-family: uniicons;
+	font-size: 24px;
+	font-weight: normal;
+	font-style: normal;
+	line-height: 1;
+	display: inline-block;
+	text-decoration: none;
+	-webkit-font-smoothing: antialiased;
+}
+
+.uni-icon.uni-active {
+	color: #007aff;
+}
+
+.uni-icon-contact:before {
+	content: '\e100';
+}
+
+.uni-icon-person:before {
+	content: '\e101';
+}
+
+.uni-icon-personadd:before {
+	content: '\e102';
+}
+
+.uni-icon-contact-filled:before {
+	content: '\e130';
+}
+
+.uni-icon-person-filled:before {
+	content: '\e131';
+}
+
+.uni-icon-personadd-filled:before {
+	content: '\e132';
+}
+
+.uni-icon-phone:before {
+	content: '\e200';
+}
+
+.uni-icon-email:before {
+	content: '\e201';
+}
+
+.uni-icon-chatbubble:before {
+	content: '\e202';
+}
+
+.uni-icon-chatboxes:before {
+	content: '\e203';
+}
+
+.uni-icon-phone-filled:before {
+	content: '\e230';
+}
+
+.uni-icon-email-filled:before {
+	content: '\e231';
+}
+
+.uni-icon-chatbubble-filled:before {
+	content: '\e232';
+}
+
+.uni-icon-chatboxes-filled:before {
+	content: '\e233';
+}
+
+.uni-icon-weibo:before {
+	content: '\e260';
+}
+
+.uni-icon-weixin:before {
+	content: '\e261';
+}
+
+.uni-icon-pengyouquan:before {
+	content: '\e262';
+}
+
+.uni-icon-chat:before {
+	content: '\e263';
+}
+
+.uni-icon-qq:before {
+	content: '\e264';
+}
+
+.uni-icon-videocam:before {
+	content: '\e300';
+}
+
+.uni-icon-camera:before {
+	content: '\e301';
+}
+
+.uni-icon-mic:before {
+	content: '\e302';
+}
+
+.uni-icon-location:before {
+	content: '\e303';
+}
+
+.uni-icon-mic-filled:before,
+.uni-icon-speech:before {
+	content: '\e332';
+}
+
+.uni-icon-location-filled:before {
+	content: '\e333';
+}
+
+.uni-icon-micoff:before {
+	content: '\e360';
+}
+
+.uni-icon-image:before {
+	content: '\e363';
+}
+
+.uni-icon-map:before {
+	content: '\e364';
+}
+
+.uni-icon-compose:before {
+	content: '\e400';
+}
+
+.uni-icon-trash:before {
+	content: '\e401';
+}
+
+.uni-icon-upload:before {
+	content: '\e402';
+}
+
+.uni-icon-download:before {
+	content: '\e403';
+}
+
+.uni-icon-close:before {
+	content: '\e404';
+}
+
+.uni-icon-redo:before {
+	content: '\e405';
+}
+
+.uni-icon-undo:before {
+	content: '\e406';
+}
+
+.uni-icon-refresh:before {
+	content: '\e407';
+}
+
+.uni-icon-star:before {
+	content: '\e408';
+}
+
+.uni-icon-plus:before {
+	content: '\e409';
+}
+
+.uni-icon-minus:before {
+	content: '\e410';
+}
+
+.uni-icon-circle:before,
+.uni-icon-checkbox:before {
+	content: '\e411';
+}
+
+.uni-icon-close-filled:before,
+.uni-icon-clear:before {
+	content: '\e434';
+}
+
+.uni-icon-refresh-filled:before {
+	content: '\e437';
+}
+
+.uni-icon-star-filled:before {
+	content: '\e438';
+}
+
+.uni-icon-plus-filled:before {
+	content: '\e439';
+}
+
+.uni-icon-minus-filled:before {
+	content: '\e440';
+}
+
+.uni-icon-circle-filled:before {
+	content: '\e441';
+}
+
+.uni-icon-checkbox-filled:before {
+	content: '\e442';
+}
+
+.uni-icon-closeempty:before {
+	content: '\e460';
+}
+
+.uni-icon-refreshempty:before {
+	content: '\e461';
+}
+
+.uni-icon-reload:before {
+	content: '\e462';
+}
+
+.uni-icon-starhalf:before {
+	content: '\e463';
+}
+
+.uni-icon-spinner:before {
+	content: '\e464';
+}
+
+.uni-icon-spinner-cycle:before {
+	content: '\e465';
+}
+
+.uni-icon-search:before {
+	content: '\e466';
+}
+
+.uni-icon-plusempty:before {
+	content: '\e468';
+}
+
+.uni-icon-forward:before {
+	content: '\e470';
+}
+
+.uni-icon-back:before,
+.uni-icon-left-nav:before {
+	content: '\e471';
+}
+
+.uni-icon-checkmarkempty:before {
+	content: '\e472';
+}
+
+.uni-icon-home:before {
+	content: '\e500';
+}
+
+.uni-icon-navigate:before {
+	content: '\e501';
+}
+
+.uni-icon-gear:before {
+	content: '\e502';
+}
+
+.uni-icon-paperplane:before {
+	content: '\e503';
+}
+
+.uni-icon-info:before {
+	content: '\e504';
+}
+
+.uni-icon-help:before {
+	content: '\e505';
+}
+
+.uni-icon-locked:before {
+	content: '\e506';
+}
+
+.uni-icon-more:before {
+	content: '\e507';
+}
+
+.uni-icon-flag:before {
+	content: '\e508';
+}
+
+.uni-icon-home-filled:before {
+	content: '\e530';
+}
+
+.uni-icon-gear-filled:before {
+	content: '\e532';
+}
+
+.uni-icon-info-filled:before {
+	content: '\e534';
+}
+
+.uni-icon-help-filled:before {
+	content: '\e535';
+}
+
+.uni-icon-more-filled:before {
+	content: '\e537';
+}
+
+.uni-icon-settings:before {
+	content: '\e560';
+}
+
+.uni-icon-list:before {
+	content: '\e562';
+}
+
+.uni-icon-bars:before {
+	content: '\e563';
+}
+
+.uni-icon-loop:before {
+	content: '\e565';
+}
+
+.uni-icon-paperclip:before {
+	content: '\e567';
+}
+
+.uni-icon-eye:before {
+	content: '\e568';
+}
+
+.uni-icon-arrowup:before {
+	content: '\e580';
+}
+
+.uni-icon-arrowdown:before {
+	content: '\e581';
+}
+
+.uni-icon-arrowleft:before {
+	content: '\e582';
+}
+
+.uni-icon-arrowright:before {
+	content: '\e583';
+}
+
+.uni-icon-arrowthinup:before {
+	content: '\e584';
+}
+
+.uni-icon-arrowthindown:before {
+	content: '\e585';
+}
+
+.uni-icon-arrowthinleft:before {
+	content: '\e586';
+}
+
+.uni-icon-arrowthinright:before {
+	content: '\e587';
+}
+
+.uni-icon-pulldown:before {
+	content: '\e588';
+}
+
+.uni-icon-scan:before {
+    content: "\e612";
+}
+
+/* 分界线 */
+.uni-divider{
+    height: 110upx;
+    display: flex;
+    align-items:center;
+    justify-content: center;
+    position: relative;
+}
+.uni-divider__content{
+    font-size: 28upx;
+    color: #999;
+    padding: 0 20upx;
+    position: relative;
+    z-index: 101;
+    background: #F4F5F6;
+}
+.uni-divider__line{
+    background-color: #CCCCCC;
+    height: 1px;
+    width: 100%;
+    position: absolute;
+    z-index: 100;
+    top: 50%;
+    left: 0;
+    transform: translateY(50%);
+}

+ 171 - 0
common/utils.js

@@ -0,0 +1,171 @@
+/**
+ * 工具类
+ */
+var utils = {
+	/**
+	 * scene解码
+	 */
+	scene_decode(e) {
+		if (e === undefined)
+			return {};
+		let scene = decodeURIComponent(e),
+			params = scene.split(','),
+			data = {};
+		for (let i in params) {
+			var val = params[i].split(':');
+			val.length > 0 && val[0] && (data[val[0]] = val[1] || null)
+		}
+		return data;
+	},
+
+	/**
+	 * 格式化日期格式 (用于兼容ios Date对象)
+	 */
+	format_date(time) {
+		// 将xxxx-xx-xx的时间格式,转换为 xxxx/xx/xx的格式 
+		return time.replace(/\-/g, "/");
+	},
+
+	/**
+	 * 格式化详情内容,去除图片之间的间隙,图片宽度最大100%
+	 */
+	format_content(str) {
+		return str.replace(/\<img/gi, '<img style="display:block; margin:0 auto; max-width:100%;" ');
+	},
+
+	/**
+	 * 对象转URL
+	 */
+	urlEncode(data) {
+		var _result = [];
+		for (var key in data) {
+			var value = data[key];
+			if (value.constructor == Array) {
+				value.forEach(_value => {
+					_result.push(key + "=" + _value);
+				});
+			} else {
+				_result.push(key + '=' + value);
+			}
+		}
+		return _result.join('&');
+	},
+
+	/**
+	 * 遍历对象
+	 */
+	objForEach(obj, callback) {
+		Object.keys(obj).forEach((key) => {
+			callback(obj[key], key);
+		});
+	},
+
+	/**
+	 * 是否在数组内
+	 */
+	inArray(search, array) {
+		for (var i in array) {
+			if (array[i] == search) {
+				return true;
+			}
+		}
+		return false;
+	},
+
+	/**
+	 * 判断是否为正整数
+	 */
+	isPositiveInteger(value) {
+		return /(^[0-9]\d*$)/.test(value);
+	},
+
+	/**
+	 * 获取场景值(scene)
+	 */
+	getSceneData(query) {
+		return query.scene ? this.scene_decode(query.scene) : {};
+	},
+	// 判断是否为身份证
+	isVail(value) {
+
+		if (!/^\d{17}(\d|x)$/i.test(value)) {
+			return false;
+		}
+
+		var now = new Date();
+		var yYear = Number(value.substr(6, 4));
+		var yMonth = Number(value.substr(10, 2)) + 1;
+		var yDay = Number(value.substr(12, 2));
+
+		var birthFlag = false;
+		if (yYear <= Number(now.getFullYear()) && yYear > 0) {
+			if (yMonth <= 12 && yMonth > 0) {
+				// 获取当月天数
+				 var preMonth = new Date(yYear, yMonth - 1, 0);
+
+				if (yDay <= preMonth.getDate() && yDay > 0) {
+					birthFlag = true;
+				}
+			}
+		}
+
+		if (!birthFlag) {
+			return false;
+		}
+
+		var iSum = 0;
+		value = value.replace(/x$/i, "a");
+		for (var i = 17; i >= 0; i--) {
+			iSum += (Math.pow(2, i) % 11) * parseInt(value.charAt(17 - i), 11);
+		}
+		if (iSum % 11 != 1) {
+			return false;
+		}
+		return true
+	},
+	// 判断是否为手机号
+	isPoneAvailable(pone) {
+		var myreg = /^[1][3,4,5,6,7,8,9][0-9]{9}$/;
+		if (!myreg.test(pone)) {
+			return false;
+		} else {
+			return true;
+		}
+	},
+	// 判断是否为座机或者手机号
+	isTelAvailable(tel) {
+		var myreg = /^(([0\+]\d{2,3}-)?(0\d{2,3})-)(\d{7,8})(-(\d{3,}))?$/;
+		var myregs = /^[1][3,4,5,6,7,8,9][0-9]{9}$/;
+		var flag = false;
+		if (myreg.test(tel)) {
+			flag = true;
+		}
+		if (myregs.test(tel)) {
+			flag = true;
+		}
+		if(flag){
+			return true
+		}else{
+			return false
+		}
+	},
+	// 判断是否为电子邮箱
+	isMail(mail) {
+		var filter = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
+		if (filter.test(mail)){
+			return true;
+		} else {
+			return false;
+		}
+	},
+	// 判断是否为数字
+	isNum(num) {
+		var filter = /^[0-9]*$/;
+		if (filter.test(num)){
+			return true;
+		} else {
+			return false;
+		}
+	}
+};
+export default utils;

+ 203 - 0
components/app-share.vue

@@ -0,0 +1,203 @@
+<template>
+
+	<view class="bottom-panel popup-bg" :class="Visible?'bottom-panel open':'bottom-panel close'" @click="closePopup">
+		<view class="content" v-on:click.stop>
+
+			<view class="module-box module-share">
+				<view class="hd d-c-c">
+					分享
+				</view>
+				<view class="p30 box-s-b">
+					<view class="d-c-c">
+						<view class="item flex-1 d-c-c d-c">
+							<button open-type="share" @click="share(0, 'WXSceneSession')">
+								<view class="icon-box d-c-c share-friend">
+									<text class="iconfont icon-fenxiang"></text>
+								</view>
+								<text class="pt20">微信好友</text>
+							</button>
+						</view>
+						<view class="item flex-1 d-c-c d-c">
+							<button class="d-c-c d-c" @click="share(0, 'WXSenceTimeline')">
+								<view class="icon-box d-c-c">
+									<text class="iconfont icon-edit"></text>
+								</view>
+								<text class="pt20">微信朋友圈</text>
+							</button>
+						</view>
+					</view>
+				</view>
+				<view class="btns">
+					<button type="default" @click="closePopup(1)">取消</button>
+				</view>
+			</view>
+
+		</view>
+	</view>
+
+</template>
+
+<script>
+	import config from '@/config.js';
+	export default {
+		data() {
+			return {
+				/*是否可见*/
+				Visible: false,
+				/*分享配置*/
+				shareConfig: {},
+				// logo
+				logo: ''
+			}
+		},
+		created() {
+			this.getData();
+		},
+		props: ['isAppShare', 'appParams'],
+		watch: {
+			'isAppShare': function(n, o) {
+				if (n != o) {
+					this.Visible = n;
+				}
+			}
+		},
+		methods: {
+			getData(){
+				let self = this;
+				self._get(
+					'settings/appShare',{},
+					function(res) {
+						self.shareConfig = res.data.appshare;
+						self.logo = res.data.logo;
+					}
+				);
+			},
+			/*关闭弹窗*/
+			closePopup(type) {
+				this.$emit('close');
+			},
+			// 分享
+			share: function(shareType, scene) {
+				let shareOPtions = {
+					provider: "weixin",
+					scene: scene, //WXSceneSession”分享到聊天界面,“WXSenceTimeline”分享到朋友圈
+					type: shareType,
+					success: function (res) {
+					    console.log("success:" + JSON.stringify(res));
+					},
+					fail: function (err) {
+					    console.log("fail:" + JSON.stringify(err));
+					}
+				}
+				if(this.shareConfig.type != 2){
+					shareOPtions.summary = this.appParams.summary;
+					shareOPtions.imageUrl = this.logo;
+					shareOPtions.title = this.appParams.title;
+					// 公众号/h5
+					if(this.shareConfig.type == 1){
+						shareOPtions.href = this.shareConfig.open_site + this.appParams.path;
+					}else if(this.shareConfig.type == 3){
+						//下载页
+						if(this.shareConfig.bind_type == 1){
+							shareOPtions.href = this.shareConfig.down_url;
+						}else{
+							shareOPtions.href = config.app_url + "/index.php/api/user.useropen/invite?app_id="+ config.app_id +"&referee_id=" + uni.getStorageSync('user_id');
+						}
+					}
+				}else{
+					// 分享到小程序
+					shareOPtions.scene = 'WXSceneSession';
+					shareOPtions.type = 5;
+					shareOPtions.imageUrl = this.appParams.image ? this.appParams.image : this.logo;
+					shareOPtions.title = this.appParams.title;
+					shareOPtions.miniProgram = {
+						id: this.shareConfig.gh_id,
+						path: this.appParams.path,
+						webUrl: this.shareConfig.web_url,
+						type:0
+					};
+				}
+				uni.share(shareOPtions);
+			},
+		}
+	}
+</script>
+
+<style>
+	.bottom-panel{
+		
+	}
+	.bottom-panel.popup-bg {
+		position: fixed;
+		top: 0;
+		right: 0;
+		bottom: 0;
+		left: 0;
+		background: rgba(0, 0, 0, .6);
+		height: 100%;
+		z-index: 98;
+	}
+	.bottom-panel.popup-bg .wechat-box{ padding-top: var(--window-top);}
+	.bottom-panel.popup-bg .wechat-box image{ width: 100%;}
+
+	.bottom-panel .content {
+		position: fixed;
+		width: 100%;
+		bottom: 0;
+		min-height: 200rpx;
+		max-height: 900rpx;
+		background-color: #fff;
+		transform: translate3d(0, 980rpx, 0);
+		transition: transform .2s cubic-bezier(0, 0, .25, 1);
+		bottom: env(safe-area-inset-bottom);
+		z-index: 99;
+	}
+
+	.bottom-panel.open .content {
+		transform: translate3d(0, 0, 0);
+	}
+
+	.bottom-panel.close.popup-bg {
+		display: none;
+	}
+
+	.module-share .hd {
+		height: 90rpx;
+		line-height: 90rpx;
+		font-size: 36rpx;
+	}
+	
+	.module-share .item button,.module-share .item button::after{ background: none; border: none;}
+	
+
+	.module-share .icon-box {
+		width: 100rpx;
+		height: 100rpx;
+		border-radius: 50%;
+		background: #f6bd1d;
+	}
+
+	.module-share .icon-box .iconfont {
+		font-size: 60rpx;
+		color: #FFFFFF;
+	}
+
+	.module-share .btns {
+		margin-top: 30rpx;
+	}
+
+	.module-share .btns button {
+		height: 90rpx;
+		line-height: 90rpx;
+		border-radius: 0;
+		border-top: 1px solid #EEEEEE;
+	}
+
+	.module-share .btns button::after {
+		border-radius: 0;
+	}
+
+	.module-share .share-friend {
+		background: #04BE01;
+	}
+</style>

+ 180 - 0
components/countdown/countdown.vue

@@ -0,0 +1,180 @@
+<template>
+	<!--倒计时-->
+	<view class="countdown">
+		<template v-if="config.type == null">
+			<text v-if="status == 0">{{title}}</text>
+			<text v-if="status == 1">活动具体时间:</text>
+			<text v-if="status == 2">活动结束时间:</text>
+			<text class="box" :style="'background-color: '+back_color+';color:'+cut_color">{{ day }}</text>
+			<text class="p-0-10" :style="'color:'+color">天</text>
+			<text class="box" :style="'background-color: '+back_color+';color:'+cut_color">{{ hour }}</text>
+			<text class="p-0-10" :style="'color:'+color">:</text>
+			<text class="box" :style="'background-color: '+back_color+';color:'+cut_color">{{ minute }}</text>
+			<text class="p-0-10" :style="'color:'+color">:</text>
+			<text class="box" :style="'background-color: '+back_color+';color:'+cut_color">{{ second }}</text>
+			<text class="p-0-10" :style="'color:'+color"></text>
+		</template>
+		<template v-if="config.type === 'text'">
+			{{title}}{{ parseInt(day * 24) + parseInt(hour) }}:{{ minute }}:{{ second }}
+		</template>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				/*状态*/
+				status: 0,
+				/*天*/
+				day: '0',
+				/*时*/
+				hour: '0',
+				/*分*/
+				minute: '0',
+				/*秒*/
+				second: '0',
+				/*定时器*/
+				timer: null,
+				/*剩余秒*/
+				totalSeconds: 0,
+				/*标题*/
+				title: '活动剩余:'
+			};
+		},
+		props: {
+			config: {
+				type: Object,
+				default: function() {
+					return {
+						type: 'all',
+					};
+				}
+			},
+			back_color: {
+				type: String,
+				default: function() {
+					return {
+						type: 'all',
+					};
+				}
+			},
+			cut_color: {
+				type: String,
+				default: function() {
+					return {
+						type: 'all',
+					};
+				}
+			},
+			color: {
+				type: String,
+				default: function() {
+					return {
+						type: 'all',
+					};
+				}
+			}
+		},
+		created() {},
+		watch: {
+			config: {
+				deep: true,
+				handler: function(n, o) {
+					if (n != o && n.endstamp != 0) {
+						if (n.title && typeof n.title != 'undefined') {
+							this.title = n.title;
+						}
+						this.setTime();
+					}
+				},
+				immediate: true
+			}
+		},
+		methods: {
+			/*轮循*/
+			setTime() {
+				let self = this;
+				self.timer = setInterval(function() {
+					self.init();
+				}, 1000);
+			},
+
+			/*初始化*/
+			init() {
+				let nowseconds = Date.now() / 1000;
+				if (nowseconds < this.config.startstamp) {
+					//活动时间还没到
+					this.status = 1;
+				} else if (nowseconds > this.config.endstamp) {
+					//活动已过期
+					this.status = 2;
+				} else {
+					//活动进行中
+					this.totalSeconds = parseInt(this.config.endstamp - nowseconds);
+					this.status = 0;
+					this.countDown();
+				}
+				this.$emit('returnVal', this.status);
+			},
+
+			/*计算时分秒*/
+			countDown() {
+				let totalSeconds = this.totalSeconds;
+				//天数
+				let day = Math.floor(totalSeconds / (60 * 60 * 24));
+				//取模(余数)
+				let modulo = totalSeconds % (60 * 60 * 24);
+				//小时数
+				let hour = Math.floor(modulo / (60 * 60));
+				modulo = modulo % (60 * 60);
+				//分钟
+				let minute = Math.floor(modulo / 60);
+				//秒
+				let second = modulo % 60;
+				this.day = this.convertTwo(day);
+				this.hour = this.convertTwo(hour);
+				this.minute = this.convertTwo(minute);
+				this.second = this.convertTwo(second);
+				this.totalSeconds--;
+			},
+
+			/*转两位数*/
+			convertTwo(n) {
+				let str = '';
+				if (n < 10) {
+					str = '0' + n;
+				} else {
+					str = n;
+				}
+				return str;
+			},
+
+			/*把时间戳转普通时间*/
+			getLocalTime(nS) {
+				return new Date(parseInt(nS) * 1000).toLocaleString().replace(/:\d{1,2}$/, ' ');
+			},
+			clear() {
+				console.log(1)
+				clearInterval(this.timer);
+				this.timer = null;
+			},
+		},
+
+		destroyed() {
+			clearInterval(this.timer);
+		}
+	};
+</script>
+
+<style>
+	.countdown .box {
+		display: inline-block;
+		padding: 4rpx;
+		/* width: 34rpx; */
+		border-radius: 8rpx;
+		background: #000000;
+		text-align: center;
+		color: #ffffff;
+	}
+</style>

+ 94 - 0
components/diy/article/article.vue

@@ -0,0 +1,94 @@
+<template>
+	<view class="diy-article">
+		<!--文章列表-->
+		<view class="article-item" v-for="(item, index) in listData" :class="'show-type__'+ itemData.style.display" :key="index"
+		 @click="gotoPageFunc(item)">
+			<!-- 有图模式 -->
+			<template v-if="itemData.style.display == 10">
+				<view class="d-b-c d-stretch d-c flex-1">
+					<view class="">
+						<view class="text-ellipsis f32">
+							{{ item.article_title }}
+						</view>
+						<view class="des text-ellipsis mt10 f24 gray6">
+							{{ item.dec }}
+						</view>
+					</view>
+					<view class="d-s-c gray9 f26">
+						<text>{{ item.create_time }}</text>
+						<text class="ml30">阅读量:</text>
+						<text class="ml10">{{ item.actual_views }}</text>
+					</view>
+				</view>
+				<view class="picture ml20" v-if="item.image!=null&&item.image.file_path!=''">
+					<image :src="item.image.file_path" mode="aspectFill"></image>
+				</view>
+			</template>
+			<!-- 无图模式-->
+			<template v-if="itemData.style.display == 20">
+				<view class="f32 text-ellipsis lh200">
+					{{ item.article_title }}
+				</view>
+			</template>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				/*数据列表*/
+				listData: []
+			};
+		},
+		props: ['itemData'],
+		created() {
+			this.listData = this.itemData.data;
+		},
+		methods: {
+
+			/*跳转页面*/
+			gotoPageFunc(e) {
+				let _url = 'pages/article/detail/detail?article_id=' + e.article_id;
+				this.gotoPage(_url);
+			}
+		}
+	};
+</script>
+
+<style>
+	.diy-article {
+		background: #ffffff;
+		margin: 20rpx;
+		border-radius: 12rpx;
+	}
+
+	.diy-article .show-type__10,
+	.diy-article .show-type__20 {
+		display: flex;
+		padding: 30rpx;
+		border-bottom: 1rpx solid #D9D9D9;
+	}
+
+	.diy-article .show-type__10 .picture {
+		width: 210rpx;
+		height: 140rpx;
+		border-radius: 12rpx;
+
+	}
+
+	.diy-article .show-type__10 .title {
+		height: 80rpx;
+	}
+
+	.diy-article .show-type__10 .des {
+		height: 36rpx;
+	}
+
+	.diy-article image {
+		width: 100%;
+		height: 100%;
+		border-radius: 12rpx;
+	}
+</style>

+ 204 - 0
components/diy/assembleProduct/assembleProduct.vue

@@ -0,0 +1,204 @@
+<template>
+	<view class="diy-assembleproduct" v-if="itemData.data.product_list.length>0">
+		<view class="diy-head d-b-c" :style="'background-image: url('+itemData.style.background_image+');'">
+			<view class="right" @click="gotoList">
+				<text class="f26 gray9">更多</text>
+				<text class="iconfont icon-jiantou"></text>
+			</view>
+		</view>
+		<view class="diy-body">
+			<scroll-view scroll-x="true">
+				<view class="product-list column__3">
+					<view class="product-item" v-for="(item, index) in itemData.data.product_list" :key="index" @click="gotoDetail(item)">
+						<!-- 两列三列 -->
+						<template>
+							<view class="product-cover pr">
+								<image :src="item.product.file_path" mode="aspectFit"></image>
+								<view class="assemble-num"><text>{{ item.assemble_num }}人团</text></view>
+							</view>
+							<view class="product-info p-0-10">
+								<view class="product-title" v-if="itemData.style.show.productName === true">{{ item.product.product_name }}</view>
+								<view class="product-price" v-if="itemData.style.show.assemblePrice == true">
+									<text class="red f20">¥</text>
+									<text class="red fb f32">{{ item.assemble_price }}</text>
+									<text class="ml10 gray9 text-d-line f20" v-if="itemData.style.show.linePrice == true">¥</text>
+									<text class="gray9 f24 text-d-line" v-if="itemData.style.show.linePrice == true">{{ item.product_price }}</text>
+								</view>
+							</view>
+							<view class="assemble_btn">去开团</view>
+						</template>
+					</view>
+				</view>
+			</scroll-view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		components: {},
+		data() {
+			return {};
+		},
+		props: ['itemData'],
+		created() {
+			console.log(this.$props.itemData)
+		},
+		methods: {
+			scroll(e) {},
+
+			/*跳转列表*/
+			gotoList() {
+				let url = '/pages/plus/assemble/list/list';
+				this.gotoPage(url);
+			},
+
+			/*跳转产品详情*/
+			gotoDetail(e) {
+				let url = '/pages/plus/assemble/detail/detail?assemble_product_id=' + e.assemble_product_id;
+				this.gotoPage(url);
+			}
+		}
+	};
+</script>
+
+<style lang="scss">
+	.diy-assembleproduct {
+		margin: 20rpx;
+		border-radius: 20rpx;
+		padding: 0 20rpx 20rpx;
+		background: #FFFFFF;
+	}
+
+	.diy-assembleproduct .diy-head {
+		height: 90rpx;
+		display: flex;
+		justify-content: flex-end;
+		align-items: center;background-size: 100% 100%;
+		
+	}
+
+	.diy-assembleproduct .diy-head .name {
+		font-size: 32rpx;
+		font-weight: bold;
+	}
+
+	.diy-assembleproduct .diy-head .datetime {
+		margin-left: 40rpx;
+	}
+
+	.diy-assembleproduct .diy-head .datetime::v-deep>span {
+		display: inline-block;
+	}
+
+	.diy-assembleproduct .diy-head .datetime::v-deep text {
+		font-size: 24rpx;
+		color: #F6220C;
+	}
+
+	.diy-assembleproduct .diy-head .datetime::v-deep .box {
+		padding: 4rpx;
+		font-size: 22rpx;
+		background: #F6220C;
+		color: #F6220C;
+	}
+
+	.diy-assembleproduct .diy-head .icon-jiantou {
+		margin-left: 8rpx;
+		color: #999999;
+		font-size: 22rpx;
+	}
+
+	.diy-assembleproduct .product-list {
+		flex-wrap: nowrap;
+	}
+
+	.diy-assembleproduct .product-list .product-item {
+		flex-shrink: 0;
+		border-radius: 12rpx;
+		width: 245rpx;
+		overflow: hidden;
+	}
+
+	.diy-assembleproduct .product-list image {
+		width: 100%;
+		height: 100%;
+		background-color: #f6f6f6;
+	}
+
+	.diy-assembleproduct .product-list .product-title {
+		margin: 0 auto;
+		margin-top: 32rpx;
+		width: 80%;
+		height: 30rpx;
+		display: -webkit-box;
+		overflow: hidden;
+		-webkit-line-clamp: 1;
+		-webkit-box-orient: vertical;
+		font-size: 30rpx;
+	}
+
+	.diy-assembleproduct .product-list .product-price {
+		margin: 0 auto;
+		margin-top: 16rpx;
+		margin-bottom: 24rpx;
+		width: 80%;
+		// line-height: 24rpx;
+		display: -webkit-box;
+		overflow: hidden;
+		-webkit-line-clamp: 1;
+		-webkit-box-orient: vertical;
+		text-align: left;
+	}
+
+	.diy-assembleproduct .product-list.column__3 .product-title {
+		height: 30rpx;
+		line-height: 30rpx;
+		font-size: 30rpx;
+	}
+
+	.diy-assembleproduct .product-list.column__2,
+	.diy-assembleproduct .product-list.column__3 {
+		display: flex;
+		justify-content: flex-start;
+		align-items: center;
+	}
+
+	.diy-assembleproduct .product-list .assemble-num {
+		padding: 0rpx 16rpx;
+		font-size: 24rpx;
+		color: #ffffff;
+		position: absolute;
+		bottom: -2rpx;
+		left:0;
+		background-color: #fd5456;
+		border-top-right-radius: 12rpx;
+		height: 33rpx;
+		line-height: 33rpx;
+	}
+
+	.diy-assembleproduct .column__3 .product-item {
+		width: 245rpx;
+		margin-right: 20rpx;
+	}
+
+	.diy-assembleproduct .column__3 .product-cover {
+		width: 244rpx;
+		height: 226rpx;
+		margin: 0 auto;
+		border-radius: 12rpx;
+		overflow: hidden;
+	}
+
+	.diy-assembleproduct .column__3 .assemble_btn {
+		background: #fe3c30;
+		width: 202rpx;
+		height: 46rpx;
+		line-height: 46rpx;
+		font-size: 22rpx;
+		text-align: center;
+		color: #FFFFFF;
+		margin: 0 auto;
+		border-radius: 24rpx;
+	}
+</style>

+ 161 - 0
components/diy/banner/banner.vue

@@ -0,0 +1,161 @@
+<template>
+	<view class="diy-banner-box pr" :class="itemData.style.imgShape"
+		:style="'background-color:'+itemData.style.background+';'">
+		<swiper class="swiper" :autoplay="autoplay" :interval="interval" :duration="duration" @change="changeSwiper"  :style="itemData.style.imgShape=='square'?'height:'+itemData.style.height+'rpx;':'height:'+(itemData.style.height*0.92)+'rpx;'">
+			<swiper-item v-for="(item,index) in itemData.data" :key="index" @click="gotoPages(item,itemData)">
+				<image :style="itemData.style.imgShape=='square'?'height:'+itemData.style.height+'rpx;':'height:'+(itemData.style.height*0.92)+'rpx;'" :src="item.imgUrl"></image>
+			</swiper-item>
+		</swiper>
+		<view class="swiper-dots ww100 d-c-c" :class="itemData.style.btnShape">
+			<view :class="current==index?'swiper-dot active':'swiper-dot'" v-for="(item,index) in itemData.data"
+				:style="current==index?'background-color:'+indicatorActiveColor+';':''" :key="index">
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				indicatorDots: true,
+				autoplay: true,
+				interval: 2000,
+				duration: 500,
+				indicatorActiveColor: '#ffffff',
+				current: 0
+			}
+		},
+		props: ['itemData'],
+		created() {
+			this.interval = this.itemData.params.interval;
+			this.indicatorActiveColor = this.itemData.style.btnColor;
+			
+		},
+		methods: {
+			changeSwiper(e) {
+				this.current = e.detail.current;
+			},
+			/*跳转页面*/
+			gotoPages(e,data) {
+				let urlStr = e.linkUrl.split('?')[1]
+				// 创建空对象存储参数
+				let obj = {};
+				// 再通过 & 将每一个参数单独分割出来
+				let paramsArr = urlStr.split('&')
+				for(let i = 0,len = paramsArr.length;i < len;i++){
+				    // 再通过 = 将每一个参数分割为 key:value 的形式
+				    let arr = paramsArr[i].split('=')
+				    obj[arr[0]] = arr[1];
+				}
+				let AppId = obj.naviAppId;
+				if(AppId!=""&&AppId!=null&&AppId!=undefined){
+					uni.navigateToMiniProgram({
+					    appId:AppId,// appid
+					    path:e.linkUrl,// 首页路径
+					    envVersion:"release",
+					    success: res => {
+					         console.log("打开成功", res);
+					    },
+					    fail: err => {
+					         console.log(err);
+					    }
+					});
+					return;
+				}
+							
+				// #ifdef MP-WEIXIN
+				this.gotoPage(e.linkUrl);
+				// #endif
+				
+				// #ifndef MP-WEIXIN
+				console.log('不在微信',e,data.data)
+				let a = e.linkUrl
+					a = a.split('/')[0]
+				if(a == 'pages'){
+					this.gotoPage(e.linkUrl);
+				}else{
+					window.location.href = e.linkUrl
+				}
+				console.log(a)
+				
+				// #endif
+			}
+		}
+	}
+</script>
+
+<style>
+	.diy-banner-box,
+	.diy-banner-box .swiper {
+		overflow-x: hidden;
+		width: 750rpx;
+		/* background-color: #FFFFFF; */
+	}
+
+	.diy-banner-box.round,
+	.diy-banner-box.round .swiper {
+		width: 750rpx;
+		/* background-color: #FFFFFF; */
+	}
+
+	.diy-banner-box image {
+		width: 750rpx;
+	}
+	.diy-banner-box.round{
+		padding: 30rpx;
+		box-sizing: border-box;
+	}
+	.diy-banner-box.round image {
+		width: 690rpx;
+		border-radius: 12rpx;
+	}
+
+	.diy-banner-box.round .swiper-dots {
+		position: absolute;
+		bottom: 40rpx;
+		left: 0;
+		right: 0;
+		margin: auto;
+	}
+
+	.diy-banner-box.square .swiper-dots {
+		position: absolute;
+		bottom: 20rpx;
+		left: 0;
+		right: 0;
+		margin: auto;
+	}
+
+	.swiper-dots.square .swiper-dot {
+		width: 14rpx;
+		height: 14rpx;
+		margin: 0 4rpx;
+		background: #ebedf0;
+		opacity: 0.3;
+	}
+
+	.swiper-dots.round .swiper-dot {
+		width: 22rpx;
+		height: 22rpx;
+		margin: 0 4rpx;
+		background: #ebedf0;
+		opacity: 0.3;
+		border-radius: 50%;
+	}
+
+	.swiper-dots.rectangle .swiper-dot {
+		width: 40rpx;
+		height: 6rpx;
+		margin: 0 4rpx;
+		background: #ebedf0;
+		opacity: 0.3;
+		border-radius: 4rpx;
+	}
+
+	.swiper-dots.round .swiper-dot.active,
+	.swiper-dots.square .swiper-dot.active,
+	.swiper-dots.rectangle .swiper-dot.active {
+		opacity: 1;
+	}
+</style>

+ 189 - 0
components/diy/bargainProduct/bargainProduct.vue

@@ -0,0 +1,189 @@
+<template>
+	<view class="diy-bargainProduct" v-if="itemData.data.product_list.length>0">
+		<view class="bargainProduct-head d-b-c"  :style="'background-image: url('+itemData.style.background_image+');'">
+			<view class="left d-s-c">
+				<view class="name color_bargain d-c-c">
+				</view>
+				<view class="datetime d-s-c ml20">
+					<Countdown :back_color="itemData.style.countdown_back_color" :color='itemData.style.color' :cut_color="itemData.style.countdown_color"  :config="countdownConfig"></Countdown>
+				</view>
+			</view>
+			<view class="right" @click="gotoList">
+				<text class="f26 color_bargain ">更多</text>
+				<text class="iconfont icon-jiantou mr20" style="font-size: 22rpx;margin-left: 4rpx;color: #ffffff;"></text>
+			</view>
+		</view>
+		<view class="bargainProduct-body">
+			<scroll-view scroll-x="true">
+				<view class="product-list column__3">
+					<view class="product-item" v-for="(item, index) in itemData.data.product_list" :key="index"  @click="gotoDetail(item.bargain_product_id)">
+						<!-- 两列三列 -->
+						<template>
+							<view class="product-cover">
+								<image :src="item.product.file_path" mode="aspectFit"></image>
+							</view>
+							<view class="product-info p-0-10">
+								<view v-if="itemData.style.show.productName == '1'" class="product-title">{{ item.product.product_name }}</view>
+								<view class="price d-s-c p-20-0 f20">
+									<view v-if="itemData.style.show.floorPrice == '1'" class="redF6">
+										<text>¥</text>
+										<text class="f32 fb">{{ item.bargain_price }}</text>
+									</view>
+									<view class="ml10 gray9 text-d-line" v-if="itemData.style.show.originalPrice == '1'">
+										<text class="f20">¥</text>
+										<text class="f24">{{ item.product_price }}</text>
+									</view>
+								</view>
+								<view>
+									<view class="bargain_btn">立即砍价</view>
+								</view>
+							</view>
+						</template>
+					</view>
+				</view>
+			</scroll-view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import Countdown from '@/components/countdown/countdown.vue';
+	export default {
+		components: {
+			Countdown
+		},
+		data() {
+			return {
+				/*倒计时配置*/
+				countdownConfig: {
+					/*开始时间*/
+					startstamp: 0,
+					/*结束时间*/
+					endstamp: 0,
+					/*标题*/
+					title: ' '
+				}
+			};
+		},
+		props: ['itemData'],
+		created() {
+			this.countdownConfig.endstamp = this.itemData.data.end_time;
+			this.countdownConfig.startstamp = this.itemData.data.start_time;
+		},
+		methods: {
+			scroll(e) {},
+
+			/*跳转列表*/
+			gotoList() {
+				let url = '/pages/plus/bargain/list/list';
+				this.gotoPage(url);
+			},
+
+			/*跳转详情*/
+			gotoDetail(e) {
+				let url = '/pages/plus/bargain/detail/detail?bargain_product_id=' + e;
+				this.gotoPage(url);
+			}
+		}
+	};
+</script>
+
+<style>
+	.color_bargain {
+		color: #ffffff;
+	}
+
+	.diy-bargainProduct {
+		margin: 20rpx;
+		border-radius: 12rpx;
+		background: #ffffff;
+		overflow: hidden;
+	}
+	.diy-bargainProduct .bargainProduct-body{
+		padding: 0 20rpx;
+	}
+	.bargainProduct-head {
+		height: 90rpx;
+		background-size: 100% 100%;
+	}
+
+	.bargainProduct-head .name {
+		font-size: 32rpx;
+		font-weight: bold;
+		width: 200rpx;
+	}
+
+	.bargainProduct-head .datetime::v-deep>span {
+		display: inline-block;
+	}
+
+	.bargainProduct-head .datetime::v-deep text {
+		font-size: 24rpx;
+		color: #ffffff;
+	}
+
+	.bargainProduct-head .datetime::v-deep .box {
+		padding: 4rpx 10rpx;
+		font-size: 22rpx;
+		background: #FFFFFF;
+		color: #FFFFFF;
+	}
+
+	.diy-bargainProduct .product-list image {
+		width: 100%;
+		height: 100%;
+	}
+
+	.diy-bargainProduct .product-list .product-title {
+		margin-top: 32rpx;
+		height: 40rpx;
+		line-height: 40rpx;
+		display: -webkit-box;
+		overflow: hidden;
+		-webkit-line-clamp: 1;
+		-webkit-box-orient: vertical;
+		font-size: 30rpx;
+	}
+
+	.diy-bargainProduct .product-list .price {
+		height: 24rpx;
+		line-height: 24rpx;
+	}
+
+	.diy-bargainProduct .product-list.column__3 {
+		display: flex;
+		flex-wrap: nowrap;
+		justify-content: flex-start;
+	}
+
+	.diy-bargainProduct .column__3 .product-item {
+		width: 245rpx;
+		margin-right: 20rpx;
+		background: #ffffff;
+		border-radius: 12rpx;
+		flex-shrink: 0;
+		padding-top: 20rpx;
+	}
+
+	.diy-bargainProduct .column__3 .product-cover {
+		width: 244rpx;
+		height: 226rpx;
+		margin: 0 auto;
+		background-color: #f6f6f6;
+		border-radius: 12rpx;
+		overflow: hidden;
+	}
+
+	.bargain_btn {
+		background: #fe3c30;
+		width: 202rpx;
+		height: 46rpx;
+		line-height: 46rpx;
+		font-size: 22rpx;
+		text-align: center;
+		color: #FFFFFF;
+		margin: 0 auto;
+		border-radius: 24rpx;
+		margin-bottom: 28rpx;
+	}
+</style>

+ 18 - 0
components/diy/blank/blank.vue

@@ -0,0 +1,18 @@
+<template>
+	<view class="diy-blank" :style="{height: itemData.style.height +'px', background:itemData.style.background }">
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {};
+		},
+		props: ['itemData'],
+		methods: {}
+	};
+</script>
+
+<style>
+	
+</style>

+ 221 - 0
components/diy/coupon/coupon.vue

@@ -0,0 +1,221 @@
+<template>
+	<view class="diy-coupon"
+		:style="{ background: itemData.style.background, padding: itemData.style.paddingTop + 'px 20rpx' }">
+		<scroll-view scroll-x="true">
+			<view class="swiper swiper-list">
+				<view class="coupon-item" :class="'bg-' + item.color.text" v-for="(item, index) in listData"
+					:key="index">
+					<view class="side-line left-side-line" ><text class="round" :style="{ background: itemData.style.background}"></text></view>
+					<view class="side-line right-side-line"><text class="round"  :style="{ background: itemData.style.background}"></text></view>
+					<view class="left-type d-c-c">{{ item.coupon_type.text }}</view>
+					<view class="center-content pr">
+						<view class="content-top">
+							<template v-if="item.coupon_type.value == 10">
+								<text class="f22">¥</text>
+								<text class="f28 fb">{{ item.reduce_price }}</text>
+							</template>
+							<template v-if="item.coupon_type.value == 20">
+								<text class="f28 fb">{{ item.discount }}</text>
+								<text>折</text>
+							</template>
+						</view>
+						<view class="content-bottom">
+							<text class="f20">{{ item.name }}</text>
+						</view>
+					</view>
+					<!--领取-->
+					<view v-if="item.state.value == 1" class="right-receive d-c-c" @click="receiveCoupon(index)">
+						立即领取
+					</view>
+					<view v-else class="right-receive no-receive d-c-c">
+						{{ item.state.text }}
+					</view>
+				</view>
+			</view>
+		</scroll-view>
+
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				/*是否显示点*/
+				indicatorDots: false,
+				/*是否自动*/
+				autoplay: true,
+				/*切换时间*/
+				interval: 5000,
+				/*动画过渡时间*/
+				duration: 1000,
+				/*数据列表*/
+				listData: []
+			};
+		},
+		props: ['itemData'],
+		created() {
+			this.listData = this.itemData.data;
+		},
+		methods: {
+			scroll(e) {},
+			/**
+			 * 领取优惠券
+			 */
+			receiveCoupon: function(index) {
+				let self = this;
+				let item = self.listData[index];
+				if (item.state.value == 0) {
+					return false;
+				}
+				self._post(
+					'user.coupon/receive', {
+						coupon_id: item.coupon_id
+					},
+					function(result) {
+						uni.showToast({
+							title: '领取成功',
+							icon: 'success',
+							mask: true,
+							duration: 2000
+						});
+						item.state.value = 0;
+						item.state.text = '已领取';
+					}
+				);
+			}
+		}
+	};
+</script>
+
+<style>
+	.diy-coupon {
+		margin:0 20rpx;
+		border-radius: 20rpx;
+		
+	}
+
+	.f-s-0 {
+		flex-shrink: 0;
+	}
+
+	.diy-coupon .swiper {
+		height: 174rpx;
+		display: flex;
+		justify-content: flex-start;
+		align-items: center;
+		overflow-x: auto;
+	}
+
+	.diy-coupon .coupon-item {
+		width: 196rpx;
+		height: 158rpx;
+		color: #ffffff;
+		flex-shrink: 0;
+		margin: 8rpx;
+		position: relative;
+		border-radius: 8rpx;
+		overflow: hidden;
+		background: #feefef;
+		color: #ef3325;
+		display: block;
+	}
+
+	.diy-coupon .coupon-item.bg-red .right-receive {
+		background: #fe3d30;
+	}
+
+	.diy-coupon .coupon-item.bg-blue .right-receive{
+		background: #178ed9;
+	}
+
+	.diy-coupon .coupon-item.bg-yellow .right-receive{
+		background: #fe961a;
+	}
+
+	.diy-coupon .coupon-item.bg-violet .right-receive{
+		background: #ab0bf6;
+	}
+
+	.diy-coupon .coupon-item .left-type {
+		padding: 4rpx 8rpx;
+		font-size: 18rpx;
+		line-height: 18rpx;
+		text-align: center;
+		position: absolute;
+		right: 0;
+		top: 0;
+		color: #ffffff;
+		background: linear-gradient(to right, #ff5b00, #fe8802);
+		border-bottom-left-radius: 8rpx;
+	}
+
+	.diy-coupon .left-side-line {
+		position: absolute;
+		width: 12rpx;
+		bottom: 36rpx;
+		left: -6rpx;
+		overflow: hidden;
+	}
+
+	.diy-coupon .right-side-line {
+		position: absolute;
+		width: 12rpx;
+		bottom: 36rpx;
+		right: -6rpx;
+		overflow: hidden;
+	}
+
+	.diy-coupon .side-line .round {
+		display: block;
+		width: 12rpx;
+		height: 12rpx;
+		border-radius: 50%;
+		margin: 4rpx 0;
+		background: #ffffff;
+	}
+
+	.diy-coupon .center-content::before {
+		top: 0;
+		right: -16rpx;
+		border-radius: 0 0 15rpx 15rpx;
+	}
+
+	.diy-coupon .coupon-item .center-content {
+		padding: 26rpx 23rpx;
+		display: flex;
+		justify-content: space-between;
+		flex-direction: column;
+		align-items: flex-start;
+		flex: 1;
+		height: 112rpx;
+		box-sizing: border-box;
+	}
+
+	.diy-coupon .coupon-item .center-content .content-top {
+		height: 28rpx;
+		line-height: 28rpx;
+	}
+
+	.diy-coupon .coupon-item .center-content .content-datatime {
+		padding: 4rpx 10rpx;
+		border-radius: 30rpx;
+		font-size: 20rpx;
+		background: rgba(0, 0, 0, .2);
+	}
+
+	.diy-coupon .coupon-item .right-receive {
+		height: 46rpx;
+		width: 100%;
+		text-align: center;
+		font-size: 20rpx;
+		line-height: 20rpx;
+		text-align: center;
+		color: #FFFFFF;
+	}
+
+	.diy-coupon .coupon-item .no-receive {
+		background: #acacac !important;
+		color: #ffffff;
+	}
+</style>

+ 174 - 0
components/diy/diy.vue

@@ -0,0 +1,174 @@
+<template>
+	<view>
+		<block v-for="(item,index) in diyItems" :key="index">
+
+			<!--搜索框-->
+			<!-- <template v-if="item.type==='search'">
+				<search :itemData="item"></search>
+			</template> -->
+
+			<!--轮播图-->
+			<template v-if="item.type==='banner'&&item.data!=null">
+				<banner :itemData="item"></banner>
+			</template>
+
+			<!--单组图-->
+			<template v-if="item.type==='imageSingle'&&item.data!=null">
+				<imagesingle :itemData="item"></imagesingle>
+			</template>
+
+			<!-- 橱窗-->
+			<template v-if="item.type == 'window'&&item.data!=null">
+				<windows :itemData="item"></windows>
+			</template>
+
+			<!-- 视频组-->
+			<template v-if="item.type == 'video'">
+				<videos :itemData="item"></videos>
+			</template>
+
+			<!--文章-->
+			<template v-if="item.type == 'article'&&item.data!=null">
+				<articles :itemData="item"></articles>
+			</template>
+
+			<!--头条快报-->
+			<template v-if="item.type == 'special'&&item.data!=null">
+				<special :itemData="item"></special>
+			</template>
+
+			<!--公告组-->
+			<template v-if="item.type == 'notice'">
+				<notice :itemData="item"></notice>
+			</template>
+			<!--标题组-->
+			<template v-if="item.type == 'title'">
+				<titles :itemData="item"></titles>
+			</template>
+			<!--导航组-->
+			<template v-if="item.type==='navBar'&&item.data!=null">
+				<navBar :itemData="item"></navBar>
+			</template>
+
+			<!--商品组-->
+			<template v-if="item.type==='product'&&item.data!=null">
+				<product :itemData="item"></product>
+			</template>
+
+			<!--优惠券-->
+			<template v-if="item.type==='coupon'&&item.data!=null">
+				<coupon :itemData="item"></coupon>
+			</template>
+
+			<!--门店-->
+			<template v-if="item.type == 'store'&&item.data!=null">
+				<store :itemData="item"></store>
+			</template>
+
+			<!--客服-->
+			<template v-if="item.type == 'service'">
+				<service :itemData="item"></service>
+			</template>
+
+			<!--富文本-->
+			<template v-if="item.type==='richText'">
+				<richText :itemData="item"></richText>
+			</template>
+
+			<!--辅助空白-->
+			<template v-if="item.type == 'blank'">
+				<blank :itemData="item"></blank>
+			</template>
+
+			<!--辅助线-->
+			<template v-if="item.type == 'guide'">
+				<guide :itemData="item"></guide>
+			</template>
+
+			<!--秒杀-->
+			<template v-if="item.type == 'seckillProduct'&&item.data!=null">
+				<seckillProduct :itemData="item"></seckillProduct>
+			</template>
+
+			<!--拼团-->
+			<template v-if="item.type == 'assembleProduct'&&item.data!=null">
+				<assembleProduct :itemData="item"></assembleProduct>
+			</template>
+
+			<!--砍价-->
+			<template v-if="item.type == 'bargainProduct'&&item.data!=null">
+				<bargainProduct :itemData="item"></bargainProduct>
+			</template>
+
+			<!--微信直播-->
+			<!-- #ifdef MP-WEIXIN -->
+			<template v-if="item.type == 'wxlive'&&item.data!=null">
+				<wxlive :itemData="item"></wxlive>
+			</template>
+			<!-- #endif -->
+		</block>
+	</view>
+</template>
+
+<script>
+	import search from './search/search';
+	import banner from './banner/banner';
+	import imagesingle from './imagesingle/imagesingle';
+	import windows from './window/window';
+	import videos from './videos/videos';
+	import articles from './article/article';
+	import special from './special/special';
+	import notice from './notice/notice';
+	import titles from './title/title';
+	import coupon from './coupon/coupon';
+	import richText from './richText/richText';
+	import navBar from './navBar/navBar';
+	import store from './store/store';
+	import service from './service/service';
+	import blank from './blank/blank';
+	import guide from './guide/guide';
+	import product from './product/product';
+	import seckillProduct from './seckillProduct/seckillProduct';
+	import assembleProduct from './assembleProduct/assembleProduct';
+	import bargainProduct from './bargainProduct/bargainProduct';
+	import wxlive from './wxlive/wxlive';
+
+	export default {
+		components: {
+			search,
+			banner,
+			imagesingle,
+			windows,
+			videos,
+			articles,
+			special,
+			notice,
+			titles,
+			coupon,
+			richText,
+			navBar,
+			store,
+			service,
+			blank,
+			guide,
+			product,
+			seckillProduct,
+			assembleProduct,
+			bargainProduct,
+			wxlive
+		},
+		data() {
+			return {
+
+			}
+		},
+		props: ['diyItems'],
+		created() {}
+	}
+</script>
+
+<style>
+	page{
+		overflow-x: hidden;
+	}
+</style>

+ 19 - 0
components/diy/guide/guide.vue

@@ -0,0 +1,19 @@
+<template>
+	<view class="diy-guide" :style="{padding: itemData.style.paddingTop +'px '+'0', background:itemData.style.background }">
+	  <view class="line" :style="{borderTopWidth: itemData.style.lineHeight +'px',borderTopColor:itemData.style.lineColor,borderTopStyle: itemData.style.lineStyle }">
+	  </view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {};
+		},
+		props: ['itemData'],
+		methods: {}
+	};
+</script>
+
+<style>
+</style>

+ 44 - 0
components/diy/imagesingle/imagesingle.vue

@@ -0,0 +1,44 @@
+<template>
+	
+		<view
+			class="diy-imageSingle"
+			:style="
+				'padding-top: ' +
+					itemData.style.paddingTop +
+					'px;padding-bottom:' +
+					itemData.style.paddingTop +
+					'px; padding-left:' +
+					itemData.style.paddingLeft +
+					'px;padding-right:' +
+					itemData.style.paddingLeft +
+					'px;  background:' +
+					itemData.style.background
+			"
+		>
+		<view class="d-c-c" v-for="(imageSingle, index) in itemData.data" :key="index"  @click="gotoPages(imageSingle)">
+			<image :src="imageSingle.imgUrl" mode="widthFix"></image>
+		</view>
+			
+		</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {};
+	},
+	props: ['itemData'],
+	methods: {
+		/*跳转页面*/
+		gotoPages(e) {
+			this.gotoPage(e.linkUrl);
+		}
+	}
+};
+</script>
+
+<style>
+.diy-imageSingle image {
+	width: 100%;
+}
+</style>

+ 71 - 0
components/diy/navBar/navBar.vue

@@ -0,0 +1,71 @@
+<template>
+	<view>
+		<!--图标入口-->
+		<view class="diy-navbar" :style="{background:itemData.style.background}">
+			<view class="item" v-for="(item, index) in itemData.data" :key="index" :style="'width:'+item_width+';'" @click="gotoDetail(item)">
+				<image :src="item.imgUrl" mode="widthFix"></image>
+				<text class="gray3" :style="{color:item.color}">{{item.text}}</text>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				//单个宽度
+				item_width: '25%'
+			}
+		},
+		props: ['itemData'],
+		created() {
+			this.item_width = 100 / Math.abs(this.itemData.style.rowsNum) + '%';
+		},
+		methods: {
+
+			/*跳转页面*/
+			gotoDetail(e) {
+				this.gotoPage(e.linkUrl);
+			}
+		}
+	}
+</script>
+
+<style>
+	.diy-navbar {
+		margin: 20rpx;
+		padding: 20rpx 0;
+		border-radius: 12rpx;
+		background: #FFFFFF;
+		display: flex;
+		justify-content: flex-start;
+		flex-wrap: wrap;
+	}
+
+	.diy-navbar .item {
+		display: flex;
+		flex-direction: column;
+		justify-content: center;
+		align-items: center;
+		margin-top: 20rpx;
+		width: 120rpx;
+		height: 140rpx;
+	}
+
+	.diy-navbar .item image {
+		width: 70rpx;
+		height: 70rpx;
+	}
+
+	.diy-navbar .item text {
+		display: block;
+		text-overflow: ellipsis;
+		white-space: nowrap;
+		width: 100%;
+		overflow: hidden;
+		line-height: 66rpx;
+		font-size: 26rpx;
+		text-align: center;
+	}
+</style>

+ 66 - 0
components/diy/notice/notice.vue

@@ -0,0 +1,66 @@
+<template>
+	<view class="diy-notice" :style="{ padding: itemData.style.paddingTop + 'px' + ' 10px', background: itemData.style.background }" @click="gotoPages(item)">
+		<view class="notice-icon"><image :src="itemData.params.icon" mode="aspectFill"></image></view>
+		<view class="notice-text flex-1 text-ellipsisss">
+			<text :style="{ color: itemData.style.textColor }">{{ textData }}</text>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			textData:''
+		};
+	},
+	props: ['itemData'],
+	created() {
+		this.textData=this.itemData.params.text;
+		this.horseRaceLamp();
+	},
+	methods: {
+		
+		horseRaceLamp(){
+			let self=this;
+			setTimeout(function(){
+				let firstWord=self.textData.slice(0,1);
+				let afterWord=self.textData.slice(1,self.textData.length);
+				self.textData=afterWord+firstWord;
+				self.horseRaceLamp();
+				
+			},200);
+		},
+		
+		/*跳转页面*/
+		gotoPages(e) {
+			this.gotoPage(e.linkUrl);
+		}
+	}
+};
+</script>
+
+<style>
+.diy-notice {
+	margin: 20rpx;
+	display: flex;
+	justify-content: flex-start;
+	align-items: center;
+	border-radius: 20rpx;
+	/* box-shadow: 0 0 8rpx rgba(0, 0, 0, 0.1); */
+
+}
+.diy-notice .notice-icon {
+	width: 32px;
+	height: 32px;
+}
+.diy-notice .notice-icon image {
+	width: 100%;
+	height: 100%;
+}
+.diy-notice .notice-text {
+	overflow: hidden;
+	white-space: nowrap;
+	margin-left: 10px;
+}
+</style>

+ 277 - 0
components/diy/product/product.vue

@@ -0,0 +1,277 @@
+<template>
+	<view class="diy-product" :style="{ background: itemData.style.background }">
+		<view :class="['display__' + itemData.style.display]">
+			<template v-if="itemData.style.display == 'list'">
+				<view class="product-list" :class="['column__' + itemData.style.column]">
+					<view class="product-item" v-for="(product, index) in itemData.data" :key="index" @click="gotoDetail(product.product_id)">
+						<!-- 单列商品 -->
+						<template v-if="itemData.style.column == 1">
+							<view class="product-item-box">
+								<!-- 商品图片 -->
+								<view class="product-cover">
+									<image :src="product.image" mode="aspectFill"></image>
+								</view>
+								<view class="product-info">
+									<!-- 商品名称 -->
+									<view v-if="itemData.style.show.productName" class="product-title">
+										<text>{{ product.product_name }}</text>
+									</view>
+									<!-- 商品卖点 -->
+									<view v-if="itemData.style.show.sellingPoint" class="selling-point gray9">
+										<text>{{ product.selling_point }}</text>
+									</view>
+									<!-- 商品销量 -->
+									<view v-if="itemData.style.show.productSales" class="already-sale">
+										<text>已售{{ product.product_sales }}件</text>
+									</view>
+									<!-- 商品价格 -->
+									<view class="price d-s-c mt10">
+										<view v-if="itemData.style.show.productPrice" class="red">
+											<text>¥</text>
+											<text class="">{{ product.product_price }}</text>
+										</view>
+										<view class="ml10 gray9 text-d-line f28" v-if="itemData.style.show.linePrice && product.line_price > 0">
+											<text>¥</text>
+											<text>{{ product.line_price }}</text>
+										</view>
+									</view>
+								</view>
+							</view>
+						</template>
+
+						<!-- 两列三列 -->
+						<template v-else>
+							<view class="product-cover">
+								<image :src="product.image" mode="aspectFill"></image>
+							</view>
+							<view class="product-info">
+								<view v-if="itemData.style.show.productName == 1" class="product-title">{{ product.product_name }}</view>
+								<view class="price d-s-c">
+									<view v-if="itemData.style.show.productPrice == 1" class="red">
+										<text class="f22">¥</text>
+										<text class="">{{ product.product_price }}</text>
+									</view>
+									<view class="ml20 gray9 text-d-line" v-if="itemData.style.show.linePrice == 1 && product.line_price > 0"><text
+										 class="f22">¥</text>{{ product.line_price }}</view>
+								</view>
+							</view>
+						</template>
+					</view>
+				</view>
+			</template>
+			<template v-else>
+				<scroll-view :scroll-top="scrollTop" scroll-x="true">
+					<view class="product-list" :class="['column__' + itemData.style.column]">
+						<view v-for="(product, index) in itemData.data" :key="index" @click="gotoDetail(product.product_id)">
+							<view class="product-item">
+								<view class="product-cover">
+									<image :src="product.image" mode="aspectFill"></image>
+								</view>
+								<view class="product-info">
+									<view v-if="itemData.style.show.productName == 1" class="product-title">{{ product.product_name }}</view>
+									<view class="price d-s-c f12">
+										<view v-if="itemData.style.show.productPrice == 1" class="orange">
+											<text>¥</text>
+											<text class="">{{ product.product_price }}</text>
+										</view>
+										<view class="ml10 gray9 text-d-line" v-if="itemData.style.show.linePrice == 1 && product.line_price > 0">¥{{ product.line_price }}</view>
+									</view>
+								</view>
+							</view>
+						</view>
+					</view>
+				</scroll-view>
+			</template>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		components: {},
+		data() {
+			return {};
+		},
+		props: ['itemData'],
+		created() {},
+		methods: {
+			scroll(e) {},
+
+			/*跳转产品详情*/
+			gotoDetail(e) {
+				let url = '/pages/product/detail/detail?product_id=' + e;
+				this.gotoPage(url);
+			}
+		}
+	};
+</script>
+
+<style>
+	.diy-product {
+		overflow-x: hidden !important;
+		overflow-y: auto;
+		padding: 0 20rpx;
+	}
+
+	.diy-product .product-list.column__1 .product-item {
+		margin-bottom: 20rpx;
+		background: #ffffff;
+		width: 100%;
+	}
+
+	.diy-product .product-list.column__1 .product-item-box {
+		display: flex;
+		justify-content: flex-start;
+		align-items: stretch;
+	}
+
+	.diy-product .product-list .product-cover image {
+		width: 100%;
+		height: 100%;
+	}
+
+	.diy-product .product-list.column__1 .product-cover {
+		width: 240rpx;
+		height: 240rpx;
+		border-radius: 20rpx;
+		overflow: hidden;
+	}
+
+	.diy-product .product-list.column__1 .product-info {
+		margin: 20rpx 20rpx 20rpx 30rpx;
+		flex: 1;
+		display: flex;
+		flex-direction: column;
+		justify-content: space-between;
+	}
+
+	.diy-product .product-list .product-info .already-sale text {
+		padding: 4rpx 8rpx;
+		border-radius: 8rpx;
+		background: #f2f2f7;
+		color: #999;
+	}
+
+	.diy-product .product-list .product-title {
+		display: -webkit-box;
+		font-size: 32rpx;
+		overflow: hidden;
+		-webkit-line-clamp: 2;
+		-webkit-box-orient: vertical;
+	}
+
+	.diy-product .product-list.column__1 .product-title {
+		max-height: 80rpx;
+		line-height: 40rpx;
+	}
+
+	.diy-product .product-list.column__1 .selling-point {
+		display: -webkit-box;
+		overflow: hidden;
+		-webkit-line-clamp: 2;
+		-webkit-box-orient: vertical;
+		line-height: 30rpx;
+		max-height: 60rpx;
+	}
+
+	.diy-product .product-list.column__1 .already-sale {
+		margin-top: 10rpx;
+	}
+
+	.diy-product .product-list.column__2 .product-title {
+		height: 80rpx;
+		line-height: 40rpx;
+		margin-top: 20rpx;
+	}
+
+	.diy-product .product-list.column__3 .product-title {
+		margin-top: 20rpx;
+		margin-left: 10rpx;
+		margin-right: 10rpx;
+		height: 72rpx;
+		line-height: 36rpx;
+		font-size: 30rpx;
+	}
+
+	.diy-product .product-list.column__2 .product-info {
+		padding: 0 24rpx;
+	}
+
+	.diy-product .product-list .price {
+		font-size: 34rpx;
+	}
+
+	.diy-product .product-list.column__2 .price {
+		margin-top: 10rpx;
+		font-size: 30rpx;
+	}
+
+	.diy-product .product-list.column__3 .price {
+		margin-top: 10rpx;
+		padding: 0 10rpx;
+		font-size: 28rpx;
+	}
+
+	.diy-product .product-list.column__3 .price .text-d-line {
+		font-size: 22rpx;
+	}
+
+	.diy-product .product-list.column__2,
+	.diy-product .product-list.column__3 {
+		display: flex;
+		flex-wrap: wrap;
+		justify-content: flex-start;
+	}
+
+	.diy-product .column__2 .product-item {
+		width: 350rpx;
+		border-radius: 20rpx;
+		margin-right: 10rpx;
+		margin-bottom: 10rpx;
+		padding-bottom: 20rpx;
+		overflow: hidden;
+		background: #ffffff;
+		box-shadow: 0 0 8rpx rgba(0, 0, 0, 0.1);
+	}
+
+	.diy-product .display__list .column__2 .product-item:nth-child(2n + 0) {
+		margin-right: 0;
+	}
+
+	.diy-product .column__2 .product-cover {
+		width: 350rpx;
+		height: 350rpx;
+	}
+
+	.diy-product .column__3 .product-item {
+		width: 230rpx;
+		margin-bottom: 10rpx;
+		margin-right: 10rpx;
+		padding-bottom: 10rpx;
+		border-radius: 8rpx;
+		overflow: hidden;
+		background: #ffffff;
+		box-shadow: 0 0 8rpx rgba(0, 0, 0, 0.1);
+	}
+
+	.diy-product .display__list .column__3 .product-item:nth-child(3n + 0) {
+		margin-right: 0;
+	}
+
+	.diy-product .column__3 .product-cover {
+		width: 230rpx;
+		height: 230rpx;
+	}
+
+	.diy-product .display__slide .product-list {
+		flex-wrap: nowrap;
+	}
+
+	.diy-product .display__slide .column__2 .product-item {
+		width: 300rpx;
+	}
+
+	.diy-product .display__slide .column__3 .product-item {
+		width: 200rpx;
+	}
+</style>

+ 30 - 0
components/diy/richText/richText.vue

@@ -0,0 +1,30 @@
+<template>
+	<view>
+		<view class="diy-richText" :style="{background: itemData.style.background, padding: itemData.style.paddingTop + 'px ' + itemData.style.paddingLeft + 'px'}"
+		  v-html="formatContent(itemData.params.content)">
+		</view>
+	</view>
+</template>
+
+<script>
+	import utils from '@/common/utils.js';
+	export default {
+		data() {
+			return {
+				
+			}
+		},
+		props:['itemData'],
+		created(){
+		},
+		methods: {
+			formatContent(e){
+				return utils.format_content(e);
+			}
+		}
+	}
+</script>
+
+<style>
+
+</style>

+ 55 - 0
components/diy/search/search.vue

@@ -0,0 +1,55 @@
+<template>
+	<view class="index-search-box" id="searchBox">
+		<view class="index-search diy-search t-c" :class="'diy-search-style-'+itemData.style.searchStyle+' diy-search-textAlign-'+itemData.style.textAlign"
+		 @click="gotoSearch">
+			<span class="icon iconfont icon-sousuo"></span>
+			<text class="ml10">{{itemData.params.placeholder}}</text>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {}
+		},
+		props: ['itemData'],
+		methods: {
+
+			/*跳转搜索页面*/
+			gotoSearch() {
+				let url = '/pages/product/search/search';
+				this.gotoPage(url);
+			}
+		}
+	}
+</script>
+
+<style>
+	/*search*/
+	.diy-search-style-3 {}
+
+	.diy-search-style-6 {
+		border-radius: 16rpx;
+	}
+
+	.diy-search-style-9 {
+		border-radius: 50rpx;
+	}
+
+	.diy-search-textAlign-3 {
+		justify-content: flex-start;
+	}
+
+	.diy-search-textAlign-6 {
+		justify-content: center;
+	}
+
+	.diy-search-textAlign-9 {
+		justify-content: flex-end;
+	}
+
+	.diy-search .svg-icon {
+		margin-right: 10rpx;
+	}
+</style>

+ 196 - 0
components/diy/seckillProduct/seckillProduct.vue

@@ -0,0 +1,196 @@
+<template>
+	<view class="diy-seckillProduct" v-if="itemData.data.product_list.length>0">
+		<view class="sharpproduct-head d-b-c" :style="'background-image: url('+itemData.style.background_image+');'">
+			<view class="left d-s-c">
+				<view class="name d-c-c">
+				</view>
+				<view class="datetime d-s-c ml20">
+					<Countdown :back_color="itemData.style.countdown_back_color" :color='itemData.style.color' :cut_color="itemData.style.countdown_color" :config="countdownConfig"></Countdown>
+				</view>
+			</view>
+			<view class="right d-e-c" @click="gotoList">
+				<text class="white f26">更多</text>
+				<text class="iconfont icon-jiantou mr10"></text>
+			</view>
+		</view>
+		<view class="sharpproduct-body column__3">
+			<scroll-view scroll-x="true">
+				<view class="product-list">
+					<view class="product-item" v-for="(item, index) in itemData.data.product_list" :key="index"
+						@click="gotoDetail(item.seckill_product_id)">
+						<!-- 两列三列 -->
+						<template>
+							<view class="product-cover">
+								<image :src="item.product.file_path" mode="aspectFit"></image>
+							</view>
+							<view class="product-info p-0-10">
+								<view v-if="itemData.style.show.productName == true" class="product-title">
+									{{ item.product.product_name }}</view>
+								<view class="price d-c-c">
+									<view v-if="itemData.style.show.seckillPrice == true" class="red">
+										<text class="f20">¥</text>
+										<text class="f32 fb">{{ item.seckill_price }}</text>
+									</view>
+									<text class="ml10 gray9 f20 text-d-line"
+										v-if="itemData.style.show.linePrice == true">¥</text>
+									<text class="gray9 f24 text-d-line"
+										v-if="itemData.style.show.linePrice == true">{{ item.product_price }}</text>
+								</view>
+							</view>
+						</template>
+					</view>
+				</view>
+			</scroll-view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import Countdown from '@/components/countdown/countdown.vue';
+	export default {
+		components: {
+			Countdown
+		},
+		data() {
+			return {
+				/*倒计时配置*/
+				countdownConfig: {
+					/*开始时间*/
+					startstamp: 0,
+					/*结束时间*/
+					endstamp: 0,
+					/*标题*/
+					title: ' '
+				}
+			};
+		},
+		props: ['itemData'],
+		created() {
+			this.countdownConfig.endstamp = this.itemData.data.end_time;
+			this.countdownConfig.startstamp = this.itemData.data.start_time;
+		},
+		methods: {
+			scroll(e) {},
+
+			/*跳转列表*/
+			gotoList() {
+				let url = '/pages/plus/seckill/list/list';
+				this.gotoPage(url);
+			},
+
+			/*跳转产品详情*/
+			gotoDetail(e) {
+				let url = '/pages/plus/seckill/detail/detail?seckill_product_id=' + e;
+				this.gotoPage(url);
+			}
+		}
+	};
+</script>
+
+<style lang="scss">
+	.diy-seckillProduct {
+		margin: 20rpx 20rpx;
+		border-radius: 20rpx;
+		background: #ffffff;
+		overflow: hidden;
+	}
+
+	.diy-seckillProduct .sharpproduct-head {
+		height: 90rpx;
+		color: #000000;
+		background-size: 100% 100%;
+	}
+
+	.diy-seckillProduct .name {
+		width: 200rpx;
+	}
+
+	.diy-seckillProduct .sharpproduct-body {
+		padding: 0 20rpx;
+	}
+
+	.diy-seckillProduct .sharpproduct-head .name {
+		font-size: 32rpx;
+		font-weight: bold;
+	}
+
+	.diy-seckillProduct .sharpproduct-head .datetime::v-deep text {
+		font-size: 24rpx;
+		color: #ffffff;
+	}
+
+	.diy-seckillProduct .sharpproduct-head .datetime::v-deep .box {
+		padding: 4rpx 10rpx;
+		font-size: 22rpx;
+		background: #FFEBEB;
+		color: #EE1413;
+	}
+
+	.diy-seckillProduct .sharpproduct-head .icon-jiantou {
+		margin-left: 8rpx;
+		color: #ffffff;
+		font-size: 22rpx;
+	}
+
+	.diy-seckillProduct .product-list .product-item {
+		overflow: hidden;
+		flex-shrink: 0;
+	}
+
+	.diy-seckillProduct .product-list .product-cover image {
+		width: 100%;
+		height: 100%;
+		background-color: #F4F4F4;
+		border-radius: 12rpx;
+	}
+
+	.diy-seckillProduct .product-list .price {
+		font-size: 20rpx;
+		color: #F01A1A;
+		line-height: 26rpx;
+		padding-top: 16rpx;
+		padding-bottom: 8rpx;
+	}
+
+	.diy-seckillProduct .product-list .product-title {
+		margin-top: 26rpx;
+		height: 30rpx;
+		line-height: 30rpx;
+		display: -webkit-box;
+		overflow: hidden;
+		-webkit-line-clamp: 1;
+		-webkit-box-orient: vertical;
+		font-size: 30rpx;
+	}
+
+	.diy-seckillProduct .column__3 .product-list .product-title {
+		font-size: 28rpx;
+	}
+
+	.diy-seckillProduct .column__3 .product-list {
+		display: flex;
+		flex-wrap: nowrap;
+		justify-content: flex-start;
+	}
+
+	.diy-seckillProduct .column__3 .product-item {
+		width: 240rpx;
+		margin-right: 20rpx;
+		border-radius: 12rpx;
+		overflow: hidden;
+		background: #ffffff;
+		margin-top:20rpx;
+		margin-bottom: 20rpx;
+	}
+
+	.diy-seckillProduct .column__3 .product-cover {
+		width: 240rpx;
+		height: 240rpx;
+		margin: 0 auto;
+
+	}
+
+	.diy-assembleproduct .product-list {
+		flex-wrap: nowrap;
+	}
+</style>

+ 36 - 0
components/diy/service/service.vue

@@ -0,0 +1,36 @@
+<template>
+	<view class="diy-service drag optional drag__nomove"
+	  :style="{ right: itemData.style.right + '%', bottom: itemData.style.bottom + '%', opacity: itemData.style.opacity / 100 }">
+	  <view class="service-icon" v-if="itemData.params.type=='phone'" @click="callPhone">
+		  <image :src="itemData.params.image" mode="aspectFill"></image>
+	  </view>
+	  <button class="service-icon" open-type="contact" session-from="wxapp" v-if="itemData.params.type=='chat'">
+		  <image :src="itemData.params.image" mode="aspectFill"></image>
+	  </button>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {};
+		},
+		props: ['itemData'],
+		methods: {
+			/*拨打电话*/
+			callPhone(){
+				let self=this;
+				uni.makePhoneCall({
+					phoneNumber: self.itemData.params.phone_num
+				});
+			}
+		}
+	};
+</script>
+
+<style>
+	.diy-service{ position: fixed; width: 120rpx; height: 120rpx; z-index: 90; right: 0; bottom: 0;}
+	.diy-service .service-icon{ width: 120rpx; height: 120rpx; }
+	.diy-service button.service-icon{ padding: 0; background: none; }
+	.diy-service .service-icon image{ width: 100%; height: 100%;}
+</style>

+ 142 - 0
components/diy/special/special.vue

@@ -0,0 +1,142 @@
+<template>
+	<view class="diy-special" v-if="listData.length>0">
+		<view class="special-left">
+			<image :src="itemData.style.image" mode="aspectFill"></image>
+		</view>
+		<view class="right-shadow"></view>
+		<view class="special-content" :class="'display_' + itemData.style.display">
+			<view class="special-content-list" :style="'transform: translate(0,'+styleValue+'px);'">
+				<view class="content-item text-ellipsis" v-for="(item, index) in listData" :key="index" @click="gotoPageFunc(item)">
+					<text>{{ item.article_title }}</text>
+				</view>
+			</view>
+		</view>
+		<view class="special-more" @click="gotoPageFunc()"><text class="iconfont icon-jiantou"></text></view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				/*数据列表*/
+				listData: [],
+				/*样式*/
+				styleValue: '',
+				/*当前角标*/
+				index_num: 0,
+				/*高度*/
+				lineHeight: 0,
+				/*最大数*/
+				maxSize: 0,
+				/*时间*/
+				timer: null
+			};
+		},
+		props: ['itemData'],
+		created() {
+			this.listData = this.itemData.data;
+			this.init();
+		},
+		methods: {
+
+			/*初始化*/
+			init() {
+				let self = this;
+				if ((this.itemData.style.display == 1 && this.listData.length > 1) || (this.itemData.style.display == 2 && this.listData
+						.length > 2)) {
+					uni.getSystemInfo({
+						success(res) {
+							self.lineHeight = res.windowWidth / 750 * 30;
+							self.maxSize = self.listData.length
+							if (self.itemData.style.display == 2) {
+								self.lineHeight = self.lineHeight * 2;
+								self.maxSize = self.maxSize / 2;
+							}
+							self.timer = setInterval(function() {
+								self.animation();
+							}, 3000);
+						}
+					});
+				}
+			},
+
+			/*动画*/
+			animation() {
+				let self = this;
+				self.index_num++;
+				if (self.index_num >= self.maxSize) {
+					self.index_num = 0;
+				}
+				this.styleValue = -self.lineHeight * self.index_num;
+			},
+
+			/*跳转页面*/
+			gotoPageFunc(e) {
+				let url = null;
+				if (e && typeof e != 'undefined') {
+					url = 'pages/article/detail/detail?article_id=' + e.article_id;
+				} else {
+					url = 'pages/article/list/list';
+				}
+				this.gotoPage(url);
+			}
+		}
+	};
+</script>
+
+<style>
+	.diy-special {
+		background-color: #FFFFFF;
+		padding: 0 20rpx 0 24rpx;
+		margin: 20rpx;
+		display: flex;
+		justify-content: space-between;
+		align-items: center;
+		overflow: hidden;
+	}
+
+	.diy-special .special-left {
+		width: 136rpx;
+		height: 33rpx;
+	}
+
+	.diy-special .special-left image {
+		width: 100%;
+		height: 100%;
+	}
+
+	.diy-special .special-more .icon-jiantou {
+		font-size: 24rpx;
+	}
+
+	.diy-special .special-content {
+		flex: 1;
+		margin: 0 20rpx;
+		overflow: hidden;
+	}
+
+	.diy-special .special-content-list {
+		transition: transform .4s;
+	}
+
+	.diy-special .content-item {
+		height: 30rpx;
+		line-height: 30rpx;
+	}
+
+	.diy-special .special-content.display_1 {
+		height: 30rpx;
+	}
+
+	.diy-special .special-content.display_2 {
+		height: 60rpx;
+	}
+
+	.right-shadow {
+		width: 15rpx;
+		height: 90rpx;
+		background: linear-gradient(90deg, #E4E4E4 0%, rgba(255, 255, 255, 0) 100%);
+		margin-left: 30rpx;
+	}
+</style>

+ 64 - 0
components/diy/store/store.vue

@@ -0,0 +1,64 @@
+<template>
+	<view class="diy-store" :style="{ background: itemData.style.background }">
+		<view class="diy-head d-b-c">
+			<view class="left d-s-c">
+				<view class="name">
+					线下门店
+				</view>
+			</view>
+		</view>
+		<view class="store-item d-s-c p-30-0" :key="index" v-for="(store, index) in itemData.data" @click="gotoDetail(store.store_id)">
+			<view class="store-item-logo mr30"><image :src="store.logo_image" mode="aspectFill"></image></view>
+			<view class="flex-1 o-h">
+				<view class="ww100 f34 gray3 text-ellipsis">
+					<text>{{ store.store_name }}</text>
+				</view>
+				<view class="text-ellipsis mt10 f24 gray3">门店地址:{{ store.region.province }}{{ store.region.city }}{{ store.region.region }}{{ store.address }}</view>
+				<view class="mt10 f24">
+					<text>联系电话:{{ store.phone }}</text>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {};
+	},
+	props: ['itemData'],
+	methods: {
+		/*跳转门店详情*/
+		gotoDetail(e) {
+			let url = 'pages/store/detail/detail?store_id=' + e;
+			this.gotoPage(url);
+		}
+	}
+};
+</script>
+
+<style>
+.diy-store {
+	margin: 20rpx;
+	border-radius: 20rpx;
+	padding: 0 20rpx 20rpx;
+	background: #ffffff;
+	box-shadow: 0 0 8rpx rgba(0, 0, 0, 0.1);
+}
+.diy-store .diy-head {
+	height: 100rpx;
+}
+.diy-store .diy-head .name {
+	font-size: 36rpx;
+	font-weight: bold;
+}
+.diy-store .store-item {
+	border-top: 1rpx solid #eeeeee;
+}
+.diy-store .store-item-logo,
+.diy-store .store-item-logo image {
+	width: 120rpx;
+	height: 120rpx;
+}
+</style>

+ 73 - 0
components/diy/title/title.vue

@@ -0,0 +1,73 @@
+<template>
+	<view class="diy-notice pr"
+		:style="{ padding: itemData.style.paddingTop + 'px' + ' 10px', background: itemData.style.background }"
+		@click="gotoPages(item)">
+		<view class="notice-icon pr" :style="{background: itemData.style.background }"
+			v-if="itemData.params.show_icon=='yes'">
+			<image :src="itemData.params.icon" mode="aspectFill"></image>
+		</view>
+		<text class="pr notice-text text-ellipsisss f38 fb"
+			:style="{background: itemData.style.background, color: itemData.style.textColor }">
+			{{ itemData.params.title }}
+		</text>
+		<view class="center-line"></view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {};
+		},
+		props: ['itemData'],
+		created() {},
+		methods: {
+			/*跳转页面*/
+			gotoPages(e) {
+				this.gotoPage(e.linkUrl);
+			}
+		}
+	};
+</script>
+
+<style>
+	.diy-notice {
+		display: flex;
+		justify-content: center;
+		align-items: center;
+	}
+
+	.diy-notice .notice-icon {
+		width: 26px;
+		height: 26px;
+		background-color: #FFFFFF;
+		padding: 0 10rpx;
+		z-index: 1;
+	}
+
+	.diy-notice .notice-icon image {
+		width: 100%;
+		height: 100%;
+	}
+
+	.diy-notice .notice-text {
+		overflow: hidden;
+		white-space: nowrap;
+		background-color: #FFFFFF;
+		padding: 0 10rpx;
+		z-index: 1;
+	}
+	.center-line{
+		width: 490rpx;
+		height: 2rpx;
+		background-color: #c7c7c7;
+		border-radius: 2rpx;
+		position: absolute;
+		left: 0;
+		bottom: 0;
+		top: 0;
+		right: 0;
+		margin: auto;
+		z-index: 0;
+	}
+</style>

+ 29 - 0
components/diy/videos/videos.vue

@@ -0,0 +1,29 @@
+<template>
+	<view class="diy-video" :style="{padding:itemData.style.paddingTop + 'px 20rpx'}">
+		<video :style="{height:itemData.style.height + 'px'}" :src="itemData.params.videoUrl" :poster="itemData.params.poster"
+		 :autoplay="itemData.params.autoplay == '1'" controls objectFit="contain">
+		</video>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+
+			}
+		},
+		props: ['itemData'],
+		methods: {
+
+		}
+	}
+</script>
+
+<style>
+	.diy-video uni-video,
+	.diy-video video {
+		width: 100%;
+		border-radius: 12rpx;
+	}
+</style>

+ 135 - 0
components/diy/window/window.vue

@@ -0,0 +1,135 @@
+<template>
+	<view class="diy-window" :style="{ background: itemData.style.background, padding: itemData.style.paddingTop + 'px ' + itemData.style.paddingLeft + 'px' }">
+		<view class="data-list" v-if="itemData.style.layout > -1" :class="'column__' + itemData.style.layout">
+			<view class="item" :key="index" v-for="(item, index) in itemData.data"  @click="gotoPages(item)">
+				<view class="item-image" :style="{ padding: itemData.style.paddingTop + 'px ' + itemData.style.paddingLeft + 'px' }">
+					<image :src="item.imgUrl" mode="aspectFill"></image>
+				</view>
+			</view>
+		</view>
+		<view class="display" v-else :style="{ padding: itemData.style.paddingTop + 'px ' + itemData.style.paddingLeft + 'px' }">
+			<view class="img-box-wrap-1">
+				<view class="img-box" @click="gotoPages(itemData.data[0])">
+					<image :src="itemData.data[0].imgUrl" mode="aspectFill"></image>
+				</view>
+			</view>
+			<view class="percent-w50 d-s-c d-c" >
+				
+					<view class="img-box-wrap-2" v-if="itemData.data.length >= 2">
+						<view class="img-box" @click="gotoPages(itemData.data[1])">
+							<image :src="itemData.data[1].imgUrl" mode="aspectFill"></image>
+						</view>
+					</view>
+					<view class="d-s-c img-box-wrap-3">
+						<view class="img-box-wrap-4" v-if="itemData.data.length >= 3">
+							<view class="img-box" @click="gotoPages(itemData.data[2])">
+								<image :src="itemData.data[2].imgUrl" mode="aspectFill"></image>
+							</view>
+						</view>
+						<view class="img-box-wrap-4" v-if="itemData.data.length >= 4">
+							<view class="img-box" @click="gotoPages(itemData.data[3])">
+								<image :src="itemData.data[3].imgUrl" mode="aspectFill"></image>
+							</view>
+						</view>
+					</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+
+export default {
+	data() {
+		return {};
+	},
+	props: ['itemData'],
+	methods: {
+		/*跳转页面*/
+		gotoPages(e){
+			this.gotoPage(e.linkUrl);
+		}
+	}
+};
+</script>
+
+<style>
+	
+	.diy-window{
+		margin: 20rpx;
+		border-radius: 20rpx;
+		overflow: hidden;
+		box-shadow: 0 0 8rpx rgba(0, 0, 0, 0.1);
+	}
+	
+.diy-window .data-list {
+	display: flex;
+	flex-wrap: wrap;
+}
+
+.diy-window image{
+	width: 100%;
+	height: 100%;
+}
+.diy-window .data-list.column__2 .item {
+	width: 50%;
+}
+.diy-window .data-list.column__3 .item {
+	width: 33.333333333333%;
+}
+.diy-window .data-list.column__4 .item {
+	width: 25%;
+}
+.diy-window .data-list.column__2 .item {
+	position: relative;
+	padding-top: 50%;
+}
+.diy-window .data-list.column__3 .item {
+	position: relative;
+	padding-top: 33.3333333%;
+}
+.diy-window .data-list.column__4 .item {
+	position: relative;
+	padding-top: 25%;
+}
+.diy-window .data-list .item .item-image,
+.diy-window .display .img-box {
+	position: absolute;
+	box-sizing: border-box;
+	top: 0;
+	left: 0;
+	width: 100%;
+	height: 100%;
+}
+
+.diy-window .display {
+	display: flex;
+}
+.diy-window .display .img-box-wrap-1 {
+	position: relative;
+	width: 50%;
+	padding-top: 50%;
+}
+.diy-window .display .img-box-wrap-2 {
+	position: relative;
+	width: 100%;
+	height: 50%;
+}
+
+.diy-window .display .percent-w50 {
+	box-sizing: border-box;
+	width: 50%;
+}
+.diy-window .display .img-box .item-image {
+	height: 100%;
+}
+.diy-window .display .img-box-wrap-3 {
+	width: 100%;
+	height: 50%;
+}
+.diy-window .display .img-box-wrap-4 {
+	position: relative;
+	width: 50%;
+	height: 100%;
+}
+</style>

+ 170 - 0
components/diy/wxlive/wxlive.vue

@@ -0,0 +1,170 @@
+<template>
+	<view class="diy-live" :style="{ background: itemData.style.background }" v-if="itemData.data.length>0">
+		<view class="diy-head d-e-c" :style="'background-image: url('+itemData.style.background_image+');'">
+			<!-- <view class="right" @click="gotoList">
+				<text class="white">更多</text>
+				<text class="iconfont icon-jiantou mr20" style="font-size: 24rpx;color: #999999;"></text>
+			</view> -->
+		</view>
+		<view class="list d-s-c f-w">
+			<view class="item" v-for="(item, index) in itemData.data" :key="index" @click="gotoDetail(item)">
+				<view class="pic pr">
+					<text class="state"
+						:class="{bg101:item.live_status==101,bg102:item.live_status==102,bg103:item.live_status==103}"
+						v-if="item.live_status==101||item.live_status==102||item.live_status==103">
+						{{convertStatus(item.live_status)}}
+					</text>
+					<image :src="item.share_img" mode="aspectFill"></image>
+					<view class="anchor">{{item.anchor_name}}</view>
+				</view>
+				<view class="p20">
+					<view class="text-ellipsis-2 f26">{{ item.name }}</view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		components: {},
+		data() {
+			return {};
+		},
+		props: ['itemData'],
+		created() {},
+		methods: {
+			scroll(e) {},
+
+			/*状态转换*/
+			convertStatus(num) {
+				let str = '';
+				switch (num) {
+					case 101:
+						str = '直播中';
+						break;
+					case 102:
+						str = '未开始';
+						break;
+					case 103:
+						str = '已结束';
+						break;
+					case 104:
+						str = '禁播';
+						break;
+					case 105:
+						str = '暂停';
+						break;
+					case 106:
+						str = '异常';
+						break;
+					case 107:
+						str = '已过期';
+						break;
+				}
+				return str;
+			},
+
+			/*跳转列表*/
+			gotoList() {
+				let url = '/pages/plus/live/wx/list';
+				this.gotoPage(url);
+			},
+
+			/*跳转产品详情*/
+			gotoDetail(item) {
+				let roomId = item.roomid;
+				let customParams = {
+					path: 'pages/index/index'
+				};				
+				wx.navigateTo({
+					url: `plugin-private://wx2b03c6e691cd7370/pages/live-player-plugin?room_id=${roomId}&custom_params=${encodeURIComponent(JSON.stringify(customParams))}`					
+				});
+			}
+		}
+	};
+</script>
+
+<style lang="scss">
+	.diy-live {
+		margin: 20rpx;
+		border-radius: 20rpx;
+		background: #ffffff;
+		// box-shadow: 0 0 8rpx rgba(0, 0, 0, 0.1);
+		overflow: hidden;
+	}
+
+	.diy-live .diy-head {
+		height: 90rpx;
+		align-items: center;
+		background-size: 100% 100%;
+
+	}
+
+	.diy-live .diy-head .name {
+		font-size: 36rpx;
+		font-weight: bold;
+		width: 200rpx;
+	}
+
+	.diy-live .list {
+		padding: 20rpx;
+	}
+
+	.diy-live .list .item {
+		width: 320rpx;
+		margin-right: 30rpx;
+		margin-bottom: 30rpx;
+		height: 340rpx;
+		background-color: #f6f6f6;
+		border-radius: 12rpx;
+		overflow: hidden;
+	}
+
+	.diy-live .list .item:nth-child(2n + 0) {
+		margin-right: 0;
+	}
+
+	.diy-live .list .item .pic {
+		width: 246rpx;
+		height: 240rpx;
+	}
+
+	.diy-live .list .item .pic .state {
+		position: absolute;
+		z-index: 80;
+		top: 20rpx;
+		left: 20rpx;
+		padding: 4rpx 8rpx;
+		background: red;
+		color: #FFFFFF;
+		border-radius: 8rpx;
+	}
+
+	.diy-live .list .item .pic .state.bg101 {
+		background: red;
+	}
+
+	.diy-live .list .item .pic .state.bg102 {
+		background: #ffb100;
+	}
+
+	.diy-live .list .item .pic .state.bg103 {
+		background: #333333;
+	}
+
+	.diy-live .list .item image {
+		width: 320rpx;
+		height: 240rpx;
+		border-radius: 12rpx;
+	}
+
+	.diy-live .anchor {
+		position: absolute;
+		bottom: 12rpx;
+		left: 18rpx;
+		font-size: 24rpx;
+		line-height: 24rpx;
+
+	}
+</style>

+ 30 - 0
components/header.vue

@@ -0,0 +1,30 @@
+<template>
+	<view>
+		<view class="status_bar" :style="bcolor?'background-color:'+bcolor+';':''"></view>
+		<view class="top_view" :style="bcolor?'background-color:'+bcolor+';':''"></view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+
+			}
+		},
+		props: ['bcolor'],
+		watch:{
+			'bcolor':function(n,o){
+				if(n!=o){
+					console.log(n)
+				}
+			}
+		}	
+	}
+</script>
+
+<style>
+	.s{
+		flex-shrink: 0;
+	}
+</style>

+ 114 - 0
components/mp-share.vue

@@ -0,0 +1,114 @@
+<template>
+
+	<view class="bottom-panel" :class="Visible?'bottom-panel open':'bottom-panel close'" @click="closePopup">
+		<view class="popup-bg">
+			<view class="wechat-box">
+				<image src="/static/share.png" mode="widthFix"></image>
+			</view>
+		</view>
+	</view>
+
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				/*是否可见*/
+				Visible: false,
+				poster_img: '',
+				/*公众号分享是否显示*/
+				wechat_share:false
+			}
+		},
+		props: ['isMpShare'],
+		watch: {
+			'isMpShare': function(n, o) {
+				if (n != o) {
+					this.Visible = n;
+				}
+			}
+		},
+		methods: {
+			/*关闭弹窗*/
+			closePopup() {
+				this.$emit('close');
+			},
+		}
+	}
+</script>
+
+<style>
+	.bottom-panel .popup-bg {
+		position: fixed;
+		top: 0;
+		right: 0;
+		bottom: 0;
+		left: 0;
+		background: rgba(0, 0, 0, .6);
+		z-index: 98;
+	}
+	.bottom-panel .popup-bg .wechat-box{ padding-top: var(--window-top);}
+	.bottom-panel .popup-bg .wechat-box image{ width: 100%;}
+
+	.bottom-panel .content {
+		position: fixed;
+		width: 100%;
+		bottom: 0;
+		min-height: 200rpx;
+		max-height: 900rpx;
+		background-color: #fff;
+		transform: translate3d(0, 980rpx, 0);
+		transition: transform .2s cubic-bezier(0, 0, .25, 1);
+		bottom: env(safe-area-inset-bottom);
+		z-index: 99;
+	}
+
+	.bottom-panel.open .content {
+		transform: translate3d(0, 0, 0);
+	}
+
+	.bottom-panel.close .popup-bg {
+		display: none;
+	}
+
+	.module-share .hd {
+		height: 90rpx;
+		line-height: 90rpx;
+		font-size: 36rpx;
+	}
+	
+	.module-share .item button,.module-share .item button::after{ background: none; border: none;}
+	
+
+	.module-share .icon-box {
+		width: 100rpx;
+		height: 100rpx;
+		border-radius: 50%;
+		background: #f6bd1d;
+	}
+
+	.module-share .icon-box .iconfont {
+		font-size: 60rpx;
+		color: #FFFFFF;
+	}
+
+	.module-share .btns {
+		margin-top: 30rpx;
+	}
+
+	.module-share .btns button {
+		height: 90rpx;
+		line-height: 90rpx;
+		border-radius: 0;
+		border-top: 1px solid #EEEEEE;
+	}
+
+	.module-share .btns button::after {
+		border-radius: 0;
+	}
+
+	.module-share .share-friend {
+		background: #04BE01;
+	}
+</style>

+ 90 - 0
components/mpservice/Mpservice.vue

@@ -0,0 +1,90 @@
+<template>
+	<Popup :show="isPopup" :width="width" :padding="0" @hidePopup="hidePopupFunc">
+		<view class="d-s-s d-c p20 mpservice-wrap" >
+			<view class="d-b-c p-30-0 f34 ww100 border-b" @click="copyQQ(dataModel.qq)">
+				<text class="gray9" style="width: 140rpx;">QQ:</text>
+				<text class="p-0-30 flex-1">{{dataModel.qq}}</text>
+				<text class="blue">复制</text>
+			</view>
+			<view class="d-b-c p-30-0 f34 ww100" @click="copyQQ(dataModel.qq)">
+				<text class="gray9" style="width: 140rpx;">微信号:</text>
+				<text class="p-0-30 flex-1">{{dataModel.wechat}}</text>
+				<text class="blue">复制</text>
+			</view>
+			<view class="mp-image">
+				<image :src="dataModel.mp_image" mode="widthFix"></image>
+			</view>
+			<view class="ww100 pt10 tc f30 gray9">
+				公众号
+			</view>
+		</view>
+		<view class="d-c-c ww100">
+			<view class="p20" @click="hidePopupFunc(true)"><text class="icon iconfont icon-guanbi"></text></view>
+		</view>
+	</Popup>
+</template>
+
+<script>
+	import Popup from '@/components/uni-popup.vue';
+	export default {
+		components: {
+			Popup
+		},
+		data(){
+			return {
+				/*是否打开*/
+				isPopup:false,
+				/*宽度*/
+				width: 600,
+				/*数据对象*/
+				dataModel:{}
+			}
+		},
+		created() {
+			this.isPopup=true;
+			this.getData();
+		},
+		methods:{
+			
+			/*获取数据*/
+			getData() {
+				let self = this;
+				self._get(
+					'index/mpService',
+					{},
+					function(res) {
+						self.dataModel=res.data.mp_service;
+					}
+				);
+			},
+			
+			/*关闭弹窗*/
+			hidePopupFunc(e) {
+				this.isPopup = false;
+				this.$emit('close');
+			},
+			
+			/*复制*/
+			copyQQ(message) {
+				var input = document.createElement("input");
+				input.value = message;
+				document.body.appendChild(input);
+				input.select();
+				input.setSelectionRange(0, input.value.length), document.execCommand('Copy');
+				document.body.removeChild(input);
+				uni.showToast({
+				    title: '复制成功',
+					icon: 'success',
+					mask:true,
+					duration:2000
+				});
+			}
+		
+		}
+	}
+</script>
+
+<style>
+.mpservice-wrap .mp-image{ width: 560rpx; margin-top: 40rpx;}
+.mpservice-wrap .mp-image image{ width: 100%;}
+</style>

+ 239 - 0
components/mpvue-citypicker/mpvueCityPicker.vue

@@ -0,0 +1,239 @@
+<template>
+	<div class="mpvue-picker">
+		<div :class="{'pickerMask':showPicker}" @click="maskClick" catchtouchmove="true"></div>
+		<div class="mpvue-picker-content " :class="{'mpvue-picker-view-show':showPicker}">
+			<div class="mpvue-picker__hd" catchtouchmove="true">
+				<div class="mpvue-picker__action" @click="pickerCancel">取消</div>
+				<div class="mpvue-picker__action" :style="{color:themeColor}" @click="pickerConfirm">确定</div>
+			</div>
+			<picker-view indicator-style="height: 40px;" class="mpvue-picker-view" :value="pickerValue"
+				@change="pickerChange">
+				<block>
+					<picker-view-column>
+						<div class="picker-item" v-for="(item,index) in provinceDataList" :key="index">{{item.label}}
+						</div>
+					</picker-view-column>
+					<picker-view-column>
+						<div class="picker-item" v-for="(item,index) in cityDataList" :key="index">{{item.label}}</div>
+					</picker-view-column>
+					<picker-view-column>
+						<div class="picker-item" v-for="(item,index) in areaDataList" :key="index">{{item.label}}</div>
+					</picker-view-column>
+				</block>
+			</picker-view>
+		</div>
+	</div>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				pickerValue: [0, 0, 0],
+				provinceDataList: [],
+				cityDataList: [],
+				areaDataList: [],
+				/* 是否显示控件 */
+				showPicker: false,
+				provinceData: [],
+				cityData: [],
+				areaData: []
+			};
+		},
+		created() {
+			this.init()
+		},
+		props: {
+			/* 默认值 */
+			pickerValueDefault: {
+				type: Array,
+				default () {
+					return [0, 0, 0]
+				}
+			},
+			/* 主题色 */
+			themeColor: String,
+			province: {
+				type: Array
+			},
+			city: {
+				type: Array
+			},
+			area: {
+				type: Array
+			}
+		},
+		watch: {
+			pickerValueDefault() {
+				this.init();
+			}
+		},
+		methods: {
+			init() {
+				this.provinceData = this.province;
+				this.cityData = this.city;
+				this.areaData = this.area;
+				this.handPickValueDefault(); // 对 pickerValueDefault 做兼容处理
+				this.provinceDataList = this.provinceData;
+				this.cityDataList = this.cityData[this.pickerValueDefault[0]];
+				this.areaDataList = this.areaData[this.pickerValueDefault[0]][this.pickerValueDefault[1]];
+				this.pickerValue = this.pickerValueDefault;
+			},
+			show() {
+				setTimeout(() => {
+					this.showPicker = true;
+				}, 0);
+			},
+			maskClick() {
+				//this.pickerCancel();
+			},
+			pickerCancel() {
+				this.showPicker = false;
+				this._$emit('onCancel');
+			},
+			pickerConfirm(e) {
+				this.showPicker = false;
+				this._$emit('onConfirm');
+			},
+			showPickerView() {
+				this.showPicker = true;
+			},
+			handPickValueDefault() {
+				if (this.pickerValueDefault !== [0, 0, 0]) {
+					if (this.pickerValueDefault[0] > this.provinceData.length - 1) {
+						this.pickerValueDefault[0] = this.provinceData.length - 1;
+					}
+					if (this.pickerValueDefault[1] > this.cityData[this.pickerValueDefault[0]].length - 1) {
+						this.pickerValueDefault[1] = this.cityData[this.pickerValueDefault[0]].length - 1;
+					}
+					if (this.pickerValueDefault[2] > this.areaData[this.pickerValueDefault[0]][this.pickerValueDefault[1]]
+						.length - 1) {
+						this.pickerValueDefault[2] = this.areaData[this.pickerValueDefault[0]][this.pickerValueDefault[1]]
+							.length - 1;
+					}
+				}
+			},
+			pickerChange(e) {
+				let changePickerValue = e.mp.detail.value;
+				if (this.pickerValue[0] !== changePickerValue[0]) {
+					// 第一级发生滚动
+					this.cityDataList = this.cityData[changePickerValue[0]];
+					this.areaDataList = this.areaData[changePickerValue[0]][0];
+					changePickerValue[1] = 0;
+					changePickerValue[2] = 0;
+				} else if (this.pickerValue[1] !== changePickerValue[1]) {
+					// 第二级滚动
+					this.areaDataList =
+						this.areaData[changePickerValue[0]][changePickerValue[1]];
+					changePickerValue[2] = 0;
+				}
+				this.pickerValue = changePickerValue;
+				this._$emit('onChange');
+			},
+			_$emit(emitName) {
+				let pickObj = {
+					label: this._getLabel(),
+					value: this.pickerValue,
+					cityCode: this._getCityCode()
+				};
+				this.$emit(emitName, pickObj);
+			},
+			_getLabel() {
+				let pcikerLabel =
+					this.provinceDataList[this.pickerValue[0]].label +
+					',' +
+					this.cityDataList[this.pickerValue[1]].label +
+					',' +
+					this.areaDataList[this.pickerValue[2]].label;
+				return pcikerLabel;
+			},
+			_getCityCode() {
+				let pcikerCode = [0, 0, 0];
+				pcikerCode[0] = this.provinceDataList[this.pickerValue[0]].value;
+				pcikerCode[1] = this.cityDataList[this.pickerValue[1]].value;
+				pcikerCode[2] = this.areaDataList[this.pickerValue[2]].value;
+				return pcikerCode;
+			}
+		}
+	};
+</script>
+
+<style>
+	.pickerMask {
+		position: fixed;
+		z-index: 1000;
+		top: 0;
+		right: 0;
+		left: 0;
+		bottom: 0;
+		background: rgba(0, 0, 0, 0.6);
+	}
+
+	.mpvue-picker-content {
+		position: fixed;
+		bottom: 0;
+		left: 0;
+		width: 100%;
+		transition: all 0.3s ease;
+		transform: translateY(100%);
+		z-index: 3000;
+	}
+
+	.mpvue-picker-view-show {
+		transform: translateY(0);
+	}
+
+	.mpvue-picker__hd {
+		display: flex;
+		padding: 9px 15px;
+		background-color: #fff;
+		position: relative;
+		text-align: center;
+		font-size: 17px;
+	}
+
+	.mpvue-picker__hd:after {
+		content: ' ';
+		position: absolute;
+		left: 0;
+		bottom: 0;
+		right: 0;
+		height: 1px;
+		border-bottom: 1px solid #e5e5e5;
+		color: #e5e5e5;
+		transform-origin: 0 100%;
+		transform: scaleY(0.5);
+	}
+
+	.mpvue-picker__action {
+		display: block;
+		flex: 1;
+		color: #1aad19;
+	}
+
+	.mpvue-picker__action:first-child {
+		text-align: left;
+		color: #888;
+	}
+
+	.mpvue-picker__action:last-child {
+		text-align: right;
+	}
+
+	.picker-item {
+		text-align: center;
+		line-height: 40px;
+		text-overflow: ellipsis;
+		white-space: nowrap;
+		font-size: 16px;
+	}
+
+	.mpvue-picker-view {
+		position: relative;
+		bottom: 0;
+		left: 0;
+		width: 100%;
+		height: 238px;
+		background-color: rgba(255, 255, 255, 1);
+	}
+</style>

+ 463 - 0
components/mpvue-picker/mpvuePicker.vue

@@ -0,0 +1,463 @@
+<template>
+    <view class="mpvue-picker">
+        <view :class="{'pickerMask':showPicker}" @click="maskClick" catchtouchmove="true"></view>
+        <view class="mpvue-picker-content " :class="{'mpvue-picker-view-show':showPicker}">
+            <view class="mpvue-picker__hd" catchtouchmove="true">
+                <view class="mpvue-picker__action" @click="pickerCancel">取消</view>
+                <view class="mpvue-picker__action" :style="{color:themeColor}" @click="pickerConfirm">确定</view>
+            </view>
+            <!-- 单列 -->
+            <picker-view indicator-style="height: 40px;" class="mpvue-picker-view" :value="pickerValue" @change="pickerChange" v-if="mode==='selector' && pickerValueSingleArray.length > 0">
+                <block>
+                    <picker-view-column>
+                        <view class="picker-item" v-for="(item,index) in pickerValueSingleArray" :key="index">{{item.label}}</view>
+                    </picker-view-column>
+                </block>
+            </picker-view>
+            <!-- 时间选择器 -->
+            <picker-view indicator-style="height: 40px;" class="mpvue-picker-view" :value="pickerValue" @change="pickerChange" v-if="mode==='timeSelector'">
+                <block>
+                    <picker-view-column>
+                        <view class="picker-item" v-for="(item,index) in pickerValueHour" :key="index">{{item.label}}</view>
+                    </picker-view-column>
+                    <picker-view-column>
+                        <view class="picker-item" v-for="(item,index) in pickerValueMinute" :key="index">{{item.label}}</view>
+                    </picker-view-column>
+                </block>
+            </picker-view>
+            <!-- 多列选择 -->
+            <picker-view indicator-style="height: 40px;" class="mpvue-picker-view" :value="pickerValue" @change="pickerChange" v-if="mode==='multiSelector'">
+                <block v-for="(n,index) in pickerValueMulArray.length" :key="index">
+                    <picker-view-column>
+                        <view class="picker-item" v-for="(item,index1) in pickerValueMulArray[n]" :key="index1">{{item.label}}</view>
+                    </picker-view-column>
+                </block>
+            </picker-view>
+            <!-- 二级联动 -->
+            <picker-view indicator-style="height: 40px;" class="mpvue-picker-view" :value="pickerValue" @change="pickerChangeMul" v-if="mode==='multiLinkageSelector' && deepLength===2">
+                <block>
+                    <picker-view-column>
+                        <view class="picker-item" v-for="(item,index) in pickerValueMulTwoOne" :key="index">{{item.label}}</view>
+                    </picker-view-column>
+                    <picker-view-column>
+                        <view class="picker-item" v-for="(item,index) in pickerValueMulTwoTwo" :key="index">{{item.label}}</view>
+                    </picker-view-column>
+                </block>
+            </picker-view>
+            <!-- 三级联动 -->
+            <picker-view indicator-style="height: 40px;" class="mpvue-picker-view" :value="pickerValue" @change="pickerChangeMul" v-if="mode==='multiLinkageSelector' && deepLength===3">
+                <block>
+                    <picker-view-column>
+                        <view class="picker-item" v-for="(item,index) in pickerValueMulThreeOne" :key="index">{{item.label}}</view>
+                    </picker-view-column>
+                    <picker-view-column>
+                        <view class="picker-item" v-for="(item,index) in pickerValueMulThreeTwo" :key="index">{{item.label}}</view>
+                    </picker-view-column>
+                    <picker-view-column>
+                        <view class="picker-item" v-for="(item,index) in pickerValueMulThreeThree" :key="index">{{item.label}}</view>
+                    </picker-view-column>
+                </block>
+            </picker-view>
+        </view>
+    </view>
+</template>
+
+<script>
+    export default {
+        data() {
+            return {
+                pickerChangeValue: [],
+                pickerValue: [],
+                pickerValueArrayChange: true,
+                modeChange: false,
+                pickerValueSingleArray: [],
+                pickerValueHour: [],
+                pickerValueMinute: [],
+                pickerValueMulArray: [],
+                pickerValueMulTwoOne: [],
+                pickerValueMulTwoTwo: [],
+                pickerValueMulThreeOne: [],
+                pickerValueMulThreeTwo: [],
+                pickerValueMulThreeThree: [],
+				/* 是否显示控件 */
+				showPicker: false,
+            };
+        },
+        props: {
+            /* mode */
+            mode: {
+                type: String,
+                default: 'selector'
+            },
+            /* picker 数值 */
+            pickerValueArray: {
+                type: Array,
+                default(){
+					return []
+				}
+            },
+            /* 默认值 */
+            pickerValueDefault: {
+                type: Array,
+                default(){
+                	return []
+                }
+            },
+            /* 几级联动 */
+            deepLength: {
+                type: Number,
+                default: 2
+            },
+            /* 主题色 */
+            themeColor: String
+        },
+        watch: {
+            pickerValueArray(oldVal, newVal) {
+                this.pickerValueArrayChange = true;
+            },
+            mode(oldVal, newVal) {
+                this.modeChange = true;
+            },
+			pickerValueArray(val){
+				this.initPicker(val);
+			}
+        },
+        methods: {
+            initPicker(valueArray) {
+                let pickerValueArray = valueArray;
+                this.pickerValue = this.pickerValueDefault;
+                // 初始化多级联动
+                if (this.mode === 'selector') {
+                    this.pickerValueSingleArray = valueArray;
+                } else if (this.mode === 'timeSelector') {
+                    this.modeChange = false;
+                    let hourArray = [];
+                    let minuteArray = [];
+                    for (let i = 0; i < 24; i++) {
+                        hourArray.push({
+                            value: i,
+                            label: i > 9 ? `${i} 时` : `0${i} 时`
+                        });
+                    }
+                    for (let i = 0; i < 60; i++) {
+                        minuteArray.push({
+                            value: i,
+                            label: i > 9 ? `${i} 分` : `0${i} 分`
+                        });
+                    }
+                    this.pickerValueHour = hourArray;
+                    this.pickerValueMinute = minuteArray;
+                } else if (this.mode === 'multiSelector') {
+                    this.pickerValueMulArray = valueArray;
+                } else if (this.mode === 'multiLinkageSelector' && this.deepLength === 2) {
+                    // 两级联动
+                    let pickerValueMulTwoOne = [];
+                    let pickerValueMulTwoTwo = [];
+                    // 第一列
+                    for (let i = 0, length = pickerValueArray.length; i < length; i++) {
+                        pickerValueMulTwoOne.push(pickerValueArray[i]);
+                    }
+                    // 渲染第二列
+                    // 如果有设定的默认值
+                    if (this.pickerValueDefault.length === 2) {
+                        let num = this.pickerValueDefault[0];
+                        for (
+                            let i = 0, length = pickerValueArray[num].children.length; i < length; i++
+                        ) {
+                            pickerValueMulTwoTwo.push(pickerValueArray[num].children[i]);
+                        }
+                    } else {
+                        for (
+                            let i = 0, length = pickerValueArray[0].children.length; i < length; i++
+                        ) {
+                            pickerValueMulTwoTwo.push(pickerValueArray[0].children[i]);
+                        }
+                    }
+                    this.pickerValueMulTwoOne = pickerValueMulTwoOne;
+                    this.pickerValueMulTwoTwo = pickerValueMulTwoTwo;
+                } else if (
+                    this.mode === 'multiLinkageSelector' &&
+                    this.deepLength === 3
+                ) {
+                    let pickerValueMulThreeOne = [];
+                    let pickerValueMulThreeTwo = [];
+                    let pickerValueMulThreeThree = [];
+                    // 第一列
+                    for (let i = 0, length = pickerValueArray.length; i < length; i++) {
+                        pickerValueMulThreeOne.push(pickerValueArray[i]);
+                    }
+                    // 渲染第二列
+                    this.pickerValueDefault =
+                        this.pickerValueDefault.length === 3 ?
+                        this.pickerValueDefault :
+                        [0, 0, 0];
+                    if (this.pickerValueDefault.length === 3) {
+                        let num = this.pickerValueDefault[0];
+                        for (
+                            let i = 0, length = pickerValueArray[num].children.length; i < length; i++
+                        ) {
+                            pickerValueMulThreeTwo.push(pickerValueArray[num].children[i]);
+                        }
+                        // 第三列
+                        let numSecond = this.pickerValueDefault[1];
+                        for (let i = 0, length = pickerValueArray[num].children[numSecond].children.length; i < length; i++) {
+                            pickerValueMulThreeThree.push(
+                                pickerValueArray[num].children[numSecond].children[i]
+                            );
+                        }
+                    }
+                    this.pickerValueMulThreeOne = pickerValueMulThreeOne;
+                    this.pickerValueMulThreeTwo = pickerValueMulThreeTwo;
+                    this.pickerValueMulThreeThree = pickerValueMulThreeThree;
+                }
+            },
+            show() {
+                setTimeout(() => {
+                    if (this.pickerValueArrayChange || this.modeChange) {
+                        this.initPicker(this.pickerValueArray);
+                        this.showPicker = true;
+                        this.pickerValueArrayChange = false;
+                        this.modeChange = false;
+                    } else {
+                        this.showPicker = true;
+                    }
+                }, 0);
+            },
+            maskClick() {
+                this.pickerCancel();
+            },
+            pickerCancel() {
+                this.showPicker = false;
+                this._initPickerVale();
+                let pickObj = {
+                    index: this.pickerValue,
+                    value: this._getPickerLabelAndValue(this.pickerValue, this.mode).value,
+                    label: this._getPickerLabelAndValue(this.pickerValue, this.mode).label
+                };
+                this.$emit('onCancel', pickObj);
+            },
+            pickerConfirm(e) {
+                this.showPicker = false;
+                this._initPickerVale();
+                let pickObj = {
+                    index: this.pickerValue,
+                    value: this._getPickerLabelAndValue(this.pickerValue, this.mode).value,
+                    label: this._getPickerLabelAndValue(this.pickerValue, this.mode).label
+                };
+                this.$emit('onConfirm', pickObj);
+            },
+            showPickerView() {
+                this.showPicker = true;
+            },
+            pickerChange(e) {
+                this.pickerValue = e.mp.detail.value;
+                let pickObj = {
+                    index: this.pickerValue,
+                    value: this._getPickerLabelAndValue(this.pickerValue, this.mode).value,
+                    label: this._getPickerLabelAndValue(this.pickerValue, this.mode).label
+                };
+                this.$emit('onChange', pickObj);
+            },
+            pickerChangeMul(e) {
+                if (this.deepLength === 2) {
+                    let pickerValueArray = this.pickerValueArray;
+                    let changeValue = e.mp.detail.value;
+                    // 处理第一列滚动
+                    if (changeValue[0] !== this.pickerValue[0]) {
+                        let pickerValueMulTwoTwo = [];
+                        // 第一列滚动第二列数据更新
+                        for (let i = 0, length = pickerValueArray[changeValue[0]].children.length; i < length; i++) {
+                            pickerValueMulTwoTwo.push(pickerValueArray[changeValue[0]].children[i]);
+                        }
+                        this.pickerValueMulTwoTwo = pickerValueMulTwoTwo;
+                        // 第二列初始化为 0
+                        changeValue[1] = 0;
+                    }
+                    this.pickerValue = changeValue;
+                } else if (this.deepLength === 3) {
+                    let pickerValueArray = this.pickerValueArray;
+                    let changeValue = e.mp.detail.value;
+                    let pickerValueMulThreeTwo = [];
+                    let pickerValueMulThreeThree = [];
+                    // 重新渲染第二列
+                    // 如果是第一列滚动
+                    if (changeValue[0] !== this.pickerValue[0]) {
+                        this.pickerValueMulThreeTwo = [];
+                        for (let i = 0, length = pickerValueArray[changeValue[0]].children.length; i < length; i++) {
+                            pickerValueMulThreeTwo.push(pickerValueArray[changeValue[0]].children[i]);
+                        }
+                        // 重新渲染第三列
+                        for (let i = 0, length = pickerValueArray[changeValue[0]].children[0].children.length; i <
+                            length; i++) {
+                            pickerValueMulThreeThree.push(pickerValueArray[changeValue[0]].children[0].children[i]);
+                        }
+                        changeValue[1] = 0;
+                        changeValue[2] = 0;
+                        this.pickerValueMulThreeTwo = pickerValueMulThreeTwo;
+                        this.pickerValueMulThreeThree = pickerValueMulThreeThree;
+                    } else if (changeValue[1] !== this.pickerValue[1]) {
+                        // 第二列滚动
+                        // 重新渲染第三列
+                        this.pickerValueMulThreeThree = [];
+                        pickerValueMulThreeTwo = this.pickerValueMulThreeTwo;
+                        for (let i = 0, length = pickerValueArray[changeValue[0]].children[changeValue[1]].children.length; i <
+                            length; i++) {
+                            pickerValueMulThreeThree.push(pickerValueArray[changeValue[0]].children[changeValue[1]].children[
+                                i]);
+                        }
+                        changeValue[2] = 0;
+                        this.pickerValueMulThreeThree = pickerValueMulThreeThree;
+                    }
+                    this.pickerValue = changeValue;
+                }
+                let pickObj = {
+                    index: this.pickerValue,
+                    value: this._getPickerLabelAndValue(this.pickerValue, this.mode).value,
+                    label: this._getPickerLabelAndValue(this.pickerValue, this.mode).label
+                };
+                this.$emit('onChange', pickObj);
+            },
+            // 获取 pxikerLabel
+            _getPickerLabelAndValue(value, mode) {
+                let pickerLable;
+                let pickerGetValue = [];
+                // selector
+                if (mode === 'selector') {
+                    pickerLable = this.pickerValueSingleArray[value].label;
+                    pickerGetValue.push(this.pickerValueSingleArray[value].value);
+                } else if (mode === 'timeSelector') {
+                    pickerLable = `${this.pickerValueHour[value[0]].label}-${this.pickerValueMinute[value[1]].label}`;
+                    pickerGetValue.push(this.pickerValueHour[value[0]].value);
+                    pickerGetValue.push(this.pickerValueHour[value[1]].value);
+                } else if (mode === 'multiSelector') {
+                    for (let i = 0; i < value.length; i++) {
+                        if (i > 0) {
+                            pickerLable += this.pickerValueMulArray[i][value[i]].label + (i === value.length - 1 ? '' :
+                                '-');
+                        } else {
+                            pickerLable = this.pickerValueMulArray[i][value[i]].label + '-';
+                        }
+                        pickerGetValue.push(this.pickerValueMulArray[i][value[i]].value);
+                    }
+                } else if (mode === 'multiLinkageSelector') {
+                    /* eslint-disable indent */
+                    pickerLable =
+                        this.deepLength === 2 ?
+                        `${this.pickerValueMulTwoOne[value[0]].label}-${this.pickerValueMulTwoTwo[value[1]].label}` :
+                        `${this.pickerValueMulThreeOne[value[0]].label}-${this.pickerValueMulThreeTwo[value[1]].label}-${this.pickerValueMulThreeThree[value[2]].label}`;
+                    if (this.deepLength === 2) {
+                        pickerGetValue.push(this.pickerValueMulTwoOne[value[0]].value);
+                        pickerGetValue.push(this.pickerValueMulTwoTwo[value[1]].value);
+                    } else {
+                        pickerGetValue.push(this.pickerValueMulThreeOne[value[0]].value);
+                        pickerGetValue.push(this.pickerValueMulThreeTwo[value[1]].value);
+                        pickerGetValue.push(this.pickerValueMulThreeThree[value[2]].value);
+                    }
+                    /* eslint-enable indent */
+                }
+                return {
+                    label: pickerLable,
+                    value: pickerGetValue
+                };
+            },
+            // 初始化 pickerValue 默认值
+            _initPickerVale() {
+                if (this.pickerValue.length === 0) {
+                    if (this.mode === 'selector') {
+                        this.pickerValue = [0];
+                    } else if (this.mode === 'multiSelector') {
+                        this.pickerValue = new Int8Array(this.pickerValueArray.length);
+                    } else if (
+                        this.mode === 'multiLinkageSelector' &&
+                        this.deepLength === 2
+                    ) {
+                        this.pickerValue = [0, 0];
+                    } else if (
+                        this.mode === 'multiLinkageSelector' &&
+                        this.deepLength === 3
+                    ) {
+                        this.pickerValue = [0, 0, 0];
+                    }
+                }
+            }
+        }
+    };
+</script>
+
+<style>
+    .pickerMask {
+        position: fixed;
+        z-index: 1000;
+        top: 0;
+        right: 0;
+        left: 0;
+        bottom: 0;
+        background: rgba(0, 0, 0, 0.6);
+    }
+
+    .mpvue-picker-content {
+        position: fixed;
+        bottom: 0;
+        left: 0;
+        width: 100%;
+        transition: all 0.3s ease;
+        transform: translateY(100%);
+        z-index: 3000;
+    }
+
+    .mpvue-picker-view-show {
+        transform: translateY(0);
+    }
+
+    .mpvue-picker__hd {
+        display: flex;
+        padding: 9px 15px;
+        background-color: #fff;
+        position: relative;
+        text-align: center;
+        font-size: 17px;
+    }
+
+    .mpvue-picker__hd:after {
+        content: ' ';
+        position: absolute;
+        left: 0;
+        bottom: 0;
+        right: 0;
+        height: 1px;
+        border-bottom: 1px solid #e5e5e5;
+        color: #e5e5e5;
+        transform-origin: 0 100%;
+        transform: scaleY(0.5);
+    }
+
+    .mpvue-picker__action {
+        display: block;
+        flex: 1;
+        color: #1aad19;
+    }
+
+    .mpvue-picker__action:first-child {
+        text-align: left;
+        color: #888;
+    }
+
+    .mpvue-picker__action:last-child {
+        text-align: right;
+    }
+
+    .picker-item {
+        text-align: center;
+        line-height: 40px;
+        font-size: 16px;
+    }
+
+    .mpvue-picker-view {
+        position: relative;
+        bottom: 0;
+        left: 0;
+        width: 100%;
+        height: 238px;
+        background-color: rgba(255, 255, 255, 1);
+    }
+</style>

+ 100 - 0
components/navBar/navBar.vue

@@ -0,0 +1,100 @@
+<template>
+	<view>
+		<scroll-view scroll-y="true" class="scroll" @scroll="scrollChnage">
+			<view class="navbar-section" :class="{'navbar-fixed-section': isFixed}">
+				<ss-scroll-navbar :tabCurrentIndex="currentIndex" @navbarTap="navbarTapHandler" :scrollChangeIndex="currentI"
+				 :navArr="navList"></ss-scroll-navbar>
+			</view>
+		</scroll-view>
+	</view>
+</template>
+
+<script>
+	import ssScrollNavbar from '@/components/navBar/scroll-navbar.vue'
+
+	export default {
+		props: ['currentI', 'navList'],
+		components: {
+			ssScrollNavbar
+		},
+		data() {
+			return {
+				currentIndex: 0,
+				isFixed: false,
+				topHeight: 0,
+				listData: [],
+			}
+		},
+		onLoad(options) {
+			// uni.setNavigationBarTitle({
+			// 	title: options.title
+			// });
+			this.calculateTopSectionHeight();
+		},
+		created() {},
+		methods: {
+
+			navbarTapHandler(index) {
+				this.currentIndex = index;
+				this.$emit('currentIndex', index)
+			},
+			scrollChnage(e) {
+				let top = e.detail.scrollTop;
+				if (top >= this.topHeight) {
+					this.isFixed = true;
+				} else {
+					this.isFixed = false;
+				}
+			},
+			/**
+			 * 计算头部视图的高度
+			 */
+			calculateTopSectionHeight() {
+				var that = this;
+				let topView = uni.createSelectorQuery().select(".top-section");
+				topView.fields({
+					size: true
+				}, data => {
+					that.topHeight = data.height;
+				}).exec();
+			}
+		},
+		watch: {
+			currentI: function(newVal) {
+				this.navbarTapHandler(newVal)
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.scroll {
+		// position: absolute;
+		// top: 0upx;
+		// left: 0upx;
+		// bottom: 0upx;
+		// right: 0upx;
+
+		// .navbar-fixed-section {
+		// 	position: fixed;
+		// 	top: 0upx;
+		// 	left: 0upx;
+		// 	right: 0upx;
+		// }
+
+		.top-section {
+			height: 350upx;
+			background-color: green;
+		}
+
+		.bottom-section {
+			height: 1500upx;
+			background-color: yellow;
+		}
+
+		.footer-section {
+			height: 1500upx;
+			background-color: blue;
+		}
+	}
+</style>

+ 137 - 0
components/navBar/scroll-navbar.vue

@@ -0,0 +1,137 @@
+<template>
+	<scroll-view class="ss-scroll-navbar" scroll-x :scroll-left="scrollLeft" scroll-with-animation="true">
+		<view v-for="(item, index) in navArr" :key="item.category_id" class="nav-item" :class="{current: index === tabCurrentIndex}"
+		 @click="tabChange(index)" :id="'item-' + index">
+			<text class="title">{{item.name}}</text>
+		</view>
+	</scroll-view>
+
+
+</template>
+
+<script>
+	export default {
+		name: 'ss-scroll-navbar',
+		props: {
+			navArr: {
+				type: Array,
+				default () {
+					return [{
+						name: '推荐',
+						category_id: 'recent'
+					}]
+				}
+			},
+			tabCurrentIndex: {
+				type: Number,
+				default: 0
+			},
+			scrollChangeIndex: {
+				type: Number,
+				default: 0
+			},
+		},
+		data() {
+			return {
+				scrollLeft: 0,
+				widthList: [],
+				screenWidth: 0,
+			}
+		},
+		methods: {
+			/**
+			 * 导航栏navbar
+			 * 点击事件
+			 */
+			tabChange(index) {
+				this.$emit('navbarTap', index);
+				var widthArr = this.widthList;
+				var scrollWidth = 0;
+				for (var i = 0; i < index + 1; i++) {
+					scrollWidth += widthArr[i];
+				}
+				let currentWidth = widthArr[index];
+				// scrollView 居中算法
+				// 减去固定宽度位移
+				// 减去选中的bar的宽度的一半
+				scrollWidth -= this.screenWidth / 2;
+				scrollWidth -= currentWidth / 2;
+				this.scrollLeft = scrollWidth;
+			},
+			calculateItemWidth() {
+				var that = this;
+				var arr = [];
+				let w = 0;
+				this.navArr.forEach((item, index) => {
+					let view = uni.createSelectorQuery().in(this).select("#item-" + index);
+					view.fields({
+						size: true
+					}, data => {
+						arr.push(data.width);
+					}).exec();
+				})
+				this.widthList = arr;
+			},
+			calculateWindowWidth() {
+				var info = uni.getSystemInfoSync();
+				this.screenWidth = info.screenWidth;
+			}
+		},
+		created() {
+			var that = this;
+			this.calculateWindowWidth();
+			setTimeout(function() {
+				that.calculateItemWidth();
+			}, 1000);
+		},
+		watch: {
+			scrollChangeIndex(val) {
+				this.tabChange(val)
+			},
+		},
+
+	}
+</script>
+
+<style lang="scss">
+	.ss-scroll-navbar {
+		width: 100%;
+		height: 80rpx;
+		box-shadow: 0 2upx 8upx rgba(0, 0, 0, .06);
+		white-space: nowrap;
+		text-align: start;
+		.nav-item {
+			height: 80rpx;
+			text-align: center;
+			padding: 0upx 20upx;
+			color: #FFFFFF;
+			display: inline-block;
+			position: relative;
+			font-size: 32upx;
+
+			.title {
+				line-height: 80rpx;
+			}
+
+			&:after {
+				content: '';
+				width: 0;
+				height: 0;
+				border-bottom: 4upx solid #ffffff;
+				position: absolute;
+				left: 50%;
+				bottom: 0;
+				transform: translateX(-50%);
+				transition: .3s;
+			}
+		}
+
+		.current {
+			color: #ffffff;
+			font-weight: bold;
+			&:after {
+				width: 50%;
+			}
+		}
+	}
+</style>

+ 38 - 0
components/page-foot.vue

@@ -0,0 +1,38 @@
+<template name="page-foot">
+	<view class="page-share-title">
+		<text>感谢{{name}}提供本示例,</text>
+		<text class="submit" @tap="submit">我也提交</text>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: "page-foot",
+		props: {
+			name: {
+				type: String,
+				default: ""
+			}
+		},
+		methods: {
+			submit() {
+				uni.showModal({
+					content:"hello uni-app开源地址为https://github.com/dcloudio/uni-app/tree/master/examples,请在这个开源项目上贡献你的代码",
+					showCancel:false
+				})
+			}
+		}
+	}
+</script>
+<style>
+	.page-share-title {
+		text-align: center;
+		font-size: 30upx;
+		color: #BEBEBE;
+		padding: 20upx 0;
+	}
+
+	.submit {
+		border-bottom: 1upx solid #BEBEBE;
+	}
+</style>

+ 179 - 0
components/recommendProduct/recommendProduct.vue

@@ -0,0 +1,179 @@
+<template>
+	<view class="recommend-product" v-if="isShow">
+		<view class="title d-c-c">
+			<text class="line-left"></text>
+			<text class="name">{{showName}}</text>
+			<text class="line-right"></text>
+		</view>
+		<view class="recommend-product-list">
+			<view class="item" v-for="(item, index) in listData" :key="index" @click="gotoProduct(item.product_id)">
+				<view class="product-cover">
+					<image :src="item.product_image" mode="aspectFill"></image>
+				</view>
+				<view class="product-info">
+					<view class="product-title">{{ item.product_name }}</view>
+					<view class="d-b-c mt20">
+						<!-- <view class="already-sale f22 gray9">已售{{ item.product_sales }}件</view> -->
+						<view class="price">
+							¥
+							<text class="num">{{ item.product_sku.product_price }}</text>
+						</view>
+					</view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				/*数据*/
+				listData: [],
+				isShow: false,
+				showName: ''
+			};
+		},
+		created() {
+			this.getData();
+		},
+		props: ['location'],
+		methods: {
+			/*获取数据*/
+			getData() {
+				let self = this;
+				let page = self.page;
+				self._post(
+					'product.product/recommendProduct', {
+						location: self.location
+					},
+					function(res) {
+						if (res.data.is_recommend == true) {
+							self.isShow = true;
+							self.showName = res.data.recommend.name;
+							self.listData = res.data.list;
+						}
+					}
+				);
+			},
+
+			/*推荐商品跳转*/
+			gotoProduct(e) {
+				let url = 'pages/product/detail/detail?product_id=' + e
+				this.gotoPage(url);
+			}
+		}
+	};
+</script>
+
+<style lang="scss">
+	.recommend-product {
+		margin-top: 40rpx;
+	}
+
+	.recommend-product .title {
+		heigth: 100rpx;
+		font-size: 30rpx;
+	}
+
+	.recommend-product .title .name {
+		margin: 0 20rpx;
+		font-size: 30rpx;
+	}
+
+	.recommend-product .title .line {
+		position: relative;
+		display: block;
+		width: 100rpx;
+		border-top: 1px solid red;
+	}
+
+	.recommend-product .title .line::after {
+		position: absolute;
+		content: '';
+		display: block;
+		width: 16rpx;
+		height: 16rpx;
+		border-radius: 50%;
+		background: red;
+	}
+
+	.recommend-product .title .left-line::after {
+		right: 0;
+		top: -9rpx;
+	}
+
+	.recommend-product .title .right-line::after {
+		left: 0;
+		top: -9rpx;
+	}
+
+	.recommend-product-list {
+		padding: 20rpx;
+		display: flex;
+		justify-content: space-between;
+		align-items: flex-start;
+		flex-wrap: wrap;
+	}
+
+	.recommend-product-list .item {
+		width: 350rpx;
+		border-radius: 20rpx;
+		margin-right: 10rpx;
+		margin-bottom: 20rpx;
+		padding-bottom: 20rpx;
+		overflow: hidden;
+		background: #ffffff;
+		box-shadow: 0 0 8rpx rgba(0, 0, 0, .1);
+		margin-bottom: 10rpx;
+	}
+
+	.recommend-product-list .item:nth-child(2n+0) {
+		margin-right: 0;
+	}
+
+	.recommend-product-list .product-cover {
+		width: 350rpx;
+		height: 350rpx;
+	}
+
+	.recommend-product-list image {
+		width: 100%;
+		height: 100%;
+	}
+
+	.recommend-product-list .product-info {
+		padding: 0 24rpx;
+	}
+
+	.recommend-product-list .product-title {
+		height: 80rpx;
+		margin-top: 20rpx;
+		display: -webkit-box;
+		overflow: hidden;
+		-webkit-line-clamp: 2;
+		-webkit-box-orient: vertical;
+		font-size: 30rpx;
+	}
+
+	.recommend-product-list .price {
+		color: $dominant-color;
+	}
+
+	.recommend-product-list .price .num {
+		font-size: 30rpx;
+		font-weight: bold;
+	}
+	.line-left {
+		width: 80px;
+		height: 3px;
+		background-image: linear-gradient(to right, #EBEBEB, #666666);
+	}
+	
+	.line-right {
+		width: 80px;
+		height: 3px;
+		background-image: linear-gradient(to left, #EBEBEB, #666666);
+	}
+</style>

+ 193 - 0
components/searchProduct.vue

@@ -0,0 +1,193 @@
+<template>
+	<view v-if="isShow" @touchmove.stop.prevent="stopTouchMove">
+		<view class="search-wrap">
+			<!-- #ifdef H5-->
+			<view class="state_top"></view>
+			<!-- #endif -->
+			<view class="head_top" :style="'height:'+topBarTop()+'px;'"></view>
+			<!-- 搜索框 -->
+			<view class="index-search-box d-b-c" id="searchBox"
+				:style="topBarHeight() == 0 ? '': 'height:'+topBarHeight()+'px;padding-right: 200rpx'">
+				<view class="reg180" :style="topBarHeight() == 0 ? '': 'height:'+topBarHeight()+'px;'">
+					<text @click="closeSearch" class="icon iconfont icon-jiantou"></text>
+				</view>
+				<view class="index-search t-c flex-1" :style="topBarHeight() == 0 ? '': 'height:'+topBarHeight()+'px;'">
+					<text class="icon iconfont icon-sousuo"></text>
+					<input type="text" v-model="form.keyWord" class="flex-1 ml10 f30 gray3" value=""
+						placeholder-class="f24 gray6" placeholder="输入你要的商品" confirm-type="search" @confirm="search()" />
+						<!-- <text @click="closeSearch">取消</text> -->
+				</view>
+			</view>
+			<view class="p-0-20 bg-white">
+				<view class="group-hd">
+					<view class="left"><text class="min-name">最近搜索</text></view>
+					<view class="right">
+						<text class="icon iconfont icon-lajitong" @click='clearStorage'></text>
+					</view>
+				</view>
+				<view class="before-search">
+					<text class="item" v-for="(item,index) in arr" :key="index"
+						@click="search(arr[index])">{{arr[index]}}</text>
+				</view>
+			</view>
+
+		</view>
+	</view>
+
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				form: {
+
+				},
+				arr: [],
+			}
+		},
+		mounted() {
+			/*获取缓存数据*/
+			this.getData();
+		},
+		props: ['isShow'],
+		methods: {
+			/*获取缓存里的搜索历史*/
+			getData() {
+				let self = this;
+				/*获取搜索记录*/
+				uni.getStorage({
+					key: 'search_list',
+					success: function(res) {
+						if (res != null && res.data != null) {
+							self.arr = res.data;
+						}
+					}
+				});
+
+			},
+			/* 禁止手动滑动 */
+			stopTouchMove() {
+				return true
+			},
+			/*搜索*/
+			search(str) {
+				let self = this;
+				let search = null;
+				if (str != null) {
+					search = str;
+				} else {
+					search = this.form.keyWord;
+					let arrs = this.arr;
+					if (typeof search != "undefined" && search != null && search != '') {
+						arrs.push(search);
+					} else {
+						uni.showToast({
+							title: '请输入搜索的关键字',
+							icon: 'none',
+							duration: 2000
+						});
+						return false;
+					}
+					/*设置搜索记录*/
+					uni.setStorage({
+						key: 'search_list',
+						data: arrs,
+						success: function() {
+							console.log('success');
+						}
+					});
+				}
+				let category_id = 0;
+				let sortType = 'all';
+
+				self.gotoPage('/pages/product/list/list?search=' + search + '&category_id=' + category_id + '&sortType=' +
+					sortType);
+
+			},
+			/*清楚缓存*/
+			clearStorage() {
+				let self = this;
+				uni.removeStorage({
+					key: 'search_list',
+					success: function(res) {
+						self.arr = [];
+					}
+				});
+			},
+			closeSearch(){
+				this.$emit('close')
+			}
+		}
+	}
+</script>
+
+<style>
+	.search-wrap {
+		position: fixed;
+		z-index: 999;
+		top: 0;
+		left: 0;
+		width: 100%;
+		height: 100%;
+		background-color: #f5f5f5;
+	}
+
+	.search-wrap .index-search-box .search-box {
+		padding: 0 20rpx;
+		height: 64rpx;
+		line-height: 64rpx;
+		background: #F5F5F5;
+		border-radius: 50rpx;
+		overflow: hidden;
+		font-size: 28rpx;
+		color: #999;
+		box-sizing: border-box;
+	}
+
+	.search-wrap .index-search-box button {
+		height: 78rpx;
+		line-height: 78rpx;
+		border: solid 1rpx #CCCCCC;
+		color: #333333;
+		background: #FFFFFF;
+	}
+	.search-wrap .index-search-box{
+		padding: 0 30rpx;
+		padding-bottom: 30rpx;
+		background-color: #F5F5F5;
+	}
+	.before-search {
+		display: flex;
+		justify-content: flex-start;
+		align-items: center;
+		flex-flow: wrap;
+	}
+
+	.before-search .item {
+		padding: 16rpx;
+		margin-right: 16rpx;
+		margin-bottom: 16rpx;
+		border-radius: 8rpx;
+		color: #686868;
+		background: #f0f2f5;
+		font-size: 24rpx;
+	}
+	.reg180 {
+		padding-left: 20rpx;
+		text-align: center;
+		transform: rotateY(180deg);
+		display: flex;
+		justify-content: flex-end;
+		align-items: center;
+	}
+	
+	 .reg180 .icon-jiantou {
+		color: #333333;
+		display: block;
+		width: 44rpx;
+		height: 44rpx;
+		line-height: 44rpx;
+		font-size: 36rpx;
+	}
+</style>

+ 127 - 0
components/uni-icon/readme.md

@@ -0,0 +1,127 @@
+### Icon 图标
+
+用于展示 icon,组件名:``uni-icon``,代码块: uIcon。
+
+**使用方式:**
+
+在 ``script`` 中引用组件 
+
+```javascript
+import uniIcon from "@/components/uni-icon/uni-icon.vue"
+export default {
+    components: {uniIcon}
+}
+```
+
+在 ``template`` 中使用组件
+
+```html
+<uni-icon type="contact" size="30"></uni-icon>
+```
+
+实际效果参考:[https://github.com/dcloudio/uni-ui](https://github.com/dcloudio/uni-ui)
+
+**Icon 属性说明:**
+
+|属性名		|类型|默认值	|说明|
+|---|----|---|---|
+|type	|String	|-|图标图案,参考下表|
+|color	|String	|-|图标颜色	|
+|size	|Number	|24|图标大小|
+|@click	|EventHandle|-|点击 Icon 触发事件|
+
+**type 类型:**
+
+<div>
+  <link rel="stylesheet" type="text/css" href="https://img-cdn-qiniu.dcloud.net.cn/uniapp/doc/icon1.1.css"/>
+  <ul class="icon-group">
+  	<li class="icon-item"><span class="uni-icon uni-icon-contact"></span><span>contact</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-person"></span><span>person</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-personadd"></span><span>personadd</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-contact-filled"></span><span>contact-filled</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-person-filled"></span><span>person-filled</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-personadd-filled"></span><span>personadd-filled</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-phone"></span><span>phone</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-email"></span><span>email</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-chatbubble"></span><span>chatbubble</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-chatboxes"></span><span>chatboxes</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-phone-filled"></span><span>phone-filled</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-email-filled"></span><span>email-filled</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-chatbubble-filled"></span><span>chatbubble-filled</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-chatboxes-filled"></span><span>chatboxes-filled</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-weibo"></span><span>weibo</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-weixin"></span><span>weixin</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-pengyouquan"></span><span>pengyouquan</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-chat"></span><span>chat</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-qq"></span><span>qq</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-videocam"></span><span>videocam</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-camera"></span><span>camera</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-mic"></span><span>mic</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-location"></span><span>location</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-mic-filled"></span><span>mic-filled</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-location-filled"></span><span>location-filled</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-micoff"></span><span>micoff</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-image"></span><span>image</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-map"></span><span>map</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-compose"></span><span>compose</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-trash"></span><span>trash</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-upload"></span><span>upload</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-download"></span><span>download</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-close"></span><span>close</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-redo"></span><span>redo</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-undo"></span><span>undo</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-refresh"></span><span>refresh</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-star"></span><span>star</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-plus"></span><span>plus</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-minus"></span><span>minus</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-circle"></span><span>circle</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-clear"></span><span>clear</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-refresh-filled"></span><span>refresh-filled</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-star-filled"></span><span>star-filled</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-plus-filled"></span><span>plus-filled</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-minus-filled"></span><span>minus-filled</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-circle-filled"></span><span>circle-filled</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-checkbox-filled"></span><span>checkbox-filled</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-closeempty"></span><span>closeempty</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-refreshempty"></span><span>refreshempty</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-reload"></span><span>reload</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-starhalf"></span><span>starhalf</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-spinner"></span><span>spinner</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-spinner-cycle"></span><span>spinner-cycle</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-search"></span><span>search</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-plusempty"></span><span>plusempty</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-forward"></span><span>forward</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-back"></span><span>back</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-checkmarkempty"></span><span>checkmarkempty</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-home"></span><span>home</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-navigate"></span><span>navigate</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-gear"></span><span>gear</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-paperplane"></span><span>paperplane</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-info"></span><span>info</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-help"></span><span>help</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-locked"></span><span>locked</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-more"></span><span>more</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-flag"></span><span>flag</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-home-filled"></span><span>home-filled</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-gear-filled"></span><span>gear-filled</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-info-filled"></span><span>info-filled</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-help-filled"></span><span>help-filled</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-more-filled"></span><span>more-filled</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-settings"></span><span>settings</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-list"></span><span>list</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-bars"></span><span>bars</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-loop"></span><span>loop</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-paperclip"></span><span>paperclip</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-eye"></span><span>eye</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-arrowup"></span><span>arrowup</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-arrowdown"></span><span>arrowdown</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-arrowleft"></span><span>arrowleft</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-arrowright"></span><span>arrowright</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-arrowthinup"></span><span>arrowthinup</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-arrowthindown"></span><span>arrowthindown</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-arrowthinleft"></span><span>arrowthinleft</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-arrowthinright"></span><span>arrowthinright</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-pulldown"></span><span>pulldown</span></li>
+  	<li class="icon-item"><span class="uni-icon uni-icon-scan"></span><span>scan</span></li>
+  </ul>
+</div>

File diff suppressed because it is too large
+ 39 - 0
components/uni-icon/uni-icon.vue


+ 192 - 0
components/uni-load-more.vue

@@ -0,0 +1,192 @@
+<template>
+	<view class="load-more">
+		<view class="loading-img" v-show="loadingType === 1 && showImage">
+			<view class="load1">
+				<view :style="{background:color}"></view>
+				<view :style="{background:color}"></view>
+				<view :style="{background:color}"></view>
+				<view :style="{background:color}"></view>
+			</view>
+			<view class="load2">
+				<view :style="{background:color}"></view>
+				<view :style="{background:color}"></view>
+				<view :style="{background:color}"></view>
+				<view :style="{background:color}"></view>
+			</view>
+			<view class="load3">
+				<view :style="{background:color}"></view>
+				<view :style="{background:color}"></view>
+				<view :style="{background:color}"></view>
+				<view :style="{background:color}"></view>
+			</view>
+		</view>
+		<text class="loading-text" :style="{color:color}">{{loadingType === 0 ? contentText.contentdown : (loadingType === 1 ? contentText.contentrefresh : contentText.contentnomore)}}</text>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: "load-more",
+		props: {
+			loadingType: {
+				//上拉的状态:0-loading前;1-loading中;2-没有更多了
+				type: Number,
+				default: 0
+			},
+			showImage: {
+				type: Boolean,
+				default: true
+			},
+			color: {
+				type: String,
+				default: "#777777"
+			},
+			contentText: {
+				type: Object,
+				default () {
+					return {
+						contentdown: "上拉显示更多",
+						contentrefresh: "正在加载...",
+						contentnomore: "没有更多数据了"
+					};
+				}
+			}
+		},
+		data() {
+			return {}
+		}
+	}
+</script>
+
+<style>
+	.load-more {
+		display: flex;
+		flex-direction: row;
+		height: 80upx;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.loading-img {
+		height: 24px;
+		width: 24px;
+		margin-right: 10px;
+	}
+
+	.loading-text {
+		font-size: 28upx;
+		color: #777777;
+	}
+
+	.loading-img>view {
+		position: absolute;
+	}
+
+	.load1,
+	.load2,
+	.load3 {
+		height: 24px;
+		width: 24px;
+	}
+
+	.load2 {
+		transform: rotate(30deg);
+	}
+
+	.load3 {
+		transform: rotate(60deg);
+	}
+
+	.loading-img>view view {
+		width: 6px;
+		height: 2px;
+		border-top-left-radius: 1px;
+		border-bottom-left-radius: 1px;
+		background: #777;
+		position: absolute;
+		opacity: 0.2;
+		transform-origin: 50%;
+		-webkit-animation: load 1.56s ease infinite;
+	}
+
+	.loading-img>view view:nth-child(1) {
+		transform: rotate(90deg);
+		top: 2px;
+		left: 9px;
+	}
+
+	.loading-img>view view:nth-child(2) {
+		-webkit-transform: rotate(180deg);
+		top: 11px;
+		right: 0px;
+	}
+
+	.loading-img>view view:nth-child(3) {
+		transform: rotate(270deg);
+		bottom: 2px;
+		left: 9px;
+	}
+
+	.loading-img>view view:nth-child(4) {
+		top: 11px;
+		left: 0px;
+	}
+
+	.load1 view:nth-child(1) {
+		animation-delay: 0s;
+	}
+
+	.load2 view:nth-child(1) {
+		animation-delay: 0.13s;
+	}
+
+	.load3 view:nth-child(1) {
+		animation-delay: 0.26s;
+	}
+
+	.load1 view:nth-child(2) {
+		animation-delay: 0.39s;
+	}
+
+	.load2 view:nth-child(2) {
+		animation-delay: 0.52s;
+	}
+
+	.load3 view:nth-child(2) {
+		animation-delay: 0.65s;
+	}
+
+	.load1 view:nth-child(3) {
+		animation-delay: 0.78s;
+	}
+
+	.load2 view:nth-child(3) {
+		animation-delay: 0.91s;
+	}
+
+	.load3 view:nth-child(3) {
+		animation-delay: 1.04s;
+	}
+
+	.load1 view:nth-child(4) {
+		animation-delay: 1.17s;
+	}
+
+	.load2 view:nth-child(4) {
+		animation-delay: 1.30s;
+	}
+
+	.load3 view:nth-child(4) {
+		animation-delay: 1.43s;
+	}
+
+	@-webkit-keyframes load {
+		0% {
+			opacity: 1;
+		}
+
+		100% {
+			opacity: 0.2;
+		}
+	}
+</style>

+ 173 - 0
components/uni-number-box.vue

@@ -0,0 +1,173 @@
+<template>
+	<view class="uni-numbox">
+		<view class="uni-numbox-minus" :class="{'uni-numbox-disabled': disableSubtract}" @click="_calcValue('subtract')">-</view>
+		<input class="uni-numbox-value" type="number" :disabled="disabled" :value="inputValue" @blur="_onBlur">
+		<view class="uni-numbox-plus" :class="{'uni-numbox-disabled': disableAdd}" @click="_calcValue('add')">+</view>
+	</view>
+</template>
+<script>
+	export default {
+		name: 'uni-number-box',
+		props: {
+			value: {
+				type: Number,
+				default: 0
+			},
+			min: {
+				type: Number,
+				default: -Infinity
+			},
+			max: {
+				type: Number,
+				default: Infinity
+			},
+			step: {
+				type: Number,
+				default: 1
+			},
+			disabled: {
+				type: Boolean,
+				default: false
+			}
+		},
+		data() {
+			return {
+				inputValue: this.value
+			}
+		},
+		computed: {
+			disableSubtract() {
+				return this.value <= this.min
+			},
+			disableAdd() {
+				return this.value >= this.max
+			}
+		},
+		watch: {
+			value(val) {
+				this.inputValue = val;
+			},
+			inputValue(val) {
+				this.$emit('change', val);
+			}
+		},
+		methods: {
+			_calcValue(type) {
+				const scale = this._getDecimalScale();
+				let value = this.inputValue * scale;
+				let step = this.step * scale;
+
+				if (type === 'subtract') {
+					value -= step
+				} else if (type === 'add') {
+					value += step
+				}
+				if (value < this.min || value > this.max) {
+					return
+				}
+				this.inputValue = value / scale;
+			},
+			_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>
+	.uni-numbox {
+		display: inline-flex;
+		flex-direction: row;
+		justify-content: flex-start;
+		height: 70upx;
+		position: relative;
+	}
+
+	.uni-numbox::after {
+		content: '';
+		position: absolute;
+		transform-origin: center;
+		box-sizing: border-box;
+		pointer-events: none;
+		top: -50%;
+		left: -50%;
+		right: -50%;
+		bottom: -50%;
+		border: 1px solid #c8c7cc;
+		transform: scale(.5);
+	}
+
+	.uni-numbox-minus,
+	.uni-numbox-plus {
+		margin: 0;
+		background-color: #f9f9f9;
+		width: 80upx;
+		height: 100%;
+		line-height: 70upx;
+		text-align: center;
+		color: #555555;
+		position: relative;
+	}
+
+	.uni-numbox-minus {
+		border-right: none;
+		border-top-left-radius: 6upx;
+		border-bottom-left-radius: 6upx;
+	}
+
+	.uni-numbox-plus {
+		border-left: none;
+		border-top-right-radius: 6upx;
+		border-bottom-right-radius: 6upx;
+	}
+
+	.uni-numbox-value {
+		position: relative;
+		background-color: #ffffff;
+		width: 80upx;
+		height: 100%;
+		text-align: center;
+		padding: 0;
+	}
+
+	.uni-numbox-value::after {
+		content: '';
+		position: absolute;
+		transform-origin: center;
+		box-sizing: border-box;
+		pointer-events: none;
+		top: -50%;
+		left: -50%;
+		right: -50%;
+		bottom: -50%;
+		border-style: solid;
+		border-color: #cccccc;
+		border-left-width: 1px;
+		border-right-width: 1px;
+		border-top-width: 0;
+		border-bottom-width: 0;
+		transform: scale(.5);
+	}
+
+	.uni-numbox-disabled {
+		color: #c0c0c0;
+	}
+</style>

+ 112 - 0
components/uni-popup.vue

@@ -0,0 +1,112 @@
+<template>
+	<view>
+		<view class="uni-mask" v-show="show" :style="{top:offsetTop + 'px'}" @click="hide"></view>
+		<view :class="['uni-popup','uni-popup-'+type]" v-show="show" :style="'width:'+width+'rpx; heigth:'+heigth+'rpx;padding:'+padding+'rpx;background-color:'+backgroundColor+';box-shadow:'+boxShadow+';'">
+			<view class="popup-head" v-if="msg!=''">
+		 	{{msg}}
+			</view>	
+			<slot></slot>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		props: {
+			show: {
+				type: Boolean,
+				default: false
+			},
+			type: {
+				type: String,
+				//top - 顶部, middle - 居中, bottom - 底部
+				default: 'middle'
+			},
+			width: {
+				type: Number,
+				default: 600
+			},
+			heigth: {
+				type: Number,
+				default: 800
+			},
+			padding:{
+				type: Number,
+				default: 30
+			},
+			backgroundColor:{
+				type: String,
+				default: '#ffffff'
+			},
+			boxShadow:{
+				type: String,
+				default: '0 0 30upx rgba(0, 0, 0, .1)'
+			},
+			msg: {
+				type: String,
+				default: ""
+			}
+		},
+		data() {
+			let offsetTop = 0;
+			//#ifdef H5
+			offsetTop = 0;
+			//#endif
+			return {
+				offsetTop: offsetTop
+			}
+		},
+		methods: {
+			hide: function() {
+				this.$emit('hidePopup');
+			}
+		}
+	}
+</script>
+<style>
+	.uni-mask {
+		position: fixed;
+		z-index: 998;
+		top: 0;
+		right: 0;
+		bottom: 0;
+		left: 0;
+		background-color: rgba(0, 0, 0, .3);
+	}
+
+	.uni-popup {
+		position: fixed;
+		z-index: 999;
+	}
+
+	.uni-popup-middle {
+		display: flex;
+		flex-direction: column;
+		align-items: flex-start;
+		width: 600upx;
+		/* height:800upx; */
+		border-radius: 10upx;
+		top: 50%;
+		left: 50%;
+		transform: translate(-50%, -50%);
+		justify-content: flex-start;
+		padding: 30upx;
+		overflow: auto;
+	}
+	.popup-head{ width: 100%; padding-bottom: 40rpx; box-sizing: border-box; font-size: 30rpx; font-weight: bold;}
+	.uni-popup-top {
+		top: 0;
+		left: 0;
+		width: 100%;
+		height: 100upx;
+		line-height: 100upx;
+		text-align: center;
+	}
+
+	.uni-popup-bottom {
+		left: 0;
+		bottom: 0;
+		width: 100%;
+		text-align: center;
+	}
+</style>

+ 134 - 0
components/uni-segmented-control.vue

@@ -0,0 +1,134 @@
+<template>
+	<view class="segmented-control" :class="styleType" :style="wrapStyle">
+		<view v-for="(item, index) in values" class="segmented-control-item" :class="styleType" :key="index" :style="index === currentIndex ? activeStyle : itemStyle" @click="onClick(index)">
+			{{item}}
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: 'segmented-control',
+		props: {
+			current: {
+				type: Number,
+				default: 0
+			},
+			values: {
+				type: Array,
+				default () {
+					return [];
+				}
+			},
+			activeColor: {
+				type: String,
+				default: '#007aff'
+			},
+			styleType: {
+				type: String,
+				default: 'button'
+			}
+		},
+		data() {
+			return {
+				currentIndex: this.current
+			}
+		},
+		watch: {
+			current(val) {
+				if (val !== this.currentIndex) {
+					this.currentIndex = val;
+				}
+			}
+		},
+		computed: {
+			wrapStyle() {
+				let styleString = '';
+				switch (this.styleType) {
+					case 'text':
+						styleString = `border:0;`;
+						break;
+					default:
+						styleString = `border-color: ${this.activeColor}`;
+						break;
+				}
+				return styleString;
+			},
+			itemStyle() {
+				let styleString = '';
+				switch (this.styleType) {
+					case 'text':
+						styleString = `color:#000;border-left:0;`;
+						break;
+					default:
+						styleString = `color:${this.activeColor};border-color:${this.activeColor};`;
+						break;
+				}
+				return styleString;
+			},
+			activeStyle() {
+				let styleString = '';
+				switch (this.styleType) {
+					case 'text':
+						styleString = `color:${this.activeColor};border-left:0;border-bottom-style:solid;`;
+						break;
+					default:
+						styleString = `color:#fff;border-color:${this.activeColor};background-color:${this.activeColor}`;
+						break;
+				}
+				return styleString;
+			}
+		},
+		methods: {
+			onClick(index) {
+				if (this.currentIndex !== index) {
+					this.currentIndex = index;
+					this.$emit('clickItem', index);
+				}
+			}
+		},
+	}
+</script>
+
+<style>
+	.segmented-control {
+		display: flex;
+		flex-direction: row;
+		justify-content: center;
+		width: 75%;
+		font-size: 28upx;
+		border-radius: 10upx;
+		box-sizing: border-box;
+		margin: 0 auto;
+		overflow: hidden;
+	}
+
+	.segmented-control.button {
+		border: 2upx solid;
+	}
+
+	.segmented-control.text {
+		border: 0;
+		border-radius: 0upx;
+	}
+
+
+	.segmented-control-item {
+		flex: 1;
+		text-align: center;
+		line-height: 60upx;
+		box-sizing: border-box;
+	}
+
+	.segmented-control-item.button {
+		border-left: 1upx solid;
+	}
+
+	.segmented-control-item.text {
+		border-left: 0;
+	}
+
+	.segmented-control-item:first-child {
+		border-left-width: 0;
+	}
+</style>

+ 50 - 0
components/uni-steps/readme.md

@@ -0,0 +1,50 @@
+### Steps 步骤条
+
+评分组件,组件名:``uni-steps``,代码块: uSteps。
+
+**使用方式:**
+
+在 ``script`` 中引用组件 
+
+```javascript
+import uniSteps from "@/components/uni-steps/uni-steps.vue"
+export default {
+    components: {uniSteps}
+}
+```
+
+基本用法
+
+```html
+<uni-steps :data="[
+    {title: '事件一'}, 
+    {title: '事件二'}, 
+    {title: '事件三'}, 
+    {title: '事件四'}]" 
+    :active="1">
+</uni-steps>
+```
+
+纵向排列
+
+```html
+<uni-steps :data="[
+    {title:'买家下单',desc:'2018-11-11'},
+    {title:'卖家发货',desc:'2018-11-12'},
+    {title:'买家签收',desc:'2018-11-13'},
+    {title:'交易完成',desc:'2018-11-14'}]" 
+    direction="column" 
+    :active="2">
+</uni-steps>
+```
+
+实际效果参考:[https://github.com/dcloudio/uni-ui](https://github.com/dcloudio/uni-ui)
+
+**属性说明:**
+
+|属性名|类型|默认值	|说明|
+|---|----|---|---|
+|data|Array&lt;Object&gt;|-|数据源,格式为:[{title:'xxx',desc:'xxx'},{title:'xxx',desc:'xxx'}]|
+|active|Number|0|当前步骤|
+|direction|String|row|排列方向,可取值:row(横向)、column(纵向)|
+|active-color|String|#1aad19|选中状态的颜色|

+ 257 - 0
components/uni-steps/uni-steps.vue

@@ -0,0 +1,257 @@
+<template>
+	<view class="uni-steps">
+		<view class="uni-steps-items" :class="'uni-steps-' + direction">
+			<view class="uni-steps-item" v-for="(item,index) in steps" :key="index" :class="[item.status ? 'uni-steps-' + item.status : '']">
+				<view class="uni-steps-item-title-container" :style="{color:item.status === 'process' ? activeColor : ''}">
+					<view class="uni-steps-item-title">{{ item.title }}</view>
+					<view class="uni-steps-item-desc" v-if="item.desc">{{ item.desc}}</view>
+				</view>
+				<view class="uni-steps-item-circle-container">
+					<view class="uni-steps-item-circle" v-if="item.status !== 'process'" :style="{backgroundColor:item.status === 'finish' ? activeColor : ''}"></view>
+					<uni-icon v-else type="checkbox-filled" size="14" :color="activeColor"></uni-icon>
+				</view>
+				<view class="uni-steps-item-line" v-if="index !== steps.length-1" :style="{backgroundColor:item.status === 'finish' ? activeColor : ''}"></view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import uniIcon from '../uni-icon/uni-icon.vue'
+	export default {
+		name: "uni-steps",
+		components: {
+			uniIcon
+		},
+		props: {
+			direction: { //排列方向 row column
+				type: String,
+				default: 'row'
+			},
+			activeColor: { //激活状态颜色
+				type: String,
+				default: '#1aad19'
+			},
+			active: { //当前步骤
+				type: [Number, String],
+				default: 0
+			},
+			data: Array //数据
+		},
+		data() {
+			return {}
+		},
+		computed: {
+			steps() {
+				let steps = []
+				this.data.forEach((item, index) => {
+					let step = {}
+					step.title = item.title
+					step.desc = item.desc
+					step.status = this.getStatus(index)
+					steps.push(step)
+				})
+				return steps
+			}
+		},
+		methods: {
+			getStatus(index) {
+				if (index < Number(this.active)) {
+					return 'finish'
+				} else if (index === Number(this.active)) {
+					return 'process'
+				}
+				return ''
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	$steps-line-color:#ebedf0;
+	$steps-text-color:#969799;
+	$steps-title-size:28upx;
+	$steps-desc-size:24upx;
+	$steps-text-finish-color:#333333;
+	$steps-bg-color:#ffffff;
+
+	.uni-steps {
+		width: 100%;
+		box-sizing: border-box;
+		display: flex;
+		flex-direction: column;
+		overflow: hidden;
+		position: relative;
+
+		&-items {
+			position: relative;
+			display: flex;
+			flex-direction: row;
+			margin: 10px;
+			box-sizing: border-box;
+			overflow: hidden;
+
+			&.uni-steps-column {
+				margin: 10px 0;
+				padding-left: 31px;
+				flex-direction: column;
+
+				.uni-steps-item {
+					&:after {
+						content: ' ';
+						position: absolute;
+						height: 1px;
+						width: 100%;
+						bottom: 9px;
+						left: 0;
+						background-color: #ebedf0;
+						transform: scaleY(0.5);
+					}
+
+					&:last-child {
+						position: relative;
+
+						&:after {
+							height: 0px;
+						}
+
+						.uni-steps-item-title-container {
+							text-align: left;
+						}
+
+						.uni-steps-item-circle-container {
+							left: -17px;
+							right: auto
+						}
+					}
+
+					&-title-container {
+						transform: none;
+						display: block;
+						line-height: 36upx;
+					}
+
+					&-title {
+                        text-overflow: ellipsis;
+                        //white-space: nowrap;
+                        overflow: hidden;
+                    }
+
+					&-desc {
+						white-space: normal;
+						display: -webkit-box;
+						-webkit-box-orient: vertical;
+						-webkit-line-clamp: 2;
+						overflow: hidden;
+					}
+
+					&-circle-container {
+						left: -17px;
+						top: -1px;
+						bottom: auto;
+						padding: 8px 0px;
+						z-index: 1;
+					}
+
+					&-line {
+						height: 100%;
+						width: 1px;
+						left: -15px;
+						top: -1px;
+						bottom: auto;
+					}
+
+
+					&.uni-steps-process {
+						.uni-steps-item-circle-container {
+							bottom: auto;
+							left: -21px;
+						}
+					}
+				}
+			}
+		}
+
+		&-item {
+			flex: 1;
+			position: relative;
+			padding-bottom: 18px;
+
+			&-title-container {
+				text-align: left;
+				margin-left: 3px;
+				display: inline-block;
+				transform: translateX(-50%);
+				color: $steps-text-color;
+			}
+
+			&-title {
+				font-size: $steps-title-size;
+			}
+
+			&-desc {
+				font-size: $steps-desc-size;
+			}
+
+			&:first-child {
+				.uni-steps-item-title-container {
+					transform: none;
+					margin-left: 0;
+				}
+			}
+
+			&:last-child {
+				position: absolute;
+				right: 0;
+
+				.uni-steps-item-title-container {
+					transform: none;
+					text-align: right;
+				}
+
+				.uni-steps-item-circle-container {
+					left: auto;
+					right: -8px
+				}
+			}
+
+			&-circle-container {
+				position: absolute;
+				bottom: 8px;
+				left: -8px;
+				padding: 0 8px;
+				background-color: $steps-bg-color;
+				z-index: 1;
+			}
+
+			&-circle {
+				width: 5px;
+				height: 5px;
+				background-color: $steps-text-color;
+				border-radius: 50%;
+			}
+
+			&-line {
+				background-color: $steps-line-color;
+				position: absolute;
+				bottom: 10px;
+				left: 0;
+				width: 100%;
+				height: 1px;
+			}
+
+			&.uni-steps-finish {
+				.uni-steps-item-title-container {
+					color: $steps-text-finish-color;
+				}
+			}
+
+			&.uni-steps-process {
+				.uni-steps-item-circle-container {
+					bottom: 3px;
+					display: flex;
+				}
+			}
+		}
+	}
+</style>

+ 80 - 0
components/upload/upload.vue

@@ -0,0 +1,80 @@
+<template>
+	<view></view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			/*需要返回的图片*/
+			imageList:[]
+		};
+	},
+	onLoad() {},
+	props:['num'],
+	mounted() {
+		this.chooseImageFunc();
+	},
+	methods: {
+		
+		/*打开相机或者相册,选择图片*/
+		chooseImageFunc() {
+			let self=this;
+			uni.chooseImage({
+				count: self.$props.num || 9, //默认9
+				sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
+				sourceType: ['album', 'camera'], //从相册选择
+				success: function(res) {
+					self.uploadFile(res.tempFilePaths);
+				},
+				fail:function(res){
+					self.$emit('getImgs',null);
+				},
+				complete:function(res){
+					
+				}
+			});
+		},
+		
+		/*上传图片*/
+		uploadFile: function(tempList) {
+			let self = this;
+			let i = 0;
+			let img_length=tempList.length;
+			let params = {
+				token: uni.getStorageSync('token'),
+                app_id: self.getAppId()
+			};
+			uni.showLoading({
+			    title: '图片上传中'
+			});
+			tempList.forEach(function(filePath, fileKey) {
+				uni.uploadFile({
+					url: self.websiteUrl + '/index.php?s=/api/file.upload/image',
+					filePath: filePath,
+					name: 'iFile',
+					formData: params,
+					success: function(res) {
+						let result = typeof res.data === 'object' ? res.data : JSON.parse(res.data);
+						if (result.code === 1) {
+							self.imageList.push(result.data);
+						}else{
+							self.showError(result.msg);
+						}
+					},
+					complete: function() {
+						i++;
+						if (img_length === i) {
+							uni.hideLoading();
+							// 所有文件上传完成
+							self.$emit('getImgs',self.imageList);
+						}
+					}
+				});
+			});
+		}
+	}
+};
+</script>
+
+<style></style>

+ 116 - 0
components/zz-prompt.vue

@@ -0,0 +1,116 @@
+<template>
+  <view class="prompt-box" v-if="visible" @touchmove="true">
+    <view class="prompt">
+      <view class="prompt-top">
+        <text class="prompt-title">{{title}}</text>
+        <input class="prompt-input" type="text" :placeholder="placeholder" v-model="value">
+      </view>
+      <slot></slot>
+      <view class="prompt-buttons" :style="'background:' + mainColor">
+        <button class="prompt-cancle" :style="'color:' + mainColor" @click="close">取消</button>
+        <button @click="$emit('confirm', value)">确定</button>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  props: {
+    visible: {
+      type: Boolean,
+      default: false,
+      required: true,
+    },
+    title: {
+      type: String,
+      default: '提示',
+    },
+    placeholder: {
+      type: String,
+      default: '请输入内容',
+    },
+    mainColor: {
+      type: String,
+      default: '#e74a39',
+    },
+    defaultValue: {
+      type: String,
+    }
+  },
+  data() {
+    return {
+      value: '',
+    }
+  },
+  mounted() {
+    this.value = this.defaultValue
+  },
+  methods: {
+    close() {
+      this.$emit('update:visible', false)
+    }
+  }
+}
+</script>
+
+<style scoped>
+  view, button, input {
+    box-sizing: border-box;
+  }
+  
+  .prompt-box {
+    position: fixed;
+    left: 0;
+    top: 0;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    width: 100%;
+    height: 100vh;
+    background: rgba(0, 0, 0, .2);
+    transition: opacity .2s linear;
+  }
+  .prompt {
+    position: relative;
+    display: flex;
+    flex-direction: column;
+    justify-content: space-between;
+    align-items: center;
+    width: 600upx;
+    min-height: 300upx;
+    background: white;
+    border-radius: 20upx;
+    overflow: hidden;
+  }
+  .prompt-top {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    width: 100%;
+  }
+  .prompt-title {
+    margin: 20upx 0;
+    color: #333;
+  }
+  .prompt-input {
+    width: 520upx;
+		height: 80upx;
+    font-size: 28upx;
+    border-radius: 8upx;
+		border: 1px solid #ccc;
+		padding: 5upx 10upx;
+  }
+  .prompt-buttons {
+    display: flex;
+    width: 100%;
+    box-shadow: 0 0 2upx 2upx #eee;
+  }
+  button {
+    width: 50%;
+    border-radius: 0;
+  }
+  .prompt-cancle {
+    background: white;
+  }
+</style>

+ 24 - 0
config.js

@@ -0,0 +1,24 @@
+// var app_url = 'http://testaikang.7starsoft2.com';//测试
+// var app_url = 'http://cni-ekshop.cni.com.cn';	
+var app_url = 'https://cni-ekshop.com';	//正式
+// 如果是本地测试环境
+if(process.env.NODE_ENV === 'development'){
+    //#ifdef H5
+	app_url = app_url;
+	//#endif
+}
+// 如果是生产环境,h5环境下直接读取url
+if(process.env.NODE_ENV === 'production'){
+    //#ifdef H5
+	app_url = window.location.protocol+'//' + window.location.host;
+	//#endif
+}
+
+export default {
+	/*服务器地址*/
+	app_url: app_url,
+	/*appid*/
+	app_id: 10001,
+	//h5发布路径
+	h5_addr: '/h5',
+} 

+ 30 - 0
jweixin-module/README.md

@@ -0,0 +1,30 @@
+# jweixin-module
+
+微信JS-SDK
+
+## 安装
+
+### NPM
+
+```shell
+npm install jweixin-module --save
+```
+
+### UMD
+
+```http
+https://unpkg.com/jweixin-module/out/index.js
+```
+
+## 使用
+
+```js
+var wx = require('jweixin-module')
+wx.ready(function(){
+    // TODO
+});
+```
+
+## 完整API
+
+>[微信JS-SDK说明文档](https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115)

File diff suppressed because it is too large
+ 0 - 0
jweixin-module/out/index.js


+ 60 - 0
jweixin-module/package.json

@@ -0,0 +1,60 @@
+{
+  "_from": "jweixin-module",
+  "_id": "jweixin-module@1.4.1",
+  "_inBundle": false,
+  "_integrity": "sha1-H8j6QmIiQ/bDVlHScs1Yfev1bNE=",
+  "_location": "/jweixin-module",
+  "_phantomChildren": {},
+  "_requested": {
+    "type": "tag",
+    "registry": true,
+    "raw": "jweixin-module",
+    "name": "jweixin-module",
+    "escapedName": "jweixin-module",
+    "rawSpec": "",
+    "saveSpec": null,
+    "fetchSpec": "latest"
+  },
+  "_requiredBy": [
+    "#USER",
+    "/"
+  ],
+  "_resolved": "https://registry.npm.taobao.org/jweixin-module/download/jweixin-module-1.4.1.tgz",
+  "_shasum": "1fc8fa42622243f6c35651d272cd587debf56cd1",
+  "_spec": "jweixin-module",
+  "_where": "D:\\xampp",
+  "author": {
+    "name": "Shengqiang Guo"
+  },
+  "bugs": {
+    "url": "https://github.com/zhetengbiji/jweixin-module/issues"
+  },
+  "bundleDependencies": false,
+  "deprecated": false,
+  "description": "微信JS-SDK",
+  "devDependencies": {
+    "textfile": "^1.2.0",
+    "uglify-js": "^3.4.9"
+  },
+  "homepage": "https://github.com/zhetengbiji/jweixin-module#readme",
+  "keywords": [
+    "wxjssdk",
+    "weixin",
+    "jweixin",
+    "wechat",
+    "jssdk",
+    "wx"
+  ],
+  "license": "ISC",
+  "main": "out/index.js",
+  "name": "jweixin-module",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/zhetengbiji/jweixin-module.git"
+  },
+  "scripts": {
+    "build": "node build",
+    "prepublish": "npm run build"
+  },
+  "version": "1.4.1"
+}

+ 393 - 0
main.js

@@ -0,0 +1,393 @@
+import Vue from 'vue'
+import App from './App'
+import directive from './common/directive.js'
+import utils from './common/utils.js'
+import config from './config.js'
+import onfire from './common/onfire.js'
+import {
+	gotopage
+} from '@/common/gotopage.js'
+
+/* Vuex */
+import store from "./store/index.js"
+Vue.prototype.$store = store;
+
+// 公共组件
+import headerBar from './components/header.vue'
+Vue.component('header-bar', headerBar)
+
+// import Vconsole from 'vconsole'
+// const vConsole = new Vconsole()
+// Vue.use(vConsole)
+Vue.prototype.$fire = new onfire()
+
+Vue.config.productionTip = false
+
+App.mpType = 'app'
+
+Vue.prototype.config = config
+
+const app = new Vue({
+	...App
+})
+app.$mount()
+
+Vue.prototype.websiteUrl = config.app_url;
+Vue.prototype.app_id = config.app_id;
+//h5发布路径
+Vue.prototype.h5_addr = config.h5_addr;
+/*页面跳转*/
+Vue.prototype.gotoPage = gotopage;
+
+
+//#ifdef H5
+app.$router.afterEach((to, from) => {
+	const u = navigator.userAgent.toLowerCase()
+	if (u.indexOf("like mac os x") < 0 || u.match(/MicroMessenger/i) != 'micromessenger') return
+	if (to.path !== global.location.pathname) {
+		location.assign(config.h5_addr + to.fullPath);
+	}
+})
+//#endif
+
+
+//是否是ios
+Vue.prototype.ios = function() {
+	const u = navigator.userAgent.toLowerCase();
+	if (u.indexOf("like mac os x") < 0 || u.match(/MicroMessenger/i) != 'micromessenger') {
+		return false;
+	}
+	return true;
+};
+
+//get请求
+Vue.prototype._get = function(path, data, success, fail, complete) {
+	data = data || {};
+	data.token = uni.getStorageSync('token') || '';
+	data.app_id = this.getAppId();
+	uni.request({
+		url: this.websiteUrl + '/index.php/api/' + path,
+		data: data,
+		dataType: 'json',
+		method: 'GET',
+		success: (res) => {
+			if (res.statusCode !== 200 || typeof res.data !== 'object') {
+				return false;
+			}
+			if (res.data.code === -2) {
+				console.log('用户已删除');
+				console.log(res.data.msg)
+				this.showError(res.data.msg, function() {
+					uni.removeStorageSync('token');
+					this.gotoPage('/pages/index/index', 'reLaunch');
+				})
+			} else if (res.data.code === -1) {
+				// 登录态失效, 重新登录
+				console.log('登录态失效, 重新登录');
+				this.doLogin();
+			} else if (res.data.code === 0) {
+				this.showError(res.data.msg, function() {
+					fail && fail(res);
+				});
+				return false;
+			} else {
+				success && success(res.data);
+			}
+		},
+		fail: (res) => {
+			fail && fail(res);
+		},
+		complete: (res) => {
+			uni.hideLoading();
+			complete && complete(res);
+		},
+	});
+};
+
+//get请求
+Vue.prototype._post = function(path, data, success, fail, complete) {
+	data = data || {};
+	data.token = uni.getStorageSync('token') || '';
+	data.app_id = this.getAppId();
+	uni.request({
+		url: this.websiteUrl + '/index.php/api/' + path,
+		data: data,
+		dataType: 'json',
+		method: 'POST',
+		header: {
+			'content-type': 'application/x-www-form-urlencoded',
+		},
+		success: (res) => {
+			if (res.statusCode !== 200 || typeof res.data !== 'object') {
+				return false;
+			}
+			if (res.data.code === -1) {
+				// 登录态失效, 重新登录
+				console.log('登录态失效, 重新登录');
+				this.doLogin();
+			} else if (res.data.code === 0) {
+				this.showError(res.data.msg, function() {
+					fail && fail(res);
+				});
+				return false;
+			} else {
+				success && success(res.data);
+			}
+		},
+		fail: (res) => {
+			fail && fail(res);
+		},
+		complete: (res) => {
+			uni.hideLoading();
+			complete && complete(res);
+		},
+	});
+};
+
+Vue.prototype.doLogin = function() {
+	let pages = getCurrentPages();
+	if (pages.length) {
+		let currentPage = pages[pages.length - 1];
+		if ("pages/login/login" != currentPage.route &&
+			"pages/login/weblogin" != currentPage.route &&
+			"pages/login/openlogin" != currentPage.route) {
+			uni.setStorageSync("currentPage", currentPage.route);
+			uni.setStorageSync("currentPageOptions", currentPage.options);
+		}
+	}
+	//公众号
+	// #ifdef  H5
+	if (this.isWeixin()) {
+		let invitation_id = uni.getStorageSync('invitation_id') ? uni.getStorageSync('invitation_id') : 0;
+		window.location.href = this.websiteUrl + '/index.php/api/user.usermp/login?app_id=' + this.getAppId() +
+			'&referee_id=' + uni.getStorageSync('referee_id') + '&invitation_id=' + invitation_id;
+	} else {
+		this.gotoPage("/pages/login/weblogin");
+	}
+	// #endif
+	// #ifdef APP-PLUS
+	this.gotoPage("/pages/login/openlogin");
+	return;
+	// #endif
+	// 非公众号,跳转授权页面
+	// #ifndef  H5
+	this.gotoPage("/pages/login/login");
+	// #endif
+};
+
+
+/**
+ * 显示失败提示框
+ */
+Vue.prototype.showError = function(msg, callback) {
+	uni.showModal({
+		title: '友情提示',
+		content: msg,
+		showCancel: false,
+		success: function(res) {
+			callback && callback();
+		}
+	});
+};
+
+/**
+ * 显示失败提示框
+ */
+Vue.prototype.showSuccess = function(msg, callback) {
+	uni.showModal({
+		title: '友情提示',
+		content: msg,
+		showCancel: false,
+		success: function(res) {
+			callback && callback();
+		}
+	});
+};
+
+/**
+ * 获取应用ID
+ */
+Vue.prototype.getAppId = function() {
+	return this.app_id || 10001;
+};
+
+Vue.prototype.compareVersion = function(v1, v2) {
+	v1 = v1.split('.')
+	v2 = v2.split('.')
+	const len = Math.max(v1.length, v2.length)
+
+	while (v1.length < len) {
+		v1.push('0')
+	}
+	while (v2.length < len) {
+		v2.push('0')
+	}
+
+	for (let i = 0; i < len; i++) {
+		const num1 = parseInt(v1[i])
+		const num2 = parseInt(v2[i])
+
+		if (num1 > num2) {
+			return 1
+		} else if (num1 < num2) {
+			return -1
+		}
+	}
+
+	return 0
+};
+
+
+/**
+ * 生成转发的url参数
+ */
+Vue.prototype.getShareUrlParams = function(params) {
+	let self = this;
+	return utils.urlEncode(Object.assign({
+		referee_id: self.getUserId(),
+		app_id: self.getAppId()
+	}, params));
+};
+
+/**
+ * 当前用户id
+ */
+Vue.prototype.getUserId = function() {
+	return uni.getStorageSync('user_id');
+};
+
+//#ifdef H5
+var jweixin = require('jweixin-module');
+
+Vue.prototype.configWx = function(signPackage, shareParams, params) {
+	if (signPackage == '') {
+		return;
+	}
+	let self = this;
+	jweixin.config(JSON.parse(signPackage));
+
+	let url_params = self.getShareUrlParams(params);
+
+	jweixin.ready(function(res) {
+		jweixin.updateAppMessageShareData({
+			title: shareParams.title,
+			desc: shareParams.desc,
+			link: self.websiteUrl + self.h5_addr + shareParams.link + '?' + url_params,
+			imgUrl: shareParams.imgUrl,
+			success: function() {
+
+			}
+		});
+		jweixin.updateTimelineShareData({
+			title: shareParams.title,
+			desc: shareParams.desc,
+			link: self.websiteUrl + self.h5_addr + shareParams.link + '?' + url_params,
+			imgUrl: shareParams.imgUrl,
+			success: function() {
+
+			}
+		});
+	});
+};
+
+Vue.prototype.configWxScan = function(signPackage) {
+	if (signPackage == '') {
+		return;
+	}
+	jweixin.config(JSON.parse(signPackage));
+	return jweixin;
+};
+//#endif
+
+/**
+ * 获取当前平台
+ */
+Vue.prototype.getPlatform = function(params) {
+	let platform = 'wx';
+	// #ifdef  APP-PLUS
+	platform = 'app';
+	// #endif
+	// #ifdef  H5
+	if (this.isWeixin()) {
+		platform = 'mp';
+	} else {
+		platform = 'h5';
+	}
+	// #endif
+	return platform;
+};
+
+/**
+ * 订阅通知,目前仅小程序
+ */
+Vue.prototype.subMessage = function(temlIds, callback) {
+	let self = this;
+	// #ifdef  MP-WEIXIN
+	//小程序订阅消息
+	const version = wx.getSystemInfoSync().SDKVersion;
+	if (temlIds && temlIds.length != 0 && self.compareVersion(version, '2.8.2') >= 0) {
+		wx.requestSubscribeMessage({
+			tmplIds: temlIds,
+			success(res) {},
+			fail(res) {},
+			complete(res) {
+				callback();
+			},
+		});
+	} else {
+		callback();
+	}
+	// #endif
+	// #ifndef MP-WEIXIN
+	callback();
+	// #endif
+};
+
+Vue.prototype.isWeixin = function() {
+	var ua = navigator.userAgent.toLowerCase();
+	if (ua.match(/MicroMessenger/i) == "micromessenger") {
+		return true;
+	} else {
+		return false;
+	}
+};
+
+Vue.prototype.topBarTop = function() {
+	// #ifdef MP-WEIXIN
+	return uni.getMenuButtonBoundingClientRect().top;
+	// #endif
+	// #ifndef MP-WEIXIN
+	const SystemInfo = uni.getSystemInfoSync();
+	return SystemInfo.statusBarHeight;
+	// #endif
+};
+Vue.prototype.topBarHeight = function() {
+	// #ifdef MP-WEIXIN
+	return uni.getMenuButtonBoundingClientRect().height;
+	// #endif
+	// #ifndef MP-WEIXIN
+	return 0
+	// #endif
+};
+Vue.prototype.yulan = function(e, i) {
+	let image_path_arr = [];
+	if (!Array.isArray(e)) {
+		image_path_arr = [e];
+	} else {
+		if (e[0].file_path) {
+			e.forEach((item, index) => {
+				image_path_arr.push(item.file_path)
+			})
+		} else {
+			image_path_arr = e
+		}
+	}
+	let picnum = i * 1;
+	uni.previewImage({
+		urls: image_path_arr,
+		current: picnum,
+	});
+}
+Vue.prototype.theme = function() {
+	return this.$store.state.theme
+}

+ 165 - 0
manifest.json

@@ -0,0 +1,165 @@
+{
+    "name" : "青松go",
+    "appid" : "__UNI__6EF60F8",
+    "description" : "青松go",
+    "versionName" : "1.0.2",
+    "versionCode" : 102,
+    "transformPx" : false,
+    "app-plus" : {
+        /* 5+App特有相关 */
+        "splashscreen" : {
+            "alwaysShowBeforeRender" : true,
+            "waiting" : true,
+            "autoclose" : true,
+            "delay" : 0
+        },
+        "modules" : {
+            "OAuth" : {},
+            "LivePusher" : {},
+            "Share" : {},
+            "VideoPlayer" : {},
+            "Payment" : {},
+            "Geolocation" : {},
+            "Push" : {}
+        },
+        /* 模块配置 */
+        "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.MODIFY_AUDIO_SETTINGS\"/>",
+                    "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
+                    "<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_SETTINGS\"/>"
+                ],
+                "abiFilters" : [ "armeabi-v7a", "arm64-v8a", "x86" ]
+            },
+            "ios" : {
+                "idfa" : false,
+                "privacyDescription" : {
+                    "NSPhotoLibraryUsageDescription" : "评论时需要上传评论图片",
+                    "NSCameraUsageDescription" : "评论时需要上传评论图片",
+                    "NSLocationWhenInUseUsageDescription" : "需要获取您的地理位置,为您推荐最近门店"
+                }
+            },
+            /* ios打包配置 */
+            "sdkConfigs" : {
+                "oauth" : {
+                    "weixin" : {
+                        "appid" : "wxf16a5e84b3e8ac5d",
+                        "appsecret" : "",
+                        "UniversalLinks" : "https://business.jjjshop.net/"
+                    },
+                    "apple" : {}
+                },
+                "push" : {
+                    "unipush" : {}
+                },
+                "ad" : {},
+                "share" : {
+                    "weixin" : {
+                        "appid" : "wxf16a5e84b3e8ac5d",
+                        "UniversalLinks" : "https://business.jjjshop.net/"
+                    }
+                },
+                "payment" : {
+                    "weixin" : {
+                        "__platform__" : [ "ios", "android" ],
+                        "appid" : "wxf16a5e84b3e8ac5d",
+                        "UniversalLinks" : "https://business.jjjshop.net/"
+                    }
+                },
+                "geolocation" : {
+                    "amap" : {
+                        "__platform__" : [ "ios", "android" ],
+                        "appkey_ios" : "9491f4a5d4efd1fe3e31874caff48ff9",
+                        "appkey_android" : "ede3e65ba8ba017e040e7a001d659e48"
+                    }
+                }
+            },
+            "icons" : {
+                "android" : {
+                    "hdpi" : "unpackage/res/icons/72x72.png",
+                    "xhdpi" : "unpackage/res/icons/96x96.png",
+                    "xxhdpi" : "unpackage/res/icons/144x144.png",
+                    "xxxhdpi" : "unpackage/res/icons/192x192.png"
+                },
+                "ios" : {
+                    "appstore" : "unpackage/res/icons/1024x1024.png",
+                    "ipad" : {
+                        "app" : "unpackage/res/icons/76x76.png",
+                        "app@2x" : "unpackage/res/icons/152x152.png",
+                        "notification" : "unpackage/res/icons/20x20.png",
+                        "notification@2x" : "unpackage/res/icons/40x40.png",
+                        "proapp@2x" : "unpackage/res/icons/167x167.png",
+                        "settings" : "unpackage/res/icons/29x29.png",
+                        "settings@2x" : "unpackage/res/icons/58x58.png",
+                        "spotlight" : "unpackage/res/icons/40x40.png",
+                        "spotlight@2x" : "unpackage/res/icons/80x80.png"
+                    },
+                    "iphone" : {
+                        "app@2x" : "unpackage/res/icons/120x120.png",
+                        "app@3x" : "unpackage/res/icons/180x180.png",
+                        "notification@2x" : "unpackage/res/icons/40x40.png",
+                        "notification@3x" : "unpackage/res/icons/60x60.png",
+                        "settings@2x" : "unpackage/res/icons/58x58.png",
+                        "settings@3x" : "unpackage/res/icons/87x87.png",
+                        "spotlight@2x" : "unpackage/res/icons/80x80.png",
+                        "spotlight@3x" : "unpackage/res/icons/120x120.png"
+                    }
+                }
+            },
+            "splashscreen" : {
+                "androidStyle" : "default",
+                "iosStyle" : "common",
+                "android" : {
+                    "hdpi" : "E:/工作/小程序/公司产品/分销商城/android/1.png",
+                    "xhdpi" : "E:/工作/小程序/公司产品/分销商城/android/2.png",
+                    "xxhdpi" : "E:/工作/小程序/公司产品/分销商城/android/3.png"
+                }
+            }
+        }
+    },
+    /* SDK配置 */
+    "quickapp" : {},
+    /* 快应用特有相关 */
+    "mp-weixin" : {
+        "appid" : "wxdc431326921378b2",
+        "setting" : {
+            "urlCheck" : false,
+            "es6" : true,
+            "postcss" : true,
+            "minified" : true
+        },
+        "usingComponents" : true,
+        "permission" : {
+            "scope.userLocation" : {
+                "desc" : "你的位置信息将用于小程序位置接口的效果展示"
+            }
+        },
+        "plugins" : {
+            "live-player-plugin" : {
+                "version" : "1.3.2",
+                "provider" : "wx2b03c6e691cd7370"
+            }
+        }
+    }
+}

+ 22 - 0
node_modules/@babel/runtime/LICENSE

@@ -0,0 +1,22 @@
+MIT License
+
+Copyright (c) 2014-present Sebastian McKenzie and other contributors
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 19 - 0
node_modules/@babel/runtime/README.md

@@ -0,0 +1,19 @@
+# @babel/runtime
+
+> babel's modular runtime helpers
+
+See our website [@babel/runtime](https://babeljs.io/docs/en/babel-runtime) for more information.
+
+## Install
+
+Using npm:
+
+```sh
+npm install --save @babel/runtime
+```
+
+or using yarn:
+
+```sh
+yarn add @babel/runtime
+```

+ 64 - 0
node_modules/@babel/runtime/helpers/AsyncGenerator.js

@@ -0,0 +1,64 @@
+var OverloadYield = require("./OverloadYield.js");
+function AsyncGenerator(gen) {
+  var front, back;
+  function resume(key, arg) {
+    try {
+      var result = gen[key](arg),
+        value = result.value,
+        overloaded = value instanceof OverloadYield;
+      Promise.resolve(overloaded ? value.v : value).then(function (arg) {
+        if (overloaded) {
+          var nextKey = "return" === key ? "return" : "next";
+          if (!value.k || arg.done) return resume(nextKey, arg);
+          arg = gen[nextKey](arg).value;
+        }
+        settle(result.done ? "return" : "normal", arg);
+      }, function (err) {
+        resume("throw", err);
+      });
+    } catch (err) {
+      settle("throw", err);
+    }
+  }
+  function settle(type, value) {
+    switch (type) {
+      case "return":
+        front.resolve({
+          value: value,
+          done: !0
+        });
+        break;
+      case "throw":
+        front.reject(value);
+        break;
+      default:
+        front.resolve({
+          value: value,
+          done: !1
+        });
+    }
+    (front = front.next) ? resume(front.key, front.arg) : back = null;
+  }
+  this._invoke = function (key, arg) {
+    return new Promise(function (resolve, reject) {
+      var request = {
+        key: key,
+        arg: arg,
+        resolve: resolve,
+        reject: reject,
+        next: null
+      };
+      back ? back = back.next = request : (front = back = request, resume(key, arg));
+    });
+  }, "function" != typeof gen["return"] && (this["return"] = void 0);
+}
+AsyncGenerator.prototype["function" == typeof Symbol && Symbol.asyncIterator || "@@asyncIterator"] = function () {
+  return this;
+}, AsyncGenerator.prototype.next = function (arg) {
+  return this._invoke("next", arg);
+}, AsyncGenerator.prototype["throw"] = function (arg) {
+  return this._invoke("throw", arg);
+}, AsyncGenerator.prototype["return"] = function (arg) {
+  return this._invoke("return", arg);
+};
+module.exports = AsyncGenerator, module.exports.__esModule = true, module.exports["default"] = module.exports;

+ 4 - 0
node_modules/@babel/runtime/helpers/AwaitValue.js

@@ -0,0 +1,4 @@
+function _AwaitValue(value) {
+  this.wrapped = value;
+}
+module.exports = _AwaitValue, module.exports.__esModule = true, module.exports["default"] = module.exports;

+ 4 - 0
node_modules/@babel/runtime/helpers/OverloadYield.js

@@ -0,0 +1,4 @@
+function _OverloadYield(value, kind) {
+  this.v = value, this.k = kind;
+}
+module.exports = _OverloadYield, module.exports.__esModule = true, module.exports["default"] = module.exports;

+ 24 - 0
node_modules/@babel/runtime/helpers/applyDecoratedDescriptor.js

@@ -0,0 +1,24 @@
+function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) {
+  var desc = {};
+  Object.keys(descriptor).forEach(function (key) {
+    desc[key] = descriptor[key];
+  });
+  desc.enumerable = !!desc.enumerable;
+  desc.configurable = !!desc.configurable;
+  if ('value' in desc || desc.initializer) {
+    desc.writable = true;
+  }
+  desc = decorators.slice().reverse().reduce(function (desc, decorator) {
+    return decorator(target, property, desc) || desc;
+  }, desc);
+  if (context && desc.initializer !== void 0) {
+    desc.value = desc.initializer ? desc.initializer.call(context) : void 0;
+    desc.initializer = undefined;
+  }
+  if (desc.initializer === void 0) {
+    Object.defineProperty(target, property, desc);
+    desc = null;
+  }
+  return desc;
+}
+module.exports = _applyDecoratedDescriptor, module.exports.__esModule = true, module.exports["default"] = module.exports;

+ 242 - 0
node_modules/@babel/runtime/helpers/applyDecs.js

@@ -0,0 +1,242 @@
+var _typeof = require("./typeof.js")["default"];
+function old_createMetadataMethodsForProperty(metadataMap, kind, property, decoratorFinishedRef) {
+  return {
+    getMetadata: function getMetadata(key) {
+      old_assertNotFinished(decoratorFinishedRef, "getMetadata"), old_assertMetadataKey(key);
+      var metadataForKey = metadataMap[key];
+      if (void 0 !== metadataForKey) if (1 === kind) {
+        var pub = metadataForKey["public"];
+        if (void 0 !== pub) return pub[property];
+      } else if (2 === kind) {
+        var priv = metadataForKey["private"];
+        if (void 0 !== priv) return priv.get(property);
+      } else if (Object.hasOwnProperty.call(metadataForKey, "constructor")) return metadataForKey.constructor;
+    },
+    setMetadata: function setMetadata(key, value) {
+      old_assertNotFinished(decoratorFinishedRef, "setMetadata"), old_assertMetadataKey(key);
+      var metadataForKey = metadataMap[key];
+      if (void 0 === metadataForKey && (metadataForKey = metadataMap[key] = {}), 1 === kind) {
+        var pub = metadataForKey["public"];
+        void 0 === pub && (pub = metadataForKey["public"] = {}), pub[property] = value;
+      } else if (2 === kind) {
+        var priv = metadataForKey.priv;
+        void 0 === priv && (priv = metadataForKey["private"] = new Map()), priv.set(property, value);
+      } else metadataForKey.constructor = value;
+    }
+  };
+}
+function old_convertMetadataMapToFinal(obj, metadataMap) {
+  var parentMetadataMap = obj[Symbol.metadata || Symbol["for"]("Symbol.metadata")],
+    metadataKeys = Object.getOwnPropertySymbols(metadataMap);
+  if (0 !== metadataKeys.length) {
+    for (var i = 0; i < metadataKeys.length; i++) {
+      var key = metadataKeys[i],
+        metaForKey = metadataMap[key],
+        parentMetaForKey = parentMetadataMap ? parentMetadataMap[key] : null,
+        pub = metaForKey["public"],
+        parentPub = parentMetaForKey ? parentMetaForKey["public"] : null;
+      pub && parentPub && Object.setPrototypeOf(pub, parentPub);
+      var priv = metaForKey["private"];
+      if (priv) {
+        var privArr = Array.from(priv.values()),
+          parentPriv = parentMetaForKey ? parentMetaForKey["private"] : null;
+        parentPriv && (privArr = privArr.concat(parentPriv)), metaForKey["private"] = privArr;
+      }
+      parentMetaForKey && Object.setPrototypeOf(metaForKey, parentMetaForKey);
+    }
+    parentMetadataMap && Object.setPrototypeOf(metadataMap, parentMetadataMap), obj[Symbol.metadata || Symbol["for"]("Symbol.metadata")] = metadataMap;
+  }
+}
+function old_createAddInitializerMethod(initializers, decoratorFinishedRef) {
+  return function (initializer) {
+    old_assertNotFinished(decoratorFinishedRef, "addInitializer"), old_assertCallable(initializer, "An initializer"), initializers.push(initializer);
+  };
+}
+function old_memberDec(dec, name, desc, metadataMap, initializers, kind, isStatic, isPrivate, value) {
+  var kindStr;
+  switch (kind) {
+    case 1:
+      kindStr = "accessor";
+      break;
+    case 2:
+      kindStr = "method";
+      break;
+    case 3:
+      kindStr = "getter";
+      break;
+    case 4:
+      kindStr = "setter";
+      break;
+    default:
+      kindStr = "field";
+  }
+  var metadataKind,
+    metadataName,
+    ctx = {
+      kind: kindStr,
+      name: isPrivate ? "#" + name : name,
+      isStatic: isStatic,
+      isPrivate: isPrivate
+    },
+    decoratorFinishedRef = {
+      v: !1
+    };
+  if (0 !== kind && (ctx.addInitializer = old_createAddInitializerMethod(initializers, decoratorFinishedRef)), isPrivate) {
+    metadataKind = 2, metadataName = Symbol(name);
+    var access = {};
+    0 === kind ? (access.get = desc.get, access.set = desc.set) : 2 === kind ? access.get = function () {
+      return desc.value;
+    } : (1 !== kind && 3 !== kind || (access.get = function () {
+      return desc.get.call(this);
+    }), 1 !== kind && 4 !== kind || (access.set = function (v) {
+      desc.set.call(this, v);
+    })), ctx.access = access;
+  } else metadataKind = 1, metadataName = name;
+  try {
+    return dec(value, Object.assign(ctx, old_createMetadataMethodsForProperty(metadataMap, metadataKind, metadataName, decoratorFinishedRef)));
+  } finally {
+    decoratorFinishedRef.v = !0;
+  }
+}
+function old_assertNotFinished(decoratorFinishedRef, fnName) {
+  if (decoratorFinishedRef.v) throw new Error("attempted to call " + fnName + " after decoration was finished");
+}
+function old_assertMetadataKey(key) {
+  if ("symbol" != _typeof(key)) throw new TypeError("Metadata keys must be symbols, received: " + key);
+}
+function old_assertCallable(fn, hint) {
+  if ("function" != typeof fn) throw new TypeError(hint + " must be a function");
+}
+function old_assertValidReturnValue(kind, value) {
+  var type = _typeof(value);
+  if (1 === kind) {
+    if ("object" !== type || null === value) throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0");
+    void 0 !== value.get && old_assertCallable(value.get, "accessor.get"), void 0 !== value.set && old_assertCallable(value.set, "accessor.set"), void 0 !== value.init && old_assertCallable(value.init, "accessor.init"), void 0 !== value.initializer && old_assertCallable(value.initializer, "accessor.initializer");
+  } else if ("function" !== type) {
+    var hint;
+    throw hint = 0 === kind ? "field" : 10 === kind ? "class" : "method", new TypeError(hint + " decorators must return a function or void 0");
+  }
+}
+function old_getInit(desc) {
+  var initializer;
+  return null == (initializer = desc.init) && (initializer = desc.initializer) && "undefined" != typeof console && console.warn(".initializer has been renamed to .init as of March 2022"), initializer;
+}
+function old_applyMemberDec(ret, base, decInfo, name, kind, isStatic, isPrivate, metadataMap, initializers) {
+  var desc,
+    initializer,
+    value,
+    newValue,
+    get,
+    set,
+    decs = decInfo[0];
+  if (isPrivate ? desc = 0 === kind || 1 === kind ? {
+    get: decInfo[3],
+    set: decInfo[4]
+  } : 3 === kind ? {
+    get: decInfo[3]
+  } : 4 === kind ? {
+    set: decInfo[3]
+  } : {
+    value: decInfo[3]
+  } : 0 !== kind && (desc = Object.getOwnPropertyDescriptor(base, name)), 1 === kind ? value = {
+    get: desc.get,
+    set: desc.set
+  } : 2 === kind ? value = desc.value : 3 === kind ? value = desc.get : 4 === kind && (value = desc.set), "function" == typeof decs) void 0 !== (newValue = old_memberDec(decs, name, desc, metadataMap, initializers, kind, isStatic, isPrivate, value)) && (old_assertValidReturnValue(kind, newValue), 0 === kind ? initializer = newValue : 1 === kind ? (initializer = old_getInit(newValue), get = newValue.get || value.get, set = newValue.set || value.set, value = {
+    get: get,
+    set: set
+  }) : value = newValue);else for (var i = decs.length - 1; i >= 0; i--) {
+    var newInit;
+    if (void 0 !== (newValue = old_memberDec(decs[i], name, desc, metadataMap, initializers, kind, isStatic, isPrivate, value))) old_assertValidReturnValue(kind, newValue), 0 === kind ? newInit = newValue : 1 === kind ? (newInit = old_getInit(newValue), get = newValue.get || value.get, set = newValue.set || value.set, value = {
+      get: get,
+      set: set
+    }) : value = newValue, void 0 !== newInit && (void 0 === initializer ? initializer = newInit : "function" == typeof initializer ? initializer = [initializer, newInit] : initializer.push(newInit));
+  }
+  if (0 === kind || 1 === kind) {
+    if (void 0 === initializer) initializer = function initializer(instance, init) {
+      return init;
+    };else if ("function" != typeof initializer) {
+      var ownInitializers = initializer;
+      initializer = function initializer(instance, init) {
+        for (var value = init, i = 0; i < ownInitializers.length; i++) {
+          value = ownInitializers[i].call(instance, value);
+        }
+        return value;
+      };
+    } else {
+      var originalInitializer = initializer;
+      initializer = function initializer(instance, init) {
+        return originalInitializer.call(instance, init);
+      };
+    }
+    ret.push(initializer);
+  }
+  0 !== kind && (1 === kind ? (desc.get = value.get, desc.set = value.set) : 2 === kind ? desc.value = value : 3 === kind ? desc.get = value : 4 === kind && (desc.set = value), isPrivate ? 1 === kind ? (ret.push(function (instance, args) {
+    return value.get.call(instance, args);
+  }), ret.push(function (instance, args) {
+    return value.set.call(instance, args);
+  })) : 2 === kind ? ret.push(value) : ret.push(function (instance, args) {
+    return value.call(instance, args);
+  }) : Object.defineProperty(base, name, desc));
+}
+function old_applyMemberDecs(ret, Class, protoMetadataMap, staticMetadataMap, decInfos) {
+  for (var protoInitializers, staticInitializers, existingProtoNonFields = new Map(), existingStaticNonFields = new Map(), i = 0; i < decInfos.length; i++) {
+    var decInfo = decInfos[i];
+    if (Array.isArray(decInfo)) {
+      var base,
+        metadataMap,
+        initializers,
+        kind = decInfo[1],
+        name = decInfo[2],
+        isPrivate = decInfo.length > 3,
+        isStatic = kind >= 5;
+      if (isStatic ? (base = Class, metadataMap = staticMetadataMap, 0 !== (kind -= 5) && (initializers = staticInitializers = staticInitializers || [])) : (base = Class.prototype, metadataMap = protoMetadataMap, 0 !== kind && (initializers = protoInitializers = protoInitializers || [])), 0 !== kind && !isPrivate) {
+        var existingNonFields = isStatic ? existingStaticNonFields : existingProtoNonFields,
+          existingKind = existingNonFields.get(name) || 0;
+        if (!0 === existingKind || 3 === existingKind && 4 !== kind || 4 === existingKind && 3 !== kind) throw new Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + name);
+        !existingKind && kind > 2 ? existingNonFields.set(name, kind) : existingNonFields.set(name, !0);
+      }
+      old_applyMemberDec(ret, base, decInfo, name, kind, isStatic, isPrivate, metadataMap, initializers);
+    }
+  }
+  old_pushInitializers(ret, protoInitializers), old_pushInitializers(ret, staticInitializers);
+}
+function old_pushInitializers(ret, initializers) {
+  initializers && ret.push(function (instance) {
+    for (var i = 0; i < initializers.length; i++) {
+      initializers[i].call(instance);
+    }
+    return instance;
+  });
+}
+function old_applyClassDecs(ret, targetClass, metadataMap, classDecs) {
+  if (classDecs.length > 0) {
+    for (var initializers = [], newClass = targetClass, name = targetClass.name, i = classDecs.length - 1; i >= 0; i--) {
+      var decoratorFinishedRef = {
+        v: !1
+      };
+      try {
+        var ctx = Object.assign({
+            kind: "class",
+            name: name,
+            addInitializer: old_createAddInitializerMethod(initializers, decoratorFinishedRef)
+          }, old_createMetadataMethodsForProperty(metadataMap, 0, name, decoratorFinishedRef)),
+          nextNewClass = classDecs[i](newClass, ctx);
+      } finally {
+        decoratorFinishedRef.v = !0;
+      }
+      void 0 !== nextNewClass && (old_assertValidReturnValue(10, nextNewClass), newClass = nextNewClass);
+    }
+    ret.push(newClass, function () {
+      for (var i = 0; i < initializers.length; i++) {
+        initializers[i].call(newClass);
+      }
+    });
+  }
+}
+function applyDecs(targetClass, memberDecs, classDecs) {
+  var ret = [],
+    staticMetadataMap = {},
+    protoMetadataMap = {};
+  return old_applyMemberDecs(ret, targetClass, protoMetadataMap, staticMetadataMap, memberDecs), old_convertMetadataMapToFinal(targetClass.prototype, protoMetadataMap), old_applyClassDecs(ret, targetClass, staticMetadataMap, classDecs), old_convertMetadataMapToFinal(targetClass, staticMetadataMap), ret;
+}
+module.exports = applyDecs, module.exports.__esModule = true, module.exports["default"] = module.exports;

+ 190 - 0
node_modules/@babel/runtime/helpers/applyDecs2203.js

@@ -0,0 +1,190 @@
+var _typeof = require("./typeof.js")["default"];
+function createAddInitializerMethod(initializers, decoratorFinishedRef) {
+  return function (initializer) {
+    assertNotFinished(decoratorFinishedRef, "addInitializer"), assertCallable(initializer, "An initializer"), initializers.push(initializer);
+  };
+}
+function memberDec(dec, name, desc, initializers, kind, isStatic, isPrivate, value) {
+  var kindStr;
+  switch (kind) {
+    case 1:
+      kindStr = "accessor";
+      break;
+    case 2:
+      kindStr = "method";
+      break;
+    case 3:
+      kindStr = "getter";
+      break;
+    case 4:
+      kindStr = "setter";
+      break;
+    default:
+      kindStr = "field";
+  }
+  var get,
+    set,
+    ctx = {
+      kind: kindStr,
+      name: isPrivate ? "#" + name : name,
+      "static": isStatic,
+      "private": isPrivate
+    },
+    decoratorFinishedRef = {
+      v: !1
+    };
+  0 !== kind && (ctx.addInitializer = createAddInitializerMethod(initializers, decoratorFinishedRef)), 0 === kind ? isPrivate ? (get = desc.get, set = desc.set) : (get = function get() {
+    return this[name];
+  }, set = function set(v) {
+    this[name] = v;
+  }) : 2 === kind ? get = function get() {
+    return desc.value;
+  } : (1 !== kind && 3 !== kind || (get = function get() {
+    return desc.get.call(this);
+  }), 1 !== kind && 4 !== kind || (set = function set(v) {
+    desc.set.call(this, v);
+  })), ctx.access = get && set ? {
+    get: get,
+    set: set
+  } : get ? {
+    get: get
+  } : {
+    set: set
+  };
+  try {
+    return dec(value, ctx);
+  } finally {
+    decoratorFinishedRef.v = !0;
+  }
+}
+function assertNotFinished(decoratorFinishedRef, fnName) {
+  if (decoratorFinishedRef.v) throw new Error("attempted to call " + fnName + " after decoration was finished");
+}
+function assertCallable(fn, hint) {
+  if ("function" != typeof fn) throw new TypeError(hint + " must be a function");
+}
+function assertValidReturnValue(kind, value) {
+  var type = _typeof(value);
+  if (1 === kind) {
+    if ("object" !== type || null === value) throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0");
+    void 0 !== value.get && assertCallable(value.get, "accessor.get"), void 0 !== value.set && assertCallable(value.set, "accessor.set"), void 0 !== value.init && assertCallable(value.init, "accessor.init");
+  } else if ("function" !== type) {
+    var hint;
+    throw hint = 0 === kind ? "field" : 10 === kind ? "class" : "method", new TypeError(hint + " decorators must return a function or void 0");
+  }
+}
+function applyMemberDec(ret, base, decInfo, name, kind, isStatic, isPrivate, initializers) {
+  var desc,
+    init,
+    value,
+    newValue,
+    get,
+    set,
+    decs = decInfo[0];
+  if (isPrivate ? desc = 0 === kind || 1 === kind ? {
+    get: decInfo[3],
+    set: decInfo[4]
+  } : 3 === kind ? {
+    get: decInfo[3]
+  } : 4 === kind ? {
+    set: decInfo[3]
+  } : {
+    value: decInfo[3]
+  } : 0 !== kind && (desc = Object.getOwnPropertyDescriptor(base, name)), 1 === kind ? value = {
+    get: desc.get,
+    set: desc.set
+  } : 2 === kind ? value = desc.value : 3 === kind ? value = desc.get : 4 === kind && (value = desc.set), "function" == typeof decs) void 0 !== (newValue = memberDec(decs, name, desc, initializers, kind, isStatic, isPrivate, value)) && (assertValidReturnValue(kind, newValue), 0 === kind ? init = newValue : 1 === kind ? (init = newValue.init, get = newValue.get || value.get, set = newValue.set || value.set, value = {
+    get: get,
+    set: set
+  }) : value = newValue);else for (var i = decs.length - 1; i >= 0; i--) {
+    var newInit;
+    if (void 0 !== (newValue = memberDec(decs[i], name, desc, initializers, kind, isStatic, isPrivate, value))) assertValidReturnValue(kind, newValue), 0 === kind ? newInit = newValue : 1 === kind ? (newInit = newValue.init, get = newValue.get || value.get, set = newValue.set || value.set, value = {
+      get: get,
+      set: set
+    }) : value = newValue, void 0 !== newInit && (void 0 === init ? init = newInit : "function" == typeof init ? init = [init, newInit] : init.push(newInit));
+  }
+  if (0 === kind || 1 === kind) {
+    if (void 0 === init) init = function init(instance, _init) {
+      return _init;
+    };else if ("function" != typeof init) {
+      var ownInitializers = init;
+      init = function init(instance, _init2) {
+        for (var value = _init2, i = 0; i < ownInitializers.length; i++) {
+          value = ownInitializers[i].call(instance, value);
+        }
+        return value;
+      };
+    } else {
+      var originalInitializer = init;
+      init = function init(instance, _init3) {
+        return originalInitializer.call(instance, _init3);
+      };
+    }
+    ret.push(init);
+  }
+  0 !== kind && (1 === kind ? (desc.get = value.get, desc.set = value.set) : 2 === kind ? desc.value = value : 3 === kind ? desc.get = value : 4 === kind && (desc.set = value), isPrivate ? 1 === kind ? (ret.push(function (instance, args) {
+    return value.get.call(instance, args);
+  }), ret.push(function (instance, args) {
+    return value.set.call(instance, args);
+  })) : 2 === kind ? ret.push(value) : ret.push(function (instance, args) {
+    return value.call(instance, args);
+  }) : Object.defineProperty(base, name, desc));
+}
+function applyMemberDecs(ret, Class, decInfos) {
+  for (var protoInitializers, staticInitializers, existingProtoNonFields = new Map(), existingStaticNonFields = new Map(), i = 0; i < decInfos.length; i++) {
+    var decInfo = decInfos[i];
+    if (Array.isArray(decInfo)) {
+      var base,
+        initializers,
+        kind = decInfo[1],
+        name = decInfo[2],
+        isPrivate = decInfo.length > 3,
+        isStatic = kind >= 5;
+      if (isStatic ? (base = Class, 0 !== (kind -= 5) && (initializers = staticInitializers = staticInitializers || [])) : (base = Class.prototype, 0 !== kind && (initializers = protoInitializers = protoInitializers || [])), 0 !== kind && !isPrivate) {
+        var existingNonFields = isStatic ? existingStaticNonFields : existingProtoNonFields,
+          existingKind = existingNonFields.get(name) || 0;
+        if (!0 === existingKind || 3 === existingKind && 4 !== kind || 4 === existingKind && 3 !== kind) throw new Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + name);
+        !existingKind && kind > 2 ? existingNonFields.set(name, kind) : existingNonFields.set(name, !0);
+      }
+      applyMemberDec(ret, base, decInfo, name, kind, isStatic, isPrivate, initializers);
+    }
+  }
+  pushInitializers(ret, protoInitializers), pushInitializers(ret, staticInitializers);
+}
+function pushInitializers(ret, initializers) {
+  initializers && ret.push(function (instance) {
+    for (var i = 0; i < initializers.length; i++) {
+      initializers[i].call(instance);
+    }
+    return instance;
+  });
+}
+function applyClassDecs(ret, targetClass, classDecs) {
+  if (classDecs.length > 0) {
+    for (var initializers = [], newClass = targetClass, name = targetClass.name, i = classDecs.length - 1; i >= 0; i--) {
+      var decoratorFinishedRef = {
+        v: !1
+      };
+      try {
+        var nextNewClass = classDecs[i](newClass, {
+          kind: "class",
+          name: name,
+          addInitializer: createAddInitializerMethod(initializers, decoratorFinishedRef)
+        });
+      } finally {
+        decoratorFinishedRef.v = !0;
+      }
+      void 0 !== nextNewClass && (assertValidReturnValue(10, nextNewClass), newClass = nextNewClass);
+    }
+    ret.push(newClass, function () {
+      for (var i = 0; i < initializers.length; i++) {
+        initializers[i].call(newClass);
+      }
+    });
+  }
+}
+function applyDecs2203(targetClass, memberDecs, classDecs) {
+  var ret = [];
+  return applyMemberDecs(ret, targetClass, memberDecs), applyClassDecs(ret, targetClass, classDecs), ret;
+}
+module.exports = applyDecs2203, module.exports.__esModule = true, module.exports["default"] = module.exports;

+ 8 - 0
node_modules/@babel/runtime/helpers/arrayLikeToArray.js

@@ -0,0 +1,8 @@
+function _arrayLikeToArray(arr, len) {
+  if (len == null || len > arr.length) len = arr.length;
+  for (var i = 0, arr2 = new Array(len); i < len; i++) {
+    arr2[i] = arr[i];
+  }
+  return arr2;
+}
+module.exports = _arrayLikeToArray, module.exports.__esModule = true, module.exports["default"] = module.exports;

+ 4 - 0
node_modules/@babel/runtime/helpers/arrayWithHoles.js

@@ -0,0 +1,4 @@
+function _arrayWithHoles(arr) {
+  if (Array.isArray(arr)) return arr;
+}
+module.exports = _arrayWithHoles, module.exports.__esModule = true, module.exports["default"] = module.exports;

+ 5 - 0
node_modules/@babel/runtime/helpers/arrayWithoutHoles.js

@@ -0,0 +1,5 @@
+var arrayLikeToArray = require("./arrayLikeToArray.js");
+function _arrayWithoutHoles(arr) {
+  if (Array.isArray(arr)) return arrayLikeToArray(arr);
+}
+module.exports = _arrayWithoutHoles, module.exports.__esModule = true, module.exports["default"] = module.exports;

+ 7 - 0
node_modules/@babel/runtime/helpers/assertThisInitialized.js

@@ -0,0 +1,7 @@
+function _assertThisInitialized(self) {
+  if (self === void 0) {
+    throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
+  }
+  return self;
+}
+module.exports = _assertThisInitialized, module.exports.__esModule = true, module.exports["default"] = module.exports;

+ 24 - 0
node_modules/@babel/runtime/helpers/asyncGeneratorDelegate.js

@@ -0,0 +1,24 @@
+var OverloadYield = require("./OverloadYield.js");
+function _asyncGeneratorDelegate(inner) {
+  var iter = {},
+    waiting = !1;
+  function pump(key, value) {
+    return waiting = !0, value = new Promise(function (resolve) {
+      resolve(inner[key](value));
+    }), {
+      done: !1,
+      value: new OverloadYield(value, 1)
+    };
+  }
+  return iter["undefined" != typeof Symbol && Symbol.iterator || "@@iterator"] = function () {
+    return this;
+  }, iter.next = function (value) {
+    return waiting ? (waiting = !1, value) : pump("next", value);
+  }, "function" == typeof inner["throw"] && (iter["throw"] = function (value) {
+    if (waiting) throw waiting = !1, value;
+    return pump("throw", value);
+  }), "function" == typeof inner["return"] && (iter["return"] = function (value) {
+    return waiting ? (waiting = !1, value) : pump("return", value);
+  }), iter;
+}
+module.exports = _asyncGeneratorDelegate, module.exports.__esModule = true, module.exports["default"] = module.exports;

+ 45 - 0
node_modules/@babel/runtime/helpers/asyncIterator.js

@@ -0,0 +1,45 @@
+function _asyncIterator(iterable) {
+  var method,
+    async,
+    sync,
+    retry = 2;
+  for ("undefined" != typeof Symbol && (async = Symbol.asyncIterator, sync = Symbol.iterator); retry--;) {
+    if (async && null != (method = iterable[async])) return method.call(iterable);
+    if (sync && null != (method = iterable[sync])) return new AsyncFromSyncIterator(method.call(iterable));
+    async = "@@asyncIterator", sync = "@@iterator";
+  }
+  throw new TypeError("Object is not async iterable");
+}
+function AsyncFromSyncIterator(s) {
+  function AsyncFromSyncIteratorContinuation(r) {
+    if (Object(r) !== r) return Promise.reject(new TypeError(r + " is not an object."));
+    var done = r.done;
+    return Promise.resolve(r.value).then(function (value) {
+      return {
+        value: value,
+        done: done
+      };
+    });
+  }
+  return AsyncFromSyncIterator = function AsyncFromSyncIterator(s) {
+    this.s = s, this.n = s.next;
+  }, AsyncFromSyncIterator.prototype = {
+    s: null,
+    n: null,
+    next: function next() {
+      return AsyncFromSyncIteratorContinuation(this.n.apply(this.s, arguments));
+    },
+    "return": function _return(value) {
+      var ret = this.s["return"];
+      return void 0 === ret ? Promise.resolve({
+        value: value,
+        done: !0
+      }) : AsyncFromSyncIteratorContinuation(ret.apply(this.s, arguments));
+    },
+    "throw": function _throw(value) {
+      var thr = this.s["return"];
+      return void 0 === thr ? Promise.reject(value) : AsyncFromSyncIteratorContinuation(thr.apply(this.s, arguments));
+    }
+  }, new AsyncFromSyncIterator(s);
+}
+module.exports = _asyncIterator, module.exports.__esModule = true, module.exports["default"] = module.exports;

+ 31 - 0
node_modules/@babel/runtime/helpers/asyncToGenerator.js

@@ -0,0 +1,31 @@
+function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
+  try {
+    var info = gen[key](arg);
+    var value = info.value;
+  } catch (error) {
+    reject(error);
+    return;
+  }
+  if (info.done) {
+    resolve(value);
+  } else {
+    Promise.resolve(value).then(_next, _throw);
+  }
+}
+function _asyncToGenerator(fn) {
+  return function () {
+    var self = this,
+      args = arguments;
+    return new Promise(function (resolve, reject) {
+      var gen = fn.apply(self, args);
+      function _next(value) {
+        asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
+      }
+      function _throw(err) {
+        asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
+      }
+      _next(undefined);
+    });
+  };
+}
+module.exports = _asyncToGenerator, module.exports.__esModule = true, module.exports["default"] = module.exports;

+ 5 - 0
node_modules/@babel/runtime/helpers/awaitAsyncGenerator.js

@@ -0,0 +1,5 @@
+var OverloadYield = require("./OverloadYield.js");
+function _awaitAsyncGenerator(value) {
+  return new OverloadYield(value, 0);
+}
+module.exports = _awaitAsyncGenerator, module.exports.__esModule = true, module.exports["default"] = module.exports;

+ 6 - 0
node_modules/@babel/runtime/helpers/checkPrivateRedeclaration.js

@@ -0,0 +1,6 @@
+function _checkPrivateRedeclaration(obj, privateCollection) {
+  if (privateCollection.has(obj)) {
+    throw new TypeError("Cannot initialize the same private elements twice on an object");
+  }
+}
+module.exports = _checkPrivateRedeclaration, module.exports.__esModule = true, module.exports["default"] = module.exports;

+ 18 - 0
node_modules/@babel/runtime/helpers/classApplyDescriptorDestructureSet.js

@@ -0,0 +1,18 @@
+function _classApplyDescriptorDestructureSet(receiver, descriptor) {
+  if (descriptor.set) {
+    if (!("__destrObj" in descriptor)) {
+      descriptor.__destrObj = {
+        set value(v) {
+          descriptor.set.call(receiver, v);
+        }
+      };
+    }
+    return descriptor.__destrObj;
+  } else {
+    if (!descriptor.writable) {
+      throw new TypeError("attempted to set read only private field");
+    }
+    return descriptor;
+  }
+}
+module.exports = _classApplyDescriptorDestructureSet, module.exports.__esModule = true, module.exports["default"] = module.exports;

+ 7 - 0
node_modules/@babel/runtime/helpers/classApplyDescriptorGet.js

@@ -0,0 +1,7 @@
+function _classApplyDescriptorGet(receiver, descriptor) {
+  if (descriptor.get) {
+    return descriptor.get.call(receiver);
+  }
+  return descriptor.value;
+}
+module.exports = _classApplyDescriptorGet, module.exports.__esModule = true, module.exports["default"] = module.exports;

+ 11 - 0
node_modules/@babel/runtime/helpers/classApplyDescriptorSet.js

@@ -0,0 +1,11 @@
+function _classApplyDescriptorSet(receiver, descriptor, value) {
+  if (descriptor.set) {
+    descriptor.set.call(receiver, value);
+  } else {
+    if (!descriptor.writable) {
+      throw new TypeError("attempted to set read only private field");
+    }
+    descriptor.value = value;
+  }
+}
+module.exports = _classApplyDescriptorSet, module.exports.__esModule = true, module.exports["default"] = module.exports;

+ 6 - 0
node_modules/@babel/runtime/helpers/classCallCheck.js

@@ -0,0 +1,6 @@
+function _classCallCheck(instance, Constructor) {
+  if (!(instance instanceof Constructor)) {
+    throw new TypeError("Cannot call a class as a function");
+  }
+}
+module.exports = _classCallCheck, module.exports.__esModule = true, module.exports["default"] = module.exports;

+ 6 - 0
node_modules/@babel/runtime/helpers/classCheckPrivateStaticAccess.js

@@ -0,0 +1,6 @@
+function _classCheckPrivateStaticAccess(receiver, classConstructor) {
+  if (receiver !== classConstructor) {
+    throw new TypeError("Private static access of wrong provenance");
+  }
+}
+module.exports = _classCheckPrivateStaticAccess, module.exports.__esModule = true, module.exports["default"] = module.exports;

+ 6 - 0
node_modules/@babel/runtime/helpers/classCheckPrivateStaticFieldDescriptor.js

@@ -0,0 +1,6 @@
+function _classCheckPrivateStaticFieldDescriptor(descriptor, action) {
+  if (descriptor === undefined) {
+    throw new TypeError("attempted to " + action + " private static field before its declaration");
+  }
+}
+module.exports = _classCheckPrivateStaticFieldDescriptor, module.exports.__esModule = true, module.exports["default"] = module.exports;

+ 7 - 0
node_modules/@babel/runtime/helpers/classExtractFieldDescriptor.js

@@ -0,0 +1,7 @@
+function _classExtractFieldDescriptor(receiver, privateMap, action) {
+  if (!privateMap.has(receiver)) {
+    throw new TypeError("attempted to " + action + " private field on non-instance");
+  }
+  return privateMap.get(receiver);
+}
+module.exports = _classExtractFieldDescriptor, module.exports.__esModule = true, module.exports["default"] = module.exports;

+ 4 - 0
node_modules/@babel/runtime/helpers/classNameTDZError.js

@@ -0,0 +1,4 @@
+function _classNameTDZError(name) {
+  throw new Error("Class \"" + name + "\" cannot be referenced in computed property keys.");
+}
+module.exports = _classNameTDZError, module.exports.__esModule = true, module.exports["default"] = module.exports;

+ 7 - 0
node_modules/@babel/runtime/helpers/classPrivateFieldDestructureSet.js

@@ -0,0 +1,7 @@
+var classApplyDescriptorDestructureSet = require("./classApplyDescriptorDestructureSet.js");
+var classExtractFieldDescriptor = require("./classExtractFieldDescriptor.js");
+function _classPrivateFieldDestructureSet(receiver, privateMap) {
+  var descriptor = classExtractFieldDescriptor(receiver, privateMap, "set");
+  return classApplyDescriptorDestructureSet(receiver, descriptor);
+}
+module.exports = _classPrivateFieldDestructureSet, module.exports.__esModule = true, module.exports["default"] = module.exports;

+ 7 - 0
node_modules/@babel/runtime/helpers/classPrivateFieldGet.js

@@ -0,0 +1,7 @@
+var classApplyDescriptorGet = require("./classApplyDescriptorGet.js");
+var classExtractFieldDescriptor = require("./classExtractFieldDescriptor.js");
+function _classPrivateFieldGet(receiver, privateMap) {
+  var descriptor = classExtractFieldDescriptor(receiver, privateMap, "get");
+  return classApplyDescriptorGet(receiver, descriptor);
+}
+module.exports = _classPrivateFieldGet, module.exports.__esModule = true, module.exports["default"] = module.exports;

+ 6 - 0
node_modules/@babel/runtime/helpers/classPrivateFieldInitSpec.js

@@ -0,0 +1,6 @@
+var checkPrivateRedeclaration = require("./checkPrivateRedeclaration.js");
+function _classPrivateFieldInitSpec(obj, privateMap, value) {
+  checkPrivateRedeclaration(obj, privateMap);
+  privateMap.set(obj, value);
+}
+module.exports = _classPrivateFieldInitSpec, module.exports.__esModule = true, module.exports["default"] = module.exports;

+ 7 - 0
node_modules/@babel/runtime/helpers/classPrivateFieldLooseBase.js

@@ -0,0 +1,7 @@
+function _classPrivateFieldBase(receiver, privateKey) {
+  if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) {
+    throw new TypeError("attempted to use private field on non-instance");
+  }
+  return receiver;
+}
+module.exports = _classPrivateFieldBase, module.exports.__esModule = true, module.exports["default"] = module.exports;

+ 5 - 0
node_modules/@babel/runtime/helpers/classPrivateFieldLooseKey.js

@@ -0,0 +1,5 @@
+var id = 0;
+function _classPrivateFieldKey(name) {
+  return "__private_" + id++ + "_" + name;
+}
+module.exports = _classPrivateFieldKey, module.exports.__esModule = true, module.exports["default"] = module.exports;

+ 8 - 0
node_modules/@babel/runtime/helpers/classPrivateFieldSet.js

@@ -0,0 +1,8 @@
+var classApplyDescriptorSet = require("./classApplyDescriptorSet.js");
+var classExtractFieldDescriptor = require("./classExtractFieldDescriptor.js");
+function _classPrivateFieldSet(receiver, privateMap, value) {
+  var descriptor = classExtractFieldDescriptor(receiver, privateMap, "set");
+  classApplyDescriptorSet(receiver, descriptor, value);
+  return value;
+}
+module.exports = _classPrivateFieldSet, module.exports.__esModule = true, module.exports["default"] = module.exports;

+ 7 - 0
node_modules/@babel/runtime/helpers/classPrivateMethodGet.js

@@ -0,0 +1,7 @@
+function _classPrivateMethodGet(receiver, privateSet, fn) {
+  if (!privateSet.has(receiver)) {
+    throw new TypeError("attempted to get private field on non-instance");
+  }
+  return fn;
+}
+module.exports = _classPrivateMethodGet, module.exports.__esModule = true, module.exports["default"] = module.exports;

+ 6 - 0
node_modules/@babel/runtime/helpers/classPrivateMethodInitSpec.js

@@ -0,0 +1,6 @@
+var checkPrivateRedeclaration = require("./checkPrivateRedeclaration.js");
+function _classPrivateMethodInitSpec(obj, privateSet) {
+  checkPrivateRedeclaration(obj, privateSet);
+  privateSet.add(obj);
+}
+module.exports = _classPrivateMethodInitSpec, module.exports.__esModule = true, module.exports["default"] = module.exports;

+ 4 - 0
node_modules/@babel/runtime/helpers/classPrivateMethodSet.js

@@ -0,0 +1,4 @@
+function _classPrivateMethodSet() {
+  throw new TypeError("attempted to reassign private method");
+}
+module.exports = _classPrivateMethodSet, module.exports.__esModule = true, module.exports["default"] = module.exports;

+ 9 - 0
node_modules/@babel/runtime/helpers/classStaticPrivateFieldDestructureSet.js

@@ -0,0 +1,9 @@
+var classApplyDescriptorDestructureSet = require("./classApplyDescriptorDestructureSet.js");
+var classCheckPrivateStaticAccess = require("./classCheckPrivateStaticAccess.js");
+var classCheckPrivateStaticFieldDescriptor = require("./classCheckPrivateStaticFieldDescriptor.js");
+function _classStaticPrivateFieldDestructureSet(receiver, classConstructor, descriptor) {
+  classCheckPrivateStaticAccess(receiver, classConstructor);
+  classCheckPrivateStaticFieldDescriptor(descriptor, "set");
+  return classApplyDescriptorDestructureSet(receiver, descriptor);
+}
+module.exports = _classStaticPrivateFieldDestructureSet, module.exports.__esModule = true, module.exports["default"] = module.exports;

+ 9 - 0
node_modules/@babel/runtime/helpers/classStaticPrivateFieldSpecGet.js

@@ -0,0 +1,9 @@
+var classApplyDescriptorGet = require("./classApplyDescriptorGet.js");
+var classCheckPrivateStaticAccess = require("./classCheckPrivateStaticAccess.js");
+var classCheckPrivateStaticFieldDescriptor = require("./classCheckPrivateStaticFieldDescriptor.js");
+function _classStaticPrivateFieldSpecGet(receiver, classConstructor, descriptor) {
+  classCheckPrivateStaticAccess(receiver, classConstructor);
+  classCheckPrivateStaticFieldDescriptor(descriptor, "get");
+  return classApplyDescriptorGet(receiver, descriptor);
+}
+module.exports = _classStaticPrivateFieldSpecGet, module.exports.__esModule = true, module.exports["default"] = module.exports;

+ 10 - 0
node_modules/@babel/runtime/helpers/classStaticPrivateFieldSpecSet.js

@@ -0,0 +1,10 @@
+var classApplyDescriptorSet = require("./classApplyDescriptorSet.js");
+var classCheckPrivateStaticAccess = require("./classCheckPrivateStaticAccess.js");
+var classCheckPrivateStaticFieldDescriptor = require("./classCheckPrivateStaticFieldDescriptor.js");
+function _classStaticPrivateFieldSpecSet(receiver, classConstructor, descriptor, value) {
+  classCheckPrivateStaticAccess(receiver, classConstructor);
+  classCheckPrivateStaticFieldDescriptor(descriptor, "set");
+  classApplyDescriptorSet(receiver, descriptor, value);
+  return value;
+}
+module.exports = _classStaticPrivateFieldSpecSet, module.exports.__esModule = true, module.exports["default"] = module.exports;

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