Browse Source

uni-app框架搭建完成

zhengJ_docnet 1 year ago
parent
commit
68b95ebfda
48 changed files with 9242 additions and 0 deletions
  1. 20 0
      App.vue
  2. 184 0
      colorui/animation.css
  3. 65 0
      colorui/components/cu-custom.vue
  4. 139 0
      colorui/components/curry-slide.vue
  5. 410 0
      colorui/components/curry-swiper.vue
  6. 1226 0
      colorui/icon.css
  7. 4090 0
      colorui/main.css
  8. 346 0
      common/iconfont.css
  9. 0 0
      common/main.css
  10. 125 0
      common/utils/airport.js
  11. 1 0
      common/utils/amap-wx.js
  12. 239 0
      common/utils/https.js
  13. 34 0
      common/utils/request.js
  14. 60 0
      common/utils/tips.js
  15. 419 0
      components/icon/icon.vue
  16. 268 0
      components/indexed-list/indexed-list.vue
  17. 20 0
      main.js
  18. 131 0
      manifest.json
  19. 377 0
      package-lock.json
  20. 57 0
      pages.json
  21. 8 0
      pages/components/login/login.vue
  22. 8 0
      pages/components/login/pLogin.vue
  23. 8 0
      pages/components/login/wLogin.vue
  24. 103 0
      pages/components/personal/index.vue
  25. 200 0
      pages/components/signin/sign.vue
  26. 227 0
      pages/index/index.vue
  27. 68 0
      pages/list/list.vue
  28. 146 0
      pages/mypersonal/personal.vue
  29. 145 0
      pages/setting/setting.vue
  30. BIN
      static/arrow.png
  31. BIN
      static/close.png
  32. BIN
      static/cloud.jpg
  33. BIN
      static/danger.png
  34. BIN
      static/home.png
  35. BIN
      static/home_light.png
  36. BIN
      static/icon.png
  37. BIN
      static/info.png
  38. BIN
      static/location.png
  39. BIN
      static/logo.png
  40. BIN
      static/menu.png
  41. BIN
      static/people.png
  42. BIN
      static/people_light.png
  43. BIN
      static/question.png
  44. BIN
      static/setting.png
  45. BIN
      static/share_circle.png
  46. 12 0
      store/index.js
  47. 19 0
      store/modules/global.js
  48. 87 0
      uni.scss

+ 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 "colorui/main.css";
+	@import "colorui/icon.css";
+	@import "common/main.css"; /* 你的项目css */
+	@import "common/iconfont.css"
+</style>

+ 184 - 0
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)
+    }
+}

+ 65 - 0
colorui/components/cu-custom.vue

@@ -0,0 +1,65 @@
+<template>
+	<view>
+		<view class="cu-custom" :style="[{height:CustomBar + 'px'}]">
+			<view class="cu-bar fixed" :style="style" :class="[bgImage!=''?'none-bg text-white bg-img':'',bgColor]">
+				<view class="action" @tap="BackPage" v-if="isBack">
+					<text class="cuIcon-back"></text>
+					<slot name="backText"></slot>
+				</view>
+				<view class="content" :style="[{top:StatusBar + 'px'}]">
+					<slot name="content"></slot>
+				</view>
+				<slot name="right"></slot>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				StatusBar: this.StatusBar,
+				CustomBar: this.CustomBar
+			};
+		},
+		name: 'cu-custom',
+		computed: {
+			style() {
+				var StatusBar= this.StatusBar;
+				var CustomBar= this.CustomBar;
+				var bgImage = this.bgImage;
+				var style = `height:${CustomBar}px;padding-top:${StatusBar}px;`;
+				if (this.bgImage) {
+					style = `${style}background-image:url(${bgImage});`;
+				}
+				return style
+			}
+		},
+		props: {
+			bgColor: {
+				type: String,
+				default: ''
+			},
+			isBack: {
+				type: [Boolean, String],
+				default: false
+			},
+			bgImage: {
+				type: String,
+				default: ''
+			},
+		},
+		methods: {
+			BackPage() {
+				uni.navigateBack({
+					delta: 1
+				});
+			}
+		}
+	}
+</script>
+
+<style>
+
+</style>

+ 139 - 0
colorui/components/curry-slide.vue

@@ -0,0 +1,139 @@
+<template>
+  <view class="carousel-3d-slide" :style="slideStyle" :class="computedClasses" @click="goTo()">
+    <slot :index="index" :isCurrent="isCurrent" :leftIndex="leftIndex" :rightIndex="rightIndex"/>
+  </view>
+</template>
+
+<script>
+/* eslint-disable */
+export default {
+  name: 'curry-slide',
+  props: {
+    index: {
+      type: Number
+    }
+  },
+  data () {
+    return {
+      parent: this.$parent,
+      styles: {},
+      zIndex: 999
+    }
+  },
+  computed: {
+    isCurrent () {
+      return this.index === this.parent.currentIndex
+    },
+    leftIndex () {
+      return this.getSideIndex(this.parent.leftIndices)
+    },
+    rightIndex () {
+      return this.getSideIndex(this.parent.rightIndices)
+    },
+    slideStyle () {
+      let styles = {}
+      if (!this.isCurrent) {
+        const rIndex = this.leftIndex
+        const lIndex = this.rightIndex
+        if (rIndex >= 0 || lIndex >= 0) {
+          styles = rIndex >= 0 ? this.calculatePosition(rIndex, true, this.zIndex) : this.calculatePosition(lIndex, false, this.zIndex)
+          styles.opacity = 1
+          styles.visibility = 'visible'
+        }
+        if (this.parent.hasHiddenSlides) {
+          if (this.matchIndex(this.parent.leftOutIndex)) {
+            styles = this.calculatePosition(this.parent.leftIndices.length - 1, false, this.zIndex)
+          } else if (this.matchIndex(this.parent.rightOutIndex)) {
+            styles = this.calculatePosition(this.parent.rightIndices.length - 1, true, this.zIndex)
+          }
+        }
+      }
+      return Object.assign(styles, {
+        'border-width': this.parent.border + 'px',
+        'width': this.parent.slideWidth + 'px',
+        'height': this.parent.slideHeight + 'px',
+        'transition': ' transform ' + this.parent.animationSpeed + 'ms, ' +
+        '               opacity ' + this.parent.animationSpeed + 'ms, ' +
+        '               visibility ' + this.parent.animationSpeed + 'ms'
+      })
+    },
+    computedClasses () {
+      return {
+        [`left-${this.leftIndex + 1}`]: this.leftIndex >= 0,
+        [`right-${this.rightIndex + 1}`]: this.rightIndex >= 0,
+        'current': this.isCurrent
+      }
+    }
+  },
+  methods: {
+    getSideIndex (array) {
+      let index = -1
+      array.forEach((pos, i) => {
+        if (this.matchIndex(pos)) {
+          index = i
+        }
+      })
+      return index
+    },
+    matchIndex (index) {
+      return (index >= 0) ? this.index === index : (this.parent.total + index) === this.index
+    },
+    calculatePosition (i, positive, zIndex) {
+      const z = !this.parent.disable3d ? parseInt(this.parent.inverseScaling) + ((i + 1) * 100) : 0
+      const y = !this.parent.disable3d ? parseInt(this.parent.perspective) : 0
+      const leftRemain = (this.parent.space === 'auto')
+        ? parseInt((i + 1) * (this.parent.width / 1.2), 10) // 1.5
+        : parseInt((i + 1) * (this.parent.space), 10)
+      const transform = (positive)
+        ? 'translateX(' + (leftRemain) + 'px) translateZ(-' + z + 'px) ' +
+        'rotateY(-' + y + 'deg)'
+        : 'translateX(-' + (leftRemain) + 'px) translateZ(-' + z + 'px) ' +
+        'rotateY(' + y + 'deg)'
+      const top = this.parent.space === 'auto' ? 0 : parseInt((i + 1) * (this.parent.space))
+      return {
+        transform: transform,
+        top: top,
+        zIndex: zIndex - (Math.abs(i) + 1)
+      }
+    },
+    goTo () {
+      if (!this.isCurrent) {
+        if (this.parent.clickable === true) {
+          this.parent.goFar(this.index)
+        }
+      } else {
+        this.parent.onMainSlideClick()
+      }
+    }
+  }
+}
+</script>
+
+<style>
+  .carousel-3d-slide {
+    position: absolute;
+    opacity: 0;
+    visibility: hidden;
+    overflow: hidden;
+    top: 0;
+    border-color: #023c41;
+    border-style: solid;
+    background-size: cover;
+    background-color: #ccc;
+    display: block;
+    margin: 0;
+    box-sizing: border-box;
+  }
+  .carousel-3d-slide {
+    text-align: left;
+  }
+  .carousel-3d-slide img {
+    width: 100%;
+  }
+  .carousel-3d-slide.current {
+    opacity: 1 !important;
+    visibility: visible !important;
+    transform: none !important;
+    z-index: 999;
+  }
+</style>

+ 410 - 0
colorui/components/curry-swiper.vue

@@ -0,0 +1,410 @@
+<template>
+  <view class="carousel-3d-container" :style="{height: this.slideHeight + 'px'}">
+    <view class="carousel-3d-slider" :style="{width: this.slideWidth + 'px', height: this.slideHeight + 'px'}">
+      <slot></slot>
+    </view>
+  </view>
+</template>
+
+<script>
+/* eslint-disable */
+  const noop = () => {
+  }
+  export default {
+    name: 'curry-swiper',
+    props: {
+      // Number of slides
+      count: {
+        type: [Number, String],
+        default: 0
+      },
+      // Slides perspective position
+      perspective: {
+        type: [Number, String],
+        default: 35
+      },
+      // Number of slides displayed on each page
+      display: {
+        type: [Number, String],
+        default: 3
+      },
+      loop: {
+        type: Boolean,
+        default: true
+      },
+      // Animation between slides in milliseconds
+      animationSpeed: {
+        type: [Number, String],
+        default: 500
+      },
+      // Animation direction
+      dir: {
+        type: String,
+        default: 'ltr'
+      },
+      width: {
+        type: [Number, String],
+        default: 360
+      },
+      height: {
+        type: [Number, String],
+        default: 270
+      },
+      border: {
+        type: [Number, String],
+        default: 1
+      },
+      // Space between slides in pixels
+      space: {
+        type: [Number, String],
+        default: 'auto'
+      },
+      // Start slide index. First slide has 0 index
+      startIndex: {
+        type: [Number, String],
+        default: 0
+      },
+      // Enable navigation by clicking on slide
+      clickable: {
+        type: Boolean,
+        default: true
+      },
+      disable3d: {
+        type: Boolean,
+        default: false
+      },
+      // Minimum distance in pixels to swipe before a slide advance is triggered
+      minSwipeDistance: {
+        type: Number,
+        default: 10
+      },
+      // Slide inverse scaling
+      inverseScaling: {
+        type: [Number, String],
+        default: 300
+      },
+      onLastSlide: {
+        type: Function,
+        default: noop
+      },
+      onSlideChange: {
+        type: Function,
+        default: noop
+      },
+      bias: {
+        type: String,
+        default: 'left'
+      },
+      onMainSlideClick: {
+        type: Function,
+        default: noop
+      }
+    },
+    data () {
+      return {
+        viewport: 0,
+        currentIndex: 0,
+        total: 0,
+        dragOffset: 0,
+        dragStartX: 0,
+        mousedown: false,
+        zIndex: 998
+      }
+    },
+    watch: {
+      count () {
+        this.computeData()
+      }
+    },
+    computed: {
+      isLastSlide () {
+        return this.currentIndex === this.total - 1
+      },
+      isFirstSlide () {
+        return this.currentIndex === 0
+      },
+      isNextPossible () {
+        return !(!this.loop && this.isLastSlide)
+      },
+      isPrevPossible () {
+        return !(!this.loop && this.isFirstSlide)
+      },
+      slideWidth () {
+        const vw = this.viewport
+        const sw = parseInt(this.width) + (parseInt(this.border, 10) * 2)
+        return vw < sw ? vw : sw
+      },
+      slideHeight () {
+        const sw = parseInt(this.width, 10) + (parseInt(this.border, 10) * 2)
+        const sh = parseInt(parseInt(this.height) + (this.border * 2), 10)
+        const ar = this.calculateAspectRatio(sw, sh)
+        return this.slideWidth / ar
+      },
+      visible () {
+        const v = (this.display > this.total) ? this.total : this.display
+        return v
+      },
+      hasHiddenSlides () {
+        return this.total > this.visible
+      },
+      leftIndices () {
+        let n = (this.visible - 1) / 2
+        n = (this.bias.toLowerCase() === 'left' ? Math.ceil(n) : Math.floor(n))
+        const indices = []
+        for (let m = 1; m <= n; m++) {
+          indices.push((this.dir === 'ltr')
+            ? (this.currentIndex + m) % (this.total)
+            : (this.currentIndex - m) % (this.total))
+        }
+        return indices
+      },
+      rightIndices () {
+        let n = (this.visible - 1) / 2
+        n = (this.bias.toLowerCase() === 'right' ? Math.ceil(n) : Math.floor(n))
+        const indices = []
+        for (let m = 1; m <= n; m++) {
+          indices.push((this.dir === 'ltr')
+            ? (this.currentIndex - m) % (this.total)
+            : (this.currentIndex + m) % (this.total))
+        }
+        return indices
+      },
+      leftOutIndex () {
+        let n = (this.visible - 1) / 2
+        n = (this.bias.toLowerCase() === 'left' ? Math.ceil(n) : Math.floor(n))
+        n++
+        if (this.dir === 'ltr') {
+          return ((this.total - this.currentIndex - n) <= 0)
+            ? (-parseInt(this.total - this.currentIndex - n))
+            : (this.currentIndex + n)
+        } else {
+          return (this.currentIndex - n)
+        }
+      },
+      rightOutIndex () {
+        let n = (this.visible - 1) / 2
+        n = (this.bias.toLowerCase() === 'right' ? Math.ceil(n) : Math.floor(n))
+        n++
+        if (this.dir === 'ltr') {
+          return (this.currentIndex - n)
+        } else {
+          return ((this.total - this.currentIndex - n) <= 0)
+            ? (-parseInt(this.total - this.currentIndex - n, 10))
+            : (this.currentIndex + n)
+        }
+      }
+    },
+    methods: {
+      /**
+       * Go to next slide
+       */
+      goNext () {
+        if (this.isNextPossible) {
+          this.isLastSlide ? this.goSlide(0) : this.goSlide(this.currentIndex + 1)
+        }
+      },
+      /**
+       * Go to previous slide
+       */
+      goPrev () {
+        if (this.isPrevPossible) {
+          this.isFirstSlide ? this.goSlide(this.total - 1) : this.goSlide(this.currentIndex - 1)
+        }
+      },
+      /**
+       * Go to slide
+       * @param  {String} index of slide where to go
+       */
+      goSlide (index) {
+        this.currentIndex = (index < 0 || index > this.total - 1) ? 0 : index
+        if (this.isLastSlide) {
+          if (this.onLastSlide !== noop) {
+            console.warn('onLastSlide deprecated, please use @last-slide')
+          }
+          this.onLastSlide(this.currentIndex)
+          this.$emit('last-slide', this.currentIndex)
+        }
+        this.$emit('before-slide-change', this.currentIndex)
+        setTimeout(() => this.animationEnd(), this.animationSpeed)
+      },
+      /**
+       * Go to slide far slide
+       */
+      goFar (index) {
+        let diff = (index === this.total - 1 && this.isFirstSlide) ? -1 : (index - this.currentIndex)
+        if (this.isLastSlide && index === 0) {
+          diff = 1
+        }
+        const diff2 = (diff < 0) ? -diff : diff
+        let timeBuff = 0
+        let i = 0
+        while (i < diff2) {
+          i += 1
+          const timeout = (diff2 === 1) ? 0 : (timeBuff)
+          setTimeout(() => (diff < 0) ? this.goPrev(diff2) : this.goNext(diff2), timeout)
+          timeBuff += (this.animationSpeed / (diff2))
+        }
+      },
+      /**
+       * Trigger actions when animation ends
+       */
+      animationEnd () {
+        if (this.onSlideChange !== noop) {
+          console.warn('onSlideChange deprecated, please use @after-slide-change')
+        }
+        this.onSlideChange(this.currentIndex)
+        this.$emit('after-slide-change', this.currentIndex)
+      },
+      /**
+       * Trigger actions when mouse is released
+       * @param  {Object} e The event object
+       */
+      handleMouseup () {
+        this.mousedown = false
+        this.dragOffset = 0
+      },
+      /**
+       * Trigger actions when mouse is pressed
+       * @param  {Object} e The event object
+       */
+      handleMousedown (e) {
+        if (!e.touches) {
+          e.preventDefault()
+        }
+        this.mousedown = true
+        this.dragStartX = ('ontouchstart' in window) ? e.touches[0].clientX : e.clientX
+      },
+      /**
+       * Trigger actions when mouse is pressed and then moved (mouse drag)
+       * @param  {Object} e The event object
+       */
+      handleMousemove (e) {
+          if (!this.mousedown) {
+            return
+          }
+          const eventPosX = ('ontouchstart' in window) ? e.touches[0].clientX : e.clientX
+          const deltaX = (this.dragStartX - eventPosX)
+          this.dragOffset = deltaX
+          if (this.dragOffset > this.minSwipeDistance) {
+            this.handleMouseup()
+            this.goNext()
+          } else if (this.dragOffset < -this.minSwipeDistance) {
+            this.handleMouseup()
+            this.goPrev()
+          }
+      },
+      /**
+       * A mutation observer is used to detect changes to the containing node
+       * in order to keep the magnet container in sync with the height its reference node.
+       */
+      attachMutationObserver () {
+        const MutationObserver = window.MutationObserver ||
+          window.WebKitMutationObserver ||
+          window.MozMutationObserver
+        if (MutationObserver) {
+          const config = {
+            attributes: true,
+            childList: true,
+            characterData: true
+          }
+          this.mutationObserver = new MutationObserver(() => {
+            this.$nextTick(() => {
+              this.computeData()
+            })
+          })
+          if (this.$el) {
+            this.mutationObserver.observe(this.$el, config)
+          }
+        }
+      },
+      /**
+       * Stop listening to mutation changes
+       */
+      detachMutationObserver () {
+        if (this.mutationObserver) {
+          this.mutationObserver.disconnect()
+        }
+      },
+      /**
+       * Get the number of slides
+       * @return {Number} Number of slides
+       */
+      getSlideCount () {
+        if (this.$slots.default !== undefined) {
+          return this.$slots.default.filter((value) => {
+            return value.tag !== void 0
+          }).length
+        }
+        return 0
+      },
+      /**
+       * Calculate slide with and keep defined aspect ratio
+       * @return {Number} Aspect ratio number
+       */
+      calculateAspectRatio (width, height) {
+        return Math.min(width / height)
+      },
+      /**
+       * Re-compute the number of slides and current slide
+       */
+      computeData (firstRun) {
+        this.total = this.getSlideCount()
+        if (firstRun || this.currentIndex >= this.total) {
+          this.currentIndex = parseInt(this.startIndex) > this.total - 1 ? this.total - 1 : parseInt(this.startIndex)
+        }
+        this.viewport = this.$el.clientWidth
+      },
+      setSize () {
+        this.$el.style.cssText += 'height:' + this.slideHeight + 'px;'
+        this.$el.childNodes[0].style.cssText += 'width:' + this.slideWidth + 'px;' + ' height:' + this.slideHeight + 'px;'
+      }
+    },
+    mounted () {
+      this.computeData(true)
+      this.attachMutationObserver()
+      if (!this.$isServer) {
+        window.addEventListener('resize', this.setSize)
+        if ('ontouchstart' in window) {
+          this.$el.addEventListener('touchstart', this.handleMousedown)
+          this.$el.addEventListener('touchend', this.handleMouseup)
+          this.$el.addEventListener('touchmove', this.handleMousemove)
+        } else {
+          this.$el.addEventListener('mousedown', this.handleMousedown)
+          this.$el.addEventListener('mouseup', this.handleMouseup)
+          this.$el.addEventListener('mousemove', this.handleMousemove)
+        }
+      }
+    },
+    beforeDestroy () {
+      if (!this.$isServer) {
+        this.detachMutationObserver()
+        if ('ontouchstart' in window) {
+          this.$el.removeEventListener('touchmove', this.handleMousemove)
+        } else {
+          this.$el.removeEventListener('mousemove', this.handleMousemove)
+        }
+        window.removeEventListener('resize', this.setSize)
+      }
+    }
+  }
+</script>
+
+<style lang="scss" scoped>
+  .carousel-3d-container {
+    min-height: 1px;
+    width: 100%;
+    position: relative;
+    z-index: 0;
+    overflow: hidden;
+    margin: 0px auto;
+    box-sizing: border-box;
+  }
+  .carousel-3d-slider {
+    position: relative;
+    margin: 0 auto;
+    transform-style: preserve-3d;
+    -webkit-perspective: 1000px;
+    -moz-perspective: 1000px;
+    perspective: 1000px;
+  }
+</style>

File diff suppressed because it is too large
+ 1226 - 0
colorui/icon.css


File diff suppressed because it is too large
+ 4090 - 0
colorui/main.css


+ 346 - 0
common/iconfont.css

@@ -0,0 +1,346 @@
+@font-face {
+  font-family: 'iconfont';  /* project id 878519 */
+  src: url('//at.alicdn.com/t/font_878519_lkhdlz7l07h.eot');
+  src: url('//at.alicdn.com/t/font_878519_lkhdlz7l07h.eot?#iefix') format('embedded-opentype'),
+  url('//at.alicdn.com/t/font_878519_lkhdlz7l07h.woff2') format('woff2'),
+  url('//at.alicdn.com/t/font_878519_lkhdlz7l07h.woff') format('woff'),
+  url('//at.alicdn.com/t/font_878519_lkhdlz7l07h.ttf') format('truetype'),
+  url('//at.alicdn.com/t/font_878519_lkhdlz7l07h.svg#iconfont') format('svg');
+}
+
+.iconfont {
+  font-family: "iconfont" !important;
+  font-size: 16px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+.icon-30:before {
+  content: "\e686";
+}
+
+.icon-05:before {
+  content: "\e688";
+}
+
+.icon-menu:before {
+  content: "\e630";
+}
+
+.icon-unie64d:before {
+  content: "\e6b0";
+}
+
+.icon-31:before {
+  content: "\e637";
+}
+
+.icon-19:before {
+  content: "\e8b7";
+}
+
+.icon-09:before {
+  content: "\e758";
+}
+
+.icon-tishi:before {
+  content: "\e653";
+}
+
+.icon-xiaoxizhongxin:before {
+  content: "\e665";
+}
+
+.icon-shezhi:before {
+  content: "\e68f";
+}
+
+.icon-xitongcaidan:before {
+  content: "\e696";
+}
+
+.icon-16:before {
+  content: "\e6f1";
+}
+
+.icon-10:before {
+  content: "\e6f2";
+}
+
+.icon-01:before {
+  content: "\e6f4";
+}
+
+.icon-leidian:before {
+  content: "\e6f5";
+}
+
+.icon-00:before {
+  content: "\e6f6";
+}
+
+.icon-14:before {
+  content: "\e6f7";
+}
+
+.icon-07:before {
+  content: "\e6f9";
+}
+
+.icon-02:before {
+  content: "\e6fa";
+}
+
+.icon-13:before {
+  content: "\e6fb";
+}
+
+.icon-03:before {
+  content: "\e6fc";
+}
+
+.icon-15:before {
+  content: "\e6fd";
+}
+
+.icon-08:before {
+  content: "\e6fe";
+}
+
+.icon-fanhui:before {
+  content: "\e6ff";
+}
+
+.icon-bingbao:before {
+  content: "\e706";
+}
+
+.icon-53:before {
+  content: "\e709";
+}
+
+.icon-18:before {
+  content: "\e70a";
+}
+
+.icon-06:before {
+  content: "\e70b";
+}
+
+.icon-yuyan:before {
+  content: "\e62c";
+}
+
+.icon-qingchu:before {
+  content: "\e64a";
+}
+
+.icon-04:before {
+  content: "\e658";
+}
+
+.icon-gengduo-hengxiang:before {
+  content: "\e8c4";
+}
+
+.icon-xiazaidaoru:before {
+  content: "\e8c6";
+}
+
+.icon-add:before {
+  content: "\e6df";
+}
+
+.icon-addition:before {
+  content: "\e6e0";
+}
+
+.icon-document:before {
+  content: "\e6f3";
+}
+
+.icon-enter:before {
+  content: "\e6f8";
+}
+
+.icon-like_fill:before {
+  content: "\e707";
+}
+
+.icon-like:before {
+  content: "\e708";
+}
+
+.icon-play_fill:before {
+  content: "\e717";
+}
+
+.icon-trash:before {
+  content: "\e738";
+}
+
+.icon-search:before {
+  content: "\e741";
+}
+
+.icon-tongzhi:before {
+  content: "\e61d";
+}
+
+.icon-29:before {
+  content: "\e60b";
+}
+
+.icon-bofang:before {
+  content: "\e624";
+}
+
+.icon-zanting:before {
+  content: "\e629";
+}
+
+.icon-shoucang:before {
+  content: "\e627";
+}
+
+.icon-jiantouxia:before {
+  content: "\e62d";
+}
+
+.icon-dizhiguanli:before {
+  content: "\e63f";
+}
+
+.icon-11:before {
+  content: "\e614";
+}
+
+.icon-yinle:before {
+  content: "\e990";
+}
+
+.icon-yinle1:before {
+  content: "\e62b";
+}
+
+.icon-17:before {
+  content: "\e631";
+}
+
+.icon-tubiaolunkuo-:before {
+  content: "\e613";
+}
+
+.icon-unmap:before {
+  content: "\e600";
+}
+
+.icon-home:before {
+  content: "\e7c6";
+}
+
+.icon-comf:before {
+  content: "\e669";
+}
+
+.icon-20:before {
+  content: "\e6d6";
+}
+
+.icon-sousuo1:before {
+  content: "\eafe";
+}
+
+.icon-kuaisugongzuoliu_o:before {
+  content: "\eb55";
+}
+
+.icon-shouye:before {
+  content: "\e632";
+}
+
+.icon-wode:before {
+  content: "\e633";
+}
+
+.icon-liebiao:before {
+  content: "\e63a";
+}
+
+.icon-xingbiao:before {
+  content: "\e642";
+}
+
+.icon-sousuo:before {
+  content: "\e644";
+}
+
+.icon-sousuo_light-copy:before {
+  content: "\e645";
+}
+
+.icon-xingbiao_light-copy:before {
+  content: "\e646";
+}
+
+.icon-liebiao_light-copy:before {
+  content: "\e647";
+}
+
+.icon-wode_light-copy:before {
+  content: "\e648";
+}
+
+.icon-shouye_light-copy:before {
+  content: "\e649";
+}
+
+.icon-play-copy:before {
+  content: "\eb57";
+}
+
+.icon-stop-copy:before {
+  content: "\eb58";
+}
+
+.icon-left-copy:before {
+  content: "\eb59";
+}
+
+.icon-12:before {
+  content: "\e743";
+}
+
+.icon-air:before {
+  content: "\e604";
+}
+
+.icon-trav:before {
+  content: "\e61c";
+}
+
+.icon-drsg:before {
+  content: "\e602";
+}
+
+.icon-flu:before {
+  content: "\e603";
+}
+
+.icon-uv:before {
+  content: "\e601";
+}
+
+.icon-guanbi:before {
+  content: "\e610";
+}
+
+.icon-sport:before {
+  content: "\e656";
+}
+
+.icon-cw:before {
+  content: "\e62f";
+}
+

+ 0 - 0
common/main.css


File diff suppressed because it is too large
+ 125 - 0
common/utils/airport.js


File diff suppressed because it is too large
+ 1 - 0
common/utils/amap-wx.js


+ 239 - 0
common/utils/https.js

@@ -0,0 +1,239 @@
+const weather = 'https://free-api.heweather.net/s6/weather'
+const future = 'http://v.juhe.cn/weather/index'
+const air = 'https://free-api.heweather.net/s6/air/now'
+const locl = 'http://apis.juhe.cn/geo/'
+const QQ_MAP_KEY1 = '630ac2e3d80941b48c80fe3a8ed1a042'
+const QQ_MAP_KEY2 = 'c649beb3621c84ee57c365f45a9a6ed4'
+const QQ_MAP_KEY3 = 'dd35eaa26348f268f1f02b4a8fbe4aaf'
+
+
+//添加finally事件
+Promise.prototype.finally = function (callback) {
+    var Promise = this.constructor;
+    return this.then(
+        function (value) {
+            Promise.resolve(callback()).then(
+                function () {
+                    return value;
+                }
+            );
+        },
+        function (reason) {
+            Promise.resolve(callback()).then(
+                function () {
+                    throw reason;
+                }
+            );
+        }
+    );
+}
+
+// 实况天气
+function getWeather(location) {
+	return new Promise((resolve, reject) => {
+		uni.request({
+			url: weather+"/now",
+			data: {
+				location:location,
+				key: QQ_MAP_KEY1
+			},
+			success: (res) => {
+				resolve({result: res.data})
+			},
+			fail: (e) => {
+				reject(e)
+			},
+			complete: (e) => {
+		  	
+			}
+		})
+	})
+}
+// 未来天气
+function getFuture(location) {
+	return new Promise((resolve, reject) => {
+		uni.request({
+			// url: "/v/weather/index",
+			url: weather+"/forecast",
+			data: {
+				// cityname:location,
+				// key: QQ_MAP_KEY2
+				
+				location:location,
+				key: QQ_MAP_KEY1
+			},
+			success: (res) => {
+				resolve({result: res.data})
+			},
+			fail: (e) => {
+				reject(e)
+			},
+			complete: (e) => {
+		  	
+			}
+		})
+	})
+}
+// 生活指数
+function getLift(location) {
+	return new Promise((resolve, reject) => {
+	    uni.request({
+	        url: weather+"/lifestyle",
+	        data: {
+	            location:location,
+	            key: QQ_MAP_KEY1,
+	        },
+	        success: (res) => {
+	            resolve({result:res.data})
+	        },
+	        fail: (e) => {
+	            reject(e)
+	        }
+	    })
+	})
+}
+// 空气质量---废弃
+function getAir(location) {
+	return new Promise((resolve, reject) => {
+	    uni.request({
+	        url: air,
+	        data: {
+	            location:location,
+	            key: QQ_MAP_KEY1,
+	        },
+	        success: (res) => {
+	            resolve({result:res.data})
+	        },
+	        fail: (e) => {
+	            reject(e)
+	        }
+	    })
+	})
+}
+// 經緯度逆解析
+function gelocation(obj) {
+	return new Promise((resolve, reject) => {
+	    uni.request({
+	        url: "/api/geo/",
+	        data: {
+	          key: QQ_MAP_KEY3,
+	          lat:obj.lat,
+	          lng:obj.lng,
+	          type:1
+	        },
+	        success: (res) => {
+	            resolve({result:res.data})
+	        },
+	        fail: (e) => {
+	            reject(e)
+	        }
+	    })
+	})
+}
+
+export {
+	getWeather,
+	getFuture,
+	getLift,
+	getAir,
+	gelocation
+}
+
+
+// export const getWeather = (location) => {
+//   return new Promise((resolve, reject) => {
+//     wx.request({
+//       url: 'https://free-api.heweather.net/s6/weather/now',
+//       data: {
+//         location:location,
+//         key: QQ_MAP_KEY1
+//       },
+//       success: (res) => {
+//         resolve({result: res.data})
+//       },
+//       fail: (e) => {
+//         reject(e)
+//       },
+// 	  complete: (e) => {
+// 	  	
+// 	  }
+//     })
+//   })
+// }
+// 未来七天天气
+// export const getFuture = (location) => {
+//   return new Promise((resolve, reject) => {
+//     wx.request({
+//       url: 'http://v.juhe.cn/weather/index',
+//       data: {
+//         cityname:location,
+//         key: QQ_MAP_KEY2
+//       },
+//       success: (res) => {
+//         console.log(res)
+//         resolve({result: res.data})
+//       },
+//       fail: (e) => {
+//         console.log("haha  chucuo 2 ")
+//         reject(e)
+//       }
+//     })
+//   })
+// }
+// 生活指数
+// export const getLift = (location) => {
+//     return new Promise((resolve, reject) => {
+//         wx.request({
+//             url: 'https://free-api.heweather.net/s6/weather/lifestyle',
+//             data: {
+//                 location:location,
+//                 key: QQ_MAP_KEY1,
+//             },
+//             success: (res) => {
+//                 resolve({result:res.data})
+//             },
+//             fail: (e) => {
+//                 reject(e)
+//             }
+//         })
+//     })
+// }
+// 获取空气质量
+// export const getAir = (location) => {
+//   return new Promise((resolve, reject) => {
+//       wx.request({
+//           url: 'https://free-api.heweather.net/s6/air/now',
+//           data: {
+//               location:location,
+//               key: QQ_MAP_KEY1,
+//           },
+//           success: (res) => {
+//               resolve({result:res.data})
+//           },
+//           fail: (e) => {
+//               reject(e)
+//           }
+//       })
+//   })
+// }
+// 经纬度逆向解析
+// export const gelocation = (obj) => {
+//   return new Promise((resolve, reject) => {
+//       wx.request({
+//           url: 'http://apis.juhe.cn/geo/',
+//           data: {
+//             key: QQ_MAP_KEY3,
+//             lat:obj.lat,
+//             lng:obj.lng,
+//             type:1
+//           },
+//           success: (res) => {
+//               resolve({result:res.data})
+//           },
+//           fail: (e) => {
+//               reject(e)
+//           }
+//       })
+//   })
+// }
+

+ 34 - 0
common/utils/request.js

@@ -0,0 +1,34 @@
+// get方法
+const Get =  function(url, msg) {
+	return new Promise((resolve, reject) => {
+		uni.request({
+			url: url,
+			success: (res) => {
+				resolve({result: res.data})
+			},
+			fail: (e) => {
+				reject(e)
+			}
+		})
+	})
+}
+// post方法
+const Post = function(url, data, msg) {
+	return new Promise((resolve, reject) => {
+		uni.request({
+			url: url,
+			data: data,
+			success: (res) => {
+				resolve({result: res.data})
+			},
+			fail: (e) => {
+				reject(e)
+			}
+		})
+	})
+}
+
+export default {
+	Get,
+	Post
+}

+ 60 - 0
common/utils/tips.js

@@ -0,0 +1,60 @@
+var WEEK_NAME = ['周一', '周二', '周三', '周四', '周五', '周六', '周日', '周一', '周二', '周三', '周四', '周五', '周六', '周日']
+
+function tip(str) {
+	uni.showToast({
+		title: str,
+		icon:"none",
+		duration:5000
+	})
+}
+
+function tips(str) {
+	uni.showToast({
+		title: str,
+		icon:"success",
+		duration:2000
+	})
+}
+
+function Loding(str) {
+	uni.showLoading({
+		title:str,
+		mask:true
+	})
+}
+
+function HideLoding() {
+	uni.hideLoading();
+}
+
+function cutting(val){
+	var strArr = val.split("~")
+	return strArr
+}
+
+function humidity(h) {
+    if (h) {
+        return '湿度 ' + h + '%'
+    }
+    return h
+}
+
+function formatWeeklyDate(i) {
+	var now = getDate()
+	var names = ['今天', '明天', '后天']
+	if (names[i]) {
+		return names[i]
+	}
+	var curWeek = now.getDay() - 1 + i
+	return WEEK_NAME[curWeek]
+}
+
+export {
+	tip,
+	tips,
+	Loding,
+	HideLoding,
+	cutting,
+	humidity,
+	formatWeeklyDate
+}

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


+ 268 - 0
components/indexed-list/indexed-list.vue

@@ -0,0 +1,268 @@
+<template>
+	<view class="uni-indexed">
+		<scroll-view :scroll-into-view="scrollViewId" :style="{ height: winHeight + 'px' }" class="uni-indexed__list" scroll-y>
+			<block v-for="(list, idx) in lists" :key="idx">
+				<view v-if="list.items && list.items.length > 0" :id="'uni-indexed-list-' + list.key" class="uni-indexed__list-title">{{ list.key }}</view>
+				<view v-if="list.items && list.items.length > 0" class="uni-list">
+					<view v-for="(item, index) in list.items" :key="index" class="uni-list-item" hover-class="uni-list-item--hover">
+						<view class="uni-list-item__container" @click="onClick(idx, index)">
+							<view v-if="showSelect" style="margin-right: 20upx;">
+								<uni-icon :type="item.checked ? 'checkbox-filled' : 'circle'" :color="item.checked ? '#007aff' : '#aaa'" size="24" />
+							</view>
+							<view class="uni-list-item__content">{{ item.name }}</view>
+						</view>
+					</view>
+				</view>
+			</block>
+		</scroll-view>
+		<view :class="touchmove ? 'active' : ''" :style="{ height: winHeight + 'px' }" class="uni-indexed__menu" @touchstart="touchStart" @touchmove.stop.prevent="touchMove" @touchend="touchEnd">
+			<text v-for="(list, key) in lists" :key="key" :class="touchmoveIndex == key ? 'active' : ''" :style="{ height: itemHeight + 'px', lineHeight: itemHeight + 'px' }" class="uni-indexed__menu-item">
+				{{ list.key }}
+			</text>
+		</view>
+		<view v-if="touchmove" class="uni-indexed--alert">{{ lists[touchmoveIndex].key }}</view>
+	</view>
+</template>
+<script>
+	import uniIcon from '../icon/icon.vue';
+	export default {
+		name: 'UniIndexedList',
+		components: {
+			uniIcon
+		},
+		props: {
+			options: {
+				type: Array,
+				default () {
+					return [];
+				}
+			},
+			showSelect: {
+				type: Boolean,
+				default: false
+			}
+		},
+		data() {
+			return {
+				lists: [],
+				touchmove: false,
+				touchmoveIndex: -1,
+				itemHeight: 0,
+				winHeight: 0,
+				scrollViewId: ''
+			};
+		},
+		created() {
+			let winHeight = uni.getSystemInfoSync().windowHeight;
+			this.itemHeight = winHeight / this.options.length;
+			this.winHeight = winHeight;
+
+			// if (!this.showSelect) {
+			// 	this.lists = this.options;
+			// 	return;
+			// }
+			// console.log(this.options)
+			this.lists = this.options.map(value => {
+				// console.log(value)
+				let items = value.data.map(item => {
+					let obj = {};
+					// for (let key in item) {
+					obj['key'] = value.letter;
+					obj['name'] = item
+					// }
+					obj.checked = item.checked ? item.checked : false;
+					return obj;
+				});
+				return {
+					title: value.letter,
+					key: value.letter,
+					items: items
+				};
+			});
+			// console.log(this.lists)
+		},
+		methods: {
+			touchStart(e) {
+				this.touchmove = true;
+				let pageY = e.touches[0].pageY;
+				let index = Math.floor(pageY / this.itemHeight);
+				let item = this.lists[index];
+				if (item) {
+					this.scrollViewId = 'uni-indexed-list-' + item.key;
+					this.touchmoveIndex = index;
+				}
+			},
+			touchMove(e) {
+				let pageY = e.touches[0].pageY;
+				let index = Math.floor(pageY / this.itemHeight);
+				let item = this.lists[index];
+				if (item) {
+					this.scrollViewId = 'uni-indexed-list-' + item.key;
+					this.touchmoveIndex = index;
+				}
+			},
+			touchEnd() {
+				this.touchmove = false;
+				this.touchmoveIndex = -1;
+			},
+			onClick(idx, index) {
+				let obj = {};
+				for (let key in this.lists[idx].items[index]) {
+					obj[key] = this.lists[idx].items[index][key];
+				}
+				let select = [];
+				if (this.showSelect) {
+					this.lists[idx].items[index].checked = !this.lists[idx].items[index].checked;
+					this.lists.forEach((value, idx) => {
+						value.items.forEach((item, index) => {
+							if (item.checked) {
+								let obj = {};
+								for (let key in this.lists[idx].items[index]) {
+									obj[key] = this.lists[idx].items[index][key];
+								}
+								select.push(obj);
+							}
+						});
+					});
+				}
+				this.$emit('click', {
+					item: obj,
+					select: select
+				});
+			}
+		}
+	};
+</script>
+<style>
+	@charset "UTF-8";
+
+	.uni-list {
+		background-color: #fff;
+		position: relative;
+		width: 100%;
+		display: flex;
+		flex-direction: column
+	}
+
+	.uni-list::after {
+		position: absolute;
+		z-index: 10;
+		right: 0;
+		bottom: 0;
+		left: 0;
+		height: 1px;
+		content: '';
+		-webkit-transform: scaleY(.5);
+		transform: scaleY(.5);
+		background-color: #c8c7cc
+	}
+
+	.uni-list::before {
+		position: absolute;
+		z-index: 10;
+		right: 0;
+		top: 0;
+		left: 0;
+		height: 1px;
+		content: '';
+		-webkit-transform: scaleY(.5);
+		transform: scaleY(.5);
+		background-color: #c8c7cc
+	}
+
+	.uni-list-item {
+		font-size: 32upx;
+		position: relative;
+		display: flex;
+		flex-direction: column;
+		justify-content: space-between;
+		align-items: center
+	}
+
+	.uni-list-item__container {
+		padding: 24upx 30upx;
+		width: 100%;
+		box-sizing: border-box;
+		flex: 1;
+		position: relative;
+		display: flex;
+		flex-direction: row;
+		justify-content: space-between;
+		align-items: center
+	}
+
+	.uni-list-item__container:after {
+		position: absolute;
+		z-index: 3;
+		right: 0;
+		bottom: 0;
+		left: 30upx;
+		height: 1px;
+		content: '';
+		-webkit-transform: scaleY(.5);
+		transform: scaleY(.5);
+		background-color: #c8c7cc
+	}
+
+	.uni-indexed {
+		display: flex;
+		flex-direction: row
+	}
+
+	.uni-indexed__list {
+		flex: 1;
+		height: 100vh
+	}
+
+	.uni-indexed__list-title {
+		padding: 10upx 24upx;
+		line-height: 1.5;
+		background-color: #f7f7f7;
+		font-size: 24upx
+	}
+
+	.uni-indexed__menu {
+		width: 46upx;
+		height: 100vh;
+		background-color: #d3d3d3;
+		display: flex;
+		flex-direction: column
+	}
+
+	.uni-indexed__menu.active {
+		background-color: #c8c8c8
+	}
+
+	.uni-indexed__menu.active .uni-indexed__menu-item {
+		color: #333
+	}
+
+	.uni-indexed__menu.active .uni-indexed__menu-item.active {
+		color: #007aff
+	}
+
+	.uni-indexed__menu-item {
+		color: #aaa;
+		font-size: 22upx;
+		text-align: center
+	}
+
+	.uni-indexed--alert {
+		position: absolute;
+		display: inline-flex;
+		align-items: center;
+		justify-content: center;
+		z-index: 20;
+		width: 160upx;
+		height: 160upx;
+		left: 50%;
+		top: 50%;
+		margin-left: -80upx;
+		margin-top: -80upx;
+		border-radius: 80upx;
+		text-align: center;
+		font-size: 70upx;
+		color: #fff;
+		background-color: rgba(0, 0, 0, .5)
+	}
+</style>

+ 20 - 0
main.js

@@ -0,0 +1,20 @@
+import Vue from 'vue'
+import App from './App'
+
+Vue.config.productionTip = false
+
+import store  from './store'
+Vue.prototype.$store = store 
+
+import api from "@/common/utils/request.js"
+Vue.prototype.$api = api
+import * as tos from "@/common/utils/tips.js"
+Vue.prototype.$tos = tos
+
+App.mpType = 'app'
+
+const app = new Vue({
+	store ,
+    ...App
+})
+app.$mount()

+ 131 - 0
manifest.json

@@ -0,0 +1,131 @@
+{
+    "name" : "helle-app",
+    "appid" : "__UNI__564D069",
+    "description" : "",
+    "versionName" : "1.0.0",
+    "versionCode" : "100",
+    "transformPx" : false,
+    "app-plus" : {
+        /* 5+App特有相关 */
+        "usingComponents" : true,
+        "splashscreen" : {
+            "alwaysShowBeforeRender" : true,
+            "waiting" : true,
+            "autoclose" : true,
+            "delay" : 0
+        },
+        "modules" : {
+            "Bluetooth" : {},
+            "Contacts" : {},
+            "Fingerprint" : {},
+            "LivePusher" : {},
+            "Maps" : {},
+            "OAuth" : {},
+            "Payment" : {},
+            "Push" : {},
+            "Share" : {},
+            "Speech" : {},
+            "SQLite" : {},
+            "VideoPlayer" : {}
+        },
+        /* 模块配置 */
+        "distribute" : {
+            /* 应用发布信息 */
+            "android" : {
+                /* android打包配置 */
+                "permissions" : [
+                    "<uses-feature android:name=\"android.hardware.camera\"/>",
+                    "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CALL_PHONE\"/>",
+                    "<uses-permission android:name=\"android.permission.CAMERA\"/>",
+                    "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.DELETE_CACHE_FILES\"/>",
+                    "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
+                    "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
+                    "<uses-permission android:name=\"android.permission.INTERNET\"/>",
+                    "<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
+                    "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_CONTACTS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
+                    "<uses-permission android:name=\"android.permission.USE_FINGERPRINT\"/>",
+                    "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
+                    "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
+                    "<uses-permission android:name=\"android.permission.WRITE_CONTACTS\"/>",
+                    "<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"/>",
+                    "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
+                ]
+            },
+            "ios" : {},
+            /* ios打包配置 */
+            "sdkConfigs" : {
+                "speech" : {
+                    "ifly" : {}
+                }
+            }
+        }
+    },
+    /* SDK配置 */
+    "quickapp" : {},
+    /* 快应用特有相关 */
+    "mp-weixin" : {
+        "appid" : "wxe44775f71378af60",
+        "setting" : {
+            "urlCheck" : false,
+            "es6" : true,
+            "postcss" : true,
+            "minified" : true
+        },
+        "usingComponents" : true,
+        "permission" : {
+            "scope.userLocation" : {
+                "desc" : "获取位置信息,提供最优服务"
+            }
+        }
+    },
+    "h5" : {
+        "router" : {},
+        // "base" : "/m/"
+        "asyuc" : {
+            "loading" : "AsyncLoading",
+            "error" : "AsyncError",
+            "delay" : 100,
+            "timeout" : 5000
+        },
+        "devServer" : {
+            "disableHostCheck" : true,
+            "proxy" : {
+                "/v" : {
+                    "target" : "http://v.juhe.cn",
+                    "ws" : false,
+                    "secure" : false,
+                    "changeOrigin" : true,
+                    "pathRewrite" : {
+                        "^/v" : "/"
+                    }
+                },
+                "/api" : {
+                    "target" : "http://apis.juhe.cn",
+                    "ws" : false,
+                    "secure" : false,
+                    "changeOrigin" : true,
+                    "pathRewrite" : {
+                        "^/api" : "/"
+                    }
+                }
+            },
+            "https" : false
+        },
+        "title" : "首頁",
+        "domain" : ""
+    },
+    "networkTimeout" : {
+        "request" : 5000
+    }
+}

+ 377 - 0
package-lock.json

@@ -0,0 +1,377 @@
+{
+  "requires": true,
+  "lockfileVersion": 1,
+  "dependencies": {
+    "accepts": {
+      "version": "1.3.7",
+      "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
+      "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
+      "requires": {
+        "mime-types": "~2.1.24",
+        "negotiator": "0.6.2"
+      }
+    },
+    "array-flatten": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+      "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
+    },
+    "body-parser": {
+      "version": "1.19.0",
+      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
+      "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
+      "requires": {
+        "bytes": "3.1.0",
+        "content-type": "~1.0.4",
+        "debug": "2.6.9",
+        "depd": "~1.1.2",
+        "http-errors": "1.7.2",
+        "iconv-lite": "0.4.24",
+        "on-finished": "~2.3.0",
+        "qs": "6.7.0",
+        "raw-body": "2.4.0",
+        "type-is": "~1.6.17"
+      }
+    },
+    "bytes": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
+      "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
+    },
+    "content-disposition": {
+      "version": "0.5.3",
+      "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
+      "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
+      "requires": {
+        "safe-buffer": "5.1.2"
+      }
+    },
+    "content-type": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
+      "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
+    },
+    "cookie": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
+      "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
+    },
+    "cookie-signature": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+      "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
+    },
+    "debug": {
+      "version": "2.6.9",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "requires": {
+        "ms": "2.0.0"
+      }
+    },
+    "depd": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+      "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
+    },
+    "destroy": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
+      "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
+    },
+    "ee-first": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+      "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
+    },
+    "encodeurl": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+      "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
+    },
+    "escape-html": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+      "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
+    },
+    "etag": {
+      "version": "1.8.1",
+      "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+      "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
+    },
+    "express": {
+      "version": "4.17.0",
+      "resolved": "https://registry.npmjs.org/express/-/express-4.17.0.tgz",
+      "integrity": "sha512-1Z7/t3Z5ZnBG252gKUPyItc4xdeaA0X934ca2ewckAsVsw9EG71i++ZHZPYnus8g/s5Bty8IMpSVEuRkmwwPRQ==",
+      "requires": {
+        "accepts": "~1.3.7",
+        "array-flatten": "1.1.1",
+        "body-parser": "1.19.0",
+        "content-disposition": "0.5.3",
+        "content-type": "~1.0.4",
+        "cookie": "0.4.0",
+        "cookie-signature": "1.0.6",
+        "debug": "2.6.9",
+        "depd": "~1.1.2",
+        "encodeurl": "~1.0.2",
+        "escape-html": "~1.0.3",
+        "etag": "~1.8.1",
+        "finalhandler": "~1.1.2",
+        "fresh": "0.5.2",
+        "merge-descriptors": "1.0.1",
+        "methods": "~1.1.2",
+        "on-finished": "~2.3.0",
+        "parseurl": "~1.3.3",
+        "path-to-regexp": "0.1.7",
+        "proxy-addr": "~2.0.5",
+        "qs": "6.7.0",
+        "range-parser": "~1.2.1",
+        "safe-buffer": "5.1.2",
+        "send": "0.17.1",
+        "serve-static": "1.14.1",
+        "setprototypeof": "1.1.1",
+        "statuses": "~1.5.0",
+        "type-is": "~1.6.18",
+        "utils-merge": "1.0.1",
+        "vary": "~1.1.2"
+      }
+    },
+    "finalhandler": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
+      "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
+      "requires": {
+        "debug": "2.6.9",
+        "encodeurl": "~1.0.2",
+        "escape-html": "~1.0.3",
+        "on-finished": "~2.3.0",
+        "parseurl": "~1.3.3",
+        "statuses": "~1.5.0",
+        "unpipe": "~1.0.0"
+      }
+    },
+    "forwarded": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
+      "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
+    },
+    "fresh": {
+      "version": "0.5.2",
+      "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+      "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
+    },
+    "http-errors": {
+      "version": "1.7.2",
+      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
+      "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
+      "requires": {
+        "depd": "~1.1.2",
+        "inherits": "2.0.3",
+        "setprototypeof": "1.1.1",
+        "statuses": ">= 1.5.0 < 2",
+        "toidentifier": "1.0.0"
+      }
+    },
+    "iconv-lite": {
+      "version": "0.4.24",
+      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+      "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+      "requires": {
+        "safer-buffer": ">= 2.1.2 < 3"
+      }
+    },
+    "inherits": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+      "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+    },
+    "ipaddr.js": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz",
+      "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA=="
+    },
+    "media-typer": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+      "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
+    },
+    "merge-descriptors": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+      "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
+    },
+    "methods": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+      "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
+    },
+    "mime": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+      "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
+    },
+    "mime-db": {
+      "version": "1.40.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
+      "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA=="
+    },
+    "mime-types": {
+      "version": "2.1.24",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
+      "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
+      "requires": {
+        "mime-db": "1.40.0"
+      }
+    },
+    "ms": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+    },
+    "negotiator": {
+      "version": "0.6.2",
+      "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
+      "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
+    },
+    "on-finished": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+      "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+      "requires": {
+        "ee-first": "1.1.1"
+      }
+    },
+    "parseurl": {
+      "version": "1.3.3",
+      "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+      "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
+    },
+    "path-to-regexp": {
+      "version": "0.1.7",
+      "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+      "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
+    },
+    "proxy-addr": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz",
+      "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==",
+      "requires": {
+        "forwarded": "~0.1.2",
+        "ipaddr.js": "1.9.0"
+      }
+    },
+    "qs": {
+      "version": "6.7.0",
+      "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
+      "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
+    },
+    "range-parser": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+      "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
+    },
+    "raw-body": {
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
+      "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
+      "requires": {
+        "bytes": "3.1.0",
+        "http-errors": "1.7.2",
+        "iconv-lite": "0.4.24",
+        "unpipe": "1.0.0"
+      }
+    },
+    "safe-buffer": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+    },
+    "safer-buffer": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+    },
+    "send": {
+      "version": "0.17.1",
+      "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
+      "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
+      "requires": {
+        "debug": "2.6.9",
+        "depd": "~1.1.2",
+        "destroy": "~1.0.4",
+        "encodeurl": "~1.0.2",
+        "escape-html": "~1.0.3",
+        "etag": "~1.8.1",
+        "fresh": "0.5.2",
+        "http-errors": "~1.7.2",
+        "mime": "1.6.0",
+        "ms": "2.1.1",
+        "on-finished": "~2.3.0",
+        "range-parser": "~1.2.1",
+        "statuses": "~1.5.0"
+      },
+      "dependencies": {
+        "ms": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+          "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
+        }
+      }
+    },
+    "serve-static": {
+      "version": "1.14.1",
+      "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
+      "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
+      "requires": {
+        "encodeurl": "~1.0.2",
+        "escape-html": "~1.0.3",
+        "parseurl": "~1.3.3",
+        "send": "0.17.1"
+      }
+    },
+    "setprototypeof": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
+      "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
+    },
+    "statuses": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+      "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
+    },
+    "toidentifier": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
+      "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
+    },
+    "type-is": {
+      "version": "1.6.18",
+      "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+      "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+      "requires": {
+        "media-typer": "0.3.0",
+        "mime-types": "~2.1.24"
+      }
+    },
+    "unpipe": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+      "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
+    },
+    "utils-merge": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+      "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
+    },
+    "vary": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+      "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
+    },
+    "vuex": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/vuex/-/vuex-3.1.1.tgz",
+      "integrity": "sha512-ER5moSbLZuNSMBFnEBVGhQ1uCBNJslH9W/Dw2W7GZN23UQA69uapP5GTT9Vm8Trc0PzBSVt6LzF3hGjmv41xcg=="
+    }
+  }
+}

