1
0
Prechádzať zdrojové kódy

中网小程序微信国际(香港)支付小程序前端模块提交

hyq 6 rokov pred
rodič
commit
72963872c1
100 zmenil súbory, kde vykonal 18151 pridanie a 0 odobranie
  1. 31 0
      wx-mall-hk/app.js
  2. 104 0
      wx-mall-hk/app.json
  3. 508 0
      wx-mall-hk/app.wxss
  4. 142 0
      wx-mall-hk/config/api.js
  5. 462 0
      wx-mall-hk/lib/qqmap/qqmap-wx-jssdk.js
  6. 0 0
      wx-mall-hk/lib/qqmap/qqmap-wx-jssdk.min.js
  7. 244 0
      wx-mall-hk/lib/wxParse/html2json.js
  8. 182 0
      wx-mall-hk/lib/wxParse/htmlparser.js
  9. 2529 0
      wx-mall-hk/lib/wxParse/showdown.js
  10. 206 0
      wx-mall-hk/lib/wxParse/wxDiscode.js
  11. 146 0
      wx-mall-hk/lib/wxParse/wxParse.js
  12. 928 0
      wx-mall-hk/lib/wxParse/wxParse.wxml
  13. 200 0
      wx-mall-hk/lib/wxParse/wxParse.wxss
  14. 80 0
      wx-mall-hk/pages/activity/activity.js
  15. 1 0
      wx-mall-hk/pages/activity/activity.json
  16. 48 0
      wx-mall-hk/pages/activity/activity.wxml
  17. 187 0
      wx-mall-hk/pages/activity/activity.wxss
  18. 101 0
      wx-mall-hk/pages/auth/btnAuth/btnAuth.js
  19. 4 0
      wx-mall-hk/pages/auth/btnAuth/btnAuth.json
  20. 14 0
      wx-mall-hk/pages/auth/btnAuth/btnAuth.wxml
  21. 63 0
      wx-mall-hk/pages/auth/btnAuth/btnAuth.wxss
  22. 106 0
      wx-mall-hk/pages/auth/login/login.js
  23. 1 0
      wx-mall-hk/pages/auth/login/login.json
  24. 30 0
      wx-mall-hk/pages/auth/login/login.wxml
  25. 89 0
      wx-mall-hk/pages/auth/login/login.wxss
  26. 187 0
      wx-mall-hk/pages/auth/newuser/newuser.js
  27. 1 0
      wx-mall-hk/pages/auth/newuser/newuser.json
  28. 22 0
      wx-mall-hk/pages/auth/newuser/newuser.wxml
  29. 104 0
      wx-mall-hk/pages/auth/newuser/newuser.wxss
  30. 130 0
      wx-mall-hk/pages/auth/register/register.js
  31. 1 0
      wx-mall-hk/pages/auth/register/register.json
  32. 30 0
      wx-mall-hk/pages/auth/register/register.wxml
  33. 89 0
      wx-mall-hk/pages/auth/register/register.wxss
  34. 56 0
      wx-mall-hk/pages/auth/reset/reset.js
  35. 1 0
      wx-mall-hk/pages/auth/reset/reset.json
  36. 20 0
      wx-mall-hk/pages/auth/reset/reset.wxml
  37. 68 0
      wx-mall-hk/pages/auth/reset/reset.wxss
  38. 56 0
      wx-mall-hk/pages/brand/brand.js
  39. 1 0
      wx-mall-hk/pages/brand/brand.json
  40. 16 0
      wx-mall-hk/pages/brand/brand.wxml
  41. 52 0
      wx-mall-hk/pages/brand/brand.wxss
  42. 63 0
      wx-mall-hk/pages/brandDetail/brandDetail.js
  43. 3 0
      wx-mall-hk/pages/brandDetail/brandDetail.json
  44. 28 0
      wx-mall-hk/pages/brandDetail/brandDetail.wxml
  45. 110 0
      wx-mall-hk/pages/brandDetail/brandDetail.wxss
  46. 522 0
      wx-mall-hk/pages/cart/cart.js
  47. 3 0
      wx-mall-hk/pages/cart/cart.json
  48. 286 0
      wx-mall-hk/pages/cart/cart.wxml
  49. 724 0
      wx-mall-hk/pages/cart/cart.wxss
  50. 369 0
      wx-mall-hk/pages/catalog/catalog.js
  51. 1 0
      wx-mall-hk/pages/catalog/catalog.json
  52. 157 0
      wx-mall-hk/pages/catalog/catalog.wxml
  53. 450 0
      wx-mall-hk/pages/catalog/catalog.wxss
  54. 340 0
      wx-mall-hk/pages/category/category.js
  55. 3 0
      wx-mall-hk/pages/category/category.json
  56. 118 0
      wx-mall-hk/pages/category/category.wxml
  57. 291 0
      wx-mall-hk/pages/category/category.wxss
  58. 133 0
      wx-mall-hk/pages/comment/comment.js
  59. 3 0
      wx-mall-hk/pages/comment/comment.json
  60. 49 0
      wx-mall-hk/pages/comment/comment.wxml
  61. 185 0
      wx-mall-hk/pages/comment/comment.wxss
  62. 193 0
      wx-mall-hk/pages/commentPost/commentPost.js
  63. 3 0
      wx-mall-hk/pages/commentPost/commentPost.json
  64. 99 0
      wx-mall-hk/pages/commentPost/commentPost.wxml
  65. 279 0
      wx-mall-hk/pages/commentPost/commentPost.wxss
  66. 532 0
      wx-mall-hk/pages/goods/goods.js
  67. 1 0
      wx-mall-hk/pages/goods/goods.json
  68. 300 0
      wx-mall-hk/pages/goods/goods.wxml
  69. 1138 0
      wx-mall-hk/pages/goods/goods.wxss
  70. 97 0
      wx-mall-hk/pages/goodsActivity/goodsActivity.js
  71. 1 0
      wx-mall-hk/pages/goodsActivity/goodsActivity.json
  72. 28 0
      wx-mall-hk/pages/goodsActivity/goodsActivity.wxml
  73. 7 0
      wx-mall-hk/pages/goodsActivity/goodsActivity.wxss
  74. 85 0
      wx-mall-hk/pages/group/group.js
  75. 3 0
      wx-mall-hk/pages/group/group.json
  76. 25 0
      wx-mall-hk/pages/group/group.wxml
  77. 52 0
      wx-mall-hk/pages/group/group.wxss
  78. 363 0
      wx-mall-hk/pages/groupDetail/groupDetail.js
  79. 1 0
      wx-mall-hk/pages/groupDetail/groupDetail.json
  80. 206 0
      wx-mall-hk/pages/groupDetail/groupDetail.wxml
  81. 767 0
      wx-mall-hk/pages/groupDetail/groupDetail.wxss
  82. 277 0
      wx-mall-hk/pages/hotGoods/hotGoods.js
  83. 3 0
      wx-mall-hk/pages/hotGoods/hotGoods.json
  84. 128 0
      wx-mall-hk/pages/hotGoods/hotGoods.wxml
  85. 349 0
      wx-mall-hk/pages/hotGoods/hotGoods.wxss
  86. 384 0
      wx-mall-hk/pages/index/index.js
  87. 1 0
      wx-mall-hk/pages/index/index.json
  88. 213 0
      wx-mall-hk/pages/index/index.wxml
  89. 644 0
      wx-mall-hk/pages/index/index.wxss
  90. 237 0
      wx-mall-hk/pages/joinGroup/joinGroup.js
  91. 1 0
      wx-mall-hk/pages/joinGroup/joinGroup.json
  92. 99 0
      wx-mall-hk/pages/joinGroup/joinGroup.wxml
  93. 354 0
      wx-mall-hk/pages/joinGroup/joinGroup.wxss
  94. 14 0
      wx-mall-hk/pages/logs/logs.js
  95. 3 0
      wx-mall-hk/pages/logs/logs.json
  96. 6 0
      wx-mall-hk/pages/logs/logs.wxml
  97. 8 0
      wx-mall-hk/pages/logs/logs.wxss
  98. 159 0
      wx-mall-hk/pages/map/map.js
  99. 3 0
      wx-mall-hk/pages/map/map.json
  100. 10 0
      wx-mall-hk/pages/map/map.wxml

+ 31 - 0
wx-mall-hk/app.js

@@ -0,0 +1,31 @@
+var util = require('./utils/util.js');
+var api = require('./config/api.js');
+var user = require('./services/user.js');
+
+App({
+  onLaunch: function () {
+    var that = this;
+    //获取用户的登录信息
+    // user.checkLogin().then(res => {
+    // }).catch(() => {
+    //   user.loginByWeixin();
+    // });
+
+    // 设备信息
+    wx.getSystemInfo({
+      success: function (res) {
+        that.globalData.systemInfo = res;
+      }
+    });
+    console.log("that.globalData.systemInfo:"+that.globalData.systemInfo);
+  },
+  globalData: {
+    systemInfo: '',
+    userInfo: {
+      nickName: '点击头像登录',
+      avatarUrl: 'http://120.76.26.84:80/group1/M00/00/01/rBJEdVvr17OACigOAAAB_us54MA744.png'
+    },
+    token: '',
+    appGoodsBizType: '00'
+  }
+})

+ 104 - 0
wx-mall-hk/app.json

@@ -0,0 +1,104 @@
+{
+  "pages": [
+    "pages/index/index",
+    "pages/catalog/catalog",
+    "pages/newGoods/newGoods",
+    "pages/hotGoods/hotGoods",
+    "pages/ucenter/address/address",
+    "pages/ucenter/addressAdd/addressAdd",
+    "pages/ucenter/orderDetail/orderDetail",
+    "pages/ucenter/footprint/footprint",
+    "pages/ucenter/order/order",
+    "pages/ucenter/feedback/feedback",
+    "pages/ucenter/coupon/coupon",
+    "pages/ucenter/collect/collect",
+    "pages/auth/login/login",
+    "pages/auth/register/register",
+    "pages/auth/reset/reset",
+    "pages/pay/pay",
+    "pages/payResult/payResult",
+    "pages/ucenter/index/index",
+    "pages/topic/topic",
+    "pages/comment/comment",
+    "pages/commentPost/commentPost",
+    "pages/topicComment/topicComment",
+    "pages/brand/brand",
+    "pages/brandDetail/brandDetail",
+    "pages/search/search",
+    "pages/category/category",
+    "pages/cart/cart",
+    "pages/shopping/checkout/checkout",
+    "pages/shopping/address/address",
+    "pages/shopping/addressAdd/addressAdd",
+    "pages/goods/goods",
+    "pages/store/store",
+    "pages/topicDetail/topicDetail",
+    "pages/ucenter/help/help",
+    "pages/ucenter/helpInfo/helpInfo",
+    "pages/auth/newuser/newuser",
+    "pages/group/group",
+    "pages/groupDetail/groupDetail",
+    "pages/shopping/coupon/coupon",
+    "pages/ucenter/share/share",
+    "pages/activity/activity",
+    "pages/goodsActivity/goodsActivity",
+    "pages/ucenter/group/group",
+    "pages/joinGroup/joinGroup",
+    "pages/shopping/groupcheck/groupcheck",
+    "pages/map/map",
+    "pages/auth/btnAuth/btnAuth",
+    "pages/ucenter/wuliu/wuliu",
+    "pages/ucenter/wuliuwebview/wuliuwebview",
+    "pages/ucenter/idCard/idCard",
+    "pages/ucenter/applyRefund/applyRefund"
+  ],
+  "window": {
+    "backgroundTextStyle": "dark",
+    "navigationBarBackgroundColor": "#fff",
+    "navigationBarTitleText": "中网国际跨境商城",
+    "navigationBarTextStyle": "black",
+    "enablePullDownRefresh": false
+  },
+  "tabBar": {
+    "backgroundColor": "#fafafa",
+    "borderStyle": "white",
+    "selectedColor": "#b4282d",
+    "color": "#666",
+    "list": [
+      {
+        "pagePath": "pages/index/index",
+        "iconPath": "static/images/ic_menu_choice_nor.png",
+        "selectedIconPath": "static/images/ic_menu_choice_pressed.png",
+        "text": "首页"
+      },
+      {
+        "pagePath": "pages/catalog/catalog",
+        "iconPath": "static/images/ic_menu_sort_nor.png",
+        "selectedIconPath": "static/images/ic_menu_sort_pressed.png",
+        "text": "分类"
+      },
+      {
+        "pagePath": "pages/cart/cart",
+        "iconPath": "static/images/ic_menu_shoping_nor.png",
+        "selectedIconPath": "static/images/ic_menu_shoping_pressed.png",
+        "text": "购物车"
+      },
+      {
+        "pagePath": "pages/ucenter/index/index",
+        "iconPath": "static/images/ic_menu_me_nor.png",
+        "selectedIconPath": "static/images/ic_menu_me_pressed.png",
+        "text": "我的"
+      }
+    ]
+  },
+  "networkTimeout": {
+    "request": 10000,
+    "downloadFile": 10000
+  },
+  "debug": true,
+  "permission":{
+    "scope.userLocation":{
+      "desc": "您的位置信息将用于小程序位置接口的效果展示"
+    }
+  }
+}

+ 508 - 0
wx-mall-hk/app.wxss

@@ -0,0 +1,508 @@
+/**app.wxss**/
+
+.container {
+  box-sizing: border-box;
+  background-color: #f4f4f4;
+  font-family: PingFangSC-Light, helvetica, 'Heiti SC';
+}
+
+view, image, text, navigator {
+  box-sizing: border-box;
+  padding: 0;
+  margin: 0;
+}
+
+view, text {
+  font-family: PingFangSC-Light, helvetica, 'Heiti SC';
+  font-size: 29rpx;
+  color: #333;
+}
+
+.arrow::after {
+  content: " ";
+  display: inline-block;
+  height: 6px;
+  width: 6px;
+  border-width: 2px 2px 0 0;
+  border-color: #666;
+  border-style: solid;
+  transform: matrix(0.71, 0.71, -0.71, 0.71, 0, 0);
+  position: absolute;
+  top: 50%;
+  margin-top: -5px;
+  right: -16px;
+}
+
+.arrow-down::after {
+  transform: matrix(0.71, 0.71, -0.71, 0.71, 0, 0) rotate(90deg);
+}
+
+.arrow-up::after {
+  transform: matrix(0.71, 0.71, -0.71, 0.71, 0, 0) rotate(-90deg);
+}
+
+.list-group {
+  margin-top: 0.6em;
+  background-color: #fff;
+  line-height: 1.41176471;
+  font-size: 28rpx;
+  overflow: hidden;
+  position: relative;
+}
+
+.list-group::before {
+  content: " ";
+  position: absolute;
+  left: 0;
+  top: 0;
+  right: 0;
+  height: 1px;
+  border-top: 1px solid #d9d9d9;
+  color: #d9d9d9;
+  transform-origin: 0 0;
+  transform: scaleY(0.5);
+}
+
+.list-group::after {
+  content: " ";
+  position: absolute;
+  left: 0;
+  bottom: 0;
+  right: 0;
+  height: 1px;
+  border-bottom: 1px solid #d9d9d9;
+  color: #d9d9d9;
+  transform-origin: 0 100%;
+  transform: scaleY(0.5);
+}
+
+.list-cell {
+  padding: 10px 15px;
+  position: relative;
+  display: flex;
+  align-items: center;
+}
+
+.list-cell:first-of-type::before {
+  display: none;
+}
+
+.list-cell::before {
+  content: " ";
+  position: absolute;
+  top: 0;
+  right: 0;
+  height: 1px;
+  border-top: 1px solid #d9d9d9;
+  color: #d9d9d9;
+  transform-origin: 0 0;
+  transform: scaleY(0.5);
+  left: 15px;
+}
+
+.list-cell-hd {
+  display: flex;
+  align-items: center;
+}
+
+.list-cell-bd {
+  flex: 1;
+}
+
+.list-cell-bd .list-label {
+  font-size: 24rpx;
+}
+
+.list-cell-bd .list-label-desc {
+  font-size: 24rpx;
+  color: #9b9b9b;
+  padding-top: 5px;
+}
+
+.list-cell-ft {
+  padding-right: 13px;
+  position: relative;
+  text-align: right;
+  color: #999;
+}
+.list-cell-ft .txt {
+  font-size: 24rpx;
+}
+
+.list-cell-ft.router::after {
+  content: " ";
+  display: inline-block;
+  height: 6px;
+  width: 6px;
+  border-width: 2px 2px 0 0;
+  border-color: #c8c8cd;
+  border-style: solid;
+  transform: matrix(0.71, 0.71, -0.71, 0.71, 0, 0);
+  top: -2px;
+  position: absolute;
+  top: 50%;
+  margin-top: -4px;
+  right: 2px;
+}
+
+.modal-wrap {
+  position: fixed;
+  width: 100%;
+  height: 100%;
+  z-index: 500;
+  top: 0;
+  left: 0;
+  background-color: rgba(0, 0, 0, 0.5);
+}
+
+.x-close {
+  position: relative;
+  display: inline-block;
+  vertical-align: middle;
+  color: #999;
+  width: 48rpx;
+  height: 48rpx;
+}
+
+.x-close::before, .x-close::after {
+  content: '';
+  position: absolute;
+  left: 0;
+  top: 11px;
+  width: 24px;
+  height: 1px;
+  background-color: currentColor;
+  transform: rotate(-45deg);
+}
+
+.x-close::after {
+  transform: rotate(45deg);
+}
+
+.no-data {
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+  padding-top: 150rpx;
+}
+
+.no-data image {
+  width: 250rpx;
+  height: 250rpx;
+}
+
+.no-data text {
+  text-align: center;
+  margin-top: 50rpx;
+  color: #999;
+}
+
+/* 底部购物车 */
+
+.cart-panel {
+  display: flex;
+  height: 80rpx;
+  width: 700rpx;
+  line-height: 80rpx;
+  border-radius: 40rpx;
+  background-color: #4d4d4e;
+  position: fixed;
+  bottom: 20rpx;
+  z-index: 499;
+  left: 50%;
+  margin-left: -350rpx;
+}
+
+.cart-panel .cart-icon {
+  width: 80rpx;
+  height: 80rpx;
+  background-color: #343434;
+  border-radius: 50%;
+  position: relative;
+}
+
+.cart-panel .cart-icon navigator {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.cart-panel .cart-icon .cart-num {
+  position: absolute;
+  width: 30rpx;
+  height: 30rpx;
+  line-height: 30rpx;
+  text-align: center;
+  top: -10rpx;
+  right: -10rpx;
+  background-color: #ff8902;
+  color: #fff;
+  border-radius: 50%;
+  font-size: 20rpx;
+}
+
+.cart-panel .cart-icon image {
+  width: 40rpx;
+  height: 40rpx;
+}
+
+.cart-panel .cart-body {
+  flex: 1;
+  color: #fff;
+  padding-left: 20rpx;
+}
+
+.cart-panel .cart-pay {
+  width: 200rpx;
+  color: #fff;
+  background-color: #ff8902;
+  border-radius: 0 40rpx 40rpx 0;
+  text-align: center;
+}
+
+/* 快捷导航 */
+
+.fast-nav {
+  position: fixed;
+  right: 20rpx;
+  bottom: 180rpx;
+  z-index: 9999;
+  display: flex;
+  flex-direction: column;
+  align-items: flex-end;
+}
+
+.fast-nav .nav {
+  width: 100rpx;
+  height: 100rpx;
+  border-radius: 50%;
+  background-color: #424242;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  margin-top: 20rpx;
+  opacity: 0.6;
+}
+
+.fast-nav .nav text {
+  color: #fff;
+  font-size: 20rpx;
+}
+
+.fast-nav .contact {
+  width: 100rpx;
+  height: 100rpx;
+  border-radius: 50%;
+  background-color: #19c322;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  opacity: 0.6;
+}
+
+.fast-nav .nav-list .nav-item {
+  height: 80rpx;
+  width: 200rpx;
+  margin-bottom: 20rpx;
+  display: flex;
+  justify-content: flex-end;
+  align-items: center;
+}
+
+.fast-nav .nav-list .nav-item .nav-text {
+  line-height: 80rpx;
+  text-align: center;
+  padding-right: 20rpx;
+  color: #fff;
+}
+
+.fast-nav .nav-list .nav-item .nav-cell {
+  height: 80rpx;
+  width: 80rpx;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  background-color: #fff;
+  border-radius: 50%;
+}
+
+.fast-nav .nav-list .nav-item .nav-cell image {
+  height: 40rpx;
+  width: 40rpx;
+}
+
+.fast-nav .close {
+  width: 100rpx;
+  height: 100rpx;
+  border-radius: 50%;
+  color: #fff;
+  background-color: #ff5778;
+  font-size: 50rpx;
+  text-align: center;
+  line-height: 100rpx;
+}
+
+.wx-contact-button-wrapper {
+  background-image: url(http://120.76.26.84:80/group1/M00/00/01/rBJEdVvr1iWAacIoAAABhZLlqls595.png) !important;
+  margin: 10rpx 0;
+}
+
+.fast-nav .contact text {
+  color: #fff;
+  font-size: 20rpx;
+}
+
+/*商品列表*/
+
+.topic-list {
+  width: 750rpx;
+  height: 100%;
+  overflow: hidden;
+  background: #f4f4f4;
+}
+
+.topic-list .item {
+  width: 100%;
+  height: auto;
+  overflow: hidden;
+  background: #fff;
+  margin-bottom: 10rpx;
+}
+
+.topic-list .item .imgtt {
+  width: 100%;
+  height: 100vw;
+  position: relative;
+}
+
+.topic-list .item .imgtt .img {
+  width: 100%;
+  height: 100vw;
+  position:  relative;
+  overflow: hidden;
+}
+
+.topic-list .item .imgtt .imgline {
+  position: absolute;
+  left: 0px;
+  bottom: 0px;
+  width: 100%;
+  background: #333;
+  opacity: 0.6;
+  height: 80rpx;
+  color: #fff;
+}
+
+.topic-list .item .imgtt .imgline .priceInfo {
+  float: left;
+  text-align: left;
+  height: 33rpx;
+  line-height: 38rpx;
+  overflow: hidden;
+  color: #fff;
+  font-size: 33rpx;
+  margin-top: 25rpx;
+  padding-left: 33rpx;
+}
+
+.topic-list .item .imgtt .imgline .priceInfo  .price {
+  font-size: 33rpx;
+  color: #fff;
+}
+
+.topic-list .item .imgtt .imgline .priceInfo .orgPrice {
+  font-size: 24rpx;
+  margin-left: 10rpx;
+  color: #fff;
+}
+
+.topic-list .item .imgtt .imgline .right {
+  float: right;
+  color: #fff;
+}
+
+.topic-list .item .imgtt .imgline .btn {
+  height: 80rpx;
+  line-height: 80rpx;
+  text-align: center;
+  font-size: 28rpx;
+  color: #fff;
+  background: #b4282d;
+  border-radius: 0px;
+}
+
+.topic-list .info {
+  width: 100%;
+  height: 150rpx;
+  overflow: hidden;
+}
+
+.topic-list .title {
+  display: block;
+  text-align: center;
+  width: 100%;
+  height: 33rpx;
+  line-height: 35rpx;
+  color: #333;
+  overflow: hidden;
+  font-size: 35rpx;
+  margin-top: 30rpx;
+}
+
+.topic-list .desc {
+  display: block;
+  text-align: center;
+  position: relative;
+  width: auto;
+  height: 24rpx;
+  line-height: 24rpx;
+  overflow: hidden;
+  color: #999;
+  font-size: 24rpx;
+  margin-top: 16rpx;
+  margin-bottom: 12rpx;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  padding: 0 24rpx;
+}
+
+.page {
+  width: 750rpx;
+  height: 108rpx;
+  background: #fff;
+  margin-bottom: 20rpx;
+}
+
+.page view {
+  height: 108rpx;
+  width: 50%;
+  float: left;
+  font-size: 29rpx;
+  color: #333;
+  text-align: center;
+  line-height: 108rpx;
+}
+
+.page .prev {
+  border-right: 1px solid #d9d9d9;
+}
+
+.page .disabled {
+  color: #ccc;
+}
+
+.line-through {
+  text-decoration: line-through;
+}
+::-webkit-scrollbar {
+  width: 5px;
+  background-color: #f5f5f5;
+}
+
+::-webkit-scrollbar-thumb {
+  background-color: #999;
+}

+ 142 - 0
wx-mall-hk/config/api.js

@@ -0,0 +1,142 @@
+//开发环境
+//var NewApiRootUrl = 'http://localhost:8080/api/';
+//var NewApiRootUrl = 'http://192.168.1.138:8080/api/';
+var NewApiRootUrl = 'http://qhdswl.f3322.net:9001/platform-framework/api/';//hyq
+// var NewApiRootUrl = 'http://qhdswl.f3322.net:9003/api/';
+
+//测试环境
+// var NewApiRootUrl = 'https://mp-test.k1net.cn/api/';
+
+//生产环境
+// var NewApiRootUrl = 'https://mp.k1net.cn/api/';
+//中网国际生产环境
+// var NewApiRootUrl = 'https://easymp.k1net.cn/api/';
+
+module.exports = {
+
+    // tab
+    IndexUrl: NewApiRootUrl + 'index/index', //首页数据接口
+    CatalogList: NewApiRootUrl + 'catalog/index',  //分类目录全部分类数据接口
+    CatalogCurrent: NewApiRootUrl + 'catalog/current',  //分类目录当前分类数据接口
+    CatalogProductList: NewApiRootUrl + 'goods/productlist',  //分类目录当前产品
+    // 权限
+    AuthLoginByWeixin: NewApiRootUrl + 'auth/login_by_weixin', //微信登录
+    ChooseStoreId: NewApiRootUrl + 'auth/chooseStoreId', //选择门店Id
+    NearbyList: NewApiRootUrl + 'auth/nearbyList',//根据经纬度获取配送范围内的门店
+    StoreByCity: NewApiRootUrl + 'auth/storeListByCity',//获取地市的门店
+    //
+    ActivityList: NewApiRootUrl + 'activity/list', //活动列表
+
+    GoodsSku: NewApiRootUrl + 'goods/sku',  //获取sku信息
+    GoodsCount: NewApiRootUrl + 'goods/count',  //统计商品总数
+    GoodsList: NewApiRootUrl + 'goods/list',  //获得商品列表
+    GoodsCategory: NewApiRootUrl + 'goods/category',  //获得分类数据
+    GoodsDetail: NewApiRootUrl + 'goods/detail',  //获得商品的详情
+    GoodsHot: NewApiRootUrl + 'goods/hot',  //热门
+    GoodsRelated: NewApiRootUrl + 'goods/related',  //商品详情页的关联商品(大家都在看)
+    GoodsCrashList: NewApiRootUrl + 'goodscrash/list',  //搭配减价
+    GoodsTransferCoupon: NewApiRootUrl + 'goods/transferCoupon',  //转发获取优惠券
+    GoodsGallery: NewApiRootUrl + 'goods/goodsGallery',  //商品画廊
+
+    HotGoodsList: NewApiRootUrl + 'goods/hotGoodsList',  //疯狂折扣商品列表
+
+    BrandList: NewApiRootUrl + 'brand/list',  //品牌列表
+    BrandDetail: NewApiRootUrl + 'brand/detail',  //品牌详情
+
+    CartList: NewApiRootUrl + 'cart/index', //获取购物车的数据
+    CartAdd: NewApiRootUrl + 'cart/add', // 添加商品到购物车
+    CartAddByOrder: NewApiRootUrl + 'cart/addByOrder', // 根据订单id添加商品到购物车
+    CartMinus: NewApiRootUrl + 'cart/minus', // 删除购物车
+    CartUpdate: NewApiRootUrl + 'cart/update', // 更新购物车的商品
+    CartDelete: NewApiRootUrl + 'cart/delete', // 删除购物车的商品
+    CartChecked: NewApiRootUrl + 'cart/checked', // 选择或取消选择商品
+    CartGoodsCount: NewApiRootUrl + 'cart/goodscount', // 获取购物车商品件数
+    CartCheckout: NewApiRootUrl + 'cart/checkout', // 下单前信息确认
+    CartCouponList: NewApiRootUrl + 'cart/checkedCouponList', // 选择用户可用优惠券
+    GetFootCart: NewApiRootUrl + 'cart/getFootCart', // 底部购物车显示
+    deleteValidCart: NewApiRootUrl + 'cart/deleteValidCart', //清空购物车失效商品
+
+    OrderSubmit: NewApiRootUrl + 'order/submit', // 提交订单
+    PayPrepayId: NewApiRootUrl + 'pay/pay_prepay', //获取微信统一下单prepay_id
+    Payorder: NewApiRootUrl + 'pay/pingan/payorder', //获取平安支付
+    MpconfigQuery: NewApiRootUrl + 'pay/pingan/mpconfig/setKey', //获取平安支付配置
+    refund: NewApiRootUrl + 'pay/refund', //订单申请退款
+  
+    CheckStore: NewApiRootUrl + 'address/checkStore', //下单前,门店校验
+
+    CollectList: NewApiRootUrl + 'collect/list',  //收藏列表
+    CollectAddOrDelete: NewApiRootUrl + 'collect/addordelete',  //添加或取消收藏
+
+    CommentList: NewApiRootUrl + 'comment/list',  //评论列表
+    CommentCount: NewApiRootUrl + 'comment/count',  //评论总数
+    CommentPost: NewApiRootUrl + 'comment/post',   //发表评论
+
+    TopicList: NewApiRootUrl + 'topic/list',  //专题列表
+    TopicDetail: NewApiRootUrl + 'topic/detail',  //专题详情
+    TopicRelated: NewApiRootUrl + 'topic/related',  //相关专题
+
+    SearchIndex: NewApiRootUrl + 'search/index',  //搜索页面数据
+    SearchResult: NewApiRootUrl + 'search/result',  //搜索数据
+    SearchHelper: NewApiRootUrl + 'search/helper',  //搜索帮助
+    SearchClearHistory: NewApiRootUrl + 'search/clearhistory',  //搜索帮助
+
+    AddressList: NewApiRootUrl + 'address/list',  //收货地址列表
+    AddressDetail: NewApiRootUrl + 'address/detail',  //收货地址详情
+    AddressSave: NewApiRootUrl + 'address/save',  //保存收货地址
+    AddressDelete: NewApiRootUrl + 'address/delete',  //保存收货地址
+    AddressSync: NewApiRootUrl + 'address/syncAddress',  //同步小程序地址
+
+    FeedbackSave: NewApiRootUrl + 'feedback/save',//反馈
+    RegionIdsByNames: NewApiRootUrl + 'region/regionIdsByNames',  //地市名翻译
+    RegionList: NewApiRootUrl + 'region/list',  //获取区域列表
+
+    OrderList: NewApiRootUrl + 'order/list',  //订单列表
+    OrderDetail: NewApiRootUrl + 'order/detail',  //订单详情
+    OrderDetailList: NewApiRootUrl + 'order/detailList',  //多条订单详情
+    OrderCancel: NewApiRootUrl + 'order/cancelOrder',  //取消订单
+    OrderConfirm: NewApiRootUrl + 'order/confirmOrder',  //确认收货
+
+    FootprintList: NewApiRootUrl + 'footprint/list',  //足迹列表
+    FootprintDelete: NewApiRootUrl + 'footprint/delete', //删除足迹
+    ShareList: NewApiRootUrl + 'footprint/sharelist', //
+
+    footbackSave: NewApiRootUrl + 'footprint/delete',  //会员反馈
+
+    GuessFootprintList: NewApiRootUrl + 'footprint/glist',  //足迹列表
+
+    EnableActivity: NewApiRootUrl + 'coupon/enableActivity', //获取活动弹出框
+    newUserCoupn: NewApiRootUrl + 'coupon/newuser',  //新用户领取券
+    CouponList: NewApiRootUrl + 'coupon/list',  //个人优惠券列表
+    CouponExchange: NewApiRootUrl + 'coupon/exchange',  //个人优惠券列表
+    CouponTransActivit: NewApiRootUrl + 'coupon/transActivit',  //转发优惠券
+    checkActivit: NewApiRootUrl + 'coupon/checkActivit',  //校验是否领取优惠券
+
+    smscodeSend: NewApiRootUrl + 'user/smscode',  //发送短信
+
+    GroupList: NewApiRootUrl + 'group/list',  //团购列表
+    GroupDetail: NewApiRootUrl + 'group/info',  //团购详情
+    GroupOpenList: NewApiRootUrl + 'groupopen/list',  //拼团列表
+    GroupOpenMyList: NewApiRootUrl + 'groupopen/myList',  //我的拼团列表
+    GroupCheckInfo: NewApiRootUrl + 'groupopen/groupcheck',  //拼团订单check
+
+    OpenGroup: NewApiRootUrl + 'groupopen/openGroup',  //单独拼团
+    OpenInfo: NewApiRootUrl + 'groupopen/info',  //开团详情
+    AttendGroup: NewApiRootUrl + 'groupopen/attendGroup',  //参与拼团
+    AttendList: NewApiRootUrl + 'groupopen/attendList',  //参与拼团的人
+    GroupOpenDetail: NewApiRootUrl + 'groupopen/groupOpenDetail',  //根据开团明细查询开团详情
+
+    HelpTypeList: NewApiRootUrl + 'helpissue/typeList',  //查看帮助类型列表
+    HelpIssueList: NewApiRootUrl + 'helpissue/issueList',  //查看问题列表
+
+    UploadFileURL: NewApiRootUrl + 'upload/upload',  //图片上传
+    getCurUser: NewApiRootUrl + 'user/getCurUser',  //获取当前登录人信息
+
+    UcenterIndex: NewApiRootUrl + 'index/ucenterIndex',  //个人中心首页
+
+  GetLogistics: NewApiRootUrl + 'order/getLogistics',  //查询物流信息
+  getCheckedDataByType: NewApiRootUrl + 'cart/getCheckedDataByType',  //校验该业务类型的购物车数据
+  idCardRealName: NewApiRootUrl + 'index/idCardRealName', //身份证实名
+  saveApplyRefund: NewApiRootUrl + 'order/saveApplyRefund', //申请维权
+  updateLoginUser: NewApiRootUrl + 'auth/updateLoginUser',
+  GlobalPayorder: NewApiRootUrl + '/global/pay/pay_prepay',
+};

+ 462 - 0
wx-mall-hk/lib/qqmap/qqmap-wx-jssdk.js

@@ -0,0 +1,462 @@
+/**
+ * 微信小程序JavaScriptSDK
+ * 
+ * @version 1.0
+ * @date 2017-01-10
+ * @author jaysonzhou@tencent.com
+ */
+
+var ERROR_CONF = {
+    KEY_ERR: 311,
+    KEY_ERR_MSG: 'key格式错误',
+    PARAM_ERR: 310,
+    PARAM_ERR_MSG: '请求参数信息有误',
+    SYSTEM_ERR: 600,
+    SYSTEM_ERR_MSG: '系统错误',
+    WX_ERR_CODE: 1000,
+    WX_OK_CODE: 200
+};
+var BASE_URL = 'https://apis.map.qq.com/ws/';
+var URL_SEARCH = BASE_URL + 'place/v1/search';
+var URL_SUGGESTION = BASE_URL + 'place/v1/suggestion';
+var URL_GET_GEOCODER = BASE_URL + 'geocoder/v1/';
+var URL_CITY_LIST = BASE_URL + 'district/v1/list';
+var URL_AREA_LIST = BASE_URL + 'district/v1/getchildren';
+var URL_DISTANCE = BASE_URL + 'distance/v1/';
+var Utils = {
+    /**
+     * 得到终点query字符串
+     * @param {Array|String} 检索数据
+     */
+    location2query(data) {
+        if (typeof data == 'string') {
+            return data;
+        }
+        var query = '';
+        for (var i = 0; i < data.length; i++) {
+            var d = data[i];
+            if (!!query) {
+                query += ';';
+            }
+            if (d.location) {
+                query = query + d.location.lat + ',' + d.location.lng;
+            }
+            if (d.latitude && d.longitude) {
+                query = query + d.latitude + ',' + d.longitude;
+            }
+        }
+        return query;
+    },
+
+    /**
+     * 使用微信接口进行定位
+     */
+    getWXLocation(success, fail, complete) {
+        wx.getLocation({
+            type: 'gcj02',
+            success: success,
+            fail: fail,
+            complete: complete
+        });
+    },
+
+    /**
+     * 获取location参数
+     */
+    getLocationParam(location) {
+        if (typeof location == 'string') {
+            var locationArr = location.split(',');
+            if (locationArr.length === 2) {
+                location = {
+                    latitude: location.split(',')[0],
+                    longitude: location.split(',')[1]
+                };
+            } else {
+                location = {};
+            }
+        }
+        return location;
+    },
+
+    /**
+     * 回调函数默认处理
+     */
+    polyfillParam(param) {
+        param.success = param.success || function () { };
+        param.fail = param.fail || function () { };
+        param.complete = param.complete || function () { };
+    },
+
+    /**
+     * 验证param对应的key值是否为空
+     * 
+     * @param {Object} param 接口参数
+     * @param {String} key 对应参数的key
+     */
+    checkParamKeyEmpty(param, key) {
+        if (!param[key]) {
+            var errconf = this.buildErrorConfig(ERROR_CONF.PARAM_ERR, ERROR_CONF.PARAM_ERR_MSG + key +'参数格式有误');
+            param.fail(errconf);
+            param.complete(errconf);
+            return true;
+        }
+        return false;
+    },
+
+    /**
+     * 验证参数中是否存在检索词keyword
+     * 
+     * @param {Object} param 接口参数
+     */
+    checkKeyword(param){
+        return !this.checkParamKeyEmpty(param, 'keyword');
+    },
+
+    /**
+     * 验证location值
+     * 
+     * @param {Object} param 接口参数
+     */
+    checkLocation(param) {
+        var location = this.getLocationParam(param.location);
+        if (!location || !location.latitude || !location.longitude) {
+            var errconf = this.buildErrorConfig(ERROR_CONF.PARAM_ERR, ERROR_CONF.PARAM_ERR_MSG + ' location参数格式有误')
+            param.fail(errconf);
+            param.complete(errconf);
+            return false;
+        }
+        return true;
+    },
+
+    /**
+     * 构造错误数据结构
+     * @param {Number} errCode 错误码
+     * @param {Number} errMsg 错误描述
+     */
+    buildErrorConfig(errCode, errMsg) {
+        return {
+            status: errCode,
+            message: errMsg
+        };
+    },
+
+    /**
+     * 构造微信请求参数,公共属性处理
+     * 
+     * @param {Object} param 接口参数
+     * @param {Object} param 配置项
+     */
+    buildWxRequestConfig(param, options) {
+        var that = this;
+        options.header = { "content-type": "application/json" };
+        options.method = 'GET';
+        options.success = function (res) {
+            var data = res.data;
+            if (data.status === 0) {
+                param.success(data);
+            } else {
+                param.fail(data);
+            }
+        };
+        options.fail = function (res) {
+            res.statusCode = ERROR_CONF.WX_ERR_CODE;
+            param.fail(that.buildErrorConfig(ERROR_CONF.WX_ERR_CODE, result.errMsg));
+        };
+        options.complete = function (res) {
+            var statusCode = +res.statusCode;
+            switch(statusCode) {
+                case ERROR_CONF.WX_ERR_CODE: {
+                    param.complete(that.buildErrorConfig(ERROR_CONF.WX_ERR_CODE, res.errMsg));
+                    break;
+                }
+                case ERROR_CONF.WX_OK_CODE: {
+                    var data = res.data;
+                    if (data.status === 0) {
+                        param.complete(data);
+                    } else {
+                        param.complete(that.buildErrorConfig(data.status, data.message));
+                    }
+                    break;
+                }
+                default:{
+                    param.complete(that.buildErrorConfig(ERROR_CONF.SYSTEM_ERR, ERROR_CONF.SYSTEM_ERR_MSG));
+                }
+
+            }
+        }
+        return options;
+    },
+
+    /**
+     * 处理用户参数是否传入坐标进行不同的处理
+     */
+    locationProcess(param, locationsuccess, locationfail, locationcomplete) {
+        var that = this;
+        locationfail = locationfail || function (res) {
+            res.statusCode = ERROR_CONF.WX_ERR_CODE;
+            param.fail(that.buildErrorConfig(ERROR_CONF.WX_ERR_CODE, res.errMsg));
+        };
+        locationcomplete = locationcomplete || function (res) {
+            if (res.statusCode == ERROR_CONF.WX_ERR_CODE) {
+                param.complete(that.buildErrorConfig(ERROR_CONF.WX_ERR_CODE, res.errMsg));
+            }
+        };
+        if (!param.location) {
+            that.getWXLocation(locationsuccess, locationfail, locationcomplete);
+        } else if (that.checkLocation(param)) {
+            var location = Utils.getLocationParam(param.location);
+            locationsuccess(location);
+        }
+    }
+}
+
+
+class QQMapWX {
+
+    /**
+     * 构造函数
+     * 
+     * @param {Object} options 接口参数,key 为必选参数
+     */
+    constructor(options) {
+        if (!options.key) {
+            throw Error('key值不能为空');
+        }
+        this.key = options.key;
+    }
+
+    /**
+     * POI周边检索
+     *
+     * @param {Object} options 接口参数对象
+     * 
+     * 参数对象结构可以参考
+     * @see http://lbs.qq.com/webservice_v1/guide-search.html
+     */
+    search(options) {
+        var that = this;
+        options = options || {};
+
+        Utils.polyfillParam(options);
+
+        if (!Utils.checkKeyword(options)) {
+            return;
+        }
+
+        var requestParam = {
+            keyword: options.keyword,
+            orderby: options.orderby || '_distance',
+            page_size: options.page_size || 10,
+            page_index: options.page_index || 1,
+            output: 'json',
+            key: that.key
+        };
+
+        if (options.address_format) {
+            requestParam.address_format = options.address_format;
+        }
+
+        if (options.filter) {
+            requestParam.filter = options.filter;
+        }
+
+        var distance = options.distance || "1000";
+        var auto_extend = options.auto_extend || 1;
+
+        var locationsuccess = function (result) {
+            requestParam.boundary = "nearby(" + result.latitude + "," + result.longitude + "," + distance + "," + auto_extend +")";
+            wx.request(Utils.buildWxRequestConfig(options, {
+                url: URL_SEARCH,
+                data: requestParam
+            }));
+        }
+        Utils.locationProcess(options, locationsuccess);
+    }
+
+    /**
+     * sug模糊检索
+     *
+     * @param {Object} options 接口参数对象
+     * 
+     * 参数对象结构可以参考
+     * http://lbs.qq.com/webservice_v1/guide-suggestion.html
+     */
+    getSuggestion(options) {
+        var that = this;
+        options = options || {};
+        Utils.polyfillParam(options);
+
+        if (!Utils.checkKeyword(options)) {
+            return;
+        }
+
+        var requestParam = {
+            keyword: options.keyword,
+            region: options.region || '全国',
+            region_fix: options.region_fix || 0,
+            policy: options.policy || 0,
+            output: 'json',
+            key: that.key
+        };
+        wx.request(Utils.buildWxRequestConfig(options, {
+            url: URL_SUGGESTION,
+            data: requestParam
+        }));
+    }
+
+    /**
+     * 逆地址解析
+     *
+     * @param {Object} options 接口参数对象
+     * 
+     * 请求参数结构可以参考
+     * http://lbs.qq.com/webservice_v1/guide-gcoder.html
+     */
+    reverseGeocoder(options) {
+        var that = this;
+        options = options || {};
+        Utils.polyfillParam(options);
+        var requestParam = {
+            coord_type: options.coord_type || 5,
+            get_poi: options.get_poi || 0,
+            output: 'json',
+            key: that.key
+        };
+        if (options.poi_options) {
+            requestParam.poi_options = options.poi_options
+        }
+
+        var locationsuccess = function (result) {
+            requestParam.location = result.latitude + ',' + result.longitude;
+            wx.request(Utils.buildWxRequestConfig(options, {
+                url: URL_GET_GEOCODER,
+                data: requestParam
+            }));
+        };
+        Utils.locationProcess(options, locationsuccess);
+    }
+
+    /**
+     * 地址解析
+     *
+     * @param {Object} options 接口参数对象
+     * 
+     * 请求参数结构可以参考
+     * http://lbs.qq.com/webservice_v1/guide-geocoder.html
+     */
+    geocoder(options) {
+        var that = this;
+        options = options || {};
+        Utils.polyfillParam(options);
+
+        if (Utils.checkParamKeyEmpty(options, 'address')) {
+            return;
+        }
+
+        var requestParam = {
+            address: options.address,
+            output: 'json',
+            key: that.key
+        };
+
+        wx.request(Utils.buildWxRequestConfig(options, {
+            url: URL_GET_GEOCODER,
+            data: requestParam
+        }));
+    }
+
+
+    /**
+     * 获取城市列表
+     *
+     * @param {Object} options 接口参数对象
+     * 
+     * 请求参数结构可以参考
+     * http://lbs.qq.com/webservice_v1/guide-region.html
+     */
+    getCityList(options) {
+        var that = this;
+        options = options || {};
+        Utils.polyfillParam(options);
+        var requestParam = {
+            output: 'json',
+            key: that.key
+        };
+
+        wx.request(Utils.buildWxRequestConfig(options, {
+            url: URL_CITY_LIST,
+            data: requestParam
+        }));
+    }
+
+    /**
+     * 获取对应城市ID的区县列表
+     *
+     * @param {Object} options 接口参数对象
+     * 
+     * 请求参数结构可以参考
+     * http://lbs.qq.com/webservice_v1/guide-region.html
+     */
+    getDistrictByCityId(options) {
+        var that = this;
+        options = options || {};
+        Utils.polyfillParam(options);
+
+        if (Utils.checkParamKeyEmpty(options, 'id')) {
+            return;
+        }
+
+        var requestParam = {
+            id: options.id || '',
+            output: 'json',
+            key: that.key
+        };
+
+        wx.request(Utils.buildWxRequestConfig(options, {
+            url: URL_AREA_LIST,
+            data: requestParam
+        }));
+    }
+
+    /**
+     * 用于单起点到多终点的路线距离(非直线距离)计算:
+     * 支持两种距离计算方式:步行和驾车。
+     * 起点到终点最大限制直线距离10公里。
+     *
+     * @param {Object} options 接口参数对象
+     * 
+     * 请求参数结构可以参考
+     * http://lbs.qq.com/webservice_v1/guide-distance.html
+     */
+    calculateDistance(options) {
+        var that = this;
+        options = options || {};
+        Utils.polyfillParam(options);
+
+        if (Utils.checkParamKeyEmpty(options, 'to')) {
+            return;
+        }
+
+        var requestParam = {
+            mode: options.mode || 'walking',
+            to: Utils.location2query(options.to),
+            output: 'json',
+            key: that.key
+        };
+
+        var locationsuccess = function (result) {
+            requestParam.from = result.latitude + ',' + result.longitude;
+            wx.request(Utils.buildWxRequestConfig(options, {
+                url: URL_DISTANCE,
+                data: requestParam
+            }));
+        }
+        if (options.from) {
+            options.location = options.from;
+        }
+        
+        Utils.locationProcess(options, locationsuccess);
+    }
+}
+
+module.exports = QQMapWX;

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 0 - 0
wx-mall-hk/lib/qqmap/qqmap-wx-jssdk.min.js


+ 244 - 0
wx-mall-hk/lib/wxParse/html2json.js

@@ -0,0 +1,244 @@
+/**
+ * author: Di (微信小程序开发工程师)
+ * organization: WeAppDev(微信小程序开发论坛)(http://weappdev.com)
+ *               垂直微信小程序开发交流社区
+ * 
+ * github地址: https://github.com/icindy/wxParse
+ * 
+ * for: 微信小程序富文本解析
+ * detail : http://weappdev.com/t/wxparse-alpha0-1-html-markdown/184
+ */
+
+var __placeImgeUrlHttps = "https";
+var __emojisReg = '';
+var __emojisBaseSrc = '';
+var __emojis = {};
+var wxDiscode = require('wxDiscode.js');
+var HTMLParser = require('htmlparser.js');
+// Empty Elements - HTML 5
+var empty = makeMap("area,base,basefont,br,col,frame,hr,img,input,link,meta,param,embed,command,keygen,source,track,wbr");
+// Block Elements - HTML 5
+var block = makeMap("br,a,code,address,article,applet,aside,audio,blockquote,button,canvas,center,dd,del,dir,div,dl,dt,fieldset,figcaption,figure,footer,form,frameset,h1,h2,h3,h4,h5,h6,header,hgroup,hr,iframe,ins,isindex,li,map,menu,noframes,noscript,object,ol,output,p,pre,section,script,table,tbody,td,tfoot,th,thead,tr,ul,video");
+
+// Inline Elements - HTML 5
+var inline = makeMap("abbr,acronym,applet,b,basefont,bdo,big,button,cite,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var");
+
+// Elements that you can, intentionally, leave open
+// (and which close themselves)
+var closeSelf = makeMap("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr");
+
+// Attributes that have their values filled in disabled="disabled"
+var fillAttrs = makeMap("checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected");
+
+// Special Elements (can contain anything)
+var special = makeMap("wxxxcode-style,script,style,view,scroll-view,block");
+function makeMap(str) {
+    var obj = {}, items = str.split(",");
+    for (var i = 0; i < items.length; i++)
+        obj[items[i]] = true;
+    return obj;
+}
+
+function q(v) {
+    return '"' + v + '"';
+}
+
+function removeDOCTYPE(html) {
+    return html
+        .replace(/<\?xml.*\?>\n/, '')
+        .replace(/<!doctype.*\>\n/, '')
+        .replace(/<!DOCTYPE.*\>\n/, '');
+}
+
+
+function html2json(html, bindName) {
+    //处理字符串
+    html = removeDOCTYPE(html);
+    html = wxDiscode.strDiscode(html);
+    //生成node节点
+    var bufArray = [];
+    var results = {
+        node: bindName,
+        nodes: [],
+        images:[],
+        imageUrls:[]
+    };
+    HTMLParser(html, {
+        start: function (tag, attrs, unary) {
+            //debug(tag, attrs, unary);
+            // node for this element
+            var node = {
+                node: 'element',
+                tag: tag,
+            };
+
+            if (block[tag]) {
+                node.tagType = "block";
+            } else if (inline[tag]) {
+                node.tagType = "inline";
+            } else if (closeSelf[tag]) {
+                node.tagType = "closeSelf";
+            }
+
+            if (attrs.length !== 0) {
+                node.attr = attrs.reduce(function (pre, attr) {
+                    var name = attr.name;
+                    var value = attr.value;
+                    if (name == 'class') {
+                        // console.dir(value);
+                        console.log(value)
+                        //  value = value.join("")
+                        node.classStr = value;
+                    }
+                    // has multi attibutes
+                    // make it array of attribute
+                    if (name == 'style') {
+                        // console.dir(value);
+                        console.log(value)
+                        //  value = value.join("")
+                        node.styleStr = value;
+                    }
+                    if (value.match(/ /)) {
+                        value = value.split(' ');
+                    }
+                    
+
+                    // if attr already exists
+                    // merge it
+                    if (pre[name]) {
+                        if (Array.isArray(pre[name])) {
+                            // already array, push to last
+                            pre[name].push(value);
+                        } else {
+                            // single value, make it array
+                            pre[name] = [pre[name], value];
+                        }
+                    } else {
+                        // not exist, put it
+                        pre[name] = value;
+                    }
+
+                    return pre;
+                }, {});
+            }
+
+            //对img添加额外数据
+            if (node.tag === 'img') {
+                node.imgIndex = results.images.length;
+                var imgUrl = node.attr.src;
+                imgUrl = wxDiscode.urlToHttpUrl(imgUrl, __placeImgeUrlHttps);
+                node.attr.src = imgUrl;
+                node.from = bindName;
+                results.images.push(node);
+                results.imageUrls.push(imgUrl);
+            }
+
+            if (unary) {
+                // if this tag dosen't have end tag
+                // like <img src="hoge.png"/>
+                // add to parents
+                var parent = bufArray[0] || results;
+                if (parent.nodes === undefined) {
+                    parent.nodes = [];
+                }
+                parent.nodes.push(node);
+            } else {
+                bufArray.unshift(node);
+            }
+        },
+        end: function (tag) {
+            //debug(tag);
+            // merge into parent tag
+            var node = bufArray.shift();
+            if (node.tag !== tag) console.error('invalid state: mismatch end tag');
+
+            if (bufArray.length === 0) {
+                results.nodes.push(node);
+            } else {
+                var parent = bufArray[0];
+                if (parent.nodes === undefined) {
+                    parent.nodes = [];
+                }
+                parent.nodes.push(node);
+            }
+        },
+        chars: function (text) {
+            //debug(text);
+            var node = {
+                node: 'text',
+                text: text,
+                textArray:transEmojiStr(text)
+            };
+            
+            if (bufArray.length === 0) {
+                results.nodes.push(node);
+            } else {
+                var parent = bufArray[0];
+                if (parent.nodes === undefined) {
+                    parent.nodes = [];
+                }
+                parent.nodes.push(node);
+            }
+        },
+        comment: function (text) {
+            //debug(text);
+            var node = {
+                node: 'comment',
+                text: text,
+            };
+            var parent = bufArray[0];
+            if (parent.nodes === undefined) {
+                parent.nodes = [];
+            }
+            parent.nodes.push(node);
+        },
+    });
+    return results;
+};
+
+function transEmojiStr(str){
+  // var eReg = new RegExp("["+__reg+' '+"]");
+//   str = str.replace(/\[([^\[\]]+)\]/g,':$1:')
+  
+  var emojiObjs = [];
+  //如果正则表达式为空
+  if(__emojisReg.length == 0 || !__emojis){
+      var emojiObj = {}
+      emojiObj.node = "text";
+      emojiObj.text = str;
+      array = [emojiObj];
+      return array;
+  }
+  //这个地方需要调整
+  str = str.replace(/\[([^\[\]]+)\]/g,':$1:')
+  var eReg = new RegExp("[:]");
+  var array = str.split(eReg);
+  for(var i = 0; i < array.length; i++){
+    var ele = array[i];
+    var emojiObj = {};
+    if(__emojis[ele]){
+      emojiObj.node = "element";
+      emojiObj.tag = "emoji";
+      emojiObj.text = __emojis[ele];
+      emojiObj.baseSrc= __emojisBaseSrc;
+    }else{
+      emojiObj.node = "text";
+      emojiObj.text = ele;
+    }
+    emojiObjs.push(emojiObj);
+  }
+  
+  return emojiObjs;
+}
+
+function emojisInit(reg='',baseSrc="/wxParse/emojis/",emojis){
+    __emojisReg = reg;
+    __emojisBaseSrc=baseSrc;
+    __emojis=emojis;
+}
+
+module.exports = {
+    html2json: html2json,
+    emojisInit:emojisInit
+};
+

+ 182 - 0
wx-mall-hk/lib/wxParse/htmlparser.js

@@ -0,0 +1,182 @@
+/**
+ * author: Di (微信小程序开发工程师)
+ * organization: WeAppDev(微信小程序开发论坛)(http://weappdev.com)
+ *               垂直微信小程序开发交流社区
+ * 
+ * github地址: https://github.com/icindy/wxParse
+ * 
+ * for: 微信小程序富文本解析
+ * detail : http://weappdev.com/t/wxparse-alpha0-1-html-markdown/184
+ */
+// Regular Expressions for parsing tags and attributes
+var startTag = /^<([-A-Za-z0-9_]+)((?:\s+[a-zA-Z_:][-a-zA-Z0-9_:.]*(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/,
+	endTag = /^<\/([-A-Za-z0-9_]+)[^>]*>/,
+	attr = /([a-zA-Z_:][-a-zA-Z0-9_:.]*)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g;
+
+// Empty Elements - HTML 5
+var empty = makeMap("area,base,basefont,br,col,frame,hr,img,input,link,meta,param,embed,command,keygen,source,track,wbr");
+
+// Block Elements - HTML 5
+var block = makeMap("a,address,code,article,applet,aside,audio,blockquote,button,canvas,center,dd,del,dir,div,dl,dt,fieldset,figcaption,figure,footer,form,frameset,h1,h2,h3,h4,h5,h6,header,hgroup,hr,iframe,ins,isindex,li,map,menu,noframes,noscript,object,ol,output,p,pre,section,script,table,tbody,td,tfoot,th,thead,tr,ul,video");
+
+// Inline Elements - HTML 5
+var inline = makeMap("abbr,acronym,applet,b,basefont,bdo,big,br,button,cite,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var");
+
+// Elements that you can, intentionally, leave open
+// (and which close themselves)
+var closeSelf = makeMap("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr");
+
+// Attributes that have their values filled in disabled="disabled"
+var fillAttrs = makeMap("checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected");
+
+// Special Elements (can contain anything)
+var special = makeMap("wxxxcode-style,script,style,view,scroll-view,block");
+
+function HTMLParser(html, handler) {
+	var index, chars, match, stack = [], last = html;
+	stack.last = function () {
+		return this[this.length - 1];
+	};
+
+	while (html) {
+		chars = true;
+
+		// Make sure we're not in a script or style element
+		if (!stack.last() || !special[stack.last()]) {
+
+			// Comment
+			if (html.indexOf("<!--") == 0) {
+				index = html.indexOf("-->");
+
+				if (index >= 0) {
+					if (handler.comment)
+						handler.comment(html.substring(4, index));
+					html = html.substring(index + 3);
+					chars = false;
+				}
+
+				// end tag
+			} else if (html.indexOf("</") == 0) {
+				match = html.match(endTag);
+
+				if (match) {
+					html = html.substring(match[0].length);
+					match[0].replace(endTag, parseEndTag);
+					chars = false;
+				}
+
+				// start tag
+			} else if (html.indexOf("<") == 0) {
+				match = html.match(startTag);
+
+				if (match) {
+					html = html.substring(match[0].length);
+					match[0].replace(startTag, parseStartTag);
+					chars = false;
+				}
+			}
+
+			if (chars) {
+				index = html.indexOf("<");
+
+				var text = index < 0 ? html : html.substring(0, index);
+				html = index < 0 ? "" : html.substring(index);
+
+				if (handler.chars)
+					handler.chars(text);
+			}
+
+		} else {
+
+			html = html.replace(new RegExp("([\\s\\S]*?)<\/" + stack.last() + "[^>]*>"), function (all, text) {
+				text = text.replace(/<!--([\s\S]*?)-->|<!\[CDATA\[([\s\S]*?)]]>/g, "$1$2");
+				if (handler.chars)
+					handler.chars(text);
+
+				return "";
+			});
+
+
+			parseEndTag("", stack.last());
+		}
+
+		if (html == last)
+			throw "Parse Error: " + html;
+		last = html;
+	}
+
+	// Clean up any remaining tags
+	parseEndTag();
+
+	function parseStartTag(tag, tagName, rest, unary) {
+		tagName = tagName.toLowerCase();
+
+		if (block[tagName]) {
+			while (stack.last() && inline[stack.last()]) {
+				parseEndTag("", stack.last());
+			}
+		}
+
+		if (closeSelf[tagName] && stack.last() == tagName) {
+			parseEndTag("", tagName);
+		}
+
+		unary = empty[tagName] || !!unary;
+
+		if (!unary)
+			stack.push(tagName);
+
+		if (handler.start) {
+			var attrs = [];
+
+			rest.replace(attr, function (match, name) {
+				var value = arguments[2] ? arguments[2] :
+					arguments[3] ? arguments[3] :
+						arguments[4] ? arguments[4] :
+							fillAttrs[name] ? name : "";
+
+				attrs.push({
+					name: name,
+					value: value,
+					escaped: value.replace(/(^|[^\\])"/g, '$1\\\"') //"
+				});
+			});
+
+			if (handler.start) {
+				handler.start(tagName, attrs, unary);
+			}
+
+		}
+	}
+
+	function parseEndTag(tag, tagName) {
+		// If no tag name is provided, clean shop
+		if (!tagName)
+			var pos = 0;
+
+		// Find the closest opened tag of the same type
+		else
+			for (var pos = stack.length - 1; pos >= 0; pos--)
+				if (stack[pos] == tagName)
+					break;
+
+		if (pos >= 0) {
+			// Close all the open elements, up the stack
+			for (var i = stack.length - 1; i >= pos; i--)
+				if (handler.end)
+					handler.end(stack[i]);
+
+			// Remove the open elements from the stack
+			stack.length = pos;
+		}
+	}
+};
+
+function makeMap(str) {
+	var obj = {}, items = str.split(",");
+	for (var i = 0; i < items.length; i++)
+		obj[items[i]] = true;
+	return obj;
+}
+
+module.exports = HTMLParser;

+ 2529 - 0
wx-mall-hk/lib/wxParse/showdown.js

@@ -0,0 +1,2529 @@
+/**
+ * author: Di (微信小程序开发工程师)
+ * organization: WeAppDev(微信小程序开发论坛)(http://weappdev.com)
+ *               垂直微信小程序开发交流社区
+ * 
+ * github地址: https://github.com/icindy/wxParse
+ * 
+ * for: 微信小程序富文本解析
+ * detail : http://weappdev.com/t/wxparse-alpha0-1-html-markdown/184
+ */
+
+function getDefaultOpts(simple) {
+  'use strict';
+
+  var defaultOptions = {
+    omitExtraWLInCodeBlocks: {
+      defaultValue: false,
+      describe: 'Omit the default extra whiteline added to code blocks',
+      type: 'boolean'
+    },
+    noHeaderId: {
+      defaultValue: false,
+      describe: 'Turn on/off generated header id',
+      type: 'boolean'
+    },
+    prefixHeaderId: {
+      defaultValue: false,
+      describe: 'Specify a prefix to generated header ids',
+      type: 'string'
+    },
+    headerLevelStart: {
+      defaultValue: false,
+      describe: 'The header blocks level start',
+      type: 'integer'
+    },
+    parseImgDimensions: {
+      defaultValue: false,
+      describe: 'Turn on/off image dimension parsing',
+      type: 'boolean'
+    },
+    simplifiedAutoLink: {
+      defaultValue: false,
+      describe: 'Turn on/off GFM autolink style',
+      type: 'boolean'
+    },
+    literalMidWordUnderscores: {
+      defaultValue: false,
+      describe: 'Parse midword underscores as literal underscores',
+      type: 'boolean'
+    },
+    strikethrough: {
+      defaultValue: false,
+      describe: 'Turn on/off strikethrough support',
+      type: 'boolean'
+    },
+    tables: {
+      defaultValue: false,
+      describe: 'Turn on/off tables support',
+      type: 'boolean'
+    },
+    tablesHeaderId: {
+      defaultValue: false,
+      describe: 'Add an id to table headers',
+      type: 'boolean'
+    },
+    ghCodeBlocks: {
+      defaultValue: true,
+      describe: 'Turn on/off GFM fenced code blocks support',
+      type: 'boolean'
+    },
+    tasklists: {
+      defaultValue: false,
+      describe: 'Turn on/off GFM tasklist support',
+      type: 'boolean'
+    },
+    smoothLivePreview: {
+      defaultValue: false,
+      describe: 'Prevents weird effects in live previews due to incomplete input',
+      type: 'boolean'
+    },
+    smartIndentationFix: {
+      defaultValue: false,
+      description: 'Tries to smartly fix identation in es6 strings',
+      type: 'boolean'
+    }
+  };
+  if (simple === false) {
+    return JSON.parse(JSON.stringify(defaultOptions));
+  }
+  var ret = {};
+  for (var opt in defaultOptions) {
+    if (defaultOptions.hasOwnProperty(opt)) {
+      ret[opt] = defaultOptions[opt].defaultValue;
+    }
+  }
+  return ret;
+}
+
+/**
+ * Created by Tivie on 06-01-2015.
+ */
+
+// Private properties
+var showdown = {},
+    parsers = {},
+    extensions = {},
+    globalOptions = getDefaultOpts(true),
+    flavor = {
+      github: {
+        omitExtraWLInCodeBlocks:   true,
+        prefixHeaderId:            'user-content-',
+        simplifiedAutoLink:        true,
+        literalMidWordUnderscores: true,
+        strikethrough:             true,
+        tables:                    true,
+        tablesHeaderId:            true,
+        ghCodeBlocks:              true,
+        tasklists:                 true
+      },
+      vanilla: getDefaultOpts(true)
+    };
+
+/**
+ * helper namespace
+ * @type {{}}
+ */
+showdown.helper = {};
+
+/**
+ * TODO LEGACY SUPPORT CODE
+ * @type {{}}
+ */
+showdown.extensions = {};
+
+/**
+ * Set a global option
+ * @static
+ * @param {string} key
+ * @param {*} value
+ * @returns {showdown}
+ */
+showdown.setOption = function (key, value) {
+  'use strict';
+  globalOptions[key] = value;
+  return this;
+};
+
+/**
+ * Get a global option
+ * @static
+ * @param {string} key
+ * @returns {*}
+ */
+showdown.getOption = function (key) {
+  'use strict';
+  return globalOptions[key];
+};
+
+/**
+ * Get the global options
+ * @static
+ * @returns {{}}
+ */
+showdown.getOptions = function () {
+  'use strict';
+  return globalOptions;
+};
+
+/**
+ * Reset global options to the default values
+ * @static
+ */
+showdown.resetOptions = function () {
+  'use strict';
+  globalOptions = getDefaultOpts(true);
+};
+
+/**
+ * Set the flavor showdown should use as default
+ * @param {string} name
+ */
+showdown.setFlavor = function (name) {
+  'use strict';
+  if (flavor.hasOwnProperty(name)) {
+    var preset = flavor[name];
+    for (var option in preset) {
+      if (preset.hasOwnProperty(option)) {
+        globalOptions[option] = preset[option];
+      }
+    }
+  }
+};
+
+/**
+ * Get the default options
+ * @static
+ * @param {boolean} [simple=true]
+ * @returns {{}}
+ */
+showdown.getDefaultOptions = function (simple) {
+  'use strict';
+  return getDefaultOpts(simple);
+};
+
+/**
+ * Get or set a subParser
+ *
+ * subParser(name)       - Get a registered subParser
+ * subParser(name, func) - Register a subParser
+ * @static
+ * @param {string} name
+ * @param {function} [func]
+ * @returns {*}
+ */
+showdown.subParser = function (name, func) {
+  'use strict';
+  if (showdown.helper.isString(name)) {
+    if (typeof func !== 'undefined') {
+      parsers[name] = func;
+    } else {
+      if (parsers.hasOwnProperty(name)) {
+        return parsers[name];
+      } else {
+        throw Error('SubParser named ' + name + ' not registered!');
+      }
+    }
+  }
+};
+
+/**
+ * Gets or registers an extension
+ * @static
+ * @param {string} name
+ * @param {object|function=} ext
+ * @returns {*}
+ */
+showdown.extension = function (name, ext) {
+  'use strict';
+
+  if (!showdown.helper.isString(name)) {
+    throw Error('Extension \'name\' must be a string');
+  }
+
+  name = showdown.helper.stdExtName(name);
+
+  // Getter
+  if (showdown.helper.isUndefined(ext)) {
+    if (!extensions.hasOwnProperty(name)) {
+      throw Error('Extension named ' + name + ' is not registered!');
+    }
+    return extensions[name];
+
+    // Setter
+  } else {
+    // Expand extension if it's wrapped in a function
+    if (typeof ext === 'function') {
+      ext = ext();
+    }
+
+    // Ensure extension is an array
+    if (!showdown.helper.isArray(ext)) {
+      ext = [ext];
+    }
+
+    var validExtension = validate(ext, name);
+
+    if (validExtension.valid) {
+      extensions[name] = ext;
+    } else {
+      throw Error(validExtension.error);
+    }
+  }
+};
+
+/**
+ * Gets all extensions registered
+ * @returns {{}}
+ */
+showdown.getAllExtensions = function () {
+  'use strict';
+  return extensions;
+};
+
+/**
+ * Remove an extension
+ * @param {string} name
+ */
+showdown.removeExtension = function (name) {
+  'use strict';
+  delete extensions[name];
+};
+
+/**
+ * Removes all extensions
+ */
+showdown.resetExtensions = function () {
+  'use strict';
+  extensions = {};
+};
+
+/**
+ * Validate extension
+ * @param {array} extension
+ * @param {string} name
+ * @returns {{valid: boolean, error: string}}
+ */
+function validate(extension, name) {
+  'use strict';
+
+  var errMsg = (name) ? 'Error in ' + name + ' extension->' : 'Error in unnamed extension',
+    ret = {
+      valid: true,
+      error: ''
+    };
+
+  if (!showdown.helper.isArray(extension)) {
+    extension = [extension];
+  }
+
+  for (var i = 0; i < extension.length; ++i) {
+    var baseMsg = errMsg + ' sub-extension ' + i + ': ',
+        ext = extension[i];
+    if (typeof ext !== 'object') {
+      ret.valid = false;
+      ret.error = baseMsg + 'must be an object, but ' + typeof ext + ' given';
+      return ret;
+    }
+
+    if (!showdown.helper.isString(ext.type)) {
+      ret.valid = false;
+      ret.error = baseMsg + 'property "type" must be a string, but ' + typeof ext.type + ' given';
+      return ret;
+    }
+
+    var type = ext.type = ext.type.toLowerCase();
+
+    // normalize extension type
+    if (type === 'language') {
+      type = ext.type = 'lang';
+    }
+
+    if (type === 'html') {
+      type = ext.type = 'output';
+    }
+
+    if (type !== 'lang' && type !== 'output' && type !== 'listener') {
+      ret.valid = false;
+      ret.error = baseMsg + 'type ' + type + ' is not recognized. Valid values: "lang/language", "output/html" or "listener"';
+      return ret;
+    }
+
+    if (type === 'listener') {
+      if (showdown.helper.isUndefined(ext.listeners)) {
+        ret.valid = false;
+        ret.error = baseMsg + '. Extensions of type "listener" must have a property called "listeners"';
+        return ret;
+      }
+    } else {
+      if (showdown.helper.isUndefined(ext.filter) && showdown.helper.isUndefined(ext.regex)) {
+        ret.valid = false;
+        ret.error = baseMsg + type + ' extensions must define either a "regex" property or a "filter" method';
+        return ret;
+      }
+    }
+
+    if (ext.listeners) {
+      if (typeof ext.listeners !== 'object') {
+        ret.valid = false;
+        ret.error = baseMsg + '"listeners" property must be an object but ' + typeof ext.listeners + ' given';
+        return ret;
+      }
+      for (var ln in ext.listeners) {
+        if (ext.listeners.hasOwnProperty(ln)) {
+          if (typeof ext.listeners[ln] !== 'function') {
+            ret.valid = false;
+            ret.error = baseMsg + '"listeners" property must be an hash of [event name]: [callback]. listeners.' + ln +
+              ' must be a function but ' + typeof ext.listeners[ln] + ' given';
+            return ret;
+          }
+        }
+      }
+    }
+
+    if (ext.filter) {
+      if (typeof ext.filter !== 'function') {
+        ret.valid = false;
+        ret.error = baseMsg + '"filter" must be a function, but ' + typeof ext.filter + ' given';
+        return ret;
+      }
+    } else if (ext.regex) {
+      if (showdown.helper.isString(ext.regex)) {
+        ext.regex = new RegExp(ext.regex, 'g');
+      }
+      if (!ext.regex instanceof RegExp) {
+        ret.valid = false;
+        ret.error = baseMsg + '"regex" property must either be a string or a RegExp object, but ' + typeof ext.regex + ' given';
+        return ret;
+      }
+      if (showdown.helper.isUndefined(ext.replace)) {
+        ret.valid = false;
+        ret.error = baseMsg + '"regex" extensions must implement a replace string or function';
+        return ret;
+      }
+    }
+  }
+  return ret;
+}
+
+/**
+ * Validate extension
+ * @param {object} ext
+ * @returns {boolean}
+ */
+showdown.validateExtension = function (ext) {
+  'use strict';
+
+  var validateExtension = validate(ext, null);
+  if (!validateExtension.valid) {
+    console.warn(validateExtension.error);
+    return false;
+  }
+  return true;
+};
+
+/**
+ * showdownjs helper functions
+ */
+
+if (!showdown.hasOwnProperty('helper')) {
+  showdown.helper = {};
+}
+
+/**
+ * Check if var is string
+ * @static
+ * @param {string} a
+ * @returns {boolean}
+ */
+showdown.helper.isString = function isString(a) {
+  'use strict';
+  return (typeof a === 'string' || a instanceof String);
+};
+
+/**
+ * Check if var is a function
+ * @static
+ * @param {string} a
+ * @returns {boolean}
+ */
+showdown.helper.isFunction = function isFunction(a) {
+  'use strict';
+  var getType = {};
+  return a && getType.toString.call(a) === '[object Function]';
+};
+
+/**
+ * ForEach helper function
+ * @static
+ * @param {*} obj
+ * @param {function} callback
+ */
+showdown.helper.forEach = function forEach(obj, callback) {
+  'use strict';
+  if (typeof obj.forEach === 'function') {
+    obj.forEach(callback);
+  } else {
+    for (var i = 0; i < obj.length; i++) {
+      callback(obj[i], i, obj);
+    }
+  }
+};
+
+/**
+ * isArray helper function
+ * @static
+ * @param {*} a
+ * @returns {boolean}
+ */
+showdown.helper.isArray = function isArray(a) {
+  'use strict';
+  return a.constructor === Array;
+};
+
+/**
+ * Check if value is undefined
+ * @static
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
+ */
+showdown.helper.isUndefined = function isUndefined(value) {
+  'use strict';
+  return typeof value === 'undefined';
+};
+
+/**
+ * Standardidize extension name
+ * @static
+ * @param {string} s extension name
+ * @returns {string}
+ */
+showdown.helper.stdExtName = function (s) {
+  'use strict';
+  return s.replace(/[_-]||\s/g, '').toLowerCase();
+};
+
+function escapeCharactersCallback(wholeMatch, m1) {
+  'use strict';
+  var charCodeToEscape = m1.charCodeAt(0);
+  return '~E' + charCodeToEscape + 'E';
+}
+
+/**
+ * Callback used to escape characters when passing through String.replace
+ * @static
+ * @param {string} wholeMatch
+ * @param {string} m1
+ * @returns {string}
+ */
+showdown.helper.escapeCharactersCallback = escapeCharactersCallback;
+
+/**
+ * Escape characters in a string
+ * @static
+ * @param {string} text
+ * @param {string} charsToEscape
+ * @param {boolean} afterBackslash
+ * @returns {XML|string|void|*}
+ */
+showdown.helper.escapeCharacters = function escapeCharacters(text, charsToEscape, afterBackslash) {
+  'use strict';
+  // First we have to escape the escape characters so that
+  // we can build a character class out of them
+  var regexString = '([' + charsToEscape.replace(/([\[\]\\])/g, '\\$1') + '])';
+
+  if (afterBackslash) {
+    regexString = '\\\\' + regexString;
+  }
+
+  var regex = new RegExp(regexString, 'g');
+  text = text.replace(regex, escapeCharactersCallback);
+
+  return text;
+};
+
+var rgxFindMatchPos = function (str, left, right, flags) {
+  'use strict';
+  var f = flags || '',
+    g = f.indexOf('g') > -1,
+    x = new RegExp(left + '|' + right, 'g' + f.replace(/g/g, '')),
+    l = new RegExp(left, f.replace(/g/g, '')),
+    pos = [],
+    t, s, m, start, end;
+
+  do {
+    t = 0;
+    while ((m = x.exec(str))) {
+      if (l.test(m[0])) {
+        if (!(t++)) {
+          s = x.lastIndex;
+          start = s - m[0].length;
+        }
+      } else if (t) {
+        if (!--t) {
+          end = m.index + m[0].length;
+          var obj = {
+            left: {start: start, end: s},
+            match: {start: s, end: m.index},
+            right: {start: m.index, end: end},
+            wholeMatch: {start: start, end: end}
+          };
+          pos.push(obj);
+          if (!g) {
+            return pos;
+          }
+        }
+      }
+    }
+  } while (t && (x.lastIndex = s));
+
+  return pos;
+};
+
+/**
+ * matchRecursiveRegExp
+ *
+ * (c) 2007 Steven Levithan <stevenlevithan.com>
+ * MIT License
+ *
+ * Accepts a string to search, a left and right format delimiter
+ * as regex patterns, and optional regex flags. Returns an array
+ * of matches, allowing nested instances of left/right delimiters.
+ * Use the "g" flag to return all matches, otherwise only the
+ * first is returned. Be careful to ensure that the left and
+ * right format delimiters produce mutually exclusive matches.
+ * Backreferences are not supported within the right delimiter
+ * due to how it is internally combined with the left delimiter.
+ * When matching strings whose format delimiters are unbalanced
+ * to the left or right, the output is intentionally as a
+ * conventional regex library with recursion support would
+ * produce, e.g. "<<x>" and "<x>>" both produce ["x"] when using
+ * "<" and ">" as the delimiters (both strings contain a single,
+ * balanced instance of "<x>").
+ *
+ * examples:
+ * matchRecursiveRegExp("test", "\\(", "\\)")
+ * returns: []
+ * matchRecursiveRegExp("<t<<e>><s>>t<>", "<", ">", "g")
+ * returns: ["t<<e>><s>", ""]
+ * matchRecursiveRegExp("<div id=\"x\">test</div>", "<div\\b[^>]*>", "</div>", "gi")
+ * returns: ["test"]
+ */
+showdown.helper.matchRecursiveRegExp = function (str, left, right, flags) {
+  'use strict';
+
+  var matchPos = rgxFindMatchPos (str, left, right, flags),
+    results = [];
+
+  for (var i = 0; i < matchPos.length; ++i) {
+    results.push([
+      str.slice(matchPos[i].wholeMatch.start, matchPos[i].wholeMatch.end),
+      str.slice(matchPos[i].match.start, matchPos[i].match.end),
+      str.slice(matchPos[i].left.start, matchPos[i].left.end),
+      str.slice(matchPos[i].right.start, matchPos[i].right.end)
+    ]);
+  }
+  return results;
+};
+
+/**
+ *
+ * @param {string} str
+ * @param {string|function} replacement
+ * @param {string} left
+ * @param {string} right
+ * @param {string} flags
+ * @returns {string}
+ */
+showdown.helper.replaceRecursiveRegExp = function (str, replacement, left, right, flags) {
+  'use strict';
+
+  if (!showdown.helper.isFunction(replacement)) {
+    var repStr = replacement;
+    replacement = function () {
+      return repStr;
+    };
+  }
+
+  var matchPos = rgxFindMatchPos(str, left, right, flags),
+      finalStr = str,
+      lng = matchPos.length;
+
+  if (lng > 0) {
+    var bits = [];
+    if (matchPos[0].wholeMatch.start !== 0) {
+      bits.push(str.slice(0, matchPos[0].wholeMatch.start));
+    }
+    for (var i = 0; i < lng; ++i) {
+      bits.push(
+        replacement(
+          str.slice(matchPos[i].wholeMatch.start, matchPos[i].wholeMatch.end),
+          str.slice(matchPos[i].match.start, matchPos[i].match.end),
+          str.slice(matchPos[i].left.start, matchPos[i].left.end),
+          str.slice(matchPos[i].right.start, matchPos[i].right.end)
+        )
+      );
+      if (i < lng - 1) {
+        bits.push(str.slice(matchPos[i].wholeMatch.end, matchPos[i + 1].wholeMatch.start));
+      }
+    }
+    if (matchPos[lng - 1].wholeMatch.end < str.length) {
+      bits.push(str.slice(matchPos[lng - 1].wholeMatch.end));
+    }
+    finalStr = bits.join('');
+  }
+  return finalStr;
+};
+
+/**
+ * POLYFILLS
+ */
+if (showdown.helper.isUndefined(console)) {
+  console = {
+    warn: function (msg) {
+      'use strict';
+      alert(msg);
+    },
+    log: function (msg) {
+      'use strict';
+      alert(msg);
+    },
+    error: function (msg) {
+      'use strict';
+      throw msg;
+    }
+  };
+}
+
+/**
+ * Created by Estevao on 31-05-2015.
+ */
+
+/**
+ * Showdown Converter class
+ * @class
+ * @param {object} [converterOptions]
+ * @returns {Converter}
+ */
+showdown.Converter = function (converterOptions) {
+  'use strict';
+
+  var
+      /**
+       * Options used by this converter
+       * @private
+       * @type {{}}
+       */
+      options = {},
+
+      /**
+       * Language extensions used by this converter
+       * @private
+       * @type {Array}
+       */
+      langExtensions = [],
+
+      /**
+       * Output modifiers extensions used by this converter
+       * @private
+       * @type {Array}
+       */
+      outputModifiers = [],
+
+      /**
+       * Event listeners
+       * @private
+       * @type {{}}
+       */
+      listeners = {};
+
+  _constructor();
+
+  /**
+   * Converter constructor
+   * @private
+   */
+  function _constructor() {
+    converterOptions = converterOptions || {};
+
+    for (var gOpt in globalOptions) {
+      if (globalOptions.hasOwnProperty(gOpt)) {
+        options[gOpt] = globalOptions[gOpt];
+      }
+    }
+
+    // Merge options
+    if (typeof converterOptions === 'object') {
+      for (var opt in converterOptions) {
+        if (converterOptions.hasOwnProperty(opt)) {
+          options[opt] = converterOptions[opt];
+        }
+      }
+    } else {
+      throw Error('Converter expects the passed parameter to be an object, but ' + typeof converterOptions +
+      ' was passed instead.');
+    }
+
+    if (options.extensions) {
+      showdown.helper.forEach(options.extensions, _parseExtension);
+    }
+  }
+
+  /**
+   * Parse extension
+   * @param {*} ext
+   * @param {string} [name='']
+   * @private
+   */
+  function _parseExtension(ext, name) {
+
+    name = name || null;
+    // If it's a string, the extension was previously loaded
+    if (showdown.helper.isString(ext)) {
+      ext = showdown.helper.stdExtName(ext);
+      name = ext;
+
+      // LEGACY_SUPPORT CODE
+      if (showdown.extensions[ext]) {
+        console.warn('DEPRECATION WARNING: ' + ext + ' is an old extension that uses a deprecated loading method.' +
+          'Please inform the developer that the extension should be updated!');
+        legacyExtensionLoading(showdown.extensions[ext], ext);
+        return;
+      // END LEGACY SUPPORT CODE
+
+      } else if (!showdown.helper.isUndefined(extensions[ext])) {
+        ext = extensions[ext];
+
+      } else {
+        throw Error('Extension "' + ext + '" could not be loaded. It was either not found or is not a valid extension.');
+      }
+    }
+
+    if (typeof ext === 'function') {
+      ext = ext();
+    }
+
+    if (!showdown.helper.isArray(ext)) {
+      ext = [ext];
+    }
+
+    var validExt = validate(ext, name);
+    if (!validExt.valid) {
+      throw Error(validExt.error);
+    }
+
+    for (var i = 0; i < ext.length; ++i) {
+      switch (ext[i].type) {
+
+        case 'lang':
+          langExtensions.push(ext[i]);
+          break;
+
+        case 'output':
+          outputModifiers.push(ext[i]);
+          break;
+      }
+      if (ext[i].hasOwnProperty(listeners)) {
+        for (var ln in ext[i].listeners) {
+          if (ext[i].listeners.hasOwnProperty(ln)) {
+            listen(ln, ext[i].listeners[ln]);
+          }
+        }
+      }
+    }
+
+  }
+
+  /**
+   * LEGACY_SUPPORT
+   * @param {*} ext
+   * @param {string} name
+   */
+  function legacyExtensionLoading(ext, name) {
+    if (typeof ext === 'function') {
+      ext = ext(new showdown.Converter());
+    }
+    if (!showdown.helper.isArray(ext)) {
+      ext = [ext];
+    }
+    var valid = validate(ext, name);
+
+    if (!valid.valid) {
+      throw Error(valid.error);
+    }
+
+    for (var i = 0; i < ext.length; ++i) {
+      switch (ext[i].type) {
+        case 'lang':
+          langExtensions.push(ext[i]);
+          break;
+        case 'output':
+          outputModifiers.push(ext[i]);
+          break;
+        default:// should never reach here
+          throw Error('Extension loader error: Type unrecognized!!!');
+      }
+    }
+  }
+
+  /**
+   * Listen to an event
+   * @param {string} name
+   * @param {function} callback
+   */
+  function listen(name, callback) {
+    if (!showdown.helper.isString(name)) {
+      throw Error('Invalid argument in converter.listen() method: name must be a string, but ' + typeof name + ' given');
+    }
+
+    if (typeof callback !== 'function') {
+      throw Error('Invalid argument in converter.listen() method: callback must be a function, but ' + typeof callback + ' given');
+    }
+
+    if (!listeners.hasOwnProperty(name)) {
+      listeners[name] = [];
+    }
+    listeners[name].push(callback);
+  }
+
+  function rTrimInputText(text) {
+    var rsp = text.match(/^\s*/)[0].length,
+        rgx = new RegExp('^\\s{0,' + rsp + '}', 'gm');
+    return text.replace(rgx, '');
+  }
+
+  /**
+   * Dispatch an event
+   * @private
+   * @param {string} evtName Event name
+   * @param {string} text Text
+   * @param {{}} options Converter Options
+   * @param {{}} globals
+   * @returns {string}
+   */
+  this._dispatch = function dispatch (evtName, text, options, globals) {
+    if (listeners.hasOwnProperty(evtName)) {
+      for (var ei = 0; ei < listeners[evtName].length; ++ei) {
+        var nText = listeners[evtName][ei](evtName, text, this, options, globals);
+        if (nText && typeof nText !== 'undefined') {
+          text = nText;
+        }
+      }
+    }
+    return text;
+  };
+
+  /**
+   * Listen to an event
+   * @param {string} name
+   * @param {function} callback
+   * @returns {showdown.Converter}
+   */
+  this.listen = function (name, callback) {
+    listen(name, callback);
+    return this;
+  };
+
+  /**
+   * Converts a markdown string into HTML
+   * @param {string} text
+   * @returns {*}
+   */
+  this.makeHtml = function (text) {
+    //check if text is not falsy
+    if (!text) {
+      return text;
+    }
+
+    var globals = {
+      gHtmlBlocks:     [],
+      gHtmlMdBlocks:   [],
+      gHtmlSpans:      [],
+      gUrls:           {},
+      gTitles:         {},
+      gDimensions:     {},
+      gListLevel:      0,
+      hashLinkCounts:  {},
+      langExtensions:  langExtensions,
+      outputModifiers: outputModifiers,
+      converter:       this,
+      ghCodeBlocks:    []
+    };
+
+    // attacklab: Replace ~ with ~T
+    // This lets us use tilde as an escape char to avoid md5 hashes
+    // The choice of character is arbitrary; anything that isn't
+    // magic in Markdown will work.
+    text = text.replace(/~/g, '~T');
+
+    // attacklab: Replace $ with ~D
+    // RegExp interprets $ as a special character
+    // when it's in a replacement string
+    text = text.replace(/\$/g, '~D');
+
+    // Standardize line endings
+    text = text.replace(/\r\n/g, '\n'); // DOS to Unix
+    text = text.replace(/\r/g, '\n'); // Mac to Unix
+
+    if (options.smartIndentationFix) {
+      text = rTrimInputText(text);
+    }
+
+    // Make sure text begins and ends with a couple of newlines:
+    //text = '\n\n' + text + '\n\n';
+    text = text;
+    // detab
+    text = showdown.subParser('detab')(text, options, globals);
+
+    // stripBlankLines
+    text = showdown.subParser('stripBlankLines')(text, options, globals);
+
+    //run languageExtensions
+    showdown.helper.forEach(langExtensions, function (ext) {
+      text = showdown.subParser('runExtension')(ext, text, options, globals);
+    });
+
+    // run the sub parsers
+    text = showdown.subParser('hashPreCodeTags')(text, options, globals);
+    text = showdown.subParser('githubCodeBlocks')(text, options, globals);
+    text = showdown.subParser('hashHTMLBlocks')(text, options, globals);
+    text = showdown.subParser('hashHTMLSpans')(text, options, globals);
+    text = showdown.subParser('stripLinkDefinitions')(text, options, globals);
+    text = showdown.subParser('blockGamut')(text, options, globals);
+    text = showdown.subParser('unhashHTMLSpans')(text, options, globals);
+    text = showdown.subParser('unescapeSpecialChars')(text, options, globals);
+
+    // attacklab: Restore dollar signs
+    text = text.replace(/~D/g, '$$');
+
+    // attacklab: Restore tildes
+    text = text.replace(/~T/g, '~');
+
+    // Run output modifiers
+    showdown.helper.forEach(outputModifiers, function (ext) {
+      text = showdown.subParser('runExtension')(ext, text, options, globals);
+    });
+    return text;
+  };
+
+  /**
+   * Set an option of this Converter instance
+   * @param {string} key
+   * @param {*} value
+   */
+  this.setOption = function (key, value) {
+    options[key] = value;
+  };
+
+  /**
+   * Get the option of this Converter instance
+   * @param {string} key
+   * @returns {*}
+   */
+  this.getOption = function (key) {
+    return options[key];
+  };
+
+  /**
+   * Get the options of this Converter instance
+   * @returns {{}}
+   */
+  this.getOptions = function () {
+    return options;
+  };
+
+  /**
+   * Add extension to THIS converter
+   * @param {{}} extension
+   * @param {string} [name=null]
+   */
+  this.addExtension = function (extension, name) {
+    name = name || null;
+    _parseExtension(extension, name);
+  };
+
+  /**
+   * Use a global registered extension with THIS converter
+   * @param {string} extensionName Name of the previously registered extension
+   */
+  this.useExtension = function (extensionName) {
+    _parseExtension(extensionName);
+  };
+
+  /**
+   * Set the flavor THIS converter should use
+   * @param {string} name
+   */
+  this.setFlavor = function (name) {
+    if (flavor.hasOwnProperty(name)) {
+      var preset = flavor[name];
+      for (var option in preset) {
+        if (preset.hasOwnProperty(option)) {
+          options[option] = preset[option];
+        }
+      }
+    }
+  };
+
+  /**
+   * Remove an extension from THIS converter.
+   * Note: This is a costly operation. It's better to initialize a new converter
+   * and specify the extensions you wish to use
+   * @param {Array} extension
+   */
+  this.removeExtension = function (extension) {
+    if (!showdown.helper.isArray(extension)) {
+      extension = [extension];
+    }
+    for (var a = 0; a < extension.length; ++a) {
+      var ext = extension[a];
+      for (var i = 0; i < langExtensions.length; ++i) {
+        if (langExtensions[i] === ext) {
+          langExtensions[i].splice(i, 1);
+        }
+      }
+      for (var ii = 0; ii < outputModifiers.length; ++i) {
+        if (outputModifiers[ii] === ext) {
+          outputModifiers[ii].splice(i, 1);
+        }
+      }
+    }
+  };
+
+  /**
+   * Get all extension of THIS converter
+   * @returns {{language: Array, output: Array}}
+   */
+  this.getAllExtensions = function () {
+    return {
+      language: langExtensions,
+      output: outputModifiers
+    };
+  };
+};
+
+/**
+ * Turn Markdown link shortcuts into XHTML <a> tags.
+ */
+showdown.subParser('anchors', function (text, options, globals) {
+  'use strict';
+
+  text = globals.converter._dispatch('anchors.before', text, options, globals);
+
+  var writeAnchorTag = function (wholeMatch, m1, m2, m3, m4, m5, m6, m7) {
+    if (showdown.helper.isUndefined(m7)) {
+      m7 = '';
+    }
+    wholeMatch = m1;
+    var linkText = m2,
+        linkId = m3.toLowerCase(),
+        url = m4,
+        title = m7;
+
+    if (!url) {
+      if (!linkId) {
+        // lower-case and turn embedded newlines into spaces
+        linkId = linkText.toLowerCase().replace(/ ?\n/g, ' ');
+      }
+      url = '#' + linkId;
+
+      if (!showdown.helper.isUndefined(globals.gUrls[linkId])) {
+        url = globals.gUrls[linkId];
+        if (!showdown.helper.isUndefined(globals.gTitles[linkId])) {
+          title = globals.gTitles[linkId];
+        }
+      } else {
+        if (wholeMatch.search(/\(\s*\)$/m) > -1) {
+          // Special case for explicit empty url
+          url = '';
+        } else {
+          return wholeMatch;
+        }
+      }
+    }
+
+    url = showdown.helper.escapeCharacters(url, '*_', false);
+    var result = '<a href="' + url + '"';
+
+    if (title !== '' && title !== null) {
+      title = title.replace(/"/g, '&quot;');
+      title = showdown.helper.escapeCharacters(title, '*_', false);
+      result += ' title="' + title + '"';
+    }
+
+    result += '>' + linkText + '</a>';
+
+    return result;
+  };
+
+  // First, handle reference-style links: [link text] [id]
+  /*
+   text = text.replace(/
+   (							// wrap whole match in $1
+   \[
+   (
+   (?:
+   \[[^\]]*\]		// allow brackets nested one level
+   |
+   [^\[]			// or anything else
+   )*
+   )
+   \]
+
+   [ ]?					// one optional space
+   (?:\n[ ]*)?				// one optional newline followed by spaces
+
+   \[
+   (.*?)					// id = $3
+   \]
+   )()()()()					// pad remaining backreferences
+   /g,_DoAnchors_callback);
+   */
+  text = text.replace(/(\[((?:\[[^\]]*]|[^\[\]])*)][ ]?(?:\n[ ]*)?\[(.*?)])()()()()/g, writeAnchorTag);
+
+  //
+  // Next, inline-style links: [link text](url "optional title")
+  //
+
+  /*
+   text = text.replace(/
+   (						// wrap whole match in $1
+   \[
+   (
+   (?:
+   \[[^\]]*\]	// allow brackets nested one level
+   |
+   [^\[\]]			// or anything else
+   )
+   )
+   \]
+   \(						// literal paren
+   [ \t]*
+   ()						// no id, so leave $3 empty
+   <?(.*?)>?				// href = $4
+   [ \t]*
+   (						// $5
+   (['"])				// quote char = $6
+   (.*?)				// Title = $7
+   \6					// matching quote
+   [ \t]*				// ignore any spaces/tabs between closing quote and )
+   )?						// title is optional
+   \)
+   )
+   /g,writeAnchorTag);
+   */
+  text = text.replace(/(\[((?:\[[^\]]*]|[^\[\]])*)]\([ \t]*()<?(.*?(?:\(.*?\).*?)?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,
+                      writeAnchorTag);
+
+  //
+  // Last, handle reference-style shortcuts: [link text]
+  // These must come last in case you've also got [link test][1]
+  // or [link test](/foo)
+  //
+
+  /*
+   text = text.replace(/
+   (                // wrap whole match in $1
+   \[
+   ([^\[\]]+)       // link text = $2; can't contain '[' or ']'
+   \]
+   )()()()()()      // pad rest of backreferences
+   /g, writeAnchorTag);
+   */
+  text = text.replace(/(\[([^\[\]]+)])()()()()()/g, writeAnchorTag);
+
+  text = globals.converter._dispatch('anchors.after', text, options, globals);
+  return text;
+});
+
+showdown.subParser('autoLinks', function (text, options, globals) {
+  'use strict';
+
+  text = globals.converter._dispatch('autoLinks.before', text, options, globals);
+
+  var simpleURLRegex  = /\b(((https?|ftp|dict):\/\/|www\.)[^'">\s]+\.[^'">\s]+)(?=\s|$)(?!["<>])/gi,
+      delimUrlRegex   = /<(((https?|ftp|dict):\/\/|www\.)[^'">\s]+)>/gi,
+      simpleMailRegex = /(?:^|[ \n\t])([A-Za-z0-9!#$%&'*+-/=?^_`\{|}~\.]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)(?:$|[ \n\t])/gi,
+      delimMailRegex  = /<(?:mailto:)?([-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi;
+
+  text = text.replace(delimUrlRegex, replaceLink);
+  text = text.replace(delimMailRegex, replaceMail);
+  // simpleURLRegex  = /\b(((https?|ftp|dict):\/\/|www\.)[-.+~:?#@!$&'()*,;=[\]\w]+)\b/gi,
+  // Email addresses: <address@domain.foo>
+
+  if (options.simplifiedAutoLink) {
+    text = text.replace(simpleURLRegex, replaceLink);
+    text = text.replace(simpleMailRegex, replaceMail);
+  }
+
+  function replaceLink(wm, link) {
+    var lnkTxt = link;
+    if (/^www\./i.test(link)) {
+      link = link.replace(/^www\./i, 'http://www.');
+    }
+    return '<a href="' + link + '">' + lnkTxt + '</a>';
+  }
+
+  function replaceMail(wholeMatch, m1) {
+    var unescapedStr = showdown.subParser('unescapeSpecialChars')(m1);
+    return showdown.subParser('encodeEmailAddress')(unescapedStr);
+  }
+
+  text = globals.converter._dispatch('autoLinks.after', text, options, globals);
+
+  return text;
+});
+
+/**
+ * These are all the transformations that form block-level
+ * tags like paragraphs, headers, and list items.
+ */
+showdown.subParser('blockGamut', function (text, options, globals) {
+  'use strict';
+
+  text = globals.converter._dispatch('blockGamut.before', text, options, globals);
+
+  // we parse blockquotes first so that we can have headings and hrs
+  // inside blockquotes
+  text = showdown.subParser('blockQuotes')(text, options, globals);
+  text = showdown.subParser('headers')(text, options, globals);
+
+  // Do Horizontal Rules:
+  var key = showdown.subParser('hashBlock')('<hr />', options, globals);
+  text = text.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm, key);
+  text = text.replace(/^[ ]{0,2}([ ]?\-[ ]?){3,}[ \t]*$/gm, key);
+  text = text.replace(/^[ ]{0,2}([ ]?_[ ]?){3,}[ \t]*$/gm, key);
+
+  text = showdown.subParser('lists')(text, options, globals);
+  text = showdown.subParser('codeBlocks')(text, options, globals);
+  text = showdown.subParser('tables')(text, options, globals);
+
+  // We already ran _HashHTMLBlocks() before, in Markdown(), but that
+  // was to escape raw HTML in the original Markdown source. This time,
+  // we're escaping the markup we've just created, so that we don't wrap
+  // <p> tags around block-level tags.
+  text = showdown.subParser('hashHTMLBlocks')(text, options, globals);
+  text = showdown.subParser('paragraphs')(text, options, globals);
+
+  text = globals.converter._dispatch('blockGamut.after', text, options, globals);
+
+  return text;
+});
+
+showdown.subParser('blockQuotes', function (text, options, globals) {
+  'use strict';
+
+  text = globals.converter._dispatch('blockQuotes.before', text, options, globals);
+  /*
+   text = text.replace(/
+   (								// Wrap whole match in $1
+   (
+   ^[ \t]*>[ \t]?			// '>' at the start of a line
+   .+\n					// rest of the first line
+   (.+\n)*					// subsequent consecutive lines
+   \n*						// blanks
+   )+
+   )
+   /gm, function(){...});
+   */
+
+  text = text.replace(/((^[ \t]{0,3}>[ \t]?.+\n(.+\n)*\n*)+)/gm, function (wholeMatch, m1) {
+    var bq = m1;
+
+    // attacklab: hack around Konqueror 3.5.4 bug:
+    // "----------bug".replace(/^-/g,"") == "bug"
+    bq = bq.replace(/^[ \t]*>[ \t]?/gm, '~0'); // trim one level of quoting
+
+    // attacklab: clean up hack
+    bq = bq.replace(/~0/g, '');
+
+    bq = bq.replace(/^[ \t]+$/gm, ''); // trim whitespace-only lines
+    bq = showdown.subParser('githubCodeBlocks')(bq, options, globals);
+    bq = showdown.subParser('blockGamut')(bq, options, globals); // recurse
+
+    bq = bq.replace(/(^|\n)/g, '$1  ');
+    // These leading spaces screw with <pre> content, so we need to fix that:
+    bq = bq.replace(/(\s*<pre>[^\r]+?<\/pre>)/gm, function (wholeMatch, m1) {
+      var pre = m1;
+      // attacklab: hack around Konqueror 3.5.4 bug:
+      pre = pre.replace(/^  /mg, '~0');
+      pre = pre.replace(/~0/g, '');
+      return pre;
+    });
+
+    return showdown.subParser('hashBlock')('<blockquote>\n' + bq + '\n</blockquote>', options, globals);
+  });
+
+  text = globals.converter._dispatch('blockQuotes.after', text, options, globals);
+  return text;
+});
+
+/**
+ * Process Markdown `<pre><code>` blocks.
+ */
+showdown.subParser('codeBlocks', function (text, options, globals) {
+  'use strict';
+
+  text = globals.converter._dispatch('codeBlocks.before', text, options, globals);
+  /*
+   text = text.replace(text,
+   /(?:\n\n|^)
+   (								// $1 = the code block -- one or more lines, starting with a space/tab
+   (?:
+   (?:[ ]{4}|\t)			// Lines must start with a tab or a tab-width of spaces - attacklab: g_tab_width
+   .*\n+
+   )+
+   )
+   (\n*[ ]{0,3}[^ \t\n]|(?=~0))	// attacklab: g_tab_width
+   /g,function(){...});
+   */
+
+  // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
+  text += '~0';
+
+  var pattern = /(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g;
+  text = text.replace(pattern, function (wholeMatch, m1, m2) {
+    var codeblock = m1,
+        nextChar = m2,
+        end = '\n';
+
+    codeblock = showdown.subParser('outdent')(codeblock);
+    codeblock = showdown.subParser('encodeCode')(codeblock);
+    codeblock = showdown.subParser('detab')(codeblock);
+    codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines
+    codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing newlines
+
+    if (options.omitExtraWLInCodeBlocks) {
+      end = '';
+    }
+
+    codeblock = '<pre><code>' + codeblock + end + '</code></pre>';
+
+    return showdown.subParser('hashBlock')(codeblock, options, globals) + nextChar;
+  });
+
+  // attacklab: strip sentinel
+  text = text.replace(/~0/, '');
+
+  text = globals.converter._dispatch('codeBlocks.after', text, options, globals);
+  return text;
+});
+
+/**
+ *
+ *   *  Backtick quotes are used for <code></code> spans.
+ *
+ *   *  You can use multiple backticks as the delimiters if you want to
+ *     include literal backticks in the code span. So, this input:
+ *
+ *         Just type ``foo `bar` baz`` at the prompt.
+ *
+ *       Will translate to:
+ *
+ *         <p>Just type <code>foo `bar` baz</code> at the prompt.</p>
+ *
+ *    There's no arbitrary limit to the number of backticks you
+ *    can use as delimters. If you need three consecutive backticks
+ *    in your code, use four for delimiters, etc.
+ *
+ *  *  You can use spaces to get literal backticks at the edges:
+ *
+ *         ... type `` `bar` `` ...
+ *
+ *       Turns to:
+ *
+ *         ... type <code>`bar`</code> ...
+ */
+showdown.subParser('codeSpans', function (text, options, globals) {
+  'use strict';
+
+  text = globals.converter._dispatch('codeSpans.before', text, options, globals);
+
+  /*
+   text = text.replace(/
+   (^|[^\\])					// Character before opening ` can't be a backslash
+   (`+)						// $2 = Opening run of `
+   (							// $3 = The code block
+   [^\r]*?
+   [^`]					// attacklab: work around lack of lookbehind
+   )
+   \2							// Matching closer
+   (?!`)
+   /gm, function(){...});
+   */
+
+  if (typeof(text) === 'undefined') {
+    text = '';
+  }
+  text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,
+    function (wholeMatch, m1, m2, m3) {
+      var c = m3;
+      c = c.replace(/^([ \t]*)/g, '');	// leading whitespace
+      c = c.replace(/[ \t]*$/g, '');	// trailing whitespace
+      c = showdown.subParser('encodeCode')(c);
+      return m1 + '<code>' + c + '</code>';
+    }
+  );
+
+  text = globals.converter._dispatch('codeSpans.after', text, options, globals);
+  return text;
+});
+
+/**
+ * Convert all tabs to spaces
+ */
+showdown.subParser('detab', function (text) {
+  'use strict';
+
+  // expand first n-1 tabs
+  text = text.replace(/\t(?=\t)/g, '    '); // g_tab_width
+
+  // replace the nth with two sentinels
+  text = text.replace(/\t/g, '~A~B');
+
+  // use the sentinel to anchor our regex so it doesn't explode
+  text = text.replace(/~B(.+?)~A/g, function (wholeMatch, m1) {
+    var leadingText = m1,
+        numSpaces = 4 - leadingText.length % 4;  // g_tab_width
+
+    // there *must* be a better way to do this:
+    for (var i = 0; i < numSpaces; i++) {
+      leadingText += ' ';
+    }
+
+    return leadingText;
+  });
+
+  // clean up sentinels
+  text = text.replace(/~A/g, '    ');  // g_tab_width
+  text = text.replace(/~B/g, '');
+
+  return text;
+
+});
+
+/**
+ * Smart processing for ampersands and angle brackets that need to be encoded.
+ */
+showdown.subParser('encodeAmpsAndAngles', function (text) {
+  'use strict';
+  // Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin:
+  // http://bumppo.net/projects/amputator/
+  text = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g, '&amp;');
+
+  // Encode naked <'s
+  text = text.replace(/<(?![a-z\/?\$!])/gi, '&lt;');
+
+  return text;
+});
+
+/**
+ * Returns the string, with after processing the following backslash escape sequences.
+ *
+ * attacklab: The polite way to do this is with the new escapeCharacters() function:
+ *
+ *    text = escapeCharacters(text,"\\",true);
+ *    text = escapeCharacters(text,"`*_{}[]()>#+-.!",true);
+ *
+ * ...but we're sidestepping its use of the (slow) RegExp constructor
+ * as an optimization for Firefox.  This function gets called a LOT.
+ */
+showdown.subParser('encodeBackslashEscapes', function (text) {
+  'use strict';
+  text = text.replace(/\\(\\)/g, showdown.helper.escapeCharactersCallback);
+  text = text.replace(/\\([`*_{}\[\]()>#+-.!])/g, showdown.helper.escapeCharactersCallback);
+  return text;
+});
+
+/**
+ * Encode/escape certain characters inside Markdown code runs.
+ * The point is that in code, these characters are literals,
+ * and lose their special Markdown meanings.
+ */
+showdown.subParser('encodeCode', function (text) {
+  'use strict';
+
+  // Encode all ampersands; HTML entities are not
+  // entities within a Markdown code span.
+  text = text.replace(/&/g, '&amp;');
+
+  // Do the angle bracket song and dance:
+  text = text.replace(/</g, '&lt;');
+  text = text.replace(/>/g, '&gt;');
+
+  // Now, escape characters that are magic in Markdown:
+  text = showdown.helper.escapeCharacters(text, '*_{}[]\\', false);
+
+  // jj the line above breaks this:
+  //---
+  //* Item
+  //   1. Subitem
+  //            special char: *
+  // ---
+
+  return text;
+});
+
+/**
+ *  Input: an email address, e.g. "foo@example.com"
+ *
+ *  Output: the email address as a mailto link, with each character
+ *    of the address encoded as either a decimal or hex entity, in
+ *    the hopes of foiling most address harvesting spam bots. E.g.:
+ *
+ *    <a href="&#x6D;&#97;&#105;&#108;&#x74;&#111;:&#102;&#111;&#111;&#64;&#101;
+ *       x&#x61;&#109;&#x70;&#108;&#x65;&#x2E;&#99;&#111;&#109;">&#102;&#111;&#111;
+ *       &#64;&#101;x&#x61;&#109;&#x70;&#108;&#x65;&#x2E;&#99;&#111;&#109;</a>
+ *
+ *  Based on a filter by Matthew Wickline, posted to the BBEdit-Talk
+ *  mailing list: <http://tinyurl.com/yu7ue>
+ *
+ */
+showdown.subParser('encodeEmailAddress', function (addr) {
+  'use strict';
+
+  var encode = [
+    function (ch) {
+      return '&#' + ch.charCodeAt(0) + ';';
+    },
+    function (ch) {
+      return '&#x' + ch.charCodeAt(0).toString(16) + ';';
+    },
+    function (ch) {
+      return ch;
+    }
+  ];
+
+  addr = 'mailto:' + addr;
+
+  addr = addr.replace(/./g, function (ch) {
+    if (ch === '@') {
+      // this *must* be encoded. I insist.
+      ch = encode[Math.floor(Math.random() * 2)](ch);
+    } else if (ch !== ':') {
+      // leave ':' alone (to spot mailto: later)
+      var r = Math.random();
+      // roughly 10% raw, 45% hex, 45% dec
+      ch = (
+        r > 0.9 ? encode[2](ch) : r > 0.45 ? encode[1](ch) : encode[0](ch)
+      );
+    }
+    return ch;
+  });
+
+  addr = '<a href="' + addr + '">' + addr + '</a>';
+  addr = addr.replace(/">.+:/g, '">'); // strip the mailto: from the visible part
+
+  return addr;
+});
+
+/**
+ * Within tags -- meaning between < and > -- encode [\ ` * _] so they
+ * don't conflict with their use in Markdown for code, italics and strong.
+ */
+showdown.subParser('escapeSpecialCharsWithinTagAttributes', function (text) {
+  'use strict';
+
+  // Build a regex to find HTML tags and comments.  See Friedl's
+  // "Mastering Regular Expressions", 2nd Ed., pp. 200-201.
+  var regex = /(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|<!(--.*?--\s*)+>)/gi;
+
+  text = text.replace(regex, function (wholeMatch) {
+    var tag = wholeMatch.replace(/(.)<\/?code>(?=.)/g, '$1`');
+    tag = showdown.helper.escapeCharacters(tag, '\\`*_', false);
+    return tag;
+  });
+
+  return text;
+});
+
+/**
+ * Handle github codeblocks prior to running HashHTML so that
+ * HTML contained within the codeblock gets escaped properly
+ * Example:
+ * ```ruby
+ *     def hello_world(x)
+ *       puts "Hello, #{x}"
+ *     end
+ * ```
+ */
+showdown.subParser('githubCodeBlocks', function (text, options, globals) {
+  'use strict';
+
+  // early exit if option is not enabled
+  if (!options.ghCodeBlocks) {
+    return text;
+  }
+
+  text = globals.converter._dispatch('githubCodeBlocks.before', text, options, globals);
+
+  text += '~0';
+
+  text = text.replace(/(?:^|\n)```(.*)\n([\s\S]*?)\n```/g, function (wholeMatch, language, codeblock) {
+    var end = (options.omitExtraWLInCodeBlocks) ? '' : '\n';
+
+    // First parse the github code block
+    codeblock = showdown.subParser('encodeCode')(codeblock);
+    codeblock = showdown.subParser('detab')(codeblock);
+    codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines
+    codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing whitespace
+
+    codeblock = '<pre><code' + (language ? ' class="' + language + ' language-' + language + '"' : '') + '>' + codeblock + end + '</code></pre>';
+
+    codeblock = showdown.subParser('hashBlock')(codeblock, options, globals);
+
+    // Since GHCodeblocks can be false positives, we need to
+    // store the primitive text and the parsed text in a global var,
+    // and then return a token
+    return '\n\n~G' + (globals.ghCodeBlocks.push({text: wholeMatch, codeblock: codeblock}) - 1) + 'G\n\n';
+  });
+
+  // attacklab: strip sentinel
+  text = text.replace(/~0/, '');
+
+  return globals.converter._dispatch('githubCodeBlocks.after', text, options, globals);
+});
+
+showdown.subParser('hashBlock', function (text, options, globals) {
+  'use strict';
+  text = text.replace(/(^\n+|\n+$)/g, '');
+  return '\n\n~K' + (globals.gHtmlBlocks.push(text) - 1) + 'K\n\n';
+});
+
+showdown.subParser('hashElement', function (text, options, globals) {
+  'use strict';
+
+  return function (wholeMatch, m1) {
+    var blockText = m1;
+
+    // Undo double lines
+    blockText = blockText.replace(/\n\n/g, '\n');
+    blockText = blockText.replace(/^\n/, '');
+
+    // strip trailing blank lines
+    blockText = blockText.replace(/\n+$/g, '');
+
+    // Replace the element text with a marker ("~KxK" where x is its key)
+    blockText = '\n\n~K' + (globals.gHtmlBlocks.push(blockText) - 1) + 'K\n\n';
+
+    return blockText;
+  };
+});
+
+showdown.subParser('hashHTMLBlocks', function (text, options, globals) {
+  'use strict';
+
+  var blockTags = [
+      'pre',
+      'div',
+      'h1',
+      'h2',
+      'h3',
+      'h4',
+      'h5',
+      'h6',
+      'blockquote',
+      'table',
+      'dl',
+      'ol',
+      'ul',
+      'script',
+      'noscript',
+      'form',
+      'fieldset',
+      'iframe',
+      'math',
+      'style',
+      'section',
+      'header',
+      'footer',
+      'nav',
+      'article',
+      'aside',
+      'address',
+      'audio',
+      'canvas',
+      'figure',
+      'hgroup',
+      'output',
+      'video',
+      'p'
+    ],
+    repFunc = function (wholeMatch, match, left, right) {
+      var txt = wholeMatch;
+      // check if this html element is marked as markdown
+      // if so, it's contents should be parsed as markdown
+      if (left.search(/\bmarkdown\b/) !== -1) {
+        txt = left + globals.converter.makeHtml(match) + right;
+      }
+      return '\n\n~K' + (globals.gHtmlBlocks.push(txt) - 1) + 'K\n\n';
+    };
+
+  for (var i = 0; i < blockTags.length; ++i) {
+    text = showdown.helper.replaceRecursiveRegExp(text, repFunc, '^(?: |\\t){0,3}<' + blockTags[i] + '\\b[^>]*>', '</' + blockTags[i] + '>', 'gim');
+  }
+
+  // HR SPECIAL CASE
+  text = text.replace(/(\n[ ]{0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,
+    showdown.subParser('hashElement')(text, options, globals));
+
+  // Special case for standalone HTML comments:
+  text = text.replace(/(<!--[\s\S]*?-->)/g,
+    showdown.subParser('hashElement')(text, options, globals));
+
+  // PHP and ASP-style processor instructions (<?...?> and <%...%>)
+  text = text.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,
+    showdown.subParser('hashElement')(text, options, globals));
+  return text;
+});
+
+/**
+ * Hash span elements that should not be parsed as markdown
+ */
+showdown.subParser('hashHTMLSpans', function (text, config, globals) {
+  'use strict';
+
+  var matches = showdown.helper.matchRecursiveRegExp(text, '<code\\b[^>]*>', '</code>', 'gi');
+
+  for (var i = 0; i < matches.length; ++i) {
+    text = text.replace(matches[i][0], '~L' + (globals.gHtmlSpans.push(matches[i][0]) - 1) + 'L');
+  }
+  return text;
+});
+
+/**
+ * Unhash HTML spans
+ */
+showdown.subParser('unhashHTMLSpans', function (text, config, globals) {
+  'use strict';
+
+  for (var i = 0; i < globals.gHtmlSpans.length; ++i) {
+    text = text.replace('~L' + i + 'L', globals.gHtmlSpans[i]);
+  }
+
+  return text;
+});
+
+/**
+ * Hash span elements that should not be parsed as markdown
+ */
+showdown.subParser('hashPreCodeTags', function (text, config, globals) {
+  'use strict';
+
+  var repFunc = function (wholeMatch, match, left, right) {
+    // encode html entities
+    var codeblock = left + showdown.subParser('encodeCode')(match) + right;
+    return '\n\n~G' + (globals.ghCodeBlocks.push({text: wholeMatch, codeblock: codeblock}) - 1) + 'G\n\n';
+  };
+
+  text = showdown.helper.replaceRecursiveRegExp(text, repFunc, '^(?: |\\t){0,3}<pre\\b[^>]*>\\s*<code\\b[^>]*>', '^(?: |\\t){0,3}</code>\\s*</pre>', 'gim');
+  return text;
+});
+
+showdown.subParser('headers', function (text, options, globals) {
+  'use strict';
+
+  text = globals.converter._dispatch('headers.before', text, options, globals);
+
+  var prefixHeader = options.prefixHeaderId,
+      headerLevelStart = (isNaN(parseInt(options.headerLevelStart))) ? 1 : parseInt(options.headerLevelStart),
+
+  // Set text-style headers:
+  //	Header 1
+  //	========
+  //
+  //	Header 2
+  //	--------
+  //
+      setextRegexH1 = (options.smoothLivePreview) ? /^(.+)[ \t]*\n={2,}[ \t]*\n+/gm : /^(.+)[ \t]*\n=+[ \t]*\n+/gm,
+      setextRegexH2 = (options.smoothLivePreview) ? /^(.+)[ \t]*\n-{2,}[ \t]*\n+/gm : /^(.+)[ \t]*\n-+[ \t]*\n+/gm;
+
+  text = text.replace(setextRegexH1, function (wholeMatch, m1) {
+
+    var spanGamut = showdown.subParser('spanGamut')(m1, options, globals),
+        hID = (options.noHeaderId) ? '' : ' id="' + headerId(m1) + '"',
+        hLevel = headerLevelStart,
+        hashBlock = '<h' + hLevel + hID + '>' + spanGamut + '</h' + hLevel + '>';
+    return showdown.subParser('hashBlock')(hashBlock, options, globals);
+  });
+
+  text = text.replace(setextRegexH2, function (matchFound, m1) {
+    var spanGamut = showdown.subParser('spanGamut')(m1, options, globals),
+        hID = (options.noHeaderId) ? '' : ' id="' + headerId(m1) + '"',
+        hLevel = headerLevelStart + 1,
+      hashBlock = '<h' + hLevel + hID + '>' + spanGamut + '</h' + hLevel + '>';
+    return showdown.subParser('hashBlock')(hashBlock, options, globals);
+  });
+
+  // atx-style headers:
+  //  # Header 1
+  //  ## Header 2
+  //  ## Header 2 with closing hashes ##
+  //  ...
+  //  ###### Header 6
+  //
+  text = text.replace(/^(#{1,6})[ \t]*(.+?)[ \t]*#*\n+/gm, function (wholeMatch, m1, m2) {
+    var span = showdown.subParser('spanGamut')(m2, options, globals),
+        hID = (options.noHeaderId) ? '' : ' id="' + headerId(m2) + '"',
+        hLevel = headerLevelStart - 1 + m1.length,
+        header = '<h' + hLevel + hID + '>' + span + '</h' + hLevel + '>';
+
+    return showdown.subParser('hashBlock')(header, options, globals);
+  });
+
+  function headerId(m) {
+    var title, escapedId = m.replace(/[^\w]/g, '').toLowerCase();
+
+    if (globals.hashLinkCounts[escapedId]) {
+      title = escapedId + '-' + (globals.hashLinkCounts[escapedId]++);
+    } else {
+      title = escapedId;
+      globals.hashLinkCounts[escapedId] = 1;
+    }
+
+    // Prefix id to prevent causing inadvertent pre-existing style matches.
+    if (prefixHeader === true) {
+      prefixHeader = 'section';
+    }
+
+    if (showdown.helper.isString(prefixHeader)) {
+      return prefixHeader + title;
+    }
+    return title;
+  }
+
+  text = globals.converter._dispatch('headers.after', text, options, globals);
+  return text;
+});
+
+/**
+ * Turn Markdown image shortcuts into <img> tags.
+ */
+showdown.subParser('images', function (text, options, globals) {
+  'use strict';
+
+  text = globals.converter._dispatch('images.before', text, options, globals);
+
+  var inlineRegExp    = /!\[(.*?)]\s?\([ \t]*()<?(\S+?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(['"])(.*?)\6[ \t]*)?\)/g,
+      referenceRegExp = /!\[([^\]]*?)] ?(?:\n *)?\[(.*?)]()()()()()/g;
+
+  function writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title) {
+
+    var gUrls   = globals.gUrls,
+        gTitles = globals.gTitles,
+        gDims   = globals.gDimensions;
+
+    linkId = linkId.toLowerCase();
+
+    if (!title) {
+      title = '';
+    }
+
+    if (url === '' || url === null) {
+      if (linkId === '' || linkId === null) {
+        // lower-case and turn embedded newlines into spaces
+        linkId = altText.toLowerCase().replace(/ ?\n/g, ' ');
+      }
+      url = '#' + linkId;
+
+      if (!showdown.helper.isUndefined(gUrls[linkId])) {
+        url = gUrls[linkId];
+        if (!showdown.helper.isUndefined(gTitles[linkId])) {
+          title = gTitles[linkId];
+        }
+        if (!showdown.helper.isUndefined(gDims[linkId])) {
+          width = gDims[linkId].width;
+          height = gDims[linkId].height;
+        }
+      } else {
+        return wholeMatch;
+      }
+    }
+
+    altText = altText.replace(/"/g, '&quot;');
+    altText = showdown.helper.escapeCharacters(altText, '*_', false);
+    url = showdown.helper.escapeCharacters(url, '*_', false);
+    var result = '<img src="' + url + '" alt="' + altText + '"';
+
+    if (title) {
+      title = title.replace(/"/g, '&quot;');
+      title = showdown.helper.escapeCharacters(title, '*_', false);
+      result += ' title="' + title + '"';
+    }
+
+    if (width && height) {
+      width  = (width === '*') ? 'auto' : width;
+      height = (height === '*') ? 'auto' : height;
+
+      result += ' width="' + width + '"';
+      result += ' height="' + height + '"';
+    }
+
+    result += ' />';
+    return result;
+  }
+
+  // First, handle reference-style labeled images: ![alt text][id]
+  text = text.replace(referenceRegExp, writeImageTag);
+
+  // Next, handle inline images:  ![alt text](url =<width>x<height> "optional title")
+  text = text.replace(inlineRegExp, writeImageTag);
+
+  text = globals.converter._dispatch('images.after', text, options, globals);
+  return text;
+});
+
+showdown.subParser('italicsAndBold', function (text, options, globals) {
+  'use strict';
+
+  text = globals.converter._dispatch('italicsAndBold.before', text, options, globals);
+
+  if (options.literalMidWordUnderscores) {
+    //underscores
+    // Since we are consuming a \s character, we need to add it
+    text = text.replace(/(^|\s|>|\b)__(?=\S)([\s\S]+?)__(?=\b|<|\s|$)/gm, '$1<strong>$2</strong>');
+    text = text.replace(/(^|\s|>|\b)_(?=\S)([\s\S]+?)_(?=\b|<|\s|$)/gm, '$1<em>$2</em>');
+    //asterisks
+    text = text.replace(/(\*\*)(?=\S)([^\r]*?\S[*]*)\1/g, '<strong>$2</strong>');
+    text = text.replace(/(\*)(?=\S)([^\r]*?\S)\1/g, '<em>$2</em>');
+
+  } else {
+    // <strong> must go first:
+    text = text.replace(/(\*\*|__)(?=\S)([^\r]*?\S[*_]*)\1/g, '<strong>$2</strong>');
+    text = text.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g, '<em>$2</em>');
+  }
+
+  text = globals.converter._dispatch('italicsAndBold.after', text, options, globals);
+  return text;
+});
+
+/**
+ * Form HTML ordered (numbered) and unordered (bulleted) lists.
+ */
+showdown.subParser('lists', function (text, options, globals) {
+  'use strict';
+
+  text = globals.converter._dispatch('lists.before', text, options, globals);
+  /**
+   * Process the contents of a single ordered or unordered list, splitting it
+   * into individual list items.
+   * @param {string} listStr
+   * @param {boolean} trimTrailing
+   * @returns {string}
+   */
+  function processListItems (listStr, trimTrailing) {
+    // The $g_list_level global keeps track of when we're inside a list.
+    // Each time we enter a list, we increment it; when we leave a list,
+    // we decrement. If it's zero, we're not in a list anymore.
+    //
+    // We do this because when we're not inside a list, we want to treat
+    // something like this:
+    //
+    //    I recommend upgrading to version
+    //    8. Oops, now this line is treated
+    //    as a sub-list.
+    //
+    // As a single paragraph, despite the fact that the second line starts
+    // with a digit-period-space sequence.
+    //
+    // Whereas when we're inside a list (or sub-list), that line will be
+    // treated as the start of a sub-list. What a kludge, huh? This is
+    // an aspect of Markdown's syntax that's hard to parse perfectly
+    // without resorting to mind-reading. Perhaps the solution is to
+    // change the syntax rules such that sub-lists must start with a
+    // starting cardinal number; e.g. "1." or "a.".
+    globals.gListLevel++;
+
+    // trim trailing blank lines:
+    listStr = listStr.replace(/\n{2,}$/, '\n');
+
+    // attacklab: add sentinel to emulate \z
+    listStr += '~0';
+
+    var rgx = /(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+((\[(x|X| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm,
+        isParagraphed = (/\n[ \t]*\n(?!~0)/.test(listStr));
+
+    listStr = listStr.replace(rgx, function (wholeMatch, m1, m2, m3, m4, taskbtn, checked) {
+      checked = (checked && checked.trim() !== '');
+      var item = showdown.subParser('outdent')(m4, options, globals),
+          bulletStyle = '';
+
+      // Support for github tasklists
+      if (taskbtn && options.tasklists) {
+        bulletStyle = ' class="task-list-item" style="list-style-type: none;"';
+        item = item.replace(/^[ \t]*\[(x|X| )?]/m, function () {
+          var otp = '<input type="checkbox" disabled style="margin: 0px 0.35em 0.25em -1.6em; vertical-align: middle;"';
+          if (checked) {
+            otp += ' checked';
+          }
+          otp += '>';
+          return otp;
+        });
+      }
+      // m1 - Leading line or
+      // Has a double return (multi paragraph) or
+      // Has sublist
+      if (m1 || (item.search(/\n{2,}/) > -1)) {
+        item = showdown.subParser('githubCodeBlocks')(item, options, globals);
+        item = showdown.subParser('blockGamut')(item, options, globals);
+      } else {
+        // Recursion for sub-lists:
+        item = showdown.subParser('lists')(item, options, globals);
+        item = item.replace(/\n$/, ''); // chomp(item)
+        if (isParagraphed) {
+          item = showdown.subParser('paragraphs')(item, options, globals);
+        } else {
+          item = showdown.subParser('spanGamut')(item, options, globals);
+        }
+      }
+      item =  '\n<li' + bulletStyle + '>' + item + '</li>\n';
+      return item;
+    });
+
+    // attacklab: strip sentinel
+    listStr = listStr.replace(/~0/g, '');
+
+    globals.gListLevel--;
+
+    if (trimTrailing) {
+      listStr = listStr.replace(/\s+$/, '');
+    }
+
+    return listStr;
+  }
+
+  /**
+   * Check and parse consecutive lists (better fix for issue #142)
+   * @param {string} list
+   * @param {string} listType
+   * @param {boolean} trimTrailing
+   * @returns {string}
+   */
+  function parseConsecutiveLists(list, listType, trimTrailing) {
+    // check if we caught 2 or more consecutive lists by mistake
+    // we use the counterRgx, meaning if listType is UL we look for UL and vice versa
+    var counterRxg = (listType === 'ul') ? /^ {0,2}\d+\.[ \t]/gm : /^ {0,2}[*+-][ \t]/gm,
+      subLists = [],
+      result = '';
+
+    if (list.search(counterRxg) !== -1) {
+      (function parseCL(txt) {
+        var pos = txt.search(counterRxg);
+        if (pos !== -1) {
+          // slice
+          result += '\n\n<' + listType + '>' + processListItems(txt.slice(0, pos), !!trimTrailing) + '</' + listType + '>\n\n';
+
+          // invert counterType and listType
+          listType = (listType === 'ul') ? 'ol' : 'ul';
+          counterRxg = (listType === 'ul') ? /^ {0,2}\d+\.[ \t]/gm : /^ {0,2}[*+-][ \t]/gm;
+
+          //recurse
+          parseCL(txt.slice(pos));
+        } else {
+          result += '\n\n<' + listType + '>' + processListItems(txt, !!trimTrailing) + '</' + listType + '>\n\n';
+        }
+      })(list);
+      for (var i = 0; i < subLists.length; ++i) {
+
+      }
+    } else {
+      result = '\n\n<' + listType + '>' + processListItems(list, !!trimTrailing) + '</' + listType + '>\n\n';
+    }
+
+    return result;
+  }
+
+  // attacklab: add sentinel to hack around khtml/safari bug:
+  // http://bugs.webkit.org/show_bug.cgi?id=11231
+  text += '~0';
+
+  // Re-usable pattern to match any entire ul or ol list:
+  var wholeList = /^(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm;
+
+  if (globals.gListLevel) {
+    text = text.replace(wholeList, function (wholeMatch, list, m2) {
+      var listType = (m2.search(/[*+-]/g) > -1) ? 'ul' : 'ol';
+      return parseConsecutiveLists(list, listType, true);
+    });
+  } else {
+    wholeList = /(\n\n|^\n?)(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm;
+    //wholeList = /(\n\n|^\n?)( {0,3}([*+-]|\d+\.)[ \t]+[\s\S]+?)(?=(~0)|(\n\n(?!\t| {2,}| {0,3}([*+-]|\d+\.)[ \t])))/g;
+    text = text.replace(wholeList, function (wholeMatch, m1, list, m3) {
+
+      var listType = (m3.search(/[*+-]/g) > -1) ? 'ul' : 'ol';
+      return parseConsecutiveLists(list, listType);
+    });
+  }
+
+  // attacklab: strip sentinel
+  text = text.replace(/~0/, '');
+
+  text = globals.converter._dispatch('lists.after', text, options, globals);
+  return text;
+});
+
+/**
+ * Remove one level of line-leading tabs or spaces
+ */
+showdown.subParser('outdent', function (text) {
+  'use strict';
+
+  // attacklab: hack around Konqueror 3.5.4 bug:
+  // "----------bug".replace(/^-/g,"") == "bug"
+  text = text.replace(/^(\t|[ ]{1,4})/gm, '~0'); // attacklab: g_tab_width
+
+  // attacklab: clean up hack
+  text = text.replace(/~0/g, '');
+
+  return text;
+});
+
+/**
+ *
+ */
+showdown.subParser('paragraphs', function (text, options, globals) {
+  'use strict';
+
+  text = globals.converter._dispatch('paragraphs.before', text, options, globals);
+  // Strip leading and trailing lines:
+  text = text.replace(/^\n+/g, '');
+  text = text.replace(/\n+$/g, '');
+
+  var grafs = text.split(/\n{2,}/g),
+      grafsOut = [],
+      end = grafs.length; // Wrap <p> tags
+
+  for (var i = 0; i < end; i++) {
+    var str = grafs[i];
+    // if this is an HTML marker, copy it
+    if (str.search(/~(K|G)(\d+)\1/g) >= 0) {
+      grafsOut.push(str);
+    } else {
+      str = showdown.subParser('spanGamut')(str, options, globals);
+      str = str.replace(/^([ \t]*)/g, '<p>');
+      str += '</p>';
+      grafsOut.push(str);
+    }
+  }
+
+  /** Unhashify HTML blocks */
+  end = grafsOut.length;
+  for (i = 0; i < end; i++) {
+    var blockText = '',
+        grafsOutIt = grafsOut[i],
+        codeFlag = false;
+    // if this is a marker for an html block...
+    while (grafsOutIt.search(/~(K|G)(\d+)\1/) >= 0) {
+      var delim = RegExp.$1,
+          num   = RegExp.$2;
+
+      if (delim === 'K') {
+        blockText = globals.gHtmlBlocks[num];
+      } else {
+        // we need to check if ghBlock is a false positive
+        if (codeFlag) {
+          // use encoded version of all text
+          blockText = showdown.subParser('encodeCode')(globals.ghCodeBlocks[num].text);
+        } else {
+          blockText = globals.ghCodeBlocks[num].codeblock;
+        }
+      }
+      blockText = blockText.replace(/\$/g, '$$$$'); // Escape any dollar signs
+
+      grafsOutIt = grafsOutIt.replace(/(\n\n)?~(K|G)\d+\2(\n\n)?/, blockText);
+      // Check if grafsOutIt is a pre->code
+      if (/^<pre\b[^>]*>\s*<code\b[^>]*>/.test(grafsOutIt)) {
+        codeFlag = true;
+      }
+    }
+    grafsOut[i] = grafsOutIt;
+  }
+  text = grafsOut.join('\n\n');
+  // Strip leading and trailing lines:
+  text = text.replace(/^\n+/g, '');
+  text = text.replace(/\n+$/g, '');
+  return globals.converter._dispatch('paragraphs.after', text, options, globals);
+});
+
+/**
+ * Run extension
+ */
+showdown.subParser('runExtension', function (ext, text, options, globals) {
+  'use strict';
+
+  if (ext.filter) {
+    text = ext.filter(text, globals.converter, options);
+
+  } else if (ext.regex) {
+    // TODO remove this when old extension loading mechanism is deprecated
+    var re = ext.regex;
+    if (!re instanceof RegExp) {
+      re = new RegExp(re, 'g');
+    }
+    text = text.replace(re, ext.replace);
+  }
+
+  return text;
+});
+
+/**
+ * These are all the transformations that occur *within* block-level
+ * tags like paragraphs, headers, and list items.
+ */
+showdown.subParser('spanGamut', function (text, options, globals) {
+  'use strict';
+
+  text = globals.converter._dispatch('spanGamut.before', text, options, globals);
+  text = showdown.subParser('codeSpans')(text, options, globals);
+  text = showdown.subParser('escapeSpecialCharsWithinTagAttributes')(text, options, globals);
+  text = showdown.subParser('encodeBackslashEscapes')(text, options, globals);
+
+  // Process anchor and image tags. Images must come first,
+  // because ![foo][f] looks like an anchor.
+  text = showdown.subParser('images')(text, options, globals);
+  text = showdown.subParser('anchors')(text, options, globals);
+
+  // Make links out of things like `<http://example.com/>`
+  // Must come after _DoAnchors(), because you can use < and >
+  // delimiters in inline links like [this](<url>).
+  text = showdown.subParser('autoLinks')(text, options, globals);
+  text = showdown.subParser('encodeAmpsAndAngles')(text, options, globals);
+  text = showdown.subParser('italicsAndBold')(text, options, globals);
+  text = showdown.subParser('strikethrough')(text, options, globals);
+
+  // Do hard breaks:
+  text = text.replace(/  +\n/g, ' <br />\n');
+
+  text = globals.converter._dispatch('spanGamut.after', text, options, globals);
+  return text;
+});
+
+showdown.subParser('strikethrough', function (text, options, globals) {
+  'use strict';
+
+  if (options.strikethrough) {
+    text = globals.converter._dispatch('strikethrough.before', text, options, globals);
+    text = text.replace(/(?:~T){2}([\s\S]+?)(?:~T){2}/g, '<del>$1</del>');
+    text = globals.converter._dispatch('strikethrough.after', text, options, globals);
+  }
+
+  return text;
+});
+
+/**
+ * Strip any lines consisting only of spaces and tabs.
+ * This makes subsequent regexs easier to write, because we can
+ * match consecutive blank lines with /\n+/ instead of something
+ * contorted like /[ \t]*\n+/
+ */
+showdown.subParser('stripBlankLines', function (text) {
+  'use strict';
+  return text.replace(/^[ \t]+$/mg, '');
+});
+
+/**
+ * Strips link definitions from text, stores the URLs and titles in
+ * hash references.
+ * Link defs are in the form: ^[id]: url "optional title"
+ *
+ * ^[ ]{0,3}\[(.+)\]: // id = $1  attacklab: g_tab_width - 1
+ * [ \t]*
+ * \n?                  // maybe *one* newline
+ * [ \t]*
+ * <?(\S+?)>?          // url = $2
+ * [ \t]*
+ * \n?                // maybe one newline
+ * [ \t]*
+ * (?:
+ * (\n*)              // any lines skipped = $3 attacklab: lookbehind removed
+ * ["(]
+ * (.+?)              // title = $4
+ * [")]
+ * [ \t]*
+ * )?                 // title is optional
+ * (?:\n+|$)
+ * /gm,
+ * function(){...});
+ *
+ */
+showdown.subParser('stripLinkDefinitions', function (text, options, globals) {
+  'use strict';
+
+  var regex = /^ {0,3}\[(.+)]:[ \t]*\n?[ \t]*<?(\S+?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n+|(?=~0))/gm;
+
+  // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
+  text += '~0';
+
+  text = text.replace(regex, function (wholeMatch, linkId, url, width, height, blankLines, title) {
+    linkId = linkId.toLowerCase();
+    globals.gUrls[linkId] = showdown.subParser('encodeAmpsAndAngles')(url);  // Link IDs are case-insensitive
+
+    if (blankLines) {
+      // Oops, found blank lines, so it's not a title.
+      // Put back the parenthetical statement we stole.
+      return blankLines + title;
+
+    } else {
+      if (title) {
+        globals.gTitles[linkId] = title.replace(/"|'/g, '&quot;');
+      }
+      if (options.parseImgDimensions && width && height) {
+        globals.gDimensions[linkId] = {
+          width:  width,
+          height: height
+        };
+      }
+    }
+    // Completely remove the definition from the text
+    return '';
+  });
+
+  // attacklab: strip sentinel
+  text = text.replace(/~0/, '');
+
+  return text;
+});
+
+showdown.subParser('tables', function (text, options, globals) {
+  'use strict';
+
+  if (!options.tables) {
+    return text;
+  }
+
+  var tableRgx = /^[ \t]{0,3}\|?.+\|.+\n[ \t]{0,3}\|?[ \t]*:?[ \t]*(?:-|=){2,}[ \t]*:?[ \t]*\|[ \t]*:?[ \t]*(?:-|=){2,}[\s\S]+?(?:\n\n|~0)/gm;
+
+  function parseStyles(sLine) {
+    if (/^:[ \t]*--*$/.test(sLine)) {
+      return ' style="text-align:left;"';
+    } else if (/^--*[ \t]*:[ \t]*$/.test(sLine)) {
+      return ' style="text-align:right;"';
+    } else if (/^:[ \t]*--*[ \t]*:$/.test(sLine)) {
+      return ' style="text-align:center;"';
+    } else {
+      return '';
+    }
+  }
+
+  function parseHeaders(header, style) {
+    var id = '';
+    header = header.trim();
+    if (options.tableHeaderId) {
+      id = ' id="' + header.replace(/ /g, '_').toLowerCase() + '"';
+    }
+    header = showdown.subParser('spanGamut')(header, options, globals);
+
+    return '<th' + id + style + '>' + header + '</th>\n';
+  }
+
+  function parseCells(cell, style) {
+    var subText = showdown.subParser('spanGamut')(cell, options, globals);
+    return '<td' + style + '>' + subText + '</td>\n';
+  }
+
+  function buildTable(headers, cells) {
+    var tb = '<table>\n<thead>\n<tr>\n',
+        tblLgn = headers.length;
+
+    for (var i = 0; i < tblLgn; ++i) {
+      tb += headers[i];
+    }
+    tb += '</tr>\n</thead>\n<tbody>\n';
+
+    for (i = 0; i < cells.length; ++i) {
+      tb += '<tr>\n';
+      for (var ii = 0; ii < tblLgn; ++ii) {
+        tb += cells[i][ii];
+      }
+      tb += '</tr>\n';
+    }
+    tb += '</tbody>\n</table>\n';
+    return tb;
+  }
+
+  text = globals.converter._dispatch('tables.before', text, options, globals);
+
+  text = text.replace(tableRgx, function (rawTable) {
+
+    var i, tableLines = rawTable.split('\n');
+
+    // strip wrong first and last column if wrapped tables are used
+    for (i = 0; i < tableLines.length; ++i) {
+      if (/^[ \t]{0,3}\|/.test(tableLines[i])) {
+        tableLines[i] = tableLines[i].replace(/^[ \t]{0,3}\|/, '');
+      }
+      if (/\|[ \t]*$/.test(tableLines[i])) {
+        tableLines[i] = tableLines[i].replace(/\|[ \t]*$/, '');
+      }
+    }
+
+    var rawHeaders = tableLines[0].split('|').map(function (s) { return s.trim();}),
+        rawStyles = tableLines[1].split('|').map(function (s) { return s.trim();}),
+        rawCells = [],
+        headers = [],
+        styles = [],
+        cells = [];
+
+    tableLines.shift();
+    tableLines.shift();
+
+    for (i = 0; i < tableLines.length; ++i) {
+      if (tableLines[i].trim() === '') {
+        continue;
+      }
+      rawCells.push(
+        tableLines[i]
+          .split('|')
+          .map(function (s) {
+            return s.trim();
+          })
+      );
+    }
+
+    if (rawHeaders.length < rawStyles.length) {
+      return rawTable;
+    }
+
+    for (i = 0; i < rawStyles.length; ++i) {
+      styles.push(parseStyles(rawStyles[i]));
+    }
+
+    for (i = 0; i < rawHeaders.length; ++i) {
+      if (showdown.helper.isUndefined(styles[i])) {
+        styles[i] = '';
+      }
+      headers.push(parseHeaders(rawHeaders[i], styles[i]));
+    }
+
+    for (i = 0; i < rawCells.length; ++i) {
+      var row = [];
+      for (var ii = 0; ii < headers.length; ++ii) {
+        if (showdown.helper.isUndefined(rawCells[i][ii])) {
+
+        }
+        row.push(parseCells(rawCells[i][ii], styles[ii]));
+      }
+      cells.push(row);
+    }
+
+    return buildTable(headers, cells);
+  });
+
+  text = globals.converter._dispatch('tables.after', text, options, globals);
+
+  return text;
+});
+
+/**
+ * Swap back in all the special characters we've hidden.
+ */
+showdown.subParser('unescapeSpecialChars', function (text) {
+  'use strict';
+
+  text = text.replace(/~E(\d+)E/g, function (wholeMatch, m1) {
+    var charCodeToReplace = parseInt(m1);
+    return String.fromCharCode(charCodeToReplace);
+  });
+  return text;
+});
+module.exports = showdown;

+ 206 - 0
wx-mall-hk/lib/wxParse/wxDiscode.js

@@ -0,0 +1,206 @@
+// HTML 支持的数学符号
+function strNumDiscode(str){
+    str = str.replace(/&forall;/g, '∀');
+    str = str.replace(/&part;/g, '∂');
+    str = str.replace(/&exists;/g, '∃');
+    str = str.replace(/&empty;/g, '∅');
+    str = str.replace(/&nabla;/g, '∇');
+    str = str.replace(/&isin;/g, '∈');
+    str = str.replace(/&notin;/g, '∉');
+    str = str.replace(/&ni;/g, '∋');
+    str = str.replace(/&prod;/g, '∏');
+    str = str.replace(/&sum;/g, '∑');
+    str = str.replace(/&minus;/g, '−');
+    str = str.replace(/&lowast;/g, '∗');
+    str = str.replace(/&radic;/g, '√');
+    str = str.replace(/&prop;/g, '∝');
+    str = str.replace(/&infin;/g, '∞');
+    str = str.replace(/&ang;/g, '∠');
+    str = str.replace(/&and;/g, '∧');
+    str = str.replace(/&or;/g, '∨');
+    str = str.replace(/&cap;/g, '∩');
+    str = str.replace(/&cap;/g, '∪');
+    str = str.replace(/&int;/g, '∫');
+    str = str.replace(/&there4;/g, '∴');
+    str = str.replace(/&sim;/g, '∼');
+    str = str.replace(/&cong;/g, '≅');
+    str = str.replace(/&asymp;/g, '≈');
+    str = str.replace(/&ne;/g, '≠');
+    str = str.replace(/&le;/g, '≤');
+    str = str.replace(/&ge;/g, '≥');
+    str = str.replace(/&sub;/g, '⊂');
+    str = str.replace(/&sup;/g, '⊃');
+    str = str.replace(/&nsub;/g, '⊄');
+    str = str.replace(/&sube;/g, '⊆');
+    str = str.replace(/&supe;/g, '⊇');
+    str = str.replace(/&oplus;/g, '⊕');
+    str = str.replace(/&otimes;/g, '⊗');
+    str = str.replace(/&perp;/g, '⊥');
+    str = str.replace(/&sdot;/g, '⋅');
+    return str;
+}
+
+//HTML 支持的希腊字母
+function strGreeceDiscode(str){
+    str = str.replace(/&Alpha;/g, 'Α');
+    str = str.replace(/&Beta;/g, 'Β');
+    str = str.replace(/&Gamma;/g, 'Γ');
+    str = str.replace(/&Delta;/g, 'Δ');
+    str = str.replace(/&Epsilon;/g, 'Ε');
+    str = str.replace(/&Zeta;/g, 'Ζ');
+    str = str.replace(/&Eta;/g, 'Η');
+    str = str.replace(/&Theta;/g, 'Θ');
+    str = str.replace(/&Iota;/g, 'Ι');
+    str = str.replace(/&Kappa;/g, 'Κ');
+    str = str.replace(/&Lambda;/g, 'Λ');
+    str = str.replace(/&Mu;/g, 'Μ');
+    str = str.replace(/&Nu;/g, 'Ν');
+    str = str.replace(/&Xi;/g, 'Ν');
+    str = str.replace(/&Omicron;/g, 'Ο');
+    str = str.replace(/&Pi;/g, 'Π');
+    str = str.replace(/&Rho;/g, 'Ρ');
+    str = str.replace(/&Sigma;/g, 'Σ');
+    str = str.replace(/&Tau;/g, 'Τ');
+    str = str.replace(/&Upsilon;/g, 'Υ');
+    str = str.replace(/&Phi;/g, 'Φ');
+    str = str.replace(/&Chi;/g, 'Χ');
+    str = str.replace(/&Psi;/g, 'Ψ');
+    str = str.replace(/&Omega;/g, 'Ω');
+
+    str = str.replace(/&alpha;/g, 'α');
+    str = str.replace(/&beta;/g, 'β');
+    str = str.replace(/&gamma;/g, 'γ');
+    str = str.replace(/&delta;/g, 'δ');
+    str = str.replace(/&epsilon;/g, 'ε');
+    str = str.replace(/&zeta;/g, 'ζ');
+    str = str.replace(/&eta;/g, 'η');
+    str = str.replace(/&theta;/g, 'θ');
+    str = str.replace(/&iota;/g, 'ι');
+    str = str.replace(/&kappa;/g, 'κ');
+    str = str.replace(/&lambda;/g, 'λ');
+    str = str.replace(/&mu;/g, 'μ');
+    str = str.replace(/&nu;/g, 'ν');
+    str = str.replace(/&xi;/g, 'ξ');
+    str = str.replace(/&omicron;/g, 'ο');
+    str = str.replace(/&pi;/g, 'π');
+    str = str.replace(/&rho;/g, 'ρ');
+    str = str.replace(/&sigmaf;/g, 'ς');
+    str = str.replace(/&sigma;/g, 'σ');
+    str = str.replace(/&tau;/g, 'τ');
+    str = str.replace(/&upsilon;/g, 'υ');
+    str = str.replace(/&phi;/g, 'φ');
+    str = str.replace(/&chi;/g, 'χ');
+    str = str.replace(/&psi;/g, 'ψ');
+    str = str.replace(/&omega;/g, 'ω');
+    str = str.replace(/&thetasym;/g, 'ϑ');
+    str = str.replace(/&upsih;/g, 'ϒ');
+    str = str.replace(/&piv;/g, 'ϖ');
+    str = str.replace(/&middot;/g, '·');
+    return str;
+}
+
+// 
+
+function strcharacterDiscode(str){
+    // 加入常用解析
+    str = str.replace(/&nbsp;/g, ' ');
+    str = str.replace(/&quot;/g, '"');
+    str = str.replace(/&amp;/g, '&');
+    // str = str.replace(/&lt;/g, '‹');
+    // str = str.replace(/&gt;/g, '›');
+
+    str = str.replace(/&lt;/g, '<');
+    str = str.replace(/&gt;/g, '>');
+
+    return str;
+}
+
+// HTML 支持的其他实体
+function strOtherDiscode(str){
+    str = str.replace(/&OElig;/g, 'Œ');
+    str = str.replace(/&oelig;/g, 'œ');
+    str = str.replace(/&Scaron;/g, 'Š');
+    str = str.replace(/&scaron;/g, 'š');
+    str = str.replace(/&Yuml;/g, 'Ÿ');
+    str = str.replace(/&fnof;/g, 'ƒ');
+    str = str.replace(/&circ;/g, 'ˆ');
+    str = str.replace(/&tilde;/g, '˜');
+    str = str.replace(/&ensp;/g, '');
+    str = str.replace(/&emsp;/g, '');
+    str = str.replace(/&thinsp;/g, '');
+    str = str.replace(/&zwnj;/g, '');
+    str = str.replace(/&zwj;/g, '');
+    str = str.replace(/&lrm;/g, '');
+    str = str.replace(/&rlm;/g, '');
+    str = str.replace(/&ndash;/g, '–');
+    str = str.replace(/&mdash;/g, '—');
+    str = str.replace(/&lsquo;/g, '‘');
+    str = str.replace(/&rsquo;/g, '’');
+    str = str.replace(/&sbquo;/g, '‚');
+    str = str.replace(/&ldquo;/g, '“');
+    str = str.replace(/&rdquo;/g, '”');
+    str = str.replace(/&bdquo;/g, '„');
+    str = str.replace(/&dagger;/g, '†');
+    str = str.replace(/&Dagger;/g, '‡');
+    str = str.replace(/&bull;/g, '•');
+    str = str.replace(/&hellip;/g, '…');
+    str = str.replace(/&permil;/g, '‰');
+    str = str.replace(/&prime;/g, '′');
+    str = str.replace(/&Prime;/g, '″');
+    str = str.replace(/&lsaquo;/g, '‹');
+    str = str.replace(/&rsaquo;/g, '›');
+    str = str.replace(/&oline;/g, '‾');
+    str = str.replace(/&euro;/g, '€');
+    str = str.replace(/&trade;/g, '™');
+
+    str = str.replace(/&larr;/g, '←');
+    str = str.replace(/&uarr;/g, '↑');
+    str = str.replace(/&rarr;/g, '→');
+    str = str.replace(/&darr;/g, '↓');
+    str = str.replace(/&harr;/g, '↔');
+    str = str.replace(/&crarr;/g, '↵');
+    str = str.replace(/&lceil;/g, '⌈');
+    str = str.replace(/&rceil;/g, '⌉');
+
+    str = str.replace(/&lfloor;/g, '⌊');
+    str = str.replace(/&rfloor;/g, '⌋');
+    str = str.replace(/&loz;/g, '◊');
+    str = str.replace(/&spades;/g, '♠');
+    str = str.replace(/&clubs;/g, '♣');
+    str = str.replace(/&hearts;/g, '♥');
+
+    str = str.replace(/&diams;/g, '♦');
+
+    return str;
+}
+
+function strMoreDiscode(str){
+    str = str.replace(/\r\n/g,"");  
+    str = str.replace(/\n/g,"");
+
+    str = str.replace(/code/g,"wxxxcode-style");
+    return str;
+}
+
+function strDiscode(str){
+    str = strNumDiscode(str);
+    str = strGreeceDiscode(str);
+    str = strcharacterDiscode(str);
+    str = strOtherDiscode(str);
+    str = strMoreDiscode(str);
+    return str;
+}
+function urlToHttpUrl(url,rep){
+    
+    var patt1 = new RegExp("^//");
+    var result = patt1.test(url);
+    if(result){
+        url = rep+":"+url;
+    }
+    return  url;
+}
+
+module.exports = {
+    strDiscode:strDiscode,
+    urlToHttpUrl:urlToHttpUrl
+}

+ 146 - 0
wx-mall-hk/lib/wxParse/wxParse.js

@@ -0,0 +1,146 @@
+/**
+ * author: Di (微信小程序开发工程师)
+ * organization: WeAppDev(微信小程序开发论坛)(http://weappdev.com)
+ *               垂直微信小程序开发交流社区
+ * 
+ * github地址: https://github.com/icindy/wxParse
+ * 
+ * for: 微信小程序富文本解析
+ * detail : http://weappdev.com/t/wxparse-alpha0-1-html-markdown/184
+ */
+
+/**
+ * utils函数引入
+ **/
+import showdown from 'showdown.js';
+import HtmlToJson from 'html2json.js';
+/**
+ * 配置及公有属性
+ **/
+/**
+ * 主函数入口区
+ **/
+function wxParse(bindName = 'wxParseData', type='html', data='<div class="color:red;">数据不能为空</div>', target,imagePadding) {
+  var that = target;
+  var transData = {};//存放转化后的数据
+  if (type == 'html') {
+    transData = HtmlToJson.html2json(data, bindName);
+    // console.log(JSON.stringify(transData, ' ', ' '));
+  } else if (type == 'md' || type == 'markdown') {
+    var converter = new showdown.Converter();
+    var html = converter.makeHtml(data);
+    transData = HtmlToJson.html2json(html, bindName);
+    // console.log(JSON.stringify(transData, ' ', ' '));
+  }
+  transData.view = {};
+  transData.view.imagePadding = 0;
+  if(typeof(imagePadding) != 'undefined'){
+    transData.view.imagePadding = imagePadding
+  }
+  var bindData = {};
+  bindData[bindName] = transData;
+  that.setData(bindData)
+  that.wxParseImgLoad = wxParseImgLoad;
+  that.wxParseImgTap = wxParseImgTap;
+}
+// 图片点击事件
+function wxParseImgTap(e) {
+  var that = this;
+  var nowImgUrl = e.target.dataset.src;
+  var tagFrom = e.target.dataset.from;
+  if (typeof (tagFrom) != 'undefined' && tagFrom.length > 0) {
+    wx.previewImage({
+      current: nowImgUrl, // 当前显示图片的http链接
+      urls: that.data[tagFrom].imageUrls // 需要预览的图片http链接列表
+    })
+  }
+}
+
+/**
+ * 图片视觉宽高计算函数区 
+ **/
+function wxParseImgLoad(e) {
+  var that = this;
+  var tagFrom = e.target.dataset.from;
+  var idx = e.target.dataset.idx;
+  if (typeof (tagFrom) != 'undefined' && tagFrom.length > 0) {
+    calMoreImageInfo(e, idx, that, tagFrom)
+  } 
+}
+// 假循环获取计算图片视觉最佳宽高
+function calMoreImageInfo(e, idx, that, bindName) {
+  var temData = that.data[bindName];
+  if (temData.images.length == 0) {
+    return;
+  }
+  var temImages = temData.images;
+  //因为无法获取view宽度 需要自定义padding进行计算,稍后处理
+  var recal = wxAutoImageCal(e.detail.width, e.detail.height,that,bindName); 
+  temImages[idx].width = recal.imageWidth;
+  temImages[idx].height = recal.imageheight; 
+  temData.images = temImages;
+  var bindData = {};
+  bindData[bindName] = temData;
+  that.setData(bindData);
+}
+
+// 计算视觉优先的图片宽高
+function wxAutoImageCal(originalWidth, originalHeight,that,bindName) {
+  //获取图片的原始长宽
+  var windowWidth = 0, windowHeight = 0;
+  var autoWidth = 0, autoHeight = 0;
+  var results = {};
+  wx.getSystemInfo({
+    success: function (res) {
+      var padding = that.data[bindName].view.imagePadding;
+      windowWidth = res.windowWidth-2*padding;
+      windowHeight = res.windowHeight;
+      //判断按照那种方式进行缩放
+      // console.log("windowWidth" + windowWidth);
+      if (originalWidth > windowWidth) {//在图片width大于手机屏幕width时候
+        autoWidth = windowWidth;
+        // console.log("autoWidth" + autoWidth);
+        autoHeight = (autoWidth * originalHeight) / originalWidth;
+        // console.log("autoHeight" + autoHeight);
+        results.imageWidth = autoWidth;
+        results.imageheight = autoHeight;
+      } else {//否则展示原来的数据
+        results.imageWidth = originalWidth;
+        results.imageheight = originalHeight;
+      }
+    }
+  })
+  return results;
+}
+
+function wxParseTemArray(temArrayName,bindNameReg,total,that){
+  var array = [];
+  var temData = that.data;
+  var obj = null;
+  for(var i = 0; i < total; i++){
+    var simArr = temData[bindNameReg+i].nodes;
+    array.push(simArr);
+  }
+
+  temArrayName = temArrayName || 'wxParseTemArray';
+  obj = JSON.parse('{"'+ temArrayName +'":""}');
+  obj[temArrayName] = array;
+  that.setData(obj);
+}
+
+/**
+ * 配置emojis
+ * 
+ */
+
+function emojisInit(reg='',baseSrc="/wxParse/emojis/",emojis){
+   HtmlToJson.emojisInit(reg,baseSrc,emojis);
+}
+
+module.exports = {
+  wxParse: wxParse,
+  wxParseTemArray:wxParseTemArray,
+  emojisInit:emojisInit
+}
+
+

+ 928 - 0
wx-mall-hk/lib/wxParse/wxParse.wxml

@@ -0,0 +1,928 @@
+
+<!--**
+ * author: Di (微信小程序开发工程师)
+ * organization: WeAppDev(微信小程序开发论坛)(http://weappdev.com)
+ *               垂直微信小程序开发交流社区
+ * 
+ * github地址: https://github.com/icindy/wxParse
+ * 
+ * for: 微信小程序富文本解析
+ * detail : http://weappdev.com/t/wxparse-alpha0-1-html-markdown/184
+ */-->
+
+ <!--基础元素-->
+<template name="wxParseVideo">
+    <!--增加video标签支持,并循环添加-->
+    <view class="{{item.classStr}} wxParse-{{item.tag}}" style="{{item.styleStr}}">
+        <video class="{{item.classStr}} wxParse-{{item.tag}}-video" src="{{item.attr.src}}"></video>
+    </view>
+</template>
+
+<template name="wxParseImg">
+    <image class="{{item.classStr}} wxParse-{{item.tag}}" data-from="{{item.from}}" data-src="{{item.attr.src}}"  data-idx="{{item.imgIndex}}"  src="{{item.attr.src}}" mode="aspectFit" bindload="wxParseImgLoad" bindtap="wxParseImgTap" style="width:{{item.width}}px;height:{{item.height}}px;{{item.attr.style}}"   />
+</template>
+
+<template name="WxEmojiView">
+  <view class="WxEmojiView wxParse-inline" style="{{item.styleStr}}">
+    <block wx:for="{{item.textArray}}" wx:key="">
+      <block class="{{item.text == '\\n' ? 'wxParse-hide':''}}" wx:if="{{item.node == 'text'}}">{{item.text}}</block>
+      <block wx:elif="{{item.node == 'element'}}">
+        <image class="wxEmoji" src="{{item.baseSrc}}{{item.text}}" />
+      </block>
+    </block>
+  </view>
+</template>
+
+<!--入口模版-->
+
+<template name="wxParse">
+    <block wx:for="{{wxParseData}}" wx:key="">
+        <template is="wxParse0" data="{{item}}"/>
+    </block>
+</template>
+
+
+<!--循环模版-->
+<template name="wxParse0">
+    <!--<template is="wxParse1" data="{{item}}" />-->
+    <!--判断是否是标签节点-->
+    <block wx:if="{{item.node == 'element'}}">
+        <block wx:if="{{item.tag == 'button'}}">
+            <button type="default" size="mini" >
+                <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                    <template is="wxParse1" data="{{item}}"/>
+                </block>
+             </button>
+        </block>
+        <!--li类型-->
+        <block wx:elif="{{item.tag == 'li'}}">
+            <view class="{{item.classStr}} wxParse-li">
+                <view class="{{item.classStr}} wxParse-li-inner">
+                    <view class="{{item.classStr}} wxParse-li-text">
+                        <view class="{{item.classStr}} wxParse-li-circle"></view>
+                    </view>
+                    <view class="{{item.classStr}} wxParse-li-text">
+                        <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                            <template is="wxParse1" data="{{item}}"/>
+                        </block>
+                    </view>
+                </view>
+            </view>
+        </block>
+
+        <!--video类型-->
+        <block wx:elif="{{item.tag == 'video'}}">
+            <template is="wxParseVideo" data="{{item}}"/>  
+        </block>
+
+        <!--img类型-->
+        <block wx:elif="{{item.tag == 'img'}}">
+            <template is="wxParseImg" data="{{item}}"/>
+        </block>
+
+        <!--a类型-->
+        <block wx:elif="{{item.tag == 'a'}}">
+            <view bindtap="wxParseTagATap" class="wxParse-inline {{item.classStr}} wxParse-{{item.tag}}" data-c="{{item.attr.href}}"  style="{{item.styleStr}}">
+                <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                    <template is="wxParse1" data="{{item}}"/>
+                </block>
+            </view>
+        </block>
+        <block wx:elif="{{item.tag == 'table'}}">
+            <view class="{{item.classStr}} wxParse-{{item.tag}}" style="{{item.styleStr}}">
+                <block  wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">       
+                    <template is="wxParse1" data="{{item}}"/>                 
+                </block>
+            </view>
+        </block>
+
+        <!--其他块级标签-->
+        <block wx:elif="{{item.tagType == 'block'}}">
+            <view class="{{item.classStr}} wxParse-{{item.tag}}" style="{{item.styleStr}}">
+                <block  wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">       
+                    <template is="wxParse1" data="{{item}}"/>                 
+                </block>
+            </view>
+        </block>
+
+        <!--内联标签-->
+        <view wx:else class="{{item.classStr}} wxParse-{{item.tag}} wxParse-{{item.tagType}}" style="{{item.styleStr}}">
+            <block  wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">       
+                <template is="wxParse1" data="{{item}}"/>                 
+            </block>
+        </view>
+
+    </block>
+
+    <!--判断是否是文本节点-->
+    <block wx:elif="{{item.node == 'text'}}">
+        <!--如果是,直接进行-->
+        <template is="WxEmojiView" data="{{item}}"/>
+    </block>
+
+</template>
+
+
+
+<!--循环模版-->
+<template name="wxParse1">
+    <!--<template is="wxParse2" data="{{item}}" />-->
+    <!--判断是否是标签节点-->
+    <block wx:if="{{item.node == 'element'}}">
+        <block wx:if="{{item.tag == 'button'}}">
+            <button type="default" size="mini" >
+                <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                    <template is="wxParse2" data="{{item}}"/>
+                </block>
+             </button>
+        </block>
+        <!--li类型-->
+        <block wx:elif="{{item.tag == 'li'}}">
+            <view class="{{item.classStr}} wxParse-li">
+                <view class="{{item.classStr}} wxParse-li-inner">
+                    <view class="{{item.classStr}} wxParse-li-text">
+                        <view class="{{item.classStr}} wxParse-li-circle"></view>
+                    </view>
+                    <view class="{{item.classStr}} wxParse-li-text">
+                        <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                            <template is="wxParse2" data="{{item}}"/>
+                        </block>
+                    </view>
+                </view>
+            </view>
+        </block>
+
+        <!--video类型-->
+        <block wx:elif="{{item.tag == 'video'}}">
+            <template is="wxParseVideo" data="{{item}}"/>  
+        </block>
+
+        <!--img类型-->
+        <block wx:elif="{{item.tag == 'img'}}">
+            <template is="wxParseImg" data="{{item}}"/>
+        </block>
+
+        <!--a类型-->
+        <block wx:elif="{{item.tag == 'a'}}">
+            <view bindtap="wxParseTagATap" class="wxParse-inline {{item.classStr}} wxParse-{{item.tag}}" data-src="{{item.attr.href}}"  style="{{item.styleStr}}">
+                <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                    <template is="wxParse2" data="{{item}}"/>
+                </block>
+            </view>
+        </block>
+        
+        <!--其他块级标签-->
+        <block wx:elif="{{item.tagType == 'block'}}">
+            <view class="{{item.classStr}} wxParse-{{item.tag}}" style="{{item.styleStr}}">
+                <block  wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">       
+                    <template is="wxParse2" data="{{item}}"/>                 
+                </block>
+            </view>
+        </block>
+
+        <!--内联标签-->
+        <view wx:else class="{{item.classStr}} wxParse-{{item.tag}} wxParse-{{item.tagType}}" style="{{item.styleStr}}">
+            <block  wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">       
+                <template is="wxParse2" data="{{item}}"/>                 
+            </block>
+        </view>
+
+    </block>
+
+    <!--判断是否是文本节点-->
+    <block wx:elif="{{item.node == 'text'}}">
+        <!--如果是,直接进行-->
+        <template is="WxEmojiView" data="{{item}}"/>
+    </block>
+
+</template>
+
+
+<!--循环模版-->
+<template name="wxParse2">
+    <!--<template is="wxParse3" data="{{item}}" />-->
+    <!--判断是否是标签节点-->
+    <block wx:if="{{item.node == 'element'}}">
+        <block wx:if="{{item.tag == 'button'}}">
+            <button type="default" size="mini" >
+                <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                    <template is="wxParse3" data="{{item}}"/>
+                </block>
+             </button>
+        </block>
+        <!--li类型-->
+        <block wx:elif="{{item.tag == 'li'}}">
+            <view class="{{item.classStr}} wxParse-li">
+                <view class="{{item.classStr}} wxParse-li-inner">
+                    <view class="{{item.classStr}} wxParse-li-text">
+                        <view class="{{item.classStr}} wxParse-li-circle"></view>
+                    </view>
+                    <view class="{{item.classStr}} wxParse-li-text">
+                        <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                            <template is="wxParse3" data="{{item}}"/>
+                        </block>
+                    </view>
+                </view>
+            </view>
+        </block>
+
+        <!--video类型-->
+        <block wx:elif="{{item.tag == 'video'}}">
+            <template is="wxParseVideo" data="{{item}}"/>  
+        </block>
+
+        <!--img类型-->
+        <block wx:elif="{{item.tag == 'img'}}">
+            <template is="wxParseImg" data="{{item}}"/>
+        </block>
+
+        <!--a类型-->
+        <block wx:elif="{{item.tag == 'a'}}">
+            <view bindtap="wxParseTagATap" class="wxParse-inline {{item.classStr}} wxParse-{{item.tag}}" data-src="{{item.attr.href}}"  style="{{item.styleStr}}">
+                <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                    <template is="wxParse3" data="{{item}}"/>
+                </block>
+            </view>
+        </block>
+        
+        <!--其他块级标签-->
+        <block wx:elif="{{item.tagType == 'block'}}">
+            <view class="{{item.classStr}} wxParse-{{item.tag}}" style="{{item.styleStr}}">
+                <block  wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">       
+                    <template is="wxParse3" data="{{item}}"/>                 
+                </block>
+            </view>
+        </block>
+
+        <!--内联标签-->
+        <view wx:else class="{{item.classStr}} wxParse-{{item.tag}} wxParse-{{item.tagType}}" style="{{item.styleStr}}">
+            <block  wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">       
+                <template is="wxParse3" data="{{item}}"/>                 
+            </block>
+        </view>
+
+    </block>
+
+    <!--判断是否是文本节点-->
+    <block wx:elif="{{item.node == 'text'}}">
+        <!--如果是,直接进行-->
+        <template is="WxEmojiView" data="{{item}}"/>
+    </block>
+
+</template>
+
+<!--循环模版-->
+<template name="wxParse3">
+    <!--<template is="wxParse4" data="{{item}}" />-->
+    <!--判断是否是标签节点-->
+    <block wx:if="{{item.node == 'element'}}">
+        <block wx:if="{{item.tag == 'button'}}">
+            <button type="default" size="mini" >
+                <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                    <template is="wxParse4" data="{{item}}"/>
+                </block>
+             </button>
+        </block>
+        <!--li类型-->
+        <block wx:elif="{{item.tag == 'li'}}">
+            <view class="{{item.classStr}} wxParse-li">
+                <view class="{{item.classStr}} wxParse-li-inner">
+                    <view class="{{item.classStr}} wxParse-li-text">
+                        <view class="{{item.classStr}} wxParse-li-circle"></view>
+                    </view>
+                    <view class="{{item.classStr}} wxParse-li-text">
+                        <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                            <template is="wxParse4" data="{{item}}"/>
+                        </block>
+                    </view>
+                </view>
+            </view>
+        </block>
+
+        <!--video类型-->
+        <block wx:elif="{{item.tag == 'video'}}">
+            <template is="wxParseVideo" data="{{item}}"/>  
+        </block>
+
+        <!--img类型-->
+        <block wx:elif="{{item.tag == 'img'}}">
+            <template is="wxParseImg" data="{{item}}"/>
+        </block>
+
+        <!--a类型-->
+        <block wx:elif="{{item.tag == 'a'}}">
+            <view bindtap="wxParseTagATap" class="wxParse-inline {{item.classStr}} wxParse-{{item.tag}}" data-src="{{item.attr.href}}"  style="{{item.styleStr}}">
+                <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                    <template is="wxParse4" data="{{item}}"/>
+                </block>
+            </view>
+        </block>
+        
+        <!--其他块级标签-->
+        <block wx:elif="{{item.tagType == 'block'}}">
+            <view class="{{item.classStr}} wxParse-{{item.tag}}" style="{{item.styleStr}}">
+                <block  wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">       
+                    <template is="wxParse4" data="{{item}}"/>                 
+                </block>
+            </view>
+        </block>
+
+        <!--内联标签-->
+        <view wx:else class="{{item.classStr}} wxParse-{{item.tag}} wxParse-{{item.tagType}}" style="{{item.styleStr}}">
+            <block  wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">       
+                <template is="wxParse4" data="{{item}}"/>                 
+            </block>
+        </view>
+
+    </block>
+
+    <!--判断是否是文本节点-->
+    <block wx:elif="{{item.node == 'text'}}">
+        <!--如果是,直接进行-->
+        <template is="WxEmojiView" data="{{item}}"/>
+    </block>
+
+</template>
+
+<!--循环模版-->
+<template name="wxParse4">
+    <!--<template is="wxParse5" data="{{item}}" />-->
+    <!--判断是否是标签节点-->
+    <block wx:if="{{item.node == 'element'}}">
+        <block wx:if="{{item.tag == 'button'}}">
+            <button type="default" size="mini" >
+                <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                    <template is="wxParse5" data="{{item}}"/>
+                </block>
+             </button>
+        </block>
+        <!--li类型-->
+        <block wx:elif="{{item.tag == 'li'}}">
+            <view class="{{item.classStr}} wxParse-li">
+                <view class="{{item.classStr}} wxParse-li-inner">
+                    <view class="{{item.classStr}} wxParse-li-text">
+                        <view class="{{item.classStr}} wxParse-li-circle"></view>
+                    </view>
+                    <view class="{{item.classStr}} wxParse-li-text">
+                        <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                            <template is="wxParse5" data="{{item}}"/>
+                        </block>
+                    </view>
+                </view>
+            </view>
+        </block>
+
+        <!--video类型-->
+        <block wx:elif="{{item.tag == 'video'}}">
+            <template is="wxParseVideo" data="{{item}}"/>  
+        </block>
+
+        <!--img类型-->
+        <block wx:elif="{{item.tag == 'img'}}">
+            <template is="wxParseImg" data="{{item}}"/>
+        </block>
+
+        <!--a类型-->
+        <block wx:elif="{{item.tag == 'a'}}">
+            <view bindtap="wxParseTagATap" class="wxParse-inline {{item.classStr}} wxParse-{{item.tag}}" data-src="{{item.attr.href}}"  style="{{item.styleStr}}">
+                <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                    <template is="wxParse5" data="{{item}}"/>
+                </block>
+            </view>
+        </block>
+        
+        <!--其他块级标签-->
+        <block wx:elif="{{item.tagType == 'block'}}">
+            <view class="{{item.classStr}} wxParse-{{item.tag}}" style="{{item.styleStr}}">
+                <block  wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">       
+                    <template is="wxParse5" data="{{item}}"/>                 
+                </block>
+            </view>
+        </block>
+
+        <!--内联标签-->
+        <view wx:else class="{{item.classStr}} wxParse-{{item.tag}} wxParse-{{item.tagType}}" style="{{item.styleStr}}">
+            <block  wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">       
+                <template is="wxParse5" data="{{item}}"/>                 
+            </block>
+        </view>
+
+    </block>
+
+    <!--判断是否是文本节点-->
+    <block wx:elif="{{item.node == 'text'}}">
+        <!--如果是,直接进行-->
+        <template is="WxEmojiView" data="{{item}}"/>
+    </block>
+
+</template>
+
+<!--循环模版-->
+<template name="wxParse5">
+    <!--<template is="wxParse6" data="{{item}}" />-->
+    <!--判断是否是标签节点-->
+    <block wx:if="{{item.node == 'element'}}">
+        <block wx:if="{{item.tag == 'button'}}">
+            <button type="default" size="mini" >
+                <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                    <template is="wxParse6" data="{{item}}"/>
+                </block>
+             </button>
+        </block>
+        <!--li类型-->
+        <block wx:elif="{{item.tag == 'li'}}">
+            <view class="{{item.classStr}} wxParse-li">
+                <view class="{{item.classStr}} wxParse-li-inner">
+                    <view class="{{item.classStr}} wxParse-li-text">
+                        <view class="{{item.classStr}} wxParse-li-circle"></view>
+                    </view>
+                    <view class="{{item.classStr}} wxParse-li-text">
+                        <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                            <template is="wxParse6" data="{{item}}"/>
+                        </block>
+                    </view>
+                </view>
+            </view>
+        </block>
+
+        <!--video类型-->
+        <block wx:elif="{{item.tag == 'video'}}">
+            <template is="wxParseVideo" data="{{item}}"/>  
+        </block>
+
+        <!--img类型-->
+        <block wx:elif="{{item.tag == 'img'}}">
+            <template is="wxParseImg" data="{{item}}"/>
+        </block>
+
+        <!--a类型-->
+        <block wx:elif="{{item.tag == 'a'}}">
+            <view bindtap="wxParseTagATap" class="wxParse-inline {{item.classStr}} wxParse-{{item.tag}}" data-src="{{item.attr.href}}"  style="{{item.styleStr}}">
+                <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                    <template is="wxParse6" data="{{item}}"/>
+                </block>
+            </view>
+        </block>
+        
+        <!--其他块级标签-->
+        <block wx:elif="{{item.tagType == 'block'}}">
+            <view class="{{item.classStr}} wxParse-{{item.tag}}" style="{{item.styleStr}}">
+                <block  wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">       
+                    <template is="wxParse6" data="{{item}}"/>                 
+                </block>
+            </view>
+        </block>
+
+        <!--内联标签-->
+        <view wx:else class="{{item.classStr}} wxParse-{{item.tag}} wxParse-{{item.tagType}}" style="{{item.styleStr}}">
+            <block  wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">       
+                <template is="wxParse6" data="{{item}}"/>                 
+            </block>
+        </view>
+
+    </block>
+
+    <!--判断是否是文本节点-->
+    <block wx:elif="{{item.node == 'text'}}">
+        <!--如果是,直接进行-->
+        <template is="WxEmojiView" data="{{item}}"/>
+    </block>
+
+</template>
+
+<!--循环模版-->
+<template name="wxParse6">
+    <!--<template is="wxParse7" data="{{item}}" />-->
+    <!--判断是否是标签节点-->
+    <block wx:if="{{item.node == 'element'}}">
+        <block wx:if="{{item.tag == 'button'}}">
+            <button type="default" size="mini" >
+                <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                    <template is="wxParse7" data="{{item}}"/>
+                </block>
+             </button>
+        </block>
+        <!--li类型-->
+        <block wx:elif="{{item.tag == 'li'}}">
+            <view class="{{item.classStr}} wxParse-li">
+                <view class="{{item.classStr}} wxParse-li-inner">
+                    <view class="{{item.classStr}} wxParse-li-text">
+                        <view class="{{item.classStr}} wxParse-li-circle"></view>
+                    </view>
+                    <view class="{{item.classStr}} wxParse-li-text">
+                        <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                            <template is="wxParse7" data="{{item}}"/>
+                        </block>
+                    </view>
+                </view>
+            </view>
+        </block>
+
+        <!--video类型-->
+        <block wx:elif="{{item.tag == 'video'}}">
+            <template is="wxParseVideo" data="{{item}}"/>  
+        </block>
+
+        <!--img类型-->
+        <block wx:elif="{{item.tag == 'img'}}">
+            <template is="wxParseImg" data="{{item}}"/>
+        </block>
+
+        <!--a类型-->
+        <block wx:elif="{{item.tag == 'a'}}">
+            <view bindtap="wxParseTagATap" class="wxParse-inline {{item.classStr}} wxParse-{{item.tag}}" data-src="{{item.attr.href}}"  style="{{item.styleStr}}">
+                <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                    <template is="wxParse7" data="{{item}}"/>
+                </block>
+            </view>
+        </block>
+        
+        <!--其他块级标签-->
+        <block wx:elif="{{item.tagType == 'block'}}">
+            <view class="{{item.classStr}} wxParse-{{item.tag}}" style="{{item.styleStr}}">
+                <block  wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">       
+                    <template is="wxParse7" data="{{item}}"/>                 
+                </block>
+            </view>
+        </block>
+
+        <!--内联标签-->
+        <view wx:else class="{{item.classStr}} wxParse-{{item.tag}} wxParse-{{item.tagType}}" style="{{item.styleStr}}">
+            <block  wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">       
+                <template is="wxParse7" data="{{item}}"/>                 
+            </block>
+        </view>
+
+    </block>
+
+    <!--判断是否是文本节点-->
+    <block wx:elif="{{item.node == 'text'}}">
+        <!--如果是,直接进行-->
+        <template is="WxEmojiView" data="{{item}}"/>
+    </block>
+
+</template>
+<!--循环模版-->
+<template name="wxParse7">
+    <!--<template is="wxParse8" data="{{item}}" />-->
+    <!--判断是否是标签节点-->
+    <block wx:if="{{item.node == 'element'}}">
+        <block wx:if="{{item.tag == 'button'}}">
+            <button type="default" size="mini" >
+                <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                    <template is="wxParse8" data="{{item}}"/>
+                </block>
+             </button>
+        </block>
+        <!--li类型-->
+        <block wx:elif="{{item.tag == 'li'}}">
+            <view class="{{item.classStr}} wxParse-li">
+                <view class="{{item.classStr}} wxParse-li-inner">
+                    <view class="{{item.classStr}} wxParse-li-text">
+                        <view class="{{item.classStr}} wxParse-li-circle"></view>
+                    </view>
+                    <view class="{{item.classStr}} wxParse-li-text">
+                        <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                            <template is="wxParse8" data="{{item}}"/>
+                        </block>
+                    </view>
+                </view>
+            </view>
+        </block>
+
+        <!--video类型-->
+        <block wx:elif="{{item.tag == 'video'}}">
+            <template is="wxParseVideo" data="{{item}}"/>  
+        </block>
+
+        <!--img类型-->
+        <block wx:elif="{{item.tag == 'img'}}">
+            <template is="wxParseImg" data="{{item}}"/>
+        </block>
+
+        <!--a类型-->
+        <block wx:elif="{{item.tag == 'a'}}">
+            <view bindtap="wxParseTagATap" class="wxParse-inline {{item.classStr}} wxParse-{{item.tag}}" data-src="{{item.attr.href}}"  style="{{item.styleStr}}">
+                <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                    <template is="wxParse8" data="{{item}}"/>
+                </block>
+            </view>
+        </block>
+        
+        <!--其他块级标签-->
+        <block wx:elif="{{item.tagType == 'block'}}">
+            <view class="{{item.classStr}} wxParse-{{item.tag}}" style="{{item.styleStr}}">
+                <block  wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">       
+                    <template is="wxParse8" data="{{item}}"/>                 
+                </block>
+            </view>
+        </block>
+
+        <!--内联标签-->
+        <view wx:else class="{{item.classStr}} wxParse-{{item.tag}} wxParse-{{item.tagType}}" style="{{item.styleStr}}">
+            <block  wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">       
+                <template is="wxParse8" data="{{item}}"/>                 
+            </block>
+        </view>
+
+    </block>
+
+    <!--判断是否是文本节点-->
+    <block wx:elif="{{item.node == 'text'}}">
+        <!--如果是,直接进行-->
+        <template is="WxEmojiView" data="{{item}}"/>
+    </block>
+
+</template>
+
+<!--循环模版-->
+<template name="wxParse8">
+    <!--<template is="wxParse9" data="{{item}}" />-->
+    <!--判断是否是标签节点-->
+    <block wx:if="{{item.node == 'element'}}">
+        <block wx:if="{{item.tag == 'button'}}">
+            <button type="default" size="mini" >
+                <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                    <template is="wxParse9" data="{{item}}"/>
+                </block>
+             </button>
+        </block>
+        <!--li类型-->
+        <block wx:elif="{{item.tag == 'li'}}">
+            <view class="{{item.classStr}} wxParse-li">
+                <view class="{{item.classStr}} wxParse-li-inner">
+                    <view class="{{item.classStr}} wxParse-li-text">
+                        <view class="{{item.classStr}} wxParse-li-circle"></view>
+                    </view>
+                    <view class="{{item.classStr}} wxParse-li-text">
+                        <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                            <template is="wxParse9" data="{{item}}"/>
+                        </block>
+                    </view>
+                </view>
+            </view>
+        </block>
+
+        <!--video类型-->
+        <block wx:elif="{{item.tag == 'video'}}">
+            <template is="wxParseVideo" data="{{item}}"/>  
+        </block>
+
+        <!--img类型-->
+        <block wx:elif="{{item.tag == 'img'}}">
+            <template is="wxParseImg" data="{{item}}"/>
+        </block>
+
+        <!--a类型-->
+        <block wx:elif="{{item.tag == 'a'}}">
+            <view bindtap="wxParseTagATap" class="wxParse-inline {{item.classStr}} wxParse-{{item.tag}}" data-src="{{item.attr.href}}"  style="{{item.styleStr}}">
+                <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                    <template is="wxParse9" data="{{item}}"/>
+                </block>
+            </view>
+        </block>
+        
+        <!--其他块级标签-->
+        <block wx:elif="{{item.tagType == 'block'}}">
+            <view class="{{item.classStr}} wxParse-{{item.tag}}" style="{{item.styleStr}}">
+                <block  wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">       
+                    <template is="wxParse9" data="{{item}}"/>                 
+                </block>
+            </view>
+        </block>
+
+        <!--内联标签-->
+        <view wx:else class="{{item.classStr}} wxParse-{{item.tag}} wxParse-{{item.tagType}}" style="{{item.styleStr}}">
+            <block  wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">       
+                <template is="wxParse9" data="{{item}}"/>                 
+            </block>
+        </view>
+
+    </block>
+
+    <!--判断是否是文本节点-->
+    <block wx:elif="{{item.node == 'text'}}">
+        <!--如果是,直接进行-->
+        <template is="WxEmojiView" data="{{item}}"/>
+    </block>
+
+</template>
+
+<!--循环模版-->
+<template name="wxParse9">
+    <!--<template is="wxParse10" data="{{item}}" />-->
+    <!--判断是否是标签节点-->
+    <block wx:if="{{item.node == 'element'}}">
+        <block wx:if="{{item.tag == 'button'}}">
+            <button type="default" size="mini" >
+                <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                    <template is="wxParse10" data="{{item}}"/>
+                </block>
+             </button>
+        </block>
+        <!--li类型-->
+        <block wx:elif="{{item.tag == 'li'}}">
+            <view class="{{item.classStr}} wxParse-li">
+                <view class="{{item.classStr}} wxParse-li-inner">
+                    <view class="{{item.classStr}} wxParse-li-text">
+                        <view class="{{item.classStr}} wxParse-li-circle"></view>
+                    </view>
+                    <view class="{{item.classStr}} wxParse-li-text">
+                        <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                            <template is="wxParse10" data="{{item}}"/>
+                        </block>
+                    </view>
+                </view>
+            </view>
+        </block>
+
+        <!--video类型-->
+        <block wx:elif="{{item.tag == 'video'}}">
+            <template is="wxParseVideo" data="{{item}}"/>  
+        </block>
+
+        <!--img类型-->
+        <block wx:elif="{{item.tag == 'img'}}">
+            <template is="wxParseImg" data="{{item}}"/>
+        </block>
+
+        <!--a类型-->
+        <block wx:elif="{{item.tag == 'a'}}">
+            <view bindtap="wxParseTagATap" class="wxParse-inline {{item.classStr}} wxParse-{{item.tag}}" data-src="{{item.attr.href}}"  style="{{item.styleStr}}">
+                <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                    <template is="wxParse10" data="{{item}}"/>
+                </block>
+            </view>
+        </block>
+        
+        <!--其他块级标签-->
+        <block wx:elif="{{item.tagType == 'block'}}">
+            <view class="{{item.classStr}} wxParse-{{item.tag}}" style="{{item.styleStr}}">
+                <block  wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">       
+                    <template is="wxParse10" data="{{item}}"/>                 
+                </block>
+            </view>
+        </block>
+
+        <!--内联标签-->
+        <view wx:else class="{{item.classStr}} wxParse-{{item.tag}} wxParse-{{item.tagType}}" style="{{item.styleStr}}">
+            <block  wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">       
+                <template is="wxParse10" data="{{item}}"/>                 
+            </block>
+        </view>
+
+    </block>
+
+    <!--判断是否是文本节点-->
+    <block wx:elif="{{item.node == 'text'}}">
+        <!--如果是,直接进行-->
+        <template is="WxEmojiView" data="{{item}}"/>
+    </block>
+
+</template>
+
+<!--循环模版-->
+<template name="wxParse10">
+    <!--<template is="wxParse11" data="{{item}}" />-->
+    <!--判断是否是标签节点-->
+    <block wx:if="{{item.node == 'element'}}">
+        <block wx:if="{{item.tag == 'button'}}">
+            <button type="default" size="mini" >
+                <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                    <template is="wxParse11" data="{{item}}"/>
+                </block>
+             </button>
+        </block>
+        <!--li类型-->
+        <block wx:elif="{{item.tag == 'li'}}">
+            <view class="{{item.classStr}} wxParse-li">
+                <view class="{{item.classStr}} wxParse-li-inner">
+                    <view class="{{item.classStr}} wxParse-li-text">
+                        <view class="{{item.classStr}} wxParse-li-circle"></view>
+                    </view>
+                    <view class="{{item.classStr}} wxParse-li-text">
+                        <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                            <template is="wxParse11" data="{{item}}"/>
+                        </block>
+                    </view>
+                </view>
+            </view>
+        </block>
+
+        <!--video类型-->
+        <block wx:elif="{{item.tag == 'video'}}">
+            <template is="wxParseVideo" data="{{item}}"/>  
+        </block>
+
+        <!--img类型-->
+        <block wx:elif="{{item.tag == 'img'}}">
+            <template is="wxParseImg" data="{{item}}"/>
+        </block>
+
+        <!--a类型-->
+        <block wx:elif="{{item.tag == 'a'}}">
+            <view bindtap="wxParseTagATap" class="wxParse-inline {{item.classStr}} wxParse-{{item.tag}}" data-src="{{item.attr.href}}"  style="{{item.styleStr}}">
+                <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                    <template is="wxParse11" data="{{item}}"/>
+                </block>
+            </view>
+        </block>
+        
+        <!--其他块级标签-->
+        <block wx:elif="{{item.tagType == 'block'}}">
+            <view class="{{item.classStr}} wxParse-{{item.tag}}" style="{{item.styleStr}}">
+                <block  wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">       
+                    <template is="wxParse11" data="{{item}}"/>                 
+                </block>
+            </view>
+        </block>
+
+        <!--内联标签-->
+        <view wx:else class="{{item.classStr}} wxParse-{{item.tag}} wxParse-{{item.tagType}}" style="{{item.styleStr}}">
+            <block  wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">       
+                <template is="wxParse11" data="{{item}}"/>                 
+            </block>
+        </view>
+
+    </block>
+
+    <!--判断是否是文本节点-->
+    <block wx:elif="{{item.node == 'text'}}">
+        <!--如果是,直接进行-->
+        <template is="WxEmojiView" data="{{item}}"/>
+    </block>
+
+</template>
+
+<!--循环模版-->
+<template name="wxParse11">
+    <!--<template is="wxParse12" data="{{item}}" />-->
+    <!--判断是否是标签节点-->
+    <block wx:if="{{item.node == 'element'}}">
+        <block wx:if="{{item.tag == 'button'}}">
+            <button type="default" size="mini" >
+                <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                    <template is="wxParse12" data="{{item}}"/>
+                </block>
+             </button>
+        </block>
+        <!--li类型-->
+        <block wx:elif="{{item.tag == 'li'}}">
+            <view class="{{item.classStr}} wxParse-li">
+                <view class="{{item.classStr}} wxParse-li-inner">
+                    <view class="{{item.classStr}} wxParse-li-text">
+                        <view class="{{item.classStr}} wxParse-li-circle"></view>
+                    </view>
+                    <view class="{{item.classStr}} wxParse-li-text">
+                        <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                            <template is="wxParse12" data="{{item}}"/>
+                        </block>
+                    </view>
+                </view>
+            </view>
+        </block>
+
+        <!--video类型-->
+        <block wx:elif="{{item.tag == 'video'}}">
+            <template is="wxParseVideo" data="{{item}}"/>  
+        </block>
+
+        <!--img类型-->
+        <block wx:elif="{{item.tag == 'img'}}">
+            <template is="wxParseImg" data="{{item}}"/>
+        </block>
+
+        <!--a类型-->
+        <block wx:elif="{{item.tag == 'a'}}">
+            <view bindtap="wxParseTagATap" class="wxParse-inline {{item.classStr}} wxParse-{{item.tag}}" data-src="{{item.attr.href}}"  style="{{item.styleStr}}">
+                <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">
+                    <template is="wxParse12" data="{{item}}"/>
+                </block>
+            </view>
+        </block>
+        
+        <!--其他块级标签-->
+        <block wx:elif="{{item.tagType == 'block'}}">
+            <view class="{{item.classStr}} wxParse-{{item.tag}}" style="{{item.styleStr}}">
+                <block  wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">       
+                    <template is="wxParse12" data="{{item}}"/>                 
+                </block>
+            </view>
+        </block>
+
+        <!--内联标签-->
+        <view wx:else class="{{item.classStr}} wxParse-{{item.tag}} wxParse-{{item.tagType}}" style="{{item.styleStr}}">
+            <block  wx:for="{{item.nodes}}" wx:for-item="item" wx:key="">       
+                <template is="wxParse12" data="{{item}}"/>                 
+            </block>
+        </view>
+
+    </block>
+
+    <!--判断是否是文本节点-->
+    <block wx:elif="{{item.node == 'text'}}">
+        <!--如果是,直接进行-->
+        <template is="WxEmojiView" data="{{item}}"/>
+    </block>
+
+</template>

+ 200 - 0
wx-mall-hk/lib/wxParse/wxParse.wxss

@@ -0,0 +1,200 @@
+
+/**
+ * author: Di (微信小程序开发工程师)
+ * organization: WeAppDev(微信小程序开发论坛)(http://weappdev.com)
+ *               垂直微信小程序开发交流社区
+ * 
+ * github地址: https://github.com/icindy/wxParse
+ * 
+ * for: 微信小程序富文本解析
+ * detail : http://weappdev.com/t/wxparse-alpha0-1-html-markdown/184
+ */
+
+.wxParse{
+    margin: 0 5px;
+    font-family: Helvetica,sans-serif;
+    font-size: 28rpx;
+    color: #666;
+    line-height: 1.8;
+}
+
+.wxParse-inline{
+    display: inline;
+    margin: 0;
+    padding: 0;
+}
+/*//标题 */
+.wxParse-div{margin: 0;padding: 0;}
+.wxParse-h1{ font-size:2em; margin: .67em 0 }
+.wxParse-h2{ font-size:1.5em; margin: .75em 0 }
+.wxParse-h3{ font-size:1.17em; margin: .83em 0 }
+.wxParse-h4{ margin: 1.12em 0}
+.wxParse-h5 { font-size:.83em; margin: 1.5em 0 }
+.wxParse-h6{ font-size:.75em; margin: 1.67em 0 }
+
+.wxParse-h1 {
+  font-size: 18px;
+  font-weight: 400;
+  margin-bottom: .9em;
+}
+.wxParse-h2 {
+  font-size: 16px;
+  font-weight: 400;
+  margin-bottom: .34em;
+}
+.wxParse-h3 {
+  font-weight: 400;
+  font-size: 15px;
+  margin-bottom: .34em;
+}
+.wxParse-h4 {
+  font-weight: 400;
+  font-size: 14px;
+  margin-bottom: .24em;
+}
+.wxParse-h5 {
+  font-weight: 400;
+  font-size: 13px;
+  margin-bottom: .14em;
+}
+.wxParse-h6 {
+  font-weight: 400;
+  font-size: 12px;
+  margin-bottom: .04em;
+}
+
+.wxParse-h1, .wxParse-h2, .wxParse-h3, .wxParse-h4, .wxParse-h5, .wxParse-h6, .wxParse-b, .wxParse-strong  { font-weight: bolder }
+
+.wxParse-i,.wxParse-cite,.wxParse-em,.wxParse-var,.wxParse-address{font-style:italic}
+.wxParse-pre,.wxParse-tt,.wxParse-code,.wxParse-kbd,.wxParse-samp{font-family:monospace}
+.wxParse-pre{white-space:pre}
+.wxParse-big{font-size:1.17em}
+.wxParse-small,.wxParse-sub,.wxParse-sup{font-size:.83em}
+.wxParse-sub{vertical-align:sub}
+.wxParse-sup{vertical-align:super}
+.wxParse-s,.wxParse-strike,.wxParse-del{text-decoration:line-through}
+/*wxparse-自定义个性化的css样式*/
+/*增加video的css样式*/
+.wxParse-strong,wxParse-s{display: inline}
+.wxParse-a{
+    color: deepskyblue;
+    word-break:break-all;
+    overflow:auto;
+}
+
+.wxParse-video{
+    text-align: center;
+    margin: 10px 0;
+}
+
+.wxParse-video-video{
+    width:100%;
+}
+
+.wxParse-img{
+    background-color: #efefef;
+    overflow: hidden;
+    width:40px;
+    height: 40px;
+}
+
+.wxParse-blockquote {
+    margin: 0;
+    padding:10px 0 10px 5px;
+    font-family:Courier, Calibri,"宋体";
+    background:#f5f5f5;
+    border-left: 3px solid #dbdbdb;
+}
+
+.wxParse-code,.wxParse-wxxxcode-style{
+    display: inline;
+    background:#f5f5f5;
+}
+.wxParse-ul{
+    margin: 20rpx 10rpx;
+}
+
+.wxParse-li,.wxParse-li-inner{
+    display: flex;
+    align-items: baseline;
+    margin: 10rpx 0;
+}
+.wxParse-li-text{
+    
+    align-items: center;
+    line-height: 20px;
+}
+
+.wxParse-li-circle{
+    display: inline-flex;
+    width: 5px;
+    height: 5px;
+    background-color: #333;
+    margin-right: 5px;
+}
+
+.wxParse-li-square{
+    display: inline-flex;
+    width: 10rpx;
+    height: 10rpx;
+    background-color: #333;
+    margin-right: 5px;
+}
+.wxParse-li-ring{
+    display: inline-flex;
+    width: 10rpx;
+    height: 10rpx;
+    border: 2rpx solid #333;
+    border-radius: 50%;
+    background-color: #fff;
+    margin-right: 5px;
+}
+
+/*.wxParse-table{
+    width: 100%;
+    height: 400px;
+}
+.wxParse-thead,.wxParse-tfoot,.wxParse-tr{
+    display: flex;
+    flex-direction: row;
+}
+.wxParse-th,.wxParse-td{
+    display: flex;
+    width: 580px;
+    overflow: auto;
+}*/
+
+.wxParse-u {
+  text-decoration: underline;
+}
+.wxParse-hide{
+    display: none;
+}
+.WxEmojiView{
+    align-items: center;
+}
+.wxEmoji{
+    width: 16px;
+    height:16px;
+}
+.wxParse-tr{
+	display: flex;
+	border-right:1px solid #e0e0e0;
+	border-bottom:1px solid #e0e0e0;
+}
+.wxParse-th,
+.wxParse-td{
+	flex:1;
+	padding:5px;
+	font-size:28rpx;
+	border-left:1px solid #e0e0e0;
+	word-break: break-all;
+}
+.wxParse-td:last{
+	border-top:1px solid #e0e0e0;
+}
+.wxParse-th{
+	background:#f0f0f0;
+	border-top:1px solid #e0e0e0;
+}
+

+ 80 - 0
wx-mall-hk/pages/activity/activity.js

@@ -0,0 +1,80 @@
+var api = require('../../config/api.js');
+var util = require('../../utils/util.js');
+var app = getApp();
+Page({
+  data: {
+    couponList: [],
+    referrer: 0,
+    sourceKey: '',
+    scrollTop: 0
+  },
+  onLoad: function (options) {
+    let that = this;
+    // 页面初始化 options为页面跳转所带来的参数
+    if (options.referrer) {
+      that.setData({
+        referrer: parseInt(options.referrer),
+        sourceKey: options.sourceKey
+      });
+    }
+    let code = null;
+    if (null == wx.getStorageInfoSync('userInfo')) {
+      util.login().then((res) => {
+        code = res.code;
+        return util.getUserInfo();
+      }).then((userInfo) => {
+        //登录远程服务器
+        wx.request({
+          url: api.AuthLoginByWeixin,
+          data: {
+            code: code, userInfo: userInfo
+          },
+          method: 'POST',
+          header: {
+            'Content-Type': 'application/json'
+          },
+          success: function (res) {
+            if (res.errno === 0) {
+              //存储用户信息
+              wx.setStorageSync('userInfo', res.data.userInfo);
+              wx.setStorageSync('token', res.data.token);
+              wx.setStorageSync('userId', res.data.userId);
+              that.getCouponList();
+            }
+          },
+          fail: function (err) {
+            reject(err)
+            console.log("failed")
+          }
+        })
+      })
+    } else {
+      that.getCouponList();
+    }
+  },
+  onReady: function () {
+  },
+  onShow: function () {
+  },
+  onHide: function () {
+    // 页面隐藏
+  },
+  onUnload: function () {
+    // 页面关闭
+  },
+  getCouponList() {
+    let that = this;
+    util.request(api.CouponTransActivit).then(function (res) {
+      if (res.errno === 0) {
+        that.setData({
+          couponList: res.data
+        });
+      } else if (res.errno === 2) {
+        util.showErrorToast(res.errmsg)
+        that.setData({
+          couponList: res.data
+        });
+      }
+    });
+  }
+})

+ 1 - 0
wx-mall-hk/pages/activity/activity.json

@@ -0,0 +1 @@
+{}

+ 48 - 0
wx-mall-hk/pages/activity/activity.wxml

@@ -0,0 +1,48 @@
+<view class="container">
+  <scroll-view class="form-box" scroll-y="true" scroll-top="{{scrollTop}}">
+
+    <view class="wrapper">
+      <view class="t-banner">
+        <image src="http://120.76.26.84:80/group1/M00/00/01/rBJEdVvr1vmAO3FoAAKNlA-iHSY636.png" background-size="cover"></image>
+      </view>
+    </view>
+
+    <view class="coupon-list" wx:for="{{couponList}}" wx:key="{{item.id}}" bindtap="" data-coupon-id="{{item.id}}">
+      <view class="item">
+        <view class="tag" wx:if="{{item.send_type==4}}">新人专享</view>
+        <view class="content">
+          <view class="left">
+            <view class="name">{{item.name}}</view>
+            <view class="time">{{item.use_start_date}}-{{item.use_end_date}}</view>
+          </view>
+          <!-- <view class="right">  -->
+          <!-- <button class="go">去使用</button> -->
+          <!-- </view> -->
+        </view>
+        <view class="condition" wx:if="{{item.coupon_txt}}">
+          <text class="txt">{{item.coupon_txt}}</text>
+          <image src="http://120.76.26.84:80/group1/M00/00/01/rBJEdVvr1xiAOIslAAABEXmc7LY394.png" class="icon"></image>
+        </view>
+      </view>
+    </view>
+
+    <view class="content-bg margin-gap">
+      <view class="rule">
+        <view class="sec-sub-title">活动规则</view>
+        <ul class="act-rules">
+          <li>1.下单即可分享红包给小伙伴</li>
+          <li></li>
+          <li>2.每个链接会按领取顺序随机发放一个大额红包</li>
+          <li></li>
+          <li>3.每人每个链接仅限领取1次</li>
+          <li></li>
+          <li>4.红包仅限在线支付使用</li>
+          <li></li>
+          <li>5.其他未尽事宜,请咨询客服</li>
+          <li></li>
+        </ul>
+      </view>
+    </view>
+    <view class="blank"> </view>
+  </scroll-view>
+</view>

+ 187 - 0
wx-mall-hk/pages/activity/activity.wxss

@@ -0,0 +1,187 @@
+page, .container {
+  width: 750rpx;
+  height: 100%;
+  overflow: hidden;
+  background: #f4f4f4;
+}
+
+.form-box {
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+  padding: 0 40rpx;
+  margin-top: 36rpx;
+  background: rgb(240, 78, 76);
+}
+
+.wrapper {
+  max-width: 20rem;
+  overflow: hidden;
+  margin: 0 auto;
+  padding-bottom: 1rem;
+}
+
+.t-banner {
+  position: relative;
+  /* width: 100%;  *//* height: 50%; */
+}
+
+.content-bg {
+  width: 91%;
+  padding-right: 30rpx;
+  background: rgba(255, 255, 255, 0.6);
+  height: auto;
+  overflow: hidden;
+  padding-bottom: 1rem;
+}
+
+.margin-gap {
+  margin-top: 0.3rem;
+}
+
+.coupon-list {
+  width: 95%;
+  height: auto;
+  overflow: hidden;
+  padding-right: 30rpx;
+}
+
+.item {
+  position: relative;
+  height: 200rpx;
+  width: 100%;
+  background: linear-gradient(to right, #cfa568, #e3bf79);
+  margin-bottom: 25rpx;
+  padding-top: 25rpx;
+}
+
+.tag {
+  height: 32rpx;
+  background: #a48143;
+  padding-left: 16rpx;
+  padding-right: 16rpx;
+  position: absolute;
+  left: 20rpx;
+  color: #fff;
+  top: 20rpx;
+  font-size: 20rpx;
+  text-align: center;
+  line-height: 32rpx;
+}
+
+.content {
+  margin-top: 24rpx;
+  margin-left: 40rpx;
+  display: flex;
+  margin-right: 40rpx;
+  flex-direction: row;
+  align-items: center;
+}
+
+.content .left {
+  flex: 1;
+}
+
+.name {
+  font-size: 44rpx;
+  color: #fff;
+  margin-bottom: 14rpx;
+}
+
+.time {
+  font-size: 24rpx;
+  color: rgba(255, 255, 255, 0.8);
+  line-height: 30rpx;
+}
+
+.content .right {
+  width: 162rpx;
+}
+
+.go {
+  height: 48rpx;
+  border: none;
+  width: 162rpx;
+  background: rgba(255, 255, 255, 0.8);
+  border-radius: 4rpx;
+  line-height: 48rpx;
+  color: #b69150;
+  font-size: 24rpx;
+}
+
+.condition {
+  position: absolute;
+  width: 100%;
+  bottom: 0;
+  left: 0;
+  height: 78rpx;
+  background: rgba(0, 0, 0, 0.08);
+  padding: 24rpx 40rpx;
+  display: flex;
+  flex-direction: row;
+}
+
+.condition .txt {
+  display: block;
+  height: 30rpx;
+  flex: 1;
+  overflow: hidden;
+  font-size: 24rpx;
+  line-height: 30rpx;
+  color: #fff;
+}
+
+.condition .icon {
+  margin-left: 30rpx;
+  width: 24rpx;
+  height: 24rpx;
+}
+
+.rule {
+  width: 95%;
+  margin: 0 auto;
+}
+
+.sec-sub-title {
+  line-height: 1rem;
+  background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAgkAAAABAQMAAABuYK//AAAABlBMV…RSTlMzAIL4qAgAAAAVSURBVAjXY2hgQAfy/3GDAwwYoAEAySocxUiGKqkAAAAASUVORK5CYII=) no-repeat;
+  background-size: 100% auto;
+  background-position: 0px;
+  font-size: 0.8rem;
+  color: #333;
+  text-align: center;
+  font-weight: normal;
+  margin: 0 auto;
+  margin-top: 0.25rem;
+  width: 93%;
+  display: block;
+  -webkit-margin-before: 0.9em;
+  -webkit-margin-after: 0.9em;
+  -webkit-margin-start: 0px;
+  -webkit-margin-end: 0px;
+}
+
+.rule ul {
+  width: 95%;
+  margin: 0 auto;
+  padding-left: 0;
+  list-style-type: none;
+}
+
+.rule li {
+  font-size: 0.8rem;
+  line-height: 0.78rem;
+  margin-bottom: 0.28rem;
+  color: #333;
+  list-style-type: none;
+}
+
+li {
+  display: list-item;
+  text-align: -webkit-match-parent;
+}
+
+.blank {
+  margin-top: 30rpx;
+  margin-bottom: 30rpx;
+}

+ 101 - 0
wx-mall-hk/pages/auth/btnAuth/btnAuth.js

@@ -0,0 +1,101 @@
+const util = require('../../../utils/util.js');
+const api = require('../../../config/api.js');
+const user = require('../../../services/user.js');
+
+//获取应用实例
+const app = getApp()
+Page({
+  data: {
+    canIUse: wx.canIUse('button.open-type.getUserInfo'),
+    navUrl: ''
+  },
+
+  onLoad: function (options) {
+    let that = this;
+    if (wx.getStorageSync("navUrl")) {
+      that.setData(
+        {
+          navUrl: wx.getStorageSync("navUrl")
+        }
+      )
+    }else{
+      that.setData(
+        {
+          navUrl: '/pages/index/index'
+        }
+      )
+    }
+  },
+
+  bindGetUserInfo: function (e) {
+    let that = this;
+    // console.log(e.detail.userInfo)
+    // console.log(that.data.navUrl);
+    wx.login({
+      success: function (res) {
+        if (res.code) {
+          wx.getUserInfo({
+            withCredentials: true,
+            success: function (succRes) {
+              // console.log(res);
+              //登录远程服务器
+              wx.request({
+                url: api.AuthLoginByWeixin,
+                data: {
+                  code: res.code, userInfo: succRes, storeId: wx.getStorageSync('storeId'), merchSn: wx.getStorageSync('merchSn')
+                },
+                method: 'POST',
+                header: {
+                  'Content-Type': 'application/json'
+                },
+                success: function (wxRes) {
+                  if (wxRes.data.errno === 0) {
+                    //存储用户信息
+                    wx.setStorageSync('userInfo', wxRes.data.data.userInfo);
+                    wx.setStorageSync('token', wxRes.data.data.token);
+                    wx.setStorageSync('userId', wxRes.data.data.userId);
+
+                    if (that.data.navUrl && that.data.navUrl == '/pages/index/index') {
+                      wx.switchTab({
+                        url: that.data.navUrl,
+                      });
+                    } else if (that.data.navUrl) {
+                      wx.redirectTo({
+                        url: that.data.navUrl,
+                      });
+                    }
+                    console.log("登录成功");
+                  }
+                },
+                fail: function (err) {
+                  console.log("failed");
+                }
+              });
+            },
+            fail: function (err) {
+              console.log("重新认证");
+            }
+          });
+        } else {
+          console.log("failed");
+        }
+      },
+      fail: function (err) {
+        console.log("failed");
+      }
+    });
+
+  },
+  onReady: function () {
+    // 页面渲染完成
+  },
+  onShow: function () {
+    // 页面显示
+  },
+  onHide: function () {
+    // 页面隐藏
+  },
+  onUnload: function () {
+    // 页面关闭
+  }
+})

+ 4 - 0
wx-mall-hk/pages/auth/btnAuth/btnAuth.json

@@ -0,0 +1,4 @@
+{
+  "component": true,
+  "usingComponents": {}
+}

+ 14 - 0
wx-mall-hk/pages/auth/btnAuth/btnAuth.wxml

@@ -0,0 +1,14 @@
+<!--index.wxml-->
+<view class="page">
+
+    <view class="page_title">欢迎你</view>
+
+  <view class="bd spacing">
+    <!-- 需要使用 button 来授权登录 -->
+    <button wx:if="{{canIUse}}" open-type="getUserInfo" class="weui_btn weui_btn_primary" bindgetuserinfo="bindGetUserInfo">授权登录</button>
+    <!-- <view wx:else>请升级微信版本</view> -->
+  </view>
+
+
+
+</view>

+ 63 - 0
wx-mall-hk/pages/auth/btnAuth/btnAuth.wxss

@@ -0,0 +1,63 @@
+/* @import '/style/weui.wxss'; */
+
+.page {
+  line-height: 1.6;
+  font-family: -apple-system-font, Helvetica Neue, sans-serif;
+}
+.hd {
+    padding: 10px 15px 0;
+}
+
+.page_title {
+    text-align: center;
+    font-size: 34px;
+    color: #3CC51F;
+    font-weight: 400;
+    margin: 10% 25% 0% 25%;
+
+}
+.bd {
+  margin: 10% 25% 0% 25%;
+   padding-left: 20px;
+}
+
+.weui_btn_primary {
+    background-color: #04be02;
+}
+
+
+.weui_btn {
+    position: relative;
+    display: block;
+    margin-left: auto;
+    margin-right: auto;
+    padding-left: 14px;
+    padding-right: 14px;
+    box-sizing: border-box;
+    font-size: 18px;
+    text-align: center;
+    text-decoration: none;
+    color: #FFFFFF;
+    line-height: 2.33333333;
+    border-radius: 5px;
+    -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+    overflow: hidden;
+}
+
+.weui_btn:after {
+    content: " ";
+    width: 200%;
+    height: 200%;
+    position: absolute;
+    top: 0;
+    left: 0;
+    border: 1px solid rgba(0, 0, 0, 0.2);
+    -webkit-transform: scale(0.5);
+    -ms-transform: scale(0.5);
+    transform: scale(0.5);
+    -webkit-transform-origin: 0 0;
+    -ms-transform-origin: 0 0;
+    transform-origin: 0 0;
+    box-sizing: border-box;
+    border-radius: 10px;
+}

+ 106 - 0
wx-mall-hk/pages/auth/login/login.js

@@ -0,0 +1,106 @@
+var api = require('../../../config/api.js');
+var app = getApp();
+Page({
+  data: {
+    username: '',
+    password: '',
+    code: '',
+    loginErrorCount: 0
+  },
+  onLoad: function (options) {
+    // 页面初始化 options为页面跳转所带来的参数
+    // 页面渲染完成
+
+  },
+  onReady: function () {
+
+  },
+  onShow: function () {
+    // 页面显示
+  },
+  onHide: function () {
+    // 页面隐藏
+
+  },
+  onUnload: function () {
+    // 页面关闭
+
+  },
+  startLogin: function () {
+    var that = this;
+
+    if (that.data.password.length < 1 || that.data.username.length < 1) {
+      wx.showModal({
+        title: '错误信息',
+        content: '请输入用户名和密码',
+        showCancel: false
+      });
+      return false;
+    }
+
+    wx.request({
+      url: api.ApiRootUrl + 'auth/login',
+      data: {
+        username: that.data.username,
+        password: that.data.password
+      },
+      method: 'POST',
+      header: {
+        'content-type': 'application/json'
+      },
+      success: function (res) {
+        if(res.data.code == 200){
+          that.setData({
+            'loginErrorCount': 0
+          });
+          wx.setStorage({
+            key:"token",
+            data: res.data.data.token,
+            success: function(){
+              wx.switchTab({
+                url: '/pages/ucenter/index/index'
+              });
+            }
+          });
+        }
+      }
+    });
+  },
+  bindUsernameInput: function (e) {
+
+    this.setData({
+      username: e.detail.value
+    });
+  },
+  bindPasswordInput: function (e) {
+
+    this.setData({
+      password: e.detail.value
+    });
+  },
+  bindCodeInput: function (e) {
+
+    this.setData({
+      code: e.detail.value
+    });
+  },
+  clearInput: function (e) {
+    switch (e.currentTarget.id) {
+      case 'clear-username':
+        this.setData({
+          username: ''
+        });
+        break;
+      case 'clear-password':
+        this.setData({
+          password: ''
+        });
+        break;
+      case 'clear-code':
+        this.setData({
+          code: ''
+        });
+        break;
+    }
+  }
+})

+ 1 - 0
wx-mall-hk/pages/auth/login/login.json

@@ -0,0 +1 @@
+{}

+ 30 - 0
wx-mall-hk/pages/auth/login/login.wxml

@@ -0,0 +1,30 @@
+<view class="container">
+    <view class="form-box">
+
+    	<view class="form-item">
+    		<input class="username" value="{{username}}" bindinput="bindUsernameInput" placeholder="账号" auto-focus/>
+    		<image wx:if="{{ username.length > 0 }}" id="clear-username" class="clear" src="/static/images/clear_input.png" catchtap="clearInput"></image>
+    	</view>
+
+    	<view class="form-item">
+    		<input class="password" value="{{password}}" password bindinput="bindPasswordInput" placeholder="密码"/>
+    		<image class="clear" id="clear-password" wx:if="{{ password.length > 0 }}" src="/static/images/clear_input.png" catchtap="clearInput"></image>
+    	</view>
+
+		<view class="form-item-code" wx-if="{{loginErrorCount >= 3}}">
+			<view class="form-item code-item">
+				<input class="code" value="{{code}}" bindinput="bindCodeInput" placeholder="验证码"/>
+				<image class="clear" id="clear-code" wx:if="{{ code.length > 0 }}" src="/static/images/clear_input.png" catchtap="clearInput"></image>
+			</view>
+			<image class="code-img" src="https://dl.reg.163.com/cp?pd=yanxuan_web&pkid=SkeBZeG&random=1489903563234"></image>
+		</view>
+
+    	<button type="default" class="login-btn" bindtap="startLogin">登录</button>
+
+    	<view class="form-item-text">
+    		<navigator url="/pages/auth/register/register" class="register">注册账号</navigator>
+			<navigator url="/pages/auth/reset/reset" class="reset">忘记密码</navigator>
+    	</view>
+
+    </view>
+</view>

+ 89 - 0
wx-mall-hk/pages/auth/login/login.wxss

@@ -0,0 +1,89 @@
+.form-box{
+    width: 100%;
+    height: auto;
+    overflow: hidden;
+    padding: 0 40rpx;
+    margin-top: 96rpx;
+    background: #fff;
+}
+
+.form-item{
+    position: relative;
+    background: #fff;
+    height: 96rpx;
+    border-bottom: 1px solid #d9d9d9;
+}
+
+.form-item .username, .form-item .password, .form-item .code{
+    position: absolute;
+    top: 26rpx;
+    left: 0;
+    display: block;
+    width: 100%;
+    height: 44rpx;
+    background: #fff;
+    color: #333;
+    font-size: 30rpx;
+}
+
+.form-item-code{
+    margin-top:32rpx;
+    height: auto;
+    overflow: hidden;
+    width: 100%;
+}
+
+.form-item-code .form-item{
+    float: left;
+    width: 350rpx;
+}
+
+.form-item-code .code-img{
+    float: right;
+    margin-top: 4rpx;
+    height: 88rpx;
+    width: 236rpx;
+}
+
+.form-item .clear{
+    position: absolute;
+    top: 26rpx;
+    right: 18rpx;
+    z-index: 2;
+    display: block;
+    background: #fff;
+    height: 44rpx;
+    width: 44rpx;
+}
+
+.login-btn{
+    margin: 60rpx 0 40rpx 0;
+    height: 96rpx;
+    line-height: 96rpx;
+    color: #fff;
+    font-size: 30rpx;
+    width: 100%;
+    background: #b4282d;
+    border-radius: 6rpx;
+}
+
+.form-item-text{
+    height: 35rpx;
+    width: 100%;
+}
+
+.form-item-text .register{
+    display: block;
+    height: 34rpx;
+    float: left;
+    font-size: 28rpx;
+    color: #999;
+}
+
+.form-item-text .reset{
+    display: block;
+    height: 34rpx;
+    float: right;
+    font-size: 28rpx;
+    color: #999;
+}

+ 187 - 0
wx-mall-hk/pages/auth/newuser/newuser.js

@@ -0,0 +1,187 @@
+var api = require('../../../config/api.js');
+var util = require('../../../utils/util.js');
+var app = getApp();
+Page({
+
+  /**
+   * 页面的初始数据
+   */
+  data: {
+    phone: '',
+    smscode: '',
+    second: '发送验证码',
+    disabled: false,
+    disabledUpdate: false
+  },
+  clearPhone(){
+    this.setData({
+      phone: ''
+    });
+  },
+  clearCode(){
+    this.setData({
+      smscode: ''
+    });
+  },
+  bindPhoneInput: function (e) {
+    this.setData({
+      phone: e.detail.value
+    });
+  },
+  bindSmscodeInput: function (e) {
+    this.setData({
+      smscode: e.detail.value
+    });
+  },
+  /**
+  * 用户领券
+  */
+  getCoupon: function () {
+    var that = this;
+    let regular = /^1[3|4|5|7|8]\d{9}$/;
+    if (!regular.test(that.data.phone)) {
+      util.showErrorToast('手机格式不正确')
+      return false;
+    }
+    if (that.data.smscode.length == 0) {
+      util.showErrorToast('验证码不能为空')
+      return false;
+    }
+
+    util.request(api.newUserCoupn, {
+      smscode: that.data.smscode,
+      phone: that.data.phone
+    }, 'POST').then(function (res) {
+      if (res.errno === 0) {
+        wx.showToast({
+          title: '手机号绑定成功'
+        });
+        wx.redirectTo({ url: '/pages/ucenter/coupon/coupon' });
+      } else {
+        util.showErrorToast(res.errmsg);
+      }
+    });
+  },
+  /**
+   * 发送短信
+   */
+  smscode: function () {
+    var that = this;
+
+    let regular = /^1[3|4|5|7|8]\d{9}$/;
+    if (!regular.test(that.data.phone)) {
+      util.showErrorToast('手机格式不正确')
+      return false;
+    }
+    util.request(api.smscodeSend, {
+      phone: that.data.phone
+    }, 'POST').then(function (res) {
+      let n = 59;
+      var timer = setInterval(function () {
+        if (n == 0) {
+          clearInterval(timer);
+          that.setData({
+            second: '发送验证码',
+            disabled: false
+          });
+        } else {
+          that.setData({
+            second: n-- +'s后重新获取',
+            disabled: true
+          });
+        }
+      }, 1000);
+      if (res.errno == 0) {
+        wx.showToast({
+          title: '短信发送成功'
+        })
+      } else{
+        util.showErrorToast('发送失败');
+        clearInterval(timer);
+        that.setData({
+          second: '发送验证码',
+          disabled: false
+        });
+        return false;
+      }
+    });
+  },
+  /**
+   * 生命周期函数--监听页面加载
+   */
+  onLoad: function (options) {
+    this.checkActivit();
+  },
+
+  /**
+   * 生命周期函数--监听页面初次渲染完成
+   */
+  onReady: function () {
+
+  },
+
+  /**
+   * 生命周期函数--监听页面显示
+   */
+  onShow: function () {
+
+  },
+
+  /**
+   * 生命周期函数--监听页面隐藏
+   */
+  onHide: function () {
+
+  },
+
+  /**
+   * 生命周期函数--监听页面卸载
+   */
+  onUnload: function () {
+
+  },
+
+  /**
+   * 页面相关事件处理函数--监听用户下拉动作
+   */
+  onPullDownRefresh: function () {
+
+  },
+
+  /**
+   * 页面上拉触底事件的处理函数
+   */
+  onReachBottom: function () {
+
+  },
+
+  /**
+   * 用户点击右上角分享
+   */
+  onShareAppMessage: function () {
+
+  },
+  checkActivit() {
+    let that = this;
+    util.request(api.checkActivit).then(function (res) {
+      if (res.errno === 2) {
+        wx.showModal({
+          title: '',
+          content: res.errmsg,
+          showCancel: false,
+          success: function (res) {
+            if (res.confirm) {
+              wx.switchTab({
+                url: '/pages/index/index'
+              });
+            }
+          }
+        });
+        that.setData({
+          disabled: true,
+          disabledUpdate: true
+        });
+      }
+    });
+  }
+})

+ 1 - 0
wx-mall-hk/pages/auth/newuser/newuser.json

@@ -0,0 +1 @@
+{}

+ 22 - 0
wx-mall-hk/pages/auth/newuser/newuser.wxml

@@ -0,0 +1,22 @@
+<view class="container">
+  <view class="form-box">
+
+    <view class="form-item">
+      <input class="phone" value="{{phone}}" disabled="{{disabledUpdate}}"  type="number" maxlength="{{11}}" bindinput="bindPhoneInput" placeholder="手机号" auto-focus/>
+      <image wx:if="{{ phone.length > 0 }}" id="clear-phone" class="clear" src="/static/images/clear_input.png" catchtap="clearPhone"></image>
+    </view>
+
+    <view class="form-item-code">
+      <view class="form-item code-item">
+        <input class="smscode" disabled="{{disabledUpdate}}" value="{{smscode}}" type="number" bindinput="bindSmscodeInput" placeholder="短信码" />
+        <image class="clear" id="clear-smscode" wx:if="{{ smscode.length > 0 }}" src="/static/images/clear_input.png" catchtap="clearCode"></image>
+      </view>
+
+      <view class="sms-rr">
+          <button class="btn" disabled="{{disabled}}" catchtap="smscode" >{{second}}</button>
+      </view>
+
+    </view>
+  </view>
+  <button type="primary" disabled="{{disabledUpdate}}"  class="login-btn" bindtap="getCoupon">提交</button>
+</view>

+ 104 - 0
wx-mall-hk/pages/auth/newuser/newuser.wxss

@@ -0,0 +1,104 @@
+page ,.container{
+   width: 750rpx;
+    height: 100%;
+    overflow: hidden;
+    background: #fff;
+}
+
+.form-box{
+    width: 100%;
+    height: auto;
+    overflow: hidden;
+    padding: 0 80rpx;
+    margin-top: 96rpx;
+}
+
+.form-item{
+    position: relative;
+    background: #fff;
+    display: flex;
+    flex: 1;
+    align-items: center;
+    border-bottom: 1px solid #d9d9d9;
+    border-radius: 4px;
+}
+.form-item input{
+  flex: 1;
+}
+.form-item .username, .form-item .password, .form-item .code{
+    position: absolute;
+    top: 26rpx;
+    left: 0;
+    display: block;
+    width: 100%;
+    height: 44rpx;
+    background: #fff;
+    color: #333;
+    font-size: 30rpx;
+}
+
+.form-item-code{
+    margin-top:32rpx;
+    height: auto;
+    overflow: hidden;
+    width: 100%;
+    display: flex;
+    align-items: center;
+}
+
+.form-item-code .form-item{
+    float: left;
+    width: 350rpx;
+}
+
+.form-item-code .sms-r{
+    float: right;
+    margin-top: 4rpx;
+    height: 68rpx;
+    width: 186rpx;
+}
+
+.form-item .clear{
+    display: block;
+    background: #fff;
+    height: 44rpx;
+    width: 44rpx;
+}
+
+.login-btn{
+    margin: 120rpx auto;
+    height: 96rpx;
+    line-height: 96rpx;
+    color: #fff;
+    font-size: 30rpx;
+    width: 90%;
+    background: #b4282d;
+    border-radius: 6rpx;
+}
+
+.form-item-text{
+    height: 35rpx;
+    width: 100%;
+}
+
+.form-item-text .register{
+    display: block;
+    height: 34rpx;
+    float: left;
+    font-size: 28rpx;
+    color: #999;
+}
+
+.form-item-text .reset{
+    display: block;
+    height: 34rpx;
+    float: right;
+    font-size: 28rpx;
+    color: #999;
+}
+
+.sms-rr .btn{
+  height: 50rpx;
+  line-height: 50rpx;
+  font-size: 28rpx;
+}

+ 130 - 0
wx-mall-hk/pages/auth/register/register.js

@@ -0,0 +1,130 @@
+var api = require('../../../config/api.js');
+var app = getApp();
+Page({
+  data: {
+    username: '',
+    password: '',
+    confirmPassword: '',
+    code: '',
+    loginErrorCount: 0
+  },
+  onLoad: function (options) {
+    // 页面初始化 options为页面跳转所带来的参数
+    // 页面渲染完成
+
+  },
+  onReady: function () {
+
+  },
+  onShow: function () {
+    // 页面显示
+
+  },
+  onHide: function () {
+    // 页面隐藏
+
+  },
+  onUnload: function () {
+    // 页面关闭
+
+  },
+  startRegister: function () {
+    var that = this;
+
+    if (that.data.password.length < 3 || that.data.username.length < 3) {
+      wx.showModal({
+        title: '错误信息',
+        content: '用户名和密码不得少于3位',
+        showCancel: false
+      });
+      return false;
+    }
+
+    if (that.data.password != that.data.confirmPassword) {
+      wx.showModal({
+        title: '错误信息',
+        content: '确认密码不一致',
+        showCancel: false
+      });
+      return false;
+    }
+
+    wx.request({
+      url: api.ApiRootUrl + 'auth/register',
+      data: {
+        username: that.data.username,
+        password: that.data.password
+      },
+      method: 'POST',
+      header: {
+        'content-type': 'application/json'
+      },
+      success: function (res) {
+        if (res.data.code == 200) {
+          that.setData({
+            'loginErrorCount': 0
+          });
+          wx.setStorage({
+            key: "token",
+            data: res.data.data.token,
+            success: function () {
+              wx.switchTab({
+                url: '/pages/ucenter/index/index'
+              });
+            }
+          });
+
+        }
+        console.log(res.data.data.token)
+      }
+    });
+  },
+  bindUsernameInput: function (e) {
+
+    this.setData({
+      username: e.detail.value
+    });
+  },
+  bindPasswordInput: function (e) {
+
+    this.setData({
+      password: e.detail.value
+    });
+  },
+  bindConfirmPasswordInput: function (e) {
+
+    this.setData({
+      confirmPassword: e.detail.value
+    });
+  },
+  bindCodeInput: function (e) {
+
+    this.setData({
+      code: e.detail.value
+    });
+  },
+  clearInput: function (e) {
+    switch (e.currentTarget.id) {
+      case 'clear-username':
+        this.setData({
+          username: ''
+        });
+        break;
+      case 'clear-password':
+        this.setData({
+          password: ''
+        });
+        break;
+      case 'clear-confirm-password':
+        this.setData({
+          confirmPassword: ''
+        });
+        break;
+      case 'clear-code':
+        this.setData({
+          code: ''
+        });
+        break;
+    }
+  }
+})

+ 1 - 0
wx-mall-hk/pages/auth/register/register.json

@@ -0,0 +1 @@
+{}

+ 30 - 0
wx-mall-hk/pages/auth/register/register.wxml

@@ -0,0 +1,30 @@
+<view class="container">
+    <view class="form-box">
+
+    	<view class="form-item">
+    		<input class="username" value="{{username}}" bindinput="bindUsernameInput" placeholder="用户名" auto-focus/>
+    		<image wx:if="{{ username.length > 0 }}" id="clear-username" class="clear" src="/static/images/clear_input.png" catchtap="clearInput"></image>
+    	</view>
+
+    	<view class="form-item">
+    		<input class="password" value="{{password}}" password bindinput="bindPasswordInput" placeholder="密码"/>
+    		<image class="clear" id="clear-password" wx:if="{{ password.length > 0 }}" src="/static/images/clear_input.png" catchtap="clearInput"></image>
+    	</view>
+
+        <view class="form-item">
+    		<input class="password" value="{{confirmPassword}}" password bindinput="bindConfirmPasswordInput" placeholder="确认密码"/>
+    		<image class="clear" id="clear-confirm-password" wx:if="{{ confirmPassword.length > 0 }}" src="/static/images/clear_input.png" catchtap="clearInput"></image>
+    	</view>
+
+		<view class="form-item-code" >
+			<view class="form-item code-item">
+				<input class="code" value="{{code}}" bindinput="bindCodeInput" placeholder="验证码"/>
+				<image class="clear" id="clear-code" wx:if="{{ code.length > 0 }}" src="/static/images/clear_input.png" catchtap="clearInput"></image>
+			</view>
+			<image class="code-img" src="https://dl.reg.163.com/cp?pd=yanxuan_web&pkid=SkeBZeG&random=1489903563234"></image>
+		</view>
+
+    	<button type="default" class="login-btn" bindtap="startRegister">注册</button>
+
+    </view>
+</view>

+ 89 - 0
wx-mall-hk/pages/auth/register/register.wxss

@@ -0,0 +1,89 @@
+.form-box{
+    width: 100%;
+    height: auto;
+    overflow: hidden;
+    padding: 0 40rpx;
+    margin-top: 96rpx;
+    background: #fff;
+}
+
+.form-item{
+    position: relative;
+    background: #fff;
+    height: 96rpx;
+    border-bottom: 1px solid #d9d9d9;
+}
+
+.form-item .username, .form-item .password, .form-item .code{
+    position: absolute;
+    top: 26rpx;
+    left: 0;
+    display: block;
+    width: 100%;
+    height: 44rpx;
+    background: #fff;
+    color: #333;
+    font-size: 30rpx;
+}
+
+.form-item-code{
+    margin-top:32rpx;
+    height: auto;
+    overflow: hidden;
+    width: 100%;
+}
+
+.form-item-code .form-item{
+    float: left;
+    width: 350rpx;
+}
+
+.form-item-code .code-img{
+    float: right;
+    margin-top: 4rpx;
+    height: 88rpx;
+    width: 236rpx;
+}
+
+.form-item .clear{
+    position: absolute;
+    top: 26rpx;
+    right: 18rpx;
+    z-index: 2;
+    display: block;
+    background: #fff;
+    height: 44rpx;
+    width: 44rpx;
+}
+
+.login-btn{
+    margin: 60rpx 0 40rpx 0;
+    height: 96rpx;
+    line-height: 96rpx;
+    color: #fff;
+    font-size: 30rpx;
+    width: 100%;
+    background: #b4282d;
+    border-radius: 6rpx;
+}
+
+.form-item-text{
+    height: 35rpx;
+    width: 100%;
+}
+
+.form-item-text .register{
+    display: block;
+    height: 34rpx;
+    float: left;
+    font-size: 28rpx;
+    color: #999;
+}
+
+.form-item-text .reset{
+    display: block;
+    height: 34rpx;
+    float: right;
+    font-size: 28rpx;
+    color: #999;
+}

+ 56 - 0
wx-mall-hk/pages/auth/reset/reset.js

@@ -0,0 +1,56 @@
+var app = getApp();
+Page({
+  data: {
+    username: '',
+    code: ''
+  },
+  onLoad: function (options) {
+    // 页面初始化 options为页面跳转所带来的参数
+    // 页面渲染完成
+    
+  },
+  onReady: function () {
+
+  },
+  onShow: function () {
+    // 页面显示
+
+  },
+  onHide: function () {
+    // 页面隐藏
+
+  },
+  onUnload: function () {
+    // 页面关闭
+
+  },
+  startLogin: function(){
+    var that = this;
+  },
+  bindUsernameInput: function(e){
+    
+    this.setData({
+      username: e.detail.value
+    });
+  },
+  bindCodeInput: function(e){
+    
+    this.setData({
+      code: e.detail.value
+    });
+  },
+  clearInput: function(e){
+    switch (e.currentTarget.id){
+      case 'clear-username':
+        this.setData({
+          username: ''
+        });
+        break;
+        case 'clear-code':
+        this.setData({
+          code: ''
+        });
+        break;
+    }
+  }
+})

+ 1 - 0
wx-mall-hk/pages/auth/reset/reset.json

@@ -0,0 +1 @@
+{}

+ 20 - 0
wx-mall-hk/pages/auth/reset/reset.wxml

@@ -0,0 +1,20 @@
+<view class="container">
+    <view class="form-box">
+
+    	<view class="form-item">
+    		<input class="username" value="{{username}}" bindinput="bindUsernameInput" placeholder="请输入账号" auto-focus/>
+    		<image wx:if="{{ username.length > 0 }}" id="clear-username" class="clear" src="/static/images/clear_input.png" catchtap="clearInput"></image>
+    	</view>
+
+		<view class="form-item-code" >
+			<view class="form-item code-item">
+				<input class="code" value="{{code}}" bindinput="bindCodeInput" placeholder="验证码"/>
+				<image class="clear" id="clear-code" wx:if="{{ code.length > 0 }}" src="/static/images/clear_input.png" catchtap="clearInput"></image>
+			</view>
+			<image class="code-img" src="https://dl.reg.163.com/cp?pd=yanxuan_web&pkid=SkeBZeG&random=1489903563234"></image>
+		</view>
+
+    	<button type="default" class="login-btn" bindtap="startNext">下一步</button>
+
+    </view>
+</view>

+ 68 - 0
wx-mall-hk/pages/auth/reset/reset.wxss

@@ -0,0 +1,68 @@
+.form-box{
+    width: 100%;
+    height: auto;
+    overflow: hidden;
+    padding: 0 40rpx;
+    margin-top: 96rpx;
+    background: #fff;
+}
+
+.form-item{
+    position: relative;
+    background: #fff;
+    height: 96rpx;
+    border-bottom: 1px solid #d9d9d9;
+}
+
+.form-item .username, .form-item .code{
+    position: absolute;
+    top: 26rpx;
+    left: 0;
+    display: block;
+    width: 100%;
+    height: 44rpx;
+    background: #fff;
+    color: #333;
+    font-size: 30rpx;
+}
+
+.form-item-code{
+    margin-top:32rpx;
+    height: auto;
+    overflow: hidden;
+    width: 100%;
+}
+
+.form-item-code .form-item{
+    float: left;
+    width: 350rpx;
+}
+
+.form-item-code .code-img{
+    float: right;
+    margin-top: 4rpx;
+    height: 88rpx;
+    width: 236rpx;
+}
+
+.form-item .clear{
+    position: absolute;
+    top: 26rpx;
+    right: 18rpx;
+    z-index: 2;
+    display: block;
+    background: #fff;
+    height: 44rpx;
+    width: 44rpx;
+}
+
+.login-btn{
+    margin: 60rpx 0 40rpx 0;
+    height: 96rpx;
+    line-height: 96rpx;
+    color: #fff;
+    font-size: 30rpx;
+    width: 100%;
+    background: #b4282d;
+    border-radius: 6rpx;
+}

+ 56 - 0
wx-mall-hk/pages/brand/brand.js

@@ -0,0 +1,56 @@
+var util = require('../../utils/util.js');
+var api = require('../../config/api.js');
+var app = getApp();
+Page({
+  data: {
+    brandList: [],
+    page: 1,
+    size: 10,
+    totalPages: 1
+  },
+  onLoad: function (options) {
+    // 页面初始化 options为页面跳转所带来的参数
+    this.getBrandList();
+  },
+  getBrandList: function () {
+    wx.showLoading({
+      title: '加载中...',
+    });
+    let that = this;
+    util.request(api.BrandList, { page: that.data.page, size: that.data.size }).then(function (res) {
+      if (res.errno === 0) {
+        that.setData({
+          brandList: that.data.brandList.concat(res.data.data),
+          totalPages: res.data.totalPages
+        });
+      }
+      wx.hideLoading();
+    });
+  },
+  onReachBottom (){
+    if (this.data.totalPages > this.data.page) {
+      this.setData({
+        page: this.data.page + 1
+      });
+    } else {
+      return false;
+    }
+
+    this.getBrandList();
+  },
+  onReady: function () {
+
+  },
+  onShow: function () {
+    // 页面显示
+
+  },
+  onHide: function () {
+    // 页面隐藏
+
+  },
+  onUnload: function () {
+    // 页面关闭
+
+  }
+})

+ 1 - 0
wx-mall-hk/pages/brand/brand.json

@@ -0,0 +1 @@
+{}

+ 16 - 0
wx-mall-hk/pages/brand/brand.wxml

@@ -0,0 +1,16 @@
+<view class="container">
+    <view class="brand-list" >
+        <navigator url="../brandDetail/brandDetail?id={{item.id}}"  class="item" wx:for="{{brandList}}" wx:key="id">
+            <view class="img-bg">
+                <image src="{{item.app_list_pic_url}}" background-size="cover"></image>
+            </view>
+            <view class="txt-box">
+                <view class="line">
+                    <text class="name" >{{item.name}}</text>
+                    <text class="s">|</text>
+                    <text class="price">{{item.floor_price}}元起</text>
+                </view>
+            </view>
+        </navigator >
+    </view>
+</view>

+ 52 - 0
wx-mall-hk/pages/brand/brand.wxss

@@ -0,0 +1,52 @@
+.brand-list .item{
+    display: block;
+    width: 750rpx;
+    height: 416rpx;
+    position: relative;
+    margin-bottom: 4rpx;
+}
+
+.brand-list .item .img-bg{
+    position: absolute;
+    left:0;
+    top:0;
+    z-index: 0;
+    width: 750rpx;
+    height: 417rpx;
+    overflow: hidden;
+}
+
+.brand-list .item .img-bg image{
+    width: 750rpx;
+    height: 416rpx;
+}
+
+.brand-list .item .txt-box{
+    position: absolute;
+    left:0;
+    top:0;
+    display: table;
+    z-index: 0;
+    width: 750rpx;
+    height: 417rpx;
+}
+
+.brand-list .item .line{
+    display: table-cell;
+    vertical-align: middle;
+    text-align: center;
+    height: 63rpx;
+    line-height: 63rpx;
+}
+
+.brand-list .item .line text{
+    font-size: 35rpx;
+    font-weight: 700;
+    text-shadow: 1rpx 1rpx rgba(0,0,0,.32);
+    color: #fff;
+}
+
+.brand-list .item .line .s{
+    padding: 0 10rpx;
+    font-size: 40rpx;
+}

+ 63 - 0
wx-mall-hk/pages/brandDetail/brandDetail.js

@@ -0,0 +1,63 @@
+var util = require('../../utils/util.js');
+var api = require('../../config/api.js');
+
+
+var app = getApp();
+
+Page({
+  data: {
+    id: 0,
+    brand: {},
+    goodsList: [],
+    page: 1,
+    size: 1000
+  },
+  onLoad: function (options) {
+    // 页面初始化 options为页面跳转所带来的参数
+    var that = this;
+    that.setData({
+      id: parseInt(options.id)
+    });
+    this.getBrand();
+  },
+  getBrand: function () {
+    let that = this;
+    util.request(api.BrandDetail, { id: that.data.id }).then(function (res) {
+      if (res.errno === 0) {
+        that.setData({
+          brand: res.data.brand
+        });
+
+        that.getGoodsList();
+      }
+    });
+  },
+  getGoodsList() {
+    var that = this;
+
+    util.request(api.GoodsList, { brandId: that.data.id, page: that.data.page, size: that.data.size})
+      .then(function (res) {
+        if (res.errno === 0) {
+          that.setData({
+            goodsList: res.data.data
+          });
+        }
+      });
+  },
+  onReady: function () {
+    // 页面渲染完成
+
+  },
+  onShow: function () {
+    // 页面显示
+
+  },
+  onHide: function () {
+    // 页面隐藏
+
+  },
+  onUnload: function () {
+    // 页面关闭
+
+  }
+})

+ 3 - 0
wx-mall-hk/pages/brandDetail/brandDetail.json

@@ -0,0 +1,3 @@
+{
+    
+}

+ 28 - 0
wx-mall-hk/pages/brandDetail/brandDetail.wxml

@@ -0,0 +1,28 @@
+<view class="container">
+    <view class="brand-info">
+        <view class="name">
+            <image class="img" src="{{brand.app_list_pic_url}}" background-size="cover"></image>
+            <view class="info-box">
+                <view class="info">
+                    <text class="txt">{{brand.name}}</text>
+                    <text class="line"></text>
+                </view>
+            </view>
+        </view>
+        <view class="desc">
+            {{brand.simple_desc}}
+        </view>
+    </view>
+
+    <view class="cate-item">
+        <view class="b">
+            <block wx:for="{{goodsList}}" wx:for-index="iindex" wx:for-item="iitem">
+            <navigator class="item {{iindex % 2 == 0 ? 'item-b' : ''}}" url="../goods/goods?id={{iitem.id}}">
+                <image class="img" src="{{iitem.list_pic_url}}" background-size="cover"></image>
+                <text class="name">{{iitem.name}}</text>
+                <text class="price">¥{{iitem.retail_price}}</text>
+            </navigator>
+            </block>
+        </view>
+    </view>
+</view>

+ 110 - 0
wx-mall-hk/pages/brandDetail/brandDetail.wxss

@@ -0,0 +1,110 @@
+page{
+    background: #f4f4f4;
+}
+.brand-info .name{
+    width: 100%;
+    height: 290rpx;
+    position: relative;
+}
+
+.brand-info .img{
+    position: absolute;
+    top:0;
+    left:0;
+    width: 100%;
+    height: 290rpx;
+}
+
+.brand-info .info-box{
+    position: absolute;
+    top:0;
+    left:0;
+    width: 100%;
+    height: 290rpx;
+    text-align: center;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+}
+
+.brand-info .info{
+    display: block;
+}
+
+.brand-info .txt{
+    display: block;
+    height: 37.5rpx;
+    font-size: 37.5rpx;
+    color: #fff;
+}
+
+.brand-info .line{
+    margin: 0 auto;
+    margin-top: 16rpx;
+    display: block;
+    height: 2rpx;
+    width: 145rpx;
+    background: #fff;
+}
+
+.brand-info .desc{
+    background: #fff;
+    width: 100%;
+    height: auto;
+    overflow: hidden;
+    padding: 41.5rpx 31.25rpx;
+    font-size: 30rpx;
+    color: #666;
+    line-height: 41.5rpx;
+    text-align: center;
+}
+
+.cate-item .b{
+  width: 750rpx;
+  height: auto;
+  overflow: hidden;
+  border-top: 1rpx solid #f4f4f4;
+  margin-top: 20rpx;
+}
+
+.cate-item .b .item{
+  float: left;
+  background: #fff;
+  width: 375rpx;
+  padding-bottom: 33.333rpx;
+  border-bottom: 1rpx solid #f4f4f4;
+  height: auto;
+  overflow: hidden;
+  text-align: center;
+}
+
+.cate-item .b .item-b{
+ border-right: 1rpx solid #f4f4f4;
+}
+
+.cate-item .item .img{
+    margin-top: 10rpx;
+  width: 302rpx;
+  height: 302rpx;
+}
+
+.cate-item .item .name{
+  display: block;
+  width: 365.625rpx;
+  height: 35rpx;
+  padding: 0 20rpx;
+  overflow: hidden;
+  margin: 11.5rpx 0 22rpx 0;
+  text-align: center;
+  font-size: 26rpx;
+  color: #333;
+}
+
+.cate-item .item .price{
+  display: block;
+  width: 365.625rpx;
+  height: 30rpx;
+  text-align: center;
+  font-size: 30rpx;
+  color: #b4282d;
+}

+ 522 - 0
wx-mall-hk/pages/cart/cart.js

@@ -0,0 +1,522 @@
+var util = require('../../utils/util.js');
+var goodsUtil = require('../../utils/goods.js');
+var api = require('../../config/api.js');
+
+var app = getApp();
+
+Page({
+  data: {
+    cartGoods00: [],//保税仓数据
+    cartGoods02: [],//保税展示数据
+    cartGoods10: [],//现场速递数据
+    cartGoods11: [],//普通商品
+    cartGoods: [],
+    validCartList: [],
+    goodsBizTypeList: ['保税仓','保税展示','现场速递','普通商品'],
+    goodsBizType: '',//货品业务类型
+    footprintList: [],
+    cartTotal: {
+      "goodsCount": 0,
+      "goodsAmount": 0.00,
+      "checkedGoodsCount": 0,
+      "checkedGoodsAmount": 0.00
+    },
+    checkedAllStatus: true,
+    checkedTypeStatus00: true,
+    checkedTypeStatus02: true,
+    checkedTypeStatus10: true,
+    checkedTypeStatus11: true,
+    couponInfoList: [],
+    openAttr: false,
+    specificationList: {},
+    checkedSpecText: '请选择规格数量',
+    number: 1,
+    isAdd: true,
+    mobile: '',
+    retailPrice: '',
+    stockNum: 0,
+    cartNumber: 0,
+  },
+  onLoad: function (options) {
+    // 页面初始化 options为页面跳转所带来的参数
+  },
+  onReady: function () {
+    // 页面渲染完成
+
+  },
+  onShow: function () {
+    // 页面显示
+    if (wx.getStorageSync('userInfo') || wx.getStorageSync('token')) {
+      this.getCartList();
+      this.getFootprintList();
+    } else {
+      wx.navigateTo({
+        url: '/pages/auth/btnAuth/btnAuth',
+      })
+    }
+  },
+  onHide: function () {
+    // 页面隐藏
+
+  },
+  onUnload: function () {
+    // 页面关闭
+
+  },
+  setCommonData(res) {
+    let that = this;
+    that.setData({
+      cartGoods: res.data.cartList,
+      cartGoods00: res.data.cart00List,
+      cartGoods02: res.data.cart02List,
+      cartGoods10: res.data.cart10List,
+      cartGoods11: res.data.cart11List,
+      validCartList: res.data.validCartList,
+      cartTotal: res.data.cartTotal,
+      couponInfoList: res.data.couponInfoList
+    });
+  },
+  setCheckedData() {
+    let that = this;
+    that.setData({
+      checkedAllStatus: that.isCheckedAll(),
+      checkedTypeStatus00: that.isCheckedTypeStatus00(),
+      checkedTypeStatus02: that.isCheckedTypeStatus02(),
+      checkedTypeStatus10: that.isCheckedTypeStatus10(),
+      checkedTypeStatus11: that.isCheckedTypeStatus11()
+    });
+  },
+  setCheckedAllData() {
+    let that = this;
+    that.setData({
+      checkedAllStatus: that.isCheckedAll(),
+      checkedTypeStatus00: that.isCheckedAll(),
+      checkedTypeStatus02: that.isCheckedAll(),
+      checkedTypeStatus10: that.isCheckedAll(),
+      checkedTypeStatus11: that.isCheckedAll()
+    });
+  },
+  getCartList: function () {//获取购物车数据
+    let that = this;
+    wx.showLoading({
+      title: '加载中...',
+    });
+    util.request(api.CartList).then(function (res) {
+      if (res.errno === 0) {
+        that.setCommonData(res);
+      }
+      wx.hideLoading();
+      //数据渲染选中
+      that.setCheckedData();
+    });
+  },
+  isCheckedAll: function () {
+    //判断购物车所有商品是否已全选
+    return this.data.cartGoods.every(function (element, index, array) {
+      if (element.checked == true) {
+        return true;
+      } else {
+        return false;
+      }
+    });
+  },
+  isCheckedTypeStatus00: function () {
+      //判断该业务类型的购物车商品是否已全选
+      return this.data.cartGoods00.every(function (element, index, array) {
+        if (element.checked == true) {
+          return true;
+        } else {
+          return false;
+        }
+      });     
+  },
+  isCheckedTypeStatus02: function () {
+    //判断该业务类型的购物车商品是否已全选
+    return this.data.cartGoods02.every(function (element, index, array) {
+      if (element.checked == true) {
+        return true;
+      } else {
+        return false;
+      }
+    });
+  },
+  isCheckedTypeStatus10: function () {
+    //判断该业务类型的购物车商品是否已全选
+    return this.data.cartGoods10.every(function (element, index, array) {
+      if (element.checked == true) {
+        return true;
+      } else {
+        return false;
+      }
+    });
+  },
+  isCheckedTypeStatus11: function () {
+    //判断该业务类型的购物车商品是否已全选
+    return this.data.cartGoods11.every(function (element, index, array) {
+      if (element.checked == true) {
+        return true;
+      } else {
+        return false;
+      }
+    });
+  },
+  toIndexPage: function () {
+    wx.switchTab({
+      url: "/pages/index/index"
+    });
+  },
+  checkedItem: function (event) {
+    let itemIndex = event.target.dataset.itemIndex;
+    let that = this;
+
+    util.request(api.CartChecked, {
+      productIds: that.data.cartGoods[itemIndex].product_id,
+      isChecked: that.data.cartGoods[itemIndex].checked ? 0 : 1
+    }, 'POST').then(function (res) {
+      if (res.errno === 0) {
+        that.setCommonData(res);
+      }
+      that.setCheckedData();
+    });
+
+  },
+  getCheckedGoodsCount: function () {
+    let checkedGoodsCount = 0;
+    this.data.cartGoods.forEach(function (v) {
+      if (v.checked === true) {
+        checkedGoodsCount += v.number;
+      }
+    });
+    console.log(checkedGoodsCount);
+    return checkedGoodsCount;
+  },
+  checkedAll: function () {
+    let that = this;
+    var productIds = this.data.cartGoods.map(function (v) {
+      return v.product_id;
+    });
+    util.request(api.CartChecked, {
+      productIds: productIds.join(','),
+      isChecked: that.isCheckedAll() ? 0 : 1
+    }, 'POST').then(function (res) {
+      if (res.errno === 0) {
+        that.setCommonData(res);
+      }
+      that.setCheckedAllData();
+    });
+  },
+  checkedAllGoodType: function (e) {
+    let that = this;
+    let goodsBizType = e.target.dataset.goodsBizType;
+    let isCheckedTypeStatu;
+    if (goodsBizType == '00') {
+      isCheckedTypeStatu = that.isCheckedTypeStatus00();
+    }
+    if (goodsBizType == '02') {
+      isCheckedTypeStatu = that.isCheckedTypeStatus02();
+    }
+    if (goodsBizType == '10') {
+      isCheckedTypeStatu = that.isCheckedTypeStatus10();
+    }
+    if (goodsBizType == '11') {
+      isCheckedTypeStatu = that.isCheckedTypeStatus11();
+    }
+    util.request(api.CartChecked, {
+      isChecked: isCheckedTypeStatu ? 0 : 1,
+      goodsBizType: goodsBizType
+    }, 'POST').then(function (res) {
+      if (res.errno === 0) {
+        that.setCommonData(res);
+      }
+
+      if (goodsBizType == '00') {
+          that.setData({
+            checkedTypeStatus00: that.isCheckedTypeStatus00()
+        });
+      }
+      if (goodsBizType == '02') {
+        that.setData({
+          checkedTypeStatus02: that.isCheckedTypeStatus02()
+        });
+      }
+      if (goodsBizType == '10') {
+        that.setData({
+          checkedTypeStatus10: that.isCheckedTypeStatus10()
+        });
+      }
+      if (goodsBizType == '11') {
+        that.setData({
+          checkedTypeStatus11: that.isCheckedTypeStatus11()
+        });
+      }
+      that.setData({
+        checkedAllStatus: that.isCheckedAll()
+      });
+    });
+  },
+  updateCart: function (productId, goodsId, number, beforeNumber, id, itemIndex) {
+    let that = this;
+
+    util.request(api.CartUpdate, {
+      productId: productId,
+      goodsId: goodsId,
+      number: number,
+      id: id
+    }, 'POST').then(function (res) {
+      if (res.errno === 0) {
+        // console.log(res.data);
+        that.setCommonData(res);
+      } else {
+        // util.showErrorToast(res.errmsg);
+        wx.showModal({
+          title: '提示信息',
+          content: res.errmsg,
+          showCancel: false
+        });
+        let cartItem = that.data.cartGoods[itemIndex];
+        cartItem.number = beforeNumber;
+        that.setData({
+          cartGoods: that.data.cartGoods
+        });
+        that.setCommonData(res);
+      }
+      that.setCheckedData();
+    });
+  },
+  cutNumber: function (event) {
+    let itemIndex = event.target.dataset.itemIndex;
+    let cartItem = this.data.cartGoods[itemIndex];
+    let beforeNumber = cartItem.number;
+    let number = (cartItem.number - 1 > 1) ? cartItem.number - 1 : 1;
+    cartItem.number = number;
+    this.setData({
+      cartGoods: this.data.cartGoods
+    });
+    this.updateCart(cartItem.product_id, cartItem.goods_id, number, beforeNumber, cartItem.id, itemIndex);
+  },
+  addNumber: function (event) {
+    let itemIndex = event.target.dataset.itemIndex;
+    let cartItem = this.data.cartGoods[itemIndex];
+    let beforeNumber = cartItem.number;
+    let number = cartItem.number + 1;
+    cartItem.number = number;
+    this.setData({
+      cartGoods: this.data.cartGoods
+    });
+    this.updateCart(cartItem.product_id, cartItem.goods_id, number, beforeNumber, cartItem.id, itemIndex);
+  },
+  checkoutOrder: function () {
+    //获取已选择的商品
+    let that = this;
+    util.request(api.getCurUser, {
+      userInfo: app.globalData.userInfo
+    }, 'POST').then(function (res) {
+      if (res.errno === 0) {
+        // console.log('that.data.mobile:' + res.data.mobile);
+        if (res.data.mobile == '' || res.data.mobile == null) {
+          wx.showModal({
+            title: '',
+            confirmColor: '#b4282d',
+            showCancel: false,
+            content: '您的手机号码未绑定,请先绑定手机号再进行购买',
+            success: function (res) {
+              if (res.confirm) {
+                wx.navigateTo({
+                  url: '../../pages/auth/newuser/newuser'
+                });
+              }
+            }
+          });
+        } else {
+          var checkedGoods = that.data.cartGoods.filter(function (element, index, array) {
+            if (element.checked == true) {
+              return true;
+            } else {
+              return false;
+            }
+          });
+
+          if (checkedGoods.length <= 0) {
+            return false;
+          }
+          wx.navigateTo({
+            url: '../shopping/checkout/checkout'
+          })
+        }
+      }
+    });
+  },
+  deleteCart: function (event) {
+    //获取已选择的商品
+    let that = this;
+
+    let cartId = event.target.dataset.cartId;
+    let goodsName = event.target.dataset.goodsName;
+
+    wx.showModal({
+      title: '',
+      content: '确定要删除' + goodsName + '?',
+      success: function (res) {
+        if (res.confirm) {
+          util.request(api.CartDelete, {
+            cartId: cartId
+          }, 'POST').then(function (res) {
+            if (res.errno === 0) {
+              that.setCommonData(res);
+            }
+            that.setCheckedData();
+          });
+          console.log('用户点击确定')
+        }
+      }
+    });
+  },
+  getFootprintList() {
+    let that = this;
+    util.request(api.GuessFootprintList, { storeId: wx.getStorageSync('storeId') },).then(function (res) {
+      if (res.errno === 0) {
+        that.setData({
+          footprintList: res.data.list
+        });
+      }
+    });
+  },
+  switchAttrPop: function () {
+    this.setData({
+      openAttr: !this.data.openAttr
+    })
+  },
+  clickSkuValue: function (event) {
+    let that = this;
+    let specValueId = event.currentTarget.dataset.valueId;
+    let index = event.currentTarget.dataset.index;
+    let _specificationList = this.data.specificationList;
+    for (let j = 0; j < _specificationList[index].valueList.length; j++) {
+      if (_specificationList[index].valueList[j].id == specValueId) {
+        //如果已经选中,则反选
+        if (_specificationList[index].valueList[j].checked) {
+          _specificationList[index].valueList[j].checked = false;
+        } else {
+          _specificationList[index].valueList[j].checked = true;
+        }
+      } else {
+        _specificationList[index].valueList[j].checked = false;
+      }
+    }
+    this.setData({
+      'specificationList': _specificationList
+    });
+    //重新计算spec改变后的信息
+    goodsUtil.changeSpecInfo(that);
+  },
+  cutNumber2: function () {
+    this.setData({
+      number: (this.data.number - 1 > 1) ? this.data.number - 1 : 1
+    });
+  },
+  addNumber2: function () {
+    this.setData({
+      number: this.data.number + 1
+    });
+  },
+
+  //购物车增加
+  addCart: function (e) {
+    let that = this;
+    that.setData({
+      number:1
+    });
+    var goodsId = e.currentTarget.dataset.goodsId;
+    util.request(api.GoodsSku, { goodsId: goodsId }).then(function (res) {
+      if (res.errno === 0 && null != res.data) {
+        that.setData({
+          goodsVo: res.data.goodsVo,
+          specificationList: res.data.specificationList,
+          productList: res.data.productList,
+          openAttr: !that.data.openAttr,
+          stockNum: res.data.productList[0].stock_num,
+          cartNumber: res.data.cartNumber,
+          checkedSpecText: res.data.specificationList[0].valueList[0].value
+        });
+        //
+        let _specificationList = res.data.specificationList;
+        for (let i = 0; i < _specificationList.length; i++) {
+          if (_specificationList[i].valueList.length == 1) {
+            //如果已经选中,则反选
+            _specificationList[i].valueList[0].checked = true;
+          }
+        }
+        that.setData({
+          'specificationList': _specificationList
+        });
+      }
+    });
+  },
+  //购物车增加
+  addToCart: function () {
+    let that = this;
+    var goodsId = that.data.goodsVo.id;
+    //提示选择完整规格
+    if (!that.data.productList || !that.data.productList.length) {
+      util.showErrorToast('当前门店没有库存');
+      return false;
+    }
+    //提示选择完整规格
+    if (!goodsUtil.isCheckedAllSpec(that)) {
+      return false;
+    }
+    //根据选中的规格,判断是否有对应的sku信息
+    let checkedProduct = goodsUtil.getCheckedProductItem(goodsUtil.getCheckedSpecKey(that), that);
+    if (!checkedProduct || checkedProduct.length <= 0) {
+      //找不到对应的product信息,提示没有库存
+      return false;
+    }
+    //验证库存
+    if (checkedProduct.stock_num < this.data.number) {
+      //找不到对应的product信息,提示没有库存
+      return false;
+    }
+    util.request(api.CartAdd, {
+      goodsId: goodsId,
+      productId: checkedProduct[0].id,
+      number: this.data.number
+    }, 'POST').then(function (res) {
+      if (res.errno === 0 && null != res.data) {
+        wx.showToast({
+          title: '添加成功',
+          icon: 'success',
+          mask: true
+        });
+        that.setData({
+          openAttr: !that.data.openAttr
+        })
+        // 页面显示
+        that.getCartList();
+        that.getFootprintList();
+      } else {
+        wx.showToast({
+          title: res.errmsg,
+          icon: 'none'
+        })
+      }
+    });
+  },
+  deleteValidCart: function () {//获取购物车数据
+    let that = this;
+    wx.showModal({
+      title: '',
+      content: '确定要清空所有失效商品?',
+      success: function (res) {
+        if (res.confirm) {
+          util.request(api.deleteValidCart).then(function (res) {
+            if (res.errno === 0) {
+              that.setCommonData(res);
+            } else {
+              util.showErrorToast(res.errmsg);
+            }
+          });
+        }
+      }
+    });
+  }
+})

+ 3 - 0
wx-mall-hk/pages/cart/cart.json

@@ -0,0 +1,3 @@
+{
+  "navigationBarTitleText": "购物车"
+}

+ 286 - 0
wx-mall-hk/pages/cart/cart.wxml

@@ -0,0 +1,286 @@
+<view class="container">
+  <view class="service-policy">
+    <!-- <view class="item">30分钟速达</view>
+    <view class="item">每日优选生鲜</view>
+    <view class="item">满88元免配送费</view> -->
+    <view class="item">新用户可领取5元优惠券</view>
+  </view> 
+  <view class="no-cart" wx:if="{{cartGoods.length <= 0}}">
+    <view class="c">
+      <view class="title-box">
+        购物车空空如也~
+      </view>
+      <view class="to-index-btn" bindtap="toIndexPage">
+        去逛逛
+      </view>
+    </view>
+  </view>
+  <view class="cart-view" >
+    <!-- <view class="group-item" wx:if="{{couponInfoList.length > 0}}">
+      <view class="coupon-info header" wx:for="{{couponInfoList}}" wx:key="{{item}}">
+        <text class="txt" wx:if="{{item.type===0}}">{{item.msg}}</text>
+        <navigator wx:if="{{item.type===1}}" url="../catalog/catalog" open-type="switchTab">
+          <text class="txt">{{item.msg}},去凑单  >>></text>
+        </navigator>
+      </view>
+    </view> -->
+    <view class="list">
+      <view class="group-item">
+        <view class="goods">
+          <view wx:if="{{cartGoods00.length != 0}}" class="checkbox-biz-type {{checkedTypeStatus00 ? 'checked' : ''}}" bindtap="checkedAllGoodType" data-goods-Biz-Type="00">
+          <image src="../../../static/images/service-bao.png" class="search-icon-shop"></image>
+          <text class="title-name ">保税仓</text></view>
+          <view class="item" wx:for="{{cartGoods}}" wx:if="{{item.goodsBizType == 00}}" wx:key="{{item.id}}">
+            <view class="checkbox {{item.checked ? 'checked' : ''}}" bindtap="checkedItem" data-item-index="{{index}}"></view>
+            <view class="cart-goods">
+              <navigator url="/pages/goods/goods?id={{item.goods_id}}">
+                <image class="img" src="{{item.list_pic_url}}"></image>
+              </navigator>
+              <view class="info">
+                <view class="t">
+                  <navigator url="/pages/goods/goods?id={{item.goods_id}}">
+                    <text class="name">{{item.goods_name}}</text>
+                  </navigator>
+                  <view class="goods-do">
+                    <text class="price">¥{{item.retail_price}}</text>
+                    <text class="org-price line-through">¥{{item.market_price}}</text>
+                  </view>
+                </view>
+                <view class="attr">{{null==item.goods_specification_name_value?"":item.goods_specification_name_value}}
+                </view>
+                <!-- //数量加减 -->
+                <view class="number-item">
+                  <view class="selnum">
+                    <view class="cut" data-goods-id="{{item.id}}" data-item-index="{{index}}" data-product-id="{{item.product_id}}" bindtap="cutNumber"></view>
+                    <input value="{{item.number}}" class="number" disabled="true" type="number" />
+                    
+                    <image class="add2" src="{{item.number < item.stockNum ? '/static/images/service-hsjh.png':'/static/images/service-ehsjh.png'}}" data-goods-id="{{item.id}}" data-item-index="{{index}}" data-product-id="{{item.product_id}}" catchtap="{{item.number < item.stockNum ?  'addNumber' : ''}}"></image>
+                    
+                  </view>
+                </view>
+                <view class="handle">
+                  <image catchtap="deleteCart" data-cart-id="{{item.id}}" data-goods-name="{{item.goods_name}}" class="del" src="/static/images/del-address.png"></image>
+                </view>
+              </view>
+            </view>
+          </view>
+
+        <view wx:if="{{cartGoods02.length != 0}}" class="checkbox-biz-type {{checkedTypeStatus02 ? 'checked' : ''}}" bindtap="checkedAllGoodType" data-goods-Biz-Type="02">
+          <image src="../../../static/images/service-zs.png" class="search-icon-shop"></image>
+          <text class="title-name">保税展示</text>
+        </view>
+
+          <view class="item" wx:for="{{cartGoods}}" wx:if="{{item.goodsBizType == 02}}" wx:key="{{item.id}}">
+            <view class="checkbox {{item.checked ? 'checked' : ''}}" bindtap="checkedItem" data-item-index="{{index}}"></view>
+            <view class="cart-goods">
+              <navigator url="/pages/goods/goods?id={{item.goods_id}}">
+                <image class="img" src="{{item.list_pic_url}}"></image>
+              </navigator>
+              <view class="info">
+                <view class="t">
+                  <navigator url="/pages/goods/goods?id={{item.goods_id}}">
+                    <text class="name">{{item.goods_name}}</text>
+                  </navigator>
+                  <view class="goods-do">
+                    <text class="price">¥{{item.retail_price}}</text>
+                    <text class="org-price line-through">¥{{item.market_price}}</text>
+                  </view>
+                </view>
+                <view class="attr">{{null==item.goods_specification_name_value?"":item.goods_specification_name_value}}
+                </view>
+                <!-- //数量加减 -->
+                <view class="number-item">
+                  <view class="selnum">
+                    <view class="cut" data-goods-id="{{item.id}}" data-item-index="{{index}}" data-product-id="{{item.product_id}}" bindtap="cutNumber"></view>
+                    <input value="{{item.number}}" class="number" disabled="true" type="number" />
+                    
+                    <image class="add2" src="{{item.number < item.stockNum ? '/static/images/service-hsjh.png':'/static/images/service-ehsjh.png'}}" data-goods-id="{{item.id}}" data-item-index="{{index}}" data-product-id="{{item.product_id}}" catchtap="{{item.number < item.stockNum ?  'addNumber' : ''}}"></image>
+                    
+                  </view>
+                </view>
+                <view class="handle">
+                  <image catchtap="deleteCart" data-cart-id="{{item.id}}" data-goods-name="{{item.goods_name}}" class="del" src="/static/images/del-address.png"></image>
+                </view>
+              </view>
+            </view>
+          </view>
+
+   
+          <view wx:if="{{cartGoods10.length != 0}}" class="checkbox-biz-type {{checkedTypeStatus10 ? 'checked' : ''}}" bindtap="checkedAllGoodType" data-goods-Biz-Type="10">
+            <image src="../../../static/images/service-ziti.png" class="search-icon-shop"></image>
+            <text class="title-name">现场速递</text>
+          </view>
+
+          <view class="item" wx:for="{{cartGoods}}" wx:if="{{item.goodsBizType == 10}}" wx:key="{{item.id}}">
+            <view class="checkbox {{item.checked ? 'checked' : ''}}" bindtap="checkedItem" data-item-index="{{index}}"></view>
+            <view class="cart-goods">
+              <navigator url="/pages/goods/goods?id={{item.goods_id}}">
+                <image class="img" src="{{item.list_pic_url}}"></image>
+              </navigator>
+              <view class="info">
+                <view class="t">
+                  <navigator url="/pages/goods/goods?id={{item.goods_id}}">
+                    <text class="name">{{item.goods_name}}</text>
+                  </navigator>
+                  <view class="goods-do">
+                    <text class="price">¥{{item.retail_price}}</text>
+                    <text class="org-price line-through">¥{{item.market_price}}</text>
+                  </view>
+                </view>
+                <view class="attr">{{null==item.goods_specification_name_value?"":item.goods_specification_name_value}}
+                </view>
+                <!-- //数量加减 -->
+                <view class="number-item">
+                  <view class="selnum">
+                    <view class="cut" data-goods-id="{{item.id}}" data-item-index="{{index}}" data-product-id="{{item.product_id}}" bindtap="cutNumber"></view>
+                    <input value="{{item.number}}" class="number" disabled="true" type="number" />
+                    
+                    <image class="add2" src="{{item.number < item.stockNum ? '/static/images/service-hsjh.png':'/static/images/service-ehsjh.png'}}" data-goods-id="{{item.id}}" data-item-index="{{index}}" data-product-id="{{item.product_id}}" catchtap="{{item.number < item.stockNum ?  'addNumber' : ''}}"></image>
+                    
+                  </view>
+                </view>
+                <view class="handle">
+                  <image catchtap="deleteCart" data-cart-id="{{item.id}}" data-goods-name="{{item.goods_name}}" class="del" src="/static/images/del-address.png"></image>
+                </view>
+              </view>
+            </view>
+          </view>
+   
+
+          <view wx:if="{{cartGoods11.length != 0}}" class="checkbox-biz-type {{checkedTypeStatus11 ? 'checked' : ''}}" bindtap="checkedAllGoodType" data-goods-Biz-Type="11">
+            <image src="../../../static/images/service-ptsp.png" class="search-icon-shop"></image>
+            <text class="title-name">普通商品</text>
+          </view>
+
+          <view class="item" wx:for="{{cartGoods}}" wx:if="{{item.goodsBizType == 11}}" wx:key="{{item.id}}">
+            <view class="checkbox {{item.checked ? 'checked' : ''}}" bindtap="checkedItem" data-item-index="{{index}}"></view>
+            <view class="cart-goods">
+              <navigator url="/pages/goods/goods?id={{item.goods_id}}">
+                <image class="img" src="{{item.list_pic_url}}"></image>
+              </navigator>
+              <view class="info">
+                <view class="t">
+                  <navigator url="/pages/goods/goods?id={{item.goods_id}}">
+                    <text class="name">{{item.goods_name}}</text>
+                  </navigator>
+                  <view class="goods-do">
+                    <text class="price">¥{{item.retail_price}}</text>
+                    <text class="org-price line-through">¥{{item.market_price}}</text>
+                  </view>
+                </view>
+                <view class="attr">{{null==item.goods_specification_name_value?"":item.goods_specification_name_value}}
+                </view>
+                <view class="number-item">
+                  <view class="selnum">
+                    <view class="cut" data-goods-id="{{item.id}}" data-item-index="{{index}}" data-product-id="{{item.product_id}}" bindtap="cutNumber"></view>
+                    <input value="{{item.number}}" class="number" disabled="true" type="number" />
+                   
+                    <image class="add2" src="{{item.number < item.stockNum ? '/static/images/service-hsjh.png':'/static/images/service-ehsjh.png'}}" data-goods-id="{{item.id}}" data-item-index="{{index}}" data-product-id="{{item.product_id}}" catchtap="{{item.number < item.stockNum ?  'addNumber' : ''}}"></image>
+                    
+                  </view>
+                </view>
+                <view class="handle">
+                  <image catchtap="deleteCart" data-cart-id="{{item.id}}" data-goods-name="{{item.goods_name}}" class="del" src="/static/images/del-address.png"></image>
+                </view>
+              </view>
+            </view>
+          </view>
+
+          </view>
+      </view>
+    </view>
+
+    <view class="list" wx:if="{{validCartList.length > 0}}">
+      <view class="group-item">
+        <view style='margin-left: 8rpx;margin-top: 8rpx;float:left;width:166px;'>
+          <text style='font-size:24rpx;color:rgba(87, 86, 86, 0.63);'>失效宝贝{{validCartList.length}}件</text>
+        </view>
+        <view style='float:right;width:90px;margin-top: 8rpx;' bindtap='deleteValidCart'>
+          <text style='font-size:24rpx;color:red;'>清空失效宝贝</text>
+        </view>
+        <view class="goods">
+          <view class="item" wx:for="{{validCartList}}" wx:key="{{item.id}}">
+            <view class="shixiao">失效</view>
+            <view class="cart-goods">
+              <navigator url="/pages/goods/goods?id={{item.goods_id}}">
+                <image class="img" src="{{item.list_pic_url}}"></image>
+              </navigator>
+              <view class="info">
+                <view class="t">
+                  <navigator url="/pages/goods/goods?id={{item.goods_id}}">
+                    <text class="name" style='color:rgba(87, 86, 86, 0.63);'>{{item.goods_name}} {{null==item.goods_specification_name_value?"":item.goods_specification_name_value}}</text>
+                  </navigator>
+                </view>
+                <view class="number-item-text">
+                  商品已不能购买,请联系卖家
+                </view>
+                <!-- <view class="handle">
+                  找相似
+                </view> -->
+              </view>
+            </view>
+          </view>
+          </view>
+      </view>
+    </view>
+
+    <view class="a-guess" wx:if="{{footprintList.length > 0}}">
+      <view class="h">
+        <view>
+          <text class="txt">猜你喜欢</text>
+        </view>
+      </view>
+      <view class="b">
+        <block wx:for="{{footprintList}}" wx:for-index="iindex" wx:for-item="iitem" wx:key="unique">
+          <navigator wx:if="{{iitem.retail_price > 0}}" class="item {{iindex % 2 == 0 ? 'item-b' : '' }}" url="../goods/goods?id={{iitem.goods_id}}">
+            <image class="img2" src="{{iitem.list_pic_url}}" ></image>
+            <text class="name">{{iitem.name}}</text>
+            <view class="price" data-goods-id="{{iitem.goods_id}}" catchtap='addCart' >¥{{iitem.retail_price}}
+              <image data-goods-id="{{iitem.goods_id}}" catchtap='addCart' class="cart" src="/static/images/cart.png" background-size="cover"></image>
+            </view>
+          </navigator>
+        </block>
+      </view>
+
+       <view wx:if="{{openAttr}}" class="attr-pop">
+              <view class="attr-close" bindtap="switchAttrPop">X</view>
+              <view class="img-info">
+                <image class="img" src="{{goodsVo.list_pic_url}}"></image>
+                <view class="info">
+                  <view class="c">
+                    <view class="p">价格:¥{{goodsVo.retail_price}}</view>
+                    <view class="a" wx:if="{{productList.length>0}}">已选择:{{checkedSpecText}}</view>
+                  </view>
+                </view>
+              </view>
+              <view class="spec-con">
+                <view class="spec-item" wx:for="{{specificationList}}" wx:key="{{item.specification_id}}"  wx:for-index="itemIndex">
+                  <view class="name">{{item.name}}</view>
+                  <view class="values">
+                    <view class="value {{vitem.checked ? 'selected' : ''}}" bindtap="clickSkuValue" wx:for="{{item.valueList}}" wx:for-item="vitem" wx:key="{{vitem.id}}"   data-index="{{itemIndex}}"
+                     data-value-id="{{vitem.id}}" data-name-id="{{vitem.specification_id}}">{{vitem.value}}</view>
+                  </view>
+                </view>
+
+                <view class="number-item">
+                  <view class="name">数量</view>
+                  <view class="selnum">
+                    <view class="cut" bindtap="cutNumber2">-</view>
+                    <input value="{{number}}" class="number" disabled="true" type="number" />
+                    <view class="{{number+cartNumber>= stockNum? 'addEnabel':'addCart'}}" bindtap="{{number+cartNumber>= stockNum ? '':'addNumber2'}}">+</view>
+                  </view>
+                </view>
+              </view>
+                <view class="bottom-btn">
+               <view class="r" bindtap="addToCart">加入购物车</view>
+                </view>
+            </view>
+    </view>
+
+    <view class="cart-bottom">
+      <view class="checkbox {{checkedAllStatus ? 'checked' : ''}}" bindtap="checkedAll">全选({{cartTotal.checkedGoodsCount}})</view>
+      <view class="total">{{'¥'+cartTotal.checkedGoodsAmount}}</view>
+      <view class="checkout" bindtap="checkoutOrder" wx:if="{{!isEditCart}}">下单</view>
+    </view>
+  </view>
+</view>

+ 724 - 0
wx-mall-hk/pages/cart/cart.wxss

@@ -0,0 +1,724 @@
+page {
+  height: 100%;
+  min-height: 100%;
+  background: #f4f4f4;
+}
+
+.container {
+  background: #f4f4f4;
+  width: 100%;
+  height: auto;
+  min-height: 100%;
+  overflow: hidden;
+}
+
+.service-policy {
+  width: 750rpx;
+  height: 73rpx;
+  background: #f4f4f4;
+  padding: 0 31.25rpx;
+  display: flex;
+  flex-flow: row nowrap;
+  align-items: center;
+  justify-content: space-between;
+}
+
+.service-policy .item {
+  background: url(http://120.76.26.84:80/group1/M00/00/01/rBJEdVvr10OAUODSAAAA2Yyhu9Q336.png) 0 center no-repeat;
+  background-size: 10rpx;
+  padding-left: 15rpx;
+  display: flex;
+  align-items: center;
+  font-size: 25rpx;
+  color: #666;
+}
+
+.no-cart {
+  width: 100%;
+  height: auto;
+  margin: 0 auto;
+}
+
+.no-cart .c {
+  width: 100%;
+  height: auto;
+  margin-top: 120rpx;
+}
+
+.no-cart .c image {
+  margin: 0 auto;
+  display: block;
+  text-align: center;
+  width: 258rpx;
+  height: 258rpx;
+}
+
+.no-cart .c text {
+  margin: 0 auto;
+  display: block;
+  width: 258rpx;
+  height: 29rpx;
+  line-height: 29rpx;
+  text-align: center;
+  font-size: 29rpx;
+  color: #999;
+}
+
+.title-box {
+  width: 100%;
+  padding-top: 98rpx;
+  text-align: center;
+  font-size: 28rpx;
+  color: #999;
+  background: url(http://120.76.26.84:80/group1/M00/00/01/rBJEdVvr11yATJl8AAAQcvbdsNw695.png) no-repeat center 5rpx;
+  background-size: 100rpx auto;
+  margin-bottom: 50rpx;
+}
+
+.to-index-btn {
+  color: #fff;
+  background: #e64340;
+  border-radius: 6px;
+  width: 300rpx;
+  height: auto;
+  line-height: 70rpx;
+  text-align: center;
+  font-size: 28rpx;
+  margin: 0 auto;
+  display: block;
+  margin-bottom:180rpx;
+}
+
+.cart-view .group-item .header {
+  width: 100%;
+  height: 94rpx;
+  line-height: 94rpx;
+  padding: 0 26rpx;
+  border-bottom: 1px solid #f4f4f4;
+}
+
+.cart-view {
+  width: 96%;
+  height: auto;
+  overflow: hidden;
+  margin-left: 14rpx;
+}
+
+.cart-view .list {
+  height: auto;
+  width: 100%;
+  overflow: hidden;
+  /* margin-bottom: 10rpx; */
+}
+
+.cart-view .group-item {
+  height: auto;
+  width: 100%;
+  background: #fff;
+  margin-bottom: 18rpx;
+}
+
+.cart-view .item {
+  height: 230rpx;
+  width: 100%;
+  overflow: hidden;
+}
+
+.cart-view .item .checkbox {
+  float: left;
+  height: 34rpx;
+  width: 5%;
+  margin: 65rpx 18rpx 65rpx 22rpx;
+  background: url(http://120.76.26.84:80/group1/M00/00/01/rBJEdVvr1-aAFY_xAAAByIPHW08081.png) no-repeat;
+  background-size: 34rpx;
+}
+
+.cart-view .item .checkbox.checked {
+  background: url(http://120.76.26.84:80/group1/M00/00/02/rBJEdVvr2AmALCJBAAABdbLfmi0325.png) no-repeat;
+  background-size: 34rpx;
+}
+
+.cart-view .item .cart-goods {
+  float: left;
+  height: 200rpx;
+  width: 80%;
+  border-bottom: 1px solid #f4f4f4;
+  margin-left: 5rpx;
+  position: relative;
+}
+
+.cart-view .item .img {
+  float: left;
+  height: 155rpx;
+  width: 155rpx;
+  background: #f4f4f4;
+  margin: 19.5rpx 18rpx 19.5rpx 0;
+}
+
+.cart-view .item .info {
+  float: left;
+  height: 125rpx;
+  width: 65%;
+  margin: 19.5rpx 26rpx 19.5rpx 0;
+}
+
+.cart-view .item .t {
+  margin: 8rpx 0;
+  font-size: 25rpx;
+  color: #333;
+}
+
+.cart-view .item .cart-goods .name {
+  width: 270rpx;
+  font-size: 25rpx;
+  color: #333;
+  display: inline-block;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.cart-view .item .num {
+  height: 28rpx;
+  line-height: 28rpx;
+  float: right;
+}
+
+.cart-view .item .attr {
+  margin-bottom: 17rpx;
+  height: 24rpx;
+  line-height: 24rpx;
+  font-size: 22rpx;
+  color: #666;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
+
+.cart-view .item .goods-do {
+  position: absolute;
+  right: 20rpx;
+  top: 20rpx;
+}
+
+.cart-view .item .goods-do .org-price {
+  color: #999;
+  font-size: 23rpx;
+}
+
+.cart-view .item .open {
+  height: 28rpx;
+  width: 150rpx;
+  display: block;
+  float: right;
+  background: url(http://120.76.26.84:80/group1/M00/00/02/rBJEdVvr2EaAGOLDAAABEv1p1iM011.png) right center no-repeat;
+  background-size: 25rpx;
+  font-size: 25rpx;
+  color: #333;
+}
+
+.goods .number-item {
+  display: inline-flex;
+  -webkit-box-pack: justify;
+  align-items: center;
+  position: absolute;
+  /* right: 0; */
+  margin-right: 17rpx;
+}
+
+.goods .number-item .selnum {
+  height: 71rpx;
+  display: flex;
+}
+
+.goods .number-item .selnum .cut {
+  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADQAAAA0CAMAAADypuvZAAAAM1BMVEX////Z296wsLD6+vvo6evi5Obe3+Lr7O709fb5+fr3+Pjb3eDw8fLu7/Hl5+nk5ui5ubmS1nTyAAABG0lEQVRIx52WWXLEIAxEeUGSGeNl7n/aME6lUmQWm+5f+5l2A5LSC+XFPCrUcFtyuqDbFHSK6XaCzE7TvpZ8LFnWnSafPyB5g2oldSpWYXvrcgKmkQdNDpbfWDDwVwEE8cH6HMRTIAX8Y7rZofxbByydyKBfKx7MORV9Bn4CPL82EfkKlOMv+QxzuqQZfr++YemijK3Dz9Sb8mb0sib8Z4tqGlDldrA2AtnhKygjUCGOX0tDesS2sI9BO0vzuI5BK5acMgYVPAV5DMpEy71P9P71pHu/J9REDzXmBdVDSJBkTwpCilzaXOkYSQdWuRrSJZSuu1JYpBKmFEupLCsNQGk1SlOT2qfSqJWRQBg+lDFHG6j00U0fEqVx9BvALAkNabHL3QAAAABJRU5ErkJggg==);
+  box-sizing: border-box;
+  width: 25px;
+  border: none;
+  border-radius: 50%;
+  height: 25px;
+  background-size: 100% 100%;
+}
+
+.goods .number-item .selnum .number {
+  width: 2em;
+  text-align: center;
+  color: #333;
+  margin-top:-2px;
+}
+
+.goods .number-item .selnum .add {
+  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAMAAAAp4XiDAAAANlBMVEX/0WH///8zMzP/02b//fb/+u7/5qj/45z/3oz/1W1KRDj/8c//78j/7L7/6rX/2HfEo1P/3IXeVLZ3AAAA70lEQVRIx52WWQ7DIAxEJzFrNpL7X7ZIbdUUnITh/aIngW1sY6gwiwspisQU3GLq81KxaxCckLDaW8V6KHh7qRgnUBFndGWOuCTOmrLhlq1WPB7wpXLgkeNf8WjAn5UNTWw/ZUYj81cxEY1E81EcmnFvxQqaEZuVi2jt07TrUcuKhcY0jhM0bFZWaIwZaKxZCZwSBhjhFDFYwClZcKziEFglILFKQiwyOFYUOY0QnFGMMqfSo/AX63k+H+SeVPIF01OWfPHzX6zrI/Ptgm9KfOvjGyzfxvlhwY8kfvDx45Uf4vyqwC8kvWtP/3LFr3AvL0kJEWHNe5sAAAAASUVORK5CYII=);
+  box-sizing: border-box;
+  width: 25px;
+  border: none;
+  border-radius: 50%;
+  height: 25px;
+  background-size: 100% 100%;
+}
+
+.goods .number-item .selnum .add2 {
+  display: block;
+  width: 52rpx;
+  height: 52rpx;
+}
+
+.cart-view .item .b {
+  height: 28rpx;
+  line-height: 28rpx;
+  font-size: 25rpx;
+  color: #333;
+  overflow: hidden;
+  display: inline-flex;
+  right: 0;
+}
+
+.cart-view .group-item .handle {
+  display: inline-flex;
+  -webkit-box-pack: justify;
+  align-items: center;
+  position: absolute;
+  right: 0;
+  margin-right: 17rpx;
+}
+
+.cart-view .group-item .handle .del {
+  display: block;
+  width: 52rpx;
+  height: 52rpx;
+}
+
+.cart-view .promotion .icon {
+  display: inline-block;
+  height: 24rpx;
+  width: 15rpx;
+}
+
+.cart-view .promotion {
+  margin-top: 25.5rpx;
+  float: left;
+  height: 43rpx;
+  width: 480rpx;
+  /*margin-right: 84rpx;*/
+  line-height: 43rpx;
+  font-size: 0;
+}
+
+.cart-view .promotion .tag {
+  border: 1px solid #f48f18;
+  height: 37rpx;
+  line-height: 31rpx;
+  padding: 0 9rpx;
+  margin-right: 10rpx;
+  color: #f48f18;
+  font-size: 24.5rpx;
+}
+
+.cart-view .promotion .txt {
+  height: 43rpx;
+  line-height: 43rpx;
+  padding-right: 10rpx;
+  color: #333;
+  font-size: 29rpx;
+  overflow: hidden;
+}
+
+.cart-view .get {
+  margin-top: 18rpx;
+  float: right;
+  height: 58rpx;
+  padding-left: 14rpx;
+  border-left: 1px solid #d9d9d9;
+  line-height: 58rpx;
+  font-size: 29rpx;
+  color: #333;
+}
+
+.cart-view .coupon-info .header {
+  width: 100%;
+  height: 94rpx;
+  line-height: 94rpx;
+  text-align: center;
+}
+
+.cart-view .coupon-info .txt {
+  color: #f48f18;
+}
+
+.cart-bottom {
+  position: fixed;
+  bottom: 0;
+  left: 0;
+  height: 100rpx;
+  width: 100%;
+  background: #fff;
+  display: flex;
+  align-items: center;
+  z-index: 499;
+}
+
+.cart-bottom .checkbox {
+  height: 34rpx;
+  padding-left: 60rpx;
+  line-height: 34rpx;
+  margin: 0 18rpx 0 36rpx;
+  background: url(http://120.76.26.84:80/group1/M00/00/02/rBJEdVvr2GyABbtjAAAByIPHW08157.png) no-repeat;
+  background-size: 34rpx;
+  font-size: 29rpx;
+}
+
+.cart-bottom .checkbox.checked {
+  background: url(http://120.76.26.84:80/group1/M00/00/02/rBJEdVvr2AmALCJBAAABdbLfmi0325.png) no-repeat;
+  background-size: 34rpx;
+}
+
+.cart-bottom .total {
+  height: 34rpx;
+  flex: 1;
+  font-size: 29rpx;
+  color: #b4282d;
+  margin-top: -10rpx;
+}
+
+.cart-bottom .delete {
+  height: 34rpx;
+  width: auto;
+  margin: 33rpx 18rpx;
+  font-size: 29rpx;
+}
+
+.cart-bottom .checkout {
+  height: 100rpx;
+  width: 210rpx;
+  text-align: center;
+  line-height: 100rpx;
+  font-size: 29rpx;
+  background: #b4282d;
+  color: #fff;
+}
+
+.line-through {
+  text-decoration: line-through;
+}
+
+.a-guess {
+  width: 750rpx;
+  height: auto;
+  overflow: hidden;
+  background: #fff;
+  color: #333;
+  margin-top: 0rpx;
+  margin-bottom: 150rpx;
+}
+
+.a-guess  .h {
+  display: flex;
+  flex-flow: row nowrap;
+  align-items: center;
+  justify-content: center;
+  height: 90rpx;
+}
+
+.a-guess .h .txt {
+  padding-right: 30rpx;
+  background: url("http://120.76.26.84:80/group1/M00/00/02/rBJEdVvr2W6ATlkvAAAA_rntq4s180.png") right 4rpx no-repeat;
+  background-size: 16.656rpx 27rpx;
+  display: inline-block;
+  height: 36rpx;
+  font-size: 33rpx;
+  line-height: 36rpx;
+}
+
+.a-guess .b {
+  width: 750rpx;
+  height: auto;
+  overflow: hidden;
+  border-top: 1rpx solid #f4f4f4;
+  margin-top: 20rpx;
+}
+
+.a-guess .b .item {
+  float: left;
+  background: #fff;
+  width: 375rpx;
+  padding-bottom: 33.333rpx;
+  border-bottom: 1rpx solid #f4f4f4;
+  height: auto;
+  overflow: hidden;
+  text-align: center;
+}
+
+.a-guess .b .item-b {
+  border-right: 1rpx solid #f4f4f4;
+}
+
+.a-guess .item .img2 {
+  margin-top: 10rpx;
+  width: 302rpx;
+  height: 302rpx;
+  background-size:202rpx 202rpx;
+}
+
+.a-guess .item .name {
+  display: block;
+  width: 365.625rpx;
+  height: 80rpx;
+  padding: 0 20rpx;
+  margin: 11.5rpx 0 22rpx 0;
+  text-align: center;
+  font-size: 26rpx;
+  color: #333;
+}
+
+.a-guess .item .price {
+  display: block;
+  width: 365.625rpx;
+  height: 30rpx;
+  text-align: center;
+  font-size: 30rpx;
+  color: #b4282d;
+}
+
+.a-guess .item .price .cart {
+  margin-left: 20rpx;
+  width: 35rpx;
+  height: 35rpx;
+  vertical-align: -6rpx;
+}
+
+/* //////////////////////////////////////////// */
+
+.attr-pop {
+  width: 100%;
+  height: auto;
+  padding: 31.25rpx;
+  background: #fff;
+  position: fixed;
+  bottom: 100rpx;
+  z-index: 600;
+}
+
+.attr-close {
+  float: right;
+  width: 40rpx;
+  height: 40rpx;
+  line-height: 40rpx;
+  border-radius: 50%;
+  font-size: 40rpx;
+  text-align: center;
+  overflow: hidden;
+}
+
+.attr-pop .img-info {
+  width: 687.5rpx;
+  height: 177rpx;
+  overflow: hidden;
+  margin-bottom: 41.5rpx;
+}
+
+.attr-pop .img {
+  float: left;
+  height: 177rpx;
+  width: 177rpx;
+  background: #f4f4f4;
+  margin-right: 31.25rpx;
+}
+
+.attr-pop .info {
+  float: left;
+  height: 177rpx;
+  display: flex;
+  align-items: flex-start;
+}
+
+.attr-pop .p {
+  font-size: 33rpx;
+  color: #333;
+  height: 33rpx;
+  line-height: 33rpx;
+  margin-bottom: 10rpx;
+}
+
+.attr-pop .a {
+  font-size: 29rpx;
+  color: #333;
+  height: 40rpx;
+  line-height: 40rpx;
+  width: 260px;
+  display: block;
+  word-break: break-all;
+  word-wrap: break-word;
+}
+
+.spec-con {
+  width: 100%;
+  height: auto;
+  overflow: hidden;
+}
+
+.spec-con .name {
+  height: 32rpx;
+  margin-bottom: 22rpx;
+  font-size: 29rpx;
+  color: #333;
+}
+
+.spec-con .values {
+  height: auto;
+  margin-bottom: 31.25rpx;
+  font-size: 0;
+}
+
+.spec-con .value {
+  display: inline-block;
+  height: 62rpx;
+  padding: 0 35rpx;
+  line-height: 56rpx;
+  text-align: center;
+  margin-right: 25rpx;
+  margin-bottom: 16.5rpx;
+  border: 1px solid #333;
+  font-size: 25rpx;
+  color: #333;
+}
+
+.spec-con .value.disable {
+  border: 1px solid #ccc;
+  color: #ccc;
+}
+
+.spec-con .value.selected {
+  border: 1px solid #b4282d;
+  color: #b4282d;
+}
+
+.spec-con .number-item .selnum {
+  width: 322rpx;
+  height: 71rpx;
+  border: 1px solid #ccc;
+  display: flex;
+}
+
+.spec-con .number-item .cut {
+  width: 93.75rpx;
+  height: 100%;
+  text-align: center;
+  line-height: 65rpx;
+}
+
+.spec-con .number-item .number {
+  flex: 1;
+  height: 100%;
+  text-align: center;
+  line-height: 68.75rpx;
+  border-left: 1px solid #ccc;
+  border-right: 1px solid #ccc;
+  float: left;
+}
+
+.spec-con .number-item .add {
+  width: 93.75rpx;
+  height: 100%;
+  text-align: center;
+  line-height: 65rpx;
+}
+
+.bottom-btn {
+  position: fixed;
+  left: 0;
+  bottom: 0;
+  z-index: 10;
+  width: 750rpx;
+  height: 100rpx;
+  display: flex;
+  background: #fff;
+}
+
+.bottom-btn .r {
+  border: 1px solid #b4282d;
+  background: #b4282d;
+  float: left;
+  height: 100rpx;
+  line-height: 96rpx;
+  flex: 1;
+  text-align: center;
+  color: #fff;
+}
+
+.checkbox-biz-type {
+  float: left;
+  height: 30rpx;
+  width: 100%;
+  margin-top: 10rpx;
+  margin-left: 24rpx;
+  background: url(http://120.76.26.84/group1/M00/00/02/rBJEdVvr2GyABbtjAAAByIPHW08157.png) no-repeat;
+  background-size: 30rpx;
+  vertical-align: middle;
+}
+
+.checkbox-biz-type.checked {
+  background: url(http://120.76.26.84:80/group1/M00/00/02/rBJEdVvr2AmALCJBAAABdbLfmi0325.png) no-repeat;
+  background-size: 30rpx;
+}
+
+.search-icon-shop {
+  width: 30rpx;
+  height: 30rpx;
+  /* margin-left: 15rpx;
+  margin-top: 20rpx; 
+  margin-bottom:-18rpx;*/
+  margin-bottom:9rpx;
+  margin-left:40rpx;
+  vertical-align: middle;
+
+}
+
+
+.title-name {
+  width: 100%;
+  height: 30rpx;
+  line-height: 30rpx;
+  text-align: left;
+  font-size: 28rpx;
+  color: rgba(87, 86, 86, 0.63);
+  margin-left: 10rpx;
+  font-weight: bolder;
+  padding-bottom: 10rpx;
+  vertical-align: middle;
+}
+.number-item-text {
+  display: inline-flex;
+  -webkit-box-pack: justify;
+  align-items: center;
+  position: absolute;
+  /* right: 0; */
+  margin-right: 17rpx;
+  font-size: 26rpx;
+  color: black;
+}
+.shixiao {
+  float: left;
+  height: 34rpx;
+  margin: 65rpx 6rpx 65rpx 4rpx;
+  background-size: 34rpx;
+  background-color: rgba(87, 86, 86, 0.63);
+  border-radius:30rpx;
+  color: #fff;
+  font-size: 22rpx;
+  width: 70rpx;
+  padding-left: 10rpx;
+}
+.addCart {
+  width: 93.75rpx;
+  height: 100%;
+  text-align: center;
+  line-height: 65rpx;
+}
+.addEnabel {
+  width: 93.75rpx;
+  height: 100%;
+  text-align: center;
+  line-height: 65rpx;
+  color: #ccc;
+}

+ 369 - 0
wx-mall-hk/pages/catalog/catalog.js

@@ -0,0 +1,369 @@
+var util = require('../../utils/util.js');
+var api = require('../../config/api.js');
+//获取应用实例
+const app = getApp();
+
+Page({
+  data: {
+    navList: [],
+    categoryList: [],
+    currentCategory: {},
+    scrollLeft: 0,
+    scrollTop: 0,
+    goodsCount: 0,
+    scrollHeight: 0,
+    //
+    filterCategory: [],
+    goodsList: [],
+    categoryId: 0,
+    currentSortType: 'default',
+    currentSortOrder: 'desc',
+    filterDiscount: 0,// 0不限 1特价 2活动
+    goodsBizType: app.globalData.appGoodsBizType,//业务类型
+    page: 1,
+    size: 50,
+    showNavList: false,
+    footCart: {},
+    referrer: 0,
+    sourceKey: '',
+    openCoupon: false
+  },
+  toggleNav() {
+    this.setData({
+      showNavList: !this.data.showNavList
+    })
+  },
+  switchNav(event) {
+    let name = event.currentTarget.dataset.name;
+    wx.switchTab({
+      url: `/pages/${name}/${name}`,
+    });
+  },
+  onLoad: function (options) {
+    let that = this;
+    // 页面初始化 options为页面跳转所带来的参数
+    if (options.referrer){
+      that.setData({
+        referrer: parseInt(options.referrer),
+        sourceKey: options.sourceKey,
+        openCoupon: true
+      });
+    }
+    // that.setData({
+    //   goodsBizType: app.globalData.appGoodsBizType
+    // });
+
+    wx.setNavigationBarTitle({
+      title: '分类'
+    });
+  },
+  getCatalog: function () {
+    //CatalogList
+    let that = this;
+    
+    util.request(api.CatalogList).then(function (res) { 
+      if (!wx.getStorageSync('currentCategory')) {
+        that.setData({
+          navList: res.data.categoryList,
+          currentCategory: res.data.currentCategory
+        });
+        wx.setStorageSync('currentCategory', res.data.currentCategory);
+      } else {
+        if (that.data.currentCategory && that.data.currentCategory.id > 0) {
+          that.setData({
+            navList: res.data.categoryList
+          });
+        } else {
+          that.setData({
+            navList: res.data.categoryList,
+            currentCategory: res.data.currentCategory
+          });
+        }
+      }
+      that.getCategoryData();
+    });
+    util.request(api.GoodsCount).then(function (res) {
+      that.setData({
+        goodsCount: res.data.goodsCount
+      });
+    });
+  },
+  getCurrentCategory: function (id) {
+    let that = this;
+    util.request(api.CatalogCurrent, { id: id })
+      .then(function (res) {
+        that.setData({
+          currentCategory: res.data.currentCategory
+        });
+        console.log(that.data.currentCategory);
+        that.getGoodsList();
+      });
+  },
+  onReady: function () {
+    // 页面渲染完成
+  },
+  onShow: function () {
+    this.setData({
+      goodsBizType: app.globalData.appGoodsBizType
+    });
+
+    // 页面显示
+    if (wx.getStorageSync('userInfo') || wx.getStorageSync('token')) {
+      this.getFootCart();
+      this.getCatalog();
+    } else {
+      wx.navigateTo({
+        url: '/pages/auth/btnAuth/btnAuth',
+      })
+    }
+  },
+  onHide: function () {
+    // 页面隐藏
+    this.setData({
+      showNavList: false
+    })
+  },
+  onUnload: function () {
+    // 页面关闭
+  },
+  getList: function () {
+    var that = this;
+    util.request(api.ApiRootUrl + 'api/catalog/' + that.data.currentCategory.id)
+      .then(function (res) {
+        that.setData({
+          categoryList: res.data,
+        });
+      });
+  },
+  switchCate: function (event) {
+    var that = this;
+    var currentTarget = event.currentTarget;
+    if (this.data.currentCategory.id == event.currentTarget.dataset.id) {
+      return false;
+    }
+
+    this.getCurrentCategory(event.currentTarget.dataset.id);
+  },
+  //
+  getCategoryData: function () {
+    let that = this;
+    that.getGoodsList();
+  },
+  getGoodsList() {
+    wx.showLoading({
+      title: '加载中...',
+    });
+    var that = this;
+    if (that.data.currentCategory){
+      util.request(api.CatalogProductList, {
+        page: that.data.page,
+        size: that.data.size,
+        order: that.data.currentSortOrder,
+        sort: that.data.currentSortType,
+        // discount: that.data.filterDiscount,
+        goodsBizType: that.data.goodsBizType,
+        categoryId: that.data.currentCategory.id
+      })
+        .then(function (res) {
+          if (res.errno === 0) {
+            that.setData({
+              goodsList: res.data.data,
+              filterCategory: res.data.filterCategory
+            });
+            wx.hideLoading();
+          }
+        });
+    }
+    wx.hideLoading();
+  },
+  getFootCart: function () {
+    let that = this;
+    util.request(api.GetFootCart).then(function (res) {
+      if (res.errno === 0) {
+        that.setData({
+          footCart: res.data,
+        });
+      }
+    });
+  },
+  //购物车减少
+  cutNumber: function (e) {
+    let that = this;
+    var goodsId = e.currentTarget.dataset.goodsId;
+    var productId = e.currentTarget.dataset.productId;
+
+    var goodsList = that.data.goodsList;
+    // goodsList.forEach(function (val, index, arr) {
+    //     if (val.product_id == productId) {
+    //         val.cart_num = val.cart_num - 1;
+    //         if (val.cart_num >= 0) {
+    //             goodsList[index] = val;
+    //             that.setData({goodsList: goodsList});
+    //         }
+    //     }
+    // });
+    // that.setData({goodsList: goodsList});
+    util.request(api.CartMinus, { goodsId: goodsId, productId: productId, number: 1 }, 'POST').then(function (res) {
+      if (res.errno === 0 && null != res.data) {
+        var goodsList = that.data.goodsList;
+        that.getFootCart();
+        goodsList.forEach(function (val, index, arr) {
+          if (val.product_id == productId) {
+            val.cart_num = res.data;
+            goodsList[index] = val;
+            if(val.cart_num == 0){
+              util.showErrorToast('不能再减了');
+            }
+          }
+        }, that);
+        that.setData({ goodsList: goodsList });
+      }
+    });
+  },
+  //购物车增加
+  addNumber: function (e) {
+    let that = this;
+    var goodsId = e.currentTarget.dataset.goodsId;
+    var productId = e.currentTarget.dataset.productId;
+    var goodsList = that.data.goodsList;
+    // goodsList.forEach(function (val, index, arr) {
+    //     if (val.product_id == productId) {
+    //         val.cart_num = val.cart_num + 1;
+    //         goodsList[index] = val;
+    //     }
+    // });
+    // that.setData({goodsList: goodsList});
+    util.request(api.CartAdd, { goodsId: goodsId, productId: productId, number: 1 }, 'POST').then(function (res) {
+      if (res.errno === 0 && null != res.data) {
+        that.getFootCart();
+        goodsList.forEach(function (val, index, arr) {
+          res.data.cartList.forEach(function (cartVal, cartIndex, cartArr) {
+            if (val.product_id == cartVal.product_id) {
+              val.cart_num = cartVal.number;
+              goodsList[index] = val;
+            }
+          });
+        }, that);
+        that.setData({ goodsList: goodsList });
+      }
+    });
+  },
+  openSortFilter: function (event) {
+    let that = this; 
+    let currentId = event.currentTarget.id;
+    console.log('currentId:'+currentId);
+    switch (currentId) {
+      case 'defaultActivity':
+        that.setData({
+          'goodsBizType': '00'
+        });
+        app.globalData.appGoodsBizType = '00';
+        this.getGoodsList();
+        break;
+      case 'discountActivity':
+        that.setData({
+          'goodsBizType': '02'
+        });
+        app.globalData.appGoodsBizType = '02';
+        this.getGoodsList();
+        break;
+      case 'groupActivity':
+        that.setData({
+          'goodsBizType': '10'
+        });
+        app.globalData.appGoodsBizType = '10';
+        this.getGoodsList();
+        break;
+      case 'ordActivity':
+        that.setData({
+          'goodsBizType': '11'
+        });
+        app.globalData.appGoodsBizType = '11';
+        this.getGoodsList();
+        break;
+      case 'sellSort':
+        let tmpSortOrder = 'asc';
+        if (this.data.currentSortOrder == 'asc') {
+          tmpSortOrder = 'desc';
+        }
+        this.setData({
+          'currentSortType': 'sell',
+          'currentSortOrder': tmpSortOrder,
+        });
+        this.getGoodsList();
+        break;
+      case 'priceSort':
+        tmpSortOrder = 'asc';
+        if (this.data.currentSortOrder == 'asc') {
+          tmpSortOrder = 'desc';
+        }
+        this.setData({
+          'currentSortType': 'price',
+          'currentSortOrder': tmpSortOrder,
+        });
+
+        this.getGoodsList();
+        break;
+      default:
+        //综合排序
+        this.setData({
+          'currentSortType': 'default',
+          'currentSortOrder': 'desc',
+        });
+        this.getGoodsList();
+    }
+  },
+  takeShareCoupon() {
+    let that = this;
+    util.request(api.CouponTransActivit, {
+      referrer: that.data.sourceKey,
+      sourceKey: that.data.sourceKey
+    }).then(function (res) {
+      if (res.errno === 0) {
+        util.showErrorToast("领取成功");
+        that.setData({
+          couponList: res.data,
+          openCoupon: false
+        });
+      } else if (res.errno === 2) {
+        util.showErrorToast(res.errmsg)
+        that.setData({
+          couponList: res.data,
+          openCoupon: false
+        });
+      }
+    });
+  },
+  closeCoupon: function () {
+    var that = this;
+    that.setData({
+      openCoupon: false
+    });
+  },
+  bindtapGoodsDetail: function (e) {
+    var that = this;
+    let url = '';
+    var itemId = e.currentTarget.dataset.itemId;
+    if (that.data.filterDiscount != 2) {
+      url = '/pages/goods/goods?id=' + itemId;
+    } else {
+      url = '/pages/groupDetail/groupDetail?id=' + itemId;
+    }
+    wx.navigateTo({
+      url: url,
+    })
+  }, 
+  sercherCategory: function (e) {
+    var that = this;
+    let url = '';
+    var replyType = e.currentTarget.dataset.replyType;
+    var currentIndex = e.currentTarget.dataset.currentIndex;
+    // console.log('replyType:' + e.currentTarget.dataset.replyType);
+    // console.log('goodsBizType:' + that.data.goodsBizType);
+    // 跳转页面
+    wx.navigateTo({
+      url: '/pages/category/category?id=' + replyType + '&&goodsBizType=' + that.data.goodsBizType + '&&currentIndex=' + currentIndex
+    })
+
+  }
+})

+ 1 - 0
wx-mall-hk/pages/catalog/catalog.json

@@ -0,0 +1 @@
+{}

+ 157 - 0
wx-mall-hk/pages/catalog/catalog.wxml

@@ -0,0 +1,157 @@
+<view class="container">
+  <view class="cart-panel" wx:if="{{footCart.goodsCount>0}}">
+    <view class="cart-icon">
+      <navigator class="nav-cell" open-type='switchTab' url="/pages/cart/cart">
+        <image src="../../static/images/cart-fixed.png">
+        </image>
+      </navigator>
+      <view class="cart-num">{{footCart.goodsCount}}</view>
+    </view>
+    <view class="cart-body">¥{{footCart.checkedGoodsAmount}}</view>
+    <navigator class="nav-cell" open-type='switchTab' url="/pages/cart/cart">
+      <view class="cart-pay">去结算 > </view>
+    </navigator>
+  </view>
+  <view wx:if="{{showNavList}}" class="modal-wrap"></view>
+  <view class="fast-nav">
+    <contact-button wx:if="{{!showNavList}}" class="contact" size="25" type="primary" session-from="weapp">
+      <text>找客服</text>
+    </contact-button>
+    <view wx:if="{{!showNavList}}" class="nav" bindtap="toggleNav">
+      <text>快捷</text>
+      <text>导航</text>
+    </view>
+    <view class="nav-list" wx:if="{{showNavList}}">
+      <view class="nav-item">
+        <text class="nav-text">首页</text>
+        <view class="nav-cell" bindtap="switchNav" data-name="index">
+          <image src="../../static/images/nav-1.png"></image>
+        </view>
+      </view>
+      <view class="nav-item">
+        <text class="nav-text">足迹</text>
+        <navigator class="nav-cell" url="../ucenter/footprint/footprint">
+          <image src="../../static/images/nav-2.png"></image>
+        </navigator>
+      </view>
+      <view class="nav-item">
+        <text class="nav-text">搜索</text>
+        <navigator class="nav-cell" url="../search/search">
+          <image src="../../static/images/nav-3.png"></image>
+        </navigator>
+      </view>
+      <view class="nav-item">
+        <text class="nav-text">购物车</text>
+        <view class="nav-cell" bindtap="switchNav" data-name="cart">
+          <image src="../../static/images/nav-4.png"></image>
+        </view>
+      </view>
+    </view>
+    <view wx:if="{{showNavList}}" class="close" bindtap="toggleNav">X</view>
+  </view>
+  <view class="search">
+    <navigator url="/pages/search/search" class="input">
+      <image class="icon"></image>
+      <text class="txt">商品搜索, 共{{goodsCount}}款好物</text>
+    </navigator>
+  </view>
+  <view class="activity">
+    <view class="activity-box">
+      <view class="item {{goodsBizType == '00' ? 'active' : ''}}" bindtap="openSortFilter" id="defaultActivity">
+        <text class="txt">保税仓</text>
+      </view>
+      <!-- <view class="item by-sell {{goodsBizType == '02' ? 'active' : ''}}" bindtap="openSortFilter" id="discountActivity">
+        <text class="txt">保税展示</text>
+      </view>
+      <view class="item by-price {{goodsBizType == '10' ? 'active' : ''}}" bindtap="openSortFilter" id="groupActivity">
+        <text class="txt">现场速递</text>
+      </view> -->
+      <view class="item by-price {{goodsBizType == '11' ? 'active' : ''}}" bindtap="openSortFilter" id="ordActivity">
+        <text class="txt">普通商品</text>
+      </view>
+    </view>
+  </view>
+  <view class="catalog">
+    <scroll-view class="nav" scroll-y="true">
+      <view class="item {{ currentCategory.id == item.id ? 'active' : ''}}" wx:for="{{navList}}" data-id="{{item.id}}" data-index="{{index}}" bindtap="switchCate" wx:key="{{index}}">{{item.name}}</view>
+      <!-- <view class="contact">
+        <button open-type="contact" size="20" session-from="weapp">
+          </button>
+      </view> -->
+    </scroll-view>
+    <scroll-view class="cate" scroll-y="true">
+      <navigator url="url" class="banner">
+        <image class="image" wx:if="{{currentCategory.wap_banner_url}}" src="{{currentCategory.wap_banner_url}}"></image>
+        <view class="txt">{{currentCategory.front_name?currentCategory.front_name:""}}</view>
+      </navigator>
+      <view class="hd" wx:if="{{currentCategory}}">
+        <text class="line"></text>
+        <text class="txt">{{currentCategory.name?currentCategory.name:""}}分类</text>
+        <text class="line"></text>
+      </view>
+      <view class="bd">
+        <navigator bindtap="sercherCategory" data-reply-Type="{{item.id}}" data-current-Index="{{index}}" class="item {{(index+1) % 3 == 0 ? 'last' : ''}}" wx:for="{{currentCategory.subCategoryList}}" wx:key="{{item.id}}">
+          <image class="icon" wx:if="{{item.wap_banner_url}}" src="{{item.wap_banner_url}}"></image>
+          <text class="txt">{{item.name?item.name:""}}</text>
+        </navigator>
+      </view>
+      <view class="sort" wx:if="{{goodsList.length > 0 }}">
+        <view class="sort-box">
+          <view class="item {{currentSortType == 'default' ? 'active' : ''}}" bindtap="openSortFilter" id="defaultSort">
+            <text class="txt">综合</text>
+          </view>
+          <view class="item by-sell {{currentSortType == 'sell' ? 'active' : ''}} {{currentSortOrder == 'asc'  ? 'asc' : 'desc'}}" bindtap="openSortFilter" id="sellSort">
+            <text class="txt">销量</text>
+          </view>
+          <view class="item by-price {{currentSortType == 'price' ? 'active' : ''}} {{currentSortOrder == 'asc'  ? 'asc' : 'desc'}}" bindtap="openSortFilter" id="priceSort">
+            <text class="txt">价格</text>
+          </view>
+        </view>
+      </view>
+      <view class="cate-item">
+        <view wx:if="{{goodsList != null && goodsList.length == 0}}" class="item-text">未找到相关商品</view>
+        <view class="item" wx:for="{{goodsList}}" wx:for-index="index" wx:for-item="item" wx:key="{{item.id}}">
+          <navigator url="/pages/goods/goods?id={{item.id}}">
+            <view class="left">
+              <image class="img" wx:if="{{item.list_pic_url}}" src="{{item.list_pic_url}}"></image>
+            </view>
+          </navigator>
+
+          <view class="right">
+            <view class="text">
+
+          <navigator url="/pages/goods/goods?id={{item.id}}">
+            <text class="name" bindtap="bindtapGoodsDetail" data-item-id="{{filterDiscount != 2?item.id:item.group_id}}">{{item.name?item.name:""}}</text>
+            <text class="desc" bindtap="bindtapGoodsDetail" data-item-id="{{filterDiscount != 2?item.id:item.group_id}}">{{item.goods_brief?item.goods_brief:""}}</text>
+          </navigator>
+
+
+          <view class="goods-do">
+            <navigator url="/pages/goods/goods?id={{item.id}}">
+              <text class="price">{{item.retail_price?"¥"+item.retail_price:"¥0"}}</text>
+              <text class="org-price line-through">{{item.market_price?"¥"+item.market_price:""}}</text>
+            </navigator>
+            <!-- //数量加减 -->
+            <view class="number-item">
+                  <view class="selnum">
+                    <view class="cut" data-goods-id="{{item.id}}" data-product-id="{{item.product_id}}" bindtap="cutNumber"></view>
+                    <input value="{{item.cart_num}}" class="number" disabled="true" type="number" />
+                    <!-- <view class="add" data-goods-id="{{item.id}}" data-product-id="{{item.product_id}}" bindtap="addNumber"></view> -->
+                    <image class="add2" src="{{item.cart_num < item.stockNum ? '/static/images/service-hsjh.png':'/static/images/service-ehsjh.png'}}" data-goods-id="{{item.id}}" data-product-id="{{item.product_id}}"  catchtap="{{item.cart_num < item.stockNum ?  'addNumber' : ''}}"></image>
+                  </view>
+                </view>
+              </view>
+            </view>
+
+          </view>
+
+        </view>
+      </view>
+    </scroll-view>
+  </view>
+
+  <view class="coupon" wx:if="{{openCoupon}}">
+     <view class="attr-close" bindtap="closeCoupon">X</view>
+      <image class="img" src="/static/imgys/coupon-gun.png" bindtap="takeShareCoupon"/>
+    </view>
+</view>

+ 450 - 0
wx-mall-hk/pages/catalog/catalog.wxss

@@ -0,0 +1,450 @@
+page {
+  height: 100%;
+}
+
+.container {
+  background: #f9f9f9;
+  height: 100%;
+  width: 100%;
+  display: flex;
+  flex-direction: column;
+}
+
+.search {
+  height: 88rpx;
+  width: 100%;
+  padding: 0 30rpx;
+  background: #fff;
+  display: flex;
+  align-items: center;
+}
+
+.search .input {
+  width: 690rpx;
+  height: 56rpx;
+  background: #ededed;
+  border-radius: 8rpx;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.search .icon {
+  background: url(http://120.76.26.84:80/group1/M00/00/02/rBJEdVvr2eOAETvOAAABevWIuCY300.png) center no-repeat;
+  background-size: 100%;
+  width: 28rpx;
+  height: 28rpx;
+}
+
+.search .txt {
+  height: 42rpx;
+  line-height: 42rpx;
+  color: #666;
+  padding-left: 10rpx;
+  font-size: 30rpx;
+}
+
+.catalog {
+  flex: 1;
+  width: 100%;
+  background: #fff;
+  display: flex;
+  border-top: 1px solid #fafafa;
+}
+
+.catalog .nav {
+  width: 142rpx;
+  height: 100%;
+}
+
+.catalog .nav .item {
+  text-align: center;
+  line-height: 90rpx;
+  width: 162rpx;
+  height: 90rpx;
+  color: #333;
+  font-size: 28rpx;
+  border-left: 6rpx solid #fff;
+}
+
+.catalog .nav .item.active {
+  color: #ab2b2b;
+  font-size: 30rpx;
+  border-left: 6rpx solid #ab2b2b;
+}
+
+.catalog .cate {
+  border-left: 1px solid #fafafa;
+  flex: 1;
+  height: 100%;
+  padding: 0 10rpx 0 10rpx;
+}
+
+.banner {
+  display: block;
+  height: 222rpx;
+  width: 100%;
+  position: relative;
+}
+
+.banner .image {
+  position: absolute;
+  top: 30rpx;
+  left: 0;
+  border-radius: 4rpx;
+  height: 192rpx;
+  width: 100%;
+}
+
+.banner .txt {
+  position: absolute;
+  top: 30rpx;
+  text-align: center;
+  color: #fff;
+  font-size: 28rpx;
+  left: 0;
+  height: 192rpx;
+  line-height: 192rpx;
+  width: 100%;
+}
+
+.catalog .hd {
+  height: 108rpx;
+  width: 100%;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+.catalog .hd .txt {
+  font-size: 24rpx;
+  text-align: center;
+  color: #333;
+  padding: 0 10rpx;
+  width: auto;
+}
+
+.catalog .hd .line {
+  width: 40rpx;
+  height: 1px;
+  background: #d9d9d9;
+}
+
+.catalog .bd {
+  height: auto;
+  width: 100%;
+  overflow: hidden;
+}
+
+.catalog .bd .item {
+  display: block;
+  float: left;
+  height: 246rpx;
+  /* width: 170rpx; */
+  margin-right: 54rpx;
+}
+
+.catalog .bd .item.last {
+  margin-right: 0;
+}
+
+.catalog .bd .item .icon {
+  height: 144rpx;
+  width: 144rpx;
+}
+
+.catalog .bd .item .txt {
+  display: block;
+  text-align: center;
+  font-size: 24rpx;
+  color: #333;
+  height: 72rpx;
+  width: 144rpx;
+}
+
+.catalog .nav .contact {
+  text-align: center;
+  line-height: 90rpx;
+  width: 162rpx;
+  height: 90rpx;
+  color: #333;
+  font-size: 28rpx;
+  border-left: 6rpx solid #fff;
+  filter: alpha(Opacity=100);
+  -moz-opacity: 1;
+  opacity: 1;
+  background: url('http://120.76.26.84:80/group1/M00/00/02/rBJEdVvr2f-ATIZ6AAAh9NXovEg111.jpg') center no-repeat;
+  background-size: 75rpx 70rpx;
+}
+
+.sort {
+  position: relative;
+  background: #fff;
+  width: 100%;
+  height: 78rpx;
+}
+
+.sort-box {
+  background: #fff;
+  width: 100%;
+  height: 78rpx;
+  overflow: hidden;
+  padding: 0 30rpx;
+  display: flex;
+}
+
+.sort-box .item {
+  height: 78rpx;
+  line-height: 78rpx;
+  text-align: center;
+  flex: 1;
+  color: #333;
+  font-size: 26rpx;
+}
+
+.sort-box .item .txt {
+  display: block;
+  width: 100%;
+  height: 100%;
+  color: #333;
+}
+
+.sort-box .item.active .txt {
+  color: #b4282d;
+}
+
+.sort-box .item.by-price {
+  background: url(http://120.76.26.84:80/group1/M00/00/02/rBJEdVvr2jOAM4X6AAABD1aCMbo590.png) 135rpx center no-repeat;
+  background-size: 20rpx 30rpx;
+}
+
+.sort-box .item.by-price.active.asc {
+  background: url(http://120.76.26.84:80/group1/M00/00/02/rBJEdVvr2keASXmNAAABHU5MD_M495.png) 135rpx center no-repeat;
+  background-size: 20rpx 30rpx;
+}
+
+.sort-box .item.by-price.active.desc {
+  background: url(http://120.76.26.84:80/group1/M00/00/02/rBJEdVvr2lKAJ-QhAAABdVcSS6A874.png) 135rpx center no-repeat;
+  background-size: 20rpx 30rpx;
+}
+
+.sort-box .item.by-sell {
+  background: url(http://120.76.26.84:80/group1/M00/00/02/rBJEdVvr2jOAM4X6AAABD1aCMbo590.png) 135rpx center no-repeat;
+  background-size: 20rpx 30rpx;
+}
+
+.sort-box .item.by-sell.active.asc {
+  background: url(http://120.76.26.84:80/group1/M00/00/02/rBJEdVvr2keASXmNAAABHU5MD_M495.png) 135rpx center no-repeat;
+  background-size: 20rpx 30rpx;
+}
+
+.sort-box .item.by-sell.active.desc {
+  background: url(http://120.76.26.84:80/group1/M00/00/02/rBJEdVvr2lKAJ-QhAAABdVcSS6A874.png) 135rpx center no-repeat;
+  background-size: 20rpx 30rpx;
+}
+
+/*  */
+
+.cate-item {
+  width: 100%;
+  height: auto;
+  overflow: hidden;
+  border-top: 1rpx solid #f4f4f4;
+  margin-top: 20rpx;
+  margin-bottom: 100rpx;
+}
+
+.cate-item .item {
+  border-top: 1px solid #d9d9d9;
+  margin: 0 10rpx;
+  height: 272rpx;
+  width: 100%;
+}
+.item-text{
+  margin-top: 10rpx;
+  height: 100rpx;
+  width: 100%;
+  color: #a8a6a6;
+  text-align: center;
+}
+.cate-item .item .left {
+  width: 190rpx;
+  height: 272rpx;
+  float: left;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+.cate-item .item .left .img {
+  width: 180rpx; 
+  height: 180rpx;
+}
+
+.cate-item .item .right {
+  /* float: left; */
+  height: 264rpx;
+  width: 350rpx;
+  display: flex;
+  flex-flow: row nowrap;
+  padding-left: 15rpx;
+}
+
+.cate-item .item .right .text {
+  display: flex;
+  flex-wrap: nowrap;
+  flex-direction: column;
+  justify-content: center;
+  overflow: hidden;
+  height: 264rpx;
+  width: 456rpx;
+}
+
+.cate-item .item .right .name {
+  display: block;
+  color: #333;
+  line-height: 50rpx;
+  font-size: 26rpx;
+}
+
+.cate-item .item .right .desc {
+  width: 456rpx;
+  display: block;
+  color: #999;
+  line-height: 50rpx;
+  font-size: 23rpx;
+}
+
+.cate-item .item .right .goods-do {
+  display: inline;
+}
+
+.cate-item .item .right .goods-do .price {
+  width: 50rpx;
+  display: block;
+  color: #b4282d;
+  line-height: 50rpx;
+  font-size: 27rpx;
+  display: inline;
+}
+
+.cate-item .item .right .goods-do .org-price {
+  width: 40rpx;
+  display: block;
+  color: #333;
+  line-height: 50rpx;
+  font-size: 23rpx;
+  display: inline;
+  padding-left: 10rpx;
+}
+
+.number-item {
+  display: inline-flex;
+  -webkit-box-pack: justify;
+  align-items: center;
+  position: absolute;
+  right: 0;
+  margin-right: 17rpx;
+}
+
+.number-item .selnum {
+  height: 71rpx;
+  display: flex;
+}
+
+.number-item .cut {
+  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADQAAAA0CAMAAADypuvZAAAAM1BMVEX////Z296wsLD6+vvo6evi5Obe3+Lr7O709fb5+fr3+Pjb3eDw8fLu7/Hl5+nk5ui5ubmS1nTyAAABG0lEQVRIx52WWXLEIAxEeUGSGeNl7n/aME6lUmQWm+5f+5l2A5LSC+XFPCrUcFtyuqDbFHSK6XaCzE7TvpZ8LFnWnSafPyB5g2oldSpWYXvrcgKmkQdNDpbfWDDwVwEE8cH6HMRTIAX8Y7rZofxbByydyKBfKx7MORV9Bn4CPL82EfkKlOMv+QxzuqQZfr++YemijK3Dz9Sb8mb0sib8Z4tqGlDldrA2AtnhKygjUCGOX0tDesS2sI9BO0vzuI5BK5acMgYVPAV5DMpEy71P9P71pHu/J9REDzXmBdVDSJBkTwpCilzaXOkYSQdWuRrSJZSuu1JYpBKmFEupLCsNQGk1SlOT2qfSqJWRQBg+lDFHG6j00U0fEqVx9BvALAkNabHL3QAAAABJRU5ErkJggg==);
+  box-sizing: border-box;
+  width: 25px;
+  border: none;
+  border-radius: 50%;
+  height: 25px;
+  background-size: 100% 100%;
+}
+
+.number-item .number {
+  width: 2em;
+  text-align: center;
+  color: #333;
+
+}
+
+.number-item .add {
+  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAMAAAAp4XiDAAAANlBMVEX/0WH///8zMzP/02b//fb/+u7/5qj/45z/3oz/1W1KRDj/8c//78j/7L7/6rX/2HfEo1P/3IXeVLZ3AAAA70lEQVRIx52WWQ7DIAxEJzFrNpL7X7ZIbdUUnITh/aIngW1sY6gwiwspisQU3GLq81KxaxCckLDaW8V6KHh7qRgnUBFndGWOuCTOmrLhlq1WPB7wpXLgkeNf8WjAn5UNTWw/ZUYj81cxEY1E81EcmnFvxQqaEZuVi2jt07TrUcuKhcY0jhM0bFZWaIwZaKxZCZwSBhjhFDFYwClZcKziEFglILFKQiwyOFYUOY0QnFGMMqfSo/AX63k+H+SeVPIF01OWfPHzX6zrI/Ptgm9KfOvjGyzfxvlhwY8kfvDx45Uf4vyqwC8kvWtP/3LFr3AvL0kJEWHNe5sAAAAASUVORK5CYII=);
+  box-sizing: border-box;
+  width: 25px;
+  border: none;
+  border-radius: 50%;
+  height: 25px;
+  background-size: 100% 100%;
+}
+
+
+.line-through {
+  text-decoration: line-through;
+}
+
+/* activity */
+
+.activity {
+  position: relative;
+  background: #fff;
+  width: 100%;
+  height: 78rpx;
+}
+
+.activity-box {
+  background: #fff;
+  width: 100%;
+  height: 78rpx;
+  overflow: hidden;
+  padding: 0 30rpx;
+  display: flex;
+}
+
+.activity-box .item {
+  height: 78rpx;
+  line-height: 78rpx;
+  text-align: center;
+  flex: 1;
+  color: #333;
+  font-size: 26rpx;
+}
+
+.activity-box .item .txt {
+  display: block;
+  width: 100%;
+  height: 100%;
+  color: #333;
+}
+
+.activity-box .item.active .txt {
+  color: #b4282d;
+}
+
+.attr-close{
+    position: absolute;
+    text-align: center;
+    top:130rpx;
+    right:20rpx;
+}
+
+.coupon .img  {
+    left: 5%;
+    position: absolute;
+    top: 10%;
+    height:80%;
+    width:90%;
+    z-index: 999;
+    background: #FFFFFF;
+    filter:alpha(opacity=10);
+    -moz-opacity:10;
+    opacity:10;
+}
+.add2 {
+  box-sizing:border-box;
+  width:25px;
+  border:none;
+  border-radius:50%;
+  height:25px;
+}

+ 340 - 0
wx-mall-hk/pages/category/category.js

@@ -0,0 +1,340 @@
+var util = require('../../utils/util.js');
+var goodsUtil = require('../../utils/goods.js');
+var api = require('../../config/api.js');
+
+Page({
+    data: {
+        // text:"这是一个页面"
+        navList: [],
+        goodsList: [],
+        id: 0,
+        goodsBizType: '00',
+        currentTab: 0,
+        navIndex: 0,
+        currentCategory: {},
+        scrollLeft: 0,
+        scrollTop: 0,
+        scrollHeight: 0,
+        page: 1,
+        size: 10,
+        showNavList: false,
+        footCart: {},
+        openAttr: false,
+        productList: {},
+        specificationList: {},
+        checkedSpecText: '请选择规格数量',
+        number: 1
+    },
+    toggleNav() {
+        this.setData({
+            showNavList: !this.data.showNavList
+        })
+    },
+    // 滚动切换标签样式
+    switchTab: function (e) {
+        let that = this;
+        //当页面改变是会触发
+        console.log("e.detail.current:" + e.detail.current);
+        this.setData({
+            currentTab: e.detail.current
+        });
+        // console.log("currentTab:" + that.data.currentTab);
+        if (that.data.navIndex == e.detail.current) {
+            this.setData({
+                navIndex: -1
+            });
+            return;
+        }
+        let navListCount = that.data.navList.length;
+        for (let i = 0; i < navListCount; i++) {
+            if (i == e.detail.current) {
+                that.setData({
+                    id: that.data.navList[i].id
+                });
+                break;
+            }
+        }
+        that.setData({
+            scrollLeft: (e.detail.current - 1) * 60
+        });
+        that.refreshCategoryInfo();
+    },
+    switchNav(event) {
+        let name = event.currentTarget.dataset.name;
+        wx.switchTab({
+            url: `/pages/${name}/${name}`,
+        });
+    },
+    onLoad: function (options) {
+        // 页面初始化 options为页面跳转所带来的参数
+        var that = this;
+        if (options.id) {
+            that.setData({
+                id: parseInt(options.id)
+            });
+        } else {
+            that.setData({
+                id: 0,
+                currentCategory: {}
+            });
+        }
+        if (options.goodsBizType) {
+            that.setData({
+                goodsBizType: options.goodsBizType
+            });
+        }
+        if (options.currentIndex) {
+            that.setData({
+                currentTab: options.currentIndex
+            });
+        }
+        wx.getSystemInfo({
+            success: function (res) {
+                var clientHeight = res.windowHeight,
+                    clientWidth = res.windowWidth,
+                    rpxR = 750 / clientWidth;
+                var calc = clientHeight * rpxR - 180;
+                that.setData({
+                    scrollHeight: calc
+                });
+            }
+        });
+        this.getCategoryInfo();
+    },
+    getFootCart: function () {
+        let that = this;
+        util.request(api.GetFootCart).then(function (res) {
+            if (res.errno === 0) {
+                that.setData({
+                    footCart: res.data,
+                });
+            }
+        });
+    },
+    getCategoryInfo: function () {
+        let that = this;
+        util.request(api.GoodsCategory, { id: that.data.id, goodsBizType: that.data.goodsBizType })
+            .then(function (res) {
+                if (res.errno == 0) {
+                    that.setData({
+                        navList: res.data.brotherCategory,
+                        currentCategory: res.data.currentCategory
+                    });
+                    //nav位置
+                    let currentIndex = that.data.currentTab;
+                    let navListCount = that.data.navList.length;
+                    for (let i = 0; i < navListCount; i++) {
+                        if (that.data.navList[i].id == that.data.id) {
+                            break;
+                        }
+                    }
+                    if (currentIndex > navListCount / 2 && navListCount > 5) {
+                        that.setData({
+                            scrollLeft: currentIndex * 60
+                        });
+                    }
+                    that.setData({
+                        currentTab: currentIndex,
+                        navIndex: currentIndex
+                    });
+                    that.getGoodsList();
+                } else {
+                    //显示错误信息
+                }
+            });
+    },
+    refreshCategoryInfo: function () {
+        let that = this;
+        util.request(api.GoodsCategory, { id: this.data.id })
+            .then(function (res) {
+                if (res.errno == 0) {
+                    that.setData({
+                        navList: res.data.brotherCategory,
+                        currentCategory: res.data.currentCategory,
+                        goodsList: []
+                    });
+                    that.getGoodsList();
+                } else {
+                    //显示错误信息
+                }
+            });
+    },
+    onReady: function () {
+        // 页面渲染完成
+    },
+    onShow: function () {
+        // 页面显示
+        this.getFootCart();
+    },
+    onHide: function () {
+        // 页面隐藏
+    },
+    getGoodsList: function () {
+        var that = this;
+        wx.showLoading({
+            title: '加载中...',
+        });
+        util.request(api.GoodsList, { categoryId: that.data.id, goodsBizType: that.data.goodsBizType, page: that.data.page, size: that.data.size })
+            .then(function (res) {
+                let goodsList = that.data.goodsList.concat(res.data.data);
+                that.setData({
+                    goodsList: goodsList,
+                });
+                wx.hideLoading();
+            });
+    },
+    onUnload: function () {
+        // 页面关闭
+    },
+    switchAttrPop: function () {
+        this.setData({
+            openAttr: !this.data.openAttr
+        })
+    }
+    ,
+    //购物车增加
+    addCart: function (e) {
+        let that = this;
+        var goodsId = e.currentTarget.dataset.goodsId;
+        util.request(api.GoodsSku, {goodsId: goodsId}).then(function (res) {
+            if (res.errno === 0 && null != res.data) {
+                that.setData({
+                    goodsVo: res.data.goodsVo,
+                    specificationList: res.data.specificationList,
+                    productList: res.data.productList,
+                    openAttr: !that.data.openAttr,
+                    checkedSpecText: res.data.specificationList[0].valueList[0].value
+                });
+                //
+                let _specificationList = res.data.specificationList;
+                for (let i = 0; i < _specificationList.length; i++) {
+                    if (_specificationList[i].valueList.length == 1) {
+                        //如果已经选中,则反选
+                        _specificationList[i].valueList[0].checked = true;
+                    }
+                }
+                that.setData({
+                    'specificationList': _specificationList
+                });
+
+            }
+        });
+    }
+    ,
+    clickSkuValue: function (event) {
+        let that = this;
+        let specValueId = event.currentTarget.dataset.valueId;
+        let index = event.currentTarget.dataset.index;
+        let _specificationList = this.data.specificationList;
+        for (let j = 0; j < _specificationList[index].valueList.length; j++) {
+            if (_specificationList[index].valueList[j].id == specValueId) {
+                //如果已经选中,则反选
+                if (_specificationList[index].valueList[j].checked) {
+                    _specificationList[index].valueList[j].checked = false;
+                } else {
+                    _specificationList[index].valueList[j].checked = true;
+                }
+            } else {
+                _specificationList[index].valueList[j].checked = false;
+            }
+        }
+        this.setData({
+            'specificationList': _specificationList
+        });
+        //重新计算spec改变后的信息
+        goodsUtil.changeSpecInfo(that);
+    }
+    ,
+    cutNumber: function () {
+        this.setData({
+            number: (this.data.number - 1 > 1) ? this.data.number - 1 : 1
+        });
+    }
+    ,
+    addNumber: function () {
+        this.setData({
+            number: this.data.number + 1
+        });
+    }
+    ,
+    //购物车增加
+    addToCart: function () {
+        let that = this;
+        var goodsId = that.data.goodsVo.id;
+        //提示选择完整规格
+        if (!that.data.productList || !that.data.productList.length) {
+            util.showErrorToast('当前门店没有库存');
+            return false;
+        }
+        //提示选择完整规格
+        if (!goodsUtil.isCheckedAllSpec(that)) {
+            return false;
+        }
+        //根据选中的规格,判断是否有对应的sku信息
+        let checkedProduct = goodsUtil.getCheckedProductItem(goodsUtil.getCheckedSpecKey(that), that);
+        if (!checkedProduct || checkedProduct.length <= 0) {
+            //找不到对应的product信息,提示没有库存
+            return false;
+        }
+        //验证库存
+        if (checkedProduct.stock_num < this.data.number) {
+            //找不到对应的product信息,提示没有库存
+            return false;
+        }
+        util.request(api.CartAdd, {
+            goodsId: goodsId,
+            productId: checkedProduct[0].id,
+            number: this.data.number
+        }, 'POST').then(function (res) {
+            if (res.errno === 0 && null != res.data) {
+                wx.showToast({
+                    title: '添加成功',
+                    icon: 'success',
+                    mask: true
+                });
+                that.setData({
+                    openAttr: !that.data.openAttr
+                })
+                that.getFootCart();
+            } else {
+                util.showErrorToast(res.errmsg)
+            }
+        });
+    },
+    switchCate: function (event) {
+        console.log(this.data.scrollLeft);
+        if (this.data.id == event.currentTarget.dataset.id) {
+            return false;
+        }
+        var that = this;
+        that.setData({
+            goodsList: [],
+            page: 1,
+            currentTab: event.currentTarget.dataset.current
+        });
+        console.log("currentIndex:" + that.data.currentTab);
+        var clientX = event.detail.x;
+        var currentTarget = event.currentTarget;
+        if (clientX < 60) {
+            that.setData({
+                scrollLeft: currentTarget.offsetLeft - 60
+            });
+        } else if (clientX > 330) {
+            that.setData({
+                scrollLeft: currentTarget.offsetLeft
+            });
+        }
+        this.setData({
+            id: event.currentTarget.dataset.id,
+            goodsBizType: that.data.goodsBizType
+        });
+        this.getCategoryInfo();
+    },
+    onReachBottom() {
+        var that = this;
+        that.setData({
+            page: that.data.page + 1,
+        });
+        that.getGoodsList();
+    }
+})

+ 3 - 0
wx-mall-hk/pages/category/category.json

@@ -0,0 +1,3 @@
+{
+  "onReachBottomDistance": 450
+}

+ 118 - 0
wx-mall-hk/pages/category/category.wxml

@@ -0,0 +1,118 @@
+<view class="container">
+  <view class="cart-panel" wx:if="{{footCart.goodsCount>0}}">
+    <view class="cart-icon">
+      <navigator class="nav-cell" open-type='switchTab' url="/pages/cart/cart">
+        <image src="../../static/images/cart-fixed.png">
+        </image>
+      </navigator>
+      <view class="cart-num" bindtap="switchNav" data-name="cart">{{footCart.goodsCount}}</view>
+    </view>
+    <view class="cart-body" bindtap="switchNav" data-name="cart">¥{{footCart.checkedGoodsAmount}}</view>
+    <navigator class="nav-cell" open-type='switchTab' url="/pages/cart/cart">
+      <view class="cart-pay">去结算 > </view>
+    </navigator>
+  </view>
+  <view wx:if="{{showNavList}}" class="modal-wrap"></view>
+  <view class="fast-nav">
+    <contact-button wx:if="{{!showNavList}}" class="contact" size="25" type="primary" session-from="weapp">
+      <text>找客服</text>
+    </contact-button>
+    <view wx:if="{{!showNavList}}" class="nav" bindtap="toggleNav">
+      <text>快捷</text>
+      <text>导航</text>
+    </view>
+    <view class="nav-list" wx:if="{{showNavList}}">
+      <view class="nav-item">
+        <text class="nav-text">首页</text>
+        <view class="nav-cell" bindtap="switchNav" data-name="index">
+          <image src="../../static/images/nav-1.png"></image>
+        </view>
+      </view>
+      <view class="nav-item">
+        <text class="nav-text">足迹</text>
+        <navigator class="nav-cell" url="../ucenter/footprint/footprint">
+          <image src="../../static/images/nav-2.png"></image>
+        </navigator>
+      </view>
+      <view class="nav-item">
+        <text class="nav-text">搜索</text>
+        <navigator class="nav-cell" url="../search/search">
+          <image src="../../static/images/nav-3.png"></image>
+        </navigator>
+      </view>
+      <view class="nav-item">
+        <text class="nav-text">购物车</text>
+        <view class="nav-cell" bindtap="switchNav" data-name="cart">
+          <image src="../../static/images/nav-4.png"></image>
+        </view>
+      </view>
+    </view>
+    <view wx:if="{{showNavList}}" class="close" bindtap="toggleNav">X</view>
+  </view>
+  <view class="cate-nav">
+    <scroll-view scroll-x="true" class="cate-nav-body" style="width: 750rpx;" scroll-left="{{scrollLeft}}" >
+      <view wx:for="{{navList}}" class="item {{ id == item.id ? 'active' : ''}}" data-current="{{index}}" data-id="{{item.id}}" bindtap="switchCate" wx:key="{{index}}">
+        <view class="name">{{item.name}}</view>
+      </view>
+    </scroll-view>
+  </view>
+  <!-- bindchange="switchTab" -->
+  <swiper class="" current="{{currentTab}}" scroll-top="{{scrollTop}}" style="height:{{scrollHeight}}px;">
+    <swiper-item wx:for="{{navList}}"  wx:key="{{navIndex}}">
+      <scroll-view scroll-y="true" class="cate-item">
+        <view class="h">
+          <text class="name">{{currentCategory.name}}</text>
+          <text class="desc">{{currentCategory.front_name?currentCategory.front_name:""}}</text>
+        </view>
+        <view class="b">
+          <block wx:for="{{goodsList}}" wx:for-index="iindex" wx:for-item="iitem" wx:key="unique">
+            <view class="item {{iindex % 2 == 0 ? 'item-b' : '' }}">
+
+              <navigator url="../goods/goods?id={{iitem.id}}&&currentIndex={{navIndex}}">
+                <image class="img" src="{{iitem.list_pic_url}}"></image>
+                <text class="name">{{iitem.name}}</text>
+              </navigator>
+
+              <view class="price">¥{{iitem.retail_price == null?'':iitem.retail_price}}
+                <image class="cart" src="/static/images/cart.png" data-goods-id="{{iitem.id}}" data-product-id="{{iitem.product_id}}" bindtap='addCart' background-size="cover"></image>
+              </view>
+            </view>
+          </block>
+        </view>
+      </scroll-view>
+    </swiper-item>
+  </swiper>
+
+   <view wx:if="{{openAttr}}" class="attr-pop">
+          <view class="attr-close" bindtap="switchAttrPop">X</view>
+          <view class="img-info">
+            <image class="img" src="{{goodsVo.list_pic_url}}"></image>
+            <view class="info">
+              <view class="c">
+                <view class="p">价格:¥{{goodsVo.retail_price}}</view>
+                <view class="a" wx:if="{{productList.length>0}}">已选择:{{checkedSpecText}}</view>
+              </view>
+            </view>
+          </view>
+          <view class="spec-con">
+            <view class="spec-item" wx:for="{{specificationList}}" wx:key="{{item.specification_id}}" wx:for-index="itemIndex">
+              <view class="name">{{item.name}}</view>
+              <view class="values">
+                <view class="value {{vitem.checked ? 'selected' : ''}}" bindtap="clickSkuValue" wx:for="{{item.valueList}}" wx:for-item="vitem" wx:key="{{vitem.id}}" data-index="{{itemIndex}}" data-value-id="{{vitem.id}}" data-name-id="{{vitem.specification_id}}">{{vitem.value}}</view>
+              </view>
+            </view>
+
+            <view class="number-item">
+              <view class="name">数量</view>
+              <view class="selnum">
+                <view class="cut" bindtap="cutNumber">-</view>
+                <input value="{{number}}" class="number" disabled="true" type="number" />
+                <view class="add" bindtap="addNumber">+</view>
+              </view>
+            </view>
+          </view>
+          <view class="bottom-btn">
+            <view class="r" bindtap="addToCart">加入购物车</view>
+          </view>
+        </view>
+</view>

+ 291 - 0
wx-mall-hk/pages/category/category.wxss

@@ -0,0 +1,291 @@
+.container{
+    background: #f9f9f9;
+}
+
+.cate-nav{
+    position: fixed;
+    left:0;
+    top:0;
+    z-index: 100;
+    width: 100%;
+    white-space: nowrap;
+}
+
+.cate-nav-body{
+  width: auto;
+    height: 84rpx;
+    /* white-space: nowrap;    */
+    background: #fff;
+     border-top: 1px solid rgba(0,0,0,.15); 
+    overflow: hidden;
+}
+
+::-webkit-scrollbar{
+width: 0;
+height: 0;
+color: transparent;
+}
+/* scroll-view隐藏滚动条方法 */
+.cate-nav .item{
+    display: inline-block;
+    height: 84rpx;
+    /* min-width: 130rpx; */
+    padding: 0 15rpx;
+}
+
+.cate-nav .item .name{
+    display: block;
+    height: 84rpx;
+    padding: 0 20rpx;
+    line-height: 84rpx;
+    color: #333;
+    font-size: 30rpx;
+    width: auto;
+}
+
+.cate-nav .item.active .name{
+    color: #ab2b2b;
+    border-bottom: 2px solid #ab2b2b;
+}
+
+.cate-item{
+    margin-top: 94rpx;
+    height: 100%;
+    overflow: hidden;
+}
+
+.cate-item .h{
+    height: 145rpx;
+    width: 750rpx;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+}
+
+.cate-item .h .name{
+    display: block;
+    height: 35rpx;
+    margin-bottom: 18rpx;
+    font-size: 30rpx;
+    color: #333;
+}
+
+.cate-item .h .desc{
+    display: block;
+    height: 24rpx;
+    font-size: 24rpx;
+    color: #999;
+}
+
+.cate-item .b{
+  width: 750rpx;
+  padding: 0 6.25rpx;
+  height: auto;
+  overflow: hidden;
+  margin-bottom: 400rpx;
+}
+
+.cate-item .b .item{
+  float: left;
+  background: #fff;
+  width: 365rpx;
+  margin-bottom: 6.25rpx;
+  padding-bottom: 33.333rpx;
+  height: auto;
+  overflow: hidden;
+  text-align: center;
+}
+
+.cate-item .b .item-b{
+  margin-left: 6.25rpx;
+}
+
+.cate-item .item .img{
+  width: 302rpx;
+  height: 302rpx;
+  background-size: 202rpx 202rpx;
+}
+
+.cate-item .item .name{
+  display: block;
+  width: 365.625rpx;
+  height: 70rpx;
+  margin: 11.5rpx 0 22rpx 0;
+  text-align: center;
+  padding: 0 20rpx;
+  font-size: 26rpx;
+  color: #333;
+}
+.cate-item .item .price{
+  display: block;
+  width: 365.625rpx;
+  height: 30rpx;
+  text-align: center;
+  font-size: 30rpx;
+  color: #b4282d;
+}
+.cate-item .item .price .cart{
+  margin-left: 20rpx;
+  width: 35rpx;
+  height: 35rpx;
+  vertical-align: -6rpx;
+}
+
+
+.attr-pop {
+  width: 100%;
+  height: auto;
+  padding: 31.25rpx;
+  background: #fff;
+  position: fixed;
+  bottom: 100rpx;
+  z-index: 500;
+}
+
+.attr-close{
+  float: right;
+  width: 40rpx;
+  height: 40rpx;
+  line-height: 40rpx;
+  border-radius: 50%;
+  font-size: 40rpx;
+  text-align: center;
+  overflow: hidden;
+}
+
+.attr-pop .img-info {
+  width: 687.5rpx;
+  height: 177rpx;
+  overflow: hidden;
+  margin-bottom: 41.5rpx;
+}
+
+.attr-pop .img {
+  float: left;
+  height: 177rpx;
+  width: 177rpx;
+  background: #f4f4f4;
+  margin-right: 31.25rpx;
+}
+
+.attr-pop .info {
+  float: left;
+  height: 177rpx;
+  display: flex;
+  align-items: flex-start;
+}
+
+.attr-pop .p {
+  font-size: 33rpx;
+  color: #333;
+  height: 33rpx;
+  line-height: 33rpx;
+  margin-bottom: 10rpx;
+}
+
+.attr-pop .a {
+  font-size: 29rpx;
+  color: #333;
+  height: 40rpx;
+  line-height: 40rpx;
+  width: 260px;
+  display:block;
+  word-break: break-all;
+  word-wrap: break-word;
+}
+
+.spec-con {
+  width: 100%;
+  height: auto;
+  overflow: hidden;
+}
+
+.spec-con .name {
+  height: 32rpx;
+  margin-bottom: 22rpx;
+  font-size: 29rpx;
+  color: #333;
+}
+
+.spec-con .values {
+  height: auto;
+  margin-bottom: 31.25rpx;
+  font-size: 0;
+}
+
+.spec-con .value {
+  display: inline-block;
+  height: 62rpx;
+  padding: 0 35rpx;
+  line-height: 56rpx;
+  text-align: center;
+  margin-right: 25rpx;
+  margin-bottom: 16.5rpx;
+  border: 1px solid #333;
+  font-size: 25rpx;
+  color: #333;
+}
+
+.spec-con .value.disable {
+  border: 1px solid #ccc;
+  color: #ccc;
+}
+
+.spec-con .value.selected {
+  border: 1px solid #b4282d;
+  color: #b4282d;
+}
+
+.number-item .selnum {
+  width: 322rpx;
+  height: 71rpx;
+  border: 1px solid #ccc;
+  display: flex;
+}
+
+.number-item .cut {
+  width: 93.75rpx;
+  height: 100%;
+  text-align: center;
+  line-height: 65rpx;
+}
+
+.number-item .number {
+  flex: 1;
+  height: 100%;
+  text-align: center;
+  line-height: 68.75rpx;
+  border-left: 1px solid #ccc;
+  border-right: 1px solid #ccc;
+  float: left;
+}
+
+.number-item .add {
+  width: 93.75rpx;
+  height: 100%;
+  text-align: center;
+  line-height: 65rpx;
+}
+
+.bottom-btn {
+  position: fixed;
+  left: 0;
+  bottom: 0;
+  z-index: 10;
+  width: 750rpx;
+  height: 100rpx;
+  display: flex;
+  background: #fff;
+}
+
+.bottom-btn .r {
+  border: 1px solid #b4282d;
+  background: #b4282d;
+  float: left;
+  height: 100rpx;
+  line-height: 96rpx;
+  flex: 1;
+  text-align: center;
+  color: #fff;
+}

+ 133 - 0
wx-mall-hk/pages/comment/comment.js

@@ -0,0 +1,133 @@
+var app = getApp();
+var util = require('../../utils/util.js');
+var api = require('../../config/api.js');
+
+Page({
+  data: {
+    comments: [],
+    allCommentList: [],
+    picCommentList: [],
+    typeId: 0,
+    valueId: 0,
+    orderId: 0,
+    showType: 0,
+    allCount: 0,
+    hasPicCount: 0,
+    allPage: 1,
+    picPage: 1,
+    size: 20
+  },
+  getCommentCount: function () {
+    let that = this;
+    util.request(api.CommentCount, { valueId: that.data.valueId, typeId: that.data.typeId, orderId: that.data.orderId }).then(function (res) {
+      if (res.errno === 0) {
+
+        that.setData({
+          allCount: res.data.allCount,
+          hasPicCount: res.data.hasPicCount
+        });
+      }
+    });
+  },
+  getCommentList: function () {
+    let that = this;
+    util.request(api.CommentList, {
+      valueId: that.data.valueId,
+      typeId: that.data.typeId,
+      orderId: that.data.orderId,
+      size: that.data.size,
+      page: (that.data.showType == 0 ? that.data.allPage : that.data.picPage),
+      showType: that.data.showType
+    }).then(function (res) {
+      if (res.errno === 0) {
+
+        if (that.data.showType == 0) {
+          that.setData({
+            allCommentList: res.data.data,
+            allPage: res.data.currentPage,
+            comments: res.data.data,
+          });
+        } else {
+          that.setData({
+            picCommentList: res.data.data,
+            picPage: res.data.currentPage,
+            comments: res.data.data
+          });
+        }
+      }
+    });
+  },
+  onLoad: function (options) {
+    // 页面初始化 options为页面跳转所带来的参数
+    if (options.typeId) {
+      this.setData({
+        typeId: options.typeId
+      });
+    }
+    if (options.valueId) {
+      this.setData({
+        valueId: options.valueId,
+      });
+    }
+    if (options.orderId) {
+      this.setData({
+        orderId: options.orderId
+      });
+    }
+    this.getCommentCount();
+    this.getCommentList();
+  },
+  onReady: function () {
+    // 页面渲染完成
+
+  },
+  onShow: function () {
+    // 页面显示
+
+  },
+  onHide: function () {
+    // 页面隐藏
+
+  },
+  onUnload: function () {
+    // 页面关闭
+
+  },
+  switchTab: function () {
+    this.setData({
+      showType: this.data.showType == 1 ? 0 : 1
+    });
+
+    this.getCommentList();
+  },
+  onReachBottom: function () {
+    console.log('onPullDownRefresh');
+    if (this.data.showType == 0) {
+
+      if (this.data.allCount / this.data.size < this.data.allPage) {
+        return false;
+      }
+
+      this.setData({
+        'allPage': this.data.allPage + 1
+      });
+    } else {
+      if (this.data.hasPicCount / this.data.size < this.data.picPage) {
+        return false;
+      }
+
+      this.setData({
+        'picPage': this.data.picPage + 1
+      });
+    }
+    this.getCommentList();
+  },
+  previewPic(e) {
+    let url = e.currentTarget.dataset.url;
+    let urls = [];
+    urls[0] = url;
+    wx.previewImage({
+      urls
+    })
+  }
+})

+ 3 - 0
wx-mall-hk/pages/comment/comment.json

@@ -0,0 +1,3 @@
+{
+
+}

+ 49 - 0
wx-mall-hk/pages/comment/comment.wxml

@@ -0,0 +1,49 @@
+<view class="comments">
+    <view class="h">
+        <view class="item {{ showType == 0 ? 'active' : ''}}" bindtap="switchTab">
+            <view class="txt">全部({{allCount}})</view>
+        </view>
+        <view class="item {{ showType == 0 ? '' : 'active'}}" bindtap="switchTab">
+            <view class="txt">有图({{hasPicCount}})</view>
+        </view>
+    </view>
+  <view class="b">
+    <view class="item" wx:for="{{comments}}" wx:key="{{item.id}}">
+      <view class="info">
+        <view class="user">
+          <image src="{{item.user_info.avatar}}"></image>
+          <text>{{item.user_info.nickname}}</text>
+        </view>
+        <view class="time">{{item.add_time}}</view>
+      </view>
+      <view class="comment">{{item.content}}</view>
+      <view class="imgs" wx:if="{{item.pic_list.length > 0}}">
+        <image class="img"  data-url="{{pitem.pic_url}}"  wx:for="{{item.pic_list}}" bindtap="previewPic" wx:key="{{pitem.id}}" wx:for-item="pitem" src="{{pitem.pic_url}}"></image>
+      </view>
+      <view class="spec">
+        <!-- <text class="item">白色 2件</text> -->
+      </view>
+      <!--<view class="customer-service" wx:if="{{item.commentReplyVO}}">
+        <text class="u">小选回复:</text>
+        <text class="c">{{item.commentReplyVO.replyContent}}</text>
+      </view>-->
+
+
+       <view class="service-box">
+    <view class="service-item">
+      <text class="label">服务态度</text>
+      <view class="star-box">
+        <text class="star checked" wx:for="{{item.evalLevel}}" wx:key="{{index}}" data-score="{{index + 1}}" >★</text>
+      </view>
+    </view>
+    <view class="service-item">
+      <text class="label">商品质量</text>
+      <view class="star-box">
+ <text class="star checked" wx:for="{{item.goodsLevel}}" wx:key="{{index}}" data-score="{{index + 1}}" >★</text>
+      </view>
+    </view>
+  </view>
+    </view>
+
+  </view>
+</view>

+ 185 - 0
wx-mall-hk/pages/comment/comment.wxss

@@ -0,0 +1,185 @@
+.comments {
+  width: 100%;
+  height: auto;
+  padding-left: 30rpx;
+  background: #fff;
+  margin: 20rpx 0;
+}
+
+.comments .h {
+  position: fixed;
+  left: 0;
+  top: 0;
+  z-index: 1000;
+  width: 100%;
+  display: flex;
+  background: #fff;
+  height: 84rpx;
+  border-bottom: 1px solid rgba(0, 0, 0, 0.15);
+}
+
+.comments .h .item {
+  display: inline-block;
+  height: 82rpx;
+  width: 50%;
+  padding: 0 15rpx;
+  text-align: center;
+}
+
+.comments .h .item .txt {
+  display: inline-block;
+  height: 82rpx;
+  padding: 0 20rpx;
+  line-height: 82rpx;
+  color: #333;
+  font-size: 30rpx;
+  width: 170rpx;
+}
+
+.comments .h .item.active .txt {
+  color: #ab2b2b;
+  border-bottom: 4rpx solid #ab2b2b;
+}
+
+.comments .b {
+  margin-top: 85rpx;
+  height: auto;
+  width: 720rpx;
+}
+
+.comments .b.no-h {
+  margin-top: 0;
+}
+
+.comments .item {
+  height: auto;
+  width: 720rpx;
+  overflow: hidden;
+  border-bottom: 1px solid #d9d9d9;
+  padding-bottom: 25rpx;
+}
+
+.comments .info {
+  height: 127rpx;
+  width: 100%;
+  padding: 33rpx 0 27rpx 0;
+}
+
+.comments .user {
+  float: left;
+  width: auto;
+  height: 67rpx;
+  line-height: 67rpx;
+  font-size: 0;
+}
+
+.comments .user image {
+  float: left;
+  width: 67rpx;
+  height: 67rpx;
+  margin-right: 17rpx;
+  border-radius: 50%;
+}
+
+.comments .user text {
+  display: inline-block;
+  width: auto;
+  height: 66rpx;
+  overflow: hidden;
+  font-size: 29rpx;
+  line-height: 66rpx;
+}
+
+.comments .time {
+  display: block;
+  float: right;
+  width: auto;
+  height: 67rpx;
+  line-height: 67rpx;
+  color: #7f7f7f;
+  font-size: 25rpx;
+  margin-right: 30rpx;
+}
+
+.comments .comment {
+  width: 720rpx;
+  padding-right: 30rpx;
+  line-height: 45.8rpx;
+  font-size: 29rpx;
+  margin-bottom: 16rpx;
+}
+
+.comments .imgs {
+  width: 720rpx;
+  height: 150rpx;
+  margin-bottom: 25rpx;
+}
+
+.comments .imgs .img {
+  height: 150rpx;
+  width: 150rpx;
+  margin-right: 28rpx;
+}
+
+.comments .spec {
+  width: 720rpx;
+  height: 25rpx;
+  font-size: 24rpx;
+  color: #999;
+}
+
+.comments .spec .item {
+  color: #7f7f7f;
+  font-size: 25rpx;
+}
+
+.comments .customer-service {
+  width: 690rpx;
+  height: auto;
+  overflow: hidden;
+  margin-top: 23rpx;
+  background: rgba(0, 0, 0, 0.03);
+  padding: 21rpx;
+}
+
+.comments .customer-service .u {
+  font-size: 24rpx;
+  color: #333;
+  line-height: 37.5rpx;
+}
+
+.comments .customer-service .c {
+  font-size: 24rpx;
+  color: #999;
+  line-height: 37.5rpx;
+}
+
+.service-box {
+  background-color: #fff;
+  margin-top: 0px;
+  padding: 0 0px;
+}
+
+.service-item {
+  height: 60rpx;
+  display: flex;
+  align-items: center;
+}
+
+.service-item .label {
+  color: #999;
+}
+
+.service-item text:not(.label) {
+  padding-left: 10px;
+}
+
+.star-box .star {
+  font-size: 1.7em;
+  padding-left: 5px;
+  color: #ddd;
+}
+
+.star-box .star.checked {
+  color: #feb54c;
+}

+ 193 - 0
wx-mall-hk/pages/commentPost/commentPost.js

@@ -0,0 +1,193 @@
+var app = getApp();
+var util = require('../../utils/util.js');
+var api = require('../../config/api.js');
+Page({
+  data: {
+    typeId: 0,
+    mannerScore: 5,//服务态度
+    speedScore: 5,//配送速度
+    goodsList: [{
+      score: 5,
+      comment: '',
+      pics: []
+    },{
+      score: 5,
+      comment: '',
+      pics: []
+    }],
+    orderId:0,
+    orderInfo: {}, // 订单详情
+    orderGoods: {}, // 订单商品
+    coupon: {},
+    handleDesc: ['很差','一般','满意','很满意','非常满意']
+  }, 
+  handleScore(e){
+    let aim = e.currentTarget.dataset.aim;
+    let score = e.currentTarget.dataset.score;
+    let obj = {};
+    obj[aim] = score;
+    this.setData(obj);
+  },
+  previewPic(e){
+    let urls = e.currentTarget.dataset.urls;
+    wx.previewImage({
+      urls
+    })
+  },
+  handleDelete(e){
+    let that = this;
+    let src = e.currentTarget.dataset.src;
+    let goodsIndex = e.currentTarget.dataset.goodsIndex;
+    let pics = e.currentTarget.dataset.pics;
+    pics = pics.filter(item => item != src);
+    //
+    let goodsList = that.data.goodsList;
+    goodsList[goodsIndex].pics = pics;
+    this.setData({
+      goodsList:goodsList
+    });
+  },
+  bindInpuntValue(event) {
+    let that = this;
+    let goodsIndex = event.target.dataset.goodsIndex;
+    let value = event.detail.value;
+    let goodsList = that.data.goodsList;
+    goodsList[goodsIndex].comment = value
+    this.setData({
+      goodsList:goodsList
+    })
+  },
+  chooseImageTap: function (e) {
+    let that = this;
+    let goodsIndex = e.currentTarget.dataset.goodsIndex;
+    let pics = e.currentTarget.dataset.pics;
+    wx.showActionSheet({
+      itemList: ['从相册中选择', '拍照'],
+      itemColor: "#f7982a",
+      success: function (res) {
+        if (!res.cancel) {
+          if (res.tapIndex == 0) {
+            that.chooseWxImage('album', goodsIndex, pics);
+          } else if (res.tapIndex == 1) {
+            that.chooseWxImage('camera', goodsIndex, pics);
+          }
+        }
+      }
+    })
+  },
+  chooseWxImage: function (type, goodsIndex, pics) {
+    let _this = this;
+    wx.chooseImage({
+      sizeType: ['original', 'compressed'],
+      sourceType: [type],
+      success: function (res) {
+        var tempFilePaths = res.tempFilePaths
+        console.log(res);
+        wx.uploadFile({
+          url: api.UploadFileURL,
+          filePath: tempFilePaths[0],
+          name: 'file',
+          header: {
+            'content-type': 'multipart/form-data'
+          },
+          success: function (res) {
+            var pic = JSON.parse(res.data);
+            pics.unshift(pic.data);
+            let goodsList = _this.data.goodsList;
+            goodsList[goodsIndex].pics = pics;
+            _this.setData({
+              goodsList:goodsList
+            })
+          }
+        })
+      }
+    })
+  },
+  onLoad: function (options) {
+    var that = this;
+    that.setData({
+      typeId: parseInt(options.typeId),
+      orderId: parseInt(options.orderId)
+    });
+    that.getOrderDetail();
+  },
+  onClose() {
+    wx.navigateBack({
+      delta: 1
+    });
+  },
+  onPost() {
+    let that = this;
+    util.request(api.CommentPost, {
+      typeId: that.data.typeId,
+      orderId: that.data.orderId,
+      mannerScore: that.data.mannerScore,
+      speedScore: that.data.speedScore,
+      goodsList: that.data.goodsList
+    }, 'POST').then(function (res) {
+      if (res.errno === 0 && res.data.coupon) {
+        that.setData({
+          coupon: res.data.coupon
+        });
+      } else if (res.errno === 0) {
+        wx.showToast({
+          title: '评论成功',
+          duration: 2000
+        });
+        setTimeout(function () {
+          wx.navigateBack({
+            delta: 2
+          });
+        }, 2000);
+      }
+      console.log(res)
+    });
+  },
+  couponClickBack: function () {
+    wx.navigateBack({
+      delta: 2
+    });
+  },
+  onReady: function () {
+
+  },
+  onShow: function () {
+    // 页面显示
+  },
+  onHide: function () {
+    // 页面隐藏
+
+  },
+  onUnload: function () {
+    // 页面关闭
+  }  ,
+  getOrderDetail() {
+    let that = this;
+    util.request(api.OrderDetail, {
+      orderId: that.data.orderId
+    }).then(function (res) {
+      if (res.errno === 0) {
+        console.log(res.data);
+        that.setData({
+          orderInfo: res.data.orderInfo,
+          orderGoods: res.data.orderGoods,
+        });
+        var goodsList = new Array();
+        for(var i=0;i<res.data.orderGoods.length;i++) {
+          let goodVo = {};
+          goodVo.goods_id = res.data.orderGoods[i].goods_id;
+          goodVo.goods_name = res.data.orderGoods[i].goods_name;
+          goodVo.product_id = res.data.orderGoods[i].product_id;
+          goodVo.list_pic_url = res.data.orderGoods[i].list_pic_url;
+          goodVo.goods_specification_name_value = null!=res.data.orderGoods[i].goods_specification_name_value?res.data.orderGoods[i].goods_specification_name_value:"";
+          goodVo.score = 5;
+          goodVo.pics = [];
+          goodVo.comment = '';
+          goodsList.push(goodVo);
+        }
+        that.setData({goodsList:goodsList
+        });
+      }
+    });
+  }
+})

+ 3 - 0
wx-mall-hk/pages/commentPost/commentPost.json

@@ -0,0 +1,3 @@
+{
+  "navigationBarTitleText": "填写留言"
+}

+ 99 - 0
wx-mall-hk/pages/commentPost/commentPost.wxml

@@ -0,0 +1,99 @@
+<view class="container">
+  <view class="list-group" style="margin-top: 0px;">
+    <view class="list-cell">
+      <view class="list-cell-hd">
+        <image style="width: 80rpx;height:80rpx;" src="/static/images/rider.png"></image>
+      </view>
+      <view class="list-cell-bd">
+        <view class="list-label" style="padding-left: 20rpx;">
+          {{orderInfo.shipping_name}}
+        </view>
+      </view>
+      <view class="list-cell-ft" style="font-size: .7em;">
+        小伙伴都挺不容易的,能不能给个好评,亲 ^_^
+      </view>
+    </view>
+  </view>
+
+  <view class="service-box">
+    <view class="service-item">
+      <text class="label">服务态度</text>
+      <view class="star-box">
+        <text class="star {{ mannerScore > index ? 'checked' : '' }}" bindtap="handleScore" wx:for="{{5}}" wx:key="{{index}}" data-score="{{index + 1}}" data-aim="mannerScore">★</text>
+      </view>
+      <text class="desc">{{handleDesc[mannerScore -1]}}</text>
+    </view>
+    <!-- <view class="service-item">
+      <text class="label">配送速度</text>
+      <view class="star-box">
+        <text class="star {{ speedScore > index ? 'checked' : '' }}" bindtap="handleScore" wx:for="{{5}}" wx:key="{{index}}" data-score="{{index + 1}}" data-aim="speedScore">★</text>
+      </view>
+      <text class="desc">{{handleDesc[speedScore -1]}}</text>
+    </view> -->
+  </view>
+
+  <view class="goods-list" wx:for="{{goodsList}}" wx:key="{{num}}" wx:for-index="num">
+    <view class="list-group">
+      <view class="list-cell">
+        <view class="list-cell-hd">
+          <image style="width: 100rpx;height:100rpx;" src="{{item.list_pic_url}}"></image>
+        </view>
+        <view class="list-cell-bd" style="padding-left: 20rpx;">
+          <view class="list-label">
+            {{item.goods_name}}
+          </view>
+          <view class="list-label-desc">
+            规格:{{item.goods_specification_name_value}}
+          </view>
+        </view>
+      </view>
+      <view class="service-item" style="padding-left:20px">
+        <text class="label">商品质量</text>
+        <view class="star-box">
+          <text class="star {{ goodsList[num].score > index ? 'checked' : '' }}" bindtap="handleScore" wx:for="{{5}}" wx:key="{{index}}" data-score="{{index + 1}}" data-aim="{{ 'goodsList['+num+'].score' }}">★</text>
+        </view>
+        <text class="desc">{{handleDesc[goodsList[num].score -1]}}</text>
+      </view>
+
+      <view class="input-box">
+        <textarea class="content" bindinput="bindInpuntValue" auto-height data-goods-index="{{num}}" maxlength="140" placeholder="留言经过筛选后,对所有人可见" />
+        <text class="count">{{goodsList[num].comment.length}}/140</text>
+      </view>
+      <view class="pic-box">
+        <view class="pic-item" wx:for="{{goodsList[num].pics}}" wx:key="index">
+          <image src="{{item}}" bindtap="previewPic" data-urls="{{goodsList[num].pics}}"></image>
+          <text class="pic-delete" bindtap="handleDelete" data-src="{{item}}" data-pics="{{goodsList[num].pics}}" data-goods-index="{{num}}">x</text>
+        </view>
+        <view class="pic-item pic-handle" wx:if="{{goodsList[num].pics.length < 3}}" bindtap="chooseImageTap" data-pics="{{goodsList[num].pics}}" data-goods-index="{{num}}">
+          <image src="/static/images/photo_icon.png"></image>
+          <text class="desc">添加图片</text>
+        </view>
+      </view>
+
+    </view>
+  </view>
+  <view class="btn-box">
+    <button type="primary" bindtap="onPost">发 布</button>
+  </view>
+</view>
+
+<view class="drawer_box" wx:if="{{coupon.name}}">
+   <view class="drawer_title">恭喜你获取一张优惠券</view>
+   <view style="margin: 5px 10px;">
+      <view class="coupon-box coupon-box1 coupon-box-g">
+        <view class="coupon-bg coupon-bg1">
+          <view>
+            <text class="coupon-currency">¥</text>{{ coupon.type_money }}</view>
+          <view class="coupon-type" wx:if="{{coupon.send_type==4}}">新人专享</view>
+        </view>
+        <view class="coupon-info">
+          <view class="coupon-title">{{ coupon.name }}</view>
+          <view class="coupon-desc">
+            <view>{{ coupon.use_start_date }}-{{ coupon.use_end_date }}</view>
+            <view>{{ null!=item.coupon_txt?item.coupon_txt:"" }}</view>
+          </view>
+        </view>
+      </view>
+    </view>
+  <view class="btn_ok" bindtap="couponClickBack">确定</view>
+</view>

+ 279 - 0
wx-mall-hk/pages/commentPost/commentPost.wxss

@@ -0,0 +1,279 @@
+page, .container {
+  height: 100%;
+  background: #f4f4f4;
+}
+
+
+.service-box{
+  background-color: #fff;
+  margin-top: 10px;
+  padding: 0 20px;
+}
+
+.service-item{
+  height: 100rpx;
+  display: flex;
+  align-items: center;
+}
+
+.service-item .label{
+  color: #999999;
+}
+
+.service-item text:not(.label){
+  padding-left: 10px;
+}
+
+.star-box .star{
+  font-size: 1.7em;
+  padding-left: 5px;
+  color: #ddd;
+}
+
+.star-box .star.checked{
+  color: #FEB54C;
+}
+
+.goods-list{
+  background-color: #fff;
+}
+
+.goods-list .input-box{
+  border: 1px solid #ccc;
+  margin: 0 20px;
+  padding: 10px;
+  padding-bottom: 25px;
+}
+
+.goods-list .input-box .content{
+  width: 100%;
+}
+.goods-list .input-box .count{
+  float: right;
+}
+
+.pic-box{
+  margin-top: 10px;
+  padding: 0 20px;
+  padding-bottom: 20px;
+  display: flex;
+  flex-wrap: nowrap;
+}
+
+.pic-item{
+  position: relative;
+  width: 200rpx;
+  height: 200rpx;
+  margin-right: 10px;
+  display: inline-block;
+}
+
+.pic-item image{
+  width: 100%;
+  height: 100%;
+}
+
+.pic-item .pic-delete{
+  position: absolute;
+  width: 30rpx;
+  height: 30rpx;
+  text-align: center;
+  color: #fff;
+  line-height: 30rpx;
+  top: -15rpx;
+  right: -15rpx;
+  border-radius: 50%;
+  background-color: red;
+}
+
+.pic-handle{
+  display: inline-flex;
+  align-items: center;
+  justify-content: center;
+  flex-direction: column;
+  border: 1px solid #ccc;
+  border-radius: 3px;
+}
+
+.pic-item.pic-handle image{
+  width: 100rpx;
+  height: 100rpx;
+}
+
+.pic-handle .desc{
+  padding-top: 10px;
+  font-size: .9em;
+  color: #9B9B9B;
+}
+
+.coupon{
+  margin-top: 24rpx;
+  margin-left: 40rpx;
+  display: flex;
+  margin-right: 40rpx;
+  flex-direction: row;
+  align-items: center;
+}
+
+.coupon .left{
+  flex: 1;
+}
+
+.btn-box{
+  margin: 20px 0;
+  padding: 10px 20px;
+}
+
+.name{
+  font-size: 34rpx;
+  color: #fff;
+  margin-bottom: 14rpx;
+}
+
+.time{
+  font-size: 24rpx;
+  color: rgba(255,255,255, 0.8);
+  line-height: 30rpx;
+}
+
+.coupon .right{
+  width: 162rpx;
+}
+
+.condition{
+  position: absolute;
+  width: 100%;
+  bottom: 0;
+  left:0;
+  height: 78rpx;
+  background: rgba(0,0,0,.08);
+  padding: 24rpx 40rpx;
+  display: flex;
+  flex-direction: row;
+}
+
+.condition .txt{
+  display: block;
+  height: 30rpx;
+  flex: 1;
+  overflow: hidden;
+  font-size: 24rpx;
+  line-height: 30rpx;
+  color: #fff;
+}
+
+.condition .icon{
+  margin-left: 30rpx;
+  width: 24rpx;
+  height: 24rpx;
+}
+
+.drawer_box {
+  width: 650rpx;
+  overflow: hidden;
+  position: fixed;
+  top: 50%;
+  left: 0;
+  z-index: 1001;
+  background: #f4f4f4;
+  margin: -150px 50rpx 0 50rpx;
+  border-radius: 3px;
+}
+
+.drawer_title {
+  padding: 15px;
+  font: 20px "microsoft yahei";
+  text-align: center;
+  background: #b4282d;
+}
+
+.drawer_content {
+  height: 410px;
+  overflow-y: scroll; /*超出父盒子高度可滚动*/
+}
+
+.btn_ok {
+  padding: 10px;
+  font: 20px "microsoft yahei";
+  text-align: center;
+  border-top: 1px solid #e8e8ea;
+  color: #b4282d;
+}
+
+
+.coupon-box {
+  background-color: #fff;
+  display: flex;
+  border-radius: 5px;
+  flex-direction: row;
+  position: relative;
+}
+
+.coupon-box .coupon-used {
+  position: absolute;
+  top: 50%;
+  right: 10px;
+  margin-top: -7.5vmin;
+  height: 15vmin;
+  width: 15vmin;
+  background: url(http://120.76.26.84:80/group1/M00/00/02/rBJEdVvr2s2AIzXWAAAPHxXo1UI166.png) no-repeat center;
+  background-size: contain;
+}
+
+.coupon-box-g {
+  background: linear-gradient(to right, #f0f0f0, #fff);
+}
+
+
+.coupon-bg {
+  width: 35%;
+  background-position: left;
+  background-size: cover;
+  color: #fff;
+  font-size: 2.4rem;
+  display: flex;
+  justify-content: center;
+  flex-direction: column;
+  align-items: center;
+}
+.coupon-bg > view{
+  font-size: inherit;
+  color: #fff;
+}
+
+.coupon-bg .coupon-currency {
+  font-size: 1rem;
+  padding-right: 5px;
+  color: #fff;
+}
+
+.coupon-bg .coupon-type {
+  font-size: 0.8rem;
+  color: #fff;
+}
+
+.coupon-bg1 {
+  background-image: url(http://120.76.26.84:80/group1/M00/00/02/rBJEdVvr2v6AcFmPAAAXWs0DSHQ136.png);
+}
+
+.coupon-bg2 {
+  background-image: url(http://120.76.26.84:80/group1/M00/00/02/rBJEdVvr2x6AEzgOAAAPIKZoCH4265.png);
+}
+
+.coupon-info {
+  width: 50%;
+  margin-left: 40px;
+}
+
+.coupon-info .coupon-title {
+  font-size: 1.1rem;
+  padding: 8px 0 4px 0;
+}
+
+.coupon-info .coupon-desc {
+  font-size: 0.9rem;
+  color: #9b9b9b;
+  list-style: outside;
+  padding: 4px 0 8px 0;
+}
+

+ 532 - 0
wx-mall-hk/pages/goods/goods.js

@@ -0,0 +1,532 @@
+var app = getApp();
+var WxParse = require('../../lib/wxParse/wxParse.js');
+var util = require('../../utils/util.js');
+var api = require('../../config/api.js');
+var goodsUtil = require('../../utils/goods.js');
+
+Page({
+  data: {
+    winHeight: "",
+    id: 0,
+    referrer: 0,
+    goods: {},
+    gallery: [],
+    attribute: [],
+    issueList: [],
+    comment: [],
+    brand: {},
+    specificationList: [],
+    productList: [],
+    relatedGoods: [],
+    cartGoodsCount: 0,
+    userHasCollect: 0,
+    crashList: {},
+    number: 1,
+    checkedSpecText: '请选择规格数量',
+    openAttr: false,
+    noCollectImage: "/static/images/icon_collect.png",
+    hasCollectImage: "/static/images/icon_collect_checked.png",
+    collectBackImage: "/static/images/icon_collect.png",
+    showNavList: false,
+    stockNum: '',
+    cartNumber: 0,
+    autoplay: false,
+    defaultFreight: 0,
+    current: 0,//banner当前的index
+    isPlay: true,
+    indexNum: 0,
+    windowWidth: 0,
+    leftWidth: 0,
+    startX:0,
+    curr_id: '',
+    videoHiddenName: true,
+    imgHiddenName: false
+  },
+  toggleNav() {
+    this.setData({
+      showNavList: !this.data.showNavList
+    })
+  },
+  switchNav(event) {
+    let name = event.currentTarget.dataset.name;
+    wx.switchTab({
+      url: `/pages/${name}/${name}`,
+    });
+  },
+  getGoodsInfo: function () {
+    wx.showLoading({
+      title: '加载中...',
+    });
+    let that = this;
+    util.request(api.GoodsDetail, { id: that.data.id, referrer: this.data.referrer, 
+      merchSn: wx.getStorageSync('merchSn') }).then(function (res) {
+      if (res.errno === 0) {
+        that.setData({
+          goods: res.data.info,
+          gallery: res.data.gallery,
+          attribute: res.data.attribute,
+          issueList: res.data.issue,
+          comment: res.data.comment,
+          brand: res.data.brand,
+          specificationList: res.data.specificationList,
+          productList: res.data.productList,
+          userHasCollect: res.data.userHasCollect,
+          stockNum: res.data.stockNum,
+          cartNumber: res.data.cartNumber,
+          defaultFreight: res.data.defaultFreight,
+          checkedSpecText: res.data.specificationList[0].valueList[0].value
+        });
+
+        if (res.data.userHasCollect == 1) {
+          that.setData({
+            'collectBackImage': that.data.hasCollectImage
+          });
+        } else {
+          that.setData({
+            'collectBackImage': that.data.noCollectImage
+          });
+        }
+
+        WxParse.wxParse('goodsDetail', 'html', res.data.info.goods_desc, that);
+
+        that.getGoodsRelated();
+
+        that.getGoodsCrashList();
+
+        //
+        let _specificationList = that.data.specificationList;
+        for (let i = 0; i < _specificationList.length; i++) {
+          if (_specificationList[i].valueList.length == 1) {
+            //如果已经选中,则反选,前端默认选中
+            _specificationList[i].valueList[0].checked = true;
+          }
+        }
+        that.setData({
+          'specificationList': _specificationList
+        });
+        }
+        wx.hideLoading();
+    });
+    if (null != that.data.referrer && that.data.referrer > 0) {
+      util.request(api.GoodsTransferCoupon, {
+        goods_id: that.data.id,
+        referrer: that.data.referrer, send_type: 2
+      }).then(function (res) {
+
+      });
+    }
+    util.request(api.GoodsGallery, {
+      goods_id: that.data.id
+    }).then(function (res) {
+      if (res.errno === 0) {
+        that.setData({
+          gallery: res.data
+        })
+      }
+      ;
+    });
+  },
+
+  getGoodsCrashList: function () {
+    let that = this;
+    util.request(api.GoodsCrashList, { goodsId: that.data.id }).then(function (res) {
+      if (res.errno === 0) {
+        that.setData({
+          crashList: res.data,
+        });
+        that.data.crashList.length;
+      }
+    });
+  },
+
+  getGoodsRelated: function () {
+    let that = this;
+    util.request(api.GoodsRelated, { id: that.data.id }).then(function (res) {
+      if (res.errno === 0) {
+        that.setData({
+          relatedGoods: res.data.goodsList,
+        });
+      }
+    });
+
+  },
+  clickSkuValue: function (event) {
+    let that = this;
+    let specNameId = event.currentTarget.dataset.nameId;
+    let specValueId = event.currentTarget.dataset.valueId;
+
+    //
+    let _specificationList = this.data.specificationList;
+    for (let i = 0; i < _specificationList.length; i++) {
+      if (_specificationList[i].specification_id == specNameId) {
+        for (let j = 0; j < _specificationList[i].valueList.length; j++) {
+          if (_specificationList[i].valueList[j].id == specValueId) {
+            //如果已经选中,则反选
+            if (_specificationList[i].valueList[j].checked) {
+              _specificationList[i].valueList[j].checked = false;
+            } else {
+              _specificationList[i].valueList[j].checked = true;
+            }
+          } else {
+            _specificationList[i].valueList[j].checked = false;
+          }
+        }
+      }
+    }
+    this.setData({
+      'specificationList': _specificationList
+    });
+    //重新计算spec改变后的信息
+    goodsUtil.changeSpecInfo(that);
+  },
+  onLoad: function (options) {
+    // 页面初始化 options为页面跳转所带来的参数
+    this.setData({
+      id: parseInt(options.id)
+      // id: 1181000
+    });
+    var that = this;
+    this.getGoodsInfo();
+    util.request(api.CartGoodsCount).then(function (res) {
+      if (res.errno === 0) {
+        that.setData({
+          cartGoodsCount: res.data.cartTotal.goodsCount
+        });
+
+      }
+    });
+    var that = this;
+    //  高度自适应
+    wx.getSystemInfo({
+        success: function (res) {
+            var clientHeight = res.windowHeight,
+                clientWidth = res.windowWidth,
+                rpxR = 750 / clientWidth;
+            var calc = clientHeight * rpxR - 100;
+            // console.log(calc);
+            that.setData({
+              winHeight: calc,
+              windowWidth: res.windowWidth
+            });
+        }
+    });
+  },
+  onReady: function () {
+    let that = this;
+    this.videoContext = wx.createVideoContext('myVideo');
+    // 页面渲染完成
+    // wx.setClipboardData({
+    //     data: '/pages/goods/goods?id=' + that.data.id,
+    //     success: function (res) {
+    //         wx.getClipboardData({
+    //             success: function (res) {
+    //                 // console.log(res.data) // data
+    //             }
+    //         })
+    //     }
+    // })
+  },
+  //购物车增加
+  addNumber2: function (e) {
+    let that = this;
+    var goodsId = e.currentTarget.dataset.goodsId;
+    var productId = e.currentTarget.dataset.productId;
+    var hotGoods = that.data.hotGoods;
+    util.request(api.CartAdd, { goodsId: goodsId, productId: productId, number: 1 }, 'POST').then(function (res) {
+      if (res.errno === 0 && null != res.data) {
+        util.request(api.CartGoodsCount).then(function (res) {
+          if (res.errno === 0) {
+            that.setData({
+              cartGoodsCount: res.data.cartTotal.goodsCount
+            });
+
+          }
+        });
+        wx.showToast({
+          title: '添加成功',
+          icon: 'success',
+          mask: true
+        });
+      } else {
+        util.showErrorToast(res.errmsg)
+      }
+    });
+  },
+  onShow: function () {
+    // 页面显示
+
+  },
+  onHide: function () {
+    // 页面隐藏
+
+  },
+  onUnload: function () {
+    // 页面关闭
+
+  },
+  switchAttrPop: function () {
+    this.setData({
+      openAttr: !this.data.openAttr
+    })
+  },  
+  hideSwitchAttrPop: function() {
+    this.setData({
+      openAttr: false
+    })
+  },
+  changeProperty: function (e) {
+    var propertyName = e.currentTarget.dataset.propertyName;
+    console.log(propertyName);
+  },
+  closeAttrOrCollect: function () {
+    let that = this;
+    //添加或是取消收藏
+    util.request(api.CollectAddOrDelete, { typeId: 0, valueId: this.data.id }, "POST")
+      .then(function (res) {
+        let _res = res;
+        if (_res.errno == 0) {
+          if (_res.data.type == 'add') {
+            that.setData({
+              'collectBackImage': that.data.hasCollectImage
+            });
+            wx.showToast({
+              title: "收藏成功",
+              mask: true
+            });
+          } else {
+            that.setData({
+              'collectBackImage': that.data.noCollectImage
+            });
+            wx.showToast({
+              title: "收藏取消",
+              mask: true
+            });
+          }
+
+        } else {
+          wx.showToast({
+            image: '/static/images/icon_error.png',
+            title: _res.errmsg,
+            mask: true
+          });
+        }
+
+      });
+  },
+  openCartPage: function () {
+    wx.switchTab({
+      url: '/pages/cart/cart',
+    });
+  },
+  addToCart: function () {
+    var that = this;
+    if (this.data.openAttr == false) {
+      //打开规格选择窗口
+      this.setData({
+        openAttr: !this.data.openAttr
+      });
+    } else {
+
+      //提示选择完整规格
+      if (!goodsUtil.isCheckedAllSpec(that)) {
+        return false;
+      }
+
+      if (that.data.number + that.data.cartNumber > that.data.stockNum){
+        // wx.showToast({
+        //   title: '库存不足',
+        //   mask: true
+        // });
+        util.showErrorToast('库存不足');
+        //找不到对应的product信息,提示没有库存
+        return false;
+      }
+
+      // //根据选中的规格,判断是否有对应的sku信息
+      let checkedProduct = goodsUtil.getCheckedProductItem(goodsUtil.getCheckedSpecKey(that), that);
+      if (!checkedProduct || checkedProduct.length <= 0) {
+        wx.showToast({
+          title: '库存不足',
+          icon: 'none'
+        });
+        //找不到对应的product信息,提示没有库存
+        return false;
+      }
+
+      //验证库存
+      // if (checkedProduct.goods_number < this.data.number) {
+      //   //找不到对应的product信息,提示没有库存
+      //   return false;
+      // }
+
+      //添加到购物车
+      util.request(api.CartAdd, {
+        goodsId: this.data.goods.id,
+        number: this.data.number,
+        productId: checkedProduct[0].id
+      }, "POST")
+        .then(function (res) {
+          let _res = res;
+          if (_res.errno == 0) {
+            wx.showToast({
+              title: '添加成功'
+            });
+            that.setData({
+              openAttr: !that.data.openAttr,
+              cartGoodsCount: _res.data.cartTotal.goodsCount
+            });
+            if (that.data.userHasCollect == 1) {
+              that.setData({
+                'collectBackImage': that.data.hasCollectImage
+              });
+            } else {
+              that.setData({
+                'collectBackImage': that.data.noCollectImage
+              });
+            }
+          } else {
+            wx.showToast({
+              title: _res.errmsg,
+              icon: 'none'
+            })
+            that.hideSwitchAttrPop();
+            that.setData({
+              stockNum: 0
+            });
+          }
+        });
+
+    }
+  },
+  cutNumber: function () {
+    this.setData({
+      number: (this.data.number - 1 > 1) ? this.data.number - 1 : 1
+    });
+  },
+  addNumber: function () {
+    this.setData({
+      number: this.data.number + 1
+    });
+  },
+  onShareAppMessage: function () {
+    var that = this;
+    // console.log("url:" + that.data.goods.list_pic_url);
+    // var userId = wx.getStorageSync('userId');
+    // console.log("userId:" + userId);
+    return {
+      title: '商业版',
+      desc: null != that.data.goods.name ? that.data.goods.name : "商业版",
+      imageUrl: that.data.goods.list_pic_url,
+      path: '/pages/goods/goods?id=' + that.data.id + '&&referrer=' + wx.getStorageSync('userId'),
+      success: function (res) {
+        console.log("转发成功");
+        // 转发成功
+      },
+      fail: function (res) {
+        // 转发失败
+        console.log("转发失败");
+      }
+    }
+  },
+  //购物车增加
+  addCrashNumber: function (e) {
+    let that = this;
+    var goodsId = e.currentTarget.dataset.goodsId;
+    var productId = e.currentTarget.dataset.productId;
+    util.request(api.CartAdd, { goodsId: goodsId, productId: productId, number: 1 }, 'POST').then(function (res) {
+      if (res.errno === 0 && null != res.data) {
+        var hotGoods = that.data.hotGoods;
+        hotGoods.forEach(function (val, index, arr) {
+          if (val.id == goodsId) {
+            val.cart_num = res.data;
+            hotGoods[index] = val;
+            that.setData({ hotGoods: hotGoods });
+          }
+        }, that);
+      }
+    });
+  },
+  previewPic(e) {
+    let url = e.currentTarget.dataset.url;
+    let urls = [];
+    urls[0] = url;
+    wx.previewImage({
+      urls
+    })
+  },
+  switchNav(event) {
+    wx.switchTab({
+      url: '/pages/index/index'
+    });
+  },
+  //触摸事件start
+  touchStart(e) {
+    let startX = e.changedTouches[0].pageX
+    this.setData({
+      startX: startX
+    })
+    console.log("startX:" + startX);
+  },
+
+  //触摸事件end
+  touchEnd(e) {
+    let _self = this;
+    let windowWidth = this.data.windowWidth;
+    let moveWidth = e.changedTouches[0].pageX - this.data.startX;
+    let defineWidth = windowWidth / 20;
+    let rankList = this.data.gallery;
+    let index_now = e.currentTarget.dataset.index;
+    if (moveWidth >= defineWidth) {
+      //上一张
+      let transWidth = (index_now - 1) * (-this.data.windowWidth);
+      if (index_now >= 1) {
+        this.setData({
+          indexNum: index_now - 1,
+          rankList: rankList,
+          leftWidth: transWidth
+        })
+      }
+    } else if (moveWidth <= (0 - defineWidth)) {
+      //下一张
+      this.videoContext.pause();
+      let transWidth = (index_now + 1) * (-this.data.windowWidth);
+      if (index_now < rankList.length - 1) {
+        this.setData({
+          indexNum: index_now + 1,
+          rankList: rankList,
+          leftWidth: transWidth
+        })
+      }
+    } else {
+      //console.log('不能修改样式')
+    }
+  },
+  videoPlay(e) {
+    // if (this.data.curr_id == e.currentTarget.dataset.id) {
+    //   this.setData({
+    //     curr_id: 0,
+    //   })
+    // } else {
+    //   this.setData({
+    //     curr_id: e.currentTarget.dataset.id,
+    //   })
+    // }
+    this.setData({
+      imgHiddenName: true,
+      videoHiddenName: false
+    })
+    this.videoContext.play();
+  },
+  //触摸事件start
+  touchStart2(e) {
+    
+  },
+  touchEnd2(e) {
+    this.setData({
+      curr_id: 0,
+      imgHiddenName: false,
+      videoHiddenName: true
+    })
+    this.videoContext.pause();
+  }
+})

+ 1 - 0
wx-mall-hk/pages/goods/goods.json

@@ -0,0 +1 @@
+{}

+ 300 - 0
wx-mall-hk/pages/goods/goods.wxml

@@ -0,0 +1,300 @@
+<scroll-view class="container" style="height: {{winHeight}}rpx" scroll-y="true">
+  <view wx:if="{{showNavList}}" class="modal-wrap"></view>
+  <view class="fast-nav">
+    <contact-button wx:if="{{!showNavList}}" class="contact" size="25" type="primary" session-from="weapp">
+      <text>找客服</text>
+    </contact-button>
+    <view wx:if="{{!showNavList}}" class="nav" bindtap="toggleNav">
+      <text>快捷</text>
+      <text>导航</text>
+    </view>
+    <view class="nav-list" wx:if="{{showNavList}}">
+      <view class="nav-item">
+        <text class="nav-text">首页</text>
+        <view class="nav-cell" bindtap="switchNav" data-name="index">
+          <image src="../../static/images/nav-1.png"></image>
+        </view>
+      </view>
+      <view class="nav-item">
+        <text class="nav-text">足迹</text>
+        <navigator class="nav-cell" url="../ucenter/footprint/footprint">
+          <image src="../../static/images/nav-2.png"></image>
+        </navigator>
+      </view>
+      <view class="nav-item">
+        <text class="nav-text">搜索</text>
+        <navigator class="nav-cell" url="../search/search">
+          <image src="../../static/images/nav-3.png"></image>
+        </navigator>
+      </view>
+      <view class="nav-item">
+        <text class="nav-text">购物车</text>
+        <view class="nav-cell" bindtap="openCartPage" data-name="cart">
+          <image src="../../static/images/nav-4.png"></image>
+        </view>
+      </view>
+    </view>
+    <view wx:if="{{showNavList}}" class="close" bindtap="toggleNav">X</view>
+  </view>
+  <view>   
+  <!-- 滚动的卡片布局 -->
+  <view class='goodsimgs' bindtap="hideSwitchAttrPop">
+    <view class='content-wrapper'>
+      <view class='scroll-wrapper'>
+        <scroll-view class='scroll-view'>
+          <view class="items-wrapper" style="transform:translate3d({{leftWidth}}px, 0, 0)">
+          <!-- 循环商品图开始 -->
+            <view wx:for="{{gallery}}" wx:key="index" data-index="{{index}}" class="item" bindtouchstart='touchStart' bindtouchend='touchEnd'>
+              <view class='rank-num' style="background-color: #c8c8c8">{{index+1}}/{{gallery.length}}</view>
+              <view class='img-wrapper'>
+              <!-- 视频播放开始 -->
+              <view class="video2" data-id="{{item.id}}" bindtap="videoPlay" wx:if="{{item.file_type == 1}}">
+                <view hidden="{{videoHiddenName}}">
+                <video id="myVideo" style="width: 750rpx;height: calc(9 * 750rpx / 16);" src="{{item.img_url}}" objectFit="cover" show-center-play-btn enable-progress-gesture  controls></video>
+                  </view>
+
+                <view style="width: 750rpx;height: calc(9 * 750rpx / 16);" hidden="{{imgHiddenName}}">
+                  <image class="model-img" style="width: 750rpx;height: calc(9 * 750rpx / 16);background-size:650rpx 321rpx;" mode="aspectFill" src="{{gallery[1].img_url}}" background-size="cover"></image>
+                  <view class="model-btn">
+                    <view class="play-icon"></view>
+                  </view>
+                </view>
+              </view>
+              <!-- 视频播放结束 -->
+              <view wx:else >
+                <image src="{{item.img_url}}" class="imageClass" mode='aspectFill' catchtap='preview' data-url="{{item.img_url}}"/>
+              </view>
+              </view>
+              
+            </view>
+            <!-- 循环商品图结束 -->
+          </view>
+    </scroll-view>
+  </view>
+</view>
+</view>
+      <!-- <swiper indicator-dots indicator-color="{{indicator}}" current="{{current}}" indicator-active-color="{{activeIndicator}}" class="goodsimgs" duration="300">  
+        <block wx:for="{{gallery}}" wx:key="item.id">  
+          <swiper-item>  
+            <block wx:if="{{item.file_type == 1}}">  
+              <block wx:if="{{isPlay}}" class='video-wrapper'>  
+                <video src="{{item.img_url}}" class='video' id='myVideo' binderror="videoErrorCallback" initial-time='2' show-center-play-btn enable-progress-gesture controls></video>  
+              </block>  
+              <block wx:else class='video-host-wrapper' catchtap='play'>  
+                <image src="{{gallery[1].img_url}}" mode='aspectFill' />
+              </block>  
+            </block>
+            <block wx:else>
+              <image src="{{item.img_url}}" mode='aspectFill' catchtap='preview' data-url="{{item.img_url}}" />
+            </block>
+          </swiper-item>  
+        </block>  
+      </swiper> -->
+    <!-- <swiper class="goodsimgs" indicator-dots="true" autoplay="{{autoplay}}" bindtap="hideSwitchAttrPop"> 
+      <swiper-item wx:for="{{gallery}}" wx:key="{{item.id}}">
+        <video wx:if="{{item.file_type==1}}" id="myVideo" style='height:400rpx;width:100%;margin-top:140rpx;'  src="{{item.img_url}}" binderror="videoErrorCallback" objectFit="cover" initial-time='2' show-center-play-btn enable-progress-gesture controls></video>
+        <image class="imageClass" wx:if="{{item.file_type==0}}" src="{{item.img_url}}"></image>
+      </swiper-item>
+    </swiper> -->
+  
+    <!-- <view class="service-policy">
+      <view class="item">30分钟速达</view>
+      <view class="item">每日优选生鲜</view>
+      <view class="item">满88元免运费</view>
+    </view> -->
+    <view class="goods-info" bindtouchstart='touchStart2' bindtouchend='touchEnd2'>
+      <view class="c" bindtap="hideSwitchAttrPop">
+        <view class="goods-do">
+          <text class="price">{{goods.retail_price?"¥"+goods.retail_price:"¥0"}}</text>
+          <text class="org-price line-through">{{goods.market_price?"¥"+goods.market_price:""}}</text>
+        </view>
+        <text class="name">{{goods.name?goods.name:""}}</text>
+        <!-- <text class="desc">{{goods.goods_brief?goods.goods_brief:""}}</text> -->
+        <!-- <view class="brand" wx:if="{{brand.name}}">
+          <navigator url="../brandDetail/brandDetail?id={{brand.id}}">
+            <text>{{brand.name}}</text>
+          </navigator>
+        </view> -->
+        <view style='margin-top:20px;'>
+          <text class="desc">快递:{{defaultFreight==0?"免邮":"元"}}</text>
+          <text class="desc2">销量:{{goods.sell_volume==null?0:goods.sell_volume}}</text>
+        </view>
+      </view>
+    </view>
+    <view class="section-nav section-attr" bindtap="switchAttrPop"  wx:if="{{stockNum >0}}"  bindtouchstart='touchStart2' bindtouchend='touchEnd2'>
+      <view class="t">{{checkedSpecText=="请选择规格数量"?"请选择规格数量":"已选:【"+checkedSpecText+"】"}}</view>
+      <image class="i" src="../../static/images/address_right.png" background-size="cover"></image>
+    </view>
+
+    <view class="crash-goods" wx:if="{{crashList.length > 0}}" bindtap="hideSwitchAttrPop">
+      <view class="h">
+        <view class="line"></view>
+        <text class="title">搭配减价</text>
+      </view>
+      <view class="b">
+        <view class="item" wx:for="{{crashList}}" wx:key="{{item.id}}">
+          <navigator url="/pages/goods/goods?id={{item.goods_crash_id}}">
+            <image class="img" src="{{item.list_pic_url}}" background-size="cover"></image>
+            <text class="name">{{item.name}}</text>
+          </navigator>
+
+          <view class="goods-do">
+            <text class="price">¥{{item.market_price}}</text>
+            <text class="org-price line-through">¥{{item.retail_price}}</text>
+            <view class="add" data-goods-id="{{item.goods_crash_id}}" data-product-id="{{item.product_crash_id}}" bindtap="addCrashNumber">+</view>
+          </view>
+        </view>
+      </view>
+    </view>
+
+    <!--<view class="section-nav section-act">
+      <view class="t">
+        <view class="label">1个促销:</view>
+        <view class="tag">万圣趴</view>
+        <view class="text">全场满499,额外送糖果</view>
+      </view>
+      <image class="i" src="../../static/images/address_right.png" background-size="cover"></image>
+    </view>-->
+    <view class="comments" bindtap="hideSwitchAttrPop" bindtouchstart='touchStart2' bindtouchend='touchEnd2'>
+      <view class="h">
+        <navigator url='../comment/comment?valueId={{goods.id}}&typeId=0'>
+          <text class="t">评价({{comment.count > 999 ? '999+' : comment.count}})</text>
+          <text class="i">查看全部</text>
+        </navigator>
+      </view>
+      <view class="b">
+        <view class="item" wx:if="{{comment.count == 0}}">
+          <view class="info">
+            暂无评论
+          </view>
+        </view>
+        <view class="item" wx:if="{{comment.count > 0}}">
+          <view class="info">
+            <view class="user">
+              <image src="{{comment.data.avatar}}"></image>
+              <text>{{comment.data.nickname}}</text>
+            </view>
+            <view class="time">{{comment.data.add_time}}</view>
+          </view>
+          <view class="content">
+            {{comment.data.content}}
+          </view>
+          <view class="imgs" wx:if="{{comment.data.pic_list.length > 0}}">
+            <image class="img" data-url="{{item.pic_url}}" wx:for="{{comment.data.pic_list}}" wx:key="{{item.id}}" bindtap="previewPic" src="{{item.pic_url}}"></image>
+          </view>
+          <!-- <view class="spec">白色 2件</view> -->
+        </view>
+      </view>
+    </view>
+    <!-- <view class="comments" bindtap="hideSwitchAttrPop">
+      <view class="h">
+          <text class="t">{{goods.storeName}}</text>
+          <text class="i">全部商品</text>
+      </view>
+    </view> -->
+    <view class="goods-attr" wx:if="{{attribute.length>0}}" bindtap="hideSwitchAttrPop">
+      <view class="t">商品参数</view>
+      <view class="l">
+        <view class="item" wx:for="{{attribute}}" wx:key="{{item.name}}">
+          <text class="left">{{item.name}}</text>
+          <text class="right">{{item.value}}</text>
+        </view>
+      </view>
+    </view>
+    <view class="detail"  bindtap="hideSwitchAttrPop">
+      <view class="t">商品详情</view>
+      <import src="../../lib/wxParse/wxParse.wxml" />
+      <template is="wxParse" data="{{wxParseData:goodsDetail.nodes}}" />
+    </view>
+
+
+    <view class="common-problem" bindtap="hideSwitchAttrPop">
+      <view class="h">
+        <view class="line"></view>
+        <text class="title">常见问题</text>
+      </view>
+      <view class="b">
+        <view class="item" wx:for="{{issueList}}" wx:key="{{item.id}}">
+          <view class="question-box">
+            <text class="spot"></text>
+            <text class="question">{{item.question}}</text>
+          </view>
+          <view class="answer">
+            {{item.answer}}
+          </view>
+        </view>
+      </view>
+    </view>
+
+    <view class="related-goods" wx:if="{{relatedGoods.length > 0}}">
+      <view class="h">
+        <view class="line"></view>
+        <text class="title">大家都在看</text>
+      </view>
+      <view class="b">
+        <view class="item" wx:for="{{relatedGoods}}" wx:key="{{item.id}}">
+          <navigator url="/pages/goods/goods?id={{item.id}}">
+            <image class="img" src="{{item.list_pic_url}}"></image>
+            <text class="name">{{item.name}}</text>
+            <view class="price">¥{{item.retail_price}}
+              <image class="cart" data-goods-id="{{item.id}}" data-product-id="{{item.product_id}}" catchtap='addNumber2' src="/static/images/cart.png" background-size="cover"></image>
+            </view>
+          </navigator>
+        </view>
+      </view>
+    </view>
+
+  </view>
+  <view wx:if="{{openAttr}}" class="attr-pop">
+    <view class="attr-close" bindtap="switchAttrPop">X</view>
+    <view class="img-info">
+      <image class="img" src="{{goods.list_pic_url}}"></image>
+      <view class="info">
+        <view class="c">
+          <view class="p">价格:¥{{goods.retail_price}}</view>
+          <view class="a" wx:if="{{productList.length>0}}">已选择:{{checkedSpecText}}</view>
+          <view class="a">库存{{stockNum}}件</view>
+          
+        </view>
+      </view>
+    </view>
+    <view class="spec-con">
+      <view class="spec-item" wx:for="{{specificationList}}" wx:key="{{item.specification_id}}">
+        <view class="name">{{item.name}}</view>
+        <view class="values">        
+          <view class="value {{vitem.checked ? 'selected' : ''}}" bindtap="clickSkuValue" wx:for="{{item.valueList}}" wx:for-item="vitem" wx:key="{{vitem.id}}" data-value-id="{{vitem.id}}" data-name-id="{{vitem.specification_id}}">{{vitem.value}}</view>
+        </view>
+      </view>
+
+      <view class="number-item">
+        <view class="name">数量</view>
+        <view class="selnum">
+          <view class="cut" bindtap="cutNumber">-</view>
+          <input value="{{number}}" class="number" disabled="true" type="number" />
+          <view class="{{number+cartNumber>= stockNum? 'addEnabel':'add'}}" bindtap="{{number+cartNumber>= stockNum ? '':'addNumber'}}">+</view>
+        </view>
+      </view>
+    </view>
+  </view>
+</scroll-view>
+  <view class='shelves-view' wx:if="{{stockNum ==0 || goods.is_on_sale == 0}}">
+    <view class="shelves">
+      <text class='shelves-text'>已下架</text>
+    </view>
+  </view>
+  <view class="bottom-btn">
+    <view class="l l-home" bindtap="switchNav">
+      <image class="icon" src="/static/images/nav-1.png"></image>
+    </view>
+    <view class="l l-collect {{ openAttr ? 'back' : ''}}" bindtap="closeAttrOrCollect">
+      <image class="icon" src="{{ collectBackImage }}"></image>
+    </view>
+    <view class="l l-cart">
+      <view class="box">
+        <text class="cart-count">{{cartGoodsCount}}</text>
+        <image bindtap="openCartPage" class="icon" src="/static/images/ic_menu_shoping_nor.png"></image>
+      </view>
+    </view>
+    <!-- <view class="c">立即购买</view> -->
+    <view class='{{stockNum ==0 || goods.is_on_sale == 0?"r-disable":"r"}}' bindtap='{{stockNum ==0 || goods.is_on_sale == 0?"":"addToCart"}}'>加入购物车</view>
+  </view>

+ 1138 - 0
wx-mall-hk/pages/goods/goods.wxss

@@ -0,0 +1,1138 @@
+.container {
+  margin-bottom: 100rpx;
+}
+
+.goodsimgs {
+  position: relative;
+  width: 750rpx;
+  height: 750rpx;
+  background: #fff;
+  top:0rpx;
+}
+
+/* .goodsimgs image {
+  width: 750rpx;
+  height: 750rpx;
+}
+.goodsimgs video{
+  position: absolute;
+  display: block;
+  top:0rpx;
+  width: 750rpx;
+  height: 450rpx;
+  margin-top:150rpx;
+} */
+
+.content-wrapper {
+  /* position: fixed; */
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 2;
+  /* width: 750rpx;
+  height: 750rpx; */
+}
+.content-wrapper .overflow {
+  /* width: 750rpx;
+  height: 750rpx; */
+}
+.content-wrapper .scroll-wrapper {
+  width: 750rpx;
+  height: 750rpx;
+  overflow: hidden;
+}
+.content-wrapper .scroll-view {
+  white-space: nowrap;
+  display: block;
+  /* height: 750rpx; */
+  overflow-x: auto;
+  margin-top: -100rpx;
+  /* padding-bottom: 100rpx; */
+  -webkit-transform: translateY(100rpx);
+  transform: translateY(100rpx);
+}
+.content-wrapper .scroll-view .items-wrapper {
+  height: 750rpx;
+  box-sizing: border-box;
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -moz-box;
+  display: flex;
+  flex-flow: row nowrap;
+  -webkit-box-orient: horizontal;
+  flex-direction: row;
+  -webkit-box-align: center;
+  -webkit-align-items: center;
+  align-items: center;
+  position:relative;
+  transition:all 0.3s ease;
+  -webkit-overflow-scrolling:touch; 
+  transform: translateZ(0);
+}
+.content-wrapper .scroll-view .item {
+  display: block;
+  position: relative;
+  flex-shrink: 0;
+  transition: transform 0.2s ease;
+  transform-origin: center;
+  letter-spacing: 0;
+}
+.video2{ margin-top: 150rpx;
+	position: relative;
+}
+.model-img{
+  background-size:650rpx 321rpx;
+}
+.model-btn{
+	position:absolute;
+  left:0;
+  top:0;
+  bottom:0;
+  right:0;
+  margin:auto;
+  width:100rpx;
+  height:100rpx;
+  border-radius:50%;
+  background-color: rgba(0,0,0,.3);
+}
+.play-icon{
+    margin:28rpx 42rpx;
+    border-top:26rpx solid transparent;
+    border-left:36rpx solid #fff;
+    border-bottom:22rpx solid transparent;
+}
+.content-wrapper .scroll-view .item .img-wrapper .myVideo {
+  width: 750rpx;
+  height: calc(9 * 750rpx / 16);
+  /* left:0; */
+}
+/* .content-wrapper .scroll-view .item:nth-child(1) {
+   margin-left: 127rpx; 
+} */
+.content-wrapper .scroll-view .item .rank-num {
+  position: absolute;
+  left: 650rpx;
+  top: 680rpx;
+  padding: 0 20rpx;
+  line-height: 50rpx;
+  height: 50rpx;
+  border-radius: 8rpx;
+  color: #ffffff;
+}
+.content-wrapper .scroll-view .item .img-wrapper {
+  width: 750rpx;
+  height: 750rpx;
+  border-radius: 8rpx;
+  overflow: hidden;
+}
+.content-wrapper .scroll-view .item .img-wrapper .img {
+  display: block;
+  width: 750rpx;
+  min-height: 750rpx;
+}
+.content-wrapper .scroll-view .item .content {
+  padding: 20rpx;
+  background-color: rgba(255, 255, 255, 0.9);
+  box-sizing: border-box;
+  position: absolute;
+  right: 20rpx;
+  bottom: 20rpx;
+  left: 20rpx;
+  z-index: 2;
+  border-radius: 8rpx;
+  overflow: hidden;
+}
+.content-wrapper .scroll-view .item .content .title {
+  display: block;
+  font-size: 32rpx;
+  line-height: 44rpx;
+  color: #333333;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  margin-bottom: 10rpx;
+}
+.content-wrapper .scroll-view .item .content .rank-wrapper {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -moz-box;
+  display: flex;
+  flex-flow: row nowrap;
+  -webkit-box-orient: horizontal;
+  flex-direction: row;
+  -webkit-box-align: center;
+  -webkit-align-items: center;
+  align-items: center;
+  margin-bottom: 12rpx;
+}
+.content-wrapper .scroll-view .item .content .rank-wrapper .stars-wrapper {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -moz-box;
+  display: flex;
+  flex-flow: row nowrap;
+  -webkit-box-orient: horizontal;
+  flex-direction: row;
+  margin-right: 20rpx;
+}
+.content-wrapper .scroll-view .item .content .rank-wrapper .stars-wrapper .star {
+  display: block;
+  width: 32rpx;
+  height: 32rpx;
+}
+.content-wrapper .scroll-view .item .content .rank-wrapper .score {
+  font-size: 32rpx;
+  line-height: 44rpx;
+  color: #333333;
+}
+.content-wrapper .scroll-view .item .content .p {
+  display: block;
+  font-size: 28rpx;
+  line-height: 40rpx;
+  color: white;
+}
+
+/* 如果不为激活状态,那就添加图层蒙版  */
+.poker-face {
+ filter: brightness(40%)
+}
+
+/* 添加激活状态 */
+.active {
+  transform: scale(1.083333)
+}
+
+
+
+.imageClass{
+  background-size:600rpx 600rpx;
+  width: 750rpx;
+  height: 750rpx;
+}
+.weui-cells{
+  margin-top: 80rpx;
+  text-align: left;
+}
+.weui-label{
+  width: 5em;
+}
+
+.page-body-button {
+  margin-bottom: 30rpx;
+}
+.service-policy {
+  width: 750rpx;
+  height: 73rpx;
+  background: #f5f1f1ef;
+  padding: 0 31.25rpx;
+  display: flex;
+  flex-flow: row nowrap;
+  align-items: center;
+  justify-content: space-between;
+}
+
+.service-policy .item {
+  background: url(http://120.76.26.84:80/group1/M00/00/02/rBJEdVvr25eAGT4BAAAA2Yyhu9Q372.png) 0 center no-repeat;
+  background-size: 10rpx;
+  padding-left: 15rpx;
+  display: flex;
+  align-items: center;
+  font-size: 25rpx;
+  color: #666;
+}
+
+.goods-info {
+  width: 750rpx;
+  height: 210rpx;
+  overflow: hidden;
+  background: #fff;
+}
+
+.goods-info .c {
+  display: block;
+  width: 718.75rpx;
+  /* height: 100%; */
+  margin-left: 31.25rpx;
+  padding: 38rpx 31.25rpx 38rpx 0;
+  border-bottom: 1px solid #f4f4f4;
+}
+
+.goods-info .c text {
+  display: block;
+  /* width: 687.5rpx; */
+  text-align: left;
+  font-weight: bolder;
+}
+
+.goods-info .name {
+  height: 41rpx;
+  margin-bottom: 20rpx;
+  font-size: 30rpx;
+  line-height: 41rpx;
+  margin-top: 10rpx;
+}
+
+.goods-info .desc {
+  height: 43rpx;
+  margin-bottom: 41rpx;
+  font-size: 24rpx;
+  line-height: 36rpx;
+  color: #999;
+  width: 200rpx;
+}
+.desc2{
+  position:absolute;
+  right:220rpx;
+  top:910rpx;
+  height: 43rpx;
+  margin-bottom: 41rpx;
+  font-size: 24rpx;
+  line-height: 36rpx;
+  color: #999;
+
+}
+.goods-info .goods-do {
+  text-align:left;
+}
+
+.goods-info .goods-do .price {
+  /* height: 35rpx; */
+  font-size: 35rpx;
+  line-height: 35rpx;
+  color: #b4282d;
+  display: inline;
+  text-align: left;
+}
+
+.goods-info .goods-do .org-price {
+  /* height: 25rpx; */
+  font-size: 25rpx;
+  line-height: 35rpx;
+  color: #303030;
+  display: inline;
+  text-align: left;
+}
+
+.goods-info .brand {
+  margin-top: 23rpx;
+  min-height: 40rpx;
+  text-align: center;
+}
+
+.goods-info .brand text {
+  display: inline-block;
+  width: auto;
+  padding: 2px 30rpx 2px 10.5rpx;
+  line-height: 35.5rpx;
+  border: 1px solid #f48f18;
+  font-size: 25rpx;
+  color: #f48f18;
+  border-radius: 4px;
+  background: url(http://120.76.26.84:80/group1/M00/00/02/rBJEdVvr28mAes5qAAABHjRl7xw575.png) 95% center no-repeat;
+  background-size: 10.75rpx 18.75rpx;
+}
+
+.section-nav {
+  width: 750rpx;
+  height: 108rpx;
+  background: #fff;
+  margin-bottom: 20rpx;
+}
+
+.section-nav .t {
+  float: left;
+  width: 600rpx;
+  height: 108rpx;
+  line-height: 108rpx;
+  font-size: 29rpx;
+  color: #333;
+  margin-left: 31.25rpx;
+}
+
+.section-nav .i {
+  float: right;
+  width: 52rpx;
+  height: 52rpx;
+  margin-right: 16rpx;
+  margin-top: 28rpx;
+}
+
+.section-act .t {
+  float: left;
+  display: flex;
+  align-items: center;
+  width: 600rpx;
+  height: 108rpx;
+  overflow: hidden;
+  line-height: 108rpx;
+  font-size: 29rpx;
+  color: #999;
+  margin-left: 31.25rpx;
+}
+
+.section-act .label {
+  color: #999;
+}
+
+.section-act .tag {
+  display: flex;
+  align-items: center;
+  padding: 0 10rpx;
+  border-radius: 3px;
+  height: 37rpx;
+  width: auto;
+  color: #f48f18;
+  overflow: hidden;
+  border: 1px solid #f48f18;
+  font-size: 25rpx;
+  margin: 0 10rpx;
+}
+
+.section-act .text {
+  display: flex;
+  align-items: center;
+  height: 37rpx;
+  width: auto;
+  overflow: hidden;
+  color: #f48f18;
+  font-size: 29rpx;
+}
+
+.comments {
+  width: 100%;
+  height: auto;
+  padding-left: 30rpx;
+  background: #fff;
+  margin: 20rpx 0;
+}
+
+.comments .h {
+  height: 102.5rpx;
+  line-height: 100.5rpx;
+  width: 718.75rpx;
+  padding-right: 16rpx;
+  border-bottom: 1px solid #d9d9d9;
+}
+
+.comments .h .t {
+  display: block;
+  float: left;
+  width: 50%;
+  font-size: 38.5rpx;
+  color: #333;
+}
+
+.comments .h .i {
+  display: block;
+  float: right;
+  width: 164rpx;
+  height: 100.5rpx;
+  line-height: 100.5rpx;
+  background: url(http://120.76.26.84:80/group1/M00/00/02/rBJEdVvr2_OAO7zoAAABG9E7g8o485.png) right center no-repeat;
+  background-size: 52rpx;
+}
+
+.comments .b {
+  height: auto;
+  width: 720rpx;
+}
+
+.comments .item {
+  height: auto;
+  width: 720rpx;
+  overflow: hidden;
+}
+
+.comments .info {
+  height: 127rpx;
+  width: 100%;
+  padding: 33rpx 0 27rpx 0;
+}
+
+.comments .user {
+  float: left;
+  width: auto;
+  height: 67rpx;
+  line-height: 67rpx;
+  font-size: 0;
+}
+
+.comments .user image {
+  float: left;
+  width: 67rpx;
+  height: 67rpx;
+  margin-right: 17rpx;
+  border-radius: 50%;
+}
+
+.comments .user text {
+  display: inline-block;
+  width: auto;
+  height: 66rpx;
+  overflow: hidden;
+  font-size: 29rpx;
+  line-height: 66rpx;
+}
+
+.comments .time {
+  display: block;
+  float: right;
+  width: auto;
+  height: 67rpx;
+  line-height: 67rpx;
+  color: #7f7f7f;
+  font-size: 25rpx;
+  margin-right: 30rpx;
+}
+
+.comments .content {
+  width: 720rpx;
+  padding-right: 30rpx;
+  line-height: 45.8rpx;
+  font-size: 29rpx;
+  margin-bottom: 24rpx;
+}
+
+.comments .imgs {
+  width: 720rpx;
+  height: auto;
+  margin-bottom: 25rpx;
+}
+
+.comments .imgs .img {
+  height: 150rpx;
+  width: 150rpx;
+  margin-right: 28rpx;
+}
+
+.comments .spec {
+  width: 720rpx;
+  padding-right: 30rpx;
+  line-height: 30rpx;
+  font-size: 24rpx;
+  color: #999;
+  margin-bottom: 30rpx;
+}
+
+.goods-attr {
+  width: 750rpx;
+  height: auto;
+  overflow: hidden;
+  padding: 0 31.25rpx 25rpx 31.25rpx;
+  background: #fff;
+}
+
+.goods-attr .t {
+  width: 687.5rpx;
+  height: 104rpx;
+  line-height: 104rpx;
+  font-size: 38.5rpx;
+}
+
+.goods-attr .item {
+  width: 687.5rpx;
+  height: 68rpx;
+  padding: 11rpx 20rpx;
+  margin-bottom: 11rpx;
+  background: #f7f7f7;
+  font-size: 38.5rpx;
+}
+
+.goods-attr .left {
+  float: left;
+  font-size: 25rpx;
+  width: 134rpx;
+  height: 45rpx;
+  line-height: 45rpx;
+  overflow: hidden;
+  color: #999;
+}
+
+.goods-attr .right {
+  float: left;
+  font-size: 26rpx;
+  margin-left: 20rpx;
+  width: 480rpx;
+  height: 45rpx;
+  line-height: 45rpx;
+  overflow: hidden;
+  color: #333;
+}
+
+.detail {
+  width: 750rpx;
+  height: auto;
+  overflow: hidden;
+
+  padding: 0 31.25rpx 25rpx 31.25rpx;
+  background: #fff;
+}
+
+.detail image {
+  width: 750rpx;
+  display: block;
+}
+
+.common-problem {
+  width: 750rpx;
+  height: auto;
+  overflow: hidden;
+}
+
+.common-problem .h {
+  position: relative;
+  height: 145.5rpx;
+  width: 750rpx;
+  padding: 56.25rpx 0;
+  background: #fff;
+  text-align: center;
+}
+
+.common-problem .h .line {
+  display: inline-block;
+  position: absolute;
+  top: 72rpx;
+  left: 0;
+  z-index: 2;
+  height: 1px;
+  margin-left: 225rpx;
+  width: 300rpx;
+  background: #ccc;
+}
+
+.common-problem .h .title {
+  display: inline-block;
+  position: absolute;
+  top: 56.125rpx;
+  left: 0;
+  z-index: 3;
+  height: 33rpx;
+  margin-left: 285rpx;
+  width: 180rpx;
+  background: #fff;
+}
+
+.common-problem .b {
+  width: 750rpx;
+  height: auto;
+  overflow: hidden;
+  padding: 0rpx 30rpx;
+  background: #fff;
+}
+
+.common-problem .item {
+  height: auto;
+  overflow: hidden;
+  padding-bottom: 25rpx;
+}
+
+.common-problem .question-box .spot {
+  float: left;
+  display: block;
+  height: 8rpx;
+  width: 8rpx;
+  background: #b4282d;
+  border-radius: 50%;
+  margin-top: 11rpx;
+}
+
+.common-problem .question-box .question {
+  float: left;
+  line-height: 30rpx;
+  padding-left: 8rpx;
+  display: block;
+  font-size: 26rpx;
+  padding-bottom: 15rpx;
+  color: #303030;
+}
+
+.common-problem .answer {
+  line-height: 36rpx;
+  padding-left: 16rpx;
+  font-size: 26rpx;
+  color: #787878;
+}
+
+.related-goods {
+  width: 750rpx;
+  height: auto;
+  overflow: hidden;
+}
+
+.related-goods .h {
+  position: relative;
+  height: 145.5rpx;
+  width: 750rpx;
+  padding: 56.25rpx 0;
+  background: #fff;
+  text-align: center;
+  border-bottom: 1px solid #f4f4f4;
+}
+
+.related-goods .h .line {
+  display: inline-block;
+  position: absolute;
+  top: 72rpx;
+  left: 0;
+  z-index: 2;
+  height: 1px;
+  margin-left: 225rpx;
+  width: 300rpx;
+  background: #ccc;
+}
+
+.related-goods .h .title {
+  display: inline-block;
+  position: absolute;
+  top: 56.125rpx;
+  left: 0;
+  z-index: 3;
+  height: 33rpx;
+  margin-left: 285rpx;
+  width: 180rpx;
+  background: #fff;
+}
+
+.related-goods .b {
+  width: 750rpx;
+  height: auto;
+  overflow: hidden;
+}
+
+.related-goods .b .item {
+  float: left;
+  background: #fff;
+  width: 375rpx;
+  height: auto;
+  overflow: hidden;
+  text-align: center;
+  padding: 15rpx 31.25rpx;
+  border-right: 1px solid #f4f4f4;
+  border-bottom: 1px solid #f4f4f4;
+}
+
+.related-goods .item .img {
+  width: 311.45rpx;
+  height: 311.45rpx;
+  background-size:211rpx 211rpx;
+}
+
+.related-goods .item .name {
+  display: block;
+  width: 311.45rpx;
+  margin: 11.5rpx 0 15rpx 0;
+  text-align: center;
+  font-size: 30rpx;
+  color: #333;
+}
+
+.related-goods .item .price {
+  width: 311.45rpx;
+  text-align: center;
+  font-size: 30rpx;
+  color: #b4282d;
+}
+
+.related-goods .item .price .cart{
+  margin-left: 20rpx;
+  width: 35rpx;
+  height: 35rpx;
+  vertical-align: -6rpx;
+}
+
+.bottom-btn {
+  position: fixed;
+  left: 0;
+  bottom: 0;
+  z-index: 10;
+  width: 750rpx;
+  height: 100rpx;
+  display: flex;
+  background: #fff;
+}
+
+.bottom-btn .l {
+  float: left;
+  height: 100rpx;
+  width: 122rpx;
+  border: 1px solid #f4f4f4;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.bottom-btn .l.l-home {
+  border-right: none;
+  border-left: none;
+  text-align: center;
+}
+
+.bottom-btn .l.l-collect {
+  border-right: none;
+  border-left: none;
+  text-align: center;
+}
+
+.bottom-btn .l.l-cart .box {
+  position: relative;
+  height: 60rpx;
+  width: 60rpx;
+}
+
+.bottom-btn .l.l-cart .cart-count {
+  height: 28rpx;
+  width: 28rpx;
+  z-index: 10;
+  position: absolute;
+  top: 0;
+  right: 0;
+  background: #b4282d;
+  text-align: center;
+  font-size: 18rpx;
+  color: #fff;
+  line-height: 28rpx;
+  border-radius: 50%;
+}
+
+.bottom-btn .l.l-cart .icon {
+  position: absolute;
+  top: 10rpx;
+  left: 0;
+}
+
+.bottom-btn .l .icon {
+  display: block;
+  height: 44rpx;
+  width: 44rpx;
+}
+
+.bottom-btn .c {
+  float: left;
+  height: 100rpx;
+  line-height: 96rpx;
+  flex: 1;
+  text-align: center;
+  color: #333;
+  border-top: 1px solid #f4f4f4;
+  border-bottom: 1px solid #f4f4f4;
+}
+
+.bottom-btn .contact {
+  float: left;
+  height: 100rpx;
+  width: 122rpx;
+  border: 1px solid #f4f4f4;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.bottom-btn .r {
+  border: 1px solid #b4282d;
+  background: #b4282d;
+  float: left;
+  height: 100rpx;
+  line-height: 96rpx;
+  flex: 1;
+  text-align: center;
+  color: #fff;
+}
+@import "../../lib/wxParse/wxParse.wxss";
+
+.bottom-btn .r-disable {
+  border: 1px solid #c57477;
+  background: #c57477;
+  float: left;
+  height: 100rpx;
+  line-height: 96rpx;
+  flex: 1;
+  text-align: center;
+  color: rgb(248, 206, 206);
+}
+.attr-pop {
+  width: 100%;
+  height: auto;
+  padding: 31.25rpx;
+  background: #fff;
+  position: fixed;
+  bottom: 100rpx;
+  z-index: 500;
+}
+
+.attr-close{
+  float: right;
+  width: 40rpx;
+  height: 40rpx;
+  line-height: 40rpx;
+  border-radius: 50%;
+  font-size: 40rpx;
+  text-align: center;
+  overflow: hidden;
+}
+
+.attr-pop .img-info {
+  width: 687.5rpx;
+  height: 177rpx;
+  overflow: hidden;
+  margin-bottom: 41.5rpx;
+}
+
+.attr-pop .img {
+  float: left;
+  height: 177rpx;
+  width: 177rpx;
+  background: #f4f4f4;
+  margin-right: 31.25rpx;
+}
+
+.attr-pop .info {
+  float: left;
+  height: 177rpx;
+  display: flex;
+  align-items: center;
+}
+
+.attr-pop .p {
+  font-size: 33rpx;
+  color: #333;
+  height: 33rpx;
+  line-height: 33rpx;
+  margin-bottom: 10rpx;
+}
+
+.attr-pop .a {
+  font-size: 29rpx;
+  color: #333;
+  height: 40rpx;
+  line-height: 40rpx;
+  width: 260px;
+  display:block;
+  word-break: break-all;
+  word-wrap: break-word;
+}
+
+.spec-con {
+  width: 100%;
+  height: auto;
+  overflow: hidden;
+}
+
+.spec-con .name {
+  height: 32rpx;
+  margin-bottom: 22rpx;
+  font-size: 29rpx;
+  color: #333;
+}
+
+.spec-con .values {
+  height: auto;
+  margin-bottom: 31.25rpx;
+  font-size: 0;
+}
+
+.spec-con .value {
+  display: inline-block;
+  height: 62rpx;
+  padding: 0 35rpx;
+  line-height: 56rpx;
+  text-align: center;
+  margin-right: 25rpx;
+  margin-bottom: 16.5rpx;
+  border: 1px solid #333;
+  font-size: 25rpx;
+  color: #333;
+}
+
+.spec-con .value.disable {
+  border: 1px solid #ccc;
+  color: #ccc;
+}
+
+.spec-con .value.selected {
+  border: 1px solid #b4282d;
+  color: #b4282d;
+}
+
+.number-item .selnum {
+  width: 322rpx;
+  height: 71rpx;
+  border: 1px solid #ccc;
+  display: flex;
+}
+
+.number-item .cut {
+  width: 93.75rpx;
+  height: 100%;
+  text-align: center;
+  line-height: 65rpx;
+}
+
+.number-item .number {
+  flex: 1;
+  height: 100%;
+  text-align: center;
+  line-height: 68.75rpx;
+  border-left: 1px solid #ccc;
+  border-right: 1px solid #ccc;
+  float: left;
+}
+
+.number-item .add {
+  width: 93.75rpx;
+  height: 100%;
+  text-align: center;
+  line-height: 65rpx;
+}
+.number-item .addEnabel {
+  width: 93.75rpx;
+  height: 100%;
+  text-align: center;
+  line-height: 65rpx;
+  color: #ccc;
+}
+
+.line-through {
+  text-decoration: line-through;
+}
+
+.crash-goods {
+  width: 750rpx;
+  height: auto;
+  overflow: hidden;
+}
+
+.crash-goods .h {
+  position: relative;
+  height: 145.5rpx;
+  width: 750rpx;
+  padding: 56.25rpx 0;
+  background: #fff;
+  text-align: center;
+  border-bottom: 1px solid #f4f4f4;
+}
+
+.crash-goods .h .line {
+  display: inline-block;
+  position: absolute;
+  top: 72rpx;
+  left: 0;
+  z-index: 2;
+  height: 1px;
+  margin-left: 225rpx;
+  width: 300rpx;
+  background: #ccc;
+}
+
+.crash-goods .h .title {
+  display: inline-block;
+  position: absolute;
+  top: 56.125rpx;
+  left: 0;
+  z-index: 3;
+  height: 33rpx;
+  margin-left: 285rpx;
+  width: 180rpx;
+  background: #fff;
+}
+
+.crash-goods .b {
+  width: 750rpx;
+  height: auto;
+  overflow: hidden;
+}
+
+.crash-goods .b .item {
+  float: left;
+  background: #fff;
+  width: 375rpx;
+  height: auto;
+  overflow: hidden;
+  text-align: center;
+  padding: 15rpx 31.25rpx;
+  border-right: 1px solid #f4f4f4;
+  border-bottom: 1px solid #f4f4f4;
+}
+
+.crash-goods .item .img {
+  width: 311.45rpx;
+  height: 311.45rpx;
+}
+
+.crash-goods .item .name {
+  display: block;
+  width: 311.45rpx;
+  height: 35rpx;
+  margin: 11.5rpx 0 15rpx 0;
+  text-align: center;
+  overflow: hidden;
+  font-size: 30rpx;
+  color: #333;
+}
+
+.crash-goods .item .goods-do {
+  text-align:left;
+}
+
+.crash-goods .item .goods-do .price {
+  /* display: block; */
+  /* width: 70.45rpx; */
+  /* height: 30rpx; */
+  text-align: left;
+  font-size: 30rpx;
+  color: #b4282d;
+  display: inline;
+}
+
+.crash-goods .item .goods-do .org-price {
+  /* display: block; */
+  /* width: 70.45rpx; */
+  /* height: 23rpx; */
+  text-align: left;
+  font-size: 30rpx;
+  color: #303030;
+  display: inline;
+}
+
+.crash-goods .item .goods-do .add {
+  /* width: 93.75rpx; */
+  /* height: 100%; */
+  text-align: right;
+  line-height: 65rpx;
+   display: inline;
+}
+
+.shelves-view {
+  position: fixed;
+  left: 0;
+  bottom: 100rpx;
+  z-index: 10;
+  width: 100%;
+  height: 60rpx;
+  display: flex;
+  background: #fff;
+}
+.shelves-view .shelves {
+  border: 1px solid #7c7b7b;
+  background: #7c7b7b;
+  float: left;
+  height: 60rpx;
+  line-height: 60rpx;
+  flex: 1;
+  text-align: center;
+  color: #fff;
+  width: 100%;
+}
+.shelves-view .shelves .shelves-text {
+  font-size: 28rpx;
+  flex: 1;
+  text-align: center;
+  color: #fff;
+}
+
+.detail .t {
+  width: 687.5rpx;
+  height: 104rpx;
+  line-height: 104rpx;
+  font-size: 38.5rpx;
+}

+ 97 - 0
wx-mall-hk/pages/goodsActivity/goodsActivity.js

@@ -0,0 +1,97 @@
+var util = require('../../utils/util.js');
+var api = require('../../config/api.js');
+var app = getApp()
+Page({
+  data: {
+    // text:"这是一个页面"
+    activityList: [],
+    page: 1,
+    size: 10,
+    count: 0,
+    scrollTop: 0,
+    type: 0,//活动类型 1 2团购
+    showPage: false
+  },
+  onLoad: function (options) {
+    // 页面初始化 options为页面跳转所带来的参数
+    this.setData({
+      type: null!=options.type?parseInt(options.type):0
+    });
+    
+    wx.setNavigationBarTitle({
+      title: '活动'
+    })
+  },
+  onReady: function () {
+    // 页面渲染完成
+
+  },
+  onShow: function () {
+    // 页面显示
+    this.getActivityList();
+  },
+  onHide: function () {
+    // 页面隐藏
+  },
+  onUnload: function () {
+    // 页面关闭
+  },
+  nextPage: function (event) {
+    console.log();
+    var that = this;
+    if (this.data.page + 1 > that.data.count / that.data.size) {
+      return true;
+    }
+
+    that.setData({
+      "page": parseInt(that.data.page) + 1
+    });
+
+    this.getActivityList();
+
+  },
+  getActivityList: function () {
+
+    let that = this;
+    that.setData({
+      scrollTop: 0,
+      showPage: false,
+      topicList: []
+    });
+    // 页面渲染完成
+    wx.showToast({
+      title: '加载中...',
+      icon: 'loading',
+      duration: 2000
+    });
+
+    util.request(api.ActivityList, { page: that.data.page, size: that.data.size,type:that.data.type }).then(function (res) {
+      if (res.errno === 0) {
+
+        that.setData({
+          scrollTop: 0,
+          activityList: res.data.data,
+          showPage: true,
+          count: res.data.count
+        });
+      }
+      wx.hideToast();
+    });
+  },
+  prevPage: function (event) {
+    if (this.data.page <= 1) {
+      return false;
+    }
+
+    var that = this;
+    that.setData({
+      "page": parseInt(that.data.page) - 1
+    });
+    this.getActivityList();
+  },
+  gotoGroup(event) {
+    wx.redirectTo({
+      url: '/pages/group/group?goods_id=' + event.currentTarget.dataset.goodsId
+    })
+  },
+})

+ 1 - 0
wx-mall-hk/pages/goodsActivity/goodsActivity.json

@@ -0,0 +1 @@
+{}

+ 28 - 0
wx-mall-hk/pages/goodsActivity/goodsActivity.wxml

@@ -0,0 +1,28 @@
+<view class="container">
+  <scroll-view class="topic-list" scroll-y="true" scroll-top="{{scrollTop}}">
+    <view class="item" wx:for="{{activityList}}" wx:key="{{item.id}}">
+      <view class="imgtt" wx:if="{{item.type==2}}">
+        <navigator url="../groupDetail/groupDetail?id={{item.id}}">
+          <image class="img" src="{{item.item_pic_url}}"></image>
+          <view class="imgline">
+            <view class="priceInfo">最低开团价:
+              <text class="price">¥{{item.retail_min_price}}</text>
+              <text class="orgPrice line-through">¥{{item.retail_price}}</text>
+            </view>
+            <view class="right">
+              <button class="btn" data-goods-id="{{item.goods_id}}">立即开团</button>
+            </view>
+          </view>
+        </navigator>
+      </view>
+      <view class="info">
+        <text class="title">{{item.title}}</text>
+        <text class="desc">{{item.subtitle}}</text>
+      </view>
+    </view>
+    <view class="page" wx:if="{{showPage}}">
+      <view class="prev {{ page <= 1 ? 'disabled' : ''}}" bindtap="prevPage">上一页</view>
+      <view class="next {{ (count / size) < page +1 ? 'disabled' : ''}}" bindtap="nextPage">下一页</view>
+    </view>
+  </scroll-view>
+</view>

+ 7 - 0
wx-mall-hk/pages/goodsActivity/goodsActivity.wxss

@@ -0,0 +1,7 @@
+page, .container {
+  width: 750rpx;
+  height: 100%;
+  overflow: hidden;
+  background: #f4f4f4;
+}
+

+ 85 - 0
wx-mall-hk/pages/group/group.js

@@ -0,0 +1,85 @@
+var util = require('../../utils/util.js');
+var api = require('../../config/api.js');
+var app = getApp()
+Page({
+  data: {
+    // text:"这是一个页面"
+    groupList: [],
+    page: 1,
+    size: 10,
+    count: 0,
+    scrollTop: 0,
+    showPage: false
+  },
+  onLoad: function (options) {
+    // 页面初始化 options为页面跳转所带来的参数
+    this.getTopic();
+
+  },
+  onReady: function () {
+    // 页面渲染完成
+  },
+  onShow: function () {
+    // 页面显示
+  },
+  onHide: function () {
+    // 页面隐藏
+  },
+  onUnload: function () {
+    // 页面关闭
+  },
+  nextPage: function (event) {
+    console.log();
+    var that = this;
+    if (this.data.page + 1 > that.data.count / that.data.size) {
+      return true;
+    }
+
+
+    that.setData({
+      "page": parseInt(that.data.page) + 1
+    });
+
+    this.getTopic();
+
+  },
+  getTopic: function () {
+
+    let that = this;
+    that.setData({
+      scrollTop: 0,
+      showPage: false
+    });
+    // 页面渲染完成
+    wx.showToast({
+      title: '加载中...',
+      icon: 'loading',
+      duration: 2000
+    });
+
+    util.request(api.GroupList, { page: that.data.page, size: that.data.size }).then(function (res) {
+      if (res.errno === 0) {
+
+        that.setData({
+          scrollTop: 0,
+          groupList: res.data.data,
+          showPage: true,
+          count: res.data.count
+        });
+      }
+      wx.hideToast();
+    });
+
+  },
+  prevPage: function (event) {
+    if (this.data.page <= 1) {
+      return false;
+    }
+
+    var that = this;
+    that.setData({
+      "page": parseInt(that.data.page) - 1
+    });
+    this.getTopic();
+  }
+})

+ 3 - 0
wx-mall-hk/pages/group/group.json

@@ -0,0 +1,3 @@
+{
+  "navigationBarTitleText": "团购商品"
+}

+ 25 - 0
wx-mall-hk/pages/group/group.wxml

@@ -0,0 +1,25 @@
+<view class="container">
+  <scroll-view class="topic-list" scroll-y="true" scroll-top="{{scrollTop}}">
+
+    <navigator class="group-box" wx:for="{{groupList}}" wx:key="{{item.id}}" url="../groupDetail/groupDetail?id={{item.id}}">
+      <image class="img" src="{{item.item_pic_url}}"></image>
+      <view class="imgline">
+        <view class="title">{{item.title}}</view>
+        <view class="desc">{{item.subtitle}}</view>
+        <view class="priceInfo">最低开团价:
+          <text class="price">¥{{item.retail_min_price}}</text>
+          <text class="orgPrice line-through">¥{{item.retail_price}}</text>
+        </view>
+        <view class="btn-view">
+          <view class="surplus">还剩余{{item.stock_num}}件</view>
+          <button class="btn">立即开团</button>
+        </view>
+      </view>
+    </navigator>
+
+    <view class="page" wx:if="{{showPage}}">
+      <view class="prev {{ page <= 1 ? 'disabled' : ''}}" bindtap="prevPage">上一页</view>
+      <view class="next {{ (count / size) < page +1 ? 'disabled' : ''}}" bindtap="nextPage">下一页</view>
+    </view>
+  </scroll-view>
+</view>

+ 52 - 0
wx-mall-hk/pages/group/group.wxss

@@ -0,0 +1,52 @@
+page ,.container{
+   width: 750rpx;
+    height: 100%;
+    overflow: hidden;
+    background: #f4f4f4;
+}
+
+
+.group-box {
+  display: flex;
+  padding: 10px 10px;
+  background-color: #fff;
+  margin-bottom: 5px;
+}
+
+.group-box .img {
+  width: 240rpx;
+  height: 240rpx;
+  margin-top: 9px;
+}
+.group-box .title, .group-box .desc {
+  text-align: left;
+  padding: 0;
+}
+.group-box .imgline {
+  flex: 1;
+  padding-left: 15px;
+}
+.priceInfo .price {
+  color:#b4282d;
+  font-size: 40rpx;
+}
+.btn-view .btn {
+  color: #fff;
+  background-color: #f48f18;
+  width: 200rpx;
+  margin-top: 10px;
+
+  font-size: 28rpx;
+  float: right;
+}
+
+.btn-view .surplus {
+  float: left;
+  padding: 5px 10px;
+  background-color: #ffdf80;
+  text-align: center;
+  margin-top: 15px;
+  align-items: center;
+  font-size: 28rpx;
+  border-radius: 16px 16px 16px 16px;
+}

+ 363 - 0
wx-mall-hk/pages/groupDetail/groupDetail.js

@@ -0,0 +1,363 @@
+var app = getApp();
+var WxParse = require('../../lib/wxParse/wxParse.js');
+var util = require('../../utils/util.js');
+var api = require('../../config/api.js');
+
+Page({
+  data: {
+    winHeight: "",
+    id: 0,
+    referrer: 0,
+    goods: {},
+    group: {},
+    gallery: [],
+    attribute: [],
+    issueList: [],
+    comment: [],
+    brand: {},
+    specificationList: [],
+    productList: [],
+    relatedGoods: [],
+    cartGoodsCount: 0,
+    userHasCollect: 0,
+    crashList: {},
+    groupOpenList: [],
+    number: 1,
+    checkedSpecText: '请选择规格数量',
+    openAttr: false,
+    noCollectImage: "/static/images/icon_collect.png",
+    hasCollectImage: "/static/images/icon_collect_checked.png",
+    collectBackImage: "/static/images/icon_collect.png",
+    showNavList: false
+  },
+  toggleNav(){
+    this.setData({
+      showNavList: !this.data.showNavList
+    })
+  },
+  switchNav(event){
+    let name = event.currentTarget.dataset.name;
+    wx.switchTab({
+      url: `/pages/${name}/${name}`,
+    });
+  },
+  getGoodsInfo: function () {
+    let that = this;
+    util.request(api.GroupDetail, { id: that.data.id }).then(function (res) {
+      if (res.errno === 0) {
+        that.setData({
+          group: res.data.groupVo,
+          goods: res.data.info,
+          gallery: res.data.gallery,
+          attribute: res.data.attribute,
+          issueList: res.data.issue,
+          comment: res.data.comment,
+          // brand: res.data.brand,
+          specificationList: res.data.specificationList,
+          productList: res.data.productList,
+          userHasCollect: res.data.userHasCollect
+        });
+          //
+          let _specificationList = res.data.specificationList;
+          for (let i = 0; i < _specificationList.length; i++) {
+              if (_specificationList[i].valueList.length == 1) {
+                  //如果已经选中,则反选
+                  _specificationList[i].valueList[0].checked = true;
+              }
+          }
+          that.setData({
+              'specificationList': _specificationList
+          });
+
+        that.getGroupOpenList(res.data.groupVo.id)
+        if (res.data.userHasCollect == 1) {
+          that.setData({
+            'collectBackImage': that.data.hasCollectImage
+          });
+        } else {
+          that.setData({
+            'collectBackImage': that.data.noCollectImage
+          });
+        }
+
+        wx.hideLoading()
+
+        WxParse.wxParse('goodsDetail', 'html', res.data.info.goods_desc, that);
+        util.countdown(that,res.data.groupVo,'group',null)
+      }
+    });
+  },
+  //获取拼团列表
+  getGroupOpenList(groupId) {
+    let that = this;
+    util.request(api.GroupOpenList, { groupId: groupId, type:1}).then(function (res) {
+      if (res.errno === 0) {
+        that.setData({
+          groupOpenList: res.data
+        });
+
+        res.data.forEach((item,num)=>{
+          util.countdown(that, res.data, 'groupOpenList', num)
+        })
+      }
+    });
+  },
+  clickSkuValue: function (event) {
+    let that = this;
+    let specNameId = event.currentTarget.dataset.nameId;
+    let specValueId = event.currentTarget.dataset.valueId;
+
+    //判断是否可以点击
+
+    //TODO 性能优化,可在wx:for中添加index,可以直接获取点击的属性名和属性值,不用循环
+    let _specificationList = this.data.specificationList;
+    for (let i = 0; i < _specificationList.length; i++) {
+      if (_specificationList[i].specification_id == specNameId) {
+        for (let j = 0; j < _specificationList[i].valueList.length; j++) {
+          if (_specificationList[i].valueList[j].id == specValueId) {
+            //如果已经选中,则反选
+            if (_specificationList[i].valueList[j].checked) {
+              _specificationList[i].valueList[j].checked = false;
+            } else {
+              _specificationList[i].valueList[j].checked = true;
+            }
+          } else {
+            _specificationList[i].valueList[j].checked = false;
+          }
+        }
+      }
+    }
+    this.setData({
+      'specificationList': _specificationList
+    });
+    //重新计算spec改变后的信息
+    this.changeSpecInfo();
+
+    //重新计算哪些值不可以点击
+  },
+
+  //获取选中的规格信息
+  getCheckedSpecValue: function () {
+    let checkedValues = [];
+    let _specificationList = this.data.specificationList;
+    for (let i = 0; i < _specificationList.length; i++) {
+      let _checkedObj = {
+        nameId: _specificationList[i].specification_id,
+        valueId: 0,
+        valueText: ''
+      };
+      for (let j = 0; j < _specificationList[i].valueList.length; j++) {
+        if (_specificationList[i].valueList[j].checked) {
+          _checkedObj.valueId = _specificationList[i].valueList[j].id;
+          _checkedObj.valueText = _specificationList[i].valueList[j].value;
+        }
+      }
+      checkedValues.push(_checkedObj);
+    }
+
+    return checkedValues;
+
+  },
+  //根据已选的值,计算其它值的状态
+  setSpecValueStatus: function () {
+
+  },
+  //判断规格是否选择完整
+  isCheckedAllSpec: function () {
+    return !this.getCheckedSpecValue().some(function (v) {
+      if (v.valueId == 0) {
+        util.showErrorToast('请选齐规格');
+        return true;
+      }
+    });
+  },
+  getCheckedSpecKey: function () {
+    let checkedValue = this.getCheckedSpecValue().map(function (v) {
+      return v.valueId;
+    });
+
+    return checkedValue.join('_');
+  },
+  changeSpecInfo: function () {
+    let checkedNameValue = this.getCheckedSpecValue();
+
+    //设置选择的信息
+    let checkedValue = checkedNameValue.filter(function (v) {
+      if (v.valueId != 0) {
+        return true;
+      } else {
+        return false;
+      }
+    }).map(function (v) {
+      return v.valueText;
+    });
+    if (checkedValue.length > 0) {
+      this.setData({
+        'checkedSpecText': checkedValue.join(' ')
+      });
+    } else {
+      this.setData({
+        'checkedSpecText': '请选择规格数量'
+      });
+    }
+
+  },
+  getCheckedProductItem: function (key) {
+    if (this.data.productList.length ==1){
+      return this.data.productList;
+    }
+    return this.data.productList.filter(function (v) {
+      if (v.goods_specification_ids == key) {
+        return true;
+      } else {
+        return false;
+      }
+    });
+  },
+  onLoad: function (options) {
+    wx.showLoading({
+      mask: true
+    })
+    // 页面初始化 options为页面跳转所带来的参数
+    this.setData({
+      id: parseInt(options.id),
+      referrer: (null!=options.referrer?parseInt(options.referrer):0)
+    });
+    var that = this;
+    this.getGoodsInfo();
+    var that = this
+    //  高度自适应
+    wx.getSystemInfo({
+        success: function (res) {
+            var clientHeight = res.windowHeight,
+                clientWidth = res.windowWidth,
+                rpxR = 750 / clientWidth;
+            var calc = clientHeight * rpxR - 100;
+            console.log(calc)
+            that.setData({
+                winHeight: calc
+            });
+        }
+    });
+  },
+  onReady: function () {
+    let that = this;
+    // 页面渲染完成
+  },
+  onShow: function () {
+    // 页面显示
+
+  },
+  onHide: function () {
+    //页面隐藏
+    this.setData({
+      openAttr: false,
+      showNavList: false
+    })
+
+  },
+  onUnload: function () {
+    // 页面关闭
+
+  },
+  switchAttrPop: function () {
+    this.setData({
+      openAttr: !this.data.openAttr
+    })
+  },
+  closeAttrOrCollect: function () {
+    let that = this;
+    //添加或是取消收藏
+    util.request(api.CollectAddOrDelete, { typeId: 0, valueId: this.data.id }, "POST")
+      .then(function (res) {
+        let _res = res;
+        if (_res.errno == 0) {
+          if (_res.data.type == 'add') {
+            that.setData({
+              'collectBackImage': that.data.hasCollectImage
+            });
+          } else {
+            that.setData({
+              'collectBackImage': that.data.noCollectImage
+            });
+          }
+
+        } else {
+          wx.showToast({
+            image: '/static/images/icon_error.png',
+            title: _res.errmsg,
+            mask: true
+          });
+        }
+      });
+  },
+  cutNumber: function () {
+    this.setData({
+      number: (this.data.number - 1 > 1) ? this.data.number - 1 : 1
+    });
+  },
+  addNumber: function () {
+    this.setData({
+      number: this.data.number + 1
+    });
+  },
+  onShareAppMessage: function () {
+    var that = this;
+    // console.log("url:" + that.data.goods.list_pic_url);
+    // var userId = wx.getStorageSync('userId');
+    // console.log("userId:" + userId);
+    return {
+      title: that.data.goods.name,
+      desc: '商业版',
+      imageUrl: that.data.goods.list_pic_url,
+      path: '/pages/groupDetail/groupDetail?id=' + that.data.id + '&&referrer=' + wx.getStorageSync('userId'),
+      success: function (res) {
+        console.log("转发成功");
+        // 转发成功
+      },
+      fail: function (res) {
+        // 转发失败
+        console.log("转发失败");
+      }
+    }
+  },
+  checkProduct: function () {
+    var that = this;
+    if (this.data.openAttr == false) {
+      //打开规格选择窗口
+      this.setData({
+        openAttr: !this.data.openAttr,
+        collectBackImage: "/static/images/detail_back.png"
+      });
+    } else {
+
+      //提示选择完整规格
+      if (!this.isCheckedAllSpec()) {
+        return false;
+      }
+
+      //根据选中的规格,判断是否有对应的sku信息
+      let checkedProduct = this.getCheckedProductItem(this.getCheckedSpecKey());
+      if (!checkedProduct || checkedProduct.length <= 0) {
+        //找不到对应的product信息,提示没有库存
+        return false;
+      }
+
+      //验证库存
+      if (checkedProduct.goods_number < this.data.number) {
+        //找不到对应的product信息,提示没有库存
+        return false;
+      }
+
+      wx.redirectTo({
+        url: '/pages/shopping/groupcheck/groupcheck?number=' + this.data.number + '&productId=' + checkedProduct[0].id
+        + '&groupId=' + this.data.id,
+      })
+    }
+  },
+  switchNav(event) {
+    wx.switchTab({
+      url: '/pages/index/index'
+    });
+  },
+})

+ 1 - 0
wx-mall-hk/pages/groupDetail/groupDetail.json

@@ -0,0 +1 @@
+{}

+ 206 - 0
wx-mall-hk/pages/groupDetail/groupDetail.wxml

@@ -0,0 +1,206 @@
+<scroll-view class="container" style="height: {{winHeight}}rpx" scroll-y="true">
+  <view>
+  <view wx:if="{{showNavList}}" class="modal-wrap"></view>
+  <view class="fast-nav">
+    <contact-button wx:if="{{!showNavList}}" class="contact" size="25" type="primary" session-from="weapp"><text>找客服</text></contact-button>
+    <view wx:if="{{!showNavList}}" class="nav" bindtap="toggleNav"><text>快捷</text><text>导航</text></view>
+    <view class="nav-list" wx:if="{{showNavList}}">
+      <view class="nav-item">
+        <text class="nav-text">首页</text>
+        <view class="nav-cell" bindtap="switchNav" data-name="index">
+          <image src="../../static/images/nav-1.png"></image>
+        </view>
+      </view>
+      <view class="nav-item">
+        <text class="nav-text">足迹</text>
+        <navigator class="nav-cell" url="../ucenter/footprint/footprint">
+          <image src="../../static/images/nav-2.png"></image>
+        </navigator>
+      </view>
+      <view class="nav-item">
+        <text class="nav-text">搜索</text>
+        <navigator class="nav-cell" url="../search/search">
+          <image src="../../static/images/nav-3.png"></image>
+        </navigator>
+      </view>
+      <view class="nav-item">
+        <text class="nav-text">购物车</text>
+        <view class="nav-cell" bindtap="switchNav" data-name="cart">
+          <image src="../../static/images/nav-4.png"></image>
+        </view>
+      </view>
+    </view>
+    <view wx:if="{{showNavList}}" class="close" bindtap="toggleNav">X</view>
+  </view>
+    <swiper class="goodsimgs" indicator-dots="true" autoplay="true" interval="3000" duration="1000">
+      <swiper-item wx:for="{{gallery}}" wx:key="{{item.id}}">
+        <image src="{{item.img_url}}" background-size="cover"></image>
+      </swiper-item>
+    </swiper>
+    <!-- <view class="service-policy">
+      <view class="item">30分钟速达</view>
+      <view class="item">每日优选生鲜</view>
+      <view class="item">满88元免运费</view>
+    </view> -->
+    <view class="group-panel">
+      <view class="group-title">拼团</view>
+      <view class="group-desc">限时火拼·超值底价</view>
+      <view class="group-deadline">
+        <view class="desc">距结束仅剩</view>
+        <view class="info">
+          <text class="time-tag">{{group.dateformat.day}}</text>天<text class="time-tag">{{group.dateformat.hr}}</text>时<text class="time-tag">{{group.dateformat.min}}</text>分<text class="time-tag">{{group.dateformat.sec}}</text>秒</view>
+      </view>
+    </view>
+    <view class="goods-info">
+      <view class="c">
+        <view class="goods-do">
+          <text class="price">¥{{group.retail_min_price}}</text>
+          <view class="group-desc">
+            <text class="org-price line-through">¥{{group.retail_price}}</text>
+            <text class="price-desc">{{group.min_open_group}}人拼团  拼团立省¥{{group.retail_price - group.retail_min_price}}</text>
+          </view>
+        </view>
+        <!-- <text class='bizType'>{{goods.goodsBizType}}</text> -->
+        <text class="name">{{goods.name}}</text>
+        <text class="desc">{{goods.goods_brief}}</text>
+      </view>
+    </view>
+
+      <view class='goods-close' wx:if="{{group.open_status!=1}}">已关闭</view>
+
+    <!-- <view class="section-nav section-attr" bindtap="switchAttrPop">
+      <view class="t">请选择规格数量</view>
+      <image class="i" src="../../static/images/address_right.png" background-size="cover"></image>
+    </view> -->
+    <view class="join-group" wx:if="{{groupOpenList.length > 0}}">
+      <view class="join-group-desc">以下小伙伴正在发起拼团,您可以直接参与:</view>
+      <view class="join-group-list">
+        <view class="join-group-item" wx:for="{{groupOpenList}}" wx:key="index">
+          <view class="user">
+            <image src="{{item.avatar}}"></image>
+            <text>{{item.nickname}}</text>
+          </view>
+          <view class="box">
+            <view class="desc">还差{{item.min_open_group - item.attend_num}}人成团</view>
+            <view class="time">剩余 <text>{{item.dateformat.day}}天</text>
+              <text>{{item.dateformat.hr}}</text>:<text>{{item.dateformat.min}}</text>:<text>{{item.dateformat.sec}}</text>
+            </view>
+          </view>
+          <navigator url="../joinGroup/joinGroup?openId={{item.id}}&groupId={{item.group_id}}&goodsId={{group.id}}&min_open_group={{item.min_open_group}}&attend_num={{item.attend_num}}&end_time={{item.end_time}}">
+            <view class="btn" wx:if="{{group.open_status==1}}">去参团</view>
+          </navigator>
+        </view>
+      </view>
+    </view>
+    <view class="comments" wx:if="{{comment.count > 0}}">
+      <view class="h">
+        <navigator url="../comment/comment?valueId={{goods.id}}&typeId=0">
+          <text class="t">评价({{comment.count > 999 ? '999+' : comment.count}})</text>
+          <text class="i">查看全部</text>
+        </navigator>
+      </view>
+      <view class="b">
+        <view class="item">
+          <view class="info">
+            <view class="user">
+              <image src="{{comment.data.avatar}}"></image>
+              <text>{{comment.data.nickname}}</text>
+            </view>
+            <view class="time">{{comment.data.add_time}}</view>
+          </view>
+          <view class="content">
+            {{comment.data.content}}
+          </view>
+          <view class="imgs" wx:if="{{comment.data.pic_list.length > 0}}">
+            <image class="img" wx:for="{{comment.data.pic_list}}" wx:key="{{item.id}}" src="{{item.pic_url}}"></image>
+          </view>
+          <!-- <view class="spec">白色 2件</view> -->
+        </view>
+      </view>
+    </view>
+    <view class="goods-attr">
+      <view class="t">商品参数</view>
+      <view class="l">
+        <view class="item" wx:for="{{attribute}}" wx:key="{{item.name}}">
+          <text class="left">{{item.name}}</text>
+          <text class="right">{{item.value}}</text>
+        </view>
+      </view>
+    </view>
+
+    <view class="detail">
+      <import src="../../lib/wxParse/wxParse.wxml" />
+      <template is="wxParse" data="{{wxParseData:goodsDetail.nodes}}" />
+    </view>
+
+
+    <view class="common-problem">
+      <view class="h">
+        <view class="line"></view>
+        <text class="title">常见问题</text>
+      </view>
+      <view class="b">
+        <view class="item" wx:for="{{issueList}}" wx:key="{{item.id}}">
+          <view class="question-box">
+            <text class="spot"></text>
+            <text class="question">{{item.question}}</text>
+          </view>
+          <view class="answer">
+            {{item.answer}}
+          </view>
+        </view>
+      </view>
+    </view>
+
+  </view>
+  <view wx:if="{{openAttr}}" class="attr-pop">
+    <view class="attr-close" bindtap="switchAttrPop">X</view>
+    <view class="img-info">
+      <image class="img" src="{{goods.list_pic_url}}"></image>
+      <view class="info">
+        <view class="c">
+          <view class="p">价格:¥{{group.retail_min_price}}</view>
+          <view class="a" wx:if="{{productList.length>0}}">已选择:{{checkedSpecText}}</view>
+        </view>
+      </view>
+    </view>
+    <view class="spec-con">
+      <view class="spec-item" wx:for="{{specificationList}}" wx:key="{{item.specification_id}}">
+        <view class="name">{{item.name}}</view>
+        <view class="values">
+          <view class="value {{vitem.checked ? 'selected' : ''}}" bindtap="clickSkuValue" wx:for="{{item.valueList}}" wx:for-item="vitem" wx:key="{{vitem.id}}" data-value-id="{{vitem.id}}" data-name-id="{{vitem.specification_id}}">{{vitem.value}}</view>
+        </view>
+      </view>
+
+      <view class="number-item">
+        <view class="name">数量</view>
+        <view class="selnum">
+          <view class="cut" bindtap="cutNumber">-</view>
+          <input value="{{number}}" class="number" disabled="true" type="number" />
+          <view class="add" bindtap="addNumber">+</view>
+        </view>
+      </view>
+    </view>
+  </view>
+</scroll-view>
+  <view class="bottom-btn"  wx:if="{{group.open_status==1}}">
+      <view class="l l-home" bindtap="switchNav">
+      <image class="icon" src="/static/images/nav-1.png"></image>
+    </view>
+    <view wx:if="{{!openAttr}}" class="l l-collect {{ openAttr ? 'back' : ''}}" bindtap="closeAttrOrCollect">
+      <image class="icon" src="{{ collectBackImage }}"></image>
+    </view>
+    <navigator wx:if="{{!openAttr}}" url="../goods/goods?id={{group.goods_id}}">
+      <view class="m">
+        <text>¥{{group.retail_price}}</text>
+        <text>单独购买</text>
+      </view>
+    </navigator>
+    <view wx:if="{{!openAttr}}" class="r" bindtap="switchAttrPop">
+      <text>¥{{group.retail_min_price}}</text>
+      <text>{{group.min_open_group}}人拼团</text>
+    </view>
+    <view wx:if="{{openAttr}}" class="r" bindtap="checkProduct">
+      <text>确认</text>
+    </view>
+  </view>

+ 767 - 0
wx-mall-hk/pages/groupDetail/groupDetail.wxss

@@ -0,0 +1,767 @@
+.container {
+  margin-bottom: 100rpx;
+  box-sizing:border-box;
+  background-color:#f4f4f4;
+  font-family:PingFangSC-Light, helvetica, 'Heiti SC'
+}
+
+.goodsimgs {
+  width: 750rpx;
+  height: 750rpx;
+}
+
+.goodsimgs image {
+  width: 100%;
+  height: 100%;
+}
+
+.service-policy {
+  width: 100%;
+  height: 73rpx;
+  background: #f4f4f4;
+  padding: 0 31.25rpx;
+  display: flex;
+  flex-flow: row nowrap;
+  align-items: center;
+  justify-content: space-between;
+}
+
+.service-policy .item {
+  background: url(http://120.76.26.84:80/group1/M00/00/02/rBJEdVvr25eAGT4BAAAA2Yyhu9Q372.png) 0 center no-repeat;
+  background-size: 10rpx;
+  padding-left: 15rpx;
+  display: flex;
+  align-items: center;
+  font-size: 25rpx;
+  color: #666;
+}
+.group-panel{
+  height: 100rpx;
+  background: linear-gradient(to right, #FFAC2C, #FFCD5A);
+  display: flex;
+}
+
+.group-panel .group-title{
+  width: 180rpx;
+  color: #fff;
+  font-size: 50rpx;
+  padding: 0 30rpx;
+  line-height: 100rpx;
+  text-align: center;
+  font-family: YouYuan;
+  font-weight: bold;
+}
+
+.group-panel .group-desc{
+  width: 240rpx;
+  color: #fff;
+  font-size: 25rpx;
+  line-height: 150rpx;
+  overflow: hidden;
+}
+
+.group-panel .group-deadline{
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+}
+
+.group-panel .group-deadline .desc{
+  text-align: center;
+  color: red;
+  font-size: 25rpx;
+  padding-bottom: 10rpx;
+}
+.group-panel .group-deadline .info{
+ text-align: center;
+ display: flex;
+ align-items: center;
+}
+.group-panel .group-deadline .time-tag{
+  display: inline-block;
+  min-width: 40rpx;
+  height: 40rpx;
+  color: #fff;
+  text-align: center;
+  line-height: 40rpx;
+  border-radius: 2px;
+  background-color: #000;
+  margin: 0 5rpx;
+  padding: 0 5rpx;
+}
+.goods-info {
+  width: 100%;
+  background: #fff;
+}
+
+.goods-info .c {
+  display: block;
+  width: 100%;
+  /* height: 100%; */
+  padding: 38rpx 31.25rpx 38rpx 0;
+  border-bottom: 1px solid #f4f4f4;
+}
+
+.goods-info .c text {
+  display: block;
+  /* width: 687.5rpx; */
+  text-align: center;
+}
+
+.goods-info .name {
+  height: 41rpx;
+  margin: 40rpx 0 5.208rpx 0;
+  font-size: 41rpx;
+  line-height: 41rpx;
+}
+.bizType {
+  font-size: 20rpx;
+}
+
+.goods-info .desc {
+  height: 43rpx;
+  font-size: 24rpx;
+  line-height: 36rpx;
+  color: #999;
+}
+
+.goods-info .goods-do {
+ display: flex;
+}
+
+.goods-info .goods-do .price {
+  font-size: 55rpx;
+  color: #b4282d;
+  width: 180rpx;
+  text-align: center;
+}
+.goods-info .goods-do .group-desc{
+  flex: 1;
+}
+.goods-info .goods-do .org-price{
+  font-size: 25rpx;
+  color: #303030;
+  text-align: left;
+}
+
+.goods-info .goods-do .price-desc{
+  font-size: 25rpx;
+  color: #b4282d;
+  text-align: left;
+}
+
+.goods-info .brand {
+  margin-top: 23rpx;
+  min-height: 40rpx;
+  text-align: center;
+}
+
+.goods-info .brand text {
+  display: inline-block;
+  width: auto;
+  padding: 2px 30rpx 2px 10.5rpx;
+  line-height: 35.5rpx;
+  border: 1px solid #f48f18;
+  font-size: 25rpx;
+  color: #f48f18;
+  border-radius: 4px;
+  background: url(http://120.76.26.84:80/group1/M00/00/02/rBJEdVvr28mAes5qAAABHjRl7xw575.png) 95% center no-repeat;
+  background-size: 10.75rpx 18.75rpx;
+}
+
+.join-group{
+  margin-top: 25rpx;
+  background-color: #fff;
+}
+
+.join-group .join-group-desc{
+  padding: 20rpx 0 0 20rpx;
+}
+
+.join-group .join-group-item{
+  background-color: #F6F6F6;
+  display: flex;
+  height: 100rpx;
+  align-items: center;
+  margin: 20rpx 0;
+}
+
+.join-group .join-group-item .user {
+ display: flex;
+ align-items: center;
+ width: 290rpx;
+}
+
+.join-group .join-group-item .user image {
+  width: 80rpx;
+  height: 80rpx;
+  margin: 0 30rpx;
+  border-radius: 50%;
+}
+
+.join-group .join-group-item .user text {
+  display: inline-block;
+  width: 150rpx;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
+
+.join-group .join-group-item .box {
+  margin-left: auto;
+  padding: 0 20rpx;
+}
+
+.join-group .join-group-item .box .desc {
+  color: #FF527F;
+}
+
+.join-group .join-group-item .box .time {
+  color: #9D9D9D;
+  white-space: nowrap;
+}
+
+.join-group .join-group-item .box text {
+  color: #9D9D9D;
+}
+
+.join-group .join-group-item .btn {
+  margin-left: auto;
+  width: 180rpx;
+  height: 100rpx;
+  line-height: 100rpx;
+  text-align: center;
+  color:  #fff;
+  background-color: #FF5778;
+}
+
+.section-nav {
+  width: 100%;
+  height: 108rpx;
+  background: #fff;
+  margin-bottom: 20rpx;
+}
+
+.section-nav .t {
+  float: left;
+  width: 600rpx;
+  height: 108rpx;
+  line-height: 108rpx;
+  font-size: 29rpx;
+  color: #333;
+  margin-left: 31.25rpx;
+}
+
+.section-nav .i {
+  float: right;
+  width: 52rpx;
+  height: 52rpx;
+  margin-right: 16rpx;
+  margin-top: 28rpx;
+}
+
+.section-act .t {
+  float: left;
+  display: flex;
+  align-items: center;
+  width: 600rpx;
+  height: 108rpx;
+  overflow: hidden;
+  line-height: 108rpx;
+  font-size: 29rpx;
+  color: #999;
+  margin-left: 31.25rpx;
+}
+
+.section-act .label {
+  color: #999;
+}
+
+.section-act .tag {
+  display: flex;
+  align-items: center;
+  padding: 0 10rpx;
+  border-radius: 3px;
+  height: 37rpx;
+  width: auto;
+  color: #f48f18;
+  overflow: hidden;
+  border: 1px solid #f48f18;
+  font-size: 25rpx;
+  margin: 0 10rpx;
+}
+
+.section-act .text {
+  display: flex;
+  align-items: center;
+  height: 37rpx;
+  width: auto;
+  overflow: hidden;
+  color: #f48f18;
+  font-size: 29rpx;
+}
+
+.comments {
+  width: 100%;
+  height: auto;
+  padding-left: 30rpx;
+  background: #fff;
+  margin: 20rpx 0;
+}
+
+.comments .h {
+  height: 102.5rpx;
+  line-height: 100.5rpx;
+  width: 718.75rpx;
+  padding-right: 16rpx;
+  border-bottom: 1px solid #d9d9d9;
+}
+
+.comments .h .t {
+  display: block;
+  float: left;
+  width: 50%;
+  font-size: 38.5rpx;
+  color: #333;
+}
+
+.comments .h .i {
+  display: block;
+  float: right;
+  width: 164rpx;
+  height: 100.5rpx;
+  line-height: 100.5rpx;
+  background: url(http://120.76.26.84:80/group1/M00/00/02/rBJEdVvr2_OAO7zoAAABG9E7g8o485.png) right center no-repeat;
+  background-size: 52rpx;
+}
+
+.comments .b {
+  height: auto;
+  width: 720rpx;
+}
+
+.comments .item {
+  height: auto;
+  width: 720rpx;
+  overflow: hidden;
+}
+
+.comments .info {
+  height: 127rpx;
+  width: 100%;
+  padding: 33rpx 0 27rpx 0;
+}
+
+.comments .user {
+  float: left;
+  width: auto;
+  height: 67rpx;
+  line-height: 67rpx;
+  font-size: 0;
+}
+
+.comments .user image {
+  float: left;
+  width: 67rpx;
+  height: 67rpx;
+  margin-right: 17rpx;
+  border-radius: 50%;
+}
+
+.comments .user text {
+  display: inline-block;
+  width: auto;
+  height: 66rpx;
+  overflow: hidden;
+  font-size: 29rpx;
+  line-height: 66rpx;
+}
+
+.comments .time {
+  display: block;
+  float: right;
+  width: auto;
+  height: 67rpx;
+  line-height: 67rpx;
+  color: #7f7f7f;
+  font-size: 25rpx;
+  margin-right: 30rpx;
+}
+
+.comments .content {
+  width: 720rpx;
+  padding-right: 30rpx;
+  line-height: 45.8rpx;
+  font-size: 29rpx;
+  margin-bottom: 24rpx;
+}
+
+.comments .imgs {
+  width: 720rpx;
+  height: auto;
+  margin-bottom: 25rpx;
+}
+
+.comments .imgs .img {
+  height: 150rpx;
+  width: 150rpx;
+  margin-right: 28rpx;
+}
+
+.comments .spec {
+  width: 720rpx;
+  padding-right: 30rpx;
+  line-height: 30rpx;
+  font-size: 24rpx;
+  color: #999;
+  margin-bottom: 30rpx;
+}
+
+.goods-attr {
+  width: 100%;
+  height: auto;
+  overflow: hidden;
+  padding: 0 31.25rpx 25rpx 31.25rpx;
+  background: #fff;
+}
+
+.goods-attr .t {
+  width: 687.5rpx;
+  height: 104rpx;
+  line-height: 104rpx;
+  font-size: 38.5rpx;
+}
+
+.goods-attr .item {
+  width: 687.5rpx;
+  height: 68rpx;
+  padding: 11rpx 20rpx;
+  margin-bottom: 11rpx;
+  background: #f7f7f7;
+  font-size: 38.5rpx;
+}
+
+.goods-attr .left {
+  float: left;
+  font-size: 25rpx;
+  width: 134rpx;
+  height: 45rpx;
+  line-height: 45rpx;
+  overflow: hidden;
+  color: #999;
+}
+
+.goods-attr .right {
+  float: left;
+  font-size: 36.5rpx;
+  margin-left: 20rpx;
+  width: 480rpx;
+  height: 45rpx;
+  line-height: 45rpx;
+  overflow: hidden;
+  color: #333;
+}
+
+.detail {
+  width: 100%;
+  height: auto;
+  overflow: hidden;
+}
+
+.detail image {
+  width: 100%;
+  display: block;
+}
+
+.common-problem {
+  width: 100%;
+  height: auto;
+  overflow: hidden;
+}
+
+.common-problem .h {
+  position: relative;
+  height: 145.5rpx;
+  width: 100%;
+  padding: 56.25rpx 0;
+  background: #fff;
+  text-align: center;
+}
+
+.common-problem .h .line {
+  display: inline-block;
+  position: absolute;
+  top: 72rpx;
+  left: 0;
+  z-index: 2;
+  height: 1px;
+  margin-left: 225rpx;
+  width: 300rpx;
+  background: #ccc;
+}
+
+.common-problem .h .title {
+  display: inline-block;
+  position: absolute;
+  top: 56.125rpx;
+  left: 0;
+  z-index: 3;
+  height: 33rpx;
+  margin-left: 285rpx;
+  width: 180rpx;
+  background: #fff;
+}
+
+.common-problem .b {
+  width: 100%;
+  height: auto;
+  overflow: hidden;
+  padding: 0rpx 30rpx;
+  background: #fff;
+}
+
+.common-problem .item {
+  height: auto;
+  overflow: hidden;
+  padding-bottom: 25rpx;
+}
+
+.common-problem .question-box .spot {
+  float: left;
+  display: block;
+  height: 8rpx;
+  width: 8rpx;
+  background: #b4282d;
+  border-radius: 50%;
+  margin-top: 11rpx;
+}
+
+.common-problem .question-box .question {
+  line-height: 30rpx;
+  padding-left: 18rpx;
+  display: block;
+  font-size: 26rpx;
+  padding-bottom: 15rpx;
+  color: #303030;
+}
+
+.common-problem .answer {
+  line-height: 36rpx;
+  padding-left: 16rpx;
+  font-size: 26rpx;
+  color: #787878;
+}
+
+.bottom-btn {
+  position: fixed;
+  left: 0;
+  bottom: 0;
+  z-index: 10;
+  width: 100%;
+  height: 100rpx;
+  display: flex;
+  background: #fff;
+}
+
+.bottom-btn .l {
+  height: 100rpx;
+  width: 122rpx;
+  border: 1px solid #f4f4f4;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.bottom-btn .l.l-home {
+  border-right: none;
+  border-left: none;
+  text-align: center;
+}
+
+.bottom-btn .l.l-collect {
+  border-right: none;
+  border-left: none;
+  text-align: center;
+}
+
+.bottom-btn .l .icon {
+  display: block;
+  height: 44rpx;
+  width: 44rpx;
+}
+
+.bottom-btn .m {
+  height: 100rpx;
+  width: 244rpx;
+  border: 1px solid #f4f4f4;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  color: #b4282d;
+}
+
+.bottom-btn .m text {
+  color: #b4282d;
+  background-color: ccc;
+}
+
+.bottom-btn .r {
+  border: 1px solid #b4282d;
+  background: #b4282d;
+  height: 100rpx;
+  display: flex;
+  flex: 1;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  color: #fff;
+}
+
+.bottom-btn .r text {
+  color: #fff;
+}
+@import "../../lib/wxParse/wxParse.wxss";
+
+.attr-pop {
+  width: 100%;
+  height: auto;
+  padding: 31.25rpx;
+  background: #fff;
+  position: fixed;
+  bottom: 100rpx;
+  z-index: 500;
+}
+
+.attr-close{
+  float: right;
+  width: 40rpx;
+  height: 40rpx;
+  line-height: 40rpx;
+  border-radius: 50%;
+  font-size: 40rpx;
+  text-align: center;
+  overflow: hidden;
+}
+
+.attr-pop .img-info {
+  width: 687.5rpx;
+  height: 177rpx;
+  overflow: hidden;
+  margin-bottom: 41.5rpx;
+}
+
+.attr-pop .img {
+  float: left;
+  height: 177rpx;
+  width: 177rpx;
+  background: #f4f4f4;
+  margin-right: 31.25rpx;
+}
+
+.attr-pop .info {
+  float: left;
+  height: 177rpx;
+  display: flex;
+  align-items: center;
+}
+
+.attr-pop .p {
+  font-size: 33rpx;
+  color: #333;
+  height: 33rpx;
+  line-height: 33rpx;
+  margin-bottom: 10rpx;
+}
+
+.attr-pop .a {
+  font-size: 29rpx;
+  color: #333;
+  height: 40rpx;
+  line-height: 40rpx;
+}
+
+.spec-con {
+  width: 100%;
+  height: auto;
+  overflow: hidden;
+}
+
+.spec-con .name {
+  height: 32rpx;
+  margin-bottom: 22rpx;
+  font-size: 29rpx;
+  color: #333;
+}
+
+.spec-con .values {
+  height: auto;
+  margin-bottom: 31.25rpx;
+  font-size: 0;
+}
+
+.spec-con .value {
+  display: inline-block;
+  height: 62rpx;
+  padding: 0 35rpx;
+  line-height: 56rpx;
+  text-align: center;
+  margin-right: 25rpx;
+  margin-bottom: 16.5rpx;
+  border: 1px solid #333;
+  font-size: 25rpx;
+  color: #333;
+}
+
+.spec-con .value.disable {
+  border: 1px solid #ccc;
+  color: #ccc;
+}
+
+.spec-con .value.selected {
+  border: 1px solid #b4282d;
+  color: #b4282d;
+}
+
+.number-item .selnum {
+  width: 322rpx;
+  height: 71rpx;
+  border: 1px solid #ccc;
+  display: flex;
+}
+
+.number-item .cut {
+  width: 93.75rpx;
+  height: 100%;
+  text-align: center;
+  line-height: 65rpx;
+}
+
+.number-item .number {
+  flex: 1;
+  height: 100%;
+  text-align: center;
+  line-height: 68.75rpx;
+  border-left: 1px solid #ccc;
+  border-right: 1px solid #ccc;
+  float: left;
+}
+
+.number-item .add {
+  width: 93.75rpx;
+  height: 100%;
+  text-align: center;
+  line-height: 65rpx;
+}
+
+.line-through {
+  text-decoration: line-through;
+}
+
+.goods-close {
+  width: 100%;
+  font-size: 50px;
+  text-align: center;
+  background: #fff;
+}

+ 277 - 0
wx-mall-hk/pages/hotGoods/hotGoods.js

@@ -0,0 +1,277 @@
+var util = require('../../utils/util.js');
+var api = require('../../config/api.js');
+var goodsUtil = require('../../utils/goods.js');
+var app = getApp();
+
+Page({
+  data: {
+    bannerInfo: {
+      'img_url': '',
+      'name': ''
+    },
+    categoryFilter: false,
+    filterCategory: [],
+    goodsList: [],
+    categoryId: 0,
+    currentSortType: 'default',
+    currentSortOrder: 'desc',
+    page: 1,
+    size: 1000,
+    showNavList: false,
+    footCart: {},
+    openAttr: false,
+    productList: {},
+    specificationList: {},
+    checkedSpecText: '请选择规格数量',
+    number: 1,
+    retailPrice: '',
+    stockNum: 0,
+    cartNumber: 0,
+  },
+  toggleNav() {
+    this.setData({
+      showNavList: !this.data.showNavList
+    })
+  },
+  getData: function () {
+    let that = this;
+    util.request(api.GoodsHot).then(function (res) {
+      if (res.errno === 0) {
+        that.setData({
+          bannerInfo: res.data.bannerInfo,
+        });
+        that.getGoodsList();
+      }
+    });
+  },
+  getGoodsList() {
+    wx.showLoading({
+      title: '加载中...',
+    });
+    var that = this;
+
+    util.request(api.HotGoodsList, { isHot: 1, page: that.data.page, size: that.data.size, order: that.data.currentSortOrder, sort: that.data.currentSortType, categoryId: that.data.categoryId})
+      .then(function (res) {
+        if (res.errno === 0) {
+          that.setData({
+            goodsList: res.data.goodsList,
+            filterCategory: res.data.filterCategory
+          });
+          wx.hideLoading();
+          if(that.data.categoryId>0){
+            let filterCategory = that.data.filterCategory;
+            filterCategory.forEach(function (val, index, arr) {
+              if (val.id == that.data.categoryId) {
+                val.checked = true;
+                filterCategory[index] = val;
+                that.setData({ filterCategory: filterCategory });
+              }else {
+                val.checked = false;
+              }
+            }, that);
+          }
+        }
+      });
+  },
+  switchNav(event) {
+    let name = event.currentTarget.dataset.name;
+    wx.switchTab({
+      url: `/pages/${name}/${name}`,
+    });
+  },
+  onLoad: function (options) {
+    // 页面初始化 options为页面跳转所带来的参数
+    this.getData();
+    this.getFootCart();
+
+  },
+  onReady: function () {
+    // 页面渲染完成
+  },
+  onShow: function () {
+    // 页面显示
+
+  },
+  onHide: function () {
+    // 页面隐藏
+
+  },
+  onUnload: function () {
+    // 页面关闭
+
+  },
+  openSortFilter: function (event) {
+    let currentId = event.currentTarget.id;
+    switch (currentId) {
+      case 'categoryFilter':
+        this.setData({
+          'categoryFilter': !this.data.categoryFilter,
+          'currentSortType': 'category',
+          'currentSortOrder': 'asc'
+        });
+        break;
+      case 'priceSort':
+        let tmpSortOrder = 'asc';
+        if (this.data.currentSortOrder == 'asc') {
+          tmpSortOrder = 'desc';
+        }
+        this.setData({
+          'currentSortType': 'price',
+          'currentSortOrder': tmpSortOrder,
+          'categoryFilter': false
+        });
+
+        this.getData();
+        break;
+      default:
+        //综合排序
+        this.setData({
+          'currentSortType': 'default',
+          'currentSortOrder': 'desc',
+          'categoryFilter': false
+        });
+        this.getData();
+    }
+  },
+  selectCategory: function(event){
+    let that = this;
+    let currentIndex = event.target.dataset.categoryIndex;
+    this.setData({
+      categoryFilter: false,
+      categoryId: this.data.filterCategory[currentIndex].id
+    });
+    this.getData();
+  },
+  getFootCart: function () {
+    let that = this;
+    util.request(api.GetFootCart).then(function (res) {
+      if (res.errno === 0) {
+        that.setData({
+          footCart: res.data,
+        });
+      }
+    });
+  },
+  switchAttrPop: function () {
+    this.setData({
+      openAttr: !this.data.openAttr
+    })
+  },
+  //购物车增加
+  addCart: function (e) {
+    let that = this;
+    that.setData({
+      number: 1
+    });
+    var goodsId = e.currentTarget.dataset.goodsId;
+    var retailPrice = e.currentTarget.dataset.retailPrice; 
+    util.request(api.GoodsSku, {
+      goodsId: goodsId
+    }).then(function (res) {
+      if (res.errno === 0 && null != res.data) {
+        that.setData({
+          goodsVo: res.data.goodsVo,
+          specificationList: res.data.specificationList,
+          productList: res.data.productList,
+          openAttr: !that.data.openAttr,
+          retailPrice: retailPrice,
+          stockNum: res.data.productList[0].stock_num,
+          cartNumber: res.data.cartNumber,
+          checkedSpecText: res.data.specificationList[0].valueList[0].value
+        });
+        //
+        let _specificationList = res.data.specificationList;
+        for (let i = 0; i < _specificationList.length; i++) {
+          if (_specificationList[i].valueList.length == 1) {
+            //如果已经选中,则反选
+            _specificationList[i].valueList[0].checked = true;
+          }
+        }
+        that.setData({
+          'specificationList': _specificationList
+        });
+
+      }
+    });
+  },
+  clickSkuValue: function (event) {
+    let that = this;
+    let specValueId = event.currentTarget.dataset.valueId;
+    let index = event.currentTarget.dataset.index;
+    let _specificationList = this.data.specificationList;
+    for (let j = 0; j < _specificationList[index].valueList.length; j++) {
+      if (_specificationList[index].valueList[j].id == specValueId) {
+        //如果已经选中,则反选
+        if (_specificationList[index].valueList[j].checked) {
+          _specificationList[index].valueList[j].checked = false;
+        } else {
+          _specificationList[index].valueList[j].checked = true;
+        }
+      } else {
+        _specificationList[index].valueList[j].checked = false;
+      }
+    }
+    this.setData({
+      'specificationList': _specificationList
+    });
+    //重新计算spec改变后的信息
+    goodsUtil.changeSpecInfo(that);
+  },
+  cutNumber: function () {
+    this.setData({
+      number: (this.data.number - 1 > 1) ? this.data.number - 1 : 1
+    });
+  },
+  addNumber: function () {
+    this.setData({
+      number: this.data.number + 1
+    });
+  },
+  //购物车增加
+  addToCart: function () {
+    let that = this;
+    var goodsId = that.data.goodsVo.id;
+    //提示选择完整规格
+    if (!that.data.productList || !that.data.productList.length) {
+      util.showErrorToast('当前门店没有库存');
+      return false;
+    }
+    //提示选择完整规格
+    if (!goodsUtil.isCheckedAllSpec(that)) {
+      return false;
+    }
+    //根据选中的规格,判断是否有对应的sku信息
+    let checkedProduct = goodsUtil.getCheckedProductItem(goodsUtil.getCheckedSpecKey(that), that);
+    if (!checkedProduct || checkedProduct.length <= 0) {
+      //找不到对应的product信息,提示没有库存
+      return false;
+    }
+    //验证库存
+    if (checkedProduct.stock_num < this.data.number) {
+      //找不到对应的product信息,提示没有库存
+      return false;
+    }
+    util.request(api.CartAdd, {
+      goodsId: goodsId,
+      productId: checkedProduct[0].id,
+      number: this.data.number
+    }, 'POST').then(function (res) {
+      if (res.errno === 0 && null != res.data) {
+        wx.showToast({
+          title: '添加成功',
+          icon: 'success',
+          mask: true
+        });
+        that.setData({
+          openAttr: !that.data.openAttr
+        })
+        that.getFootCart();
+      } else {
+        wx.showToast({
+          title: res.errmsg,
+          icon: 'none'
+        })
+      }
+    });
+  },
+})

+ 3 - 0
wx-mall-hk/pages/hotGoods/hotGoods.json

@@ -0,0 +1,3 @@
+{
+    
+}

+ 128 - 0
wx-mall-hk/pages/hotGoods/hotGoods.wxml

@@ -0,0 +1,128 @@
+<view class="container">
+  <view class="cart-panel" wx:if="{{footCart.goodsCount>0}}">
+    <view class="cart-icon">
+      <navigator class="nav-cell" open-type='switchTab' url="/pages/cart/cart">
+        <image src="../../static/images/cart-fixed.png">
+        </image>
+      </navigator>
+      <view class="cart-num" bindtap="switchNav" data-name="cart">{{footCart.goodsCount}}</view>
+    </view>
+    <view class="cart-body" bindtap="switchNav" data-name="cart">¥{{footCart.checkedGoodsAmount}}</view>
+    <navigator class="nav-cell" open-type='switchTab' url="/pages/cart/cart">
+      <view class="cart-pay">去结算 > </view>
+    </navigator>
+  </view>
+  <view wx:if="{{showNavList}}" class="modal-wrap"></view>
+  <view class="fast-nav">
+    <contact-button wx:if="{{!showNavList}}" class="contact" size="25" type="primary" session-from="weapp">
+      <text>找客服</text>
+    </contact-button>
+    <view wx:if="{{!showNavList}}" class="nav" bindtap="toggleNav">
+      <text>快捷</text>
+      <text>导航</text>
+    </view>
+    <view class="nav-list" wx:if="{{showNavList}}">
+      <view class="nav-item">
+        <text class="nav-text">首页</text>
+        <view class="nav-cell" bindtap="switchNav" data-name="index">
+          <image src="../../static/images/nav-1.png"></image>
+        </view>
+      </view>
+      <view class="nav-item">
+        <text class="nav-text">足迹</text>
+        <navigator class="nav-cell" url="../ucenter/footprint/footprint">
+          <image src="../../static/images/nav-2.png"></image>
+        </navigator>
+      </view>
+      <view class="nav-item">
+        <text class="nav-text">搜索</text>
+        <navigator class="nav-cell" url="../search/search">
+          <image src="../../static/images/nav-3.png"></image>
+        </navigator>
+      </view>
+      <view class="nav-item">
+        <text class="nav-text">购物车</text>
+        <view class="nav-cell" bindtap="switchNav" data-name="cart">
+          <image src="../../static/images/nav-4.png"></image>
+        </view>
+      </view>
+    </view>
+    <view wx:if="{{showNavList}}" class="close" bindtap="toggleNav">X</view>
+  </view>
+  <view class="brand-info">
+    <view class="name">
+      <image class="img" src="{{bannerInfo.img_url}}"></image>
+      <view class="info-box">
+        <view class="info">
+          <text class="txt">{{bannerInfo.name}}</text>
+          <text class="line"></text>
+        </view>
+      </view>
+    </view>
+  </view>
+  <view class="sort">
+    <view class="sort-box">
+      <view class="item {{currentSortType == 'default' ? 'active' : ''}}" bindtap="openSortFilter" id="defaultSort">
+        <text class="txt">综合</text>
+      </view>
+      <view class="item by-price {{currentSortType == 'price' ? 'active' : ''}} {{currentSortOrder == 'asc'  ? 'asc' : 'desc'}}" bindtap="openSortFilter" id="priceSort">
+        <text class="txt">价格</text>
+      </view>
+      <view class="item {{currentSortType == 'category' ? 'active' : ''}}" bindtap="openSortFilter" id="categoryFilter">
+        <text class="txt">分类</text>
+      </view>
+    </view>
+    <view class="sort-box-category" wx-if="{{categoryFilter}}">
+      <view class="item {{item.checked ? 'active' : ''}}" wx:for="{{filterCategory}}" wx:key="cate-{{item.id}}" data-category-index="{{index}}" bindtap="selectCategory">{{item.name}}</view>
+    </view>
+  </view>
+  <view class="cate-item">
+    <view class="b">
+      <block wx:for="{{goodsList}}" wx:for-index="iindex" wx:for-item="iitem" wx:key="unique">
+        <view class="item {{iindex % 2 == 0 ? 'item-b' : '' }}">
+
+          <navigator url="../goods/goods?id={{iitem.id}}">
+            <image class="img" src="{{iitem.list_pic_url}}" ></image>
+            <text class="name">{{iitem.name}}</text>
+          </navigator>
+
+          <view class="price">¥{{iitem.retail_price}}
+            <image class="cart" src="/static/images/cart.png" data-goods-id="{{iitem.id}}" data-retail-price="{{iitem.retail_price}}" bindtap='addCart' background-size="cover"></image>
+          </view>
+        </view>
+      </block>
+    </view>
+  </view>
+
+  <view wx:if="{{openAttr}}" class="attr-pop">
+    <view class="attr-close" bindtap="switchAttrPop">X</view>
+    <view class="img-info">
+      <image class="img" src="{{goodsVo.list_pic_url}}"></image>
+      <view class="info">
+        <view class="c">
+          <view class="p">价格:¥{{retailPrice}}</view>
+          <view class="a" wx:if="{{productList.length>0}}">已选择:{{checkedSpecText}}</view>
+        </view>
+      </view>
+    </view>
+    <view class="spec-con">
+      <view class="spec-item" wx:for="{{specificationList}}" wx:key="{{item.specification_id}}" wx:for-index="itemIndex">
+        <view class="name">{{item.name}}</view>
+        <view class="values">
+          <view class="value {{vitem.checked ? 'selected' : ''}}" bindtap="clickSkuValue" wx:for="{{item.valueList}}" wx:for-item="vitem" wx:key="{{vitem.id}}" data-index="{{itemIndex}}" data-value-id="{{vitem.id}}" data-name-id="{{vitem.specification_id}}">{{vitem.value}}</view>
+        </view>
+      </view>
+      <view class="number-item">
+        <view class="name">数量</view>
+        <view class="selnum">
+          <view class="cut" bindtap="cutNumber">-</view>
+          <input value="{{number}}" class="number" disabled="true" type="number" />
+          <view class="{{number+cartNumber>= stockNum? 'addEnabel':'add'}}" bindtap="{{number+cartNumber>= stockNum ? '':'addNumber'}}">+</view>
+        </view>
+      </view>
+    </view>
+    <view class="bottom-btn">
+      <view class="r" bindtap="addToCart">加入购物车</view>
+    </view>
+  </view>
+</view>

+ 349 - 0
wx-mall-hk/pages/hotGoods/hotGoods.wxss

@@ -0,0 +1,349 @@
+page{
+    background: #f4f4f4;
+}
+
+.brand-info .name{
+    width: 100%;
+    height: 278rpx;
+    position: relative;
+}
+
+.brand-info .img{
+    position: absolute;
+    top:0;
+    left:0;
+    width: 100%;
+    height: 278rpx;
+}
+
+.brand-info .info-box{
+    position: absolute;
+    top:0;
+    left:0;
+    width: 100%;
+    height: 278rpx;
+    text-align: center;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+}
+
+.brand-info .info{
+    display: block;
+}
+
+.brand-info .txt{
+    display: block;
+    height: 40rpx;
+    font-size: 37.5rpx;
+    color: #fff;
+}
+
+.brand-info .line{
+    margin: 0 auto;
+    margin-top: 16rpx;
+    display: block;
+    height: 2rpx;
+    width: 145rpx;
+    background: #fff;
+}
+
+.sort{
+    position: relative;
+    background: #fff;
+    width: 100%;
+    height: 78rpx;
+}
+
+.sort-box{
+    background: #fff;
+    width: 100%;
+    height: 78rpx;
+    overflow: hidden;
+    padding: 0 30rpx;
+    display: flex;
+    border-bottom: 1px solid #d9d9d9;
+}
+
+.sort-box .item{
+    height: 78rpx;
+    line-height: 78rpx;
+    text-align: center;
+    flex:1;
+    color: #333;
+    font-size: 30rpx;
+}
+
+.sort-box .item .txt{
+    display: block;
+    width: 100%;
+    height: 100%;
+    color: #333;
+}
+
+.sort-box .item.active .txt{
+    color: #b4282d;
+}
+
+.sort-box .item.by-price{
+    background: url(http://120.76.26.84:80/group1/M00/00/02/rBJEdVvr3CSAazwCAAABD1aCMbo520.png) 155rpx center no-repeat;
+    background-size: 15rpx 21rpx;
+}
+
+.sort-box .item.by-price.active.asc{
+    background: url(http://120.76.26.84:80/group1/M00/00/02/rBJEdVvr3FOACHzqAAABHU5MD_M687.png) 155rpx center no-repeat;
+    background-size: 15rpx 21rpx;
+}
+
+.sort-box .item.by-price.active.desc{
+    background: url(http://120.76.26.84:80/group1/M00/00/02/rBJEdVvr3JCAcOP5AAABdVcSS6A457.png) 155rpx center no-repeat;
+    background-size: 15rpx 21rpx;
+}
+
+.sort-box-category{
+    background: #fff;
+    width: 100%;
+    height: auto;
+    overflow: hidden;
+    padding: 40rpx 40rpx 0 0;
+    border-bottom: 1px solid #d9d9d9;
+}
+
+.sort-box-category .item{
+    height: 54rpx;
+    line-height: 54rpx;
+    text-align: center;
+    float: left;
+    padding: 0 16rpx;
+    margin: 0 0 40rpx 40rpx;
+    border: 1px solid #666;
+    color: #333;
+    font-size: 24rpx;
+}
+
+.sort-box-category .item.active{
+    color: #b4282d;
+    border: 1px solid #b4282d;
+}
+
+.cate-item .b{
+  width: 750rpx;
+  height: auto;
+  overflow: hidden;
+  border-top: 1rpx solid #f4f4f4;
+  margin-top: 20rpx;
+  margin-bottom: 120rpx;
+}
+
+.cate-item .b .item{
+  float: left;
+  background: #fff;
+  width: 375rpx;
+  padding-bottom: 33.333rpx;
+  border-bottom: 1rpx solid #f4f4f4;
+  height: auto;
+  overflow: hidden;
+  text-align: center;
+}
+
+.cate-item .b .item-b{
+ border-right: 1rpx solid #f4f4f4;
+}
+
+.cate-item .item .img{
+  margin-top: 10rpx;
+  width: 302rpx;
+  height: 302rpx;
+  background-size:202rpx 202rpx;
+}
+
+.cate-item .item .name{
+  display: block;
+  width: 365.625rpx;
+  height: 70rpx;
+  padding: 0 20rpx;
+  margin: 11.5rpx 0 22rpx 0;
+  text-align: center;
+  font-size: 26rpx;
+  color: #333;
+}
+
+.cate-item .item .price{
+  display: block;
+  width: 365.625rpx;
+  height: 30rpx;
+  text-align: center;
+  font-size: 30rpx;
+  color: #b4282d;
+}
+.cate-item .item .price .cart{
+  margin-left: 20rpx;
+  width: 35rpx;
+  height: 35rpx;
+  vertical-align: -6rpx;
+}
+
+
+.attr-pop {
+  width: 100%;
+  height: auto;
+  padding: 31.25rpx;
+  background: #fff;
+  position: fixed;
+  bottom: 100rpx;
+  z-index: 500;
+}
+
+.attr-close{
+  float: right;
+  width: 40rpx;
+  height: 40rpx;
+  line-height: 40rpx;
+  border-radius: 50%;
+  font-size: 40rpx;
+  text-align: center;
+  overflow: hidden;
+}
+
+.attr-pop .img-info {
+  width: 687.5rpx;
+  height: 177rpx;
+  overflow: hidden;
+  margin-bottom: 41.5rpx;
+}
+
+.attr-pop .img {
+  float: left;
+  height: 177rpx;
+  width: 177rpx;
+  background: #f4f4f4;
+  margin-right: 31.25rpx;
+}
+
+.attr-pop .info {
+  float: left;
+  height: 177rpx;
+  display: flex;
+  align-items: flex-start;
+}
+
+.attr-pop .p {
+  font-size: 33rpx;
+  color: #333;
+  height: 33rpx;
+  line-height: 33rpx;
+  margin-bottom: 10rpx;
+}
+
+.attr-pop .a {
+  font-size: 29rpx;
+  color: #333;
+  height: 40rpx;
+  line-height: 40rpx;
+  width: 260px;
+  display:block;
+  word-break: break-all;
+  word-wrap: break-word;
+}
+
+.spec-con {
+  width: 100%;
+  height: auto;
+  overflow: hidden;
+}
+
+.spec-con .name {
+  height: 32rpx;
+  margin-bottom: 22rpx;
+  font-size: 29rpx;
+  color: #333;
+}
+
+.spec-con .values {
+  height: auto;
+  margin-bottom: 31.25rpx;
+  font-size: 0;
+}
+
+.spec-con .value {
+  display: inline-block;
+  height: 62rpx;
+  padding: 0 35rpx;
+  line-height: 56rpx;
+  text-align: center;
+  margin-right: 25rpx;
+  margin-bottom: 16.5rpx;
+  border: 1px solid #333;
+  font-size: 25rpx;
+  color: #333;
+}
+
+.spec-con .value.disable {
+  border: 1px solid #ccc;
+  color: #ccc;
+}
+
+.spec-con .value.selected {
+  border: 1px solid #b4282d;
+  color: #b4282d;
+}
+
+.number-item .selnum {
+  width: 322rpx;
+  height: 71rpx;
+  border: 1px solid #ccc;
+  display: flex;
+}
+
+.number-item .cut {
+  width: 93.75rpx;
+  height: 100%;
+  text-align: center;
+  line-height: 65rpx;
+}
+
+.number-item .number {
+  flex: 1;
+  height: 100%;
+  text-align: center;
+  line-height: 68.75rpx;
+  border-left: 1px solid #ccc;
+  border-right: 1px solid #ccc;
+  float: left;
+}
+
+.number-item .add {
+  width: 93.75rpx;
+  height: 100%;
+  text-align: center;
+  line-height: 65rpx;
+}
+
+.bottom-btn {
+  position: fixed;
+  left: 0;
+  bottom: 0;
+  z-index: 10;
+  width: 750rpx;
+  height: 100rpx;
+  display: flex;
+  background: #fff;
+}
+
+.bottom-btn .r {
+  border: 1px solid #b4282d;
+  background: #b4282d;
+  float: left;
+  height: 100rpx;
+  line-height: 96rpx;
+  flex: 1;
+  text-align: center;
+  color: #fff;
+}
+.addEnabel {
+  width: 93.75rpx;
+  height: 100%;
+  text-align: center;
+  line-height: 65rpx;
+  color: #ccc;
+}

+ 384 - 0
wx-mall-hk/pages/index/index.js

@@ -0,0 +1,384 @@
+const util = require('../../utils/util.js');
+const api = require('../../config/api.js');
+const user = require('../../services/user.js');
+
+//获取应用实例
+const app = getApp();
+Page({
+    data: {
+        groupGoods: [],
+        hotGoods: [],
+        topics: [],
+        brands: [],
+        floorGoods: [],
+        banner: [],
+        channel: [],
+        groupBanner: {},
+        storeName: '',
+        showPop: false,//活动弹窗
+        couponVo: {},
+        storeId: ''
+    },
+    showCouponPop() {
+        let that = this;
+        this.setData({
+            showPop: false
+        });
+        // wx.showToast({
+        //   title: '恭喜获取优惠券一张' + that.data.couponVo.name,
+        //   duration: 2000
+        // });
+        wx.showModal({
+            title: '获取优惠券一张',
+            showCancel: false,
+            content: that.data.couponVo.name
+        })
+    },
+    onShareAppMessage: function () {
+        return {
+            title: '商业版',
+            desc: '新人好礼送券',
+            path: '/pages/index/index'
+        }
+    },
+    getIndexData: function () {
+        let that = this;
+        util.request(api.IndexUrl).then(function (res) {
+            if (res.errno === 0) {
+                // console.log(res.data.banner);
+                that.setData({
+                    // newGoods: res.data.newGoodsList,
+                    hotGoods: res.data.hotGoodsList,
+                    // topics: res.data.topicList,
+                    // brand: res.data.brandList,
+                    // floorGoods: res.data.categoryList,
+                    banner: res.data.banner,
+                    // groupBanner: res.data.groupBanner,
+                    channel: res.data.channel
+                });
+            }
+        });
+    },
+    getGroupData: function () {
+        let that = this;
+        util.request(api.GroupList).then(function (res) {
+            if (res.errno === 0) {
+                that.setData({
+                    groupGoods: res.data.data,
+                });
+            }
+        });
+    },
+    onLoad: function (options) {
+        let that = this;
+        wx.setStorageSync("navUrl", "/pages/index/index");
+    },
+    onReady: function () {
+        // 页面渲染完成
+    },
+    onShow: function () {
+        // 页面显示
+        let that = this;
+        wx.setStorageSync("navUrl", "/pages/index/index");
+        if (wx.getStorageSync('userInfo') || wx.getStorageSync('token')) {
+            that.syncStore();
+        } else {
+            wx.navigateTo({
+                url: '/pages/auth/btnAuth/btnAuth',
+            })
+        }
+    },
+    onHide: function () {
+        // 页面隐藏
+    },
+    onUnload: function () {
+        // 页面关闭
+    },
+    handleStore() {
+        wx.navigateTo({
+            url: '../map/map',
+        })
+    },
+    goSearch() {
+        wx.navigateTo({
+            url: '../search/search',
+        })
+    },
+    goCatalog: function (e) {
+        let url = '';
+        // console.log('dataset.goodsBizType:' + e.currentTarget.dataset.goodsBizType);
+        app.globalData.appGoodsBizType = e.currentTarget.dataset.goodsBizType;
+        // console.log('appgoodsBizType1:' + app.globalData.appGoodsBizType);
+
+        wx.switchTab({
+            url: '/pages/catalog/catalog',
+        });
+    },
+    onReachBottom: function () {
+
+        if (this.data.bottomLoadDone === true || this.data.bottomLoading === true) {
+            return false;
+        }
+
+        this.setData({
+            bottomLoading: true
+        });
+
+        // this.getFloorCategory();
+    },
+    reLoad: function () {
+        let that = this;
+        if (wx.getStorageSync('storeId')) {
+            // console.log(wx.getStorageSync('userId'));
+            console.log(wx.getStorageSync('storeId'));
+            // console.log(wx.getStorageSync('merchSn'));
+            if (wx.getStorageSync('userId')){
+                wx.request({
+                    url: api.updateLoginUser,
+                    data: {
+                        userId: wx.getStorageSync('userId'), storeId: wx.getStorageSync('storeId'), merchSn: wx.getStorageSync('merchSn')
+                    },
+                    method: 'POST',
+                    header: {
+                        'Content-Type': 'application/json'
+                    },
+                    success: function (wxRes) {
+                        if (wxRes.data.errno === 0) {
+                            // console.log("用户信息更新成功");
+                        }
+                    },
+                    fail: function (err) {
+                        console.log("failed");
+                    }
+                });
+            }
+            that.getIndexData();
+            that.enableActivity();
+            that.getGroupData();
+        }
+    },
+    // 同步门店
+    syncStore: function () {
+        let that = this;
+        //获取附件门店信息
+        util.getLocation((lng, lat) => {
+            wx.setStorageSync('location', JSON.stringify({ lng, lat }));
+        util.request(api.NearbyList, { longitude: lng, latitude: lat }).then((res) => {
+            let nlist = res.data;
+        // console.log(nlist);
+        if (!nlist.length) {
+            wx.removeStorageSync('nearStoreList');
+        } else {
+            wx.setStorageSync('nearStoreList', JSON.stringify(nlist));
+        }
+        if (!wx.getStorageSync('storeId')) {
+            if (!nlist.length) {
+                wx.removeStorageSync('storeId');
+                wx.removeStorageSync('storeVo');
+                that.setData({
+                    storeName: '附近暂无门店'
+                })
+            } else {
+                that.setData({
+                    storeName: nlist[0].storeName,
+                    storeId: nlist[0].id
+                })
+                that.chooseStore(nlist[0].id, nlist[0].merchSn);
+                wx.setStorageSync('storeVo', JSON.stringify(nlist[0]));
+            }
+        } else {
+            var storeVo = JSON.parse(wx.getStorageSync('storeVo'));
+            that.chooseStore(storeVo.id, storeVo.merchSn);
+            that.setData({
+                storeName: storeVo.storeName,
+                storeId: storeVo.id
+            });
+        }
+    })
+    });
+
+    },
+    // 更新门店Id
+    chooseStore: function (storeId,merchSn) {
+        let that = this;
+        util.request(api.ChooseStoreId, { storeId: storeId, merchSn: merchSn }, 'POST').then(function (res) {
+            if (res.errno === 0) {
+                wx.setStorageSync('storeId', storeId);
+                wx.setStorageSync('merchSn', merchSn);
+                that.reLoad();
+            }
+        });
+    },
+    //购物车减少
+    cutNumber: function (e) {
+        let that = this;
+        var goodsId = e.currentTarget.dataset.goodsId;
+        var productId = e.currentTarget.dataset.productId;
+
+        var hotGoods = that.data.hotGoods;
+        // hotGoods.forEach(function (val, index, arr) {
+        //   if (val.product_id == productId) {
+        //     val.cart_num = val.cart_num - 1;
+        //     if (val.cart_num >= 0) {
+        //       hotGoods[index] = val;
+        //     }
+        //   }
+        // });
+        // that.setData({ hotGoods: hotGoods });
+        util.request(api.CartMinus, { goodsId: goodsId, productId: productId, number: 1 }, 'POST').then(function (res) {
+            if (res.errno === 0 && null != res.data) {
+                var hotGoods = that.data.hotGoods;
+                hotGoods.forEach(function (val, index, arr) {
+                    if (val.product_id == productId) {
+                        val.cart_num = res.data;
+                        hotGoods[index] = val;
+                        that.setData({ hotGoods: hotGoods });
+                    }
+                }, that);
+            }
+        });
+    },
+    //购物车增加
+    addNumber: function (e) {
+        let that = this;
+        var goodsId = e.currentTarget.dataset.goodsId;
+        var productId = e.currentTarget.dataset.productId;
+        var hotGoods = that.data.hotGoods;
+        // hotGoods.forEach(function (val, index, arr) {
+        //   if (val.product_id == productId) {
+        //     val.cart_num = val.cart_num + 1;
+        //     hotGoods[index] = val;
+        //   }
+        // });
+        // that.setData({ hotGoods: hotGoods });
+        util.request(api.CartAdd, { goodsId: goodsId, productId: productId, number: 1 }, 'POST').then(function (res) {
+            if (res.errno === 0 && null != res.data) {
+                hotGoods.forEach(function (val, index, arr) {
+                    res.data.cartList.forEach(function (cartVal, cartIndex, cartArr) {
+                        if (val.product_id == cartVal.product_id) {
+                            val.cart_num = cartVal.number;
+                            hotGoods[index] = val;
+                        }
+                    });
+                    that.setData({ hotGoods: hotGoods });
+                }, that);
+            } else {
+                wx.showToast({
+                    title: res.errmsg,
+                    icon: 'none'
+                })
+            }
+        });
+    },
+    // 查询是否有活动
+    enableActivity: function () {
+        let that = this;
+        let couponIds = wx.getStorageSync('couponIds');
+        if (!couponIds) {
+            couponIds = new Array();
+        }
+        util.request(api.EnableActivity, { couponIds: couponIds }).then(function (res) {
+            // if (res.errno === 0 && null != res.data.showCoupon) {
+            //   if (couponIds.contains(res.data.showCoupon.id)) {
+            //     return;
+            //   }
+            //   couponIds.push(res.data.showCoupon.id);
+            //   wx.setStorageSync('couponIds', couponIds);
+            //   that.setData({
+            //     couponVo: res.data.showCoupon,
+            //     showPop: true
+            //   });
+            // } else
+            if (res.errno === 0 && null != res.data.takeCoupon && null != res.data.takeCoupon.id) {
+                that.setData({
+                    couponVo: res.data.takeCoupon,
+                    showPop: true
+                });
+            }
+        });
+    },
+    // 商品扫码
+    scanGoodsCode: function (e) {
+        var that = this;
+        var code;
+        var value;
+        var substrValue;
+        var scanType;
+        // 调起客户端扫码界面进行扫码
+        wx.scanCode({
+            // 是否只能从相机扫码
+            onlyFromCamera: true,
+            // 扫码类型, barCode:一维码, qrCode:二维码
+            scanType: ['barCode', 'qrCode'],
+            success: function (res) {
+                that.code = "结果:" + res.result + ",路径:" + res.path + ",编码:" + res.rawData;
+                that.value = res.result;
+                that.scanType = res.scanType;
+                that.setData({
+                    goodsCode: that.code
+                });
+
+                if (that.scanType == 'QR_CODE') {//二维码
+                    that.substrValue = that.value.substring(0, 5);
+                    that.value = that.value.substring(5, that.value.length);
+                    var goodId = that.value.substring(18, that.value.length);
+
+                    if (that.substrValue != 'emato') {//../goods/goods?id=
+                        wx.showModal({
+                            title: '',
+                            content: '您所扫描的商品无效',
+                            showCancel: false,
+                            success: function (res) {
+                                if (res.confirm) {
+                                    console.log('用户点击确定')
+                                } else if (res.cancel) {
+                                    console.log('用户点击取消')
+                                }
+                            }
+                        });
+                    } else {
+
+                        util.request(api.GoodsDetail, { id: goodId, referrer: '' }).then(function (res) {
+                            if (res.errno === 0) {
+                                // 跳转页面
+                                wx.navigateTo({
+                                    url: that.value,
+                                    success: function (e) {
+                                        console.log('跳转成功');
+                                    },
+                                    fail: function (e) {
+                                        console.log('跳转失败');
+                                    }
+                                })
+                            } else {
+                                wx.showModal({
+                                    title: '扫描结果',
+                                    content: '商品不存在',
+                                    showCancel: false
+                                });
+                            }
+                        });
+                    }
+                }else{//其他码
+                    //弹框显示结果
+                    wx.showModal({
+                        title: '扫描结果',
+                        content: that.value,
+                        showCancel: false
+                    });
+                }
+            },
+
+            fail: function () {
+                // 显示提示框
+                wx.showToast({
+                    title: '扫码失败',
+                    icon: 'none',
+                    // 提示的延迟时间
+                    duration: 3000
+                })
+            }
+
+        })
+    }
+})

+ 1 - 0
wx-mall-hk/pages/index/index.json

@@ -0,0 +1 @@
+{}

+ 213 - 0
wx-mall-hk/pages/index/index.wxml

@@ -0,0 +1,213 @@
+<!--index.wxml-->
+<view class="container">
+
+<template name="dialog">
+</template>
+
+  <view class="modal-wrap" wx:if="{{showPop}}" bindtap="showCouponPop">
+    <view class="discount-dialog">
+      <!-- <view class="dialog-title">{{couponVo.name}}</view> -->
+      <view class="image-box">
+        <image wx:if="{{!couponVo.pic_url}}" src="/static/images/discount.png"></image>
+        <image wx:if="{{couponVo.pic_url}}" src="{{couponVo.pic_url}}"></image>
+      </view>
+      <view>
+        <text bindtap="showCouponPop" class="dialog-close x-close"></text>
+      </view>
+    </view>
+  </view>
+
+  <view class="search-header">
+    <view class="input-box">
+    <input name="input" class="keywrod" value="搜索商品" confirm-type="search" bindtap="goSearch" />
+    </view>
+    <image src="../../static/images/service-sao.png" class="search-icon-shop" bindtap="scanGoodsCode"></image>
+  </view>
+  <view class="home-header">
+    <view bindtap="handleStore" class="current-store arrow arrow-down">{{ storeName }}</view>
+  </view>
+
+  <swiper class="banner" indicator-dots="true" autoplay="true" interval="15000" duration="750">
+    <swiper-item wx:for="{{banner}}" wx:key="{{item.id}}">
+      <navigator url="{{item.link}}">
+        <image class="swiper-item" src="{{item.imageUrl}}" background-size="cover"></image>
+      </navigator>
+    </swiper-item>
+  </swiper>
+  <view class="m-menu">
+    <navigator class="itemb" bindtap="goCatalog" data-goods-Biz-Type="00">
+      <image src="../../static/images/service-bao.png" background-size="cover"></image>
+      <text>保税仓</text>
+    </navigator>
+    <!-- <navigator class="itemb" bindtap="goCatalog" data-goods-Biz-Type="02">
+      <image src="../../static/images/service-zs.png" background-size="cover"></image>
+      <text>保税展示</text>
+    </navigator>
+    <navigator class="itemb" bindtap="goCatalog" data-goods-Biz-Type="10">
+      <image src="../../static/images/service-ziti.png" background-size="cover"></image>
+      <text>现场速递</text>
+    </navigator> -->
+    <navigator class="itemb" bindtap="goCatalog" data-goods-Biz-Type="11">
+      <image src="../../static/images/service-ptsp.png" background-size="cover"></image>
+      <text>普通商品</text>
+    </navigator>
+    <navigator class="itemb" bindtap="scanGoodsCode">
+      <image src="../../static/images/service-smgw.png" background-size="cover"></image>
+      <text>扫码购物</text>
+    </navigator>
+
+  </view>
+  <!-- <view class="m-menu">
+    <navigator class="item" url="{{item.url}}" wx:for="{{channel}}" wx:key="{{item.id}}">
+      <image src="{{item.icon_url}}" background-size="cover"></image>
+      <text>{{item.name}}</text>
+    </navigator>
+  </view> -->
+  <!-- <view class="a-section a-brand">
+    <view class="h">
+      <navigator url="../brand/brand">
+        <text class="txt">品牌制造商直供</text>
+      </navigator>
+    </view>
+    <view class="b">
+      <view class="item item-1" wx:for="{{brand}}" wx:key="item.id">
+        <navigator url="/pages/brandDetail/brandDetail?id={{item.id}}">
+          <view class="wrap">
+            <image class="img" src="{{item.new_pic_url}}" mode="aspectFill"></image>
+            <view class="mt">
+              <text class="brand">{{item.name}}</text>
+              <text class="price">{{item.floor_price}}</text>
+              <text class="unit">元起</text>
+            </view>
+          </view>
+        </navigator>
+      </view>
+    </view>
+  </view> -->
+  <!-- <view class="a-section a-topic">
+    <view class="h">
+      <view>
+        <navigator url="../group/group">
+          <text class="txt">团购精选</text>
+        </navigator>
+      </view>
+    </view>
+    <view class="b">
+      <scroll-view scroll-x="true" class="list">
+        <view class="item">
+          <navigator url="../group/group">
+            <image class="img" src="{{groupBanner.image_url}}" wx:if="{{groupBanner.id > 0}}"></image>
+            <image class="img" src="../../static/imgys/taungou.jpg" wx:if="{{groupBanner.id < 1}}"></image>
+          </navigator>
+        </view>
+      </scroll-view>
+    </view>
+  </view> -->
+
+  <!-- <view class="a-section a-new" wx:if="{{groupGoods.length > 0}}">
+    <view class="h">
+      <view>
+        <navigator open-type='switchTab' url="../group/group">
+          <text class="txt">团购</text>
+        </navigator>
+      </view>
+    </view>
+    <view class="topic-list">
+      <navigator class="group-box" wx:for="{{groupGoods}}" wx:key="{{item.id}}" wx:if="{{index<3}}" url="../groupDetail/groupDetail?id={{item.id}}">
+        <image class="img" src="{{item.item_pic_url}}"></image>
+        <view class="imgline">
+          <view class="title">{{item.title}}</view>
+          <view class="desc">{{item.subtitle}}</view>
+          <view class="priceInfo">最低开团价:
+            <text class="price">¥{{item.retail_min_price}}</text>
+            <text class="orgPrice line-through">¥{{item.retail_price}}</text>
+          </view>
+          <view class="btn-view">
+            <view class="surplus">还剩余{{item.stock_num}}件</view>
+            <button class="btn">立即开团</button>
+          </view>
+        </view>
+      </navigator>
+    </view>
+  </view> -->
+
+  <!-- <view class="a-section a-new" wx:if="{{newGoods.length > 0}}">
+    <view class="h">
+      <view>
+        <navigator url="../newGoods/newGoods">
+          <text class="txt">周一周四 · 新品首发</text>
+        </navigator>
+      </view>
+    </view>
+    <view class="b">
+      <view class="item" wx:for="{{newGoods}}" wx:for-index="index" wx:for-item="item" wx:key="{{item.id}}">
+        <navigator url="../goods/goods?id={{item.id}}">
+          <image class="img" src="{{item.list_pic_url}}" background-size="cover"></image>
+          <text class="name">{{item.name}}</text>
+          <text class="price">¥{{item.retail_price}}</text>
+        </navigator>
+      </view>
+    </view>
+  </view> -->
+  <view class="a-section a-popular" wx:if="{{hotGoods.length > 0}}">
+    <view class="h">
+      <view>
+        <navigator url="../hotGoods/hotGoods">
+          <text class="txt">今日热销</text>
+        </navigator>
+      </view>
+    </view>
+    <view class="b">
+      <view class="item" wx:for="{{hotGoods}}" wx:for-index="index" wx:for-item="item" wx:key="{{item.id}}">
+        <navigator url="/pages/goods/goods?id={{item.id}}">
+          <image class="img" src="{{item.list_pic_url}}"></image>
+        </navigator>
+        <view class="right">
+          <view class="text">
+            <navigator url="/pages/goods/goods?id={{item.id}}">
+              <text class="name">{{item.name?item.name:""}}</text>
+              <text class="desc">{{item.goods_brief?item.goods_brief:""}}</text>
+            </navigator>
+            <view class="goods-do">
+              <text class="price">{{item.retail_price?"¥"+item.retail_price:"0"}}</text>
+              <text class="org-price line-through">{{item.market_price?"¥"+item.market_price:""}}</text>
+              <!-- //数量加减 -->
+              <view class="number-item">
+                <view class="selnum">
+                  <view class="cut" data-goods-id="{{item.id}}" data-product-id="{{item.product_id}}" bindtap="cutNumber"></view>
+                  <input value="{{item.cart_num}}" class="number" disabled="true" type="number" />
+                  <view class="add" data-goods-id="{{item.id}}" data-product-id="{{item.product_id}}" bindtap="addNumber"></view>
+                </view>
+              </view>
+            </view>
+          </view>
+        </view>
+      </view>
+    </view>
+  </view>
+
+  <view class="good-grid" wx:for="{{floorGoods}}" wx:key="{{item.id}}">
+    <view class="h">
+      <view>
+        <text>{{item.name}}</text>
+      </view>
+    </view>
+    <view class="b">
+      <block wx:for="{{item.goodsList}}" wx:for-index="iindex" wx:for-item="iitem" wx:key="{{iitem.id}}">
+        <view class="item {{iindex % 2 == 0 ? '' : 'item-b'}}">
+          <navigator url="../goods/goods?id={{iitem.id}}" class="a">
+            <image class="img" src="{{iitem.list_pic_url}}" background-size="cover"></image>
+            <text class="name">{{iitem.name}}</text>
+            <text class="price">¥{{iitem.retail_price}}</text>
+          </navigator>
+        </view>
+      </block>
+      <view class="item item-b item-more">
+        <navigator url="/pages/category/category?id={{item.id}}" class="more-a">
+          <view class="txt">{{'更多'+item.name+'好物'}}</view>
+          <image class="icon" src="../../static/images/icon_go_more.png" background-size="cover"></image>
+        </navigator>
+      </view>
+    </view>
+  </view>
+</view>

+ 644 - 0
wx-mall-hk/pages/index/index.wxss

@@ -0,0 +1,644 @@
+.banner {
+  width: 750rpx;
+  height: 365rpx;
+  padding-top: 130rpx;
+}
+
+.discount-dialog {
+  position: fixed;
+  z-index: 5000;
+  width: 80%;
+  max-width: 600rpx;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+  background-color: transparent;
+  text-align: center;
+  border-radius: 8px;
+  overflow: hidden;
+}
+
+.dialog-title {
+  height: 60rpx;
+  line-height: 60rpx;
+  text-align: center;
+  color: #fff;
+}
+
+.image-box {
+  height: 90vmin;
+  overflow: hidden;
+}
+
+.image-box image {
+  width: 100%;
+  height: 100%;
+}
+
+.dialog-close {
+  margin-top: 16rpx;
+  margin-bottom: 16rpx;
+}
+
+.home-header {
+  position: fixed;
+  width: 750rpx;
+  height: 40rpx;
+  display: flex;
+  justify-content: left;
+  align-items: left;
+  background-color: #fff;
+  z-index: 98;
+}
+
+.current-store {
+  text-align: left;
+  position: relative;
+  margin-left: 35rpx;
+  font-size: 14px;
+}
+
+.search-icon {
+  width: 40rpx;
+  height: 40rpx;
+  margin-left: auto;
+}
+
+.banner image {
+  width: 100%;
+  height: 365rpx;
+}
+
+.m-menu {
+  display: flex;
+  height: 155rpx;
+  width: 750rpx;
+  flex-flow: row nowrap;
+  align-items: center;
+  justify-content: space-between;
+  background-color: #fff;
+}
+
+.m-menu .item {
+  flex: 1;
+  display: block;
+  padding: 20rpx 0;
+}
+
+.m-menu .itemb  {
+  flex: 1;
+  display: block;
+}
+
+.m-menu image {
+  display: block;
+  width: 58rpx;
+  height: 58rpx;
+  margin: 0 auto;
+  margin-bottom: 12rpx;
+}
+
+.m-menu text {
+  display: block;
+  font-size: 24rpx;
+  text-align: center;
+  margin: 0 auto;
+  line-height: 1;
+  color: #333;
+}
+
+.a-section {
+  width: 750rpx;
+  height: auto;
+  overflow: hidden;
+  background: #fff;
+  color: #333;
+  margin-top: 10rpx;
+}
+
+.a-section .h {
+  display: flex;
+  flex-flow: row nowrap;
+  align-items: center;
+  justify-content: center;
+  height: 90rpx;
+}
+
+.a-section .h .txt {
+  padding-right: 30rpx;
+  background: url(http://120.76.26.84:80/group1/M00/00/02/rBJEdVvr2W6ATlkvAAAA_rntq4s180.png) right 4rpx no-repeat;
+  background-size: 16.656rpx 27rpx;
+  display: inline-block;
+  height: 36rpx;
+  font-size: 33rpx;
+  line-height: 36rpx;
+}
+
+.a-brand .b {
+  width: 750rpx;
+  height: auto;
+  overflow: hidden;
+  position: relative;
+}
+
+.a-brand .wrap {
+  position: relative;
+}
+
+.a-brand .img {
+  position: absolute;
+  left: 0;
+  top: 0;
+}
+
+.a-brand .mt {
+  position: absolute;
+  z-index: 2;
+  padding: 27rpx 31rpx;
+  left: 0;
+  top: 0;
+}
+
+.a-brand .mt .brand {
+  display: block;
+  font-size: 33rpx;
+  height: 43rpx;
+  color: #333;
+}
+
+.a-brand .mt .price, .a-brand .mt .unit {
+  font-size: 25rpx;
+  color: #999;
+}
+
+.a-brand .item-1 {
+  float: left;
+  width: 375rpx;
+  height: 252rpx;
+  overflow: hidden;
+  border-top: 1rpx solid #fff;
+  margin-left: 1rpx;
+}
+
+.a-brand .item-1:nth-child(2n+1) {
+  margin-left: 0;
+  width: 374rpx;
+}
+
+.a-brand .item-1 .img {
+  width: 375rpx;
+  height: 253rpx;
+}
+
+.a-new .b {
+  border-top: 1px solid #d9d9d9;
+  width: 750rpx;
+  height: auto;
+  overflow: hidden;
+  padding: 0 31rpx 45rpx 31rpx;
+}
+
+.topic-list {
+  border-top: 1px solid #d9d9d9;
+}
+
+.topic-list .item .imgtt .imgline .priceInfo {
+  float: left;
+  text-align: left;
+  width: 60%;
+  height: 33rpx;
+  line-height: 38rpx;
+  overflow: hidden;
+  color: #fff;
+  font-size: 33rpx;
+  margin-top: 25rpx;
+  padding-left: 33rpx;
+}
+
+.a-new .b .item {
+  float: left;
+  width: 302rpx;
+  margin-top: 10rpx;
+  margin-left: 21rpx;
+  margin-right: 21rpx;
+}
+
+.a-new .b .item-b {
+  margin-left: 42rpx;
+}
+
+.a-new .b .imgt {
+  width: 302rpx;
+  height: 302rpx;
+}
+
+.a-new .b .img {
+  width: 100%;
+  height: 100%;
+}
+
+.a-new .b .name {
+  text-align: center;
+  display: block;
+  width: 302rpx;
+  height: 35rpx;
+  margin-bottom: 14rpx;
+  overflow: hidden;
+  font-size: 30rpx;
+  color: #333;
+}
+
+.a-new .b .price {
+  display: inline;
+  text-align: center;
+  line-height: 30rpx;
+  font-size: 30rpx;
+  color: #b4282d;
+}
+
+.a-new .b .priceInfo {
+  float: left;
+  clear: both;
+}
+
+.a-popular {
+  width: 750rpx;
+  height: auto;
+  overflow: hidden;
+}
+
+.a-popular .b .item {
+  border-top: 1px solid #d9d9d9;
+  margin: 0 10rpx;
+  height: 254rpx;
+  width: 710rpx;
+}
+
+.a-popular .b .img {
+  margin-top: 12rpx;
+  margin-right: 15rpx;
+  float: left;
+  width: 240rpx;
+  height: 240rpx;
+  background-size: 140rpx 140rpx;
+}
+
+.a-popular .b .right {
+  float: left;
+  height: 264rpx;
+  width: 456rpx;
+  display: flex;
+  flex-flow: row nowrap;
+}
+
+.a-popular .b .text {
+  display: flex;
+  flex-wrap: nowrap;
+  flex-direction: column;
+  justify-content: center;
+  overflow: hidden;
+  height: 264rpx;
+  width: 456rpx;
+}
+
+.a-popular .b .name {
+  width: 456rpx;
+  display: block;
+  color: #333;
+  line-height: 50rpx;
+  font-size: 26rpx;
+}
+
+.a-popular .b .desc {
+  width: 456rpx;
+  display: block;
+  color: #999;
+  line-height: 50rpx;
+  font-size: 25rpx;
+}
+
+.a-popular .b .goods-do {
+  display: inline;
+}
+
+.a-popular .b .goods-do .price {
+  /* width: 50rpx; */
+  display: inline;
+  color: #b4282d;
+  line-height: 50rpx;
+  font-size: 27rpx;
+}
+
+.a-popular .b .goods-do .org-price {
+  /* width: 40rpx; */
+  display: inline;
+  color: #333;
+  line-height: 50rpx;
+  font-size: 23rpx;
+}
+
+.a-topic .b {
+  height: 433rpx;
+  width: 750rpx;
+  padding: 0 0 48rpx 0;
+}
+
+.a-topic .b .list {
+  width: 750rpx;
+  white-space: nowrap;
+}
+
+.a-topic .b .item {
+  display: inline-block;
+  width: 680.5rpx;
+  margin-left: 30rpx;
+  overflow: hidden;
+}
+
+.a-topic .b .item:last-child {
+  margin-right: 30rpx;
+}
+
+.a-topic .b .img {
+  height: 387.5rpx;
+  width: 680.5rpx;
+  margin-bottom: 10rpx;
+}
+
+.a-topic .b .np {
+  height: 35rpx;
+  margin-bottom: 13.5rpx;
+  color: #333;
+  font-size: 30rpx;
+}
+
+.a-topic .b .np .price {
+  margin-left: 20.8rpx;
+  color: #b4282d;
+}
+
+.a-topic .b .desc {
+  display: block;
+  height: 30rpx;
+  color: #999;
+  font-size: 24rpx;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+
+.good-grid {
+  width: 750rpx;
+  height: auto;
+  overflow: hidden;
+}
+
+.good-grid .h {
+  display: flex;
+  flex-flow: row nowrap;
+  align-items: center;
+  justify-content: center;
+  height: 130rpx;
+  font-size: 33rpx;
+  color: #333;
+}
+
+.good-grid .b {
+  width: 750rpx;
+  padding: 0 6.25rpx;
+  height: auto;
+  overflow: hidden;
+}
+
+.good-grid .b .item {
+  float: left;
+  background: #fff;
+  width: 365rpx;
+  margin-bottom: 6.25rpx;
+  height: 452rpx;
+  overflow: hidden;
+  text-align: center;
+}
+
+.good-grid .b .item .a {
+  height: 452rpx;
+  width: 100%;
+}
+
+.good-grid .b .item-b {
+  margin-left: 6.25rpx;
+}
+
+.good-grid .item .img {
+  margin-top: 20rpx;
+  width: 302rpx;
+  height: 302rpx;
+}
+
+.good-grid .item .name {
+  display: block;
+  width: 365.625rpx;
+  padding: 0 20rpx;
+  overflow: hidden;
+  height: 35rpx;
+  margin: 11.5rpx 0 22rpx 0;
+  text-align: center;
+  font-size: 30rpx;
+  color: #333;
+}
+
+.good-grid .item .price {
+  display: block;
+  width: 365.625rpx;
+  height: 30rpx;
+  text-align: center;
+  font-size: 30rpx;
+  color: #b4282d;
+}
+
+.good-grid .more-item {
+  height: 100%;
+  width: 100%;
+}
+
+.more-a {
+  height: 100%;
+  width: 100%;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+}
+
+.good-grid .more-a .txt {
+  height: 33rpx;
+  width: 100%;
+  line-height: 33rpx;
+  color: #333;
+  font-size: 33rpx;
+}
+
+.good-grid .more-a .icon {
+  margin: 60rpx auto 0 auto;
+  width: 70rpx;
+  height: 70rpx;
+}
+
+.line-through {
+  text-decoration: line-through;
+}
+
+.number-item {
+  display: inline-flex;
+  -webkit-box-pack: justify;
+  align-items: center;
+  position: absolute;
+  right: 0;
+  margin-right: 40rpx;
+}
+
+.number-item .selnum {
+  height: 71rpx;
+  display: flex;
+}
+
+.number-item .cut {
+  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADQAAAA0CAMAAADypuvZAAAAM1BMVEX////Z296wsLD6+vvo6evi5Obe3+Lr7O709fb5+fr3+Pjb3eDw8fLu7/Hl5+nk5ui5ubmS1nTyAAABG0lEQVRIx52WWXLEIAxEeUGSGeNl7n/aME6lUmQWm+5f+5l2A5LSC+XFPCrUcFtyuqDbFHSK6XaCzE7TvpZ8LFnWnSafPyB5g2oldSpWYXvrcgKmkQdNDpbfWDDwVwEE8cH6HMRTIAX8Y7rZofxbByydyKBfKx7MORV9Bn4CPL82EfkKlOMv+QxzuqQZfr++YemijK3Dz9Sb8mb0sib8Z4tqGlDldrA2AtnhKygjUCGOX0tDesS2sI9BO0vzuI5BK5acMgYVPAV5DMpEy71P9P71pHu/J9REDzXmBdVDSJBkTwpCilzaXOkYSQdWuRrSJZSuu1JYpBKmFEupLCsNQGk1SlOT2qfSqJWRQBg+lDFHG6j00U0fEqVx9BvALAkNabHL3QAAAABJRU5ErkJggg==);
+  box-sizing: border-box;
+  width: 25px;
+  border: none;
+  border-radius: 50%;
+  height: 25px;
+  background-size: 100% 100%;
+}
+
+.number-item .number {
+  width: 2em;
+  text-align: center;
+  color: #333;
+}
+
+.number-item .add {
+  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAMAAAAp4XiDAAAANlBMVEX/0WH///8zMzP/02b//fb/+u7/5qj/45z/3oz/1W1KRDj/8c//78j/7L7/6rX/2HfEo1P/3IXeVLZ3AAAA70lEQVRIx52WWQ7DIAxEJzFrNpL7X7ZIbdUUnITh/aIngW1sY6gwiwspisQU3GLq81KxaxCckLDaW8V6KHh7qRgnUBFndGWOuCTOmrLhlq1WPB7wpXLgkeNf8WjAn5UNTWw/ZUYj81cxEY1E81EcmnFvxQqaEZuVi2jt07TrUcuKhcY0jhM0bFZWaIwZaKxZCZwSBhjhFDFYwClZcKziEFglILFKQiwyOFYUOY0QnFGMMqfSo/AX63k+H+SeVPIF01OWfPHzX6zrI/Ptgm9KfOvjGyzfxvlhwY8kfvDx45Uf4vyqwC8kvWtP/3LFr3AvL0kJEWHNe5sAAAAASUVORK5CYII=);
+  box-sizing: border-box;
+  width: 25px;
+  border: none;
+  border-radius: 50%;
+  height: 25px;
+  background-size: 100% 100%;
+}
+
+.group-box {
+  display: flex;
+  padding: 10px 10px;
+  background-color: #fff;
+}
+
+.group-box .img {
+  width: 240rpx;
+  height: 240rpx;
+  margin-top: 9px;
+}
+
+.group-box .title, .group-box .desc {
+  text-align: left;
+  padding: 0;
+}
+
+.group-box .imgline {
+  flex: 1;
+  padding-left: 15px;
+}
+
+.priceInfo .price {
+  color: #b4282d;
+  font-size: 40rpx;
+}
+
+.btn-view .btn {
+  color: #fff;
+  background-color: #f48f18;
+  width: 200rpx;
+  margin-top: 10px;
+
+  font-size: 28rpx;
+  float: right;
+}
+
+.btn-view .surplus {
+  float: left;
+  padding: 5px 10px;
+  background-color: #ffdf80;
+  text-align: center;
+  margin-top: 15px;
+  align-items: center;
+  font-size: 28rpx;
+  border-radius: 16px 16px 16px 16px;
+}
+
+.search-header .input-box {
+  position: relative;
+  margin-top: 16rpx;
+  float: left;
+  width: 0;
+  flex: 1;
+  height: 59rpx;
+  line-height: 59rpx;
+  padding: 0 20rpx;
+  background: #f4f4f4;
+  color: #999;
+}
+
+.search-header {
+  position: fixed;
+  top: 40rpx;
+  width: 750rpx;
+  height: 91rpx;
+  display: flex;
+  background: #fff;
+  padding: 0 31.25rpx;
+  font-size: 29rpx;
+  color: #333;
+  z-index: 99;
+}
+.search-header .icon {
+  position: absolute;
+  top: 14rpx;
+  left: 20rpx;
+  width: 31rpx;
+  height: 31rpx;
+}
+
+.search-header .del {
+  position: absolute;
+  top: 3rpx;
+  right: 10rpx;
+  width: 53rpx;
+  height: 53rpx;
+  z-index: 10;
+}
+
+.search-header .keywrod {
+  position: absolute;
+  top: 0;
+  width: 506rpx;
+  height: 59rpx;
+  font-size: 12px;
+}
+
+.search-header .right {
+  margin-top: 24rpx;
+  margin-left: 31rpx;
+  margin-right: 6rpx;
+  width: 58rpx;
+  height: 43rpx;
+  line-height: 43rpx;
+  float: right;
+}
+
+.search-icon-shop {
+  width: 40rpx;
+  height: 40rpx;
+  margin-left: 15rpx;
+  margin-top: 20rpx;
+}

+ 237 - 0
wx-mall-hk/pages/joinGroup/joinGroup.js

@@ -0,0 +1,237 @@
+var app = getApp();
+var util = require('../../utils/util.js');
+var goodsUtil = require('../../utils/goods.js');
+var api = require('../../config/api.js');
+
+Page({
+  data: {
+    groupId: 0,
+    openId: 0,
+    type: 0,
+    goods: {},
+    group: {},
+    specificationList: [],
+    productList: [],
+    attendList: [],
+    groupList: [],
+    number: 1,
+    min_open_group: 0,
+    attend_num: 0,
+    checkedSpecText: '请选择规格数量',
+    openAttr: false,
+    showPage: false,
+    page: 1,
+    size: 6,
+    count: 0,
+    selfStatus: 0,// 本人参与的是否被取消 0正常 1取消
+    groupEnd: {}
+  },
+  //获取商品信息
+  getGoodsInfo: function () {
+    let that = this;
+    util.request(api.GroupDetail, { id: that.data.groupId }).then(function (res) {
+      if (res.errno === 0) {
+        that.setData({
+          group: res.data.groupVo,
+          goods: res.data.info,
+          specificationList: res.data.specificationList,
+          productList: res.data.productList
+        });
+        //
+        let _specificationList = res.data.specificationList;
+        for (let i = 0; i < _specificationList.length; i++) {
+          if (_specificationList[i].valueList.length == 1) {
+            //如果已经选中,则反选
+            _specificationList[i].valueList[0].checked = true;
+          }
+        }
+        that.setData({
+          'specificationList': _specificationList
+        });
+      }
+    });
+  },
+  //获取已经参与的人
+  getAttendList() {
+    let that = this;
+    util.request(api.AttendList, { openId: that.data.openId }).then(function (res) {
+      if (res.errno === 0) {
+        that.setData({
+          attendList: res.data
+        });
+      }
+
+      if (res.data.length > 0) {
+        for (let i = 0; i < res.data.length; i++) {
+          if (res.data[i].user_id == wx.getStorageSync('userId')) {
+            that.setData({
+              type: 1
+            })
+            if (res.data[i].attend_status == 3) {
+              that.setData({
+                selfStatus: 1
+              })
+            }
+          }
+        }
+      }
+    });
+  },
+  clickSkuValue: function (event) {
+    let that = this;
+    let specNameId = event.currentTarget.dataset.nameId;
+    let specValueId = event.currentTarget.dataset.valueId;
+
+    //判断是否可以点击
+
+    //TODO 性能优化,可在wx:for中添加index,可以直接获取点击的属性名和属性值,不用循环
+    let _specificationList = this.data.specificationList;
+    for (let i = 0; i < _specificationList.length; i++) {
+      if (_specificationList[i].specification_id == specNameId) {
+        for (let j = 0; j < _specificationList[i].valueList.length; j++) {
+          if (_specificationList[i].valueList[j].id == specValueId) {
+            //如果已经选中,则反选
+            if (_specificationList[i].valueList[j].checked) {
+              _specificationList[i].valueList[j].checked = false;
+            } else {
+              _specificationList[i].valueList[j].checked = true;
+            }
+          } else {
+            _specificationList[i].valueList[j].checked = false;
+          }
+        }
+      }
+    }
+    this.setData({
+      'specificationList': _specificationList
+    });
+    //重新计算spec改变后的信息
+    goodsUtil.changeSpecInfo(that);
+  },
+  //根据已选的值,计算其它值的状态
+  setSpecValueStatus: function () {
+
+  },
+  onLoad: function (options) {
+    // 页面初始化 options为页面跳转所带来的参数
+    let para = {
+      end_time: parseInt(options.end_time)
+    };
+    this.setData({
+      groupId: parseInt(options.groupId),
+      openId: parseInt(options.openId),
+      min_open_group: parseInt(options.min_open_group),
+      attend_num: parseInt(options.attend_num),
+      groupEnd: para
+    });
+    util.countdown(this, para, 'groupEnd', null)
+    this.getGoodsInfo()
+    this.getAttendList()
+    this.getTopic()
+  },
+  onReady: function () {
+
+  },
+  onShow: function () {
+    // 页面显示
+
+  },
+  onHide: function () {
+    // 页面隐藏
+    this.setData({
+      openAttr: false
+    })
+
+  },
+  onUnload: function () {
+    // 页面关闭
+  },
+  getTopic: function () {
+    let that = this;
+    that.setData({
+      groupList: []
+    });
+    util.request(api.GroupList, { page: that.data.page, size: that.data.size }).then(function (res) {
+      if (res.errno === 0) {
+        that.setData({
+          groupList: res.data.data
+        })
+      }
+    })
+  },
+  switchAttrPop: function () {
+    this.setData({
+      openAttr: !this.data.openAttr
+    })
+  },
+  cutNumber: function () {
+    this.setData({
+      number: (this.data.number - 1 > 1) ? this.data.number - 1 : 1
+    });
+  },
+  addNumber: function () {
+    this.setData({
+      number: this.data.number + 1
+    });
+  },
+  checkProduct: function () {
+    var that = this;
+    if (this.data.openAttr == false) {
+      //打开规格选择窗口
+      this.setData({
+        openAttr: !this.data.openAttr,
+        collectBackImage: "/static/images/detail_back.png"
+      });
+    } else {
+
+      //提示选择完整规格
+      if (!goodsUtil.isCheckedAllSpec(that)) {
+        return false;
+      }
+
+      //根据选中的规格,判断是否有对应的sku信息
+      let checkedProduct = goodsUtil.getCheckedProductItem(goodsUtil.getCheckedSpecKey(that), that);
+      if (!checkedProduct || checkedProduct.length <= 0) {
+        //找不到对应的product信息,提示没有库存
+        return false;
+      }
+
+      //验证库存
+      if (checkedProduct.goods_number < this.data.number) {
+        //找不到对应的product信息,提示没有库存
+        return false;
+      }
+
+      wx.navigateTo({
+        url: '/pages/shopping/groupcheck/groupcheck?number=' + this.data.number + '&productId=' + checkedProduct[0].id
+        + '&openId=' + this.data.openId + '&groupId=' + this.data.groupId,
+      })
+    }
+  },
+  switchNav(event) {
+    wx.switchTab({
+      url: '/pages/index/index'
+    });
+  },
+  onShareAppMessage: function () {
+    var that = this;
+    return {
+      title: that.data.goods.name,
+      desc: null != that.data.group.ad_desc ? that.data.group.ad_desc : "商业版",
+      imageUrl: '',
+      path: '/pages/joinGroup/joinGroup?openId=' + that.data.openId + '&groupId=' + that.data.groupId
+      + '&goodsId=' + that.data.goodsId
+      + '&min_open_group=' + that.data.min_open_group
+      + '&attend_num=' + that.data.attend_num
+      + '&end_time=' + that.data.groupEnd.end_time,
+      success: function (res) {
+        console.log("转发成功");
+        // 转发成功
+      },
+      fail: function (res) {
+        // 转发失败
+        console.log("转发失败");
+      }
+    }
+  }
+})

+ 1 - 0
wx-mall-hk/pages/joinGroup/joinGroup.json

@@ -0,0 +1 @@
+{}

+ 99 - 0
wx-mall-hk/pages/joinGroup/joinGroup.wxml

@@ -0,0 +1,99 @@
+<scroll-view class="container" scroll-y="true">
+  <view class="backhome" bindtap="switchNav">
+    <image src="/static/images/home.png"></image>
+    <text style="padding-left: 5px;">首页</text>
+  </view>
+  <view wx:if="{{openAttr}}" class="modal-wrap"></view>
+  <navigator url="/pages/groupDetail/groupDetail?id={{group.id}}">
+    <view class="goods-info">
+      <image class="goods-pic" src="{{goods.list_pic_url}}"></image>
+      <view class="goods-desc">
+        <text class="goods-title">{{goods.name}}</text>
+        <view class="goods-price">
+          <text class="min-price">¥{{group.retail_min_price}}</text>
+          <text class="price">¥{{group.retail_price}}</text>
+        </view>
+        <view class="price-tag">
+          <text>{{min_open_group}}人拼团</text>
+          <text>拼团立省{{group.retail_price - group.retail_min_price}}元</text>
+        </view>
+      </view>
+    </view>
+  </navigator>
+  <view class="group-info">
+    <view wx:if="{{!attendList[0].overdue && (attendList[0].attend_status == 0 || attendList[0].attend_status == 1)}}">
+      <view wx:if="{{type == 1}}" class="desc">还差
+        <text>{{min_open_group - attend_num}}</text>位新人,快喊小伙伴一起拼团吧</view>
+      <view wx:if="{{type == 0}}" class="desc">已有{{attend_num}}参与,还差
+        <text>{{min_open_group - attend_num}}</text>人拼团成功</view>
+      <view class="deadline">仅剩
+        <text>{{groupEnd.dateformat.day}}天{{groupEnd.dateformat.hr}}:{{groupEnd.dateformat.min}}:{{groupEnd.dateformat.sec}}</text>失效</view>
+    </view>
+    <view wx:if="{{attendList[0].attend_status == 2}}" class="desc">拼团成功</view>
+    <view wx:if="{{attendList[0].attend_status == 3}}" class="desc">拼团失败</view>
+    <view wx:if="{{attendList[0].overdue && attendList[0].attend_status != 2 && attendList[0].attend_status != 3}}" class="desc">该活动已结束</view>
+    <view class="member">
+      <view wx:for="{{attendList}}" style="background-image: url({{item.avatar}})" wx:key="index" class="member-item {{ index == 0 ? 'member-chief' : 'member-group' }}"></view>
+      <view wx:for="{{min_open_group - attend_num}}" wx:key="index" class="member-item member-cell">?</view>
+    </view>
+  </view>
+  <view wx:if="{{openAttr}}" class="attr-pop">
+    <view class="attr-close" bindtap="switchAttrPop">X</view>
+    <view class="img-info">
+      <image class="img" src="{{goods.list_pic_url}}"></image>
+      <view class="info">
+        <view class="c">
+          <view class="p">价格:¥{{group.retail_min_price}}</view>
+          <view class="a" wx:if="{{productList.length>0}}">已选择:{{checkedSpecText}}</view>
+        </view>
+      </view>
+    </view>
+    <view class="spec-con">
+      <view class="spec-item" wx:for="{{specificationList}}" wx:key="{{item.specification_id}}">
+        <view class="name">{{item.name}}</view>
+        <view class="values">
+          <view class="value {{vitem.checked ? 'selected' : ''}}" bindtap="clickSkuValue" wx:for="{{item.valueList}}" wx:for-item="vitem" wx:key="{{vitem.id}}" data-value-id="{{vitem.id}}" data-name-id="{{vitem.specification_id}}">{{vitem.value}}</view>
+        </view>
+      </view>
+
+      <view class="number-item">
+        <view class="name">数量</view>
+        <view class="selnum">
+          <view class="cut" bindtap="cutNumber">-</view>
+          <input value="{{number}}" class="number" disabled="true" type="number" />
+          <view class="add" bindtap="addNumber">+</view>
+        </view>
+      </view>
+    </view>
+  </view>
+  <button wx:if="{{!attendList[0].overdue&&group.open_status==1 && (attendList[0].attend_status == 0 || attendList[0].attend_status == 1)}}" class="share-btn" open-type="share">
+    <image src="/static/images/weixin.png"></image>分享给微信好友</button>
+  <button wx-if="{{group.open_status!=1 || selfStatus == 1}}" class="more-link">已关闭</button>
+  <button wx-if="{{group.open_status==1&&type == 0 && !attendList[0].overdue}}" bindtap="switchAttrPop" class="join-btn">我要参团</button>
+  <button wx-if="{{openAttr && group.open_status==1}}" bindtap="checkProduct" class="confirm-btn">确定</button>
+  <view class="more-group">更多拼团
+    <navigator class="more-link" open-type="switchTab" url="/pages/goodsActivity/goodsActivity?type=0">更多 ></navigator>
+  </view>
+  <view class="topic-list">
+    <view class="item" wx:for="{{groupList}}" wx:key="{{item.id}}">
+      <view class="imgtt">
+        <image class="img" src="{{item.item_pic_url}}"></image>
+        <view class="imgline">
+          <view class="priceInfo">最低开团价:
+            <text class="price">¥{{item.retail_min_price}}</text>
+            <text class="orgPrice line-through">¥{{item.retail_price}}</text>
+          </view>
+          <view class="right">
+            <navigator url="../groupDetail/groupDetail?id={{item.id}}">
+              <button class="btn">立即开团</button>
+            </navigator>
+          </view>
+        </view>
+      </view>
+      <view class="info">
+        <text class="title">{{item.title}}</text>
+        <text class="desc">{{item.subtitle}}</text>
+      </view>
+    </view>
+  </view>
+</scroll-view>

+ 354 - 0
wx-mall-hk/pages/joinGroup/joinGroup.wxss

@@ -0,0 +1,354 @@
+.container {
+ position: relative;
+}
+.backhome {
+    position: fixed;
+    top: 10px;
+    right: 0;
+    background-color: rgba(0,0,0,0.5);
+    padding: 2px 5px;
+    font-size: 28rpx;
+    border-radius: 16px 0 0 16px;
+    display: flex;
+    align-items: center;
+    z-index: 500;
+}
+.backhome text {
+  color: #fff;
+}
+.backhome image {
+  width: 15px;
+  height: 15px;
+}
+.goods-info{
+  display: flex;
+  height: 300rpx;
+  background-color: #fff;
+}
+
+.goods-info .goods-pic{
+  width: 240rpx;
+  height: 240rpx;
+  margin-top: 30rpx;
+}
+.goods-info .goods-desc{
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+}
+
+.goods-info .goods-desc .goods-title{
+  display: inline-block;
+  width: 500rpx;
+  padding: 20rpx;
+}
+
+.goods-info .goods-desc .min-price{
+  font-size: 50rpx;
+  color: #FF5778;
+  padding: 0 20rpx;
+}
+
+.goods-info .goods-desc .price{
+  text-decoration: line-through;
+  color: #999;
+}
+
+.goods-info .goods-desc .price-tag{
+  margin: 10rpx;
+}
+
+.goods-info .goods-desc .price-tag text{
+  background-color: #FFE7E7;
+  color: #FF5778;
+  padding: 10rpx;
+  margin: 10rpx;
+  border-radius: 10rpx;
+}
+
+.group-info{
+  width: 90%;
+  margin: 30rpx auto;
+  background-color: #FFE7E7;
+  position: relative;
+}
+
+.group-info::after{
+  position: absolute;
+  content: '';
+  width: 0;
+  height: 0;
+  border-left: 20rpx solid transparent;
+  border-right: 20rpx solid transparent;
+  border-bottom: 20rpx solid #FFE7E7;
+  top: -18rpx;
+  left: 50%;
+  margin-left: -20rpx;
+}
+
+.group-info .desc{
+  text-align: center;
+  font-size: 30rpx;
+  padding: 20rpx;
+  font-weight: bold;
+}
+
+.group-info .desc text{
+  font-size: 40rpx;
+  color: #FF5778;
+  padding: 0 10rpx;
+}
+
+.group-info .deadline{
+  text-align: center;
+  color: #555;
+}
+
+.group-info .deadline text{
+  color: #FF5778;
+  padding: 0 15rpx;
+}
+
+.group-info .member{
+  padding: 20rpx;
+  text-align: center;
+}
+.group-info .member .member-item{
+  display: inline-block;
+  width: 80rpx;
+  height: 80rpx;
+  border-radius: 50%;
+  background-size: cover;
+  background-position: center;
+  margin: 10rpx;
+  background-color: #fff;
+}
+
+.group-info .member .member-chief{
+  position: relative;
+  border: 1px solid #FF5778;
+}
+.group-info .member .member-group{
+  border: 1px solid #FF5778;
+}
+
+.group-info .member .member-chief::after{
+  position: absolute;
+  display: block;
+  width: 60rpx;
+  height: 30rpx;
+  line-height: 30rpx;
+  content: '团长';
+  color: #fff;
+  background-color: #FF5778;
+  left: 50%;
+  margin-left: -29rpx;
+  bottom: -15rpx;
+  font-size: 20rpx;
+  border-radius: 20rpx;
+}
+.group-info .member .member-cell{
+  text-align: center;
+  line-height: 80rpx;
+  font-size: 60rpx;
+  color: #FFC0CB;
+  border: 1px dashed #FF5778;
+  vertical-align: top;
+}
+
+.share-btn{
+  background-color: #07AF12;
+  width: 400rpx;
+  height: 100rpx;
+  line-height: 100rpx;
+  font-size: 35rpx;
+  color: #fff;
+  border-radius: 50rpx;
+  margin: 50rpx auto;
+}
+
+.share-btn image{
+  width: 60rpx;
+  height: 60rpx;
+  margin: 20rpx;
+  vertical-align: top;
+}
+.join-btn{
+  background-color: #FF5778;
+  width: 90%;
+  height: 100rpx;
+  line-height: 100rpx;
+  font-size: 35rpx;
+  color: #fff;
+  border-radius: 10rpx;
+  margin: 20rpx auto;
+}
+.attr-pop {
+  width: 100%;
+  height: auto;
+  padding: 31.25rpx;
+  background: #fff;
+  position: fixed;
+  bottom: 100rpx;
+  z-index: 999;
+}
+
+.attr-close{
+  float: right;
+  width: 50rpx;
+  height: 50rpx;
+  border-radius: 50%;
+  font-size: 50rpx;
+  text-align: center;
+}
+
+.attr-pop .img-info {
+  width: 687.5rpx;
+  height: 177rpx;
+  overflow: hidden;
+  margin-bottom: 41.5rpx;
+}
+
+.attr-pop .img {
+  float: left;
+  height: 177rpx;
+  width: 177rpx;
+  background: #f4f4f4;
+  margin-right: 31.25rpx;
+}
+
+.attr-pop .info {
+  float: left;
+  height: 177rpx;
+  display: flex;
+  align-items: center;
+}
+
+.attr-pop .p {
+  font-size: 33rpx;
+  color: #333;
+  height: 33rpx;
+  line-height: 33rpx;
+  margin-bottom: 10rpx;
+}
+
+.attr-pop .a {
+  font-size: 29rpx;
+  color: #333;
+  height: 40rpx;
+  line-height: 40rpx;
+}
+
+.spec-con {
+  width: 100%;
+  height: auto;
+  overflow: hidden;
+}
+
+.spec-con .name {
+  height: 32rpx;
+  margin-bottom: 22rpx;
+  font-size: 29rpx;
+  color: #333;
+}
+
+.spec-con .values {
+  height: auto;
+  margin-bottom: 31.25rpx;
+  font-size: 0;
+}
+
+.spec-con .value {
+  display: inline-block;
+  height: 62rpx;
+  padding: 0 35rpx;
+  line-height: 56rpx;
+  text-align: center;
+  margin-right: 25rpx;
+  margin-bottom: 16.5rpx;
+  border: 1px solid #333;
+  font-size: 25rpx;
+  color: #333;
+}
+
+.spec-con .value.disable {
+  border: 1px solid #ccc;
+  color: #ccc;
+}
+
+.spec-con .value.selected {
+  border: 1px solid #b4282d;
+  color: #b4282d;
+}
+
+.number-item .selnum {
+  width: 322rpx;
+  height: 71rpx;
+  border: 1px solid #ccc;
+  display: flex;
+}
+
+.number-item .cut {
+  width: 93.75rpx;
+  height: 100%;
+  text-align: center;
+  line-height: 65rpx;
+}
+
+.number-item .number {
+  flex: 1;
+  height: 100%;
+  text-align: center;
+  line-height: 68.75rpx;
+  border-left: 1px solid #ccc;
+  border-right: 1px solid #ccc;
+  float: left;
+}
+
+.number-item .add {
+  width: 93.75rpx;
+  height: 100%;
+  text-align: center;
+  line-height: 65rpx;
+}
+.confirm-btn{
+  background-color: #b4282d;
+  width: 100%;
+  height: 100rpx;
+  line-height: 100rpx;
+  font-size: 35rpx;
+  color: #fff;
+  border-radius: 0;
+  position: fixed;
+  bottom: 0;
+  z-index: 999;
+}
+.line-through {
+  text-decoration: line-through;
+}
+.topic-list .item .imgtt .imgline .priceInfo {
+  float: left;
+  text-align: left;
+  width: 60%;
+  height: 33rpx;
+  line-height: 38rpx;
+  overflow: hidden;
+  color: #fff;
+  font-size: 33rpx;
+  margin-top: 25rpx;
+  padding-left: 33rpx;
+}
+
+.more-group{
+  height: 100rpx;
+  line-height: 100rpx;
+  padding-left: 20rpx;
+  background-color: #fff;
+  font-size: 35rpx;
+}
+.more-group .more-link{
+  float: right;
+  padding-right: 20rpx;
+  color: #888;
+  font-size: 25rpx;
+}

+ 14 - 0
wx-mall-hk/pages/logs/logs.js

@@ -0,0 +1,14 @@
+//logs.js
+var util = require('../../utils/util.js')
+Page({
+  data: {
+    logs: []
+  },
+  onLoad: function () {
+    this.setData({
+      logs: (wx.getStorageSync('logs') || []).map(function (log) {
+        return util.formatTime(new Date(log))
+      })
+    })
+  }
+})

+ 3 - 0
wx-mall-hk/pages/logs/logs.json

@@ -0,0 +1,3 @@
+{
+    "navigationBarTitleText": "查看启动日志"
+}

+ 6 - 0
wx-mall-hk/pages/logs/logs.wxml

@@ -0,0 +1,6 @@
+<!--logs.wxml-->
+<view class="container log-list">
+  <block wx:for="{{logs}}" wx:for-item="log">
+    <text class="log-item">{{index + 1}}. {{log}}</text>
+  </block>
+</view>

+ 8 - 0
wx-mall-hk/pages/logs/logs.wxss

@@ -0,0 +1,8 @@
+.log-list {
+  display: flex;
+  flex-direction: column;
+  padding: 40rpx;
+}
+.log-item {
+  margin: 10rpx;
+}

+ 159 - 0
wx-mall-hk/pages/map/map.js

@@ -0,0 +1,159 @@
+var util = require('../../utils/util.js');
+var api = require('../../config/api.js');
+
+var app = getApp();
+
+Page({
+    /**
+     * 页面的初始数据
+     */
+    data: {
+        // 中心点纬度、经度
+        latitude: "",
+        longitude: "",
+        // 标记点 当前位置
+        markers: [],
+        nearStoreList: [],
+        isShow: false,
+        storeId: "",
+        storeName: "",
+        storeAddress: "",
+        distance: "",
+        merchSn: ""
+    },
+    onLoad: function (options) {
+        // 页面初始化 options为页面跳转所带来的参数
+        this.mapCtx = wx.createMapContext('myMap');
+        this.mapCtx.moveToLocation();
+
+        let nearStoreList = wx.getStorageSync('nearStoreList') ? JSON.parse(wx.getStorageSync('nearStoreList')) : [];
+        this.setData({
+            nearStoreList: nearStoreList
+        })
+
+        let that = this;
+        util.getLocation((lng, lat) => {
+            util.request(api.NearbyList, { longitude: lng, latitude: lat }).then((res) => {
+            let markers = [];
+        let points = [];
+        let nlist = res.data;
+        for (var i = 0; i < nlist.length; i++) {
+            let marker = {
+                iconPath: "/static/images/address.png",
+                id: i,
+                latitude: nlist[i].latitude,
+                longitude: nlist[i].longitude,
+                width: 35,
+                height: 35,
+                clickable: true,
+                storeId: nlist[i].id,
+                storeName: nlist[i].storeName,
+                storeAddress: nlist[i].storeAddress,
+                distance: nlist[i].distance,
+                merchSn: nlist[i].merchSn
+            };
+            markers.push(marker);
+
+            let point = {
+                latitude: nlist[i].latitude,
+                longitude: nlist[i].longitude,
+            };
+            points.push(point);
+        }
+
+        this.mapCtx.includePoints({
+            points: points,
+        })
+
+        that.setData({
+            latitude: lat,
+            longitude: lng,
+            markers: markers
+        })
+
+    })
+    })
+    },
+    onReady: function () {
+        // 页面渲染完成
+        wx.create
+    },
+    onShow: function () {
+        // 页面显示
+
+    },
+    onHide: function () {
+        // 页面隐藏
+
+    },
+    onUnload: function () {
+        // 页面关闭
+
+    },
+    markersClick: function(res) {
+        // console.log(res);
+        let that = this;
+        let marker = that.data.markers[res.markerId];
+        that.setData({
+            isShow: true,
+            storeId: marker.storeId,
+            merchSn: marker.merchSn,
+            storeName: marker.storeName,
+            storeAddress: marker.storeAddress,
+            distance: marker.distance
+        });
+    },
+    chooseStore(e) {
+        // console.log(e.currentTarget.dataset.id)
+        // console.log(e.currentTarget.dataset.merchSn)
+        let storeId = e.currentTarget.dataset.id;
+        let merchSn = e.currentTarget.dataset.merchSn;
+
+        let that = this;
+        util.request(api.ChooseStoreId, { storeId: storeId, merchSn: merchSn }, 'POST').then(function (res) {
+            if (res.errno === 0) {
+                wx.removeStorageSync('nearStoreList');
+                wx.removeStorageSync('storeId');
+                wx.removeStorageSync('storeVo');
+                wx.removeStorageSync('currentCategory');
+                wx.setStorageSync('storeId', storeId);
+                var item = "";
+                for (var i = 0; i < that.data.nearStoreList.length; i++) {
+                    if (storeId == that.data.nearStoreList[i].id) {
+                        item = that.data.nearStoreList[i];
+                        wx.setStorageSync('storeVo', JSON.stringify(item));
+                        break;
+                    }
+                }
+
+                var pages = getCurrentPages();
+                var currPage = pages[pages.length - 1];  //当前页面
+                var prevPage = pages[pages.length - 2]; //上一个页面
+                if (item == "") {
+                    wx.removeStorageSync('nearStoreList');
+                    wx.removeStorageSync('storeId');
+                    wx.removeStorageSync('storeVo');
+                    that.setData({
+                        storeName: '附近暂无门店'
+                    })
+                } else {
+                    //直接调用上一个页面的setData()方法,把数据存到上一个页面中去
+                    prevPage.setData({
+                        storeName: item.storeName
+                    })
+                    // that.setData({
+                    //   storeName: item.storeName
+                    // })
+                }
+                // wx.switchTab({
+                //   url: '/pages/index/index'
+                // });
+
+                prevPage.getIndexData();
+                prevPage.enableActivity();
+                prevPage.getGroupData();
+                wx.navigateBack()
+            }
+        })
+    }
+})

+ 3 - 0
wx-mall-hk/pages/map/map.json

@@ -0,0 +1,3 @@
+{
+    "navigationBarTitleText": "附近门店"
+}

+ 10 - 0
wx-mall-hk/pages/map/map.wxml

@@ -0,0 +1,10 @@
+<view class="map_container">
+  <map id="myMap" class="map" longitude="{{longitude}}" latitude="{{latitude}}" markers='{{markers}}' show-location bindmarkertap='markersClick'>
+      <cover-view class="map-tab-bar map-foot {{isShow ? '' : 'map-hide'}}">
+        <cover-view class="map-storeName">{{storeName}}</cover-view>
+        <cover-view class="map-storeAddress">{{storeAddress}}</cover-view>
+        <cover-view class="map-distance">距离当前定位地址{{distance}}米</cover-view>
+        <button data-id="{{storeId}}" data-merch-sn="{{merchSn}}" bindtap='chooseStore'>确定</button>
+      </cover-view>
+  </map>
+</view>

Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov