lyqu 5 år sedan
incheckning
4e8af82632
100 ändrade filer med 9335 tillägg och 0 borttagningar
  1. 20 0
      App.vue
  2. 23 0
      common/css/app.scss
  3. 184 0
      common/css/colorui/animation.css
  4. 36 0
      common/css/colorui/icon.css
  5. 3962 0
      common/css/colorui/main.css
  6. 116 0
      common/http/http.api.js
  7. 116 0
      common/http/http.interceptor.js
  8. 64 0
      components/basic/bottom-bar.vue
  9. 47 0
      components/basic/search-bar.vue
  10. 149 0
      components/views/activity-view.vue
  11. 113 0
      components/views/mine-view.vue
  12. 8 0
      components/views/points-view.vue
  13. 14 0
      main.js
  14. 71 0
      manifest.json
  15. 153 0
      pages.json
  16. 22 0
      pages/activity/activityDetail.vue
  17. 181 0
      pages/activity/boost.vue
  18. 55 0
      pages/activity/hot.vue
  19. 95 0
      pages/activity/signUp.vue
  20. 195 0
      pages/activity/songRank.vue
  21. 76 0
      pages/home/home.vue
  22. 117 0
      pages/index/index.vue
  23. 59 0
      pages/mine/boostDetail.vue
  24. 94 0
      pages/mine/edit.vue
  25. 89 0
      pages/mine/introduction.vue
  26. 85 0
      pages/mine/myAwards.vue
  27. 60 0
      pages/mine/myBoost.vue
  28. 231 0
      pages/mine/myGift.vue
  29. 127 0
      pages/mine/myMusic.vue
  30. 106 0
      pages/mine/myWelfare.vue
  31. 62 0
      pages/mine/order/address.vue
  32. 154 0
      pages/mine/order/orderConfirm.vue
  33. 69 0
      pages/mine/pointsDetail.vue
  34. BIN
      static/1.png
  35. BIN
      static/2.png
  36. BIN
      static/3.png
  37. BIN
      static/activity.png
  38. BIN
      static/address.png
  39. BIN
      static/avatar.png
  40. BIN
      static/avatar2.png
  41. BIN
      static/bgimg.png
  42. BIN
      static/crown.png
  43. BIN
      static/dialogBgImg.png
  44. BIN
      static/gift/commodity1.png
  45. BIN
      static/gift/commodity2.png
  46. BIN
      static/gift/commodity3.png
  47. BIN
      static/gift/commodity4.png
  48. BIN
      static/hot.png
  49. BIN
      static/icon-activity.png
  50. BIN
      static/icon-awards.png
  51. BIN
      static/icon-gift.png
  52. BIN
      static/icon-history.png
  53. BIN
      static/icon-lottery.png
  54. BIN
      static/icon-mall.png
  55. BIN
      static/icon-music.png
  56. BIN
      static/icon-order.png
  57. BIN
      static/icon-person.png
  58. BIN
      static/icon-points.png
  59. BIN
      static/icon-rule.png
  60. BIN
      static/icon-vip.png
  61. BIN
      static/icon-welfare.png
  62. BIN
      static/index/finish.png
  63. BIN
      static/index/fire.png
  64. BIN
      static/index/huodong1.png
  65. BIN
      static/index/huodong2x.png
  66. BIN
      static/index/ing.png
  67. BIN
      static/index/swiper.png
  68. BIN
      static/long.png
  69. BIN
      static/more.png
  70. BIN
      static/musicCover.png
  71. BIN
      static/personBgImg.png
  72. BIN
      static/present1.png
  73. BIN
      static/present2.png
  74. BIN
      static/present3.png
  75. BIN
      static/present4.png
  76. BIN
      static/signUp.png
  77. BIN
      static/singerBg.png
  78. BIN
      static/song.png
  79. BIN
      static/songRank/fm1.png
  80. BIN
      static/songRank/fm2.png
  81. BIN
      static/songRank/fm3.png
  82. BIN
      static/songRank/fm4.png
  83. BIN
      static/songRank/medal.png
  84. BIN
      static/songRank/songRankBgImg.png
  85. BIN
      static/swiper1.png
  86. BIN
      static/userBgImg.png
  87. BIN
      static/welfare/welfare1.png
  88. BIN
      static/welfare/welfare2.png
  89. BIN
      static/welfare/welfare3.png
  90. BIN
      static/welfare/welfare4.png
  91. BIN
      static/welfare/welfare5.png
  92. 77 0
      uni.scss
  93. 21 0
      uview-ui/LICENSE
  94. 106 0
      uview-ui/README.md
  95. 190 0
      uview-ui/components/u-action-sheet/u-action-sheet.vue
  96. 256 0
      uview-ui/components/u-alert-tips/u-alert-tips.vue
  97. 290 0
      uview-ui/components/u-avatar-cropper/u-avatar-cropper.vue
  98. 1265 0
      uview-ui/components/u-avatar-cropper/weCropper.js
  99. 24 0
      uview-ui/components/u-avatar/u-avatar.vue
  100. 153 0
      uview-ui/components/u-back-top/u-back-top.vue

+ 20 - 0
App.vue

@@ -0,0 +1,20 @@
+<script>
+	export default {
+		onLaunch: function() {
+			console.log('App Launch')
+		},
+		onShow: function() {
+			console.log('App Show')
+		},
+		onHide: function() {
+			console.log('App Hide')
+		}
+	}
+</script>
+
+<style lang="scss">
+		@import "uview-ui/index.scss";
+		@import "common/css/colorui/main.css";
+		@import "common/css/colorui/icon.css";
+		@import "common/css/app.scss";
+</style>

+ 23 - 0
common/css/app.scss

@@ -0,0 +1,23 @@
+	.footer-fixed {
+		position: fixed;
+		z-index: 10000;
+		width: 100%;
+		bottom: 0;
+		left: 0;
+	}
+	.footer-fixed.foot-pb {
+		padding-bottom: calc(env(safe-area-inset-bottom) / 2);
+	}
+	.theme-bg-color {
+		background-color: #5a3ee8;
+	}
+	.theme-color {
+		color: #5a3ee8;
+	}
+	.text-cut-2 {
+		overflow: hidden;
+		text-overflow: ellipsis;
+		display: -webkit-box;
+		-webkit-line-clamp: 2;
+		-webkit-box-orient: vertical;
+	}

+ 184 - 0
common/css/colorui/animation.css

@@ -0,0 +1,184 @@
+/* 
+  Animation 微动画  
+  基于ColorUI组建库的动画模块 by 文晓港 2019年3月26日19:52:28
+ */
+
+/* css 滤镜 控制黑白底色gif的 */
+.gif-black{  
+  mix-blend-mode: screen;  
+}
+.gif-white{  
+  mix-blend-mode: multiply; 
+}
+
+
+/* Animation css */
+[class*=animation-] {
+    animation-duration: .5s;
+    animation-timing-function: ease-out;
+    animation-fill-mode: both
+}
+
+.animation-fade {
+    animation-name: fade;
+    animation-duration: .8s;
+    animation-timing-function: linear
+}
+
+.animation-scale-up {
+    animation-name: scale-up
+}
+
+.animation-scale-down {
+    animation-name: scale-down
+}
+
+.animation-slide-top {
+    animation-name: slide-top
+}
+
+.animation-slide-bottom {
+    animation-name: slide-bottom
+}
+
+.animation-slide-left {
+    animation-name: slide-left
+}
+
+.animation-slide-right {
+    animation-name: slide-right
+}
+
+.animation-shake {
+    animation-name: shake
+}
+
+.animation-reverse {
+    animation-direction: reverse
+}
+
+@keyframes fade {
+    0% {
+        opacity: 0
+    }
+
+    100% {
+        opacity: 1
+    }
+}
+
+@keyframes scale-up {
+    0% {
+        opacity: 0;
+        transform: scale(.2)
+    }
+
+    100% {
+        opacity: 1;
+        transform: scale(1)
+    }
+}
+
+@keyframes scale-down {
+    0% {
+        opacity: 0;
+        transform: scale(1.8)
+    }
+
+    100% {
+        opacity: 1;
+        transform: scale(1)
+    }
+}
+
+@keyframes slide-top {
+    0% {
+        opacity: 0;
+        transform: translateY(-100%)
+    }
+
+    100% {
+        opacity: 1;
+        transform: translateY(0)
+    }
+}
+
+@keyframes slide-bottom {
+    0% {
+        opacity: 0;
+        transform: translateY(100%)
+    }
+
+    100% {
+        opacity: 1;
+        transform: translateY(0)
+    }
+}
+
+@keyframes shake {
+
+    0%,
+    100% {
+        transform: translateX(0)
+    }
+
+    10% {
+        transform: translateX(-9px)
+    }
+
+    20% {
+        transform: translateX(8px)
+    }
+
+    30% {
+        transform: translateX(-7px)
+    }
+
+    40% {
+        transform: translateX(6px)
+    }
+
+    50% {
+        transform: translateX(-5px)
+    }
+
+    60% {
+        transform: translateX(4px)
+    }
+
+    70% {
+        transform: translateX(-3px)
+    }
+
+    80% {
+        transform: translateX(2px)
+    }
+
+    90% {
+        transform: translateX(-1px)
+    }
+}
+
+@keyframes slide-left {
+    0% {
+        opacity: 0;
+        transform: translateX(-100%)
+    }
+
+    100% {
+        opacity: 1;
+        transform: translateX(0)
+    }
+}
+
+@keyframes slide-right {
+    0% {
+        opacity: 0;
+        transform: translateX(100%)
+    }
+
+    100% {
+        opacity: 1;
+        transform: translateX(0)
+    }
+}

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 36 - 0
common/css/colorui/icon.css


+ 3962 - 0
common/css/colorui/main.css

@@ -0,0 +1,3962 @@
+
+/* ==================
+        初始化
+ ==================== */
+body {
+	background-color: #f1f1f1;
+	font-size: 28upx;
+	color: #333333;
+	font-family: Helvetica Neue, Helvetica, sans-serif;
+}
+
+view,
+scroll-view,
+swiper,
+button,
+input,
+textarea,
+label,
+navigator,
+image {
+	box-sizing: border-box;
+}
+
+.round {
+	border-radius: 5000upx;
+}
+
+.radius {
+	border-radius: 6upx;
+}
+
+/* ==================
+          图片
+ ==================== */
+
+image {
+	max-width: 100%;
+	display: inline-block;
+	position: relative;
+	z-index: 0;
+}
+
+image.loading::before {
+	content: "";
+	background-color: #f5f5f5;
+	display: block;
+	position: absolute;
+	width: 100%;
+	height: 100%;
+	z-index: -2;
+}
+
+image.loading::after {
+	content: "\e7f1";
+	font-family: "cuIcon";
+	position: absolute;
+	top: 0;
+	left: 0;
+	width: 32upx;
+	height: 32upx;
+	line-height: 32upx;
+	right: 0;
+	bottom: 0;
+	z-index: -1;
+	font-size: 32upx;
+	margin: auto;
+	color: #ccc;
+	-webkit-animation: cuIcon-spin 2s infinite linear;
+	animation: cuIcon-spin 2s infinite linear;
+	display: block;
+}
+
+.response {
+	width: 100%;
+}
+
+/* ==================
+         开关
+ ==================== */
+
+switch,
+checkbox,
+radio {
+	position: relative;
+}
+
+switch::after,
+switch::before {
+	font-family: "cuIcon";
+	content: "\e645";
+	position: absolute;
+	color: #ffffff !important;
+	top: 0%;
+	left: 0upx;
+	font-size: 26upx;
+	line-height: 26px;
+	width: 50%;
+	text-align: center;
+	pointer-events: none;
+	transform: scale(0, 0);
+	transition: all 0.3s ease-in-out 0s;
+	z-index: 9;
+	bottom: 0;
+	height: 26px;
+	margin: auto;
+}
+
+switch::before {
+	content: "\e646";
+	right: 0;
+	transform: scale(1, 1);
+	left: auto;
+}
+
+switch[checked]::after,
+switch.checked::after {
+	transform: scale(1, 1);
+}
+
+switch[checked]::before,
+switch.checked::before {
+	transform: scale(0, 0);
+}
+
+/* #ifndef MP-ALIPAY */
+radio::before,
+checkbox::before {
+	font-family: "cuIcon";
+	content: "\e645";
+	position: absolute;
+	color: #ffffff !important;
+	top: 50%;
+	margin-top: -8px;
+	right: 5px;
+	font-size: 32upx;
+	line-height: 16px;
+	pointer-events: none;
+	transform: scale(1, 1);
+	transition: all 0.3s ease-in-out 0s;
+	z-index: 9;
+}
+
+radio .wx-radio-input,
+checkbox .wx-checkbox-input,
+radio .uni-radio-input,
+checkbox .uni-checkbox-input {
+	margin: 0;
+	width: 24px;
+	height: 24px;
+}
+
+checkbox.round .wx-checkbox-input,
+checkbox.round .uni-checkbox-input {
+	border-radius: 100upx;
+}
+
+/* #endif */
+
+switch[checked]::before {
+	transform: scale(0, 0);
+}
+
+switch .wx-switch-input,
+switch .uni-switch-input {
+	border: none;
+	padding: 0 24px;
+	width: 48px;
+	height: 26px;
+	margin: 0;
+	border-radius: 100upx;
+}
+
+switch .wx-switch-input:not([class*="bg-"]),
+switch .uni-switch-input:not([class*="bg-"]) {
+	background: #8799a3 !important;
+}
+
+switch .wx-switch-input::after,
+switch .uni-switch-input::after {
+	margin: auto;
+	width: 26px;
+	height: 26px;
+	border-radius: 100upx;
+	left: 0upx;
+	top: 0upx;
+	bottom: 0upx;
+	position: absolute;
+	transform: scale(0.9, 0.9);
+	transition: all 0.1s ease-in-out 0s;
+}
+
+switch .wx-switch-input.wx-switch-input-checked::after,
+switch .uni-switch-input.uni-switch-input-checked::after {
+	margin: auto;
+	left: 22px;
+	box-shadow: none;
+	transform: scale(0.9, 0.9);
+}
+
+radio-group {
+	display: inline-block;
+}
+
+
+
+switch.radius .wx-switch-input::after,
+switch.radius .wx-switch-input,
+switch.radius .wx-switch-input::before,
+switch.radius .uni-switch-input::after,
+switch.radius .uni-switch-input,
+switch.radius .uni-switch-input::before {
+	border-radius: 10upx;
+}
+
+switch .wx-switch-input::before,
+radio.radio::before,
+checkbox .wx-checkbox-input::before,
+radio .wx-radio-input::before,
+switch .uni-switch-input::before,
+radio.radio::before,
+checkbox .uni-checkbox-input::before,
+radio .uni-radio-input::before {
+	display: none;
+}
+
+radio.radio[checked]::after,
+radio.radio .uni-radio-input-checked::after {
+	content: "";
+	background-color: transparent;
+	display: block;
+	position: absolute;
+	width: 8px;
+	height: 8px;
+	z-index: 999;
+	top: 0upx;
+	left: 0upx;
+	right: 0;
+	bottom: 0;
+	margin: auto;
+	border-radius: 200upx;
+	/* #ifndef MP */
+	border: 7px solid #ffffff !important;
+	/* #endif */
+
+	/* #ifdef MP */
+	border: 8px solid #ffffff !important;
+	/* #endif */
+}
+
+.switch-sex::after {
+	content: "\e71c";
+}
+
+.switch-sex::before {
+	content: "\e71a";
+}
+
+.switch-sex .wx-switch-input,
+.switch-sex .uni-switch-input {
+	background: #e54d42 !important;
+	border-color: #e54d42 !important;
+}
+
+.switch-sex[checked] .wx-switch-input,
+.switch-sex.checked .uni-switch-input {
+	background: #0081ff !important;
+	border-color: #0081ff !important;
+}
+
+switch.red[checked] .wx-switch-input.wx-switch-input-checked,
+checkbox.red[checked] .wx-checkbox-input,
+radio.red[checked] .wx-radio-input,
+switch.red.checked .uni-switch-input.uni-switch-input-checked,
+checkbox.red.checked .uni-checkbox-input,
+radio.red.checked .uni-radio-input {
+	background-color: #e54d42 !important;
+	border-color: #e54d42 !important;
+	color: #ffffff !important;
+}
+
+switch.orange[checked] .wx-switch-input,
+checkbox.orange[checked] .wx-checkbox-input,
+radio.orange[checked] .wx-radio-input,
+switch.orange.checked .uni-switch-input,
+checkbox.orange.checked .uni-checkbox-input,
+radio.orange.checked .uni-radio-input {
+	background-color: #f37b1d !important;
+	border-color: #f37b1d !important;
+	color: #ffffff !important;
+}
+
+switch.yellow[checked] .wx-switch-input,
+checkbox.yellow[checked] .wx-checkbox-input,
+radio.yellow[checked] .wx-radio-input,
+switch.yellow.checked .uni-switch-input,
+checkbox.yellow.checked .uni-checkbox-input,
+radio.yellow.checked .uni-radio-input {
+	background-color: #fbbd08 !important;
+	border-color: #fbbd08 !important;
+	color: #333333 !important;
+}
+
+switch.olive[checked] .wx-switch-input,
+checkbox.olive[checked] .wx-checkbox-input,
+radio.olive[checked] .wx-radio-input,
+switch.olive.checked .uni-switch-input,
+checkbox.olive.checked .uni-checkbox-input,
+radio.olive.checked .uni-radio-input {
+	background-color: #8dc63f !important;
+	border-color: #8dc63f !important;
+	color: #ffffff !important;
+}
+
+switch.green[checked] .wx-switch-input,
+switch[checked] .wx-switch-input,
+checkbox.green[checked] .wx-checkbox-input,
+checkbox[checked] .wx-checkbox-input,
+radio.green[checked] .wx-radio-input,
+radio[checked] .wx-radio-input,
+switch.green.checked .uni-switch-input,
+switch.checked .uni-switch-input,
+checkbox.green.checked .uni-checkbox-input,
+checkbox.checked .uni-checkbox-input,
+radio.green.checked .uni-radio-input,
+radio.checked .uni-radio-input {
+	background-color: #39b54a !important;
+	border-color: #39b54a !important;
+	color: #ffffff !important;
+	border-color: #39B54A !important;
+}
+
+switch.cyan[checked] .wx-switch-input,
+checkbox.cyan[checked] .wx-checkbox-input,
+radio.cyan[checked] .wx-radio-input,
+switch.cyan.checked .uni-switch-input,
+checkbox.cyan.checked .uni-checkbox-input,
+radio.cyan.checked .uni-radio-input {
+	background-color: #1cbbb4 !important;
+	border-color: #1cbbb4 !important;
+	color: #ffffff !important;
+}
+
+switch.blue[checked] .wx-switch-input,
+checkbox.blue[checked] .wx-checkbox-input,
+radio.blue[checked] .wx-radio-input,
+switch.blue.checked .uni-switch-input,
+checkbox.blue.checked .uni-checkbox-input,
+radio.blue.checked .uni-radio-input {
+	background-color: #0081ff !important;
+	border-color: #0081ff !important;
+	color: #ffffff !important;
+}
+
+switch.purple[checked] .wx-switch-input,
+checkbox.purple[checked] .wx-checkbox-input,
+radio.purple[checked] .wx-radio-input,
+switch.purple.checked .uni-switch-input,
+checkbox.purple.checked .uni-checkbox-input,
+radio.purple.checked .uni-radio-input {
+	background-color: #6739b6 !important;
+	border-color: #6739b6 !important;
+	color: #ffffff !important;
+}
+
+switch.mauve[checked] .wx-switch-input,
+checkbox.mauve[checked] .wx-checkbox-input,
+radio.mauve[checked] .wx-radio-input,
+switch.mauve.checked .uni-switch-input,
+checkbox.mauve.checked .uni-checkbox-input,
+radio.mauve.checked .uni-radio-input {
+	background-color: #9c26b0 !important;
+	border-color: #9c26b0 !important;
+	color: #ffffff !important;
+}
+
+switch.pink[checked] .wx-switch-input,
+checkbox.pink[checked] .wx-checkbox-input,
+radio.pink[checked] .wx-radio-input,
+switch.pink.checked .uni-switch-input,
+checkbox.pink.checked .uni-checkbox-input,
+radio.pink.checked .uni-radio-input {
+	background-color: #e03997 !important;
+	border-color: #e03997 !important;
+	color: #ffffff !important;
+}
+
+switch.brown[checked] .wx-switch-input,
+checkbox.brown[checked] .wx-checkbox-input,
+radio.brown[checked] .wx-radio-input,
+switch.brown.checked .uni-switch-input,
+checkbox.brown.checked .uni-checkbox-input,
+radio.brown.checked .uni-radio-input {
+	background-color: #a5673f !important;
+	border-color: #a5673f !important;
+	color: #ffffff !important;
+}
+
+switch.grey[checked] .wx-switch-input,
+checkbox.grey[checked] .wx-checkbox-input,
+radio.grey[checked] .wx-radio-input,
+switch.grey.checked .uni-switch-input,
+checkbox.grey.checked .uni-checkbox-input,
+radio.grey.checked .uni-radio-input {
+	background-color: #8799a3 !important;
+	border-color: #8799a3 !important;
+	color: #ffffff !important;
+}
+
+switch.gray[checked] .wx-switch-input,
+checkbox.gray[checked] .wx-checkbox-input,
+radio.gray[checked] .wx-radio-input,
+switch.gray.checked .uni-switch-input,
+checkbox.gray.checked .uni-checkbox-input,
+radio.gray.checked .uni-radio-input {
+	background-color: #f0f0f0 !important;
+	border-color: #f0f0f0 !important;
+	color: #333333 !important;
+}
+
+switch.black[checked] .wx-switch-input,
+checkbox.black[checked] .wx-checkbox-input,
+radio.black[checked] .wx-radio-input,
+switch.black.checked .uni-switch-input,
+checkbox.black.checked .uni-checkbox-input,
+radio.black.checked .uni-radio-input {
+	background-color: #333333 !important;
+	border-color: #333333 !important;
+	color: #ffffff !important;
+}
+
+switch.white[checked] .wx-switch-input,
+checkbox.white[checked] .wx-checkbox-input,
+radio.white[checked] .wx-radio-input,
+switch.white.checked .uni-switch-input,
+checkbox.white.checked .uni-checkbox-input,
+radio.white.checked .uni-radio-input {
+	background-color: #ffffff !important;
+	border-color: #ffffff !important;
+	color: #333333 !important;
+}
+
+/* ==================
+          边框
+ ==================== */
+
+/* -- 实线 -- */
+
+.solid,
+.solid-top,
+.solid-right,
+.solid-bottom,
+.solid-left,
+.solids,
+.solids-top,
+.solids-right,
+.solids-bottom,
+.solids-left,
+.dashed,
+.dashed-top,
+.dashed-right,
+.dashed-bottom,
+.dashed-left {
+	position: relative;
+}
+
+.solid::after,
+.solid-top::after,
+.solid-right::after,
+.solid-bottom::after,
+.solid-left::after,
+.solids::after,
+.solids-top::after,
+.solids-right::after,
+.solids-bottom::after,
+.solids-left::after,
+.dashed::after,
+.dashed-top::after,
+.dashed-right::after,
+.dashed-bottom::after,
+.dashed-left::after {
+	content: " ";
+	width: 200%;
+	height: 200%;
+	position: absolute;
+	top: 0;
+	left: 0;
+	border-radius: inherit;
+	transform: scale(0.5);
+	transform-origin: 0 0;
+	pointer-events: none;
+	box-sizing: border-box;
+}
+
+.solid::after {
+	border: 1upx solid rgba(0, 0, 0, 0.1);
+}
+
+.solid-top::after {
+	border-top: 1upx solid rgba(0, 0, 0, 0.1);
+}
+
+.solid-right::after {
+	border-right: 1upx solid rgba(0, 0, 0, 0.1);
+}
+
+.solid-bottom::after {
+	border-bottom: 1upx solid rgba(0, 0, 0, 0.1);
+}
+
+.solid-left::after {
+	border-left: 1upx solid rgba(0, 0, 0, 0.1);
+}
+
+.solids::after {
+	border: 8upx solid #eee;
+}
+
+.solids-top::after {
+	border-top: 8upx solid #eee;
+}
+
+.solids-right::after {
+	border-right: 8upx solid #eee;
+}
+
+.solids-bottom::after {
+	border-bottom: 8upx solid #eee;
+}
+
+.solids-left::after {
+	border-left: 8upx solid #eee;
+}
+
+/* -- 虚线 -- */
+
+.dashed::after {
+	border: 1upx dashed #ddd;
+}
+
+.dashed-top::after {
+	border-top: 1upx dashed #ddd;
+}
+
+.dashed-right::after {
+	border-right: 1upx dashed #ddd;
+}
+
+.dashed-bottom::after {
+	border-bottom: 1upx dashed #ddd;
+}
+
+.dashed-left::after {
+	border-left: 1upx dashed #ddd;
+}
+
+/* -- 阴影 -- */
+
+.shadow[class*='white'] {
+	--ShadowSize: 0 1upx 6upx;
+}
+
+.shadow-lg {
+	--ShadowSize: 0upx 40upx 100upx 0upx;
+}
+
+.shadow-warp {
+	position: relative;
+	box-shadow: 0 0 10upx rgba(0, 0, 0, 0.1);
+}
+
+.shadow-warp:before,
+.shadow-warp:after {
+	position: absolute;
+	content: "";
+	top: 20upx;
+	bottom: 30upx;
+	left: 20upx;
+	width: 50%;
+	box-shadow: 0 30upx 20upx rgba(0, 0, 0, 0.2);
+	transform: rotate(-3deg);
+	z-index: -1;
+}
+
+.shadow-warp:after {
+	right: 20upx;
+	left: auto;
+	transform: rotate(3deg);
+}
+
+.shadow-blur {
+	position: relative;
+}
+
+.shadow-blur::before {
+	content: "";
+	display: block;
+	background: inherit;
+	filter: blur(10upx);
+	position: absolute;
+	width: 100%;
+	height: 100%;
+	top: 10upx;
+	left: 10upx;
+	z-index: -1;
+	opacity: 0.4;
+	transform-origin: 0 0;
+	border-radius: inherit;
+	transform: scale(1, 1);
+}
+
+/* ==================
+          按钮
+ ==================== */
+
+.cu-btn {
+	position: relative;
+	border: 0upx;
+	display: inline-flex;
+	align-items: center;
+	justify-content: center;
+	box-sizing: border-box;
+	padding: 0 30upx;
+	font-size: 28upx;
+	height: 64upx;
+	line-height: 1;
+	text-align: center;
+	text-decoration: none;
+	overflow: visible;
+	margin-left: initial;
+	transform: translate(0upx, 0upx);
+	margin-right: initial;
+}
+
+.cu-btn::after {
+	display: none;
+}
+
+.cu-btn:not([class*="bg-"]) {
+	background-color: #f0f0f0;
+}
+
+.cu-btn[class*="line"] {
+	background-color: transparent;
+}
+
+.cu-btn[class*="line"]::after {
+	content: " ";
+	display: block;
+	width: 200%;
+	height: 200%;
+	position: absolute;
+	top: 0;
+	left: 0;
+	border: 1upx solid currentColor;
+	transform: scale(0.5);
+	transform-origin: 0 0;
+	box-sizing: border-box;
+	border-radius: 12upx;
+	z-index: 1;
+	pointer-events: none;
+}
+
+.cu-btn.round[class*="line"]::after {
+	border-radius: 1000upx;
+}
+
+.cu-btn[class*="lines"]::after {
+	border: 6upx solid currentColor;
+}
+
+.cu-btn[class*="bg-"]::after {
+	display: none;
+}
+
+.cu-btn.sm {
+	padding: 0 20upx;
+	font-size: 20upx;
+	height: 48upx;
+}
+
+.cu-btn.df {
+	padding: 0 22upx;
+	font-size: 22upx;
+	height: 50upx;
+}
+
+.cu-btn.lg {
+	padding: 0 40upx;
+	font-size: 32upx;
+	height: 80upx;
+}
+
+.cu-btn.cuIcon.sm {
+	width: 48upx;
+	height: 48upx;
+}
+
+.cu-btn.cuIcon {
+	width: 64upx;
+	height: 64upx;
+	border-radius: 500upx;
+	padding: 0;
+}
+
+button.cuIcon.lg {
+	width: 80upx;
+	height: 80upx;
+}
+
+.cu-btn.shadow-blur::before {
+	top: 4upx;
+	left: 4upx;
+	filter: blur(6upx);
+	opacity: 0.6;
+}
+
+.cu-btn.button-hover {
+	transform: translate(1upx, 1upx);
+}
+
+.block {
+	display: block;
+}
+
+.cu-btn.block {
+	display: flex;
+}
+
+.cu-btn[disabled] {
+	opacity: 0.6;
+	color: #ffffff;
+}
+
+/* ==================
+          徽章
+ ==================== */
+
+.cu-tag {
+	font-size: 24upx;
+	vertical-align: middle;
+	position: relative;
+	display: inline-flex;
+	align-items: center;
+	justify-content: center;
+	box-sizing: border-box;
+	padding: 0upx 16upx;
+	height: 48upx;
+	font-family: Helvetica Neue, Helvetica, sans-serif;
+	white-space: nowrap;
+}
+
+.cu-tag:not([class*="bg"]):not([class*="line"]) {
+	background-color: #f1f1f1;
+}
+
+.cu-tag[class*="line-"]::after {
+	content: " ";
+	width: 200%;
+	height: 200%;
+	position: absolute;
+	top: 0;
+	left: 0;
+	border: 1upx solid currentColor;
+	transform: scale(0.5);
+	transform-origin: 0 0;
+	box-sizing: border-box;
+	border-radius: inherit;
+	z-index: 1;
+	pointer-events: none;
+}
+
+.cu-tag.radius[class*="line"]::after {
+	border-radius: 12upx;
+}
+
+.cu-tag.round[class*="line"]::after {
+	border-radius: 1000upx;
+}
+
+.cu-tag[class*="line-"]::after {
+	border-radius: 0;
+}
+
+.cu-tag+.cu-tag {
+	margin-left: 10upx;
+}
+
+.cu-tag.sm {
+	font-size: 20upx;
+	padding: 0upx 12upx;
+	height: 32upx;
+}
+
+.cu-capsule {
+	display: inline-flex;
+	vertical-align: middle;
+}
+
+.cu-capsule+.cu-capsule {
+	margin-left: 10upx;
+}
+
+.cu-capsule .cu-tag {
+	margin: 0;
+}
+
+.cu-capsule .cu-tag[class*="line-"]:last-child::after {
+	border-left: 0upx solid transparent;
+}
+
+.cu-capsule .cu-tag[class*="line-"]:first-child::after {
+	border-right: 0upx solid transparent;
+}
+
+.cu-capsule.radius .cu-tag:first-child {
+	border-top-left-radius: 6upx;
+	border-bottom-left-radius: 6upx;
+}
+
+.cu-capsule.radius .cu-tag:last-child::after,
+.cu-capsule.radius .cu-tag[class*="line-"] {
+	border-top-right-radius: 12upx;
+	border-bottom-right-radius: 12upx;
+}
+
+.cu-capsule.round .cu-tag:first-child {
+	border-top-left-radius: 200upx;
+	border-bottom-left-radius: 200upx;
+	text-indent: 4upx;
+}
+
+.cu-capsule.round .cu-tag:last-child::after,
+.cu-capsule.round .cu-tag:last-child {
+	border-top-right-radius: 200upx;
+	border-bottom-right-radius: 200upx;
+	text-indent: -4upx;
+}
+
+.cu-tag.badge {
+	border-radius: 200upx;
+	position: absolute;
+	top: -10upx;
+	right: -10upx;
+	font-size: 20upx;
+	padding: 0upx 10upx;
+	height: 28upx;
+	color: #ffffff;
+}
+
+.cu-tag.badge:not([class*="bg-"]) {
+	background-color: #dd514c;
+}
+
+.cu-tag:empty:not([class*="cuIcon-"]) {
+	padding: 0upx;
+	width: 16upx;
+	height: 16upx;
+	top: -4upx;
+	right: -4upx;
+}
+
+.cu-tag[class*="cuIcon-"] {
+	width: 32upx;
+	height: 32upx;
+	top: -4upx;
+	right: -4upx;
+}
+
+/* ==================
+          头像
+ ==================== */
+
+.cu-avatar {
+	font-variant: small-caps;
+	margin: 0;
+	padding: 0;
+	display: inline-flex;
+	text-align: center;
+	justify-content: center;
+	align-items: center;
+	background-color: #ccc;
+	color: #ffffff;
+	white-space: nowrap;
+	position: relative;
+	width: 64upx;
+	height: 64upx;
+	background-size: cover;
+	background-position: center;
+	vertical-align: middle;
+	font-size: 1.5em;
+}
+
+.cu-avatar.sm {
+	width: 48upx;
+	height: 48upx;
+	font-size: 1em;
+}
+
+.cu-avatar.lg {
+	width: 96upx;
+	height: 96upx;
+	font-size: 2em;
+}
+
+.cu-avatar.xl {
+	width: 128upx;
+	height: 128upx;
+	font-size: 2.5em;
+}
+
+.cu-avatar .avatar-text {
+	font-size: 0.4em;
+}
+
+.cu-avatar-group {
+	direction: rtl;
+	unicode-bidi: bidi-override;
+	padding: 0 10upx 0 40upx;
+	display: inline-block;
+}
+
+.cu-avatar-group .cu-avatar {
+	margin-left: -30upx;
+	border: 4upx solid #f1f1f1;
+	vertical-align: middle;
+}
+
+.cu-avatar-group .cu-avatar.sm {
+	margin-left: -20upx;
+	border: 1upx solid #f1f1f1;
+}
+
+/* ==================
+         进度条
+ ==================== */
+
+.cu-progress {
+	overflow: hidden;
+	height: 28upx;
+	background-color: #ebeef5;
+	display: inline-flex;
+	align-items: center;
+	width: 100%;
+}
+
+.cu-progress+view,
+.cu-progress+text {
+	line-height: 1;
+}
+
+.cu-progress.xs {
+	height: 10upx;
+}
+
+.cu-progress.sm {
+	height: 20upx;
+}
+
+.cu-progress view {
+	width: 0;
+	height: 100%;
+	align-items: center;
+	display: flex;
+	justify-items: flex-end;
+	justify-content: space-around;
+	font-size: 20upx;
+	color: #ffffff;
+	transition: width 0.6s ease;
+}
+
+.cu-progress text {
+	align-items: center;
+	display: flex;
+	font-size: 20upx;
+	color: #333333;
+	text-indent: 10upx;
+}
+
+.cu-progress.text-progress {
+	padding-right: 60upx;
+}
+
+.cu-progress.striped view {
+	background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+	background-size: 72upx 72upx;
+}
+
+.cu-progress.active view {
+	animation: progress-stripes 2s linear infinite;
+}
+
+@keyframes progress-stripes {
+	from {
+		background-position: 72upx 0;
+	}
+
+	to {
+		background-position: 0 0;
+	}
+}
+
+/* ==================
+          加载
+ ==================== */
+
+.cu-load {
+	display: block;
+	line-height: 3em;
+	text-align: center;
+}
+
+.cu-load::before {
+	font-family: "cuIcon";
+	display: inline-block;
+	margin-right: 6upx;
+}
+
+.cu-load.loading::before {
+	content: "\e67a";
+	animation: cuIcon-spin 2s infinite linear;
+}
+
+.cu-load.loading::after {
+	content: "加载中...";
+}
+
+.cu-load.over::before {
+	content: "\e64a";
+}
+
+.cu-load.over::after {
+	content: "没有更多了";
+}
+
+.cu-load.erro::before {
+	content: "\e658";
+}
+
+.cu-load.erro::after {
+	content: "加载失败";
+}
+
+.cu-load.load-cuIcon::before {
+	font-size: 32upx;
+}
+
+.cu-load.load-cuIcon::after {
+	display: none;
+}
+
+.cu-load.load-cuIcon.over {
+	display: none;
+}
+
+.cu-load.load-modal {
+	position: fixed;
+	top: 0;
+	right: 0;
+	bottom: 140upx;
+	left: 0;
+	margin: auto;
+	width: 260upx;
+	height: 260upx;
+	background-color: #ffffff;
+	border-radius: 10upx;
+	box-shadow: 0 0 0upx 2000upx rgba(0, 0, 0, 0.5);
+	display: flex;
+	align-items: center;
+	flex-direction: column;
+	justify-content: center;
+	font-size: 28upx;
+	z-index: 9999;
+	line-height: 2.4em;
+}
+
+.cu-load.load-modal [class*="cuIcon-"] {
+	font-size: 60upx;
+}
+
+.cu-load.load-modal image {
+	width: 70upx;
+	height: 70upx;
+}
+
+.cu-load.load-modal::after {
+	content: "";
+	position: absolute;
+	background-color: #ffffff;
+	border-radius: 50%;
+	width: 200upx;
+	height: 200upx;
+	font-size: 10px;
+	border-top: 6upx solid rgba(0, 0, 0, 0.05);
+	border-right: 6upx solid rgba(0, 0, 0, 0.05);
+	border-bottom: 6upx solid rgba(0, 0, 0, 0.05);
+	border-left: 6upx solid #f37b1d;
+	animation: cuIcon-spin 1s infinite linear;
+	z-index: -1;
+}
+
+.load-progress {
+	pointer-events: none;
+	top: 0;
+	position: fixed;
+	width: 100%;
+	left: 0;
+	z-index: 2000;
+}
+
+.load-progress.hide {
+	display: none;
+}
+
+.load-progress .load-progress-bar {
+	position: relative;
+	width: 100%;
+	height: 4upx;
+	overflow: hidden;
+	transition: all 200ms ease 0s;
+}
+
+.load-progress .load-progress-spinner {
+	position: absolute;
+	top: 10upx;
+	right: 10upx;
+	z-index: 2000;
+	display: block;
+}
+
+.load-progress .load-progress-spinner::after {
+	content: "";
+	display: block;
+	width: 24upx;
+	height: 24upx;
+	-webkit-box-sizing: border-box;
+	box-sizing: border-box;
+	border: solid 4upx transparent;
+	border-top-color: inherit;
+	border-left-color: inherit;
+	border-radius: 50%;
+	-webkit-animation: load-progress-spinner 0.4s linear infinite;
+	animation: load-progress-spinner 0.4s linear infinite;
+}
+
+@-webkit-keyframes load-progress-spinner {
+	0% {
+		-webkit-transform: rotate(0);
+		transform: rotate(0);
+	}
+
+	100% {
+		-webkit-transform: rotate(360deg);
+		transform: rotate(360deg);
+	}
+}
+
+@keyframes load-progress-spinner {
+	0% {
+		-webkit-transform: rotate(0);
+		transform: rotate(0);
+	}
+
+	100% {
+		-webkit-transform: rotate(360deg);
+		transform: rotate(360deg);
+	}
+}
+
+/* ==================
+          列表
+ ==================== */
+.grayscale {
+	filter: grayscale(1);
+}
+
+.cu-list+.cu-list {
+	margin-top: 30upx
+}
+
+.cu-list>.cu-item {
+	transition: all .6s ease-in-out 0s;
+	transform: translateX(0upx)
+}
+
+.cu-list>.cu-item.move-cur {
+	transform: translateX(-260upx)
+}
+
+.cu-list>.cu-item .move {
+	position: absolute;
+	right: 0;
+	display: flex;
+	width: 260upx;
+	height: 100%;
+	transform: translateX(100%)
+}
+
+.cu-list>.cu-item .move view {
+	display: flex;
+	flex: 1;
+	justify-content: center;
+	align-items: center
+}
+
+.cu-list.menu-avatar {
+	overflow: hidden;
+}
+
+.cu-list.menu-avatar>.cu-item {
+	position: relative;
+	display: flex;
+	padding-right: 10upx;
+	height: 140upx;
+	background-color: #ffffff;
+	justify-content: flex-end;
+	align-items: center
+}
+
+.cu-list.menu-avatar>.cu-item>.cu-avatar {
+	position: absolute;
+	left: 30upx
+}
+
+.cu-list.menu-avatar>.cu-item .flex .text-cut {
+	max-width: 510upx
+}
+
+.cu-list.menu-avatar>.cu-item .content {
+	position: absolute;
+	left: 146upx;
+	width: calc(100% - 96upx - 60upx - 120upx - 20upx);
+	line-height: 1.6em;
+}
+
+.cu-list.menu-avatar>.cu-item .content.flex-sub {
+	width: calc(100% - 96upx - 60upx - 20upx);
+}
+
+.cu-list.menu-avatar>.cu-item .content>view:first-child {
+	font-size: 30upx;
+	display: flex;
+	align-items: center
+}
+
+.cu-list.menu-avatar>.cu-item .content .cu-tag.sm {
+	display: inline-block;
+	margin-left: 10upx;
+	height: 28upx;
+	font-size: 16upx;
+	line-height: 32upx
+}
+
+.cu-list.menu-avatar>.cu-item .action {
+	width: 100upx;
+	text-align: center
+}
+
+.cu-list.menu-avatar>.cu-item .action view+view {
+	margin-top: 10upx
+}
+
+.cu-list.menu-avatar.comment>.cu-item .content {
+	position: relative;
+	left: 0;
+	width: auto;
+	flex: 1;
+}
+
+.cu-list.menu-avatar.comment>.cu-item {
+	padding: 30upx 30upx 30upx 120upx;
+	height: auto
+}
+
+.cu-list.menu-avatar.comment .cu-avatar {
+	align-self: flex-start
+}
+
+.cu-list.menu>.cu-item {
+	position: relative;
+	display: flex;
+	padding: 0 30upx;
+	min-height: 100upx;
+	background-color: #ffffff;
+	justify-content: space-between;
+	align-items: center
+}
+
+.cu-list.menu>.cu-item:last-child:after {
+	border: none
+}
+
+.cu-list.menu-avatar>.cu-item:after,
+.cu-list.menu>.cu-item:after {
+	position: absolute;
+	top: 0;
+	left: 0;
+	box-sizing: border-box;
+	width: 200%;
+	height: 200%;
+	border-bottom: 1upx solid #ddd;
+	border-radius: inherit;
+	content: " ";
+	transform: scale(.5);
+	transform-origin: 0 0;
+	pointer-events: none
+}
+
+.cu-list.menu>.cu-item.grayscale {
+	background-color: #f5f5f5
+}
+
+.cu-list.menu>.cu-item.cur {
+	background-color: #fcf7e9
+}
+
+.cu-list.menu>.cu-item.arrow {
+	padding-right: 90upx
+}
+
+.cu-list.menu>.cu-item.arrow:before {
+	position: absolute;
+	top: 0;
+	right: 30upx;
+	bottom: 0;
+	display: block;
+	margin: auto;
+	width: 30upx;
+	height: 30upx;
+	color: #8799a3;
+	content: "\e6a3";
+	text-align: center;
+	font-size: 34upx;
+	font-family: cuIcon;
+	line-height: 30upx
+}
+
+.cu-list.menu>.cu-item.checked {
+	padding-right: 90upx
+}
+
+.cu-list.menu>.cu-item.checked:before {
+	position: absolute;
+	top: 0;
+	right: 30upx;
+	bottom: 0;
+	display: block;
+	margin: auto;
+	width: 30upx;
+	height: 30upx;
+	color: #8799a3;
+	content: "\e645";
+	text-align: center;
+	font-size: 34upx;
+	font-family: cuIcon;
+	line-height: 30upx
+}
+
+
+
+.cu-list.menu>.cu-item button.content {
+	padding: 0;
+	background-color: transparent;
+	justify-content: flex-start
+}
+
+.cu-list.menu>.cu-item button.content:after {
+	display: none
+}
+
+.cu-list.menu>.cu-item .cu-avatar-group .cu-avatar {
+	border-color: #ffffff
+}
+
+.cu-list.menu>.cu-item .content>view:first-child {
+	display: flex;
+	align-items: center
+}
+
+.cu-list.menu>.cu-item .content>text[class*=cuIcon] {
+	display: inline-block;
+	margin-right: 10upx;
+	width: 1.6em;
+	text-align: center
+}
+
+.cu-list.menu>.cu-item .content>image {
+	display: inline-block;
+	margin-right: 10upx;
+	width: 1.6em;
+	height: 1.6em;
+	vertical-align: middle
+}
+
+.cu-list.menu>.cu-item .content {
+	font-size: 30upx;
+	line-height: 1.6em;
+	flex: 1
+}
+
+.cu-list.menu>.cu-item .content .cu-tag.sm {
+	display: inline-block;
+	margin-left: 10upx;
+	height: 28upx;
+	font-size: 16upx;
+	line-height: 32upx
+}
+
+.cu-list.menu>.cu-item .action .cu-tag:empty {
+	right: 10upx
+}
+
+.cu-list.menu {
+	display: block;
+	overflow: hidden
+}
+
+.cu-list.menu.sm-border>.cu-item:after {
+	left: 30upx;
+	width: calc(200% - 120upx)
+}
+
+.cu-list.grid>.cu-item {
+	position: relative;
+	display: flex;
+	padding: 20upx 0 30upx;
+	transition-duration: 0s;
+	flex-direction: column
+}
+
+.cu-list.grid>.cu-item:after {
+	position: absolute;
+	top: 0;
+	left: 0;
+	box-sizing: border-box;
+	width: 200%;
+	height: 200%;
+	border-right: 1px solid rgba(0, 0, 0, .1);
+	border-bottom: 1px solid rgba(0, 0, 0, .1);
+	border-radius: inherit;
+	content: " ";
+	transform: scale(.5);
+	transform-origin: 0 0;
+	pointer-events: none
+}
+
+.cu-list.grid>.cu-item text {
+	display: block;
+	margin-top: 10upx;
+	color: #888;
+	font-size: 26upx;
+	line-height: 40upx
+}
+
+.cu-list.grid>.cu-item [class*=cuIcon] {
+	position: relative;
+	display: block;
+	margin-top: 20upx;
+	width: 100%;
+	font-size: 48upx
+}
+
+.cu-list.grid>.cu-item .cu-tag {
+	right: auto;
+	left: 50%;
+	margin-left: 20upx
+}
+
+.cu-list.grid {
+	background-color: #ffffff;
+	text-align: center
+}
+
+.cu-list.grid.no-border>.cu-item {
+	padding-top: 10upx;
+	padding-bottom: 20upx
+}
+
+.cu-list.grid.no-border>.cu-item:after {
+	border: none
+}
+
+.cu-list.grid.no-border {
+	padding: 20upx 10upx
+}
+
+.cu-list.grid.col-3>.cu-item:nth-child(3n):after,
+.cu-list.grid.col-4>.cu-item:nth-child(4n):after,
+.cu-list.grid.col-5>.cu-item:nth-child(5n):after {
+	border-right-width: 0
+}
+
+.cu-list.card-menu {
+	overflow: hidden;
+	margin-right: 30upx;
+	margin-left: 30upx;
+	border-radius: 20upx
+}
+
+
+/* ==================
+          操作条
+ ==================== */
+
+.cu-bar {
+	display: flex;
+	position: relative;
+	align-items: center;
+	min-height: 100upx;
+	justify-content: space-between;
+}
+
+.cu-bar .action {
+	display: flex;
+	align-items: center;
+	height: 100%;
+	justify-content: center;
+	max-width: 100%;
+}
+
+.cu-bar .action.border-title {
+	position: relative;
+	top: -10upx;
+}
+
+.cu-bar .action.border-title text[class*="bg-"]:last-child {
+	position: absolute;
+	bottom: -0.5rem;
+	min-width: 2rem;
+	height: 6upx;
+	left: 0;
+}
+
+.cu-bar .action.sub-title {
+	position: relative;
+	top: -0.2rem;
+}
+
+.cu-bar .action.sub-title text {
+	position: relative;
+	z-index: 1;
+}
+
+.cu-bar .action.sub-title text[class*="bg-"]:last-child {
+	position: absolute;
+	display: inline-block;
+	bottom: -0.2rem;
+	border-radius: 6upx;
+	width: 100%;
+	height: 0.6rem;
+	left: 0.6rem;
+	opacity: 0.3;
+	z-index: 0;
+}
+
+.cu-bar .action.sub-title text[class*="text-"]:last-child {
+	position: absolute;
+	display: inline-block;
+	bottom: -0.7rem;
+	left: 0.5rem;
+	opacity: 0.2;
+	z-index: 0;
+	text-align: right;
+	font-weight: 900;
+	font-size: 36upx;
+}
+
+.cu-bar.justify-center .action.border-title text:last-child,
+.cu-bar.justify-center .action.sub-title text:last-child {
+	left: 0;
+	right: 0;
+	margin: auto;
+	text-align: center;
+}
+
+.cu-bar .action:first-child {
+	margin-left: 30upx;
+	font-size: 30upx;
+}
+
+.cu-bar .action text.text-cut {
+	text-align: left;
+	width: 100%;
+}
+
+.cu-bar .cu-avatar:first-child {
+	margin-left: 20upx;
+}
+
+.cu-bar .action:first-child>text[class*="cuIcon-"] {
+	margin-left: -0.3em;
+	margin-right: 0.3em;
+}
+
+.cu-bar .action:last-child {
+	margin-right: 30upx;
+}
+
+.cu-bar .action>text[class*="cuIcon-"],
+.cu-bar .action>view[class*="cuIcon-"] {
+	font-size: 36upx;
+}
+
+.cu-bar .action>text[class*="cuIcon-"]+text[class*="cuIcon-"] {
+	margin-left: 0.5em;
+}
+
+.cu-bar .content {
+	position: absolute;
+	text-align: center;
+	width: calc(100% - 340upx);
+	left: 0;
+	right: 0;
+	bottom: 0;
+	top: 0;
+	margin: auto;
+	height: 60upx;
+	font-size: 32upx;
+	line-height: 60upx;
+	cursor: none;
+	pointer-events: none;
+	text-overflow: ellipsis;
+	white-space: nowrap;
+	overflow: hidden;
+}
+
+.cu-bar.ios .content {
+	bottom: 7px;
+	height: 30px;
+	font-size: 32upx;
+	line-height: 30px;
+}
+
+.cu-bar.btn-group {
+	justify-content: space-around;
+}
+
+.cu-bar.btn-group button {
+	padding: 20upx 32upx;
+}
+
+.cu-bar.btn-group button {
+	flex: 1;
+	margin: 0 20upx;
+	max-width: 50%;
+}
+
+.cu-bar .search-form {
+	background-color: #f5f5f5;
+	line-height: 64upx;
+	height: 64upx;
+	font-size: 24upx;
+	color: #333333;
+	flex: 1;
+	display: flex;
+	align-items: center;
+	margin: 0 30upx;
+}
+
+.cu-bar .search-form+.action {
+	margin-right: 30upx;
+}
+
+.cu-bar .search-form input {
+	flex: 1;
+	padding-right: 30upx;
+	height: 64upx;
+	line-height: 64upx;
+	font-size: 26upx;
+	background-color: transparent;
+}
+
+.cu-bar .search-form [class*="cuIcon-"] {
+	margin: 0 0.5em 0 0.8em;
+}
+
+.cu-bar .search-form [class*="cuIcon-"]::before {
+	top: 0upx;
+}
+
+.cu-bar.fixed,
+.nav.fixed {
+	position: fixed;
+	width: 100%;
+	top: 0;
+	z-index: 1024;
+	box-shadow: 0 1upx 6upx rgba(0, 0, 0, 0.1);
+}
+
+.cu-bar.foot {
+	position: fixed;
+	width: 100%;
+	bottom: 0;
+	z-index: 1024;
+	box-shadow: 0 -1upx 6upx rgba(0, 0, 0, 0.1);
+}
+
+.cu-bar.tabbar {
+	padding: 0;
+	height: calc(100upx + env(safe-area-inset-bottom) / 2);
+	padding-bottom: calc(env(safe-area-inset-bottom) / 2);
+}
+
+.cu-tabbar-height {
+	min-height: 100upx;
+	height: calc(100upx + env(safe-area-inset-bottom) / 2);
+}
+
+.cu-bar.tabbar.shadow {
+	box-shadow: 0 -1upx 6upx rgba(0, 0, 0, 0.1);
+}
+
+.cu-bar.tabbar .action {
+	font-size: 22upx;
+	position: relative;
+	flex: 1;
+	text-align: center;
+	padding: 0;
+	display: block;
+	height: auto;
+	line-height: 1;
+	margin: 0;
+	background-color: inherit;
+	overflow: initial;
+}
+
+.cu-bar.tabbar.shop .action {
+	width: 140upx;
+	flex: initial;
+}
+
+.cu-bar.tabbar .action.add-action {
+	position: relative;
+	z-index: 2;
+	padding-top: 50upx;
+}
+
+.cu-bar.tabbar .action.add-action [class*="cuIcon-"] {
+	position: absolute;
+	width: 70upx;
+	z-index: 2;
+	height: 70upx;
+	border-radius: 50%;
+	line-height: 70upx;
+	font-size: 50upx;
+	top: -35upx;
+	left: 0;
+	right: 0;
+	margin: auto;
+	padding: 0;
+}
+
+.cu-bar.tabbar .action.add-action::after {
+	content: "";
+	position: absolute;
+	width: 100upx;
+	height: 100upx;
+	top: -50upx;
+	left: 0;
+	right: 0;
+	margin: auto;
+	box-shadow: 0 -3upx 8upx rgba(0, 0, 0, 0.08);
+	border-radius: 50upx;
+	background-color: inherit;
+	z-index: 0;
+}
+
+.cu-bar.tabbar .action.add-action::before {
+	content: "";
+	position: absolute;
+	width: 100upx;
+	height: 30upx;
+	bottom: 30upx;
+	left: 0;
+	right: 0;
+	margin: auto;
+	background-color: inherit;
+	z-index: 1;
+}
+
+.cu-bar.tabbar .btn-group {
+	flex: 1;
+	display: flex;
+	justify-content: space-around;
+	align-items: center;
+	padding: 0 10upx;
+}
+
+.cu-bar.tabbar button.action::after {
+	border: 0;
+}
+
+.cu-bar.tabbar .action [class*="cuIcon-"] {
+	width: 100upx;
+	position: relative;
+	display: block;
+	height: auto;
+	margin: 0 auto 10upx;
+	text-align: center;
+	font-size: 40upx;
+}
+
+.cu-bar.tabbar .action .cuIcon-cu-image {
+	margin: 0 auto;
+}
+
+.cu-bar.tabbar .action .cuIcon-cu-image image {
+	width: 50upx;
+	height: 50upx;
+	display: inline-block;
+}
+
+.cu-bar.tabbar .submit {
+	align-items: center;
+	display: flex;
+	justify-content: center;
+	text-align: center;
+	position: relative;
+	flex: 2;
+	align-self: stretch;
+}
+
+.cu-bar.tabbar .submit:last-child {
+	flex: 2.6;
+}
+
+.cu-bar.tabbar .submit+.submit {
+	flex: 2;
+}
+
+.cu-bar.tabbar.border .action::before {
+	content: " ";
+	width: 200%;
+	height: 200%;
+	position: absolute;
+	top: 0;
+	left: 0;
+	transform: scale(0.5);
+	transform-origin: 0 0;
+	border-right: 1upx solid rgba(0, 0, 0, 0.1);
+	z-index: 3;
+}
+
+.cu-bar.tabbar.border .action:last-child:before {
+	display: none;
+}
+
+.cu-bar.input {
+	padding-right: 20upx;
+	background-color: #ffffff;
+}
+
+.cu-bar.input input {
+	overflow: initial;
+	line-height: 64upx;
+	height: 64upx;
+	min-height: 64upx;
+	flex: 1;
+	font-size: 30upx;
+	margin: 0 20upx;
+}
+
+.cu-bar.input .action {
+	margin-left: 20upx;
+}
+
+.cu-bar.input .action [class*="cuIcon-"] {
+	font-size: 48upx;
+}
+
+.cu-bar.input input+.action {
+	margin-right: 20upx;
+	margin-left: 0upx;
+}
+
+.cu-bar.input .action:first-child [class*="cuIcon-"] {
+	margin-left: 0upx;
+}
+
+.cu-custom {
+	display: block;
+	position: relative;
+}
+
+.cu-custom .cu-bar .content {
+	width: calc(100% - 440upx);
+}
+
+/* #ifdef MP-ALIPAY */
+.cu-custom .cu-bar .action .cuIcon-back {
+	opacity: 0;
+}
+
+/* #endif */
+
+.cu-custom .cu-bar .content image {
+	height: 60upx;
+	width: 240upx;
+}
+
+.cu-custom .cu-bar {
+	min-height: 0px;
+	/* #ifdef MP-WEIXIN */
+	padding-right: 220upx;
+	/* #endif */
+	/* #ifdef MP-ALIPAY */
+	padding-right: 150upx;
+	/* #endif */
+	box-shadow: 0upx 0upx 0upx;
+	z-index: 9999;
+}
+
+.cu-custom .cu-bar .border-custom {
+	position: relative;
+	background: rgba(0, 0, 0, 0.15);
+	border-radius: 1000upx;
+	height: 30px;
+}
+
+.cu-custom .cu-bar .border-custom::after {
+	content: " ";
+	width: 200%;
+	height: 200%;
+	position: absolute;
+	top: 0;
+	left: 0;
+	border-radius: inherit;
+	transform: scale(0.5);
+	transform-origin: 0 0;
+	pointer-events: none;
+	box-sizing: border-box;
+	border: 1upx solid #ffffff;
+	opacity: 0.5;
+}
+
+.cu-custom .cu-bar .border-custom::before {
+	content: " ";
+	width: 1upx;
+	height: 110%;
+	position: absolute;
+	top: 22.5%;
+	left: 0;
+	right: 0;
+	margin: auto;
+	transform: scale(0.5);
+	transform-origin: 0 0;
+	pointer-events: none;
+	box-sizing: border-box;
+	opacity: 0.6;
+	background-color: #ffffff;
+}
+
+.cu-custom .cu-bar .border-custom text {
+	display: block;
+	flex: 1;
+	margin: auto !important;
+	text-align: center;
+	font-size: 34upx;
+}
+
+/* ==================
+         导航栏
+ ==================== */
+
+.nav {
+	white-space: nowrap;
+}
+
+::-webkit-scrollbar {
+	display: none;
+}
+
+.nav .cu-item {
+	height: 90upx;
+	display: inline-block;
+	line-height: 90upx;
+	margin: 0 10upx;
+	padding: 0 20upx;
+}
+
+.nav .cu-item.cur {
+	border-bottom: 4upx solid;
+}
+
+/* ==================
+         时间轴
+ ==================== */
+
+.cu-timeline {
+	display: block;
+	background-color: #ffffff;
+}
+
+.cu-timeline .cu-time {
+	width: 120upx;
+	text-align: center;
+	padding: 20upx 0;
+	font-size: 26upx;
+	color: #888;
+	display: block;
+}
+
+.cu-timeline>.cu-item {
+	padding: 30upx 30upx 30upx 120upx;
+	position: relative;
+	display: block;
+	z-index: 0;
+}
+
+.cu-timeline>.cu-item:not([class*="text-"]) {
+	color: #ccc;
+}
+
+.cu-timeline>.cu-item::after {
+	content: "";
+	display: block;
+	position: absolute;
+	width: 1upx;
+	background-color: #ddd;
+	left: 60upx;
+	height: 100%;
+	top: 0;
+	z-index: 8;
+}
+
+.cu-timeline>.cu-item::before {
+	font-family: "cuIcon";
+	display: block;
+	position: absolute;
+	top: 36upx;
+	z-index: 9;
+	background-color: #ffffff;
+	width: 50upx;
+	height: 50upx;
+	text-align: center;
+	border: none;
+	line-height: 50upx;
+	left: 36upx;
+}
+
+.cu-timeline>.cu-item:not([class*="cuIcon-"])::before {
+	content: "\e763";
+}
+
+.cu-timeline>.cu-item[class*="cuIcon-"]::before {
+	background-color: #ffffff;
+	width: 50upx;
+	height: 50upx;
+	text-align: center;
+	border: none;
+	line-height: 50upx;
+	left: 36upx;
+}
+
+.cu-timeline>.cu-item>.content {
+	padding: 30upx;
+	border-radius: 6upx;
+	display: block;
+	line-height: 1.6;
+}
+
+.cu-timeline>.cu-item>.content:not([class*="bg-"]) {
+	background-color: #f1f1f1;
+	color: #333333;
+}
+
+.cu-timeline>.cu-item>.content+.content {
+	margin-top: 20upx;
+}
+
+/* ==================
+         聊天
+ ==================== */
+
+.cu-chat {
+	display: flex;
+	flex-direction: column;
+}
+
+.cu-chat .cu-item {
+	display: flex;
+	padding: 30upx 30upx 70upx;
+	position: relative;
+}
+
+.cu-chat .cu-item>.cu-avatar {
+	width: 80upx;
+	height: 80upx;
+}
+
+.cu-chat .cu-item>.main {
+	max-width: calc(100% - 260upx);
+	margin: 0 40upx;
+	display: flex;
+	align-items: center;
+}
+
+.cu-chat .cu-item>image {
+	height: 320upx;
+}
+
+.cu-chat .cu-item>.main .content {
+	padding: 20upx;
+	border-radius: 6upx;
+	display: inline-flex;
+	max-width: 100%;
+	align-items: center;
+	font-size: 30upx;
+	position: relative;
+	min-height: 80upx;
+	line-height: 40upx;
+	text-align: left;
+}
+
+.cu-chat .cu-item>.main .content:not([class*="bg-"]) {
+	background-color: #ffffff;
+	color: #333333;
+}
+
+.cu-chat .cu-item .date {
+	position: absolute;
+	font-size: 24upx;
+	color: #8799a3;
+	width: calc(100% - 320upx);
+	bottom: 20upx;
+	left: 160upx;
+}
+
+.cu-chat .cu-item .action {
+	padding: 0 30upx;
+	display: flex;
+	align-items: center;
+}
+
+.cu-chat .cu-item>.main .content::after {
+	content: "";
+	top: 27upx;
+	transform: rotate(45deg);
+	position: absolute;
+	z-index: 100;
+	display: inline-block;
+	overflow: hidden;
+	width: 24upx;
+	height: 24upx;
+	left: -12upx;
+	right: initial;
+	background-color: inherit;
+}
+
+.cu-chat .cu-item.self>.main .content::after {
+	left: auto;
+	right: -12upx;
+}
+
+.cu-chat .cu-item>.main .content::before {
+	content: "";
+	top: 30upx;
+	transform: rotate(45deg);
+	position: absolute;
+	z-index: -1;
+	display: inline-block;
+	overflow: hidden;
+	width: 24upx;
+	height: 24upx;
+	left: -12upx;
+	right: initial;
+	background-color: inherit;
+	filter: blur(5upx);
+	opacity: 0.3;
+}
+
+.cu-chat .cu-item>.main .content:not([class*="bg-"])::before {
+	background-color: #333333;
+	opacity: 0.1;
+}
+
+.cu-chat .cu-item.self>.main .content::before {
+	left: auto;
+	right: -12upx;
+}
+
+.cu-chat .cu-item.self {
+	justify-content: flex-end;
+	text-align: right;
+}
+
+.cu-chat .cu-info {
+	display: inline-block;
+	margin: 20upx auto;
+	font-size: 24upx;
+	padding: 8upx 12upx;
+	background-color: rgba(0, 0, 0, 0.2);
+	border-radius: 6upx;
+	color: #ffffff;
+	max-width: 400upx;
+	line-height: 1.4;
+}
+
+/* ==================
+         卡片
+ ==================== */
+
+.cu-card {
+	display: block;
+	overflow: hidden;
+}
+
+.cu-card>.cu-item {
+	display: block;
+	background-color: #ffffff;
+	overflow: hidden;
+	border-radius: 10upx;
+	margin: 30upx;
+}
+
+.cu-card>.cu-item.shadow-blur {
+	overflow: initial;
+}
+
+.cu-card.no-card>.cu-item {
+	margin: 0upx;
+	border-radius: 20upx;
+}
+
+.cu-card .grid.grid-square {
+	margin-bottom: -20upx;
+}
+
+.cu-card.case .image {
+	position: relative;
+}
+
+.cu-card.case .image image {
+	width: 100%;
+}
+
+.cu-card.case .image .cu-tag {
+	position: absolute;
+	left: 0;
+	top: 0;
+}
+
+.cu-card.case .image .indexvideoIcon{
+	position: absolute;
+	left: 35%;
+	top: 30%;
+}
+
+.cu-card.case .image .videoIcon{
+	position: absolute;
+	left: 45%;
+	top: 30%;
+}
+
+.cu-card.case .image .cu-bar {
+	position: absolute;
+	bottom: 0;
+	width: 100%;
+	background-color: transparent;
+	padding: 0upx;
+	padding-left: 30rpx;
+}
+
+.cu-card.case.no-card .image {
+	margin: 30upx 30upx 0;
+	overflow: hidden;
+	border-radius: 10upx;
+}
+
+.cu-card.dynamic {
+	display: block;
+}
+
+.cu-card.dynamic>.cu-item {
+	display: block;
+	background-color: #ffffff;
+	overflow: hidden;
+}
+
+.cu-card.dynamic>.cu-item>.text-content {
+	padding: 0 30upx 0;
+	max-height: 6.4em;
+	overflow: hidden;
+	font-size: 30upx;
+	margin-bottom: 20upx;
+}
+
+.cu-card.dynamic>.cu-item .square-img {
+	width: 100%;
+	height: 200upx;
+	border-radius: 6upx;
+}
+
+.cu-card.dynamic>.cu-item .only-img {
+	width: 100%;
+	height: 320upx;
+	border-radius: 6upx;
+}
+
+/* card.dynamic>.cu-item .comment {
+  padding: 20upx;
+  background-color: #f1f1f1;
+  margin: 0 30upx 30upx;
+  border-radius: 6upx;
+} */
+
+.cu-card.article {
+	display: block;
+}
+
+.cu-card.article>.cu-item {
+	padding-bottom: 30upx;
+}
+
+.cu-card.article>.cu-item .title {
+	font-size: 30upx;
+	font-weight: 900;
+	color: #333333;
+	line-height: 100upx;
+	padding: 0 30upx;
+}
+
+.cu-card.article>.cu-item .content {
+	display: flex;
+	padding: 0 30upx;
+}
+
+.cu-card.article>.cu-item .content>image {
+	width: 240upx;
+	height: 6.4em;
+	margin-right: 20upx;
+	border-radius: 6upx;
+}
+
+.cu-card.article>.cu-item .content .desc {
+	flex: 1;
+	display: flex;
+	flex-direction: column;
+	justify-content: space-between;
+}
+
+.cu-card.article>.cu-item .content .text-content {
+	font-size: 28upx;
+	color: #888;
+	height: 4.8em;
+	overflow: hidden;
+}
+
+/* ==================
+         表单
+ ==================== */
+
+.cu-form-group {
+	background-color: #ffffff;
+	padding: 1upx 30upx;
+	display: flex;
+	align-items: center;
+	min-height: 100upx;
+	justify-content: space-between;
+}
+
+.cu-form-group+.cu-form-group {
+	border-top: 1upx solid #eee;
+}
+
+.cu-form-group .title {
+	text-align: justify;
+	padding-right: 30upx;
+	font-size: 30upx;
+	position: relative;
+	height: 60upx;
+	line-height: 60upx;
+}
+
+.cu-form-group input {
+	flex: 1;
+	font-size: 30upx;
+	color: #555;
+	padding-right: 20upx;
+}
+
+.cu-form-group>text[class*="cuIcon-"] {
+	font-size: 36upx;
+	padding: 0;
+	box-sizing: border-box;
+}
+
+.cu-form-group textarea {
+	margin: 32upx 0 30upx;
+	height: 4.6em;
+	width: 100%;
+	line-height: 1.2em;
+	flex: 1;
+	font-size: 28upx;
+	padding: 0;
+}
+
+.cu-form-group.align-start .title {
+	height: 1em;
+	margin-top: 32upx;
+	line-height: 1em;
+}
+
+.cu-form-group picker {
+	flex: 1;
+	padding-right: 40upx;
+	overflow: hidden;
+	position: relative;
+}
+
+.cu-form-group picker .picker {
+	line-height: 100upx;
+	font-size: 28upx;
+	text-overflow: ellipsis;
+	white-space: nowrap;
+	overflow: hidden;
+	width: 100%;
+	text-align: right;
+}
+
+.cu-form-group picker::after {
+	font-family: cuIcon;
+	display: block;
+	content: "\e6a3";
+	position: absolute;
+	font-size: 34upx;
+	color: #8799a3;
+	line-height: 100upx;
+	width: 60upx;
+	text-align: center;
+	top: 0;
+	bottom: 0;
+	right: -20upx;
+	margin: auto;
+}
+
+.cu-form-group textarea[disabled],
+.cu-form-group textarea[disabled] .placeholder {
+	color: transparent;
+}
+
+/* ==================
+         模态窗口
+ ==================== */
+
+.cu-modal {
+	position: fixed;
+	top: 0;
+	right: 0;
+	bottom: 0;
+	left: 0;
+	z-index: 1110;
+	opacity: 0;
+	outline: 0;
+	text-align: center;
+	-ms-transform: scale(1.185);
+	transform: scale(1.185);
+	backface-visibility: hidden;
+	perspective: 2000upx;
+	background: rgba(0, 0, 0, 0.6);
+	transition: all 0.3s ease-in-out 0s;
+	pointer-events: none;
+}
+
+.cu-modal::before {
+	content: "\200B";
+	display: inline-block;
+	height: 100%;
+	vertical-align: middle;
+}
+
+.cu-modal.show {
+	opacity: 1;
+	transition-duration: 0.3s;
+	-ms-transform: scale(1);
+	transform: scale(1);
+	overflow-x: hidden;
+	overflow-y: auto;
+	pointer-events: auto;
+}
+
+.cu-dialog {
+	position: relative;
+	display: inline-block;
+	vertical-align: middle;
+	margin-left: auto;
+	margin-right: auto;
+	width: 680upx;
+	max-width: 100%;
+	background-color: #f8f8f8;
+	border-radius: 10upx;
+	overflow: hidden;
+}
+
+.cu-modal.bottom-modal::before {
+	vertical-align: bottom;
+}
+
+.cu-modal.bottom-modal .cu-dialog {
+	width: 100%;
+	border-radius: 0;
+}
+
+.cu-modal.bottom-modal {
+	margin-bottom: -1000upx;
+}
+
+.cu-modal.bottom-modal.show {
+	margin-bottom: 0;
+}
+
+.cu-modal.drawer-modal {
+	transform: scale(1);
+	display: flex;
+}
+
+.cu-modal.drawer-modal .cu-dialog {
+	height: 100%;
+	min-width: 200upx;
+	border-radius: 0;
+	margin: initial;
+	transition-duration: 0.3s;
+}
+
+.cu-modal.drawer-modal.justify-start .cu-dialog {
+	transform: translateX(-100%);
+}
+
+.cu-modal.drawer-modal.justify-end .cu-dialog {
+	transform: translateX(100%);
+}
+
+.cu-modal.drawer-modal.show .cu-dialog {
+	transform: translateX(0%);
+}
+.cu-modal .cu-dialog>.cu-bar:first-child .action{
+  min-width: 100rpx;
+  margin-right: 0;
+  min-height: 100rpx;
+}
+/* ==================
+         轮播
+ ==================== */
+swiper .a-swiper-dot {
+	display: inline-block;
+	width: 16upx;
+	height: 16upx;
+	background: rgba(0, 0, 0, .3);
+	border-radius: 50%;
+	vertical-align: middle;
+}
+
+swiper[class*="-dot"] .wx-swiper-dots,
+swiper[class*="-dot"] .a-swiper-dots,
+swiper[class*="-dot"] .uni-swiper-dots {
+	display: flex;
+	align-items: center;
+	width: 100%;
+	justify-content: center;
+}
+
+swiper.square-dot .wx-swiper-dot,
+swiper.square-dot .a-swiper-dot,
+swiper.square-dot .uni-swiper-dot {
+	background-color: #ffffff;
+	opacity: 0.4;
+	width: 10upx;
+	height: 10upx;
+	border-radius: 20upx;
+	margin: 0 8upx !important;
+}
+
+swiper.square-dot .wx-swiper-dot.wx-swiper-dot-active,
+swiper.square-dot .a-swiper-dot.a-swiper-dot-active,
+swiper.square-dot .uni-swiper-dot.uni-swiper-dot-active {
+	opacity: 1;
+	width: 30upx;
+}
+
+swiper.round-dot .wx-swiper-dot,
+swiper.round-dot .a-swiper-dot,
+swiper.round-dot .uni-swiper-dot {
+	width: 10upx;
+	height: 10upx;
+	position: relative;
+	margin: 4upx 8upx !important;
+}
+
+swiper.round-dot .wx-swiper-dot.wx-swiper-dot-active::after,
+swiper.round-dot .a-swiper-dot.a-swiper-dot-active::after,
+swiper.round-dot .uni-swiper-dot.uni-swiper-dot-active::after {
+	content: "";
+	position: absolute;
+	width: 10upx;
+	height: 10upx;
+	top: 0upx;
+	left: 0upx;
+	right: 0;
+	bottom: 0;
+	margin: auto;
+	background-color: #ffffff;
+	border-radius: 20upx;
+}
+
+swiper.round-dot .wx-swiper-dot.wx-swiper-dot-active,
+swiper.round-dot .a-swiper-dot.a-swiper-dot-active,
+swiper.round-dot .uni-swiper-dot.uni-swiper-dot-active {
+	width: 18upx;
+	height: 18upx;
+}
+
+.screen-swiper {
+	min-height: 375upx;
+}
+
+.screen-swiper image,
+.screen-swiper video,
+.swiper-item image,
+.swiper-item video {
+	width: 100%;
+	display: block;
+	height: 100%;
+	margin: 0;
+	pointer-events: none;
+}
+
+.card-swiper {
+	height: 420upx !important;
+}
+
+.card-swiper swiper-item {
+	width: 610upx !important;
+	left: 70upx;
+	box-sizing: border-box;
+	padding: 40upx 0upx 70upx;
+	overflow: initial;
+}
+
+.card-swiper swiper-item .swiper-item {
+	width: 100%;
+	display: block;
+	height: 100%;
+	border-radius: 10upx;
+	transform: scale(0.9);
+	transition: all 0.2s ease-in 0s;
+	overflow: hidden;
+}
+
+.card-swiper swiper-item.cur .swiper-item {
+	transform: none;
+	transition: all 0.2s ease-in 0s;
+}
+
+
+.tower-swiper {
+	height: 420upx;
+	position: relative;
+	max-width: 750upx;
+	overflow: hidden;
+}
+
+.tower-swiper .tower-item {
+	position: absolute;
+	width: 300upx;
+	height: 380upx;
+	top: 0;
+	bottom: 0;
+	left: 50%;
+	margin: auto;
+	transition: all 0.2s ease-in 0s;
+	opacity: 1;
+}
+
+.tower-swiper .tower-item.none {
+	opacity: 0;
+}
+
+.tower-swiper .tower-item .swiper-item {
+	width: 100%;
+	height: 100%;
+	border-radius: 6upx;
+	overflow: hidden;
+}
+
+/* ==================
+          步骤条
+ ==================== */
+
+.cu-steps {
+	display: flex;
+}
+
+scroll-view.cu-steps {
+	display: block;
+	white-space: nowrap;
+}
+
+scroll-view.cu-steps .cu-item {
+	display: inline-block;
+}
+
+.cu-steps .cu-item {
+	flex: 1;
+	text-align: center;
+	position: relative;
+	min-width: 100upx;
+}
+
+.cu-steps .cu-item:not([class*="text-"]) {
+	color: #8799a3;
+}
+
+.cu-steps .cu-item [class*="cuIcon-"],
+.cu-steps .cu-item .num {
+	display: block;
+	font-size: 40upx;
+	line-height: 80upx;
+}
+
+.cu-steps .cu-item::before,
+.cu-steps .cu-item::after,
+.cu-steps.steps-arrow .cu-item::before,
+.cu-steps.steps-arrow .cu-item::after {
+	content: "";
+	display: block;
+	position: absolute;
+	height: 0px;
+	width: calc(100% - 80upx);
+	border-bottom: 1px solid #ccc;
+	left: calc(0px - (100% - 80upx) / 2);
+	top: 40upx;
+	z-index: 0;
+}
+
+.cu-steps.steps-arrow .cu-item::before,
+.cu-steps.steps-arrow .cu-item::after {
+	content: "\e6a3";
+	font-family: 'cuIcon';
+	height: 30upx;
+	border-bottom-width: 0px;
+	line-height: 30upx;
+	top: 0;
+	bottom: 0;
+	margin: auto;
+	color: #ccc;
+}
+
+.cu-steps.steps-bottom .cu-item::before,
+.cu-steps.steps-bottom .cu-item::after {
+	bottom: 40upx;
+	top: initial;
+}
+
+.cu-steps .cu-item::after {
+	border-bottom: 1px solid currentColor;
+	width: 0px;
+	transition: all 0.3s ease-in-out 0s;
+}
+
+.cu-steps .cu-item[class*="text-"]::after {
+	width: calc(100% - 80upx);
+	color: currentColor;
+}
+
+.cu-steps .cu-item:first-child::before,
+.cu-steps .cu-item:first-child::after {
+	display: none;
+}
+
+.cu-steps .cu-item .num {
+	width: 40upx;
+	height: 40upx;
+	border-radius: 50%;
+	line-height: 40upx;
+	margin: 20upx auto;
+	font-size: 24upx;
+	border: 1px solid currentColor;
+	position: relative;
+	overflow: hidden;
+}
+
+.cu-steps .cu-item[class*="text-"] .num {
+	background-color: currentColor;
+}
+
+.cu-steps .cu-item .num::before,
+.cu-steps .cu-item .num::after {
+	content: attr(data-index);
+	position: absolute;
+	left: 0;
+	right: 0;
+	top: 0;
+	bottom: 0;
+	margin: auto;
+	transition: all 0.3s ease-in-out 0s;
+	transform: translateY(0upx);
+}
+
+.cu-steps .cu-item[class*="text-"] .num::before {
+	transform: translateY(-40upx);
+	color: #ffffff;
+}
+
+.cu-steps .cu-item .num::after {
+	transform: translateY(40upx);
+	color: #ffffff;
+	transition: all 0.3s ease-in-out 0s;
+}
+
+.cu-steps .cu-item[class*="text-"] .num::after {
+	content: "\e645";
+	font-family: 'cuIcon';
+	color: #ffffff;
+	transform: translateY(0upx);
+}
+
+.cu-steps .cu-item[class*="text-"] .num.err::after {
+	content: "\e646";
+}
+
+/* ==================
+          布局
+ ==================== */
+
+/*  -- flex弹性布局 -- */
+
+.flex {
+	display: flex;
+}
+
+.basis-xs {
+	flex-basis: 20%;
+}
+
+.basis-sm {
+	flex-basis: 40%;
+}
+
+.basis-df {
+	flex-basis: 50%;
+}
+
+.basis-lg {
+	flex-basis: 60%;
+}
+
+.basis-xl {
+	flex-basis: 80%;
+}
+
+.flex-sub {
+	flex: 1;
+}
+
+.flex-twice {
+	flex: 2;
+}
+
+.flex-treble {
+	flex: 3;
+}
+
+.flex-direction {
+	flex-direction: column;
+}
+
+.flex-wrap {
+	flex-wrap: wrap;
+}
+
+.align-start {
+	align-items: flex-start;
+}
+
+.align-end {
+	align-items: flex-end;
+}
+
+.align-center {
+	align-items: center;
+}
+
+.align-stretch {
+	align-items: stretch;
+}
+
+.self-start {
+	align-self: flex-start;
+}
+
+.self-center {
+	align-self: flex-center;
+}
+
+.self-end {
+	align-self: flex-end;
+}
+
+.self-stretch {
+	align-self: stretch;
+}
+
+.align-stretch {
+	align-items: stretch;
+}
+
+.justify-start {
+	justify-content: flex-start;
+}
+
+.justify-end {
+	justify-content: flex-end;
+}
+
+.justify-center {
+	justify-content: center;
+}
+
+.justify-between {
+	justify-content: space-between;
+}
+
+.justify-around {
+	justify-content: space-around;
+}
+
+/* grid布局 */
+
+.grid {
+	display: flex;
+	flex-wrap: wrap;
+}
+
+.grid.grid-square {
+	overflow: hidden;
+}
+
+.grid.grid-square .cu-tag {
+	position: absolute;
+	right: 0;
+	top: 0;
+	border-bottom-left-radius: 6upx;
+	padding: 6upx 12upx;
+	height: auto;
+	background-color: rgba(0, 0, 0, 0.5);
+}
+
+.grid.grid-square>view>text[class*="cuIcon-"] {
+	font-size: 52upx;
+	position: absolute;
+	color: #8799a3;
+	margin: auto;
+	top: 0;
+	bottom: 0;
+	left: 0;
+	right: 0;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	flex-direction: column;
+}
+
+.grid.grid-square>view {
+	margin-right: 20upx;
+	margin-bottom: 20upx;
+	border-radius: 6upx;
+	position: relative;
+	overflow: hidden;
+}
+.grid.grid-square>view.bg-img image {
+	width: 100%;
+	height: 100%;
+	position: absolute;
+}
+.grid.col-1.grid-square>view {
+	padding-bottom: 100%;
+	height: 0;
+	margin-right: 0;
+}
+
+.grid.col-2.grid-square>view {
+	padding-bottom: calc((100% - 20upx)/2);
+	height: 0;
+	width: calc((100% - 20upx)/2);
+}
+
+.grid.col-3.grid-square>view {
+	padding-bottom: calc((100% - 40upx)/3);
+	height: 0;
+	width: calc((100% - 40upx)/3);
+}
+
+.grid.col-4.grid-square>view {
+	padding-bottom: calc((100% - 60upx)/4);
+	height: 0;
+	width: calc((100% - 60upx)/4);
+}
+
+.grid.col-5.grid-square>view {
+	padding-bottom: calc((100% - 80upx)/5);
+	height: 0;
+	width: calc((100% - 80upx)/5);
+}
+
+.grid.col-2.grid-square>view:nth-child(2n),
+.grid.col-3.grid-square>view:nth-child(3n),
+.grid.col-4.grid-square>view:nth-child(4n),
+.grid.col-5.grid-square>view:nth-child(5n) {
+	margin-right: 0;
+}
+
+.grid.col-1>view {
+	width: 100%;
+}
+
+.grid.col-2>view {
+	width: 50%;
+}
+
+.grid.col-3>view {
+	width: 33.33%;
+}
+
+.grid.col-4>view {
+	width: 25%;
+}
+
+.grid.col-5>view {
+	width: 20%;
+}
+
+/*  -- 内外边距 -- */
+
+.margin-0 {
+	margin: 0;
+}
+
+.margin-xs {
+	margin: 10upx;
+}
+
+.margin-sm {
+	margin: 20upx;
+}
+
+.margin {
+	margin: 30upx;
+}
+
+.margin-lg {
+	margin: 40upx;
+}
+
+.margin-xl {
+	margin: 50upx;
+}
+
+.margin-top-xs {
+	margin-top: 10upx;
+}
+
+.margin-top-sm {
+	margin-top: 20upx;
+}
+
+.margin-top {
+	margin-top: 30upx;
+}
+
+.margin-top-lg {
+	margin-top: 40upx;
+}
+
+.margin-top-xl {
+	margin-top: 50upx;
+}
+
+.margin-right-xs {
+	margin-right: 10upx;
+}
+
+.margin-right-sm {
+	margin-right: 20upx;
+}
+
+.margin-right {
+	margin-right: 30upx;
+}
+
+.margin-right-lg {
+	margin-right: 40upx;
+}
+
+.margin-right-xl {
+	margin-right: 50upx;
+}
+
+.margin-bottom-xs {
+	margin-bottom: 10upx;
+}
+
+.margin-bottom-sm {
+	margin-bottom: 20upx;
+}
+
+.margin-bottom {
+	margin-bottom: 30upx;
+}
+
+.margin-bottom-lg {
+	margin-bottom: 40upx;
+}
+
+.margin-bottom-xl {
+	margin-bottom: 50upx;
+}
+
+.margin-left-xs {
+	margin-left: 10upx;
+}
+
+.margin-left-sm {
+	margin-left: 20upx;
+}
+
+.margin-left {
+	margin-left: 30upx;
+}
+
+.margin-left-lg {
+	margin-left: 40upx;
+}
+
+.margin-left-xl {
+	margin-left: 50upx;
+}
+
+.margin-lr-xs {
+	margin-left: 10upx;
+	margin-right: 10upx;
+}
+
+.margin-lr-sm {
+	margin-left: 20upx;
+	margin-right: 20upx;
+}
+
+.margin-lr {
+	margin-left: 30upx;
+	margin-right: 30upx;
+}
+
+.margin-lr-lg {
+	margin-left: 40upx;
+	margin-right: 40upx;
+}
+
+.margin-lr-xl {
+	margin-left: 50upx;
+	margin-right: 50upx;
+}
+
+.margin-tb-xs {
+	margin-top: 10upx;
+	margin-bottom: 10upx;
+}
+
+.margin-tb-sm {
+	margin-top: 20upx;
+	margin-bottom: 20upx;
+}
+
+.margin-tb {
+	margin-top: 30upx;
+	margin-bottom: 30upx;
+}
+
+.margin-tb-lg {
+	margin-top: 40upx;
+	margin-bottom: 40upx;
+}
+
+.margin-tb-xl {
+	margin-top: 50upx;
+	margin-bottom: 50upx;
+}
+
+.padding-0 {
+	padding: 0;
+}
+
+.padding-xs {
+	padding: 10upx;
+}
+
+.padding-sm {
+	padding: 20upx;
+}
+
+.padding {
+	padding: 30upx;
+}
+
+.padding-lg {
+	padding: 40upx;
+}
+
+.padding-xl {
+	padding: 50upx;
+}
+
+.padding-top-xs {
+	padding-top: 10upx;
+}
+
+.padding-top-sm {
+	padding-top: 20upx;
+}
+
+.padding-top {
+	padding-top: 30upx;
+}
+
+.padding-top-lg {
+	padding-top: 40upx;
+}
+
+.padding-top-xl {
+	padding-top: 50upx;
+}
+
+.padding-right-xs {
+	padding-right: 10upx;
+}
+
+.padding-right-sm {
+	padding-right: 20upx;
+}
+
+.padding-right {
+	padding-right: 30upx;
+}
+
+.padding-right-lg {
+	padding-right: 40upx;
+}
+
+.padding-right-xl {
+	padding-right: 50upx;
+}
+
+.padding-bottom-xs {
+	padding-bottom: 10upx;
+}
+
+.padding-bottom-sm {
+	padding-bottom: 20upx;
+}
+
+.padding-bottom {
+	padding-bottom: 30upx;
+}
+
+.padding-bottom-lg {
+	padding-bottom: 40upx;
+}
+
+.padding-bottom-xl {
+	padding-bottom: 50upx;
+}
+
+.padding-left-xs {
+	padding-left: 10upx;
+}
+
+.padding-left-sm {
+	padding-left: 20upx;
+}
+
+.padding-left {
+	padding-left: 30upx;
+}
+
+.padding-left-lg {
+	padding-left: 40upx;
+}
+
+.padding-left-xl {
+	padding-left: 50upx;
+}
+
+.padding-lr-xs {
+	padding-left: 10upx;
+	padding-right: 10upx;
+}
+
+.padding-lr-sm {
+	padding-left: 20upx;
+	padding-right: 20upx;
+}
+
+.padding-lr {
+	padding-left: 30upx;
+	padding-right: 30upx;
+}
+
+.padding-lr-lg {
+	padding-left: 40upx;
+	padding-right: 40upx;
+}
+
+.padding-lr-xl {
+	padding-left: 50upx;
+	padding-right: 50upx;
+}
+
+.padding-tb-xs {
+	padding-top: 10upx;
+	padding-bottom: 10upx;
+}
+
+.padding-tb-sm {
+	padding-top: 20upx;
+	padding-bottom: 20upx;
+}
+
+.padding-tb {
+	padding-top: 30upx;
+	padding-bottom: 30upx;
+}
+
+.padding-tb-lg {
+	padding-top: 40upx;
+	padding-bottom: 40upx;
+}
+
+.padding-tb-xl {
+	padding-top: 50upx;
+	padding-bottom: 50upx;
+}
+
+/* -- 浮动 --  */
+
+.cf::after,
+.cf::before {
+	content: " ";
+	display: table;
+}
+
+.cf::after {
+	clear: both;
+}
+
+.fl {
+	float: left;
+}
+
+.fr {
+	float: right;
+}
+
+/* ==================
+          背景
+ ==================== */
+
+.line-red::after,
+.lines-red::after {
+	border-color: #e54d42;
+}
+
+.line-orange::after,
+.lines-orange::after {
+	border-color: #f37b1d;
+}
+
+.line-yellow::after,
+.lines-yellow::after {
+	border-color: #ffac07;
+}
+
+.line-olive::after,
+.lines-olive::after {
+	border-color: #8dc63f;
+}
+
+.line-green::after,
+.lines-green::after {
+	border-color: #39b54a;
+}
+
+.line-cyan::after,
+.lines-cyan::after {
+	border-color: #1cbbb4;
+}
+
+.line-blue::after,
+.lines-blue::after {
+	border-color: #0081ff;
+}
+
+.line-purple::after,
+.lines-purple::after {
+	border-color: #6739b6;
+}
+
+.line-mauve::after,
+.lines-mauve::after {
+	border-color: #9c26b0;
+}
+
+.line-pink::after,
+.lines-pink::after {
+	border-color: #e03997;
+}
+
+.line-brown::after,
+.lines-brown::after {
+	border-color: #a5673f;
+}
+
+.line-grey::after,
+.lines-grey::after {
+	border-color: #8799a3;
+}
+
+.line-gray::after,
+.lines-gray::after {
+	border-color: #aaaaaa;
+}
+
+.line-black::after,
+.lines-black::after {
+	border-color: #333333;
+}
+
+.line-white::after,
+.lines-white::after {
+	border-color: #ffffff;
+}
+
+.bg-red {
+	background-color: #e54d42;
+	color: #ffffff;
+}
+
+.bg-orange {
+	background-color: #f37b1d;
+	color: #ffffff;
+}
+
+.bg-yellow {
+	background-color: #fbbd08;
+	color: #333333;
+}
+
+.bg-olive {
+	background-color: #8dc63f;
+	color: #ffffff;
+}
+
+.bg-green {
+	background-color: #39b54a;
+	color: #ffffff;
+}
+
+.bg-cyan {
+	background-color: #1cbbb4;
+	color: #ffffff;
+}
+
+.bg-blue {
+	background-color: #0081ff;
+	color: #ffffff;
+}
+
+.bg-purple {
+	background-color: #6739b6;
+	color: #ffffff;
+}
+
+.bg-mauve {
+	background-color: #9c26b0;
+	color: #ffffff;
+}
+
+.bg-pink {
+	background-color: #e03997;
+	color: #ffffff;
+}
+
+.bg-brown {
+	background-color: #a5673f;
+	color: #ffffff;
+}
+
+.bg-grey {
+	background-color: #8799a3;
+	color: #ffffff;
+}
+
+.bg-gray {
+	background-color: #f0f0f0;
+	color: #333333;
+}
+
+.bg-black {
+	background-color: #333333;
+	color: #ffffff;
+}
+
+.bg-white {
+	background-color: #ffffff;
+	color: #666666;
+}
+
+.bg-shadeTop {
+	background-image: linear-gradient(rgba(0, 0, 0, 1), rgba(0, 0, 0, 0.01));
+	color: #ffffff;
+}
+
+.bg-shadeBottom {
+	background-image: linear-gradient(rgba(0, 0, 0, 0.01), rgba(0, 0, 0, 1));
+	color: #ffffff;
+}
+
+.bg-red.light {
+	color: #e54d42;
+	background-color: #fadbd9;
+}
+
+.bg-orange.light {
+	color: #f37b1d;
+	background-color: #fde6d2;
+}
+
+.bg-yellow.light {
+	color: #fbbd08;
+	background-color: #fef2ced2;
+}
+
+.bg-olive.light {
+	color: #8dc63f;
+	background-color: #e8f4d9;
+}
+
+.bg-green.light {
+	color: #39b54a;
+	background-color: #d7f0dbff;
+}
+
+.bg-cyan.light {
+	color: #1cbbb4;
+	background-color: #d2f1f0;
+}
+
+.bg-blue.light {
+	color: #0081ff;
+	background-color: #cce6ff;
+}
+
+.bg-purple.light {
+	color: #6739b6;
+	background-color: #e1d7f0;
+}
+
+.bg-mauve.light {
+	color: #9c26b0;
+	background-color: #ebd4ef;
+}
+
+.bg-pink.light {
+	color: #e03997;
+	background-color: #f9d7ea;
+}
+
+.bg-brown.light {
+	color: #a5673f;
+	background-color: #ede1d9;
+}
+
+.bg-grey.light {
+	color: #8799a3;
+	background-color: #e7ebed;
+}
+
+.bg-gradual-red {
+	background-image: linear-gradient(45deg, #f43f3b, #ec008c);
+	color: #ffffff;
+}
+
+.bg-gradual-orange {
+	background-image: linear-gradient(45deg, #ff9700, #ed1c24);
+	color: #ffffff;
+}
+
+.bg-gradual-green {
+	background-image: linear-gradient(45deg, #39b54a, #8dc63f);
+	color: #ffffff;
+}
+
+.bg-gradual-purple {
+	background-image: linear-gradient(45deg, #9000ff, #5e00ff);
+	color: #ffffff;
+}
+
+.bg-gradual-pink {
+	background-image: linear-gradient(45deg, #ec008c, #6739b6);
+	color: #ffffff;
+}
+
+.bg-gradual-blue {
+	background-image: linear-gradient(45deg, #0081ff, #1cbbb4);
+	color: #ffffff;
+}
+
+.shadow[class*="-red"] {
+	box-shadow: 6upx 6upx 8upx rgba(204, 69, 59, 0.2);
+}
+
+.shadow[class*="-orange"] {
+	box-shadow: 6upx 6upx 8upx rgba(217, 109, 26, 0.2);
+}
+
+.shadow[class*="-yellow"] {
+	box-shadow: 6upx 6upx 8upx rgba(224, 170, 7, 0.2);
+}
+
+.shadow[class*="-olive"] {
+	box-shadow: 6upx 6upx 8upx rgba(124, 173, 55, 0.2);
+}
+
+.shadow[class*="-green"] {
+	box-shadow: 6upx 6upx 8upx rgba(48, 156, 63, 0.2);
+}
+
+.shadow[class*="-cyan"] {
+	box-shadow: 6upx 6upx 8upx rgba(28, 187, 180, 0.2);
+}
+
+.shadow[class*="-blue"] {
+	box-shadow: 6upx 6upx 8upx rgba(0, 102, 204, 0.2);
+}
+
+.shadow[class*="-purple"] {
+	box-shadow: 6upx 6upx 8upx rgba(88, 48, 156, 0.2);
+}
+
+.shadow[class*="-mauve"] {
+	box-shadow: 6upx 6upx 8upx rgba(133, 33, 150, 0.2);
+}
+
+.shadow[class*="-pink"] {
+	box-shadow: 6upx 6upx 8upx rgba(199, 50, 134, 0.2);
+}
+
+.shadow[class*="-brown"] {
+	box-shadow: 6upx 6upx 8upx rgba(140, 88, 53, 0.2);
+}
+
+.shadow[class*="-grey"] {
+	box-shadow: 6upx 6upx 8upx rgba(114, 130, 138, 0.2);
+}
+
+.shadow[class*="-gray"] {
+	box-shadow: 6upx 6upx 8upx rgba(114, 130, 138, 0.2);
+}
+
+.shadow[class*="-black"] {
+	box-shadow: 6upx 6upx 8upx rgba(26, 26, 26, 0.2);
+}
+
+.shadow[class*="-white"] {
+	box-shadow: 6upx 6upx 8upx rgba(26, 26, 26, 0.2);
+}
+
+.text-shadow[class*="-red"] {
+	text-shadow: 6upx 6upx 8upx rgba(204, 69, 59, 0.2);
+}
+
+.text-shadow[class*="-orange"] {
+	text-shadow: 6upx 6upx 8upx rgba(217, 109, 26, 0.2);
+}
+
+.text-shadow[class*="-yellow"] {
+	text-shadow: 6upx 6upx 8upx rgba(224, 170, 7, 0.2);
+}
+
+.text-shadow[class*="-olive"] {
+	text-shadow: 6upx 6upx 8upx rgba(124, 173, 55, 0.2);
+}
+
+.text-shadow[class*="-green"] {
+	text-shadow: 6upx 6upx 8upx rgba(48, 156, 63, 0.2);
+}
+
+.text-shadow[class*="-cyan"] {
+	text-shadow: 6upx 6upx 8upx rgba(28, 187, 180, 0.2);
+}
+
+.text-shadow[class*="-blue"] {
+	text-shadow: 6upx 6upx 8upx rgba(0, 102, 204, 0.2);
+}
+
+.text-shadow[class*="-purple"] {
+	text-shadow: 6upx 6upx 8upx rgba(88, 48, 156, 0.2);
+}
+
+.text-shadow[class*="-mauve"] {
+	text-shadow: 6upx 6upx 8upx rgba(133, 33, 150, 0.2);
+}
+
+.text-shadow[class*="-pink"] {
+	text-shadow: 6upx 6upx 8upx rgba(199, 50, 134, 0.2);
+}
+
+.text-shadow[class*="-brown"] {
+	text-shadow: 6upx 6upx 8upx rgba(140, 88, 53, 0.2);
+}
+
+.text-shadow[class*="-grey"] {
+	text-shadow: 6upx 6upx 8upx rgba(114, 130, 138, 0.2);
+}
+
+.text-shadow[class*="-gray"] {
+	text-shadow: 6upx 6upx 8upx rgba(114, 130, 138, 0.2);
+}
+
+.text-shadow[class*="-black"] {
+	text-shadow: 6upx 6upx 8upx rgba(26, 26, 26, 0.2);
+}
+
+.bg-img {
+	background-size: cover;
+	background-position: center;
+	background-repeat: no-repeat;
+}
+
+.bg-mask {
+	background-color: #333333;
+	position: relative;
+}
+
+.bg-mask::after {
+	content: "";
+	border-radius: inherit;
+	width: 100%;
+	height: 100%;
+	display: block;
+	background-color: rgba(0, 0, 0, 0.4);
+	position: absolute;
+	left: 0;
+	right: 0;
+	bottom: 0;
+	top: 0;
+}
+
+.bg-mask view,
+.bg-mask cover-view {
+	z-index: 5;
+	position: relative;
+}
+
+.bg-video {
+	position: relative;
+}
+
+.bg-video video {
+	display: block;
+	height: 100%;
+	width: 100%;
+	-o-object-fit: cover;
+	object-fit: cover;
+	position: absolute;
+	top: 0;
+	z-index: 0;
+	pointer-events: none;
+}
+
+/* ==================
+          文本
+ ==================== */
+
+.text-xs {
+	font-size: 20upx;
+}
+
+.text-sm {
+	font-size: 24upx;
+}
+
+.text-df {
+	font-size: 28upx;
+}
+
+.text-lg {
+	font-size: 32upx;
+}
+
+.text-xl {
+	font-size: 36upx;
+}
+
+.text-xxl {
+	font-size: 44upx;
+}
+
+.text-sl {
+	font-size: 80upx;
+}
+
+.text-xsl {
+	font-size: 120upx;
+}
+
+.text-Abc {
+	text-transform: Capitalize;
+}
+
+.text-ABC {
+	text-transform: Uppercase;
+}
+
+.text-abc {
+	text-transform: Lowercase;
+}
+
+.text-price::before {
+	content: "¥";
+	font-size: 80%;
+	margin-right: 4upx;
+}
+
+.text-cut {
+	text-overflow: ellipsis;
+	white-space: nowrap;
+	overflow: hidden;
+}
+
+.text-bold {
+	font-weight: bold;
+}
+
+.text-center {
+	text-align: center;
+}
+
+.text-content {
+	line-height: 1.6;
+}
+
+.text-left {
+	text-align: left;
+}
+
+.text-right {
+	text-align: right;
+}
+
+.text-red,
+.line-red,
+.lines-red {
+	color: #e54d42;
+}
+
+.text-orange,
+.line-orange,
+.lines-orange {
+	color: #f37b1d;
+}
+
+.text-yellow,
+.line-yellow,
+.lines-yellow {
+	color: #fbbd08;
+}
+
+.text-olive,
+.line-olive,
+.lines-olive {
+	color: #8dc63f;
+}
+
+.text-green,
+.line-green,
+.lines-green {
+	color: #39b54a;
+}
+
+.text-cyan,
+.line-cyan,
+.lines-cyan {
+	color: #1cbbb4;
+}
+
+.text-gj,
+.line-gj,
+.lines-gj {
+	color: #06c7a6;
+}
+
+.bg-vip{
+	background-color: #ffad08;
+	color: #FFFFFF;
+}
+
+.bg-gj{
+	background-color: #06c7a6;
+	color: #FFFFFF;
+}
+
+.text-blue,
+.line-blue,
+.lines-blue {
+	color: #0081ff;
+}
+
+.text-purple,
+.line-purple,
+.lines-purple {
+	color: #6739b6;
+}
+
+.text-mauve,
+.line-mauve,
+.lines-mauve {
+	color: #9c26b0;
+}
+
+.text-pink,
+.line-pink,
+.lines-pink {
+	color: #e03997;
+}
+
+.text-brown,
+.line-brown,
+.lines-brown {
+	color: #a5673f;
+}
+
+.text-grey,
+.line-grey,
+.lines-grey {
+	color: #8799a3;
+}
+
+.text-gray,
+.line-gray,
+.lines-gray {
+	color: #aaaaaa;
+}
+
+.text-black,
+.line-black,
+.lines-black {
+	color: #333333;
+}
+
+.text-white,
+.line-white,
+.lines-white {
+	color: #ffffff;
+}

+ 116 - 0
common/http/http.api.js

@@ -0,0 +1,116 @@
+//活动管理
+let activityUrl = {
+	listUrl : '/vote-activity/activity/list',
+	detailUrl : 'vote-activity/activity/detail',
+	addPageViewUrl : '/vote-activity/activity/addpageview',
+}
+//作品管理
+let artworkUrl = {
+	detailUrl : '/vote-works/works/detail',
+	listUrl : '/vote-works/works/list',
+	saveUrl : '/vote-works/works/save',
+	searchUrl : '/vote-works/works/search',
+	getCountUrl : '/vote-works/works/getCount'
+}
+
+//投票者管理
+let voterUrl = {
+	detailUrl : '/vote-voter/voter/detail',
+	saveUrl :'/vote-voter/voter/save'
+}
+
+//投票管理
+let voteUrl = {
+	saveUrl : '/vote-records/records/save'
+}
+
+//礼物管理
+let giftUrl = {
+	listUrl : '/vote-present/present/list'
+}
+
+//小程序被封管理
+let appUrl = {
+	detailUrl : '/vote-second/second/detail',
+}
+
+//投诉管理
+let complainUrl = {
+	saveUrl : '/vote-complain/complain/save',
+}
+
+//获取小程序码
+let getWxCodeUrl = {
+	getAccessTokenUrl : '/wx/getAccessToken',
+	getQrCodeUrl : '/getUnlimitCode'
+}
+
+//微信登录
+let wxInfoUrl = {
+	getOpenIdUrl :'/blade-link/auth/getOpenid',
+}
+//微信支付
+let wxPayUrl = {
+	createOrder :'/pay/createOrder',
+	addOrder: "/vote-order/order/save"
+}
+
+
+// 此处第二个参数vm,就是我们在页面使用的this,你可以通过vm获取vuex等操作,更多内容详见uView对拦截器的介绍部分:
+// https://uviewui.com/js/http.html#%E4%BD%95%E8%B0%93%E8%AF%B7%E6%B1%82%E6%8B%A6%E6%88%AA%EF%BC%9F
+const install = (Vue, vm) => {
+	
+	let activity = {
+		list:(params = {}) => vm.$u.get(activityUrl.listUrl, params),
+		detail:(params = {}) => vm.$u.get(activityUrl.detailUrl, params),
+		add:(params = {}) => vm.$u.post(activityUrl.addPageViewUrl, params),
+	}
+	
+	let artwork = {
+		detail:(params = {}) => vm.$u.get(artworkUrl.detailUrl, params),
+		list:(params = {}) => vm.$u.get(artworkUrl.listUrl, params),
+		save:(params = {}) => vm.$u.post(artworkUrl.saveUrl, params),
+		search:(params = {}) => vm.$u.get(artworkUrl.searchUrl, params),
+		getCount:(params = {}) => vm.$u.get(artworkUrl.getCountUrl, params),
+	}
+	
+	let voter = {
+		detail:(params = {}) => vm.$u.get(voterUrl.detailUrl, params),
+		save:(params = {}) => vm.$u.post(voterUrl.saveUrl, params),
+	}
+	
+	let vote = {
+		save:(params = {}) => vm.$u.post(voteUrl.saveUrl, params),
+	}
+	
+	let gift = {
+		list:(params = {}) => vm.$u.get(giftUrl.listUrl, params),
+	}
+	
+	let app = {
+		detail:(params = {}) => vm.$u.get(appUrl.detailUrl, params),
+	}
+	
+	let complain = {
+		save:(params = {}) => vm.$u.post(complainUrl.saveUrl, params),
+	}
+	
+	let getWxCode = {
+		getAccessToken:(params = {}) => vm.$u.get(getWxCodeUrl.getAccessTokenUrl, params),
+		getQrCode:(params = {}) => vm.$u.post(getWxCodeUrl.getQrCodeUrl, params),
+	}
+	
+	let wxInfo = {
+		getOpenId:(params = {}) => vm.$u.get(wxInfoUrl.getOpenIdUrl, params),
+	}
+	let wxPay = {
+		createOrder:(params = {}) => vm.$u.post(wxPayUrl.createOrder, params),
+		addOrder:(params = {}) => vm.$u.post(wxPayUrl.addOrder, params),
+	}
+	// 将各个定义的接口名称,统一放进对象挂载到vm.$u.api(因为vm就是this,也即this.$u.api)下
+	vm.$u.api = {activity,artwork,voter,vote,gift,app,complain,getWxCode,wxInfo,wxPay};
+}
+
+export default {
+	install
+}

+ 116 - 0
common/http/http.interceptor.js

@@ -0,0 +1,116 @@
+ let baseUrl = 'https://vote.yitige.com/api/'
+   // let baseUrl = 'http://192.168.0.123:9090/'
+let tokenUrl = "https://vote.yitige.com/api/blade-auth/oauth/token?tenantId=000000&password=21232f297a57a5a743894a0e4a801fc3&username=admin"
+
+let myConfig={}
+
+const refreshToken = ()=>{
+	return new Promise((resolve,reject)=>{
+		uni.request({
+			url:tokenUrl,
+			method: "POST",
+			header:{
+				Authorization:"Basic c2FiZXI6c2FiZXJfc2VjcmV0"
+			},
+			success: (res)=>{
+				let token=res.data.token_type+" "+res.data.access_token
+				let tokenExprieIn=res.data.expires_in
+				let tokenExpireTime = Date.now() + tokenExprieIn * 1000
+				let data=JSON.stringify({"token":token,"tokenExpireTime":tokenExpireTime})
+				uni.setStorage({key: 'token',data: data})
+				resolve(token)
+			},
+			fail: (err)=>{
+				reject(err)
+			}
+		})
+  })
+}
+
+function getToken () {
+  let tokenObj = {}
+  try {
+    tokenObj = uni.getStorageSync("token")
+    tokenObj = tokenObj ? JSON.parse(tokenObj) : {}
+  } catch(e) {
+    console.error('get token from storage error')
+  }
+  return tokenObj
+}
+
+const install = async (Vue, vm) => {
+	// 此为自定义配置参数,具体参数见上方说明
+	Vue.prototype.$u.http.setConfig({
+		baseUrl: baseUrl,
+		loadingText: '努力加载中~',
+		loadingTime: 800,
+		header: {
+			'content-type': 'application/json;charset=UTF-8'
+		},
+	});
+	// 请求拦截,配置Token等参数
+	Vue.prototype.$u.http.interceptor.request = (async (config) => 	{
+		const tokenObj = getToken()
+		config.header['Blade-Auth'] = tokenObj.token
+		if (tokenObj.token && tokenObj.tokenExpireTime) {
+		  const now = new Date() + 0;
+		  if (now >= tokenObj.tokenExpireTime) {
+			  config.header['Blade-Auth']= await refreshToken()
+		  }
+		} else {
+			config.header['Blade-Auth'] = await refreshToken()
+		}
+		return config;
+	})
+Vue.prototype.$u.http.interceptor.response = (async (res) => {
+	return new Promise((resolve,reject)=>{
+		if(res.code == 200) {
+			return resolve(res.data);
+		} else if(res.code == 401) {
+			uni.showToast({
+				title: '授权已过期,请重新进入小程序',
+				icon: 'none',
+			})
+			return reject(res);
+		} else if(res.code == 500){
+			uni.showToast({
+				title:'服务器异常',
+				icon:'none'
+			})
+			return reject(res);
+		} else {
+			// 如果返回false,则会调用Promise的reject回调,
+			// 并将进入this.$u.post(url).then().catch(res=>{})的catch回调中,res为服务端的返回值
+			return reject(res);
+		}
+	});
+})
+		
+// Vue.prototype.$u.http.interceptor.response = async (res) => {
+// 	if(res.code == 200) {
+// 		return res.data;
+// 	}else if(res.code==401){
+// 		uni.showToast({
+// 			title:'授权已过期,请重新进入小程序',
+// 			icon:'none',
+// 		})
+// 		return false
+// 	}
+// 	else if(res.code==500){
+// 		uni.showToast({
+// 			title:'服务器异常',
+// 			icon:'none'
+// 		})
+// 	}
+// 	else {
+// 		console.log(res)
+// 		// 如果返回false,则会调用Promise的reject回调,
+// 		// 并将进入this.$u.post(url).then().catch(res=>{})的catch回调中,res为服务端的返回值
+// 		return false;
+// 	}
+// }
+
+}
+export default {
+	install
+}

+ 64 - 0
components/basic/bottom-bar.vue

@@ -0,0 +1,64 @@
+<template>
+	<view>
+		<view class="cu-bar tabbar bg-white">
+			<view class="action" @click="change(0)">
+				<view class="cuIcon-cu-image">
+					<block v-if="current == 0">
+						<view class="cuIcon-discoverfill theme-color"></view>
+					</block>
+					<block v-else>
+						<view class="cuIcon-discoverfill "></view>
+					</block>
+				</view>
+				<view :class="current == 0 ? 'selectColor':''">活动</view>
+			</view>
+			<view class="action" @click="change(1)">
+				<view class="cuIcon-cu-image">
+					<block v-if="current == 1">
+						<view class="cuIcon-goodsfill theme-color"></view>
+					</block>
+					<block v-else>
+						<view class="cuIcon-goodsfill"></view>
+					</block>
+				</view>
+				<view :class="current == 1 ? 'selectColor':''">花积分</view>
+			</view>
+			<view class="action" @click="change(2)">
+				<view class="cuIcon-cu-image">
+					<block v-if="current == 2">
+						<view class="cuIcon-friendfill theme-color"></view>
+					</block>
+					<block v-else>
+						<view class="cuIcon-friendfill"></view>
+					</block>
+				</view>
+				<view :class="current == 2 ? 'selectColor':''">我的</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				current: 0,
+			};
+		},
+		props: {
+			
+		},
+		methods: {
+			change(index) {
+				this.current = index;
+				this.$emit("onTap",index);
+			},
+		}
+	}
+</script>
+
+<style>
+.selectColor {
+	color: #583ce6;
+}
+</style>

+ 47 - 0
components/basic/search-bar.vue

@@ -0,0 +1,47 @@
+<template>
+	<view>
+		<!--disabled为false时 可以在搜索框输入内容 使用 @onSearch :disabled="false"-->
+		<!--disabled为true时 默认为true 则是跳转到新页面进行搜索 使用 @onNavigator -->
+		<view class="cu-bar bg-white search" @click="navNewPage">
+			<view class="search-form radius">
+				<text class="cuIcon-search"></text>
+				<input v-model="textValue" :adjust-position="false" :disabled="disabled" :placeholder="placeholder"></input>
+			</view>
+			<view class="action" @click="searchItem(textValue)">
+				<text>搜索</text>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		props: {
+			disabled: {
+				type: Boolean,
+				default: true,
+			},
+			placeholder: {
+				type: String,
+				default: '请输入参赛选手名字'
+			}
+		},
+		data() {
+			return {
+				textValue:'',
+			}
+		},
+		methods:{
+			navNewPage() {
+				this.$emit('onNavigator');
+			},
+			searchItem(value) {
+				this.$emit('onSearch',value);
+			},
+		}
+	}
+</script>
+
+<style>
+
+</style>

+ 149 - 0
components/views/activity-view.vue

@@ -0,0 +1,149 @@
+<template>
+	<view>
+		<view class="searchBar">
+			<search-bar :disabled="true"></search-bar>
+		</view>
+		<view class="padding-tb bg-white">
+			<u-swiper height="350" mode="none" :list="imgList" :effect3d="true" bg-color="#fff" interval="5000"></u-swiper>
+		</view>
+		<view class="flex justify-around text-center padding-tb bg-white">
+			<block v-for="(item,index) in icons" :key="index">
+				<view @click="navByIcon(item.url)">
+					<image :src="item.image" style="width: 80upx;height: 80upx;"></image>
+					<view class="margin-top-xs text-sm text-bold">{{item.name}}</view>
+				</view>
+			</block>
+		</view>
+		<view class="margin-top-sm bg-white flex justify-around align-end" style="height: 350upx;">
+			<view class="second text-center">
+				<view class="margin-top-sm">
+					<u-avatar src="/static/avatar.png" size="120"></u-avatar>
+				</view>
+				<view class="text-bold text-lg text-black">1230545</view>
+				<view class="flex justify-center" @click="navWithParm">
+					<view class="hot-btn margin-top-xs">
+						<text class="cuIcon-hotfill padding-right-xs"></text>
+						<text>打榜</text>
+					</view>
+				</view>
+			</view>
+			<view class="first text-center">
+				<view class="margin-top-sm">
+					<u-avatar src="/static/avatar.png" size="130"></u-avatar>
+				</view>
+				<view class="margin-top-xs text-bold text-lg text-black">1230545</view>
+				<view class="flex justify-center" @click="navWithParm">
+					<view class="hot-btn margin-top-xs">
+						<text class="cuIcon-hotfill padding-right-xs"></text>
+						<text>打榜</text>
+					</view>
+				</view>
+			</view>
+			<view class="third text-center">
+				<view class="margin-top-sm">
+					<u-avatar src="/static/avatar.png" size="120"></u-avatar>
+				</view>
+				<view class="text-bold text-lg text-black">1230545</view>
+				<view class="flex justify-center" @click="navWithParm">
+					<view class="hot-btn margin-top-xs">
+						<text class="cuIcon-hotfill padding-right-xs"></text>
+						<text>打榜</text>
+					</view>
+				</view>
+			</view>
+		</view>
+		<block v-for="(item, index) in 6" :key="index">
+			<view class="padding-sm flex justify-between align-center bg-white">
+				<view class="flex justify-around align-center">
+					<view class="padding-right text-black text-bold">{{index + 4}}</view>
+					<view class="padding-right">
+						<u-avatar src="/static/avatar.png" size="130"></u-avatar>
+					</view>
+					<view>
+						<view class="text-bold text-black">薛之谦</view>
+						<view class="margin-tb-xs">300 热力值</view>
+					</view>
+				</view>
+				<view class="padding-right">
+					<button class="cu-btn round  text-white" style="background-color: #583ce6;height: 68upx;">
+						<text class="cuIcon-hotfill padding-right-xs"></text>
+						<text>打榜</text>
+					</button>
+				</view>
+			</view>
+		</block>
+		<view class="text-center bg-white" style="line-height: 80upx;" @click="navByIcon('/pages/activity/hot')">
+			<text class="text-bold text-black">全部歌手</text>
+			<text class="cuIcon-right"></text>
+		</view>
+	</view>
+</template>
+
+<script>
+	import searchBar from "@/components/basic/search-bar.vue";
+	export default {
+		components: {
+			searchBar,
+		},
+		props: {
+			imgList: {
+				type: Array,
+				default() {
+					return []
+				}
+			},
+		},
+		data() {
+			return {
+				icons: [
+					{image: '/static/activity.png', name: '活动介绍', url: '/pages/activity/activityDetail'},
+					{image: '/static/signUp.png', name: '点击报名', url: '/pages/activity/signUp'},
+					{image: '/static/hot.png', name: '热度榜', url: '/pages/activity/hot'},
+					{image: '/static/more.png', name: '更多', url: '/pages/activity/songRank'},
+				],
+			}
+		},
+		methods: {
+			navByIcon(url) {
+				uni.navigateTo({
+					url: url,
+				})
+			},
+			//跳转需要带惨方法
+			navWithParm() {
+				uni.navigateTo({
+					url: "/pages/activity/boost"
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.first {
+		height: 300upx;
+		width: 30%;
+		border-radius: 30upx;
+		box-shadow: -1upx -1upx 60upx #d8d8d8;
+	}
+	.second {
+		height: 260upx;
+		width: 27%;
+		border-radius: 30upx;
+		box-shadow: -1upx -1upx 60upx #d8d8d8;
+	}
+	.third {
+		height: 260upx;
+		width: 27%;
+		border-radius: 30upx;
+		box-shadow: -1upx -1upx 60upx #d8d8d8;
+	}
+	.hot-btn {
+		color: #FFFFFF;
+		line-height: 56upx;
+		width: 70%;
+		border-radius: 30upx;
+		background-color: #583ce6;
+		font-weight: bold;
+	}
+</style>

+ 113 - 0
components/views/mine-view.vue

@@ -0,0 +1,113 @@
+<template>
+	<view>
+		<view class="container">
+			<view class="flex justify-between align-center" style="height: 200upx;">
+				<view class="padding-left">
+					<view class="text-black text-bold text-xl">{{name}}</view>
+					<view class="flex align-center padding-top-sm">
+						<view>
+							<view class="text-black text-bold">205</view>
+							<view class="text-gray text-sm margin-top-xs">热力</view>
+						</view>
+						<view style="height: 60upx;border: #dadada 1px solid; margin: 0 30upx;"></view>
+						<view>
+							<view class="text-black text-bold">886</view>
+							<view class="text-gray text-sm margin-top-xs">积分</view>
+						</view>
+						<view class="padding-left">
+							<button class="cu-btn sm line-black round" @click="edit">
+								<text class="cuIcon-post padding-right-xs"></text>
+								<text>修改资料</text>
+							</button>
+						</view>
+					</view>
+				</view>
+				<view class="flex align-center">
+					<view class="padding-right">
+						<u-avatar src="/static/avatar.png" size="120"></u-avatar>
+					</view>
+				</view>
+			</view>
+			<view class="padding-lg flex justify-around align-center">
+				<view class="flex" @click="navByIcon('/pages/mine/pointsDetail')">
+					<image src="/static/icon-points.png" style="width: 80upx;height: 80upx;"></image>
+					<view class="padding-left-sm">
+						<view class="text-bold text-lg">积分明细</view>
+						<view class="text-gray">消费赚积分</view>
+					</view>
+				</view>
+				<view class="flex" @click="navByIcon('/pages/mine/boostDetail')">
+					<image src="/static/icon-order.png" style="width: 80upx;height: 80upx;"></image>
+					<view class="padding-left-sm">
+						<view class="text-bold text-lg">热力明细</view>
+						<view class="text-gray">助力奖赏</view>
+					</view>
+				</view>
+			</view>
+		</view>
+		<view class="container">
+			<block v-for="(item, index) in iconList" :key="index">
+				<view class="padding" v-if="item.name == '分割线'">
+					<u-line color="#d3d3d3"></u-line>
+				</view>
+				<view class="flex justify-between align-center padding" @click="navByIcon(item.url)" v-else>
+					<view class="flex align-center">
+						<view class="flex align-center" style="width: 38rpx;height: 38rpx;">
+							<image :src="item.icon" :style="{width: item.width, height: item.height}"></image>
+						</view>
+						<view class="text-black text-bold text-lg padding-left">{{item.name}}</view>
+					</view>
+					<view class="cuIcon-right"></view>
+				</view>
+			</block>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		props: {
+
+		},
+		data() {
+			return {
+				name: 'Daniel Hua',
+				hotVaule: '205',
+				points: '886',
+				iconList: [
+					{name: '我的礼品', icon: '/static/icon-gift.png', width: '36upx', height: '33upx', url: '/pages/mine/myGift'},
+					{name: '我的音乐', icon: '/static/icon-music.png', width: '33upx', height: '32upx', url: '/pages/mine/myMusic'},
+					{name: '我的奖金', icon: '/static/icon-awards.png', width: '29upx', height: '38upx', url: '/pages/mine/myAwards'},
+					{name: '我的助力', icon: '/static/icon-history.png', width: '32upx', height: '32upx', url: '/pages/mine/myBoost'},
+					{name: '我的公益', icon: '/static/icon-welfare.png', width: '31upx', height: '31upx', url: '/pages/mine/myWelfare'},
+					{name: '分割线', icon: '', width: '', height: '', url: ''},
+					{name: '花积分', icon: '/static/icon-mall.png', width: '30upx', height: '26upx', url: ''},
+					{name: '更多活动', icon: '/static/icon-activity.png', width: '26upx', height: '31upx', url: ''},
+					{name: '活动规则', icon: '/static/icon-rule.png', width: '29upx', height: '33upx', url: ''}
+				],
+			}
+		},
+		methods: {
+			//跳转需要带参数
+			edit() {
+				uni.navigateTo({
+					url: '/pages/mine/edit'
+				})
+			},
+			navByIcon(url) {
+				uni.navigateTo({
+					url: url
+				})
+			}
+		}
+	}
+</script>
+
+<style>
+	.container {
+		margin: 30upx;
+		background-color: #ffffff;
+		border-radius: 28upx;
+		box-shadow: -1upx -1upx 60upx #d8d8d8;
+	}
+</style>

+ 8 - 0
components/views/points-view.vue

@@ -0,0 +1,8 @@
+<template>
+</template>
+
+<script>
+</script>
+
+<style>
+</style>

+ 14 - 0
main.js

@@ -0,0 +1,14 @@
+import Vue from 'vue'
+import App from './App'
+
+import uView from "uview-ui";
+Vue.use(uView);
+
+Vue.config.productionTip = false
+
+App.mpType = 'app'
+
+const app = new Vue({
+    ...App
+})
+app.$mount()

+ 71 - 0
manifest.json

@@ -0,0 +1,71 @@
+{
+    "name" : "SoundOfMusic-H5",
+    "appid" : "",
+    "description" : "",
+    "versionName" : "1.0.0",
+    "versionCode" : "100",
+    "transformPx" : false,
+    /* 5+App特有相关 */
+    "app-plus" : {
+        "usingComponents" : true,
+        "nvueCompiler" : "uni-app",
+        "compilerVersion" : 3,
+        "splashscreen" : {
+            "alwaysShowBeforeRender" : true,
+            "waiting" : true,
+            "autoclose" : true,
+            "delay" : 0
+        },
+        /* 模块配置 */
+        "modules" : {},
+        /* 应用发布信息 */
+        "distribute" : {
+            /* android打包配置 */
+            "android" : {
+                "permissions" : [
+                    "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
+                    "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
+                    "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CAMERA\"/>",
+                    "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
+                    "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
+                    "<uses-feature android:name=\"android.hardware.camera\"/>",
+                    "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
+                ]
+            },
+            /* ios打包配置 */
+            "ios" : {},
+            /* SDK配置 */
+            "sdkConfigs" : {}
+        }
+    },
+    /* 快应用特有相关 */
+    "quickapp" : {},
+    /* 小程序特有相关 */
+    "mp-weixin" : {
+        "appid" : "",
+        "setting" : {
+            "urlCheck" : false
+        },
+        "usingComponents" : true
+    },
+    "mp-alipay" : {
+        "usingComponents" : true
+    },
+    "mp-baidu" : {
+        "usingComponents" : true
+    },
+    "mp-toutiao" : {
+        "usingComponents" : true
+    },
+    "uniStatistics": {  
+        "enable": false
+    }
+}

+ 153 - 0
pages.json

@@ -0,0 +1,153 @@
+{	
+	"easycom": {
+		"^u-(.*)": "@/uview-ui/components/u-$1/u-$1.vue"
+	},
+	"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
+		{
+			"path": "pages/index/index",
+			"style": {
+				"navigationBarTitleText": "活动列表"
+			}
+		}
+	    ,{
+            "path" : "pages/home/home",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "活动详情"
+            }
+            
+        }
+        ,{
+            "path" : "pages/activity/activityDetail",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "活动简介"
+            }
+            
+        }
+        ,{
+            "path" : "pages/activity/signUp",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "报名登记"
+            }
+            
+        }
+        ,{
+            "path" : "pages/mine/myMusic",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "我的音乐"
+            }
+            
+        }
+        ,{
+            "path" : "pages/mine/edit",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "修改资料"
+            }
+            
+        }
+        ,{
+            "path" : "pages/activity/boost",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "打榜助力"
+            }
+            
+        }
+        ,{
+            "path" : "pages/mine/myBoost",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "我的助力"
+            }
+            
+        }
+        ,{
+            "path" : "pages/activity/songRank",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": ""
+            }
+            
+        }
+        ,{
+            "path" : "pages/mine/boostDetail",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "热力明细"
+            }
+            
+        }
+        ,{
+            "path" : "pages/mine/pointsDetail",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "积分明细"
+            }
+            
+        }
+        ,{
+            "path" : "pages/mine/myWelfare",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "我的公益"
+            }
+            
+        }
+        ,{
+            "path" : "pages/mine/myAwards",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": ""
+            }
+            
+        }
+        ,{
+            "path" : "pages/mine/myGift",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "我的礼品"
+            }
+            
+        }
+        ,{
+            "path" : "pages/mine/introduction",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": ""
+            }
+            
+        }
+        ,{
+            "path" : "pages/activity/hot",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "热度榜"
+            }
+            
+        }
+        ,{
+            "path" : "pages/mine/order/orderConfirm",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "确认订单"
+            }
+            
+        }
+        ,{
+            "path" : "pages/mine/order/address",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "添加收货地址"
+            }
+            
+        }
+    ],
+	"globalStyle": {
+		"navigationStyle": "custom",
+		"backgroundColor": "#F8F8F8"
+	}
+}

+ 22 - 0
pages/activity/activityDetail.vue

@@ -0,0 +1,22 @@
+<template>
+	<view>
+		<u-image :src="src" mode="widthFix"></u-image>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				src: '/static/long.png'
+			}
+		},
+		methods: {
+			
+		}
+	}
+</script>
+
+<style>
+
+</style>

+ 181 - 0
pages/activity/boost.vue

@@ -0,0 +1,181 @@
+<template>
+	<view>
+		<view class="bg-img" style="background-image: url('/static/singerBg.png');height: 563upx;"></view>
+		<view class="head">
+			<view class="title">为{{name}}打榜</view>
+			<view class="flex justify-between align-center padding-lr">
+				<view class="flex align-center">
+					<u-avatar src="/static/avatar.png" size="120"></u-avatar>
+					<view class="padding-left">
+						<view class="number">{{hotValue}}</view>
+						<view class="tag">
+							<image src="/static/crown.png" style="width: 22upx;height: 19upx;margin-right: 10upx;"></image>
+							<view class="text-sm text-white">热力榜第1</view>
+						</view>
+					</view>
+				</view>
+				<view class="text-center">
+					<button class="cu-btn round theme-bg-color text-white text-bold">
+						<text>打榜</text>
+						<text class="cuIcon-hot padding-lr-xs"></text>
+						<text>X1</text>
+					</button>
+					<view class="text-sm text-gray margin-top-xs">今日可打榜次数: 3</view>
+				</view>
+			</view>
+		</view>
+		<view class="flex justify-between align-center bg-white" style="padding: 40upx 30upx 30upx 30upx;">
+			<view class="flex align-center">
+				<image src="/static/icon-person.png" style="width: 82upx;height: 82upx;"></image>
+				<view class="padding-left-sm">
+					<view class="text-lg text-bold text-black">转发邀请打榜</view>
+					<view class="text-sm text-gray padding-top-xs">成功邀请一位好友打榜,热力值+5</view>
+				</view>
+			</view>
+			<button style="height: 56upx;" class="cu-btn round theme-bg-color text-white text-sm">去邀请</button>
+		</view>
+		<view class="container">
+			<view class="title">打call助力</view>
+		</view>
+		<view class="bg-white padding-sm">
+			<view class="flex justify-around">
+				<block v-for="(item,index) in present" :key="index">
+					<view class="text-center padding-top-xs" :class="current == index ? 'boder':''" @click="change(index)">
+						<image :src="item.icon" style="width: 80upx;height: 80upx;"></image>
+						<view class="text-sm margin-tb-xs">金额: {{item.price}}</view>
+						<view style="margin-bottom: 10upx;">
+							<text class="cuIcon-hotfill theme-color"></text>
+							<text style="font-size: 20upx;">{{item.tips}}</text>
+						</view>
+					</view>
+				</block>
+			</view>
+		</view>
+		<view class="bg-white padding-sm">
+			<view class="text-sm text-gray">所有的打call助力均会由本平台发起公益捐赠</view>
+		</view>
+		<view style="height: 100upx;"></view>
+		<view class="footer-fixed bg-white padding-sm flex justify-between align-center">
+			<view>
+				<text style="font-size: 36upx;color: #FF4200">¥</text>
+				<text style="font-size: 46upx;font-family: PingFang SC;font-weight: bold;color: #FF4200">{{count * currentPresentSum}}</text>
+			</view>
+			<view  class="flex align-center">
+				<view class="flex align-center">
+					<view class="padding-right-sm" @click="minus"> <u-icon name="minus-circle-fill" color="#5a3ee8" size="36"></u-icon> </view>
+					<input type="number" class="text-center input" v-model="count" />
+					<view class="padding-left-sm" @click="plus"> <u-icon name="plus-circle-fill" color="#5a3ee8" size="36"></u-icon> </view>
+				</view>
+				<button style="width: 150upx;" class="margin-left cu-btn round theme-bg-color text-white text-sm" @click="dialogShow = true">助力</button>
+			</view>
+		</view>
+		<u-popup v-model="dialogShow" mode="center" width="500rpx" height="600rpx" border-radius="30">
+			<view class="bg-img text-center" style="background-image: url('/static/dialogBgImg.png');height: 600rpx;">
+				<view style="height: 120upx;"></view>
+				<u-avatar src="/static/avatar.png" size="160"></u-avatar>
+				<view class="margin-top" style="font-size: 24upx;font-family: PingFang SC;font-weight: bold;color: #323035;">你将为{{name}}增加50热力值</view>
+				<view class="text-gray text-sm">公益勋章X1</view>
+				<view class="text-gray text-sm">立白助力礼包A</view>
+				<view class="text-gray text-sm">可得300积分,可用于国信商城兑换</view>
+				<view class="padding">
+					<u-button class="custom-style" shape="circle">去支付</u-button>
+				</view>
+			</view>
+		</u-popup>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				current: 0,
+				name: '易烊千玺',
+				dialogShow: false,
+				hotValue: '184056',
+				present: [
+					{icon: '/static/present1.png', price: 68, tips: '66热力值/388积分', name: ''},
+					{icon: '/static/present2.png', price: 168, tips: '66热力值/688积分', name: ''},
+					{icon: '/static/present3.png', price: 268, tips: '188热力值/1888积分', name: ''},
+					{icon: '/static/present4.png', price: 368, tips: '66热力值/388积分', name: '立白助力礼包A'}
+				],
+				count: 1,
+				currentPresentSum: 0,
+			}
+		},
+		onLoad() {
+			this.currentPresentSum = this.present[this.current].price;
+		},
+		methods: {
+			change(index) {
+				this.currentPresentSum = 0;
+				this.count = 1;
+				this.current = index;
+				this.currentPresentSum = this.present[index].price;
+			},
+			//礼物+
+			plus() {
+				this.count++
+			}, 
+			//礼物 -
+			minus() {
+				if (this.count > 1) {
+					this.count--
+				}
+			},
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.head {
+		background-color: #ffffff;
+		margin-top: -26upx;
+		border-radius: 26upx 26upx 0 0;
+		.number {
+			font-size: 38upx;
+			font-family: PingFang SC;
+			font-weight: 800;
+			color: #222222;
+		}
+		.tag {
+			padding: 0 10upx;
+			line-height: 40upx;
+			display: flex;
+			align-items: center;
+			justify-content: center;
+			background: linear-gradient(90deg, #7355F4 0%, #573BE5 100%);
+			margin-top: 8upx;
+			border-radius: 30upx;
+		}
+	}
+	.title {
+		line-height: 50px;
+		padding-left: 30upx;
+		font-size: 30upx;
+		font-family: PingFang SC;
+		font-weight: 800;
+		color: #201F1F;
+	}
+	.container {
+		background-color: #FFFFFF;
+		margin-top: 30upx;
+	}
+	.boder {
+		box-shadow: -1upx -1upx 60upx #d8d8d8;
+		border-radius: 16upx;
+	}
+	.input {
+		width: 80upx;
+		background-color: #ffffff;
+		text-align: center;
+		border: none;
+		height: 60rpx;
+		min-height: 1.8rem;
+	}
+	.custom-style {
+		background-color: #5b3ee7;
+		width: 250upx;
+		color: #ffffff;
+	}
+</style>

+ 55 - 0
pages/activity/hot.vue

@@ -0,0 +1,55 @@
+<template>
+	<view>
+		<block v-for="(item, index) in hotList" :key="index">
+			<view class="padding-sm flex justify-between align-center bg-white">
+				<view class="flex justify-around align-center">
+					<view class="padding-right text-black text-bold">{{index + 1}}</view>
+					<view class="padding-right">
+						<u-avatar :src="item.avatar" size="130"></u-avatar>
+					</view>
+					<view>
+						<view class="text-bold text-black">{{item.name}}</view>
+						<view class="margin-tb-xs">{{item.hotValue}} 热力值</view>
+					</view>
+				</view>
+				<view class="padding-right">
+					<button class="cu-btn round  text-white" style="background-color: #583ce6;height: 68upx;">
+						<text class="cuIcon-hotfill padding-right-xs"></text>
+						<text>打榜</text>
+					</button>
+				</view>
+			</view>
+		</block>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				hotList: [
+					{avatar: '/static/avatar.png', name: '易烊千玺', hotValue: '300'},
+					{avatar: '/static/avatar.png', name: '易烊千玺', hotValue: '300'},
+					{avatar: '/static/avatar2.png', name: '易烊千玺', hotValue: '300'},
+					{avatar: '/static/avatar.png', name: '易烊千玺', hotValue: '300'},
+					{avatar: '/static/avatar2.png', name: '易烊千玺', hotValue: '300'},
+					{avatar: '/static/avatar.png', name: '易烊千玺', hotValue: '300'},
+					{avatar: '/static/avatar.png', name: '易烊千玺', hotValue: '300'},
+					{avatar: '/static/avatar2.png', name: '易烊千玺', hotValue: '300'},
+					{avatar: '/static/avatar.png', name: '易烊千玺', hotValue: '300'},
+					{avatar: '/static/avatar2.png', name: '易烊千玺', hotValue: '300'}
+				]
+			}
+		},
+		onReachBottom() {
+			console.log("到底了")
+		},
+		methods: {
+			
+		}
+	}
+</script>
+
+<style>
+
+</style>

+ 95 - 0
pages/activity/signUp.vue

@@ -0,0 +1,95 @@
+<template>
+	<view>
+		<view class="image-container">
+			<view class="cuIcon-roundaddfill theme-color" style="font-size: 80upx;padding: 100upx 0 30upx 0;"></view>
+			<view class="text-black text-bold text-sm">添加图片或视频</view>
+		</view>
+		<view class="basic-container">
+			<view class="padding-sm">
+				<text class="cuIcon-titles theme-color" style="font-size: 36upx;"></text>
+				<text class="text-black text-bold text-lg">基本信息</text>
+			</view>
+			<view class="padding-sm flex justify-around align-center">
+				<view class="tags" :class="current == 0 ? 'theme-bg-color text-white' : ''" @click="current = 0">男歌手</view>
+				<view class="tags" :class="current == 1 ? 'theme-bg-color text-white' : ''" @click="current = 1">女歌手</view>
+				<view class="tags" :class="current == 2 ? 'theme-bg-color text-white' : ''" @click="current = 2">组合</view>
+			</view>
+			<view class="padding-sm">
+				<text class="text-black text-bold text-lg padding-left-sm">歌手名字</text>
+				<view style="padding: 30upx 20upx;">
+					<u-input v-model="name" placeholder="请输入歌手名字" />
+				</view>
+				<view style="padding: 0 20upx 40upx 20upx;">
+					<u-line color="#e3e3e3" />
+				</view>
+				<text class="text-black text-bold text-lg padding-left-sm">歌曲名称</text>
+				<view style="padding: 30upx 20upx;">
+					<u-input v-model="music" placeholder="请输入歌曲名称" />
+				</view>
+				<view style="padding: 0 20upx 40upx 20upx;">
+					<u-line color="#e3e3e3" />
+				</view>
+				<text class="text-black text-bold text-lg padding-left-sm">个人简介</text>
+				<view style="padding: 30upx 20upx 0 20upx;">
+					<u-input v-model="introduction" type="textarea" :clearable="false" height="140" :autoHeight="false" maxlength="60" placeholder="请输入个人简介" />
+				</view>
+				<view class="flex justify-end padding-right-sm padding-bottom-sm text-gray">{{introduction.length}} / 60</view>
+				<view style="padding: 0 20upx 40upx 20upx;">
+					<u-line color="#e3e3e3" />
+				</view>
+				<view style="margin: 30upx 0 40upx 0;">
+					<u-button class="custom-style" shape="circle" @click="navWithParam">确定提交</u-button>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				current: 0,
+				name: '',
+				introduction: '',
+				music: '',
+			}
+		},
+		methods: {
+			navWithParam() {
+				uni.navigateTo({
+					url: '/pages/mine/introduction'
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.image-container {
+		text-align: center;
+		background-color: #FFFFFF;
+		height: 400upx;
+		margin: 30upx;
+		border-radius: 30upx;
+	}
+	.basic-container {
+		background-color: #FFFFFF;
+		margin: 20upx;
+		border-radius: 30upx;
+	}
+	.tags {
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		width: 30%;
+		height: 70upx;
+		border: #4f4f4f 1px solid;
+		border-radius: 28upx;
+	}
+	.custom-style {
+		background-color: #5a3ee8;
+		color: #FFFFFF;
+		width: 400rpx;
+	}
+</style>

+ 195 - 0
pages/activity/songRank.vue

@@ -0,0 +1,195 @@
+<template>
+	<view>
+		<view class="bg-img flex justify-center align-center" style="background-image: url('/static/songRank/songRankBgImg.png');height: 402upx;">
+			<view class="title">歌曲排行榜</view>
+		</view>
+		<view class="flex justify-center align-center padding-bottom">
+			<view class="search">
+				<text class="cuIcon-search padding-right-xs"></text>
+				{{searValue}}
+			</view>
+		</view>
+		<u-sticky h5-nav-height="0">
+			<u-tabs :list="list" active-color="#5c40e8" :bold="false" :is-scroll="false" :current="current" @change="change"></u-tabs>
+		</u-sticky>
+		<view class="flex align-center padding-left" style="margin-top: 40upx;">
+			<image src="/static/songRank/medal.png" style="width: 32upx;height: 40upx"></image>
+			<view style="font-size: 36upx;font-weight: 800;color: #000000;padding-left: 20upx;">提名歌曲</view>
+		</view>
+		<block v-for="(item, index) in songList" :key="index">
+			<block v-if="index == 0 || index == 1 || index == 2">
+				<view class="margin-sm flex align-center" :class="index == 0 ? 'first' : index == 1 ? 'second' : index == 2 ? 'third' : '' ">
+					<u-image width="200" height="200" :src="item.coverImg"></u-image>
+					<view class="flex justify-between container" :style="{width: (index == 0 ? '70%': index == 1 ? '69%' : index == 2 ? '68%' : '60%')}">
+						<view class="left"  style="width: 65%;">
+							<view class="name text-cut">{{item.name}}</view>
+							<view class="padding-tb-sm text-sm">{{item.singer}}</view>
+							<view class="hot-value">热力值 {{item.hotVaule}}</view>
+						</view>
+						<view class="right">
+							<view class="rank" :style="{coloar: (index == 0 ? '#ECDA47': index == 1 ? '#C1D4DA' : index == 2 ? '#C1D4DA' : '')}">
+								NO.{{index + 1}}
+							</view>
+							<view>
+								<button class="cu-btn round theme-bg-color sm text-white">
+									<text class="cuIcon-hotfill"></text>
+									<text class="padding-left-xs">打榜</text>
+								</button>
+							</view>
+						</view>
+					</view>
+				</view>
+			</block>
+			<block v-else>
+				<view class="flex" style="padding: 10upx 30upx 30upx 40upx;">
+					<view class="flex justify-center align-center text-bold text-lg padding-right">{{index + 1}}</view>
+					<image :src="item.coverImg" style="width: 120upx;height: 120upx;margin-right: 20upx;"></image>
+					<view style="width: 70%;">
+						<view class="flex justify-between">
+							<view class="music" style="width: 75%;">
+								<view class="name text-cut">{{item.name}}</view>
+								<view class="author">{{item.singer}}</view>
+								<view class="hot-vaule">热力值 {{item.hotVaule}}</view>
+							</view>
+							<view class="flex align-end">
+								<button class="cu-btn round lines-purple sm" style="width: 110upx;">打榜</button>
+							</view>
+						</view>
+						<view class="margin-top-xs"><u-line color="#cacaca"></u-line> </view>
+					</view>
+				</view>
+			</block>
+		</block>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				current: 0,
+				list: [{
+					name: '全部'
+				}, {
+					name: '男歌手榜'
+				}, {
+					name: '女歌手榜'
+				}, {
+					name: '组合榜'
+				}],
+				searValue: '不存在的关系 - XMASwu',
+				songList: [
+					{coverImg: '/static/songRank/fm1.png', name: '巴赫旧约', singer: '沈以诚', hotVaule: '3.5w'},
+					{coverImg: '/static/songRank/fm2.png', name: '1987我不知会遇见你', singer: '孟慧圆/邓见超', hotVaule: '3.5w'},
+					{coverImg: '/static/songRank/fm3.png', name: '孤影', singer: 'C-BLOCK', hotVaule: '3.5w'},
+					{coverImg: '/static/musicCover.png', name: '海底(live)', singer: '凤凰传奇', hotVaule: '3.5w'},
+					{coverImg: '/static/songRank/fm4.png', name: '一次就好', singer: '理迎趣', hotVaule: '3.5w'},
+					{coverImg: '/static/songRank/fm1.png', name: '巴赫旧约', singer: '沈以诚', hotVaule: '3.5w'},
+					{coverImg: '/static/songRank/fm2.png', name: '1987我不知会遇见你', singer: '孟慧圆/邓见超', hotVaule: '3.5w'},
+					{coverImg: '/static/songRank/fm3.png', name: '孤影', singer: 'C-BLOCK', hotVaule: '3.5w'},
+					{coverImg: '/static/musicCover.png', name: '海底(live)', singer: '凤凰传奇', hotVaule: '3.5w'},
+					{coverImg: '/static/songRank/fm4.png', name: '一次就好', singer: '理迎趣', hotVaule: '3.5w'}
+				]
+			}
+		},
+		methods: {
+			change(index) {
+				this.current = index;
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.search {
+		margin-top: -40upx;
+		width: 80%;
+		border-radius: 50upx;
+		line-height: 60upx;
+		background-color: #FFFFFF;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		color: #9D9D9D;
+		font-size: 20upx;
+		box-shadow: 10upx 20upx 60upx #d8d8d8;
+	}
+	.title {
+		font-size: 56upx;
+		font-family: PingFang SC;
+		font-weight: 800;
+		color: #FFFFFF;
+	}
+	.first {
+		background-color: #fbf8e5;
+		border-radius: 20upx;
+		box-shadow: -1upx -1upx 60upx #d8d8d8;
+	}
+	.second {
+		background-color: #f0f5f9;
+		border-radius: 20upx;
+		box-shadow: -1upx -1upx 60upx #d8d8d8;
+		margin: 0 30upx;
+	}
+	.third {
+		background-color: #fef0ef;
+		border-radius: 20upx;
+		box-shadow: -1upx -1upx 60upx #d8d8d8;
+		margin: 20upx 40upx;
+	}
+	.container {
+		.left {
+			padding-left: 20upx;
+			.name {
+				font-size: 30upx;
+				font-family: PingFang SC;
+				font-weight: 800;
+				color: #000000;
+			}
+			.hot-value {
+				font-size: 24upx;
+				font-family: PingFang SC;
+				font-weight: 400;
+				color: #3F372A;
+			}
+		}
+		.right {
+			text-align: center;
+			padding-right: 10upx;
+			.rank {
+				height: 70%;
+				font-size: 36upx;
+				font-family: PingFang SC;
+				font-weight: 800;
+				font-style: italic;
+			}
+		}
+	}
+	.music {
+		.name {
+			font-size: 30upx;
+			font-family: PingFang SC;
+			font-weight: 400;
+			color: #000000;
+		}
+		.author {
+			font-size: 14upx;
+			font-family: PingFang SC;
+			font-weight: 400;
+			color: #9A9A9A;
+		}
+		.hot-vaule {
+			margin-top: 10upx;
+			font-size: 14upx;
+			font-family: PingFang SC;
+			font-weight: 400;
+			color: #3F372A;
+		}
+	}
+	.lines-purple::after {
+		border-color: #5a3ee8;
+	}
+	.lines-purple {
+		color: #5a3ee8;
+	}
+</style>

+ 76 - 0
pages/home/home.vue

@@ -0,0 +1,76 @@
+<template>
+	<view>
+		<!--活动页面-->
+		<view v-if="current == 0">
+			<activity-view :imgList="imgList"></activity-view>
+		</view>
+		
+		<!--个人中心-->
+		<view v-if="current == 2">
+			<mine-view></mine-view>
+		</view>
+		<view style="height: 100upx;"></view>
+		<view class="footer-fixed">
+			<bottom-bar @onTap="change"></bottom-bar>
+		</view>
+	</view>
+</template>
+
+<script>
+	import searchBar from "@/components/basic/search-bar.vue";
+	import bottomBar from "@/components/basic/bottom-bar.vue";
+	import activityView from "@/components/views/activity-view.vue";
+	import mineView from "@/components/views/mine-view.vue";
+	export default {
+		components: {
+			searchBar,
+			bottomBar,
+			activityView,
+			mineView
+		},
+		data() {
+			return {
+				current: 0,
+				imgList: [
+					{image: '/static/swiper1.png'},
+					{image: '/static/swiper1.png'},
+					{image: '/static/swiper1.png'}
+				],
+			}
+		},
+		methods: {
+			change(index) {
+				this.current = index;
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.first {
+		height: 300upx;
+		width: 30%;
+		border-radius: 30upx;
+		box-shadow: -1upx -1upx 60upx #d8d8d8;
+	}
+	.second {
+		height: 260upx;
+		width: 27%;
+		border-radius: 30upx;
+		box-shadow: -1upx -1upx 60upx #d8d8d8;
+	}
+	.third {
+		height: 260upx;
+		width: 27%;
+		border-radius: 30upx;
+		box-shadow: -1upx -1upx 60upx #d8d8d8;
+	}
+	.hot-btn {
+		color: #FFFFFF;
+		line-height: 56upx;
+		width: 70%;
+		border-radius: 30upx;
+		background-color: #583ce6;
+		font-weight: bold;
+	}
+</style>

+ 117 - 0
pages/index/index.vue

@@ -0,0 +1,117 @@
+<template>
+	<view>
+		<view class="bg-white" style="padding: 30upx; 30upx 0upx 30upx">
+			<u-swiper height="268" :list="imgList" bg-color="#fff" interval="5000"></u-swiper>
+		</view>
+		<view>
+			<search-bar :disabled="false" @onSearch="onSearch" placeholder="请输入活动名称"></search-bar>
+		</view>
+		<view class="padding-lr-sm bg-white flex flex-wrap" style="padding-bottom: 10upx;">
+			<block v-for="(item, index) in activityTags" :key="index">
+				<view class="activity-tag">{{item}}</view>
+			</block>
+		</view>
+		<view class="container" @click="navWithParm">
+			<view class="flex align-center">
+				<view style="margin: 30upx 0 10upx 20upx;">
+					<image src="/static/index/huodong1.png" style="width: 234upx;height: 188upx;"></image>
+				</view>
+				<view class="padding-lr-sm">
+					<view class="flex">
+						<view style="width: 80%">
+							<view class="text-lg text-bold">音乐先锋榜</view>
+							<view class="text-sm margin-tb-xs">2021.07.01 - 2021.12.31</view>
+							<view class="text-sm text-cut-2">
+								简介: 面向中国及海外22岁以下的非专业音乐学习者,包括在中国生活学习的外国友人
+							</view>
+						</view>
+						<view style="margin-top: 10upx;">
+							<image src="/static/index/ing.png" style="width: 83upx;height: 73upx;"></image>
+						</view>
+					</view>
+					<!-- <view class="text-sm flex flex-wrap">
+						<block v-for="(item, index) in awardTags" :key="index">
+							<view class="award-tag">{{item}}</view>
+						</block>
+					</view> -->
+				</view>
+			</view>
+			<view class="flex justify-end padding-right-sm">
+				<block v-for="(item, index) in tags" :key="index">
+					<view class="tag">{{item}}</view>
+				</block>
+			</view>
+			<view class="flex align-center justify-end text-sm" style="padding: 20upx 30upx 30upx ;">
+				<text class="cuIcon-hotfill text-orange"></text>
+				<view class="padding-left-xs">已有1.2万人报名</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import searchBar from "@/components/basic/search-bar.vue";
+	export default {
+		components: {searchBar},
+		data() {
+			return {
+				imgList: [
+					{image: '/static/index/swiper.png'},
+					{image: '/static/index/swiper.png'},
+					{image: '/static/index/swiper.png'}
+				],
+				activityTags: ['K歌之王','城市争霸','CF城市争霸赛', '主持人比赛'],
+				awardTags: ['1万RMB','点歌机','100000积分'],
+				tags: ['音乐','交友','竞技','全国','积分']
+			}
+		},
+		onLoad() {
+			console.log("路过");
+		},
+		methods: {
+			navWithParm() {
+				uni.navigateTo({
+					url: "/pages/home/home"
+				})
+			},
+			onSearch(item) {
+				console.log(item)
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.activity-tag {
+		margin: 10upx;
+		padding: 0 10upx;
+		font-size: 24upx;
+		line-height: 40upx;
+		background-color: #efefef;
+		border-radius: 16upx;
+	}
+	.award-tag {
+		margin: 10upx;
+		padding: 0 10upx;
+		font-size: 20upx;
+		line-height: 40upx;
+		background-color: #fff0d9;
+		border-radius: 10upx;
+		color: #feac65;
+	}
+	.tag {
+		border-radius: 30upx;
+		border: #fd8678 1upx solid;
+		color: #fd8678;
+		background-color: #FFFFFF;
+		line-height: 40upx;
+		font-size: 20upx;
+		padding: 0 20upx;
+		margin: 0 8upx;
+	}
+	.container {
+		margin: 20upx;
+		background-color: #FFFFFF;
+		border-radius: 20upx;
+	}
+</style>

+ 59 - 0
pages/mine/boostDetail.vue

@@ -0,0 +1,59 @@
+<template>
+	<view>
+		<block v-for="(item, index) in boostList" :key="index">
+			<view class="flex align-center justify-between boder">
+				<view class="flex align-center" style="width: 50%;">
+					<view class="padding-sm">
+						<u-avatar :src="item.image" size="82"></u-avatar>
+					</view>
+					<view>
+						<view class="name">{{item.name}}</view>
+						<view class="time padding-top-xs">{{item.time}}</view>
+					</view>
+				</view>
+				<view class="text-sm" style="color: #757575;">{{item.type}}</view>
+				<view class="name padding-right flex justify-end" style="width: 180upx;">{{item.hotValue}}热力值</view>
+			</view>
+		</block>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				boostList: [
+					{image: '/static/avatar.png', name: '私自弟弟', time: '2021-6-7 10:28:46', type: '打榜', hotValue: '12'},
+					{image: '/static/avatar2.png', name: '安置若梦', time: '2021-6-7 10:28:46', type: '礼物', hotValue: '13'},
+					{image: '/static/avatar.png', name: '莫忘莫寻', time: '2021-6-7 10:28:46', type: '打榜', hotValue: '188'},
+					{image: '/static/avatar2.png', name: 'kris-Lee', time: '2021-6-7 10:28:46', type: '打榜', hotValue: '88'},
+					{image: '/static/avatar.png', name: 'RainBow维', time: '2021-6-7 10:28:46', type: '礼物', hotValue: '13'},
+					{image: '/static/avatar.png', name: 'Niconic', time: '2021-6-7 10:28:46', type: '转发', hotValue: '1'},
+					{image: '/static/avatar2.png', name: '晨光中。', time: '2021-6-7 10:28:46', type: '打榜', hotValue: '5'}
+				],
+			}
+		},
+		methods: {
+			
+		}
+	}
+</script>
+
+<style>
+	.name {
+		font-size: 26upx;
+		font-family: PingFang SC;
+		font-weight: bold;
+		color: #111111;
+	}
+	.time {
+		font-size: 16upx;
+		font-family: PingFang SC;
+		color: #9E9E9E;
+	}
+	.boder {
+		margin: 20upx;
+		box-shadow: -1upx -1upx 60upx #d0d0d0;
+		border-radius: 30upx;
+	}
+</style>

+ 94 - 0
pages/mine/edit.vue

@@ -0,0 +1,94 @@
+<template>
+	<view>
+		<view class="flex padding justify-between align-center">
+			<view class="title">头像</view>
+			<u-avatar src="/static/avatar.png" size="120"></u-avatar>
+		</view>
+		<u-line color="#f1f1f1"></u-line>
+		<view class="flex padding justify-between align-center">
+			<view class="title">昵称</view>
+			<u-input v-model="name" :clearable="false" inputAlign="right" placeholder="请输入昵称"></u-input>
+		</view>
+		<u-line color="#f1f1f1"></u-line>
+		<view class="flex padding justify-between align-center">
+			<view class="title">性别</view>
+			<view style="width: 200upx;">
+				<u-input v-model="sex" type="select" :border="border" @click="sexShow = true"></u-input>
+				<u-action-sheet :list="actionSheetList" v-model="sexShow" @click="actionSheetCallback"></u-action-sheet>
+			</view>
+		</view>
+		<u-line color="#f1f1f1"></u-line>
+		<view class="flex padding justify-between align-center" @click="calendarShow = true">
+			<view class="title">生日</view>
+			<view>{{birthday}}</view>
+			<u-calendar v-model="calendarShow" mode="date" @change="change"></u-calendar>
+		</view>
+		<u-line color="#f1f1f1"></u-line>
+		<view class="padding">
+			<view class="title">个人介绍</view>
+		</view>
+		<view style="padding: 0 40upx">
+			<u-input v-model="introduction" type="textarea" :clearable="false" height="140" :autoHeight="false" maxlength="60" placeholder="请输入个人简介" />
+		</view>
+		<view class="flex justify-end padding-right-sm padding-bottom-sm text-gray">{{introduction.length}} / 60</view>
+		<view class="footer-fixed margin-bottom">
+			<u-button class="custom-style" shape="circle">保存</u-button>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				name: 'Daniel Hua',
+				sex: '男',
+				sexShow: false,
+				border: true,
+				show: false,
+				actionSheetList: [
+					{
+						text: '男'
+					},
+					{
+						text: '女'
+					},
+					{
+						text: '保密'
+					}
+				],
+				calendarShow: false,
+				birthday: '2020-7-14',
+				introduction: '',
+			}
+		},
+		methods: {
+			// 点击actionSheet回调
+			actionSheetCallback(index) {
+				this.sex = this.actionSheetList[index].text;
+			},
+			change(e) {
+				console.log(e);
+				this.birthday = e.result;
+			}
+		}
+	}
+</script>
+<style>
+	page {
+		background-color: #ffffff;
+	}
+</style>
+<style lang="scss" scoped>
+	.title {
+		font-size: 30upx;
+		font-weight: bold;
+		color: #060606;
+		padding-left: 10upx;
+	}
+	.custom-style {
+		background-color: #5a3ee7;
+		color: #ffffff;
+		width: 600rpx;
+	}
+</style>

+ 89 - 0
pages/mine/introduction.vue

@@ -0,0 +1,89 @@
+<template>
+	<view>
+		<view class="bg-img flex align-center" style="background-image: url('/static/userBgImg.png');height: 450upx;"></view>
+		<view class="container" style="margin: -60upx 20upx 20upx 20upx;">
+			<view class="text-center">
+				<view class="cu-avatar avatar round" :style="[{backgroundImage:'url('+ avatar +')'}]"></view>
+				<view class="padding-tb-xs" style="font-size: 38upx;font-family: PingFang SC;font-weight: 800;color: #222222;">易烊千玺</view>
+				<view class="flex justify-center align-center">
+					<view class="padding-right-sm" style="font-size: 30upx;font-family: PingFang SC;font-weight: 800;color: #222222;">184056</view>
+					<view class="tag">
+						<image src="/static/crown.png" style="width: 22upx;height: 19upx;margin-right: 10upx;"></image>
+						<view class="text-sm text-white">热力榜第1</view>
+					</view>
+				</view>
+			</view>
+			<view style="padding: 0 60upx;">
+				<view>歌手简介:易烊千玺,2000年11月28日生于湖南省怀化市,中国内地男演员、歌手、舞者,演唱组合TFBOYS成员,就读于中央戏剧学院。</view>
+			</view>
+			<view class="flex justify-around padding">
+				<button class="theme-bg-color text-white round cu-btn" style="width: 200upx;height: 70upx;">转发好友</button>
+				<button class="theme-bg-color text-white round cu-btn" style="width: 200upx;height: 70upx;">生成海报</button>
+			</view>
+		</view>
+		<view class="container margin-sm">
+			<block v-for="(item, index) in boostList" :key="index">
+				<view class="flex align-center justify-between padding-lr-sm">
+					<view class="flex align-center" style="width: 40%;">
+						<view class="padding-sm">
+							<u-avatar :src="item.image" size="82"></u-avatar>
+						</view>
+						<view class="name">{{item.name}}</view>
+					</view>
+					<view class="text-sm" style="color: #757575;">{{item.type}}</view>
+					<view class="name padding-right flex justify-end" style="width: 180upx;">{{item.hotValue}}热力值</view>
+				</view>
+			</block>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				avatar: '/static/avatar.png',
+				boostList: [
+					{image: '/static/avatar.png', name: '易烊千玺', time: '2021-6-7 10:28:46', type: '打榜', hotValue: '12'},
+					{image: '/static/avatar2.png', name: '许嵩', time: '2021-6-7 10:28:46', type: '礼物', hotValue: '13'},
+					{image: '/static/avatar.png', name: '林俊杰', time: '2021-6-7 10:28:46', type: '打榜', hotValue: '188'},
+					{image: '/static/avatar2.png', name: '沈以诚', time: '2021-6-7 10:28:46', type: '打榜', hotValue: '88'},
+					{image: '/static/avatar.png', name: '颜人中', time: '2021-6-7 10:28:46', type: '礼物', hotValue: '13'},
+					{image: '/static/avatar.png', name: '毛不易', time: '2021-6-7 10:28:46', type: '转发', hotValue: '1'},
+					{image: '/static/avatar2.png', name: '陈奕迅', time: '2021-6-7 10:28:46', type: '打榜', hotValue: '5'}
+				],
+			}
+		},
+		methods: {
+			
+		}
+	}
+</script>
+
+<style>
+	.container {
+		background-color: #ffffff;
+		border-radius: 30upx;
+		box-shadow: 10upx 10upx 60upx #d0d0d0;
+	}
+	.avatar {
+		width: 145upx;
+		height: 145upx;
+		margin-top: -60upx;
+	}
+	.tag {
+		padding: 0 10upx;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		background: linear-gradient(90deg, #7355F4 0%, #573BE5 100%);
+		margin-top: 8upx;
+		border-radius: 30upx;
+	}
+	.name {
+		font-size: 26upx;
+		font-family: PingFang SC;
+		font-weight: bold;
+		color: #111111;
+	}
+</style>

+ 85 - 0
pages/mine/myAwards.vue

@@ -0,0 +1,85 @@
+<template>
+	<view>
+		<view class="bg-img" style="background-image: url('/static/bgimg.png');height: 310upx;"></view>
+		<view class="container" style="margin: -80upx 30upx 30upx 30upx;">
+			<view class="padding">
+				<text class="text-bold text-black padding-right-sm">账户热力值</text>
+				<text class="text-bold" style="color: #f87a3a;">可兑换到账288元</text>
+			</view>
+			<view class="padding-lr flex justify-between align-center">
+				<view>
+					<text style="font-size: 60upx;font-family: PingFang SC;font-weight: 800;color: #F3484E;">28216</text>
+					<text class="padding-left-xs" style="font-size: 24upx;font-family: PingFang SC;font-weight: 800;color: #878787;">热力值</text>
+				</view>
+				<button class="cu-btn round text-white" style="background-color: #f75757;width: 140upx;">提现</button>
+			</view>
+			<view style="margin: 10upx 20upx;">
+				<u-line color="#e0e0e0"></u-line>
+			</view>
+			<view style="padding: 20upx 0upx 0upx 30upx;">
+				<text class="title">已提现:</text>
+				<text class="number">100</text>
+				<text class="title padding-left-xs">元</text>
+			</view>
+			<view style="padding: 10upx 0upx 20upx 30upx;">
+				<text class="title">可提现:</text>
+				<text class="number">188</text>
+				<text class="title padding-left-xs">元</text>
+			</view>
+		</view>
+		<view class="container margin-lr">
+			<view class="padding flex align-center">
+				<view class="cuIcon-text text-bold padding-right-xs" style="font-size: 38upx;"></view>
+				<view class="title">提现明细</view>
+			</view>
+			<block v-for="(item, index) in 6" :key="index">
+				<view class="flex align-center justify-between">
+					<view class="padding-lr">
+						<view class="title">热力提现</view>
+						<view style="font-size: 24upx;font-family: PingFang SC;font-weight: bold;color: #686868;">2020-11-24 00:32</view>
+					</view>
+					<view class="padding-right">
+						<text style="font-size: 36upx;font-family: PingFang SC;font-weight: bold;color: #F3484E;">+45</text>
+						<text class="text-bold padding-left-xs">元</text>
+					</view>
+				</view>
+				<view style="padding: 20upx;">
+					<u-line color="#e0e0e0"></u-line>
+				</view>
+			</block>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				
+			}
+		},
+		methods: {
+			
+		}
+	}
+</script>
+
+<style>
+	.container {
+		background-color: #FFFFFF;
+		border-radius: 16upx;
+		box-shadow: 0px 3px 79px 0px rgba(132, 132, 132, 0.22);
+	}
+	.title {
+		font-size: 28upx;
+		font-family: PingFang SC;
+		font-weight: 800;
+		color: #000000;
+	}
+	.number {
+		font-size: 30upx;
+		font-family: PingFang SC;
+		font-weight: 800;
+		color: #F3484E;
+	}
+</style>