+ 57 - 0
pages.json

@@ -0,0 +1,57 @@
+{
+	// pages数组中第一项表示应用启动页,设置页面路径及窗口表现
+	"pages": [ 
+		{
+			"path": "pages/index/index",
+			"style": {
+				"navigationStyle":"custom",				//导航栏样式,仅支持 default/custom。custom即取消默认的原生导航栏	微信小程序7.0+、百度小程序、H5。
+				"backgroundColor":"#eeeeee",			//窗口的背景色	微信小程序、百度小程序、头条小程序
+				"backgroundTextStyle":"dark",			//下拉 loading 的样式,仅支持 dark/light	
+				"enablePullDownRefresh":true			//是否开启下拉刷新,详见页面生命周期。
+			}
+		},
+		{
+			"path":"pages/mypersonal/personal",
+			"style":{
+				"navigationStyle":"default"
+			}
+		}
+	    ,{
+            "path" : "pages/list/list",
+            "style" : {
+				"navigationBarTitleText":"城市列表"
+			}
+        }
+        ,{
+            "path" : "pages/setting/setting",
+            "style" : {}
+        }
+    ],
+	"tabBar": {
+		"color":"#C0C4C6",					//tab 上的文字默认颜色	
+		"selectedColor":"#2386EE",			//tab 上的文字选中时的颜色	
+		"backgroundColor":"#FFFFFF",		//tab 的背景色	
+		"borderStyle":"black",	 			//tabbar 上边框的颜色,仅支持 black/white	
+		"list":[
+			{
+				"iconPath":"static/home.png",
+				"selectedIconPath":"static/home_light.png",
+				"pagePath":"pages/index/index",	//页面路径,必须在 pages 中先定义
+				"text":"首頁"					//tab 上按钮文字,在 5+APP 和 H5 平台为非必填。例如中间可放一个没有文字的+号图标
+			},
+			{
+				"iconPath":"static/people.png",
+				"selectedIconPath":"static/people_light.png",
+				"pagePath":"pages/mypersonal/personal",	
+				"text":"我的"		
+			}
+		],		
+		"position":"bottom"
+	},
+	"globalStyle": {
+		"navigationBarTextStyle": "black",
+		"navigationBarTitleText": "",
+		"navigationBarBackgroundColor": "#FFFFFF",
+		"backgroundColor": "#FFFFFF"
+	}
+}

