xuhaolan 3 лет назад
Родитель
Сommit
2309f6536a
100 измененных файлов с 21957 добавлено и 0 удалено
  1. 3 0
      .gitignore
  2. 16 0
      .hbuilderx/launch.json
  3. 257 0
      App.vue
  4. 36 0
      api/address.js
  5. 27 0
      api/award.js
  6. 26 0
      api/cart.js
  7. 10 0
      api/category.js
  8. 29 0
      api/coupon.js
  9. 18 0
      api/favorite.js
  10. 37 0
      api/groupBooking.js
  11. 36 0
      api/index.js
  12. 29 0
      api/integral.js
  13. 57 0
      api/login.js
  14. 26 0
      api/moments.js
  15. 38 0
      api/money.js
  16. 10 0
      api/myteam.js
  17. 95 0
      api/order.js
  18. 92 0
      api/product.js
  19. 59 0
      api/received.js
  20. 19 0
      api/reply.js
  21. 18 0
      api/seckill.js
  22. 44 0
      api/set.js
  23. 10 0
      api/shareQrCode.js
  24. 14 0
      api/shoping.js
  25. 27 0
      api/sign.js
  26. 28 0
      api/user.js
  27. 109 0
      api/wallet.js
  28. 40 0
      api/wx.js
  29. 36 0
      components/canvasLove/canvasLove.vue
  30. 18 0
      components/empty.vue
  31. 133 0
      components/mix-list-cell.vue
  32. 6 0
      components/mix-loading/mix-loading.vue
  33. 202 0
      components/share.vue
  34. 218 0
      components/ss-calendar/ss-calendar.vue
  35. 1207 0
      components/tki-qrcode/qrcode.js
  36. 218 0
      components/tki-qrcode/tki-qrcode.vue
  37. 122 0
      components/uni-badge/uni-badge.vue
  38. 188 0
      components/uni-countdown/uni-countdown.vue
  39. 96 0
      components/uni-icons/icons.js
  40. 10 0
      components/uni-icons/uni-icons.vue
  41. 230 0
      components/uni-list-item/uni-list-item.vue
  42. 68 0
      components/uni-list/uni-list.vue
  43. 65 0
      components/uni-list/uni-refresh.vue
  44. 87 0
      components/uni-list/uni-refresh.wxs
  45. 194 0
      components/uni-load-more/uni-load-more.vue
  46. 361 0
      components/uni-notice-bar/uni-notice-bar.vue
  47. 198 0
      components/uni-number-box.vue
  48. 22 0
      components/uni-popup/message.js
  49. 25 0
      components/uni-popup/popup.js
  50. 243 0
      components/uni-popup/uni-popup-dialog.vue
  51. 116 0
      components/uni-popup/uni-popup-message.vue
  52. 165 0
      components/uni-popup/uni-popup-share.vue
  53. 294 0
      components/uni-popup/uni-popup.vue
  54. 141 0
      components/uni-rate/uni-rate.vue
  55. 279 0
      components/uni-transition/uni-transition.vue
  56. 226 0
      components/upload-images.vue
  57. 4914 0
      components/wangding-pickerAddress/data.js
  58. 103 0
      components/wangding-pickerAddress/wangding-pickerAddress.vue
  59. 280 0
      components/xuan-popup/xuan-popup.vue
  60. 34 0
      interceptor.js
  61. 44 0
      main.js
  62. 165 0
      manifest.json
  63. 30 0
      node_modules/jweixin-module/README.md
  64. 0 0
      node_modules/jweixin-module/out/index.js
  65. 60 0
      node_modules/jweixin-module/package.json
  66. 11 0
      package-lock.json
  67. 637 0
      pages.json
  68. 216 0
      pages/address/address.vue
  69. 225 0
      pages/address/addressManage.vue
  70. 173 0
      pages/address/shopList.vue
  71. 333 0
      pages/award/award.vue
  72. 313 0
      pages/award/withdmoenys.vue
  73. 332 0
      pages/award/withdrawal.vue
  74. 428 0
      pages/cart/cart.vue
  75. 230 0
      pages/category/category.vue
  76. 167 0
      pages/contract/agreement.vue
  77. 252 0
      pages/contract/privacy.vue
  78. 137 0
      pages/contract/start.vue
  79. 198 0
      pages/coupon/consumer.vue
  80. 307 0
      pages/coupon/coupon.vue
  81. 372 0
      pages/coupon/details.vue
  82. 332 0
      pages/detail/detail.vue
  83. 167 0
      pages/favorites/favorites.vue
  84. 388 0
      pages/groupBooking/detail.vue
  85. 257 0
      pages/groupBooking/index.vue
  86. 75 0
      pages/groupBooking/inviteImg.vue
  87. 513 0
      pages/index/index.vue
  88. 246 0
      pages/index/seckill.vue
  89. 185 0
      pages/integral/index.vue
  90. 138 0
      pages/moments/details.vue
  91. 425 0
      pages/money/pay.vue
  92. 65 0
      pages/money/paySuccess.vue
  93. 360 0
      pages/myteam/myteam.vue
  94. 153 0
      pages/notice/notice.vue
  95. 176 0
      pages/order/createOrder.vue
  96. 408 0
      pages/order/evaluate.vue
  97. 662 0
      pages/order/order.vue
  98. 179 0
      pages/order/orderDetail.vue
  99. 251 0
      pages/order/orderRefund.vue
  100. 638 0
      pages/order/refundOrder.vue

+ 3 - 0
.gitignore

@@ -0,0 +1,3 @@
+unpackage/debug
+unpackage/dist
+unpackage/resources

+ 16 - 0
.hbuilderx/launch.json

@@ -0,0 +1,16 @@
+{ // launch.json 配置了启动调试时相关设置,configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
+  // launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数
+    "version": "0.0",
+    "configurations": [{
+     	"default" : 
+     	{
+     		"launchtype" : "local"
+     	},
+     	"h5" : 
+     	{
+     		"launchtype" : "local"
+     	},
+     	"type" : "uniCloud"
+     }
+    ]
+}

+ 257 - 0
App.vue

@@ -0,0 +1,257 @@
+<script>
+/**
+ * vuex管理登陆状态,具体可以参考官方登陆模板示例
+ */
+import { mapMutations } from 'vuex';
+// #ifdef H5
+import { weixindata } from './utils/wxAuthorized';
+// #endif
+// #ifdef APP-PLUS
+import { getUpApp } from './utils/upApp.js';
+// #endif
+export default {
+	data() {
+		return {};
+	},
+	onLaunch: function(urlObj) {
+		let obj = this;
+		// 加载缓存中的用户信息
+		let userInfo = uni.getStorageSync('userInfo') || '';
+		// 判断是否拥有用户信息
+		if (userInfo.uid) {
+			// 更新登录信息
+			obj.login();
+			//更新登陆状态
+			uni.getStorage({
+				key: 'userInfo',
+				success: res => {
+					obj.setUserInfo(res.data);
+				}
+			});
+		}
+		// #ifdef H5
+		//判断是否已经缓存浏览器
+		let bool = uni.getStorageSync('weichatBrowser') || '';
+		if (bool === '') {
+			//判断是否为微信浏览 
+			bool = navigator.userAgent.toLowerCase().match(/MicroMessenger/i) == 'micromessenger';
+			// 保存当前是否为微信内核浏览器
+			uni.setStorageSync('weichatBrowser', bool);
+		}
+		if (bool) {
+			// 加载微信信息
+			weixindata();
+		}
+		// #endif
+		// #ifdef APP-PLUS
+		// 判断是否升级
+		getUpApp()
+		// 获取当前运行系统
+		let system = uni.getStorageSync('platform') || '';
+		if (!system) {
+			uni.setStorage({
+				key: 'platform',
+				data: uni.getSystemInfoSync().platform
+			});
+		}
+		// #endif
+	},
+	onShow: function() {
+		// 加载拦截
+		// console.log('App Show');
+	},
+	onHide: function() {
+		// console.log('App Hide');
+	},
+	methods: {
+		...mapMutations('user', ['setUserInfo', 'login', 'hasLogin']),
+	}
+};
+</script>
+
+<style lang="scss">
+/*全局公共样式和字体图标*/
+@import '/static/css/cmy.css';
+view,
+scroll-view,
+swiper,
+swiper-item,
+cover-view,
+cover-image,
+icon,
+text,
+rich-text,
+progress,
+button,
+checkbox,
+form,
+input,
+label,
+radio,
+slider,
+switch,
+textarea,
+navigator,
+audio,
+camera,
+image,
+video {
+	box-sizing: border-box;
+}
+page{
+	width: 0;
+	min-width: 100%;
+}
+/* 骨架屏替代方案 */
+.Skeleton {
+	background: #f3f3f3;
+	padding: 20rpx 0;
+	border-radius: 8rpx;
+}
+
+/* 图片载入替代方案 */
+.image-wrapper {
+	font-size: 0;
+	background: #f3f3f3;
+	border-radius: 4px;
+	image {
+		width: 100%;
+		height: 100%;
+		transition: 0.6s;
+		opacity: 0;
+		&.loaded {
+			opacity: 1;
+		}
+	}
+}
+// 设置富文本中图片最大宽度
+uni-rich-text img {
+	max-width: 100% !important;
+}
+/*边框*/
+.b-b:after,
+.b-t:after {
+	position: absolute;
+	z-index: 3;
+	left: 0;
+	right: 0;
+	height: 0;
+	content: '';
+	transform: scaleY(0.5);
+	border-bottom: 1px solid $border-color-base;
+}
+
+.b-b:after {
+	bottom: 0;
+}
+
+.b-t:after {
+	top: 0;
+}
+
+/* button样式改写 */
+uni-button,
+button {
+	height: 80rpx;
+	line-height: 80rpx;
+	font-size: $font-lg + 2rpx;
+	font-weight: normal;
+
+	&.no-border:before,
+	&.no-border:after {
+		border: 0;
+	}
+}
+
+uni-button[type='default'],
+button[type='default'] {
+	color: $font-color-dark;
+}
+
+/* input 样式 */
+.input-placeholder {
+	color: #999999;
+}
+
+.placeholder {
+	color: #999999;
+}
+// 边距样式
+@for $i from 1 to 4 {
+	.margin-l-#{$i * 10} {
+		margin-left: $i * 10rpx !important;
+	}
+	.margin-r-#{$i * 10} {
+		margin-right: $i * 10rpx !important;
+	}
+	.margin-t-#{$i * 10} {
+		margin-top: $i * 10rpx !important;
+	}
+	.margin-b-#{$i * 10} {
+		margin-bottom: $i * 10rpx !important;
+	}
+	.margin-#{$i * 10} {
+		margin: $i * 10rpx !important;
+	}
+	.margin-v-#{$i * 10} {
+		margin-top: $i * 10rpx !important;
+		margin-bottom: $i * 10rpx !important;
+	}
+	.margin-c-#{$i * 10} {
+		margin-left: $i * 10rpx !important;
+		margin-right: $i * 10rpx !important;
+	}
+	.padding-l-#{$i * 10} {
+		padding-left: $i * 10rpx !important;
+	}
+	.padding-r-#{$i * 10} {
+		padding-right: $i * 10rpx !important;
+	}
+	.padding-t-#{$i * 10} {
+		padding-top: $i * 10rpx !important;
+	}
+	.padding-b-#{$i * 10} {
+		padding-bottom: $i * 10rpx !important;
+	}
+	.padding-#{$i * 10} {
+		padding: $i * 10rpx !important;
+	}
+	.padding-v-#{$i * 10} {
+		padding-top: $i * 10rpx !important;
+		padding-bottom: $i * 10rpx !important;
+	}
+	.padding-c-#{$i * 10} {
+		padding-left: $i * 10rpx !important;
+		padding-right: $i * 10rpx !important;
+	}
+}
+// 字体大小
+.font-size-sm {
+	font-size: $font-sm;
+}
+.font-size-base {
+	font-size: $font-base;
+}
+.font-size-lg {
+	font-size: $font-lg;
+}
+// 字体颜色
+.font-color-yellow {
+	color: $color-yellow;
+}
+.font-color-gray {
+	color: $color-gray;
+}
+.font-color-red {
+	color: $color-red;
+}
+// 边框颜色
+.border-color-yellow {
+	border: 1rpx solid $color-yellow;
+}
+
+// 修改默认背景颜色
+uni-page-wrapper {
+	background-color: $page-color-base;
+}
+</style>

+ 36 - 0
api/address.js

@@ -0,0 +1,36 @@
+import request from '@/utils/request'
+
+export function getAddressList(data) {
+	return request({
+		url: '/api/address/list',
+		method: 'get',
+		data
+	});
+}
+export function addressEdit(data) {
+	return request({
+		url: '/api/address/edit',
+		method: 'post',
+		data
+	});
+}
+// 删除地址
+export function addressDel(data) {
+	return request({
+		url: '/api/address/del',
+		method: 'post',
+		data
+	});
+}
+
+// 获取门店信息
+// export function addressDel(data) {
+// 	return request({
+// 		url: '/api/address/del',
+// 		method: 'post',
+// 		data
+// 	});
+// }
+
+
+

+ 27 - 0
api/award.js

@@ -0,0 +1,27 @@
+import request from '@/utils/request'
+
+// 佣金明细
+export function spreadCommission(data,type) {
+	return request({
+		url: '/api/spread/commission/'+type,
+		method: 'get',
+		data
+	});
+}
+
+// 修改购物车数量
+export function getCartNum(data) {
+	return request({
+		url: '/api/cart/num',
+		method: 'post',
+		data
+	});
+}
+//删除购物车
+export function cartDel(data) {
+	return request({
+		url: '/api/cart/del',
+		method: 'post',
+		data
+	});
+}

+ 26 - 0
api/cart.js

@@ -0,0 +1,26 @@
+import request from '@/utils/request'
+
+export function getCartList(data) {
+	return request({
+		url: '/api/cart/list',
+		method: 'get',
+		data
+	});
+}
+
+// 修改购物车数量
+export function getCartNum(data) {
+	return request({
+		url: '/api/cart/num',
+		method: 'post',
+		data
+	});
+}
+//删除购物车
+export function cartDel(data) {
+	return request({
+		url: '/api/cart/del',
+		method: 'post',
+		data
+	});
+}

+ 10 - 0
api/category.js

@@ -0,0 +1,10 @@
+import request from '@/utils/request'
+
+// 获取商品分类
+export function getList(data) {
+	return request({
+		url: '/api/category',
+		method: 'get',
+		data
+	});
+}

+ 29 - 0
api/coupon.js

@@ -0,0 +1,29 @@
+import request from '@/utils/request'
+
+//获取优惠券列表
+export function getCouponsList(data,types) {
+	//优惠券状态 0全部 1未使用 2已使用
+	return request({
+		url: '/api/coupons/user/'+types,
+		method: 'get',
+		data
+	});
+}
+
+//领取优惠券
+export function setCoupons(data) {
+	return request({
+		url: '/api/coupon/receive',
+		method: 'post',
+		data
+	});
+}
+
+//获取可使用优惠券
+export function couponsOrder(data,price) {
+	return request({
+		url: '/api/coupons/order/'+price,
+		method: 'get',
+		data
+	});
+}

+ 18 - 0
api/favorite.js

@@ -0,0 +1,18 @@
+import request from '@/utils/request'
+
+//获取收藏夹列表
+export function getcollectList(data) {
+	return request({
+		url: '/api/collect/user',
+		method: 'get',
+		data
+	});
+}
+// 取消收藏
+export function delcollect(data) {
+	return request({
+		url: '/api/collect/del',
+		method: 'post',
+		data
+	});
+}

+ 37 - 0
api/groupBooking.js

@@ -0,0 +1,37 @@
+import request from '@/utils/request'
+
+// 获取拼团列表
+export function getCombinationList(data) {
+	return request({
+		url: '/api/combination/list',
+		method: 'get',
+		data
+	});
+}
+
+//取消拼团
+export function getCombinationLisRemove(data,id) {
+	return request({
+		url: '/api/combination/remove'+id,
+		method: 'get',
+		data
+	});
+}
+
+//拼团开团页面数据
+export function getCombinationLisPink(data,id) {
+	return request({
+		url: '/api/combination/pink/'+id,
+		method: 'get',
+		data
+	});
+}
+
+// 获取拼团海报
+export function getCombinationPoster(data) {
+	return request({
+		url: '/api/combination/poster',
+		method: 'post',
+		data
+	});
+}

+ 36 - 0
api/index.js

@@ -0,0 +1,36 @@
+import request from '@/utils/request'
+
+// 促销商品
+export function groom4(data) {
+	return request({
+		url: '/api/groom/list/4',
+		method: 'get',
+		data
+	});
+}
+// 精品推荐
+export function groom1(data) {
+	return request({
+		url: '/api/groom/list/1',
+		method: 'get',
+		data
+	});
+}
+// 新品首发
+export function groom3(data) {
+	return request({
+		url: '/api/groom/list/3',
+		method: 'get',
+		data
+	});
+}
+
+// 获取首页信息
+export function loadIndexs(data) {
+	return request({
+		url: '/api/index',
+		method: 'get',
+		data
+	});
+}
+

+ 29 - 0
api/integral.js

@@ -0,0 +1,29 @@
+import request from '@/utils/request'
+
+//	积分列表
+export function integrallist(data) {
+	return request({
+		url: '/api/integral/list',
+		method: 'get',
+		data
+	});
+}
+
+//	积分列表
+export function rechList(data) {
+	return request({
+		url: '/api/rech',
+		method: 'get',
+		data
+	});
+}
+//	消费券列表
+export function consumerList(data) {
+	return request({
+		url: '/api/consumer/list',
+		method: 'get',
+		data
+	});
+}
+
+

+ 57 - 0
api/login.js

@@ -0,0 +1,57 @@
+import request from '@/utils/request'
+
+// 登录
+export function login(data) {
+	return request({
+		url: '/api/login',
+		method: 'post',
+		data
+	});
+}
+// 注册
+export function register(data) {
+	return request({
+		url: '/api/register',
+		method: 'post',
+		data
+	});
+}
+// 验证码
+export function verify(data) {
+	// type=register为注册
+	// type=login为登录
+	return request({
+		url: '/api/register/verify',
+		method: 'post',
+		data
+	});
+}
+
+// 获取用户信息
+export function getUserInfo(data) {
+	return request({
+		url: '/api/userinfo',
+		method: 'get',
+		data
+	});
+}
+
+// 短信登录
+export function loginMobile(data) {
+	return request({
+		url: '/api/login/mobile',
+		method: 'post',
+		data
+	});
+}
+// 微信授权登录
+export function loginWx(data) {
+	return request({
+		url: '/api/wechat/appauth',
+		method: 'get',
+		data
+	});
+}
+
+
+

+ 26 - 0
api/moments.js

@@ -0,0 +1,26 @@
+import request from '@/utils/request'
+
+export function category(data) {
+	return request({
+		url: '/api/article/category/list',
+		method: 'get',
+		data
+	});
+}
+export function article(data,cid) {
+	return request({
+		url: '/api/article/list/'+cid,
+		method: 'get',
+		data
+	});
+}
+export function details(data,id) {
+	return request({
+		url: '/api/article/details/'+id,
+		method: 'get',
+		data
+	});
+}
+
+
+

+ 38 - 0
api/money.js

@@ -0,0 +1,38 @@
+import request from '@/utils/request'
+
+
+// 统计金额
+export function computedOrderkey(data) {
+	return request({
+		url: '/api/order/computed/'+data.orderkey,
+		method: 'post',
+		data
+	});
+}
+
+// 创建订单
+export function createOrderkey(data,key) {
+	return request({
+		url: '/api/order/create/'+key,
+		method: 'post',
+		data
+	});
+}
+// 账户余额
+export function balance(data) {
+	return request({
+		url: '/api/user/balance',
+		method: 'get',
+		data
+	});
+}
+
+// 订单支付
+export function orderPay(data) {
+	return request({
+		url: '/api/order/pay',
+		method: 'post',
+		data
+	});
+}
+

+ 10 - 0
api/myteam.js

@@ -0,0 +1,10 @@
+import request from '@/utils/request'
+
+// 获取我的团队
+export function spreadPeople(data) {
+	return request({
+		url: '/api/spread/people',
+		method:'post',
+		data
+	});
+}

+ 95 - 0
api/order.js

@@ -0,0 +1,95 @@
+import request from '@/utils/request'
+
+// 订单确认
+export function confirm(data) {
+	return request({
+		url: '/api/order/confirm',
+		method: 'post',
+		data
+	});
+}
+
+// 订单列表
+export function orderList(data) {
+	return request({
+		url: '/api/order/list',
+		method: 'get',
+		data
+	});
+}
+// 订单详细
+export function orderDetail(data,orderid) {
+	return request({
+		url: '/api/order/detail/'+orderid,
+		method: 'get',
+		data
+	});
+}
+
+// 取消订单
+export function orderCancel(data) {
+	return request({
+		url: '/api/order/cancel',
+		method: 'post',
+		data
+	});
+}
+
+// 删除订单
+export function orderDel(data) {
+	return request({
+		url: '/api/order/del',
+		method: 'get',
+		data
+	});
+}
+// 申请退款
+export function refund(data) {
+	return request({
+		url: '/api/order/refund/verify',
+		method: 'post',
+		data
+	});
+}
+// 退款理由列表
+export function refundReason(data) {
+	return request({
+		url: '/api/order/refund/reason',
+		method: 'get',
+		data
+	});
+	
+}
+
+// 确认收货
+export function orderTake(data) {
+	return request({
+		url: '/api/order/take',
+		method: 'post',
+		data
+	});
+}
+//提交评论
+export function product(data) {
+	return request({
+		url: '/api/order/product',
+		method: 'post',
+		data
+	});
+}
+//上传图片
+export function upload(data) {
+	return upFilse({
+		url: '/api/upload/image',
+		method: 'post',
+		data
+	});
+}
+//提交评论
+export function order_comment(data) {
+	return request({
+		url: '/api/order/comment',
+		method: 'post',
+		data
+	});
+}

+ 92 - 0
api/product.js

@@ -0,0 +1,92 @@
+import request from '@/utils/request'
+
+// 获取商品列表
+export function getProducts(data) {
+	// 	{
+	// 参数名称	是否必须	示例	备注
+	// sid			否			二级分类编号
+	// cid			否			一级分类编号(!)
+	// keyword		否			搜索
+	// priceOrder	否			价格排序
+	// salesOrder	否			销量排序
+	// news			否			是否新品
+	// page			否			分页参数起始值
+	// limit		否			分页数步长值
+	// }
+	return request({
+		url: '/api/products',
+		method: 'get',
+		data
+	});
+}
+// 获取商品详情
+export function goodsDetail(data, id) {
+	return request({
+		url: '/api/product/detail/' + id,
+		method: 'get',
+		data
+	});
+}
+// 加入购物车
+export function cartAdd(data) {
+	return request({
+		url: '/api/cart/add',
+		method: 'post',
+		data
+	});
+}
+
+// 收藏商品
+export function collectAdd(data) {
+	return request({
+		url: '/api/collect/add',
+		method: 'post',
+		data
+	});
+}
+
+// 取消收藏商品
+export function collectDel(data) {
+	return request({
+		url: '/api/collect/del',
+		method: 'post',
+		data
+	});
+}
+
+// 获取搜搜关键字
+export function searchKeyword(data) {
+	return request({
+		url: '/api/search/keyword',
+		method: 'get',
+		data
+	});
+}
+
+// 获取热门分类信息
+export function groomList(data,type) {
+	// 获取产品类型 1 精品推荐 2 热门榜单 3首发新品 4促销单品
+	return request({
+		url: '/api/groom/list/'+type,
+		method: 'get',
+		data
+	});
+}
+// 获取秒杀商品详细
+export function seckillGoods(data,id) {
+	return request({
+		url: '/api/seckill/detail/'+id,
+		method: 'get',
+		data
+	});
+}
+// 获取拼团商品详细
+export function groupGoods(data,id) {
+	return request({
+		url: '/api/combination/detail/'+id,
+		method: 'get',
+		data
+	});
+}
+
+

+ 59 - 0
api/received.js

@@ -0,0 +1,59 @@
+import request from '@/utils/request'
+
+
+// 获取商户收款码
+export function receivedCollectionCode(data,id) {
+	return request({
+		url: '/api/received/collection_code',
+		method: 'get',
+		data
+	});
+}
+// 获取付款码
+export function receivedPaymentCode(data,id) {
+	return request({
+		url: '/api/received/payment_code',
+		method: 'get',
+		data
+	});
+}
+// 检测是否有效
+export function receivedCodeState(data,id) {
+	return request({
+		url: '/api/received/code_state',
+		method: 'post',
+		data
+	});
+}
+// 创建订单
+export function receivedPaymentCreate(data,id) {
+	return request({
+		url: '/api/received/payment_create',
+		method: 'post',
+		data
+	});
+}
+// 我的订单
+export function receivedLst(data,id) {
+	return request({
+		url: '/api/received/lst',
+		method: 'get',
+		data
+	});
+}
+// 收款记录
+export function collectionLst(data,id) {
+	return request({
+		url: '/api/received/collection_lst',
+		method: 'post',
+		data
+	});
+}
+// 已提醒
+export function collectionSetTip(data,id) {
+	return request({
+		url: '/api/received/collection_set_tip',
+		method: 'post',
+		data
+	});
+}

+ 19 - 0
api/reply.js

@@ -0,0 +1,19 @@
+import request from '@/utils/request'
+
+
+// 产品评价数量和好评度
+export function reply_config(data,id) {
+	return request({
+		url: '/api/reply/config/'+id,
+		method: 'get',
+		data
+	});
+}
+// 获取产品评论
+export function reply_list(data,id) {
+	return request({
+		url: '/api/reply/list/'+id,
+		method: 'get',
+		data
+	});
+}

+ 18 - 0
api/seckill.js

@@ -0,0 +1,18 @@
+import request from '@/utils/request'
+
+// 获取秒杀分类
+export function getClass(data) {
+	return request({
+		url: '/api/seckill/index',
+		method: 'get',
+		data
+	});
+}
+// 获取秒杀列表
+export function getList(data,id) {
+	return request({
+		url: '/api/seckill/list/'+id,
+		method: 'get',
+		data
+	});
+}

+ 44 - 0
api/set.js

@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 修改用户信息
+export function userEdit(data) {
+	return request({
+		url: '/api/user/edit',
+		method: 'post',
+		data
+	});
+}
+
+//退出登录
+export function logout(data) {
+	return request({
+		url: '/api/logout',
+		method: 'get',
+		data
+	});
+}
+//修改密码
+export function registerReset(data) {
+	return request({
+		url: '/api/register/reset',
+		method: 'post',
+		data
+	});
+}
+
+//绑定手机
+export function binding(data) {
+	return request({
+		url: '/api/binding',
+		method: 'post',
+		data
+	});
+}
+//苹果生成账户
+export function applelogin(data) {
+	return request({
+		url: '/api/applelogin',
+		method: 'post',
+		data
+	});
+}

+ 10 - 0
api/shareQrCode.js

@@ -0,0 +1,10 @@
+import request from '@/utils/request'
+
+// 修改用户信息
+export function spreadBanner(data) {
+	return request({
+		url: '/api/spread/banner',
+		method: 'get',
+		data
+	});
+}

+ 14 - 0
api/shoping.js

@@ -0,0 +1,14 @@
+import request from '@/utils/request'
+
+
+// 获取店铺信息
+export function getShoping(data) {
+	return request({
+		url: '/api/merchant',
+		method: 'get',
+		data
+	});
+}
+
+
+

+ 27 - 0
api/sign.js

@@ -0,0 +1,27 @@
+import request from '@/utils/request'
+
+// 获取签到列表
+export function signList(data) {
+	return request({
+		url: '/api/sign/list',
+		method: 'get',
+		data
+	});
+}
+// 点击签到
+export function integral(data) {
+	return request({
+		url: '/api/sign/integral',
+		method: 'post',
+		data
+	});
+}
+
+// 签到信息
+export function signUser(data) {
+	return request({
+		url: '/api/sign/user',
+		method: 'post',
+		data
+	});
+}

+ 28 - 0
api/user.js

@@ -0,0 +1,28 @@
+import request from '@/utils/request'
+
+// 订单统计信息
+export function orderData(data) {
+	return request({
+		url: '/api/order/data',
+		method: 'get',
+		data
+	});
+}
+
+// 订单统计信息
+export function orderVerific(data) {
+	return request({
+		url: '/api/order/order_verific',
+		method: 'post',
+		data
+	});
+}
+
+// 获取用户信息
+export function userinfo(data) {
+	return request({
+		url: '/api/userinfo',
+		method: 'get',
+		data
+	});
+}

+ 109 - 0
api/wallet.js

@@ -0,0 +1,109 @@
+import request from '@/utils/request'
+
+// 获取用户消费记录
+export function spreadCommission(data,state) {
+	return request({
+		url: '/api/spread/commission/'+state,
+		method: 'get',
+		data
+	});
+}
+
+// 获取账户余额
+export function userBalance(data) {
+	return request({
+		url: '/api/user/balance',
+		method: 'get',
+		data
+	});
+}
+
+// 提现
+export function extractCash(data) {
+	return request({
+		url: '/api/extract/cash',
+		method: 'post',
+		data
+	});
+}
+// 转入
+export function rechargemoneys(data) {
+	return request({
+		url: '/api/user/do',
+		method: 'get',
+		data
+	});
+}
+
+//佣金转余额
+export function extractCashs(data) {
+	return request({
+		url: '/api/recharge/wechat',
+		method: 'post',
+		data
+	});
+}
+
+
+// 提现信息
+export function extractBank(data) {
+	return request({
+		url: '/api/extract/bank',
+		method: 'get',
+		data
+	});
+}
+// 佣金信息
+export function commission(data) {
+	return request({
+		url: '/api/commission',
+		method: 'get',
+		data
+	});
+}
+
+
+// 充值
+export function rechargeWechat(data) {
+	return request({
+		url: '/api/recharge/wechat',
+		method: 'post',
+		data
+	});
+}
+// 获取提现支付宝账号
+export function aliInfo(data) {
+	return request({
+		url: '/api/ali/info',
+		method: 'get',
+		data
+	});
+}
+//获取默认银行卡账号
+export function bankInfo(data) {
+	return request({
+		url: '/api/bank/info',
+		method: 'get',
+		data
+	});
+}
+// 保存提现支付宝账号
+export function setAliInfo(data) {
+	return request({
+		url: '/api/ali/edit',
+		method: 'post',
+		data
+	});
+}
+//保存默认银行卡账号
+export function setBankInfo(data) {
+	return request({
+		url: '/api/bank/edit',
+		method: 'post',
+		data
+	});
+}
+
+
+
+

+ 40 - 0
api/wx.js

@@ -0,0 +1,40 @@
+import request from '@/utils/request'
+import store from '@/store';
+// #ifdef H5
+//微信配置
+export function wechatConfig(data) {
+	return request({
+		url: '/api/wechat/config',
+		method: 'get',
+		data:{
+			url:window.location.href
+		}
+	});
+}
+// 微信分享信息
+export function share(data) {
+	return request({
+		url: '/api/share',
+		method: 'get',
+		data
+	});
+}
+// 微信h5code地址
+export function wechatAuth(data) {
+	return request({
+		url: '/api/wechat/auth',
+		method: 'get',
+		data
+	});
+}
+// #endif
+// #ifdef MP-WEIXIN
+// 微信小程序code地址
+export function wechatMpAuth(data) {
+	return request({
+		url: '/api/wechat/mp_auth',
+		method: 'post',
+		data
+	});
+}
+// #endif

+ 36 - 0
components/canvasLove/canvasLove.vue

@@ -0,0 +1,36 @@
+<template>
+	<canvas class="canvasBox" :id="'canvasId_' + canvasId"></canvas>
+</template>
+
+<script>
+export default {
+	props: {
+		canvasId: {
+			type: String,
+			default: '1'
+		}
+	},
+	data() {
+		return {
+			canvasObj: value
+		};
+	},
+	created() {
+		// 保存画布对象
+		this.canvasObj = uni.createCanvasContext('canvasId' + this.canvasId, this);
+		
+		// 获取可使用窗口宽度
+		let width = uni.getSystemInfoSync().windowWidth 
+		this.width = `${width}px` 
+		
+	}
+};
+</script>
+
+<style>
+	.canvasBox{
+		width: 110rpx;
+		height: 370rpx;
+	}
+	
+</style>

Разница между файлами не показана из-за своего большого размера
+ 18 - 0
components/empty.vue


+ 133 - 0
components/mix-list-cell.vue

@@ -0,0 +1,133 @@
+<template>
+	<view class="content">
+		
+		<view class="mix-list-cell" :class="border" @click="eventClick" hover-class="cell-hover"  :hover-stay-time="50">
+			<image
+				v-if="icon"
+				class="cell-icon"
+				:style="[{
+					color: iconColor,
+				}]"
+				:src='icon'
+				mode='aspectFit'
+			></image>
+			<text class="cell-tit clamp">{{title}}</text>
+			<text v-if="tips" class="cell-tip">{{tips}}</text>
+			<text class="cell-more yticon"
+				:class="typeList[navigateType]"
+			></text>
+		</view>
+
+	</view>
+</template>
+ 
+<script>
+	/**
+	 *  简单封装了下, 应用范围比较狭窄,可以在此基础上进行扩展使用
+	 *  比如加入image, iconSize可控等
+	 */
+	export default {
+		data() {
+			return {
+				typeList: {
+					left: 'icon-zuo',
+					right: 'icon-you',
+					up: 'icon-shang',
+					down: 'icon-xia'
+				},
+			}
+		},
+		props: {
+			// 图标
+			icon: {
+				type: String,
+				default: ''
+			},
+			// 标题
+			title: {
+				type: String,
+				default: '标题'
+			},
+			// 右侧角标内容
+			tips: {
+				type: String,
+				default: ''
+			},
+			// 是否显示右侧角标
+			showType:{
+				type: Boolean,
+				default: true
+			},
+			// 右侧角标类型
+			navigateType: {
+				type: String,
+				default: 'right'
+			},
+			// 边框
+			border: {
+				type: String,
+				default: 'border-bottom-light'
+			},
+			// 点击时背景颜色
+			hoverClass: {
+				type: String,
+				default: 'cell-hover'
+			},
+			// 图标颜色
+			iconColor: {
+				type: String,
+				default: '#333'
+			}
+		},
+		methods: {
+			eventClick(){
+				this.$emit('eventClick');
+			}
+		},
+	}
+</script>
+
+<style lang='scss'>
+
+	.icon .mix-list-cell.b-b:after{
+		left: 30rpx;
+	}
+	.mix-list-cell{
+		display:flex;
+		align-items:baseline;
+		padding: 20rpx $page-row-spacing;
+		line-height:60rpx;
+		position:relative;
+		
+		&.cell-hover{
+			background:#fafafa;
+		}
+		&.b-b:after{
+			left: 30rpx;
+		}
+
+		.cell-icon{
+			align-self:center;
+			width:58rpx;
+			max-height:36rpx;
+			font-size:38rpx;
+			padding-right: 20rpx;
+		}
+		.cell-more{
+			align-self: center;
+			font-size:30rpx;
+			color:$font-color-base;
+			margin-left:$uni-spacing-row-sm;
+		}
+		.cell-tit{
+			flex: 1;
+			font-size: $font-base;
+			color: $font-color-dark;
+			margin-right:10rpx;
+		}
+		.cell-tip{
+			font-size: $font-sm+2rpx;
+			color: $font-color-light;
+		}
+	}
+</style>

Разница между файлами не показана из-за своего большого размера
+ 6 - 0
components/mix-loading/mix-loading.vue


+ 202 - 0
components/share.vue

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

+ 218 - 0
components/ss-calendar/ss-calendar.vue

@@ -0,0 +1,218 @@
+<template>
+	<view class="calendar__wrap">
+		<view class="header">
+			<view class="current-date">{{ currentDate }}</view>
+		</view>
+		<view class="body">
+			<view class="weeks">
+				<view class="week__item" v-for="week in weeks" :key="week">{{ week }}</view>
+			</view>
+			<view class="day__list">
+				<view class="day__item" v-for="(item, index) in dateData" :key="index">
+					<view class="checked-box" :class="[checksClass]" v-if="item === 'checked'">
+						<text class="checked iconfont iconfavor" v-if="!checksIcon"></text>
+						<image v-else :src="checksIcon" mode="aspectFit"></image>
+						<view class="check_text" v-if="checkTextShow">{{ dayLoad(index) }}</view>
+					</view>
+					<text class="current-box" :class="[item === day ? (actionClass ? actionClass : 'current') : '']" v-else>{{ item }}</text>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	props: {
+		//选中的日期数据
+		checks: {
+			type: Array,
+			default() {
+				// 例子[1,2,3,4],表示本月1,2,3,4号4天被选中
+				return [];
+			}
+		},
+		// 选中物品的样式类
+		checksClass: {
+			type: String,
+			default: ''
+		},
+		// 选中时图标
+		checksIcon: {
+			type: String
+		},
+		// 选中时是否显示文字
+		checkTextShow: {
+			type: Boolean, 
+			default: false
+		},
+		// 表示当前日期的样式
+		actionClass: {
+			type: String,
+			default: ''
+		}
+	},
+	data() {
+		const { year, month, day } = this.getDate();
+		const dateData = this.getDateData(year, month);
+		const noDay = ( new Date(year,month-1,1)).getDay();
+		return {
+			year,
+			month,
+			day,
+			dateData,
+			noDay,//本月1号是星期几
+			weeks: ['日', '一', '二', '三', '四', '五', '六'],
+		};
+	},
+	computed: {
+		// 获取当前日期
+		currentDate() {
+			return `${this.year}-${this.format(this.month)}`;
+		}
+	},
+	watch: {
+		checks(val) {
+			const { year, month } = this.getDate();
+			const dateData = this.getDateData(year, month);
+			// 保存当前月份信息
+			this.dateData = dateData;
+		},
+	},
+	methods: {
+		// 重新计算时间
+		dayLoad: function(value) {
+			return value + 1 - this.noDay;
+		},
+		// 获取当前日期
+		getDate(current) {
+			const date = current ? new Date(current) : new Date();
+			const year = date.getFullYear();
+			// 月份值默认从0开始
+			const month = date.getMonth() + 1;
+			const day = date.getDate();
+			return {
+				year,
+				month,
+				day
+			};
+		},
+		// 日期处理
+		getDateData(year, month) {
+			// 新增月份时需要减少1个月
+			const date = new Date(year,month-1,1);
+			const firstDayWeek = date.getDay();
+			const data = [...this.getEmptys(firstDayWeek), ...this.getDays(firstDayWeek)];
+			return data;
+		},
+		// 查询日期列表有几个空格
+		getEmptys(count) {
+			let arr = [];
+			if (count) {
+				for (let i = 0; i < count; i++) {
+					arr.push('');
+				}
+			}
+			return arr;
+		},
+		getLastDay() {
+			let { year, month } = this.getDate();
+			month += 1;
+			if (month > 11) {
+				year += 1;
+				month = 1;
+			}
+			let firstDayTimeStamp = new Date(`${year}/${month}/1`).getTime();
+			let oneDayTimeStamp = 24 * 60 * 60 * 1000;
+			let lastDay = new Date(firstDayTimeStamp - oneDayTimeStamp).getDate();
+			return lastDay;
+		},
+		getDays() {
+			const lastDay = this.getLastDay();
+			const days = [];
+			for (let i = 1; i <= lastDay; i++) {
+				days.push(this.checks.includes(i) ? 'checked' : i);
+			}
+			return days;
+		},
+		format(num) {
+			return num < 10 ? `0${num}` : num;
+		}
+	}
+};
+</script>
+
+<style lang="scss" scoped>
+.calendar__wrap {
+	background-color: #fff;
+	color: $uni-text-color;
+	.header {
+		padding: 0 24rpx;
+		.current-date {
+			text-align: center;
+			font-size: $font-lg + 2rpx;
+			// border-bottom: 2rpx solid #eee;
+			padding: 32rpx 0;
+		}
+	}
+	.body {
+		.weeks {
+			display: flex;
+			font-size: $font-lg;
+			padding: 10rpx 0;
+			background-color: #f4f7ff;
+			.week__item {
+				flex: 1;
+				text-align: center;
+			}
+		}
+		.day__list {
+			display: flex;
+			flex-wrap: wrap;
+			.day__item {
+				display: flex;
+				justify-content: center;
+				width: 14.285%;
+				text-align: center;
+				padding: 30rpx 0;
+				font-size: 34rpx;
+				color: $font-color-light;
+				.checked-box,
+				.current-box {
+					display: flex;
+					align-items: center;
+					justify-content: center;
+					border-radius: 100%;
+					box-sizing: border-box;
+					position: relative;
+				}
+				image,
+				.checked-box,
+				.current-box,
+				.check_text {
+					width: 56rpx;
+					height: 56rpx;
+					line-height: 56rpx;
+				}
+				image,
+				.check_text {
+					position: absolute;
+					top: 0;
+					left: 0;
+				}
+				.checked {
+					font-size: 40rpx;
+					background-color: #3f9dff;
+					color: #fff;
+				}
+				.current {
+					padding: 12rpx;
+					background-color: $background-color;
+					color: #fff;
+					font-size: 28rpx;
+				}
+			}
+		}
+	}
+}
+</style>

+ 1207 - 0
components/tki-qrcode/qrcode.js

@@ -0,0 +1,1207 @@
+let QRCode = {};
+(function () {
+    /**
+     * 获取单个字符的utf8编码
+     * unicode BMP平面约65535个字符
+     * @param {num} code
+     * return {array}
+     */
+    function unicodeFormat8(code) {
+        // 1 byte
+        var c0, c1, c2;
+        if (code < 128) {
+            return [code];
+            // 2 bytes
+        } else if (code < 2048) {
+            c0 = 192 + (code >> 6);
+            c1 = 128 + (code & 63);
+            return [c0, c1];
+            // 3 bytes
+        } else {
+            c0 = 224 + (code >> 12);
+            c1 = 128 + (code >> 6 & 63);
+            c2 = 128 + (code & 63);
+            return [c0, c1, c2];
+        }
+    }
+    /**
+     * 获取字符串的utf8编码字节串
+     * @param {string} string
+     * @return {array}
+     */
+    function getUTF8Bytes(string) {
+        var utf8codes = [];
+        for (var i = 0; i < string.length; i++) {
+            var code = string.charCodeAt(i);
+            var utf8 = unicodeFormat8(code);
+            for (var j = 0; j < utf8.length; j++) {
+                utf8codes.push(utf8[j]);
+            }
+        }
+        return utf8codes;
+    }
+    /**
+     * 二维码算法实现
+     * @param {string} data              要编码的信息字符串
+     * @param {num} errorCorrectLevel 纠错等级
+     */
+    function QRCodeAlg(data, errorCorrectLevel) {
+        this.typeNumber = -1; //版本
+        this.errorCorrectLevel = errorCorrectLevel;
+        this.modules = null; //二维矩阵,存放最终结果
+        this.moduleCount = 0; //矩阵大小
+        this.dataCache = null; //数据缓存
+        this.rsBlocks = null; //版本数据信息
+        this.totalDataCount = -1; //可使用的数据量
+        this.data = data;
+        this.utf8bytes = getUTF8Bytes(data);
+        this.make();
+    }
+    QRCodeAlg.prototype = {
+		
+        constructor: QRCodeAlg,
+        /**
+         * 获取二维码矩阵大小
+         * @return {num} 矩阵大小
+         */
+        getModuleCount: function () {
+            return this.moduleCount;
+        },
+        /**
+         * 编码
+         */
+        make: function () {
+            this.getRightType();
+            this.dataCache = this.createData();
+            this.createQrcode();
+        },
+        /**
+         * 设置二位矩阵功能图形
+         * @param  {bool} test 表示是否在寻找最好掩膜阶段
+         * @param  {num} maskPattern 掩膜的版本
+         */
+        makeImpl: function (maskPattern) {
+            this.moduleCount = this.typeNumber * 4 + 17;
+            this.modules = new Array(this.moduleCount);
+            for (var row = 0; row < this.moduleCount; row++) {
+                this.modules[row] = new Array(this.moduleCount);
+            }
+            this.setupPositionProbePattern(0, 0);
+            this.setupPositionProbePattern(this.moduleCount - 7, 0);
+            this.setupPositionProbePattern(0, this.moduleCount - 7);
+            this.setupPositionAdjustPattern();
+            this.setupTimingPattern();
+            this.setupTypeInfo(true, maskPattern);
+            if (this.typeNumber >= 7) {
+                this.setupTypeNumber(true);
+            }
+            this.mapData(this.dataCache, maskPattern);
+        },
+        /**
+         * 设置二维码的位置探测图形
+         * @param  {num} row 探测图形的中心横坐标
+         * @param  {num} col 探测图形的中心纵坐标
+         */
+        setupPositionProbePattern: function (row, col) {
+            for (var r = -1; r <= 7; r++) {
+                if (row + r <= -1 || this.moduleCount <= row + r) continue;
+                for (var c = -1; c <= 7; c++) {
+                    if (col + c <= -1 || this.moduleCount <= col + c) continue;
+                    if ((0 <= r && r <= 6 && (c == 0 || c == 6)) || (0 <= c && c <= 6 && (r == 0 || r == 6)) || (2 <= r && r <= 4 && 2 <= c && c <= 4)) {
+                        this.modules[row + r][col + c] = true;
+                    } else {
+                        this.modules[row + r][col + c] = false;
+                    }
+                }
+            }
+        },
+        /**
+         * 创建二维码
+         * @return {[type]} [description]
+         */
+        createQrcode: function () {
+            var minLostPoint = 0;
+            var pattern = 0;
+            var bestModules = null;
+            for (var i = 0; i < 8; i++) {
+                this.makeImpl(i);
+                var lostPoint = QRUtil.getLostPoint(this);
+                if (i == 0 || minLostPoint > lostPoint) {
+                    minLostPoint = lostPoint;
+                    pattern = i;
+                    bestModules = this.modules;
+                }
+            }
+            this.modules = bestModules;
+            this.setupTypeInfo(false, pattern);
+            if (this.typeNumber >= 7) {
+                this.setupTypeNumber(false);
+            }
+        },
+        /**
+         * 设置定位图形
+         * @return {[type]} [description]
+         */
+        setupTimingPattern: function () {
+            for (var r = 8; r < this.moduleCount - 8; r++) {
+                if (this.modules[r][6] != null) {
+                    continue;
+                }
+                this.modules[r][6] = (r % 2 == 0);
+                if (this.modules[6][r] != null) {
+                    continue;
+                }
+                this.modules[6][r] = (r % 2 == 0);
+            }
+        },
+        /**
+         * 设置矫正图形
+         * @return {[type]} [description]
+         */
+        setupPositionAdjustPattern: function () {
+            var pos = QRUtil.getPatternPosition(this.typeNumber);
+            for (var i = 0; i < pos.length; i++) {
+                for (var j = 0; j < pos.length; j++) {
+                    var row = pos[i];
+                    var col = pos[j];
+                    if (this.modules[row][col] != null) {
+                        continue;
+                    }
+                    for (var r = -2; r <= 2; r++) {
+                        for (var c = -2; c <= 2; c++) {
+                            if (r == -2 || r == 2 || c == -2 || c == 2 || (r == 0 && c == 0)) {
+                                this.modules[row + r][col + c] = true;
+                            } else {
+                                this.modules[row + r][col + c] = false;
+                            }
+                        }
+                    }
+                }
+            }
+        },
+        /**
+         * 设置版本信息(7以上版本才有)
+         * @param  {bool} test 是否处于判断最佳掩膜阶段
+         * @return {[type]}      [description]
+         */
+        setupTypeNumber: function (test) {
+            var bits = QRUtil.getBCHTypeNumber(this.typeNumber);
+            for (var i = 0; i < 18; i++) {
+                var mod = (!test && ((bits >> i) & 1) == 1);
+                this.modules[Math.floor(i / 3)][i % 3 + this.moduleCount - 8 - 3] = mod;
+                this.modules[i % 3 + this.moduleCount - 8 - 3][Math.floor(i / 3)] = mod;
+            }
+        },
+        /**
+         * 设置格式信息(纠错等级和掩膜版本)
+         * @param  {bool} test
+         * @param  {num} maskPattern 掩膜版本
+         * @return {}
+         */
+        setupTypeInfo: function (test, maskPattern) {
+            var data = (QRErrorCorrectLevel[this.errorCorrectLevel] << 3) | maskPattern;
+            var bits = QRUtil.getBCHTypeInfo(data);
+            // vertical
+            for (var i = 0; i < 15; i++) {
+                var mod = (!test && ((bits >> i) & 1) == 1);
+                if (i < 6) {
+                    this.modules[i][8] = mod;
+                } else if (i < 8) {
+                    this.modules[i + 1][8] = mod;
+                } else {
+                    this.modules[this.moduleCount - 15 + i][8] = mod;
+                }
+                // horizontal
+                var mod = (!test && ((bits >> i) & 1) == 1);
+                if (i < 8) {
+                    this.modules[8][this.moduleCount - i - 1] = mod;
+                } else if (i < 9) {
+                    this.modules[8][15 - i - 1 + 1] = mod;
+                } else {
+                    this.modules[8][15 - i - 1] = mod;
+                }
+            }
+            // fixed module
+            this.modules[this.moduleCount - 8][8] = (!test);
+        },
+        /**
+         * 数据编码
+         * @return {[type]} [description]
+         */
+        createData: function () {
+            var buffer = new QRBitBuffer();
+            var lengthBits = this.typeNumber > 9 ? 16 : 8;
+            buffer.put(4, 4); //添加模式
+            buffer.put(this.utf8bytes.length, lengthBits);
+            for (var i = 0, l = this.utf8bytes.length; i < l; i++) {
+                buffer.put(this.utf8bytes[i], 8);
+            }
+            if (buffer.length + 4 <= this.totalDataCount * 8) {
+                buffer.put(0, 4);
+            }
+            // padding
+            while (buffer.length % 8 != 0) {
+                buffer.putBit(false);
+            }
+            // padding
+            while (true) {
+                if (buffer.length >= this.totalDataCount * 8) {
+                    break;
+                }
+                buffer.put(QRCodeAlg.PAD0, 8);
+                if (buffer.length >= this.totalDataCount * 8) {
+                    break;
+                }
+                buffer.put(QRCodeAlg.PAD1, 8);
+            }
+            return this.createBytes(buffer);
+        },
+        /**
+         * 纠错码编码
+         * @param  {buffer} buffer 数据编码
+         * @return {[type]}
+         */
+        createBytes: function (buffer) {
+            var offset = 0;
+            var maxDcCount = 0;
+            var maxEcCount = 0;
+            var length = this.rsBlock.length / 3;
+            var rsBlocks = new Array();
+            for (var i = 0; i < length; i++) {
+                var count = this.rsBlock[i * 3 + 0];
+                var totalCount = this.rsBlock[i * 3 + 1];
+                var dataCount = this.rsBlock[i * 3 + 2];
+                for (var j = 0; j < count; j++) {
+                    rsBlocks.push([dataCount, totalCount]);
+                }
+            }
+            var dcdata = new Array(rsBlocks.length);
+            var ecdata = new Array(rsBlocks.length);
+            for (var r = 0; r < rsBlocks.length; r++) {
+                var dcCount = rsBlocks[r][0];
+                var ecCount = rsBlocks[r][1] - dcCount;
+                maxDcCount = Math.max(maxDcCount, dcCount);
+                maxEcCount = Math.max(maxEcCount, ecCount);
+                dcdata[r] = new Array(dcCount);
+                for (var i = 0; i < dcdata[r].length; i++) {
+                    dcdata[r][i] = 0xff & buffer.buffer[i + offset];
+                }
+                offset += dcCount;
+                var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);
+                var rawPoly = new QRPolynomial(dcdata[r], rsPoly.getLength() - 1);
+                var modPoly = rawPoly.mod(rsPoly);
+                ecdata[r] = new Array(rsPoly.getLength() - 1);
+                for (var i = 0; i < ecdata[r].length; i++) {
+                    var modIndex = i + modPoly.getLength() - ecdata[r].length;
+                    ecdata[r][i] = (modIndex >= 0) ? modPoly.get(modIndex) : 0;
+                }
+            }
+            var data = new Array(this.totalDataCount);
+            var index = 0;
+            for (var i = 0; i < maxDcCount; i++) {
+                for (var r = 0; r < rsBlocks.length; r++) {
+                    if (i < dcdata[r].length) {
+                        data[index++] = dcdata[r][i];
+                    }
+                }
+            }
+            for (var i = 0; i < maxEcCount; i++) {
+                for (var r = 0; r < rsBlocks.length; r++) {
+                    if (i < ecdata[r].length) {
+                        data[index++] = ecdata[r][i];
+                    }
+                }
+            }
+            return data;
+
+        },
+        /**
+         * 布置模块,构建最终信息
+         * @param  {} data
+         * @param  {} maskPattern
+         * @return {}
+         */
+        mapData: function (data, maskPattern) {
+            var inc = -1;
+            var row = this.moduleCount - 1;
+            var bitIndex = 7;
+            var byteIndex = 0;
+            for (var col = this.moduleCount - 1; col > 0; col -= 2) {
+                if (col == 6) col--;
+                while (true) {
+                    for (var c = 0; c < 2; c++) {
+                        if (this.modules[row][col - c] == null) {
+                            var dark = false;
+                            if (byteIndex < data.length) {
+                                dark = (((data[byteIndex] >>> bitIndex) & 1) == 1);
+                            }
+                            var mask = QRUtil.getMask(maskPattern, row, col - c);
+                            if (mask) {
+                                dark = !dark;
+                            }
+                            this.modules[row][col - c] = dark;
+                            bitIndex--;
+                            if (bitIndex == -1) {
+                                byteIndex++;
+                                bitIndex = 7;
+                            }
+                        }
+                    }
+                    row += inc;
+                    if (row < 0 || this.moduleCount <= row) {
+                        row -= inc;
+                        inc = -inc;
+                        break;
+                    }
+                }
+            }
+        }
+    };
+    /**
+     * 填充字段
+     */
+    QRCodeAlg.PAD0 = 0xEC;
+    QRCodeAlg.PAD1 = 0x11;
+    //---------------------------------------------------------------------
+    // 纠错等级对应的编码
+    //---------------------------------------------------------------------
+    var QRErrorCorrectLevel = [1, 0, 3, 2];
+    //---------------------------------------------------------------------
+    // 掩膜版本
+    //---------------------------------------------------------------------
+    var QRMaskPattern = {
+        PATTERN000: 0,
+        PATTERN001: 1,
+        PATTERN010: 2,
+        PATTERN011: 3,
+        PATTERN100: 4,
+        PATTERN101: 5,
+        PATTERN110: 6,
+        PATTERN111: 7
+    };
+    //---------------------------------------------------------------------
+    // 工具类
+    //---------------------------------------------------------------------
+    var QRUtil = {
+        /*
+        每个版本矫正图形的位置
+         */
+        PATTERN_POSITION_TABLE: [
+            [],
+            [6, 18],
+            [6, 22],
+            [6, 26],
+            [6, 30],
+            [6, 34],
+            [6, 22, 38],
+            [6, 24, 42],
+            [6, 26, 46],
+            [6, 28, 50],
+            [6, 30, 54],
+            [6, 32, 58],
+            [6, 34, 62],
+            [6, 26, 46, 66],
+            [6, 26, 48, 70],
+            [6, 26, 50, 74],
+            [6, 30, 54, 78],
+            [6, 30, 56, 82],
+            [6, 30, 58, 86],
+            [6, 34, 62, 90],
+            [6, 28, 50, 72, 94],
+            [6, 26, 50, 74, 98],
+            [6, 30, 54, 78, 102],
+            [6, 28, 54, 80, 106],
+            [6, 32, 58, 84, 110],
+            [6, 30, 58, 86, 114],
+            [6, 34, 62, 90, 118],
+            [6, 26, 50, 74, 98, 122],
+            [6, 30, 54, 78, 102, 126],
+            [6, 26, 52, 78, 104, 130],
+            [6, 30, 56, 82, 108, 134],
+            [6, 34, 60, 86, 112, 138],
+            [6, 30, 58, 86, 114, 142],
+            [6, 34, 62, 90, 118, 146],
+            [6, 30, 54, 78, 102, 126, 150],
+            [6, 24, 50, 76, 102, 128, 154],
+            [6, 28, 54, 80, 106, 132, 158],
+            [6, 32, 58, 84, 110, 136, 162],
+            [6, 26, 54, 82, 110, 138, 166],
+            [6, 30, 58, 86, 114, 142, 170]
+        ],
+        G15: (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0),
+        G18: (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0),
+        G15_MASK: (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1),
+        /*
+        BCH编码格式信息
+         */
+        getBCHTypeInfo: function (data) {
+            var d = data << 10;
+            while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) {
+                d ^= (QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15)));
+            }
+            return ((data << 10) | d) ^ QRUtil.G15_MASK;
+        },
+        /*
+        BCH编码版本信息
+         */
+        getBCHTypeNumber: function (data) {
+            var d = data << 12;
+            while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) {
+                d ^= (QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18)));
+            }
+            return (data << 12) | d;
+        },
+        /*
+        获取BCH位信息
+         */
+        getBCHDigit: function (data) {
+            var digit = 0;
+            while (data != 0) {
+                digit++;
+                data >>>= 1;
+            }
+            return digit;
+        },
+        /*
+        获取版本对应的矫正图形位置
+         */
+        getPatternPosition: function (typeNumber) {
+            return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1];
+        },
+        /*
+        掩膜算法
+         */
+        getMask: function (maskPattern, i, j) {
+            switch (maskPattern) {
+                case QRMaskPattern.PATTERN000:
+                    return (i + j) % 2 == 0;
+                case QRMaskPattern.PATTERN001:
+                    return i % 2 == 0;
+                case QRMaskPattern.PATTERN010:
+                    return j % 3 == 0;
+                case QRMaskPattern.PATTERN011:
+                    return (i + j) % 3 == 0;
+                case QRMaskPattern.PATTERN100:
+                    return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 == 0;
+                case QRMaskPattern.PATTERN101:
+                    return (i * j) % 2 + (i * j) % 3 == 0;
+                case QRMaskPattern.PATTERN110:
+                    return ((i * j) % 2 + (i * j) % 3) % 2 == 0;
+                case QRMaskPattern.PATTERN111:
+                    return ((i * j) % 3 + (i + j) % 2) % 2 == 0;
+                default:
+                    throw new Error("bad maskPattern:" + maskPattern);
+            }
+        },
+        /*
+        获取RS的纠错多项式
+         */
+        getErrorCorrectPolynomial: function (errorCorrectLength) {
+            var a = new QRPolynomial([1], 0);
+            for (var i = 0; i < errorCorrectLength; i++) {
+                a = a.multiply(new QRPolynomial([1, QRMath.gexp(i)], 0));
+            }
+            return a;
+        },
+        /*
+        获取评价
+         */
+        getLostPoint: function (qrCode) {
+            var moduleCount = qrCode.getModuleCount(),
+                lostPoint = 0,
+                darkCount = 0;
+            for (var row = 0; row < moduleCount; row++) {
+                var sameCount = 0;
+                var head = qrCode.modules[row][0];
+                for (var col = 0; col < moduleCount; col++) {
+                    var current = qrCode.modules[row][col];
+                    //level 3 评价
+                    if (col < moduleCount - 6) {
+                        if (current && !qrCode.modules[row][col + 1] && qrCode.modules[row][col + 2] && qrCode.modules[row][col + 3] && qrCode.modules[row][col + 4] && !qrCode.modules[row][col + 5] && qrCode.modules[row][col + 6]) {
+                            if (col < moduleCount - 10) {
+                                if (qrCode.modules[row][col + 7] && qrCode.modules[row][col + 8] && qrCode.modules[row][col + 9] && qrCode.modules[row][col + 10]) {
+                                    lostPoint += 40;
+                                }
+                            } else if (col > 3) {
+                                if (qrCode.modules[row][col - 1] && qrCode.modules[row][col - 2] && qrCode.modules[row][col - 3] && qrCode.modules[row][col - 4]) {
+                                    lostPoint += 40;
+                                }
+                            }
+                        }
+                    }
+                    //level 2 评价
+                    if ((row < moduleCount - 1) && (col < moduleCount - 1)) {
+                        var count = 0;
+                        if (current) count++;
+                        if (qrCode.modules[row + 1][col]) count++;
+                        if (qrCode.modules[row][col + 1]) count++;
+                        if (qrCode.modules[row + 1][col + 1]) count++;
+                        if (count == 0 || count == 4) {
+                            lostPoint += 3;
+                        }
+                    }
+                    //level 1 评价
+                    if (head ^ current) {
+                        sameCount++;
+                    } else {
+                        head = current;
+                        if (sameCount >= 5) {
+                            lostPoint += (3 + sameCount - 5);
+                        }
+                        sameCount = 1;
+                    }
+                    //level 4 评价
+                    if (current) {
+                        darkCount++;
+                    }
+                }
+            }
+            for (var col = 0; col < moduleCount; col++) {
+                var sameCount = 0;
+                var head = qrCode.modules[0][col];
+                for (var row = 0; row < moduleCount; row++) {
+                    var current = qrCode.modules[row][col];
+                    //level 3 评价
+                    if (row < moduleCount - 6) {
+                        if (current && !qrCode.modules[row + 1][col] && qrCode.modules[row + 2][col] && qrCode.modules[row + 3][col] && qrCode.modules[row + 4][col] && !qrCode.modules[row + 5][col] && qrCode.modules[row + 6][col]) {
+                            if (row < moduleCount - 10) {
+                                if (qrCode.modules[row + 7][col] && qrCode.modules[row + 8][col] && qrCode.modules[row + 9][col] && qrCode.modules[row + 10][col]) {
+                                    lostPoint += 40;
+                                }
+                            } else if (row > 3) {
+                                if (qrCode.modules[row - 1][col] && qrCode.modules[row - 2][col] && qrCode.modules[row - 3][col] && qrCode.modules[row - 4][col]) {
+                                    lostPoint += 40;
+                                }
+                            }
+                        }
+                    }
+                    //level 1 评价
+                    if (head ^ current) {
+                        sameCount++;
+                    } else {
+                        head = current;
+                        if (sameCount >= 5) {
+                            lostPoint += (3 + sameCount - 5);
+                        }
+                        sameCount = 1;
+                    }
+                }
+            }
+            // LEVEL4
+            var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
+            lostPoint += ratio * 10;
+            return lostPoint;
+        }
+
+    };
+    //---------------------------------------------------------------------
+    // QRMath使用的数学工具
+    //---------------------------------------------------------------------
+    var QRMath = {
+        /*
+        将n转化为a^m
+         */
+        glog: function (n) {
+            if (n < 1) {
+                throw new Error("glog(" + n + ")");
+            }
+            return QRMath.LOG_TABLE[n];
+        },
+        /*
+        将a^m转化为n
+         */
+        gexp: function (n) {
+            while (n < 0) {
+                n += 255;
+            }
+            while (n >= 256) {
+                n -= 255;
+            }
+            return QRMath.EXP_TABLE[n];
+        },
+        EXP_TABLE: new Array(256),
+        LOG_TABLE: new Array(256)
+
+    };
+    for (var i = 0; i < 8; i++) {
+        QRMath.EXP_TABLE[i] = 1 << i;
+    }
+    for (var i = 8; i < 256; i++) {
+        QRMath.EXP_TABLE[i] = QRMath.EXP_TABLE[i - 4] ^ QRMath.EXP_TABLE[i - 5] ^ QRMath.EXP_TABLE[i - 6] ^ QRMath.EXP_TABLE[i - 8];
+    }
+    for (var i = 0; i < 255; i++) {
+        QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]] = i;
+    }
+    //---------------------------------------------------------------------
+    // QRPolynomial 多项式
+    //---------------------------------------------------------------------
+    /**
+     * 多项式类
+     * @param {Array} num   系数
+     * @param {num} shift a^shift
+     */
+    function QRPolynomial(num, shift) {
+        if (num.length == undefined) {
+            throw new Error(num.length + "/" + shift);
+        }
+        var offset = 0;
+        while (offset < num.length && num[offset] == 0) {
+            offset++;
+        }
+        this.num = new Array(num.length - offset + shift);
+        for (var i = 0; i < num.length - offset; i++) {
+            this.num[i] = num[i + offset];
+        }
+    }
+    QRPolynomial.prototype = {
+        get: function (index) {
+            return this.num[index];
+        },
+        getLength: function () {
+            return this.num.length;
+        },
+        /**
+         * 多项式乘法
+         * @param  {QRPolynomial} e 被乘多项式
+         * @return {[type]}   [description]
+         */
+        multiply: function (e) {
+            var num = new Array(this.getLength() + e.getLength() - 1);
+            for (var i = 0; i < this.getLength(); i++) {
+                for (var j = 0; j < e.getLength(); j++) {
+                    num[i + j] ^= QRMath.gexp(QRMath.glog(this.get(i)) + QRMath.glog(e.get(j)));
+                }
+            }
+            return new QRPolynomial(num, 0);
+        },
+        /**
+         * 多项式模运算
+         * @param  {QRPolynomial} e 模多项式
+         * @return {}
+         */
+        mod: function (e) {
+            var tl = this.getLength(),
+                el = e.getLength();
+            if (tl - el < 0) {
+                return this;
+            }
+            var num = new Array(tl);
+            for (var i = 0; i < tl; i++) {
+                num[i] = this.get(i);
+            }
+            while (num.length >= el) {
+                var ratio = QRMath.glog(num[0]) - QRMath.glog(e.get(0));
+
+                for (var i = 0; i < e.getLength(); i++) {
+                    num[i] ^= QRMath.gexp(QRMath.glog(e.get(i)) + ratio);
+                }
+                while (num[0] == 0) {
+                    num.shift();
+                }
+            }
+            return new QRPolynomial(num, 0);
+        }
+    };
+
+    //---------------------------------------------------------------------
+    // RS_BLOCK_TABLE
+    //---------------------------------------------------------------------
+    /*
+    二维码各个版本信息[块数, 每块中的数据块数, 每块中的信息块数]
+     */
+    var RS_BLOCK_TABLE = [
+        // L
+        // M
+        // Q
+        // H
+        // 1
+        [1, 26, 19],
+        [1, 26, 16],
+        [1, 26, 13],
+        [1, 26, 9],
+
+        // 2
+        [1, 44, 34],
+        [1, 44, 28],
+        [1, 44, 22],
+        [1, 44, 16],
+
+        // 3
+        [1, 70, 55],
+        [1, 70, 44],
+        [2, 35, 17],
+        [2, 35, 13],
+
+        // 4
+        [1, 100, 80],
+        [2, 50, 32],
+        [2, 50, 24],
+        [4, 25, 9],
+
+        // 5
+        [1, 134, 108],
+        [2, 67, 43],
+        [2, 33, 15, 2, 34, 16],
+        [2, 33, 11, 2, 34, 12],
+
+        // 6
+        [2, 86, 68],
+        [4, 43, 27],
+        [4, 43, 19],
+        [4, 43, 15],
+
+        // 7
+        [2, 98, 78],
+        [4, 49, 31],
+        [2, 32, 14, 4, 33, 15],
+        [4, 39, 13, 1, 40, 14],
+
+        // 8
+        [2, 121, 97],
+        [2, 60, 38, 2, 61, 39],
+        [4, 40, 18, 2, 41, 19],
+        [4, 40, 14, 2, 41, 15],
+
+        // 9
+        [2, 146, 116],
+        [3, 58, 36, 2, 59, 37],
+        [4, 36, 16, 4, 37, 17],
+        [4, 36, 12, 4, 37, 13],
+
+        // 10
+        [2, 86, 68, 2, 87, 69],
+        [4, 69, 43, 1, 70, 44],
+        [6, 43, 19, 2, 44, 20],
+        [6, 43, 15, 2, 44, 16],
+
+        // 11
+        [4, 101, 81],
+        [1, 80, 50, 4, 81, 51],
+        [4, 50, 22, 4, 51, 23],
+        [3, 36, 12, 8, 37, 13],
+
+        // 12
+        [2, 116, 92, 2, 117, 93],
+        [6, 58, 36, 2, 59, 37],
+        [4, 46, 20, 6, 47, 21],
+        [7, 42, 14, 4, 43, 15],
+
+        // 13
+        [4, 133, 107],
+        [8, 59, 37, 1, 60, 38],
+        [8, 44, 20, 4, 45, 21],
+        [12, 33, 11, 4, 34, 12],
+
+        // 14
+        [3, 145, 115, 1, 146, 116],
+        [4, 64, 40, 5, 65, 41],
+        [11, 36, 16, 5, 37, 17],
+        [11, 36, 12, 5, 37, 13],
+
+        // 15
+        [5, 109, 87, 1, 110, 88],
+        [5, 65, 41, 5, 66, 42],
+        [5, 54, 24, 7, 55, 25],
+        [11, 36, 12],
+
+        // 16
+        [5, 122, 98, 1, 123, 99],
+        [7, 73, 45, 3, 74, 46],
+        [15, 43, 19, 2, 44, 20],
+        [3, 45, 15, 13, 46, 16],
+
+        // 17
+        [1, 135, 107, 5, 136, 108],
+        [10, 74, 46, 1, 75, 47],
+        [1, 50, 22, 15, 51, 23],
+        [2, 42, 14, 17, 43, 15],
+
+        // 18
+        [5, 150, 120, 1, 151, 121],
+        [9, 69, 43, 4, 70, 44],
+        [17, 50, 22, 1, 51, 23],
+        [2, 42, 14, 19, 43, 15],
+
+        // 19
+        [3, 141, 113, 4, 142, 114],
+        [3, 70, 44, 11, 71, 45],
+        [17, 47, 21, 4, 48, 22],
+        [9, 39, 13, 16, 40, 14],
+
+        // 20
+        [3, 135, 107, 5, 136, 108],
+        [3, 67, 41, 13, 68, 42],
+        [15, 54, 24, 5, 55, 25],
+        [15, 43, 15, 10, 44, 16],
+
+        // 21
+        [4, 144, 116, 4, 145, 117],
+        [17, 68, 42],
+        [17, 50, 22, 6, 51, 23],
+        [19, 46, 16, 6, 47, 17],
+
+        // 22
+        [2, 139, 111, 7, 140, 112],
+        [17, 74, 46],
+        [7, 54, 24, 16, 55, 25],
+        [34, 37, 13],
+
+        // 23
+        [4, 151, 121, 5, 152, 122],
+        [4, 75, 47, 14, 76, 48],
+        [11, 54, 24, 14, 55, 25],
+        [16, 45, 15, 14, 46, 16],
+
+        // 24
+        [6, 147, 117, 4, 148, 118],
+        [6, 73, 45, 14, 74, 46],
+        [11, 54, 24, 16, 55, 25],
+        [30, 46, 16, 2, 47, 17],
+
+        // 25
+        [8, 132, 106, 4, 133, 107],
+        [8, 75, 47, 13, 76, 48],
+        [7, 54, 24, 22, 55, 25],
+        [22, 45, 15, 13, 46, 16],
+
+        // 26
+        [10, 142, 114, 2, 143, 115],
+        [19, 74, 46, 4, 75, 47],
+        [28, 50, 22, 6, 51, 23],
+        [33, 46, 16, 4, 47, 17],
+
+        // 27
+        [8, 152, 122, 4, 153, 123],
+        [22, 73, 45, 3, 74, 46],
+        [8, 53, 23, 26, 54, 24],
+        [12, 45, 15, 28, 46, 16],
+
+        // 28
+        [3, 147, 117, 10, 148, 118],
+        [3, 73, 45, 23, 74, 46],
+        [4, 54, 24, 31, 55, 25],
+        [11, 45, 15, 31, 46, 16],
+
+        // 29
+        [7, 146, 116, 7, 147, 117],
+        [21, 73, 45, 7, 74, 46],
+        [1, 53, 23, 37, 54, 24],
+        [19, 45, 15, 26, 46, 16],
+
+        // 30
+        [5, 145, 115, 10, 146, 116],
+        [19, 75, 47, 10, 76, 48],
+        [15, 54, 24, 25, 55, 25],
+        [23, 45, 15, 25, 46, 16],
+
+        // 31
+        [13, 145, 115, 3, 146, 116],
+        [2, 74, 46, 29, 75, 47],
+        [42, 54, 24, 1, 55, 25],
+        [23, 45, 15, 28, 46, 16],
+
+        // 32
+        [17, 145, 115],
+        [10, 74, 46, 23, 75, 47],
+        [10, 54, 24, 35, 55, 25],
+        [19, 45, 15, 35, 46, 16],
+
+        // 33
+        [17, 145, 115, 1, 146, 116],
+        [14, 74, 46, 21, 75, 47],
+        [29, 54, 24, 19, 55, 25],
+        [11, 45, 15, 46, 46, 16],
+
+        // 34
+        [13, 145, 115, 6, 146, 116],
+        [14, 74, 46, 23, 75, 47],
+        [44, 54, 24, 7, 55, 25],
+        [59, 46, 16, 1, 47, 17],
+
+        // 35
+        [12, 151, 121, 7, 152, 122],
+        [12, 75, 47, 26, 76, 48],
+        [39, 54, 24, 14, 55, 25],
+        [22, 45, 15, 41, 46, 16],
+
+        // 36
+        [6, 151, 121, 14, 152, 122],
+        [6, 75, 47, 34, 76, 48],
+        [46, 54, 24, 10, 55, 25],
+        [2, 45, 15, 64, 46, 16],
+
+        // 37
+        [17, 152, 122, 4, 153, 123],
+        [29, 74, 46, 14, 75, 47],
+        [49, 54, 24, 10, 55, 25],
+        [24, 45, 15, 46, 46, 16],
+
+        // 38
+        [4, 152, 122, 18, 153, 123],
+        [13, 74, 46, 32, 75, 47],
+        [48, 54, 24, 14, 55, 25],
+        [42, 45, 15, 32, 46, 16],
+
+        // 39
+        [20, 147, 117, 4, 148, 118],
+        [40, 75, 47, 7, 76, 48],
+        [43, 54, 24, 22, 55, 25],
+        [10, 45, 15, 67, 46, 16],
+
+        // 40
+        [19, 148, 118, 6, 149, 119],
+        [18, 75, 47, 31, 76, 48],
+        [34, 54, 24, 34, 55, 25],
+        [20, 45, 15, 61, 46, 16]
+    ];
+
+    /**
+     * 根据数据获取对应版本
+     * @return {[type]} [description]
+     */
+    QRCodeAlg.prototype.getRightType = function () {
+        for (var typeNumber = 1; typeNumber < 41; typeNumber++) {
+            var rsBlock = RS_BLOCK_TABLE[(typeNumber - 1) * 4 + this.errorCorrectLevel];
+            if (rsBlock == undefined) {
+                throw new Error("bad rs block @ typeNumber:" + typeNumber + "/errorCorrectLevel:" + this.errorCorrectLevel);
+            }
+            var length = rsBlock.length / 3;
+            var totalDataCount = 0;
+            for (var i = 0; i < length; i++) {
+                var count = rsBlock[i * 3 + 0];
+                var dataCount = rsBlock[i * 3 + 2];
+                totalDataCount += dataCount * count;
+            }
+            var lengthBytes = typeNumber > 9 ? 2 : 1;
+            if (this.utf8bytes.length + lengthBytes < totalDataCount || typeNumber == 40) {
+                this.typeNumber = typeNumber;
+                this.rsBlock = rsBlock;
+                this.totalDataCount = totalDataCount;
+                break;
+            }
+        }
+    };
+
+    //---------------------------------------------------------------------
+    // QRBitBuffer
+    //---------------------------------------------------------------------
+    function QRBitBuffer() {
+        this.buffer = new Array();
+        this.length = 0;
+    }
+    QRBitBuffer.prototype = {
+        get: function (index) {
+            var bufIndex = Math.floor(index / 8);
+            return ((this.buffer[bufIndex] >>> (7 - index % 8)) & 1);
+        },
+        put: function (num, length) {
+            for (var i = 0; i < length; i++) {
+                this.putBit(((num >>> (length - i - 1)) & 1));
+            }
+        },
+        putBit: function (bit) {
+            var bufIndex = Math.floor(this.length / 8);
+            if (this.buffer.length <= bufIndex) {
+                this.buffer.push(0);
+            }
+            if (bit) {
+                this.buffer[bufIndex] |= (0x80 >>> (this.length % 8));
+            }
+            this.length++;
+        }
+    };
+
+
+
+    // xzedit
+    let qrcodeAlgObjCache = [];
+    /**
+     * 二维码构造函数,主要用于绘制
+     * @param  {参数列表} opt 传递参数
+     * @return {}
+     */
+    QRCode = function (opt) {
+        //设置默认参数
+        this.options = {
+            text: '',
+            size: 256,
+            correctLevel: 3,
+            background: '#ffffff',
+            foreground: '#000000',
+            pdground: '#000000',
+            image: '',
+            imageSize: 30,
+            canvasId: opt.canvasId,
+            context: opt.context,
+            usingComponents: opt.usingComponents,
+            showLoading: opt.showLoading,
+            loadingText: opt.loadingText,
+        };
+        if (typeof opt === 'string') { // 只编码ASCII字符串
+            opt = {
+                text: opt
+            };
+        }
+        if (opt) {
+            for (var i in opt) {
+                this.options[i] = opt[i];
+            }
+        }
+        //使用QRCodeAlg创建二维码结构
+        var qrCodeAlg = null;
+        for (var i = 0, l = qrcodeAlgObjCache.length; i < l; i++) {
+            if (qrcodeAlgObjCache[i].text == this.options.text && qrcodeAlgObjCache[i].text.correctLevel == this.options.correctLevel) {
+                qrCodeAlg = qrcodeAlgObjCache[i].obj;
+                break;
+            }
+        }
+        if (i == l) {
+            qrCodeAlg = new QRCodeAlg(this.options.text, this.options.correctLevel);
+            qrcodeAlgObjCache.push({
+                text: this.options.text,
+                correctLevel: this.options.correctLevel,
+                obj: qrCodeAlg
+            });
+        }
+        /**
+         * 计算矩阵点的前景色
+         * @param {Obj} config
+         * @param {Number} config.row 点x坐标
+         * @param {Number} config.col 点y坐标
+         * @param {Number} config.count 矩阵大小
+         * @param {Number} config.options 组件的options
+         * @return {String}
+         */
+        let getForeGround = function (config) {
+            var options = config.options;
+            if (options.pdground && (
+                (config.row > 1 && config.row < 5 && config.col > 1 && config.col < 5) ||
+                (config.row > (config.count - 6) && config.row < (config.count - 2) && config.col > 1 && config.col < 5) ||
+                (config.row > 1 && config.row < 5 && config.col > (config.count - 6) && config.col < (config.count - 2))
+            )) {
+                return options.pdground;
+            }
+            return options.foreground;
+        }
+        // 创建canvas
+        let createCanvas = function (options) {
+            if(options.showLoading){
+                uni.showLoading({
+                    title: options.loadingText,
+                    mask: true
+                });
+            }
+            var ctx = uni.createCanvasContext(options.canvasId, options.context);
+            var count = qrCodeAlg.getModuleCount();
+            var ratioSize = options.size;
+            var ratioImgSize = options.imageSize;
+            //计算每个点的长宽
+            var tileW = (ratioSize / count).toPrecision(4);
+            var tileH = (ratioSize / count).toPrecision(4);
+            //绘制
+            for (var row = 0; row < count; row++) {
+                for (var col = 0; col < count; col++) {
+                    var w = (Math.ceil((col + 1) * tileW) - Math.floor(col * tileW));
+                    var h = (Math.ceil((row + 1) * tileW) - Math.floor(row * tileW));
+                    var foreground = getForeGround({
+                        row: row,
+                        col: col,
+                        count: count,
+                        options: options
+                    });
+                    ctx.setFillStyle(qrCodeAlg.modules[row][col] ? foreground : options.background);
+                    ctx.fillRect(Math.round(col * tileW), Math.round(row * tileH), w, h);
+                }
+            }
+            if (options.image) {
+                var x = Number(((ratioSize - ratioImgSize) / 2).toFixed(2));
+                var y = Number(((ratioSize - ratioImgSize) / 2).toFixed(2));
+                drawRoundedRect(ctx, x, y, ratioImgSize, ratioImgSize, 2, 6, true, true)
+                ctx.drawImage(options.image, x, y, ratioImgSize, ratioImgSize);
+                // 画圆角矩形
+                function drawRoundedRect(ctxi, x, y, width, height, r, lineWidth, fill, stroke) {
+                    ctxi.setLineWidth(lineWidth);
+                    ctxi.setFillStyle(options.background);
+                    ctxi.setStrokeStyle(options.background);
+                    ctxi.beginPath(); // draw top and top right corner 
+                    ctxi.moveTo(x + r, y);
+                    ctxi.arcTo(x + width, y, x + width, y + r, r); // draw right side and bottom right corner 
+                    ctxi.arcTo(x + width, y + height, x + width - r, y + height, r); // draw bottom and bottom left corner 
+                    ctxi.arcTo(x, y + height, x, y + height - r, r); // draw left and top left corner 
+                    ctxi.arcTo(x, y, x + r, y, r);
+                    ctxi.closePath();
+                    if (fill) {
+                        ctxi.fill();
+                    }
+                    if (stroke) {
+                        ctxi.stroke();
+                    }
+                }
+            }
+            setTimeout(() => {
+                ctx.draw(true, () => {
+                    // 保存到临时区域
+                    setTimeout(() => {
+                        uni.canvasToTempFilePath({
+                            width: options.width,
+                            height: options.height,
+                            destWidth: options.width,
+                            destHeight: options.height,
+                            canvasId: options.canvasId,
+                            quality: Number(1),
+                            success: function (res) {
+                                if (options.cbResult) {
+                                    // 由于官方还没有统一此接口的输出字段,所以先判定下  支付宝为 res.apFilePath
+                                    if (!empty(res.tempFilePath)) {
+                                        options.cbResult(res.tempFilePath)
+                                    } else if (!empty(res.apFilePath)) {
+                                        options.cbResult(res.apFilePath)
+                                    } else {
+                                        options.cbResult(res.tempFilePath)
+                                    }
+                                }
+                            },
+                            fail: function (res) {
+                                if (options.cbResult) {
+                                    options.cbResult(res)
+                                }
+                            },
+                            complete: function () {
+                                uni.hideLoading();
+                            },
+                        }, options.context);
+                    }, options.text.length + 100);
+                });
+            }, options.usingComponents ? 0 : 150);
+        }
+        createCanvas(this.options);
+        // 空判定
+        let empty = function (v) {
+            let tp = typeof v,
+                rt = false;
+            if (tp == "number" && String(v) == "") {
+                rt = true
+            } else if (tp == "undefined") {
+                rt = true
+            } else if (tp == "object") {
+                if (JSON.stringify(v) == "{}" || JSON.stringify(v) == "[]" || v == null) rt = true
+            } else if (tp == "string") {
+                if (v == "" || v == "undefined" || v == "null" || v == "{}" || v == "[]") rt = true
+            } else if (tp == "function") {
+                rt = false
+            }
+            return rt
+        }
+    };
+    QRCode.prototype.clear = function (fn) {
+        var ctx = uni.createCanvasContext(this.options.canvasId, this.options.context)
+        ctx.clearRect(0, 0, this.options.size, this.options.size)
+        ctx.draw(false, () => {
+            if (fn) {
+                fn()
+            }
+        })
+    };
+})()
+
+export default QRCode

+ 218 - 0
components/tki-qrcode/tki-qrcode.vue

@@ -0,0 +1,218 @@
+<template xlang="wxml" minapp="mpvue">
+	<view class="tki-qrcode">
+		<canvas class="tki-qrcode-canvas" :canvas-id="cid" :style="{width:cpSize+'px',height:cpSize+'px'}"  />
+		<image class="img" v-show="show" :src="result" :style="{width:cpSize+'px',height:cpSize+'px'}" />
+	</view>
+</template>
+<script>
+import QRCode from "./qrcode.js"
+let qrcode
+export default {
+	name: "tkiQrcodes",
+	props: {
+		
+		cid: {
+			type: String,
+			default: 'tki-qrcode-canvas'
+		},
+		size: {
+			type: Number,
+			default: 200
+		},
+		unit: {
+			type: String,
+			default: 'rpx'
+		},
+		show: {
+			type: Boolean,
+			default: true
+		},
+		val: {
+			type: String,
+			default: ''
+		},
+		background: {
+			type: String,
+			default: '#ffffff'
+		},
+		foreground: {
+			type: String,
+			default: '#000000'
+		},
+		pdground: {
+			type: String,
+			default: '#000000'
+		},
+		icon: {
+			type: String,
+			default: ''
+		},
+		iconSize: {
+			type: Number,
+			default: 40
+		},
+		lv: {
+			type: Number,
+			default: 3
+		},
+		onval: {
+			type: Boolean,
+			default: false
+		},
+		loadMake: {
+			type: Boolean,
+			default: false
+		},
+		usingComponents: {
+			type: Boolean,
+			default: true
+		},
+		showLoading: {
+			type: Boolean,
+			default: true
+		},
+		loadingText: {
+			type: String,
+			default: '二维码生成中'
+		},
+	},
+	data() {
+		return {
+			result: '',
+		}
+	},
+	methods: {
+		_makeCode() {
+			this.cpSize
+			// console.log(this.val,55)
+			let that = this
+			if (!this._empty(this.val)) {
+				qrcode = new QRCode({
+					context: that, // 上下文环境
+					canvasId:that.cid, // canvas-id
+					usingComponents: that.usingComponents, // 是否是自定义组件
+					showLoading: that.showLoading, // 是否显示loading
+					loadingText: that.loadingText, // loading文字
+					text: that.val, // 生成内容
+					size: that.cpSize, // 二维码大小
+					background: that.background, // 背景色
+					foreground: that.foreground, // 前景色
+					pdground: that.pdground, // 定位角点颜色
+					correctLevel: that.lv, // 容错级别
+					image: that.icon, // 二维码图标
+					imageSize: that.iconSize,// 二维码图标大小
+					cbResult: function (res) { // 生成二维码的回调
+						that._result(res)
+					},
+				});
+			} else {
+				uni.showToast({
+					title: '二维码内容不能为空',
+					icon: 'none',
+					duration: 2000
+				});
+			}
+		},
+		_clearCode() {
+			this._result('')
+			qrcode.clear()
+		},
+		_saveCode() {
+			let that = this;
+			if (this.result != "") {
+				uni.saveImageToPhotosAlbum({
+					filePath: that.result,
+					success: function () {
+						uni.showToast({
+							title: '二维码保存成功',
+							icon: 'none',
+							duration: 2000,
+							
+							
+						});
+					}
+				});
+			}
+		},
+		_result(res) {
+			this.result = res;
+			this.$emit('result', res)
+		},
+		_empty(v) {
+			let tp = typeof v,
+				rt = false;
+			if (tp == "number" && String(v) == "") {
+				rt = true
+			} else if (tp == "undefined") {
+				rt = true
+			} else if (tp == "object") {
+				if (JSON.stringify(v) == "{}" || JSON.stringify(v) == "[]" || v == null) rt = true
+			} else if (tp == "string") {
+				if (v == "" || v == "undefined" || v == "null" || v == "{}" || v == "[]") rt = true
+			} else if (tp == "function") {
+				rt = false
+			}
+			return rt
+		}
+	},
+	watch: {
+		size: function (n, o) {
+			// console.log(11)
+			if (n != o && !this._empty(n)) {
+				this.cSize = n
+				if (!this._empty(this.val)) {
+					setTimeout(() => {
+						this._makeCode()
+					}, 100);
+				}
+			}
+		},
+		val: function (n, o) {
+			if (this.onval) {
+				if (n != o && !this._empty(n)) {
+					setTimeout(() => {
+						this._makeCode()
+					}, 0);
+				}
+			}
+			
+		}
+	},
+	computed: {
+		cpSize() {
+			if(this.unit == "upx"){
+				return uni.upx2px(this.size)
+			}else{
+				return this.size
+			}
+		}
+	},
+	mounted: function () {
+		if (this.loadMake) {
+			if (!this._empty(this.val)) {
+				setTimeout(() => {
+					this._makeCode()
+				}, 0);
+			}
+		}
+	},
+}
+</script>
+<style>
+.tki-qrcode {
+	height: 100%;
+}
+.tki-qrcode-canvas {
+  position: relative;
+ top: 0rpx;
+  left: -99999rpx;
+  /* z-index: -99999; */
+}
+/* canvas{
+	display: none;
+	} */
+	.img{
+		margin-top: -240rpx !important;
+		height: 100%;
+	}
+</style>

+ 122 - 0
components/uni-badge/uni-badge.vue

@@ -0,0 +1,122 @@
+<template>
+	<text v-if="text" :class="inverted ? 'uni-badge--' + type + ' uni-badge--' + size + ' uni-badge--' + type + '-inverted' : 'uni-badge--' + type + ' uni-badge--' + size"
+	 class="uni-badge" :style="width" @click="onClick()">{{ text }}</text>
+</template>
+
+<script>
+	export default {
+		name: 'UniBadge',
+		props: {
+			type: {
+				type: String,
+				default: 'default'
+			},
+			inverted: {
+				type: Boolean,
+				default: false
+			},
+			text: {
+				type: [String,Number],
+				default: ''
+			},
+			size: {
+				// small.normal
+				type: String,
+				default: 'normal'
+			}
+		},
+		data() {
+			return {
+				width: `display: inline-block;width: ${String(this.text).length * 15 + 25}rpx`
+			};
+		},
+		methods: {
+			onClick() {
+				this.$emit('click');
+			}
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	$bage-size: 12px;
+	$bage-small: scale(0.8);
+	$bage-height: 40rpx;
+
+	.uni-badge {
+		/* #ifndef APP-PLUS */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		height: $bage-height;
+		line-height: $bage-height;
+		color: $uni-text-color;
+		border-radius: 100px;
+		background-color: $uni-bg-color-hover;
+		background-color: transparent;
+		text-align: center;
+		font-family: 'Helvetica Neue', Helvetica, sans-serif;
+		font-size: $bage-size;
+		padding: 0;
+	}
+
+	.uni-badge--inverted {
+		padding: 0 5px 0 0;
+		color: $uni-bg-color-hover;
+	}
+
+	.uni-badge--default {
+		color: $uni-text-color;
+		background-color: $uni-bg-color-hover;
+	}
+
+	.uni-badge--default-inverted {
+		color: $uni-text-color-grey;
+		background-color: transparent;
+	}
+
+	.uni-badge--primary {
+		color: $uni-text-color-inverse;
+		background-color: $uni-color-primary;
+	}
+
+	.uni-badge--primary-inverted {
+		color: $uni-color-primary;
+		background-color: transparent;
+	}
+
+	.uni-badge--success {
+		color: $uni-text-color-inverse;
+		background-color: $uni-color-success;
+	}
+
+	.uni-badge--success-inverted {
+		color: $uni-color-success;
+		background-color: transparent;
+	}
+
+	.uni-badge--warning {
+		color: $uni-text-color-inverse;
+		background-color: $uni-color-warning;
+	}
+
+	.uni-badge--warning-inverted {
+		color: $uni-color-warning;
+		background-color: transparent;
+	}
+
+	.uni-badge--error {
+		color: $uni-text-color-inverse;
+		background-color: $uni-color-error;
+	}
+
+	.uni-badge--error-inverted {
+		color: $uni-color-error;
+		background-color: transparent;
+	}
+
+	.uni-badge--small {
+		transform: $bage-small;
+		transform-origin: center center;
+	}
+</style>

+ 188 - 0
components/uni-countdown/uni-countdown.vue

@@ -0,0 +1,188 @@
+<template>
+	<view class="uni-countdown">
+		<text v-if="showDay" :style="{ borderColor: borderColor, color: color, backgroundColor: backgroundColor }" class="uni-countdown__number">{{ d }}</text>
+		<text v-if="showDay" :style="{ color: splitorColor }" class="uni-countdown__splitor">天</text>
+		<text :style="{ borderColor: borderColor, color: color, backgroundColor: backgroundColor }" class="uni-countdown__number">{{ h }}</text>
+		<text :style="{ color: splitorColor }" class="uni-countdown__splitor">{{ showColon ? ':' : '时' }}</text>
+		<text :style="{ borderColor: borderColor, color: color, backgroundColor: backgroundColor }" class="uni-countdown__number">{{ i }}</text>
+		<text :style="{ color: splitorColor }" class="uni-countdown__splitor">{{ showColon ? ':' : '分' }}</text>
+		<text :style="{ borderColor: borderColor, color: color, backgroundColor: backgroundColor }" class="uni-countdown__number">{{ s }}</text>
+		<text v-if="!showColon" :style="{ color: splitorColor }" class="uni-countdown__splitor">秒</text>
+	</view>
+</template>
+<script>
+	export default {
+		name: 'UniCountdown',
+		props: {
+			showDay: {
+				type: Boolean,
+				default: true
+			},
+			showColon: {
+				type: Boolean,
+				default: true
+			},
+			backgroundColor: {
+				type: String,
+				default: '#FFFFFF'
+			},
+			borderColor: {
+				type: String,
+				default: '#000000'
+			},
+			color: {
+				type: String,
+				default: '#000000'
+			},
+			splitorColor: {
+				type: String,
+				default: '#000000'
+			},
+			day: {
+				type: Number,
+				default: 0
+			},
+			hour: {
+				type: Number,
+				default: 0
+			},
+			minute: {
+				type: Number,
+				default: 0
+			},
+			second: {
+				type: Number,
+				default: 0
+			}
+		},
+		data() {
+			return {
+				timer: null,
+				syncFlag: false,
+				d: '00',
+				h: '00',
+				i: '00',
+				s: '00',
+				leftTime: 0,
+				seconds: 0
+			}
+		},
+		watch: {
+			day(val) {
+				this.changeFlag()
+			},
+			hour(val) {
+				this.changeFlag()
+			},
+			minute(val) {
+				this.changeFlag()
+			},
+			second(val) {
+				this.changeFlag()
+			}
+		},
+		created: function(e) {
+			this.startData();
+		},
+		beforeDestroy() {
+			clearInterval(this.timer)
+		},
+		methods: {
+			toSeconds(day, hours, minutes, seconds) {
+				return day * 60 * 60 * 24 + hours * 60 * 60 + minutes * 60 + seconds
+			},
+			timeUp() {
+				clearInterval(this.timer)
+				this.$emit('timeup')
+			},
+			countDown() {
+				let seconds = this.seconds
+				let [day, hour, minute, second] = [0, 0, 0, 0]
+				if (seconds > 0) {
+					day = Math.floor(seconds / (60 * 60 * 24))
+					hour = Math.floor(seconds / (60 * 60)) - (day * 24)
+					minute = Math.floor(seconds / 60) - (day * 24 * 60) - (hour * 60)
+					second = Math.floor(seconds) - (day * 24 * 60 * 60) - (hour * 60 * 60) - (minute * 60)
+				} else {
+					this.timeUp()
+				}
+				if (day < 10) {
+					day = '0' + day
+				}
+				if (hour < 10) {
+					hour = '0' + hour
+				}
+				if (minute < 10) {
+					minute = '0' + minute
+				}
+				if (second < 10) {
+					second = '0' + second
+				}
+				this.d = day
+				this.h = hour
+				this.i = minute
+				this.s = second
+			},
+			startData() {
+				this.seconds = this.toSeconds(this.day, this.hour, this.minute, this.second)
+				if (this.seconds <= 0) {
+					return
+				}
+				this.countDown()
+				this.timer = setInterval(() => {
+					this.seconds--
+					if (this.seconds < 0) {
+						this.timeUp()
+						return
+					}
+					this.countDown()
+				}, 1000)
+			},
+			changeFlag() {
+				if (!this.syncFlag) {
+					this.seconds = this.toSeconds(this.day, this.hour, this.minute, this.second)
+					this.startData();
+					this.syncFlag = true;
+				}
+			}
+		}
+	}
+</script>
+<style lang="scss" scoped>
+	@import '~@/uni.scss';
+	$countdown-height: 48rpx;
+	$countdown-width: 52rpx;
+
+	.uni-countdown {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		justify-content: flex-start;
+		padding: 2rpx 0;
+	}
+
+	.uni-countdown__splitor {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		justify-content: center;
+		line-height: $countdown-height;
+		padding: 5rpx;
+		font-size: $uni-font-size-sm;
+	}
+
+	.uni-countdown__number {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		justify-content: center;
+		align-items: center;
+		width: $countdown-width;
+		height: $countdown-height;
+		line-height: $countdown-height;
+		margin: 5rpx;
+		text-align: center;
+		font-size: $uni-font-size-sm;
+	}
+</style>

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

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

Разница между файлами не показана из-за своего большого размера
+ 10 - 0
components/uni-icons/uni-icons.vue


+ 230 - 0
components/uni-list-item/uni-list-item.vue

@@ -0,0 +1,230 @@
+<template>
+	<!-- #ifdef APP-NVUE -->
+	<cell>
+	<!-- #endif -->
+	<view :class="disabled ? 'uni-list-item--disabled' : ''" :hover-class="disabled || showSwitch ? '' : 'uni-list-item--hover'"
+	 class="uni-list-item" @click="onClick">
+		<view class="uni-list-item__container" :class="{'uni-list-item--first':isFirstChild}">
+			<view v-if="thumb" class="uni-list-item__icon">
+				<image :src="thumb" mode="aspectFit" class="uni-list-item__icon-img" />
+			</view>
+			<view v-else-if="showExtraIcon" class="uni-list-item__icon">
+				<uni-icons :color="extraIcon.color" :size="extraIcon.size" :type="extraIcon.type" class="uni-icon-wrapper" />
+			</view>
+			<view class="uni-list-item__content">
+				<slot></slot>
+				<text class="uni-list-item__content-title">{{ title }}</text>
+				<text v-if="note" class="uni-list-item__content-note">{{ note }}</text>
+			</view>
+			<view class="uni-list-item__slot">
+				<slot name="right" ></slot>
+			</view>
+			<view v-if="showBadge || showArrow || showSwitch" class="uni-list-item__extra">
+				<uni-badge v-if="showBadge" :type="badgeType" :text="badgeText" />
+				<switch v-if="showSwitch" :color="switchColor" :disabled="disabled" :checked="switchChecked" @change="onSwitchChange" />
+				<uni-icons v-if="showArrow" :size="20" class="uni-icon-wrapper" color="#bbb" type="arrowright" />
+			</view>
+		</view>
+	</view>
+	<!-- #ifdef APP-NVUE -->
+	</cell>
+	<!-- #endif -->
+</template>
+
+<script>
+	import uniIcons from '../uni-icons/uni-icons.vue'
+	import uniBadge from '../uni-badge/uni-badge.vue'
+	export default {
+		name: 'UniListItem',
+		components: {
+			uniIcons,
+			uniBadge
+		},
+		props: {
+			title: {
+				type: String,
+				default: ''
+			}, // 列表标题
+			note: {
+				type: String,
+				default: ''
+			}, // 列表描述
+			disabled: {
+				// 是否禁用
+				type: [Boolean, String],
+				default: false
+			},
+			showArrow: {
+				// 是否显示箭头
+				type: [Boolean, String],
+				default: true
+			},
+			showBadge: {
+				// 是否显示数字角标
+				type: [Boolean, String],
+				default: false
+			},
+			showSwitch: {
+				// 是否显示Switch
+				type: [Boolean, String],
+				default: false
+			},
+			switchChecked: {
+				// Switch是否被选中
+				type: [Boolean, String],
+				default: false
+			},
+			switchColor:{
+				type:String,
+				default:''
+			},
+			badgeText: {
+				// badge内容
+				type: String,
+				default: ''
+			},
+			badgeType: {
+				// badge类型
+				type: String,
+				default: 'success'
+			},
+			thumb: {
+				// 缩略图
+				type: String,
+				default: ''
+			},
+			showExtraIcon: {
+				// 是否显示扩展图标
+				type: [Boolean, String],
+				default: false
+			},
+			extraIcon: {
+				type: Object,
+				default () {
+					return {
+						type: 'contact',
+						color: '#000000',
+						size: 20
+					}
+				}
+			}
+		},
+		inject: ['list'],
+		data() {
+			return {
+				isFirstChild: false
+			}
+		},
+		mounted() {
+			if (!this.list.firstChildAppend) {
+				this.list.firstChildAppend = true
+				this.isFirstChild = true
+			}
+		},
+		methods: {
+			onClick() {
+				this.$emit('click')
+			},
+			onSwitchChange(e) {
+				this.$emit('switchChange', e.detail)
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	@import '~@/uni.scss';
+
+	$list-item-pd: $uni-spacing-col-lg $uni-spacing-row-lg;
+
+	.uni-list-item {
+		font-size: $uni-font-size-lg;
+		position: relative;
+		flex-direction: column;
+		justify-content: space-between;
+		padding-left: $uni-spacing-row-lg;
+	}
+
+	.uni-list-item--disabled {
+		opacity: 0.3;
+	}
+
+	.uni-list-item--hover {
+		background-color: $uni-bg-color-hover;
+	}
+
+	.uni-list-item__container {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		padding: $list-item-pd;
+		padding-left: 0;
+		flex: 1;
+		position: relative;
+		justify-content: space-between;
+		align-items: center;
+		border-top-color: $uni-border-color;
+		border-top-style: solid;
+		border-top-width: 1px;
+	}
+
+	.uni-list-item--first {
+		border-top-width: 0px;
+	}
+
+	.uni-list-item__content {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex: 1;
+		overflow: hidden;
+		flex-direction: column;
+		color: #3b4144;
+
+	}
+
+	.uni-list-item__content-title {
+		font-size: $uni-font-size-base;
+		color: #3b4144;
+		overflow: hidden;
+	}
+
+	.uni-list-item__content-note {
+		margin-top: 6rpx;
+		color: $uni-text-color-grey;
+		font-size: $uni-font-size-sm;
+		overflow: hidden;
+	}
+
+	.uni-list-item__extra {
+		// width: 25%;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		justify-content: flex-end;
+		align-items: center;
+	}
+
+	.uni-list-item__icon {
+		margin-right: 18rpx;
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+		display: flex;
+	}
+
+	.uni-list-item__icon-img {
+		height: $uni-img-size-base;
+		width: $uni-img-size-base;
+	}
+	// 修改switch默认大小
+	switch{
+		transform: translateX(16rpx) scale(.84);
+	}
+	.uni-list-item__slot{
+		color: #909399;
+		font-size: 28rpx;
+	}
+</style>

+ 68 - 0
components/uni-list/uni-list.vue

@@ -0,0 +1,68 @@
+<template>
+	<!-- #ifndef APP-NVUE -->
+	<view class="uni-list">
+		<slot />
+	</view>
+	<!-- #endif -->
+	<!-- #ifdef APP-NVUE -->
+	<list class="uni-list" :enableBackToTop="enableBackToTop" loadmoreoffset="15" :scroll-y="scrollY" @loadmore="loadMore">
+		<slot />
+	</list>
+	<!-- #endif -->
+</template>
+
+<script>
+	export default {
+		name: 'UniList',
+		'mp-weixin': {
+			options: {
+				multipleSlots: false
+			}
+		},
+		props: {
+			enableBackToTop: {
+				type: [Boolean, String],
+				default: false
+			},
+			scrollY: {
+				type: [Boolean, String],
+				default: false
+			}
+		},
+		provide() {
+			return {
+				list: this
+			}
+		},
+		created() {
+			this.firstChildAppend = false
+		},
+		methods: {
+			loadMore(e) {
+				this.$emit("scrolltolower");
+			}
+		}
+	}
+</script>
+<style lang="scss" scoped>
+	.uni-list {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		background-color: $uni-bg-color;
+		position: relative;
+		flex-direction: column;
+		// border-bottom-color: $uni-border-color;
+		// border-bottom-style: solid;
+		// border-bottom-width: 1px;
+	}
+	/* #ifndef APP-NVUE */
+	.uni-list:before {
+		height: 0;
+	}
+	.uni-list:after {
+		height: 0;
+	}
+	/* #endif */
+
+</style>

+ 65 - 0
components/uni-list/uni-refresh.vue

@@ -0,0 +1,65 @@
+<template>
+    <!-- #ifdef APP-NVUE -->
+    <refresh :display="display" @refresh="onrefresh" @pullingdown="onpullingdown">
+        <slot />
+    </refresh>
+    <!-- #endif -->
+    <!-- #ifndef APP-NVUE -->
+    <view ref="uni-refresh" class="uni-refresh" v-show="isShow">
+        <slot />
+    </view>
+    <!-- #endif -->
+</template>
+
+<script>
+    export default {
+        name: 'UniRefresh',
+        props: {
+            display: {
+                type: [String],
+                default: "hide"
+            }
+        },
+        data() {
+            return {
+                pulling: false
+            }
+        },
+        computed: {
+            isShow() {
+                if (this.display === "show" || this.pulling === true) {
+                    return true;
+                }
+                return false;
+            }
+        },
+        created() {},
+        methods: {
+            onchange(value) {
+                this.pulling = value;
+            },
+            onrefresh(e) {
+                this.$emit("refresh", e);
+            },
+            onpullingdown(e) {
+                // #ifdef APP-NVUE
+                this.$emit("pullingdown", e);
+                // #endif
+                // #ifndef APP-NVUE
+                var detail = {
+                    viewHeight: 90,
+                    pullingDistance: e.height
+                }
+                this.$emit("pullingdown", detail);
+                // #endif
+            }
+        }
+    }
+</script>
+
+<style>
+    .uni-refresh {
+        height: 0;
+        overflow: hidden;
+    }
+</style>

+ 87 - 0
components/uni-list/uni-refresh.wxs

@@ -0,0 +1,87 @@
+var pullDown = {
+    threshold: 95,
+    maxHeight: 200,
+    callRefresh: 'onrefresh',
+    callPullingDown: 'onpullingdown',
+    refreshSelector: '.uni-refresh'
+};
+
+function ready(newValue, oldValue, ownerInstance, instance) {
+    var state = instance.getState()
+    state.canPullDown = newValue;
+    console.log(newValue);
+}
+
+function touchStart(e, instance) {
+    var state = instance.getState();
+    state.refreshInstance = instance.selectComponent(pullDown.refreshSelector);
+    state.canPullDown = (state.refreshInstance != null && state.refreshInstance != undefined);
+    if (!state.canPullDown) {
+        return
+    }
+
+    console.log("touchStart");
+
+    state.height = 0;
+    state.touchStartY = e.touches[0].pageY || e.changedTouches[0].pageY;
+    state.refreshInstance.setStyle({
+        'height': 0
+    });
+    state.refreshInstance.callMethod("onchange", true);
+}
+
+function touchMove(e, ownerInstance) {
+    var instance = e.instance;
+    var state = instance.getState();
+    if (!state.canPullDown) {
+        return
+    }
+
+    var oldHeight = state.height;
+    var endY = e.touches[0].pageY || e.changedTouches[0].pageY;
+    var height = endY - state.touchStartY;
+    if (height > pullDown.maxHeight) {
+        return;
+    }
+
+    var refreshInstance = state.refreshInstance;
+    refreshInstance.setStyle({
+        'height': height + 'px'
+    });
+
+    height = height < pullDown.maxHeight ? height : pullDown.maxHeight;
+    state.height = height;
+    refreshInstance.callMethod(pullDown.callPullingDown, {
+        height: height
+    });
+}
+
+function touchEnd(e, ownerInstance) {
+    var state = e.instance.getState();
+    if (!state.canPullDown) {
+        return
+    }
+
+    state.refreshInstance.callMethod("onchange", false);
+
+    var refreshInstance = state.refreshInstance;
+    if (state.height > pullDown.threshold) {
+        refreshInstance.callMethod(pullDown.callRefresh);
+        return;
+    }
+
+    refreshInstance.setStyle({
+        'height': 0
+    });
+}
+
+function propObserver(newValue, oldValue, instance) {
+    pullDown = newValue;
+}
+
+module.exports = {
+    touchmove: touchMove,
+    touchstart: touchStart,
+    touchend: touchEnd,
+    propObserver: propObserver
+}

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

@@ -0,0 +1,194 @@
+<template>
+	<view class="uni-load-more">
+		<view class="uni-load-more__img" v-show="status === 'loading' && showIcon">
+			<view class="load1">
+				<view :style="{background:color}"></view>
+				<view :style="{background:color}"></view>
+				<view :style="{background:color}"></view>
+				<view :style="{background:color}"></view>
+			</view>
+			<view class="load2">
+				<view :style="{background:color}"></view>
+				<view :style="{background:color}"></view>
+				<view :style="{background:color}"></view>
+				<view :style="{background:color}"></view>
+			</view>
+			<view class="load3">
+				<view :style="{background:color}"></view>
+				<view :style="{background:color}"></view>
+				<view :style="{background:color}"></view>
+				<view :style="{background:color}"></view>
+			</view>
+		</view>
+		<text class="uni-load-more__text" :style="{color:color}">{{status === 'more' ? contentText.contentdown : (status === 'loading' ? contentText.contentrefresh : contentText.contentnomore)}}</text>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: "uni-load-more",
+		props: {
+			status: {
+				//上拉的状态:more-loading前;loading-loading中;noMore-没有更多了
+				type: String,
+				default: 'more'
+			},
+			showIcon: {
+				type: Boolean,
+				default: true
+			},
+			color: {
+				type: String,
+				default: "#777777"
+			},
+			contentText: {
+				type: Object,
+				default () {
+					return {
+						contentdown: "上拉显示更多",
+						contentrefresh: "正在加载...",
+						contentnomore: "没有更多数据了"
+					};
+				}
+			}
+		},
+		data() {
+			return {}
+		}
+	}
+</script>
+
+<style>
+	@charset "UTF-8";
+
+	.uni-load-more {
+		display: flex;
+		flex-direction: row;
+		height: 80upx;
+		align-items: center;
+		justify-content: center
+	}
+
+	.uni-load-more__text {
+		font-size: 28upx;
+		color: #999
+	}
+
+	.uni-load-more__img {
+		height: 24px;
+		width: 24px;
+		margin-right: 10px
+	}
+
+	.uni-load-more__img>view {
+		position: absolute
+	}
+
+	.uni-load-more__img>view view {
+		width: 6px;
+		height: 2px;
+		border-top-left-radius: 1px;
+		border-bottom-left-radius: 1px;
+		background: #999;
+		position: absolute;
+		opacity: .2;
+		transform-origin: 50%;
+		animation: load 1.56s ease infinite
+	}
+
+	.uni-load-more__img>view view:nth-child(1) {
+		transform: rotate(90deg);
+		top: 2px;
+		left: 9px
+	}
+
+	.uni-load-more__img>view view:nth-child(2) {
+		transform: rotate(180deg);
+		top: 11px;
+		right: 0
+	}
+
+	.uni-load-more__img>view view:nth-child(3) {
+		transform: rotate(270deg);
+		bottom: 2px;
+		left: 9px
+	}
+
+	.uni-load-more__img>view view:nth-child(4) {
+		top: 11px;
+		left: 0
+	}
+
+	.load1,
+	.load2,
+	.load3 {
+		height: 24px;
+		width: 24px
+	}
+
+	.load2 {
+		transform: rotate(30deg)
+	}
+
+	.load3 {
+		transform: rotate(60deg)
+	}
+
+	.load1 view:nth-child(1) {
+		animation-delay: 0s
+	}
+
+	.load2 view:nth-child(1) {
+		animation-delay: .13s
+	}
+
+	.load3 view:nth-child(1) {
+		animation-delay: .26s
+	}
+
+	.load1 view:nth-child(2) {
+		animation-delay: .39s
+	}
+
+	.load2 view:nth-child(2) {
+		animation-delay: .52s
+	}
+
+	.load3 view:nth-child(2) {
+		animation-delay: .65s
+	}
+
+	.load1 view:nth-child(3) {
+		animation-delay: .78s
+	}
+
+	.load2 view:nth-child(3) {
+		animation-delay: .91s
+	}
+
+	.load3 view:nth-child(3) {
+		animation-delay: 1.04s
+	}
+
+	.load1 view:nth-child(4) {
+		animation-delay: 1.17s
+	}
+
+	.load2 view:nth-child(4) {
+		animation-delay: 1.3s
+	}
+
+	.load3 view:nth-child(4) {
+		animation-delay: 1.43s
+	}
+
+	@-webkit-keyframes load {
+		0% {
+			opacity: 1
+		}
+
+		100% {
+			opacity: .2
+		}
+	}
+</style>

+ 361 - 0
components/uni-notice-bar/uni-notice-bar.vue

@@ -0,0 +1,361 @@
+<template>
+	<view v-if="show" class="uni-noticebar" :style="{ backgroundColor: backgroundColor }" @click="onClick">
+		<!-- #ifdef MP-ALIPAY -->
+		<view v-if="showClose === true || showClose === 'true'" class="uni-noticebar-close" @click="close">
+			<uni-icons type="closefill" :color="color" size="12" />
+		</view>
+		<view v-if="showIcon === true || showIcon === 'true'" class="uni-noticebar-icon">
+			<uni-icons type="sound" :color="color" size="14" />
+		</view>
+		<!-- #endif -->
+		<!-- #ifndef MP-ALIPAY -->
+		<uni-icons v-if="showClose === true || showClose === 'true'" class="uni-noticebar-close" type="closefill" :color="color"
+		 size="12" @click="close" />
+		<uni-icons v-if="showIcon === true || showIcon === 'true'" class="uni-noticebar-icon" type="sound" :color="color"
+		 size="14" />
+		<!-- #endif -->
+		<view ref="textBox" class="uni-noticebar__content-wrapper" :class="{'uni-noticebar__content-wrapper--scrollable':scrollable, 'uni-noticebar__content-wrapper--single':!scrollable && (single || moreText)}">
+			<view :id="elIdBox" class="uni-noticebar__content" :class="{'uni-noticebar__content--scrollable':scrollable, 'uni-noticebar__content--single':!scrollable && (single || moreText)}">
+				<text :id="elId" ref="animationEle" class="uni-noticebar__content-text" :class="{'uni-noticebar__content-text--scrollable':scrollable,'uni-noticebar__content-text--single':!scrollable && (single || moreText)}"
+				 :style="{color:color, width:wrapWidth+'px', 'animationDuration': animationDuration, '-webkit-animationDuration': animationDuration ,animationPlayState: webviewHide?'paused':animationPlayState,'-webkit-animationPlayState':webviewHide?'paused':animationPlayState, animationDelay: animationDelay, '-webkit-animationDelay':animationDelay}">{{text}}</text>
+			</view>
+		</view>
+		<view v-if="showGetMore === true || showGetMore === 'true'" class="uni-noticebar__more" @click="clickMore">
+			<text v-if="moreText" :style="{ color: moreColor }" class="uni-noticebar__more-text">{{ moreText }}</text>
+			<uni-icons type="arrowright" :color="moreColor" size="14" />
+		</view>
+	</view>
+</template>
+
+<script>
+	import uniIcons from '../uni-icons/uni-icons.vue'
+	// #ifdef APP-NVUE
+	const dom = weex.requireModule('dom');
+	const animation = weex.requireModule('animation');
+	// #endif
+	export default {
+		name: 'UniNoticeBar',
+		components: {
+			uniIcons
+		},
+		props: {
+			text: {
+				type: String,
+				default: ''
+			},
+			moreText: {
+				type: String,
+				default: ''
+			},
+			backgroundColor: {
+				type: String,
+				default: '#fffbe8'
+			},
+			speed: {
+				// 默认1s滚动100px
+				type: [String, Number],
+				default: 100
+			},
+			color: {
+				type: String,
+				default: '#de8c17'
+			},
+			moreColor: {
+				type: String,
+				default: '#999999'
+			},
+			single: {
+				// 是否单行
+				type: [String, Boolean],
+				default: false
+			},
+			scrollable: {
+				// 是否滚动,添加后控制单行效果取消
+				type: [String, Boolean],
+				default: false
+			},
+			showIcon: {
+				// 是否显示左侧icon
+				type: [String, Boolean],
+				default: false
+			},
+			showGetMore: {
+				// 是否显示右侧查看更多
+				type: [String, Boolean],
+				default: false
+			},
+			showClose: {
+				// 是否显示左侧关闭按钮
+				type: [String, Boolean],
+				default: false
+			}
+		},
+		data() {
+			const elId = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
+			const elIdBox = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
+			return {
+				textWidth: 0,
+				boxWidth: 0,
+				wrapWidth: '',
+				webviewHide: false,
+				// #ifdef APP-NVUE
+				stopAnimation: false,
+				// #endif
+				elId: elId,
+				elIdBox: elIdBox,
+				show: true,
+				animationDuration: 'none',
+				animationPlayState: 'paused',
+				animationDelay: '0s'
+			}
+		},
+		mounted() {
+			// #ifdef APP-PLUS
+			var pages = getCurrentPages();
+			var page = pages[pages.length - 1];
+			var currentWebview = page.$getAppWebview();
+			currentWebview.addEventListener('hide',()=>{
+				this.webviewHide = true
+			})
+			currentWebview.addEventListener('show',()=>{
+				this.webviewHide = false
+			})
+			// #endif
+			this.$nextTick(() => {
+				this.initSize()
+			})
+		},
+		// #ifdef APP-NVUE
+		beforeDestroy() {
+			this.stopAnimation = true
+		},
+		// #endif
+		methods: {
+			initSize() {
+				if (this.scrollable) {
+					// #ifndef APP-NVUE
+					let query = [],
+						boxWidth = 0,
+						textWidth = 0;
+					let textQuery = new Promise((resolve, reject) => {
+						uni.createSelectorQuery()
+							.in(this)
+							.select(`#${this.elId}`)
+							.boundingClientRect()
+							.exec(ret => {
+								this.textWidth = ret[0].width
+								resolve()
+							})
+					})
+					let boxQuery = new Promise((resolve, reject) => {
+						uni.createSelectorQuery()
+							.in(this)
+							.select(`#${this.elIdBox}`)
+							.boundingClientRect()
+							.exec(ret => {
+								this.boxWidth = ret[0].width
+								resolve()
+							})
+					})
+					query.push(textQuery)
+					query.push(boxQuery)
+					Promise.all(query).then(() => {
+						this.animationDuration = `${this.textWidth / this.speed}s`
+						this.animationDelay = `-${this.boxWidth / this.speed}s`
+						setTimeout(() => {
+							this.animationPlayState = 'running'
+						}, 1000)
+					})
+					// #endif
+					// #ifdef APP-NVUE
+					dom.getComponentRect(this.$refs['animationEle'], (res) => {
+						let winWidth = uni.getSystemInfoSync().windowWidth
+						this.textWidth = res.size.width
+						animation.transition(this.$refs['animationEle'], {
+							styles: {
+								transform: `translateX(-${winWidth}px)`
+							},
+							duration: 0,
+							timingFunction: 'linear',
+							delay: 0
+						}, () => {
+							if (!this.stopAnimation) {
+								animation.transition(this.$refs['animationEle'], {
+									styles: {
+										transform: `translateX(-${this.textWidth}px)`
+									},
+									timingFunction: 'linear',
+									duration: (this.textWidth - winWidth) / this.speed * 1000,
+									delay: 1000
+								}, () => {
+									if (!this.stopAnimation) {
+										this.loopAnimation()
+									}
+								});
+							}
+						});
+					})
+					// #endif
+				}
+				// #ifdef APP-NVUE
+				if (!this.scrollable && (this.single || this.moreText)) {
+					dom.getComponentRect(this.$refs['textBox'], (res) => {
+						this.wrapWidth = res.size.width
+					})
+				}
+				// #endif
+			},
+			loopAnimation() {
+				// #ifdef APP-NVUE
+				animation.transition(this.$refs['animationEle'], {
+					styles: {
+						transform: `translateX(0px)`
+					},
+					duration: 0
+				}, () => {
+					if (!this.stopAnimation) {
+						animation.transition(this.$refs['animationEle'], {
+							styles: {
+								transform: `translateX(-${this.textWidth}px)`
+							},
+							duration: this.textWidth / this.speed * 1000,
+							timingFunction: 'linear',
+							delay: 0
+						}, () => {
+							if (!this.stopAnimation) {
+								this.loopAnimation()
+							}
+						});
+					}
+				});
+				// #endif
+			},
+			clickMore() {
+				this.$emit('getmore')
+			},
+			close() {
+				this.show = false;
+				this.$emit('close')
+			},
+			onClick() {
+				this.$emit('click')
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	@import '@/uni.scss';
+
+	.uni-noticebar {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		width: 100%;
+		box-sizing: border-box;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+		padding: 6px 12px;
+		margin-bottom: 10px;
+	}
+
+	.uni-noticebar-close {
+		margin-right: 5px;
+	}
+
+	.uni-noticebar-icon {
+		margin-right: 5px;
+	}
+
+	.uni-noticebar__content-wrapper {
+		flex: 1;
+		flex-direction: column;
+		overflow: hidden;
+	}
+
+	.uni-noticebar__content-wrapper--single {
+		/* #ifndef APP-NVUE */
+		line-height: 18px;
+		/* #endif */
+	}
+
+	.uni-noticebar__content-wrapper--single,
+	.uni-noticebar__content-wrapper--scrollable {
+		flex-direction: row;
+	}
+
+	.uni-noticebar__content--scrollable {
+		/* #ifdef APP-NVUE */
+		flex: 0;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		flex: 1;
+		display: block;
+		overflow: hidden;
+		/* #endif */
+	}
+
+	.uni-noticebar__content--single {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		flex: none;
+		width: 100%;
+		justify-content: center;
+		/* #endif */
+	}
+
+	.uni-noticebar__content-text {
+		font-size: 14px;
+		line-height: 18px;
+		/* #ifndef APP-NVUE */
+		word-break: break-all;
+		/* #endif */
+	}
+
+	.uni-noticebar__content-text--single {
+		/* #ifdef APP-NVUE */
+		lines: 1;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		display: inline-block;
+		width: 100%;
+		white-space: nowrap;
+		/* #endif */
+		overflow: hidden;
+		text-overflow: ellipsis;
+	}
+
+	.uni-noticebar__content-text--scrollable {
+		/* #ifdef APP-NVUE */
+		lines: 1;
+		padding-left: 750rpx;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		display: inline-block;
+		white-space: nowrap;
+		padding-left: 100%;
+		animation: notice 10s 0s linear infinite both;
+		animation-play-state: paused;
+		/* #endif */
+	}
+
+	.uni-noticebar__more {
+		/* #ifndef APP-NVUE */
+		display: inline-flex;
+		/* #endif */
+		flex-direction: row;
+		flex-wrap: nowrap;
+		align-items: center;
+		padding-left: 5px;
+	}
+
+	.uni-noticebar__more-text {
+		font-size: 14px;
+	}
+
+	@keyframes notice {
+		100% {
+			transform: translate3d(-100%, 0, 0);
+		}
+	}
+</style>

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

@@ -0,0 +1,198 @@
+<template>
+	<view class="uni-numbox">
+		<view class="uni-numbox-minus" 
+			@click="_calcValue('subtract')"
+		>
+			<text class="iconfont iconmove" :class="minDisabled?'uni-numbox-disabled': ''" ></text>
+		</view>
+		<input 
+			class="uni-numbox-value" 
+			type="number"  
+			:disabled="disabled"
+			:value="inputValue" 
+			@blur="_onBlur"
+		>
+		<view 
+			class="uni-numbox-plus" 
+			@click="_calcValue('add')"
+		>
+			<text class="iconfont iconadd" :class="maxDisabled?'uni-numbox-disabled': ''" ></text>
+		</view>
+	</view>
+</template>
+<script>
+	export default {
+		name: 'uni-number-box',
+		props: {
+			isMax: {
+				type: Boolean,
+				default: false
+			},
+			isMin: {
+				type: Boolean,
+				default: false
+			},
+			index: {
+				type: Number,
+				default: 0
+			},
+			value: {
+				type: Number,
+				default: 0
+			},
+			min: {
+				type: Number,
+				default: -Infinity
+			},
+			max: {
+				type: Number,
+				default: Infinity
+			},
+			step: {
+				type: Number,
+				default: 1
+			},
+			disabled: {
+				type: Boolean,
+				default: false
+			}
+		},
+		data() {
+			return {
+				inputValue: this.value,
+				minDisabled: false,
+				maxDisabled: false
+			}
+		},
+		created(){
+			this.maxDisabled = this.isMax;
+			this.minDisabled = this.isMin;
+		},
+		computed: {
+
+		},
+		watch: {
+			inputValue(number) {
+				const data = {
+					number: number,
+					index: this.index
+				}
+				this.$emit('eventChange', data);
+			}
+		},
+		methods: {
+			_calcValue(type) {
+				const scale = this._getDecimalScale();
+				let value = this.inputValue * scale;
+				let newValue = 0;
+				let step = this.step * scale;
+				
+				if(type === 'subtract'){
+					newValue = value - step;
+					if (newValue <= this.min){
+						this.minDisabled = true;
+					}
+					if(newValue < this.min){
+						newValue = this.min
+					}
+					if(newValue < this.max && this.maxDisabled === true){
+						this.maxDisabled = false;
+					}
+				}else if(type === 'add'){
+					newValue = value + step;
+					if (newValue >= this.max){
+						this.maxDisabled = true;
+					}
+					if(newValue > this.max){
+						newValue = this.max
+					}
+					if(newValue > this.min && this.minDisabled === true){
+						this.minDisabled = false;
+					}
+				}
+				if(newValue === value){
+					return;
+				}
+				this.inputValue = newValue / scale;
+			},
+			_getDecimalScale() {
+				let scale = 1;
+				// 浮点型
+				if (~~this.step !== this.step) {
+					scale = Math.pow(10, (this.step + '').split('.')[1].length);
+				}
+				return scale;
+			},
+			_onBlur(event) {
+				let value = event.detail.value;
+				if (!value) {
+					this.inputValue = 0;
+					return
+				}
+				value = +value;
+				if (value > this.max) {
+					value = this.max;
+				} else if (value < this.min) {
+					value = this.min
+				}
+
+				this.inputValue = value
+			}
+		}
+	}
+</script>
+<style>
+	.uni-numbox {
+		/* position:absolute; */
+		/* left: 30rpx; */
+		/* bottom: 0; */
+		display: flex;
+		justify-content: flex-start;
+		align-items: center;
+		width:230rpx;
+		height: 70rpx;
+		background:#f5f5f5;
+	}
+
+	.uni-numbox-minus,
+	.uni-numbox-plus {
+		margin: 0;
+		background-color: #f5f5f5;
+		width: 70rpx;
+		height: 100%;
+		line-height: 70rpx;
+		text-align: center;
+		position: relative;
+	}
+	.uni-numbox-minus .yticon,
+	.uni-numbox-plus .yticon{
+		font-size: 36rpx;
+		color: #555;
+	}
+
+	.uni-numbox-minus {
+		border-right: none;
+		border-top-left-radius: 6rpx;
+		border-bottom-left-radius: 6rpx;
+	}
+
+	.uni-numbox-plus {
+		border-left: none;
+		border-top-right-radius: 6rpx;
+		border-bottom-right-radius: 6rpx;
+	}
+
+	.uni-numbox-value {
+		position: relative;
+		background-color: #f5f5f5;
+		width: 90rpx;
+		height: 50rpx;
+		text-align: center;
+		padding: 0;
+		font-size: 30rpx;
+	}
+
+	.uni-numbox-disabled.iconfont {
+		color: #d6d6d6;
+	}
+</style>

+ 22 - 0
components/uni-popup/message.js

@@ -0,0 +1,22 @@
+export default {
+	created() {
+		if (this.type === 'message') {
+			// 不显示遮罩
+			this.maskShow = false 
+			// 获取子组件对象
+			this.childrenMsg = null
+		}
+	},
+	methods: {
+		customOpen() {
+			if (this.childrenMsg) {
+				this.childrenMsg.open()
+			}
+		},
+		customClose() {
+			if (this.childrenMsg) {
+				this.childrenMsg.close()
+			}
+		}
+	}
+}

+ 25 - 0
components/uni-popup/popup.js

@@ -0,0 +1,25 @@
+import message from './message.js';
+// 定义 type 类型:弹出类型:top/bottom/center
+const config = {
+	// 顶部弹出
+	top:'top',
+	// 底部弹出
+	bottom:'bottom',
+	// 居中弹出
+	center:'center',
+	// 消息提示
+	message:'top',
+	// 对话框
+	dialog:'center',
+	// 分享
+	share:'bottom',
+}
+
+export default {
+	data(){
+		return {
+			config:config
+		}
+	},
+	mixins: [message],
+}

+ 243 - 0
components/uni-popup/uni-popup-dialog.vue

@@ -0,0 +1,243 @@
+<template>
+	<view class="uni-popup-dialog">
+		<view class="uni-dialog-title">
+			<text class="uni-dialog-title-text" :class="['uni-popup__'+dialogType]">{{title}}</text>
+		</view>
+		<view class="uni-dialog-content">
+			<text class="uni-dialog-content-text" v-if="mode === 'base'">{{content}}</text>
+			<input v-else class="uni-dialog-input" v-model="val" type="text" :placeholder="placeholder" :focus="focus" >
+		</view>
+		<view class="uni-dialog-button-group">
+			<view class="uni-dialog-button" @click="close">
+				<text class="uni-dialog-button-text">取消</text>
+			</view>
+			<view class="uni-dialog-button uni-border-left" @click="onOk">
+				<text class="uni-dialog-button-text uni-button-color">确定</text>
+			</view>
+		</view>
+
+	</view>
+</template>
+
+<script>
+	/**
+	 * PopUp 弹出层-对话框样式
+	 * @description 弹出层-对话框样式
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=329
+	 * @property {String} value input 模式下的默认值
+	 * @property {String} placeholder input 模式下输入提示
+	 * @property {String} type = [success|warning|info|error] 主题样式
+	 *  @value success 成功
+	 * 	@value warning 提示
+	 * 	@value info 消息
+	 * 	@value error 错误
+	 * @property {String} mode = [base|input] 模式、
+	 * 	@value base 基础对话框
+	 * 	@value input 可输入对话框
+	 * @property {String} content 对话框内容
+	 * @property {Boolean} beforeClose 是否拦截取消事件
+	 * @event {Function} confirm 点击确认按钮触发
+	 * @event {Function} close 点击取消按钮触发
+	 */
+
+	export default {
+		name: "uniPopupDialog",
+		props: {
+			value: {
+				type: [String, Number],
+				default: ''
+			},
+			placeholder: {
+				type: [String, Number],
+				default: '请输入内容'
+			},
+			/**
+			 * 对话框主题 success/warning/info/error	  默认 success
+			 */
+			type: {
+				type: String,
+				default: 'error'
+			},
+			/**
+			 * 对话框模式 base/input
+			 */
+			mode: {
+				type: String,
+				default: 'base'
+			},
+			/**
+			 * 对话框标题
+			 */
+			title: {
+				type: String,
+				default: '提示'
+			},
+			/**
+			 * 对话框内容
+			 */
+			content: {
+				type: String,
+				default: ''
+			},
+			/**
+			 * 拦截取消事件 ,如果拦截取消事件,必须监听close事件,执行 done()
+			 */
+			beforeClose: {
+				type: Boolean,
+				default: false
+			}
+		},
+		data() {
+			return {
+				dialogType: 'error',
+				focus: false,
+				val: ""
+			}
+		},
+		inject: ['popup'],
+		watch: {
+			type(val) {
+				this.dialogType = val
+			},
+			mode(val) {
+				if (val === 'input') {
+					this.dialogType = 'info'
+				}
+			},
+			value(val) {
+				this.val = val
+			}
+		},
+		created() {
+			// 对话框遮罩不可点击
+			this.popup.mkclick = false
+			if (this.mode === 'input') {
+				this.dialogType = 'info'
+				this.val = this.value
+			} else {
+				this.dialogType = this.type
+			}
+		},
+		mounted() {
+			this.focus = true
+		},
+		methods: {
+			/**
+			 * 点击确认按钮
+			 */
+			onOk() {
+				this.$emit('confirm', () => {
+					this.popup.close()
+					if (this.mode === 'input') this.val = this.value
+				}, this.mode === 'input' ? this.val : '')
+			},
+			/**
+			 * 点击取消按钮
+			 */
+			close() {
+				if (this.beforeClose) {
+					this.$emit('close', () => {
+						this.popup.close()
+					})
+					return
+				}
+				this.popup.close()
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.uni-popup-dialog {
+		width: 300px;
+		border-radius: 15px;
+		background-color: #fff;
+	}
+
+	.uni-dialog-title {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		justify-content: center;
+		padding-top: 15px;
+		padding-bottom: 5px;
+	}
+
+	.uni-dialog-title-text {
+		font-size: 16px;
+		font-weight: 500;
+	}
+
+	.uni-dialog-content {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+		padding: 5px 15px 15px 15px;
+	}
+
+	.uni-dialog-content-text {
+		font-size: 14px;
+		color: #6e6e6e;
+	}
+
+	.uni-dialog-button-group {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		border-top-color: #f5f5f5;
+		border-top-style: solid;
+		border-top-width: 1px;
+	}
+
+	.uni-dialog-button {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+
+		flex: 1;
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+		height: 45px;
+	}
+
+	.uni-border-left {
+		border-left-color: #f0f0f0;
+		border-left-style: solid;
+		border-left-width: 1px;
+	}
+
+	.uni-dialog-button-text {
+		font-size: 14px;
+	}
+
+	.uni-button-color {
+		color: $uni-color-primary;
+	}
+
+	.uni-dialog-input {
+		flex: 1;
+		font-size: 14px;
+	}
+
+	.uni-popup__success {
+		color: $uni-color-success;
+	}
+
+	.uni-popup__warn {
+		color: $uni-color-warning;
+	}
+
+	.uni-popup__error {
+		color: $uni-color-error;
+	}
+
+	.uni-popup__info {
+		color: #909399;
+	}
+</style>

+ 116 - 0
components/uni-popup/uni-popup-message.vue

@@ -0,0 +1,116 @@
+<template>
+	<view class="uni-popup-message" :class="'uni-popup__'+[type]">
+		<text class="uni-popup-message-text" :class="'uni-popup__'+[type]+'-text'">{{message}}</text>
+	</view>
+</template>
+
+<script>
+	
+	/**
+	 * PopUp 弹出层-消息提示
+	 * @description 弹出层-消息提示
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=329
+	 * @property {String} type = [success|warning|info|error] 主题样式
+	 *  @value success 成功
+	 * 	@value warning 提示
+	 * 	@value info 消息
+	 * 	@value error 错误
+	 * @property {String} message 消息提示文字
+	 * @property {String} duration 显示时间,设置为 0 则不会自动关闭
+	 */
+	
+	export default {
+		name: 'UniPopupMessage',
+		props: {
+			/**
+			 * 主题 success/warning/info/error	  默认 success
+			 */
+			type: {
+				type: String,
+				default: 'success'
+			},
+			/**
+			 * 消息文字
+			 */
+			message: {
+				type: String,
+				default: ''
+			},
+			/**
+			 * 显示时间,设置为 0 则不会自动关闭
+			 */
+			duration: {
+				type: Number,
+				default: 3000
+			}
+		},
+		inject: ['popup'],
+		data() {
+			return {}
+		},
+		created() {
+			this.popup.childrenMsg = this
+		},
+		methods: {
+			open() {
+				if (this.duration === 0) return
+				clearTimeout(this.popuptimer)
+				this.popuptimer = setTimeout(() => {
+					this.popup.close()
+				}, this.duration)
+			},
+			close() {
+				clearTimeout(this.popuptimer)
+			}
+		}
+	}
+</script>
+<style lang="scss" scoped>
+	.uni-popup-message {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		background-color: #e1f3d8;
+		padding: 10px 15px;
+		border-color: #eee;
+		border-style: solid;
+		border-width: 1px;
+	}
+	.uni-popup-message-text {
+		font-size: 14px;
+		padding: 0;
+	}
+
+	.uni-popup__success {
+		background-color: #e1f3d8;
+	}
+
+	.uni-popup__success-text {
+		color: #67C23A;
+	}
+
+	.uni-popup__warn {
+		background-color: #faecd8;
+	}
+
+	.uni-popup__warn-text {
+		color: #E6A23C;
+	}
+
+	.uni-popup__error {
+		background-color: #fde2e2;
+	}
+
+	.uni-popup__error-text {
+		color: #F56C6C;
+	}
+
+	.uni-popup__info {
+		background-color: #F2F6FC;
+	}
+
+	.uni-popup__info-text {
+		color: #909399;
+	}
+</style>

+ 165 - 0
components/uni-popup/uni-popup-share.vue

@@ -0,0 +1,165 @@
+<template>
+	<view class="uni-popup-share">
+		<view class="uni-share-title"><text class="uni-share-title-text">{{title}}</text></view>
+		<view class="uni-share-content">
+			<view class="uni-share-content-box">
+				<view class="uni-share-content-item" v-for="(item,index) in bottomData" :key="index" @click.stop="select(item,index)">
+					<image class="uni-share-image" :src="item.icon" mode="aspectFill"></image>
+					<text class="uni-share-text">{{item.text}}</text>
+				</view>
+
+			</view>
+		</view>
+		<view class="uni-share-button-box">
+			<button class="uni-share-button" @click="close">取消</button>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: 'UniPopupShare',
+		props: {
+			title: {
+				type: String,
+				default: '分享到'
+			}
+		},
+		inject: ['popup'],
+		data() {
+			return {
+				bottomData: [{
+						text: '微信',
+						icon: 'https://img-cdn-qiniu.dcloud.net.cn/uni-ui/grid-2.png',
+						name: 'wx'
+					},
+					{
+						text: '支付宝',
+						icon: 'https://img-cdn-qiniu.dcloud.net.cn/uni-ui/grid-8.png',
+						name: 'wx'
+					},
+					{
+						text: 'QQ',
+						icon: 'https://img-cdn-qiniu.dcloud.net.cn/uni-ui/gird-3.png',
+						name: 'qq'
+					},
+					{
+						text: '新浪',
+						icon: 'https://img-cdn-qiniu.dcloud.net.cn/uni-ui/grid-1.png',
+						name: 'sina'
+					},
+					{
+						text: '百度',
+						icon: 'https://img-cdn-qiniu.dcloud.net.cn/uni-ui/grid-7.png',
+						name: 'copy'
+					},
+					{
+						text: '其他',
+						icon: 'https://img-cdn-qiniu.dcloud.net.cn/uni-ui/grid-5.png',
+						name: 'more'
+					}
+				]
+			}
+		},
+		created() {},
+		methods: {
+			/**
+			 * 选择内容
+			 */
+			select(item, index) {
+				this.$emit('select', {
+					item,
+					index
+				}, () => {
+					this.popup.close()
+				})
+			},
+			/**
+			 * 关闭窗口
+			 */
+			close() {
+				this.popup.close()
+			}
+		}
+	}
+</script>
+<style lang="scss" scoped>
+	.uni-popup-share {
+		background-color: #fff;
+	}
+	.uni-share-title {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+		justify-content: center;
+		height: 40px;
+	}
+	.uni-share-title-text {
+		font-size: 14px;
+		color: #666;
+	}
+	.uni-share-content {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		justify-content: center;
+		padding-top: 10px;
+	}
+	
+	.uni-share-content-box {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		flex-wrap: wrap;
+		width: 360px;
+	}
+	
+	.uni-share-content-item {
+		width: 90px;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		justify-content: center;
+		padding: 10px 0;
+		align-items: center;
+	}
+	
+	.uni-share-content-item:active {
+		background-color: #f5f5f5;
+	}
+	
+	.uni-share-image {
+		width: 30px;
+		height: 30px;
+	}
+	
+	.uni-share-text {
+		margin-top: 10px;
+		font-size: 14px;
+		color: #3B4144;
+	}
+	
+	.uni-share-button-box {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		padding: 10px 15px;
+	}
+	
+	.uni-share-button {
+		flex: 1;
+		border-radius: 50px;
+		color: #666;
+		font-size: 16px;
+	}
+	
+	.uni-share-button::after {
+		border-radius: 50px;
+	}
+</style>

+ 294 - 0
components/uni-popup/uni-popup.vue

@@ -0,0 +1,294 @@
+<template>
+	<view v-if="showPopup" class="uni-popup" :class="[popupstyle]" @touchmove.stop.prevent="clear">
+		<uni-transition v-if="maskShow" :mode-class="['fade']" :styles="maskClass" :duration="duration" :show="showTrans"
+		 @click="onTap" />
+		<uni-transition :mode-class="ani" :styles="transClass" :duration="duration" :show="showTrans" @click="onTap">
+			<view class="uni-popup__wrapper-box" @click.stop="clear">
+				<slot />
+			</view>
+		</uni-transition>
+	</view>
+</template>
+
+<script>
+	import uniTransition from '../uni-transition/uni-transition.vue'
+	import popup from './popup.js'
+	/**
+	 * PopUp 弹出层
+	 * @description 弹出层组件,为了解决遮罩弹层的问题
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=329
+	 * @property {String} type = [top|center|bottom] 弹出方式
+	 * 	@value top 顶部弹出
+	 * 	@value center 中间弹出
+	 * 	@value bottom 底部弹出
+	 * 	@value message 消息提示
+	 * 	@value dialog 对话框
+	 * 	@value share 底部分享示例
+	 * @property {Boolean} animation = [ture|false] 是否开启动画
+	 * @property {Boolean} maskClick = [ture|false] 蒙版点击是否关闭弹窗
+	 * @event {Function} change 打开关闭弹窗触发,e={show: false}
+	 */
+
+	export default {
+		name: 'UniPopup',
+		components: {
+			uniTransition
+		},
+		props: {
+			// 开启动画
+			animation: {
+				type: Boolean,
+				default: true
+			},
+			// 弹出层类型,可选值,top: 顶部弹出层;bottom:底部弹出层;center:全屏弹出层
+			// message: 消息提示 ; dialog : 对话框
+			type: {
+				type: String,
+				default: 'center'
+			},
+			// maskClick
+			maskClick: {
+				type: Boolean,
+				default: true
+			}
+		},
+		provide() {
+			return {
+				popup: this
+			}
+		},
+		mixins: [popup],
+		watch: {
+			/**
+			 * 监听type类型
+			 */
+			type: {
+				handler: function(newVal) {
+					this[this.config[newVal]]()
+				},
+				immediate: true
+			},
+			/**
+			 * 监听遮罩是否可点击
+			 * @param {Object} val
+			 */
+			maskClick(val) {
+				this.mkclick = val
+			}
+		},
+		data() {
+			return {
+				duration: 300,
+				ani: [],
+				showPopup: false,
+				showTrans: false,
+				maskClass: {
+					'position': 'fixed',
+					'bottom': 0,
+					'top': 0,
+					'left': 0,
+					'right': 0,
+					'backgroundColor': 'rgba(0, 0, 0, 0.4)'
+				},
+				transClass: {
+					'position': 'fixed',
+					'left': 0,
+					'right': 0,
+				},
+				maskShow: true,
+				mkclick: true,
+				popupstyle: 'top'
+			}
+		},
+		created() {
+			this.mkclick = this.maskClick
+			if (this.animation) {
+				this.duration = 300
+			} else {
+				this.duration = 0
+			}
+		},
+		methods: {
+			clear(e) {
+				// TODO nvue 取消冒泡
+				e.stopPropagation()
+			},
+			open() {
+				this.showPopup = true
+				this.$nextTick(() => {
+					new Promise(resolve => {
+						clearTimeout(this.timer)
+						this.timer = setTimeout(() => {
+							this.showTrans = true
+							// fixed by mehaotian 兼容 app 端
+							this.$nextTick(() => {
+								resolve();
+							})
+						}, 50);
+					}).then(res => {
+						// 自定义打开事件
+						clearTimeout(this.msgtimer)
+						this.msgtimer = setTimeout(() => {
+							this.customOpen && this.customOpen()
+						}, 100)
+						this.$emit('change', {
+							show: true,
+							type: this.type
+						})
+					})
+				})
+			},
+			close(type) {
+				this.showTrans = false
+				this.$nextTick(() => {
+					this.$emit('change', {
+						show: false,
+						type: this.type
+					})
+					clearTimeout(this.timer)
+					// 自定义关闭事件
+					this.customOpen && this.customClose()
+					this.timer = setTimeout(() => {
+						this.showPopup = false
+					}, 300)
+				})
+			},
+			onTap() {
+				if (!this.mkclick) return
+				this.close()
+			},
+			/**
+			 * 顶部弹出样式处理
+			 */
+			top() {
+				this.popupstyle = 'top'
+				this.ani = ['slide-top']
+				this.transClass = {
+					'position': 'fixed',
+					'left': 0,
+					'right': 0,
+				}
+			},
+			/**
+			 * 底部弹出样式处理
+			 */
+			bottom() {
+				this.popupstyle = 'bottom'
+				this.ani = ['slide-bottom']
+				this.transClass = {
+					'position': 'fixed',
+					'left': 0,
+					'right': 0,
+					'bottom': 0
+				}
+			},
+			/**
+			 * 中间弹出样式处理
+			 */
+			center() {
+				this.popupstyle = 'center'
+				this.ani = ['zoom-out', 'fade']
+				this.transClass = {
+					'position': 'fixed',
+					/* #ifndef APP-NVUE */
+					'display': 'flex',
+					'flexDirection': 'column',
+					/* #endif */
+					'bottom': 0,
+					'left': 0,
+					'right': 0,
+					'top': 0,
+					'justifyContent': 'center',
+					'alignItems': 'center'
+				}
+			}
+		}
+	}
+</script>
+<style lang="scss" scoped>
+	.uni-popup {
+		position: fixed;
+		/* #ifndef APP-NVUE */
+		z-index: 99;
+		/* #endif */
+	}
+
+	.uni-popup__mask {
+		position: absolute;
+		top: 0;
+		bottom: 0;
+		left: 0;
+		right: 0;
+		background-color: $uni-bg-color-mask;
+		opacity: 0;
+	}
+
+	.mask-ani {
+		transition-property: opacity;
+		transition-duration: 0.2s;
+	}
+
+	.uni-top-mask {
+		opacity: 1;
+	}
+
+	.uni-bottom-mask {
+		opacity: 1;
+	}
+
+	.uni-center-mask {
+		opacity: 1;
+	}
+
+	.uni-popup__wrapper {
+		/* #ifndef APP-NVUE */
+		display: block;
+		/* #endif */
+		position: absolute;
+	}
+
+	.top {
+		/* #ifdef H5 */
+		top: var(--window-top);
+		/* #endif */
+		/* #ifndef H5 */
+		top: 0;
+		/* #endif */
+	}
+
+	.bottom {
+		bottom: 0;
+	}
+
+	.uni-popup__wrapper-box {
+		/* #ifndef APP-NVUE */
+		display: block;
+		/* #endif */
+		position: relative;
+		/* iphonex 等安全区设置,底部安全区适配 */
+		/* #ifndef APP-NVUE */
+		padding-bottom: constant(safe-area-inset-bottom);
+		padding-bottom: env(safe-area-inset-bottom);
+		/* #endif */
+	}
+
+	.content-ani {
+		// transition: transform 0.3s;
+		transition-property: transform, opacity;
+		transition-duration: 0.2s;
+	}
+
+
+	.uni-top-content {
+		transform: translateY(0);
+	}
+
+	.uni-bottom-content {
+		transform: translateY(0);
+	}
+
+	.uni-center-content {
+		transform: scale(1);
+		opacity: 1;
+	}
+</style>

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

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

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

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

+ 226 - 0
components/upload-images.vue

@@ -0,0 +1,226 @@
+<template>
+	<view class="upload-content">
+		<block v-for="(item, index) in imageList" :key="index">
+			<view class="upload-item">
+				<image class="upload-img" :src="item.filePath" mode="aspectFill" @click="previewImage(index)"></image>
+				<image class="upload-del-btn" 
+					@click="delImage(index)" 
+					src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACYAAAAmCAYAAACoPemuAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RjNBODgzQjUwNDM5MTFFOUJDMjlGN0UwRTJGMjVCNjQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RjNBODgzQjYwNDM5MTFFOUJDMjlGN0UwRTJGMjVCNjQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpGM0E4ODNCMzA0MzkxMUU5QkMyOUY3RTBFMkYyNUI2NCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpGM0E4ODNCNDA0MzkxMUU5QkMyOUY3RTBFMkYyNUI2NCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PuYQTIAAAAHNSURBVHjazJgxasMwFIbjnsD4BDmCLxDQDZrNQ5bcILlBvXvpDRLIWmiHFkyH2t0LyVbwEkPpbE/eYlUCGYQax096UuIffkIgij7ryU/vyZuYy2e+Z56K70R8lsJcOfPn5AriMCvmZ2YKdMW8EQ/hRA9iEorwXlpZtObMRySQ6kysvrFWloHUEIcmUBuHUDLccmxQskErt7wyVLdy00tQ4Q2g5De2V9kNwWjffiNDA33f/42i6E13Qj5uNptlwJD+SyODuaqqqi/KVBTFOxSKA7VtW/NxSZI8AcbE2nuraZpvKgSBk6G4drsdBOwogz1CwAghH/JEl+BUKJ1VltPHHjoIAoeE4l53YFqb+RKcBSgqyqXhtxEKZwkKB3YOThYCqjPuCDoHZwGK3mGLtdPp5LmqTI1Dqe4p26EkNqA4iE6eg2z+iQ0okyQMATvYgLIIt9Y6knTyFBIudHqIq3BpmkL60VJ9O0sXZY8MBwSLtdNGEAQ/i8XiVXcz83EcEPDbuq/fzMdYWt+6GTmMsX2rh9q3TtsxNrzXhKt1rwg6rR1Dhdjqo7QMlWOvoWTF4imxQMRF7eaL8L5ohmwrLgDB8pCQc8DlcG7y538CDABJNGPqfaJgfgAAAABJRU5ErkJggg==" 
+					mode="scaleToFill">
+				</image>
+				<view class="upload-progress" v-if="item.progress < 100">{{item.progress}}%</view>
+			</view>
+		</block>
+		<view class="upload-add-btn" v-if="rduLength > 0" @click="chooseImage"></view>
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			imageList: []
+		};
+	},
+	props: {
+		url: {
+			type: String,
+			value: '' //上传接口地址
+		},
+		count: {
+			type: Number,
+			value: 4 //单次可选择的图片数量
+		},
+		length: {
+			type: Number,
+			value: 50 //可上传总数量
+		}
+	},
+	computed: {
+		rduLength(){
+			return this.length - this.imageList.length;
+		}
+	},
+	methods: {
+		//选择图片
+		chooseImage: function(){
+			uni.chooseImage({
+				count: this.rduLength < this.count ? this.rduLength : this.count, //最多可以选择的图片张数,默认9
+				sizeType: ['original', 'compressed'], //original 原图,compressed 压缩图,默认二者都有
+				sourceType: ['album'], //album 从相册选图,camera 使用相机,默认二者都有
+				success: (res)=> {
+					const images = res.tempFilePaths;
+					this.uploadFiles(images);
+				}
+			});
+		},
+		//上传图片
+		async uploadFiles(images){
+			this.imageList.push({
+				filePath: images[0],
+				progress: 0
+			});
+			uni.showLoading({
+				title: '请稍后..',
+				mask: true,
+			})
+			try{
+				const uploadUrl = await this.uploadImage(images[0]);
+			}catch(err){
+				console.log(err);
+				return;
+			}
+			
+			if(uploadUrl !== false){
+				images.splice(0, 1);
+				this.imageList[this.imageList.length - 1].src = uploadUrl;
+
+				//判断是否需要继续上传
+				if(images.length > 0 && this.rduLength > 0){
+					this.uploadFiles(images);
+				}else{
+					uni.hideLoading();
+				}
+			}else{
+				//上传失败处理
+				this.imageList.pop();
+				uni.hideLoading();
+				uni.showToast({
+					title: '上传中出现问题,已终止上传',
+					icon: 'none',
+					mask: true,
+					duration: 2000
+				});
+			}
+		},
+		uploadImage: function(file){
+			return new Promise((resolve, reject)=> {
+				//发送给后端的附加参数
+				const formData = {
+					thumb_mode: 1,  
+				};
+				this.uploadTask = uni.uploadFile({
+					url: this.url, 
+					filePath: file,
+					name: 'file',
+					formData: formData,
+					success(uploadFileResult){
+						const uploadFileRes = JSON.parse(uploadFileResult.data) || {};
+						if(uploadFileRes.status === 1 && uploadFileRes.data){
+							resolve(uploadFileRes.data);
+						}else{
+							reject('接口返回错误');
+						}
+					}, 
+					fail(){
+						reject('网络链接错误');
+					}
+				});
+				//上传进度
+				this.uploadTask.onProgressUpdate((progressRes)=> {
+					this.imageList[this.imageList.length - 1].progress = progressRes.progress;
+				});
+			});
+		},
+		//删除图片
+		delImage: function(index){
+			uni.showModal({
+				content: '确定要放弃这张图片么?',
+				success: (confirmRes)=> {
+					if (confirmRes.confirm) {
+						this.imageList.splice(index, 1);
+					} 
+				}
+			});
+		},
+		//预览图片
+		previewImage: function(index){
+			const urls = [];
+			this.imageList.forEach((item)=> {
+				urls.push(item.filePath);
+			})
+			uni.previewImage({
+				current: urls[index],
+				urls: urls,
+				indicator: "number"
+			})
+		}
+	}
+}
+</script>
+
+<style lang="scss">
+	.upload-content{
+		padding:24upx 0 0 28upx;
+		background-color: #fff;
+		overflow:hidden;
+	}
+	.upload-item{
+		position: relative;
+		float:left;
+		width:150upx;
+		height:150upx;
+		margin-right:30upx;
+		margin-bottom:30upx;
+		&:nth-child(4n){
+			margin-right:0;
+		}
+		.upload-img{
+			width:100%;
+			height:100%;
+			border-radius:8upx;
+		}
+		.upload-del-btn{
+			position: absolute;
+			right:-16upx;
+			top:-14upx;
+			width:36upx;
+			height:36upx;
+			border: 4upx solid #fff;
+			border-radius: 100px;
+		}
+		.upload-progress{
+			position: absolute;
+			left:0;
+			top:0;
+			display:flex;
+			align-items:center;
+			justify-content: center;
+			width:100%;
+			height:100%;
+			background-color: rgba(0,0,0,.4);
+			color:#fff;
+			font-size:24upx;
+			border-radius:8upx;
+		}
+	}
+	.upload-add-btn {
+		position: relative;
+		float:left;
+		width: 150upx;
+		height: 150upx;
+		z-index: 99;
+		border-radius:8upx;
+		background:#f9f9f9;
+		&:before,
+		&:after {
+			content: " ";
+			position: absolute;
+			top: 50%;
+			left: 50%;
+			-webkit-transform: translate(-50%, -50%);
+			transform: translate(-50%, -50%);
+			width: 4upx;
+			height: 60upx;
+			background-color: #d6d6d6;
+		}
+		&:after {
+			width: 60upx;
+			height: 4upx;
+		}
+		&:active {
+			background-color: #f7f7f7;
+		}
+	}
+
+</style>

+ 4914 - 0
components/wangding-pickerAddress/data.js

@@ -0,0 +1,4914 @@
+export default [
+  {
+    "name": "北京市",
+    "city": [
+      {
+        "name": "北京市",
+        "area": [
+          "东城区",
+          "西城区",
+          "崇文区",
+          "宣武区",
+          "朝阳区",
+          "丰台区",
+          "石景山区",
+          "海淀区",
+          "门头沟区",
+          "房山区",
+          "通州区",
+          "顺义区",
+          "昌平区",
+          "大兴区",
+          "平谷区",
+          "怀柔区",
+          "密云县",
+          "延庆县"
+        ]
+      }
+    ]
+  },
+  {
+    "name": "天津市",
+    "city": [
+      {
+        "name": "天津市",
+        "area": [
+          "和平区",
+          "河东区",
+          "河西区",
+          "南开区",
+          "河北区",
+          "红桥区",
+          "塘沽区",
+          "汉沽区",
+          "大港区",
+          "东丽区",
+          "西青区",
+          "津南区",
+          "北辰区",
+          "武清区",
+          "宝坻区",
+          "宁河县",
+          "静海县",
+          "蓟  县"
+        ]
+      }
+    ]
+  },
+  {
+    "name": "河北省",
+    "city": [
+      {
+        "name": "石家庄市",
+        "area": [
+          "长安区",
+          "桥东区",
+          "桥西区",
+          "新华区",
+          "郊  区",
+          "井陉矿区",
+          "井陉县",
+          "正定县",
+          "栾城县",
+          "行唐县",
+          "灵寿县",
+          "高邑县",
+          "深泽县",
+          "赞皇县",
+          "无极县",
+          "平山县",
+          "元氏县",
+          "赵  县",
+          "辛集市",
+          "藁",
+          "晋州市",
+          "新乐市",
+          "鹿泉市"
+        ]
+      },
+      {
+        "name": "唐山市",
+        "area": [
+          "路南区",
+          "路北区",
+          "古冶区",
+          "开平区",
+          "新  区",
+          "丰润县",
+          "滦  县",
+          "滦南县",
+          "乐亭县",
+          "迁西县",
+          "玉田县",
+          "唐海县",
+          "遵化市",
+          "丰南市",
+          "迁安市"
+        ]
+      },
+      {
+        "name": "秦皇岛市",
+        "area": [
+          "海港区",
+          "山海关区",
+          "北戴河区",
+          "青龙满族自治县",
+          "昌黎县",
+          "抚宁县",
+          "卢龙县"
+        ]
+      },
+      {
+        "name": "邯郸市",
+        "area": [
+          "邯山区",
+          "丛台区",
+          "复兴区",
+          "峰峰矿区",
+          "邯郸县",
+          "临漳县",
+          "成安县",
+          "大名县",
+          "涉  县",
+          "磁  县",
+          "肥乡县",
+          "永年县",
+          "邱  县",
+          "鸡泽县",
+          "广平县",
+          "馆陶县",
+          "魏  县",
+          "曲周县",
+          "武安市"
+        ]
+      },
+      {
+        "name": "邢台市",
+        "area": [
+          "桥东区",
+          "桥西区",
+          "邢台县",
+          "临城县",
+          "内丘县",
+          "柏乡县",
+          "隆尧县",
+          "任  县",
+          "南和县",
+          "宁晋县",
+          "巨鹿县",
+          "新河县",
+          "广宗县",
+          "平乡县",
+          "威  县",
+          "清河县",
+          "临西县",
+          "南宫市",
+          "沙河市"
+        ]
+      },
+      {
+        "name": "保定市",
+        "area": [
+          "新市区",
+          "北市区",
+          "南市区",
+          "满城县",
+          "清苑县",
+          "涞水县",
+          "阜平县",
+          "徐水县",
+          "定兴县",
+          "唐  县",
+          "高阳县",
+          "容城县",
+          "涞源县",
+          "望都县",
+          "安新县",
+          "易  县",
+          "曲阳县",
+          "蠡  县",
+          "顺平县",
+          "博野",
+          "雄县",
+          "涿州市",
+          "定州市",
+          "安国市",
+          "高碑店市"
+        ]
+      },
+      {
+        "name": "张家口",
+        "area": [
+          "桥东区",
+          "桥西区",
+          "宣化区",
+          "下花园区",
+          "宣化县",
+          "张北县",
+          "康保县",
+          "沽源县",
+          "尚义县",
+          "蔚  县",
+          "阳原县",
+          "怀安县",
+          "万全县",
+          "怀来县",
+          "涿鹿县",
+          "赤城县",
+          "崇礼县"
+        ]
+      },
+      {
+        "name": "承德市",
+        "area": [
+          "双桥区",
+          "双滦区",
+          "鹰手营子矿区",
+          "承德县",
+          "兴隆县",
+          "平泉县",
+          "滦平县",
+          "隆化县",
+          "丰宁满族自治县",
+          "宽城满族自治县",
+          "围场满族蒙古族自治县"
+        ]
+      },
+      {
+        "name": "沧州市",
+        "area": [
+          "新华区",
+          "运河区",
+          "沧  县",
+          "青  县",
+          "东光县",
+          "海兴县",
+          "盐山县",
+          "肃宁县",
+          "南皮县",
+          "吴桥县",
+          "献  县",
+          "孟村回族自治县",
+          "泊头市",
+          "任丘市",
+          "黄骅市",
+          "河间市"
+        ]
+      },
+      {
+        "name": "廊坊市",
+        "area": [
+          "安次区",
+          "固安县",
+          "永清县",
+          "香河县",
+          "大城县",
+          "文安县",
+          "大厂回族自治县",
+          "霸州市",
+          "三河市"
+        ]
+      },
+      {
+        "name": "衡水市",
+        "area": [
+          "桃城区",
+          "枣强县",
+          "武邑县",
+          "武强县",
+          "饶阳县",
+          "安平县",
+          "故城县",
+          "景  县",
+          "阜城县",
+          "冀州市",
+          "深州市"
+        ]
+      }
+    ]
+  },
+  {
+    "name": "山西省",
+    "city": [
+      {
+        "name": "太原市",
+        "area": [
+          "小店区",
+          "迎泽区",
+          "杏花岭区",
+          "尖草坪区",
+          "万柏林区",
+          "晋源区",
+          "清徐县",
+          "阳曲县",
+          "娄烦县",
+          "古交市"
+        ]
+      },
+      {
+        "name": "大同市",
+        "area": [
+          "城  区",
+          "矿  区",
+          "南郊区",
+          "新荣区",
+          "阳高县",
+          "天镇县",
+          "广灵县",
+          "灵丘县",
+          "浑源县",
+          "左云县",
+          "大同县"
+        ]
+      },
+      {
+        "name": "阳泉市",
+        "area": [
+          "城  区",
+          "矿  区",
+          "郊  区",
+          "平定县",
+          "盂  县"
+        ]
+      },
+      {
+        "name": "长治市",
+        "area": [
+          "城  区",
+          "郊  区",
+          "长治县",
+          "襄垣县",
+          "屯留县",
+          "平顺县",
+          "黎城县",
+          "壶关县",
+          "长子县",
+          "武乡县",
+          "沁  县",
+          "沁源县",
+          "潞城市"
+        ]
+      },
+      {
+        "name": "晋城市",
+        "area": [
+          "城  区",
+          "沁水县",
+          "阳城县",
+          "陵川县",
+          "泽州县",
+          "高平市"
+        ]
+      },
+      {
+        "name": "朔州市",
+        "area": [
+          "朔城区",
+          "平鲁区",
+          "山阴县",
+          "应  县",
+          "右玉县",
+          "怀仁县"
+        ]
+      },
+      {
+        "name": "忻州市",
+        "area": [
+          "忻府区",
+          "原平市",
+          "定襄县",
+          "五台县",
+          "代  县",
+          "繁峙县",
+          "宁武县",
+          "静乐县",
+          "神池县",
+          "五寨县",
+          "岢岚县",
+          "河曲县",
+          "保德县",
+          "偏关县"
+        ]
+      },
+      {
+        "name": "吕梁市",
+        "area": [
+          "离石区",
+          "孝义市",
+          "汾阳市",
+          "文水县",
+          "交城县",
+          "兴  县",
+          "临  县",
+          "柳林县",
+          "石楼县",
+          "岚  县",
+          "方山县",
+          "中阳县",
+          "交口县"
+        ]
+      },
+      {
+        "name": "晋中市",
+        "area": [
+          "榆次市",
+          "介休市",
+          "榆社县",
+          "左权县",
+          "和顺县",
+          "昔阳县",
+          "寿阳县",
+          "太谷县",
+          "祁  县",
+          "平遥县",
+          "灵石县"
+        ]
+      },
+      {
+        "name": "临汾市",
+        "area": [
+          "临汾市",
+          "侯马市",
+          "霍州市",
+          "曲沃县",
+          "翼城县",
+          "襄汾县",
+          "洪洞县",
+          "古  县",
+          "安泽县",
+          "浮山县",
+          "吉  县",
+          "乡宁县",
+          "蒲  县",
+          "大宁县",
+          "永和县",
+          "隰  县",
+          "汾西县"
+        ]
+      },
+      {
+        "name": "运城市",
+        "area": [
+          "运城市",
+          "永济市",
+          "河津市",
+          "芮城县",
+          "临猗县",
+          "万荣县",
+          "新绛县",
+          "稷山县",
+          "闻喜县",
+          "夏  县",
+          "绛  县",
+          "平陆县",
+          "垣曲县"
+        ]
+      }
+    ]
+  },
+  {
+    "name": "内蒙古",
+    "city": [
+      {
+        "name": "呼和浩特市",
+        "area": [
+          "新城区",
+          "回民区",
+          "玉泉区",
+          "郊  区",
+          "土默特左旗",
+          "托克托县",
+          "和林格尔县",
+          "清水河县",
+          "武川县"
+        ]
+      },
+      {
+        "name": "包头市",
+        "area": [
+          "东河区",
+          "昆都伦区",
+          "青山区",
+          "石拐矿区",
+          "白云矿区",
+          "郊  区",
+          "土默特右旗",
+          "固阳县",
+          "达尔罕茂明安联合旗"
+        ]
+      },
+      {
+        "name": "乌海市",
+        "area": [
+          "海勃湾区",
+          "海南区",
+          "乌达区"
+        ]
+      },
+      {
+        "name": "赤峰市",
+        "area": [
+          "红山区",
+          "元宝山区",
+          "松山区",
+          "阿鲁科尔沁旗",
+          "巴林左旗",
+          "巴林右旗",
+          "林西县",
+          "克什克腾旗",
+          "翁牛特旗",
+          "喀喇沁旗",
+          "宁城县",
+          "敖汉旗"
+        ]
+      },
+      {
+        "name": "呼伦贝尔市",
+        "area": [
+          "海拉尔市",
+          "满洲里市",
+          "扎兰屯市",
+          "牙克石市",
+          "根河市",
+          "额尔古纳市",
+          "阿荣旗",
+          "莫力达瓦达斡尔族自治旗",
+          "鄂伦春自治旗",
+          "鄂温克族自治旗",
+          "新巴尔虎右旗",
+          "新巴尔虎左旗",
+          "陈巴尔虎旗"
+        ]
+      },
+      {
+        "name": "兴安盟",
+        "area": [
+          "乌兰浩特市",
+          "阿尔山市",
+          "科尔沁右翼前旗",
+          "科尔沁右翼中旗",
+          "扎赉特旗",
+          "突泉县"
+        ]
+      },
+      {
+        "name": "通辽市",
+        "area": [
+          "科尔沁区",
+          "霍林郭勒市",
+          "科尔沁左翼中旗",
+          "科尔沁左翼后旗",
+          "开鲁县",
+          "库伦旗",
+          "奈曼旗",
+          "扎鲁特旗"
+        ]
+      },
+      {
+        "name": "锡林郭勒盟",
+        "area": [
+          "二连浩特市",
+          "锡林浩特市",
+          "阿巴嘎旗",
+          "苏尼特左旗",
+          "苏尼特右旗",
+          "东乌珠穆沁旗",
+          "西乌珠穆沁旗",
+          "太仆寺旗",
+          "镶黄旗",
+          "正镶白旗",
+          "正蓝旗",
+          "多伦县"
+        ]
+      },
+      {
+        "name": "乌兰察布盟",
+        "area": [
+          "集宁市",
+          "丰镇市",
+          "卓资县",
+          "化德县",
+          "商都县",
+          "兴和县",
+          "凉城县",
+          "察哈尔右翼前旗",
+          "察哈尔右翼中旗",
+          "察哈尔右翼后旗",
+          "四子王旗"
+        ]
+      },
+      {
+        "name": "伊克昭盟",
+        "area": [
+          "东胜市",
+          "达拉特旗",
+          "准格尔旗",
+          "鄂托克前旗",
+          "鄂托克旗",
+          "杭锦旗",
+          "乌审旗",
+          "伊金霍洛旗"
+        ]
+      },
+      {
+        "name": "巴彦淖尔盟",
+        "area": [
+          "临河市",
+          "五原县",
+          "磴口县",
+          "乌拉特前旗",
+          "乌拉特中旗",
+          "乌拉特后旗",
+          "杭锦后旗"
+        ]
+      },
+      {
+        "name": "阿拉善盟",
+        "area": [
+          "阿拉善左旗",
+          "阿拉善右旗",
+          "额济纳旗"
+        ]
+      }
+    ]
+  },
+  {
+    "name": "辽宁省",
+    "city": [
+      {
+        "name": "沈阳市",
+        "area": [
+          "沈河区",
+          "皇姑区",
+          "和平区",
+          "大东区",
+          "铁西区",
+          "苏家屯区",
+          "东陵区",
+          "于洪区",
+          "新民市",
+          "法库县",
+          "辽中县",
+          "康平县",
+          "新城子区"
+        ]
+      },
+      {
+        "name": "大连市",
+        "area": [
+          "西岗区",
+          "中山区",
+          "沙河口区",
+          "甘井子区",
+          "旅顺口区",
+          "金州区",
+          "瓦房店市",
+          "普兰店市",
+          "庄河市",
+          "长海县"
+        ]
+      },
+      {
+        "name": "鞍山市",
+        "area": [
+          "铁东区",
+          "铁西区",
+          "立山区",
+          "千山区",
+          "海城市",
+          "台安县",
+          "岫岩满族自治县"
+        ]
+      },
+      {
+        "name": "抚顺市",
+        "area": [
+          "顺城区",
+          "新抚区",
+          "东洲区",
+          "望花区",
+          "抚顺县",
+          "清原满族自治县",
+          "新宾满族自治县"
+        ]
+      },
+      {
+        "name": "本溪市",
+        "area": [
+          "平山区",
+          "明山区",
+          "溪湖区",
+          "南芬区",
+          "本溪满族自治县",
+          "桓仁满族自治县"
+        ]
+      },
+      {
+        "name": "丹东市",
+        "area": [
+          "振兴区",
+          "元宝区",
+          "振安区",
+          "东港市",
+          "凤城市",
+          "宽甸满族自治县"
+        ]
+      },
+      {
+        "name": "锦州市",
+        "area": [
+          "太和区",
+          "古塔区",
+          "凌河区",
+          "凌海市",
+          "黑山县",
+          "义县",
+          "北宁市"
+        ]
+      },
+      {
+        "name": "营口市",
+        "area": [
+          "站前区",
+          "西市区",
+          "鲅鱼圈区",
+          "老边区",
+          "大石桥市",
+          "盖州市"
+        ]
+      },
+      {
+        "name": "阜新市",
+        "area": [
+          "海州区",
+          "新邱区",
+          "太平区",
+          "清河门区",
+          "细河区",
+          "彰武县",
+          "阜新蒙古族自治县"
+        ]
+      },
+      {
+        "name": "辽阳市",
+        "area": [
+          "白塔区",
+          "文圣区",
+          "宏伟区",
+          "太子河区",
+          "弓长岭区",
+          "灯塔市",
+          "辽阳县"
+        ]
+      },
+      {
+        "name": "盘锦",
+        "area": [
+          "双台子区",
+          "兴隆台区",
+          "盘山县",
+          "大洼县"
+        ]
+      },
+      {
+        "name": "铁岭市",
+        "area": [
+          "银州区",
+          "清河区",
+          "调兵山市",
+          "开原市",
+          "铁岭县",
+          "昌图县",
+          "西丰县"
+        ]
+      },
+      {
+        "name": "朝阳市",
+        "area": [
+          "双塔区",
+          "龙城区",
+          "凌源市",
+          "北票市",
+          "朝阳县",
+          "建平县",
+          "喀喇沁左翼蒙古族自治县"
+        ]
+      },
+      {
+        "name": "葫芦岛市",
+        "area": [
+          "龙港区",
+          "南票区",
+          "连山区",
+          "兴城市",
+          "绥中县",
+          "建昌县"
+        ]
+      }
+    ]
+  },
+  {
+    "name": "吉林省",
+    "city": [
+      {
+        "name": "长春市",
+        "area": [
+          "朝阳区",
+          "宽城区",
+          "二道区",
+          "南关区",
+          "绿园区",
+          "双阳区",
+          "九台市",
+          "榆树市",
+          "德惠市",
+          "农安县"
+        ]
+      },
+      {
+        "name": "吉林市",
+        "area": [
+          "船营区",
+          "昌邑区",
+          "龙潭区",
+          "丰满区",
+          "舒兰市",
+          "桦甸市",
+          "蛟河市",
+          "磐石市",
+          "永吉县"
+        ]
+      },
+      {
+        "name": "四平",
+        "area": [
+          "铁西区",
+          "铁东区",
+          "公主岭市",
+          "双辽市",
+          "梨树县",
+          "伊通满族自治县"
+        ]
+      },
+      {
+        "name": "辽源市",
+        "area": [
+          "龙山区",
+          "西安区",
+          "东辽县",
+          "东丰县"
+        ]
+      },
+      {
+        "name": "通化市",
+        "area": [
+          "东昌区",
+          "二道江区",
+          "梅河口市",
+          "集安市",
+          "通化县",
+          "辉南县",
+          "柳河县"
+        ]
+      },
+      {
+        "name": "白山市",
+        "area": [
+          "八道江区",
+          "江源区",
+          "临江市",
+          "靖宇县",
+          "抚松县",
+          "长白朝鲜族自治县"
+        ]
+      },
+      {
+        "name": "松原市",
+        "area": [
+          "宁江区",
+          "乾安县",
+          "长岭县",
+          "扶余县",
+          "前郭尔罗斯蒙古族自治县"
+        ]
+      },
+      {
+        "name": "白城市",
+        "area": [
+          "洮北区",
+          "大安市",
+          "洮南市",
+          "镇赉县",
+          "通榆县"
+        ]
+      },
+      {
+        "name": "延边朝鲜族自治州",
+        "area": [
+          "延吉市",
+          "图们市",
+          "敦化市",
+          "龙井市",
+          "珲春市",
+          "和龙市",
+          "安图县",
+          "汪清县"
+        ]
+      }
+    ]
+  },
+  {
+    "name": "黑龙江省",
+    "city": [
+      {
+        "name": "哈尔滨市",
+        "area": [
+          "松北区",
+          "道里区",
+          "南岗区",
+          "平房区",
+          "香坊区",
+          "道外区",
+          "呼兰区",
+          "阿城区",
+          "双城市",
+          "尚志市",
+          "五常市",
+          "宾县",
+          "方正县",
+          "通河县",
+          "巴彦县",
+          "延寿县",
+          "木兰县",
+          "依兰县"
+        ]
+      },
+      {
+        "name": "齐齐哈尔市",
+        "area": [
+          "龙沙区",
+          "昂昂溪区",
+          "铁锋区",
+          "建华区",
+          "富拉尔基区",
+          "碾子山区",
+          "梅里斯达斡尔族区",
+          "讷河市",
+          "富裕县",
+          "拜泉县",
+          "甘南县",
+          "依安县",
+          "克山县",
+          "泰来县",
+          "克东县",
+          "龙江县"
+        ]
+      },
+      {
+        "name": "鹤岗市",
+        "area": [
+          "兴山区",
+          "工农区",
+          "南山区",
+          "兴安区",
+          "向阳区",
+          "东山区",
+          "萝北县",
+          "绥滨县"
+        ]
+      },
+      {
+        "name": "双鸭山",
+        "area": [
+          "尖山区",
+          "岭东区",
+          "四方台区",
+          "宝山区",
+          "集贤县",
+          "宝清县",
+          "友谊县",
+          "饶河县"
+        ]
+      },
+      {
+        "name": "鸡西市",
+        "area": [
+          "鸡冠区",
+          "恒山区",
+          "城子河区",
+          "滴道区",
+          "梨树区",
+          "麻山区",
+          "密山市",
+          "虎林市",
+          "鸡东县"
+        ]
+      },
+      {
+        "name": "大庆市",
+        "area": [
+          "萨尔图区",
+          "红岗区",
+          "龙凤区",
+          "让胡路区",
+          "大同区",
+          "林甸县",
+          "肇州县",
+          "肇源县",
+          "杜尔伯特蒙古族自治县"
+        ]
+      },
+      {
+        "name": "伊春市",
+        "area": [
+          "伊春区",
+          "带岭区",
+          "南岔区",
+          "金山屯区",
+          "西林区",
+          "美溪区",
+          "乌马河区",
+          "翠峦区",
+          "友好区",
+          "上甘岭区",
+          "五营区",
+          "红星区",
+          "新青区",
+          "汤旺河区",
+          "乌伊岭区",
+          "铁力市",
+          "嘉荫县"
+        ]
+      },
+      {
+        "name": "牡丹江市",
+        "area": [
+          "爱民区",
+          "东安区",
+          "阳明区",
+          "西安区",
+          "绥芬河市",
+          "宁安市",
+          "海林市",
+          "穆棱市",
+          "林口县",
+          "东宁县"
+        ]
+      },
+      {
+        "name": "佳木斯市",
+        "area": [
+          "向阳区",
+          "前进区",
+          "东风区",
+          "郊区",
+          "同江市",
+          "富锦市",
+          "桦川县",
+          "抚远县",
+          "桦南县",
+          "汤原县"
+        ]
+      },
+      {
+        "name": "七台河市",
+        "area": [
+          "桃山区",
+          "新兴区",
+          "茄子河区",
+          "勃利县"
+        ]
+      },
+      {
+        "name": "黑河市",
+        "area": [
+          "爱辉区",
+          "北安市",
+          "五大连池市",
+          "逊克县",
+          "嫩江县",
+          "孙吴县"
+        ]
+      },
+      {
+        "name": "绥化市",
+        "area": [
+          "北林区",
+          "安达市",
+          "肇东市",
+          "海伦市",
+          "绥棱县",
+          "兰西县",
+          "明水县",
+          "青冈县",
+          "庆安县",
+          "望奎县"
+        ]
+      },
+      {
+        "name": "大兴安岭地区",
+        "area": [
+          "呼玛县",
+          "塔河县",
+          "漠河县",
+          "大兴安岭辖区"
+        ]
+      }
+    ]
+  },
+  {
+    "name": "上海市",
+    "city": [
+      {
+        "name": "上海市",
+        "area": [
+          "黄浦区",
+          "卢湾区",
+          "徐汇区",
+          "长宁区",
+          "静安区",
+          "普陀区",
+          "闸北区",
+          "虹口区",
+          "杨浦区",
+          "宝山区",
+          "闵行区",
+          "嘉定区",
+          "松江区",
+          "金山区",
+          "青浦区",
+          "南汇区",
+          "奉贤区",
+          "浦东新区",
+          "崇明县"
+        ]
+      }
+    ]
+  },
+  {
+    "name": "江苏省",
+    "city": [
+      {
+        "name": "南京市",
+        "area": [
+          "玄武区",
+          "白下区",
+          "秦淮区",
+          "建邺区",
+          "鼓楼区",
+          "下关区",
+          "栖霞区",
+          "雨花台区",
+          "浦口区",
+          "江宁区",
+          "六合区",
+          "溧水县",
+          "高淳县"
+        ]
+      },
+      {
+        "name": "苏州市",
+        "area": [
+          "金阊区",
+          "平江区",
+          "沧浪区",
+          "虎丘区",
+          "吴中区",
+          "相城区",
+          "常熟市",
+          "张家港市",
+          "昆山市",
+          "吴江市",
+          "太仓市"
+        ]
+      },
+      {
+        "name": "无锡市",
+        "area": [
+          "崇安区",
+          "南长区",
+          "北塘区",
+          "滨湖区",
+          "锡山区",
+          "惠山区",
+          "江阴市",
+          "宜兴市"
+        ]
+      },
+      {
+        "name": "常州市",
+        "area": [
+          "钟楼区",
+          "天宁区",
+          "戚墅堰区",
+          "新北区",
+          "武进区",
+          "金坛市",
+          "溧阳市"
+        ]
+      },
+      {
+        "name": "镇江市",
+        "area": [
+          "京口区",
+          "润州区",
+          "丹徒区",
+          "丹阳市",
+          "扬中市",
+          "句容市"
+        ]
+      },
+      {
+        "name": "南通市",
+        "area": [
+          "崇川区",
+          "港闸区",
+          "通州市",
+          "如皋市",
+          "海门市",
+          "启东市",
+          "海安县",
+          "如东县"
+        ]
+      },
+      {
+        "name": "泰州市",
+        "area": [
+          "海陵区",
+          "高港区",
+          "姜堰市",
+          "泰兴市",
+          "靖江市",
+          "兴化市"
+        ]
+      },
+      {
+        "name": "扬州市",
+        "area": [
+          "广陵区",
+          "维扬区",
+          "邗江区",
+          "江都市",
+          "仪征市",
+          "高邮市",
+          "宝应县"
+        ]
+      },
+      {
+        "name": "盐城市",
+        "area": [
+          "亭湖区",
+          "盐都区",
+          "大丰市",
+          "东台市",
+          "建湖县",
+          "射阳县",
+          "阜宁县",
+          "滨海县",
+          "响水县"
+        ]
+      },
+      {
+        "name": "连云港市",
+        "area": [
+          "新浦区",
+          "海州区",
+          "连云区",
+          "东海县",
+          "灌云县",
+          "赣榆县",
+          "灌南县"
+        ]
+      },
+      {
+        "name": "徐州市",
+        "area": [
+          "云龙区",
+          "鼓楼区",
+          "九里区",
+          "泉山区",
+          "贾汪区",
+          "邳州市",
+          "新沂市",
+          "铜山县",
+          "睢宁县",
+          "沛县",
+          "丰县"
+        ]
+      },
+      {
+        "name": "淮安市",
+        "area": [
+          "清河区",
+          "清浦区",
+          "楚州区",
+          "淮阴区",
+          "涟水县",
+          "洪泽县",
+          "金湖县",
+          "盱眙县"
+        ]
+      },
+      {
+        "name": "宿迁市",
+        "area": [
+          "宿城区",
+          "宿豫区",
+          "沭阳县",
+          "泗阳县",
+          "泗洪县"
+        ]
+      }
+    ]
+  },
+  {
+    "name": "浙江省",
+    "city": [
+      {
+        "name": "杭州市",
+        "area": [
+          "拱墅区",
+          "西湖区",
+          "上城区",
+          "下城区",
+          "江干区",
+          "滨江区",
+          "余杭区",
+          "萧山区",
+          "建德市",
+          "富阳市",
+          "临安市",
+          "桐庐县",
+          "淳安县"
+        ]
+      },
+      {
+        "name": "宁波市",
+        "area": [
+          "海曙区",
+          "江东区",
+          "江北区",
+          "镇海区",
+          "北仑区",
+          "鄞州区",
+          "余姚市",
+          "慈溪市",
+          "奉化市",
+          "宁海县",
+          "象山县"
+        ]
+      },
+      {
+        "name": "温州市",
+        "area": [
+          "鹿城区",
+          "龙湾区",
+          "瓯海区",
+          "瑞安市",
+          "乐清市",
+          "永嘉县",
+          "洞头县",
+          "平阳县",
+          "苍南县",
+          "文成县",
+          "泰顺县"
+        ]
+      },
+      {
+        "name": "嘉兴市",
+        "area": [
+          "秀城区",
+          "秀洲区",
+          "海宁市",
+          "平湖市",
+          "桐乡市",
+          "嘉善县",
+          "海盐县"
+        ]
+      },
+      {
+        "name": "湖州市",
+        "area": [
+          "吴兴区",
+          "南浔区",
+          "长兴县",
+          "德清县",
+          "安吉县"
+        ]
+      },
+      {
+        "name": "绍兴市",
+        "area": [
+          "越城区",
+          "诸暨市",
+          "上虞市",
+          "嵊州市",
+          "绍兴县",
+          "新昌县"
+        ]
+      },
+      {
+        "name": "金华市",
+        "area": [
+          "婺城区",
+          "金东区",
+          "兰溪市",
+          "义乌市",
+          "东阳市",
+          "永康市",
+          "武义县",
+          "浦江县",
+          "磐安县"
+        ]
+      },
+      {
+        "name": "衢州市",
+        "area": [
+          "柯城区",
+          "衢江区",
+          "江山市",
+          "龙游县",
+          "常山县",
+          "开化县"
+        ]
+      },
+      {
+        "name": "舟山市",
+        "area": [
+          "定海区",
+          "普陀区",
+          "岱山县",
+          "嵊泗县"
+        ]
+      },
+      {
+        "name": "台州市",
+        "area": [
+          "椒江区",
+          "黄岩区",
+          "路桥区",
+          "临海市",
+          "温岭市",
+          "玉环县",
+          "天台县",
+          "仙居县",
+          "三门县"
+        ]
+      },
+      {
+        "name": "丽水市",
+        "area": [
+          "莲都区",
+          "龙泉市",
+          "缙云县",
+          "青田县",
+          "云和县",
+          "遂昌县",
+          "松阳县",
+          "庆元县",
+          "景宁畲族自治县"
+        ]
+      }
+    ]
+  },
+  {
+    "name": "安徽省",
+    "city": [
+      {
+        "name": "合肥市",
+        "area": [
+          "庐阳区",
+          "瑶海区",
+          "蜀山区",
+          "包河区",
+          "长丰县",
+          "肥东县",
+          "肥西县"
+        ]
+      },
+      {
+        "name": "芜湖市",
+        "area": [
+          "镜湖区",
+          "弋江区",
+          "鸠江区",
+          "三山区",
+          "芜湖县",
+          "南陵县",
+          "繁昌县"
+        ]
+      },
+      {
+        "name": "蚌埠市",
+        "area": [
+          "蚌山区",
+          "龙子湖区",
+          "禹会区",
+          "淮上区",
+          "怀远县",
+          "固镇县",
+          "五河县"
+        ]
+      },
+      {
+        "name": "淮南市",
+        "area": [
+          "田家庵区",
+          "大通区",
+          "谢家集区",
+          "八公山区",
+          "潘集区",
+          "凤台县"
+        ]
+      },
+      {
+        "name": "马鞍山市",
+        "area": [
+          "雨山区",
+          "花山区",
+          "金家庄区",
+          "当涂县"
+        ]
+      },
+      {
+        "name": "淮北市",
+        "area": [
+          "相山区",
+          "杜集区",
+          "烈山区",
+          "濉溪县"
+        ]
+      },
+      {
+        "name": "铜陵市",
+        "area": [
+          "铜官山区",
+          "狮子山区",
+          "郊区",
+          "铜陵县"
+        ]
+      },
+      {
+        "name": "安庆市",
+        "area": [
+          "迎江区",
+          "大观区",
+          "宜秀区",
+          "桐城市",
+          "宿松县",
+          "枞阳县",
+          "太湖县",
+          "怀宁县",
+          "岳西县",
+          "望江县",
+          "潜山县"
+        ]
+      },
+      {
+        "name": "黄山市",
+        "area": [
+          "屯溪区",
+          "黄山区",
+          "徽州区",
+          "休宁县",
+          "歙县",
+          "祁门县",
+          "黟县"
+        ]
+      },
+      {
+        "name": "滁州市",
+        "area": [
+          "琅琊区",
+          "南谯区",
+          "天长市",
+          "明光市",
+          "全椒县",
+          "来安县",
+          "定远县",
+          "凤阳县"
+        ]
+      },
+      {
+        "name": "阜阳市",
+        "area": [
+          "颍州区",
+          "颍东区",
+          "颍泉区",
+          "界首市",
+          "临泉县",
+          "颍上县",
+          "阜南县",
+          "太和县"
+        ]
+      },
+      {
+        "name": "宿州市",
+        "area": [
+          "埇桥区",
+          "萧县",
+          "泗县",
+          "砀山县",
+          "灵璧县"
+        ]
+      },
+      {
+        "name": "巢湖市",
+        "area": [
+          "居巢区",
+          "含山县",
+          "无为县",
+          "庐江县",
+          "和县"
+        ]
+      },
+      {
+        "name": "六安市",
+        "area": [
+          "金安区",
+          "裕安区",
+          "寿县",
+          "霍山县",
+          "霍邱县",
+          "舒城县",
+          "金寨县"
+        ]
+      },
+      {
+        "name": "亳州市",
+        "area": [
+          "谯城区",
+          "利辛县",
+          "涡阳县",
+          "蒙城县"
+        ]
+      },
+      {
+        "name": "池州市",
+        "area": [
+          "贵池区",
+          "东至县",
+          "石台县",
+          "青阳县"
+        ]
+      },
+      {
+        "name": "宣城市",
+        "area": [
+          "宣州区",
+          "宁国市",
+          "广德县",
+          "郎溪县",
+          "泾县",
+          "旌德县",
+          "绩溪县"
+        ]
+      }
+    ]
+  },
+  {
+    "name": "福建省",
+    "city": [
+      {
+        "name": "福州市",
+        "area": [
+          "鼓楼区",
+          "台江区",
+          "仓山区",
+          "马尾区",
+          "晋安区",
+          "福清市",
+          "长乐市",
+          "闽侯县",
+          "闽清县",
+          "永泰县",
+          "连江县",
+          "罗源县",
+          "平潭县"
+        ]
+      },
+      {
+        "name": "厦门市",
+        "area": [
+          "思明区",
+          "海沧区",
+          "湖里区",
+          "集美区",
+          "同安区",
+          "翔安区"
+        ]
+      },
+      {
+        "name": "莆田市",
+        "area": [
+          "城厢区",
+          "涵江区",
+          "荔城区",
+          "秀屿区",
+          "仙游县"
+        ]
+      },
+      {
+        "name": "三明市",
+        "area": [
+          "梅列区",
+          "三元区",
+          "永安市",
+          "明溪县",
+          "将乐县",
+          "大田县",
+          "宁化县",
+          "建宁县",
+          "沙县",
+          "尤溪县",
+          "清流县",
+          "泰宁县"
+        ]
+      },
+      {
+        "name": "泉州市",
+        "area": [
+          "鲤城区",
+          "丰泽区",
+          "洛江区",
+          "泉港区",
+          "石狮市",
+          "晋江市",
+          "南安市",
+          "惠安县",
+          "永春县",
+          "安溪县",
+          "德化县",
+          "金门县"
+        ]
+      },
+      {
+        "name": "漳州市",
+        "area": [
+          "芗城区",
+          "龙文区",
+          "龙海市",
+          "平和县",
+          "南靖县",
+          "诏安县",
+          "漳浦县",
+          "华安县",
+          "东山县",
+          "长泰县",
+          "云霄县"
+        ]
+      },
+      {
+        "name": "南平市",
+        "area": [
+          "延平区",
+          "建瓯市",
+          "邵武市",
+          "武夷山市",
+          "建阳市",
+          "松溪县",
+          "光泽县",
+          "顺昌县",
+          "浦城县",
+          "政和县"
+        ]
+      },
+      {
+        "name": "龙岩市",
+        "area": [
+          "新罗区",
+          "漳平市",
+          "长汀县",
+          "武平县",
+          "上杭县",
+          "永定县",
+          "连城县"
+        ]
+      },
+      {
+        "name": "宁德市",
+        "area": [
+          "蕉城区",
+          "福安市",
+          "福鼎市",
+          "寿宁县",
+          "霞浦县",
+          "柘荣县",
+          "屏南县",
+          "古田县",
+          "周宁县"
+        ]
+      }
+    ]
+  },
+  {
+    "name": "江西省",
+    "city": [
+      {
+        "name": "南昌市",
+        "area": [
+          "东湖区",
+          "西湖区",
+          "青云谱区",
+          "湾里区",
+          "青山湖区",
+          "新建县",
+          "南昌县",
+          "进贤县",
+          "安义县"
+        ]
+      },
+      {
+        "name": "景德镇市",
+        "area": [
+          "珠山区",
+          "昌江区",
+          "乐平市",
+          "浮梁县"
+        ]
+      },
+      {
+        "name": "萍乡市",
+        "area": [
+          "安源区",
+          "湘东区",
+          "莲花县",
+          "上栗县",
+          "芦溪县"
+        ]
+      },
+      {
+        "name": "九江市",
+        "area": [
+          "浔阳区",
+          "庐山区",
+          "瑞昌市",
+          "九江县",
+          "星子县",
+          "武宁县",
+          "彭泽县",
+          "永修县",
+          "修水县",
+          "湖口县",
+          "德安县",
+          "都昌县"
+        ]
+      },
+      {
+        "name": "新余市",
+        "area": [
+          "渝水区",
+          "分宜县"
+        ]
+      },
+      {
+        "name": "鹰潭市",
+        "area": [
+          "月湖区",
+          "贵溪市",
+          "余江县"
+        ]
+      },
+      {
+        "name": "赣州市",
+        "area": [
+          "章贡区",
+          "瑞金市",
+          "南康市",
+          "石城县",
+          "安远县",
+          "赣县",
+          "宁都县",
+          "寻乌县",
+          "兴国县",
+          "定南县",
+          "上犹县",
+          "于都县",
+          "龙南县",
+          "崇义县",
+          "信丰县",
+          "全南县",
+          "大余县",
+          "会昌县"
+        ]
+      },
+      {
+        "name": "吉安市",
+        "area": [
+          "吉州区",
+          "青原区",
+          "井冈山市",
+          "吉安县",
+          "永丰县",
+          "永新县",
+          "新干县",
+          "泰和县",
+          "峡江县",
+          "遂川县",
+          "安福县",
+          "吉水县",
+          "万安县"
+        ]
+      },
+      {
+        "name": "宜春市",
+        "area": [
+          "袁州区",
+          "丰城市",
+          "樟树市",
+          "高安市",
+          "铜鼓县",
+          "靖安县",
+          "宜丰县",
+          "奉新县",
+          "万载县",
+          "上高县"
+        ]
+      },
+      {
+        "name": "抚州市",
+        "area": [
+          "临川区",
+          "南丰县",
+          "乐安县",
+          "金溪县",
+          "南城县",
+          "东乡县",
+          "资溪县",
+          "宜黄县",
+          "广昌县",
+          "黎川县",
+          "崇仁县"
+        ]
+      },
+      {
+        "name": "上饶市",
+        "area": [
+          "信州区",
+          "德兴市",
+          "上饶县",
+          "广丰县",
+          "鄱阳县",
+          "婺源县",
+          "铅山县",
+          "余干县",
+          "横峰县",
+          "弋阳县",
+          "玉山县",
+          "万年县"
+        ]
+      }
+    ]
+  },
+  {
+    "name": "山东省",
+    "city": [
+      {
+        "name": "济南市",
+        "area": [
+          "市中区",
+          "历下区",
+          "天桥区",
+          "槐荫区",
+          "历城区",
+          "长清区",
+          "章丘市",
+          "平阴县",
+          "济阳县",
+          "商河县"
+        ]
+      },
+      {
+        "name": "青岛市",
+        "area": [
+          "市南区",
+          "市北区",
+          "城阳区",
+          "四方区",
+          "李沧区",
+          "黄岛区",
+          "崂山区",
+          "胶南市",
+          "胶州市",
+          "平度市",
+          "莱西市",
+          "即墨市"
+        ]
+      },
+      {
+        "name": "淄博市",
+        "area": [
+          "张店区",
+          "临淄区",
+          "淄川区",
+          "博山区",
+          "周村区",
+          "桓台县",
+          "高青县",
+          "沂源县"
+        ]
+      },
+      {
+        "name": "枣庄市",
+        "area": [
+          "市中区",
+          "山亭区",
+          "峄城区",
+          "台儿庄区",
+          "薛城区",
+          "滕州市"
+        ]
+      },
+      {
+        "name": "东营市",
+        "area": [
+          "东营区",
+          "河口区",
+          "垦利县",
+          "广饶县",
+          "利津县"
+        ]
+      },
+      {
+        "name": "烟台市",
+        "area": [
+          "芝罘区",
+          "福山区",
+          "牟平区",
+          "莱山区",
+          "龙口市",
+          "莱阳市",
+          "莱州市",
+          "招远市",
+          "蓬莱市",
+          "栖霞市",
+          "海阳市",
+          "长岛县"
+        ]
+      },
+      {
+        "name": "潍坊市",
+        "area": [
+          "潍城区",
+          "寒亭区",
+          "坊子区",
+          "奎文区",
+          "青州市",
+          "诸城市",
+          "寿光市",
+          "安丘市",
+          "高密市",
+          "昌邑市",
+          "昌乐县",
+          "临朐县"
+        ]
+      },
+      {
+        "name": "济宁市",
+        "area": [
+          "市中区",
+          "任城区",
+          "曲阜市",
+          "兖州市",
+          "邹城市",
+          "鱼台县",
+          "金乡县",
+          "嘉祥县",
+          "微山县",
+          "汶上县",
+          "泗水县",
+          "梁山县"
+        ]
+      },
+      {
+        "name": "泰安市",
+        "area": [
+          "泰山区",
+          "岱岳区",
+          "新泰市",
+          "肥城市",
+          "宁阳县",
+          "东平县"
+        ]
+      },
+      {
+        "name": "威海市",
+        "area": [
+          "环翠区",
+          "乳山市",
+          "文登市",
+          "荣成市"
+        ]
+      },
+      {
+        "name": "日照市",
+        "area": [
+          "东港区",
+          "岚山区",
+          "五莲县",
+          "莒县"
+        ]
+      },
+      {
+        "name": "莱芜市",
+        "area": [
+          "莱城区",
+          "钢城区"
+        ]
+      },
+      {
+        "name": "临沂市",
+        "area": [
+          "兰山区",
+          "罗庄区",
+          "河东区",
+          "沂南县",
+          "郯城县",
+          "沂水县",
+          "苍山县",
+          "费县",
+          "平邑县",
+          "莒南县",
+          "蒙阴县",
+          "临沭县"
+        ]
+      },
+      {
+        "name": "德州市",
+        "area": [
+          "德城区",
+          "乐陵市",
+          "禹城市",
+          "陵县",
+          "宁津县",
+          "齐河县",
+          "武城县",
+          "庆云县",
+          "平原县",
+          "夏津县",
+          "临邑县"
+        ]
+      },
+      {
+        "name": "聊城市",
+        "area": [
+          "东昌府区",
+          "临清市",
+          "高唐县",
+          "阳谷县",
+          "茌平县",
+          "莘县",
+          "东阿县",
+          "冠县"
+        ]
+      },
+      {
+        "name": "滨州市",
+        "area": [
+          "滨城区",
+          "邹平县",
+          "沾化县",
+          "惠民县",
+          "博兴县",
+          "阳信县",
+          "无棣县"
+        ]
+      },
+      {
+        "name": "菏泽市",
+        "area": [
+          "牡丹区",
+          "鄄城县",
+          "单县",
+          "郓城县",
+          "曹县",
+          "定陶县",
+          "巨野县",
+          "东明县",
+          "成武县"
+        ]
+      }
+    ]
+  },
+  {
+    "name": "河南省",
+    "city": [
+      {
+        "name": "郑州市",
+        "area": [
+          "中原区",
+          "金水区",
+          "二七区",
+          "管城回族区",
+          "上街区",
+          "惠济区",
+          "巩义市",
+          "新郑市",
+          "新密市",
+          "登封市",
+          "荥阳市",
+          "中牟县"
+        ]
+      },
+      {
+        "name": "开封市",
+        "area": [
+          "鼓楼区",
+          "龙亭区",
+          "顺河回族区",
+          "禹王台区",
+          "金明区",
+          "开封县",
+          "尉氏县",
+          "兰考县",
+          "杞县",
+          "通许县"
+        ]
+      },
+      {
+        "name": "洛阳市",
+        "area": [
+          "西工区",
+          "老城区",
+          "涧西区",
+          "瀍河回族区",
+          "洛龙区",
+          "吉利区",
+          "偃师市",
+          "孟津县",
+          "汝阳县",
+          "伊川县",
+          "洛宁县",
+          "嵩县",
+          "宜阳县",
+          "新安县",
+          "栾川县"
+        ]
+      },
+      {
+        "name": "平顶山市",
+        "area": [
+          "新华区",
+          "卫东区",
+          "湛河区",
+          "石龙区",
+          "汝州市",
+          "舞钢市",
+          "宝丰县",
+          "叶县",
+          "郏县",
+          "鲁山县"
+        ]
+      },
+      {
+        "name": "安阳市",
+        "area": [
+          "北关区",
+          "文峰区",
+          "殷都区",
+          "龙安区",
+          "林州市",
+          "安阳县",
+          "滑县",
+          "内黄县",
+          "汤阴县"
+        ]
+      },
+      {
+        "name": "鹤壁市",
+        "area": [
+          "淇滨区",
+          "山城区",
+          "鹤山区",
+          "浚县",
+          "淇县"
+        ]
+      },
+      {
+        "name": "新乡市",
+        "area": [
+          "卫滨区",
+          "红旗区",
+          "凤泉区",
+          "牧野区",
+          "卫辉市",
+          "辉县市",
+          "新乡县",
+          "获嘉县",
+          "原阳县",
+          "长垣县",
+          "封丘县",
+          "延津县"
+        ]
+      },
+      {
+        "name": "焦作市",
+        "area": [
+          "解放区",
+          "中站区",
+          "马村区",
+          "山阳区",
+          "沁阳市",
+          "孟州市",
+          "修武县",
+          "温县",
+          "武陟县",
+          "博爱县"
+        ]
+      },
+      {
+        "name": "濮阳市",
+        "area": [
+          "华龙区",
+          "濮阳县",
+          "南乐县",
+          "台前县",
+          "清丰县",
+          "范县"
+        ]
+      },
+      {
+        "name": "许昌市",
+        "area": [
+          "魏都区",
+          "禹州市",
+          "长葛市",
+          "许昌县",
+          "鄢陵县",
+          "襄城县"
+        ]
+      },
+      {
+        "name": "漯河市",
+        "area": [
+          "源汇区",
+          "郾城区",
+          "召陵区",
+          "临颍县",
+          "舞阳县"
+        ]
+      },
+      {
+        "name": "三门峡市",
+        "area": [
+          "湖滨区",
+          "义马市",
+          "灵宝市",
+          "渑池县",
+          "卢氏县",
+          "陕县"
+        ]
+      },
+      {
+        "name": "南阳市",
+        "area": [
+          "卧龙区",
+          "宛城区",
+          "邓州市",
+          "桐柏县",
+          "方城县",
+          "淅川县",
+          "镇平县",
+          "唐河县",
+          "南召县",
+          "内乡县",
+          "新野县",
+          "社旗县",
+          "西峡县"
+        ]
+      },
+      {
+        "name": "商丘市",
+        "area": [
+          "梁园区",
+          "睢阳区",
+          "永城市",
+          "宁陵县",
+          "虞城县",
+          "民权县",
+          "夏邑县",
+          "柘城县",
+          "睢县"
+        ]
+      },
+      {
+        "name": "信阳市",
+        "area": [
+          "浉河区",
+          "平桥区",
+          "潢川县",
+          "淮滨县",
+          "息县",
+          "新县",
+          "商城县",
+          "固始县",
+          "罗山县",
+          "光山县"
+        ]
+      },
+      {
+        "name": "周口市",
+        "area": [
+          "川汇区",
+          "项城市",
+          "商水县",
+          "淮阳县",
+          "太康县",
+          "鹿邑县",
+          "西华县",
+          "扶沟县",
+          "沈丘县",
+          "郸城县"
+        ]
+      },
+      {
+        "name": "驻马店市",
+        "area": [
+          "驿城区",
+          "确山县",
+          "新蔡县",
+          "上蔡县",
+          "西平县",
+          "泌阳县",
+          "平舆县",
+          "汝南县",
+          "遂平县",
+          "正阳县"
+        ]
+      },
+      {
+        "name": "焦作市",
+        "area": [
+          "济源市"
+        ]
+      }
+    ]
+  },
+  {
+    "name": "湖北省",
+    "city": [
+      {
+        "name": "武汉市",
+        "area": [
+          "江岸区",
+          "武昌区",
+          "江汉区",
+          "硚口区",
+          "汉阳区",
+          "青山区",
+          "洪山区",
+          "东西湖区",
+          "汉南区",
+          "蔡甸区",
+          "江夏区",
+          "黄陂区",
+          "新洲区"
+        ]
+      },
+      {
+        "name": "黄石市",
+        "area": [
+          "黄石港区",
+          "西塞山区",
+          "下陆区",
+          "铁山区",
+          "大冶市",
+          "阳新县"
+        ]
+      },
+      {
+        "name": "十堰市",
+        "area": [
+          "张湾区",
+          "茅箭区",
+          "丹江口市",
+          "郧县",
+          "竹山县",
+          "房县",
+          "郧西县",
+          "竹溪县"
+        ]
+      },
+      {
+        "name": "荆州市",
+        "area": [
+          "沙市区",
+          "荆州区",
+          "洪湖市",
+          "石首市",
+          "松滋市",
+          "监利县",
+          "公安县",
+          "江陵县"
+        ]
+      },
+      {
+        "name": "宜昌市",
+        "area": [
+          "西陵区",
+          "伍家岗区",
+          "点军区",
+          "猇亭区",
+          "夷陵区",
+          "宜都市",
+          "当阳市",
+          "枝江市",
+          "秭归县",
+          "远安县",
+          "兴山县",
+          "五峰土家族自治县",
+          "长阳土家族自治县"
+        ]
+      },
+      {
+        "name": "襄樊市",
+        "area": [
+          "襄城区",
+          "樊城区",
+          "襄阳区",
+          "老河口市",
+          "枣阳市",
+          "宜城市",
+          "南漳县",
+          "谷城县",
+          "保康县"
+        ]
+      },
+      {
+        "name": "鄂州市",
+        "area": [
+          "鄂城区",
+          "华容区",
+          "梁子湖区"
+        ]
+      },
+      {
+        "name": "荆门市",
+        "area": [
+          "东宝区",
+          "掇刀区",
+          "钟祥市",
+          "京山县",
+          "沙洋县"
+        ]
+      },
+      {
+        "name": "孝感市",
+        "area": [
+          "孝南区",
+          "应城市",
+          "安陆市",
+          "汉川市",
+          "云梦县",
+          "大悟县",
+          "孝昌县"
+        ]
+      },
+      {
+        "name": "黄冈市",
+        "area": [
+          "黄州区",
+          "麻城市",
+          "武穴市",
+          "红安县",
+          "罗田县",
+          "浠水县",
+          "蕲春县",
+          "黄梅县",
+          "英山县",
+          "团风县"
+        ]
+      },
+      {
+        "name": "咸宁市",
+        "area": [
+          "咸安区",
+          "赤壁市",
+          "嘉鱼县",
+          "通山县",
+          "崇阳县",
+          "通城县"
+        ]
+      },
+      {
+        "name": "随州市",
+        "area": [
+          "曾都区",
+          "广水市"
+        ]
+      },
+      {
+        "name": "恩施土家族苗族自治州",
+        "area": [
+          "恩施市",
+          "利川市",
+          "建始县",
+          "来凤县",
+          "巴东县",
+          "鹤峰县",
+          "宣恩县",
+          "咸丰县"
+        ]
+      },
+      {
+        "name": "仙桃市",
+        "area": [
+          "仙桃"
+        ]
+      },
+      {
+        "name": "天门市",
+        "area": [
+          "天门"
+        ]
+      },
+      {
+        "name": "潜江市",
+        "area": [
+          "潜江"
+        ]
+      },
+      {
+        "name": "神农架林区",
+        "area": [
+          "神农架林区"
+        ]
+      }
+    ]
+  },
+  {
+    "name": "湖南省",
+    "city": [
+      {
+        "name": "长沙市",
+        "area": [
+          "岳麓区",
+          "芙蓉区",
+          "天心区",
+          "开福区",
+          "雨花区",
+          "浏阳市",
+          "长沙县",
+          "望城县",
+          "宁乡县"
+        ]
+      },
+      {
+        "name": "株洲市",
+        "area": [
+          "天元区",
+          "荷塘区",
+          "芦淞区",
+          "石峰区",
+          "醴陵市",
+          "株洲县",
+          "炎陵县",
+          "茶陵县",
+          "攸县"
+        ]
+      },
+      {
+        "name": "湘潭市",
+        "area": [
+          "岳塘区",
+          "雨湖区",
+          "湘乡市",
+          "韶山市",
+          "湘潭县"
+        ]
+      },
+      {
+        "name": "衡阳市",
+        "area": [
+          "雁峰区",
+          "珠晖区",
+          "石鼓区",
+          "蒸湘区",
+          "南岳区",
+          "耒阳市",
+          "常宁市",
+          "衡阳县",
+          "衡东县",
+          "衡山县",
+          "衡南县",
+          "祁东县"
+        ]
+      },
+      {
+        "name": "邵阳市",
+        "area": [
+          "双清区",
+          "大祥区",
+          "北塔区",
+          "武冈市",
+          "邵东县",
+          "洞口县",
+          "新邵县",
+          "绥宁县",
+          "新宁县",
+          "邵阳县",
+          "隆回县",
+          "城步苗族自治县"
+        ]
+      },
+      {
+        "name": "岳阳市",
+        "area": [
+          "岳阳楼区",
+          "云溪区",
+          "君山区",
+          "临湘市",
+          "汨罗市",
+          "岳阳县",
+          "湘阴县",
+          "平江县",
+          "华容县"
+        ]
+      },
+      {
+        "name": "常德市",
+        "area": [
+          "武陵区",
+          "鼎城区",
+          "津市市",
+          "澧县",
+          "临澧县",
+          "桃源县",
+          "汉寿县",
+          "安乡县",
+          "石门县"
+        ]
+      },
+      {
+        "name": "张家界市",
+        "area": [
+          "永定区",
+          "武陵源区",
+          "慈利县",
+          "桑植县"
+        ]
+      },
+      {
+        "name": "益阳市",
+        "area": [
+          "赫山区",
+          "资阳区",
+          "沅江市",
+          "桃江县",
+          "南县",
+          "安化县"
+        ]
+      },
+      {
+        "name": "郴州市",
+        "area": [
+          "北湖区",
+          "苏仙区",
+          "资兴市",
+          "宜章县",
+          "汝城县",
+          "安仁县",
+          "嘉禾县",
+          "临武县",
+          "桂东县",
+          "永兴县",
+          "桂阳县"
+        ]
+      },
+      {
+        "name": "永州市",
+        "area": [
+          "冷水滩区",
+          "零陵区",
+          "祁阳县",
+          "蓝山县",
+          "宁远县",
+          "新田县",
+          "东安县",
+          "江永县",
+          "道县",
+          "双牌县",
+          "江华瑶族自治县"
+        ]
+      },
+      {
+        "name": "怀化市",
+        "area": [
+          "鹤城区",
+          "洪江市",
+          "会同县",
+          "沅陵县",
+          "辰溪县",
+          "溆浦县",
+          "中方县",
+          "新晃侗族自治县",
+          "芷江侗族自治县",
+          "通道侗族自治县",
+          "靖州苗族侗族自治县",
+          "麻阳苗族自治县"
+        ]
+      },
+      {
+        "name": "娄底市",
+        "area": [
+          "娄星区",
+          "冷水江市",
+          "涟源市",
+          "新化县",
+          "双峰县"
+        ]
+      },
+      {
+        "name": "湘西土家族苗族自治州",
+        "area": [
+          "吉首市",
+          "古丈县",
+          "龙山县",
+          "永顺县",
+          "凤凰县",
+          "泸溪县",
+          "保靖县",
+          "花垣县"
+        ]
+      }
+    ]
+  },
+  {
+    "name": "广东省",
+    "city": [
+      {
+        "name": "广州市",
+        "area": [
+          "越秀区",
+          "荔湾区",
+          "海珠区",
+          "天河区",
+          "白云区",
+          "黄埔区",
+          "番禺区",
+          "花都区",
+          "南沙区",
+          "萝岗区",
+          "增城市",
+          "从化市"
+        ]
+      },
+      {
+        "name": "深圳市",
+        "area": [
+          "福田区",
+          "罗湖区",
+          "南山区",
+          "宝安区",
+          "龙岗区",
+          "盐田区"
+        ]
+      },
+      {
+        "name": "东莞市",
+        "area": [
+          "莞城",
+          "常平",
+          "塘厦",
+          "塘厦",
+          "塘厦"
+        ]
+      },
+      {
+        "name": "中山市",
+        "area": [
+          "中山"
+        ]
+      },
+      {
+        "name": "潮州市",
+        "area": [
+          "湘桥区",
+          "潮安县",
+          "饶平县"
+        ]
+      },
+      {
+        "name": "揭阳市",
+        "area": [
+          "榕城区",
+          "揭东县",
+          "揭西县",
+          "惠来县",
+          "普宁市"
+        ]
+      },
+      {
+        "name": "云浮市",
+        "area": [
+          "云城区",
+          "新兴县",
+          "郁南县",
+          "云安县",
+          "罗定市"
+        ]
+      },
+      {
+        "name": "珠海市",
+        "area": [
+          "香洲区",
+          "斗门区",
+          "金湾区"
+        ]
+      },
+      {
+        "name": "汕头市",
+        "area": [
+          "金平区",
+          "濠江区",
+          "龙湖区",
+          "潮阳区",
+          "潮南区",
+          "澄海区",
+          "南澳县"
+        ]
+      },
+      {
+        "name": "韶关市",
+        "area": [
+          "浈江区",
+          "武江区",
+          "曲江区",
+          "乐昌市",
+          "南雄市",
+          "始兴县",
+          "仁化县",
+          "翁源县",
+          "新丰县",
+          "乳源瑶族自治县"
+        ]
+      },
+      {
+        "name": "佛山市",
+        "area": [
+          "禅城区",
+          "南海区",
+          "顺德区",
+          "三水区",
+          "高明区"
+        ]
+      },
+      {
+        "name": "江门市",
+        "area": [
+          "蓬江区",
+          "江海区",
+          "新会区",
+          "恩平市",
+          "台山市",
+          "开平市",
+          "鹤山市"
+        ]
+      },
+      {
+        "name": "湛江市",
+        "area": [
+          "赤坎区",
+          "霞山区",
+          "坡头区",
+          "麻章区",
+          "吴川市",
+          "廉江市",
+          "雷州市",
+          "遂溪县",
+          "徐闻县"
+        ]
+      },
+      {
+        "name": "茂名市",
+        "area": [
+          "茂南区",
+          "茂港区",
+          "化州市",
+          "信宜市",
+          "高州市",
+          "电白县"
+        ]
+      },
+      {
+        "name": "肇庆市",
+        "area": [
+          "端州区",
+          "鼎湖区",
+          "高要市",
+          "四会市",
+          "广宁县",
+          "怀集县",
+          "封开县",
+          "德庆县"
+        ]
+      },
+      {
+        "name": "惠州市",
+        "area": [
+          "惠城区",
+          "惠阳区",
+          "博罗县",
+          "惠东县",
+          "龙门县"
+        ]
+      },
+      {
+        "name": "梅州市",
+        "area": [
+          "梅江区",
+          "兴宁市",
+          "梅县",
+          "大埔县",
+          "丰顺县",
+          "五华县",
+          "平远县",
+          "蕉岭县"
+        ]
+      },
+      {
+        "name": "汕尾市",
+        "area": [
+          "城区",
+          "陆丰市",
+          "海丰县",
+          "陆河县"
+        ]
+      },
+      {
+        "name": "河源市",
+        "area": [
+          "源城区",
+          "紫金县",
+          "龙川县",
+          "连平县",
+          "和平县",
+          "东源县"
+        ]
+      },
+      {
+        "name": "阳江市",
+        "area": [
+          "江城区",
+          "阳春市",
+          "阳西县",
+          "阳东县"
+        ]
+      },
+      {
+        "name": "清远市",
+        "area": [
+          "清城区",
+          "英德市",
+          "连州市",
+          "佛冈县",
+          "阳山县",
+          "清新县",
+          "连山壮族瑶族自治县",
+          "连南瑶族自治县"
+        ]
+      }
+    ]
+  },
+  {
+    "name": "广西",
+    "city": [
+      {
+        "name": "南宁市",
+        "area": [
+          "青秀区",
+          "兴宁区",
+          "西乡塘区",
+          "良庆区",
+          "江南区",
+          "邕宁区",
+          "武鸣县",
+          "隆安县",
+          "马山县",
+          "上林县",
+          "宾阳县",
+          "横县"
+        ]
+      },
+      {
+        "name": "柳州市",
+        "area": [
+          "城中区",
+          "鱼峰区",
+          "柳北区",
+          "柳南区",
+          "柳江县",
+          "柳城县",
+          "鹿寨县",
+          "融安县",
+          "融水苗族自治县",
+          "三江侗族自治县"
+        ]
+      },
+      {
+        "name": "桂林市",
+        "area": [
+          "象山区",
+          "秀峰区",
+          "叠彩区",
+          "七星区",
+          "雁山区",
+          "阳朔县",
+          "临桂县",
+          "灵川县",
+          "全州县",
+          "平乐县",
+          "兴安县",
+          "灌阳县",
+          "荔浦县",
+          "资源县",
+          "永福县",
+          "龙胜各族自治县",
+          "恭城瑶族自治县"
+        ]
+      },
+      {
+        "name": "梧州市",
+        "area": [
+          "万秀区",
+          "蝶山区",
+          "长洲区",
+          "岑溪市",
+          "苍梧县",
+          "藤县",
+          "蒙山县"
+        ]
+      },
+      {
+        "name": "北海市",
+        "area": [
+          "海城区",
+          "银海区",
+          "铁山港区",
+          "合浦县"
+        ]
+      },
+      {
+        "name": "防城港市",
+        "area": [
+          "港口区",
+          "防城区",
+          "东兴市",
+          "上思县"
+        ]
+      },
+      {
+        "name": "钦州市",
+        "area": [
+          "钦南区",
+          "钦北区",
+          "灵山县",
+          "浦北县"
+        ]
+      },
+      {
+        "name": "贵港市",
+        "area": [
+          "港北区",
+          "港南区",
+          "覃塘区",
+          "桂平市",
+          "平南县"
+        ]
+      },
+      {
+        "name": "玉林市",
+        "area": [
+          "玉州区",
+          "北流市",
+          "容县",
+          "陆川县",
+          "博白县",
+          "兴业县"
+        ]
+      },
+      {
+        "name": "百色市",
+        "area": [
+          "右江区",
+          "凌云县",
+          "平果县",
+          "西林县",
+          "乐业县",
+          "德保县",
+          "田林县",
+          "田阳县",
+          "靖西县",
+          "田东县",
+          "那坡县",
+          "隆林各族自治县"
+        ]
+      },
+      {
+        "name": "贺州市",
+        "area": [
+          "八步区",
+          "钟山县",
+          "昭平县",
+          "富川瑶族自治县"
+        ]
+      },
+      {
+        "name": "河池市",
+        "area": [
+          "金城江区",
+          "宜州市",
+          "天峨县",
+          "凤山县",
+          "南丹县",
+          "东兰县",
+          "都安瑶族自治县",
+          "罗城仫佬族自治县",
+          "巴马瑶族自治县",
+          "环江毛南族自治县",
+          "大化瑶族自治县"
+        ]
+      },
+      {
+        "name": "来宾市",
+        "area": [
+          "兴宾区",
+          "合山市",
+          "象州县",
+          "武宣县",
+          "忻城县",
+          "金秀瑶族自治县"
+        ]
+      },
+      {
+        "name": "崇左市",
+        "area": [
+          "江州区",
+          "凭祥市",
+          "宁明县",
+          "扶绥县",
+          "龙州县",
+          "大新县",
+          "天等县"
+        ]
+      }
+    ]
+  },
+  {
+    "name": "海南省",
+    "city": [
+      {
+        "name": "海口市",
+        "area": [
+          "龙华区",
+          "秀英区",
+          "琼山区",
+          "美兰区"
+        ]
+      },
+      {
+        "name": "三亚市",
+        "area": [
+          "三亚市"
+        ]
+      },
+      {
+        "name": "五指山市",
+        "area": [
+          "五指山"
+        ]
+      },
+      {
+        "name": "琼海市",
+        "area": [
+          "琼海"
+        ]
+      },
+      {
+        "name": "儋州市",
+        "area": [
+          "儋州"
+        ]
+      },
+      {
+        "name": "文昌市",
+        "area": [
+          "文昌"
+        ]
+      },
+      {
+        "name": "万宁市",
+        "area": [
+          "万宁"
+        ]
+      },
+      {
+        "name": "东方市",
+        "area": [
+          "东方"
+        ]
+      },
+      {
+        "name": "澄迈县",
+        "area": [
+          "澄迈县"
+        ]
+      },
+      {
+        "name": "定安县",
+        "area": [
+          "定安县"
+        ]
+      },
+      {
+        "name": "屯昌县",
+        "area": [
+          "屯昌县"
+        ]
+      },
+      {
+        "name": "临高县",
+        "area": [
+          "临高县"
+        ]
+      },
+      {
+        "name": "白沙黎族自治县",
+        "area": [
+          "白沙黎族自治县"
+        ]
+      },
+      {
+        "name": "昌江黎族自治县",
+        "area": [
+          "昌江黎族自治县"
+        ]
+      },
+      {
+        "name": "乐东黎族自治县",
+        "area": [
+          "乐东黎族自治县"
+        ]
+      },
+      {
+        "name": "陵水黎族自治县",
+        "area": [
+          "陵水黎族自治县"
+        ]
+      },
+      {
+        "name": "保亭黎族苗族自治县",
+        "area": [
+          "保亭黎族苗族自治县"
+        ]
+      },
+      {
+        "name": "琼中黎族苗族自治县",
+        "area": [
+          "琼中黎族苗族自治县"
+        ]
+      }
+    ]
+  },
+  {
+    "name": "重庆市",
+    "city": [
+      {
+        "name": "重庆市",
+        "area": [
+          "渝中区",
+          "大渡口区",
+          "江北区",
+          "南岸区",
+          "北碚区",
+          "渝北区",
+          "巴南区",
+          "长寿区",
+          "双桥区",
+          "沙坪坝区",
+          "万盛区",
+          "万州区",
+          "涪陵区",
+          "黔江区",
+          "永川区",
+          "合川区",
+          "江津区",
+          "九龙坡区",
+          "南川区",
+          "綦江县",
+          "潼南县",
+          "荣昌县",
+          "璧山县",
+          "大足县",
+          "铜梁县",
+          "梁平县",
+          "开县",
+          "忠县",
+          "城口县",
+          "垫江县",
+          "武隆县",
+          "丰都县",
+          "奉节县",
+          "云阳县",
+          "巫溪县",
+          "巫山县",
+          "石柱土家族自治县",
+          "秀山土家族苗族自治县",
+          "酉阳土家族苗族自治县",
+          "彭水苗族土家族自治县"
+        ]
+      }
+    ]
+  },
+  {
+    "name": "四川省",
+    "city": [
+      {
+        "name": "成都市",
+        "area": [
+          "青羊区",
+          "锦江区",
+          "金牛区",
+          "武侯区",
+          "成华区",
+          "龙泉驿区",
+          "青白江区",
+          "新都区",
+          "温江区",
+          "都江堰市",
+          "彭州市",
+          "邛崃市",
+          "崇州市",
+          "金堂县",
+          "郫县",
+          "新津县",
+          "双流县",
+          "蒲江县",
+          "大邑县"
+        ]
+      },
+      {
+        "name": "自贡市",
+        "area": [
+          "大安区",
+          "自流井区",
+          "贡井区",
+          "沿滩区",
+          "荣县",
+          "富顺县"
+        ]
+      },
+      {
+        "name": "攀枝花市",
+        "area": [
+          "仁和区",
+          "米易县",
+          "盐边县",
+          "东区",
+          "西区"
+        ]
+      },
+      {
+        "name": "泸州市",
+        "area": [
+          "江阳区",
+          "纳溪区",
+          "龙马潭区",
+          "泸县",
+          "合江县",
+          "叙永县",
+          "古蔺县"
+        ]
+      },
+      {
+        "name": "德阳市",
+        "area": [
+          "旌阳区",
+          "广汉市",
+          "什邡市",
+          "绵竹市",
+          "罗江县",
+          "中江县"
+        ]
+      },
+      {
+        "name": "绵阳市",
+        "area": [
+          "涪城区",
+          "游仙区",
+          "江油市",
+          "盐亭县",
+          "三台县",
+          "平武县",
+          "安县",
+          "梓潼县",
+          "北川羌族自治县"
+        ]
+      },
+      {
+        "name": "广元市",
+        "area": [
+          "元坝区",
+          "朝天区",
+          "青川县",
+          "旺苍县",
+          "剑阁县",
+          "苍溪县",
+          "市中区"
+        ]
+      },
+      {
+        "name": "遂宁市",
+        "area": [
+          "船山区",
+          "安居区",
+          "射洪县",
+          "蓬溪县",
+          "大英县"
+        ]
+      },
+      {
+        "name": "内江市",
+        "area": [
+          "市中区",
+          "东兴区",
+          "资中县",
+          "隆昌县",
+          "威远县"
+        ]
+      },
+      {
+        "name": "乐山市",
+        "area": [
+          "市中区",
+          "五通桥区",
+          "沙湾区",
+          "金口河区",
+          "峨眉山市",
+          "夹江县",
+          "井研县",
+          "犍为县",
+          "沐川县",
+          "马边彝族自治县",
+          "峨边彝族自治县"
+        ]
+      },
+      {
+        "name": "南充",
+        "area": [
+          "顺庆区",
+          "高坪区",
+          "嘉陵区",
+          "阆中市",
+          "营山县",
+          "蓬安县",
+          "仪陇县",
+          "南部县",
+          "西充县"
+        ]
+      },
+      {
+        "name": "眉山市",
+        "area": [
+          "东坡区",
+          "仁寿县",
+          "彭山县",
+          "洪雅县",
+          "丹棱县",
+          "青神县"
+        ]
+      },
+      {
+        "name": "宜宾市",
+        "area": [
+          "翠屏区",
+          "宜宾县",
+          "兴文县",
+          "南溪县",
+          "珙县",
+          "长宁县",
+          "高县",
+          "江安县",
+          "筠连县",
+          "屏山县"
+        ]
+      },
+      {
+        "name": "广安市",
+        "area": [
+          "广安区",
+          "华蓥市",
+          "岳池县",
+          "邻水县",
+          "武胜县"
+        ]
+      },
+      {
+        "name": "达州市",
+        "area": [
+          "通川区",
+          "万源市",
+          "达县",
+          "渠县",
+          "宣汉县",
+          "开江县",
+          "大竹县"
+        ]
+      },
+      {
+        "name": "雅安市",
+        "area": [
+          "雨城区",
+          "芦山县",
+          "石棉县",
+          "名山县",
+          "天全县",
+          "荥经县",
+          "宝兴县",
+          "汉源县"
+        ]
+      },
+      {
+        "name": "巴中市",
+        "area": [
+          "巴州区",
+          "南江县",
+          "平昌县",
+          "通江县"
+        ]
+      },
+      {
+        "name": "资阳市",
+        "area": [
+          "雁江区",
+          "简阳市",
+          "安岳县",
+          "乐至县"
+        ]
+      },
+      {
+        "name": "阿坝藏族羌族自治州",
+        "area": [
+          "马尔康县",
+          "九寨沟县",
+          "红原县",
+          "汶川县",
+          "阿坝县",
+          "理县",
+          "若尔盖县",
+          "小金县",
+          "黑水县",
+          "金川县",
+          "松潘县",
+          "壤塘县",
+          "茂县"
+        ]
+      },
+      {
+        "name": "甘孜藏族自治州",
+        "area": [
+          "康定县",
+          "丹巴县",
+          "炉霍县",
+          "九龙县",
+          "甘孜县",
+          "雅江县",
+          "新龙县",
+          "道孚县",
+          "白玉县",
+          "理塘县",
+          "德格县",
+          "乡城县",
+          "石渠县",
+          "稻城县",
+          "色达县",
+          "巴塘县",
+          "泸定县",
+          "得荣县"
+        ]
+      },
+      {
+        "name": "凉山彝族自治州",
+        "area": [
+          "西昌市",
+          "美姑县",
+          "昭觉县",
+          "金阳县",
+          "甘洛县",
+          "布拖县",
+          "雷波县",
+          "普格县",
+          "宁南县",
+          "喜德县",
+          "会东县",
+          "越西县",
+          "会理县",
+          "盐源县",
+          "德昌县",
+          "冕宁县",
+          "木里藏族自治县"
+        ]
+      }
+    ]
+  },
+  {
+    "name": "贵州省",
+    "city": [
+      {
+        "name": "贵阳市",
+        "area": [
+          "南明区",
+          "云岩区",
+          "花溪区",
+          "乌当区",
+          "白云区",
+          "小河区",
+          "清镇市",
+          "开阳县",
+          "修文县",
+          "息烽县"
+        ]
+      },
+      {
+        "name": "六盘水市",
+        "area": [
+          "钟山区",
+          "水城县",
+          "盘县",
+          "六枝特区"
+        ]
+      },
+      {
+        "name": "遵义市",
+        "area": [
+          "红花岗区",
+          "汇川区",
+          "赤水市",
+          "仁怀市",
+          "遵义县",
+          "绥阳县",
+          "桐梓县",
+          "习水县",
+          "凤冈县",
+          "正安县",
+          "余庆县",
+          "湄潭县",
+          "道真仡佬族苗族自治县",
+          "务川仡佬族苗族自治县"
+        ]
+      },
+      {
+        "name": "安顺市",
+        "area": [
+          "西秀区",
+          "普定县",
+          "平坝县",
+          "镇宁布依族苗族自治县",
+          "紫云苗族布依族自治县",
+          "关岭布依族苗族自治县"
+        ]
+      },
+      {
+        "name": "铜仁地区",
+        "area": [
+          "铜仁市",
+          "德江县",
+          "江口县",
+          "思南县",
+          "石阡县",
+          "玉屏侗族自治县",
+          "松桃苗族自治县",
+          "印江土家族苗族自治县",
+          "沿河土家族自治县",
+          "万山特区"
+        ]
+      },
+      {
+        "name": "毕节地区",
+        "area": [
+          "毕节市",
+          "黔西县",
+          "大方县",
+          "织金县",
+          "金沙县",
+          "赫章县",
+          "纳雍县",
+          "威宁彝族回族苗族自治县"
+        ]
+      },
+      {
+        "name": "黔西南布依族苗族自治州",
+        "area": [
+          "兴义市",
+          "望谟县",
+          "兴仁县",
+          "普安县",
+          "册亨县",
+          "晴隆县",
+          "贞丰县",
+          "安龙县"
+        ]
+      },
+      {
+        "name": "黔东南苗族侗族自治州",
+        "area": [
+          "凯里市",
+          "施秉县",
+          "从江县",
+          "锦屏县",
+          "镇远县",
+          "麻江县",
+          "台江县",
+          "天柱县",
+          "黄平县",
+          "榕江县",
+          "剑河县",
+          "三穗县",
+          "雷山县",
+          "黎平县",
+          "岑巩县",
+          "丹寨县"
+        ]
+      },
+      {
+        "name": "黔南布依族苗族自治州",
+        "area": [
+          "都匀市",
+          "福泉市",
+          "贵定县",
+          "惠水县",
+          "罗甸县",
+          "瓮安县",
+          "荔波县",
+          "龙里县",
+          "平塘县",
+          "长顺县",
+          "独山县",
+          "三都水族自治县"
+        ]
+      }
+    ]
+  },
+  {
+    "name": "云南省",
+    "city": [
+      {
+        "name": "昆明市",
+        "area": [
+          "盘龙区",
+          "五华区",
+          "官渡区",
+          "西山区",
+          "东川区",
+          "安宁市",
+          "呈贡县",
+          "晋宁县",
+          "富民县",
+          "宜良县",
+          "嵩明县",
+          "石林彝族自治县",
+          "禄劝彝族苗族自治县",
+          "寻甸回族彝族自治县"
+        ]
+      },
+      {
+        "name": "曲靖市",
+        "area": [
+          "麒麟区",
+          "宣威市",
+          "马龙县",
+          "沾益县",
+          "富源县",
+          "罗平县",
+          "师宗县",
+          "陆良县",
+          "会泽县"
+        ]
+      },
+      {
+        "name": "玉溪市",
+        "area": [
+          "红塔区",
+          "江川县",
+          "澄江县",
+          "通海县",
+          "华宁县",
+          "易门县",
+          "峨山彝族自治县",
+          "新平彝族傣族自治县",
+          "元江哈尼族彝族傣族自治县"
+        ]
+      },
+      {
+        "name": "保山市",
+        "area": [
+          "隆阳区",
+          "施甸县",
+          "腾冲县",
+          "龙陵县",
+          "昌宁县"
+        ]
+      },
+      {
+        "name": "昭通市",
+        "area": [
+          "昭阳区",
+          "鲁甸县",
+          "巧家县",
+          "盐津县",
+          "大关县",
+          "永善县",
+          "绥江县",
+          "镇雄县",
+          "彝良县",
+          "威信县",
+          "水富县"
+        ]
+      },
+      {
+        "name": "丽江市",
+        "area": [
+          "古城区",
+          "永胜县",
+          "华坪县",
+          "玉龙纳西族自治县",
+          "宁蒗彝族自治县"
+        ]
+      },
+      {
+        "name": "普洱市",
+        "area": [
+          "思茅区",
+          "普洱哈尼族彝族自治县",
+          "墨江哈尼族自治县",
+          "景东彝族自治县",
+          "景谷傣族彝族自治县",
+          "镇沅彝族哈尼族拉祜族自治县",
+          "江城哈尼族彝族自治县",
+          "孟连傣族拉祜族佤族自治县",
+          "澜沧拉祜族自治县",
+          "西盟佤族自治县"
+        ]
+      },
+      {
+        "name": "临沧市",
+        "area": [
+          "临翔区",
+          "凤庆县",
+          "云县",
+          "永德县",
+          "镇康县",
+          "双江拉祜族佤族布朗族傣族自治县",
+          "耿马傣族佤族自治县",
+          "沧源佤族自治县"
+        ]
+      },
+      {
+        "name": "德宏傣族景颇族自治州",
+        "area": [
+          "潞西市",
+          "瑞丽市",
+          "梁河县",
+          "盈江县",
+          "陇川县"
+        ]
+      },
+      {
+        "name": "怒江傈僳族自治州",
+        "area": [
+          "泸水县",
+          "福贡县",
+          "贡山独龙族怒族自治县",
+          "兰坪白族普米族自治县"
+        ]
+      },
+      {
+        "name": "迪庆藏族自治州",
+        "area": [
+          "香格里拉县",
+          "德钦县",
+          "维西傈僳族自治县"
+        ]
+      },
+      {
+        "name": "大理白族自治州",
+        "area": [
+          "大理市",
+          "祥云县",
+          "宾川县",
+          "弥渡县",
+          "永平县",
+          "云龙县",
+          "洱源县",
+          "剑川县",
+          "鹤庆县",
+          "漾濞彝族自治县",
+          "南涧彝族自治县",
+          "巍山彝族回族自治县"
+        ]
+      },
+      {
+        "name": "楚雄彝族自治州",
+        "area": [
+          "楚雄市",
+          "双柏县",
+          "牟定县",
+          "南华县",
+          "姚安县",
+          "大姚县",
+          "永仁县",
+          "元谋县",
+          "武定县",
+          "禄丰县"
+        ]
+      },
+      {
+        "name": "红河哈尼族彝族自治州",
+        "area": [
+          "蒙自县",
+          "个旧市",
+          "开远市",
+          "绿春县",
+          "建水县",
+          "石屏县",
+          "弥勒县",
+          "泸西县",
+          "元阳县",
+          "红河县",
+          "金平苗族瑶族傣族自治县",
+          "河口瑶族自治县",
+          "屏边苗族自治县"
+        ]
+      },
+      {
+        "name": "文山壮族苗族自治州",
+        "area": [
+          "文山县",
+          "砚山县",
+          "西畴县",
+          "麻栗坡县",
+          "马关县",
+          "丘北县",
+          "广南县",
+          "富宁县"
+        ]
+      },
+      {
+        "name": "西双版纳傣族自治州",
+        "area": [
+          "景洪市",
+          "勐海县",
+          "勐腊县"
+        ]
+      }
+    ]
+  },
+  {
+    "name": "西藏",
+    "city": [
+      {
+        "name": "拉萨市",
+        "area": [
+          "城关区",
+          "林周县",
+          "当雄县",
+          "尼木县",
+          "曲水县",
+          "堆龙德庆县",
+          "达孜县",
+          "墨竹工卡县"
+        ]
+      },
+      {
+        "name": "那曲地区",
+        "area": [
+          "那曲县",
+          "嘉黎县",
+          "比如县",
+          "聂荣县",
+          "安多县",
+          "申扎县",
+          "索县",
+          "班戈县",
+          "巴青县",
+          "尼玛县"
+        ]
+      },
+      {
+        "name": "昌都地区",
+        "area": [
+          "昌都县",
+          "江达县",
+          "贡觉县",
+          "类乌齐县",
+          "丁青县",
+          "察雅县",
+          "八宿县",
+          "左贡县",
+          "芒康县",
+          "洛隆县",
+          "边坝县"
+        ]
+      },
+      {
+        "name": "林芝地区",
+        "area": [
+          "林芝县",
+          "工布江达县",
+          "米林县",
+          "墨脱县",
+          "波密县",
+          "察隅县",
+          "朗县"
+        ]
+      },
+      {
+        "name": "山南地区",
+        "area": [
+          "乃东县",
+          "扎囊县",
+          "贡嘎县",
+          "桑日县",
+          "琼结县",
+          "曲松县",
+          "措美县",
+          "洛扎县",
+          "加查县",
+          "隆子县",
+          "错那县",
+          "浪卡子县"
+        ]
+      },
+      {
+        "name": "日喀则地区",
+        "area": [
+          "日喀则市",
+          "南木林县",
+          "江孜县",
+          "定日县",
+          "萨迦县",
+          "拉孜县",
+          "昂仁县",
+          "谢通门县",
+          "白朗县",
+          "仁布县",
+          "康马县",
+          "定结县",
+          "仲巴县",
+          "亚东县",
+          "吉隆县",
+          "聂拉木县",
+          "萨嘎县",
+          "岗巴县"
+        ]
+      },
+      {
+        "name": "阿里地区",
+        "area": [
+          "噶尔县",
+          "普兰县",
+          "札达县",
+          "日土县",
+          "革吉县",
+          "改则县",
+          "措勤县"
+        ]
+      }
+    ]
+  },
+  {
+    "name": "陕西省",
+    "city": [
+      {
+        "name": "西安市",
+        "area": [
+          "莲湖区",
+          "新城区",
+          "碑林区",
+          "雁塔区",
+          "灞桥区",
+          "未央区",
+          "阎良区",
+          "临潼区",
+          "长安区",
+          "高陵县",
+          "蓝田县",
+          "户县",
+          "周至县"
+        ]
+      },
+      {
+        "name": "铜川市",
+        "area": [
+          "耀州区",
+          "王益区",
+          "印台区",
+          "宜君县"
+        ]
+      },
+      {
+        "name": "宝鸡市",
+        "area": [
+          "渭滨区",
+          "金台区",
+          "陈仓区",
+          "岐山县",
+          "凤翔县",
+          "陇县",
+          "太白县",
+          "麟游县",
+          "扶风县",
+          "千阳县",
+          "眉县",
+          "凤县"
+        ]
+      },
+      {
+        "name": "咸阳市",
+        "area": [
+          "秦都区",
+          "渭城区",
+          "杨陵区",
+          "兴平市",
+          "礼泉县",
+          "泾阳县",
+          "永寿县",
+          "三原县",
+          "彬县",
+          "旬邑县",
+          "长武县",
+          "乾县",
+          "武功县",
+          "淳化县"
+        ]
+      },
+      {
+        "name": "渭南市",
+        "area": [
+          "临渭区",
+          "韩城市",
+          "华阴市",
+          "蒲城县",
+          "潼关县",
+          "白水县",
+          "澄城县",
+          "华县",
+          "合阳县",
+          "富平县",
+          "大荔县"
+        ]
+      },
+      {
+        "name": "延安市",
+        "area": [
+          "宝塔区",
+          "安塞县",
+          "洛川县",
+          "子长县",
+          "黄陵县",
+          "延川县",
+          "富县",
+          "延长县",
+          "甘泉县",
+          "宜川县",
+          "志丹县",
+          "黄龙县",
+          "吴起县"
+        ]
+      },
+      {
+        "name": "汉中市",
+        "area": [
+          "汉台区",
+          "留坝县",
+          "镇巴县",
+          "城固县",
+          "南郑县",
+          "洋县",
+          "宁强县",
+          "佛坪县",
+          "勉县",
+          "西乡县",
+          "略阳县"
+        ]
+      },
+      {
+        "name": "榆林市",
+        "area": [
+          "榆阳区",
+          "清涧县",
+          "绥德县",
+          "神木县",
+          "佳县",
+          "府谷县",
+          "子洲县",
+          "靖边县",
+          "横山县",
+          "米脂县",
+          "吴堡县",
+          "定边县"
+        ]
+      },
+      {
+        "name": "安康市",
+        "area": [
+          "汉滨区",
+          "紫阳县",
+          "岚皋县",
+          "旬阳县",
+          "镇坪县",
+          "平利县",
+          "石泉县",
+          "宁陕县",
+          "白河县",
+          "汉阴县"
+        ]
+      },
+      {
+        "name": "商洛市",
+        "area": [
+          "商州区",
+          "镇安县",
+          "山阳县",
+          "洛南县",
+          "商南县",
+          "丹凤县",
+          "柞水县"
+        ]
+      }
+    ]
+  },
+  {
+    "name": "甘肃省",
+    "city": [
+      {
+        "name": "兰州市",
+        "area": [
+          "城关区",
+          "七里河区",
+          "西固区",
+          "安宁区",
+          "红古区",
+          "永登县",
+          "皋兰县",
+          "榆中县"
+        ]
+      },
+      {
+        "name": "嘉峪关市",
+        "area": [
+          "嘉峪关市"
+        ]
+      },
+      {
+        "name": "金昌市",
+        "area": [
+          "金川区",
+          "永昌县"
+        ]
+      },
+      {
+        "name": "白银市",
+        "area": [
+          "白银区",
+          "平川区",
+          "靖远县",
+          "会宁县",
+          "景泰县"
+        ]
+      },
+      {
+        "name": "天水市",
+        "area": [
+          "清水县",
+          "秦安县",
+          "甘谷县",
+          "武山县",
+          "张家川回族自治县",
+          "北道区",
+          "秦城区"
+        ]
+      },
+      {
+        "name": "武威市",
+        "area": [
+          "凉州区",
+          "民勤县",
+          "古浪县",
+          "天祝藏族自治县"
+        ]
+      },
+      {
+        "name": "酒泉市",
+        "area": [
+          "肃州区",
+          "玉门市",
+          "敦煌市",
+          "金塔县",
+          "肃北蒙古族自治县",
+          "阿克塞哈萨克族自治县",
+          "安西县"
+        ]
+      },
+      {
+        "name": "张掖市",
+        "area": [
+          "甘州区",
+          "民乐县",
+          "临泽县",
+          "高台县",
+          "山丹县",
+          "肃南裕固族自治县"
+        ]
+      },
+      {
+        "name": "庆阳市",
+        "area": [
+          "西峰区",
+          "庆城县",
+          "环县",
+          "华池县",
+          "合水县",
+          "正宁县",
+          "宁县",
+          "镇原县"
+        ]
+      },
+      {
+        "name": "平凉市",
+        "area": [
+          "崆峒区",
+          "泾川县",
+          "灵台县",
+          "崇信县",
+          "华亭县",
+          "庄浪县",
+          "静宁县"
+        ]
+      },
+      {
+        "name": "定西市",
+        "area": [
+          "安定区",
+          "通渭县",
+          "临洮县",
+          "漳县",
+          "岷县",
+          "渭源县",
+          "陇西县"
+        ]
+      },
+      {
+        "name": "陇南市",
+        "area": [
+          "武都区",
+          "成县",
+          "宕昌县",
+          "康县",
+          "文县",
+          "西和县",
+          "礼县",
+          "两当县",
+          "徽县"
+        ]
+      },
+      {
+        "name": "临夏回族自治州",
+        "area": [
+          "临夏市",
+          "临夏县",
+          "康乐县",
+          "永靖县",
+          "广河县",
+          "和政县",
+          "东乡族自治县",
+          "积石山保安族东乡族撒拉族自治县"
+        ]
+      },
+      {
+        "name": "甘南藏族自治州",
+        "area": [
+          "合作市",
+          "临潭县",
+          "卓尼县",
+          "舟曲县",
+          "迭部县",
+          "玛曲县",
+          "碌曲县",
+          "夏河县"
+        ]
+      }
+    ]
+  },
+  {
+    "name": "青海省",
+    "city": [
+      {
+        "name": "西宁市",
+        "area": [
+          "城中区",
+          "城东区",
+          "城西区",
+          "城北区",
+          "湟源县",
+          "湟中县",
+          "大通回族土族自治县"
+        ]
+      },
+      {
+        "name": "海东地区",
+        "area": [
+          "平安县",
+          "乐都县",
+          "民和回族土族自治县",
+          "互助土族自治县",
+          "化隆回族自治县",
+          "循化撒拉族自治县"
+        ]
+      },
+      {
+        "name": "海北藏族自治州",
+        "area": [
+          "海晏县",
+          "祁连县",
+          "刚察县",
+          "门源回族自治县"
+        ]
+      },
+      {
+        "name": "海南藏族自治州",
+        "area": [
+          "共和县",
+          "同德县",
+          "贵德县",
+          "兴海县",
+          "贵南县"
+        ]
+      },
+      {
+        "name": "黄南藏族自治州",
+        "area": [
+          "同仁县",
+          "尖扎县",
+          "泽库县",
+          "河南蒙古族自治县"
+        ]
+      },
+      {
+        "name": "果洛藏族自治州",
+        "area": [
+          "玛沁县",
+          "班玛县",
+          "甘德县",
+          "达日县",
+          "久治县",
+          "玛多县"
+        ]
+      },
+      {
+        "name": "玉树藏族自治州",
+        "area": [
+          "玉树县",
+          "杂多县",
+          "称多县",
+          "治多县",
+          "囊谦县",
+          "曲麻莱县"
+        ]
+      },
+      {
+        "name": "海西蒙古族藏族自治州",
+        "area": [
+          "德令哈市",
+          "格尔木市",
+          "乌兰县",
+          "都兰县",
+          "天峻县"
+        ]
+      }
+    ]
+  },
+  {
+    "name": "宁夏",
+    "city": [
+      {
+        "name": "银川市",
+        "area": [
+          "兴庆区",
+          "西夏区",
+          "金凤区",
+          "灵武市",
+          "永宁县",
+          "贺兰县"
+        ]
+      },
+      {
+        "name": "石嘴山市",
+        "area": [
+          "大武口区",
+          "惠农区",
+          "平罗县"
+        ]
+      },
+      {
+        "name": "吴忠市",
+        "area": [
+          "利通区",
+          "青铜峡市",
+          "盐池县",
+          "同心县"
+        ]
+      },
+      {
+        "name": "固原市",
+        "area": [
+          "原州区",
+          "西吉县",
+          "隆德县",
+          "泾源县",
+          "彭阳县"
+        ]
+      },
+      {
+        "name": "中卫市",
+        "area": [
+          "沙坡头区",
+          "中宁县",
+          "海原县"
+        ]
+      }
+    ]
+  },
+  {
+    "name": "新疆",
+    "city": [
+      {
+        "name": "乌鲁木齐市",
+        "area": [
+          "天山区",
+          "沙依巴克区",
+          "新市区",
+          "水磨沟区",
+          "头屯河区",
+          "达坂城区",
+          "东山区",
+          "乌鲁木齐县"
+        ]
+      },
+      {
+        "name": "克拉玛依市",
+        "area": [
+          "克拉玛依区",
+          "独山子区",
+          "白碱滩区",
+          "乌尔禾区"
+        ]
+      },
+      {
+        "name": "吐鲁番地区",
+        "area": [
+          "吐鲁番市",
+          "托克逊县",
+          "鄯善县"
+        ]
+      },
+      {
+        "name": "哈密地区",
+        "area": [
+          "哈密市",
+          "伊吾县",
+          "巴里坤哈萨克自治县"
+        ]
+      },
+      {
+        "name": "和田地区",
+        "area": [
+          "和田市",
+          "和田县",
+          "洛浦县",
+          "民丰县",
+          "皮山县",
+          "策勒县",
+          "于田县",
+          "墨玉县"
+        ]
+      },
+      {
+        "name": "阿克苏地区",
+        "area": [
+          "阿克苏市",
+          "温宿县",
+          "沙雅县",
+          "拜城县",
+          "阿瓦提县",
+          "库车县",
+          "柯坪县",
+          "新和县",
+          "乌什县"
+        ]
+      },
+      {
+        "name": "喀什地区",
+        "area": [
+          "喀什市",
+          "巴楚县",
+          "泽普县",
+          "伽师县",
+          "叶城县",
+          "岳普湖县",
+          "疏勒县",
+          "麦盖提县",
+          "英吉沙县",
+          "莎车县",
+          "疏附县",
+          "塔什库尔干塔吉克自治县"
+        ]
+      },
+      {
+        "name": "克孜勒苏柯尔克孜自治州",
+        "area": [
+          "阿图什市",
+          "阿合奇县",
+          "乌恰县",
+          "阿克陶县"
+        ]
+      },
+      {
+        "name": "巴音郭楞蒙古自治州",
+        "area": [
+          "库尔勒市",
+          "和静县",
+          "尉犁县",
+          "和硕县",
+          "且末县",
+          "博湖县",
+          "轮台县",
+          "若羌县",
+          "焉耆回族自治县"
+        ]
+      },
+      {
+        "name": "昌吉回族自治州",
+        "area": [
+          "昌吉市",
+          "阜康市",
+          "奇台县",
+          "玛纳斯县",
+          "吉木萨尔县",
+          "呼图壁县",
+          "木垒哈萨克自治县",
+          "米泉市"
+        ]
+      },
+      {
+        "name": "博尔塔拉蒙古自治州",
+        "area": [
+          "博乐市",
+          "精河县",
+          "温泉县"
+        ]
+      },
+      {
+        "name": "石河子",
+        "area": [
+          "石河子"
+        ]
+      },
+      {
+        "name": "阿拉尔",
+        "area": [
+          "阿拉尔"
+        ]
+      },
+      {
+        "name": "图木舒克",
+        "area": [
+          "图木舒克"
+        ]
+      },
+      {
+        "name": "五家渠",
+        "area": [
+          "五家渠"
+        ]
+      },
+      {
+        "name": "伊犁哈萨克自治州",
+        "area": [
+          "伊宁市",
+          "奎屯市",
+          "伊宁县",
+          "特克斯县",
+          "尼勒克县",
+          "昭苏县",
+          "新源县",
+          "霍城县",
+          "巩留县",
+          "察布查尔锡伯自治县",
+          "塔城地区",
+          "阿勒泰地区"
+        ]
+      }
+    ]
+  },
+  {
+    "name": "台湾省",
+    "city": [
+      {
+        "name": "台北市",
+        "area": [
+          "内湖区",
+          "南港区",
+          "中正区",
+          "万华区",
+          "大同区",
+          "中山区",
+          "松山区",
+          "大安区",
+          "信义区",
+          "文山区",
+          "士林区",
+          "北投区"
+        ]
+      },
+      {
+        "name": "新北市",
+        "area": [
+          "板桥区",
+          "汐止区",
+          "新店区"
+        ]
+      },
+      {
+        "name": "桃园市",
+        "area": [
+          "其他"
+        ]
+      },
+      {
+        "name": "台中市",
+        "area": [
+          "其他"
+        ]
+      },
+      {
+        "name": "台南市",
+        "area": [
+          "其他"
+        ]
+      },
+      {
+        "name": "高雄市",
+        "area": [
+          "其他"
+        ]
+      }
+    ]
+  },
+  {
+    "name": "澳门",
+    "city": [
+      {
+        "name": "澳门",
+        "area": [
+          "花地玛堂区",
+          "圣安多尼堂区",
+          "大堂区",
+          "望德堂区",
+          "风顺堂区",
+          "嘉模堂区",
+          "圣方济各堂区",
+          "路凼"
+        ]
+      }
+    ]
+  },
+  {
+    "name": "香港",
+    "city": [
+      {
+        "name": "香港",
+        "area": [
+          "深水埗区",
+          "油尖旺区",
+          "九龙城区",
+          "黄大仙区",
+          "观塘区",
+          "北区",
+          "大埔区",
+          "沙田区",
+          "西贡区",
+          "元朗区",
+          "屯门区",
+          "荃湾区",
+          "葵青区",
+          "离岛区",
+          "中西区",
+          "湾仔区",
+          "东区",
+          "南区"
+        ]
+      }
+    ]
+  }
+]

+ 103 - 0
components/wangding-pickerAddress/wangding-pickerAddress.vue

@@ -0,0 +1,103 @@
+<template>
+	<picker @change="bindPickerChange" @columnchange="columnchange" :range="array" range-key="name" :value="value" mode="multiSelector">
+		<slot></slot>
+	</picker>
+</template>
+
+<script>
+	import AllAddress from './data.js'
+	let selectVal = ['','','']
+	
+	export default {
+		data() {
+			return{
+				value: [0,0,0],
+				array: [],
+				index: 0
+			}
+		},
+		created() {
+			this.initSelect()
+		},
+		methods:{
+			// 初始化地址选项
+			initSelect() {
+				this.updateSourceDate() // 更新源数据
+				.updateAddressDate() // 更新结果数据
+				.$forceUpdate()  // 触发双向绑定
+			},
+			// 地址控件改变控件
+			columnchange(d) {
+				this.updateSelectIndex(d.detail.column, d.detail.value) // 更新选择索引
+				.updateSourceDate() // 更新源数据
+				.updateAddressDate() // 更新结果数据
+				.$forceUpdate()  // 触发双向绑定
+			},
+			
+			/**
+			 * 更新源数据
+			 * */
+			updateSourceDate() {
+				this.array = []
+				this.array[0] = AllAddress.map(obj => {
+					return {
+						name: obj.name
+					}
+				})
+				this.array[1] = AllAddress[this.value[0]].city.map(obj => {
+					return {
+						name: obj.name
+					}
+				})
+				this.array[2] = AllAddress[this.value[0]].city[this.value[1]].area.map(obj => { 
+					return {
+						name: obj
+					}
+				})
+				return this
+			},
+			
+			/**
+			 * 更新索引
+			 * */
+			updateSelectIndex(column, value){
+				let arr = JSON.parse(JSON.stringify(this.value)) 
+				arr[column] = value
+				if(column === 0 ) {
+					arr[1] = 0
+					arr[2] = 0
+				}
+				if(column === 1 ) {
+					arr[2] = 0
+				}
+				this.value = arr
+				return this
+			},
+			
+			/**
+			 * 更新结果数据 
+			 * */
+			updateAddressDate() {
+				selectVal[0] = this.array[0][this.value[0]].name
+				selectVal[1] = this.array[1][this.value[1]].name 
+				selectVal[2] = this.array[2][this.value[2]].name 
+				return this
+			},
+			
+			/**
+			 * 点击确定
+			 * */
+			bindPickerChange(e) {
+				this.$emit('change', {
+					index: this.value,
+					data: selectVal
+				})
+				return this
+			}
+			
+		}
+	}
+</script>
+
+<style>
+</style>

+ 280 - 0
components/xuan-popup/xuan-popup.vue

@@ -0,0 +1,280 @@
+<!-- 
+ *属性 isdistance 每个弹窗之间是否有间距
+ *数组形式传值
+ *type,类型 success warn info err loading(string)
+ *content,内容(string)
+ *timeout,消失时间(Number)
+ *isClick,是否点击消失(Boolean)
+ -->
+<template>
+	<view class="popup_list">
+		<view v-for="(items,index) of popup_list" :id="items.uuid" :key="items.uuid" >
+			<view class="mpopup" :style="{ background: items.color ,top:index*distance+45+'px'}" :class="[items.animator,items.typeClass]" @click="close(items.uuid,index)">
+				<view class="pic"><image class="icon" mode="aspectFit" :src="items.icon"></image></view>
+				<text class="text" :style="{ color: items.colortext }">{{ items.content }}</text>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default{
+		data(){
+			return{
+				popup_list:[],//弹窗数组
+				distance:65//每个弹窗之间间距
+			}
+		},
+		props:{
+			//是否有间距
+			isdistance:{
+				type:Boolean,
+				default:true
+			},
+			
+		},
+		methods:{
+			init:function(list){			
+				if (list.type == 'success') {
+					list.icon = '../../static/xuan-popup/success.png';
+					list.typeClass='mpopup-success';
+					return list;
+				}
+				if (list.type == 'warn') {
+					list.icon = '../../static/xuan-popup/warn.png';
+					list.typeClass='mpopup-warn';
+					return list;
+				}
+				if (list.type == 'info') {
+					list.icon = '../../static/xuan-popup/info.png';
+					list.typeClass='mpopup-info';
+					return list;
+				}
+				if (list.type == 'err') {
+					list.icon = '../../static/xuan-popup/err.png';
+					list.typeClass='mpopup-err';
+					return list;
+				}
+				if (list.type == 'loading') {
+					list.icon = '../../static/xuan-popup/loading.png';
+					list.typeClass='mpopup-loading';
+					return list;
+				}
+			},
+			open:function(list){
+				if(!this.isdistance){this.distance=0}
+				//生成uuid
+				let uuid=this.guid();
+				list.uuid=uuid;
+				//添加动画
+				list.animator='fade_Down';
+				//判断是否可点击消失/可控制消失
+				if(typeof(list.isClick)!='boolean'){list.isClick=false;}
+				//if(typeof(list.isControl)!='boolean'){list.isControl=false;}
+				
+				//初始化
+				let new_list=this.init(list);		
+				//添加进数组
+				this.popup_list.push(new_list);
+		
+				if(!new_list.isClick){
+					this.disappear(new_list.uuid,new_list.timeout);
+				}//可点击消失
+				else{
+					this.$emit('uuidCallback',new_list.uuid);
+				}
+				// else if(new_list.isControl){
+				// 	this.$emit('Callback',new_list.uuid);
+				// }
+				
+			},
+			//自动消失
+			disappear:function(uuid,timeout){
+				//退出动画之后,短暂延迟后移除本元素
+				this.fade_out_animator(uuid,timeout).then(res=>{
+					setTimeout(()=>{
+						for(let i=0;i<this.popup_list.length;i++){
+							if(this.popup_list[i].uuid==res){
+								//移除本元素
+								this.popup_list.splice(i,1);
+								this.$forceUpdate()
+							}
+						}
+					},250)
+				});
+			},
+			fade_out_animator:function(uuid,timeout){
+				//timeout秒后退出
+				if(!timeout||typeof(timeout)!='number'){timeout=3000;}
+				return new Promise(res=>{
+					setTimeout(()=>{
+						for(let i=0;i<this.popup_list.length;i++){
+							if(this.popup_list[i].uuid==uuid){
+								//添加退出动画
+								this.popup_list[i].animator='fade_Top';
+								res(uuid);
+							}
+						}
+					},timeout)
+				})
+			},
+			//可控制关闭的弹出框
+			close:function(uuid,ind){
+				if(ind){
+					if(!this.popup_list[ind].isClick){return}
+				}
+				this.remove_element(uuid).then((res)=>{
+					setTimeout(()=>{
+						for(let i=0;i<this.popup_list.length;i++){
+							if(this.popup_list[i].uuid==res){
+								//移除本元素
+								this.popup_list.splice(i,1);
+								this.$emit('closeCallback',uuid);
+								this.$forceUpdate()
+							}
+						}
+					},250)
+				})
+			},
+			//控制移除元素
+			remove_element:function(uuid){
+				return new Promise(res=>{
+					for (var i = 0; i < this.popup_list.length; i++) {
+						if(this.popup_list[i].uuid==uuid){
+							this.popup_list[i].animator='fade_Top';
+							res(uuid)
+							break;
+						} 
+					}
+				})
+				
+			},
+			//更新
+			update:function(update_list){
+				for (var i = 0; i < this.popup_list.length; i++) {
+					if(this.popup_list[i].uuid==update_list.uuid){
+						this.popup_list[i].type=update_list.type;
+						this.init(this.popup_list[i]);
+						this.popup_list[i].content=update_list.content;
+						break;
+					} 
+				}
+			},
+			//生成uuid
+			guid:function() {
+			    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
+			        var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
+			        return v.toString(16);
+			    });
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.mpopup{
+		display: flex;
+		flex-direction: row;
+		text-align: center;
+		justify-content: center;
+		align-items: center;
+		min-height: 45px;
+		width: 550rpx;
+		transition :all .5s;
+		position: fixed;
+		left: 0;
+		right: 0;
+		margin: 0 auto;
+		border-radius: 5px;	
+		z-index:998;
+		.pic{
+			display: flex;
+			text-align: center;
+			justify-content: center;
+			width: 15px;
+			height: 15px;
+			margin: auto 20px auto 0;
+			.icon{
+				width: 100%;
+				height: auto;
+			}
+		}
+		.text{
+			margin: auto 20px auto 0;
+			width: 65%;
+			font-size: 16px;
+		}
+	}
+	.mpopup-success{
+		background: #f0f9eb;
+		border: 1px solid #e1f3d8;
+		color: #67c23a;
+	}
+	.mpopup-err{
+		background: #fef0f0;
+		border: 1px solid #fde2e2;
+		color: #f56c6c;
+	}
+	.mpopup-warn{
+		background: #fdf6ec;
+		border: 1px solid #faecd8;
+		color: #e6a23c;
+	}
+	.mpopup-info{
+		background: #edf2fc;
+		border: 1px solid #ebeef5;
+		color: #909399;
+	}
+	.mpopup-loading{
+		background: #e2f5ff;
+		border: 1px solid #ceeeff;
+		color: #5cbaff;
+		image{
+			animation: rotate360 1.5s ease infinite;
+		}
+	}
+	.fade_Down{
+		animation: fadeInDown 0.6s both;
+	}
+	.fade_Top{
+		animation: fadeInTop 0.5s forwards;
+	}
+	/*从上到下*/
+	@keyframes fadeInDown
+	{
+	    from {
+	        opacity: 0;
+	        -webkit-transform: translate(0,-100px); 
+	        transform: stranslate(0,-100px); 
+	    }
+	    to {
+	        opacity:1;
+	        -webkit-transform: translate(0,10px);
+	        transform: stranslate(0,10px);
+	    }
+	}
+	/*从下到上*/
+	@keyframes fadeInTop
+	{
+	    from {
+	        opacity:1;
+	        -webkit-transform: translate(0,10px); 
+	        transform: stranslate(0,10px);
+	    }
+	    to {
+	
+			opacity: 0;
+			-webkit-transform: translate(0,-100px);
+			transform: stranslate(0,-100px);
+	    }
+	}
+	@keyframes rotate360
+	{
+		from {
+			transform: rotate(0);
+		}
+		to{
+			transform: rotate(360deg);
+		}
+	}
+</style>

+ 34 - 0
interceptor.js

@@ -0,0 +1,34 @@
+// 应用打开后拦截
+const loadRouter = function() {
+	// 获取上个页面
+	let pages = getCurrentPages();
+	let prePage = pages[pages.length - 2];
+	// #ifdef H5
+	let page =  prePage;
+	// #endif
+	// #ifdef APP-PLUS
+	let page = prePage.$vm;
+	// #endif
+	interceptor(page,prePage)
+}
+// 路由拦截
+/**
+ * @param {Object} now 当前页面
+ * @param {Object} before 上一个页面
+ */
+const interceptor = function(now,before) {
+	// 获取用户信息判断是否登录过
+	let userInfo = uni.getStorageSync('userInfo') || '';
+	// 判断是否需要拦截
+	let state = uni.getStorageSync('loginInterceptor');
+	// 判断是否需要拦截
+	if (state) {
+		// 拦截条件
+		if (!userInfo.id) {
+			uni.navigateTo({
+				url: '/pages/public/login'
+			})
+		}
+	}
+}
+export default loadRouter

+ 44 - 0
main.js

@@ -0,0 +1,44 @@
+import Vue from 'vue'
+import store from './store'
+import App from './App'
+/**
+ *  所有测试用数据均存放于根目录json.js
+ *  
+ *  css部分使用了App.vue下的全局样式和iconfont图标,有需要图标库的可以留言。
+ *  示例使用了uni.scss下的变量, 除变量外已尽量移除特有语法,可直接替换为其他预处理器使用
+ */
+const msg = (title, duration=1500, mask=false, icon='none')=>{
+	//统一提示方便全局修改
+	if(Boolean(title) === false){
+		return;
+	}
+	uni.showToast({
+		title,
+		duration,
+		mask,
+		icon
+	});
+}
+
+const prePage = ()=>{
+	// 获取当前页面
+	let pages = getCurrentPages();
+	let prePage = pages[pages.length - 2];
+	// #ifdef H5
+	return prePage;
+	// #endif
+	return prePage.$vm;
+}
+
+
+Vue.config.productionTip = false
+Vue.prototype.$fire = new Vue();
+Vue.prototype.$store = store;
+Vue.prototype.$api = {msg, prePage};
+
+App.mpType = 'app'
+
+const app = new Vue({
+    ...App
+})
+app.$mount()

+ 165 - 0
manifest.json

@@ -0,0 +1,165 @@
+{
+    "name" : "满园春线上商城",
+    "appid" : "__UNI__F0EBD91",
+    "description" : "",
+    "versionName" : "1.0.4",
+    "versionCode" : 111,
+    "transformPx" : false,
+    "uniStatistics" : {
+        "enable" : false //全局关闭  
+    },
+    "app-plus" : {
+        /* 5+App特有相关 */
+        "usingComponents" : true,
+        "splashscreen" : {
+            "alwaysShowBeforeRender" : true,
+            "waiting" : true,
+            "autoclose" : true,
+            "delay" : 0
+        },
+        "modules" : {
+            "OAuth" : {},
+            "Share" : {},
+            "Payment" : {}
+        },
+        /* 模块配置 */
+        "distribute" : {
+            /* 应用发布信息 */
+            "android" : {
+                /* android打包配置 */
+                "permissions" : [
+                    "<uses-feature android:name=\"android.hardware.camera\"/>",
+                    "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CALL_PHONE\"/>",
+                    "<uses-permission android:name=\"android.permission.CAMERA\"/>",
+                    "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
+                    "<uses-permission android:name=\"android.permission.INTERNET\"/>",
+                    "<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
+                    "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
+                    "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
+                    "<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"/>"
+                ],
+                "abiFilters" : [ "armeabi-v7a", "arm64-v8a", "x86" ],
+                "autoSdkPermissions" : true
+            },
+            "ios" : {
+                "idfa" : false,
+                "capabilities" : {
+                    "entitlements" : {
+                        "com.apple.developer.associated-domains" : [ "applinks:yrh.liuniu946.com" ]
+                    }
+                }
+            },
+            /* ios打包配置 */
+            "sdkConfigs" : {
+                "maps" : {},
+                "oauth" : {
+                    "weixin" : {
+                        "appid" : "wx3ff7aa4ad9ada474",
+                        "appsecret" : "05b46c28ed0efe79de119a559b4de1c3",
+                        "UniversalLinks" : "https://yrh.liuniu946.com/links/"
+                    },
+                    "apple" : {}
+                },
+                "payment" : {
+                    "weixin" : {
+                        "appid" : "wx3ff7aa4ad9ada474",
+                        "UniversalLinks" : "https://yrh.liuniu946.com/links/"
+                    }
+                },
+                "share" : {
+                    "weixin" : {
+                        "appid" : "wx3ff7aa4ad9ada474",
+                        "UniversalLinks" : "https://yrh.liuniu946.com/links/"
+                    }
+                },
+                "ad" : {}
+            },
+            "icons" : {
+                "android" : {
+                    "hdpi" : "unpackage/res/icons/72x72.png",
+                    "xhdpi" : "unpackage/res/icons/96x96.png",
+                    "xxhdpi" : "unpackage/res/icons/144x144.png",
+                    "xxxhdpi" : "unpackage/res/icons/192x192.png"
+                },
+                "ios" : {
+                    "appstore" : "unpackage/res/icons/1024x1024.png",
+                    "ipad" : {
+                        "app" : "unpackage/res/icons/76x76.png",
+                        "app@2x" : "unpackage/res/icons/152x152.png",
+                        "notification" : "unpackage/res/icons/20x20.png",
+                        "notification@2x" : "unpackage/res/icons/40x40.png",
+                        "proapp@2x" : "unpackage/res/icons/167x167.png",
+                        "settings" : "unpackage/res/icons/29x29.png",
+                        "settings@2x" : "unpackage/res/icons/58x58.png",
+                        "spotlight" : "unpackage/res/icons/40x40.png",
+                        "spotlight@2x" : "unpackage/res/icons/80x80.png"
+                    },
+                    "iphone" : {
+                        "app@2x" : "unpackage/res/icons/120x120.png",
+                        "app@3x" : "unpackage/res/icons/180x180.png",
+                        "notification@2x" : "unpackage/res/icons/40x40.png",
+                        "notification@3x" : "unpackage/res/icons/60x60.png",
+                        "settings@2x" : "unpackage/res/icons/58x58.png",
+                        "settings@3x" : "unpackage/res/icons/87x87.png",
+                        "spotlight@2x" : "unpackage/res/icons/80x80.png",
+                        "spotlight@3x" : "unpackage/res/icons/120x120.png"
+                    }
+                }
+            },
+            "splashscreen" : {
+                "android" : {
+                    "hdpi" : "unpackage/res/app图/启动图/480x762.png",
+                    "xhdpi" : "unpackage/res/app图/启动图/720x1242.png",
+                    "xxhdpi" : "unpackage/res/app图/启动图/1080x1882.png"
+                },
+                "ios" : {
+                    "iphone" : {
+                        "portrait-896h@3x" : "D:/app项目文件/满园春/app图/启动图/1242x2688.png",
+                        "portrait-896h@2x" : "D:/app项目文件/满园春/app图/启动图/828x1792.png",
+                        "iphonex" : "D:/app项目文件/满园春/app图/启动图/1125x2436.png",
+                        "retina55" : "D:/app项目文件/满园春/app图/启动图/1242x2208.png",
+                        "retina47" : "D:/app项目文件/满园春/app图/启动图/750x1334.png",
+                        "retina40" : "D:/app项目文件/满园春/app图/启动图/640x1136.png"
+                    },
+                    "storyboard" : "unpackage/res/CustomStoryboard.zip"
+                },
+                "iosStyle" : "storyboard",
+                "androidStyle" : "default"
+            }
+        }
+    },
+    /* SDK配置 */
+    "quickapp" : {},
+    /* 快应用特有相关 */
+    "mp-weixin" : {
+        /* 小程序特有相关 */
+        "usingComponents" : true,
+        "appid" : "",
+        "setting" : {
+            "urlCheck" : true
+        }
+    },
+    "h5" : {
+        "title" : "满园春线上商城",
+        "domain" : "",
+        "router" : {
+            "base" : "/index/",
+            "mode" : "history"
+        },
+        "devServer" : {
+            "port" : ""
+        },
+        "optimization" : {
+            "treeShaking" : {
+                "enable" : true
+            }
+        }
+    }
+}

+ 30 - 0
node_modules/jweixin-module/README.md

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

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
node_modules/jweixin-module/out/index.js


+ 60 - 0
node_modules/jweixin-module/package.json

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

+ 11 - 0
package-lock.json

@@ -0,0 +1,11 @@
+{
+  "requires": true,
+  "lockfileVersion": 1,
+  "dependencies": {
+    "jweixin-module": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/jweixin-module/-/jweixin-module-1.4.1.tgz",
+      "integrity": "sha512-2R2oa1lYhAsclfjKSf3DP4ZiP1dcrQUbM7aklbeJA+UAg/LS7MqoA6UbTy1cs4sbB34z62K4bKW0Z9iazD8ejg=="
+    }
+  }
+}

+ 637 - 0
pages.json

@@ -0,0 +1,637 @@
+{
+	"pages": [{
+			"path": "pages/index/index",
+			"style": {
+				"navigationBarTitleText": "满园春商城",
+				"app-plus": {
+					"titleNView": {
+						"type": "transparent",
+						"searchInput": {
+							"backgroundColor": "rgba(231, 231, 231,.7)",
+							"borderRadius": "16px",
+							"placeholder": "请输入关键字",
+							"disabled": true,
+							"placeholderColor": "#606266",
+							"align": "left"
+						}
+					}
+				}
+			}
+		}, {
+			"path": "pages/public/register",
+			"style": {
+				"navigationBarTitleText": "注册",
+				"app-plus": {
+					"titleNView": {
+						"type": "transparent"
+					}
+				}
+			}
+		},
+		{
+			"path": "pages/moments/details",
+			"style": {
+				"navigationBarTitleText": "文章页",
+				"app-plus": {
+					"titleNView": false
+				}
+			}
+		},
+		{
+			"path": "pages/public/login",
+			"style": {
+				"navigationBarTitleText": "登录",
+				"app-plus": {
+					"titleNView": {
+						"type": "transparent"
+					}
+				}
+			}
+		},
+		{
+			"path": "pages/public/wxLogin",
+			"style": {
+				"navigationBarTitleText": "微信登录",
+				"app-plus": {
+					"titleNView": {
+						"type": "transparent"
+					}
+				}
+			}
+		},
+		{
+			"path": "pages/public/forget",
+			"style": {
+				"navigationBarTitleText": "忘记密码",
+				"app-plus": {
+					"titleNView": {
+						"type": "transparent"
+					}
+				}
+			}
+		}, {
+			"path": "pages/product/classify",
+			"style": {
+				"navigationStyle": "custom",
+				"app-plus": {
+					"titleNView": {
+						"type": "transparent"
+					}
+				}
+			}
+		}, {
+			"path": "pages/product/giftBag",
+			"style": {
+				"navigationBarTitleText": "联盟礼包"
+			}
+		}, {
+			"path": "pages/myteam/myteam",
+			"style": {
+				"navigationBarTitleText": "我的团队"
+			}
+		},
+		{
+			"path": "pages/product/product",
+			"style": {
+				"navigationBarTitleText": "详情展示",
+				"app-plus": {
+					"titleNView": {
+						"type": "transparent"
+					}
+				}
+			}
+		}, {
+			"path": "pages/product/search",
+			"style": {
+				"enablePullDownRefresh": true,
+				// #ifdef MP
+				"navigationStyle": "custom",
+				// #endif
+				// #ifndef MP
+				"app-plus": {
+					"titleNView": {
+						"searchInput": {
+							"backgroundColor": "rgba(231, 231, 231,.7)",
+							"borderRadius": "16px",
+							"placeholder": "请输入关键字",
+							"disabled": false,
+							"placeholderColor": "#606266",
+							"align": "left"
+						},
+						"buttons": [{
+							"text": "搜索",
+							"fontSize": "14",
+							"color": "#303133",
+							"background": "rgba(0,0,0,0)",
+							"width": "40px"
+						}]
+					}
+				},
+				// #endif
+				"navigationBarTitleText": "搜索"
+			}
+		}, {
+			"path": "pages/set/set",
+			"style": {
+				"navigationBarTitleText": "设置"
+			}
+		}, 
+		{
+			"path": "pages/set/about",
+			"style": {
+				"navigationBarTitleText": "关于我们"
+			}
+		}, 
+		{
+			"path": "pages/set/password",
+			"style": {
+				"navigationBarTitleText": "修改密码"
+			}
+		},
+		{
+			"path": "pages/set/phone",
+			"style": {
+				"navigationBarTitleText": "绑定手机号"
+			}
+		},
+		{
+			"path": "pages/product/reply",
+			"style": {
+				"navigationBarTitleText": "评论"
+			}
+		},{
+			"path": "pages/order/evaluate",
+			"style": {
+				"navigationBarTitleText": "评论"
+			}
+		},
+		{
+			"path": "pages/userinfo/userinfo",
+			"style": {
+				"navigationBarTitleText": "修改资料"
+			}
+		}, {
+			"path": "pages/cart/cart",
+			"style": {
+				"navigationBarTitleText": "购物车"
+			}
+		}, {
+			"path": "pages/user/user",
+			"style": {
+				// #ifndef MP-WEIXIN
+				"navigationStyle": "custom",
+				"app-plus": {
+					"bounce": "none",
+					"titleNView": false
+					// {
+					//         "type": "transparent",
+					//         "buttons": [{
+					//                         "fontSrc": "/static/yticon.ttf",
+					//                         "text": "\ue60f",
+					//                         "fontSize": "24",
+					//                         "color": "#303133",
+					//                         "width": "46px",
+					//                         "background": "rgba(0,0,0,0)"
+					//                 },
+					//                 {
+					//                         "fontSrc": "/static/yticon.ttf",
+					//                         "text": "\ue744",
+					//                         "fontSize": "28",
+					//                         "color": "#303133",
+					//                         "background": "rgba(0,0,0,0)",
+					//                         "redDot": true
+					//                 }
+					//         ]
+					// }
+				},
+				// #endif
+				"navigationBarTitleText": "个人中心"
+			}
+		}, {
+			"path": "pages/detail/detail",
+			"style": {
+				"navigationBarTitleText": "",
+				"app-plus": {
+					"titleNView": {
+						"type": "transparent"
+					}
+				}
+			}
+		}, {
+			"path": "pages/order/order",
+			"style": {
+				"navigationBarTitleText": "我的订单",
+				"app-plus": {
+					"bounce": "none"
+				}
+			}
+		},  {
+			"path": "pages/order/refundOrder",
+			"style": {
+				"navigationBarTitleText": "退款订单",
+				"app-plus": {
+					"bounce": "none"
+				}
+			}
+		}, {
+			"path": "pages/order/orderDetail",
+			"style": {
+				"navigationBarTitleText": "订单详情",
+				"app-plus": {
+					"bounce": "none"
+				}
+			}
+		}, {
+			"path": "pages/order/orderRefund",
+			"style": {
+				"navigationBarTitleText": "申请退款"
+			}
+		}, {
+			"path": "pages/order/createOrder",
+			"style": {
+				"navigationBarTitleText": "创建订单"
+			}
+		}, {
+			"path": "pages/address/address",
+			"style": {
+				"navigationBarTitleText": "收货地址"
+			}
+		}, {
+			"path": "pages/address/shopList",
+			"style": {
+				"navigationBarTitleText": "门店列表",
+				"app-plus": {
+					"titleNView": {
+						"searchInput": {
+							"backgroundColor": "rgba(231, 231, 231,.7)",
+							"borderRadius": "16px",
+							"placeholder": "请输入关键字",
+							"placeholderColor": "#606266",
+							"align": "left"
+						},
+						"buttons": [{
+							"text": "搜索",
+							"fontSize": "14",
+							"color": "#303133",
+							"background": "rgba(0,0,0,0)",
+							"width": "40px"
+						}]
+					}
+				}
+			}
+		}, {
+			"path": "pages/address/addressManage",
+			"style": {
+				"navigationBarTitleText": "新增修改地址"
+			}
+		}, {
+			"path": "pages/money/pay",
+			"style": {
+				"navigationBarTitleText": "支付"
+			}
+		},
+		{
+			"path": "pages/money/paySuccess",
+			"style": {
+				"navigationBarTitleText": "支付成功"
+			}
+		}, {
+			"path": "pages/award/award",
+			"style": {
+				"navigationBarTitleText": "奖励明细",
+				"app-plus": {
+					"titleNView": {
+						"type": "transparent"
+					}
+				}
+			}
+		}, {
+			"path": "pages/award/withdrawal",
+			"style": {
+				"navigationBarTitleText": "奖励提现"
+			}
+		}, {
+			"path": "pages/scoreAccumulate/scoreAccumulate",
+			"style": {
+				"navigationBarTitleText": "积分明细"
+			}
+		}, {
+			"path": "pages/notice/notice",
+			"style": {
+				"navigationBarTitleText": "通知"
+			}
+		}, {
+			"path": "pages/category/category",
+			"style": {
+				"navigationBarTitleText": "分类",
+				"app-plus": {
+					"bounce": "none",
+					"titleNView": {
+						"searchInput": {
+							"backgroundColor": "rgba(231, 231, 231,.7)",
+							"borderRadius": "16px",
+							"placeholder": "商品搜索",
+							"disabled": true,
+							"placeholderColor": "#606266",
+							"align": "left"
+						}
+					}
+				}
+			}
+		}, {
+			"path": "pages/product/list",
+			"style": {
+				"enablePullDownRefresh": true,
+				"navigationBarTitleText": "商品列表"
+			}
+		},
+		{
+			"path": "pages/product/listSearch",
+			"style": {
+				"enablePullDownRefresh": true,
+				"navigationBarTitleText": "商品列表"
+			}
+		},
+		{
+			"path": "pages/wallet/wallet",
+			"style": {
+				"navigationBarTitleText": "我的钱包",
+				"app-plus": {
+					"titleNView": {
+						"type": "transparent"
+					}
+				}
+			}
+		},
+		{
+			"path": "pages/wallet/freezeList",
+			"style": {
+				"navigationBarTitleText": "冻结记录"
+			}
+		},
+		{
+			"path": "pages/wallet/account",
+			"style": {
+				"navigationBarTitleText": "提现账号"
+			}
+		},
+		{
+			"path": "pages/wallet/withdrawal",
+			"style": {
+				"navigationBarTitleText": "余额提现"
+			}
+		},
+		{
+			"path": "pages/wallet/recharge",
+			"style": {
+				"navigationBarTitleText": "充值"
+			}
+		},
+		{
+			"path": "pages/favorites/favorites",
+			"style": {
+				"navigationBarTitleText": "收藏夹"
+			}
+		}, {
+			"path": "pages/sign/index",
+			"style": {
+				"navigationBarTitleText": "每日签到",
+				"app-plus": {
+					"titleNView": {
+						"type": "transparent"
+					}
+				}
+			}
+		},
+		{
+			"path": "pages/redirect/redirect",
+			"style": {
+				"navigationBarTitleText": "微信登录跳转页面",
+				"app-plus": {
+					"titleNView": false
+				}
+			}
+		},
+		{
+			"path": "pages/integral/index",
+			"style": {
+				"navigationBarTitleText": "积分商城"
+			}
+		},
+		{
+			"path": "pages/shareQrCode/index",
+			"style": {
+				"navigationBarTitleText": "邀请好友",
+				"app-plus": {
+					"titleNView": {
+						"type": "transparent"
+					}
+				}
+			}
+		},
+		{
+			"path": "pages/shareQrCode/wechatQr",
+			"style": {
+				"navigationBarTitleText": "关注公众号"
+			}
+		},
+		{
+			"path": "pages/seckill/seckill",
+			"style": {
+				"navigationBarTitleText": "限时抢购"
+			}
+		},
+		{
+			"path": "pages/groupBooking/index",
+			"style": {
+				"enablePullDownRefresh": true,
+				"navigationBarTitleText": "超值拼团"
+			}
+		},
+		{
+			"path": "pages/groupBooking/detail",
+			"style": {
+				"navigationBarTitleText": "拼团详细",
+				"app-plus": {
+					"titleNView": false
+				}
+			}
+		},
+		{
+			"path": "pages/groupBooking/inviteImg",
+			"style": {
+				"navigationBarTitleText": "拼团邀请图",
+				"app-plus": {
+					"titleNView": false
+				}
+			}
+		}, {
+			"path": "pages/award/withdmoenys",
+			"style": {
+				"navigationBarTitleText": "转余额"
+			}
+		},
+		// {
+		// 	"path": "pages/coupon/details",
+		// 	"style": {
+		// 		"navigationBarTitleText": "付款",
+		// 		"app-plus": {
+		// 			"titleNView":{
+		// 				"backgroundColor": "#5DBC7C",
+		// 				"titleColor":"#FFFFFF"
+		// 			}
+		// 		},
+		// 		"h5":{
+		// 			"titleNView":{
+		// 				"backgroundColor": "#5DBC7C",
+		// 				"titleColor":"#FFFFFF"
+		// 			}
+		// 		}
+		// 	}
+		// },
+		{
+			"path": "pages/received/index",
+			"style": {
+				"navigationBarTitleText": "收付款",
+				"app-plus": {
+					"titleNView":{
+						"backgroundColor": "#5DBC7C",
+						"titleColor":"#FFFFFF"
+					}
+				},
+				"h5":{
+					"titleNView":{
+						"backgroundColor": "#5DBC7C",
+						"titleColor":"#FFFFFF"
+					}
+				}
+			}
+		},
+		{
+			"path": "pages/received/list",
+			"style": {
+				"navigationBarTitleText": "收付款记录",
+				"app-plus": {
+					"titleNView":{
+						"backgroundColor": "#5DBC7C",
+						"titleColor":"#FFFFFF"
+					}
+				},
+				"h5":{
+					"titleNView":{
+						"backgroundColor": "#5DBC7C",
+						"titleColor":"#FFFFFF"
+					}
+				}
+			}
+		},
+		// {
+		// 	"path": "pages/received/paySuccess",
+		// 	"style": {
+		// 		"navigationBarTitleText": "付款成功",
+		// 		"app-plus": {
+		// 			"titleNView":{
+		// 				"backgroundColor": "#5DBC7C",
+		// 				"titleColor":"#FFFFFF"
+		// 			}
+		// 		},
+		// 		"h5":{
+		// 			"titleNView":{
+		// 				"backgroundColor": "#5DBC7C",
+		// 				"titleColor":"#FFFFFF"
+		// 			}
+		// 		}
+		// 	}
+		// },
+		{
+			"path": "pages/coupon/consumer",
+			"style": {
+				"navigationBarTitleText": "消费券"
+			}
+		},
+		{
+			"path": "pages/shoping/index",
+			"style": {
+				"navigationBarTitleText": "店铺信息",
+				"app-plus": {
+					"titleNView": false
+				}
+			}
+		},
+		{
+			"path": "pages/shoping/list",
+			"style": {
+				"navigationBarTitleText": "店铺信息",
+				"app-plus": {
+					"titleNView": {
+						"searchInput": {
+							"backgroundColor": "rgba(231, 231, 231,.7)",
+							"borderRadius": "16px",
+							"placeholder": "请输入关键字",
+							"placeholderColor": "#606266",
+							"align": "left"
+						}
+					}
+				}
+			}
+		},
+		{
+			"path": "pages/contract/agreement",
+			"style": {
+				"navigationBarTitleText": "注册协议"
+			}
+		},
+		{
+			"path": "pages/contract/privacy",
+			"style": {
+				"navigationBarTitleText": "隐私政策"
+			}
+		},
+		{
+			"path": "pages/contract/start",
+			"style": {
+				"navigationBarTitleText": "授权页",
+				"app-plus": {
+					"titleNView": false
+				}
+			}
+		}
+	],
+	"globalStyle": {
+		"navigationBarTextStyle": "black",
+		"navigationBarTitleText": "uni-app",
+		"navigationBarBackgroundColor": "#FFFFFF",
+		"backgroundColor": "#f8f8f8"
+	},
+	"tabBar": {
+		"color": "#C0C4CC",
+		"selectedColor": "#5DBC7C",
+		"borderStyle": "black",
+		"backgroundColor": "#ffffff",
+		"list": [{
+				"pagePath": "pages/index/index",
+				"iconPath": "static/tabBar/tab-home.png",
+				"selectedIconPath": "static/tabBar/tab-home-current.png",
+				"text": "首页"
+			},
+			{
+				"pagePath": "pages/category/category",
+				"iconPath": "static/tabBar/tab-cate.png",
+				"selectedIconPath": "static/tabBar/tab-cate-current.png",
+				"text": "分类"
+			},
+			{
+				"pagePath": "pages/cart/cart",
+				"iconPath": "static/tabBar/tab-cart.png",
+				"selectedIconPath": "static/tabBar/tab-cart-current.png",
+				"text": "购物车"
+			},
+			{
+				"pagePath": "pages/user/user",
+				"iconPath": "static/tabBar/tab-my.png",
+				"selectedIconPath": "static/tabBar/tab-my-current.png",
+				"text": "我的"
+			}
+		]
+	}
+}

+ 216 - 0
pages/address/address.vue

@@ -0,0 +1,216 @@
+<template>
+	<view class="content b-t">
+		<view class="list" v-for="(item, index) in addressList" :key="index" @click="checkAddress(item)">
+			<view class="wrapper">
+				<view class="address-box">
+					<text class="name">{{ item.real_name }}</text>
+					<text class="mobile">{{ item.phone }}</text>
+				</view>
+				<view class="u-box">
+					<text class="address">{{ item.province + item.city + item.district }} {{ item.detail }}</text>
+				</view>
+			</view>
+			<view class="buttom">
+				<view class="default-buttom" @click.stop="defaultUp(item,index)">
+					<view class="iconfont iconroundcheckfill checkbox" :class="{ checked: item.is_default == 1 }"></view>
+					<text class="text">设为默认地址</text>
+				</view>
+				<view class="operation">
+					<view @click.stop="addAddress('edit', item)">
+						<text class="iconfont iconedit"></text>
+						<text class="text">编辑</text>
+					</view>
+					<view class="blank"></view>
+					<view @click.stop="delAddress(item)">
+						<text class="iconfont icondelete"></text>
+						<text class="text">删除</text>
+					</view>
+				</view>
+			</view>
+		</view>
+		<button class="add-btn" @click="addAddress('add')">新增地址</button>
+	</view>
+</template>
+
+<script>
+import { getAddressList, addressEdit,addressDel } from '@/api/address.js';
+export default {
+	data() {
+		return {
+			source: 0,
+			addressList: []
+		};
+	},
+	onLoad(option) {
+		this.source = option.source||0
+		this.loadAddress();
+	},
+	methods: {
+		// 加载地址
+		loadAddress() {
+			getAddressList({
+				page: 1,
+				limit: 100
+			}).then(({ data }) => {
+				this.addressList = data;
+			});
+		},
+		// 设为默认地址
+		defaultUp(data,ind) {
+			this.addressList=this.addressList.map((e) => {
+				e.is_default=0
+				return e
+			})
+			this.addressList[ind].is_default=1
+			addressEdit({
+				real_name: data.real_name,
+				phone: data.phone,
+				address: {
+					province: data.province,
+					city: data.city,
+					district: data.district
+				},
+				detail: data.detail,
+				is_default: 1,
+				id: data.id
+			}).then(({ data }) => {
+				this.loadAddress();
+			}).catch((e) => {
+				console.log(e);
+			});
+		},
+		//删除地址
+		delAddress(item) {
+			addressDel({
+				id:item.id
+			}).then(({data})=>{
+				this.$api.msg('删除成功')
+			})
+			let s = this.addressList.indexOf(item);
+			this.addressList.splice(s, 1);
+		},
+		//选择地址
+		checkAddress(item) {
+			if (this.source == 1) {
+				//this.$api.prePage()获取上一页实例,在App.vue定义
+				this.$api.prePage().addressData = item;
+				uni.navigateBack();
+			}
+		},
+		// 添加地址
+		addAddress(type, item) {
+			uni.navigateTo({
+				url: `/pages/address/addressManage?type=${type}&data=${JSON.stringify(item)}`
+			});
+		},
+		//添加或修改成功之后回调
+		refreshList() {
+			// 重新加载地址
+			this.loadAddress()
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+page {
+	padding-bottom: 120rpx;
+	padding-top: 20rpx;
+}
+.content {
+	position: relative;
+}
+.list {
+	align-items: center;
+	padding: 20rpx 30rpx;
+	background: #fff;
+	margin: 20rpx;
+	margin-top: 0;
+	.buttom {
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
+		padding-top: 10rpx;
+		.checkbox {
+			font-size: 44rpx;
+			line-height: 1;
+			padding: 4rpx;
+			color: $font-color-disabled;
+			background: #fff;
+			border-radius: 50px;
+		}
+		.checkbox.checked {
+			color: $base-color;
+		}
+		.default-buttom {
+			display: flex;
+			align-items: center;
+		}
+		.operation {
+			display: flex;
+			align-items: center;
+			.blank {
+				width: 30rpx;
+			}
+		}
+		.text {
+			padding-left: 10rpx;
+			font-size: 24rpx;
+			color: #666666;
+		}
+	}
+}
+.wrapper {
+	display: flex;
+	flex-direction: column;
+	flex: 1;
+	border-bottom: 1px solid #f0f0f0;
+	padding-bottom: 20rpx;
+}
+.address-box {
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+	.address {
+		font-size: $font-base + 2rpx;
+		color: $font-color-dark;
+	}
+	.mobile {
+		font-size: $font-base;
+		color: rgba(51, 51, 51, 1);
+	}
+}
+.u-box {
+	font-size: $font-base;
+	color: $font-color-light;
+	margin-top: 16rpx;
+	.name {
+		margin-right: 30rpx;
+	}
+}
+.icon-bianji {
+	display: flex;
+	align-items: center;
+	height: 80rpx;
+	font-size: 40rpx;
+	color: $font-color-light;
+	padding-left: 30rpx;
+}
+
+.add-btn {
+	position: fixed;
+	left: 30rpx;
+	right: 30rpx;
+	bottom: 16rpx;
+	z-index: 95;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	width: 690rpx;
+	height: 80rpx;
+	font-size: $font-lg;
+	color: #fff;
+	background-color: $base-color;
+	border-radius: 10rpx;
+}
+</style>

+ 225 - 0
pages/address/addressManage.vue

@@ -0,0 +1,225 @@
+<template>
+	<view class="content">
+		<view class="row b-b">
+			<text class="tit">联系人</text>
+			<input class="input" type="text" v-model="addressData.name" placeholder="收货人姓名" placeholder-class="placeholder" />
+		</view>
+		<view class="row b-b">
+			<text class="tit">手机号</text>
+			<input class="input" type="number" v-model="addressData.mobile" placeholder="收货人手机号码" placeholder-class="placeholder" />
+		</view>
+		<view class="row b-b">
+			<text class="tit">地址</text>
+			<pickerAddress class="input" @change="onCityClick">{{addressDetail||'请选择地址'}}</pickerAddress>
+			<text class="iconfont iconlocation"></text>
+		</view>
+		<view class="row b-b">
+			<text class="tit">门牌号</text>
+			<input class="input" type="text" v-model="addressData.area" placeholder="楼号、门牌" placeholder-class="placeholder" />
+		</view>
+
+		<uni-list class="margin-t-20">
+			<uni-list-item
+				title="设为默认"
+				:switch-checked="addressData.default"
+				:show-switch="true"
+				:show-arrow="false"
+				switch-color="#5dbc7c"
+				@switchChange="switchChange"
+			></uni-list-item>
+		</uni-list>
+
+		<button class="add-btn" @click="!loading?confirm():''">提交</button>
+	</view>
+</template>
+
+<script>
+import uniList from '@/components/uni-list/uni-list.vue';
+import uniListItem from '@/components/uni-list-item/uni-list-item.vue';
+import uniPopup from '@/components/uni-popup/uni-popup.vue';
+import  pickerAddress from '@/components/wangding-pickerAddress/wangding-pickerAddress.vue';
+import { addressEdit } from '@/api/address.js';
+export default {
+	components: {
+		uniList,
+		uniListItem,
+		pickerAddress,
+		uniPopup
+	},
+	data() {
+		return {
+			addressDetail: '',
+			addressData: {
+				name: '',
+				mobile: '',
+				address: {
+					province: '',
+					city: '',
+					district: ''
+				},
+				area: '',
+				default: false
+			},
+			loading:false
+		};
+	},
+	onLoad(option) {
+		let title = '新增收货地址';
+		if (option.type === 'edit') {
+			title = '编辑收货地址';
+			let data = JSON.parse(option.data);
+			console.log(data);
+
+			this.addressData = {
+				name: data.real_name,
+				mobile: data.phone,
+				address: {
+					province: data.province,
+					city: data.city,
+					district: data.district
+				},
+				area: data.detail,
+				default: data.is_default == 1,
+				id: data.id,
+			};
+			this.addressDetail = data.province + data.city + data.district;
+		}
+		this.manageType = option.type;
+		uni.setNavigationBarTitle({
+			title
+		});
+	},
+	methods: {
+		// 选中城市切换
+		onCityClick({data}) {
+			let address = this.addressData.address;
+			address.province = data[0];
+			address.city = data[1];
+			address.district = data[2];
+			this.addressDetail = data.join('');
+		},
+		//地图选择地址
+		chooseLocation() {
+			uni.chooseLocation({
+				success: data => {
+					console.log(data);
+					this.addressData.addressName = data.name;
+					this.addressData.address = data.name;
+				}
+			});
+		},
+		// 设置是否为默认地址
+		switchChange(e) {
+			this.addressData.default = e.value;
+		},
+		//提交
+		confirm() {
+			console.log('1');
+			let obj = this;
+			let data = this.addressData;
+			if (!data.name) {
+				this.$api.msg('请填写收货人姓名');
+				return;
+			}
+			if (!/(^1[3|4|5|7|8][0-9]{9}$)/.test(data.mobile)) {
+				this.$api.msg('请输入正确的手机号码');
+				return;
+			}
+			if (!data.address) {
+				this.$api.msg('请在地图选择所在位置');
+				return;
+			}
+			if (!data.area) {
+				this.$api.msg('请填写门牌号信息');
+				return;
+			}
+			this.loading = true;
+
+			//this.$api.prePage()获取上一页实例,可直接调用上页所有数据和方法,在App.vue定义
+			addressEdit({
+				real_name: data.name,
+				phone: data.mobile,
+				address: {
+					province: data.address.province,
+					city: data.address.city,
+					district: data.address.district
+				},
+				detail: data.area,
+				is_default: data.default,
+				id: data.id||""
+			}).then(function(e) {
+				obj.$api.prePage().refreshList();
+				uni.showToast({
+					title:'提交成功',
+					duration:2000
+				});
+				setTimeout(function() {
+					this.loading = false;
+					uni.navigateBack();
+				}, 800);
+			}).catch((e) => {
+				console.log(e);
+				this.loading = false;
+			});
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+page {
+	background: $page-color-base;
+	padding-top: 16rpx;
+}
+
+.row {
+	display: flex;
+	align-items: center;
+	position: relative;
+	padding: 0 30rpx;
+	height: 110rpx;
+	background: #fff;
+
+	.tit {
+		flex-shrink: 0;
+		width: 120rpx;
+		font-size: 30rpx;
+		color: $font-color-dark;
+	}
+	.input {
+		flex: 1;
+		font-size: 30rpx;
+		color: $font-color-dark;
+	}
+	.iconlocation {
+		font-size: 36rpx;
+		color: $font-color-light;
+	}
+}
+.default-row {
+	margin-top: 16rpx;
+	.tit {
+		flex: 1;
+	}
+	switch {
+		transform: translateX(16rpx) scale(0.9);
+	}
+}
+.add-btn {
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	width: 690rpx;
+	height: 80rpx;
+	margin: 60rpx auto;
+	font-size: $font-lg;
+	color: #fff;
+	background-color: $base-color;
+	border-radius: 10rpx;
+	// box-shadow: 1px 2px 5px rgba(219, 63, 96, 0.4);
+}
+
+.alert-box {
+	background-color: #ffffff;
+}
+</style>

+ 173 - 0
pages/address/shopList.vue

@@ -0,0 +1,173 @@
+<template>
+	<view class="content b-t">
+		<view class="list" v-for="(item, index) in addressList" :key="index" @click="checkAddress(item)">
+			<view class="wrapper">
+				<view class="address-box">
+					<text class="name">{{ item.name }}</text>
+					<text class="mobile">{{ item.phone }}</text>
+				</view>
+				<view class="u-box">
+					<view class="address">{{ item.address }}</view>
+					<view class="address">{{ item.detailed_address }}</view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+import { getAddressList } from '@/api/address.js';
+export default {
+	data() {
+		return {
+			source: 0,
+			addressList: [], //显示的地址数据
+			value: '', //保存查询值
+			addressListAll: [] //保存地址数据
+		};
+	},
+	// #ifdef APP-PLUS || H5
+	onNavigationBarButtonTap(e) {
+		if (e.text === '搜索') {
+			this.searchAddressList();
+		}
+	},
+	// 监听原生标题栏搜索输入框输入内容变化事件
+	onNavigationBarSearchInputChanged(e) {
+		this.value = e.text;
+	},
+	// 监听原生标题栏搜索输入框搜索事件,用户点击软键盘上的“搜索”按钮时触发
+	onNavigationBarSearchInputConfirmed() {
+		this.searchAddressList();
+	},
+	// #endif
+	onLoad(option) {
+		this.addressListAll = this.addressList = this.$api.prePage().system_store;
+		console.log(this.addressListAll);
+	},
+	methods: {
+		// 地址查询功能
+		searchAddressList() {
+			let obj = this;
+			obj.addressList = obj.addressListAll.filter(e => {
+				// 判断客户是否有输入值并且能查询到
+				if (e.name.indexOf(obj.value) >= 0 && obj.value) {
+					return true;
+				} else if (obj.value.length == 0) {
+					return true;
+				}
+			});
+			console.log(obj.addressList);
+		},
+		//选择地址
+		checkAddress(item) {
+			// 设置商品页面地址
+			this.$api.prePage().shopAddress = item;
+			uni.navigateBack();
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+page {
+	padding-bottom: 120rpx;
+	padding-top: 20rpx;
+}
+.content {
+	position: relative;
+}
+.list {
+	align-items: center;
+	padding: 20rpx 30rpx;
+	background: #fff;
+	margin: 20rpx;
+	margin-top: 0;
+	.buttom {
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
+		padding-top: 10rpx;
+		.checkbox {
+			font-size: 44rpx;
+			line-height: 1;
+			padding: 4rpx;
+			color: $font-color-disabled;
+			background: #fff;
+			border-radius: 50px;
+		}
+		.checkbox.checked {
+			color: $base-color;
+		}
+		.default-buttom {
+			display: flex;
+			align-items: center;
+		}
+		.operation {
+			display: flex;
+			align-items: center;
+			.blank {
+				width: 30rpx;
+			}
+		}
+		.text {
+			padding-left: 10rpx;
+			font-size: 24rpx;
+			color: #666666;
+		}
+	}
+}
+.wrapper {
+	display: flex;
+	flex-direction: column;
+	flex: 1;
+	// border-bottom: 1px solid #f0f0f0;
+	// padding-bottom: 20rpx;
+}
+.address-box {
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+	.address {
+		font-size: $font-base + 2rpx;
+		color: $font-color-dark;
+	}
+	.mobile {
+		font-size: $font-base;
+		color: rgba(51, 51, 51, 1);
+	}
+}
+.u-box {
+	font-size: $font-base;
+	color: $font-color-light;
+	margin-top: 16rpx;
+	.name {
+		margin-right: 30rpx;
+	}
+}
+.icon-bianji {
+	display: flex;
+	align-items: center;
+	height: 80rpx;
+	font-size: 40rpx;
+	color: $font-color-light;
+	padding-left: 30rpx;
+}
+
+.add-btn {
+	position: fixed;
+	left: 30rpx;
+	right: 30rpx;
+	bottom: 16rpx;
+	z-index: 95;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	width: 690rpx;
+	height: 80rpx;
+	font-size: $font-lg;
+	color: #fff;
+	background-color: $base-color;
+	border-radius: 10rpx;
+}
+</style>

+ 333 - 0
pages/award/award.vue

@@ -0,0 +1,333 @@
+<template>
+	<view class="content">
+		<view class="content-money">
+			<view class="money-box flex">
+				<view>
+					<view class="text">可提现佣金(元)</view>
+					<view class="money">{{ money | getMoneyStyle }}</view>
+				</view>
+				<navigator url="/pages/wallet/freezeList">
+					<view>
+						<view class="text">冻结佣金(元)</view>
+						<view class="money">{{ freezeMoney | getMoneyStyle }}</view>
+					</view>
+				</navigator>
+			</view>
+			<!-- <view class="moneyTx" @click="navto('./withdrawal')">提现</view> -->
+			<!-- <view class="moneyTxs" @click="navto('./withdmoenys')" >转余额</view> -->
+			<view class="flex buttom-box">
+				<view class="buttom" @click="navto('./withdrawal')">
+					<view class="icon"><image class="icon-img" src="/static/icon/i6.png" mode="aspectFit"></image></view>
+					<text class="font-size-sm">提现</text>
+				</view>
+				<view class="interval"></view>
+				<view class="buttom" @click="navto('./withdmoenys')">
+					<view class="icon"><image class="icon-img" src="/static/icon/i7.png" mode="aspectFit"></image></view>
+					<text class="font-size-sm">转余额</text>
+				</view>
+			</view>
+		</view>
+		<view class="navbar">
+			<view v-for="(item, index) in navList" :key="index" class="nav-item" :class="{ current: tabCurrentIndex === index }" @click="tabClick(index)">{{ item.text }}</view>
+		</view>
+		<swiper :current="tabCurrentIndex" :style="{ height: maxheight + 'px' }" class="swiper-box" duration="300" @change="changeTab">
+			<swiper-item class="tab-content" v-for="(tabItem, tabIndex) in navList" :key="tabIndex">
+				<scroll-view class="list-scroll-content" scroll-y @scrolltolower="loadData">
+					<!-- 空白页 -->
+					<empty v-if="tabItem.loaded === true && tabItem.orderList.length === 0"></empty>
+
+					<!-- 订单列表 -->
+					<view v-for="(item, index) in tabItem.orderList" :key="index" class="order-item flex">
+						<view class="title-box">
+							<view class="title">
+								<text>{{ item.title }}</text>
+							</view>
+							<view class="time">
+								<text>{{ item.add_time }}</text>
+							</view>
+						</view>
+						<view class="money">
+							<text>{{ (item.pm == 0 ? '-' : '+') + item.number }}</text>
+						</view>
+					</view>
+					<uni-load-more :status="tabItem.loadingType"></uni-load-more>
+				</scroll-view>
+			</swiper-item>
+		</swiper>
+	</view>
+</template>
+
+<script>
+import { spreadCommission, extractBank } from '@/api/wallet.js';
+import { mapState, mapMutations } from 'vuex';
+import { getMoneyStyle } from '@/utils/rocessor.js';
+import uniLoadMore from '@/components/uni-load-more/uni-load-more.vue';
+import empty from '@/components/empty';
+export default {
+	filters: {
+		getMoneyStyle
+	},
+	components: {
+		empty,
+		uniLoadMore
+	},
+	onReady() {
+		// 初始化获取页面宽度
+		uni.createSelectorQuery()
+			.select('.content')
+			.fields(
+				{
+					size: true
+				},
+				data => {
+					// 保存头部高度
+					this.maxheight = data.height - Math.floor((data.width / 750) * 570);
+					console.log(this.maxheight);
+				}
+			)
+			.exec();
+	},
+	data() {
+		return {
+			// 头部图高度
+			maxheight: '',
+			tabCurrentIndex: 0,
+			navList: [
+				{
+					state: 0,
+					text: '收入',
+					loadingType: 'more',
+					orderList: [],
+					page: 1, //当前页数
+					limit: 10 //每次信息条数
+				},
+				{
+					state: 1,
+					text: '支出',
+					loadingType: 'more',
+					orderList: [],
+					page: 1, //当前页数
+					limit: 10 //每次信息条数
+				}
+			],
+			money: '', //可提现佣金
+			freezeMoney: '' //冻结中的佣金
+		};
+	},
+	onLoad(options) {},
+	onShow() {
+		this.loadData();
+		// 获取用户余额
+		extractBank({}).then(({ data }) => {
+			this.money = data.commissionCount;
+			// 冻结佣金
+			this.freezeMoney = data.freezePrice;
+		});
+	},
+	methods: {
+		// 页面跳转
+		navto(e) {
+			uni.navigateTo({
+				url: e
+			});
+		},
+		//获取收入支出信息
+		async loadData(source) {
+			//这里是将订单挂载到tab列表下
+			let index = this.tabCurrentIndex;
+			let navItem = this.navList[index];
+			let state = navItem.state + 3;
+			if (source === 'tabChange' && navItem.loaded === true) {
+				//tab切换只有第一次需要加载数据
+				return;
+			}
+			if (navItem.loadingType === 'loading') {
+				//防止重复加载
+				return;
+			}
+			// 修改当前对象状态为加载中
+			navItem.loadingType = 'loading';
+
+			spreadCommission(
+				{
+					page: navItem.page,
+					limit: navItem.limit
+				},
+				state
+			)
+				.then(({ data }) => {
+					if (data.length > 0) {
+						navItem.orderList = navItem.orderList.concat(data[0].list);
+						console.log(navItem.orderList);
+						navItem.page++;
+					}
+					if (navItem.limit == data.length) {
+						//判断是否还有数据, 有改为 more, 没有改为noMore
+						navItem.loadingType = 'more';
+						return;
+					} else {
+						//判断是否还有数据, 有改为 more, 没有改为noMore
+						navItem.loadingType = 'noMore';
+					}
+					uni.hideLoading();
+					this.$set(navItem, 'loaded', true);
+				})
+				.catch(e => {
+					console.log(e);
+				});
+		},
+
+		//swiper 切换
+		changeTab(e) {
+			this.tabCurrentIndex = e.target.current;
+			this.loadData('tabChange');
+		},
+		//顶部tab点击
+		tabClick(index) {
+			this.tabCurrentIndex = index;
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+page {
+	background: #ffffff;
+	height: 100%;
+}
+.content-money {
+	padding-bottom: 30rpx;
+	background: $page-color-base;
+	.moneyTx {
+		position: absolute;
+		top: 150rpx;
+		right: 0rpx;
+		width: 150rpx;
+		padding: 10rpx 30rpx;
+		border: 2px solid #ffffff;
+		border-top-left-radius: 99rpx;
+		border-bottom-left-radius: 99rpx;
+		color: #ffffff;
+		line-height: 1;
+		font-size: $font-base;
+	}
+	.moneyTxs {
+		position: absolute;
+		top: 220rpx;
+		right: 0rpx;
+		width: 150rpx;
+		padding: 10rpx 30rpx;
+		border: 2px solid #ffffff;
+		border-top-left-radius: 99rpx;
+		border-bottom-left-radius: 99rpx;
+		color: #ffffff;
+		line-height: 1;
+		font-size: $font-base;
+	}
+	.buttom-box {
+		background-color: #ffffff;
+		text-align: center;
+		margin: 0 30rpx;
+		padding: 20rpx 0;
+		border-radius: $border-radius-sm;
+		margin-top: -60rpx;
+		.buttom {
+			font-size: $font-lg;
+			flex-grow: 1;
+		}
+		.interval {
+			width: 2px;
+			height: 60rpx;
+			background-color: #eeeeee;
+		}
+		.icon {
+			height: 50rpx;
+			width: 48rpx;
+			margin: 0 auto;
+			.icon-img {
+				width: 100%;
+				height: 100%;
+			}
+		}
+	}
+}
+.money-box {
+	background-color: $base-color;
+	padding-top: var(--status-bar-height);
+	height: 368rpx;
+	color: #ffffff;
+	text-align: center;
+	justify-content: space-around;
+	.text {
+		font-size: $font-sm;
+	}
+	.money {
+		font-size: 56rpx;
+	}
+}
+
+.navbar {
+	display: flex;
+	height: 40px;
+	padding: 0 5px;
+	background: #fff;
+	box-shadow: 0 1px 5px rgba(0, 0, 0, 0.06);
+	position: relative;
+	z-index: 10;
+	.nav-item {
+		flex: 1;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		height: 100%;
+		font-size: 15px;
+		color: $font-color-dark;
+		position: relative;
+		&.current {
+			color: $base-color;
+			&:after {
+				content: '';
+				position: absolute;
+				left: 50%;
+				bottom: 0;
+				transform: translateX(-50%);
+				width: 44px;
+				height: 0;
+				border-bottom: 2px solid $base-color;
+			}
+		}
+	}
+}
+// 列表
+
+.swiper-box {
+	padding-top: 10rpx;
+	.order-item {
+		padding: 20rpx 30rpx;
+		line-height: 1.5;
+		.title-box {
+			.title {
+				font-size: $font-lg;
+				color: $font-color-base;
+			}
+			.time {
+				font-size: $font-base;
+				color: $font-color-light;
+			}
+		}
+		.money {
+			color: #fd5b23;
+			font-size: $font-lg;
+		}
+	}
+}
+.list-scroll-content {
+	height: 100%;
+}
+.content {
+	height: 100%;
+	.empty-content {
+		background-color: #ffffff;
+	}
+}
+</style>

+ 313 - 0
pages/award/withdmoenys.vue

@@ -0,0 +1,313 @@
+<template>
+	<view class="content">
+		<uni-notice-bar single="true" text="每月25号到月底可提现上月结算余额"></uni-notice-bar>
+		<view class="content-money">
+			<view class="flex ">
+				<view class="buttom">
+					<view class="icon">{{ money | getMoneyStyle }}</view>
+					<text class="text">可提现佣金</text>
+				</view>
+				<view class="interval"></view>
+				<view class="buttom">
+					<view class=" icon">{{ freeze | getMoneyStyle }}</view>
+					<text class="text">待审核提现佣金</text>
+				</view>
+			</view>
+		</view>
+		<view class="row-box">
+			<view class="title">转账金额</view>
+			<view class="row">
+				<text class="tit">¥</text>
+				<input class="input" type="number" v-model="withdrawal" placeholder='转入金额' placeholder-class="placeholder" />
+				<view class="buttom" @click="withdrawal = money">全部转账</view>
+			</view>
+		</view>
+		<!-- #ifndef MP-WEIXIN -->
+		<!--
+		<view class="list">
+			<radio-group @change="tabRadio">
+				 <label>
+					<view class="box">
+						<view class="icon iconfont iconweixin1"></view>
+						<view class="title-box">
+							<view class="title"><text>提现至微信</text></view>
+						</view>
+						<view class="right"><radio value="weixin" color="#5dbc7c" :checked="type == 'weixin'" /></view>
+					</view>
+				</label> 
+				<label>
+					
+					<view class="box">
+						<view class="icon iconfont iconzhifubao"></view>
+						<view class="title-box">
+							<view class="title">
+								<text v-if="aliData.fullname">提现至支付宝</text>
+								<text v-else>请创建支付宝账号</text>
+							</view>
+							<view class="node">
+								<text v-if="aliData.fullname">真实姓名({{ aliData.fullname }})</text>
+							</view>
+						</view>
+						<view class="right"><radio value="alipay" color="#5dbc7c" :checked="type == 'alipay'" /></view>
+					</view>
+				</label>
+				<label>
+					<view class="box">
+						<view class="icon iconfont"><image class="icon-img" src="/static/icon/i8.png" mode="aspectFit"></image></view>
+						<view class="title-box">
+							<view class="title">
+								<text v-if="bankData.bankno">{{ bankData.bank + ' ' + bankData.bankno }}</text>
+								<text v-else>请创建银行账号</text>
+							</view>
+							<view class="node">
+								<text v-if="bankData.fullname">真实姓名({{ bankData.fullname }})</text>
+							</view>
+						</view>
+						<view class="right"><radio value="bank" color="#5dbc7c" :checked="type == 'bank'" /></view>
+					</view>
+				</label>
+			</radio-group>
+		</view>-->
+		<!-- #endif -->
+		<button class="add-btn up" :class="{'action':loding}" @click="!loding?confirm():''">转入</button>
+	</view>
+</template>
+
+<script>
+import { getMoneyStyle } from '@/utils/rocessor.js';
+import { extractCashs, extractBank, aliInfo, bankInfo } from '@/api/wallet.js';
+import uniNoticeBar from '@/components/uni-notice-bar/uni-notice-bar.vue';
+export default {
+	filters: {
+		getMoneyStyle
+	},
+	components: {
+		uniNoticeBar
+	},
+	data() {
+		return {
+			type: 'bank', //提现方式
+			money: '0.00', //可提现金额
+			freeze: '0.0', //冻结金额
+			withdrawal: '', //提现金额
+			minPrice: '', //最少提现金额
+			aliData: {},
+			bankData: {},
+			// #ifdef H5
+			weichatBsrowser: false,
+			// #endif
+			loding:false,
+		};
+	},
+	onLoad(options) {
+		// #ifdef H5
+		this.weichatBsrowser = uni.getStorageSync('weichatBrowser');
+		// #endif
+		//加载提现信息
+		this.loadData();
+		// 加载提款账号信息
+		this.loadAli();
+		this.loadBank();
+	},
+	methods: {
+		// 更新数据
+		dataUp(){
+			this.loadAli();
+			this.loadBank();
+		},
+		//加载数据
+		async loadAli(source) {
+			aliInfo({}).then(e => {
+				this.aliData = e.data;
+			});
+		},
+		// 加载银行卡信息
+		async loadBank() {
+			bankInfo({}).then(e => {
+				this.bankData = e.data;
+			});
+		},
+		// 加载余额信息
+		async loadData() {
+			extractBank({}).then(({ data }) => {
+				this.money = data.commissionCount;
+				this.freeze =data.incommissionCount
+			});
+		},
+		// 跳转
+		navTo(url) {
+			uni.navigateTo({
+				url: url
+			});
+		},
+		// 切换选中对象
+		tabRadio(e) {
+			this.type = e.detail.value;
+		},
+		// 提交
+		confirm() {
+			let obj = this;
+			obj.loding = true;
+			let data = {
+				from:"weixinh5", //
+				price: this.withdrawal, //金额
+				type: 1 //0佣金1余额
+			}
+			extractCashs(data)
+				.then(e => {
+					// 允许按钮点击
+					obj.loding = false;
+					// 初始化提现金额
+					obj.withdrawal = ''
+					uni.showToast({
+						title: '提交成功',
+						duration: 2000,
+						position: 'top'
+					});
+					
+				})
+				.catch(e => {
+					obj.loding = false;
+					console.log();
+				});
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+page {
+	height: 100%;
+}
+.content-money {
+	padding: 30rpx 0;
+	background: #ffffff;
+}
+.flex {
+	background-color: #ffffff;
+	text-align: center;
+	margin: 0 30rpx;
+	border-radius: $border-radius-sm;
+	.buttom {
+		font-size: $font-lg;
+		width: 50%;
+	}
+	.interval {
+		width: 2px;
+		height: 60rpx;
+		background-color: #eeeeee;
+	}
+	.icon {
+		background-size: 100%;
+		font-size: 42rpx;
+		color: $font-color-dark;
+		font-weight: bold;
+		background-repeat: no-repeat;
+		background-position: center;
+	}
+	.text {
+		color: $font-color-light;
+	}
+}
+
+.row-box {
+	margin-top: 30rpx;
+	padding: 20rpx 30rpx;
+	background: #fff;
+	.title {
+		font-size: $font-base + 2rpx;
+		color: $font-color-dark;
+	}
+	.row {
+		display: flex;
+		align-items: center;
+		position: relative;
+		height: 80rpx;
+		.tit {
+			flex-shrink: 0;
+			width: 40rpx;
+			font-size: 30rpx;
+			color: $font-color-dark;
+		}
+		.input {
+			flex: 1;
+			font-size: 30rpx;
+			color: $font-color-dark;
+		}
+		.iconlocation {
+			font-size: 36rpx;
+			color: $font-color-light;
+		}
+
+		.buttom {
+			color: $font-color-spec;
+			font-size: $font-base;
+		}
+	}
+}
+.add-btn {
+	&.modified {
+		color: $base-color;
+	}
+	&.up {
+		background-color: $base-color;
+		color: #fff;
+	}
+	&.action{
+		background-color: $color-gray;
+	}
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	width: 690rpx;
+	height: 80rpx;
+	margin: 0 auto;
+	margin-top: 30rpx;
+	font-size: $font-lg;
+	border-radius: 10rpx;
+	// box-shadow: 1px 2px 5px rgba(219, 63, 96, 0.4);
+}
+
+.list {
+	padding-left: 30rpx;
+	margin-top: 30rpx;
+	background-color: #ffffff;
+	.box {
+		display: flex;
+		align-items: center;
+		width: 100%;
+		height: 120rpx;
+		border-bottom: 1px solid $border-color-light;
+		.icon {
+			font-size: 48rpx;
+			padding-right: 20rpx;
+			.icon-img {
+				height: 50rpx;
+				width: 50rpx;
+			}
+		}
+		.iconweixin1 {
+			color: #18bf16;
+		}
+		.iconzhifubao {
+			color: #08aaec;
+		}
+		.title-box {
+			flex-grow: 1;
+			text-align: left;
+			.title {
+				font-size: $font-base + 2rpx;
+				color: $font-color-base;
+			}
+			.node {
+				font-size: $font-sm;
+				color: $font-color-light;
+			}
+		}
+	}
+}
+/deep/ .uni-radio-input {
+	width: 45rpx;
+	height: 45rpx;
+}
+</style>

+ 332 - 0
pages/award/withdrawal.vue

@@ -0,0 +1,332 @@
+<template>
+	<view class="content">
+		<uni-notice-bar single="true" text="每月25号到月底可提现上月结算余额"></uni-notice-bar>
+		<view class="content-money">
+			<view class="flex ">
+				<view class="buttom">
+					<view class="icon">{{ money | getMoneyStyle }}</view>
+					<text class="text">可提现佣金</text>
+				</view>
+				<view class="interval"></view>
+				<view class="buttom">
+					<view class=" icon">{{ freeze | getMoneyStyle }}</view>
+					<text class="text">待审核提现佣金</text>
+				</view>
+			</view>
+		</view>
+		<view class="row-box">
+			<view class="title">提现金额</view>
+			<view class="row">
+				<text class="tit">¥</text>
+				<input class="input" type="number" v-model="withdrawal" :placeholder="'最低提现金额' + minPrice + '元'" placeholder-class="placeholder" />
+				<view class="buttom" @click="withdrawal = money">全部提现</view>
+			</view>
+		</view>
+		<view class="row-box">
+			<view class="title">手续费</view>
+			<view class="row">
+				<text class="tit">¥</text>
+				<view class="placeholder">{{ withdrawal * 0.01*charge }}</view>
+			</view>
+		</view>
+		<!-- #ifndef MP-WEIXIN -->
+		<view class="list">
+			<radio-group @change="tabRadio">
+				<label>
+					<view class="box">
+						<view class="icon iconfont iconweixin1"></view>
+						<view class="title-box">
+							<view class="title"><text>提现至微信</text></view>
+						</view>
+						<view class="right"><radio value="weixin" color="#5dbc7c" :checked="type == 'weixin'" /></view>
+					</view>
+				</label>
+				<label>
+					<view class="box">
+						<view class="icon iconfont iconzhifubao"></view>
+						<view class="title-box">
+							<view class="title">
+								<text v-if="aliData.fullname">提现至支付宝</text>
+								<text v-else>请创建支付宝账号</text>
+							</view>
+							<view class="node">
+								<text v-if="aliData.fullname">真实姓名({{ aliData.fullname }})</text>
+							</view>
+						</view>
+						<view class="right"><radio value="alipay" color="#5dbc7c" :checked="type == 'alipay'" /></view>
+					</view>
+				</label>
+				<label>
+					<view class="box">
+						<view class="icon iconfont"><image class="icon-img" src="/static/icon/i8.png" mode="aspectFit"></image></view>
+						<view class="title-box">
+							<view class="title">
+								<text v-if="bankData.bankno">{{ bankData.bank + ' ' + bankData.bankno }}</text>
+								<text v-else>请创建银行账号</text>
+							</view>
+							<view class="node">
+								<text v-if="bankData.fullname">真实姓名({{ bankData.fullname }})</text>
+							</view>
+						</view>
+						<view class="right"><radio value="bank" color="#5dbc7c" :checked="type == 'bank'" /></view>
+					</view>
+				</label>
+			</radio-group>
+		</view>
+		<!-- #endif -->
+		<button class="add-btn up" @click="confirm">提交申请</button>
+		<button class="add-btn modified" @click="navTo('/pages/wallet/account')">账号管理</button>
+	</view>
+</template>
+
+<script>
+import { getMoneyStyle } from '@/utils/rocessor.js';
+import { extractCash, extractBank, aliInfo, bankInfo } from '@/api/wallet.js';
+import uniNoticeBar from '@/components/uni-notice-bar/uni-notice-bar.vue';
+export default {
+	filters: {
+		getMoneyStyle
+	},
+	components: {
+		uniNoticeBar
+	},
+	data() {
+		return {
+			type: 'weixin', //提现方式
+			money: '0.00', //可提现金额
+			freeze: '0.0', //冻结金额
+			withdrawal: '', //提现金额
+			minPrice: '', //最少提现金额
+			aliData: {},
+			bankData: {},
+			charge:0,
+			// #ifdef H5
+			weichatBsrowser: false
+			// #endif
+		};
+	},
+	onLoad(options) {
+		// #ifdef H5
+		this.weichatBsrowser = uni.getStorageSync('weichatBrowser');
+		// #endif
+		//加载提现信息
+		this.loadData();
+		// 加载提款账号信息
+		this.loadAli();
+		this.loadBank();
+	},
+	methods: {
+		// 更新数据
+		dataUp() {
+			this.loadAli();
+			this.loadBank();
+		},
+		//加载数据
+		async loadAli(source) {
+			aliInfo({}).then(e => {
+				this.aliData = e.data;
+			});
+		},
+		// 加载银行卡信息
+		async loadBank() {
+			bankInfo({}).then(e => {
+				this.bankData = e.data;
+			});
+		},
+		// 加载余额信息
+		async loadData() {
+			extractBank({}).then(({ data }) => {
+				this.money = data.commissionCount;
+				this.minPrice = data.minPrice;
+				this.freeze = data.incommissionCount;
+				this.charge = data.cash_out;
+			});
+		},
+		// 跳转
+		navTo(url) {
+			uni.navigateTo({
+				url: url
+			});
+		},
+		// 切换选中对象
+		tabRadio(e) {
+			this.type = e.detail.value;
+		},
+		// 提交
+		confirm() {
+			let obj = this;
+			let data = {
+				extract_type: obj.type, //bank -银行卡 alipay-支付宝 weixin-微信
+				money: obj.withdrawal, //金额
+				money_type: 0 //0佣金1余额
+			};
+			if (+obj.withdrawal < +obj.minPrice) {
+				uni.showToast({
+					title: '提现金额不可少于' + obj.minPrice,
+					duration: 2000,
+					mask: false,
+					icon: 'none'
+				});
+				return;
+			}
+			if (obj.type == 'alipay') {
+				data.name = obj.aliData.fullname;
+				data.alipay_code = obj.aliData.alino;
+			}
+			if (obj.type == 'bank') {
+				data.name = obj.bankData.fullname;
+				data.bankname = obj.bankData.bank;
+				data.cardnum = obj.bankData.bankno;
+			}
+
+			extractCash(data)
+				.then(e => {
+					uni.showToast({
+						title: '提交成功',
+						duration: 2000,
+						position: 'top'
+					});
+					// 清空提现金额
+					obj.withdrawal = '';
+				})
+				.catch(e => {
+					console.log();
+				});
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+page {
+	height: 100%;
+}
+.content-money {
+	padding: 30rpx 0;
+	background: #ffffff;
+}
+.flex {
+	background-color: #ffffff;
+	text-align: center;
+	margin: 0 30rpx;
+	border-radius: $border-radius-sm;
+	.buttom {
+		font-size: $font-lg;
+		width: 50%;
+	}
+	.interval {
+		width: 2px;
+		height: 60rpx;
+		background-color: #eeeeee;
+	}
+	.icon {
+		background-size: 100%;
+		font-size: 42rpx;
+		color: $font-color-dark;
+		font-weight: bold;
+		background-repeat: no-repeat;
+		background-position: center;
+	}
+	.text {
+		color: $font-color-light;
+	}
+}
+
+.row-box {
+	margin-top: 30rpx;
+	padding: 20rpx 30rpx;
+	background: #fff;
+	.title {
+		font-size: $font-base + 2rpx;
+		color: $font-color-dark;
+	}
+	.row {
+		display: flex;
+		align-items: center;
+		position: relative;
+		height: 80rpx;
+		.tit {
+			flex-shrink: 0;
+			width: 40rpx;
+			font-size: 30rpx;
+			color: $font-color-dark;
+		}
+		.input {
+			flex: 1;
+			font-size: 30rpx;
+			color: $font-color-dark;
+		}
+		.iconlocation {
+			font-size: 36rpx;
+			color: $font-color-light;
+		}
+
+		.buttom {
+			color: $font-color-spec;
+			font-size: $font-base;
+		}
+	}
+}
+.add-btn {
+	&.modified {
+		color: $base-color;
+	}
+	&.up {
+		background-color: $base-color;
+		color: #fff;
+	}
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	width: 690rpx;
+	height: 80rpx;
+	margin: 0 auto;
+	margin-top: 30rpx;
+	font-size: $font-lg;
+	border-radius: 10rpx;
+	// box-shadow: 1px 2px 5px rgba(219, 63, 96, 0.4);
+}
+
+.list {
+	padding-left: 30rpx;
+	margin-top: 30rpx;
+	background-color: #ffffff;
+	.box {
+		display: flex;
+		align-items: center;
+		width: 100%;
+		height: 120rpx;
+		border-bottom: 1px solid $border-color-light;
+		.icon {
+			font-size: 48rpx;
+			padding-right: 20rpx;
+			.icon-img {
+				height: 50rpx;
+				width: 50rpx;
+			}
+		}
+		.iconweixin1 {
+			color: #18bf16;
+		}
+		.iconzhifubao {
+			color: #08aaec;
+		}
+		.title-box {
+			flex-grow: 1;
+			text-align: left;
+			.title {
+				font-size: $font-base + 2rpx;
+				color: $font-color-base;
+			}
+			.node {
+				font-size: $font-sm;
+				color: $font-color-light;
+			}
+		}
+	}
+}
+/deep/ .uni-radio-input {
+	width: 45rpx;
+	height: 45rpx;
+}
+</style>

+ 428 - 0
pages/cart/cart.vue

@@ -0,0 +1,428 @@
+<template>
+	<view class="container">
+		<!-- 空白页 -->
+		<view v-if="!hasLogin || empty === true" class="empty">
+			<image src="/static/error/emptyCart.png" class="emptyImg" mode="aspectFit"></image>
+			<view v-if="hasLogin" class="empty-tips">
+				空空如也
+				<navigator class="navigator" v-if="hasLogin" url="../index/index" open-type="switchTab">随便逛逛></navigator>
+			</view>
+			<view v-else class="empty-tips">
+				空空如也
+				<view class="navigator" @click="navToLogin">去登陆></view>
+			</view>
+		</view>
+		<view v-else>
+			<!-- 列表 -->
+			<view class="cart-list">
+				<block v-for="(item, index) in cartList" :key="item.id">
+					<view class="cart-item" :class="{ 'b-b': index !== cartList.length - 1 }">
+						<view class="image-wrapper">
+							<image
+								:src="item.productInfo.image"
+								:class="[item.loaded]"
+								mode="aspectFill"
+								lazy-load
+								@load="onImageLoad('cartList', index)"
+								@error="onImageError('cartList', index)"
+							></image>
+							<view class="iconfont iconroundcheckfill checkbox" :class="{ checked: item.checked }" @click="check('item', index)"></view>
+						</view>
+						<view class="item-right">
+							<text class="clamp title">{{ item.productInfo.store_name }}</text>
+							<text class="attr">{{ item.attr_val }}</text>
+							<text class="price">¥{{ item.productInfo.price }}</text>
+							<uni-number-box
+								class="step"
+								:min="1"
+								:max="item.productInfo.stock"
+								:value="item.cart_num > item.productInfo.stock ? item.productInfo.stock : item.cart_num"
+								:isMax="item.cart_num >= item.productInfo.stock ? true : false"
+								:isMin="item.cart_num === 1"
+								:index="index"
+								@eventChange="numberChange"
+							></uni-number-box>
+						</view>
+						<text class="del-btn iconfont iconclose" @click="deleteCartItem(index)"></text>
+					</view>
+				</block>
+			</view>
+			<!-- 底部菜单栏 -->
+			<view class="action-section">
+				<view class="checkbox">
+					<image :src="allChecked ? '/static/icon/selected.png' : '/static/icon/select.png'" mode="aspectFit" @click="check('all')"></image>
+					<view class="clear-btn" @click="allChecked ? clearCart() : ''" :class="{ show: allChecked }"><text>清空</text></view>
+				</view>
+				<view class="total-box">
+					<text class="price">¥{{ total }}</text>
+					<!-- <text class="coupon">
+						已优惠
+						<text>74.35</text>
+						元
+					</text> -->
+				</view>
+				<button type="primary" class="no-border confirm-btn" @click="createOrder">去结算</button>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+import { getCartList, getCartNum, cartDel } from '@/api/cart.js';
+import { mapState } from 'vuex';
+import uniNumberBox from '@/components/uni-number-box.vue';
+export default {
+	components: {
+		uniNumberBox
+	},
+	data() {
+		return {
+			total: 0, //总价格
+			allChecked: false, //全选状态  true|false
+			empty: false, //空白页现实  true|false
+			cartList: []
+		};
+	},
+	onShow() {
+		// 只有登录时才加载数据
+		if (this.hasLogin) {
+			this.loadData();
+		}
+	},
+	watch: {
+		//显示空白页
+		cartList(e) {
+			let empty = e.length === 0 ? true : false;
+			if (this.empty !== empty) {
+				this.empty = empty;
+			}
+		}
+	},
+	computed: {
+		...mapState('user',['hasLogin'])
+	},
+	methods: {
+		//请求数据
+		async loadData() {
+			let obj = this;
+			getCartList({})
+				.then(function(e) {
+					// 获取当前购物车物品增加数量
+					let nub = obj.cartList.length;
+					// 获取之前对象数组
+					let aArray = obj.cartList.reverse();
+					// 获取返回数据对象数组
+					let bArray = e.data.valid.reverse();
+					obj.cartList = bArray.map((item, ind) => {
+						// 设置返回数据默认为勾选状态
+						item.checked = true;
+						// 获取相同数组之前对象的数据
+						let carlist = aArray[ind];
+						// 判断之前是否已经加载完毕
+						if (carlist && carlist.loaded == 'loaded') {
+							item.loaded = 'loaded';
+						}
+						return item;
+					}).reverse();
+					obj.calcTotal(); //计算总价
+				})
+				.catch(function(e) {
+					console.log(e);
+				});
+		},
+		//监听image加载完成
+		onImageLoad(key, index) {
+			// 修改载入完成后图片class样式
+			this.$set(this[key][index], 'loaded', 'loaded');
+		},
+		//监听image加载失败
+		onImageError(key, index) {
+			this[key][index].image = '/static/error/errorImage.jpg';
+		},
+		// 跳转到登录页
+		navToLogin() {
+			let url = '/pages/public/login';
+			// #ifdef H5
+			let weichatBrowser = uni.getStorageSync('weichatBrowser');
+			// 判断是否为微信浏览器
+			if (weichatBrowser) {
+				url = '/pages/public/wxLogin';
+			}
+			// #endif
+			// #ifdef MP-WEIXIN
+			url = '/pages/public/wxLogin';
+			// #endif
+			uni.navigateTo({
+				url: url
+			});
+		},
+		//选中状态处理
+		check(type, index) {
+			if (type === 'item') {
+				this.cartList[index].checked = !this.cartList[index].checked;
+			} else {
+				const checked = !this.allChecked;
+				const list = this.cartList;
+				list.forEach(item => {
+					item.checked = checked;
+				});
+				this.allChecked = checked;
+			}
+			this.calcTotal(type);
+		},
+		//数量
+		numberChange(data) {
+			let arr = this.cartList[data.index];
+			arr.cart_num = data.number;
+			getCartNum({ id: arr.id, number: data.number });
+			this.calcTotal();
+		},
+		//删除
+		deleteCartItem(index) {
+			let list = this.cartList;
+			let row = list[index];
+			let id = row.id;
+			cartDel({
+				ids: id
+			});
+			this.cartList.splice(index, 1);
+			uni.hideLoading();
+			this.calcTotal();
+		},
+		//清空
+		clearCart() {
+			uni.showModal({
+				content: '清空购物车?',
+				success: e => {
+					if (e.confirm) {
+						let st = this.cartList.map((e) => {
+							return e.id
+						})
+						cartDel({
+							ids: st.join(',')
+						}).then((e) => {
+							// console.log(e);
+						});
+						this.cartList = [];
+					}
+				}
+			});
+		},
+		//计算总价
+		calcTotal() {
+			let list = this.cartList;
+			if (list.length === 0) {
+				this.empty = true;
+				return;
+			}
+			let total = 0;
+			let checked = true;
+			list.forEach(item => {
+				if (item.checked === true) {
+					total += item.productInfo.price * item.cart_num;
+				} else if (checked === true) {
+					checked = false;
+				}
+			});
+			this.allChecked = checked;
+			this.total = Number(total.toFixed(2));
+		},
+		//创建订单
+		createOrder() {
+			let list = this.cartList;
+			let goodsData = [];
+			list.forEach(item => {
+				if (item.checked) {
+					goodsData.push(item.id);
+				}
+			});
+
+			uni.navigateTo({
+				url: '/pages/order/createOrder?id=' + goodsData.join(',')
+			});
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+	page{
+		height: 100%;
+		background-color: $page-color-base;
+	}
+.container {
+	padding-bottom: 134rpx;
+	background-color: $page-color-base;
+	/* 空白页 */
+	.empty {
+		position: fixed;
+		left: 0;
+		top: 0;
+		width: 100%;
+		height: 100vh;
+		padding-bottom: 100rpx;
+		display: flex;
+		justify-content: center;
+		flex-direction: column;
+		align-items: center;
+		background: #fff;
+		.emptyImg {
+			width: 300rpx;
+			height: 250rpx;
+			margin-bottom: 30rpx;
+		}
+		.empty-tips {
+			display: flex;
+			font-size: $font-sm + 2rpx;
+			color: $font-color-disabled;
+			.navigator {
+				color: $uni-color-primary;
+				margin-left: 16rpx;
+			}
+		}
+	}
+}
+/* 购物车列表项 */
+.cart-item {
+	display: flex;
+	position: relative;
+	padding: 30rpx 40rpx;
+	.image-wrapper {
+		width: 230rpx;
+		height: 230rpx;
+		flex-shrink: 0;
+		position: relative;
+		image {
+			border-radius: 8rpx;
+		}
+	}
+	.checkbox {
+		position: absolute;
+		left: -16rpx;
+		top: -16rpx;
+		z-index: 8;
+		font-size: 44rpx;
+		line-height: 1;
+		padding: 4rpx;
+		color: $font-color-disabled;
+		background: #fff;
+		border-radius: 50px;
+	}
+	.item-right {
+		display: flex;
+		flex-direction: column;
+		flex: 1;
+		overflow: hidden;
+		position: relative;
+		padding-left: 30rpx;
+		.title,
+		.price {
+			font-size: $font-base + 2rpx;
+			color: $font-color-dark;
+			height: 40rpx;
+			line-height: 40rpx;
+		}
+		.attr {
+			font-size: $font-sm + 2rpx;
+			color: $font-color-light;
+			height: 50rpx;
+			line-height: 50rpx;
+		}
+		.price {
+			height: 50rpx;
+			line-height: 50rpx;
+		}
+		.step {
+			margin-top: 20rpx;
+		}
+	}
+	.del-btn {
+		padding: 4rpx 10rpx;
+		font-size: 34rpx;
+		height: 50rpx;
+		color: $font-color-light;
+	}
+}
+/* 底部栏 */
+.action-section {
+	/* #ifdef H5 */
+	margin-bottom: 100rpx;
+	/* #endif */
+	position: fixed;
+	left: 30rpx;
+	bottom: 30rpx;
+	z-index: 95;
+	display: flex;
+	align-items: center;
+	width: 690rpx;
+	height: 100rpx;
+	padding: 0 30rpx;
+	background: rgba(255, 255, 255, 0.9);
+	box-shadow: 0 0 20rpx 0 rgba(0, 0, 0, 0.5);
+	border-radius: 16rpx;
+	.checkbox {
+		height: 52rpx;
+		position: relative;
+		image {
+			border-radius: 50rpx;
+			background-color: #ffffff;
+			width: 52rpx;
+			height: 100%;
+			position: relative;
+			z-index: 5;
+		}
+	}
+	.clear-btn {
+		position: absolute;
+		left: 26rpx;
+		top: 0;
+		z-index: 4;
+		width: 0;
+		height: 52rpx;
+		line-height: 52rpx;
+		padding-left: 38rpx;
+		font-size: $font-base;
+		color: #fff;
+		background: $font-color-disabled;
+		border-radius: 0 50px 50px 0;
+		opacity: 0;
+		transition: 0.2s;
+		&.show {
+			opacity: 1;
+			width: 120rpx;
+		}
+	}
+	.total-box {
+		flex: 1;
+		display: flex;
+		flex-direction: column;
+		text-align: right;
+		padding-right: 40rpx;
+		.price {
+			font-size: $font-lg;
+			color: $font-color-dark;
+		}
+		.coupon {
+			font-size: $font-sm;
+			color: $font-color-light;
+			text {
+				color: $font-color-dark;
+			}
+		}
+	}
+	.confirm-btn {
+		padding: 0 38rpx;
+		margin: 0;
+		border-radius: 100px;
+		height: 76rpx;
+		line-height: 76rpx;
+		font-size: $font-base + 2rpx;
+		background: $base-color;
+	}
+}
+/* 复选框选中状态 */
+.action-section .checkbox.checked,
+.cart-item .checkbox.checked {
+	color: $base-color;
+}
+</style>

+ 230 - 0
pages/category/category.vue

@@ -0,0 +1,230 @@
+<template>
+	<view class="content">
+		<scroll-view scroll-y class="left-aside">
+			<view v-for="item in flist" :key="item.id" class="f-item b-b" :class="{ active: item.id === currentId }" @click="tabtap(item)">{{ item.cate_name }}</view>
+		</scroll-view>
+		<scroll-view scroll-with-animation scroll-y class="right-aside" @scroll="asideScroll" :scroll-top="tabScrollTop">
+			<view v-for="item in slist" :key="item.id" class="s-list" :id="'main-' + item.id">
+				<text class="s-item">{{ item.cate_name }}</text>
+				<view class="t-list ">
+					<view @click="navToList(item.id, titem.id)" v-if="titem.pid === item.id" class="t-item" v-for="titem in tlist" :key="titem.id">
+						<image :src="titem.pic"></image>
+						<text>{{ titem.cate_name }}</text>
+					</view>
+				</view>
+			</view>
+		</scroll-view>
+	</view>
+</template>
+
+<script>
+import { getList } from '@/api/category.js';
+export default {
+	data() {
+		return {
+			sizeCalcState: false,
+			tabScrollTop: 0,
+			currentId: 1,
+			flist: [],
+			slist: [],
+			tlist: []
+		};
+	},
+	onLoad() {
+		this.loadData();
+	},
+	// #ifndef MP
+	// 监听导航栏输入框点击事件
+	onNavigationBarSearchInputClicked(e) {
+		uni.navigateTo({
+			url:'/pages/product/search',
+		})
+	},
+	// #endif
+	methods: {
+		// 载入数据
+		async loadData() {
+			let obj = this;
+			getList({})
+				.then(({ data }) => {
+					this.flist = data.map(function (s) {
+								return s
+							});
+					data.forEach(function(e) {
+						obj.slist.push(...e.children.map(function (s) {
+								return s
+							}));
+					});
+					data.forEach(function(e) {
+						e.children.forEach(function(es) {
+							obj.tlist.push(...es.children.map(function (s) {
+								return s
+							}))
+						});
+					});
+				})
+				.catch(err => {
+					console.log(err);
+				});
+		},
+		//一级分类点击
+		tabtap(item) {
+			// 判断有没有初始化页面高度对象数据
+			if (!this.sizeCalcState) {
+				this.calcSize();
+			}
+			// 获取当前点击的id
+			this.currentId = item.id;
+			let index = this.slist.findIndex(sitem => sitem.pid === item.id);
+			this.tabScrollTop = this.slist[index].top;
+		},
+		//右侧栏滚动
+		asideScroll(e) {
+			// 判断有没有初始化页面高度对象数据
+			if (!this.sizeCalcState) {
+				this.calcSize();
+			}
+			let scrollTop = e.detail.scrollTop;
+			let box = 0; //列表包裹框高度初始化
+			let bottom = 10; //距离页面底部多少像素左侧列表切换到最后一个一级分类
+			// 查询当前页面对象
+			let view = uni.createSelectorQuery().select('.content');
+			view.fields(
+				{
+					id: true,
+					dataset: true,
+					rect: true,
+					size: true,
+					scrollOffset: true
+				},
+				function(e) {
+					// 保存包裹框高度
+					box = e.height;
+				}
+			).exec();
+			// 获取所有距离顶部大于滚轮距离页面高度的所有分类
+			let tabs = this.slist.filter(item => item.top <= scrollTop).reverse();
+			if (tabs.length > 0) {
+				// 判断是否已经到达滚轮底部
+				if (box + scrollTop + bottom >= e.detail.scrollHeight) {
+					this.currentId = this.slist[this.slist.length - 1].pid;
+				} else {
+					this.currentId = tabs[0].pid;
+				}
+			}
+		},
+		//计算右侧栏每个tab的高度等信息
+		calcSize() {
+			let h = 0;
+			this.slist.forEach(item => {
+				let view = uni.createSelectorQuery().select('#main-' + item.id);
+				view.fields(
+					{
+						size: true
+					},
+					data => {
+						item.top = h;
+						h += data.height;
+						item.bottom = h;
+					}
+				).exec();
+			});
+			this.sizeCalcState = true;
+		},
+		navToList(sid, tid) {
+			// 点击导航跳转到详细页面
+			uni.navigateTo({
+				url: `/pages/product/listSearch?fid=${this.currentId}&sid=${sid}&tid=${tid}`
+			});
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+page,
+.content {
+	height: 100%;
+	background-color: #f8f8f8;
+}
+
+.content {
+	display: flex;
+}
+.left-aside {
+	flex-shrink: 0;
+	width: 200rpx;
+	height: 100%;
+	background-color: #fff;
+}
+.f-item {
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	width: 100%;
+	height: 100rpx;
+	font-size: 28rpx;
+	color: $font-color-base;
+	position: relative;
+	&.active {
+		color: $base-color;
+		background: #f8f8f8;
+		&:before {
+			content: '';
+			position: absolute;
+			left: 0;
+			top: 50%;
+			transform: translateY(-50%);
+			height: 36rpx;
+			width: 8rpx;
+			background-color: $base-color;
+			border-radius: 0 4px 4px 0;
+			opacity: 0.8;
+		}
+	}
+}
+
+.right-aside {
+	flex: 1;
+	overflow: hidden;
+	padding-left: 20rpx;
+	padding-right: 20rpx;
+}
+.s-item {
+	display: flex;
+	align-items: center;
+	height: 70rpx;
+	padding-top: 8rpx;
+	font-size: 28rpx;
+	color: $font-color-dark;
+}
+.t-list {
+	display: flex;
+	flex-wrap: wrap;
+	border-radius: 15rpx;
+	width: 100%;
+	background: #fff;
+	padding-top: 12rpx;
+	&:after {
+		content: '';
+		flex: 99;
+		height: 0;
+	}
+}
+.t-item {
+	flex-shrink: 0;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	flex-direction: column;
+	width: 171rpx;
+	font-size: 26rpx;
+	color: #666;
+	padding-bottom: 20rpx;
+
+	image {
+		width: 140rpx;
+		height: 140rpx;
+	}
+}
+</style>

+ 167 - 0
pages/contract/agreement.vue

@@ -0,0 +1,167 @@
+<template>
+	<view class="box">
+		<view class="title pt20 pb30">正一商城用户/会员注册协议</view>
+		<view class="content">欢迎您访问并使用正一商城服务平台!本协议是您与正一商城平台所有者就正一商城平台服务的相关事宜所订立的协议。</view>
+		<view class="content">
+			为维护您自身权益,请您仔细阅读本协议,您点击“同意并继续”按钮后,本协议即构成对双方具有约束力的法律文件; 阅读本协议过程中,
+			如您不同意本协议或其中任何条款的约定,您应立即停止注册程序。
+		</view>
+		<view class="title">一、定义</view>
+		<view class="content">1.1 、正一商城平台:指由浙江龍信贸易有限公司运营的网络交易平台, 包括公众号,小程序,域名为www.tzlxsc.com的网站及App。</view>
+		<view class="content">1.2 、正一商城平台用户:指正一商城平台各项服务的使用者。</view>
+		<view class="content">1.3 、正一商城平台会员:指与正一商城平台签订《正一商城平台服务协议》并完成注册流程的用户。</view>
+		<view class="content">1.4 、正一商城平台供应商: 指通过正一商城平台发布货物信息或/并通过该平台销售货物的会员。</view>
+		<view class="content">1.5 、正一商城平台采购商: 指通过正一商城平台发布采购货物信息或/并通过该平台采购货物的会员。</view>
+		<view class="content">1.6 、正一商城平台托运方: 指通过正一商城平台发布发货信息或/并通过该平台委托承运商运输货物的会员。</view>
+		<view class="content">1.7 、正一商城平台承运商: 指通过正一商城平台发布车辆信息或/并通过该平台接受托运方的委托,提供运输服务的会员。</view>
+		<view class="title">二、账户注册、注册信息的保管与使用</view>
+		<view class="content">2.1 、注册者资格</view>
+		<view class="content">
+			您确认,在您开始注册程序使用正一商城平台服务前,您是具备中华人民共和国法律规定的完全民事权利能力和完全民事行为能力的自然人、法人或其他组织。
+			若您不具备前述主体资格,则您及您的监护人应当承担因此而导致的一切后果。
+		</view>
+		<view class="content">2.2 、账户说明</view>
+		<view class="content">2.2.1 当您按照注册页面提示填写信息、阅读并同意本协议且完成会员注册程序后,您才能成为正一商城平台的会员。</view>
+		<view class="content">
+			2.2.2
+			您确认,您所填写/提供的注册资料是真实、准确、完整、合法有效的,且您保证本平台可以通过该等信息与您本人进行联系。如您的注册信息有变更,请及时予以更新。如您提供的注册资料不合法、不真实、不准确、不详尽,因此而引起的责任、后果将全部由您承担。
+		</view>
+		<view class="content">2.3 注册信息的保管与使用</view>
+		<view class="content">
+			2.3.1 您提供的注册信息,正一商城平台(以下也简称为“本平台”)将按照中华人民共和国法律、
+			法规的相关规定,采取技术和制度等手段为您妥善保管。除非得到您的授权或者按照法律及其程序要求进行透露外,本平台将保证您的信息安全。
+		</view>
+		<view class="content">
+			2.3.2
+			本平台承诺仅根据本平台的服务目的使用您的信息。服务目的包括但不限于交易确认、客户回访、政策更新、发送促销信息等,除此之外,本平台将对您的信息保密。如您认为本平台超越了正常服务范围使用了您的信息,请您立即与本平台的客服中心联系,本平台将立即予以核实、纠正。
+		</view>
+		<view class="content">
+			2.3.3
+			在您注册成功后,将产生用户名和密码等账户信息,您的账户信息由您保管,您可以根据本平台的规定改变您的密码等账户信息。本平台任何时候均不会主动要求您提供您的账户。因此,
+			请您务必保管好您的账户,谨慎合理的使用您的用户名和密码。如果因为您主动泄露、
+			遭受他人攻击、诈骗或因管理不善造成账户(包括但不限于注册账户和密码、支付账户和密码等)被复制、盗用及其他行为而导致的损失及后果,均由您自行承担。
+		</view>
+		<view class="content">2.3.4 您不得将在本平台注册获得的账户转让或借给他人使用,否则,由此产生的全部责任均由您承担。</view>
+		<view class="content">
+			2.3.5 除本平台存在过错外,您应对您账户下的所有行为后果(包括但不限于在线签署各类协议、发布信息、出售或购买商品、提供或接受物流运输服务、披露信息等)负责。
+		</view>
+		<view class="title">三、正一商城平台的权利和义务</view>
+		<view class="content">
+			3.1 正一商城平台有义务在现有技术上维护整正一商城平台网站的正常运行,保障交易数据 的安全、可靠,按约定的服务内容和标准向您提供服务,并保证努力提升和改进技术。
+		</view>
+		<view class="content">3.2 若您在本平台做出下列行为的,本平台有权做出相应的处理,并且无须事先通知您 或取得您的同意:</view>
+		<view class="content">
+			3.2.1 本平台有权审阅或审查您的注册资料、信息发布、采购交易、物流服务行为,若 发现存在任何问题或疑问,本平台均有权向您发出询问及要求改正的通知或者直接作出删除
+			信息、冻结或关闭账户、取消订单等处理;
+		</view>
+		<view class="content">
+			3.2.2 若您存在以下行为或违反本协议其他约定或违反国家法律、法规、地方规章的行 为时,
+			本平台有权删除信息、禁止您发言、限制您出售或订购、限制提供或接受物流运输服务、注销您的账户,并且有权按照相关法律规定移交有关司法、行政机关处理:
+		</view>
+		<view class="content">
+			①发布或以电子邮件或以其他方式传送存在欺诈、虚假等恶意内容的信息或侵犯公共利 益、可能严重损害正一商城平台利益、侵犯其他用户合法利益及他人人身财产权利内容的信息;
+		</view>
+		<view class="content">②进行与网上购物无关或不是以购物为目的或与提供或接受物流运输服务无关,试图扰乱正常购物、物流秩序;</view>
+		<view class="content">③干扰或破坏正一商城平台或与正一商城平台相连的服务器和网络。</view>
+		<view class="content">
+			3.4 若您在正一商城平台上的采购交易、物流服务与其他用户发生纠纷或诉讼的,用户通过司法机关或行政机关依照法定程序要求正一商城平台提供相关数据,
+			正一商城平台应积极配合并提供有关资料。
+		</view>
+		<view class="title">四、会员的权利和义务</view>
+		<view class="content">
+			4.1
+			会员有权根据本协议的约定,以及正一商城平台网站上发布的相关规则在正一商城平台上查询商品信息、订购具体商品、查询物流信息、提供或接受物流服务、发表使用体验、参与商品讨论、
+			物流体验、 参加正一商城平台网站的有关活动,以及使用正一商城平台提供的其他服务。
+		</view>
+		<view class="content">4.2 会员应当保证在出售/购买商品提供/接受物流运输服务过程中遵守诚实信用原则,不扰乱网上交易的正常秩序。</view>
+		<view class="content">4.3 会员同意严格遵守以下义务:</view>
+		<view class="content">
+			①不得传输或发表: 煽动抗拒、 破坏宪法和法律、 行政法规实施的言论,煽动颠覆国家政权,推翻社会主义制度的言论,煽动分裂国家、破坏国家统一的言论,煽动民族仇恨、民
+			族歧视、破坏民族团结的言论;
+		</view>
+		<view class="content">②不得利用正一商城平台从事洗钱、窃取商业秘密、窃取个人信息等违法犯罪活动;</view>
+		<view class="content">③不得捏造或者歪曲事实,散步谣言,扰乱社会秩序;</view>
+		<view class="content">④不得传输或发表任何封建迷信、邪教、淫秽、色情、赌博、暴力、恐怖、教唆犯罪等 不文明的信息资料;</view>
+		<view class="content">⑤不得公然侮辱他人或者捏造事实诽谤他人或者进行其他恶意共计;</view>
+		<view class="content">⑥其他违反宪法和法律、行政法规规定的。</view>
+		<view class="content">4.4 未经正一商城平台书面同意,会员不得在正一商城平台网站上发布任何形式的广告。</view>
+		<view class="content">4.5 遵守正一商城平台制定的规则。</view>
+		<view class="title">五、责任限制</view>
+		<view class="content">
+			5.1
+			正一商城平台仅限在“按现状”和“按现有”的基础上向用户提供正一商城平台服务。但无法对由于信息网络设备维护、连接故障、电脑、通讯或其他系统的故障,罢工,暴乱、骚乱,灾难性天气(如火灾、洪水、风暴等),爆炸,战争、政府行为,司法行政机关的命令或因第三方原因而造成的损害结果承担责任。
+		</view>
+		<view class="content">
+			5.2 在法律法规所允许的限度内,因使用正一商城平台服务而引起的任何损害或经济损失,
+			正一商城平台承担的全部责任均不超过就用户出售/购买的与该索赔有关的商品、提供/接受的物流运输服务等所实际获得的直接收益。
+		</view>
+		<view class="title">六、知识产权</view>
+		<view class="content">
+			6.1 正一商城平台网站上所刊登的资料信息(如文字、图标、标识、按钮图标、图像、数据 编辑和软件)均是正一商城平台运营方及其关联方的财产,受中国和国际知识产权法的保护。
+		</view>
+		<view class="content">
+			6.2 除法律另有强制性规定外,未经正一商城平台运营方明确的特别书面许可,任何单位 或个人均不得以任何方式非法地全部或部分复制、转载、引用或用作其他用途。
+		</view>
+		<view class="content">6.3 会员在正一商城平台上发表的文章、言论仅代表其本人的观点,与正一商城平台无关,因此所产生的责任由作者本人承担。</view>
+		<view class="content">七、协议的变更</view>
+		<view class="content">
+			正一商城可根据国家法律法规变化及维护交易秩序、保护消费者权益需要,不时修改本协议、补充协议,变更后的协议、补充协议(下称“变更事项”)将通过法定程序并以本协议约定的方式通知您。
+		</view>
+		<view class="content">如您不同意变更事项,您有权于变更事项确定的生效日前联系正一商城客服反馈意见。如反馈意见得以采纳,正一商城将酌情调整变更事项。</view>
+		<view class="content">
+			如您对已生效的变更事项仍不同意的,
+			您应当于变更事项确定的生效之日起停止使用正一商城平台服务,变更事项对您不产生效力;如您在变更事项生效后仍继续使用正一商城平台服务,则视为您同意已生效的变更事项。
+		</view>
+		<view class="title">八、通知</view>
+		<view class="content">您同意正一商城以以下合理的方式向您送达各类通知:</view>
+		<view class="content">(一)公示的文案;</view>
+		<view class="content">(二)站内信、客户端推送的消息;</view>
+		<view class="content">(三)根据您预留于正一商城平台的联系方式发出的电子邮件、短信、函件等。</view>
+		<view class="title">九、协议终止</view>
+		<view class="content">
+			9.1
+			会员有权向正一商城平台提出注销账户的申请,经正一商城平台运营方审核同意后,由正一商城平台注销该申请注销的账户,则本协议即告终止。账户注销后,正一商城平台没有义务为申请注销者保留或披露账户中的任何信息。
+		</view>
+		<view class="content">9.2 出现下列情况时,正一商城平台可以通过注销您的账户的方式单方解除本协议:</view>
+		<view class="content">①您违反本协议约定,正一商城平台运营者依据违约条款终止本协议的;</view>
+		<view class="content">②您盗用他人账户、发布违禁信息、 骗取他人财物、销售假冒伪劣产品、扰乱市场秩序、 采取不正当手段牟利等行为,正一商城平台对您的账户予以查封的;</view>
+		<view class="content">③除上述情形外,因您多次违反正一商城平台的相关规定且情节严重,正一商城平台对您的账户予以查封的;</view>
+		<view class="content">④正一商城平台认为需要终止本协议的其他情况。</view>
+		<view class="content">9.3 本协议终止后,正一商城平台仍享有下列权利:</view>
+		<view class="content">①继续保存您的注册信息及您使用正一商城平台服务期间的所有交易信息;</view>
+		<view class="content">②您在正一商城平台服务期间存在违法行为或违反本协议的行为的,正一商城平台运营者仍有追究您责任的权利。</view>
+		<view class="title">十、法律适用、争议解决及其他</view>
+		<view class="content">
+			10.1 法律适用:本协议的订立、执行、解释、修订、补充及争议均适用中华人民共和 国法律(不包括香港、澳门、台湾地区)。如法律无相关规定的,参照商业惯例及/或行业惯 例。
+		</view>
+		<view class="content">
+			10.2 争议解决:本协议履行过程中若发生争议,由正一商城平台与您友好协商解决。协商 不成时,任何一方均可向正一商城平台所有者住所地人民法院(即浙江省台州市椒江区人民法院)提
+			起诉讼。
+		</view>
+		<view class="content">10.3 本协议内容中以黑体、加粗等方式显著标识的条款,请您着重阅读。</view>
+		<view class="title">十一、协议的修改</view>
+		<view class="content">
+			11.1
+			正一商城有权随时修改本协议的任何条款,一旦本协议的内容发生变动,正一商城将会直接在正一商城站上公布修改之后的协议内容,该公布行为视为正一商城已经通知用户修改内容。正一商城也可通过其他适当方式向用户提示修改内容。
+		</view>
+		<view class="content pb30">11.2	如果不同意正一商城对本协议相关条款所做的修改,\用户有权停止使用网络服务。如果用户继续使用网络服务,则视为用户接受正一商城对本协议相关条款所做的修改。</view>
+	</view>
+</template>
+
+<script></script>
+
+<style>
+	.box{
+		padding: 30rpx;
+	}
+.title {
+	font-size: 32rpx;
+	font-weight: 700;
+	line-height: 2;
+}
+.content {
+	font-size: 28rpx;
+	color: #666;
+	line-height: 2;
+}
+</style>

+ 252 - 0
pages/contract/privacy.vue

@@ -0,0 +1,252 @@
+<template>
+	<view class="box">
+		<view class="title">“正一线上商城”隐私政策</view>
+		  <view class="pb10">公司名称:台州市正一健康管理有限公司</view>
+		  <view class="pb10">注册地址:浙江省台州市路桥区路北街道西路桥大道366号
+</view>
+		  <view class="pb10">办公地址:浙江省台州市路桥区路北街道西路桥大道366号
+</view>
+		  <view class="pb10">联系电话:13958676726
+</view>
+		  <view class="pb10">更新时间:2021年09月27日</view>
+		  <view class="pb10">生效时间:2021年09月27日</view>
+		<view class="title">提示条款</view>
+		<view class="content">
+			“正一商城”及其关联公司(以下简称“我们”)深知个人信息对您的重要性,并会尽力保护您的个人信息安全可靠,我们致力于维持您对我们的信任,恪守以下原则,保护您的个人信息:权责一致原则,目的明确原则,选择同意原则,最少够用原则,确保安全原则,主体参与原则,公开透明原则等等。同时我们承诺,我们将按业界成熟的安全解决方案,采取相应的安全保护措施来保护您的个人信息。鉴此,我们制定本《隐私政策》(下称“本政策
+			/本隐私政策”)并提醒您:
+		</view>
+		<view class="content">
+			本政策适用于“正一商城”产品或服务。如我们关联公司的产品或服务中使用了“正一商城”提供的产品或服务(例如直接使用“正一商城”账户登录)但未设独立隐私政策的,则本政策同样适用于该部分产品或服务。
+			需要特别说明的是,本政策不适用于其他第三方向您提供的服务,也不适用于“正一商城”中已另行独立设置隐私政策的产品或服务。
+		</view>
+		<view class="content">
+			在使用“正一商城”各项产品或服务前,请您务必仔细阅读并透彻理解本政策,在确认充分理解并同意后使用相关产品或服务。一旦您开始使用“正一商城”各项产品或服务,即表示您已充分理解并同意本政策。如对本政策内容有任何疑问、意见或建议,您可通过“正一商城”提供的各种联系方式与我们联系。
+		</view>
+		<view class="title">本隐私政策部分将帮助您了解以下内容:</view>
+		<view class="content">1、我们如何收集和使用您的个人信息</view>
+		<view class="content">2、我们如何使用 Cookie 和同类技术</view>
+		<view class="content">3、我们如何共享、转让、公开披露您的个人信息</view>
+		<view class="content">4、我们如何保护您的个人信息</view>
+		<view class="content">5、您如何管理您的个人信息</view>
+		<view class="content">6、我们如何处理未成年人的个人信息</view>
+		<view class="content">7、您的个人信息如何在全球范围转移</view>
+		<view class="content">8、本隐私政策如何更新</view>
+		<view class="content">9、如何联系我们</view>
+		<view class="title">一、我们如何收集和使用您的个人信息</view>
+		<view class="content">
+			个人信息是指以电子或者其他方式记录的能够单独或者与其他信息结合识别特定自然人身份或者反映特定自然人活动情况的各种信息,我们会出于本政策所述的以下目的,收集和使用您的个人信息:
+		</view>
+		<view class="title">(一) 帮助您成为我们的用户</view>
+		<view class="content">为完成创建账号,以便我们为您提供服务,您需要提供以下信息:您的手机号码、头像、昵称、性别,并创建用户名和密码。</view>
+		<view class="title">(二)为您展示和推送商品或服务</view>
+		<view class="content">
+			为改善我们的产品或服务、向您提供个性化的信息搜索及交易服务,我们会根据您的浏览及搜索记录、设备信息、位置信息、交易信息,提取您的浏览、搜索偏好、行为习惯、位置信息等特征,基于特征标签进行间接人群画像并展示、推送信息。
+		</view>
+		<view class="content">如果您不想接受我们给您发送的商业广告,您可随时通过点击相应按钮取消。</view>
+		<view class="title">(三)向您提供商品或服务</view>
+		<view class="content">1、您向我们提供的信息</view>
+		<view class="content">
+			您在注册账户或使用我们的服务时,向我们提供的相关个人信息,例如电话号码、电子邮件、银行卡号或支付宝账号等;您通过我们的服务向其他方提供的共享信息,以及您使用我们的服务时所储存的信息。向“正一商城”提供该其他方的前述个人信息之前,您需确保您已经取得其授权同意。您在使用我们的人脸识别分类服务时明确同意开启人物相册功能后向我们提供的本地相册信息。
+		</view>
+		<view class="content">2、我们在您使用服务过程中收集的信息</view>
+		<view class="content">为向您提供更契合您需求的页面展示和搜索结果、了解产品适配性、识别账号异常状态,我们会收集关于您使用</view>
+		<view class="content">的服务以及使用方式的信息并将这些信息进行关联,这些信息包括:</view>
+		<view class="content">
+			设备信息:我们会根据您在软件安装及使用中授予的具体权限,接收并记录您所使用的设备相关信息(例如设备型号、操作系统版本、设备设置、唯一设备标识符等软硬件特征信息)、设备所在位置相关信息(例如IP
+			地址、GPS位置以及能够提供相关信息的Wi-Fi
+			接入点、蓝牙和基站等传感器信息)。日志信息:当您使用我们的网站或客户端提供的产品或服务时,我们会自动收集您对我们服务的详细使用情况,作为有关网络日志保存。例如您的搜索查询内容、IP地址、浏览器的类型、电信运营商、使用的语言、访问日期和时间及您访问的网页记录等。请注意,单独的设备信息、日志信息等是无法识别特定自然人身份的信息。如果我们将这类非个人信息与其他信息结合用于识别特定自然人身份,或者将其与个人信息结合使用,则在结合使用期间,这类非个人信息将被视为个人信息,除取得您授权或法律法规另有规定外,我们会将该类个人信息做匿名化、去标识化处理。当您与我们联系时,我们可能会保存您的通信/通话记录和内容或您留下的联系方式等信息,以便与您联系或帮助您解决问题,或记录相关问题的处理方案及结果。
+		</view>
+		<view class="content">3、我们通过间接获得方式收集到的您的个人信息</view>
+		<view class="content">
+			您可通过“正一商城”账号在我们提供的链接入口使用我们关联公司提供的产品或服务,为便于我们基于关联账号共同向您提供一站式服务并便于您统一进行管理,我们在“正一商城”集中展示您的信息或推荐您感兴趣的信息。当您通过我们产品或服务使用上述服务时,您授权我们根据实际业务及合作需要从我们关联公司处接收、汇总、分析我们确认其来源合法或您授权同意其向我们提供的您的个人信息或交易信息。如您拒绝提供上述信息或拒绝授权,可能无法使用我们关联公司的相应产品或服务,或者无法展示相关信息,但不影响使用“正一商城”扫人/找人、贴标签、聊天等核心服务。
+		</view>
+		<view class="title">(四)为您提供安全保障</view>
+		<view class="content">
+			为提高您使用我们及我们关联公司、合作伙伴提供服务的安全性,保护您或其他用户或公众的人身财产安全免遭侵害,更好地预防钓鱼网站、欺诈、网络漏洞、计算机病毒、网络攻击、网络侵入等安全风险,更准确地识别违反法律法规或“正一商城”相关协议规则的情况,我们可能使用或整合您的用户信息、交易信息、设备信息、有关网络日志以及我们关联公司、合作伙伴取得您授权或依据法律共享的信息,来综合判断您账户及交易风险、进行身份验证、检测及防范安全事件,并依法采取必要的记录、审计、分析、处置措施。
+		</view>
+		<view class="title">(五)其他用途</view>
+		<view class="content">我们将信息用于本政策未载明的其他用途,或者将基于特定目的收集而来的信息用于其他目的时,会事先征求您的同意。</view>
+		<view class="title">(六)征得授权同意的例外</view>
+		<view class="content">根据相关法律法规规定,以下情形中收集您的个人信息无需征得您的授权同意:</view>
+		<view class="content">1、与国家安全、国防安全有关的;</view>
+		<view class="content">2、与公共安全、公共卫生、重大公共利益有关的;</view>
+		<view class="content">3、与犯罪侦查、起诉、审判和判决执行等有关的;</view>
+		<view class="content">4、出于维护个人信息主体或其他个人的生命、财产等重大合法权益但又很难得到您本人同意的;</view>
+		<view class="content">5、所收集的个人信息是您自行向社会公众公开的;</view>
+		<view class="content">6、从合法公开披露的信息中收集个人信息的,如合法的新闻报道、政府信息公开等渠道;</view>
+		<view class="content">7、根据您的要求签订合同所必需的;</view>
+		<view class="content">8、用于维护所提供的产品或服务的安全稳定运行所必需的,例如发现、处置产品或服务的故障;</view>
+		<view class="content">9、为合法的新闻报道所必需的;</view>
+		<view class="content">10、学术研究机构基于公共利益开展统计或学术研究所必要,且对外提供学术研究或描述的结果时,对结果中所</view>
+		<view class="content">包含的个人信息进行去标识化处理的;</view>
+		<view class="content">11、法律法规规定的其他情形。</view>
+		<view class="content">如我们停止运营“正一商城”产品或服务,我们将及时停止继续收集您个人信息的活动,将停止运营的通知以逐</view>
+		<view class="content">一送达或公告的形式通知您,对所持有的个人信息进行删除或匿名化处理。</view>
+		<view class="title">二、我们如何使用 Cookie 和同类技术</view>
+		<view class="title">(一)Cookie</view>
+		<view class="content">
+			为确保网站正常运转、为您获得更轻松的访问体验、向您推荐您可能感兴趣的内容,我们会在您的计算机或移动设备上存储名为 Cookie 的小数据文件。Cookie
+			通常包含标识符、站点名称以及一些号码和字符。借助于Cookie,网站能够存储您的偏好等数据。
+		</view>
+		<view class="title">(二)网站信标和像素标签</view>
+		<view class="content">
+			除 Cookie
+			外,我们还会在网站上使用网站信标和像素标签等其他同类技术。例如,我们向您发送的电子邮件可能含有链接至我们网站内容的地址链接,如果您点击该链接,我们则会跟踪此次点击,帮助我们了解您的产品或
+			服务偏好以便于我们主动改善客户服务体验。网站信标通常是一种嵌入到网站或电子邮件中的透明图像。借助于电子邮件中的像素标签,我们能够获知电子邮件是否被打开。如果您不希望自己的活动以这种方式被追踪,则可以随时从我们的寄信名单中退订。
+		</view>
+		<view class="title">三、我们如何共享、转让、公开披露您的个人信息</view>
+		<view class="title">(一)共享</view>
+		<view class="content">我们不会与“正一商城”服务提供者以外的公司、组织和个人共享您的个人信息,但以下情况除外:</view>
+		<view class="content">1、在获取明确同意的情况下共享:获得您的明确同意后,我们会与其他方共享您的个人信息。</view>
+		<view class="content">2、在法定情形下的共享:我们可能会根据法律法规规定、诉讼争议解决需要,或按行政、司法机关依法提出的要求,对外共享您的个人信息。</view>
+		<view class="content">
+			3、与关联公司间共享:为便于我们基于关联账号共同向您提供服务,推荐您可能感兴趣的信息或保护“正一商城”关联公司或其他用户或公众的人身财产安全免遭侵害,您的个人信息可能会与我们的关联公司共享。我们只会共享必要的个人信息(如为便于您使用“正一商城”账号使用我们关联公司产品或服务,我们会向关联公司共享您必要的账户信息),如果我们共享您的个人敏感信息或关联公司改变个人信息的使用及处理目的,将再次征求您的授权同意。
+		</view>
+		<view class="content">
+			4、与授权合作伙伴共享:仅为实现本隐私政策中声明的目的,我们的某些服务将由我们和授权合作伙伴共同提供。我们可能会与合作伙伴共享您的某些个人信息,以提供更好的客户服务和用户体验。例如安排合作伙伴提供服务。我们仅会出于合法、正当、必要、特定、明确的目的共享您的个人信息,并且只会共享提供服务所必要的个人信息。我们的合作伙伴无权将共享的个人信息用于与产品或服务无关的其他用途。
+			目前,我们的授权合作伙伴包括以下类型:
+		</view>
+		<view class="content">
+			(1)广告、分析服务类的授权合作伙伴。除非得到您的许可,否则我们不会将您的个人身份信息(指可以识别您身份的信息,例如姓名或电子邮箱,通过这些信息可以联系到您或识别您的身份)与提供广告、分析服务的合作伙伴共享。我们会向这些合作伙伴提供有关其广告覆盖面和有效性的信息,而不会提供您的个人身份信息,或者我们将这些信息进行汇总,以便它不会识别您个人。例如,只有在广告主同意遵守我们的广告发布准则后,我们才可能会告诉广告主他们广告的效果如何,或者有多少人看了他们广告或在看到广告后安装了应用,或者向这些合作伙伴提供不能识别个人身份的统计信息(例如“男性,25-29岁,位于北京”),帮助他们了解其受众或顾客。
+		</view>
+		<view class="content">
+			(2)供应商、服务提供商和其他合作伙伴。我们将信息发送给支持我们业务的供应商、服务提供商和其他合作伙伴,这些支持包括提供技术基础设施服务、分析我们服务的使用方式、衡量广告和服务的有效性、提供客户服务、支付便利或进行学术研究和调查。
+			对我们与之共享个人信息的公司、组织和个人,我们会与其签署严格的数据保护协定,要求他们按照我们的说明、本隐私政策以及其他任何相关的保密和安全措施来处理个人信息。
+		</view>
+		<view class="title">(二)转让</view>
+		<view class="content">我们不会将您的个人信息转让给任何公司、组织和个人,但以下情况除外:</view>
+		<view class="content">1、在获取明确同意的情况下转让:获得您的明确同意后,我们会向其他方转让您的个人信息;</view>
+		<view class="content">
+			2、在涉及合并、收购或破产清算情形,或其他涉及合并、收购或破产清算情形时,如涉及到个人信息转让,我们会要求新的持有您个人信息的公司、组织继续受本政策的约束,否则我们将要求该公司、组织和个人重新向您征求授权同意。
+		</view>
+		<view class="title">(三)公开披露</view>
+		<view class="content">我们仅会在以下情况下,公开披露您的个人信息:</view>
+		<view class="content">1、获得您明确同意或基于您的主动选择,我们可能会公开披露您的个人信息;</view>
+		<view class="content">
+			2、如果我们确定您出现违反法律法规或严重违反“正一商城”相关协议规则的情况,或为保护“正一商城”及其关联公司用户或公众的人身财产安全免遭侵害,我们可能依据法律法规或“正一商城”相关协议规则征得您同意的情况下披露关于您的个人信息,包括相关违规行为以及“正一商城”已对您采取的措施。
+		</view>
+		<view class="title">(四)共享、转让、公开披露个人信息时事先征得授权同意的例外</view>
+		<view class="content">以下情形中,共享、转让、公开披露您的个人信息无需事先征得您的授权同意:</view>
+		<view class="content">1、与国家安全、国防安全有关的;</view>
+		<view class="content">2、与公共安全、公共卫生、重大公共利益有关的;</view>
+		<view class="content">3、与犯罪侦查、起诉、审判和判决执行等有关的;</view>
+		<view class="content">4、出于维护您或其他个人的生命、财产等重大合法权益但又很难得到本人同意的;</view>
+		<view class="content">5、您自行向社会公众公开的个人信息;</view>
+		<view class="content">6、从合法公开披露的信息中收集个人信息的,如合法的新闻报道、政府信息公开等渠道。</view>
+		<view class="content">
+			根据法律规定,共享、转让经去标识化处理的个人信息,且确保数据接收方无法复原并重新识别个人信息主体的,不属于个人信息的对外共享、转让及公开披露行为,对此类数据的保存及处理将无需另行向您通知并征得您的同意。
+		</view>
+		<view class="title">四、我们如何保护您的个人信息安全</view>
+		<view class="content">
+			(一)我们已采取符合业界通用解决方案、合理可行的安全防护措施保护您提供的个人信息安全,防止个人信息遭到未经授权访问、公开披露、使用、修改、损坏或丢失。例如,在您的浏览器与服务器之间交换数据(如信用卡信息)时受
+			SSL(Secure Socket
+			Layer)协议加密保护;我们会使用加密技术提高个人信息的安全性;我们会使用受信赖的保护机制防止个人信息遭到恶意攻击;我们会部署访问控制机制,尽力确保只有授权人员才可访问个人信息;以及我们会举办安全和隐私保护培训课程,加强员工对于保护个人信息重要性的认识。
+		</view>
+		<view class="content">
+			(二)我们有行业先进的以数据为核心,围绕数据生命周期进行的数据安全管理体系,从组织建设、制度设计、人员管理、产品技术等方面多维度提升整个系统的安全性。
+		</view>
+		<view class="content">
+			(三)我们会采取合理可行的措施,尽力避免收集无关的个人信息。我们只会在达成本政策所述目的所需的期限内保留您的个人信息,除非需要延长保留期或受到法律的允许。
+		</view>
+		<view class="content">
+			(四)互联网并非绝对安全的环境,我们强烈建议您不要使用非“正一商城”推荐的通信方式发送个人信息。您可以通过我们的服务建立联系和相互分享。当您通过我们的服务创建交流、交易或分享时,您可以自主选择沟通、交易或分享的对象,作为能够看到您的交易内容、联络方式、交流信息或分享内容等相关信息的第三方。
+			如您发现自己的个人信息尤其是您的账户或密码发生泄露,请您立即联络“正一商城”用户服务的相关人员,以便我们根据您的申请采取相应措施。
+			请注意,您在使用我们服务时自愿共享甚至公开分享的信息,可能会涉及您或他人的个人信息甚至个人敏感信息,如您选择上传包含个人信息的图片。请您更加谨慎地考虑,是否在使用我们的服务时共享甚至公开分享相关信息。
+			请使用复杂密码,协助我们保证您的账号安全。我们将尽力保障您发送给我们的任何信息的安全性。 同时,我们还将按照监管部门要求,上报个人信息安全事件的处置情况。
+		</view>
+		<view class="title">五、您如何管理您的个人信息</view>
+		<view class="content">您可以通过以下方式访问及管理您的个人信息:</view>
+		<view class="content">(一)访问您的个人信息</view>
+		<view class="content">
+			您有权访问您的个人信息,法律法规规定的例外情况除外。您可以通过以下方式自行访问您的个人信息:
+			个人资料—如果您希望访问或编辑您个人资料中的昵称、头像、签名、性别等,您可以通过登录账户通过-“编辑”执行此类操作。
+			如果您无法通过上述路径访问该等个人信息,您可以加入QQ群““正一商城”用户反馈群‘与我们取得联系。
+		</view>
+		<view class="content">(二)更正或补充您的个人信息</view>
+		<view class="content">
+			当您发现我们处理的关于您的个人信息有错误时,您有权要求我们做出更正或补充。您可以通过本条“(一)访问您的个人信息”中列明的方式提出更正或补充申请。
+		</view>
+		<view class="content">(三)删除您的个人信息</view>
+		<view class="content">您可以通过本条“(一)访问您的个人信息”中列明的方式删除您的部分个人信息。</view>
+		<view class="content">在以下情形中,您可以向我们提出删除个人信息的请求:</view>
+		<view class="content">1、如果我们处理个人信息的行为违反法律法规;</view>
+		<view class="content">2、如果我们收集、使用您的个人信息,却未征得您的明确同意;</view>
+		<view class="content">3、如果我们处理个人信息的行为严重违反了与您的约定;</view>
+		<view class="content">4、如果您不再使用我们的产品或服务;</view>
+		<view class="content">5、如果我们永久不再为您提供产品或服务。</view>
+		<view class="content">
+			若我们决定响应您的删除请求,我们还将同时尽可能通知从我们处获得您的个人信息的主体,要求其及时删除,除非法律法规另有规定,或这些主体获得您的独立授权。
+			当您从我们的服务中删除信息后,我们可能不会立即从备份系统中删除相应的信息,但会在备份更新时删除这些信息。
+		</view>
+		<view class="content">(四)改变您授权同意的范围</view>
+		<view class="content">
+			每个业务功能需要一些基本的个人信息才能得以完成(见本隐私政策“第一条”)。除此之外,对于额外个人信息的收集和使用,您可以在设置或与“正一商城”客服联系给予或收回您的授权同意。
+			当您收回同意后,我们将不再处理相应的个人信息。但您收回同意的决定,不会影响此前基于您的授权而开展的个人信息处理。
+		</view>
+		<view class="content">(五)约束信息系统自动决策</view>
+		<view class="content">
+			在某些业务功能中,我们可能仅依据信息系统、算法等在内的非人工自动决策机制做出决定。如果这些决定显著影响您的合法权益,您有权要求我们做出解释,我们也将在不侵害“正一商城”商业秘密或其他用户权益、社会公共利益的前提下提供申诉方法。
+		</view>
+		<view class="content">(六)响应您的上述请求</view>
+		<view class="content">
+			为保障安全,您可能需要提供书面请求,或以其他方式证明您的身份。我们可能会先要求您验证自己的身份,然后再处理您的请求。
+			我们将在30天内做出答复。如您不满意,还可以通过“正一商城”客服发起投诉。
+			对于您合理的请求,我们原则上不收取费用,但对多次重复、超出合理限度的请求,我们将视情收取一定成本费用。对于那些无端重复、需要过多技术手段(例如,需要开发新系统或从根本上改变现行惯例)、给他人合法权益带来风险或者非常不切实际的请求,我们可能会予以拒绝。
+			在以下情形中,按照法律法规要求,我们将无法响应您的请求:
+		</view>
+		<view class="content">1、与国家安全、国防安全有关的;</view>
+		<view class="content">2、与公共安全、公共卫生、重大公共利益有关的;</view>
+		<view class="content">3、与犯罪侦查、起诉、审判和执行判决等有关的;</view>
+		<view class="content">4、有充分证据表明个人信息主体存在主观恶意或滥用权利的;</view>
+		<view class="content">5、响应您的请求将导致您或其他个人、组织的合法权益受到严重损害的;</view>
+		<view class="content">6、涉及商业秘密的。</view>
+		<view class="title">六、我们如何处理未成年人的个人信息</view>
+		<view class="content">
+			如果没有父母或监护人的同意,未成年人不得创建自己的用户账户。如您为未成年人的,建议您请您的父母或监护人仔细阅读本隐私政策,并在征得您的父母或监护人同意的前提下使用我们的服务或向我们提供信息。
+			对于经父母或监护人同意使用我们的产品或服务而收集未成年人个人信息的情况,我们只会在法律法规允许、父母或监护人明确同意或者保护未成年人所必要的情况下使用、共享、转让或披露此信息。
+		</view>
+		<view class="title">七、您的个人信息如何在全球范围转移</view>
+		<view class="content">我们在中华人民共和国境内运营中收集和产生的个人信息,存储在中国境内,以下情形除外:</view>
+		<view class="content">1、法律法规有明确规定;</view>
+		<view class="content">2、获得您的明确授权;</view>
+		<view class="content">3、您通过互联网进行跨境直播/发布动态等个人主动行为。</view>
+		<view class="content">针对以上情形,我们会确保依据本隐私政策对您的个人信息提供足够的保护。</view>
+		<view class="title">八、本隐私政策如何更新</view>
+		<view class="content">我们的隐私政策可能变更。</view>
+		<view class="content">
+			未经您明确同意,我们不会限制您按照本隐私政策所应享有的权利。对于重大变更,我们会提供显著的通知(包括我们会通过“正一商城”公示的方式进行通知甚至向您提供弹窗提示)。
+			本政策所指的重大变更包括但不限于:
+		</view>
+		<view class="content">1、我们的服务模式发生重大变化。如处理个人信息的目的、处理的个人信息类型、个人信息的使用方式等;</view>
+		<view class="content">2、我们在控制权等方面发生重大变化。如并购重组等引起的所有者变更等;</view>
+		<view class="content">3、个人信息共享、转让或公开披露的主要对象发生变化;</view>
+		<view class="content">4、您参与个人信息处理方面的权利及其行使方式发生重大变化;</view>
+		<view class="content">5、我们负责处理个人信息安全的责任部门、联络方式及投诉渠道发生变化时;</view>
+		<view class="content">6、个人信息安全影响评估报告表明存在高风险时。</view>
+		<view class="content pb30">我们还会将本隐私政策的旧版本存档,供您查阅。</view>
+	</view>
+</template>
+
+<script>
+	export default {};
+</script>
+
+<style>
+	.box{
+		padding: 30rpx;
+	}
+.title {
+	font-size: 32rpx;
+	font-weight: 700;
+	line-height: 2;
+	
+}
+.content {
+	font-size: 28rpx;
+	color: #666;
+	line-height: 2;
+}
+.pb10{
+	font-size: 28rpx;
+}
+</style>

+ 137 - 0
pages/contract/start.vue

@@ -0,0 +1,137 @@
+<template>
+	<view class="start">
+		<view class="background"></view>
+		<view class="popup">
+			<view class="title">温馨提示</view>
+			<scroll-view :scroll-y="true" class="content">
+				<text>欢迎使用正一商城APP。我们非常重视您的用户权益和个人信息的保护,在您使用正一商城APP服务前,请认真阅读</text>
+				<text class="money" @click="goUser">《用户协议》</text>
+				<text>和</text>
+				<text class="money" @click="goYs">《隐私政策》</text>
+				<text>
+					全部条款。我们将通过上述协议向您说明我们如何为您提供服务并保障您的用户权益,
+					如何收集、使用、保存、共享和保护您的相关信息,以及我们为您提供的访问、更正、删除和申诉您信息相关问题的方式。
+					我们会严格按照您的授权,在上述协议约定的范围内收集、存储和使用您的注册信息、设备信息、位置信息、日志信息或其他经您授权的信息。
+					您点击“同意并继续”视为您已同意上述协议的全部内容
+				</text>
+			</scroll-view>
+			<view class="button flex">
+				<text class="disagree" @click="disagree">不同意</text>
+				<text class="agree" @click="agree">同意并继续</text>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {};
+	},
+	onLoad() {
+		let agree = uni.getStorageSync('agree');
+		if (agree) {
+			// this.agree()
+			uni.redirectTo({ url: '/pages/index/index' });
+		}
+	},
+	methods: {
+		//前往用户协议
+		goUser() {
+			uni.navigateTo({ url: './agreement' });
+		},
+		goYs() {
+			uni.navigateTo({ url: './privacy' });
+		},
+		//不同意
+		disagree() {
+			plus.runtime.quit();
+		},
+		//同意
+		agree() {
+			uni.setStorageSync('agree', true);
+			uni.switchTab({
+				url: '/pages/index/index',
+				success(e) {
+					console.log(e);
+				},
+				fail(e) {
+					console.log(e);
+				}
+			});
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+.money {
+	color: $base-color;
+}
+.disagree {
+	padding: 10rpx 30rpx;
+	font-size: 28rpx;
+	width: 200rpx;
+	height: 64rpx;
+	color: $base-color;
+	border-radius: 999rpx;
+	border: 2rpx solid $base-color;
+}
+.agree {
+	padding: 10rpx 30rpx;
+	width: 210rpx;
+	height: 64rpx;
+	font-size: 28rpx;
+	color: #fff;
+	background-color: $base-color;
+	border-radius: 999rpx;
+	border: 2rpx solid $base-color;
+}
+.button {
+	position: absolute;
+	left: 0;
+	right: 0;
+	bottom: 0;
+	z-index: 0;
+	display: flex;
+	padding: 24rpx;
+	justify-content: center;
+	text-align: center;
+	justify-content: space-around;
+}
+.content {
+	position: absolute;
+	left: 0;
+	right: 0;
+	top: 100rpx;
+	bottom: 120rpx;
+	z-index: 0;
+	font-size: 28rpx;
+	padding: 0 50rpx;
+	line-height: 44rpx;
+}
+.title {
+	font-size: 36rpx;
+	padding: 20rpx 50rpx;
+}
+.background {
+	position: fixed;
+	left: 0;
+	right: 0;
+	top: 0;
+	bottom: 0;
+	z-index: 0;
+	background-color: rgba(0, 0, 0, 0.4);
+}
+.popup {
+	position: absolute;
+	z-index: 0;
+	left: 50%;
+	top: 50%;
+	transform: translate3d(-50%, -50%, 0);
+	width: 600rpx;
+	height: 700rpx;
+	background-color: #fff;
+	border-radius: 30rpx;
+}
+</style>

+ 198 - 0
pages/coupon/consumer.vue

@@ -0,0 +1,198 @@
+<template>
+	<view class="content">
+		<!-- <view class="navbar">
+			<view v-for="(item, index) in navList" :key="index" class="nav-item" :class="{ current: tabCurrentIndex === index }" @click="tabClick(index)">{{ item.text }}</view>
+		</view> -->
+		<swiper :current="tabCurrentIndex" class="swiper-box" duration="300" @change="changeTab">
+			<swiper-item class="tab-content" v-for="(tabItem, tabIndex) in navList" :key="tabIndex">
+				<scroll-view class="list-scroll-content" scroll-y @scrolltolower="loadData">
+					<!-- 空白页 -->
+					<empty v-if="tabItem.loaded === true && tabItem.orderList.length === 0"></empty>
+					<!-- 订单列表 -->
+					<view v-for="(item, index) in tabItem.orderList" :key="index" class="order-item flex">
+						<view class="title-box">
+							<view class="title">
+								<text>{{ item.mark }}</text>
+							</view>
+							<view class="time">
+								<text>{{ item.add_time }}</text>
+							</view>
+						</view>
+						<view class="money">
+							<text>{{ (item.pm == 0 ? '-' : '+') + item.number }}</text>
+						</view>
+					</view>
+					<uni-load-more :status="tabItem.loadingType"></uni-load-more>
+				</scroll-view>
+			</swiper-item>
+		</swiper>
+	</view>
+</template>
+
+<script>
+	
+import { consumerList } from '@/api/integral.js';
+import uniLoadMore from '@/components/uni-load-more/uni-load-more.vue';
+import empty from '@/components/empty';
+export default {
+	components: {
+		empty,
+		uniLoadMore
+	},
+	onReady() {
+		
+	},
+	data() {
+		return {
+			tabCurrentIndex: 0,
+			navList: [
+				{
+					state: 0,
+					text: '全部',
+					loadingType: 'more',
+					orderList: [],
+					page: 1, //当前页数
+					limit: 10 //每次信息条数
+				},
+			],
+		};
+	},
+	onShow() {
+		// 载入积分数据
+		this.loadData();
+	},
+	methods: {
+		// 页面跳转
+		navto(e) {
+			uni.navigateTo({
+				url: e
+			});
+		},
+		//获取收入支出信息
+		async loadData(source) {
+			//这里是将订单挂载到tab列表下
+			let index = this.tabCurrentIndex;
+			let navItem = this.navList[index];
+			let state = navItem.state;
+			if (source === 'tabChange' && navItem.loaded === true) {
+				//tab切换只有第一次需要加载数据
+				return;
+			}
+			if (navItem.loadingType === 'loading') {
+				//防止重复加载
+				return;
+			}
+			// 修改当前对象状态为加载中
+			navItem.loadingType = 'loading';
+
+			consumerList(
+				{
+					page: navItem.page,
+					limit: navItem.limit
+				}
+			)
+				.then(({ data }) => {
+					if (data.length > 0) {
+						navItem.orderList = navItem.orderList.concat(data);
+						navItem.page++;
+					}
+					if (navItem.limit == data.length) {
+						//判断是否还有数据, 有改为 more, 没有改为noMore
+						navItem.loadingType = 'more';
+						return;
+					} else {
+						//判断是否还有数据, 有改为 more, 没有改为noMore
+						navItem.loadingType = 'noMore';
+					}
+					uni.hideLoading();
+					this.$set(navItem, 'loaded', true);
+				})
+				.catch(e => {
+					console.log(e);
+				});
+		},
+
+		//swiper 切换
+		changeTab(e) {
+			this.tabCurrentIndex = e.target.current;
+			this.loadData('tabChange');
+		},
+		//顶部tab点击
+		tabClick(index) {
+			this.tabCurrentIndex = index;
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+page {
+	background: #ffffff;
+	height: 100%;
+}
+.navbar {
+	display: flex;
+	height: 40px;
+	padding: 0 5px;
+	background: #fff;
+	box-shadow: 0 1px 5px rgba(0, 0, 0, 0.06);
+	position: relative;
+	z-index: 10;
+	.nav-item {
+		flex: 1;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		height: 100%;
+		font-size: 15px;
+		color: $font-color-dark;
+		position: relative;
+		&.current {
+			color: $base-color;
+			&:after {
+				content: '';
+				position: absolute;
+				left: 50%;
+				bottom: 0;
+				transform: translateX(-50%);
+				width: 44px;
+				height: 0;
+				border-bottom: 2px solid $base-color;
+			}
+		}
+	}
+}
+// 列表
+
+.swiper-box {
+	height: calc(100% - 44px);
+	padding-top: 10rpx;
+	.order-item {
+		padding: 20rpx 30rpx;
+		line-height: 1.5;
+		.title-box {
+			.title {
+				font-size: $font-lg;
+				color: $font-color-base;
+			}
+			.time {
+				font-size: $font-base;
+				color: $font-color-light;
+			}
+		}
+		.money {
+			color: #fd5b23;
+			font-size: $font-lg;
+		}
+	}
+}
+.list-scroll-content {
+	height: 100%;
+}
+.content {
+	height: 100%;
+	.empty-content {
+		background-color: #ffffff;
+	}
+}
+</style>

+ 307 - 0
pages/coupon/coupon.vue

@@ -0,0 +1,307 @@
+<template>
+	<view class="content">
+		<view class="navbar">
+			<view v-for="(item, index) in navList" :key="index" class="nav-item" :class="{ current: tabCurrentIndex === index }" @click="tabClick(index)">{{ item.text }}</view>
+		</view>
+		<swiper :current="tabCurrentIndex" class="swiper-box" duration="300" @change="changeTab">
+			<swiper-item class="tab-content" v-for="(tabItem, tabIndex) in navList" :key="tabIndex">
+				<!-- 空白页 -->
+				<empty v-if="tabItem.loaded === true && tabItem.orderList.length === 0"></empty>
+				<view v-for="(item, index) in tabItem.orderList" :key="index" class="row flex">
+					<view class="list-money flex">
+						<image :src="item._type == 2 ? '/static/img/img08.png' : '/static/img/img07.png'" mode="scaleToFill"></image>
+						<view class="list-money-text">
+							<view class="tit" :class="{ action: item._type == 2 }">
+								<text>{{ +item.coupon_price.replace(',', '') }}</text>
+							</view>
+							<view class="price">
+								<text>满{{ +item.use_min_price.replace(',', '') }}元</text>
+							</view>
+						</view>
+					</view>
+					<view class="list-interval position-relative">
+						<view class="bottom"></view>
+						<view class="top"></view>
+					</view>
+					<view class="row_list_right">
+						<view class="right_top">
+							<!-- <text class="right_name">【满减券】</text> -->
+							<text class="right_title" :class="{ action: item._type == 2 }">{{ item.coupon_title }}</text>
+						</view>
+						<view class="right_time">
+							<text>{{ item._add_time }}-{{ item._end_time }}</text>
+						</view>
+						<view class="right_use action" v-if="item._type == 2">
+							<text>{{ item._msg }}</text>
+						</view>
+						<view class="right_use noAction" v-if="item._type == 0">
+							<text>{{ item._msg }}</text>
+						</view>
+					</view>
+				</view>
+				<uni-load-more :status="tabItem.loadingType"></uni-load-more>
+			</swiper-item>
+		</swiper>
+	</view>
+</template>
+
+<script>
+import uniLoadMore from '@/components/uni-load-more/uni-load-more.vue';
+import empty from '@/components/empty';
+import { getCouponsList } from '@/api/coupon.js';
+export default {
+	components: {
+		uniLoadMore,
+		empty
+	},
+	data() {
+		return {
+			tabCurrentIndex: 0,
+			navList: [
+				{
+					state: 0,
+					text: '全部',
+					loadingType: 'more',
+					orderList: [],
+					page: 1, //当前页数
+					limit: 10 //每次信息条数
+				},
+				{
+					state: 1,
+					text: '未使用',
+					loadingType: 'more',
+					orderList: [],
+					page: 1, //当前页数
+					limit: 10 //每次信息条数
+				},
+				{
+					state: 2,
+					text: '已使用',
+					loadingType: 'more',
+					orderList: [],
+					page: 1, //当前页数
+					limit: 10 //每次信息条数
+				}
+			]
+		};
+	},
+	onLoad(options) {
+		this.loadData();
+	},
+	methods: {
+		// 返回首页
+		navTo() {
+			uni.switchTab({
+				url: '/pages/index/index'
+			});
+		},
+		//获取订单列表
+		loadData(source) {
+			//这里是将订单挂载到tab列表下
+			let index = this.tabCurrentIndex;
+			let navItem = this.navList[index];
+			let state = navItem.state;
+			if (source === 'tabChange' && navItem.loaded === true) {
+				//tab切换只有第一次需要加载数据
+				return;
+			}
+			if (navItem.loadingType === 'loading') {
+				//防止重复加载
+				return;
+			}
+			// 修改当前对象状态为加载中
+			navItem.loadingType = 'loading';
+			getCouponsList(
+				{
+					page: navItem.page,
+					limit: navItem.limit
+				},
+				index
+			)
+				.then(({ data }) => {
+					navItem.orderList = navItem.orderList.concat(data);
+					console.log(navItem.orderList);
+					navItem.page++;
+					if (navItem.limit == data.length) {
+						//判断是否还有数据, 有改为 more, 没有改为noMore
+						navItem.loadingType = 'more';
+						return;
+					} else {
+						//判断是否还有数据, 有改为 more, 没有改为noMore
+						navItem.loadingType = 'noMore';
+					}
+					uni.hideLoading();
+					this.$set(navItem, 'loaded', true);
+				})
+				.catch(e => {
+					console.log(e);
+				});
+		},
+
+		//swiper 切换
+		changeTab(e) {
+			this.tabCurrentIndex = e.target.current;
+			this.loadData('tabChange');
+		},
+		//顶部tab点击
+		tabClick(index) {
+			this.tabCurrentIndex = index;
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+// 卡卷可用时颜色
+$card-color-action: #fc4141;
+
+.swiper-box {
+	height: calc(100% - 40px);
+	.tab-content {
+		padding: 25rpx 0px;
+		font-size: 28rpx;
+		color: #1b1b1b;
+	}
+}
+.row {
+	border-radius: 15rpx;
+	margin: 0 25rpx;
+	margin-bottom: 25rpx;
+	height: 200rpx;
+	overflow: hidden;
+	background-color: #ffffff;
+	.list-interval {
+		border: 1px dashed $border-color-light;
+		height: 100%;
+		.top,
+		.bottom {
+			border-radius: 100rpx;
+			width: 30rpx;
+			height: 30rpx;
+			position: absolute;
+			background-color: $page-color-base;
+			right: -15rpx;
+		}
+		.top {
+			top: -18rpx;
+		}
+		.bottom {
+			bottom: -18rpx;
+		}
+	}
+	.list-money {
+		height: 100%;
+		image {
+			height: 100%;
+			width: 20rpx;
+		}
+		.list-money-text {
+			width: 220rpx;
+			padding: 0 25rpx;
+			text-align: center;
+			color: $font-color-light;
+			.tit {
+				padding: 15rpx 0rpx;
+				font-size: 55rpx;
+				font-weight: bold;
+				&.action {
+					color: $card-color-action;
+				}
+			}
+			.price {
+				padding-bottom: 25rpx;
+			}
+		}
+	}
+	.row_list_right {
+		flex-grow: 1;
+		padding-left: 25rpx;
+		line-height: 1;
+		.right_time {
+			color: $font-color-light;
+			font-size: $font-sm;
+		}
+		.right_use {
+			margin: 15rpx 0;
+			padding: 10rpx;
+			width: 140rpx;
+			text-align: center;
+			border-radius: 50rpx;
+			color: #fff;
+			font-size: $font-sm - 4rpx;
+			&.action {
+				background-color: $card-color-action;
+			}
+			&.noAction {
+				background-color: $color-gray;
+			}
+		}
+		.right_top {
+			margin: 15rpx 0;
+			font-size: $font-lg;
+			height: 50rpx;
+			color: $font-color-light;
+			.right_name {
+				font-weight: bold;
+			}
+			.right_title {
+				font-weight: bold;
+				&.action {
+					color: $font-color-base;
+				}
+			}
+		}
+	}
+
+	.iconlocation {
+		font-size: 36rpx;
+		color: $font-color-light;
+	}
+}
+page,
+.content {
+	background: $page-color-base;
+	height: 100%;
+}
+
+.navbar {
+	display: flex;
+	height: 40px;
+	padding: 0 5px;
+	background: #fff;
+	box-shadow: 0 1px 5px rgba(0, 0, 0, 0.06);
+	position: relative;
+	z-index: 10;
+	.nav-item {
+		flex: 1;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		height: 100%;
+		font-size: 15px;
+		color: $font-color-dark;
+		position: relative;
+		&.current {
+			color: #bc253a;
+			&:after {
+				content: '';
+				position: absolute;
+				left: 50%;
+				bottom: 0;
+				transform: translateX(-50%);
+				width: 44px;
+				height: 0;
+				border-bottom: 2px solid #bc253a;
+			}
+		}
+	}
+}
+/* load-more */
+.uni-load-more {
+	display: flex;
+	flex-direction: row;
+	height: 80rpx;
+	align-items: center;
+	justify-content: center;
+}
+</style>

+ 372 - 0
pages/coupon/details.vue

@@ -0,0 +1,372 @@
+<template>
+	<view class="content">
+		<!-- <view class="flex_item coupon">
+			<view class="coupon_img"><image src="/static/xpy/025.png"></image></view>
+			<view class="coupon_name">
+				<view class="coupon_text">星拼乐100元商城购物卡通用元商城购物卡通用</view>
+				<view class="coupon_money">¥100</view>
+			</view>
+		</view> -->
+		<view class="row-box">
+			<view class="title">付款金额</view>
+			<view class="row">
+				<text class="tit">¥</text>
+				<input class="input" type="number" v-model="money" placeholder="请输入转让金额" placeholder-class="placeholder" />
+			</view>
+			<button class="add-btn up" :class="{ 'active-bg': payLoding }" @click="!payLoding ? confirm() : ''">生成二维码</button>
+		</view>
+		<view class="coupon_transfer" v-if="showcode">
+			<view class="erwema">
+				<tki-qrcodes
+					:cid="cid"
+					ref="qrcode"
+					:val="val"
+					:size="size"
+					:unit="unit"
+					:background="background"
+					:foreground="foreground"
+					:pdground="pdground"
+					:icon="icon"
+					:iconSize="iconSize"
+					:lv="lv"
+					:onval="onval"
+					:loadMake="loadMake"
+					:usingComponents="usingComponents"
+					@result="qrR"
+				></tki-qrcodes>
+			</view>
+			<view class="upload" @click="upload()">复制二维码</view>
+			<view class="transfer">通过扫描此二维码转让购物卡</view>
+			<!-- 	<view class="transfer_image" @click="baocun(image)"><image :src="image"></image></view> -->
+		</view>
+		<!-- <view class="orderDetialBox">
+			<view class="f-header m-t">
+				<view class="f-left-ic····························on"></view>
+				<view class="tit-box"><text class="tit">卡片信息</text></view>
+			</view>
+			<view class="item flex">
+				<view class="title-left flex">
+					<text class="title">订单编号:</text>
+					<view class="text">45875487854</view>
+				</view>
+			</view>
+			<view class="item flex">
+				<view class="title-left flex">
+					<text class="title">付款时间:</text>
+					<view class="text">2018-09-09 12:00:31</view>
+				</view>
+			</view>
+			<view class="item flex">
+				<view class="title-left flex">
+					<text class="title">拼中时间:</text>
+					<view class="text">2018-09-09 12:00:31</view>
+				</view>
+			</view>
+		</view> -->
+	</view>
+</template>
+
+<script>
+import { rechargemoneys } from '@/api/wallet.js';
+import tkiQrcodes from '@/components/tki-qrcode/tki-qrcode.vue';
+import { orderDetail } from '@/api/order.js';
+export default {
+	components: { tkiQrcodes },
+	props: {
+		qrval: {
+			// 要生成的二维码值
+			type: String
+		}
+	},
+	data() {
+		return {
+			image: 'http://img03.taobaocdn.com/tfscom/TB2Drm1jVXXXXakXpXXXXXXXXXX_!!2-dgshop.png_300x300.jpg',
+			payLoding: false, //是否加载中
+			showcode: false, //显示二维码页面
+			money: '',
+			url: '',
+			uid: '',
+			qrsize: 120, // 二维码大小
+			cid: 'tki-qrcode-canvas', //canvasId,页面存在多个二维码组件时需设置不同的ID
+			size: 180, //生成的二维码大小
+			unit: 'upx', //大小单位尺寸
+			// show: true,//默认使用组件中的image标签显示二维码
+			val: '', //要生成的内容
+			background: '#ffffff', //二维码背景色
+			foreground: '#333333', //二维码前景色
+			pdground: '#333333', //二维码角标色
+			icon: '', //二维码图标URL(必须是本地图片,网络图需要先下载至本地)
+			iconSize: 40, //二维码图标大小
+			lv: 3, //容错级别
+			onval: true, //监听val值变化自动重新生成二维码
+			loadMake: false, //组件初始化完成后自动生成二维码,val需要有值
+			usingComponents: false, //是否使用了自定义组件模式(主要是为了修复非自定义组件模式时 v-if 无法生成二维码的问题)
+			showLoading: false, //是否显示loading
+			loadingText: '二维码生成中', //loading文字
+			src: '', // 二维码生成后的图片地址或base64
+			ratio: 1, //页面比例用于计算
+			ctxSrc: '', //要显示的图片
+			loading: true, //是否载入图片中
+			canHeight: '',
+			canWeidth: ''
+		};
+	},
+	onLoad() {
+		this.loadlist;
+		let value = uni.getStorageSync('userInfo');
+		this.uid = value.uid;
+	},
+	methods: {
+		// 創建二维码
+		creatQrcode() {
+			console.log(this.$refs.qrcode._makeCode);
+			this.$refs.qrcode._makeCode();
+		},
+		// 保存二维码到图库
+		saveQrcode() {
+			this.$refs.qrcode._saveCode();
+		},
+		// 生成二维码后返回base64
+		qrR(res) {
+			this.src = res;
+		},
+		//清空二维码(清空二维码会触发result回调 返回值为空)
+		clearQrcode(e) {
+			this.$refs.qrcode._clearCode();
+			this.val = '';
+		},
+		// 载入订单详细
+		loadlist() {},
+		// 提交
+		confirm() {
+			let obj = this;
+			if (!obj.money || obj.money == '') {
+				uni.showToast({
+					title: '请填写转让金额',
+					icon: 'none',
+					duration: 2000
+				});
+				return;
+			}
+			obj.showcode = true;
+			obj.payLoding = true;
+			/**rechargemoneys({
+				money: obj.money,
+			})
+				.then(e => {
+					 console.log(e.data)
+					 obj.val='{"url":"'+e.data.url+'"}';
+				})
+				.catch(e => {
+					uni.showModal({
+						title: '失败',
+						content: '转入失败',
+						content: JSON.stringify(e),
+						showCancel: false
+					});
+				});**/
+
+			obj.val = '{"money":"' + obj.money + '","id":"' + obj.uid + '"}';
+			this.$nextTick(function() {
+				this.creatQrcode();
+			});
+		},
+		upload() {
+			this.$refs.qrcode._saveCode();
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+page {
+	background: $page-color-base;
+}
+.asdf {
+	width: 110rpx;
+	height: 110rpx;
+}
+.content {
+	border-top: 2rpx solid #f2f3f5;
+}
+// 订单详细
+.orderDetialBox {
+	margin-top: 20rpx;
+	padding: 0 30rpx;
+	background-color: #ffffff;
+	font-size: $font-base;
+	color: $font-color-base;
+	.item {
+		height: 80rpx;
+		.text {
+			padding-left: 10rpx;
+		}
+		.buttom-right {
+			width: 180rpx;
+			border-radius: 99rpx;
+			padding: 10rpx;
+			text-align: center;
+			border: 1px solid $border-color-light;
+		}
+	}
+}
+
+// 标题头
+.f-header {
+	display: flex;
+	align-items: center;
+	height: 80rpx;
+	.tit-box {
+		@extend %font-title-box;
+		border-bottom: 2rpx solid #f0f0f0;
+		padding: 25rpx 0rpx;
+	}
+	.tit {
+		@extend %font-title;
+	}
+	.f-left-icon {
+		@extend %f-left-icon;
+	}
+}
+// 共有底部高度
+$btHeight: 100rpx;
+.btHeight {
+	height: $btHeight;
+}
+.coupon {
+	width: 100%;
+	background-color: #ffffff;
+	padding: 25rpx 25rpx;
+	font-size: 30rpx;
+	.coupon_img {
+		width: 200rpx;
+		height: 118rpx;
+		margin-right: 15rpx;
+		image {
+			width: 100%;
+			height: 100%;
+		}
+	}
+	.coupon_name {
+		height: 118rpx;
+		width: 70%;
+		.coupon_text {
+			padding-bottom: 25rpx;
+			white-space: nowrap;
+			overflow: hidden;
+			text-overflow: ellipsis;
+			font-weight: bold;
+			color: rgba(51, 51, 51, 1);
+		}
+		.coupon_money {
+			font-weight: 500;
+			color: rgba(102, 102, 102, 1);
+			.coupon_time {
+				padding-left: 25rpx;
+			}
+		}
+	}
+}
+.coupon_transfer {
+	background-color: #ffffff;
+	padding: 40rpx 25rpx;
+	width: 100%;
+	height: 100%;
+	margin-top: 25rpx;
+}
+.transfer_image {
+	width: 100%;
+	height: 220rpx;
+	text-align-last: center;
+}
+.transfer_image image {
+	width: 220rpx;
+	height: 220rpx;
+}
+.upload {
+	width: 28%;
+	background: linear-gradient(90deg, rgba(253, 59, 51, 1) 0%, rgba(254, 75, 52, 1) 100%);
+	border-radius: 10rpx;
+	color: #ffffff;
+	font-size: 26rpx;
+	margin: 25rpx auto;
+	padding: 20rpx 30rpx;
+	text-align: center;
+}
+.transfer {
+	width: 100%;
+	text-align: center;
+	font-size: 26rpx;
+}
+.row-box {
+	margin-top: 30rpx;
+	padding: 20rpx 30rpx;
+	background: #fff;
+	.title {
+		font-size: $font-base + 2rpx;
+		color: $font-color-dark;
+		padding-bottom: 25rpx;
+	}
+	.row {
+		display: flex;
+		align-items: center;
+		position: relative;
+		height: 80rpx;
+		.tit {
+			flex-shrink: 0;
+			width: 40rpx;
+			font-size: 30rpx;
+			color: $font-color-dark;
+		}
+		.input {
+			flex: 1;
+			font-size: 30rpx;
+			color: $font-color-dark;
+		}
+		.iconlocation {
+			font-size: 36rpx;
+			color: $font-color-light;
+		}
+
+		.buttom {
+			color: $font-color;
+			font-size: $font-base;
+		}
+	}
+}
+.add-btn {
+	&.modified {
+		color: $base-color;
+	}
+	&.up {
+		background: #5dbc7c;
+		border-radius: 40px;
+		color: #fff;
+	}
+	&.to {
+		border: 1px solid rgba(252, 42, 63, 1);
+		border-radius: 40px;
+		border-radius: 40px;
+		color: #fc2a3f;
+	}
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	width: 560rpx;
+	height: 75rpx;
+	margin: 0 auto;
+	margin-top: 25rpx;
+	font-size: $font-lg;
+	border-radius: 10rpx;
+	// box-shadow: 1px 2px 5px rgba(219, 63, 96, 0.4);
+}
+.erwema {
+	width: 135px;
+	height: 140px;
+	background-color: #ffffff;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	margin: 0rpx auto;
+}
+</style>

+ 332 - 0
pages/detail/detail.vue

@@ -0,0 +1,332 @@
+<template>
+	<view>
+		<swiper class="carousel" indicator-dots=true circular=true interval="3000" duration="700">
+			<swiper-item v-for="(item,index) in data.imgList" :key="index">
+				<view class="image-wrapper">
+					<image
+						:src="item.src" 
+						:class="item.loaded" 
+						mode="aspectFill"
+						@load="imageOnLoad('imgList', index)" 
+					></image>
+				</view>
+			</swiper-item>
+		</swiper>
+		<view class="scroll-view-wrapper">
+			<scroll-view class="episode-panel" :class="{Skeleton:!loaded}" scroll-x>
+				<view v-for="(item, index) in data.episodeList" :key="index"
+					:class="{current: currentEpd===item}"
+					@click="changeEpd(index)"
+				>
+					{{item}}
+				</view>
+			</scroll-view>
+		</view>
+		<view class="info">
+			<view class="title">
+				<text :class="{Skeleton:!loaded}">{{data.title}}</text>
+				<text :class="{Skeleton:!loaded}">{{data.title2}}</text>
+			</view>
+			<text class="yticon icon-xia"></text>
+		</view>
+		<view class="actions">
+			<text class="yticon icon-fenxiang2" @click="share"></text>
+			<text class="yticon icon-Group-"></text>
+			<text class="yticon icon-shoucang" :class="{active: data.favorite}" @click="favorite"></text>
+		</view>
+
+		<!-- 猜你喜欢 -->
+		<view class="guess">
+			<view class="section-tit">猜你喜欢</view>
+			<view class="guess-list">
+				<view 
+					v-for="(item, index) in data.guessList" :key="index"
+					class="guess-item"
+				>
+					<view class="image-wrapper">
+						<image 
+							:src="item.src" 
+							:class="item.loaded" 
+							mode="aspectFill"
+							@load="imageOnLoad('guessList', index)" 
+						></image>
+					</view>
+					<text class='title clamp' :class="{Skeleton:!loaded}">{{item.title}}</text>
+					<text class="clamp" :class="{Skeleton:!loaded}">{{item.title2}}</text>
+				</view>
+			</view>
+		</view>
+		<!-- 评论 -->
+		<view class="evalution">
+			<view class="section-tit">评论</view>
+			<view class="eva-list" :class="{Skeleton:!loaded}">
+				<view  v-for="(item, index) in data.evaList" :key="index"
+					class="eva-item"
+				>
+					<image :src="item.src" mode="aspectFill"></image>
+					<view class="eva-right">
+						<text>{{item.nickname}}</text>
+						<text>{{item.time}}</text>
+						<view class="zan-box">
+							<text>{{item.zan}}</text>
+							<text class="yticon icon-shoucang"></text>
+						</view>
+						<text class="content">{{item.content}}</text>
+					</view>
+				</view>
+			</view>
+		</view>
+		<!-- 分享 -->
+		<share 
+			ref="share" 
+			:contentHeight="580"
+			:shareList="shareList"
+		></share>
+	</view>
+</template>
+
+<script>
+	import share from '@/components/share';
+	export default {
+		components: {
+			share
+		},
+		data() {
+			return {
+				loaded: false,
+				currentEpd: 1,
+				data: {
+					guessList: [{},{},{},{}] 
+				},
+				shareList: []
+			};
+		},
+		async onLoad(){
+			let detailData = await this.$api.json('detailData');
+			let shareList = await this.$api.json('shareList');
+			this.loaded = true;
+			this.data = detailData;
+			this.shareList = shareList;
+			uni.setNavigationBarTitle({
+				title: detailData.title
+			})
+		},
+		methods:{
+			imageOnLoad(key,index){
+				this.$set(this.data[key][index], 'loaded', 'loaded');
+			},
+			changeEpd(index){
+				let list = this.data.episodeList;
+				let epd = list[index];
+				this.$api.msg(`切换到第${epd}项`);
+				this.currentEpd = epd;
+			},
+			//分享
+			share(){
+				this.$refs.share.toggleMask();	
+			},
+			//收藏
+			favorite(){
+				this.data.favorite = !this.data.favorite;
+			}
+		},
+		//处理遮罩层物理返回键
+		onBackPress(){
+			if(this.$refs.share.show){
+				this.$refs.share.toggleMask();
+				return true;
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	page{
+		background: $page-color-base;
+	}
+
+	.carousel {
+		height: 200px;
+		.image-wrapper{
+			display: flex;
+			justify-content: center;
+			align-content: center;
+			width: 100%;
+			height: 100%;
+			overflow: hidden;
+
+			image {
+				width: 100%;
+				height: 100%;
+			}
+		}
+	}
+	.scroll-view-wrapper{
+		display:flex;
+		align-items:center;
+		height: 90rpx;
+		padding: 20rpx 0 20rpx 40rpx;
+		background: #fff;
+	}
+	.episode-panel {
+		white-space: nowrap;
+		width: 100%;
+		view {
+			display: inline-block;
+			margin-right: 30rpx;
+			width: 56rpx;
+			font-size: $font-lg;
+			color: $font-color-base;
+			&.current{
+				color: #07a7a7;
+			}
+		}
+	}
+
+	.info {
+		display: flex;
+		align-items: center;
+		padding: 10rpx 40rpx;
+		background: #fff;
+
+		.title {
+			flex: 1;
+			display: flex;
+			flex-direction: column;
+			font-size: $font-lg + 4rpx;
+			color: $font-color-dark;
+
+			text:last-child {
+				font-size: $font-sm;
+				color: $font-color-light;
+				margin-top: 4rpx;
+				&.Skeleton{
+					width:220rpx;
+				}
+			}
+		} 
+		.yticon {
+			font-size: 44rpx;
+			color: $font-color-base;
+			margin: 0 10rpx 0 30rpx;
+		}
+	}
+
+	.actions {
+		padding: 10rpx 28rpx;
+		background: #fff;
+
+		.yticon {
+			font-size: 46rpx;
+			color: $font-color-base;
+			padding: 10rpx 12rpx;
+			&.active{
+				color: #ff4443;
+			}
+			&:nth-child(2) {
+				font-size: 50rpx;
+			}
+		}
+	}
+
+	.section-tit {
+		font-size: $font-base+2rpx;
+		color: $font-color-dark;
+		margin-bottom: 30rpx;
+		text-align:center;
+	}
+
+	.guess {
+		display: flex;
+		flex-direction: column;
+		justify-content: center;
+		align-items: center;
+		padding: 30rpx 40rpx 10rpx;
+		margin-top: 16rpx;
+		background: #fff;
+	}
+
+	.guess-list {
+		display: flex;
+		flex-wrap: wrap;
+		width: 100%;
+	}
+	.guess-item {
+		display: flex;
+		flex-direction: column;
+		flex: 1;
+		overflow: hidden;
+		min-width: 40%;
+		margin-right: 26rpx;
+		padding-bottom: 40rpx;
+	
+		&:nth-child(2n) {
+			margin-right: 0;
+		}
+	
+		image {
+			width: 100%;
+			height: 200rpx;
+			border-radius: 10rpx;
+		}
+	
+		text {
+			font-size: $font-sm;
+			color: $font-color-light;
+			&.Skeleton{
+				width: 180rpx;
+				&.title{
+					width: 140rpx;
+				}
+			}
+			&.title{
+				font-size: $font-base+2rpx;
+				color: $font-color-dark;
+				margin-top:16rpx;
+				margin-bottom: 8rpx;
+			}
+		}
+	}
+	.evalution{
+		display:flex;
+		flex-direction:column;
+		background: #fff;
+		margin-top: 16rpx;
+		padding: 40rpx 0;
+	}
+
+	.eva-item{
+		display:flex;
+		padding: 20rpx 40rpx;
+		image{
+			width: 60rpx;
+			height: 60rpx;
+			border-radius: 50px;
+			flex-shrink: 0;
+			margin-right: 24rpx;
+		}
+	}
+	.eva-right{
+		display:flex;
+		flex-direction:column;
+		flex: 1;
+		font-size: $font-sm + 2rpx;
+		color: $font-color-light;
+		position:relative;
+		.zan-box{
+			display:flex;
+			align-items:base-line;
+			position:absolute;
+			top: 10rpx;
+			right: 10rpx;
+			.yticon{
+				margin-left: 8rpx; 
+			}
+		}
+		.content{
+			font-size: $font-base;
+			color: #333;
+			padding-top:20rpx;
+		}
+	}
+</style>

+ 167 - 0
pages/favorites/favorites.vue

@@ -0,0 +1,167 @@
+<template>
+	<view class="container">
+		<!-- 空白页 -->
+		<empty v-if="favoriteList.length < 1"></empty>
+		<view class="favorites flex" v-for="ls in favoriteList" @click="toproduct(ls.pid)">
+			<view class="favorites_img"><image :src="ls.image"></image></view>
+			<view class="favorites_list">
+				<view class="favorites_name">{{ ls.store_name }}</view>
+				<view class="favorites_peice flex">
+					<view>
+						<text>¥{{ ls.price }}</text>
+					</view>
+					<view @click.prevent.stop="del(ls.pid)" v-show="delshow" class="icon_del">
+						<text class="iconfont icondelete"></text>
+						<text>取消</text>
+					</view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+import { getcollectList, delcollect } from '@/api/favorite.js';
+import uniLoadMore from '@/components/uni-load-more/uni-load-more.vue';
+import empty from '@/components/empty';
+export default {
+	components: {
+		uniLoadMore,
+		empty
+	},
+	data() {
+		return {
+			tabCurrentIndex: 0,
+			favoriteList: '',
+			delshow: true
+		};
+	},
+	onLoad() {
+		this.loadData();
+	},
+	methods: {
+		//获取收藏夹列表
+		loadData() {
+			let obj = this;
+			getcollectList({
+				page: '1',
+				limit: '10'
+			})
+				.then(function(e) {
+					obj.favoriteList = e.data;
+					console.log(obj.favoriteList);
+				})
+				.catch(function(e) {
+					console.log(e);
+				});
+		},
+		//删除收藏夹商品
+		del(item) {
+			let obj = this;
+			uni.showModal({
+				title: '提示',
+				content: '是否取消收藏该商品',
+				success: e => {
+					if (e.confirm) {
+						delcollect({
+							id: item,
+							category: 'product'
+						})
+							.then(function(e) {
+								uni.showToast({
+									title: '已取消收藏',
+									duration: 1500,
+								});
+								obj.loadData();
+							})
+							.catch(function(e) {
+								console.log(e);
+							});
+					}
+				}
+			});
+		},
+		//跳转商品详情页
+		toproduct(item) {
+			let id = item;
+			uni.navigateTo({
+				url: `/pages/product/product?id=${id}`
+			});
+		}
+		// //跳转忘记密码
+		// forget() {
+		// 	uni.navigateTo({
+		// 		url: `/pages/public/forget`
+		// 	});
+		// },
+		// // 后退
+		// navBack() {
+		// 	uni.navigateBack();
+		// }
+	}
+};
+</script>
+
+<style lang="scss">
+page {
+	height: 100%;
+}
+%flex-center {
+	display: flex;
+	flex-direction: column;
+	justify-content: center;
+	align-items: center;
+}
+%section {
+	display: flex;
+	justify-content: space-around;
+	align-content: center;
+	background: #fff;
+	border-radius: 10rpx;
+}
+.container {
+	height: 100%;
+	background-color: $page-color-base;
+	padding: 15rpx 0rpx;
+	font-size: 28rpx;
+}
+.favorites {
+	width: 90%;
+	background-color: #ffffff;
+	// height:100%;
+	border-radius: 15rpx;
+	margin: 15rpx auto;
+	padding: 25rpx 25rpx;
+	margin-bottom: 25rpx;
+}
+.favorites_img {
+	width: 80px !important;
+	height: 80px;
+}
+.favorites_img image {
+	width: 100%;
+	height: 100%;
+}
+.favorites_list {
+	width: 70%;
+	padding-left: 20rpx;
+}
+.icon_del {
+	color: $font-color-base;
+	z-index: 9999;
+	font-weight: bold;
+}
+.favorites_name {
+	height: 80rpx;
+	overflow: hidden;
+	text-overflow: ellipsis;
+	display: -webkit-box;
+	-webkit-box-orient: vertical;
+	-webkit-line-clamp: 2;
+}
+.favorites_peice {
+	margin-top: 25rpx;
+	color: #db1935;
+	font-weight: bold;
+}
+</style>

+ 388 - 0
pages/groupBooking/detail.vue

@@ -0,0 +1,388 @@
+<template>
+	<view class="box">
+		<!-- 拼团 -->
+		<view class="lyy-a">
+			<view class="lyy-a-p">
+				<view class="lyy-a-f">
+					<view><image :src="goods.image" class="lyy-a-tu" /></view>
+					<view class="lyy-a-z">
+						<view class="lyy-a-word lyy-a-word2">{{ goods.title }}</view>
+						<view class="flex money-box">
+							<view class="lyy-a-f lyy-a-word margin-r-20">
+								<view class="lyy-a-word3">¥{{ goods.price }}</view>
+							</view>
+							<view class="lyy-a-tu2 lyy-a-f padding-c-20 border-radius-all">
+								<view class="lyy-a-tu3"><image src="http://lxscimg.liuniu946.com/2019-11-02_5dbd110b5928a.png" class="lyy-a-tu5"></image></view>
+								<view class="lyy-a-tu4 flex-shrink-false">{{ goods.people }}人拼</view>
+							</view>
+						</view>
+					</view>
+				</view>
+			</view>
+		</view>
+		<view class="lyy-hx"></view>
+		<!-- 第二部分 -->
+		<view class="lyy-b padding-t-20">
+			<view class="lyy-b-p">
+				<view class="lyy-b-jz flex">
+					<view class="image1"><view class="lyy-b-word">剩余时间</view></view>
+				</view>
+				<view class="lyy-b-jz flex">
+					<uni-countdown
+						v-if="pinkBool==0"
+						color="#FFFFFF"
+						splitor-color="#FC5B62"
+						background-color="#FC5B62"
+						border-color="#FC5B62"
+						:show-day="false"
+						:hour="stopTime.stopTimeH"
+						:minute="stopTime.stopTimeM"
+						:second="stopTime.stopTimeS"
+					></uni-countdown>
+				</view>
+				<view class="lyy-b-jz flex">
+					<span class="lyy-b-word2">{{ pinkT.people }}</span>
+					<span class="lyy-b-word3">人成团,还差{{ peopleNub }}人</span>
+				</view>
+				<view class="lyy-b-jz flex">
+					<view class="cmy-user-box">
+						<view class="user-list">
+							<view class="lyy-y bg-gray"><image :src="pinkT.avatar" class="user-list-img" /></view>
+							<view class="lyy-y-word clamp">{{ pinkT.nickname }}</view>
+						</view>
+						<view class="user-list" v-for="(l, i) in peopleNub" :key="i">
+							<view class="lyy-y bg-gray"></view>
+							<view class="lyy-y-word clamp">待邀请</view>
+						</view>
+					</view>
+				</view>
+				<view class="lyy-b-jz flex">
+					<view class="lyy-b-but" v-if="status == 1&&pinkBool==0" @click="invitation">邀请好友参团</view>
+					<view class="lyy-b-but" v-if="status == 0&&pinkBool==0" @click="goBuy">立即加入</view>
+					<!-- <view class="lyy-b-but" @click="goBuy">立即加入</view> -->
+					<view class="lyy-b-but bg-gray" v-if="pinkBool==-1">拼团失败</view>
+					<view class="lyy-b-but" v-if="pinkBool==1">拼团成功</view>
+				</view>
+			</view>
+		</view>
+		<view class="lyy-hx"></view>
+		<!-- 第三部分 -->
+		<view class="lyy-c">
+			<view class="lyy-c-p">
+				<view class="lyy-c-word">
+					<view>拼团规则:</view>
+					<view>1.点击商品进入商品详情,通过超值拼团进入订单支付 页,用户付款成功后,按页面提示分享给微信好友。</view>
+					<view>2.好友通过分享,加入超值拼团,完成订单支付,待达成 拼团人数后,拼团成功。</view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+import uniCountdown from '@/components/uni-countdown/uni-countdown.vue';
+import { getCombinationLisPink } from '@/api/groupBooking.js';
+import { groupGoods } from '@/api/product.js';
+import { timeComputed } from '@/utils/rocessor.js';
+import { mapState } from 'vuex';
+// 倒计时
+export default {
+	computed: {
+		// 还需要报名的人数
+		peopleNub() {
+			return  this.pinkT.people - 1 - this.people.length 
+		}
+	},
+	data() {
+		return {
+			gp_id: 0, //拼团商品id
+			goods: {}, //商品信息
+			pinkT: {}, //拼团团长信息
+			people: [], //拼团成员信息
+			people_num: 0, //总共需要多少人
+			endTime: 0, //剩余时间
+			status: 0, //判断是否为团长
+			gid: 0,
+			user_info: {}, //当前用户信息
+			// 倒计时
+			stopTime: {
+				stopTimeH: 0,
+				stopTimeM: 0,
+				stopTimeS: 0
+			},
+			pinkBool:0,//拼团状态0为待拼团 -1为拼团失败 1为拼团成功
+			userBool: 0 ,//判断用户是否已经参与拼团 0未参加 1为已参加
+			spread:'',//默认没有邀请人
+			userInfo:{}//当前用户信息
+		};
+	},
+	onLoad(e) {
+		// 保存拼团订单id
+		this.gp_id = e.id;
+		// 判断是否有人邀请
+		if (e.spread) {
+			// 存储邀请人
+			this.spread = e.spread;
+			uni.setStorageSync('spread', option.spread);
+		}
+	},
+	onShow() {
+		this.getData();
+	},
+	components: {
+		uniCountdown
+	},
+	methods: {
+		//前往参团
+		goBuy() {
+			let _self = this;
+			uni.navigateTo({
+				url: '/pages/order/createOrder?pinkId='+this.gp_id+'&type=pink'+'&pid='+this.goods.product_id+'&gid='+this.goods.id+'&merid='+this.goods.mer_id
+			});
+		},
+		//邀请参团
+		invitation() {
+			let obj = this;
+			// 判断拼团是否已经结束
+			if (obj.userBool == 0) {
+				uni.showModal({
+					title: '提示',
+					content: '该拼团已经结束!',
+					showCancel: false,
+					success: res => {},
+					fail: () => {},
+					complete: () => {}
+				});
+				return;
+			}
+			uni.navigateTo({
+				url: '/pages/groupBooking/inviteImg?id='+this.pinkT.id+'&spread='+this.userInfo.uid,
+				success: res => {},
+				fail: (e) => {
+					console.log(e);
+				},
+				complete: () => {}
+			});
+		},
+		// #ifdef H5
+		// 加载微信html5页面分享方法
+		shareDate() {
+			let obj = this;
+			// 判断是否微信浏览器
+			let bool = uni.getStorageSync('weichatBrowser') || '';
+			if (bool) {
+				// 过滤微信强制添加的链接地址
+				url = url.replace('?from=singlemessage', '');
+				let data = {
+					link: url, // 分享链接
+					imgUrl: obj.goodsObjact.image, // 分享图标
+					desc: obj.goodsObjact.store_info,
+					title: obj.goodsObjact.store_name,
+					success: function() {}
+				};
+				obj.weichatObj.updateAppMessageShareData(data);
+				obj.weichatObj.updateTimelineShareData(data);
+			}
+		},
+		// #endif
+		// 获取拼团信息
+		getData() {
+			let obj = this;
+			// let data = {gp_id:_self.gp_id},
+			getCombinationLisPink({}, this.gp_id).then(e => {
+				let r = e.data;
+				// 保存拼团商品详细
+				obj.goods = r.store_combination;
+				// 保存团长信息
+				obj.pinkT = r.pinkT;
+				/* 计算倒计时 */
+				obj.timeComputed(obj.pinkT.stop_time * 1000);
+				// 获取拼团用户列表
+				obj.people = r.pinkAll;
+				// 获取当前是否已参与过这个拼团
+				obj.userBool = r.userBool;
+				// 判断当前用户是否为团长
+				if (r.pinkT.uid == r.userInfo.uid) {
+					// 显示邀请好用选项
+					obj.status = 1;
+				}
+				// 保存当前登录用户信息
+				obj.userInfo = r.userInfo;
+				// 获取拼团是否已经过期
+				obj.pinkBool = r.pinkBool
+				// #ifdef H5
+				// 加载微信分享配置
+				this.shareDate();
+				// #endif
+			});
+		},
+		// 计算倒计时时间
+		timeComputed(da) {
+			let obj = this;
+			let stopTime = timeComputed(da);
+			obj.stopTime.stopTimeH = stopTime.hours;
+			obj.stopTime.stopTimeM = stopTime.minutes;
+			obj.stopTime.stopTimeS = stopTime.seconds;
+		},
+	}
+};
+</script>
+
+<style lang="scss">
+.box {
+	/* #ifdef APP-PLUS | MP */
+	padding-top: var(--status-bar-height);
+	/* #endif */
+}
+.lyy-c {
+	width: 100%;
+	background: rgba(255, 255, 255, 1);
+	.lyy-c-word {
+		font-size: 28rpx;
+		color: rgba(102, 102, 102, 1);
+		line-height: 50rpx;
+	}
+
+	.lyy-c-p {
+		padding: 39rpx 30rpx;
+	}
+}
+
+.lyy-wrap {
+	background-color: #f4f4f4;
+}
+
+.lyy-hx {
+	height: 14rpx;
+}
+
+.image1 {
+	width: 200rpx;
+	height: 33rpx;
+	background: url('http://lxscimg.liuniu946.com/2019-11-02_5dbd0e10a2160.png') center center no-repeat;
+	background-size: 200rpx auto;
+}
+
+.lyy-b {
+	width: 100%;
+	background-color: white;
+	.lyy-b-p {
+		padding: 30rpx 45rpx;
+		.lyy-b-word2,
+		.lyy-b-word3 {
+			font-size: 28rpx;
+			font-weight: bold;
+		}
+		.lyy-b-word2 {
+			color: #fc5b62;
+		}
+		.lyy-b-word3 {
+			color: #1d2023;
+		}
+		.lyy-b-jz {
+			width: 100%;
+			justify-content: center;
+			margin-bottom: 20rpx;
+			.lyy-y {
+				width: 80rpx;
+				height: 80rpx;
+				margin: 0px 15rpx;
+				border-radius: 40rpx;
+				overflow: hidden;
+				.user-list-img {
+					width: 100%;
+					height: 100%;
+				}
+			}
+			.lyy-y-word {
+				margin-top: 10rpx;
+				font-size: 28rpx;
+				text-align: center;
+				width: 110rpx;
+			}
+			.lyy-b-but {
+				width: 550rpx;
+				height: 80rpx;
+				background: #fc5b62;
+				border-radius: 100rpx;
+				text-align: center;
+				color: white;
+				line-height: 80rpx;
+				font-size: 32rpx;
+			}
+			.cmy-user-box {
+				.user-list {
+					display: inline-block;
+					line-height: 1;
+				}
+			}
+		}
+		.lyy-b-word {
+			text-align: center;
+			font-size: 26rpx;
+			color: rgba(29, 32, 35, 1);
+		}
+	}
+}
+
+// 商品列表样式
+.lyy-a {
+	width: 100%;
+	background-color: white;
+	.lyy-a-p {
+		padding: 22rpx 30rpx;
+		.lyy-a-f {
+			display: flex;
+			align-items: center;
+			.lyy-a-f2 {
+				flex: 1;
+			}
+			.lyy-a-tu {
+				width: 122rpx;
+				height: 122rpx;
+			}
+			.lyy-a-z {
+				padding-left: 30rpx;
+				flex-grow: 1;
+				.money-box {
+					justify-content: flex-start;
+					.lyy-a-tu2 {
+						background: rgba(255, 255, 255, 1);
+						border: 1rpx solid #fc5b62;
+						.lyy-a-tu3 {
+							background-color: #fc5b62;
+							padding: 2px 4px 0px 4px;
+							text-align: center;
+							height: 26rpx;
+							.lyy-a-tu5 {
+								width: 20rpx;
+								height: 20rpx;
+								display: block;
+							}
+						}
+						.lyy-a-tu4 {
+							margin-left: 2px;
+							font-size: 10px;
+							color: #fc5b62;
+							padding: 0px 10rpx;
+							text-align: center;
+						}
+					}
+				}
+				.lyy-a-word {
+					line-height: 56rpx;
+					.lyy-a-word3 {
+						font-size: 28rpx;
+						font-weight: bold;
+						color: #fc5b62;
+					}
+				}
+				.lyy-a-word2 {
+					font-size: 30rpx;
+					color: rgba(29, 32, 35, 1);
+				}
+			}
+		}
+	}
+}
+</style>

+ 257 - 0
pages/groupBooking/index.vue

@@ -0,0 +1,257 @@
+<template>
+	<view class="lyy-bg4">
+		<view class="lyy-f-a">
+			<view class="lyy-f-b lyy-flex">
+				<view class="lyy-f-c item" @click="goProduct(items)" v-for="(items, ind) in goodsList" :key="ind">
+					<view class="content">
+						<view><image :src="items.image" class="lyy-f-image" /></view>
+						<view class="lyy-f-word1 lyy-f-jl ellipsis">{{ items.title }}</view>
+						<view class="lyy-flex2">
+							<view class="lyy-flex3">
+								<view class="lyy-f-word2 lyy-f-jl">¥{{ items.price * 1 }}</view>
+							</view>
+							<view class="lyy-a-tu2 lyy-flex2">
+								<view class="lyy-a-tu3"><image src="../../static/img/img11.png" class="lyy-a-tu5" /></view>
+								<view class="lyy-a-tu4">{{ items.people }}人拼</view>
+							</view>
+						</view>
+					</view>
+				</view>
+			</view>
+		</view>
+		<uni-load-more :status="loadingType"></uni-load-more>
+	</view>
+</template>
+
+<script>
+import uniLoadMore from '@/components/uni-load-more/uni-load-more.vue';
+import { mapState } from 'vuex';
+import { getCombinationList } from '@/api/groupBooking.js';
+export default {
+	components: {
+		uniLoadMore
+	},
+	data() {
+		return {
+			goodsList: [],
+			loadingType: 'more', //加载更多状态
+			limit: 20, //每次加载数据条数
+			page: 1 //当前页数
+		};
+	},
+	onLoad(options) {
+		this.loadData();
+	},
+	//下拉刷新
+	onPullDownRefresh() {
+		this.loadData('refresh');
+	},
+	//监听页面是否滚动到底部加载更多
+	onReachBottom() {
+		this.loadData();
+	},
+	computed: {
+		...mapState('user',['userInfo'])
+	},
+	methods: {
+		//加载商品 ,带下拉刷新和上滑加载
+		async loadData(type = 'add', loading) {
+			let obj = this;
+			let data = {
+				page: obj.page,
+				limit: obj.limit
+			};
+			//没有更多直接返回
+			if (type === 'add') {
+				if (obj.loadingType === 'nomore') {
+					return;
+				}
+				obj.loadingType = 'loading';
+			} else {
+				obj.loadingType = 'more';
+			}
+
+			// 加载商品信息
+			getCombinationList(data)
+				.then(e => {
+					if (type === 'refresh') {
+						// 清空数组
+						obj.goodsList = [];
+					}
+					obj.goodsList = obj.goodsList.concat(e.data);
+					//判断是否还有下一页,有是more  没有是nomore
+					if (obj.limit == e.data.length) {
+						obj.page++;
+						obj.loadingType = 'more';
+					} else {
+						obj.loadingType = 'nomore';
+					}
+					if (type === 'refresh') {
+						if (loading == 1) {
+							uni.hideLoading();
+						} else {
+							uni.stopPullDownRefresh();
+						}
+					}
+				})
+				.catch();
+		},
+		goProduct(e) {
+			// if(this.userInfo.level>0){
+				uni.navigateTo({
+					url: '/pages/product/product?type=2&id=' + e.id
+				});
+			// }else{
+				// uni.showModal({
+				// 	title: '提示',
+				// 	content: '请升级为vip用户',
+				// 	success: res => {
+				// 		if(res.confirm){
+				// 			uni.navigateTo({
+				// 				url: '/pages/product/giftBag'
+				// 			});
+				// 		}
+				// 	},
+				// 	fail: (e) => {
+				// 		console.log(e);
+				// 	}
+				// });
+			// }
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+page {
+	height: 100%;
+}
+// 拼团列表
+.lyy-f-a {
+	margin: 0px 15px;
+
+	.lyy-flex {
+		/* 内部模块1*/
+		display: flex;
+		justify-content: space-between;
+	}
+	.lyy-f-b {
+		flex-wrap: wrap;
+		.lyy-f-c {
+			flex: 0 0 50%;
+			/* width: 50%; */
+			margin: 10px 0px 0px 0px;
+		}
+
+		.item:nth-child(2n + 1) .content {
+			margin: 0px 7.5px 0px 0px;
+			border-radius: 10px;
+		}
+	}
+
+	.lyy-f-b .content {
+		background-color: white;
+		.lyy-f-image {
+			width: 100%;
+			height: 340rpx;
+			border-radius: 10rpx 10rpx 0rpx 0rpx;
+		}
+		.ellipsis {
+			width: 165px;
+			white-space: nowrap;
+			overflow: hidden;
+			text-overflow: ellipsis;
+		}
+		.lyy-f-jl {
+			padding: 5px 7px;
+		}
+		.lyy-f-word1 {
+			font-size: 12px;
+			color: rgba(50, 50, 50, 1);
+			line-height: 20px;
+			width: 300rpx;
+			white-space: nowrap;
+			overflow: hidden;
+			text-overflow: ellipsis;
+		}
+	}
+
+	.item:nth-child(2n) .content {
+		margin: 0px 0 0px 7.5px;
+		border-radius: 10px;
+	}
+
+	.lyy-f-word3 {
+		font-size: 12px;
+		text-decoration: line-through;
+		color: rgba(139, 139, 139, 1);
+	}
+
+	.lyy-f-word5 {
+		font-size: 20rpx;
+		color: rgba(153, 153, 153, 1);
+		margin: 20rpx 0px 0px 0px;
+	}
+
+	.lyy-f-word4 {
+		height: 26px;
+		background: #6fb22f;
+		color: white;
+		text-align: center;
+	}
+
+	.lyy-f-d {
+		height: 24rpx;
+		border: 1px solid rgba(252, 91, 98, 1);
+		border-radius: 3px;
+		font-size: 20rpx;
+		text-align: center;
+		width: 50rpx;
+		color: rgba(252, 91, 98, 1);
+		margin: 23rpx 0rpx 0rpx 0rpx;
+		line-height: 24rpx;
+	}
+
+	.lyy-flex2 {
+		display: flex;
+		padding-right: 10rpx;
+		align-items: center;
+		.lyy-flex3 {
+			flex: 1;
+			.lyy-f-word2 {
+				font-size: 14px;
+				color: rgba(241, 13, 59, 1);
+			}
+		}
+		&.lyy-a-tu2 {
+			height: 34rpx;
+			background: rgba(255, 255, 255, 1);
+			border: 1px solid #fc5b62;
+			border-radius: 2px;
+			margin: 10rpx 0rpx;
+
+			.lyy-a-tu3 {
+				height: 30rpx;
+				background-color: #fc5b62;
+				padding: 0px 6px;
+				text-align: center;
+				.lyy-a-tu5 {
+					width: 20rpx;
+					height: 20rpx;
+					margin-top: 6rpx;
+					display: block;
+				}
+			}
+
+			.lyy-a-tu4 {
+				margin-left: 4rpx;
+				font-size: 24rpx;
+				line-height: 30rpx;
+				color: #fc5b62;
+				padding: 0px 10rpx;
+				text-align: center;
+			}
+		}
+	}
+}
+</style>

+ 75 - 0
pages/groupBooking/inviteImg.vue

@@ -0,0 +1,75 @@
+<template>
+	<view class="box">
+		<image class="inviteImg" :src="image" ></image>
+		<view class="lyy-b-but">长按图片下载</view>
+		<!-- <view class="lyy-b-but" @click="domImg">点击下载图片</view> -->
+	</view>
+</template>
+
+<script>
+	import { getCombinationPoster } from '@/api/groupBooking.js';
+	import { mapState } from 'vuex';
+	export default {
+		data() {
+			return {
+				image:'',//海报
+				ptId:'',//拼团id
+			}
+		},
+		computed: {
+			...mapState(['baseURL','urlFile'])
+		},
+		onLoad(option) {
+			// 保存拼团id
+			this.ptId = option.id;
+			// 保存团长id
+			this.spread = option.spread;
+			// 加载分享图
+			this.getCombinationPoster();
+		},
+		methods: {
+			// 加载海报
+			getCombinationPoster() {
+				let obj = this;
+				getCombinationPoster({
+					id:obj.ptId,
+					// #ifdef H5|APP-PLUS
+					url:obj.baseURL+obj.urlFile+'/pages/groupBooking/detail?id='+obj.ptId+'&spread='+obj.spread,
+					from:'wechat',//来源wechat公众号
+					// #endif
+					// #ifdef MP
+					from:'routine',//来源routine小程序
+					url:'/pages/groupBooking/detail?id='+obj.ptId
+					// #endif
+				}).then((e) => {
+					obj.image = e.data.url;
+				}).catch((e) => {
+					console.log(e);
+				})
+			}
+		},
+	}
+</script>
+
+<style lang="scss">
+	page{
+		background-color: #FFFFFF;
+		height: 100%;
+	}
+	.box{
+		.inviteImg{
+			width: 750rpx;
+			height: 1200rpx;
+		}
+	}
+	.lyy-b-but {
+		height: 80rpx;
+		background: #fc5b62;
+		border-radius: 100rpx;
+		text-align: center;
+		color: white;
+		line-height: 80rpx;
+		font-size: 32rpx;
+		margin:  0 100rpx;
+	}
+</style>

Разница между файлами не показана из-за своего большого размера
+ 513 - 0
pages/index/index.vue


+ 246 - 0
pages/index/seckill.vue

@@ -0,0 +1,246 @@
+<template>
+	<view class="seckill-section m-t" v-if="show">
+		<view class="s-header">
+			<view class="f-left-icon"></view>
+			<view class="tit-box"><text class="tit">限时秒杀</text></view>
+			<view class="tip-box">
+				<text class="tip" v-if="status == 1">{{ showTime }}点场结束</text>
+				<text class="tip" v-if="status == 2">距离下场开始</text>
+				<text class="tip" v-if="status == 0">当天活动已结束</text>
+				<uni-countdown v-if="status == 1 || status == 2" :show-day="false" :hour="stopTimeH" :minute="stopTimeM" :second="stopTimeS"></uni-countdown>
+			</view>
+			<view class="textNav iconfont iconenter" @click="navTo('/pages/seckill/seckill')">更多</view>
+		</view>
+		<scroll-view class="floor-list" scroll-x>
+			<view class="scoll-wrapper position-relative" @click="navTo('/pages/seckill/seckill')">
+				<view v-for="(item, index) in list" :key="index" class="floor-item">
+					<image class="list-img" :src="item.image" mode="aspectFill"></image>
+					<text class="title clamp">{{ item.title }}</text>
+					<text class="price">¥{{ item.price }}</text>
+				</view>
+				<view v-if="list.length == 0" class="floor-item ">
+					<image class="list-img" mode="aspectFill"></image>
+					<text class="title clamp"></text>
+					<text class="price"></text>
+				</view>
+				<view v-if="list.length == 0" class="noGoodsBg"><view>敬请期待</view></view>
+			</view>
+		</scroll-view>
+	</view>
+</template>
+
+<script>
+import uniCountdown from '@/components/uni-countdown/uni-countdown.vue';
+import { getList, getClass } from '@/api/seckill.js';
+import { timeComputed } from '@/utils/rocessor.js';
+export default {
+	components: {
+		uniCountdown
+	},
+	data() {
+		return {
+			list: [],
+			page: 1,
+			limit: 10,
+			showTime: '', //显示的时间
+			showTImeId: '', //显示时间id用于查询数据
+			stopTimeH: 0,
+			stopTimeM: 0,
+			stopTimeS: 0,
+			// 判断是否所有活动已经结束
+			stop: false, //活动是否已经结束
+			show: false, //是否显示活动
+			status: 0 //获取状态值1为有活动开始中 2为活动未开始 0为活动已经结束
+		};
+	},
+	created: function(e) {
+		// 载入分类
+		this.getClass();
+	},
+	methods: {
+		navTo(url) {
+			uni.navigateTo({
+				url
+			});
+		},
+		getList() {
+			getList(
+				{
+					page: this.page,
+					limit: this.limit
+				},
+				this.showTImeId
+			)
+				.then(e => {
+					this.list = e.data;
+				})
+				.catch(e => {
+					console.log(e);
+				});
+		},
+		getClass() {
+			let obj = this;
+			getClass({})
+				.then(({ data }) => {
+					let arr = data.seckillTime;
+					// 用于判断是否有数据
+					let showDate = false;
+					for (var i = 0; i < arr.length; i++) {
+						let ar = arr[i];
+						if (ar.status === 1 || ar.status === 2) {
+							obj.status = ar.status;
+							// 保存要显示的场次时间
+							obj.showTime = ar.time;
+							// 保存要显示活动商品的id
+							obj.showTImeId = ar.id;
+							// 保存当前状态值
+							// 计算倒计时时间
+							if (ar.status === 1) {
+								obj.timeComputed(ar.stop * 1000);
+							} else {
+								// 获取需要开始
+								let arTime = ar.time.split(':');
+								let h = arTime[0];
+								let m = arTime[1];
+								let time = new Date();
+								// 设置时间
+								time.setHours(h, m, 0);
+								obj.timeComputed(time.getTime());
+							}
+							// 获取商品列表
+							obj.getList();
+							// 保存当前有活动在举行
+							showDate = true;
+							// 任务查询结束跳出循环
+							break;
+						}
+					}
+					// 判断是否有活动
+					if (arr.length > 0) {
+						obj.show = true;
+					}
+					// 判断今天活动是否已经全部结束
+					if (!showDate) {
+						// 保存活动结束最后一个小时的活动商品
+						obj.showTImeId = arr[arr.length - 1].id;
+						// 活动已经结束
+						obj.status = 0;
+						// 获取结束时的商品
+						obj.getList();
+						console.log(obj.status);
+					}
+					// 如果所有场次均已经结束
+				})
+				.catch(e => {
+					uni.showModal({
+						title: JSON.stringify(e)
+					});
+				});
+		},
+		// 计算倒计时时间
+		timeComputed(da) {
+			let obj = this;
+			let stopTime = timeComputed(da)
+			obj.stopTimeH =stopTime.hours;
+			obj.stopTimeM = stopTime.minutes;
+			obj.stopTimeS =stopTime.seconds;
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+/* 秒杀专区 */
+.seckill-section {
+	padding: 4rpx 30rpx 24rpx;
+	.s-header {
+		display: flex;
+		align-items: center;
+		height: 92rpx;
+		line-height: 1;
+		.tit-box {
+			flex-shrink: 0;
+		}
+		.tit {
+			@extend %font-title;
+		}
+		.f-left-icon {
+			@extend %f-left-icon;
+		}
+		.textNav {
+			line-height: 1;
+			padding: 15rpx 0;
+			flex-shrink: 0;
+			flex-grow: 1;
+			min-width: 100rpx;
+		}
+		.tip-box {
+			flex-grow: 1;
+			display: flex;
+			justify-content: flex-start;
+			align-items: center;
+		}
+		.tip {
+			font-size: $font-sm;
+			color: $font-color-light;
+			padding-left: 10rpx;
+			padding-right: 10rpx;
+		}
+		.timer {
+			display: inline-block;
+			width: 40rpx;
+			height: 36rpx;
+			text-align: center;
+			line-height: 36rpx;
+			margin-right: 14rpx;
+			font-size: $font-sm + 2rpx;
+			color: #fff;
+			border-radius: 2px;
+			background: rgba(0, 0, 0, 0.8);
+		}
+		.iconenter {
+			font-size: $font-sm;
+			color: $font-color-light;
+			flex: 1;
+			text-align: right;
+		}
+	}
+	.floor-list {
+		white-space: nowrap;
+		background-color: white;
+		padding: 20rpx;
+		border-radius: 5rpx;
+		box-shadow: $box-shadow;
+	}
+	.scoll-wrapper {
+		display: flex;
+		align-items: flex-start;
+		.noGoodsBg {
+			display: flex;
+			align-items: center;
+			justify-content: center;
+			height: 100%;
+			position: absolute;
+			top: 0;
+			left: 0;
+			width: 100%;
+			color: $font-color-light;
+		}
+		.floor-item {
+			width: 150rpx;
+			margin-right: 20rpx;
+			font-size: $font-sm + 2rpx;
+			color: $font-color-dark;
+			line-height: 1.8;
+			.list-img {
+				width: 150rpx;
+				height: 150rpx;
+				border-radius: 6rpx;
+			}
+			.price {
+				color: $color-red;
+			}
+		}
+	}
+}
+</style>

+ 185 - 0
pages/integral/index.vue

@@ -0,0 +1,185 @@
+<template>
+	<view class="container">
+		<!-- 头部轮播 -->
+		<view class="carousel-section">
+			<swiper class="carousel" autoplay="true" duration="400" interval="5000">
+				<swiper-item v-for="(item, index) in bannerImg" :key="index" class="carousel-item" @click="bannerNavToUrl(item)">
+					<image :src="item.img" mode=" scaleToFill" />
+				</swiper-item>
+			</swiper>
+		</view>
+		<view class="goodsList-box">
+			<view class="goodsList-item" :key="ind" v-for="(ls, ind) in list" @click="navToDetailPage(ls)">
+				<navigator :url="'/pages/product/product?id=' + ls.id">
+					<image :src="ls.image" mode=" scaleToFill"></image>
+					<view class="goodsList-content">
+						<view class="title clamp">
+							<text>{{ ls.store_name }}</text>
+						</view>
+						<view class="goods-money flex">
+							<view class="money-box flex">
+								<view v-if="ls.use_max_integral != 0">
+									<text class="money">{{ ls.use_max_integral }}</text>
+									<text class="font-size-sm">积分</text>
+								</view>
+								<view v-else>
+									<text class="money">¥{{ ls.price }}</text>
+								</view>
+								<view class="otMoney-box" v-if="ls.use_max_integral != 0">
+									<text class="otMoney" v-if="ls.price - ls.use_max_integral > 0">+¥{{ (ls.price - ls.use_max_integral) | toFixed }}</text>
+								</view>
+							</view>
+							<view class="otprice">
+								<text>¥{{ ls.price }}</text>
+							</view>
+						</view>
+					</view>
+				</navigator>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+import { groomList } from '@/api/product.js';
+export default {
+	filters: {
+		toFixed: function(value) {
+			// 判断是否为整数
+			if (value % 1 == 0) {
+				return value;
+			} else {
+				return value.toFixed(2);
+			}
+		}
+	},
+	data() {
+		return {
+			list: [],
+			bannerImg: []
+		};
+	},
+	onLoad(option) {
+		// 加载基础数据
+		this.loadData();
+	},
+	methods: {
+		//详情页
+		navToDetailPage(item) {
+			uni.navigateTo({
+				url: '/pages/product/product?id=' + item.id
+			});
+		},
+		// 轮播图跳转
+		bannerNavToUrl(item) {
+			// #ifdef H5
+			if (item.wap_link.indexOf('http') > 0) {
+				window.location.href = item.wap_link;
+			}
+			// #endif
+			//测试数据没有写id,用title代替
+			uni.navigateTo({
+				url: item.wap_link
+			});
+		},
+		// 请求载入数据
+		async loadData() {
+			groomList({}, 5)
+				.then(({ data }) => {
+					// 保存轮播图
+					this.bannerImg = data.banner;
+					// 保存商品信息
+					this.list = data.list.map(e => {
+						e.price = Number(e.price);
+						e.ot_price = Number(e.ot_price);
+						return e;
+					});
+				})
+				.catch(e => {
+					console.log(e);
+				});
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+page {
+	background: $page-color-base;
+}
+.carousel-section {
+	margin-bottom: 30rpx;
+	padding: 0;
+	.titleNview-placing {
+		padding-top: 0;
+		height: 0;
+	}
+	.swiper-dots {
+		left: 45rpx;
+		bottom: 40rpx;
+	}
+	.carousel {
+		width: 100%;
+		height: 360rpx;
+		.carousel-item {
+			width: 100%;
+			height: 100%;
+			overflow: hidden;
+		}
+		image {
+			width: 100%;
+			height: 100%;
+		}
+	}
+}
+// 商品列表
+.goodsList-box {
+	padding: 0 25rpx;
+	display: flex;
+	flex-wrap: wrap;
+	.goodsList-item {
+		width: 340rpx;
+		margin-bottom: 30rpx;
+		background-color: #ffffff;
+		border-radius: $border-radius-sm;
+		image {
+			flex-shrink: 0;
+			height: 340rpx;
+			width: 340rpx;
+		}
+		&:nth-child(2n + 1) {
+			margin-right: 20rpx;
+		}
+		.goodsList-content {
+			padding-left: 20rpx;
+			flex-grow: 1;
+			padding: 20rpx;
+			.title {
+				font-size: $font-base;
+				color: $font-color-dark;
+				font-weight: 500;
+			}
+			.goods-money {
+				line-height: 1;
+				margin-top: 10rpx;
+				font-size: $font-sm - 4rpx;
+				.money {
+					color: $color-red;
+					font-weight: bold;
+				}
+				.font-size-sm {
+					color: $font-color-light;
+				}
+				.otMoney {
+					background-color: #ffeae2;
+					color: $color-red;
+				}
+				.otprice {
+					text-decoration: line-through;
+					color: $font-color-light;
+				}
+			}
+		}
+	}
+}
+</style>

+ 138 - 0
pages/moments/details.vue

@@ -0,0 +1,138 @@
+<template>
+	<view class="container">
+		<view class="notice-item">
+			<view class="notice_name">{{list.title}}</view>
+			<view class="flex notice_text">
+				<text class="">作者:新零售</text>
+				<text class="">{{list.add_time}}</text>
+			</view>
+			<view class="notice_content"><rich-text :nodes="list.content"></rich-text></view>
+		</view>
+		<view class="mask" v-show="show"><image @click="onTap" src="/static/img/shareimg.png"></image></view>
+	</view>
+</template>
+
+<script>
+import { details } from '@/api/moments.js';
+import { mapState } from 'vuex';
+import { saveUrl } from '@/utils/loginUtils.js';
+// #ifdef H5
+import { weixindata } from '@/utils/wxAuthorized';
+// #endif
+export default {
+	data() {
+		return {
+			id:'',
+			list:"",
+			spread:"",
+			show:false
+		};
+	},
+	async onLoad(options) {
+		this.id = options.id;
+		if(options.spread){
+			// 存储邀请人
+			this.spread = options.spread;
+			uni.setStorageSync('spread', options.spread);
+		}
+		let obj = this;
+		details({},obj.id).then(function(e) {
+			obj.list = e.data;
+			// #ifdef H5
+			obj.shareDate();
+			// #endif
+		});
+		saveUrl();
+	},
+	onShow() {
+	},
+	computed: {
+		...mapState(['userInfo', 'baseURL'])
+	},
+	methods: {
+		shareDate() {
+			let obj = this;
+			let url = window.location.href.replace(/[\?,&]{0,1}from=singlemessage/g, '')+ '&spread=' + this.userInfo.uid;
+			let bool = uni.getStorageSync('weichatBrowser') || '';
+			// 判断是否微信浏览器
+			if (bool) {
+				let data = {
+					link: url, // 分享链接
+					imgUrl: obj.list.image_input[0], // 分享图标
+					desc: obj.list.synopsis,
+					title: obj.list.title,
+					success: function() {}
+				};
+				// #ifdef H5
+				// 判断是否为微信浏览器
+				if (uni.getStorageSync('weichatBrowser')) {
+					// 加载微信注册信息
+					weixindata(data);
+				}
+				// #endif
+			}
+		},
+		//显示弹窗
+		open(){
+			this.show = true;
+	    },
+		//随意点击隐藏弹窗
+		onTap() {
+			if (!this.open) return
+			this.close()
+		},
+		close() {
+			this.show = false;
+		},
+	}
+};
+</script>
+
+<style lang="scss">
+page {
+	min-height: 100%;
+	background:#FFFFFF;
+	padding-bottom: 30rpx;
+}
+.notice_name {
+	font-size: 35rpx !important;
+	color: #303133;
+}
+.notice-item {
+	width: 100%;
+	height: 100%;
+	color: #666666;
+	padding: 35rpx 35rpx;
+	font-size: 23rpx;
+}
+.notice_text {
+	border-bottom: 1px solid #F0F0F0;
+	padding: 30rpx 0rpx;
+}
+.notice_content {
+	font-size: 28rpx;
+	padding: 25rpx 0rpx;
+	line-height: 45rpx;
+}
+.share{
+	text-align: center;
+	background-color: #e93323!important;
+	color: #FFFFFF !important;
+	padding: 20rpx 0rpx;
+	border-radius: 35rpx;
+	margin-bottom: 20rpx;
+}
+.mask{
+   z-index: 999;
+   width: 750rpx;
+   height: 100%;
+   position: fixed;
+   top: 0;
+   left: 0;
+   image{
+	   width: 100%;
+	   height: 100%;
+	   opacity: 0.9;
+   }
+}
+</style>

+ 425 - 0
pages/money/pay.vue

@@ -0,0 +1,425 @@
+<template>
+	<view class="app">
+		<view class="price-box">
+			<text>支付金额</text>
+			<text class="price">{{ money }}</text>
+		</view>
+		<view class="pay-type-list">
+			<view class="type-item b-b" @click="changePayType(1)">
+				<text class="icon iconfont iconweixin"></text>
+				<view class="con">
+					<text class="tit">微信支付</text>
+					<text>推荐使用微信支付</text>
+				</view>
+				<label class="radio"><radio value="" color="#5dbc7c" :checked="payType == 1"></radio></label>
+			</view>
+			<!-- <view class="type-item b-b" @click="changePayType(2)">
+				<text class="icon iconfont iconzhifubao"></text>
+				<view class="con"><text class="tit">支付宝支付</text></view>
+				<label class="radio"><radio value="" color="#5dbc7c" :checked="payType == 2"></radio></label>
+			</view> -->
+			<view class="type-item" @click="changePayType(3)" v-show="goodsType === 0">
+				<text class="icon iconfont iconyue"></text>
+				<view class="con">
+					<text class="tit">余额支付</text>
+					<text>可用余额 ¥{{ now_money }}</text>
+				</view>
+				<label class="radio"><radio value="" color="#5dbc7c" :checked="payType == 3"></radio></label>
+			</view>
+			<view class="type-item" @click="changePayType(4)" v-show="goodsType === 0">
+				<text class="icon iconfont" style="color:#00BCD4;">&#xe65d;</text>
+				<view class="con">
+					<text class="tit">消费券</text>
+					<text>可用余额 ¥{{ consumer }}</text>
+				</view>
+				<label class="radio"><radio value="" color="#5dbc7c" :checked="payType == 4"></radio></label>
+			</view>
+		</view>
+		<text class="mix-btn" :class="{ clickbg: payLoding }" @click="!payLoding ? confirm() : ''">确认支付</text>
+	</view>
+</template>
+
+<script>
+import { computedOrderkey, balance, createOrderkey, orderPay } from '@/api/money.js';
+import { mapState } from 'vuex';
+export default {
+	data() {
+		return {
+			payType: 1, //支付类型
+			// #ifdef H5
+			payName: 'weixin',
+			// #endif
+			// #ifdef MP-WEIXIN
+			payName: 'routine',
+			// #endif
+			// #ifdef APP-PLUS
+			payName: 'weixin',
+			// #endif
+			orderInfo: {},
+			money: 0.0, //订单金额
+			now_money: 0.0, //余额
+			consumer:0.0,//消费券
+			orderKey: '',
+			orderId: '', //保存订单id
+			payLoding: false, //判断是否支付中
+			type: '', //判断是否从订单中进入
+			// #ifdef H5
+			froms: '', //保存h5中数据来源对象
+			// #endif
+			pinkid: '', //保存拼团商品id
+			checkedPoints: '', //保存是否用积分抵扣商品
+			goodsType: 0 //商品类型1秒杀商品0为普通商品2为拼团商品
+		};
+	},
+	computed: {
+		// #ifdef H5
+		...mapState(['weichatObj'])
+		// #endif
+	},
+	onLoad(options) {
+		console.log(uni.getStorageSync('token'));
+		this.goodsType = +options.goodsType || 0;
+		//判断是否为新订单
+		if (options.type == 1) {
+			this.type = 1;
+			this.orderId = options.ordid;
+			this.money = options.money;
+			// 判断支付类型
+			if (options.payType == 1) {
+				this.checkedPoints = true;
+			}
+		} else {
+			this.orderKey = options.key;
+			let prepage = this.$api.prePage();
+			this.checkedPoints = prepage.checkedPoints;
+			computedOrderkey({
+				orderkey: this.orderKey,
+				addressId: prepage.addressData.id, //地址编号
+				useIntegral: prepage.checkedPoints ? 1 : 0,
+				is_change: prepage.is_change ? 1 : 0, //判断是否全额抵扣0为否1为是
+				shipping_type: prepage.tabCurrentIndex + 1 //提货方式 1 快递 2自提
+			}).then(({ data }) => {
+				// 获取支付金额
+				this.money = data.result.pay_price;
+			});
+			// 保存pinkid
+			if (options.pinkid) {
+				this.pinkid = options.pinkid;
+			}
+		}
+		balance({}).then(({ data }) => {
+			// 获取余额
+			this.now_money = data.now_money;
+			this.consumer = data.consumer
+		});
+	},
+	methods: {
+		//选择支付方式
+		changePayType(type) {
+			this.payType = type;
+			if (this.payType == 1) {
+				// #ifdef H5
+				this.payName = 'weixin';
+				// #endif
+				// #ifdef MP-WEIXIN
+				this.payName = 'routine';
+				// #endif
+				// #ifdef APP-PLUS
+				this.payName = 'weixin';
+				// #endif
+			}
+			if (this.payType == 2) {
+				this.payName = 'ali';
+			}
+			if (this.payType == 3) {
+				this.payName = 'yue';
+			}
+			if (this.payType == 4) {
+				this.payName = 'consumer';
+			}
+		},
+		// 支付金额
+		orderMoneyPay() {
+			let obj = this;
+			const data = {
+				uni: obj.orderId,
+				// #ifdef H5
+				from: obj.froms ? 'weixin' : 'H5', //来源
+				// #endif
+				// #ifdef MP-WEIXIN
+				from: 'routine', //来源
+				// #endif
+				// #ifdef APP-PLUS
+				from: 'weixinapp', //来源
+				// #endif
+				paytype: obj.payName //支付类型  weixin-微信 yue-余额
+			};
+			console.log(data);
+			orderPay(data)
+				.then(e => {
+					console.log(e);
+					// 判断是否为余额支付
+					if (obj.payName == 'yue') {
+						if (e.status == 200 && e.data.status == 'SUCCESS') {
+							obj.paySuccessTo();
+						} else {
+							obj.$api.msg(msg);
+						}
+					}
+					// #ifdef H5
+					if (obj.payName == 'weixin') {
+						let da = e.data.result.jsConfig;
+						obj.weichatObj.chooseWXPay({
+							timestamp: da.timestamp,
+							nonceStr: da.nonceStr,
+							package: da.package,
+							signType: da.signType,
+							paySign: da.paySign,
+							success: function(res) {
+								obj.paySuccessTo();
+							}
+						});
+					}
+					// #endif
+					// #ifdef MP-WEIXIN
+					if (obj.payName == 'routine') {
+						let da = e.data.result.jsConfig;
+						wx.requestPayment({
+							timeStamp: da.timestamp,
+							nonceStr: da.nonceStr,
+							package: da.package,
+							signType: da.signType,
+							paySign: da.paySign,
+							success: function(res) {
+								obj.paySuccessTo();
+							}
+						});
+					}
+					// #endif
+					// #ifdef APP-PLUS
+					if (obj.payName == 'weixin') {
+						let da = e.data.result.jsConfig;
+						uni.requestPayment({
+							provider:'wxpay',
+							orderInfo:da,
+							success:function () {
+								obj.paySuccessTo();
+							}
+						})
+					}
+					// #endif
+					obj.payLoding = false;
+				})
+				.catch(e => {
+					// 支付完成
+					obj.payLoding = false;
+					console.log(e);
+				});
+		},
+		// 支付成功跳转
+		paySuccessTo() {
+			uni.redirectTo({
+				url: '/pages/money/paySuccess?orderid=' + this.orderId
+			});
+		},
+		//确认支付
+		confirm: async function() {
+			let obj = this;
+			// 判断账户余额是否充足
+			if (obj.payName == 'yue' && +obj.now_money < obj.money) {
+				uni.showModal({
+					title: '提示',
+					content: '账户余额不足!',
+					showCancel: false,
+					success: res => {},
+					fail: () => {},
+					complete: () => {}
+				});
+				return;
+			}
+			// 判断消费券
+			if (obj.payName == 'consumer' && +obj.consumer < obj.money) {
+				uni.showModal({
+					title: '提示',
+					content: '账户消费券不足!',
+					showCancel: false,
+					success: res => {},
+					fail: () => {},
+					complete: () => {}
+				});
+				return;
+			}
+			// 支付中
+			obj.payLoding = true;
+			// #ifdef H5
+			// 获取当前是否为微信浏览器
+			obj.froms = uni.getStorageSync('weichatBrowser') || '';
+			// #endif
+			// 判断是否为未支付订单中跳转进入
+			if (obj.type != 1) {
+				// 初次生成订单
+				obj.firstCreateOrder();
+			} else {
+				// 已经生成订单未支付
+				obj.orderMoneyPay();
+			}
+		},
+		// 初次订单创建
+		firstCreateOrder() {
+			let obj = this;
+			// 获取下单页面数据
+			let prepage = obj.$api.prePage();
+			let data = {
+				real_name: prepage.addressData.real_name, //联系人名称
+				phone: prepage.addressData.phone, //联系人号码
+				// couponId: prepage.couponChecked.id, //优惠券编号
+				addressId: prepage.addressData.id, //支付地址id
+				useIntegral: prepage.checkedPoints ? 1 : 0, //是否积分抵扣1为是0为否
+				payType: obj.payName, //支付类型  weixin-微信 yue-余额
+				mark: prepage.desc, //备注
+				// #ifdef H5
+				from: obj.froms ? 'weixin' : 'H5', //来源
+				// #endif
+				// #ifdef MP-WEIXIN
+				from: 'routine', //来源
+				// #endif
+				// #ifdef APP-PLUS
+				from: 'weixinapp', //来源
+				// #endif
+				shipping_type: prepage.tabCurrentIndex + 1, //提货方式 1 快递 2自提
+				is_change: prepage.is_change ? 1 : 0 //判断是否全额抵扣0为否1为是
+			};
+			console.log(data);
+			console.log( obj.payName);
+			// 判断是否拼团商品
+			if (obj.pinkid) {
+				data.pinkId = obj.pinkid;
+			}
+			// 生成订单
+			createOrderkey(data, obj.orderKey)
+				.then(({ data, status, msg }) => {
+					// 判断是否支付成功
+					// 判断是否支付失败
+					if (data.status == 'ORDER_EXIST') {
+						uni.showModal({
+							title: '提示',
+							content: msg,
+							showCancel: false
+						});
+						obj.payLoding = false;
+						return;
+					}
+
+					// 保存订单号
+					obj.orderId = data.result.orderId;
+					// 判断是否微信支付成功
+					if (data.status == 'SUCCESS' && obj.payName == 'weixin' && msg == '微信支付成功') {
+						obj.paySuccessTo();
+						return;
+					}
+					// 判断是否为余额支付
+					if (obj.payName == 'yue'||obj.payName == 'consumer') {
+						if (status == 200) {
+							obj.paySuccessTo();
+						} else {
+							obj.payLoding = false;
+							obj.$api.msg(msg);
+						}
+					} else {
+						// 立即支付
+						obj.orderMoneyPay();
+					}
+				})
+				.catch(e => {
+					console.log(e);
+				});
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+.app {
+	width: 100%;
+}
+
+.price-box {
+	background-color: #fff;
+	height: 265upx;
+	display: flex;
+	flex-direction: column;
+	justify-content: center;
+	align-items: center;
+	font-size: 28upx;
+	color: #909399;
+
+	.price {
+		font-size: 50upx;
+		color: #303133;
+		margin-top: 12upx;
+		&:before {
+			content: '¥';
+			font-size: 40upx;
+		}
+	}
+}
+
+.pay-type-list {
+	margin-top: 20upx;
+	background-color: #fff;
+	padding-left: 60upx;
+	.type-item {
+		height: 120upx;
+		padding: 20upx 0;
+		display: flex;
+		justify-content: space-between;
+		align-items: center;
+		padding-right: 60upx;
+		font-size: 30upx;
+		position: relative;
+	}
+
+	.icon {
+		width: 100upx;
+		font-size: 52upx;
+	}
+	.iconyue {
+		color: #fe8e2e;
+	}
+	.iconweixin {
+		color: #36cb59;
+	}
+	.iconzhifubao {
+		color: #01aaef;
+	}
+	.tit {
+		font-size: $font-lg;
+		color: $font-color-dark;
+		margin-bottom: 4upx;
+	}
+	.con {
+		flex: 1;
+		display: flex;
+		flex-direction: column;
+		font-size: $font-sm;
+		color: $font-color-light;
+	}
+}
+.mix-btn {
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	width: 630upx;
+	height: 80upx;
+	margin: 80upx auto 30upx;
+	font-size: $font-lg;
+	color: #fff;
+	background-color: $base-color;
+	border-radius: 10upx;
+	/* box-shadow: 1px 2px 5px rgba(219, 63, 96, 0.4); */
+}
+
+.clickbg {
+	background-color: $color-gray !important;
+}
+</style>

+ 65 - 0
pages/money/paySuccess.vue

@@ -0,0 +1,65 @@
+<template>
+	<view class="content">
+		<text class="success-icon iconfont iconroundcheck"></text>
+		<text class="tit">支付成功</text>
+		<view class="btn-group">
+			<navigator :url="'/pages/order/orderDetail?id='+orderId" open-type="redirect" class="mix-btn">查看订单</navigator>
+			<navigator url="/pages/index/index" open-type="switchTab" class="mix-btn hollow">返回首页</navigator>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				orderId:''
+			}
+		},
+		onLoad(opt) {
+			// 保存订单号
+			this.orderId = opt.orderid;
+		},
+		methods: {
+			
+		}
+	}
+</script>
+
+<style lang='scss'>
+	.content{
+		display: flex;
+		flex-direction: column;
+		justify-content: center;
+		align-items: center;
+	}
+	.success-icon{
+		font-size: 160upx;
+		color: #5dbc7c;
+		margin-top: 100upx;
+	}
+	.tit{
+		font-size: 38upx;
+		color: #303133;
+	}
+	.btn-group{
+		padding-top: 100upx;
+	}
+	.mix-btn {
+		margin-top: 30upx;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		width: 600upx;
+		height: 80upx;
+		font-size: $font-lg;
+		color: #fff;
+		background-color: $base-color;
+		border-radius: 10upx;
+		&.hollow{
+			background: #fff;
+			color: #303133;
+			border: 1px solid #ccc;
+		}
+	}
+</style>

+ 360 - 0
pages/myteam/myteam.vue

@@ -0,0 +1,360 @@
+<template>
+	<view class="content">
+		<view class="content-money">
+			<view class="money-box">
+				<!-- <view class="text">当前总积分</view>
+				<view class="money">{{ userInfo.integral | getMoneyStyle }}</view> -->
+				<image :src="userInfo.avatar" class="andr-mt-avatar andr-mt-avatarBd"></image>
+				<view class="text">{{ userInfo.nickname }}</view>
+				<!--<view class="text">试用赠予次数:5(暂时固定值,需要动态修改)</view>-->
+			</view>
+			<!-- <view class="moneyTx" @click="navto('/pages/wallet/recharge')">充值</view> -->
+			<!-- <view class="flex buttom-box">
+				<view class="buttom" @click="navto('/pages/wallet/recharge')">
+					<view class="icon"><image class="icon-img" src="/static/icon/i5.png" mode="aspectFit"></image></view>
+					<text>充值</text>
+				</view>
+				<view class="interval"></view>
+				<view class="buttom" @click="navto('/pages/award/award')">
+					<view class="icon"><image class="icon-img" src="/static/icon/i1.png" mode="aspectFit"></image></view>
+					<text>我的奖励</text>
+				</view>
+			</view> -->
+		</view>
+		<view class="navbar">
+			<view v-for="(item, index) in navList" :key="index" class="nav-item" :class="{ current: tabCurrentIndex === index }" @click="tabClick(index)">
+				<text>{{ item.text }}</text>
+				<text>{{ item.num || '' }}</text>
+			</view>
+		</view>
+		<swiper :current="tabCurrentIndex" :style="{ height: maxheight + 'rpx' }" class="swiper-box" duration="300" @change="changeTab">
+			<swiper-item class="tab-content" v-for="(tabItem, tabIndex) in navList" :key="tabIndex">
+				<scroll-view class="list-scroll-content" scroll-y @scrolltolower="loadData">
+					<!-- 空白页 -->
+					<empty v-if="tabItem.loaded === true && tabItem.orderList.length === 0"></empty>
+
+					<!-- 订单列表 -->
+					<view v-for="(item, index) in tabItem.orderList" :key="item.uid" class="andr-mt-flex andr-mt-lBox">
+						<!-- 订单列表 -->
+						<image :src="item.avatar" class="andr-mt-avatar andr-mt-marR20"></image>
+						<view class="andr-mt-flex andr-mt-fdC">
+							<text class="andr-mt-lname">{{ item.nickname }}</text>
+							<text class="andr-mt-ltime">{{ item.time }}</text>
+						</view>
+					</view>
+					<uni-load-more :status="tabItem.loadingType"></uni-load-more>
+				</scroll-view>
+			</swiper-item>
+		</swiper>
+	</view>
+</template>
+
+<script>
+import { spreadPeople } from '@/api/myteam.js';
+import { userinfo } from '@/api/user.js';
+import { mapState, mapMutations } from 'vuex';
+import { getMoneyStyle } from '@/utils/rocessor.js';
+import uniLoadMore from '@/components/uni-load-more/uni-load-more.vue';
+import empty from '@/components/empty';
+export default {
+	filters: {
+		getMoneyStyle
+	},
+	components: {
+		empty,
+		uniLoadMore
+	},
+	onReady() {
+		// 初始化获取页面宽度
+		uni.createSelectorQuery()
+			.select('.content')
+			.fields(
+				{
+					size: true
+				},
+				data => {
+					// 保存头部高度
+					// this.maxheight = data.height - Math.floor((data.width / 750) * 570);
+					this.maxheight = 940;
+				}
+			)
+			.exec();
+	},
+	data() {
+		return {
+			userInfo: {},
+			// 头部图高度
+			maxheight: '',
+			tabCurrentIndex: 0,
+			navList: [
+				{
+					state: 0,
+					text: '一级团队',
+					loadingType: 'more',
+					num: 0, //人数
+					orderList: [],
+					page: 1, //当前页数
+					limit: 10 //每次信息条数
+				},
+				{
+					state: 1,
+					text: '二级团队',
+					num: 0, //团队人数
+					loadingType: 'more',
+					orderList: [],
+					page: 1, //当前页数
+					limit: 10 //每次信息条数
+				}
+			],
+			money: ''
+		};
+	},
+	onLoad(options) {},
+	onShow() {
+		this.loadData();
+		// 获取用户积分
+		let obj = this;
+		userinfo({})
+			.then(({ data }) => {
+				console.log(data);
+				obj.userInfo = data;
+			})
+			.catch(e => {});
+	},
+	methods: {
+		// 页面跳转
+		navto(e) {
+			uni.navigateTo({
+				url: e
+			});
+		},
+		//获取收入支出信息
+		async loadData(source) {
+			let obj = this;
+			//这里是将订单挂载到tab列表下
+			let index = obj.tabCurrentIndex;
+			let navItem = obj.navList[index];
+			let state = navItem.state;
+			if (source === 'tabChange' && navItem.loaded === true) {
+				//tab切换只有第一次需要加载数据
+				return;
+			}
+			if (navItem.loadingType === 'loading') {
+				//防止重复加载
+				return;
+			}
+			// 修改当前对象状态为加载中
+			navItem.loadingType = 'loading';
+			spreadPeople({
+				page: navItem.page,
+				limit: navItem.limit,
+				grade: state,
+				keyword: '',
+				sort: ''
+			})
+				.then(({ data }) => {
+					obj.navList[0].num = data.total;
+					obj.navList[1].num = data.totalLevel;
+					if (data.list.length > 0) {
+						navItem.orderList = navItem.orderList.concat(data.list);
+						console.log(navItem.orderList);
+						navItem.page++;
+					}
+					if (navItem.limit == data.list.length) {
+						//判断是否还有数据, 有改为 more, 没有改为noMore
+						navItem.loadingType = 'more';
+						return;
+					} else {
+						//判断是否还有数据, 有改为 more, 没有改为noMore
+						navItem.loadingType = 'noMore';
+					}
+					uni.hideLoading();
+					obj.$set(navItem, 'loaded', true);
+				})
+				.catch(e => {
+					console.log(e);
+				});
+		},
+
+		//swiper 切换
+		changeTab(e) {
+			this.tabCurrentIndex = e.target.current;
+			this.loadData('tabChange');
+		},
+		//顶部tab点击
+		tabClick(index) {
+			this.tabCurrentIndex = index;
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+page {
+	background: #ffffff;
+	height: 100%;
+}
+.content-money {
+	padding-bottom: 30rpx;
+	background: $page-color-base;
+	// border: 2px solid #ffffff;
+	.moneyTx {
+		position: absolute;
+		top: 150rpx;
+		right: 0rpx;
+		width: 150rpx;
+		padding: 10rpx 30rpx;
+		border: 2px solid #ffffff;
+		border-top-left-radius: 99rpx;
+		border-bottom-left-radius: 99rpx;
+		color: #ffffff;
+		line-height: 1;
+		font-size: $font-base;
+	}
+	.buttom-box {
+		background-color: #ffffff;
+		text-align: center;
+		margin: 0 30rpx;
+		padding: 20rpx 0;
+		border-radius: $border-radius-sm;
+		margin-top: -60rpx;
+		.buttom {
+			font-size: $font-lg;
+			flex-grow: 1;
+		}
+		.interval {
+			width: 2px;
+			height: 60rpx;
+			background-color: #eeeeee;
+		}
+		.icon {
+			height: 50rpx;
+			width: 48rpx;
+			margin: 0 auto;
+			.icon-img {
+				width: 100%;
+				height: 100%;
+			}
+		}
+	}
+}
+.money-box {
+	background-color: $base-color;
+	padding-top: var(--status-bar-height);
+	// height: 368rpx;
+	height: 180rpx;
+	display: flex;
+	flex-direction: column;
+	align-items: center;
+	justify-content: center;
+	color: #ffffff;
+	// text-align: center;
+	.text {
+		// padding-top: 147rpx;
+		font-size: $font-sm;
+	}
+	.money {
+		font-size: 56rpx;
+	}
+}
+
+.navbar {
+	display: flex;
+	height: 40px;
+	padding: 0 5px;
+	background: #fff;
+	box-shadow: 0 1px 5px rgba(0, 0, 0, 0.06);
+	position: relative;
+	z-index: 10;
+	.nav-item {
+		flex: 1;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		height: 100%;
+		font-size: 15px;
+		color: $font-color-dark;
+		position: relative;
+		&.current {
+			color: $base-color;
+			&:after {
+				content: '';
+				position: absolute;
+				left: 50%;
+				bottom: 0;
+				transform: translateX(-50%);
+				width: 44px;
+				height: 0;
+				border-bottom: 2px solid $base-color;
+			}
+		}
+	}
+}
+// 列表
+
+.swiper-box {
+	padding-top: 10rpx;
+	.order-item {
+		padding: 20rpx 30rpx;
+		line-height: 1.5;
+		.title-box {
+			.title {
+				font-size: $font-lg;
+				color: $font-color-base;
+			}
+			.time {
+				font-size: $font-base;
+				color: $font-color-light;
+			}
+		}
+		.money {
+			color: #fd5b23;
+			font-size: $font-lg;
+		}
+	}
+}
+.list-scroll-content {
+	height: 100%;
+}
+.content {
+	height: 100%;
+	.empty-content {
+		background-color: #ffffff;
+	}
+}
+.andr-mt-avatar {
+	width: 78rpx;
+	height: 78rpx;
+	border-radius: 50rpx;
+}
+.andr-mt-avatarBd {
+	border: 2px solid #ffffff;
+}
+.andr-mt-cname {
+	font-size: 28rpx;
+	color: #ffffff;
+}
+.andr-mt-flex {
+	display: flex;
+}
+.andr-mt-lBox {
+	background-color: #ffffff;
+	height: 130rpx;
+	padding: 20rpx 20rpx;
+	border-bottom: 1px solid #f0f0f0;
+}
+.andr-mt-marR20 {
+	margin-right: 20rpx;
+}
+.andr-mt-fdC {
+	flex-direction: column;
+}
+.andr-mt-lname {
+	font-size: 30rpx;
+	color: #3f454b;
+}
+.andr-mt-ltime {
+	font-size: 22rpx;
+	color: #999999;
+}
+</style>

+ 153 - 0
pages/notice/notice.vue

@@ -0,0 +1,153 @@
+<template>
+	<view>
+		<view class="notice-item">
+			<text class="time">11:30</text>
+			<view class="content">
+				<text class="title">新品上市,全场满199减50</text>
+				<view class="img-wrapper">
+					<image class="pic" src="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1556465765776&di=57bb5ff70dc4f67dcdb856e5d123c9e7&imgtype=0&src=http%3A%2F%2Fimg.zcool.cn%2Fcommunity%2F01fd015aa4d95fa801206d96069229.jpg%401280w_1l_2o_100sh.jpg"></image>
+				</view>
+				<text class="introduce">
+					虽然做了一件好事,但很有可能因此招来他人的无端猜测,例如被质疑是否藏有其他利己动机等,乃至谴责。即便如此,还是要做好事。
+				</text>
+				<view class="bot b-t">
+					<text>查看详情</text>
+					<text class="more-icon iconfont iconenter"></text>
+				</view>
+			</view>
+		</view>
+		<view class="notice-item">
+			<text class="time">昨天 12:30</text>
+			<view class="content">
+				<text class="title">新品上市,全场满199减50</text>
+				<view class="img-wrapper">
+					<image class="pic" src="https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=3761064275,227090144&fm=26&gp=0.jpg"></image>
+					<view class="cover">
+						活动结束
+					</view>
+				</view>
+				<view class="bot b-t">
+					<text>查看详情</text>
+					<text class="more-icon iconfont iconenter"></text>
+				</view>
+			</view>
+		</view>
+		<view class="notice-item">
+			<text class="time">2019-07-26 12:30</text>
+			<view class="content">
+				<text class="title">新品上市,全场满199减50</text>
+				<view class="img-wrapper">
+					<image class="pic" src="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1556465765776&di=57bb5ff70dc4f67dcdb856e5d123c9e7&imgtype=0&src=http%3A%2F%2Fimg.zcool.cn%2Fcommunity%2F01fd015aa4d95fa801206d96069229.jpg%401280w_1l_2o_100sh.jpg"></image>
+					<view class="cover">
+						活动结束
+					</view>
+				</view>
+				<text class="introduce">新品上市全场2折起,新品上市全场2折起,新品上市全场2折起,新品上市全场2折起,新品上市全场2折起</text>
+				<view class="bot b-t">
+					<text>查看详情</text>
+					<text class="more-icon iconfont iconenter"></text>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+
+			}
+		},
+		methods: {
+
+		}
+	}
+</script>
+
+<style lang='scss'>
+	page {
+		background-color: #f7f7f7;
+		padding-bottom: 30upx;
+	}
+
+	.notice-item {
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+	}
+
+	.time {
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		height: 80upx;
+		padding-top: 10upx;
+		font-size: 26upx;
+		color: #7d7d7d;
+	}
+
+	.content {
+		width: 710upx;
+		padding: 0 24upx;
+		background-color: #fff;
+		border-radius: 4upx;
+	}
+
+	.title {
+		display: flex;
+		align-items: center;
+		height: 90upx;
+		font-size: 32upx;
+		color: #303133;
+	}
+
+	.img-wrapper {
+		width: 100%;
+		height: 260upx;
+		position: relative;
+	}
+
+	.pic {
+		display: block;
+		width: 100%;
+		height: 100%;
+		border-radius: 6upx;
+	}
+
+	.cover {
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		position: absolute;
+		left: 0;
+		top: 0;
+		width: 100%;
+		height: 100%;
+		background-color: rgba(0, 0, 0, .5);
+		font-size: 36upx;
+		color: #fff;
+	}
+
+	.introduce {
+		display: inline-block;
+		padding: 16upx 0;
+		font-size: 28upx;
+		color: #606266;
+		line-height: 38upx;
+	}
+
+	.bot {
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
+		height: 80upx;
+		font-size: 24upx;
+		color: #707070;
+		position: relative;
+	}
+
+	.more-icon {
+		font-size: 32upx;
+	}
+</style>

Разница между файлами не показана из-за своего большого размера
+ 176 - 0
pages/order/createOrder.vue


+ 408 - 0
pages/order/evaluate.vue

@@ -0,0 +1,408 @@
+<template>
+	<view class="content">
+		<view class="order-item">
+			<view class="goods-box-single">
+				<image class="goods-img" :src="productInfo.image" mode="aspectFill"></image>
+				<view class="right position-relative">
+					<view class="flex">
+						<text class="title">{{ productInfo.store_name }}</text>
+						<view class="title-right">
+							<view class="price">{{ productInfo.price }}</view>
+							<view class="attr-box">x{{ list.cart_num }}</view>
+						</view>
+					</view>
+				</view>
+			</view>
+			<view>
+				<view class="flex_item zhil">
+					<view style="width: 100%;height: 40rpx;line-height: 40rpx;margin-bottom: 16rpx;"> 商品质量</view>
+					<view ><uniRate text="1" size="20" margin="10" :value="rateValue1" @change="rateChange1"></uniRate></view>
+				</view>
+				<view class="flex_item zhil">
+					<view style="width: 100%;height: 40rpx;line-height: 40rpx;margin-bottom: 16rpx;">服务态度</view>
+					<view ><uniRate text="1" size="20" margin="10" :value="rateValue2" @change="rateChange2"></uniRate></view>
+				</view>
+				<view class="equity_box">
+					<view class="text-box uni-textarea">
+						<textarea placeholder-style="color:#999" :placeholder="placeholder" @blur="bindTextAreaBlur"></textarea>
+					</view>
+					<view class="">
+						<view class="add-img-box flex_item">
+							<view class="add-img-item" v-for="(item, index) in imgList" :key="index">
+								<image class="add-img" @click.stop="imgInfo(index)" :src="item.url" mode="aspectFill"></image>
+								<image class="add-img-del" @click.stop="delImg(index)" src="/static/img/delete.png"></image>
+							</view>
+							<view v-if="imgList.length < 9" class="add-img-item" @click.stop="scImg()">
+								<image class="add-img" src="/static/img/add.png"></image>
+							</view>
+						</view>
+					</view>
+				</view>
+			</view>
+		</view>
+		<view @click.stop="submit" class="address-box submit-box"><text class="submit-btn">提交评论</text></view>
+	</view>
+</template>
+
+<script>
+import { product, upload, order_comment } from '@/api/order.js';
+import uniRate from '@/components/uni-rate/uni-rate.vue';
+export default {
+	components: {
+		uniRate
+	},
+	data() {
+		return {
+			list: '', //订单详情
+			productInfo: '',
+			text: '', //评论内容
+			placeholder: '商品满足你的期待么?说说你的想法,分享给想买的他们吧~',
+			imgList: [],
+			unique: '', //商品唯一标识码
+			cloudimgList: [],
+			rateValue1: '', //商品质量
+			rateValue2: '', //服务态度
+			imgCount: 6 //最多支持9张上传,可以修改
+		};
+	},
+	onLoad(option) {
+		this.unique = option.unique;
+		this.loadOrder();
+	},
+	onShow() {},
+	methods: {
+		//text
+		bindTextAreaBlur: function(e) {
+			this.text = e.detail.value;
+		},
+		//获取收入支出信息
+		async loadOrder() {
+			product({
+				unique: this.unique
+			}).then(e => {
+				this.list = e.data;
+				this.productInfo = e.data.productInfo;
+			});
+		},
+		//商品质量评分
+		rateChange1(val) {
+			this.rateValue1 = val.value;
+		},
+		//服务态度评分
+		rateChange2(val) {
+			this.rateValue2 = val.value;
+		},
+		//单张上传图片
+		scImg() {
+			let obj = this;
+			console.log(obj.imgCount, 11);
+			if (obj.imgCount == 0) {
+				uni.showToast({
+					title: '最多添加6张图片',
+					icon: 'none'
+				});
+				return;
+			}
+			upload({
+				file: ''
+			})
+				.then(e => {
+					console.log(e,'e')
+					obj.imgList = [...obj.imgList, ...e];
+					console.log(obj.imgList,'imgList')
+					obj.imgCount = 10 - obj.imgList.length;
+					console.log(obj.imgCount ,'imgCount ')
+				})
+				.catch(e => {});
+		},
+		//提交评论
+		submit(e) {
+			let obj = this;
+			// if (obj.imgList.length < 1) {
+			// 	uni.showToast({
+			// 		title: '请添加图片',
+			// 		icon: 'none'
+			// 	});
+			// 	return;
+			// }
+			for (let i = 0; i < obj.imgList.length; i++) {
+				obj.cloudimgList.push(obj.imgList[i].url);
+			}
+			let arr = obj.cloudimgList.join(',');
+			order_comment({
+				pics: arr,
+				comment: obj.text,
+				product_score: obj.rateValue1,
+				service_score: obj.rateValue2,
+				unique: obj.unique,
+				
+			})
+				.then(e => {
+					uni.navigateTo({
+						url: '/pages/order/order?state=4'
+					});
+				})
+				.catch(e => {
+					uni.navigateTo({
+						url: '/pages/order/order?state=4'
+					});
+				});
+		},
+		//点击图片显示大图
+		imgInfo(i) {
+			let tempList = [];
+			console.log(111);
+			this.imgList.forEach(e => {
+				tempList.push(e.url);
+			});
+			console.log(tempList);
+			//显示图片
+			uni.previewImage({
+				current: i,
+				loop: false,
+				urls: tempList,
+				indicator: 'default'
+			});
+		},
+		//删除图片
+		delImg(i) {
+			uni.showModal({
+				content: '确定删除这张吗',
+				success: res => {
+					if (res.confirm) {
+						this.imgList.splice(i, 1);
+						this.imgCount++;
+					} else if (res.cancel) {
+					}
+				}
+			});
+		},
+		// 页面跳转
+		navto(e) {
+			uni.navigateTo({
+				url: e
+			});
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+page {
+	background: #ffffff;
+	height: 100%;
+	.content {
+		background: #ffffff;
+		height: 100%;
+	}
+}
+/* 多条商品 */
+.order-item {
+	display: flex;
+	flex-direction: column;
+	padding: 0rpx 30rpx;
+	background: #fff;
+	margin-top: 20rpx;
+	/* 单条商品 */
+	.goods-box-single {
+		display: flex;
+		padding: 20rpx 0;
+		.goods-img {
+			display: block;
+			width: 120rpx;
+			height: 120rpx;
+		}
+		.right {
+			flex: 1;
+			display: flex;
+			flex-direction: column;
+			padding: 0 30rpx 0 24rpx;
+			overflow: hidden;
+			height: 100%;
+			.title {
+				align-self: flex-start;
+				font-size: $font-base + 2rpx;
+				color: $font-color-dark;
+				height: 80rpx;
+				overflow:hidden; 
+				text-overflow:ellipsis;
+				display:-webkit-box; 
+				-webkit-box-orient:vertical;
+				-webkit-line-clamp:2; 
+			}
+			.title-right {
+				flex-shrink: 0;
+				text-align: right;
+				align-self: flex-start;
+			}
+			.attr-box {
+				font-size: $font-sm + 2rpx;
+				color: $font-color-light;
+			}
+			.price {
+				font-size: $font-base + 2rpx;
+				color: $font-color-dark;
+				&:before {
+					content: '¥';
+					font-size: $font-sm;
+					margin: 0 2rpx 0 8rpx;
+				}
+			}
+		}
+	}
+}
+.equity_box {
+	background-color: #fafafa;
+	border-radius: 10rpx;
+	padding: 25rpx 25rpx;
+	margin: 25rpx 0rpx;
+	.text-box {
+		height: 200rpx;
+		textarea {
+			font-size: 25rpx;
+			width: 100%;
+			height: 100%;
+			overflow: hidden;
+			text-overflow: ellipsis;
+			display: -webkit-box;
+			-webkit-box-orient: vertical;
+			-webkit-line-clamp: 5;
+		}
+	}
+}
+.zhil {
+	font-size: 28rpx !important;
+	padding: 15rpx 15rpx;
+}
+.submit-box {
+	bottom: 0;
+	left: 0;
+	width: 750rpx;
+}
+.submit-btn {
+	margin-top: 10px;
+	display: inline-block;
+	width: 670rpx;
+	height: 96rpx;
+	line-height: 96rpx;
+	text-align: center;
+	background-color: #1BCC26 !important;
+	opacity: 1;
+	border-radius: 32rpx;
+	border-width: 8rpx;
+	border-color: rgba(255, 255, 255, 1);
+	box-shadow: 0rpx 8rpx 12rpx rgba(0, 0, 0, 0.16);
+	border-radius: 56rpx;
+	font-size: 39rpx;
+	font-weight: bold;
+	color: rgba(255, 255, 255, 1);
+}
+.submit-btn-txt {
+	font-size: 39rpx;
+	font-weight: bold;
+	line-height: 47rpx;
+	color: rgba(255, 255, 255, 1);
+	opacity: 1;
+}
+.map-box {
+	width: 484rpx;
+	height: 256rpx;
+	border-width: 4rpx;
+	border-color: rgba(255, 255, 255, 1);
+	box-shadow: 0rpx 0rpx 24rpx rgba(0, 0, 0, 0.16);
+	/* border-radius: 12rpx; */
+	position: relative;
+}
+.map {
+	position: absolute;
+	top: 0;
+	left: 0;
+	right: 0;
+	bottom: 0;
+	width: 476rpx;
+	height: 250rpx;
+}
+.map-img {
+	position: absolute;
+	top: 90rpx;
+	left: 156rpx;
+	width: 230rpx;
+	height: 68rpx;
+	background-color: rgba(51, 51, 51, 0.64);
+	border-width: 1rpx;
+	border-color: rgba(0, 0, 0, 0);
+	border-radius: 34px;
+
+	font-size: 28rpx;
+	font-weight: bold;
+	line-height: 66rpx;
+	color: rgba(255, 255, 255, 1);
+	text-align: center;
+}
+.address-box {
+	padding: 15rpx 40rpx;
+	margin-bottom: 10px;
+}
+.label {
+	font-size: 36rpx;
+	font-weight: bold;
+	line-height: 50rpx;
+	color: #222222;
+}
+.label-img {
+	padding-left: 40rpx;
+}
+.add-box {
+	padding: 15rpx 0;
+	flex-wrap: wrap;
+}
+.add-img-box {
+	width: 100%;
+	flex-direction: row;
+	flex-wrap: wrap;
+	margin-top: 50rpx;
+}
+.add-img-item {
+	width: 180rpx;
+	height: 180rpx;
+	border-radius: 24rpx;
+	position: relative;
+	margin: 0rpx 20rpx;
+	margin-bottom: 25rpx;
+	.add-img {
+		width: 100%;
+		height: 100%;
+		border-radius: 24rpx;
+	}
+}
+.add-img-camera {
+	flex: 1;
+}
+.add-img-del {
+	position: absolute;
+	width: 40rpx;
+	height: 40rpx;
+	left: 155rpx;
+	bottom: 155rpx;
+	//background-color: rgba(238, 0, 0, 1);
+	border-radius: 20rpx;
+}
+.address-time {
+	width: 484rpx;
+	height: 88rpx;
+	background-color: rgba(245, 245, 245, 1);
+	opacity: 1;
+	border-radius: 24rpx;
+	text-align: center;
+
+	font-size: 35rpx;
+	font-weight: 500;
+	color: rgba(51, 51, 51, 1);
+}
+.line {
+	width: 750rpx;
+	height: 1px;
+	transform: scaleY(0.3);
+	background-color: rgba(0, 0, 0, 0.5);
+}
+</style>

+ 662 - 0
pages/order/order.vue

@@ -0,0 +1,662 @@
+<template>
+	<view class="content">
+		<view class="navbar">
+			<view v-for="(item, index) in navList" :key="index" class="nav-item" :class="{ current: tabCurrentIndex === index }" @click="tabClick(index)">{{ item.text }}</view>
+		</view>
+
+		<swiper :current="tabCurrentIndex" class="swiper-box" duration="300" @change="changeTab">
+			<swiper-item class="tab-content" v-for="(tabItem, tabIndex) in navList" :key="tabIndex">
+				<scroll-view class="list-scroll-content" scroll-y @scrolltolower="loadData">
+					<!-- 空白页 -->
+					<empty v-if="tabItem.loaded === true && tabItem.orderList.length === 0"></empty>
+					<!-- 订单列表 -->
+					<view @click="goToOrderDetail(item)" v-for="(item, index) in tabItem.orderList" :key="index" class="order-item">
+						<view class="i-top b-b">
+							<text class="time">{{ item._add_time }}</text>
+							<text class="state" :style="{ color: item.stateTipColor }">{{item._status._title }}</text>
+							<text v-if="item.status === 4" class="del-btn iconfont icondelete" @click="deleteOrder(index)"></text>
+						</view>
+						<scroll-view v-if="item.cartInfo.length > 1" class="goods-box" scroll-x>
+							<view v-for="(goodsItem, goodsIndex) in item.cartInfo" :key="goodsIndex" class="goods-item">
+								<image class="goods-img" :src="goodsItem.productInfo.image" mode="aspectFill"></image>
+							</view>
+						</scroll-view>
+						<view v-if="item.cartInfo.length === 1" class="goods-box-single" v-for="(goodsItem, goodsIndex) in item.cartInfo" :key="goodsIndex">
+							<image class="goods-img" :src="goodsItem.productInfo.image" mode="aspectFill"></image>
+							<view class="right">
+								<text class="title clamp">{{ goodsItem.productInfo.store_name }}</text>
+								<text class="attr-box">{{ goodsItem.attrInfo ? goodsItem.attrInfo.suk : '' }} x {{ goodsItem.cart_num }}</text>
+								<text class="price">{{ moneyNum(goodsItem.productInfo.price) }}</text>
+							</view>
+						</view>
+						<view class="price-box">
+							共
+							<text class="num">{{ item.cartInfo.length }}</text>
+							件商品 邮费
+							<text class="price">{{ moneyNum(item.pay_postage) }}</text>
+							实付款
+							<text class="price">{{ moneyNum(item.pay_price) }}</text>
+						</view>
+						<view class="action-box b-t" v-if="item.status != 5">
+							<button v-if="item._status._title == '未支付'" class="action-btn" @click.stop="cancelOrder(item)">取消订单</button>
+							<button v-if="item._status._title == '未支付'" @click.stop="orderPay(item)" class="action-btn recom">立即支付</button>
+							<!-- <button v-if="item._status._title == 3" class="action-btn">评价</button> -->
+							
+							<button v-if="item._status._type == 3" class="action-btn" @click.stop="goToOrderDetail(item)">去评价</button>
+							<button v-if="item._status._title == '待收货'" @click.stop="orderTake(item, index)" class="action-btn">确认收货</button>
+							<button v-if="item._status._title == '未发货'||item._status._title=='待核销'" class="action-btn" @click.stop="orderRefund(item)">申请退款</button>
+						</view>
+					</view>
+					<uni-load-more :status="tabItem.loadingType"></uni-load-more>
+				</scroll-view>
+			</swiper-item>
+		</swiper>
+	</view>
+</template>
+
+<script>
+import uniLoadMore from '@/components/uni-load-more/uni-load-more.vue';
+import empty from '@/components/empty';
+import { orderList, orderCancel, orderDel, orderTake } from '@/api/order.js';
+export default {
+	components: {
+		uniLoadMore,
+		empty
+	},
+	data() {
+		return {
+			tabCurrentIndex: 0,
+			navList: [
+				{
+					state: 0,
+					text: '待付款',
+					loadingType: 'more',
+					orderList: [],
+					page: 1, //当前页数
+					limit: 10 //每次信息条数
+				},
+				{
+					state: 1,
+					text: '待发货',
+					loadingType: 'more',
+					orderList: [],
+					page: 1, //当前页数
+					limit: 10 //每次信息条数
+				},
+				{
+					state: 2,
+					text: '待收货',
+					loadingType: 'more',
+					orderList: [],
+					page: 1, //当前页数
+					limit: 10 //每次信息条数
+				},
+				{
+					state: 3,
+					text: '待评价',
+					loadingType: 'more',
+					orderList: [],
+					page: 1, //当前页数
+					limit: 10 //每次信息条数
+				},
+				{
+					state: 4,
+					text: '已完成',
+					loadingType: 'more',
+					orderList: [],
+					page: 1, //当前页数
+					limit: 10 //每次信息条数
+				},
+				{
+					state: '',
+					text: '全部',
+					loadingType: 'more',
+					orderList: [],
+					page: 1, //当前页数
+					limit: 10 //每次信息条数
+				}
+			]
+		};
+	},
+
+	onLoad(options) {
+		/**
+		 * 修复app端点击除全部订单外的按钮进入时不加载数据的问题
+		 * 替换onLoad下代码即可
+		 */
+		this.tabCurrentIndex = +options.state;
+		// #ifndef MP
+		this.loadData();
+		// #endif
+		// #ifdef MP
+		if (options.state == 0) {
+			this.loadData();
+		}
+		// #endif
+	},
+
+	methods: {
+		// 计算金额
+		moneyNum(value) {
+			return +value;
+		},
+		// 确认收货
+		orderTake(item, index) {
+			let obj = this;
+			uni.showModal({
+				title: '是否确认收货?',
+				success: (e) => {
+					if (e.confirm) {
+						orderTake({
+							uni: item.order_id
+						})
+							.then(e => {
+								obj.navList[obj.tabCurrentIndex].orderList.splice(index, 1);
+								uni.showToast({
+									title: '收货成功'
+								});
+							})
+							.catch(e => {
+								uni.showModal({
+									title: '问题',
+									content: JSON.stringify(e),
+									showCancel: false
+								});
+								console.log(e);
+							});
+					}
+				}
+			});
+		},
+		//跳转到订单详情
+		goToOrderDetail(e) {
+			uni.navigateTo({
+				url: '/pages/order/orderDetail?id=' + e.order_id
+			});
+		},
+		// 申请退款
+		orderRefund(e) {
+			uni.navigateTo({
+				url: '/pages/order/orderRefund?id=' + e.order_id
+			});
+		},
+		// 订单支付
+		orderPay(e) {
+			let url = '';
+			if (+e.deduction_price > 0) {
+				url = '/pages/money/pay?type=1&ordid=' + e.order_id + '&payType=1&money=' + e.pay_price;
+			} else {
+				url = '/pages/money/pay?type=1&ordid=' + e.order_id + '&money=' + e.pay_price;
+			}
+			uni.navigateTo({
+				url: '/pages/money/pay?type=1&ordid=' + e.order_id + '&money=' + e.pay_price
+			});
+		},
+		//获取订单列表
+		loadData(source) {
+			//这里是将订单挂载到tab列表下
+			let index = this.tabCurrentIndex;
+			let navItem = this.navList[index];
+			let state = navItem.state;
+			if (source === 'tabChange' && navItem.loaded === true) {
+				//tab切换只有第一次需要加载数据
+				return;
+			}
+			if (navItem.loadingType === 'loading') {
+				//防止重复加载
+				return;
+			}
+			if (navItem.loadingType === 'noMore') {
+				//防止重复加载
+				return;
+			}
+			// 修改当前对象状态为加载中
+			navItem.loadingType = 'loading';
+
+			orderList({
+				type: state,
+				page: navItem.page,
+				limit: navItem.limit
+			})
+				.then(({ data }) => {
+					let arr = data.map(e => {
+						let b = this.orderStateExp(e.status);
+						e.stateTip = b.stateTip;
+						e.stateTipColor = b.stateTipColor;
+						return e;
+					});
+					navItem.orderList = navItem.orderList.concat(arr);
+					// console.log(navItem.orderList);
+					navItem.page++;
+					if (navItem.limit == data.length) {
+						//判断是否还有数据, 有改为 more, 没有改为noMore
+						navItem.loadingType = 'more';
+						return;
+					} else {
+						//判断是否还有数据, 有改为 more, 没有改为noMore
+						navItem.loadingType = 'noMore';
+					}
+					uni.hideLoading();
+					this.$set(navItem, 'loaded', true);
+				})
+				.catch(e => {
+					console.log(e);
+				});
+		},
+
+		//swiper 切换
+		changeTab(e) {
+			this.tabCurrentIndex = e.target.current;
+			this.loadData('tabChange');
+		},
+		//顶部tab点击
+		tabClick(index) {
+			this.tabCurrentIndex = index;
+		},
+		//删除订单
+		deleteOrder(index) {
+			uni.showLoading({
+				title: '请稍后'
+			});
+			setTimeout(() => {
+				this.navList[this.tabCurrentIndex].orderList.splice(index, 1);
+				uni.hideLoading();
+			}, 600);
+		},
+		//取消订单
+		cancelOrder(item) {
+			uni.showModal({
+				title: '订单取消',
+				content: '是否取消订单?',
+				success: e => {
+					if (e.confirm) {
+						uni.showLoading({
+							title: '请稍后'
+						});
+						orderCancel({ id: item.order_id })
+							.then(e => {
+								uni.showToast({
+									title: '取消成功',
+									duration: 2000,
+									position: 'top'
+								});
+							})
+							.catch(e => {
+								console.log(e);
+							});
+						//取消订单后删除待付款中该项
+						let list = this.navList[this.tabCurrentIndex].orderList;
+						let index = list.findIndex(val => val.id === item.id);
+						index !== -1 && list.splice(index, 1);
+						uni.hideLoading();
+					}
+				}
+			});
+		},
+
+		//订单状态文字和颜色
+		orderStateExp(state) {
+			let stateTip = '',
+				stateTipColor = '#fa436a';
+			switch (+state) {
+				case 0:
+					stateTip = '待付款';
+					break;
+				case 1:
+					stateTip = '待发货';
+					break;
+				case 2:
+					stateTip = '待收货';
+					break;
+				case 3:
+					stateTip = '待评价';
+					break;
+				case 4:
+					stateTip = '已完成';
+					stateTipColor = '#5dbc7c';
+					break;
+				case 9:
+					stateTip = '订单已关闭';
+					stateTipColor = '#909399';
+					break;
+
+				//更多自定义
+			}
+			return { stateTip, stateTipColor };
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+page,
+.content {
+	background: $page-color-base;
+	height: 100%;
+}
+
+.swiper-box {
+	height: calc(100% - 40px);
+}
+.list-scroll-content {
+	height: 100%;
+}
+
+.navbar {
+	display: flex;
+	height: 40px;
+	padding: 0 5px;
+	background: #fff;
+	box-shadow: 0 1px 5px rgba(0, 0, 0, 0.06);
+	position: relative;
+	z-index: 10;
+	.nav-item {
+		flex: 1;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		height: 100%;
+		font-size: 15px;
+		color: $font-color-dark;
+		position: relative;
+		&.current {
+			color: $base-color;
+			&:after {
+				content: '';
+				position: absolute;
+				left: 50%;
+				bottom: 0;
+				transform: translateX(-50%);
+				width: 44px;
+				height: 0;
+				border-bottom: 2px solid $base-color;
+			}
+		}
+	}
+}
+
+.uni-swiper-item {
+	height: auto;
+}
+.order-item {
+	display: flex;
+	flex-direction: column;
+	padding-left: 30rpx;
+	background: #fff;
+	margin-top: 16rpx;
+	.i-top {
+		display: flex;
+		align-items: center;
+		height: 80rpx;
+		padding-right: 30rpx;
+		font-size: $font-base;
+		color: $font-color-dark;
+		position: relative;
+		.time {
+			flex: 1;
+		}
+		.state {
+			color: $base-color;
+		}
+		.del-btn {
+			padding: 10rpx 0 10rpx 36rpx;
+			font-size: $font-lg;
+			color: $font-color-light;
+			position: relative;
+			&:after {
+				content: '';
+				width: 0;
+				height: 30rpx;
+				border-left: 1px solid $border-color-dark;
+				position: absolute;
+				left: 20rpx;
+				top: 50%;
+				transform: translateY(-50%);
+			}
+		}
+	}
+	/* 多条商品 */
+	.goods-box {
+		height: 160rpx;
+		padding: 20rpx 0;
+		white-space: nowrap;
+		.goods-item {
+			width: 120rpx;
+			height: 120rpx;
+			display: inline-block;
+			margin-right: 24rpx;
+		}
+		.goods-img {
+			display: block;
+			width: 100%;
+			height: 100%;
+		}
+	}
+	/* 单条商品 */
+	.goods-box-single {
+		display: flex;
+		padding: 20rpx 0;
+		.goods-img {
+			display: block;
+			width: 120rpx;
+			height: 120rpx;
+		}
+		.right {
+			flex: 1;
+			display: flex;
+			flex-direction: column;
+			padding: 0 30rpx 0 24rpx;
+			overflow: hidden;
+			.title {
+				font-size: $font-base + 2rpx;
+				color: $font-color-dark;
+				line-height: 1;
+			}
+			.attr-box {
+				font-size: $font-sm + 2rpx;
+				color: $font-color-light;
+				padding: 10rpx 12rpx;
+			}
+			.price {
+				font-size: $font-base + 2rpx;
+				color: $font-color-dark;
+				&:before {
+					content: '¥';
+					font-size: $font-sm;
+					margin: 0 2rpx 0 8rpx;
+				}
+			}
+		}
+	}
+
+	.price-box {
+		display: flex;
+		justify-content: flex-end;
+		align-items: baseline;
+		padding: 20rpx 30rpx;
+		font-size: $font-sm + 2rpx;
+		color: $font-color-light;
+		.num {
+			margin: 0 8rpx;
+			color: $font-color-dark;
+		}
+		.price {
+			font-size: $font-lg;
+			color: $font-color-dark;
+			&:before {
+				content: '¥';
+				font-size: $font-sm;
+				margin: 0 2rpx 0 8rpx;
+			}
+		}
+	}
+	.action-box {
+		display: flex;
+		justify-content: flex-end;
+		align-items: center;
+		height: 100rpx;
+		position: relative;
+		padding-right: 30rpx;
+	}
+	.action-btn {
+		width: 160rpx;
+		height: 60rpx;
+		margin: 0;
+		margin-left: 24rpx;
+		padding: 0;
+		text-align: center;
+		line-height: 60rpx;
+		font-size: $font-sm + 2rpx;
+		color: $font-color-dark;
+		background: #fff;
+		border-radius: 100px;
+		&:after {
+			border-radius: 100px;
+		}
+		&.recom {
+			color: $base-color;
+			&:after {
+				border-color: $base-color;
+			}
+		}
+		&.evaluate {
+			color: $color-yellow;
+			&:after {
+				border-color: $color-yellow;
+			}
+		}
+	}
+}
+
+/* load-more */
+.uni-load-more {
+	display: flex;
+	flex-direction: row;
+	height: 80rpx;
+	align-items: center;
+	justify-content: center;
+}
+
+.uni-load-more__text {
+	font-size: 28rpx;
+	color: #999;
+}
+
+.uni-load-more__img {
+	height: 24px;
+	width: 24px;
+	margin-right: 10px;
+}
+
+.uni-load-more__img > view {
+	position: absolute;
+}
+
+.uni-load-more__img > view view {
+	width: 6px;
+	height: 2px;
+	border-top-left-radius: 1px;
+	border-bottom-left-radius: 1px;
+	background: #999;
+	position: absolute;
+	opacity: 0.2;
+	transform-origin: 50%;
+	animation: load 1.56s ease infinite;
+}
+
+.uni-load-more__img > view view:nth-child(1) {
+	transform: rotate(90deg);
+	top: 2px;
+	left: 9px;
+}
+
+.uni-load-more__img > view view:nth-child(2) {
+	transform: rotate(180deg);
+	top: 11px;
+	right: 0;
+}
+
+.uni-load-more__img > view view:nth-child(3) {
+	transform: rotate(270deg);
+	bottom: 2px;
+	left: 9px;
+}
+
+.uni-load-more__img > view view:nth-child(4) {
+	top: 11px;
+	left: 0;
+}
+
+.load1,
+.load2,
+.load3 {
+	height: 24px;
+	width: 24px;
+}
+
+.load2 {
+	transform: rotate(30deg);
+}
+
+.load3 {
+	transform: rotate(60deg);
+}
+
+.load1 view:nth-child(1) {
+	animation-delay: 0s;
+}
+
+.load2 view:nth-child(1) {
+	animation-delay: 0.13s;
+}
+
+.load3 view:nth-child(1) {
+	animation-delay: 0.26s;
+}
+
+.load1 view:nth-child(2) {
+	animation-delay: 0.39s;
+}
+
+.load2 view:nth-child(2) {
+	animation-delay: 0.52s;
+}
+
+.load3 view:nth-child(2) {
+	animation-delay: 0.65s;
+}
+
+.load1 view:nth-child(3) {
+	animation-delay: 0.78s;
+}
+
+.load2 view:nth-child(3) {
+	animation-delay: 0.91s;
+}
+
+.load3 view:nth-child(3) {
+	animation-delay: 1.04s;
+}
+
+.load1 view:nth-child(4) {
+	animation-delay: 1.17s;
+}
+
+.load2 view:nth-child(4) {
+	animation-delay: 1.3s;
+}
+
+.load3 view:nth-child(4) {
+	animation-delay: 1.43s;
+}
+
+@-webkit-keyframes load {
+	0% {
+		opacity: 1;
+	}
+
+	100% {
+		opacity: 0.2;
+	}
+}
+</style>

Разница между файлами не показана из-за своего большого размера
+ 179 - 0
pages/order/orderDetail.vue


+ 251 - 0
pages/order/orderRefund.vue

@@ -0,0 +1,251 @@
+<template>
+	<view class="content">
+		<view class="order-item">
+			<scroll-view v-if="listStyle == 1" class="goods-box" scroll-x>
+				<view v-for="(goodsItem, goodsIndex) in item.cartInfo" :key="goodsIndex" class="goods-item">
+					<image class="goods-img" :src="goodsItem.productInfo.image" mode="aspectFill"></image>
+				</view>
+			</scroll-view>
+			<view v-if="listStyle == 2" class="goods-box-single" v-for="(goodsItem, goodsIndex) in item.cartInfo" :key="goodsIndex">
+				<image class="goods-img" :src="goodsItem.productInfo.image" mode="aspectFill"></image>
+				<view class="right">
+					<text class="title clamp">{{ goodsItem.productInfo.store_name }}</text>
+					<text class="attr-box">{{ goodsItem.attrInfo ? goodsItem.attrInfo.suk : '' }} x {{ goodsItem.cart_num }}</text>
+					<text class="price">{{ goodsItem.productInfo.price | moneyNum }}</text>
+				</view>
+			</view>
+		</view>
+		<view class="orderDetial">
+			<view class="row b-b flex">
+				<text class="tit">订单总价</text>
+				<view class="input">¥{{ item.total_price | moneyNum }}</view>
+			</view>
+			<view class="row b-b flex">
+				<text class="tit">邮费</text>
+				<view class="input">{{ (item.pay_postage | moneyNum) > 0 ? '¥' + (item.pay_postage | moneyNum) : '免邮费' }}</view>
+			</view>
+			<view class="row b-b flex" v-if="item.coupon_id > 0">
+				<text class="tit">优惠券</text>
+				<view class="input">-¥{{ item.coupon_price | moneyNum }}</view>
+			</view>
+			<view class="row b-b flex" v-if="item.use_integral > 0">
+				<text class="tit">积分抵扣</text>
+				<view class="input">-¥{{ item.use_integral }}</view>
+			</view>
+			<view class="row b-b flex">
+				<text class="tit ">实付</text>
+				<view class="input payColor">¥{{ item.pay_price | moneyNum }}</view>
+			</view>
+		</view>
+		<view class="row b-b">
+			<text class="tit">退款理由</text>
+			<picker mode="selector" :range="value" @change="bindChange">
+				<view class="refund" v-if="refund">{{ refund || '请选择退款理由' }}</view>
+				<view class="noRefund" v-else>请选择退款理由</view>
+			</picker>
+		</view>
+		<view class="row b-b">
+			<text class="tit">备注说明</text>
+			<input class="input" type="text" v-model="reason" placeholder="请填写备注" placeholder-class="placeholder" />
+		</view>
+		<button class="add-btn" @click="confirm">提交</button>
+	</view>
+</template>
+
+<script>
+import { refund, refundReason, orderDetail } from '@/api/order.js';
+export default {
+	filters: {
+		moneyNum: function(value) {
+			return +value;
+		}
+	},
+	data() {
+		return {
+			refund: '', //退款理由
+			reason: '', //备注
+			value: ['1', '2', '3', '4', '5', '6', '7', '8', 9, 10, 11, 12, 13],
+			orderId: '',
+			item: {},
+			listStyle: 2
+		};
+	},
+	onLoad(option) {
+		this.orderId = option.id;
+		this.refundReason();
+		this.loadOrder();
+	},
+	methods: {
+		// 切换选中事件
+		bindChange(e) {
+			this.refund = this.value[e.detail.value];
+		},
+		// 加载退款理由
+		refundReason() {
+			refundReason({}).then(e => {
+				this.value = e.data;
+			});
+		},
+		loadOrder() {
+			orderDetail({}, this.orderId).then(e => {
+				this.item = e.data;
+			});
+		},
+		//提交
+		confirm() {
+			let obj = this;
+			if (!obj.refund) {
+				uni.showModal({
+					title: '错误',
+					content: '请填写退货理由',
+					showCancel: false
+				});
+				return false;
+			}
+			refund({
+				text: obj.refund,
+				uni: obj.orderId,
+				refund_reason_wap_explain: obj.reason
+			}).then(function(e) {
+				uni.showModal({
+					title: '提示',
+					content: '提交成功!是否返回?',
+					success: res => {
+						if(res.confirm){
+							uni.switchTab({
+								url:'/pages/user/user'
+							})
+						}
+					},
+				});
+			}).catch((e) => {
+				console.log(e);
+			});
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+page {
+	background: $page-color-base;
+	padding-top: 16rpx;
+}
+.orderDetial {
+	.row {
+		.input {
+			text-align: right;
+		}
+	}
+}
+.row {
+	display: flex;
+	align-items: center;
+	position: relative;
+	padding: 0 30rpx;
+	height: 110rpx;
+	background: #fff;
+	.refund {
+		font-size: 30rpx;
+		color: $font-color-dark;
+	}
+	.noRefund {
+		font-size: 30rpx;
+		color: $font-color-light;
+		padding-left: 20rpx;
+	}
+	.tit {
+		flex-shrink: 0;
+		width: 120rpx;
+		font-size: 30rpx;
+		color: $font-color-dark;
+	}
+	.input {
+		flex: 1;
+		font-size: 30rpx;
+		color: $font-color-dark;
+		padding-left: 20rpx;
+		&.payColor {
+			color: $color-red;
+		}
+	}
+	.iconlocation {
+		font-size: 36rpx;
+		color: $font-color-light;
+	}
+}
+.add-btn {
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	width: 690rpx;
+	height: 80rpx;
+	margin: 60rpx auto;
+	font-size: $font-lg;
+	color: #fff;
+	background-color: $base-color;
+	border-radius: 10rpx;
+	// box-shadow: 1px 2px 5px rgba(219, 63, 96, 0.4);
+}
+
+/* 多条商品 */
+.order-item {
+	display: flex;
+	flex-direction: column;
+	padding-left: 30rpx;
+	background: #fff;
+	margin-top: 16rpx;
+	.goods-box {
+		height: 160rpx;
+		padding: 20rpx 0;
+		white-space: nowrap;
+		.goods-item {
+			width: 120rpx;
+			height: 120rpx;
+			display: inline-block;
+			margin-right: 24rpx;
+		}
+		.goods-img {
+			display: block;
+			width: 100%;
+			height: 100%;
+		}
+	}
+	/* 单条商品 */
+	.goods-box-single {
+		display: flex;
+		padding: 20rpx 0;
+		.goods-img {
+			display: block;
+			width: 120rpx;
+			height: 120rpx;
+		}
+		.right {
+			flex: 1;
+			display: flex;
+			flex-direction: column;
+			padding: 0 30rpx 0 24rpx;
+			overflow: hidden;
+			.title {
+				font-size: $font-base + 2rpx;
+				color: $font-color-dark;
+				line-height: 1;
+			}
+			.attr-box {
+				font-size: $font-sm + 2rpx;
+				color: $font-color-light;
+				padding: 10rpx 12rpx;
+			}
+			.price {
+				font-size: $font-base + 2rpx;
+				color: $font-color-dark;
+				&:before {
+					content: '¥';
+					font-size: $font-sm;
+					margin: 0 2rpx 0 8rpx;
+				}
+			}
+		}
+	}
+}
+</style>

+ 638 - 0
pages/order/refundOrder.vue

@@ -0,0 +1,638 @@
+<template>
+	<view class="content">
+		<view class="navbar">
+			<view v-for="(item, index) in navList" :key="index" class="nav-item" :class="{ current: tabCurrentIndex === index }" @click="tabClick(index)">{{ item.text }}</view>
+		</view>
+
+		<swiper :current="tabCurrentIndex" class="swiper-box" duration="300" @change="changeTab">
+			<swiper-item class="tab-content" v-for="(tabItem, tabIndex) in navList" :key="tabIndex">
+				<scroll-view class="list-scroll-content" scroll-y @scrolltolower="loadData">
+					<!-- 空白页 -->
+					<empty v-if="tabItem.loaded === true && tabItem.orderList.length === 0"></empty>
+					<!-- 订单列表 -->
+					<view @click="goToOrderDetail(item)" v-for="(item, index) in tabItem.orderList" :key="index" class="order-item">
+						<view class="i-top b-b">
+							<text class="time">{{ item._add_time }}</text>
+							<text class="state" :style="{ color: item.stateTipColor }">{{item._status._title }}</text>
+							<text v-if="item.status === 4" class="del-btn iconfont icondelete" @click="deleteOrder(index)"></text>
+						</view>
+						<scroll-view v-if="item.cartInfo.length > 1" class="goods-box" scroll-x>
+							<view v-for="(goodsItem, goodsIndex) in item.cartInfo" :key="goodsIndex" class="goods-item">
+								<image class="goods-img" :src="goodsItem.productInfo.image" mode="aspectFill"></image>
+							</view>
+						</scroll-view>
+						<view v-if="item.cartInfo.length === 1" class="goods-box-single" v-for="(goodsItem, goodsIndex) in item.cartInfo" :key="goodsIndex">
+							<image class="goods-img" :src="goodsItem.productInfo.image" mode="aspectFill"></image>
+							<view class="right">
+								<text class="title clamp">{{ goodsItem.productInfo.store_name }}</text>
+								<text class="attr-box">{{ goodsItem.attrInfo ? goodsItem.attrInfo.suk : '' }} x {{ goodsItem.cart_num }}</text>
+								<text class="price">{{ moneyNum(goodsItem.productInfo.price) }}</text>
+							</view>
+						</view>
+						<view class="price-box">
+							共
+							<text class="num">{{ item.cartInfo.length }}</text>
+							件商品 邮费
+							<text class="price">{{ moneyNum(item.pay_postage) }}</text>
+							实付款
+							<text class="price">{{ moneyNum(item.pay_price) }}</text>
+						</view>
+						<view class="action-box b-t" v-if="item.status != 5">
+							<button v-if="item._status._title == '未支付'" class="action-btn" @click.stop="cancelOrder(item)">取消订单</button>
+							<button v-if="item._status._title == '未支付'" @click.stop="orderPay(item)" class="action-btn recom">立即支付</button>
+							<!-- <button v-if="item._status._title == 3" class="action-btn">评价</button> -->
+							
+							<button v-if="item._status._type == 3" class="action-btn" @click.stop="goToOrderDetail(item)">去评价</button>
+							<button v-if="item._status._title == '待收货'" @click.stop="orderTake(item, index)" class="action-btn">确认收货</button>
+							<button v-if="item._status._title == '未发货'" class="action-btn" @click.stop="orderRefund(item)">申请退款</button>
+						</view>
+					</view>
+					<uni-load-more :status="tabItem.loadingType"></uni-load-more>
+				</scroll-view>
+			</swiper-item>
+		</swiper>
+	</view>
+</template>
+
+<script>
+import uniLoadMore from '@/components/uni-load-more/uni-load-more.vue';
+import empty from '@/components/empty';
+import { orderList, orderCancel, orderDel, orderTake } from '@/api/order.js';
+export default {
+	components: {
+		uniLoadMore,
+		empty
+	},
+	data() {
+		return {
+			tabCurrentIndex: 0,
+			navList: [
+				{
+					state: -3,
+					text: '退款',
+					loadingType: 'more',
+					orderList: [],
+					page: 1, //当前页数
+					limit: 10 //每次信息条数
+				},
+				{
+					state: -1,
+					text: '退款中',
+					loadingType: 'more',
+					orderList: [],
+					page: 1, //当前页数
+					limit: 10 //每次信息条数
+				},
+				{
+					state: -2,
+					text: '已退款',
+					loadingType: 'more',
+					orderList: [],
+					page: 1, //当前页数
+					limit: 10 //每次信息条数
+				}
+			]
+		};
+	},
+
+	onLoad(options) {
+		/**
+		 * 修复app端点击除全部订单外的按钮进入时不加载数据的问题
+		 * 替换onLoad下代码即可
+		 */
+		this.tabCurrentIndex = +options.state;
+		// #ifndef MP
+		this.loadData();
+		// #endif
+		// #ifdef MP
+		if (options.state == 0) {
+			this.loadData();
+		}
+		// #endif
+	},
+
+	methods: {
+		// 计算金额
+		moneyNum(value) {
+			return +value;
+		},
+		// 确认收货
+		orderTake(item, index) {
+			let obj = this;
+			uni.showModal({
+				title: '是否确认收货?',
+				success: (e) => {
+					if (e.confirm) {
+						orderTake({
+							uni: item.order_id
+						})
+							.then(e => {
+								obj.navList[obj.tabCurrentIndex].orderList.splice(index, 1);
+								uni.showToast({
+									title: '收货成功'
+								});
+							})
+							.catch(e => {
+								uni.showModal({
+									title: '问题',
+									content: JSON.stringify(e),
+									showCancel: false
+								});
+								console.log(e);
+							});
+					}
+				}
+			});
+		},
+		//跳转到订单详情
+		goToOrderDetail(e) {
+			uni.navigateTo({
+				url: '/pages/order/orderDetail?id=' + e.order_id
+			});
+		},
+		// 申请退款
+		orderRefund(e) {
+			uni.navigateTo({
+				url: '/pages/order/orderRefund?id=' + e.order_id
+			});
+		},
+		// 订单支付
+		orderPay(e) {
+			let url = '';
+			if (+e.deduction_price > 0) {
+				url = '/pages/money/pay?type=1&ordid=' + e.order_id + '&payType=1&money=' + e.pay_price;
+			} else {
+				url = '/pages/money/pay?type=1&ordid=' + e.order_id + '&money=' + e.pay_price;
+			}
+			uni.navigateTo({
+				url: '/pages/money/pay?type=1&ordid=' + e.order_id + '&money=' + e.pay_price
+			});
+		},
+		//获取订单列表
+		loadData(source) {
+			//这里是将订单挂载到tab列表下
+			let index = this.tabCurrentIndex;
+			let navItem = this.navList[index];
+			let state = navItem.state;
+			if (source === 'tabChange' && navItem.loaded === true) {
+				//tab切换只有第一次需要加载数据
+				return;
+			}
+			if (navItem.loadingType === 'loading') {
+				//防止重复加载
+				return;
+			}
+			if (navItem.loadingType === 'noMore') {
+				//防止重复加载
+				return;
+			}
+			// 修改当前对象状态为加载中
+			navItem.loadingType = 'loading';
+
+			orderList({
+				type: state,
+				page: navItem.page,
+				limit: navItem.limit
+			})
+				.then(({ data }) => {
+					let arr = data.map(e => {
+						let b = this.orderStateExp(e.status);
+						e.stateTip = b.stateTip;
+						e.stateTipColor = b.stateTipColor;
+						return e;
+					});
+					navItem.orderList = navItem.orderList.concat(arr);
+					// console.log(navItem.orderList);
+					navItem.page++;
+					if (navItem.limit == data.length) {
+						//判断是否还有数据, 有改为 more, 没有改为noMore
+						navItem.loadingType = 'more';
+						return;
+					} else {
+						//判断是否还有数据, 有改为 more, 没有改为noMore
+						navItem.loadingType = 'noMore';
+					}
+					uni.hideLoading();
+					this.$set(navItem, 'loaded', true);
+				})
+				.catch(e => {
+					console.log(e);
+				});
+		},
+
+		//swiper 切换
+		changeTab(e) {
+			this.tabCurrentIndex = e.target.current;
+			this.loadData('tabChange');
+		},
+		//顶部tab点击
+		tabClick(index) {
+			this.tabCurrentIndex = index;
+		},
+		//删除订单
+		deleteOrder(index) {
+			uni.showLoading({
+				title: '请稍后'
+			});
+			setTimeout(() => {
+				this.navList[this.tabCurrentIndex].orderList.splice(index, 1);
+				uni.hideLoading();
+			}, 600);
+		},
+		//取消订单
+		cancelOrder(item) {
+			uni.showModal({
+				title: '订单取消',
+				content: '是否取消订单?',
+				success: e => {
+					if (e.confirm) {
+						uni.showLoading({
+							title: '请稍后'
+						});
+						orderCancel({ id: item.order_id })
+							.then(e => {
+								uni.showToast({
+									title: '取消成功',
+									duration: 2000,
+									position: 'top'
+								});
+							})
+							.catch(e => {
+								console.log(e);
+							});
+						//取消订单后删除待付款中该项
+						let list = this.navList[this.tabCurrentIndex].orderList;
+						let index = list.findIndex(val => val.id === item.id);
+						index !== -1 && list.splice(index, 1);
+						uni.hideLoading();
+					}
+				}
+			});
+		},
+
+		//订单状态文字和颜色
+		orderStateExp(state) {
+			let stateTip = '',
+				stateTipColor = '#fa436a';
+			switch (+state) {
+				case 0:
+					stateTip = '待付款';
+					break;
+				case 1:
+					stateTip = '待发货';
+					break;
+				case 2:
+					stateTip = '待收货';
+					break;
+				case 3:
+					stateTip = '待评价';
+					break;
+				case 4:
+					stateTip = '已完成';
+					stateTipColor = '#5dbc7c';
+					break;
+				case 9:
+					stateTip = '订单已关闭';
+					stateTipColor = '#909399';
+					break;
+
+				//更多自定义
+			}
+			return { stateTip, stateTipColor };
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+page,
+.content {
+	background: $page-color-base;
+	height: 100%;
+}
+
+.swiper-box {
+	height: calc(100% - 40px);
+}
+.list-scroll-content {
+	height: 100%;
+}
+
+.navbar {
+	display: flex;
+	height: 40px;
+	padding: 0 5px;
+	background: #fff;
+	box-shadow: 0 1px 5px rgba(0, 0, 0, 0.06);
+	position: relative;
+	z-index: 10;
+	.nav-item {
+		flex: 1;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		height: 100%;
+		font-size: 15px;
+		color: $font-color-dark;
+		position: relative;
+		&.current {
+			color: $base-color;
+			&:after {
+				content: '';
+				position: absolute;
+				left: 50%;
+				bottom: 0;
+				transform: translateX(-50%);
+				width: 44px;
+				height: 0;
+				border-bottom: 2px solid $base-color;
+			}
+		}
+	}
+}
+
+.uni-swiper-item {
+	height: auto;
+}
+.order-item {
+	display: flex;
+	flex-direction: column;
+	padding-left: 30rpx;
+	background: #fff;
+	margin-top: 16rpx;
+	.i-top {
+		display: flex;
+		align-items: center;
+		height: 80rpx;
+		padding-right: 30rpx;
+		font-size: $font-base;
+		color: $font-color-dark;
+		position: relative;
+		.time {
+			flex: 1;
+		}
+		.state {
+			color: $base-color;
+		}
+		.del-btn {
+			padding: 10rpx 0 10rpx 36rpx;
+			font-size: $font-lg;
+			color: $font-color-light;
+			position: relative;
+			&:after {
+				content: '';
+				width: 0;
+				height: 30rpx;
+				border-left: 1px solid $border-color-dark;
+				position: absolute;
+				left: 20rpx;
+				top: 50%;
+				transform: translateY(-50%);
+			}
+		}
+	}
+	/* 多条商品 */
+	.goods-box {
+		height: 160rpx;
+		padding: 20rpx 0;
+		white-space: nowrap;
+		.goods-item {
+			width: 120rpx;
+			height: 120rpx;
+			display: inline-block;
+			margin-right: 24rpx;
+		}
+		.goods-img {
+			display: block;
+			width: 100%;
+			height: 100%;
+		}
+	}
+	/* 单条商品 */
+	.goods-box-single {
+		display: flex;
+		padding: 20rpx 0;
+		.goods-img {
+			display: block;
+			width: 120rpx;
+			height: 120rpx;
+		}
+		.right {
+			flex: 1;
+			display: flex;
+			flex-direction: column;
+			padding: 0 30rpx 0 24rpx;
+			overflow: hidden;
+			.title {
+				font-size: $font-base + 2rpx;
+				color: $font-color-dark;
+				line-height: 1;
+			}
+			.attr-box {
+				font-size: $font-sm + 2rpx;
+				color: $font-color-light;
+				padding: 10rpx 12rpx;
+			}
+			.price {
+				font-size: $font-base + 2rpx;
+				color: $font-color-dark;
+				&:before {
+					content: '¥';
+					font-size: $font-sm;
+					margin: 0 2rpx 0 8rpx;
+				}
+			}
+		}
+	}
+
+	.price-box {
+		display: flex;
+		justify-content: flex-end;
+		align-items: baseline;
+		padding: 20rpx 30rpx;
+		font-size: $font-sm + 2rpx;
+		color: $font-color-light;
+		.num {
+			margin: 0 8rpx;
+			color: $font-color-dark;
+		}
+		.price {
+			font-size: $font-lg;
+			color: $font-color-dark;
+			&:before {
+				content: '¥';
+				font-size: $font-sm;
+				margin: 0 2rpx 0 8rpx;
+			}
+		}
+	}
+	.action-box {
+		display: flex;
+		justify-content: flex-end;
+		align-items: center;
+		height: 100rpx;
+		position: relative;
+		padding-right: 30rpx;
+	}
+	.action-btn {
+		width: 160rpx;
+		height: 60rpx;
+		margin: 0;
+		margin-left: 24rpx;
+		padding: 0;
+		text-align: center;
+		line-height: 60rpx;
+		font-size: $font-sm + 2rpx;
+		color: $font-color-dark;
+		background: #fff;
+		border-radius: 100px;
+		&:after {
+			border-radius: 100px;
+		}
+		&.recom {
+			color: $base-color;
+			&:after {
+				border-color: $base-color;
+			}
+		}
+		&.evaluate {
+			color: $color-yellow;
+			&:after {
+				border-color: $color-yellow;
+			}
+		}
+	}
+}
+
+/* load-more */
+.uni-load-more {
+	display: flex;
+	flex-direction: row;
+	height: 80rpx;
+	align-items: center;
+	justify-content: center;
+}
+
+.uni-load-more__text {
+	font-size: 28rpx;
+	color: #999;
+}
+
+.uni-load-more__img {
+	height: 24px;
+	width: 24px;
+	margin-right: 10px;
+}
+
+.uni-load-more__img > view {
+	position: absolute;
+}
+
+.uni-load-more__img > view view {
+	width: 6px;
+	height: 2px;
+	border-top-left-radius: 1px;
+	border-bottom-left-radius: 1px;
+	background: #999;
+	position: absolute;
+	opacity: 0.2;
+	transform-origin: 50%;
+	animation: load 1.56s ease infinite;
+}
+
+.uni-load-more__img > view view:nth-child(1) {
+	transform: rotate(90deg);
+	top: 2px;
+	left: 9px;
+}
+
+.uni-load-more__img > view view:nth-child(2) {
+	transform: rotate(180deg);
+	top: 11px;
+	right: 0;
+}
+
+.uni-load-more__img > view view:nth-child(3) {
+	transform: rotate(270deg);
+	bottom: 2px;
+	left: 9px;
+}
+
+.uni-load-more__img > view view:nth-child(4) {
+	top: 11px;
+	left: 0;
+}
+
+.load1,
+.load2,
+.load3 {
+	height: 24px;
+	width: 24px;
+}
+
+.load2 {
+	transform: rotate(30deg);
+}
+
+.load3 {
+	transform: rotate(60deg);
+}
+
+.load1 view:nth-child(1) {
+	animation-delay: 0s;
+}
+
+.load2 view:nth-child(1) {
+	animation-delay: 0.13s;
+}
+
+.load3 view:nth-child(1) {
+	animation-delay: 0.26s;
+}
+
+.load1 view:nth-child(2) {
+	animation-delay: 0.39s;
+}
+
+.load2 view:nth-child(2) {
+	animation-delay: 0.52s;
+}
+
+.load3 view:nth-child(2) {
+	animation-delay: 0.65s;
+}
+
+.load1 view:nth-child(3) {
+	animation-delay: 0.78s;
+}
+
+.load2 view:nth-child(3) {
+	animation-delay: 0.91s;
+}
+
+.load3 view:nth-child(3) {
+	animation-delay: 1.04s;
+}
+
+.load1 view:nth-child(4) {
+	animation-delay: 1.17s;
+}
+
+.load2 view:nth-child(4) {
+	animation-delay: 1.3s;
+}
+
+.load3 view:nth-child(4) {
+	animation-delay: 1.43s;
+}
+
+@-webkit-keyframes load {
+	0% {
+		opacity: 1;
+	}
+
+	100% {
+		opacity: 0.2;
+	}
+}
+</style>

Некоторые файлы не были показаны из-за большого количества измененных файлов