+ 60 - 0
pages/mine/myBoost.vue

@@ -0,0 +1,60 @@
+<template>
+	<view>
+		<view class="bg-img" style="background-image: url('/static/bgimg.png');height: 310upx;"></view>
+		<block v-for="(item, index) in boostList" :key="index">
+			<view class="flex align-center justify-between boder">
+				<view class="flex align-center">
+					<view class="padding-sm">
+						<u-avatar :src="item.image" size="82"></u-avatar>
+					</view>
+					<view>
+						<view class="name">{{item.name}}</view>
+						<view class="time padding-top-xs">{{item.time}}</view>
+					</view>
+				</view>
+				<view class="text-sm" style="color: #757575;">{{item.type}}</view>
+				<view class="name padding-right flex justify-end" style="width: 180upx;">{{item.hotValue}}热力值</view>
+			</view>
+		</block>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				boostList: [
+					{image: '/static/avatar.png', name: '易烊千玺', time: '2021-6-7 10:28:46', type: '打榜', hotValue: '12'},
+					{image: '/static/avatar2.png', name: '许嵩', time: '2021-6-7 10:28:46', type: '礼物', hotValue: '13'},
+					{image: '/static/avatar.png', name: '林俊杰', time: '2021-6-7 10:28:46', type: '打榜', hotValue: '188'},
+					{image: '/static/avatar2.png', name: '沈以诚', time: '2021-6-7 10:28:46', type: '打榜', hotValue: '88'},
+					{image: '/static/avatar.png', name: '颜人中', time: '2021-6-7 10:28:46', type: '礼物', hotValue: '13'},
+					{image: '/static/avatar.png', name: '毛不易', time: '2021-6-7 10:28:46', type: '转发', hotValue: '1'},
+					{image: '/static/avatar2.png', name: '陈奕迅', time: '2021-6-7 10:28:46', type: '打榜', hotValue: '5'}
+				],
+			}
+		},
+		methods: {
+			
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.name {
+		font-size: 26upx;
+		font-family: PingFang SC;
+		font-weight: bold;
+		color: #111111;
+	}
+	.time {
+		font-size: 16upx;
+		font-family: PingFang SC;
+		color: #9E9E9E;
+	}
+	.boder {
+		margin: 20upx;
+		box-shadow: -1upx -1upx 60upx #d0d0d0;
+		border-radius: 30upx;
+	}
+</style>

+ 231 - 0
pages/mine/myGift.vue

@@ -0,0 +1,231 @@
+<template>
+	<view>
+		<u-sticky h5-nav-height="0">
+			<u-tabs :list="list" active-color="#5c40e8" :is-scroll="false" :current="current" @change="change"></u-tabs>
+		</u-sticky>
+		<view v-if="current == 0">
+			<block v-for="(item, index) in giftList" :key="index">
+				<view class="card">
+					<view class="padding">
+						<view class="flex justify-between align-center padding-bottom-sm">
+							<view class="flex align-center">
+								<view class="cuIcon-goods padding-right-xs text-bold text-black" style="font-size: 40upx;"></view>
+								<view class="title">{{item.title}}</view>
+							</view>
+							<view v-if="item.status == '已完成'">
+								<text class="padding-right-sm text-gray">已完成</text>
+								<text class="cuIcon-delete text-gray" style="font-size: 30upx;"></text>
+							</view>
+							<view v-else>
+								<text class="text-red">{{item.status}}</text>
+							</view>
+						</view>
+						<view class="flex margin-top-xs">
+							<image :src="item.image" style="width: 220upx;height: 220upx;"></image>
+							<view class="padding-left-sm">
+								<view class="name text-cut" style="width: 350upx;">{{item.name}}</view>
+								<view class="specification">
+									<view>{{item.specification}}</view>
+								</view>
+							</view>
+						</view>
+					</view>
+					<view class="flex justify-end padding" style="margin-top: -120upx;">
+						<view class="count">x{{item.count}}</view>
+					</view>
+				</view>
+			</block>
+		</view>
+		<view v-if="current == 1">
+			<block v-for="(item, index) in giftList" :key="index">
+				<view class="card" @click="select(index)" v-if="item.status == '待领取'">
+					<view class="flex">
+						<view :class="item.selected ? 'theme-color cuIcon-roundcheckfill':'cuIcon-round'" class="padding-sm" style="font-size: 50upx;"></view>
+						<view class="padding-tb-sm">
+							<view class="flex align-center padding-bottom-sm">
+								<view class="cuIcon-goods padding-right-xs text-bold text-black" style="font-size: 40upx;"></view>
+								<view class="title">{{item.title}}</view>
+							</view>
+							<view class="flex margin-top-xs">
+								<image :src="item.image" style="width: 220upx;height: 220upx;"></image>
+								<view class="padding-left-sm">
+									<view class="name text-cut" style="width: 350upx;">{{item.name}}</view>
+									<view class="specification">
+										<view>{{item.specification}}</view>
+									</view>
+								</view>
+							</view>
+						</view>
+					</view>
+					<view class="flex justify-end padding" style="margin-top: -110upx;">
+						<view class="count">x{{item.count}}</view>
+					</view>
+				</view>
+			</block>
+			<view style="height: 120upx;"></view>
+			<view class="footer-fixed flex align-center justify-between padding-sm bg-white">
+				<view class="flex align-center" @click="selectAll">
+					<view :class="selectAllShow ? 'theme-color cuIcon-roundcheckfill':'cuIcon-round'" class="padding-right-xs" style="font-size: 50upx;"></view>
+					<view class="text-sm padding-right-xs">全选</view>
+				</view>
+				<view>
+					<button class="cu-btn round text-white theme-bg-color" style="width: 180upx;height: 80upx;margin-right: 30upx;" @click="donate">捐赠</button>
+					<button class="cu-btn round text-white theme-bg-color" style="width: 180upx;height: 80upx;" @click="navTap">领取</button>
+				</view>
+			</view>
+		</view>
+		<view v-if="current == 2">
+			<block v-for="(item, index) in giftList" :key="index">
+				<view class="card" v-if="item.status == '已完成'">
+					<view class="padding">
+						<view class="flex justify-between align-center padding-bottom-sm">
+							<view class="flex align-center">
+								<view class="cuIcon-goods padding-right-xs text-bold text-black" style="font-size: 40upx;"></view>
+								<view class="title">{{item.title}}</view>
+							</view>
+							<view>
+								<text class="padding-right-sm text-gray">已完成</text>
+								<text class="cuIcon-delete text-gray" style="font-size: 30upx;"></text>
+							</view>
+						</view>
+						<view class="flex margin-top-xs">
+							<image :src="item.image" style="width: 220upx;height: 220upx;"></image>
+							<view class="padding-left-sm">
+								<view class="name text-cut" style="width: 350upx;">{{item.name}}</view>
+								<view class="specification">
+									<view>{{item.specification}}</view>
+								</view>
+							</view>
+						</view>
+					</view>
+					<view class="flex justify-end padding" style="margin-top: -120upx;">
+						<view class="count">x{{item.count}}</view>
+					</view>
+				</view>
+			</block>
+		</view>
+		<u-popup v-model="dialogShow" mode="center" width="500" height="480" border-radius="30">
+			<view class="bg-img text-center" style="background-image: url('/static/dialogBgImg.png');height: 600rpx;">
+				<view style="height: 80upx;"></view>
+				<view style="font-size: 50upx;font-family: PingFang SC;font-weight: 600;color: #ffffff;">感谢你</view>
+				<view class="text-bold text-black" style="padding: 80upx 0;">广发基金会已收到您的捐赠!</view>
+				<view class="padding">
+					<u-button class="custom-style" shape="circle" @click="dialogShow = false">确定</u-button>
+				</view>
+			</view>
+		</u-popup>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				list: [{
+					name: '全部'
+				}, {
+					name: '待领取'
+				}, {
+					name: '已完成'
+				}],
+				current: 0,
+				selectAllShow: false,
+				giftList: [
+					{image: '/static/gift/commodity2.png', title: 'lilbetter化妆品旗舰', name: 'Lilbetter发泥男士定型自然', specification: '发泥+洁面乳 120ml', count: 1, selected: true, status: '已完成'},
+					{image: '/static/gift/commodity1.png', title: '轩城工艺沙发', name: '创意单人懒人沙发香蕉躺椅', specification: '黄色(皮质)', count: 3, selected: false, status: '待领取'},
+					{image: '/static/gift/commodity3.png', title: '懒虫家居生活馆', name: '懒人沙发阳台躺卧飘窗榻榻米', specification: '亚麻经典灰', count: 2, selected: true, status: '已完成'},
+					{image: '/static/gift/commodity4.png', title: '白七自制', name: '白七尼龙帆布单肩斜跨学生', specification: '黑色', count: 1, selected: false, status: '待领取'},
+					
+				],
+				dialogShow: false,
+			}
+		},
+		methods: {
+			change(index) {
+				this.current = index;
+			},
+			select(index) {
+				this.giftList[index].selected = !this.giftList[index].selected;
+				let flag = true;
+				for (let item of this.giftList) {
+					if (!item.selected) {
+						flag = false;
+					}
+				}
+				this.selectAllShow = flag;
+			},
+			selectAll() {
+				this.selectAllShow = !this.selectAllShow;
+				for (let item of this.giftList) {
+					if (this.selectAllShow) {
+						item.selected = true;
+					} else {
+					    item.selected = false;	
+					}
+				}
+			},
+			donate() {
+				let count = 0;
+				for (let item of this.giftList) {
+					if (item.status == '待领取' && item.selected) {
+						console.log(item.title);
+					} else {
+						count++
+					}
+				}
+				if (count == this.giftList.length) {
+					uni.showToast({
+						title: "请至少选择一件礼包",
+						icon: "none"
+					})
+				}
+			},
+			navTap() {
+				uni.navigateTo({
+					url: '/pages/mine/order/orderConfirm'
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.card {
+		margin: 20upx;
+		border-radius: 16upx;
+		background-color: #FFFFFF;
+		.title {
+			font-size: 28upx;
+			font-family: PingFang SC;
+			font-weight: 800;
+			color: #222222;
+		}
+		.name {
+			font-size: 26upx;
+			font-family: PingFang SC;
+			font-weight: 800;
+			color: #222222;
+		}
+		.specification {
+			padding-top: 30upx;
+			font-size: 24upx;
+			font-family: PingFang SC;
+			font-weight: bold;
+			color: #959595;
+		}
+		.count {
+			width: 60upx;
+			height: 60upx;
+			border: #d9d9d9 1upx solid;
+			border-radius: 16upx;
+			display: flex;
+			align-items: center;
+			justify-content: center;
+		}
+	}
+	.custom-style {
+		background-color: #5b3ee7;
+		width: 250upx;
+		color: #ffffff;
+	}
+</style>

+ 127 - 0
pages/mine/myMusic.vue

@@ -0,0 +1,127 @@
+<template>
+	<view>
+		<view class="bg-img flex align-center" style="background-image: url('/static/personBgImg.png');height: 450upx;"></view>
+		<view class="head">
+			<view class="cu-avatar avatar round" :style="[{backgroundImage:'url('+ avatar +')'}]"></view>
+			<view style="margin: 0 30upx 30upx 70upx;">
+				<view class="flex align-center">
+					<view class="text-black text-bold text-xl padding-right">{{name}}</view>
+					<image src="/static/icon-vip.png" style="width: 30upx;height: 34upx;"></image>
+				</view>
+				<view class="padding-tb">
+					<view class="rank">
+						<text class="text-bold padding-right-sm" style="font-style: italic;">NO.{{rank}}</text>
+						<text class="text-sm">今日排名</text>
+					</view>
+				</view>
+				<view class="flex align-center">
+					<view>
+						<text class="text-sm">共获热力</text>
+						<text class="cuIcon-hotfill padding-lr-xs"></text>
+						<text class="text-lg text-bold">22386</text>
+					</view>
+					<view style="height: 20upx;border: #dadada 1px solid; margin: 0 30upx;"></view>
+					<view>
+						<text class="text-sm">总值</text>
+						<text class="padding-left-xs">¥</text>
+						<text class="text-lg text-bold">1888</text>
+					</view>
+				</view>
+			</view>
+		</view>
+		<view class="margin-top bg-white">
+			<view class="padding-sm flex justify-between align-center">
+				<view class="margin-left-sm text-lg text-black text-bold">我的作品</view>
+				<button class="cu-btn theme-bg-color round text-white margin-right" @click="onTap">添加作品</button>
+			</view>
+		</view>
+		<block v-for="(item, index) in 8" :key="index">
+			<view class="flex bg-white" style="padding: 10upx 70upx 30upx 70upx;">
+				<image src="/static/musicCover.png" style="width: 120upx;height: 120upx;margin-right: 20upx;"></image>
+				<view style="width: 75%;">
+					<view class="flex justify-between">
+						<view class="music">
+							<view class="name">海底(Live)</view>
+							<view class="author">凤凰传奇 - 为他而歌</view>
+						</view>
+						<view>
+							<view class="text-black">
+								<text class="cuIcon-hotfill padding-right-xs"></text>
+								<text class="text-lg text-bold">22386</text>
+							</view>
+							<view class="music-rank">NO.10</view>
+						</view>
+					</view>
+					<view class="margin-top-sm"><u-line color="#cacaca"></u-line> </view>
+				</view>
+			</view>
+		</block>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				name: "Daniel Hua",
+				avatar: '/static/avatar2.png',
+				rank: 108,
+			}
+		},
+		methods: {
+			onTap() {
+				uni.navigateTo({
+					url: "/pages/activity/signUp",
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.head {
+		background-color: #ffffff;
+		margin-top: -26upx;
+		height: 320upx;
+		border-radius: 26upx 26upx 0 0;
+	}
+	.avatar {
+		width: 130upx;
+		height: 130upx;
+		margin: -60upx 0 30upx 80upx;
+	}
+	.rank {
+		display: flex;
+		justify-content: center;
+		background-color: #583be6;
+		width: 40%;
+		color: #ffffff;
+		border-radius: 16upx;
+		line-height: 60upx;
+	}
+	.music {
+		.name {
+			font-size: 28upx;
+			font-family: PingFang SC;
+			font-weight: 400;
+			color: #000000;
+			padding-bottom: 20upx;
+		}
+		.author {
+			font-size: 14upx;
+			font-family: PingFang SC;
+			font-weight: 400;
+			color: #9A9A9A;
+		}
+	}
+	.music-rank {
+		display: flex;
+		margin-top: 18upx;
+		line-height: 40upx;
+		justify-content: center;
+		border: #9d9d9d 1px solid;
+		color: #9d9d9d;
+		border-radius: 50upx;
+		font-style: italic;
+	}
+</style>

+ 106 - 0
pages/mine/myWelfare.vue

@@ -0,0 +1,106 @@
+<template>
+	<view>
+		<view class="flex bg-white align-center">
+			<view class="title padding-lr-sm">公益勋章</view>
+			<view class="text-sm">共解锁12个勋章,相当于2500积分</view>
+		</view>
+		<view class="text-center grid col-3 container">
+			<block v-for="(item, index) in welfareList" :key="index">
+				<view class="padding-tb" @click="select(index)">
+					<view>
+						<image :src="item.image" style="width: 200upx;height: 200upx;"></image>
+						<view :class="selectShow ? item.selected ? 'theme-color cuIcon-roundcheckfill': 'text-gray cuIcon-round' : 'text-white cuIcon-round'" style="position: relative;bottom: 230upx;left: 70upx;font-size: 50upx;"></view>
+					</view>
+					<view class="text-bold" style="margin-top: -50upx;">X{{item.count}}</view>
+				</view>
+			</block>
+		</view>
+		<view class="footer-fixed flex align-center justify-end padding bg-white" v-if="!selectShow">
+			<button class="cu-btn round text-white theme-bg-color" style="width: 180upx;height: 80upx;margin-right: 30upx;">公益证书</button>
+			<button class="cu-btn round text-white theme-bg-color" style="width: 180upx;height: 80upx;" @click="selectShow = true">兑换</button>
+		</view>
+		<view class="footer-fixed flex align-center justify-between padding bg-white" v-else>
+			<view class="flex align-center" @click="selectAll">
+				<view :class="selectAllShow ? 'theme-color cuIcon-roundcheckfill':'cuIcon-round'" class="padding-right-xs" style="font-size: 50upx;"></view>
+				<view class="text-sm padding-right-xs">全选</view>
+				<view class="text-sm">积分 {{total}}</view>
+			</view>
+			<view>
+				<button class="cu-btn round text-white theme-bg-color" style="width: 180upx;height: 80upx;margin-right: 30upx;">兑换</button>
+				<button class="cu-btn round line-gray" style="width: 180upx;height: 80upx;" @click="selectShow = false">取消</button>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				selectAllShow: false,
+				selectShow: false,
+				total: 0,
+				welfareList: [
+					{image: '/static/welfare/welfare1.png', count: 2, points: 200, selected: false},
+					{image: '/static/welfare/welfare2.png', count: 3, points: 200, selected: false},
+					{image: '/static/welfare/welfare3.png', count: 2, points: 200, selected: false},
+					{image: '/static/welfare/welfare4.png', count: 1, points: 200, selected: false},
+					{image: '/static/welfare/welfare5.png', count: 1, points: 200, selected: false},
+				]
+			}
+		},
+		methods: {
+			select(index) {
+				this.welfareList[index].selected = !this.welfareList[index].selected;
+				if (this.welfareList[index].selected) {
+					this.total += this.welfareList[index].count * this.welfareList[index].points;
+				} else {
+					this.total -= this.welfareList[index].count * this.welfareList[index].points;
+				}
+				let flag = true;
+				for (let item of this.welfareList) {
+					if (!item.selected) {
+						flag = false;
+					}
+				}
+				this.selectAllShow = flag;
+			},
+			selectAll() {
+				this.selectAllShow = !this.selectAllShow;
+				if (this.selectAllShow) {
+					for (let item of this.welfareList) {
+						if (!item.selected) {
+							this.total += item.count * item.points;
+						}	
+					}
+				} else {
+					for (let item of this.welfareList) {
+						this.total -= item.count * item.points;
+					}
+				}
+				for (let item of this.welfareList) {
+					if (this.selectAllShow) {
+						item.selected = true;
+					} else {
+					    item.selected = false;	
+					}
+				}
+			}
+		}
+	}
+</script>
+
+<style>
+	.title {
+		font-size: 32upx;
+		font-family: PingFang SC;
+		font-weight: 800;
+		color: #222222;
+		line-height: 36px;
+	}
+	.container {
+		margin: 20upx;
+		border-radius: 20upx;
+		background-color: #ffffff;
+	}
+</style>

+ 62 - 0
pages/mine/order/address.vue

@@ -0,0 +1,62 @@
+<template>
+	<view>
+		 <view class="container">
+			 <view class="flex align-center" style="padding: 20upx 30upx;">
+				 <view style="width: 160upx;font-family: PingFang SC;font-weight: bold;color: #000000;">收货人:</view>
+				 <u-input v-model="phone" placeholder="收货人手机号" :clearable="false" />
+			 </view>
+			 <view class="flex align-center" style="padding: 20upx 30upx;">
+				 <view style="width: 160upx;font-family: PingFang SC;font-weight: bold;color: #000000;">联系方式:</view>
+				 <u-input v-model="name" placeholder="收货人姓名" :clearable="false" />
+			 </view>
+			 <view class="flex align-center" style="padding: 20upx 30upx;" @click="regionShow = true">
+				<view style="width: 160upx;font-family: PingFang SC;font-weight: bold;color: #000000;">所在地区:</view>
+				<view class="flex align-center" :class="region.startsWith('例') ? 'eg': ''" style="height: 70upx;">
+					 {{region}}
+				</view>
+				<u-picker v-model="regionShow" mode="region" @confirm="getRegion"></u-picker>
+			 </view>
+			 <view class="flex align-center" style="padding: 20upx 30upx;">
+				<view style="width: 160upx;font-family: PingFang SC;font-weight: bold;color: #000000;">详细地址:</view>
+				<u-input v-model="address" placeholder="具体到门牌号" :clearable="false" />
+			 </view>
+		 </view>
+		 <view class="margin">
+			 <u-button class="custom-style" shape="circle">确定</u-button>
+		 </view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				name: '',
+				phone: '',
+				regionShow: false,
+				region: '例:广东省广州市天河区',
+				address: ''
+			}
+		},
+		methods: {
+			getRegion(data) {
+				this.region = data.province.label + '-' + data.city.label + '-' + data.area.label
+			}
+		}
+	}
+</script>
+
+<style>
+	.container {
+		background-color: #ffffff;
+		margin: 20upx;
+		border-radius: 16upx;
+	}
+	.eg {
+		color: #c0c4d6;
+	}
+	.custom-style {
+		background-color: #5b3ee7;
+		color: #ffffff;
+	}
+</style>