+ 8 - 0
pages/components/login/login.vue

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

+ 8 - 0
pages/components/login/pLogin.vue

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

+ 8 - 0
pages/components/login/wLogin.vue

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

+ 103 - 0
pages/components/personal/index.vue

@@ -0,0 +1,103 @@
+<style lang="scss">
+	.step{ 
+	    width: 100%; 
+	    height: auto; 
+	    padding: 10rpx 30rpx; 
+	    box-sizing: border-box; 
+	    overflow: hidden;
+	    background-color: #fff;
+	    color: #666;
+	  }
+	.step .modle{ 
+	  width: 100%; 
+	  height: 100rpx; 
+	  margin-top: 10rpx; }
+	.step .modle .mol{ 
+	  width: 100%; 
+	  height: 52rpx; 
+	  position: relative;  }
+	.step .mol-line{ 
+	  width: 100%; 
+	  height: 4rpx; 
+	  background-color: #e6e6e6; 
+	  position: absolute; 
+	  left: 0; 
+	  top: 50%; 
+	  transform: translateY(-50%);}
+	.step .mol-ites{ 
+	  width: 100%; 
+	  height: 100%;
+	  position: absolute;}
+	.mol-ites .ite{ 
+	  width: 52rpx; 
+	  height: 52rpx; 
+	  border-radius: 50%; 
+	  border: 1px solid #f5f5f5;
+	  background-color: #fff; 
+	  box-sizing: border-box;  
+	  position: absolute; 
+	  left: 0; 
+	  top: 0; 
+	  z-index: 2;}
+	.mol-ites .ite .n{ 
+	  width: 44rpx; 
+	  height: 44rpx; 
+	  line-height: 44rpx; 
+	  text-align: center; 
+	  border-radius: 50%; 
+	  background-color: #f5f5f5;
+	  position: absolute; 
+	  left: 50%; 
+	  top: 50%; 
+	  transform: translate(-50%,-50%); 
+	  font-size: 22rpx;}
+	.mol-ites .ite::after{ 
+	  content: ""; 
+	  width: 80rpx; 
+	  height: 4rpx; 
+	  background-color: transparent; 
+	  position: absolute; 
+	  left: 52rpx; 
+	  top: 50%; 
+	  margin-top: -2rpx; 
+	  z-index: 2;}
+	.mol-ites .ite:last-of-type::after{ width: 0;}
+	.mol-ites .ite:nth-of-type(2){ left: 107rpx;}
+	.mol-ites .ite:nth-of-type(3){ left: 214rpx;}
+	.mol-ites .ite:nth-of-type(4){ left: 321rpx;}
+	.mol-ites .ite:nth-of-type(5){ left: 428rpx;}
+	.mol-ites .ite:nth-of-type(6){ left: 535rpx;}
+	.mol-ites .ite:nth-of-type(7){ left: 642rpx;}
+	.mol-ites .ite.hover{ border-color: rgb(97, 165, 238);}
+	.mol-ites .ite.hover .n{ background-color: rgb(97, 165, 238); color: #fff;}
+	.mol-ites .ite.hover::after{ background-color: rgb(97, 165, 238); }
+	.moday{ 
+	  width: 100%; 
+	  height:40rpx; 
+	  overflow: hidden; 
+	  position: relative; 
+	  margin-top:16rpx;}
+	.moday .dd{ 
+	  width: 52rpx; 
+	  height: 40rpx; 
+	  line-height: 1; 
+	  text-align: center; 
+	  font-size: 22rpx;
+	  position: absolute; 
+	  left: 0; 
+	  bottom: 0;}
+	.moday .dd:nth-of-type(2){ left: 107rpx;}
+	.moday .dd:nth-of-type(3){ left: 214rpx;}
+	.moday .dd:nth-of-type(4){ left: 321rpx;}
+	.moday .dd:nth-of-type(5){ left: 428rpx;}
+	.moday .dd:nth-of-type(6){ left: 535rpx;}
+	.moday .dd:nth-of-type(7){ left: 642rpx;}
+</style>
+
+<template>
+	<view></view>
+</template>
+
+<script>
+	
+</script>

+ 200 - 0
pages/components/signin/sign.vue

@@ -0,0 +1,200 @@
+<style scoped lang="scss">
+	.step{
+		width: 100%;
+        height: auto;
+        padding: 10upx 30upx;
+        box-sizing: border-box;
+        overflow: hidden;
+        background-color: #fff;
+        color: #666;
+        margin-bottom: 20upx;
+        .modle {
+            width: 100%;
+            height: 100upx;
+            margin-top: 10upx;
+            .mol {
+                width: 100%;
+                height: 52upx;
+                position: relative;
+                .mol-line {
+                    width: 100%;
+                    height: 4upx;
+                    background-color: #e6e6e6;
+                    position: absolute;
+                    left: 0;
+                    top: 50%;
+                    transform: translateY(-50%);
+                }
+                .mol-ites {
+                    width: 100%;
+                    height: 100%;
+                    position: absolute;
+                    .ite {
+                        width: 52upx;
+                        height: 52upx;
+                        border-radius: 50%;
+                        border: 1upx solid #f5f5f5;
+                        background-color: #fff;
+                        box-sizing: border-box;
+                        position: absolute;
+                        left: 0;
+                        top: 0;
+                        z-index: 2;
+                        .n {
+                            width: 44upx;
+                            height: 44upx;
+                            line-height: 44upx;
+                            text-align: center;
+                            border-radius: 50%;
+                            background-color: #f5f5f5;
+                            position: absolute;
+                            left: 50%;
+                            top: 50%;
+                            transform: translate(-50%, -50%);
+                            font-size: 22upx;
+                        }
+                    }
+                    .ite::after {
+                        content: "";
+                        width: 80upx;
+                        height: 4upx;
+                        background-color: transparent;
+                        position: absolute;
+                        left: 52upx;
+                        top: 50%;
+                        margin-top: -2upx;
+                        z-index: 2;
+                    }
+                    .ite:last-of-type::after {
+                        width: 0;
+                    }
+                    .ite:nth-of-type(2) {
+                        left: 107upx;
+                    }
+                    .ite:nth-of-type(3) {
+                        left: 214upx;
+                    }
+                    .ite:nth-of-type(4) {
+                        left: 321upx;
+                    }
+                    .ite:nth-of-type(5) {
+                        left: 428upx;
+                    }
+                    .ite:nth-of-type(6) {
+                        left: 535upx;
+                    }
+                    .ite:nth-of-type(7) {
+                        left: 642upx;
+                    }
+                    .hover {
+                        border-color: rgb(97, 165, 238);
+                        .n {
+                            background-color: rgb(97, 165, 238);
+                            color: #fff;
+                        }
+                    }
+                    .hover::after {
+                        background-color: rgb(97, 165, 238);
+                    }
+                }
+            }
+            .moday {
+                width: 100%;
+                height: 40upx;
+                overflow: hidden;
+                position: relative;
+                margin-top: 16upx;
+                .dd {
+                    width: 52upx;
+                    height: 40upx;
+                    line-height: 1;
+                    text-align: center;
+                    font-size: 22upx;
+                    position: absolute;
+                    left: 0;
+                    bottom: 0;
+                }
+                .dd:nth-of-type(2) {
+                    left: 107upx;
+                }
+                .dd:nth-of-type(3) {
+                    left: 214upx;
+                }
+                .dd:nth-of-type(4) {
+                    left: 321upx;
+                }
+                .dd:nth-of-type(5) {
+                    left: 428upx;
+                }
+                .dd:nth-of-type(6) {
+                    left: 535upx;
+                }
+                .dd:nth-of-type(7) {
+                    left: 642upx;
+                }
+            }
+        }
+	}
+</style>
+
+<template>
+	<view class='step'>
+		<view class='modle'>
+			<view class='mol'>
+				<view class='mol-line'></view>
+				<view class='mol-ites'>
+					<view class="ite" :class="signNum >= min ? 'hover':''" :data-n='min'>
+						<label class='n'>+{{min < 7 ? 1 : 3}}</label>
+					</view>
+					<view class="ite" :class="signNum >= min+1 ? 'hover':''" :data-n='min+1'>
+						<label class='n'>+{{min+1 < 7?1:3}}</label>
+					</view>
+					<view class="ite" :class="signNum >= min+2 ? 'hover':''" :data-n='min+2'>
+						<label class='n'>+{{min+2 < 7 ? 1:3}}</label>
+					</view>
+					<view class="ite" :class="signNum >= min+3 ? 'hover':''" :data-n='min+3'>
+						<label class='n'>+{{min+3 < 7 ?1:3}}</label>
+					</view>
+					<view class="ite" :class="signNum >= min+4 ? 'hover':''" :data-n='min+4'>
+						<label class='n'>+{{min+4 < 7 ? 1:3}}</label>
+					</view>
+					<view class="ite" :class="signNum >= min+5 ? 'hover':''" :data-n='min+5'>
+						<label class='n'>+{{min+5 < 7 ? 1:3}}</label>
+					</view>
+					<view class="ite" :class="signNum >= min+6 ? 'hover':''" :data-n='max'>
+						<label class='n'>+{{min+6 < 7 ? 1:3}}</label>
+					</view>
+				</view>
+			</view>
+			<view class='moday'>
+				<label class='dd'>{{min}}天</label>
+				<label class='dd'>{{min+1}}天</label>
+				<label class='dd'>{{min+2}}天</label>
+				<label class='dd'>{{min+3}}天</label>
+				<label class='dd'>{{min+4}}天</label>
+				<label class='dd'>{{min+5}}天</label>
+				<label class='dd'>{{max}}天</label>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				min: 1,           //默认值日期第一天1
+				max: 7,           //默认值日期最后一天7
+				be: 0,            //默认倍数
+			}
+		},
+		props:{
+			signNum:Number
+		},
+		onShow() {
+			console.log(this.signNum)
+		}
+	}
+</script>
+
+