+ 154 - 0
pages/mine/order/orderConfirm.vue

@@ -0,0 +1,154 @@
+<template>
+	<view>
+		<view class="container flex align-center justify-between" @click="navTap">
+			<view class="flex padding align-center">
+				<image src="/static/address.png" style="width: 65upx;height: 65upx;"></image>
+				<view class="padding-left text-sm" v-if="writeAddress">
+					<view style="font-size: 28upx;font-family: PingFang SC;font-weight: 800;color: #000000;">赖德福 19849015150</view>
+					<view class="text-gray">广东省 广州市 荔湾区 新路街</view>
+				</view>
+				<view class="padding-left" style="font-size: 28upx;font-family: PingFang SC;font-weight: 800;color: #000000;" v-else>请选择收货地址</view>
+			</view>
+			<view class="padding">
+				<u-icon name="arrow-right" color="#d4d4d4"></u-icon>
+			</view>
+		</view>
+		<block v-for="(item, index) in giftList" :key="index">
+			<view class="card">
+				<view class="padding">
+					<view class="flex justify-between align-center padding-bottom-sm">
+						<view class="flex align-center">
+							<view class="cuIcon-goods padding-right-xs text-bold text-black" style="font-size: 40upx;"></view>
+							<view class="title">{{item.title}}</view>
+						</view>
+					</view>
+					<view class="flex margin-top-xs">
+						<image :src="item.image" style="width: 220upx;height: 220upx;"></image>
+						<view class="padding-left-sm">
+							<view class="name text-cut" style="width: 350upx;">{{item.name}}</view>
+							<view class="specification">
+								<view>{{item.specification}}</view>
+							</view>
+						</view>
+					</view>
+				</view>
+				<view class="flex justify-end padding" style="margin-top: -120upx;">
+					<view class="count">x{{item.count}}</view>
+				</view>
+			</view>
+		</block>
+		<view style="height: 120upx;"></view>
+		<view class="notice text-sm" v-if="giftList.length < 3 && count < 3">
+			提示:该礼包满3个包邮(不满3个运费需要用户自行承担)
+		</view>
+		<view class="footer-fixed flex justify-between align-center padding-sm bg-white">
+			<view v-if="giftList.length < 3 && count < 3">
+				快递配送  配送费¥8
+			</view>
+			<button class="cu-btn round text-white theme-bg-color" style="width: 180upx;height: 80upx;" @click="dialog">领取</button>
+		</view>
+		<u-popup v-model="dialogShow" mode="center" width="500" height="480" border-radius="30">
+			<view class="bg-img text-center" style="background-image: url('/static/dialogBgImg.png');height: 600rpx;">
+				<view style="height: 80upx;"></view>
+				<view style="font-size: 50upx;font-family: PingFang SC;font-weight: 600;color: #ffffff;">恭喜你</view>
+				<view class="text-bold text-black" style="padding: 80upx 0;">领取成功!请等待卖家发货</view>
+				<view class="padding">
+					<u-button class="custom-style" shape="circle" @click="onConfirm">确定</u-button>
+				</view>
+			</view>
+		</u-popup>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				dialogShow: false,
+				writeAddress: true,
+				count: 0,
+				giftList: [],
+			}
+		},
+		onLoad() {
+			this.giftList[0] = {image: '/static/gift/commodity2.png', title: 'lilbetter化妆品旗舰', name: 'Lilbetter发泥男士定型自然', specification: '发泥+洁面乳 120ml', count: 1, selected: true, status: '已完成'};
+			this.giftList[1] = {image: '/static/gift/commodity2.png', title: 'lilbetter化妆品旗舰', name: 'Lilbetter发泥男士定型自然', specification: '发泥+洁面乳 120ml', count: 1, selected: true, status: '已完成'};
+			for (let item of this.giftList) {
+				this.count += item.count;
+			}
+		},
+		methods: {
+			dialog() {
+				this.dialogShow = true;
+			},
+			onConfirm() {
+				this.dialogShow = false;
+				uni.navigateBack({
+					delta: 1
+				})
+			},
+			navTap() {
+				uni.navigateTo({
+					url: "/pages/mine/order/address"
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.card {
+		margin: 20upx;
+		border-radius: 16upx;
+		background-color: #FFFFFF;
+		.title {
+			font-size: 28upx;
+			font-family: PingFang SC;
+			font-weight: 800;
+			color: #222222;
+		}
+		.name {
+			font-size: 26upx;
+			font-family: PingFang SC;
+			font-weight: 800;
+			color: #222222;
+		}
+		.specification {
+			padding-top: 30upx;
+			font-size: 24upx;
+			font-family: PingFang SC;
+			font-weight: bold;
+			color: #959595;
+		}
+		.count {
+			width: 60upx;
+			height: 60upx;
+			border: #d9d9d9 1upx solid;
+			border-radius: 16upx;
+			display: flex;
+			align-items: center;
+			justify-content: center;
+		}
+	}
+	.container {
+		background-color: #ffffff;
+		border-radius: 16upx;
+		margin: 20upx;
+	}
+	.notice {
+		position: fixed;
+		width: 100%;
+		z-index: 10000;
+		bottom: 120upx;
+		left: 0;
+		line-height: 80upx;
+		text-align: center;
+		background-color: #fdedee;
+		color: #ff0000;
+	}
+	.custom-style {
+		background-color: #5b3ee7;
+		width: 250upx;
+		color: #ffffff;
+	}
+</style>

+ 69 - 0
pages/mine/pointsDetail.vue

@@ -0,0 +1,69 @@
+<template>
+	<view>
+		<view class="bg-img flex justify-center align-center" style="background-image: url('/static/bgimg.png');height: 310upx;">
+			<view class="text-center" style="margin-top: 80upx;">
+				<view style="font-size: 24upx;font-family: PingFang SC;font-weight: 400;color: #cfc8f9;">可用积分</view>
+				<view style="font-size: 54upx;font-family: PingFang SC;font-weight: 800;color: #ffffff;">205</view>
+			</view>
+		</view>
+		<block v-for="(item, index) in pointsList" :key="index">
+			<view class="flex justify-between align-center container">
+				<view class="padding">
+					<view class="type">{{item.type}}</view>
+					<view class="time">{{item.time}}</view>
+				</view>
+				<view class="padding">
+					<view class="points">{{item.points}} 积分</view>
+				</view>
+			</view>
+		</block>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				pointsList: [
+					{type: '每日签到', time: '2021-05-18 9:39', points: '+1'},
+					{type: '立白助力礼包', time: '2021-05-18 9:39', points: '+168'},
+					{type: '积分消费', time: '2021-05-18 9:39', points: '-80'},
+					{type: '每日签到', time: '2021-05-18 9:39', points: '+1'},
+					{type: '每日签到', time: '2021-05-18 9:39', points: '+1'},
+					{type: '每日签到', time: '2021-05-18 9:39', points: '+1'},
+					{type: '每日签到', time: '2021-05-18 9:39', points: '+1'}
+				]
+			}
+		},
+		methods: {
+			
+		}
+	}
+</script>
+
+<style>
+	.container {
+		background-color: #FFFFFF;
+		border-radius: 10upx;
+		margin: 20upx;
+	}
+	.type {
+		font-size: 32upx;
+		font-family: PingFang SC;
+		font-weight: bold;
+		margin-bottom: 20upx;
+		color: #111111;
+	}
+	.time {
+		font-size: 24upx;
+		font-family: PingFang SC;
+		font-weight: bold;
+		color: #9E9E9E;
+	}
+	.points {
+		font-size: 28upx;
+		font-family: PingFang SC;
+		font-weight: bold;
+		color: #111111;
+	}
+</style>

BIN
static/1.png


BIN
static/2.png


BIN
static/3.png


BIN
static/activity.png


BIN
static/address.png


BIN
static/avatar.png


BIN
static/avatar2.png


BIN
static/bgimg.png


BIN
static/crown.png


BIN
static/dialogBgImg.png


BIN
static/gift/commodity1.png


BIN
static/gift/commodity2.png


BIN
static/gift/commodity3.png


BIN
static/gift/commodity4.png


BIN
static/hot.png


BIN
static/icon-activity.png


BIN
static/icon-awards.png


BIN
static/icon-gift.png


BIN
static/icon-history.png


BIN
static/icon-lottery.png


BIN
static/icon-mall.png


BIN
static/icon-music.png


BIN
static/icon-order.png


BIN
static/icon-person.png


BIN
static/icon-points.png


BIN
static/icon-rule.png


BIN
static/icon-vip.png


BIN
static/icon-welfare.png


BIN
static/index/finish.png


BIN
static/index/fire.png


BIN
static/index/huodong1.png


BIN
static/index/huodong2x.png


BIN
static/index/ing.png


BIN
static/index/swiper.png


BIN
static/long.png


BIN
static/more.png


BIN
static/musicCover.png


BIN
static/personBgImg.png


BIN
static/present1.png


BIN
static/present2.png


BIN
static/present3.png


BIN
static/present4.png


BIN
static/signUp.png


BIN
static/singerBg.png


BIN
static/song.png


BIN
static/songRank/fm1.png


BIN
static/songRank/fm2.png


BIN
static/songRank/fm3.png


BIN
static/songRank/fm4.png


BIN
static/songRank/medal.png


BIN
static/songRank/songRankBgImg.png


BIN
static/swiper1.png


BIN
static/userBgImg.png


BIN
static/welfare/welfare1.png


BIN
static/welfare/welfare2.png


BIN
static/welfare/welfare3.png


BIN
static/welfare/welfare4.png


BIN
static/welfare/welfare5.png


+ 77 - 0
uni.scss

@@ -0,0 +1,77 @@
+/**
+ * 这里是uni-app内置的常用样式变量
+ *
+ * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
+ * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
+ *
+ */
+
+/**
+ * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
+ *
+ * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
+ */
+
+/* 颜色变量 */
+@import "uview-ui/theme.scss";
+
+/* 行为相关颜色 */
+$uni-color-primary: #007aff;
+$uni-color-success: #4cd964;
+$uni-color-warning: #f0ad4e;
+$uni-color-error: #dd524d;
+
+/* 文字基本颜色 */
+$uni-text-color:#333;//基本色
+$uni-text-color-inverse:#fff;//反色
+$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息
+$uni-text-color-placeholder: #808080;
+$uni-text-color-disable:#c0c0c0;
+
+/* 背景颜色 */
+$uni-bg-color:#ffffff;
+$uni-bg-color-grey:#f8f8f8;
+$uni-bg-color-hover:#f1f1f1;//点击状态颜色
+$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色
+
+/* 边框颜色 */
+$uni-border-color:#c8c7cc;
+
+/* 尺寸变量 */
+
+/* 文字尺寸 */
+$uni-font-size-sm:24rpx;
+$uni-font-size-base:28rpx;
+$uni-font-size-lg:32rpx;
+
+/* 图片尺寸 */
+$uni-img-size-sm:40rpx;
+$uni-img-size-base:52rpx;
+$uni-img-size-lg:80rpx;
+
+/* Border Radius */
+$uni-border-radius-sm: 4rpx;
+$uni-border-radius-base: 6rpx;
+$uni-border-radius-lg: 12rpx;
+$uni-border-radius-circle: 50%;
+
+/* 水平间距 */
+$uni-spacing-row-sm: 10px;
+$uni-spacing-row-base: 20rpx;
+$uni-spacing-row-lg: 30rpx;
+
+/* 垂直间距 */
+$uni-spacing-col-sm: 8rpx;
+$uni-spacing-col-base: 16rpx;
+$uni-spacing-col-lg: 24rpx;
+
+/* 透明度 */
+$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
+
+/* 文章场景相关 */
+$uni-color-title: #2C405A; // 文章标题颜色
+$uni-font-size-title:40rpx;
+$uni-color-subtitle: #555555; // 二级标题颜色
+$uni-font-size-subtitle:36rpx;
+$uni-color-paragraph: #3F536E; // 文章段落颜色
+$uni-font-size-paragraph:30rpx;

+ 21 - 0
uview-ui/LICENSE

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

+ 106 - 0
uview-ui/README.md

@@ -0,0 +1,106 @@
+<p align="center">
+    <img alt="logo" src="https://uviewui.com/common/logo.png" width="120" height="120" style="margin-bottom: 10px;">
+</p>
+<h3 align="center" style="margin: 30px 0 30px;font-weight: bold;font-size:40px;">uView</h3>
+<h3 align="center">多平台快速开发的UI框架</h3>
+
+
+## 说明
+
+uView UI,是[uni-app](https://uniapp.dcloud.io/)生态优秀的UI框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水
+
+## 特性
+
+- 兼容安卓,iOS,微信小程序,H5,QQ小程序,百度小程序,支付宝小程序,头条小程序
+- 60+精选组件,功能丰富,多端兼容,让您快速集成,开箱即用
+- 众多贴心的JS利器,让您飞镖在手,召之即来,百步穿杨
+- 众多的常用页面和布局,让您专注逻辑,事半功倍
+- 详尽的文档支持,现代化的演示效果
+- 按需引入,精简打包体积
+
+
+## 安装
+
+```bash
+# npm方式安装
+npm i uview-ui
+```
+
+## 快速上手
+
+1. `main.js`引入uView库
+```js
+// main.js
+import uView from 'uview-ui';
+Vue.use(uView);
+```
+
+2. `App.vue`引入基础样式(注意style标签需声明scss属性支持)
+```css
+/* App.vue */
+<style lang="scss">
+@import "uview-ui/index.scss";
+</style>
+```
+
+3. `uni.scss`引入全局scss变量文件
+```css
+/* uni.scss */
+@import "uview-ui/theme.scss";
+```
+
+4. `pages.json`配置easycom规则(按需引入)
+
+```js
+// pages.json
+{
+	"easycom": {
+		// npm安装的方式不需要前面的"@/",下载安装的方式需要"@/"
+		// npm安装方式
+		"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue"
+		// 下载安装方式
+		// "^u-(.*)": "@/uview-ui/components/u-$1/u-$1.vue"
+	},
+	// 此为本身已有的内容
+	"pages": [
+		// ......
+	]
+}
+```
+
+请通过[快速上手](https://uviewui.com/components/quickstart.html)了解更详细的内容 
+
+## 使用方法
+配置easycom规则后,自动按需引入,无需`import`组件,直接引用即可。
+
+```html
+<template>
+	<u-button>按钮</u-button>
+</template>
+```
+
+请通过[快速上手](https://uviewui.com/components/quickstart.html)了解更详细的内容 
+
+## 链接
+
+- [官方文档](https://uviewui.com/)
+- [更新日志](https://uviewui.com/components/changelog.html)
+- [升级指南](https://uviewui.com/components/changelog.html)
+- [关于我们](https://uviewui.com/cooperation/about.html)
+
+## 预览
+
+您可以通过**微信**扫码,查看最佳的演示效果。
+<br>
+<br>
+<img src="https://uviewui.com/common/weixin_mini_qrcode.png" width="220" height="220" >
+
+<!-- ## 捐赠uView的研发
+
+uView文档和源码全部开源免费,如果您认为uView帮到了您的开发工作,您可以捐赠uView的研发工作,捐赠无门槛,哪怕是一杯可乐也好(相信这比打赏主播更有意义)。
+
+<img src="https://uviewui.com/common/wechat.png" width="220" >
+<img style="margin-left: 100px;" src="https://uviewui.com/common/alipay.png" width="220" >
+ -->
+## 版权信息
+uView遵循[MIT](https://en.wikipedia.org/wiki/MIT_License)开源协议,意味着您无需支付任何费用,也无需授权,即可将uView应用到您的产品中。

+ 190 - 0
uview-ui/components/u-action-sheet/u-action-sheet.vue

@@ -0,0 +1,190 @@
+<template>
+	<u-popup mode="bottom" :border-radius="borderRadius" :popup="false" v-model="value" :maskCloseAble="maskCloseAble"
+	    length="auto" :safeAreaInsetBottom="safeAreaInsetBottom" @close="popupClose" :z-index="uZIndex">
+		<view class="u-tips u-border-bottom" v-if="tips.text" :style="[tipsStyle]">
+			{{tips.text}}
+		</view>
+		<block v-for="(item, index) in list" :key="index">
+			<view 
+				@touchmove.stop.prevent 
+				@tap="itemClick(index)" 
+				:style="[itemStyle(index)]" 
+				class="u-action-sheet-item u-line-1" 
+				:class="[index < list.length - 1 ? 'u-border-bottom' : '']"
+				:hover-stay-time="150"
+			>
+				<text>{{item.text}}</text>
+				<text class="u-action-sheet-item__subtext u-line-1" v-if="item.subText">{{item.subText}}</text>
+			</view>
+		</block>
+		<view class="u-gab" v-if="cancelBtn">
+		</view>
+		<view @touchmove.stop.prevent class="u-actionsheet-cancel u-action-sheet-item" hover-class="u-hover-class"
+		    :hover-stay-time="150" v-if="cancelBtn" @tap="close">{{cancelText}}</view>
+	</u-popup>
+</template>
+
+<script>
+	/**
+	 * actionSheet 操作菜单
+	 * @description 本组件用于从底部弹出一个操作菜单,供用户选择并返回结果。本组件功能类似于uni的uni.showActionSheetAPI,配置更加灵活,所有平台都表现一致。
+	 * @tutorial https://www.uviewui.com/components/actionSheet.html
+	 * @property {Array<Object>} list 按钮的文字数组,见官方文档示例
+	 * @property {Object} tips 顶部的提示文字,见官方文档示例
+	 * @property {String} cancel-text 取消按钮的提示文字
+	 * @property {Boolean} cancel-btn 是否显示底部的取消按钮(默认true)
+	 * @property {Number String} border-radius 弹出部分顶部左右的圆角值,单位rpx(默认0)
+	 * @property {Boolean} mask-close-able 点击遮罩是否可以关闭(默认true)
+	 * @property {Boolean} safe-area-inset-bottom 是否开启底部安全区适配(默认false)
+	 * @property {Number String} z-index z-index值(默认1075)
+	 * @property {String} cancel-text 取消按钮的提示文字
+	 * @event {Function} click 点击ActionSheet列表项时触发
+	 * @event {Function} close 点击取消按钮时触发
+	 * @example <u-action-sheet :list="list" @click="click" v-model="show"></u-action-sheet>
+	 */
+	export default {
+		name: "u-action-sheet",
+		props: {
+			// 点击遮罩是否可以关闭actionsheet
+			maskCloseAble: {
+				type: Boolean,
+				default: true
+			},
+			// 按钮的文字数组,可以自定义颜色和字体大小,字体单位为rpx
+			list: {
+				type: Array,
+				default () {
+					// 如下
+					// return [{
+					// 	text: '确定',
+					// 	color: '',
+					// 	fontSize: ''
+					// }]
+					return [];
+				}
+			},
+			// 顶部的提示文字
+			tips: {
+				type: Object,
+				default () {
+					return {
+						text: '',
+						color: '',
+						fontSize: '26'
+					}
+				}
+			},
+			// 底部的取消按钮
+			cancelBtn: {
+				type: Boolean,
+				default: true
+			},
+			// 是否开启底部安全区适配,开启的话,会在iPhoneX机型底部添加一定的内边距
+			safeAreaInsetBottom: {
+				type: Boolean,
+				default: false
+			},
+			// 通过双向绑定控制组件的弹出与收起
+			value: {
+				type: Boolean,
+				default: false
+			},
+			// 弹出的顶部圆角值
+			borderRadius: {
+				type: [String, Number],
+				default: 0
+			},
+			// 弹出的z-index值
+			zIndex: {
+				type: [String, Number],
+				default: 0
+			},
+			// 取消按钮的文字提示
+			cancelText: {
+				type: String,
+				default: '取消'
+			}
+		},
+		computed: {
+			// 顶部提示的样式
+			tipsStyle() {
+				let style = {};
+				if (this.tips.color) style.color = this.tips.color;
+				if (this.tips.fontSize) style.fontSize = this.tips.fontSize + 'rpx';
+				return style;
+			},
+			// 操作项目的样式
+			itemStyle() {
+				return (index) => {
+					let style = {};
+					if (this.list[index].color) style.color = this.list[index].color;
+					if (this.list[index].fontSize) style.fontSize = this.list[index].fontSize + 'rpx';
+					// 选项被禁用的样式
+					if (this.list[index].disabled) style.color = '#c0c4cc';
+					return style;
+				}
+			},
+			uZIndex() {
+				// 如果用户有传递z-index值,优先使用
+				return this.zIndex ? this.zIndex : this.$u.zIndex.popup;
+			}
+		},
+		methods: {
+			// 点击取消按钮
+			close() {
+				// 发送input事件,并不会作用于父组件,而是要设置组件内部通过props传递的value参数
+				// 这是一个vue发送事件的特殊用法
+				this.popupClose();
+				this.$emit('close');
+			},
+			// 弹窗关闭
+			popupClose() {
+				this.$emit('input', false);
+			},
+			// 点击某一个item
+			itemClick(index) {
+				// disabled的项禁止点击
+				if(this.list[index].disabled) return;
+				this.$emit('click', index);
+				this.$emit('input', false);
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	@import "../../libs/css/style.components.scss";
+
+	.u-tips {
+		font-size: 26rpx;
+		text-align: center;
+		padding: 34rpx 0;
+		line-height: 1;
+		color: $u-tips-color;
+	}
+
+	.u-action-sheet-item {
+		@include vue-flex;;
+		line-height: 1;
+		justify-content: center;
+		align-items: center;
+		font-size: 32rpx;
+		padding: 34rpx 0;
+		flex-direction: column;
+	}
+	
+	.u-action-sheet-item__subtext {
+		font-size: 24rpx;
+		color: $u-tips-color;
+		margin-top: 20rpx;
+	}
+
+	.u-gab {
+		height: 12rpx;
+		background-color: rgb(234, 234, 236);
+	}
+
+	.u-actionsheet-cancel {
+		color: $u-main-color;
+	}
+</style>

+ 256 - 0
uview-ui/components/u-alert-tips/u-alert-tips.vue

@@ -0,0 +1,256 @@
+<template>
+	<view class="u-alert-tips" v-if="show" :class="[
+		!show ? 'u-close-alert-tips': '',
+		type ? 'u-alert-tips--bg--' + type + '-light' : '',
+		type ? 'u-alert-tips--border--' + type + '-disabled' : '',
+	]" :style="{
+		backgroundColor: bgColor,
+		borderColor: borderColor
+	}">
+		<view class="u-icon-wrap">
+			<u-icon v-if="showIcon" :name="uIcon" :size="description ? 40 : 32" class="u-icon" :color="uIconType" :custom-style="iconStyle"></u-icon>
+		</view>
+		<view class="u-alert-content" @tap.stop="click">
+			<view class="u-alert-title" :style="[uTitleStyle]">
+				{{title}}
+			</view>
+			<view v-if="description" class="u-alert-desc" :style="[descStyle]">
+				{{description}}
+			</view>
+		</view>
+		<view class="u-icon-wrap">
+			<u-icon @click="close" v-if="closeAble && !closeText" hoverClass="u-type-error-hover-color" name="close" color="#c0c4cc"
+			 :size="22" class="u-close-icon" :style="{
+				top: description ? '18rpx' : '24rpx'
+			}"></u-icon>
+		</view>
+		<text v-if="closeAble && closeText" class="u-close-text" :style="{
+			top: description ? '18rpx' : '24rpx'
+		}">{{closeText}}</text>
+	</view>
+</template>
+
+<script>
+	/**
+	 * alertTips 警告提示
+	 * @description 警告提示,展现需要关注的信息
+	 * @tutorial https://uviewui.com/components/alertTips.html
+	 * @property {String} title 显示的标题文字
+	 * @property {String} description 辅助性文字,颜色比title浅一点,字号也小一点,可选
+	 * @property {String} type 关闭按钮(默认为叉号icon图标)
+	 * @property {String} icon 图标名称
+	 * @property {Object} icon-style 图标的样式,对象形式
+	 * @property {Object} title-style 标题的样式,对象形式
+	 * @property {Object} desc-style 描述的样式,对象形式
+	 * @property {String} close-able 用文字替代关闭图标,close-able为true时有效
+	 * @property {Boolean} show-icon 是否显示左边的辅助图标
+	 * @property {Boolean} show 显示或隐藏组件
+	 * @event {Function} click 点击组件时触发
+	 * @event {Function} close 点击关闭按钮时触发
+	 */
+	export default {
+		name: 'u-alert-tips',
+		props: {
+			// 显示文字
+			title: {
+				type: String,
+				default: ''
+			},
+			// 主题,success/warning/info/error
+			type: {
+				type: String,
+				default: 'warning'
+			},
+			// 辅助性文字
+			description: {
+				type: String,
+				default: ''
+			},
+			// 是否可关闭
+			closeAble: {
+				type: Boolean,
+				default: false
+			},
+			// 关闭按钮自定义文本
+			closeText: {
+				type: String,
+				default: ''
+			},
+			// 是否显示图标
+			showIcon: {
+				type: Boolean,
+				default: false
+			},
+			// 文字颜色,如果定义了color值,icon会失效
+			color: {
+				type: String,
+				default: ''
+			},
+			// 背景颜色
+			bgColor: {
+				type: String,
+				default: ''
+			},
+			// 边框颜色
+			borderColor: {
+				type: String,
+				default: ''
+			},
+			// 是否显示
+			show: {
+				type: Boolean,
+				default: true
+			},
+			// 左边显示的icon
+			icon: {
+				type: String,
+				default: ''
+			},
+			// icon的样式
+			iconStyle: {
+				type: Object,
+				default() {
+					return {}
+				}
+			},
+			// 标题的样式
+			titleStyle: {
+				type: Object,
+				default() {
+					return {}
+				}
+			},
+			// 描述文字的样式
+			descStyle: {
+				type: Object,
+				default() {
+					return {}
+				}
+			},
+		},
+		data() {
+			return {
+			}
+		},
+		computed: {
+			uTitleStyle() {
+				let style = {};
+				// 如果有描述文字的话,标题进行加粗
+				style.fontWeight = this.description ? 500 : 'normal';
+				// 将用户传入样式对象和style合并,传入的优先级比style高,同属性会被覆盖
+				return this.$u.deepMerge(style, this.titleStyle);
+			},
+			uIcon() {
+				// 如果有设置icon名称就使用,否则根据type主题,推定一个默认的图标
+				return this.icon ? this.icon : this.$u.type2icon(this.type);
+			},
+			uIconType() {
+				// 如果有设置图标的样式,优先使用,没有的话,则用type的样式
+				return Object.keys(this.iconStyle).length ? '' : this.type;
+			}
+		},
+		methods: {
+			// 点击内容
+			click() {
+				this.$emit('click');
+			},
+			// 点击关闭按钮
+			close() {
+				this.$emit('close');
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	@import "../../libs/css/style.components.scss";
+	
+	.u-alert-tips {
+		@include vue-flex;
+		align-items: center;
+		padding: 16rpx 30rpx;
+		border-radius: 8rpx;
+		position: relative;
+		transition: all 0.3s linear;
+		border: 1px solid #fff;
+		
+		&--bg--primary-light {
+			background-color: $u-type-primary-light;
+		}
+		
+		&--bg--info-light {
+			background-color: $u-type-info-light;
+		}
+		
+		&--bg--success-light {
+			background-color: $u-type-success-light;
+		}
+		
+		&--bg--warning-light {
+			background-color: $u-type-warning-light;
+		}
+		
+		&--bg--error-light {
+			background-color: $u-type-error-light;
+		}
+		
+		&--border--primary-disabled {
+			border-color: $u-type-primary-disabled;
+		}
+		
+		&--border--success-disabled {
+			border-color: $u-type-success-disabled;
+		}
+		
+		&--border--error-disabled {
+			border-color: $u-type-error-disabled;
+		}
+		
+		&--border--warning-disabled {
+			border-color: $u-type-warning-disabled;
+		}
+		
+		&--border--info-disabled {
+			border-color: $u-type-info-disabled;
+		}
+	}
+
+	.u-close-alert-tips {
+		opacity: 0;
+		visibility: hidden;
+	}
+
+	.u-icon {
+		margin-right: 16rpx;
+	}
+
+	.u-alert-title {
+		font-size: 28rpx;
+		color: $u-main-color;
+	}
+
+	.u-alert-desc {
+		font-size: 26rpx;
+		text-align: left;
+		color: $u-content-color;
+	}
+
+	.u-close-icon {
+		position: absolute;
+		top: 20rpx;
+		right: 20rpx;
+	}
+
+	.u-close-hover {
+		color: red;
+	}
+	
+	.u-close-text {
+		font-size: 24rpx;
+		color: $u-tips-color;
+		position: absolute;
+		top: 20rpx;
+		right: 20rpx;
+		line-height: 1;
+	}
+</style>

+ 290 - 0
uview-ui/components/u-avatar-cropper/u-avatar-cropper.vue

@@ -0,0 +1,290 @@
+<template>
+	<view class="content">
+		<view class="cropper-wrapper" :style="{ height: cropperOpt.height + 'px' }">
+			<canvas
+				class="cropper"
+				:disable-scroll="true"
+				@touchstart="touchStart"
+				@touchmove="touchMove"
+				@touchend="touchEnd"
+				:style="{ width: cropperOpt.width, height: cropperOpt.height, backgroundColor: 'rgba(0, 0, 0, 0.8)' }"
+				canvas-id="cropper"
+				id="cropper"
+			></canvas>
+			<canvas
+				class="cropper"
+				:disable-scroll="true"
+				:style="{
+					position: 'fixed',
+					top: `-${cropperOpt.width * cropperOpt.pixelRatio}px`,
+					left: `-${cropperOpt.height * cropperOpt.pixelRatio}px`,
+					width: `${cropperOpt.width * cropperOpt.pixelRatio}px`,
+					height: `${cropperOpt.height * cropperOpt.pixelRatio}`
+				}"
+				canvas-id="targetId"
+				id="targetId"
+			></canvas>
+		</view>
+		<view class="cropper-buttons safe-area-padding" :style="{ height: bottomNavHeight + 'px' }">
+			<!-- #ifdef H5 -->
+			<view class="upload" @tap="uploadTap">选择图片</view>
+			<!-- #endif -->
+			<!-- #ifndef H5 -->
+			<view class="upload" @tap="uploadTap">重新选择</view>
+			<!-- #endif -->
+			<view class="getCropperImage" @tap="getCropperImage(false)">确定</view>
+		</view>
+	</view>
+</template>
+
+<script>
+import WeCropper from './weCropper.js';
+export default {
+	props: {
+		// 裁剪矩形框的样式,其中可包含的属性为lineWidth-边框宽度(单位rpx),color: 边框颜色,
+		// mask-遮罩颜色,一般设置为一个rgba的透明度,如"rgba(0, 0, 0, 0.35)"
+		boundStyle: {
+			type: Object,
+			default() {
+				return {
+					lineWidth: 4,
+					borderColor: 'rgb(245, 245, 245)',
+					mask: 'rgba(0, 0, 0, 0.35)'
+				};
+			}
+		}
+		// // 裁剪框宽度,单位rpx
+		// rectWidth: {
+		// 	type: [String, Number],
+		// 	default: 400
+		// },
+		// // 裁剪框高度,单位rpx
+		// rectHeight: {
+		// 	type: [String, Number],
+		// 	default: 400
+		// },
+		// // 输出图片宽度,单位rpx
+		// destWidth: {
+		// 	type: [String, Number],
+		// 	default: 400
+		// },
+		// // 输出图片高度,单位rpx
+		// destHeight: {
+		// 	type: [String, Number],
+		// 	default: 400
+		// },
+		// // 输出的图片类型,如果发现裁剪的图片很大,可能是因为设置为了"png",改成"jpg"即可
+		// fileType: {
+		// 	type: String,
+		// 	default: 'jpg',
+		// },
+		// // 生成的图片质量
+		// // H5上无效,目前不考虑使用此参数
+		// quality: {
+		// 	type: [Number, String],
+		// 	default: 1
+		// }
+	},
+	data() {
+		return {
+			// 底部导航的高度
+			bottomNavHeight: 50,
+			originWidth: 200,
+			width: 0,
+			height: 0,
+			cropperOpt: {
+				id: 'cropper',
+				targetId: 'targetCropper',
+				pixelRatio: 1,
+				width: 0,
+				height: 0,
+				scale: 2.5,
+				zoom: 8,
+				cut: {
+					x: (this.width - this.originWidth) / 2,
+					y: (this.height - this.originWidth) / 2,
+					width: this.originWidth,
+					height: this.originWidth
+				},
+				boundStyle: {
+					lineWidth: uni.upx2px(this.boundStyle.lineWidth),
+					mask: this.boundStyle.mask,
+					color: this.boundStyle.borderColor
+				}
+			},
+			// 裁剪框和输出图片的尺寸,高度默认等于宽度
+			// 输出图片宽度,单位px
+			destWidth: 200,
+			// 裁剪框宽度,单位px
+			rectWidth: 200,
+			// 输出的图片类型,如果'png'类型发现裁剪的图片太大,改成"jpg"即可
+			fileType: 'jpg',
+			src: '', // 选择的图片路径,用于在点击确定时,判断是否选择了图片
+		};
+	},
+	onLoad(option) {
+		let rectInfo = uni.getSystemInfoSync();
+		this.width = rectInfo.windowWidth;
+		this.height = rectInfo.windowHeight - this.bottomNavHeight;
+		this.cropperOpt.width = this.width;
+		this.cropperOpt.height = this.height;
+		this.cropperOpt.pixelRatio = rectInfo.pixelRatio;
+
+		if (option.destWidth) this.destWidth = option.destWidth;
+		if (option.rectWidth) {
+			let rectWidth = Number(option.rectWidth);
+			this.cropperOpt.cut = {
+				x: (this.width - rectWidth) / 2,
+				y: (this.height - rectWidth) / 2,
+				width: rectWidth,
+				height: rectWidth
+			};
+		}
+		this.rectWidth = option.rectWidth;
+		if (option.fileType) this.fileType = option.fileType;
+		// 初始化
+		this.cropper = new WeCropper(this.cropperOpt)
+			.on('ready', ctx => {
+				// wecropper is ready for work!
+			})
+			.on('beforeImageLoad', ctx => {
+				// before picture loaded, i can do something
+			})
+			.on('imageLoad', ctx => {
+				// picture loaded
+			})
+			.on('beforeDraw', (ctx, instance) => {
+				// before canvas draw,i can do something
+			});
+		// 设置导航栏样式,以免用户在page.json中没有设置为黑色背景
+		uni.setNavigationBarColor({
+			frontColor: '#ffffff',
+			backgroundColor: '#000000'
+		});
+		uni.chooseImage({
+			count: 1, // 默认9
+			sizeType: ['compressed'], // 可以指定是原图还是压缩图,默认二者都有
+			sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
+			success: res => {
+				this.src = res.tempFilePaths[0];
+				//  获取裁剪图片资源后,给data添加src属性及其值
+				this.cropper.pushOrign(this.src);
+			}
+		});
+	},
+	methods: {
+		touchStart(e) {
+			this.cropper.touchStart(e);
+		},
+		touchMove(e) {
+			this.cropper.touchMove(e);
+		},
+		touchEnd(e) {
+			this.cropper.touchEnd(e);
+		},
+		getCropperImage(isPre = false) {
+			if(!this.src) return this.$u.toast('请先选择图片再裁剪');
+
+			let cropper_opt = {
+				destHeight: Number(this.destWidth), // uni.canvasToTempFilePath要求这些参数为数值
+				destWidth: Number(this.destWidth),
+				fileType: this.fileType
+			};
+			this.cropper.getCropperImage(cropper_opt, (path, err) => {
+				if (err) {
+					uni.showModal({
+						title: '温馨提示',
+						content: err.message
+					});
+				} else {
+					if (isPre) {
+						uni.previewImage({
+							current: '', // 当前显示图片的 http 链接
+							urls: [path] // 需要预览的图片 http 链接列表
+						});
+					} else {
+						uni.$emit('uAvatarCropper', path);
+						this.$u.route({
+							type: 'back'
+						});
+					}
+				}
+			});
+		},
+		uploadTap() {
+			const self = this;
+			uni.chooseImage({
+				count: 1, // 默认9
+				sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
+				sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
+				success: (res) => {
+					self.src = res.tempFilePaths[0];
+					//  获取裁剪图片资源后,给data添加src属性及其值
+
+					self.cropper.pushOrign(this.src);
+				}
+			});
+		}
+	}
+};
+</script>
+
+<style scoped lang="scss">
+@import '../../libs/css/style.components.scss';
+
+.content {
+	background: rgba(255, 255, 255, 1);
+}
+
+.cropper {
+	position: absolute;
+	top: 0;
+	left: 0;
+	width: 100%;
+	height: 100%;
+	z-index: 11;
+}
+
+.cropper-buttons {
+	background-color: #000000;
+	color: #eee;
+}
+
+.cropper-wrapper {
+	position: relative;
+	@include vue-flex;
+	flex-direction: row;
+	justify-content: space-between;
+	align-items: center;
+	width: 100%;
+	background-color: #000;
+}
+
+.cropper-buttons {
+	width: 100vw;
+	@include vue-flex;
+	flex-direction: row;
+	justify-content: space-between;
+	align-items: center;
+	position: fixed;
+	bottom: 0;
+	left: 0;
+	font-size: 28rpx;
+}
+
+.cropper-buttons .upload,
+.cropper-buttons .getCropperImage {
+	width: 50%;
+	text-align: center;
+}
+
+.cropper-buttons .upload {
+	text-align: left;
+	padding-left: 50rpx;
+}
+
+.cropper-buttons .getCropperImage {
+	text-align: right;
+	padding-right: 50rpx;
+}
+</style>

+ 1265 - 0
uview-ui/components/u-avatar-cropper/weCropper.js

@@ -0,0 +1,1265 @@
+/**
+ * we-cropper v1.3.9
+ * (c) 2020 dlhandsome
+ * @license MIT
+ */
+(function(global, factory) {
+	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+		typeof define === 'function' && define.amd ? define(factory) :
+		(global.WeCropper = factory());
+}(this, (function() {
+	'use strict';
+
+	var device = void 0;
+	var TOUCH_STATE = ['touchstarted', 'touchmoved', 'touchended'];
+
+	function firstLetterUpper(str) {
+		return str.charAt(0).toUpperCase() + str.slice(1)
+	}
+
+	function setTouchState(instance) {
+		var arg = [],
+			len = arguments.length - 1;
+		while (len-- > 0) arg[len] = arguments[len + 1];
+
+		TOUCH_STATE.forEach(function(key, i) {
+			if (arg[i] !== undefined) {
+				instance[key] = arg[i];
+			}
+		});
+	}
+
+	function validator(instance, o) {
+		Object.defineProperties(instance, o);
+	}
+
+	function getDevice() {
+		if (!device) {
+			device = uni.getSystemInfoSync();
+		}
+		return device
+	}
+
+	var tmp = {};
+
+	var ref = getDevice();
+	var pixelRatio = ref.pixelRatio;
+
+	var DEFAULT = {
+		id: {
+			default: 'cropper',
+			get: function get() {
+				return tmp.id
+			},
+			set: function set(value) {
+				if (typeof(value) !== 'string') {
+					console.error(("id:" + value + " is invalid"));
+				}
+				tmp.id = value;
+			}
+		},
+		width: {
+			default: 750,
+			get: function get() {
+				return tmp.width
+			},
+			set: function set(value) {
+				if (typeof(value) !== 'number') {
+					console.error(("width:" + value + " is invalid"));
+				}
+				tmp.width = value;
+			}
+		},
+		height: {
+			default: 750,
+			get: function get() {
+				return tmp.height
+			},
+			set: function set(value) {
+				if (typeof(value) !== 'number') {
+					console.error(("height:" + value + " is invalid"));
+				}
+				tmp.height = value;
+			}
+		},
+		pixelRatio: {
+			default: pixelRatio,
+			get: function get() {
+				return tmp.pixelRatio
+			},
+			set: function set(value) {
+				if (typeof(value) !== 'number') {
+					console.error(("pixelRatio:" + value + " is invalid"));
+				}
+				tmp.pixelRatio = value;
+			}
+		},
+		scale: {
+			default: 2.5,
+			get: function get() {
+				return tmp.scale
+			},
+			set: function set(value) {
+				if (typeof(value) !== 'number') {
+					console.error(("scale:" + value + " is invalid"));
+				}
+				tmp.scale = value;
+			}
+		},
+		zoom: {
+			default: 5,
+			get: function get() {
+				return tmp.zoom
+			},
+			set: function set(value) {
+				if (typeof(value) !== 'number') {
+					console.error(("zoom:" + value + " is invalid"));
+				} else if (value < 0 || value > 10) {
+					console.error("zoom should be ranged in 0 ~ 10");
+				}
+				tmp.zoom = value;
+			}
+		},
+		src: {
+			default: '',
+			get: function get() {
+				return tmp.src
+			},
+			set: function set(value) {
+				if (typeof(value) !== 'string') {
+					console.error(("src:" + value + " is invalid"));
+				}
+				tmp.src = value;
+			}
+		},
+		cut: {
+			default: {},
+			get: function get() {
+				return tmp.cut
+			},
+			set: function set(value) {
+				if (typeof(value) !== 'object') {
+					console.error(("cut:" + value + " is invalid"));
+				}
+				tmp.cut = value;
+			}
+		},
+		boundStyle: {
+			default: {},
+			get: function get() {
+				return tmp.boundStyle
+			},
+			set: function set(value) {
+				if (typeof(value) !== 'object') {
+					console.error(("boundStyle:" + value + " is invalid"));
+				}
+				tmp.boundStyle = value;
+			}
+		},
+		onReady: {
+			default: null,
+			get: function get() {
+				return tmp.ready
+			},
+			set: function set(value) {
+				tmp.ready = value;
+			}
+		},
+		onBeforeImageLoad: {
+			default: null,
+			get: function get() {
+				return tmp.beforeImageLoad
+			},
+			set: function set(value) {
+				tmp.beforeImageLoad = value;
+			}
+		},
+		onImageLoad: {
+			default: null,
+			get: function get() {
+				return tmp.imageLoad
+			},
+			set: function set(value) {
+				tmp.imageLoad = value;
+			}
+		},
+		onBeforeDraw: {
+			default: null,
+			get: function get() {
+				return tmp.beforeDraw
+			},
+			set: function set(value) {
+				tmp.beforeDraw = value;
+			}
+		}
+	};
+
+	var ref$1 = getDevice();
+	var windowWidth = ref$1.windowWidth;
+
+	function prepare() {
+		var self = this;
+
+		// v1.4.0 版本中将不再自动绑定we-cropper实例
+		self.attachPage = function() {
+			var pages = getCurrentPages();
+			// 获取到当前page上下文
+			var pageContext = pages[pages.length - 1];
+			// 把this依附在Page上下文的wecropper属性上,便于在page钩子函数中访问
+			Object.defineProperty(pageContext, 'wecropper', {
+				get: function get() {
+					console.warn(
+						'Instance will not be automatically bound to the page after v1.4.0\n\n' +
+						'Please use a custom instance name instead\n\n' +
+						'Example: \n' +
+						'this.mycropper = new WeCropper(options)\n\n' +
+						'// ...\n' +
+						'this.mycropper.getCropperImage()'
+					);
+					return self
+				},
+				configurable: true
+			});
+		};
+
+		self.createCtx = function() {
+			var id = self.id;
+			var targetId = self.targetId;
+
+			if (id) {
+				self.ctx = self.ctx || uni.createCanvasContext(id);
+				self.targetCtx = self.targetCtx || uni.createCanvasContext(targetId);
+			} else {
+				console.error("constructor: create canvas context failed, 'id' must be valuable");
+			}
+		};
+
+		self.deviceRadio = windowWidth / 750;
+	}
+
+	var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !==
+		'undefined' ? self : {};
+
+
+
+
+
+	function createCommonjsModule(fn, module) {
+		return module = {
+			exports: {}
+		}, fn(module, module.exports), module.exports;
+	}
+
+	var tools = createCommonjsModule(function(module, exports) {
+		/**
+		 * String type check
+		 */
+		exports.isStr = function(v) {
+			return typeof v === 'string';
+		};
+		/**
+		 * Number type check
+		 */
+		exports.isNum = function(v) {
+			return typeof v === 'number';
+		};
+		/**
+		 * Array type check
+		 */
+		exports.isArr = Array.isArray;
+		/**
+		 * undefined type check
+		 */
+		exports.isUndef = function(v) {
+			return v === undefined;
+		};
+
+		exports.isTrue = function(v) {
+			return v === true;
+		};
+
+		exports.isFalse = function(v) {
+			return v === false;
+		};
+		/**
+		 * Function type check
+		 */
+		exports.isFunc = function(v) {
+			return typeof v === 'function';
+		};
+		/**
+		 * Quick object check - this is primarily used to tell
+		 * Objects from primitive values when we know the value
+		 * is a JSON-compliant type.
+		 */
+		exports.isObj = exports.isObject = function(obj) {
+			return obj !== null && typeof obj === 'object'
+		};
+
+		/**
+		 * Strict object type check. Only returns true
+		 * for plain JavaScript objects.
+		 */
+		var _toString = Object.prototype.toString;
+		exports.isPlainObject = function(obj) {
+			return _toString.call(obj) === '[object Object]'
+		};
+
+		/**
+		 * Check whether the object has the property.
+		 */
+		var hasOwnProperty = Object.prototype.hasOwnProperty;
+		exports.hasOwn = function(obj, key) {
+			return hasOwnProperty.call(obj, key)
+		};
+
+		/**
+		 * Perform no operation.
+		 * Stubbing args to make Flow happy without leaving useless transpiled code
+		 * with ...rest (https://flow.org/blog/2017/05/07/Strict-Function-Call-Arity/)
+		 */
+		exports.noop = function(a, b, c) {};
+
+		/**
+		 * Check if val is a valid array index.
+		 */
+		exports.isValidArrayIndex = function(val) {
+			var n = parseFloat(String(val));
+			return n >= 0 && Math.floor(n) === n && isFinite(val)
+		};
+	});
+
+	var tools_7 = tools.isFunc;
+	var tools_10 = tools.isPlainObject;
+
+	var EVENT_TYPE = ['ready', 'beforeImageLoad', 'beforeDraw', 'imageLoad'];
+
+	function observer() {
+		var self = this;
+
+		self.on = function(event, fn) {
+			if (EVENT_TYPE.indexOf(event) > -1) {
+				if (tools_7(fn)) {
+					event === 'ready' ?
+						fn(self) :
+						self[("on" + (firstLetterUpper(event)))] = fn;
+				}
+			} else {
+				console.error(("event: " + event + " is invalid"));
+			}
+			return self
+		};
+	}
+
+	function wxPromise(fn) {
+		return function(obj) {
+			var args = [],
+				len = arguments.length - 1;
+			while (len-- > 0) args[len] = arguments[len + 1];
+
+			if (obj === void 0) obj = {};
+			return new Promise(function(resolve, reject) {
+				obj.success = function(res) {
+					resolve(res);
+				};
+				obj.fail = function(err) {
+					reject(err);
+				};
+				fn.apply(void 0, [obj].concat(args));
+			})
+		}
+	}
+
+	function draw(ctx, reserve) {
+		if (reserve === void 0) reserve = false;
+
+		return new Promise(function(resolve) {
+			ctx.draw(reserve, resolve);
+		})
+	}
+
+	var getImageInfo = wxPromise(uni.getImageInfo);
+
+	var canvasToTempFilePath = wxPromise(uni.canvasToTempFilePath);
+
+	var base64 = createCommonjsModule(function(module, exports) {
+		/*! http://mths.be/base64 v0.1.0 by @mathias | MIT license */
+		(function(root) {
+
+			// Detect free variables `exports`.
+			var freeExports = 'object' == 'object' && exports;
+
+			// Detect free variable `module`.
+			var freeModule = 'object' == 'object' && module &&
+				module.exports == freeExports && module;
+
+			// Detect free variable `global`, from Node.js or Browserified code, and use
+			// it as `root`.
+			var freeGlobal = typeof commonjsGlobal == 'object' && commonjsGlobal;
+			if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
+				root = freeGlobal;
+			}
+
+			/*--------------------------------------------------------------------------*/
+
+			var InvalidCharacterError = function(message) {
+				this.message = message;
+			};
+			InvalidCharacterError.prototype = new Error;
+			InvalidCharacterError.prototype.name = 'InvalidCharacterError';
+
+			var error = function(message) {
+				// Note: the error messages used throughout this file match those used by
+				// the native `atob`/`btoa` implementation in Chromium.
+				throw new InvalidCharacterError(message);
+			};
+
+			var TABLE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+			// http://whatwg.org/html/common-microsyntaxes.html#space-character
+			var REGEX_SPACE_CHARACTERS = /[\t\n\f\r ]/g;
+
+			// `decode` is designed to be fully compatible with `atob` as described in the
+			// HTML Standard. http://whatwg.org/html/webappapis.html#dom-windowbase64-atob
+			// The optimized base64-decoding algorithm used is based on @atk’s excellent
+			// implementation. https://gist.github.com/atk/1020396
+			var decode = function(input) {
+				input = String(input)
+					.replace(REGEX_SPACE_CHARACTERS, '');
+				var length = input.length;
+				if (length % 4 == 0) {
+					input = input.replace(/==?$/, '');
+					length = input.length;
+				}
+				if (
+					length % 4 == 1 ||
+					// http://whatwg.org/C#alphanumeric-ascii-characters
+					/[^+a-zA-Z0-9/]/.test(input)
+				) {
+					error(
+						'Invalid character: the string to be decoded is not correctly encoded.'
+					);
+				}
+				var bitCounter = 0;
+				var bitStorage;
+				var buffer;
+				var output = '';
+				var position = -1;
+				while (++position < length) {
+					buffer = TABLE.indexOf(input.charAt(position));
+					bitStorage = bitCounter % 4 ? bitStorage * 64 + buffer : buffer;
+					// Unless this is the first of a group of 4 characters…
+					if (bitCounter++ % 4) {
+						// …convert the first 8 bits to a single ASCII character.
+						output += String.fromCharCode(
+							0xFF & bitStorage >> (-2 * bitCounter & 6)
+						);
+					}
+				}
+				return output;
+			};
+
+			// `encode` is designed to be fully compatible with `btoa` as described in the
+			// HTML Standard: http://whatwg.org/html/webappapis.html#dom-windowbase64-btoa
+			var encode = function(input) {
+				input = String(input);
+				if (/[^\0-\xFF]/.test(input)) {
+					// Note: no need to special-case astral symbols here, as surrogates are
+					// matched, and the input is supposed to only contain ASCII anyway.
+					error(
+						'The string to be encoded contains characters outside of the ' +
+						'Latin1 range.'
+					);
+				}
+				var padding = input.length % 3;
+				var output = '';
+				var position = -1;
+				var a;
+				var b;
+				var c;
+				var buffer;
+				// Make sure any padding is handled outside of the loop.
+				var length = input.length - padding;
+
+				while (++position < length) {
+					// Read three bytes, i.e. 24 bits.
+					a = input.charCodeAt(position) << 16;
+					b = input.charCodeAt(++position) << 8;
+					c = input.charCodeAt(++position);
+					buffer = a + b + c;
+					// Turn the 24 bits into four chunks of 6 bits each, and append the
+					// matching character for each of them to the output.
+					output += (
+						TABLE.charAt(buffer >> 18 & 0x3F) +
+						TABLE.charAt(buffer >> 12 & 0x3F) +
+						TABLE.charAt(buffer >> 6 & 0x3F) +
+						TABLE.charAt(buffer & 0x3F)
+					);
+				}
+
+				if (padding == 2) {
+					a = input.charCodeAt(position) << 8;
+					b = input.charCodeAt(++position);
+					buffer = a + b;
+					output += (
+						TABLE.charAt(buffer >> 10) +
+						TABLE.charAt((buffer >> 4) & 0x3F) +
+						TABLE.charAt((buffer << 2) & 0x3F) +
+						'='
+					);
+				} else if (padding == 1) {
+					buffer = input.charCodeAt(position);
+					output += (
+						TABLE.charAt(buffer >> 2) +
+						TABLE.charAt((buffer << 4) & 0x3F) +
+						'=='
+					);
+				}
+
+				return output;
+			};
+
+			var base64 = {
+				'encode': encode,
+				'decode': decode,
+				'version': '0.1.0'
+			};
+
+			// Some AMD build optimizers, like r.js, check for specific condition patterns
+			// like the following:
+			if (
+				typeof undefined == 'function' &&
+				typeof undefined.amd == 'object' &&
+				undefined.amd
+			) {
+				undefined(function() {
+					return base64;
+				});
+			} else if (freeExports && !freeExports.nodeType) {
+				if (freeModule) { // in Node.js or RingoJS v0.8.0+
+					freeModule.exports = base64;
+				} else { // in Narwhal or RingoJS v0.7.0-
+					for (var key in base64) {
+						base64.hasOwnProperty(key) && (freeExports[key] = base64[key]);
+					}
+				}
+			} else { // in Rhino or a web browser
+				root.base64 = base64;
+			}
+
+		}(commonjsGlobal));
+	});
+
+	function makeURI(strData, type) {
+		return 'data:' + type + ';base64,' + strData
+	}
+
+	function fixType(type) {
+		type = type.toLowerCase().replace(/jpg/i, 'jpeg');
+		var r = type.match(/png|jpeg|bmp|gif/)[0];
+		return 'image/' + r
+	}
+
+	function encodeData(data) {
+		var str = '';
+		if (typeof data === 'string') {
+			str = data;
+		} else {
+			for (var i = 0; i < data.length; i++) {
+				str += String.fromCharCode(data[i]);
+			}
+		}
+		return base64.encode(str)
+	}
+
+	/**
+	 * 获取图像区域隐含的像素数据
+	 * @param canvasId canvas标识
+	 * @param x 将要被提取的图像数据矩形区域的左上角 x 坐标
+	 * @param y 将要被提取的图像数据矩形区域的左上角 y 坐标
+	 * @param width 将要被提取的图像数据矩形区域的宽度
+	 * @param height 将要被提取的图像数据矩形区域的高度
+	 * @param done 完成回调
+	 */
+	function getImageData(canvasId, x, y, width, height, done) {
+		uni.canvasGetImageData({
+			canvasId: canvasId,
+			x: x,
+			y: y,
+			width: width,
+			height: height,
+			success: function success(res) {
+				done(res, null);
+			},
+			fail: function fail(res) {
+				done(null, res);
+			}
+		});
+	}
+
+	/**
+	 * 生成bmp格式图片
+	 * 按照规则生成图片响应头和响应体
+	 * @param oData 用来描述 canvas 区域隐含的像素数据 { data, width, height } = oData
+	 * @returns {*} base64字符串
+	 */
+	function genBitmapImage(oData) {
+		//
+		// BITMAPFILEHEADER: http://msdn.microsoft.com/en-us/library/windows/desktop/dd183374(v=vs.85).aspx
+		// BITMAPINFOHEADER: http://msdn.microsoft.com/en-us/library/dd183376.aspx
+		//
+		var biWidth = oData.width;
+		var biHeight = oData.height;
+		var biSizeImage = biWidth * biHeight * 3;
+		var bfSize = biSizeImage + 54; // total header size = 54 bytes
+
+		//
+		//  typedef struct tagBITMAPFILEHEADER {
+		//  	WORD bfType;
+		//  	DWORD bfSize;
+		//  	WORD bfReserved1;
+		//  	WORD bfReserved2;
+		//  	DWORD bfOffBits;
+		//  } BITMAPFILEHEADER;
+		//
+		var BITMAPFILEHEADER = [
+			// WORD bfType -- The file type signature; must be "BM"
+			0x42, 0x4D,
+			// DWORD bfSize -- The size, in bytes, of the bitmap file
+			bfSize & 0xff, bfSize >> 8 & 0xff, bfSize >> 16 & 0xff, bfSize >> 24 & 0xff,
+			// WORD bfReserved1 -- Reserved; must be zero
+			0, 0,
+			// WORD bfReserved2 -- Reserved; must be zero
+			0, 0,
+			// DWORD bfOffBits -- The offset, in bytes, from the beginning of the BITMAPFILEHEADER structure to the bitmap bits.
+			54, 0, 0, 0
+		];
+
+		//
+		//  typedef struct tagBITMAPINFOHEADER {
+		//  	DWORD biSize;
+		//  	LONG  biWidth;
+		//  	LONG  biHeight;
+		//  	WORD  biPlanes;
+		//  	WORD  biBitCount;
+		//  	DWORD biCompression;
+		//  	DWORD biSizeImage;
+		//  	LONG  biXPelsPerMeter;
+		//  	LONG  biYPelsPerMeter;
+		//  	DWORD biClrUsed;
+		//  	DWORD biClrImportant;
+		//  } BITMAPINFOHEADER, *PBITMAPINFOHEADER;
+		//
+		var BITMAPINFOHEADER = [
+			// DWORD biSize -- The number of bytes required by the structure
+			40, 0, 0, 0,
+			// LONG biWidth -- The width of the bitmap, in pixels
+			biWidth & 0xff, biWidth >> 8 & 0xff, biWidth >> 16 & 0xff, biWidth >> 24 & 0xff,
+			// LONG biHeight -- The height of the bitmap, in pixels
+			biHeight & 0xff, biHeight >> 8 & 0xff, biHeight >> 16 & 0xff, biHeight >> 24 & 0xff,
+			// WORD biPlanes -- The number of planes for the target device. This value must be set to 1
+			1, 0,
+			// WORD biBitCount -- The number of bits-per-pixel, 24 bits-per-pixel -- the bitmap
+			// has a maximum of 2^24 colors (16777216, Truecolor)
+			24, 0,
+			// DWORD biCompression -- The type of compression, BI_RGB (code 0) -- uncompressed
+			0, 0, 0, 0,
+			// DWORD biSizeImage -- The size, in bytes, of the image. This may be set to zero for BI_RGB bitmaps
+			biSizeImage & 0xff, biSizeImage >> 8 & 0xff, biSizeImage >> 16 & 0xff, biSizeImage >> 24 & 0xff,
+			// LONG biXPelsPerMeter, unused
+			0, 0, 0, 0,
+			// LONG biYPelsPerMeter, unused
+			0, 0, 0, 0,
+			// DWORD biClrUsed, the number of color indexes of palette, unused
+			0, 0, 0, 0,
+			// DWORD biClrImportant, unused
+			0, 0, 0, 0
+		];
+
+		var iPadding = (4 - ((biWidth * 3) % 4)) % 4;
+
+		var aImgData = oData.data;
+
+		var strPixelData = '';
+		var biWidth4 = biWidth << 2;
+		var y = biHeight;
+		var fromCharCode = String.fromCharCode;
+
+		do {
+			var iOffsetY = biWidth4 * (y - 1);
+			var strPixelRow = '';
+			for (var x = 0; x < biWidth; x++) {
+				var iOffsetX = x << 2;
+				strPixelRow += fromCharCode(aImgData[iOffsetY + iOffsetX + 2]) +
+					fromCharCode(aImgData[iOffsetY + iOffsetX + 1]) +
+					fromCharCode(aImgData[iOffsetY + iOffsetX]);
+			}
+
+			for (var c = 0; c < iPadding; c++) {
+				strPixelRow += String.fromCharCode(0);
+			}
+
+			strPixelData += strPixelRow;
+		} while (--y)
+
+		var strEncoded = encodeData(BITMAPFILEHEADER.concat(BITMAPINFOHEADER)) + encodeData(strPixelData);
+
+		return strEncoded
+	}
+
+	/**
+	 * 转换为图片base64
+	 * @param canvasId canvas标识
+	 * @param x 将要被提取的图像数据矩形区域的左上角 x 坐标
+	 * @param y 将要被提取的图像数据矩形区域的左上角 y 坐标
+	 * @param width 将要被提取的图像数据矩形区域的宽度
+	 * @param height 将要被提取的图像数据矩形区域的高度
+	 * @param type 转换图片类型
+	 * @param done 完成回调
+	 */
+	function convertToImage(canvasId, x, y, width, height, type, done) {
+		if (done === void 0) done = function() {};
+
+		if (type === undefined) {
+			type = 'png';
+		}
+		type = fixType(type);
+		if (/bmp/.test(type)) {
+			getImageData(canvasId, x, y, width, height, function(data, err) {
+				var strData = genBitmapImage(data);
+				tools_7(done) && done(makeURI(strData, 'image/' + type), err);
+			});
+		} else {
+			console.error('暂不支持生成\'' + type + '\'类型的base64图片');
+		}
+	}
+
+	var CanvasToBase64 = {
+		convertToImage: convertToImage,
+		// convertToPNG: function (width, height, done) {
+		//   return convertToImage(width, height, 'png', done)
+		// },
+		// convertToJPEG: function (width, height, done) {
+		//   return convertToImage(width, height, 'jpeg', done)
+		// },
+		// convertToGIF: function (width, height, done) {
+		//   return convertToImage(width, height, 'gif', done)
+		// },
+		convertToBMP: function(ref, done) {
+			if (ref === void 0) ref = {};
+			var canvasId = ref.canvasId;
+			var x = ref.x;
+			var y = ref.y;
+			var width = ref.width;
+			var height = ref.height;
+			if (done === void 0) done = function() {};
+
+			return convertToImage(canvasId, x, y, width, height, 'bmp', done)
+		}
+	};
+
+	function methods() {
+		var self = this;
+
+		var boundWidth = self.width; // 裁剪框默认宽度,即整个画布宽度
+		var boundHeight = self.height; // 裁剪框默认高度,即整个画布高度
+
+		var id = self.id;
+		var targetId = self.targetId;
+		var pixelRatio = self.pixelRatio;
+
+		var ref = self.cut;
+		var x = ref.x;
+		if (x === void 0) x = 0;
+		var y = ref.y;
+		if (y === void 0) y = 0;
+		var width = ref.width;
+		if (width === void 0) width = boundWidth;
+		var height = ref.height;
+		if (height === void 0) height = boundHeight;
+
+		self.updateCanvas = function(done) {
+			if (self.croperTarget) {
+				//  画布绘制图片
+				self.ctx.drawImage(
+					self.croperTarget,
+					self.imgLeft,
+					self.imgTop,
+					self.scaleWidth,
+					self.scaleHeight
+				);
+			}
+			tools_7(self.onBeforeDraw) && self.onBeforeDraw(self.ctx, self);
+
+			self.setBoundStyle(self.boundStyle); //	设置边界样式
+
+			self.ctx.draw(false, done);
+			return self
+		};
+
+		self.pushOrigin = self.pushOrign = function(src) {
+			self.src = src;
+
+			tools_7(self.onBeforeImageLoad) && self.onBeforeImageLoad(self.ctx, self);
+
+			return getImageInfo({
+					src: src
+				})
+				.then(function(res) {
+					var innerAspectRadio = res.width / res.height;
+					var customAspectRadio = width / height;
+
+					self.croperTarget = res.path;
+
+					if (innerAspectRadio < customAspectRadio) {
+						self.rectX = x;
+						self.baseWidth = width;
+						self.baseHeight = width / innerAspectRadio;
+						self.rectY = y - Math.abs((height - self.baseHeight) / 2);
+					} else {
+						self.rectY = y;
+						self.baseWidth = height * innerAspectRadio;
+						self.baseHeight = height;
+						self.rectX = x - Math.abs((width - self.baseWidth) / 2);
+					}
+
+					self.imgLeft = self.rectX;
+					self.imgTop = self.rectY;
+					self.scaleWidth = self.baseWidth;
+					self.scaleHeight = self.baseHeight;
+
+					self.update();
+
+					return new Promise(function(resolve) {
+						self.updateCanvas(resolve);
+					})
+				})
+				.then(function() {
+					tools_7(self.onImageLoad) && self.onImageLoad(self.ctx, self);
+				})
+		};
+
+		self.removeImage = function() {
+			self.src = '';
+			self.croperTarget = '';
+			return draw(self.ctx)
+		};
+
+		self.getCropperBase64 = function(done) {
+			if (done === void 0) done = function() {};
+
+			CanvasToBase64.convertToBMP({
+				canvasId: id,
+				x: x,
+				y: y,
+				width: width,
+				height: height
+			}, done);
+		};
+
+		self.getCropperImage = function(opt, fn) {
+			var customOptions = opt;
+
+			var canvasOptions = {
+				canvasId: id,
+				x: x,
+				y: y,
+				width: width,
+				height: height
+			};
+
+			var task = function() {
+				return Promise.resolve();
+			};
+
+			if (
+				tools_10(customOptions) &&
+				customOptions.original
+			) {
+				// original mode
+				task = function() {
+					self.targetCtx.drawImage(
+						self.croperTarget,
+						self.imgLeft * pixelRatio,
+						self.imgTop * pixelRatio,
+						self.scaleWidth * pixelRatio,
+						self.scaleHeight * pixelRatio
+					);
+
+					canvasOptions = {
+						canvasId: targetId,
+						x: x * pixelRatio,
+						y: y * pixelRatio,
+						width: width * pixelRatio,
+						height: height * pixelRatio
+					};
+
+					return draw(self.targetCtx)
+				};
+			}
+
+			return task()
+				.then(function() {
+					if (tools_10(customOptions)) {
+						canvasOptions = Object.assign({}, canvasOptions, customOptions);
+					}
+
+					if (tools_7(customOptions)) {
+						fn = customOptions;
+					}
+
+					var arg = canvasOptions.componentContext ?
+						[canvasOptions, canvasOptions.componentContext] :
+						[canvasOptions];
+
+					return canvasToTempFilePath.apply(null, arg)
+				})
+				.then(function(res) {
+					var tempFilePath = res.tempFilePath;
+
+					return tools_7(fn) ?
+						fn.call(self, tempFilePath, null) :
+						tempFilePath
+				})
+				.catch(function(err) {
+					if (tools_7(fn)) {
+						fn.call(self, null, err);
+					} else {
+						throw err
+					}
+				})
+		};
+	}
+
+	/**
+	 * 获取最新缩放值
+	 * @param oldScale 上一次触摸结束后的缩放值
+	 * @param oldDistance 上一次触摸结束后的双指距离
+	 * @param zoom 缩放系数
+	 * @param touch0 第一指touch对象
+	 * @param touch1 第二指touch对象
+	 * @returns {*}
+	 */
+	var getNewScale = function(oldScale, oldDistance, zoom, touch0, touch1) {
+		var xMove, yMove, newDistance;
+		// 计算二指最新距离
+		xMove = Math.round(touch1.x - touch0.x);
+		yMove = Math.round(touch1.y - touch0.y);
+		newDistance = Math.round(Math.sqrt(xMove * xMove + yMove * yMove));
+
+		return oldScale + 0.001 * zoom * (newDistance - oldDistance)
+	};
+
+	function update() {
+		var self = this;
+
+		if (!self.src) {
+			return
+		}
+
+		self.__oneTouchStart = function(touch) {
+			self.touchX0 = Math.round(touch.x);
+			self.touchY0 = Math.round(touch.y);
+		};
+
+		self.__oneTouchMove = function(touch) {
+			var xMove, yMove;
+			// 计算单指移动的距离
+			if (self.touchended) {
+				return self.updateCanvas()
+			}
+			xMove = Math.round(touch.x - self.touchX0);
+			yMove = Math.round(touch.y - self.touchY0);
+
+			var imgLeft = Math.round(self.rectX + xMove);
+			var imgTop = Math.round(self.rectY + yMove);
+
+			self.outsideBound(imgLeft, imgTop);
+
+			self.updateCanvas();
+		};
+
+		self.__twoTouchStart = function(touch0, touch1) {
+			var xMove, yMove, oldDistance;
+
+			self.touchX1 = Math.round(self.rectX + self.scaleWidth / 2);
+			self.touchY1 = Math.round(self.rectY + self.scaleHeight / 2);
+
+			// 计算两指距离
+			xMove = Math.round(touch1.x - touch0.x);
+			yMove = Math.round(touch1.y - touch0.y);
+			oldDistance = Math.round(Math.sqrt(xMove * xMove + yMove * yMove));
+
+			self.oldDistance = oldDistance;
+		};
+
+		self.__twoTouchMove = function(touch0, touch1) {
+			var oldScale = self.oldScale;
+			var oldDistance = self.oldDistance;
+			var scale = self.scale;
+			var zoom = self.zoom;
+
+			self.newScale = getNewScale(oldScale, oldDistance, zoom, touch0, touch1);
+
+			//  设定缩放范围
+			self.newScale <= 1 && (self.newScale = 1);
+			self.newScale >= scale && (self.newScale = scale);
+
+			self.scaleWidth = Math.round(self.newScale * self.baseWidth);
+			self.scaleHeight = Math.round(self.newScale * self.baseHeight);
+			var imgLeft = Math.round(self.touchX1 - self.scaleWidth / 2);
+			var imgTop = Math.round(self.touchY1 - self.scaleHeight / 2);
+
+			self.outsideBound(imgLeft, imgTop);
+
+			self.updateCanvas();
+		};
+
+		self.__xtouchEnd = function() {
+			self.oldScale = self.newScale;
+			self.rectX = self.imgLeft;
+			self.rectY = self.imgTop;
+		};
+	}
+
+	var handle = {
+		//  图片手势初始监测
+		touchStart: function touchStart(e) {
+			var self = this;
+			var ref = e.touches;
+			var touch0 = ref[0];
+			var touch1 = ref[1];
+
+			if (!self.src) {
+				return
+			}
+
+			setTouchState(self, true, null, null);
+
+			// 计算第一个触摸点的位置,并参照改点进行缩放
+			self.__oneTouchStart(touch0);
+
+			// 两指手势触发
+			if (e.touches.length >= 2) {
+				self.__twoTouchStart(touch0, touch1);
+			}
+		},
+
+		//  图片手势动态缩放
+		touchMove: function touchMove(e) {
+			var self = this;
+			var ref = e.touches;
+			var touch0 = ref[0];
+			var touch1 = ref[1];
+
+			if (!self.src) {
+				return
+			}
+
+			setTouchState(self, null, true);
+
+			// 单指手势时触发
+			if (e.touches.length === 1) {
+				self.__oneTouchMove(touch0);
+			}
+			// 两指手势触发
+			if (e.touches.length >= 2) {
+				self.__twoTouchMove(touch0, touch1);
+			}
+		},
+
+		touchEnd: function touchEnd(e) {
+			var self = this;
+
+			if (!self.src) {
+				return
+			}
+
+			setTouchState(self, false, false, true);
+			self.__xtouchEnd();
+		}
+	};
+
+	function cut() {
+		var self = this;
+		var boundWidth = self.width; // 裁剪框默认宽度,即整个画布宽度
+		var boundHeight = self.height;
+		// 裁剪框默认高度,即整个画布高度
+		var ref = self.cut;
+		var x = ref.x;
+		if (x === void 0) x = 0;
+		var y = ref.y;
+		if (y === void 0) y = 0;
+		var width = ref.width;
+		if (width === void 0) width = boundWidth;
+		var height = ref.height;
+		if (height === void 0) height = boundHeight;
+
+		/**
+		 * 设置边界
+		 * @param imgLeft 图片左上角横坐标值
+		 * @param imgTop 图片左上角纵坐标值
+		 */
+		self.outsideBound = function(imgLeft, imgTop) {
+			self.imgLeft = imgLeft >= x ?
+				x :
+				self.scaleWidth + imgLeft - x <= width ?
+				x + width - self.scaleWidth :
+				imgLeft;
+
+			self.imgTop = imgTop >= y ?
+				y :
+				self.scaleHeight + imgTop - y <= height ?
+				y + height - self.scaleHeight :
+				imgTop;
+		};
+
+		/**
+		 * 设置边界样式
+		 * @param color	边界颜色
+		 */
+		self.setBoundStyle = function(ref) {
+			if (ref === void 0) ref = {};
+			var color = ref.color;
+			if (color === void 0) color = '#04b00f';
+			var mask = ref.mask;
+			if (mask === void 0) mask = 'rgba(0, 0, 0, 0.3)';
+			var lineWidth = ref.lineWidth;
+			if (lineWidth === void 0) lineWidth = 1;
+
+			var half = lineWidth / 2;
+			var boundOption = [{
+					start: {
+						x: x - half,
+						y: y + 10 - half
+					},
+					step1: {
+						x: x - half,
+						y: y - half
+					},
+					step2: {
+						x: x + 10 - half,
+						y: y - half
+					}
+				},
+				{
+					start: {
+						x: x - half,
+						y: y + height - 10 + half
+					},
+					step1: {
+						x: x - half,
+						y: y + height + half
+					},
+					step2: {
+						x: x + 10 - half,
+						y: y + height + half
+					}
+				},
+				{
+					start: {
+						x: x + width - 10 + half,
+						y: y - half
+					},
+					step1: {
+						x: x + width + half,
+						y: y - half
+					},
+					step2: {
+						x: x + width + half,
+						y: y + 10 - half
+					}
+				},
+				{
+					start: {
+						x: x + width + half,
+						y: y + height - 10 + half
+					},
+					step1: {
+						x: x + width + half,
+						y: y + height + half
+					},
+					step2: {
+						x: x + width - 10 + half,
+						y: y + height + half
+					}
+				}
+			];
+
+			// 绘制半透明层
+			self.ctx.beginPath();
+			self.ctx.setFillStyle(mask);
+			self.ctx.fillRect(0, 0, x, boundHeight);
+			self.ctx.fillRect(x, 0, width, y);
+			self.ctx.fillRect(x, y + height, width, boundHeight - y - height);
+			self.ctx.fillRect(x + width, 0, boundWidth - x - width, boundHeight);
+			self.ctx.fill();
+
+			boundOption.forEach(function(op) {
+				self.ctx.beginPath();
+				self.ctx.setStrokeStyle(color);
+				self.ctx.setLineWidth(lineWidth);
+				self.ctx.moveTo(op.start.x, op.start.y);
+				self.ctx.lineTo(op.step1.x, op.step1.y);
+				self.ctx.lineTo(op.step2.x, op.step2.y);
+				self.ctx.stroke();
+			});
+		};
+	}
+
+	var version = "1.3.9";
+
+	var WeCropper = function WeCropper(params) {
+		var self = this;
+		var _default = {};
+
+		validator(self, DEFAULT);
+
+		Object.keys(DEFAULT).forEach(function(key) {
+			_default[key] = DEFAULT[key].default;
+		});
+		Object.assign(self, _default, params);
+
+		self.prepare();
+		self.attachPage();
+		self.createCtx();
+		self.observer();
+		self.cutt();
+		self.methods();
+		self.init();
+		self.update();
+
+		return self
+	};
+
+	WeCropper.prototype.init = function init() {
+		var self = this;
+		var src = self.src;
+
+		self.version = version;
+
+		typeof self.onReady === 'function' && self.onReady(self.ctx, self);
+
+		if (src) {
+			self.pushOrign(src);
+		} else {
+			self.updateCanvas();
+		}
+		setTouchState(self, false, false, false);
+
+		self.oldScale = 1;
+		self.newScale = 1;
+
+		return self
+	};
+
+	Object.assign(WeCropper.prototype, handle);
+
+	WeCropper.prototype.prepare = prepare;
+	WeCropper.prototype.observer = observer;
+	WeCropper.prototype.methods = methods;
+	WeCropper.prototype.cutt = cut;
+	WeCropper.prototype.update = update;
+
+	return WeCropper;
+
+})));

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 24 - 0
uview-ui/components/u-avatar/u-avatar.vue


+ 153 - 0
uview-ui/components/u-back-top/u-back-top.vue

@@ -0,0 +1,153 @@
+<template>
+	<view @tap="backToTop" class="u-back-top" :class="['u-back-top--mode--' + mode]" :style="[{
+		bottom: bottom + 'rpx',
+		right: right + 'rpx',
+		borderRadius: mode == 'circle' ? '10000rpx' : '8rpx',
+		zIndex: uZIndex,
+		opacity: opacity
+	}, customStyle]">
+		<view class="u-back-top__content" v-if="!$slots.default && !$slots.$default">
+			<u-icon @click="backToTop" :name="icon" :custom-style="iconStyle"></u-icon>
+			<view class="u-back-top__content__tips">
+				{{tips}}
+			</view>
+		</view>
+		<slot v-else />
+	</view>
+</template>
+
+<script>
+	export default {
+		name: 'u-back-top',
+		props: {
+			// 返回顶部的形状,circle-圆形,square-方形
+			mode: {
+				type: String,
+				default: 'circle'
+			},
+			// 自定义图标
+			icon: {
+				type: String,
+				default: 'arrow-upward'
+			},
+			// 提示文字
+			tips: {
+				type: String,
+				default: ''
+			},
+			// 返回顶部滚动时间
+			duration: {
+				type: [Number, String],
+				default: 100
+			},
+			// 滚动距离
+			scrollTop: {
+				type: [Number, String],
+				default: 0
+			},
+			// 距离顶部多少距离显示,单位rpx
+			top: {
+				type: [Number, String],
+				default: 400
+			},
+			// 返回顶部按钮到底部的距离,单位rpx
+			bottom: {
+				type: [Number, String],
+				default: 200
+			},
+			// 返回顶部按钮到右边的距离,单位rpx
+			right: {
+				type: [Number, String],
+				default: 40
+			},
+			// 层级
+			zIndex: {
+				type: [Number, String],
+				default: '9'
+			},
+			// 图标的样式,对象形式
+			iconStyle: {
+				type: Object,
+				default() {
+					return {
+						color: '#909399',
+						fontSize: '38rpx'
+					}
+				}
+			},
+			// 整个组件的样式
+			customStyle: {
+				type: Object,
+				default() {
+					return {}
+				}
+			}
+		},
+		watch: {
+			showBackTop(nVal, oVal) {
+				// 当组件的显示与隐藏状态发生跳变时,修改组件的层级和不透明度
+				// 让组件有显示和消失的动画效果,如果用v-if控制组件状态,将无设置动画效果
+				if(nVal) {
+					this.uZIndex = this.zIndex;
+					this.opacity = 1;
+				} else {
+					this.uZIndex = -1;
+					this.opacity = 0;
+				}
+			}
+		},
+		computed: {
+			showBackTop() {
+				// 由于scrollTop为页面的滚动距离,默认为px单位,这里将用于传入的top(rpx)值
+				// 转为px用于比较,如果滚动条到顶的距离大于设定的距离,就显示返回顶部的按钮
+				return this.scrollTop > uni.upx2px(this.top);
+			},
+		},
+		data() {
+			return {
+				// 不透明度,为了让组件有一个显示和隐藏的过渡动画
+				opacity: 0,
+				// 组件的z-index值,隐藏时设置为-1,就会看不到
+				uZIndex: -1
+			}
+		},
+		methods: {
+			backToTop() {
+				uni.pageScrollTo({
+					scrollTop: 0,
+					duration: this.duration
+				});
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	@import "../../libs/css/style.components.scss";
+	
+	.u-back-top {
+		width: 80rpx;
+		height: 80rpx;
+		position: fixed;
+		z-index: 9;
+		@include vue-flex;
+		flex-direction: column;
+		justify-content: center;
+		background-color: #E1E1E1;
+		color: $u-content-color;
+		align-items: center;
+		transition: opacity 0.4s;
+		
+		&__content {
+			@include vue-flex;
+			flex-direction: column;
+			align-items: center;
+			
+			&__tips {
+				font-size: 24rpx;
+				transform: scale(0.8);
+				line-height: 1;
+			}
+		}
+	}
+</style>

Vissa filer visades inte eftersom för många filer har ändrats