File diff suppressed because it is too large
+ 227 - 0
pages/index/index.vue


+ 68 - 0
pages/list/list.vue

@@ -0,0 +1,68 @@
+<template>
+	<indexed-list :options="list" :showSelect="false" @click="bindClick" />
+</template>
+
+<script>
+	import {
+		mapMutations
+	} from "vuex"
+	import airport from '@/common/utils/airport.js'
+	import IndexedList from '@/components/indexed-list/indexed-list.vue'
+
+	export default {
+		components: {
+			IndexedList
+		},
+		data() {
+			return {
+				list: airport.list
+			}
+		},
+		methods: {
+			...mapMutations(["setCity"]),
+			bindClick(e) {
+				console.log('点击item,返回数据' + e.item.name + JSON.stringify(e))
+				this.setCity(e.item.name)
+				setTimeout(function() {
+					uni.navigateBack({
+						delta: 1
+					})
+				}, 500);
+			}
+		}
+	}
+</script>
+
+<style>
+	page {
+		display: flex;
+		flex-direction: column;
+		box-sizing: border-box;
+		background-color: #fff
+	}
+
+	view {
+		font-size: 28upx;
+		line-height: inherit
+	}
+
+	.example {
+		padding: 0 30upx 30upx
+	}
+
+	.example-title {
+		font-size: 32upx;
+		line-height: 32upx;
+		color: #777;
+		margin: 40upx 25upx;
+		position: relative
+	}
+
+	.example .example-title {
+		margin: 40upx 0
+	}
+
+	.example-body {
+		padding: 0 40upx
+	}
+</style>

+ 146 - 0
pages/mypersonal/personal.vue

@@ -0,0 +1,146 @@
+<style scoped lang="scss">
+	.main{
+		.portrait{
+			display: flex;
+			height: 160rpx;
+			align-items: center;
+			align-content: center;
+			/* justify-content: center;  水平居中*/
+			font-size: 30rpx;
+			color: #fff;
+			background-color: rgb(97, 165, 238);
+			.userinfo-avatar{
+				border-radius: 50%;
+				width: 100rpx;
+				height: 100rpx;
+				margin: 30rpx;
+			}
+			.sign{
+				width: 120rpx;
+				height: 60rpx;
+				line-height: 60rpx;
+				text-align: center;
+				background-color: #fff;
+				color:  rgb(97, 165, 238);
+				border-radius: 10rpx;
+				margin: 40rpx;
+				margin-left: auto;  /*子元素靠右 */
+			}
+			.signs{
+				background: #666;
+				color: #fff;
+			}
+		}
+		.userlist{
+			margin-top: 40rpx;
+			.iconfont{
+				margin-right: 10rpx;
+			}
+			button{
+				flex: 1;
+				position: absolute;
+				top: 0;
+				left: 0;
+				width: 100%;
+				height: 100%;
+				opacity: 0;
+			}
+			
+		}
+	}
+</style>
+
+<template>
+	<view class="main">
+		<view class='portrait'>
+			<image class="userinfo-avatar" :src="userInfo.avatarUrl ? userInfo.avatarUrl : '/static/icon.png'" mode="aspectFit"></image>
+			<view>{{userInfo.nickName}}</view>
+			<view class='sign' :class='signState ? "signs" : ""' @tap='signState?"":"signClick"' :data-num="signNum" :data-min="min" :data-max="max" :data-be="be">{{signState?"已签到":"签到"}}</view>
+		</view>
+		<personal/>
+		
+		<view class='userlist cu-list menu'>
+			<block v-for="(item, index) in list" :key="index">
+				<view class='cu-item arrow' @tap="bind(item.batName)">
+					<view class="content">
+						<icon class='iconfont' :class="item.className"></icon>
+						<text>{{item.name}}</text>
+					</view>
+					<button open-type="contact" v-if="item.batName === 'bindService'"/>
+					<button open-type="feedback" v-if="item.batName === 'feedback'"/>
+				</view>
+			</block>
+		</view>
+	</view>
+</template>
+
+<script >
+	import {
+		mapState,
+		mapMutations
+	} from "vuex"
+	import personal from "@/pages/components/personal/index.vue"
+	export default {
+		data() {
+			return {
+				signNum: 0,       //签到数
+				min: 1,           //默认值日期第一天1
+				max: 7,           //默认值日期最后一天7
+				be: 0,
+				list:[
+					{
+						name: '设置',
+						className: 'icon-shezhi',
+						batName:"bindSeting"
+					},
+					{
+						name: '问题反馈',
+						className: 'icon-tishi',
+						batName: "feedback"
+					},
+					{
+						name: '剪切板',
+						className: 'icon-document',
+						batName: "bindCopy"
+					},
+					{
+						name: '在线客服',
+						className: 'icon-xiaoxizhongxin',
+						batName: "bindService"
+					}
+				]
+			}
+		},
+		computed: {
+			...mapState({
+				userInfo: state => state.global.userInfo,
+				signState: state => state.global.signState,
+			})
+		},
+		onShow() {
+			
+		},
+		methods: {
+			bind(signClick) {
+				console.log("haha",signClick)
+			},
+			bindSeting() {
+				
+			},
+			bindCopy() {
+				let data = "haha"
+				wx.setClipboardData({
+					data: data,
+					success: res => {
+						uni.getToast('复制成功')
+						wx.getClipboardData({
+							success: res=> {
+								console.log(res.data)
+							}
+						})
+					}
+				})
+			}
+		}
+	}
+</script>

+ 145 - 0
pages/setting/setting.vue

@@ -0,0 +1,145 @@
+<style lang="scss" scoped>
+
+</style>
+
+<template>
+	<view class='setting'>
+	<!-- 自定义 -->
+		<view class='s'>
+			<view class='t'>